一个简单的自定义按钮

2019-10-15  本文已影响0人  良人_Coder

date : 2019.10.15
author : lrcoder


Demo 介绍

功能代码和分析

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!-- 自定义控件的类名 -->
    <declare-styleable name="CountButton">
        <!-- 自定义背景颜色 -->
        <attr name="background_color" format="color|reference"/>
        <!-- 自定义按钮形状  -->
        <attr name="button_style">
            <flag name="circle" value="0"/>
            <flag name="rect" value="1"/>
        </attr>
        <!-- 自定义数字颜色 -->
        <attr name="number_color" format="color|reference"/>
        <!-- 自定义数字大小 -->
        <attr name="number_size" format="dimension"/>
        <!-- 自定义数字最小值 -->
        <attr name="number_min" format="integer"/>
        <!-- 自定义数字最大值 -->
        <attr name="number_max" format="integer"/>
        <!-- 自定义数字初始值 -->
        <attr name="number_default" format="integer"/>
    </declare-styleable>
</resources>

有关declare-styleableattr就没什么好说的,主要来看一下format的值和含义:

format 含义 获取方式
reference 资源ID,类似于@strings/...的资源文件 mTypedArray.getResourceId() ... ...
color 颜色值 mTypedArray.getColor()
dimension 尺寸值 mTypedArray.getDimension()
integer 整型值 mTypedArray.getInt()
string 字符串 mTypedArray.getString()
boolean 布尔值 mTypedArray.getBoolean()
enum 枚举值
float 浮点值 mTypedArray.getFloat()
fraction 百分数 mTypedArray.getFraction()
flag 位或运算 ... ...

其中,enumflag给我的感觉就是键值对,我们可以通过其value值的类型来对控件作出相应的控制,接下来我们就可以在布局中使用我们刚才定义的属性值:

   <org.code.demo.countbuttonview.CountButton
       android:id="@+id/count_button"
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       app:background_color="#0744DF"
       app:button_style="circle"
       app:number_color="#ffffff"
       app:number_max="20"
       app:number_min="0"
       app:number_size="200sp"
       app:number_default="30"/>

自定义控件的继承关系:

  1. 继承已有控件进行自定义控件
  2. 继承布局文件进行自定义控件
  3. 继承View类来实现自定义控件

创建一个CountButton类,这个就是我们自定义的控件名称,他继承自View,下面先上码,具体的解释放在代码的注释中

/**
 * @ProjectName: CountButtonView
 * @Package: org.code.demo.countbuttonview
 * @ClassName: CountButton
 * @Description: 1. 自定义背景颜色,默认为红色
 *               2. 自定义按钮形状, 默认为圆形
 *               3. 自定义数字颜色, 默认为白色
 *               4. 自定义数字大小, 默认为200dp
 *               5. 自定义数字最值, 默认最大为20, 最小为0
 *               6. 自定义初始值, 默认为20
 *               7. 提供数字增加、减少的方法
 * @Author: lrcoder
 * @CreateDate: 2019/10/15
 */
public class CountButton extends View implements View.OnClickListener {

    // TAG ---> log
    private static final String TAG = CountButton.class.getSimpleName();

    public CompositeDisposable mCompositeDisposable = new CompositeDisposable();

    private int mBackgroundColor;
    private int mButtonStyle;
    private int mTextColor;
    private int mMinNumber;
    private int mMaxNumber;
    protected Paint mPaint;
    private Rect mRect;
    private int mNumber;
    float mTextSize;

    public CountButton(Context context) {
        super(context, null);
    }

