自定义View-Tab切换TabBar

效果图:

实现原理:

1、绘制背景:通过Paint.setStrokeCap(Paint.Cap.ROUND) 、Canvas.drawLine()绘制背景。

2、自定义属性,比如:TabBar的背景色、单个tab的选中颜色、字体选中(未选中)颜色。

3、根据传入的List<String>或者String[]形式的标题列表计算减去左右预留边距之后的每个Tab的宽度、高度。

4、绘制默认情况下的TabBar样式。

5、监听OnTouchEvent()判断tab切换情况,并相应的更新UI。

6、添加tab切换监听接口,提供给外部使用,并返回tab对应在列表中的index(或者标题等需要的内容)方便用户操作。

实现代码:

1、自定义属性,添加在res/values/attrs.xml文件当中。

<!-- 自定义的xml属性,方便使用该View时候设置样式 -->
    <declare-styleable name="StockInfoTabView">
        <attr name="tabBarBackground" format="color" />
        <attr name="tabColor" format="color" />
        <attr name="tabSelectedColor" format="color" />
        <attr name="tabTextSize" format="dimension" />
        <attr name="tabTextColor" format="color" />
        <attr name="tabSelectedTextColor" format="color" />
    </declare-styleable>

2、完整代码(因为比较简单,就不仔细说明了)

package customview;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.View;

import com.example.zpf.animmenu.R;

import java.util.List;

/**
 * Created by zpf on 2018/3/1.
 * TabBar展示切换View
 */

public class StockInfoTabView extends View {

