ViewPager实现图片轮播

图片轮播几乎是每个APP都会用到的功能,在这篇文章我用ViewPager实现一下这个功能。

先看一下最后的效果

这里写图片描述

支持左右两边图片轮流滑动,并且两秒自动滑动

首先看布局文件

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >

    <android.support.v4.view.ViewPager
        android:id="@+id/main_vp"
        android:layout_width="match_parent"
        android:layout_height="220dp">
    </android.support.v4.view.ViewPager>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignBottom="@id/main_vp"
        android:background="#33000000"
        android:orientation="vertical"
        android:padding="5dp"
        >

        <TextView
            android:id="@+id/main_description"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:text="我是图片的描述"
            android:textColor="@android:color/white"
            android:textSize="16sp"/>

        <LinearLayout
            android:id="@+id/main_point_group"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:orientation="horizontal"
           >
        </LinearLayout>
    </LinearLayout>


</RelativeLayout>

布局文件最外层是一个相对布局,然后定义一个高度为220dp,宽度为match_parent的ViewPager,在下面定义一个线性布局,线性布局上面是一个TextView,用来显示文字描述,下面是一个横向的线性布局,用来显示那些个圆点

图片和文字资源直接是定义好的

    private int[] imageIds = {R.drawable.a, R.drawable.b, R.drawable.c, R.drawable.d, R.drawable.e};
    private String[] imageDescriptions = {"巩俐不低俗,我就不能低俗",
            "扑树又回来啦!再唱经典老歌引万人大合唱", "揭秘北京电影如何升级", "乐视网TV版大派送", "热血屌丝的反杀"};

重写PagerAdapter

class MyPagerAdapter extends PagerAdapter {
        private List<ImageView> mImageList;

        public MyPagerAdapter(List<ImageView> imageList) {
            mImageList = imageList;
        }

        @Override
        public int getCount() {
            return mImageList.size();
        }

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

        @Override
        public Object instantiateItem(ViewGroup container, int position) {
            View view = mImageList.get(position);
            container.addView(view);
            return view;
        }

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

        }
    }

构造方法传递进来一个ImageView集合,很简单,PagerAdapter的写法就不说了。

初始化图片

  //初始化图片集合
        mImageViews = new ArrayList<>();
        for (int i = 0; i < imageIds.length; i++) {
            ImageView view = new ImageView(this);
            //为图片设置背景图片
            view.setBackgroundResource(imageIds[i]);
            //将图片添加到View集合中
            mImageViews.add(view);
        }

设置适配器

  //设置首个显示的文字
        mDescriptionTextView.setText(imageDescriptions[0]);
  //设置适配器
        mViewPager.setAdapter(new MyPagerAdapter(mImageViews));

设置滑动监听

到上面,就可以显示图片了,并且可以滑动了,但是文字并不会改变,所以我们要对ViewPager设置滑动监听

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

            }

            @Override
            public void onPageSelected(int position) {
                mDescriptionTextView.setText(imageDescriptions[position]);
            }

            @Override
            public void onPageScrollStateChanged(int state) {

            }

定义圆点样式

我们在drawable目录下自己定义圆点,一个是选中状态,一个是未选中状态。
定义一个point_normal.xml

<?xml version="1.0" encoding="utf-8"?>
<shape
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval"
    >
    <size android:width="6dp" android:height="6dp"></size>
    <solid android:color="#55000000"></solid>
</shape>

定义一个point_press.xml

<?xml version="1.0" encoding="utf-8"?>
<shape
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval">
    <size android:width="6dp" android:height="6dp"></size>
    <solid android:color="#aaffffff"></solid>
</shape>

然后再定义一个用来显示圆点的背景 point_bg.xml

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

当View的enable属性为true时,就显示point_press图标,若enable属性为false时,就显示point_normal图标。

增加圆点

