Android中ViewPager的基本用法:圖片輪播小案例

效果圖如下:

viewpager.gif

xml布局文件

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

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

    </android.support.v4.view.ViewPager>

    <LinearLayout
        android:layout_alignBottom="@id/view_pager"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:background="#77000000"
        android:padding="5dp"
        android:gravity="center_horizontal"
        android:orientation="vertical">

        <TextView
            android:id="@+id/tv_image_desc"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="16sp"
            android:textColor="#bbffffff"
            android:text="我是圖片描述信息"/>
    </LinearLayout>
</RelativeLayout>

代碼的實(shí)現(xiàn)


工程結(jié)構(gòu)如下圖

工程結(jié)構(gòu).png

第一步:初始化數(shù)據(jù)

/**
 *初始化數(shù)據(jù)
 */
//初始化圖片輪播的圖片
private void initData() {
    int[] imageResIDs = {
            R.mipmap.a,
            R.mipmap.b,
            R.mipmap.c,
            R.mipmap.d,
            R.mipmap.e
    };
    mImageList = new ArrayList<>();
    ImageView iv;
    for (int i = 0; i < imageResIDs.length; i++) {
        iv = new ImageView(this);
        iv.setBackgroundResource(imageResIDs[i]);
        mImageList.add(iv);
        
        //初始化顯示每張圖片下面現(xiàn)實(shí)的文字
        imageDescs= new String[]{
                "今年二十七八歲,我最喜歡的事就是睡覺(jué)",
                "懶蟲(chóng)具练,起床了,要上班了",
                "我翻了個(gè)身,想著如果今天是周末多好",
                "終于爬起來(lái)瓣铣,坐在沙發(fā)上一臉懵逼",
                "一個(gè)人早餐就隨便吃點(diǎn)"
        };
    }
}

第二步:設(shè)置viewpager適配器

    /**
    *新建一個(gè)adapter包,新建適配類(lèi)如下
    */
public class MyPagerAdapter extends PagerAdapter {
    private List<ImageView> imageList;
    private ViewPager viewPager;

    public MyPagerAdapter(List<ImageView> imageList, ViewPager viewPager) {
        this.imageList = imageList;
        this.viewPager = viewPager;
    }

    /**
     * 返回的int的值, 會(huì)作為ViewPager的總長(zhǎng)度來(lái)使用.
     */
    @Override
    public int getCount() {
        return Integer.MAX_VALUE;//Integer.MAX_VALUE偽無(wú)限循環(huán)
    }

    /**
     * 判斷是否使用緩存, 如果返回的是true, 使用緩存. 不去調(diào)用instantiateItem方法創(chuàng)建一個(gè)新的對(duì)象
     */
    @Override
    public boolean isViewFromObject(View view, Object object) {
        return view == object;
    }

    /**
     * 初始化一個(gè)條目
     * position 就是當(dāng)前需要加載條目的索引
     */
    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        // 把position對(duì)應(yīng)位置的ImageView添加到ViewPager中
        ImageView iv = imageList.get(position % imageList.size());
        viewPager.addView(iv);
        // 把當(dāng)前添加ImageView返回回去.
        return iv;
    }

    /**
     * 銷(xiāo)毀一個(gè)條目
     * position 就是當(dāng)前需要被銷(xiāo)毀的條目的索引
     */
    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        // 把ImageView從ViewPager中移除掉
        viewPager.removeView(imageList.get(position % imageList.size()));
    }
}

第三步:給viewpager設(shè)置輪播監(jiān)聽(tīng)器

/**
 * 當(dāng)ViewPager頁(yè)面被選中時(shí), 觸發(fā)此方法.
 * @param position 當(dāng)前被選中的頁(yè)面的索引
 */
@Override
public void onPageSelected(int position) {
    //偽無(wú)限循環(huán),滑到最后一張圖片又從新進(jìn)入第一張圖片
    int newPosition = position % mImageList.size();

    // 把當(dāng)前選中的點(diǎn)給切換了, 還有描述信息也切換
    mTvImageDesc.setText(imageDescs[newPosition]);//圖片下面設(shè)置顯示文本

    // 把當(dāng)前的索引賦值給前一個(gè)索引變量, 方便下一次再切換.
    previousPosition = newPosition;
}

