Android - 圆形 Button 与倒计时控件

前言

平时咱们开发 Button 是很常见的控件,它总是以各种形式出现。例如:加边框边框颜色各种圆角。以至于我们不得不写 n 个 shape 文件去维护。这样总是很麻烦,还很容易忘记更改某些文件。所以,我就封装了一个 RoundedButton 来减少一些不必要的操作。

先看图:

public class RoundBtn extends android.support.v7.widget.AppCompatButton {

    private GradientDrawable mShape;

    //不可用颜色
    private int mUnEnableColor;
    //按下颜色
    private int mPressedColor;
    //当前颜色
    private int mNormalColor;
    //当前圆角
    private float mBorderCorner;
    //四边边框宽度
    private float mStrokeWidth;
    //四边边框颜色
    private int mBorderColor;
    /**
     *  倒计时时间,如果要从初始值开始倒计时,需要多加 1(要从 5 秒开始,得写 6)
     */
    protected int mCountDownTime;

    private boolean mIsTouchPass = true;

    private boolean mIsEnable;

    private Context mContext;

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

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

    public RoundBtn(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mContext=context;
        initView(context,attrs);
    }

    private void initView(Context context, AttributeSet attrs){
        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.RoundBtn);
        mUnEnableColor = ta.getColor(R.styleable.RoundBtn_bgUnAbleColor, ContextCompat.getColor(context,R.color.light_blue_color));
        mNormalColor = ta.getColor(R.styleable.RoundBtn_bgAbleColor, ContextCompat.getColor(context,R.color.blue_color));
        mPressedColor = ta.getColor(R.styleable.RoundBtn_bgPressColor, ContextCompat.getColor(context,R.color.more_blue_color));
        mBorderColor = ta.getColor(R.styleable.RoundBtn_edgeColor, ContextCompat.getColor(context,R.color.blue_color));
        mStrokeWidth = ta.getInt(R.styleable.RoundBtn_edgeWidth, dp2px(context, 0));
        mBorderCorner =ta.getFloat(R.styleable.RoundBtn_roundRadius, dp2px(context, 0));
        mIsEnable = ta.getBoolean(R.styleable.RoundBtn_isEnable, true);
        mCountDownTime = ta.getInteger(R.styleable.RoundBtn_countTime, 1);

        mShape = new GradientDrawable();
        mShape.setShape(GradientDrawable.RECTANGLE);
        mShape.setCornerRadius(dp2px(context,mBorderCorner));

        setBtnStyles();
        setGravity(Gravity.CENTER);
        ta.recycle();
    }

    private void setBtnStyles() {
        setEnabled(mIsEnable);

        if(mIsEnable) {
            mShape.setColor(mNormalColor);
        }else{
            mShape.setColor(mUnEnableColor);
        }

        if (mBorderColor != 0) {
            mShape.setStroke((int) dp2px(mContext,mStrokeWidth), mBorderColor);
        }

        setBackgroundDrawable(mShape);

        if(mIsEnable) {
            //设置点击按钮之后的颜色更换
            setOnTouchListener((arg0, event) -> {
                setBackgroundDrawable(mShape);
                return setColor(event.getAction());
            });
        }

    }

    //处理按钮点击事件无效
    @Override
    public void setOnClickListener(OnClickListener l) {
        super.setOnClickListener(l);
        mIsTouchPass = false;
    }

    //处理按下去的颜色
    public boolean setColor(int action) {
        switch (action) {
            case MotionEvent.ACTION_DOWN:
                mShape.setColor(mPressedColor);
                break;
            case MotionEvent.ACTION_UP:
                mShape.setColor(mNormalColor);
                break;
            case MotionEvent.ACTION_CANCEL:
                mShape.setColor(mNormalColor);
                break;
        }

        return mIsTouchPass;
    }
    /**
     * 设置是否可点击
     */
    public RoundBtn setEnable(boolean isEnable){
        mIsEnable=isEnable;
        setBtnStyles();
        return this;
    }
}

