带下划线的RadioButton

973 阅读1分钟

在网上搜了很多相关的文章,大部分都是copy来copy去。也达不到项目的要求,所以就自己封装了一个RadioGroup。

先看效果:

实现方法也比较简单:

主要思路就是继承AppCompatRadioButton重写onDraw方法。根据RadioButton的宽高,利用画布(Canvas)和画笔(Paint)画一个矩形(Rect)。

下面就是具体的实现:

PeriodsButtonGroupView.java

public class PeriodsButtonGroupView extends RadioGroup {
    private CharSequence[] mRadioButtonEntries;
    private ColorStateList mRadioButtonTextColor;

    public PeriodsButtonGroupView(Context context) {
        super(context);
        init(context);
    }

    public PeriodsButtonGroupView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.PeriodsButtonGroupView);
        mRadioButtonEntries = typedArray.getTextArray(R.styleable.PeriodsButtonGroupView_android_entries);
        if (mRadioButtonEntries == null || mRadioButtonEntries.length == 0) {
            mRadioButtonEntries = context.getResources().getStringArray(R.array.periods_button_group_entries);
        }
        mRadioButtonTextColor = typedArray.getColorStateList(R.styleable.PeriodsButtonGroupView_radioButtonTextColor);
        if (mRadioButtonTextColor == null) {
            mRadioButtonTextColor = getResources().getColorStateList(R.color.periods_radio_button_text_color_green);
        }
        typedArray.recycle();
        init(context);
    }

    private void init(Context context) {
        setOrientation(LinearLayout.HORIZONTAL);
        initComponent(context);
    }

    private void initComponent(Context context) {
        for (CharSequence charSequence : mRadioButtonEntries) {
            PeriodsRadioButton radioButton = new PeriodsRadioButton(context);
            radioButton.setLayoutParams(new LayoutParams(0, ViewGroup.LayoutParams.MATCH_PARENT, 1));
            radioButton.setTextAlignment(TEXT_ALIGNMENT_CENTER);
            radioButton.setButtonDrawable(null);
            radioButton.setTextColor(mRadioButtonTextColor);
            radioButton.setText(charSequence);
            addView(radioButton);
        }
    }

    private static class PeriodsRadioButton extends AppCompatRadioButton {
        private Paint mPaint;

        public PeriodsRadioButton(Context context) {
            super(context);
            mPaint = new Paint();
            mPaint.setStyle(Paint.Style.FILL);
            mPaint.setAntiAlias(true);
        }

        public PeriodsRadioButton(Context context, AttributeSet attrs) {
            super(context, attrs);
        }

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

        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            if (isChecked()) {
                canvas.save();
                float left = getMeasuredWidth() * 0.45f;
                float right = getMeasuredWidth() * 0.55f;
                float top = getMeasuredHeight() * 0.85f;
                float bottom = getMeasuredHeight() * 0.95f;
                mPaint.setColor(getCurrentTextColor());
                canvas.drawRoundRect(left, top, right, bottom, 30, 30, mPaint);
                canvas.restore();
            }
        }

        @Override
        public void setChecked(boolean checked) {
            super.setChecked(checked);
            invalidate();
        }
    }
}

periods_radio_button_text_color_green.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_checked="true" android:color="#00FF00"/>
    <item android:state_pressed="true" android:color="#00FF00"/>
    <item android:color="#888888"/>
</selector>

arrays.xml(如果不需要在布局文件中传入entries,可以直接在PeriodsButtonGroupView中hardcode)

<resources>
    <string-array name="periods_button_group_entries">
        <item></item>
        <item></item>
        <item></item>
        <item></item>
    </string-array>
</resources>

attrs.xml (如果不需要在布局文件中传入entries和color,可以直接在PeriodsButtonGroupView中hardcode)

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="PeriodsButtonGroupView">
        <attr name="android:entries" />
        <attr name="radioButtonTextColor" format="color|reference" />
    </declare-styleable>
</resources>

调用的布局文件xml(如果不需要在布局文件中传入entries和color,可以直接在PeriodsButtonGroupView中hardcode,则不需要最后两行)

<com.xxx.xxx.PeriodsButtonGroupView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:radioButtonTextColor="@color/radio_button_text_color_green"
        android:entries="@array/periods_button_group_entries"/>

注意的点:

1.点击RadioButton时,onDraw方法比点击时setChecked更快调用,所以要重写AppCompatRadioButton的setChecked方法去刷新控件。
2.Paint调用setAntiAlias(true)去锯齿(会有性能的损失)。
3.要调用Canvas的drawRoundRect方法,用drawRect来画的话是直角矩形,不美观。