1. 程式人生 > >Android ViewPager控制元件

Android ViewPager控制元件

前言

ViewPager可以實現多個介面的左右滑動。

1. ViewPager簡單應用

(1) 佈局檔案

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

(2) 介面卡,需要繼承PagerAdapter類

public static class DemoPageAdapter extends PagerAdapter {
    private List<View> mViewList = new ArrayList<>();

    public DemoPageAdapter(Context context) {
        for (int index = 0; index < 4; index++) {
            TextView view = (TextView) View.inflate(context, R.layout.viewpager_text, null);
            view.setText("第" + index + "頁");
            mViewList.add(view);
        }
    }

    // 返回介面數量
    @Override
    public int getCount() {
        return mViewList.size();
    }

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

    // 新增介面,一般會添加當前頁和左右兩邊的頁面
    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        container.addView(mViewList.get(position));
        return mViewList.get(position);
    }

    // 去除頁面
    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        container.removeView(mViewList.get(position));
    }

}

(3) 設定介面卡

ViewPager viewPager = findViewById(R.id.view_pager);
viewPager.setAdapter(new DemoPageAdapter(this));

(4) 效果如下
在這裡插入圖片描述

2. OnPageChangeListener監聽器

OnPageChangeListener有三個方法

(1) onPageScrolled方法,顯示滑動時頁面狀態。

public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels)
  • 手勢從左往右滑動,position為前一頁面,positionOffset從1到0。
  • 手勢從右往左滑動,position為當前頁面,positionOffset從0到1。

(2) onPageSelected方法,position是被選擇頁面

public void onPageSelected(int position)

(3) onPageScrollStateChanged方法,

public void onPageScrollStateChanged(int state)

state有三種狀態

  • SCROLL_STATE_IDLE,靜止狀態。
  • SCROLL_STATE_DRAGGING,開始拖曳。
  • SCROLL_STATE_SETTLING,停止拖曳。

3. 迴圈的ViewPager

如何實現迴圈的ViewPager,我們需要在邊界的時候做一些特殊處理。

(1) 在第一個頁面之前和最後一個頁面之後,分別新增一個介面,這樣才能實現迴圈。

public static class CyclePageAdapter extends PagerAdapter {
    private List<View> mViewList = new ArrayList<>();

    public CyclePageAdapter(Context context) {
        for (int index = 0; index < 4; index++) {
            TextView view = (TextView) View.inflate(context, R.layout.viewpager_text, null);
            view.setText("第" + index + "頁");
            mViewList.add(view);
        }
    }

    // 返回介面數量+2
    @Override
    public int getCount() {
        return mViewList.size() + 2;
    }

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

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        View view;
        if (position == 0) {
            // 第一個介面,選擇原來的最後一個介面
            view = mViewList.get(mViewList.size() - 1);
        } else if (position == mViewList.size() + 1) {
            // 最後一個介面,選擇原來的第一個介面
            view = mViewList.get(0);
        } else {
            // 原有的依次從0開始
            view = mViewList.get(position - 1);
        }
        // 頁面如果重複新增,會發生異常
        try {
            container.addView(view);
        } catch (Exception e) {
        }
        return view;
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        // 不在刪除頁面
    }

}

(2) 到達實際邊界以後,切換當前頁。

final ViewPager viewPager = findViewById(R.id.view_pager);
final PagerAdapter adapter = new CyclePageAdapter(this);
viewPager.setAdapter(adapter);
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {

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

    @Override
    public void onPageSelected(int position) {
    }

    @Override
    public void onPageScrollStateChanged(int state) {
        if (state == ViewPager.SCROLL_STATE_IDLE) {
            int position = viewPager.getCurrentItem();
            if (position == 0) {
                // 第一個介面,切換到原來的最後一個介面
                viewPager.setCurrentItem(adapter.getCount() - 2, false);
            } else if (position == adapter.getCount() - 1) {
                // 最後一個介面,切換到原來的第一個介面
                viewPager.setCurrentItem(1, false);
            }
        }
    }
});
// 初始頁為1
viewPager.setCurrentItem(1);

(3) 效果如下
在這裡插入圖片描述

4. PageTransformer實現個性的切換動畫

transformPage(View page, float position)方法實現不一樣的動畫,

  • 手勢從右往左滑動,當前頁面position從0->-1,而下一頁面position從1->0。
  • 手勢從左往右滑動,當前頁面position為0->1,而前一頁面position從-1->0。

定義一個動畫,前一頁面左右移動,而後一頁面位置不變但伸縮顯示。

private class DemoPageTransformer implements ViewPager.PageTransformer {

    @Override
    public void transformPage(View page, float position) {
        if (position < -1) {
            page.setAlpha(0);
        } else if (position <= 0) {
            // 左右移動,並且移除時變透明
            page.setAlpha(1 + position);
        } else if (position < 1) {
            // 去除左右移動效果
            page.setTranslationX(-page.getWidth() * position);
            // 進入時變大,移除時變小
            page.setScaleX(1 - position/2);
            page.setScaleY(1 - position/2);
            page.setAlpha(1 - position);
        } else {
            page.setAlpha(0);
        }
    }
}

效果如下
在這裡插入圖片描述

5. 自定義廣告頁

廣告頁長被用於首頁,可以自己切換,也可以手動切換。
使用ViewPager實現廣告頁,主要是要判斷是否在手動切換,可以新增OnPageChangeListener來判斷。

mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
    private boolean mDragging = false;
    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
    }

    @Override
    public void onPageSelected(int position) {
    }

    @Override
    public void onPageScrollStateChanged(int state) {
        if (state == ViewPager.SCROLL_STATE_IDLE && mDragging) {
            mHandler.sendEmptyMessageDelayed(MOVE_TO_NEXT, 3000);
            mDragging = false;
        } else if (state == ViewPager.SCROLL_STATE_DRAGGING){
            mHandler.removeMessages(MOVE_TO_NEXT);
            mDragging = true;
        }
    }
});
mHandler.sendEmptyMessageDelayed(MOVE_TO_NEXT, 3000);

Handler類處理自動切換事件

private static final int MOVE_TO_NEXT = 1;

private Handler mHandler = new Handler() {

    @Override
    public void handleMessage(Message msg) {
        if (msg.what == MOVE_TO_NEXT) {
            int item = mViewPager.getCurrentItem();
            if (++item >= mAdapter.getCount()) {
                item = 0;
            }
            mViewPager.setCurrentItem(item);
            mHandler.sendEmptyMessageDelayed(MOVE_TO_NEXT, 3000);
        }
    }
};