Android自定義SeekBar控件實現

一、控件介紹

  SeekBar控件是Android原生組件之一,用於選擇連續的數據或者塊數據。一般情況下,SeekBar控件都是用來實現調節音量大小、顏色、亮度等操作。但是,在實際開發中,我們會發現自帶的SeekBar樣式不夠美觀、不夠適用。因此,本文將介紹如何自定義SeekBar控件,實現控件的樣式和功能更加多樣化。

二、自定義SeekBar的基本步驟

  自定義SeekBar的基本步驟如下:

  1、繼承SeekBar,重寫構造函數、繪製方法、觸摸事件等方法;

  2、定義SeekBar需要用到的屬性;

  3、在布局文件中引入自定義的SeekBar。

三、自定義SeekBar的具體實現

1. 自定義SeekBar屬性的定義

  首先,我們需要定義需要用到的SeekBar屬性。

<declare-styleable name="MySeekBar">    <attr name="thumb" format="reference" />    <attr name="progressColor" format="color" />    <attr name="progressBackground" format="color" />    <attr name="seekBarHeight" format="dimension" /></declare-styleable>

  其中,thumb屬性用於設置SeekBar的把手圖像,progressColor屬性用於設置SeekBar填充區域的顏色,progressBackground屬性用於設置SeekBar未填充區域的顏色,seekBarHeight屬性用於設置SeekBar的高度。

2. 自定義SeekBar的繪製過程

  接下來,我們需要重寫SeekBar的onMeasure()onDraw()onTouchEvent()方法。

2.1 onMeasure方法:測量SeekBar的大小

@Overrideprotected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {    int height = MeasureSpec.getSize(heightMeasureSpec);    int width = MeasureSpec.getSize(widthMeasureSpec);    setMeasuredDimension(width, height);}

  通過重寫onMeasure()方法,我們可以測量SeekBar的大小,並將其設置為期望的大小。

2.2 onDraw方法:繪製SeekBar的基本屬性

