viewpager实现花式图片轮播

效果图

首先,让我们了解下什么是viewpager:

这个大致意思是:这个布局管理器允许用户左右翻转并传递页面的数据,你想要的视图可以通过pagerAdapter来实现。

布局文件:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="160dp"
    android:layout_centerInParent="true"
    android:background="#aadcff"
    android:clipChildren="false">

    <android.support.v4.view.ViewPager
        android:id="@+id/view_Pager"
        android:layout_width="match_parent"
        android:layout_height="120dp"
        android:layout_gravity="center"
        android:layout_marginLeft="60dp"
        android:layout_marginRight="60dp"
        android:clipChildren="false" />

    <RadioGroup
        android:id="@+id/radio_group"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal|bottom"
        android:layout_marginBottom="10dp"
        android:orientation="horizontal" />
</FrameLayout>

布局文件很简单,只有个用于展示图片的viewpager和用于同步展示图片的radioGroup

pagerAdapter

pagerAdapter是android.support.v4包中的类,它的子类有fragmentPagerAdapter、 fragmentStatePagerAdapter,这两个adapter都是fragment的适配器,用于实现fragment的滑动效果。

 PagerAdapter pagerAdapter = new PagerAdapter() {
        @Override
        public int getCount() {
            return Integer.MAX_VALUE;
//                return images.length;
        }

        @Override
        public boolean isViewFromObject(View view, Object object) {
            //判断当前要显示的画面
            return view == object;
        }

        @Override
        public Object instantiateItem(ViewGroup container, int position) {
            position = position % images.length;
            ImageView imageView = new ImageView(ViewPagerActivity.this);
            imageView.setImageResource(images[position]);
            imageView.setScaleType(ImageView.ScaleType.FIT_XY);
            container.addView(imageView);
            return imageView;
        }

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

pagerAdapter内有四个方法:

getCount():要滑动的图片数量,这里用Integer.MAX_VALUE,目的是为了实现无限轮播。

isViewFromObject():这个方法用于判断当前要显示的图片。

instantiateItem():调用这个方法用于图片初始化,将要显示的图片放到container中缓存,viewpager的setOffscreenPageLimit()方法用于设置缓存图片的数量。

destroyItem():当滑动的图片超出缓存范围,就会销毁缓存的图片。

PageTransformer

viewPager的pageTransformer是滑动图片的一个动画效果,viewPager提供setPageTransformer()这个方法用于设置动画。

 public class PageTransform implements ViewPager.PageTransformer {
        @Override
        public void transformPage(View view, float position) {
            if (position < -1) {
                //透明度
                view.setAlpha(mMinAlpha);
                //旋转
                view.setRotation(mMaxRotate * -1);
                view.setPivotX(view.getWidth());
                view.setPivotY(view.getHeight());
            } else if (position <= 1) {
                if (position < 0) {
                    //position是0到-1的变化,1+position就是从1到0的变化
                    //(1 - mMinAlpha) * (1 + position)就是(1 - mMinAlpha)到0的变化
                    //再加上一个mMinAlpha,就变为1到mMinAlpha的变化。
                    float factor = mMinAlpha + (1 - mMinAlpha) * (1 + position);
                    view.setAlpha(factor);

                    view.setRotation(mMaxRotate * position);
                    //position为width/2到width的变化
                    view.setPivotX(view.getWidth() * 0.5f * (1 - position));
                    view.setPivotY(view.getHeight());
                } else {
                    //minAlpha到1的变化
                    float factor = mMinAlpha + (1 - mMinAlpha) * (1 - position);
                    view.setAlpha(factor);

                    view.setRotation(mMaxRotate * position);
                    view.setPivotX(view.getWidth() * 0.5f * (1 - position));
                    view.setPivotY(view.getHeight());
                }
            } else {
                view.setAlpha(mMinAlpha);

                view.setRotation(mMaxRotate);
                view.setPivotX(0);
                view.setPivotY(view.getHeight());
            }
        }
    }

小圆圈的设置

 private void initRadioButton(int length) {
        for (int i = 0; i < length; i++) {
            ImageView imageView = new ImageView(ViewPagerActivity.this);
            imageView.setImageResource(R.drawable.rg_selector);
            imageView.setPadding(20, 0, 0, 0);
            radioGroup.addView(imageView, ViewGroup.LayoutParams.WRAP_CONTENT,
                    ViewGroup.LayoutParams.WRAP_CONTENT);
            radioGroup.getChildAt(0).setEnabled(false);
        }
    }

length就是轮播图片的数量。

rg_selctor:                state_enabled:是否处于可用状态

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/rb_default" android:state_enabled="false" />
    <item android:drawable="@drawable/rb_select" android:state_enabled="true" />
</selector>

rb_default:

<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval">
    <solid android:color="@color/colorPrimaryDark" />
    <size
        android:width="20dp"
        android:height="20dp" />
</shape>

rb_select:

<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval">
    <solid android:color="#ffffff" />
    <size
        android:width="20dp"
        android:height="20dp" />
</shape>

pager改变时的监听

ViewPager.OnPageChangeListener onPageChangeListener = new ViewPager.OnPageChangeListener() {
        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

        }

        @Override
        public void onPageSelected(int position) {
            index = position;
            setCurrentDot(index % images.length);
        }

        @Override
        public void onPageScrollStateChanged(int state) {

        }
    };
 private void setCurrentDot(int i) {
        if (radioGroup.getChildAt(i) != null) {
            //当前按钮不可改变
            radioGroup.getChildAt(i).setEnabled(false);
        }
        if (radioGroup.getChildAt(preIndex) != null) {
            //上个按钮可以改变
            radioGroup.getChildAt(preIndex).setEnabled(true);
            //当前位置变为上一个,继续下次轮播
            preIndex = i;
        }
    }