代码很简单,下面我们来看看自定义属性设置

    <!-- 圆角 btn -->
    <declare-styleable name="RoundBtn">
        <attr name="bgUnAbleColor" format="color"/>
        <attr name="bgAbleColor" format="color"/>
        <attr name="bgPressColor" format="color"/>
        <attr name="edgeColor" format="color"/>
        <attr name="edgeWidth" format="integer"/>
        <attr name="roundRadius" format="float"/>
        <attr name="isEnable" format="boolean"/>
        <attr name="countTime" format="integer"/>
    </declare-styleable>

好了,代码就这么多了。

这里,我又顺便封装了一个,倒计时控件。

public class CountDownBtn extends RoundBtn {

    private Disposable mDisposable;

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

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

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

    private void initView(Context context) {
        //explain start:起始数值 count:发射数量  initialDelay:延迟执行时间 period:发射周期时间  unit:时间颗粒度
        setText(context.getString(R.string.send_code_msg));
        setOnClickListener(view -> {

            if (mListener != null) {
                mListener.start();
            }

            mDisposable = Flowable.intervalRange(1, mCountDownTime, 0, 1, TimeUnit.SECONDS)
                    .observeOn(AndroidSchedulers.mainThread())
                    .doOnNext(aLong -> {
                        setEnable(false);
                        setText(context.getString(R.string.get_code_msg_again) + " " + ((mCountDownTime) - aLong) + " 秒");
                    })
                    .doOnComplete(() -> {
                        setEnable(true);
                        setText(context.getString(R.string.send_code_msg));
                    })
                    .subscribe();
        });
    }



    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();

        if (mDisposable != null && !mDisposable.isDisposed()) {
            mDisposable.dispose();
            mDisposable = null;
        }

        if (mListener != null) {
            mListener=null;
        }
    }

    private ISendCodeListener mListener;

    public void setISendCodeListener(ISendCodeListener listener) {
        mListener=listener;
    }

    public interface ISendCodeListener{
        void start();
    }
}

使用方法:

CountDownBtn countDownBtn = findViewById(R.id.id_count_down_btn);
countDownBtn.setISendCodeListener(() -> Toast.makeText(CustomBtnActivity.this, "验证码已发送", Toast.LENGTH_SHORT).show());

到这里内容就结束啦。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏james大数据架构

仿优酷Android客户端图片左右滑动(自动滑动)

最终效果: ? 页面布局main.xml: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns...

2187
来自专栏向治洪

ViewFlipper实现多页面切换

1、屏幕切换指的是在同一个Activity内屏幕见的切换,最长见的情况就是在一个FrameLayout内有多个页面,比如一个系统设置页面;一个个性化设置页面。...

22910
来自专栏向治洪

viewgroup实现item拖动效果

网络上关于GridView可拖动的例子已经不少了,包括带动画不带动画的都有一堆,但几乎都是通过继承Android原生控件GridView来扩展的,当然这种实现方...

2496
来自专栏向治洪

android沉浸式状态栏的实现

在style.xml中添加 <style name="Theme.Timetodo" parent="@android:style/Theme.Holo.L...

2587
来自专栏Android干货园

Android 获取屏幕高宽度,密度,通知栏高度,截图等常用方法

版权声明:本文为博主原创文章,转载请标明出处。 https://blog.csdn.net/lyhhj/article/details/49...

4051
来自专栏Android干货

浅谈TabLayout(ViewPager+Tab联动)

46411
来自专栏非著名程序员

Android学习笔记(一)之仿正点闹钟时间齿轮滑动的效果

看到正点闹钟上的设置时间的滑动效果非常好看,自己就想做一个那样的,在网上就开始搜资料了,看到网上有的齿轮效果的代码非常多,也非常难懂,我就决定自己研究一下,现在...

23810
来自专栏Android开发指南

10.下拉刷新、加载更多、标记已读、轮播条、缓存

39110
来自专栏Android干货

Android项目实战(二十七):数据交互(信息编辑)填写总结

3347
来自专栏Fish

从相机or相册获取图片并显示

这个技术应该算是十分稀松平常了,但是对于小白来说,还是要费一番功夫的。因此在这里贴上我的代码,也是为了以后用到的时候方便找。。。 package com.exa...

3067

扫码关注云+社区

领取腾讯云代金券