關於自定義View的構造方法裏面的參數的含義可以參考:
代碼:
倒計時類:
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的技術,關於這個可以參考文檔 :
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小白一枚.