Android——ViewPager实现3D画廊效果(ViewPager的加载动画)

这个例子相信很多人已经接触过了,我今天觉得好玩自己写了写,参照了网上大家的一些例子,现在总结下自己的感受吧。

  • ViewPager的用法
  • android:clipChildren=”false”属性
  • ViewPager切换动画
  • 一些注意事项
  • 部分代码

ViewPager的基础用法

viewpager的实现还是比较简单的,viewpager中可以添加view,Activity和Fragment。添加Activity时要通过LocalActivityManager中startActivity(id,intent).getDecorView();方法来得多Activity对应的view;viewpager中添加Fragment时要使用FragmentViewPager。今天的例子我们使用最简单的添加view的方式来实现viewPager,所以我们使用PagerAdapter来为viewpager填充数据。

PagerAdapter中必须实现这四个方法:
(1)public int getCount()
(2)public Object instantiateItem(ViewGroup container, int position)
(3)public void destroyItem(ViewGroup container, int position, Object object)
(4)public boolean isViewFromObject(View view, Object object)

android:clipChildren=”false”属性

android:clipChildren的意思:是否限制子View在其范围内,默认值为true。在这个例子中我们想要实现画廊效果,所以android:clipChildren
设置为false,而且还必须是在ViewPager的父布局设置,否则没有效果的。同时注意要实现图片中的效果,ViewPager的宽度是不能设为match_parent的,ViewPager宽度与卡片的宽度设置一致即可。

viewpager切换动画

我们所看到的3D切换效果其实是通过设置viewPager的切换动画来实现的,我们可以多个不同的动画类来实现不同的切换效果,这里我会给出两个例子。效果如下图:

注意事项

1、上面提到的android:clipChildren很重要,如果不添加这个属性则无法实现画廊的效果,一个页面只能展示ViewPager的一个View。这个属性只要添加在ViewPager的父布局即可。
2、ViewPager每个View之间的间距问题,我这里使用了CardView来实现圆角的效果,一开始没有特别设置CardView的属性只加了圆角值,效果不甚满意,View之间的间距太小,后来添加app:cardUseCompatPadding=”true”属性,间距变大,这个属性的意思就是给CardView设置Padding,有兴趣的同学可以深入研究,这里我只介绍下这个属性,具体参考我CardView的文章。
3、xml布局文件要特别注意,ViewPager的宽度要和Item保持一致,不能是match_parent。
4、Item的上下间距可以通过Item的margin值来设置。

部分代码

1、gallery.xml


<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/white"
    android:clipChildren="false"
    android:gravity="center"
    android:layerType="software">

    <android.support.v4.view.ViewPager
        android:id="@+id/gallery"
        android:layout_width="200dp"
        android:layout_height="340dp"/>
LinearLayout>

这是个实现3D切换效果的动画,效果如下图:
Android——ViewPager实现3D画廊效果(ViewPager的加载动画)_第1张图片

public class MyTransformation implements PageTransformer {

    private static final float MIN_SCALE = 0.85f;
    private static final float MIN_ALPHA = 0.5f;
    private static final float MAX_ROTATE = 30;
    private Camera camera = new Camera();

    @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) {

        } else if (position < 0) {
            page.setScaleX(scaleFactor);
            page.setScaleY(scaleFactor);
            page.setRotationY(rotate);
        } else if (position >= 0 && position < 1) {
            page.setScaleX(scaleFactor);
            page.setScaleY(scaleFactor);
            page.setRotationY(-rotate);
        } else if (position >= 1) {
            page.setScaleX(scaleFactor);
            page.setScaleY(scaleFactor);
            page.setRotationY(-rotate);
        }
    }
}

这是个实现扁平切换,中间放大,两边模糊的动画,效果如下图:
Android——ViewPager实现3D画廊效果(ViewPager的加载动画)_第2张图片

public class ZoomOutPageTransformer implements ViewPager.PageTransformer {