@Override
public void onPageScrollStateChanged(int state) {

}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

}

第四步:設(shè)置剛打開(kāi)app時(shí)顯示的圖片和文字

/**
 * 設(shè)置剛進(jìn)入app時(shí)贷揽,顯示的圖片和文字
 */
private void setFirstLocation() {
    mTvImageDesc.setText(imageDescs[previousPosition]);
    // 把ViewPager設(shè)置為默認(rèn)選中Integer.MAX_VALUE / 2棠笑,從十幾億次開(kāi)始輪播圖片,達(dá)到無(wú)限循環(huán)目的;
    int m = (Integer.MAX_VALUE / 2) % mImageList.size();
    int currentPosition = Integer.MAX_VALUE / 2 - m;
    mViewPager.setCurrentItem(currentPosition);
}

第五步: 設(shè)置自動(dòng)播放,每隔3秒換一張圖片

/**
 * 每隔3秒自動(dòng)播放圖片
 */
private void autoPlayView() {
    //自動(dòng)播放圖片
    new Thread(new Runnable() {
        @Override
        public void run() {
            while (!isStop){
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        mViewPager.setCurrentItem(mViewPager.getCurrentItem() + 1);
                    }
                });
                SystemClock.sleep(3000);
            }
        }
    }).start();
}

第六步: 當(dāng)Activity銷(xiāo)毀時(shí)取消圖片自動(dòng)播放

/**
 *當(dāng)Activity銷(xiāo)毀時(shí)取消圖片自動(dòng)播放
 */
@Override
protected void onDestroy() {
    super.onDestroy();
    isStop = true;
}

細(xì)節(jié)問(wèn)題處理

如果發(fā)現(xiàn)左邊圖片的索引是負(fù)數(shù), 小于0, 就不會(huì)預(yù)加載.
如果發(fā)現(xiàn)右邊的圖片是索引是大于等于總圖片的個(gè)數(shù)禽绪,也不會(huì)預(yù)加載. 例如:總圖片是:5, 右邊的圖片是第6張蓖救。

圖片無(wú)限循環(huán)實(shí)現(xiàn)

1.設(shè)置是適配器返回的長(zhǎng)度為Integer的最大值
@Override
    public int getCount() {
        return Integer.MAX_VALUE;
    }
2.將position設(shè)置為如下
//偽無(wú)限循環(huán),滑到最后一張圖片又從新進(jìn)入第一張圖片
    int newPosition = position % mImageList.size();

附上全部的代碼

MainActiviy

public class MainActivity extends AppCompatActivity implements ViewPager.OnPageChangeListener{