轮播时间设置

 timer.schedule(new TimerTask() {
            @Override
            public void run() {
                if (isContinue) {
                    handler.sendEmptyMessage(1);
                }
            }
        }, 2000, 2000);

schedule()方法第三个参数是图片轮播完后多久再次执行run()方法,这里设置两秒,跟延时一致,图片会完美轮播下去。

Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case 1:
                    index++;
                    viewPager.setCurrentItem(index);
            }
        }
    };

handler调用handleMessage()方法处理消息。

完整代码

public class ViewPagerActivity extends AppCompatActivity {

    private ViewPager viewPager;
    private int images[] = {R.drawable.img01, R.drawable.img02, R.drawable.img03,
            R.drawable.img04, R.drawable.img05, R.drawable.img06};
    private RadioGroup radioGroup;
    //当前索引位置以及上一个索引位置
    private int index;
    private int preIndex;
    private Timer timer = new Timer();
    //是否需要轮播标志
    private boolean isContinue = true;

    private static final float DEFAULT_MIN_ALPHA = 0.3f;
    private float mMinAlpha = DEFAULT_MIN_ALPHA;

    private static final float DEFAULT_MAX_ROTATE = 15.0f;
    private float mMaxRotate = DEFAULT_MAX_ROTATE;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_view_image);

        viewPager = (ViewPager) findViewById(R.id.view_Pager);
        radioGroup = (RadioGroup) findViewById(R.id.radio_group);
        //设置page之间间距
        viewPager.setPageMargin(30);
        //设置缓存的页面数量
        viewPager.setOffscreenPageLimit(3);
        viewPager.setAdapter(pagerAdapter);
        viewPager.addOnPageChangeListener(onPageChangeListener);
        viewPager.setPageTransformer(true, new PageTransform());
        viewPager.setCurrentItem(images.length * 100);
        initRadioButton(images.length);

        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                if (isContinue) {
                    handler.sendEmptyMessage(1);
                }
            }
        }, 2000, 2000);
    }

    PagerAdapter pagerAdapter = new PagerAdapter() {
        @Override
        public int getCount() {
            return Integer.MAX_VALUE;
//                return images.length;
        }

        @Override
        public boolean isViewFromObject(View view, Object object) {
            //判断当前要显示的画面
            return view == object;
        }

        @Override
        public Object instantiateItem(ViewGroup container, int position) {
            position = position % images.length;
            ImageView imageView = new ImageView(ViewPagerActivity.this);
            imageView.setImageResource(images[position]);
            imageView.setScaleType(ImageView.ScaleType.FIT_XY);
            container.addView(imageView);
            return imageView;
        }

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

    /**
     * [-Infinity,-1)(1,+Infinity][-1,1]
     * 三个区间,对于前两个,拿我们的页面上目前显示的3个Page来说,前两个分别对应左右两个露出一点的Page,
     * 那么对于alpha值,只需要设置为最小值即可
     * <p>
     * [-1,1]第一页->第二页这个过程来说,主要看position的变化
     * 页1的position变化为:从0到-1, 页2的position变化为:从1到0
     * 第一页到第二页,实际上就是左滑,第一页到左边,第二页成为currentItem到达中间,
     * 那么对应alpha的变化应该是:页1到左边,对应alpha应该是:1到minAlpha
     * 页2到中间,成为currentItem,对应alpha应该是:minAlpha到1
     */
    public class PageTransform implements ViewPager.PageTransformer {
        @Override
        public void transformPage(View view, float position) {
            if (position < -1) {
                //透明度
                view.setAlpha(mMinAlpha);
                //旋转
                view.setRotation(mMaxRotate * -1);
                view.setPivotX(view.getWidth());
                view.setPivotY(view.getHeight());
            } else if (position <= 1) {
                if (position < 0) {
                    //position是0到-1的变化,1+position就是从1到0的变化
                    //(1 - mMinAlpha) * (1 + position)就是(1 - mMinAlpha)到0的变化
                    //再加上一个mMinAlpha,就变为1到mMinAlpha的变化。
                    float factor = mMinAlpha + (1 - mMinAlpha) * (1 + position);
                    view.setAlpha(factor);

                    view.setRotation(mMaxRotate * position);
                    //position为width/2到width的变化
                    view.setPivotX(view.getWidth() * 0.5f * (1 - position));
                    view.setPivotY(view.getHeight());
                } else {
                    //minAlpha到1的变化
                    float factor = mMinAlpha + (1 - mMinAlpha) * (1 - position);
                    view.setAlpha(factor);

                    view.setRotation(mMaxRotate * position);
                    view.setPivotX(view.getWidth() * 0.5f * (1 - position));
                    view.setPivotY(view.getHeight());
                }
            } else {
                view.setAlpha(mMinAlpha);

                view.setRotation(mMaxRotate);
                view.setPivotX(0);
                view.setPivotY(view.getHeight());
            }
        }
    }

    private void initRadioButton(int length) {
        for (int i = 0; i < length; i++) {
            ImageView imageView = new ImageView(ViewPagerActivity.this);
            imageView.setImageResource(R.drawable.rg_selector);
            imageView.setPadding(20, 0, 0, 0);
            radioGroup.addView(imageView, ViewGroup.LayoutParams.WRAP_CONTENT,
                    ViewGroup.LayoutParams.WRAP_CONTENT);
            radioGroup.getChildAt(0).setEnabled(false);
        }
    }

    ViewPager.OnPageChangeListener onPageChangeListener = new ViewPager.OnPageChangeListener() {
        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

        }

        @Override
        public void onPageSelected(int position) {
            index = position;
            setCurrentDot(index % images.length);
        }

        @Override
        public void onPageScrollStateChanged(int state) {

        }
    };

    private void setCurrentDot(int i) {
        if (radioGroup.getChildAt(i) != null) {
            //当前按钮不可改变
            radioGroup.getChildAt(i).setEnabled(false);
        }
        if (radioGroup.getChildAt(preIndex) != null) {
            //上个按钮可以改变
            radioGroup.getChildAt(preIndex).setEnabled(true);
            //当前位置变为上一个,继续下次轮播
            preIndex = i;
        }
    }

    Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case 1:
                    index++;
                    viewPager.setCurrentItem(index);
            }
        }
    };

}

猜你喜欢

转载自blog.csdn.net/qq_35820350/article/details/81383602