為ViewPager添加一個indicator,viewpagerindicator
天は二物を與えず
ViewPager是Android提供的一個良心組件,有了它分分鐘就可以實現了一個水平滑動的分頁功能,其中用ViewPager來全屏展示圖片是一個比較經典的使用情境,先來看一下:
在每個Page的底部中間位置有一排圓圈,實心的圓圈用來指示當前顯示的圖片,它會隨著手指滑動而移動,我們可以稱之為 ViewPager 的 indicator。
實現這個功能也比較簡單,首先定義一個水平方向的LinearLayout用來顯示 indicator,然後把這個LinearLayout和ViewPager作為子項目放在一個FrameLayout中,這樣 indicator 的 LinearLayout 會在顯示在 ViewPager 的上層,初步達到了顯示效果,但是滑動效果還沒有實現。
首先建立一個LinearLayout的子類 - CirclePageIndicator
public class CirclePageIndicator extends LinearLayout
如果要優雅地實現這個類,可以參考Android中如何優雅地自訂一個View。
根據 ViewPager 的 page 數添加 indicator, 這裡先定義好這個方法,等到後看再用。
private void addIndicator(int count) { for (int i = 0; i < count; i++) { ImageView img = new ImageView(getContext()); LayoutParams params = new LayoutParams( LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); params.leftMargin = indicatorSpacing; params.rightMargin = indicatorSpacing; img.setImageResource(R.drawable.circle_indicator_stroke); addView(img, params); } if (count > 0) { ((ImageView) getChildAt(0)).setImageResource(R.drawable.circle_indicator_solid); }}
我希望 CirclePageIndicator 的用法足夠簡單,簡單到只需要一條語句就可以把它附加到 ViewPager 上。
CirclePageIndicator indicator = (CirclePageIndicator) findViewById(R.id.indicator);indicator.setViewPager(pager);
那麼我們就為 CirclePageIndicator 添加 setViewPager 方法。
public void setViewPager(ViewPager pager) { userDefinedPageChangeListener = getOnPageChangeListener(pager); pager.setOnPageChangeListener(this); addIndicator(pager.getAdapter().getCount());}
為了能監聽 ViewPager 中 PageChange 時間,讓 CirclePageIndicator 實現了 ViewPager.OnPageChangeListener 這個介面,然後在 setViewPager 的時候,為 ViewPager 添加這個 listener。
但是,這樣問題又來了,如果 ViewPager 在傳入之前已經有了 listener ,這裡很顯然會把之前的 listener 給覆蓋掉,這個也好辦,稍微 hack 一下,用反射把之前的 listener 拿到就可以了。
private ViewPager.OnPageChangeListener getOnPageChangeListener(ViewPager pager) { try { Field f = pager.getClass().getDeclaredField("mOnPageChangeListener"); f.setAccessible(true); return (ViewPager.OnPageChangeListener) f.get(pager); } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } return null;}
剩下的把 ViewPager.OnPageChangeListener 中的方法實現一下,根據 page 的變化更新 indicator 就完成了。
猛戳源碼