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;
}
}