@Overrideprotected synchronized void onDraw(Canvas canvas) {    super.onDraw(canvas);    int width = getWidth();    int height = getHeight();    float thumbX = getThumbPosX();    // 繪製背景    RectF rectBackground = new RectF(0, height / 2 - seekBarHeight / 2, width, height / 2 + seekBarHeight / 2);    paint.setColor(progressBackground);    canvas.drawRoundRect(rectBackground, height / 2, height / 2, paint);    // 繪製填充區域    float progressEnd = thumbX + getPaddingLeft();    RectF rectProgress = new RectF(0, height / 2 - seekBarHeight / 2, progressEnd, height / 2 + seekBarHeight / 2);    paint.setColor(progressColor);    canvas.drawRoundRect(rectProgress, height / 2, height / 2, paint);    // 繪製把手圖像    canvas.drawBitmap(thumbBitmap, thumbX, height / 2 - thumbBitmap.getHeight() / 2, paint);}

  onDraw()方法是SeekBar的繪製核心方法,我們可以在該方法中實現SeekBar的基本繪製,包括背景、填充區域和把手圖像等內容。

2.3 onTouchEvent方法:監聽SeekBar的觸摸事件

@Overridepublic boolean onTouchEvent(MotionEvent event) {    if (!isEnabled()) {        return false;    }    switch (event.getAction()) {        case MotionEvent.ACTION_DOWN:            touchDownX = event.getX();            break;        case MotionEvent.ACTION_MOVE:            float touchMoveX = event.getX();            float touchDelta = touchMoveX - touchDownX;            touchDownX = touchMoveX;            int thumbPosX = (int) (getThumbPosX() + touchDelta);            int maxRange = getWidth() - getPaddingLeft() - getPaddingRight();            int seekBarWidth = thumbBitmap.getWidth();            thumbPosX = Math.max(thumbPosX, 0);            thumbPosX = Math.min(thumbPosX, maxRange);            setProgress(thumbPosX * getMax() / (maxRange - seekBarWidth));            break;        case MotionEvent.ACTION_UP:            break;        case MotionEvent.ACTION_CANCEL:            break;    }    return true;}

  onTouchEvent()方法是SeekBar的觸摸事件處理方法,通過監聽觸摸事件的四種狀態,我們可以實時更新SeekBar的視圖狀態。

3. 自定義SeekBar的樣式

3.1 基本樣式

<com.example.MySeekBar    android:id="@+id/mySeekBar"    android:layout_width="match_parent"    android:layout_height="wrap_content"    android:paddingLeft="10dp"    android:paddingRight="10dp"    app:thumb="@drawable/ic_thumb"    app:progressColor="@color/colorAccent"    app:progressBackground="@color/colorPrimary"    app:seekBarHeight="20dp" />

  通過設置app:thumbapp:progressColorapp:progressBackground等屬性,我們可以實現SeekBar的基本樣式。

3.2 高級樣式

<com.example.MySeekBar    android:id="@+id/mySeekBar"    android:layout_width="match_parent"    android:layout_height="wrap_content"    android:paddingLeft="10dp"    android:paddingRight="10dp"    app:thumb="@drawable/ic_thumb"    app:progressColor="@color/colorAccent"    app:progressBackground="@color/colorPrimary"    app:seekBarHeight="20dp"    style="?android:attr/progressBarStyleHorizontal" />

  除了基本樣式外,我們還可以通過設置style="?android:attr/progressBarStyleHorizontal"屬性,使得SeekBar的樣式與系統默認的樣式保持一致,效果更加美觀。

四、完整代碼示例

public class MySeekBar extends SeekBar {    private Paint paint;    private Bitmap thumbBitmap;    private int progressColor;    private int progressBackground;    private int seekBarHeight;    private float touchDownX;    public MySeekBar(Context context) {        super(context);        setup();    }    public MySeekBar(Context context, AttributeSet attrs) {        super(context, attrs);        setup(attrs);    }    public MySeekBar(Context context, AttributeSet attrs, int defStyle) {        super(context, attrs, defStyle);        setup(attrs);    }    private void setup() {        paint = new Paint(Paint.ANTI_ALIAS_FLAG);        thumbBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_thumb);    }    private void setup(AttributeSet attrs) {        paint = new Paint(Paint.ANTI_ALIAS_FLAG);        thumbBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_thumb);        TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.MySeekBar);        progressColor = typedArray.getColor(R.styleable.MySeekBar_progressColor, Color.RED);        progressBackground = typedArray.getColor(R.styleable.MySeekBar_progressBackground, Color.GRAY);        seekBarHeight = (int) typedArray.getDimension(R.styleable.MySeekBar_seekBarHeight, 10);        typedArray.recycle();    }    @Override    protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        int height = MeasureSpec.getSize(heightMeasureSpec);        int width = MeasureSpec.getSize(widthMeasureSpec);        setMeasuredDimension(width, height);    }    @Override    protected synchronized void onDraw(Canvas canvas) {        super.onDraw(canvas);        int width = getWidth();        int height = getHeight();        float thumbX = getThumbPosX();        // 繪製背景        RectF rectBackground = new RectF(0, height / 2 - seekBarHeight / 2, width, height / 2 + seekBarHeight / 2);        paint.setColor(progressBackground);        canvas.drawRoundRect(rectBackground, height / 2, height / 2, paint);        // 繪製填充區域        float progressEnd = thumbX + getPaddingLeft();        RectF rectProgress = new RectF(0, height / 2 - seekBarHeight / 2, progressEnd, height / 2 + seekBarHeight / 2);        paint.setColor(progressColor);        canvas.drawRoundRect(rectProgress, height / 2, height / 2, paint);        // 繪製把手圖像        canvas.drawBitmap(thumbBitmap, thumbX, height / 2 - thumbBitmap.getHeight() / 2, paint);    }    @Override    public boolean onTouchEvent(MotionEvent event) {        if (!isEnabled()) {            return false;        }        switch (event.getAction()) {            case MotionEvent.ACTION_DOWN:                touchDownX = event.getX();                break;            case MotionEvent.ACTION_MOVE:                float touchMoveX = event.getX();                float touchDelta = touchMoveX - touchDownX;                touchDownX = touchMoveX;                int thumbPosX = (int) (getThumbPosX() + touchDelta);                int maxRange = getWidth() - getPaddingLeft() - getPaddingRight();                int seekBarWidth = thumbBitmap.getWidth();                thumbPosX = Math.max(thumbPosX, 0);                thumbPosX = Math.min(thumbPosX, maxRange);                setProgress(thumbPosX * getMax() / (maxRange - seekBarWidth));                break;            case MotionEvent.ACTION_UP:                break;            case MotionEvent.ACTION_CANCEL:                break;        }        return true;    }    private float getThumbPosX() {        int width = getWidth() - getPaddingLeft() - getPaddingRight();        int seekBarWidth = thumbBitmap.getWidth();        float ratio = (float) getProgress() / (float) getMax();        return width * ratio;    }}

<declare-styleable name="MySeekBar">    <attr name="thumb" format="reference" />    <attr name="progressColor" format="color" />    <attr name="progressBackground" format="color" />    <attr name="seekBarHeight" format="dimension" /></declare-styleable>

<com.example.MySeekBar    android:id="@+id/mySeekBar"    android:layout_width="match_parent"    android:layout_height="wrap_content"    android:paddingLeft="10dp"    android:paddingRight="10dp"    app:thumb="@drawable/ic_thumb"    app:progressColor="@color/colorAccent"    app:progressBackground="@color/colorPrimary"    app:seekBarHeight="20dp" />

原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hk/n/235890.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
小藍的頭像小藍
上一篇 2024-12-12 11:56
下一篇 2024-12-12 11:57

相關推薦

