Android實(shí)現(xiàn)圓角按鈕的便捷方法

圓角按鈕是我們在做界面時(shí)常常遇到的UI樣式。
通常的辦法,是做一個drawable,比如這樣:

<?xml version="1.0" encoding="UTF-8"?> 
<shape 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:shape="rectangle"> 
    <!-- 填充的顏色 --> 
    <solid android:color="#ffae00" /> 

    <!-- 圓角的半徑 --> 
    <corners android:radius="10dp" /> 
</shape>

在Layout文件里Button的background屬性設(shè)上這個drawable.xml,就可以了。
然而這樣做的話,每次弄個按鈕都得新做一個drawable文件,各種drawable多了看著就亂。

是不是可以把color和radius放到Button的屬性里去,這樣就不用每次再拖一個drawable.xml了是吧?

自定義RoundCornerButton

<widget.RoundCornerButton
    android:id="@+id/btn_commit"
    android:layout_width="100dp"
    android:layout_height="40dp"
    android:gravity="center"
    android:text="我的按鈕"
    app:rcb_backgroundColor="@color/yellow"
    app:rcb_backgroundColorDisabled="@color/light_grey"
    app:rcb_cornerRadius="20dp"
    />

如果可以這樣在Layout文件里直接設(shè)置背景色和圓角半徑,是不是很方便!雖然不如drawable靈活,但是已經(jīng)足以應(yīng)付設(shè)計(jì)同學(xué)給出的圓角按鈕的需求了。

我們就以定義自己的styleable屬性開始吧

<declare-styleable name="RoundCornerButton">
    <attr name="rcb_backgroundColor" format="color" />
    <attr name="rcb_backgroundColorDisabled" format="color" />
    <attr name="rcb_cornerRadius" format="dimension" />
</declare-styleable>

從Drawable擴(kuò)展一個自己的Drawable,很簡單

  • 從構(gòu)造方法傳入color和radius,并創(chuàng)建一個實(shí)習(xí)的畫筆;
  • 覆寫draw方法,有現(xiàn)成的畫圓角矩形的方法可以調(diào)用;
  • 暴露一個setRect方法給外邊,用于設(shè)置繪制區(qū)域的寬高。
class RoundCornerDrawable extends Drawable {

    final int color;
    final float radius;
    final Paint paint;
    final RectF rectF;

    RoundCornerDrawable(int color, float radius) {
        this.color = color;
        this.radius = radius;

        // 實(shí)心的畫筆
        this.paint = new Paint();
        paint.setStyle(Paint.Style.FILL);
        paint.setAntiAlias(true);
        paint.setColor(color);

        this.rectF = new RectF();
    }

    // 用于設(shè)置Drawable寬高
    public void setRect(int width, int height) {
        this.rectF.left = 0;
        this.rectF.top = 0;
        this.rectF.right = width;
        this.rectF.bottom = height;
    }

    @Override
    public void draw(@NonNull Canvas canvas) {
        canvas.drawRoundRect(rectF, radius, radius, paint); // 畫圓角矩形,現(xiàn)成的方法
    }

    // 其余方法略
}

定義自己的Button類,有這么幾個要點(diǎn):

  • 與通常的自定義View一樣,覆寫三個構(gòu)造方法;
  • 從AttributeSet里讀取自定義的屬性backgroundColor和cornerRadius,這里暫時(shí)忽略backgroundColorDisabled;
  • 每一種狀態(tài)(例如普通、禁用、按下)是一個RoundCornerDrawable,組合成一個StateListDrawable;
  • onLayout的時(shí)候,記得改變每一個RoundCornerDrawable的尺寸。
public class RoundCornerButton extends AppCompatButton {

    private int colorNormal;
    private float cornerRadius;
    private RoundCornerDrawable bgDrawableNormal = null;

    // 省略三個構(gòu)造方法
    // 構(gòu)造方法最后一定要調(diào)用initCornerBackground完成初始化

    private void initCornerBackground(AttributeSet attrs, int defStyleAttr) {
        TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.RoundCornerButton, defStyleAttr, 0);

        this.cornerRadius = a.getDimension(R.styleable.RoundCornerButton_rcb_cornerRadius, 0);
        this.colorNormal = a.getColor(R.styleable.RoundCornerButton_rcb_backgroundColor, 0);
        makeBackgroundDrawable();

        a.recycle();
    }

    private void makeBackgroundDrawable() {
        bgDrawableNormal = new RoundCornerDrawable(this.colorNormal, this.cornerRadius);
        bgDrawableNormal.setRect(getWidth(), getHeight());

        // 設(shè)計(jì)通常會給出禁用時(shí)的樣式以及按下時(shí)的樣式
        // 所以這里用使用StateListDrawable
        StateListDrawable bgDrawable = new StateListDrawable();
        bgDrawable.addState(new int[]{android.R.attr.state_enabled, -android.R.attr.state_pressed}, bgDrawableNormal);
        // 每多一種狀態(tài),在這里多加一項(xiàng)
        setBackgroundDrawable(bgDrawable);
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);

        // layout之后必然會draw,所以在這里設(shè)置drawable的尺寸
        if (bgDrawableNormal != null) {
            bgDrawableNormal.setRect(right - left, bottom - top);
        }
        // 每多一種狀態(tài),在這里多加一項(xiàng)
    }
}

附上Demo源代碼:https://github.com/realxu/CodeSamples/tree/master/Android/RoundCornerButtonDemo

這就可以啦,我們看看效果:


round-corner-button-demo.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容