    //标题(可通过setmTitles()方法设置)
    private String[] mTitles = new String[]{"头条", "抖音", "段子", "火山", "西瓜"};
    //tab边距、每个tab间隔
    private final float DEFAULT_TAB_DIVIDER = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
            4, getResources().getDisplayMetrics());
    //tabBar宽度、高度
    private int tabBarWidth = 0;
    private int tabBarHeight = 0;
    private onTabChangeListener mOnTabChangeListener;
    //tabBar背景颜色
    private int mColorTabBG = Color.parseColor("#f0f0f0");
    //tab默认颜色、tab选中颜色
    private int mColorTab = Color.TRANSPARENT;
    private int mColorTabSelected = Color.parseColor("#ff4140");
    //tab文本默认、选中状态颜色
    private int mColorTabText = Color.parseColor("#666666");
    private int mColorTabTextSelected = Color.WHITE;
    //tab标题字体大小
    private float mTabTextSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 14, getResources().getDisplayMetrics());
    //绘制背景、tab颜色画笔
    private Paint mPaintBG;
    private Paint mPaintText;
    //tab选中的index
    private int mTabSelectedIndex = 0;
    //tabBar的半径/内部tab的半径
    private float mTabBarR, mTabR;
    //tab的宽度
    private float mTabWidth;

    public StockInfoTabView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        initDefineAttrs(context, attrs);
        initPaint();
    }

    public StockInfoTabView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initDefineAttrs(context, attrs);
        initPaint();
    }

    public StockInfoTabView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        initDefineAttrs(context, attrs);
        initPaint();
    }

    //获取自定义的属性值
    private void initDefineAttrs(Context context, AttributeSet attributeSet) {

        DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
        TypedArray typedArray = context.obtainStyledAttributes(attributeSet, R.styleable.StockInfoTabView);
        int count = typedArray.getIndexCount();
        for (int i = 0; i < count; i++) {

            int attr = typedArray.getIndex(i);
            switch (attr) {

                case R.styleable.StockInfoTabView_tabBarBackground:
                    mColorTabBG = typedArray.getColor(attr, Color.parseColor("#f0f0f0"));
                    break;
                case R.styleable.StockInfoTabView_tabColor:
                    mColorTab = typedArray.getColor(attr, Color.TRANSPARENT);
                    break;
                case R.styleable.StockInfoTabView_tabSelectedColor:
                    mColorTabSelected = typedArray.getColor(attr, Color.parseColor("#ff4140"));
                    break;
                case R.styleable.StockInfoTabView_tabTextSize:
                    mTabTextSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX,
                            typedArray.getDimensionPixelSize(attr, 14), displayMetrics);
                    break;
                case R.styleable.StockInfoTabView_tabTextColor:
                    mColorTabText = typedArray.getColor(attr, Color.parseColor("#666666"));
                    break;
                case R.styleable.StockInfoTabView_tabSelectedTextColor:
                    mColorTabTextSelected = typedArray.getColor(attr, Color.WHITE);
                    break;
            }
        }
        typedArray.recycle();
    }

    //初始化画笔
    private void initPaint() {

        mPaintBG = new Paint();
        mPaintBG.setAntiAlias(true);
        mPaintBG.setStyle(Paint.Style.FILL);
        mPaintBG.setStrokeCap(Paint.Cap.ROUND);

        mPaintText = new Paint();
        mPaintText.setAntiAlias(true);
        mPaintText.setStyle(Paint.Style.FILL);
        mPaintText.setStrokeWidth(1);
        mPaintText.setTextSize(mTabTextSize);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        tabBarWidth = w;
        tabBarHeight = h;
        mTabBarR = tabBarHeight / 2;
        mTabR = tabBarHeight / 2 - DEFAULT_TAB_DIVIDER;
        mTabWidth = (tabBarWidth - DEFAULT_TAB_DIVIDER * (mTitles.length + 1)) / mTitles.length;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        drawTabBarBG(canvas);
        drawTabBGAndText(canvas);
    }

    //绘制背景
    private void drawTabBarBG(Canvas mCanvas) {

        mPaintBG.setStrokeWidth(tabBarHeight);
        mPaintBG.setColor(mColorTabBG);
        mCanvas.drawLine(mTabBarR, mTabBarR, tabBarWidth - mTabBarR, mTabBarR, mPaintBG);
    }

    //绘制tab背景
    private void drawTabBGAndText(Canvas mCanvas) {

        mPaintBG.setStrokeWidth(tabBarHeight - DEFAULT_TAB_DIVIDER * 2);

        int count = mTitles.length;
        for (int i = 0; i < count; i++) {

            boolean isSelected = mTabSelectedIndex == i;
            mPaintBG.setColor(isSelected ? mColorTabSelected : mColorTab);
            mPaintText.setColor(isSelected ? mColorTabTextSelected : mColorTabText);

            float startX = DEFAULT_TAB_DIVIDER * (i + 1) + i * mTabWidth + mTabR;
            float endX = (DEFAULT_TAB_DIVIDER + mTabWidth) * (i + 1) - mTabR;
            mCanvas.drawLine(startX, mTabBarR, endX, mTabBarR, mPaintBG);

            float textW = mPaintText.measureText(mTitles[i]);
            float textStartX = DEFAULT_TAB_DIVIDER * (i + 1) + i * mTabWidth + mTabWidth / 2 - textW / 2;
            mCanvas.drawText(mTitles[i], textStartX, mTabBarR + (mTabTextSize / 3), mPaintText);
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {

        switch (event.getAction()) {
            case MotionEvent.ACTION_UP:

                float x = event.getX();
                for (int i = 0; i < mTitles.length; i++) {

                    float startX = DEFAULT_TAB_DIVIDER * (i + 1) + i * mTabWidth;
                    float endX = (DEFAULT_TAB_DIVIDER + mTabWidth) * (i + 1);
                    if (startX <= x && x <= endX) {
                        mTabSelectedIndex = i;
                        if (mOnTabChangeListener != null)
                            mOnTabChangeListener.OnTabChanged(mTabSelectedIndex);
                        invalidate();
                    }
                }
                return true;
        }
        return true;
    }

    //tab点击切换监听接口
    public interface onTabChangeListener {

        void OnTabChanged(int index);
    }

    public void setOnTabChangeListener(onTabChangeListener listener) {

        if (listener != null) this.mOnTabChangeListener = listener;
    }

    //设置标题集合
    public void setmTitles(String[] titles) {

        this.mTitles = titles;
        invalidate();
    }

    public void setmTitles(List<String> titles) {

        int size = titles.size();
        String[] newTitles = new String[size];
        for (int i = 0; i < size; i++) {

            newTitles[i] = titles.get(i);
            this.mTitles = newTitles;
        }
        invalidate();
    }
}

猜你喜欢

转载自blog.csdn.net/nsacer/article/details/80044235