    @BindView(R.id.view_pager)
    ViewPager mViewPager;
    @BindView(R.id.tv_image_desc)
    TextView mTvImageDesc;
    private List<ImageView> mImageList;
    private String[] imageDescs;
    private int previousPosition = 0; // 前一個(gè)被選中的position
    private boolean isStop = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);
        initView();
        autoPlayView();


    }

    /**
     * 第五步: 設(shè)置自動(dòng)播放,每隔3秒換一張圖片
     */
    private void autoPlayView() {
        //自動(dòng)播放圖片
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (!isStop){
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            mViewPager.setCurrentItem(mViewPager.getCurrentItem() + 1);
                        }
                    });
                    SystemClock.sleep(3000);
                }
            }
        }).start();
    }

    private void initView() {
        initData();
        MyPagerAdapter mAdapter = new MyPagerAdapter(mImageList, mViewPager);
        mViewPager.setAdapter(mAdapter);//第二步:設(shè)置viewpager適配器
        mViewPager.addOnPageChangeListener(this);
        setFirstLocation();
    }

    /**
     * 第四步:設(shè)置剛打開(kāi)app時(shí)顯示的圖片和文字
     */
    private void setFirstLocation() {
        mTvImageDesc.setText(imageDescs[previousPosition]);
        // 把ViewPager設(shè)置為默認(rèn)選中Integer.MAX_VALUE / 2丐一,從十幾億次開(kāi)始輪播圖片藻糖,達(dá)到無(wú)限循環(huán)目的;
        int m = (Integer.MAX_VALUE / 2) % mImageList.size();
        int currentPosition = Integer.MAX_VALUE / 2 - m;
        mViewPager.setCurrentItem(currentPosition);
    }

    /**
     * 第一步:初始化數(shù)據(jù)
     */
    //初始化圖片輪播的圖片
    private void initData() {
        int[] imageResIDs = {
                R.mipmap.a,
                R.mipmap.b,
                R.mipmap.c,
                R.mipmap.d,
                R.mipmap.e
        };
        mImageList = new ArrayList<>();
        ImageView iv;
        for (int i = 0; i < imageResIDs.length; i++) {
            iv = new ImageView(this);
            iv.setBackgroundResource(imageResIDs[i]);
            mImageList.add(iv);

            //初始化顯示每張圖片下面現(xiàn)實(shí)的文字
            imageDescs= new String[]{
                    "今年二十七八歲,我最喜歡的事就是睡覺(jué)",
                    "懶蟲(chóng)库车,起床了巨柒,要上班了",
                    "我翻了個(gè)身,想著如果今天是周末多好",
                    "終于爬起來(lái)柠衍,坐在沙發(fā)上一臉懵逼",
                    "一個(gè)人早餐就隨便吃點(diǎn)"
            };
        }
    }


    /**
     * 第三步:給viewpager設(shè)置輪播監(jiān)聽(tīng)器
     * viewpager的監(jiān)聽(tīng)器
     * 當(dāng)ViewPager頁(yè)面被選中時(shí), 觸發(fā)此方法.
     * @param position 當(dāng)前被選中的頁(yè)面的索引
     */
    @Override
    public void onPageSelected(int position) {
        //偽無(wú)限循環(huán)洋满,滑到最后一張圖片又從新進(jìn)入第一張圖片
        int newPosition = position % mImageList.size();

        // 把當(dāng)前選中的點(diǎn)給切換了, 還有描述信息也切換
        mTvImageDesc.setText(imageDescs[newPosition]);//圖片下面設(shè)置顯示文本

        // 把當(dāng)前的索引賦值給前一個(gè)索引變量, 方便下一次再切換.
        previousPosition = newPosition;
    }

    @Override
    public void onPageScrollStateChanged(int state) {

    }
    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

    }
    
    /**
     * 第六步: 當(dāng)Activity銷(xiāo)毀時(shí)取消圖片自動(dòng)播放
     */
    @Override
    protected void onDestroy() {
        super.onDestroy();
        isStop = true;
    }
}

MyPagerAdapter

public class MyPagerAdapter extends PagerAdapter {
    private List<ImageView> imageList;
    private ViewPager viewPager;

    public MyPagerAdapter(List<ImageView> imageList, ViewPager viewPager) {
        this.imageList = imageList;
        this.viewPager = viewPager;
    }

    /**
     * 返回的int的值, 會(huì)作為ViewPager的總長(zhǎng)度來(lái)使用.
     */
    @Override
    public int getCount() {
        return Integer.MAX_VALUE;//Integer.MAX_VALUE偽無(wú)限循環(huán)
    }

    /**
     * 判斷是否使用緩存, 如果返回的是true, 使用緩存. 不去調(diào)用instantiateItem方法創(chuàng)建一個(gè)新的對(duì)象
     */
    @Override
    public boolean isViewFromObject(View view, Object object) {
        return view == object;
    }

