現(xiàn)在很多應(yīng)用在對于提交按鈕是否可以點擊的判斷都是隨著用戶輸入的內(nèi)容或者勾選的狀態(tài)而變化的夹厌,應(yīng)該很少有人會如果用戶在界面上沒有任何輸入的時候就讓其開始點擊按鈕吧缎玫。這樣做首先是增加了用戶無謂的操作枉阵。另外也是會增加很多的非空判斷,實在是不劃算。所以才會有這種 如果該輸入的還沒有輸入喧半,該選擇的沒有任何勾選信认,那么提交按鈕就不點亮還處于不可點擊狀態(tài)這樣的設(shè)計了材义。
??好,其實今天跟大家說的就是自己現(xiàn)在在用的一個對于這種狀態(tài)判斷與控制的工具類了嫁赏。下面直接看代碼其掂。
/**
* Created by hexiaopang on 2016/11/4.
* 一個監(jiān)聽 edittext,checkbox是否有輸入和選中潦蝇,然后改變“提交”按鈕的可提交狀態(tài)
* 只需要將需要監(jiān)控的控件例如EditText款熬,CheckBox添加進(jìn)來深寥,再設(shè)置“提交”按鈕即可
*/
public class SubmitControl {
private List<View> listViews = null;//用于存儲 組件的list集合
private MyTextWatcher myWatcher = null;//edittext以及textview是否有輸入的監(jiān)聽
private MyOnCheckedChangedListener myCheckedListener;//checkbox的選中狀態(tài)監(jiān)聽
private TextView submitButton;//提交“按鈕”
private static SubmitControl myControl;
/**
* 獲取 單例實例(懶漢式)
*/
public static SubmitControl getInstance() {
if(myControl == null){
myControl = new SubmitControl();
}
return myControl;
}
/**
* 初始化數(shù)據(jù) 這個是必須得首先調(diào)用的,否則會出現(xiàn)混亂錯誤
*/
public void initConroller() {
if (listViews == null) {
listViews = new ArrayList<View>();
} else {
listViews.clear();
}
myWatcher = new MyTextWatcher();
myCheckedListener = new MyOnCheckedChangedListener();
}
/**
* 添加view組件(這個view可以是textview或者是edittext或者是checkbox了)
*/
public void addView(View... views) {
for (View viewTemp : views) {
if (!listViews.contains(viewTemp)) {
if(viewTemp instanceof CheckBox){
((CheckBox)viewTemp).setOnCheckedChangeListener(myCheckedListener);
}else if(viewTemp instanceof TextView){
((TextView)viewTemp).addTextChangedListener(myWatcher);
}
listViews.add(viewTemp);
}
}
}
//將某個組件從監(jiān)控狀態(tài)中移除
public void remove(View... views) {
for (View view : views) {
//如果list中有 要移除的元素的話
if(listViews.contains(view)){
if (view instanceof CheckBox) {
((CheckBox) view).setOnCheckedChangeListener(null);
}else if (view instanceof TextView) {
((EditText) view).removeTextChangedListener(myWatcher);
}
listViews.remove(view);
}
}
}
/**
* checkbox的監(jiān)聽
*/
private class MyOnCheckedChangedListener implements OnCheckedChangeListener {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
changeSubmitStatus();
}
}
/**
* edittext的監(jiān)聽
*/
private class MyTextWatcher implements TextWatcher {
@Override
public void afterTextChanged(Editable s) {
changeSubmitStatus();
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
}
/**
* 根據(jù) 各種組件狀態(tài)的改變贤牛,來設(shè)置提交按鈕是否可點擊
* 貌似避免不了遍歷
*/
private void changeSubmitStatus() {
int count = 0;
for (int i = 0; i < listViews.size(); i++) {
if (listViews.get(i) instanceof CheckBox) {
if (((CheckBox) listViews.get(i)).isChecked()) {
count++;
} else {
break;
}
}else if (listViews.get(i) instanceof TextView) {
if (!TextUtils.isEmpty(((TextView) listViews.get(i)).getText().toString())) {
count++;
} else {
break;
}
}
}
if (submitButton == null) {
throw new NullPointerException("你至少得調(diào)用setSubmitButton()方法設(shè)置一個提交按鈕吧");
}
submitButton.setEnabled((count == listViews.size()));
}
/**
* 設(shè)置提交按鈕
* 并且提交按鈕的狀態(tài)改變是通過 textview或者edittext或者checkbox的對應(yīng)賦值方法調(diào)用時候才會改變
*/
public void setSubmitButton(TextView button) {
this.submitButton = button;
}
}```
??我們來看下這個類惋鹅,上面聲明的變量就不說了。注釋寫的很清楚了殉簸,哈哈哈闰集。首先是initConroller了。這個方法就是初始化存放view的list集合般卑,如果不為空我們進(jìn)行清空返十,因為我們類是單例的,所以如果list不為null椭微,那么一定是存放著上個頁面的view洞坑,所以用的時候必須要進(jìn)行清空了。同樣監(jiān)聽也必須new出來蝇率。其次是addview方法了迟杂,其實是可以一次添加多個的,我們轉(zhuǎn)化出來就是一個數(shù)組了本慕。同樣我們參數(shù)類型是view排拷,因為我們對于要監(jiān)聽的任何控件基本都是繼承自view了。而方法內(nèi)部則是對于view進(jìn)行了區(qū)分锅尘,我們這里就是對于textview(edittext也是繼承自textview嘛)和checkbox加上監(jiān)聽了监氢,然后添加入我們的view的集合。我們同時也提供了將view移除監(jiān)聽的方法就是remove方法了藤违,這個或許會很少用到浪腐。但是萬一有這樣的業(yè)務(wù)需求呢。下面的兩個內(nèi)部類就是對于textview以及checkbox的監(jiān)聽的具體實現(xiàn)顿乒。我們可以看到在textview(當(dāng)然更多的是Edittext)的監(jiān)聽的afterTextChanged方法以及checkbox的監(jiān)聽的onCheckedChanged方法中都調(diào)用了changeSubmitStatus方法了议街。這個方法大家也可以看到是在我們需要監(jiān)控的控件的狀態(tài)改變的時候會被調(diào)用的了。首先是一個變量count璧榄,然后是進(jìn)行一次遍歷特漩, 如果遍歷到的當(dāng)前view是checkbox就看其是否是checked狀態(tài),是的話count+1,否的話直接break骨杂,沒有必要繼續(xù)循環(huán)下去涂身,因為這就一定代表組件沒有輸入或者沒有勾選嘛,我們的“提交按鈕”是不可以點擊的了搓蚪。同樣如果遍歷到的是textview就看其是否為非空蛤售,是的話count+1,否的話也是直接break了,原因同上悍抑。在循環(huán)的最后我們拿這個count和存放view的list集合的元素個數(shù)進(jìn)行比較鳄炉,如果相等則是代表所有需要輸入的或者勾選的都已經(jīng)勾選和非空了。按鈕便就enable可以點擊了搜骡。當(dāng)然如果“提交按鈕”都沒有設(shè)置拂盯,那就沒法玩耍了。就直接給調(diào)用方拋出一個異常吧记靡。哈哈谈竿,所以最后一個方法就是設(shè)置“提交按鈕的了”。
??代碼就是這樣子的摸吠。再說下調(diào)用了空凸。例如下面這樣子:
@Override
public void setController() {
super.setController();
SubmitControl.getInstance().initConroller();
SubmitControl.getInstance().addView(verifyEt);
SubmitControl.getInstance().setSubmitButton(submitBtn);
}```
??其實有一點特別重要的是我們的這個setController方法一定要放在Activity的onResume方法里面。因為我們的類是單例的寸痢。好比在界面A有有一些設(shè)置呀洲,然后跳轉(zhuǎn)到頁面B,但是A未銷毀啼止,然后又返回了A道逗,若此時不調(diào)用setController其實還是在監(jiān)聽B頁面的按鈕以及輸入框等的狀態(tài)了。當(dāng)然了献烦,我們一般都會有個BaseActivity就是基類滓窍,其實在基類里面寫個方法setController,然后在基類的onResume里面調(diào)用就好了巩那。
??以上如有問題吏夯,歡迎批評指正。有問題即横,也歡迎一起討論噪生。