Android自定義SeekBar

  1. 效果圖:
    運行效果圖
    好了,廢話不過說,直接上代碼:

自定義一個MySeekbar類:

public class MySeekBar extends android.support.v7.widget.AppCompatSeekBar {

    /**
     * SeekBar數值文字顏色
     */
    private int mTextColor;

    /**
     * SeekBar數值文字大小
     */
    private float mTextSize;

    /**
     * SeekBar數值文字內容
     */
    private String mText;

    /**
     * SeekBar數值文字背景
     */
    private Bitmap mBackgroundBitmap;

    /**
     * SeekBar數值文字背景寬高
     */
    private float mBgWidth, mBgHeight;

    /**
     * 畫筆
     */
    private Paint mPaint;

    /**
     * SeekBar數值文字方向
     */
    private int mTextOrientation;

    /**
     * SeekBar數值文字寬度
     */
    private float mTextWidth;

    /**
     * SeekBar數值文字基線Y座標
     */
    private float mTextBaseLineY;

    //文字方向
    private static final int ORIENTATION_TOP = 1;
    private static final int ORIENTATION_BOTTOM = 2;
    private String mSeekBarText;


    public MSeekBar(Context context) {
        this(context, null);
    }

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

    public MySeekBar(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        TypedArray ta = context.getTheme().obtainStyledAttributes(attrs, R.styleable.MySeekBar, defStyleAttr, 0);
        int count = ta.getIndexCount();
        for(int i = 0; i < count; i++) {
            int index = ta.getIndex(i);
            switch (index) {
                case R.styleable.MySeekBar_textColor:
                    mTextColor = ta.getColor(index, Color.WHITE);
                    break;

                case R.styleable.MySeekBar_textSize:
                    mTextSize = ta.getDimension(index, 15f);
                    break;

                case R.styleable.MySeekBar_textBackground:
                    //獲取文字背景圖片的寬高
                    int bgResId = ta.getResourceId(index, R.mipmap.bg_seekbar_display2);
                    mBackgroundBitmap = BitmapFactory.decodeResource(getResources(), bgResId);
                    mBgWidth = mBackgroundBitmap.getWidth();
                    mBgHeight = mBackgroundBitmap.getHeight();
                    break;
                case R.styleable.MySeekBar_textOrientation:
                    mTextOrientation = ta.getInt(index, ORIENTATION_TOP);
                    break;
            }
        }
        ta.recycle();
       /* TypedArray typedArray=context.obtainStyledAttributes(R.styleable.MySeekBar);
        mSeekBarText = typedArray.getString(R.styleable.MySeekBar_imageText);
        typedArray.recycle();*/
        //設置畫筆
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setColor(mTextColor);
        mPaint.setTextSize(mTextSize);
        //設置文字顯示方向
        if(mTextOrientation == ORIENTATION_TOP) {
            //設置SeekBar頂部數值文字預留空間,左右爲數值背景圖片的一半,頂部爲數值背景圖片高度加五的間隔
            setPadding((int) Math.ceil(mBgWidth) / 2, (int) Math.ceil(mBgHeight) + 5, (int) Math.ceil(mBgWidth), 0);
        } else {
            //設置SeekBar頂部數值文字預留空間,左右爲數值背景圖片的一半,底部爲數值背景圖片高度加五的間隔
            setPadding((int) Math.ceil(mBgWidth) / 2, 0, (int) Math.ceil(mBgWidth) / 2, (int) Math.ceil(mBgHeight) + 5);
        }

    }

    @Override
    public boolean onFilterTouchEventForSecurity(MotionEvent event) {
        return false;
    }

    @Override
    protected synchronized void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        int progress = getProgress();
        int max = getMax();
        if (progress>max/2){
            mText="較多";
        }else if(progress>max/3&&progress<max/2){
            mText="適中";
        }else {
            mText="一般";
        }
        getTextLocation();

        Rect bgRect = getProgressDrawable().getBounds();
        //計算數值背景X座標
        float bgX = bgRect.width() * getProgress() / getMax();
        //計算數值背景Y座標
        float bgY = 0;
        if(mTextOrientation == ORIENTATION_BOTTOM) {
            bgY = mBgHeight + 10;
        }

        //計算數值文字X座標
        float textX = bgX + (mBgWidth - mTextWidth)/4+5;
        float textY = (float) (mTextBaseLineY + bgY + (0.16 * mBgHeight / 2) - 10);

        //繪製文字和背景
        canvas.drawBitmap(mBackgroundBitmap, bgX, bgY, mPaint);
        canvas.drawText(mText, textX, textY, mPaint);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        invalidate();
        return super.onTouchEvent(event);
    }

    /**
     * 計算SeekBar數值文字的顯示位置
     */
    private void getTextLocation() {
        Paint.FontMetrics fm = mPaint.getFontMetrics();

        //mText = "一般";
        //測量文字寬度
        mTextWidth = mPaint.measureText(mText);
        //計算文字基線Y座標
        mTextBaseLineY = mBgHeight / 2 - fm.descent + (fm.descent - fm.ascent);
    }
}

在values文件下新建attrs.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="MySeekBar">
        <attr name="textSize" format="dimension" />
        <attr name="textColor" format="color" />
        <attr name="textBackground" format="reference" />
        <attr name="textOrientation" format="enum">
            <enum name="top" value="1" />
            <enum name="bottom" value="2" />
        </attr>
    </declare-styleable>

這樣一個自定義的seekBar就完成了,具體的使用方式跟常見的Android控件的使用方式一樣。

<com.kang.MSeekBar
    android:id="@+id/sb_main1"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:max="100"
    android:progress="50"                  
    android:thumb="@null"                     
    app:textColor="@color/white"
    app:textOrientation="top"
    app:textSize="12sp"/>

現在運行你的項目就可以看到上面的效果了。
完整代碼請QQ聯繫博主:QQ 2812456302

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