1. 程式人生 > >ViewPager系列之ViewPager一屏顯示多個子頁面

ViewPager系列之ViewPager一屏顯示多個子頁面

ViewPager一屏顯示多個子頁面,常見的有兩種形式:

1、當前展示的頁面右側顯示一部分下個頁面的內容

這裡寫圖片描述

2、當前頁面居中,左右兩邊分別顯示上一個頁面、下一個頁面

這裡寫圖片描述

第 1 種表現形式的實現程式碼

其實這種效果很容易實現,谷歌給我們提供了方法,只需要在adapter中重寫這個方法就可以了。  
/**
 * Returns the proportional width of a given page as a percentage of the
 * ViewPager's measured width from (0.f-1.f]
返回給定的頁面所佔ViewPager 測量寬度的比例,範圍(0,1]
 *
 * @param
position The position of the page requested * @return Proportional width for the given page position */
public float getPageWidth(int position) { return 1.f;//預設值 }

Adapter 程式碼,重寫 getPageWidth(int position) 方法

public class MultiplePagerAdapter extends PagerAdapter {
    private List<Integer> mList;
    private
LayoutInflater layoutInflater; public MultiplePagerAdapter(Context context, List<Integer> list) { super(); this.mList = list; layoutInflater = LayoutInflater.from(context); } @Override public int getCount() { return mList.size(); } @Override
public boolean isViewFromObject(View view, Object object) { return view == object; } /** * 頁面寬度所佔ViewPager測量寬度的權重比例,預設為1 */ @Override public float getPageWidth(int position) { return (float) 0.8; } @Override public void destroyItem(ViewGroup container, int position, Object object) { View view = (View) object; ((ViewPager) container).removeView(view); } @Override public Object instantiateItem(ViewGroup container, int position) { // 自己實現 return null; } }

第 2 種表現形式的實現程式碼

這種效果也好實現,主要的關鍵點是 android:clipChildren=”false” 這個屬性。

1.配置ViewPager 和其父佈局的 android:clipChildren屬性為”false”.
(android:clipChildren表示是否限制子View在其範圍內,預設為true. 程式碼設定setClipChildren(false))
因為如果clipChildren屬性設定為true,就表明我們要將children給clip掉,就是說對於子元素來說,超出當前view的部分都會被切掉,那我們在這裡把它設定成false,就表明超出view的部分,不要切掉,依然顯示。

注意:setClipChildren(false)在3.0以上版本中,開啟了硬體加速後將不能正常工作,所以需要將其設定為軟體加速。設定軟硬體加速使用 setLayerType(View.LAYER_TYPE_SOFTWARE, null); 也可以在佈局檔案中新增 android:layerType=”software”

<RelativeLayout
    android:id="@+id/viewPager_container"
    android:layout_width="match_parent"
    android:layout_height="200dp"
    android:background="@android:color/white"
    android:clipChildren="false"
    android:layerType="software">

    <android.support.v4.view.ViewPager
        android:id="@+id/viewPager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginLeft="110dp"
        android:layout_marginRight="110dp"
        android:clipChildren="false" />
</RelativeLayout>

2.設定幕後item的快取數目。如果一屏展示的pager數目多的話就需要設定此項。

mViewPager.setOffscreenPageLimit(3);  // 具體快取頁數自己訂吧

3.設定頁與頁之間的間距

其實我感覺這裡是最麻煩的。UI 上是指定了兩個pager間距的,而這個調整起來也頗為麻煩。可以通過setPageMargin 來設定,也可以通過ViewPager.的寬高來展示。這裡算起來確實要麻煩很多。

mViewPager.setPageMargin(int marginPixls);  // setPageMargin表示設定page之間的間距

4.設定滑動,點選事件

如果只是簡單的實現滑動,可以用設定viewPager父控制元件的onTouch監聽到ViewPager的監聽上。

// 將父類的touch事件分發至viewPgaer,否則只能滑動中間的一個view物件  
findViewById(R.id.relativeLayout).setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        return mViewPager.dispatchTouchEvent(event);
    }
});

如果要實現點選滑動可以用以下方法(注:程式碼是我找的demo,效果還不錯,是寫了個實現類繼承自ViewPager。著實當了回程式碼搬運工…Orz)

public class ClipViewPager extends ViewPager {

    public ClipViewPager(Context context) {
        super(context);
    }

    public ClipViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {

        if (ev.getAction() == MotionEvent.ACTION_UP) {
            View view = viewOfClickOnScreen(ev);
            if (view != null) {
                int index = indexOfChild(view);
                if (getCurrentItem() != index) {
                    setCurrentItem(indexOfChild(view));
                }
            }
        }
        return super.dispatchTouchEvent(ev);
    }

    /**
     * @param ev
     * @return
     */
    private View viewOfClickOnScreen(MotionEvent ev) {
        int childCount = getChildCount();
        int[] location = new int[2];
        for (int i = 0; i < childCount; i++) {
            View v = getChildAt(i);
            v.getLocationOnScreen(location);

            int minX = location[0];
            int minY = getTop();

            int maxX = location[0] + v.getWidth();
            int maxY = getBottom();

            float x = ev.getX();
            float y = ev.getY();

            if ((x > minX && x < maxX) && (y > minY && y < maxY)) {
                return v;
            }
        }
        return null;
    }
}