android自定义验证码倒计时View

关于自定义View的构造方法里面的参数的含义可以参考:

http://www.cnblogs.com/angeldevil/p/3479431.html

代码:

倒计时类:

public class CountDownBtn extends Button implements View.OnClickListener
{
    private static final String TAG = CountDownBtn.class.getSimpleName();
    private String TIP;
    private Integer TOTALTIME;
    private int tempTotalTime;
    private Integer normalBg;
    private Integer countTimeBg;
    private Activity activity;
    private final static String SECOND = "秒";
    private Timer timer;
    private GetGenerateCodeListener listener;
    private CountDownBtn instance;

    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);
        init(context, attrs, defStyleAttr);
    }

    private void init(Context context, AttributeSet attrs, int defStyleAttr)
    {
        instance = this;
        if(attrs != null)
        {
            TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.CountDown);
            if(array.length() > 0)
            {
                TIP = array.getString(R.styleable.CountDown_defTip);
                tempTotalTime = TOTALTIME = array.getInteger(R.styleable.CountDown_totalTime, 0);
                normalBg = array.getResourceId(R.styleable.CountDown_normalBg, 0);
                countTimeBg = array.getResourceId(R.styleable.CountDown_countTimeBg, 0);
                LogUtils.i(TAG, "data " + TIP + "  " + tempTotalTime + "  " + normalBg + "  " + countTimeBg);
                checkMessage(tempTotalTime, TIP, normalBg, countTimeBg);
                array.recycle();
            }
        }
    }

    public void setActivity(Activity activity)
    {
        if (activity == null) {
            throw new NullPointerException("activity non null ");
        }
        this.activity = activity;
    }

    private void start()
    {
        timer = new Timer();
        timer.schedule(new TimerTask()
        {
            @Override
            public void run()
            {
                activity.runOnUiThread(new Runnable()
                {
                    @Override
                    public void run()
                    {
                        if (TOTALTIME > 0) {
                            CountDownBtn.this.instance.setText((TOTALTIME) + SECOND);
                            TOTALTIME = TOTALTIME - 1;
                        } else {
                            CountDownBtn.this.instance.setBackground(CountDownBtn.this.getResources().getDrawable(normalBg));
                            CountDownBtn.this.instance.setText(TIP);
                            timer.cancel();
                            TOTALTIME = tempTotalTime;
                            CountDownBtn.this.instance.setClickable(true);
                        }
                    }
                });
            }
        }, 0, 1000);
    }

    /**
     *该法是在layout中不设置相关属性,则需要在code里面动态的设置属性
     * @param totalTime    倒计时的时间范围
     * @param tipId        默认的提示语
     * @param normalBgId   刚开始的默认背景.传入对应的Id
     * @param countTimeBgId   倒计时时的背景颜色.传入对应的ID
     */
    public void setMessage(int totalTime,int tipId,int normalBgId,int countTimeBgId)
    {
        tempTotalTime = this.TOTALTIME = totalTime;
        this.TIP = this.getResources().getString(tipId);
        normalBg = normalBgId;
        countTimeBg = countTimeBgId;
        checkMessage(TOTALTIME, TIP, normalBg, countTimeBg);
    }

    /**
     * 校验数据合法性.(如果数据不合法,则使用默认值).
     * @param totalTime
     * @param tip
     * @param normalBgId
     * @param countTimeBgId
     */
    private void checkMessage(int totalTime,String tip,int normalBgId,int countTimeBgId)
    {
        LogUtils.i(TAG,"checkMessage user count");
        if(totalTime <= 0)
        {
            tempTotalTime = totalTime = 60;
        }
        if(totalTime > 120)
        {
            tempTotalTime = totalTime = 120;
        }
        if(TextUtils.isEmpty(tip))
        {
            TIP = this.getResources().getString(R.string.btn_generatecode);
        }
        if(normalBgId == 0)
        {
            normalBg = R.color.colorAccent;    //默认背景,可以自己定义
        }
        if(countTimeBgId == 0)
        {
            countTimeBg = R.color.colorPrimary;   //倒计时背景,可以自己定义
        }
        this.setBackground(getResources().getDrawable(normalBg));
        this.setText(TIP);
        this.setGravity(Gravity.CENTER);
        this.setOnClickListener(this);
    }

    public void cance()
    {
        if(timer != null)
        {
            timer.cancel();
        }
    }

    @Override
    public void onClick(View v)
    {
        if(this.getText().equals(TIP))
        {
            this.setClickable(false);
            this.setBackground(this.getResources().getDrawable(countTimeBg));
            start();
            if(listener != null)
            {
                listener.getGenerateCode();
            }
        }
    }

    /**
     * 单击获取验证码以后的回调,在里面进行获取验证码的各种操作(networker)
     */
    public interface GetGenerateCodeListener
    {
        void getGenerateCode();
    }

    public void setGenerateCodeListener(GetGenerateCodeListener listener)
    {
        this.listener = listener;
    }
}

