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

<?xml version="1.0" encoding="utf-8"?>
<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切换效果的动画,效果如下图:

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);
        }
    }
}

这是个实现扁平切换,中间放大,两边模糊的动画,效果如下图:

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<View> viewList = new ArrayList<View>();
        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);
        }
    }

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

  • 3
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
ViewPager是一个Android中的View容器,可以让用户在多个页面之间进行滑动切换。要实现多页面滑动切换以及动画效果,可以按照以下步骤: 1. 在XML布局文件中添加ViewPager控件,并添加对应的布局文件,例如: ``` <android.support.v4.view.ViewPager android:id="@+id/viewPager" android:layout_width="match_parent" android:layout_height="match_parent" /> ``` 2. 在Java代码中为ViewPager设置Adapter,用于显示多个页面。例如: ``` ViewPager viewPager = findViewById(R.id.viewPager); MyPagerAdapter adapter = new MyPagerAdapter(getSupportFragmentManager()); viewPager.setAdapter(adapter); ``` 其中,MyPagerAdapter是自定义的PagerAdapter类,需要继承自FragmentPagerAdapter或FragmentStatePagerAdapter。 3. 在自定义的PagerAdapter类中实现getItem()方法,用于返回每个页面的Fragment实例。例如: ``` @Override public Fragment getItem(int position) { switch (position) { case 0: return new Fragment1(); case 1: return new Fragment2(); case 2: return new Fragment3(); default: return null; } } ``` 其中,Fragment1、Fragment2、Fragment3是自定义的Fragment类,用于显示对应页面的内容。 4. 如果需要添加页面切换的动画效果,可以在Java代码中为ViewPager设置PageTransformer。例如: ``` viewPager.setPageTransformer(true, new DepthPageTransformer()); ``` 其中,DepthPageTransformer是自定义的PageTransformer类,用于实现页面切换时的动画效果。可以参考以下代码示例: ``` public class DepthPageTransformer implements ViewPager.PageTransformer { private static final float MIN_SCALE = 0.75f; 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(0f); } else if (position <= 0) { // [-1,0] // Use the default slide transition when moving to the left page view.setAlpha(1f); view.setTranslationX(0f); view.setScaleX(1f); view.setScaleY(1f); } 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(0f); } } } ``` 以上就是实现AndroidViewPager多页面滑动切换以及动画效果的步骤。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值