增加圆点同样写在初始化图片那里

 for (int i = 0; i < imageIds.length; i++) {
            ImageView view = new ImageView(this);
            //为图片设置背景图片
            view.setBackgroundResource(imageIds[i]);
            //将图片添加到View集合中
            mImageViews.add(view);

            //初始化原点
            ImageView point=new ImageView(this);
            //设置原点的参数,高宽为warp_content
            LinearLayout.LayoutParams params=new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,LinearLayout.LayoutParams.WRAP_CONTENT);params.leftMargin=15;
            //设置上边距
            params.topMargin=2;

            //为原点设置参数
            point.setLayoutParams(params);
            //为原点设置背景
            point.setBackgroundResource(R.drawable.point_bg);
            if(i==0){
                //第一个原点设置为选中状态
                point.setEnabled(true);
            }else{
                //其他设为非选中状态
                point.setEnabled(false);
            }
            //添加到LinearLayout布局中
            mPointGroup.addView(point);
        }

当然在滑动监听器中也要设置原点的变化

定义一个mLastPosition来记录上一个显示的View,然后在ViewPager切换时将当前的View设位选中,将上一个设为正常状态,然后再次更新mLastPosition。

  @Override
            public void onPageSelected(int position) {
                mDescriptionTextView.setText(imageDescriptions[position]);
                mPointGroup.getChildAt(position).setEnabled(true);
                mPointGroup.getChildAt(mLastPosition).setEnabled(false);
                mLastPosition=position;

            }

到这里,带原点的ViewPager已经能正常运行了,但是有一个缺点,到最后一个就没办法往最后移了,在第一个就没办法向前移了,我们希望看到的是最后一个向后移能到第一个,第一个向前移能到最后一个。

我们知道PagerAdapter的getCount是获得ViewPager的View的个数,我们之前返回的是我们图片的个数,也就是5个View。如果我们让它返回一个Integer.Max值,也就是2^31-1,也就是我们告诉ViewPager我们有2^31-1个View,然后我们将ViewPager显示的第一个View设置为显示第(2^31-1)/2个,这样我们就可以向左向右无限滑动了。

  @Override
        public int getCount() {
            return Integer.MAX_VALUE;
        }

当然我们还需要在instantiateItem等地方做出改动,否则就数组越界了。

我们将position值对真正的数量取余,这样就可以循环显示这几个布局了。

  @Override
        public Object instantiateItem(ViewGroup container, int position) {
            int mPointion=position%mImageList.size();
            View view = mImageList.get(mPointion);
            container.addView(view);
            return view;
        }

设置显示的第一个View

 //使得显示的第一个View为第一张图片
        int mFirstPosition=Integer.MAX_VALUE / 2 -Integer.MAX_VALUE/2 % mImageViews.size();

 mViewPager.setCurrentItem(mFirstPosition);

当然也需要在滑动监听器那里做出改变


            @Override
            public void onPageSelected(int position) {
                int mPosition=position%mImageViews.size();
                mDescriptionTextView.setText(imageDescriptions[mPosition]);
                mPointGroup.getChildAt(mPosition).setEnabled(true);
                mPointGroup.getChildAt(mLastPosition).setEnabled(false);
                mLastPosition=mPosition;

            }

到这里就支持循环滑动了,这块可能说的不是很清楚,不过思路是很简单的。接下来实现自动滑动,当然用到了Handler机制。

 //发送一条2秒的延迟消息
  mHandler.sendEmptyMessageDelayed(1,2000);
 //定义一个Boolean值来记录是否自动轮播
    private boolean mIsAuto=false;
    private Handler mHandler=new Handler(){
        @Override
        public void handleMessage(Message msg) {
            mViewPager.setCurrentItem(mViewPager.getCurrentItem()+1);
            if(mIsAuto){
            //继续发送消息
               mHandler.sendEmptyMessageDelayed(1,2000);
            }
        }
    };

重写onDestroy方法,关闭自动轮播

 @Override
    protected void onDestroy() {
        super.onDestroy();
        mIsAuto=false;
    }

到这里图片轮播就完整实现了!

Demo地址

https://github.com/freshxu/MyBanner

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值