Android3D画廊总结整理

来源:互联网 发布:支持xen的linux内核 编辑:程序博客网 时间:2024/05/21 03:57
/**
 * 在网上看到好多的3D画廊的效果,最常见就是Gallery,但是在API16的时候就已经废弃了,现在推荐使用ViewPager和HorizontalScrollView来实现这种效果,下面就在这里对其进行整理一下,代码更多的是借鉴了好多网上的,勿喷!!!!

 */

Gallery实现


步骤:

      1、为Gallery设置Adapter

        @Override        public View getView(int position, View convertView, ViewGroup parent) {            ImageView iv;            if (convertView != null) {                iv = (ImageView) convertView;            } else {                iv = new ImageView(MainActivity.this);            }            //通过调用BitmapUtils的getBitmap方法来得到生成倒影效果的图片            Bitmap bitmap = BitmapUtils.getImageBitmap(getResources(), res[position]);            BitmapDrawable bd = new BitmapDrawable(bitmap);            bd.setAntiAlias(true);//为Bitmap设置抗锯齿效果            iv.setImageDrawable(bd);            Gallery.LayoutParams params = new Gallery.LayoutParams(160, 400);            iv.setLayoutParams(params);//为ImageView设置宽高            return iv;        }
       2、设置图片倒影效果
    public static Bitmap getBitmap(Resources res, int drawableId) {        Bitmap src_bitmap = BitmapFactory.decodeResource(res, drawableId);//原图        //1、生成倒影图片        Matrix matrix = new Matrix();        matrix.setScale(1, -1);// 让图形按照矩阵进行垂直反转        Bitmap inverted_Bitmap = Bitmap.createBitmap(src_bitmap, 0, (int) (src_bitmap.getHeight() * 0.5), src_bitmap.getWidth(), src_bitmap.getHeight() / 2, matrix, true);        //2、得到合成的图片        Bitmap result = Bitmap.createBitmap(src_bitmap.getWidth(), (int) (src_bitmap.getHeight() * 1.5 + 10), Bitmap.Config.ARGB_8888);            //将原图和倒影图画到合成图上        Canvas canvas = new Canvas(result);        canvas.drawBitmap(src_bitmap, 0, 0, null);        canvas.drawBitmap(inverted_Bitmap, 0, src_bitmap.getHeight() + 10, null);        //3、设置遮罩效果        Paint paint = new Paint();            // 设置颜色        LinearGradient lg = new LinearGradient(0, (int) (src_bitmap.getHeight() + 10), 0, result.getHeight(), 0x70ffffff, 0x00ffffff, Shader.TileMode.CLAMP);        paint.setShader(lg);            // 设置模式为: 遮罩, 是取交集        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));        canvas.drawRect(0, (int) (src_bitmap.getHeight() + 5), src_bitmap.getWidth(), result.getHeight(), paint);        src_bitmap.recycle();        inverted_Bitmap.recycle();        return result;    }
xfermode的讲解请移步:http://blog.csdn.net/weiwozhiyi/article/details/50749622
       3、自定义Gallery

为了实现3D的效果需要覆盖protected boolean getChildStaticTransformation(View child, Transformation t)方法,通过为transformation设置动画来实现图片3D的浏览效果。

        t.clear();// 设置变换效果之前, 需要把Transformation中的上一个item的变换效果清楚        t.setTransformationType(Transformation.TYPE_MATRIX);// 设置变换效果的类型为矩阵类型
接下来通过使用camera来为图片设置放大、透明度、旋转的效果
    private void startTransformation(ImageView child, int rotateAngle, Transformation t) {        camera.save();// 保存状态        int absRotateAngle = Math.abs(rotateAngle);// 取旋转角度的绝对值        //1、放大效果(中间的图片要比两边的图片要大)        camera.translate(0, 0, 100);        int zoom = -250 + absRotateAngle*2 ;        camera.translate(0, 0, zoom);        //2、 透明度(中间的图片是完全显示, 两边有一定的透明度)        int alpha = 255 - 3 * absRotateAngle;        child.setAlpha(alpha);// 透明度取值范围: 0 ~ 255, 0 就是完全隐藏, 255 完全显示        //3、旋转(在中间的图片没有旋转角度, 只要不在中间就有旋转角度)        camera.rotateY(rotateAngle);        Matrix matrix = t.getMatrix();        // 给matrix赋值        camera.getMatrix(matrix);// 把matrix矩阵给camera对象, camera对象就会把上面添加的效果转换成矩阵添加到matrix对象中    

凡是大量用到Bitmap的地方都有可能发生OOM异常,为了解决OOM异常这里应用软引用来对图片进行缓存处理

强引用:    String s = "abc";    list.add(s);   软引用:    如果若引用对象回收完之后,内存还是报警,继续回收软引用对象,还是继续内存报警,    OOM outOfMemoryException内存溢出异常SoftReference<Bitmap> softReference = new SoftReference<Bitmap>(bitmap);弱引用:    如果虚引用对象回收完之后,内存还是报警,继续回收弱引用对象虚引用:    虚拟机的内存不够使用,开始报警,这时候垃圾回收机制开始执行System.gc();    String a = "a";(定义了之后没有用这个对象则回收它)    如果没有对象回收了,回收虚引用的对象
当然你如果不想自己去写这么多代码,github提供了3DGallery的库https://github.com/davidschreiber/FancyCoverFlow
使用步骤:

          1、布局文件引用

    <at.technikum.mti.fancycoverflow.FancyCoverFlow        android:id="@+id/fancy_converflow"        android:layout_width="match_parent"        android:layout_height="match_parent">            </at.technikum.mti.fancycoverflow.FancyCoverFlow>
           2、对自定义控件进行设置

        /**         * 当然你也可以在xml进行设置         *fcf:maxRotation="45"         *fcf:unselectedAlpha="0.3"         *fcf:unselectedSaturation="0.0"         *fcf:unselectedScale="0.4"         *fcf:scaleDownGravity="0.5"         */        fancy_converflow.setUnselectedAlpha(1.0f);//未选择的Item透明度        fancy_converflow.setUnselectedSaturation(0.0f);//未选中的饱和度        fancy_converflow.setUnselectedScale(0.5f);//未选中的缩放        fancy_converflow.setSpacing(20);//设置Item之间间隙        fancy_converflow.setMaxRotation(45);//设置最大的旋转角        fancy_converflow.setScaleDownGravity(0.5f);//从哪个位置进行缩放        fancy_converflow.setReflectionEnabled(true);        fancy_converflow.setReflectionRatio(0.3f);//倒影的比例        fancy_converflow.setReflectionGap(10);//倒影和原图的间距        fancy_converflow.setActionDistance(FancyCoverFlow.ACTION_DISTANCE_AUTO);

ViewPager实现

滑动ViewPager页面显示动画效果,你需要去实现ViewPager.PageTransform类,重写public void transformPage(View page, float position) {方法

在Android官方文档提供了两种:ZoomOutPageTransformer、DepthPageTransformer

1、ZoomOutPageTransformer

代码

   public void transformPage(View view, float position) {        int pageWidth = view.getWidth();        int pageHeight = view.getHeight();         if (position < -1) { // [-Infinity,-1)            // This page is way off-screen to the left.             view.setAlpha(0);         } else if (position <= 1) { // [-1,1]            // Modify the default slide transition to shrink the page as well             float scaleFactor = Math.max(MIN_SCALE, 1 - Math.abs(position));            float vertMargin = pageHeight * (1 - scaleFactor) / 2;            float horzMargin = pageWidth * (1 - scaleFactor) / 2;            if (position < 0) {                view.setTranslationX(horzMargin - vertMargin / 2);            } else {                 view.setTranslationX(-horzMargin + vertMargin / 2);            }              // Scale the page down (between MIN_SCALE and 1)             view.setScaleX(scaleFactor);            view.setScaleY(scaleFactor);             // Fade the page relative to its size.             view.setAlpha(MIN_ALPHA +                    (scaleFactor - MIN_SCALE) /                    (1 - MIN_SCALE) * (1 - MIN_ALPHA));         } else { // (1,+Infinity]             // This page is way off-screen to the right.             view.setAlpha(0);        }     } 

2、DepthPageTransformer

代码

    public void transformPage(View view, float position) {        int pageWidth = view.getWidth();         if (position < -1) { // [-Infinity,-1)            // This page is way off-screen to the left.             view.setAlpha(0);         } else if (position <= 0) { // [-1,0]            // Use the default slide transition when moving to the left page             view.setAlpha(1);            view.setTranslationX(0);            view.setScaleX(1);            view.setScaleY(1);         } else if (position <= 1) { // (0,1]            // Fade the page out.             view.setAlpha(1 - position);             // Counteract the default slide transition             view.setTranslationX(pageWidth * -position);             // Scale the page down (between MIN_SCALE and 1)             float scaleFactor = MIN_SCALE                    + (1 - MIN_SCALE) * (1 - Math.abs(position));            view.setScaleX(scaleFactor);            view.setScaleY(scaleFactor);         } else { // (1,+Infinity]             // This page is way off-screen to the right.             view.setAlpha(0);        }     } 
更多关于ViewPager的内容请看鸿洋大神的:http://blog.csdn.net/lmj623565791/article/details/40411921/
效果

在一个屏幕显示多个Page

        //页面宽度所占ViewPager的宽度的比例,默认为1        @Override        public float getPageWidth(int position) {            return 0.4f;        }
为每个Page添加间距

vp.setPageMargin(30);
代码如下:

public class CustomTransform implements ViewPager.PageTransformer {    private static final float MIN_SCALE=0.65f;    private int MAX_ROTATION = 40;    @Override    public void transformPage(View page, float position) {        float scaleFactor=Math.max(MIN_SCALE,1-Math.abs(position));        float rotate=20*Math.abs(position);        if (position<-1){            // This page is way off-screen to the left.        }else if (position <= 1){            // Modify the default slide transition to shrink the page as well            page.setScaleX(scaleFactor);            page.setScaleY(scaleFactor);            page.setRotationY(rotate);        }else if (position>1) {            // This page is way off-screen to the right.        }    }}

0 0