讓“提交”按鈕狀態(tài)跟隨edittext以及checkbox等的狀態(tài)實時變化

現(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)用就好了巩那。
??以上如有問題吏夯,歡迎批評指正。有問題即横,也歡迎一起討論噪生。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市令境,隨后出現(xiàn)的幾起案子杠园,更是在濱河造成了極大的恐慌顾瞪,老刑警劉巖舔庶,帶你破解...
    沈念sama閱讀 212,454評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異陈醒,居然都是意外死亡惕橙,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,553評論 3 385
  • 文/潘曉璐 我一進(jìn)店門钉跷,熙熙樓的掌柜王于貴愁眉苦臉地迎上來弥鹦,“玉大人,你說我怎么就攤上這事”蚧担” “怎么了朦促?”我有些...
    開封第一講書人閱讀 157,921評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長栓始。 經(jīng)常有香客問我务冕,道長,這世上最難降的妖魔是什么幻赚? 我笑而不...
    開封第一講書人閱讀 56,648評論 1 284
  • 正文 為了忘掉前任禀忆,我火速辦了婚禮,結(jié)果婚禮上落恼,老公的妹妹穿的比我還像新娘箩退。我一直安慰自己,他們只是感情好佳谦,可當(dāng)我...
    茶點故事閱讀 65,770評論 6 386
  • 文/花漫 我一把揭開白布戴涝。 她就那樣靜靜地躺著,像睡著了一般钻蔑。 火紅的嫁衣襯著肌膚如雪喊括。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,950評論 1 291
  • 那天矢棚,我揣著相機(jī)與錄音郑什,去河邊找鬼。 笑死蒲肋,一個胖子當(dāng)著我的面吹牛蘑拯,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播兜粘,決...
    沈念sama閱讀 39,090評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼申窘,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了孔轴?” 一聲冷哼從身側(cè)響起剃法,我...
    開封第一講書人閱讀 37,817評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎路鹰,沒想到半個月后贷洲,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,275評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡晋柱,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,592評論 2 327
  • 正文 我和宋清朗相戀三年优构,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片雁竞。...
    茶點故事閱讀 38,724評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡钦椭,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情彪腔,我是刑警寧澤侥锦,帶...
    沈念sama閱讀 34,409評論 4 333
  • 正文 年R本政府宣布,位于F島的核電站德挣,受9級特大地震影響捎拯,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜盲厌,卻給世界環(huán)境...
    茶點故事閱讀 40,052評論 3 316
  • 文/蒙蒙 一署照、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧吗浩,春花似錦建芙、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,815評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至阀湿,卻和暖如春赶熟,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背陷嘴。 一陣腳步聲響...
    開封第一講書人閱讀 32,043評論 1 266
  • 我被黑心中介騙來泰國打工映砖, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人灾挨。 一個月前我還...
    沈念sama閱讀 46,503評論 2 361
  • 正文 我出身青樓邑退,卻偏偏與公主長得像,于是被迫代替她去往敵國和親劳澄。 傳聞我的和親對象是個殘疾皇子地技,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,627評論 2 350

推薦閱讀更多精彩內(nèi)容