Android 自定義控件ViewPager 指示器 ViewPagerIndicator

效果圖

效果圖

步驟

  1. 繼承HorizontalScrollView
  2. 初始化必要屬性與類
  3. 暴露方法 setTabDatum 根據數據 來創建tab
  4. 綁定ViewPager 根據ViewPager.setOnPageChangeListener來處理我們畫Tab下劃線的邏輯
  5. 在dispatchDraw中畫線

實現

  1. 繼承HorizontalScrollView
public class ViewPagerIndicator extends HorizontalScrollView 
  1. 初始化必要屬性與類
    public ViewPagerIndicator(Context context) {
        this(context, null);
    }

    public ViewPagerIndicator(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public ViewPagerIndicator(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mContainer = new LinearLayout(context);
        mContainer.setOrientation(LinearLayout.HORIZONTAL);
        addView(mContainer);
        init();
    }

    private void init() {
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setColor(mTabLineColor);
    }

    public int getScreenWidth() {
        WindowManager wm = (WindowManager) getContext().getSystemService(
                Context.WINDOW_SERVICE);
        DisplayMetrics outMetrics = new DisplayMetrics();
        wm.getDefaultDisplay().getMetrics(outMetrics);
        return outMetrics.widthPixels;
    }
  1. 暴露方法 setTabDatum 根據數據 來創建tab
  // /****************** about tab *****************/


    /**
     *  2.  set tab datum in  ViewPagerIndicator
     * @param datum
     */
    public void setTabDatum(List<String> datum) {
        if (datum == null || datum.size() <= 0) {
            return;
        }
        mContainer.removeAllViews();
        mTabCount = datum.size();
        for (int i = 0; i < datum.size(); i++) {
            TextView view = createTab(datum.get(i));
            mContainer.addView(view);
            setTabClickListener(i, view);
        }
    }

    private void setTabClickListener(final int finalI, View view) {
        view.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                if (mViewPager != null) {
                    mViewPager.setCurrentItem(finalI);
                }
            }
        });
    }

    private TextView createTab(String text) {
        TextView tv = new TextView(getContext());
        LayoutParams lp = new LayoutParams(
                LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
        lp.width = mTabWidth;
        tv.setGravity(Gravity.CENTER);
        tv.setTextColor(mTabTextColor);
        tv.setText(text);
        tv.setTextSize(TypedValue.COMPLEX_UNIT_SP, mTabTextSize);
        tv.setLayoutParams(lp);
        tv.setBackgroundColor(mTabBackgroundColor);
        return tv;
    }

    void resetAllTab() {
        for (int i = 0; i < mTabCount; i++) {
            View child = mContainer.getChildAt(i);
            if (child instanceof TextView) {
                ((TextView) child).setTextColor(mTabTextColor);
            }
        }
    }

    void setTabSelected(int position) {
        resetAllTab();
        View child = mContainer.getChildAt(position);
        if (child instanceof TextView) {
            ((TextView) child).setTextColor(mTabTextSelectedColor);
        }
    }
  1. 綁定ViewPager 根據ViewPager.setOnPageChangeListener來處理我們畫Tab下劃線的邏輯
///******************* about callback *******************/
    interface PageChangeListener {
        void onPageScrolled(int position, float positionOffset, int positionOffsetPixels);

        void onPageSelected(int position);

        void onPageScrollStateChanged(int state);}
    private PageChangeListener onPageChangeListener;
    public void setOnPageChangeListener(PageChangeListener onPageChangeListener) {
        this.onPageChangeListener = onPageChangeListener;
    }

    /**
     * 1. bind ViewPager and set tab's position
     * @param viewPager
     * @param pos
     */
    public void bindViewPager(ViewPager viewPager, int pos) {
        mViewPager = viewPager;
        mViewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
                updateLine(position, positionOffset);


                if (onPageChangeListener != null) {
                    onPageChangeListener.onPageScrolled(position, positionOffset, positionOffsetPixels);
                }
            }

            @Override
            public void onPageSelected(int position) {
                setTabSelected(position);
                if (onPageChangeListener != null) {
                    onPageChangeListener.onPageSelected(position);
                }
            }

            @Override
            public void onPageScrollStateChanged(int state) {
                if (onPageChangeListener != null) {
                    onPageChangeListener.onPageScrollStateChanged(state);
                }
            }
        });
        setTabSelected(pos);
        mViewPager.setCurrentItem(pos);
    }

    private void updateLine(int position, float positionOffset) {
        mTranslationX = (int) (getWidth() / mTabVisibleCount * (position + positionOffset));
        if (positionOffset > 0 && position >= (mTabVisibleCount - 2)
                && mContainer.getChildCount() > mTabVisibleCount) {
            if (mTabVisibleCount != 1) {
                this.scrollTo((int) ((position - (mTabVisibleCount - 2)) * mTabWidth
                        + (int) (mTabWidth * positionOffset)), 0);
            } else {
                this.scrollTo(
                        position * mTabWidth + (int) (mTabWidth * positionOffset), 0);
            }
        }
        invalidate();
    }
  1. 在dispatchDraw中畫線

// /****************** about tab line *****************/

    @Override
    protected void dispatchDraw(Canvas canvas) {
        super.dispatchDraw(canvas);

        Rect rect = new Rect(
                //if it does not set lineWidth
                mTranslationX +
                        (mLineWidth == 0 ? 0 : mTabWidth / 2 - mLineWidth / 2),
                getMeasuredHeight() - mLineHeight,
                //if it does not set lineWidth
                mTranslationX +
                        (mLineWidth == 0 ? mTabWidth : mTabWidth / 2 + mLineWidth / 2),
                getMeasuredHeight());

        canvas.drawRect(rect, mPaint);
    }

具體使用

        mViewPagerIndicator = (ViewPagerIndicator) findViewById(R.id.vpi_container);
        mViewPager = (ViewPager) findViewById(R.id.vp_container);
//        1. bind ViewPager and set tab's position
        mViewPagerIndicator.bindViewPager(mViewPager, 0);

//        2.  set tab datum in  ViewPagerIndicator
        mViewPagerIndicator.setTabDatum(mDatum);

代碼下載

https://github.com/agxxxx/ViewPagerIndicator

參考&&感謝

Hongyang 先生

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章