    /**
     * 初始化一個(gè)條目
     * position 就是當(dāng)前需要加載條目的索引
     */
    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        // 把position對(duì)應(yīng)位置的ImageView添加到ViewPager中
        ImageView iv = imageList.get(position % imageList.size());
        viewPager.addView(iv);
        // 把當(dāng)前添加ImageView返回回去.
        return iv;
    }

    /**
     * 銷(xiāo)毀一個(gè)條目
     * position 就是當(dāng)前需要被銷(xiāo)毀的條目的索引
     */
    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        // 把ImageView從ViewPager中移除掉
        viewPager.removeView(imageList.get(position % imageList.size()));
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市珍坊,隨后出現(xiàn)的幾起案子牺勾,更是在濱河造成了極大的恐慌,老刑警劉巖阵漏,帶你破解...
    沈念sama閱讀 211,884評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件驻民,死亡現(xiàn)場(chǎng)離奇詭異翻具,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)回还,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,347評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén)裆泳,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人柠硕,你說(shuō)我怎么就攤上這事工禾。” “怎么了蝗柔?”我有些...
    開(kāi)封第一講書(shū)人閱讀 157,435評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵闻葵,是天一觀(guān)的道長(zhǎng)。 經(jīng)常有香客問(wèn)我癣丧,道長(zhǎng)槽畔,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,509評(píng)論 1 284
  • 正文 為了忘掉前任坎缭,我火速辦了婚禮竟痰,結(jié)果婚禮上签钩,老公的妹妹穿的比我還像新娘掏呼。我一直安慰自己,他們只是感情好铅檩,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,611評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布憎夷。 她就那樣靜靜地躺著,像睡著了一般昧旨。 火紅的嫁衣襯著肌膚如雪拾给。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,837評(píng)論 1 290
  • 那天兔沃,我揣著相機(jī)與錄音蒋得,去河邊找鬼。 笑死乒疏,一個(gè)胖子當(dāng)著我的面吹牛额衙,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播怕吴,決...
    沈念sama閱讀 38,987評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼窍侧,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了转绷?” 一聲冷哼從身側(cè)響起伟件,我...
    開(kāi)封第一講書(shū)人閱讀 37,730評(píng)論 0 267
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎议经,沒(méi)想到半個(gè)月后斧账,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體谴返,經(jīng)...
    沈念sama閱讀 44,194評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,525評(píng)論 2 327
  • 正文 我和宋清朗相戀三年咧织,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了亏镰。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片拯爽。...
    茶點(diǎn)故事閱讀 38,664評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡索抓,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出毯炮,到底是詐尸還是另有隱情桃煎,我是刑警寧澤三椿,帶...
    沈念sama閱讀 34,334評(píng)論 4 330
  • 正文 年R本政府宣布搜锰,位于F島的核電站耿战,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏鸭栖。R本人自食惡果不足惜晕鹊,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,944評(píng)論 3 313
  • 文/蒙蒙 一捏题、第九天 我趴在偏房一處隱蔽的房頂上張望公荧。 院中可真熱鬧循狰,春花似錦关炼、人聲如沸社痛。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,764評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春约急,著一層夾襖步出監(jiān)牢的瞬間厌蔽,已是汗流浹背择浊。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,997評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工师脂, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留吃警,地道東北人汤徽。 一個(gè)月前我還...
    沈念sama閱讀 46,389評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像芳誓,于是被迫代替她去往敵國(guó)和親挟憔。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,554評(píng)論 2 349

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,790評(píng)論 25 707
  • 內(nèi)容抽屜菜單ListViewWebViewSwitchButton按鈕點(diǎn)贊按鈕進(jìn)度條TabLayout圖標(biāo)下拉刷新...
    皇小弟閱讀 46,729評(píng)論 22 665
  • 近日親媽使勁兒跟我無(wú)理取鬧她紫,鬧得我很是心焦。 都是小事,當(dāng)然都是小事雹食。無(wú)非就是她為了省錢(qián)去超市買(mǎi)的散裝米吃起來(lái)有霉...
    溫柔寒江雪閱讀 1,158評(píng)論 4 4
  • 當(dāng)時(shí)看電影竟然沒(méi)有愛(ài)上的 又回來(lái)了 Sally's song
    喃言閱讀 247評(píng)論 0 0
  • ?模式名稱(chēng):特邀嘉賓(Royal audience) 總結(jié): 安排管理層虽画、公司同事與受邀而來(lái)做專(zhuān)家推動(dòng)的嘉賓(大人...
    from1to100閱讀 223評(píng)論 0 0