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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章