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小白一枚.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章