    public CountButton(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs, 0);
        init(context, attrs);
    }

    private void init(Context context, AttributeSet attrs) {

        // 获取自定义的属性值
        TypedArray mTypedArray = context.obtainStyledAttributes(attrs, R.styleable.CountButton);
        mBackgroundColor = mTypedArray
                .getColor(R.styleable.CountButton_background_color, Color.RED);
        mButtonStyle = mTypedArray
                .getInt(R.styleable.CountButton_button_style, -1);
        mMinNumber = mTypedArray
                .getInt(R.styleable.CountButton_number_min, 0);
        mMaxNumber = mTypedArray
                .getInt(R.styleable.CountButton_number_max, 20);
        mTextColor = mTypedArray
                .getInt(R.styleable.CountButton_number_color, Color.WHITE);
        mTextSize = mTypedArray
                .getDimension(R.styleable.CountButton_number_size, 200);
        int mDefaultNumber = mTypedArray
                .getInt(R.styleable.CountButton_number_default, 20);
        mTypedArray.recycle();
        mNumber = mDefaultNumber;
        mRect = new Rect();
        mPaint = new Paint();
        this.setOnClickListener(this);
        startCount();
    }

    /**
     * 绘制控件
     *
     * @param canvas
     */
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        // 设置画笔背景 (1. 自定义背景颜色,默认为红色)
        mPaint.setColor(mBackgroundColor);
        // 确定绘制形状 (2. 自定义按钮形状, 默认为圆形)
        switch(mButtonStyle) {
            case 0:
                // todo: draw Circle
                canvas.drawCircle(
                        getWidth() / 2,
                        getHeight() / 2,
                        getWidth() / 2,
                        mPaint);
                break;
            case 1:
                // todo: draw Rect
                canvas.drawRect(
                        getLeft(),
                        getTop(),
                        getRight(),
                        getBottom(),
                        mPaint);
                break;
            default:
                // todo: draw Circle 同时 Log.i 提示
                canvas.drawCircle(
                        getWidth() / 2,
                        getHeight() / 2,
                        getWidth() / 2,
                        mPaint);
                Log.e(TAG, "error settings!!!");
                break;
        }
        // 确定数字颜色 (3. 自定义数字颜色, 默认为白色)
        mPaint.setColor(mTextColor);
        // 确定数字大小 (4. 自定义数字大小, 默认为200dp)
        mPaint.setTextSize(mTextSize);
        // 确认数字初始值
        String text =String.valueOf(mNumber);
        mPaint.getTextBounds(text, 0, text.length(), mRect);
        int width = mRect.width();
        int height = mRect.height();
        canvas.drawText(
                text,
                getWidth() / 2 - width / 2,
                getHeight() / 2 + height / 2,
                mPaint);
    }

    /**
     * add your number
     *
     * @param index
     */
    protected void add_number(int index) {

        if (mNumber + index < mMaxNumber) {
            mNumber += index;
        } else if (mNumber + index >= mMaxNumber) {
            mNumber = mMaxNumber;
        }

        Log.i("panzh", mMinNumber + "    _____   " + mNumber);

        // 通知更新视图
        invalidate();
    }

    /**
     * subtract your number
     *
     * @param index
     */
    protected void subtract_number(int index) {
        if (mNumber - index > mMinNumber) {
            mNumber -= index;
        } else if (mNumber - index <= mNumber) {
            mNumber = mMinNumber;
        }
        Log.i("panzh", mMinNumber + "    _____   " + mNumber);

        invalidate();
    }

    @Override
    public void onClick(View v) {
        subtract_number(1);
    }

    private void startCount() {
        mCompositeDisposable.add(Observable.interval(0, 5, TimeUnit.SECONDS)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribeWith(getObserver(1)));
    }

    private DisposableObserver  getObserver(final int id) {
        DisposableObserver disposableObserver = new DisposableObserver<Object>() {
            @Override
            public void onNext(Object o) {
                add_number(1);
            }

            @Override
            public void onComplete() {
                Log.d(id + TAG, "onComplete");
            }

            @Override
            public void onError(Throwable e) {
                Log.e(id + TAG, e.toString(), e);
            }
        };

        return disposableObserver;
    }

}
public class MainActivity extends AppCompatActivity {
    CountButton countButton;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        countButton = new CountButton(MainActivity.this);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        countButton.mCompositeDisposable.clear();
    }
}
上一篇下一篇

猜你喜欢

热点阅读