    private static final float MIN_SCALE = 0.9f;
    private static final float MIN_ALPHA = 0.5f;

    private static float defaultScale = 0.9f;

    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);
            view.setScaleX(defaultScale);
            view.setScaleY(defaultScale);
        } 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);
            view.setScaleX(defaultScale);
            view.setScaleY(defaultScale);
        }
    }
}

这个类实现了图片效果:

public class ImageUtil {
    public static Bitmap getReverseBitmapById(int resId, Context context) {
        Bitmap sourceBitmap = BitmapFactory.decodeResource(context.getResources(), resId);
        Matrix matrix = new Matrix();
        matrix.setScale(1, -1);
        Bitmap inverseBitmap = Bitmap.createBitmap(sourceBitmap, 0, sourceBitmap.getHeight() / 2,
                sourceBitmap.getWidth(), sourceBitmap.getHeight() / 3, matrix, false);
        Bitmap groupbBitmap = Bitmap.createBitmap(sourceBitmap.getWidth(), sourceBitmap.getHeight
                () + sourceBitmap.getHeight() / 3 + 60, sourceBitmap.getConfig());
        Canvas gCanvas = new Canvas(groupbBitmap);
        gCanvas.drawBitmap(sourceBitmap, 0, 0, null);
        gCanvas.drawBitmap(inverseBitmap, 0, sourceBitmap.getHeight() + 100, null);
        Paint paint = new Paint();
        Shader.TileMode tileMode = Shader.TileMode.CLAMP;
        LinearGradient shader = new LinearGradient(0, sourceBitmap.getHeight() + 50, 0,
                groupbBitmap.getHeight(), Color.BLACK, Color.TRANSPARENT, tileMode);
        paint.setShader(shader);
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
        gCanvas.drawRect(0, sourceBitmap.getHeight() + 50, sourceBitmap.getWidth(), groupbBitmap
                .getHeight(), paint);
        return groupbBitmap;
    }
}
设置viewpager的切换动画
viewpager.setOffscreenPageLimit(5);
viewpager.setPageTransformer(true, new MyTransformation());
//viewpager.setPageTransformer(true, new ZoomOutPageTransformer());
将父布局的touch事件传递给viewpager,解决触摸滑动ViewPager左右两边的页面无反应的问题:
findViewById(R.id.activity_main).setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {
                return gallery.dispatchTouchEvent(motionEvent);
            }
        });
class GalleryAdapter extends PagerAdapter {
        private int selectPos = 0;
        private List viewList = new ArrayList();
        Integer[] images = {R.drawable.img0001, R.drawable.img0030,
                R.drawable.img0100, R.drawable.img0130, R.drawable.img0200,
                R.drawable.img0230, R.drawable.img0330, R.drawable.img0354};
        String[] names = {"电影", "冰封重生之门", "超人", "GOLD WAR", "寒颤", "别有动机", "变脸2", "韩国电影"};

        public GalleryAdapter() {

        }

        @Override
        public int getCount() {
            return images.length;
        }

        @Override
        public boolean isViewFromObject(View view, Object object) {
            return view == object;
        }

        @Override
        public Object instantiateItem(ViewGroup container, int position) {
            View view = LayoutInflater.from(Gallery.this).inflate(R.layout
                    .gallery_item, null);
            ImageView poster = (ImageView) view.findViewById(R.id.poster);
            poster.setImageResource(images[position]);
            // view.setImageBitmap(ImageUtil.getReverseBitmapById(images[i],Gallery.this));
            TextView name = (TextView) view.findViewById(R.id.name);
            name.setText(names[position]);
            viewpager.addView(view);
            return view;
        }

        @Override
        public void destroyItem(ViewGroup container, int position, Object object) {
            gallery.removeView((View) object);
        }
    }

今天写的有点匆忙,有空继续更新。

你可能感兴趣的:(Android,高仿我的身边的APP页面)