属性设置(attr):

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="CountDown">
        <!--默认提示语-->
        <attr name="defTip" format="string"></attr>
        <!--总计的倒计时时间以秒为单位-->
        <attr name="totalTime" format="integer"></attr>
        <!--正常情况下的背景-->
        <attr name="normalBg" format="reference"></attr>
        <!--倒计时的背景颜色-->
        <attr name="countTimeBg" format="reference"></attr>
    </declare-styleable>
</resources>

布局文件:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
    >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:clipToPadding="true"
        android:fitsSystemWindows="true"
        android:orientation="vertical">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolBarBossLogin"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content">

        </android.support.v7.widget.Toolbar>

        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">

            <android.support.design.widget.TextInputLayout
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:layout_weight="1">

                <AutoCompleteTextView
                    android:id="@+id/tvPhone"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:hint="@string/hint_phonenumber"
                    android:inputType="phone"
                    android:maxLines="1"
                    android:singleLine="true"/>

            </android.support.design.widget.TextInputLayout>
            <com.channelsoft.ggsj.view.CountDownBtn
                android:id="@+id/btnGenerateCode"
                android:layout_width="90.0dp"
                android:layout_height="45.0dp"
                android:layout_weight="0"
                app:defTip = "@string/btn_generatecode"
                app:totalTime = "60"
                app:normalBg = "@android:color/holo_red_dark"
                app:countTimeBg = "@android:color/white">

            </com.channelsoft.ggsj.view.CountDownBtn>
        </LinearLayout>

        <android.support.design.widget.TextInputLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <EditText
                android:id="@+id/tvPassword"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="@string/prompt_password"
                android:imeActionId="@+id/login"
                android:imeActionLabel="@string/action_sign_in_short"
                android:imeOptions="actionUnspecified"
                android:inputType="textPassword"
                android:maxLines="1"
                android:singleLine="true"/>

        </android.support.design.widget.TextInputLayout>

        <Button
            android:id="@+id/bntLogin"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="@string/btn_login"
            />
    </LinearLayout>
</layout>

Activity:activity使用了Data Binding的技术,关于这个可以参考文档 :

https://segmentfault.com/a/1190000002876984

public class BossLoginActivity extends BaseActivity implements View.OnClickListener,CountDownBtn.GetGenerateCodeListener
{
    private ActivityBossLoginBinding binding ;
    private GenerateCodeViewModel generateCodeViewModel;
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        binding = DataBindingUtil.setContentView(this,R.layout.activity_boss_login);
        binding.bntLogin.setOnClickListener(this);
        binding.btnGenerateCode.setActivity(this);
        binding.btnGenerateCode.setGenerateCodeListener(this);
    }

    @Override
    public void onClick(View v)
    {
        switch(v.getId())
        {
            case R.id.bntLogin:
                if(checkPhoneNumber())
                {
                    generateCodeViewModel = new GenerateCodeViewModel();
                    generateCodeViewModel.getGenerateCode(binding.tvPhone.getText().toString().trim());
                }
                break;
            case R.id.btnGenerateCode:

                break;
        }
    }

    @Override
    public void getGenerateCode()
    {

    }

    @Override
    protected void onDestroy()
    {
        super.onDestroy();
        binding.btnGenerateCode.cance();
    }

    private boolean checkPhoneNumber()
    {
        return true;
    }
}

代码比较简单,这里不多做介绍,有什么问题,欢迎批评,android小白一枚.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值