1. 程式人生 > >Android自定義Seekbar滑動條,Pop提示跟隨滑動按鈕一起滑動

Android自定義Seekbar滑動條,Pop提示跟隨滑動按鈕一起滑動

由於專案需要做出此效果,自定義寫了一個。

效果圖

這裡寫圖片描述

思路:

原始的seekbar只有滑動條並沒有下方的提示文字,所以我們必須要繼承Seekbar重寫這個控制元件。

程式碼:

在values資料夾下新建attrs.xml,用於設定跟隨滑動按鈕的文字大小,顏色,背景。

<declare-styleable name="MySeekBar">
        <attr name="textsize" format="dimension" />
        <attr name="textcolor" format="color" />
        <attr
name="img" format="reference" />
</declare-styleable>

在佈局裡引用此控制元件

 <com.jzh.myseekbar.MySeekBar
            android:id="@+id/seekBar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:max="80"
android:maxHeight="10dp" android:progress="0" android:progressDrawable="@drawable/seekbar_style" android:splitTrack="false" android:thumb="@mipmap/niu" app:img="@mipmap/ann" app:textcolor="#fff" app:textsize="14dp"
/>

自定義控制元件樣式

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:id="@android:id/background">

        <shape>
            <corners android:radius="5dp" />
            <gradient
                android:angle="0"
                android:centerColor="@android:color/holo_orange_dark"
                android:endColor="@android:color/holo_red_dark"
                android:startColor="#2aade3" />
        </shape>
    </item>


</layer-list>

主要核心程式碼

/**
     * 文字的顏色
     */
    private int mTitleTextColor;
    /**
     * 文字的大小
     */
    private float mTitleTextSize;
    private String mTitleText;//文字的內容

    /**
     * 背景圖片
     */
    private int img;
    private Bitmap map;
    //bitmap對應的寬高
    private float img_width, img_height;
    Paint paint;

    private float numTextWidth;
    //測量seekbar的規格
    private Rect rect_seek;
    private Paint.FontMetrics fm;

    public static final int TEXT_ALIGN_LEFT = 0x00000001;
    public static final int TEXT_ALIGN_RIGHT = 0x00000010;
    public static final int TEXT_ALIGN_CENTER_VERTICAL = 0x00000100;
    public static final int TEXT_ALIGN_CENTER_HORIZONTAL = 0x00001000;
    public static final int TEXT_ALIGN_TOP = 0x00010000;
    public static final int TEXT_ALIGN_BOTTOM = 0x00100000;
    /**
     * 文字中軸線X座標
     */
    private float textCenterX;
    /**
     * 文字baseline線Y座標
     */
    private float textBaselineY;
    /**
     * 文字的方位
     */
    private int textAlign;

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

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

    public MySeekBar(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray array = context.getTheme().obtainStyledAttributes(attrs, R.styleable.MySeekBar, defStyleAttr, 0);
        int n = array.getIndexCount();
        for (int i = 0; i < n; i++) {
            int attr = array.getIndex(i);
            switch (attr) {
                case R.styleable.MySeekBar_textsize:
                    mTitleTextSize = array.getDimension(attr, 15f);
                    break;
                case R.styleable.MySeekBar_textcolor:
                    mTitleTextColor = array.getColor(attr, Color.WHITE);
                    break;
                case R.styleable.MySeekBar_img:
                    img = array.getResourceId(attr, R.mipmap.ic_launcher);
                    break;
            }
        }
        array.recycle();
        getImgWH();
        paint = new Paint();
        paint.setAntiAlias(true);//設定抗鋸齒
        paint.setTextSize(mTitleTextSize);//設定文字大小
        paint.setColor(mTitleTextColor);//設定文字顏色
        //設定控制元件的padding 給提示文字留出位置
        setPadding((int) Math.ceil(img_width) / 2, 0, (int) Math.ceil(img_height) / 2, (int) Math.ceil(img_height) + 10);
        textAlign = TEXT_ALIGN_CENTER_HORIZONTAL | TEXT_ALIGN_CENTER_VERTICAL;
    }

    /**
     * 獲取圖片的寬高
     */
    private void getImgWH() {
        map = BitmapFactory.decodeResource(getResources(), img);
        img_width = map.getWidth();
        img_height = map.getHeight();


    }

    @Override
    protected synchronized void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        setTextLocation();//定位文字繪製的位置
        rect_seek = this.getProgressDrawable().getBounds();
        //定位文字背景圖片的位置
        float bm_x = rect_seek.width() * getProgress() / getMax();
        float bm_y = rect_seek.height() + 20;
//        //計算文字的中心位置在bitmap
        float text_x = rect_seek.width() * getProgress() / getMax() + (img_width - numTextWidth) / 2;
        canvas.drawBitmap(map, bm_x, bm_y, paint);//畫背景圖
        // canvas.drawRoundRect();
        canvas.drawText(mTitleText, text_x, (float) (textBaselineY + bm_y + (0.16 * img_height / 2)), paint);//畫文字

    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        invalidate();//監聽手勢滑動,不斷重繪文字和背景圖的顯示位置
        return super.onTouchEvent(event);
    }

    /**
     * 定位文字繪製的位置
     */
    private void setTextLocation() {

        fm = paint.getFontMetrics();
        //文字的寬度
        mTitleText = getProgress() + 10 + "℃";

        numTextWidth = paint.measureText(mTitleText);

        float textCenterVerticalBaselineY = img_height / 2 - fm.descent + (fm.descent - fm.ascent) / 2;
        switch (textAlign) {
            case TEXT_ALIGN_CENTER_HORIZONTAL | TEXT_ALIGN_CENTER_VERTICAL:
                textCenterX = img_width / 2;
                textBaselineY = textCenterVerticalBaselineY;
                break;
            case TEXT_ALIGN_LEFT | TEXT_ALIGN_CENTER_VERTICAL:
                textCenterX = numTextWidth / 2;
                textBaselineY = textCenterVerticalBaselineY;
                break;
            case TEXT_ALIGN_RIGHT | TEXT_ALIGN_CENTER_VERTICAL:
                textCenterX = img_width - numTextWidth / 2;
                textBaselineY = textCenterVerticalBaselineY;
                break;
            case TEXT_ALIGN_BOTTOM | TEXT_ALIGN_CENTER_HORIZONTAL:
                textCenterX = img_width / 2;
                textBaselineY = img_height - fm.bottom;
                break;
            case TEXT_ALIGN_TOP | TEXT_ALIGN_CENTER_HORIZONTAL:
                textCenterX = img_width / 2;
                textBaselineY = -fm.ascent;
                break;
            case TEXT_ALIGN_TOP | TEXT_ALIGN_LEFT:
                textCenterX = numTextWidth / 2;
                textBaselineY = -fm.ascent;
                break;
            case TEXT_ALIGN_BOTTOM | TEXT_ALIGN_LEFT:
                textCenterX = numTextWidth / 2;
                textBaselineY = img_height - fm.bottom;
                break;
            case TEXT_ALIGN_TOP | TEXT_ALIGN_RIGHT:
                textCenterX = img_width - numTextWidth / 2;
                textBaselineY = -fm.ascent;
                break;
            case TEXT_ALIGN_BOTTOM | TEXT_ALIGN_RIGHT:
                textCenterX = img_width - numTextWidth / 2;
                textBaselineY = img_height - fm.bottom;
                break;
        }
    }