  • Python中自定義函數必須有return語句

    自定義函數是Python中最常見、最基本也是最重要的語句之一。在Python中,自定義函數必須有明確的返回值,即必須要有return語句。本篇文章將從以下幾個方面對此進行詳細闡述。…

    編程 2025-04-29
  • Android ViewPager和ScrollView滑動衝突問題

    Android開發中,ViewPager和ScrollView是兩個常用的控件。但是當它們同時使用時,可能會發生滑動衝突的問題。本文將從多個方面介紹解決Android ViewPa…

    編程 2025-04-28
  • Android如何點擊其他區域收起軟鍵盤

    在Android應用中,當輸入框獲取焦點彈出軟鍵盤後,我們希望能夠點擊其他區域使軟鍵盤消失,以提升用戶體驗。本篇文章將說明如何實現這一功能。 一、獲取焦點並顯示軟鍵盤 在Andro…

    編程 2025-04-28
  • Python自定義列表

    本文將為大家介紹Python中自定義列表的方法和應用場景。對自定義列表進行詳細的闡述,包括列表的基本操作、切片、列表推導式、列表的嵌套以及列表的排序,希望能夠幫助大家更好地理解和應…

    編程 2025-04-27
  • 如何添加Python自定義模塊?

    Python是一種非常流行的腳本語言,因其易學易用和功能強大而備受歡迎。自定義模塊是Python開發中經常使用的功能之一。本文將從多個方面為您介紹如何添加Python自定義模塊。 …

    編程 2025-04-27
  • Python ttk控件用法介紹

    本文將從多個方面對Python ttk控件進行詳細闡述,旨在幫助開發者更好的使用和理解這一控件。 一、ttk控件概述 ttk控件是Python tkinter模塊中的一個擴展模塊,…

    編程 2025-04-27
  • Android Studio HUD 實現指南

    本文將會以實例來詳細闡述如何在 Android Studio 中使用 HUD 功能實現菊花等待指示器的效果。 一、引入依賴庫 首先,我們需要在 build.gradle 文件中引入…

    編程 2025-04-27
  • Android和Vue3混合開發方案

    本文將介紹如何將Android和Vue3結合起來進行混合開發,以及其中的優勢和注意事項。 一、環境搭建 在進行混合開發之前,需要搭建好相應的開發環境。首先需要安裝 Android …

    編程 2025-04-27
  • Android Java Utils 可以如何提高你的開發效率

    Android Java Utils 是一款提供了一系列方便實用的工具類的 Java 庫,可以幫助開發者更加高效地進行 Android 開發,提高開發效率。本文將從以下幾個方面對 …

    編程 2025-04-27
  • 探究lodop打印控件

    一、簡介 lodop打印控件是一款適用於各種瀏覽器的打印控制插件,可用於快速、簡便地實現各種打印任務。它支持多種輸出方式,如打印、預覽、保存至PDF等,在各種行業中都被廣泛應用。 …

    編程 2025-04-25

發表回復

登錄後才能評論