viewpagerindicator,既使用viewpager翻頁時候,標題的指示條隨着改變的控件,是經常使用android控件之一,幾乎全部的新聞類APP中都有使用。以下圖所示:android
今天,咱們將從0到1實現這一控件。ide
其實,實現這一控件思路很簡單:佈局
①對頭部的標題欄進行佈局,頭部標題欄,只能進行單選,這符合radiobutton的特質,可是普通的radiobutton,不是這樣的嗎?動畫
顯然,咱們在這裏須要寫樣式進行處理,因爲頭部標題欄的條目很是的多,一個屏幕放不下,所以咱們須要一個水平滾動條來盛放這不少的條目。this
②咱們看到底部的內容隨着指示條再不斷滑動,所以底部內容是一個viewpager。spa
③下面就是這個控件最關鍵的部分,就是指示條隨着viewpager的內容相互滾動,這涉及到必定邏輯,下面我會闡述這方面的邏輯內容。3d
說了一大段開場白之後,咱們就應該庖丁解牛般的實現咱們控件,廢話少說,直接上代碼,首先,粉墨登場是頭部控件xml佈局文件。code
<!-- 頭部標題欄 包含一個水平滾動條 單選按鈕組 以及一個標題指示條 --> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <HorizontalScrollView android:id="@+id/hsv" android:layout_width="fill_parent" android:layout_height="wrap_content" android:fadingEdge="none" android:scrollbars="none" > <!-- 單選按鈕 --> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" > <RadioGroup android:id="@+id/rg" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" > </RadioGroup> <FrameLayout android:layout_width="fill_parent" android:layout_height="2dp" > <View android:id="@+id/indicator" android:layout_width="100dp" android:layout_height="2dp" android:background="#ff0000" /> </FrameLayout> </LinearLayout> </HorizontalScrollView> </LinearLayout>
咱們看到這個控件包含一個可以左右滾動水平滾動條,因爲每一個標題條目就是一個radiobutton,因此須要把這個radio button 放在一個單項按鈕組中。固然,還須要一個指示翻到第幾頁的指示條。xml
接下來,就是重頭戲了,這個自定義控件邏輯控制。咱們看一下他的流程圖對象
經過上述流程圖,咱們能夠得出指示條伴隨頭部欄與viewpager滑動而滑動。
作了這麼多鋪墊,這個控件的核心——邏輯代碼將要暴露他的廬山真面目。
一個自定義控件,首先要初始化原有控件。代碼以下:
/** * 初始化 相應控件 而且爲相應控件賦予相應的事件 * @param context */ @SuppressLint("InflateParams") private void initView(Context context) { hsv = (HorizontalScrollView) findViewById(R.id.hsv); rg = (RadioGroup) findViewById(R.id.rg); rg.setOnCheckedChangeListener(this); indicator = findViewById(R.id.indicator); } /** * 爲標題條目動態賦值 */ public void setDatas(List<String> datas) { this.datas = datas; addView(); } /** * 將標題控件動態添加radiobuttonGroup控件中去 */ @SuppressLint("ResourceAsColor") private void addView() { for (int i = 0; i < datas.size(); i++) { RadioButton radioButton = new RadioButton(getContext()); radioButton.setText(datas.get(i)); radioButton.setId(10000 + i); radioButton.setBackgroundResource(R.color.white); radioButton.setButtonDrawable(null); radioButton.setButtonDrawable(android.R.color.transparent); radioButton.setTextColor(R.color.black); LayoutParams layoutParams = new LayoutParams(Dp2Px(getContext(), 100), LayoutParams.WRAP_CONTENT); radioButton.setLayoutParams(layoutParams); radioButton.setGravity(Gravity.CENTER); int px = Dp2Px(getContext(), 8); radioButton.setPadding(px, px, px, px); rg.addView(radioButton); } }
這裏,大夥應當對兩個方面的問題引發重視:
①咱們所說哪些頭部標題並非固定的,是動態生成的,所以顯示每一個標題radiobutton控件,是隨着標題的條目動態添加到父控件中去的。
②前文說道,因爲每一個radiobutton樣式很是醜陋,不符合咱們的需求,所以咱們須要經過相應的代碼控制它的樣式。
因爲這個控件歸根結底是對viewpager翻頁效果進行一個指示,怎麼可以少得了viewpager對象,相應的源代碼以下:
/** * 設置viewpager對象 */ public void setPager(ViewPager pager) { this.pager = pager; setPagerListener(); } /** * 對viewpager翻頁進行監聽 */ private void setPagerListener() { pager.setOnPageChangeListener(this); }
其主要就是對於viewpager的翻頁效果進行監聽。
怎麼使翻頁翻到那一頁的時候,指示條也隨之移動,讓我媽老瞅瞅他的代碼:
/** * 頁面滾動 指示條隨之移動 當條目滾出屏幕的時候,水平滾動條也隨之移動 */ @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { int sum = 0; sum = (int) ((position+positionOffset)*rg.getChildAt(position).getWidth()); int green = (pager.getWidth() - rg.getChildAt(position).getWidth()) / 2; dx = sum - green;// 計算出要滑出去的距離 hsv.scrollTo(dx, 0); tempx=hsv.getScrollX(); indicatorScroll(position, positionOffset); } /** * 指示條隨着頁面的移動也跟隨着滑動 */ int tempx=0; private void indicatorScroll(int position, float positionOffset) { RadioButton button = (RadioButton) rg.getChildAt(position); int[] location = new int[2]; button.getLocationInWindow(location); // 開始作位移滑動 TranslateAnimation animation = new TranslateAnimation(fromX, location[0] + positionOffset * button.getWidth()+tempx, 0, 0); animation.setDuration(50);// 動畫持續事件 animation.setFillAfter(true); fromX = (int) (location[0] + button.getWidth() * positionOffset+tempx); indicator.startAnimation(animation);// 線開始動畫 }
對於這個邏輯,你們應當注意兩點:
第一點,單條目滾出屏幕的時候,咱們應當相應條目將其滾動到屏幕中央位置,那麼他所需滾動位置,如圖所示:
第二點,關於指示條計算就是移動到相應條目位置-水平滾動條滾動的位置。
這樣一個自定義的viewpagerindicator就大功告成了,效果以下:
源代碼地址爲:
http://pan.baidu.com/s/1eQ9Fi62