一崖疤、前言:
日常開發(fā)中,我們可能會(huì)遇到需要監(jiān)聽EditText輸入蜕依,比如判斷輸入是否為電話號(hào)碼桅锄,獲取輸入的數(shù)據(jù)長度來限定字?jǐn)?shù)等。這就需要監(jiān)聽EditText的輸入狀態(tài)样眠。EditText使用TextWatcher實(shí)現(xiàn)類似按鈕監(jiān)聽事件:
效果圖:
二友瘤、代碼展示:
1. MainActivity.java
public class MainActivity extends AppCompatActivity {
private EditText mNumber;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mNumber = (EditText) findViewById(R.id.phone_number);
//為EditText設(shè)置監(jiān)聽,注意監(jiān)聽類型為TextWatcher
mNumber.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
toast("您輸入的數(shù)據(jù)為:"+s.toString());
}
@Override
public void afterTextChanged(Editable s) {
}
});
}
private void toast(String s){
Toast.makeText(getApplication(),s,Toast.LENGTH_SHORT).show();
}
}
2. Activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:padding="10dp"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.alphathink.myapplication.MainActivity">
<EditText
android:id="@+id/phone_number"
android:layout_width="368dp"
android:layout_height="wrap_content"
android:hint="@string/number"
android:inputType="number"
tools:layout_editor_absoluteY="0dp"
tools:layout_editor_absoluteX="8dp" />
</LinearLayout>
三檐束、TextWatcher詳解
1. 注意:
CharSequence是一個(gè)接口辫秧,比較常見的String、StringBuilder被丧、StringBuffer都實(shí)現(xiàn)了這個(gè)接口盟戏。當(dāng)我們看到一個(gè)API里面有CharSequence的時(shí)候,它也是可以被其子類代替的甥桂,一般用String代替即可柿究。
我們看到TextWatcher監(jiān)聽里覆寫了3個(gè)方法:
void beforeTextChanged(CharSequence s, int start, int count, int after);
void onTextChanged(CharSequence s, int start, int before, int count);
void afterTextChanged(Editable s);
行順序來說是:beforeTextChanged()>>>onTextChanged()>>>afterTextChanged()
請勿在afterTextChanged();內(nèi)加入代碼進(jìn)行驗(yàn)證黄选,這個(gè)會(huì)進(jìn)入死循環(huán)的蝇摸,后邊講原因。
2. 關(guān)于beforeTextChanged(CharSequence s, int start, int count, int after);
官方文檔解釋:
void beforeTextChanged (CharSequence s,
int start,
int count,
int after)
This method is called to notify you that, within s, the count characters beginning at start are about to be replaced by new text with length after. It is an error to attempt to make changes to s from this callback.
意思大概是:
這個(gè)方法用來通知你办陷,在字符串s里貌夕,光標(biāo)start開始處的count個(gè)字符將要被after長的字符代替,禁止在這個(gè)回調(diào)里改字符串s民镜》茸ǎ可以理解成提醒你你做了什么操作。
操作》》》系統(tǒng)提醒你做了什么事(還沒做)》》》》系統(tǒng)開始做
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
toast("s字符串為:"+s+"開始處:"+start+"制圈,替換體的長度:"+count+"后替換體長度"+after);
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
}
分別輸入一個(gè)字符植旧、二個(gè)字符辱揭、刪除一個(gè)字符的截圖
這樣理解:
這個(gè)方法執(zhí)行獲取的狀態(tài)是在你輸入前光標(biāo)所在位置:
輸入一個(gè)字符:s字符串也就是當(dāng)前EditText中的內(nèi)容為空,所以輸出空病附;
開始處:0,司空見慣亥鬓,從0計(jì)數(shù)完沪;
替換長度:0,這個(gè)怎么理解呢嵌戈?理解成將被替換長度即可覆积,你要在光標(biāo)處往后替換然而往后并沒有
字符;
后替換體長度:1熟呛,雖然他光標(biāo)沒動(dòng)宽档,這里表示他將要改變的長度,等于你輸入字符長度1庵朝。
輸入二個(gè)字符:s字符串是什么吗冤?我們剛剛輸入的你字是不是還在,這就是s的內(nèi)容;
開始處:光標(biāo)所在位置1;
替換長度:0暗甥,為什么還是0佑笋?實(shí)話說這個(gè)是一直為0的,因?yàn)樵谀爿斎肭皥?zhí)行溪窒,你所做的操作時(shí)
一直往后增加,而增加操作相當(dāng)于用輸入字符替換了一個(gè)長度為0的字符,也就是空宣羊,所以一直為0;
后替換體長度:等于替換字符長度汰蜘。
刪除一個(gè)字符:刪除前執(zhí)行仇冯,所以內(nèi)容為“你你好”;
開始處:2鉴扫,光標(biāo)所在位赞枕;
替換體長度:1,這個(gè)這里就變了坪创,為什么變了呢炕婶?因?yàn)槲覀冏隽藙h除操作,被替換的長度是刪除的
那個(gè)字符長度也就是1莱预;
后替換體的長度:0柠掂,這個(gè)又是一直為0的,為什么呢依沮,和前邊那個(gè)一直為0的原因一樣涯贞,我們做刪除操作
等于用空來替換一個(gè)字符枪狂,所以替換的長度為空的長度,也就是0宋渔;
這個(gè)原理理解了的話州疾,對于void onTextChanged(CharSequence s, int start, int before, int count); 和這個(gè)類似,官方文檔如下:
void onTextChanged (CharSequence s,
int start,
int before,
int count)
This method is called to notify you that, within s, the count characters beginning at start have just replaced old text that had length before. It is an error to attempt to make changes to s from this callback.
意思大概是:這個(gè)方法是用來告訴你皇拣,在字符串s里严蓖,光標(biāo)start開始處的count個(gè)字符剛剛把原來的before長度的字符替換。理解為通知你剛剛做氧急,或正在做颗胡,主要與后邊afterTextChanged()方法區(qū)分;
代碼更改如下:
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
toast("s字符串為:"+s+"吩坝,開始處:"+start+"毒姨,替換體長度:"+count+",前替換體長度"+before);
}
@Override
public void afterTextChanged(Editable s) {
}
分別輸入一個(gè)字符钉寝、二個(gè)字符弧呐、刪除一個(gè)字符的截圖:
結(jié)合第一個(gè)理解:這個(gè)方法在你剛剛操作后提示你:
輸入一個(gè)字符:s替換后后執(zhí)行此方法,所以可以讀取到字符串“你”瘩蚪;
開始處0:下標(biāo)位泉懦,接下來不說了這個(gè)。
替換體:也就是你輸入的字符長度疹瘦,“你”的長度為1崩哩;
前替換體:0,你用“你”這個(gè)字符替換了長度為0
的字符言沐。
輸入二個(gè)字符:替換體為你輸入的“你好”的長度2邓嘹;
前替換體:0,同上险胰。
刪除一個(gè)字符:s字符為“你你”汹押;
替換體長度:0,好比你用長度為0的字符代替了“你”字起便;
前替換體:1棚贾,“你”的長度。
對于 void afterTextChanged(Editable s):
官方解釋:
This method is called to notify you that, somewhere within s, the text has been changed. It is legitimate to make further changes to s from this callback, but be careful not to get yourself into an infinite loop, because any changes you make will cause this method to be called again recursively. (You are not told where the change took place because other afterTextChanged() methods may already have made other changes and invalidated the offsets. But if you need to know here, you can use setSpan(Object, int, int, int) in onTextChanged(CharSequence, int, int, int) to mark your place and then look up from here where the span ended up.
意思是:這個(gè)方法告訴你榆综,在字符串s內(nèi)的某處妙痹,一些地方已經(jīng)改變了,在這個(gè)方法里可以對s做一些改變鼻疮,但是注意別讓你陷入反復(fù)調(diào)用它的問題上怯伊,因?yàn)榭赡苣阕龅娜魏胃淖儠?huì)讓他遞歸調(diào)用本身。(這個(gè)方法沒有告訴你哪里改變了判沟,或許其他afterTextChanged()可能已經(jīng)改變它了并使這個(gè)改變失效耿芹,但是如果你確定知道他是否起作用了崭篡,你可以在onTextChanged()里調(diào)用setSpan(Object, int, int, int)方法去標(biāo)記并在此驗(yàn)證是否在這結(jié)束了))
來吧我們來驗(yàn)證一下這個(gè)方法做了什么事:
修改代碼:
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
s.append("hello");
toast(s.toString());
}
假如我們輸入“你”字,預(yù)測結(jié)果是不是:
你hello
然而結(jié)果是:
.......竟然ANR了吧秕。也就是程序無響應(yīng)了 -_-琉闪!
修改EditText的輸入長度為15再試試:
android:maxLength="15"
運(yùn)行截圖:
原
詳解EditText輸入監(jiān)聽TextWatcher
2017年03月18日 18:18:35鼎鼎浩閱讀數(shù) 16291文章標(biāo)簽:EditText監(jiān)聽 android TextWatche 更多
分類專欄:Android基礎(chǔ)
<article class="baidu_pl" style="caret-color: rgb(0, 0, 0); color: rgb(0, 0, 0); font-family: -webkit-standard; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; text-decoration: none;">
版權(quán)聲明:本文為博主原創(chuàng)文章,遵循CC 4.0 BY-SA 版權(quán)協(xié)議砸彬,轉(zhuǎn)載請附上原文出處鏈接和本聲明塘偎。
本文鏈接:https://blog.csdn.net/Z_DingHao/article/details/63263129
日常開發(fā)中,我們可能會(huì)遇到需要監(jiān)聽EditText輸入拿霉,比如判斷輸入是否為電話號(hào)碼,獲取輸入的數(shù)據(jù)長度來限定字?jǐn)?shù)等咱扣。這就需要監(jiān)聽EditText的輸入狀態(tài)绽淘。EditText使用TextWatcher實(shí)現(xiàn)類似按鈕監(jiān)聽事件:
使用方法
效果圖:
MainActivity.java
public class MainActivity extends AppCompatActivity {
private EditText mNumber;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mNumber = (EditText) findViewById(R.id.phone_number);
//為EditText設(shè)置監(jiān)聽,注意監(jiān)聽類型為TextWatcher
mNumber.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
toast("您輸入的數(shù)據(jù)為:"+s.toString());
}
@Override
public void afterTextChanged(Editable s) {
}
});
}
private void toast(String s){
Toast.makeText(getApplication(),s,Toast.LENGTH_SHORT).show();
}
}
Activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:padding="10dp"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.alphathink.myapplication.MainActivity">
<EditText
android:id="@+id/phone_number"
android:layout_width="368dp"
android:layout_height="wrap_content"
android:hint="@string/number"
android:inputType="number"
tools:layout_editor_absoluteY="0dp"
tools:layout_editor_absoluteX="8dp" />
</LinearLayout>
TextWatcher詳解
注意:
CharSequence是一個(gè)接口闹伪,比較常見的String沪铭、StringBuilder、StringBuffer都實(shí)現(xiàn)了這個(gè)接口偏瓤。當(dāng)我們看到一個(gè)API里面有CharSequence的時(shí)候杀怠,它也是可以被其子類代替的,一般用String代替即可厅克。
我們看到TextWatcher監(jiān)聽里覆寫了3個(gè)方法:
void beforeTextChanged(CharSequence s, int start, int count, int after);
void onTextChanged(CharSequence s, int start, int before, int count);
void afterTextChanged(Editable s);
執(zhí)行順序來說是:beforeTextChanged()>>>onTextChanged()>>>afterTextChanged()
請勿在afterTextChanged()赔退;內(nèi)加入代碼進(jìn)行驗(yàn)證,這個(gè)會(huì)進(jìn)入死循環(huán)的证舟,后邊講原因硕旗。
關(guān)于beforeTextChanged(CharSequence s, int start, int count, int after);
官方文檔解釋:
void beforeTextChanged (CharSequence s,
int start,
int count,
int after)
This method is called to notify you that, within s, the count characters beginning at start are about to be replaced by new text with length after. It is an error to attempt to make changes to s from this callback.
意思大概是:
這個(gè)方法用來通知你,在字符串s里女责,光標(biāo)start開始處的count個(gè)字符將要被after長的字符代替漆枚,禁止在這個(gè)回調(diào)里改字符串s〉种可以理解成提醒你你做了什么操作墙基。
操作》》》系統(tǒng)提醒你做了什么事(還沒做)》》》》系統(tǒng)開始做
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
toast("s字符串為:"+s+"開始處:"+start+",替換體的長度:"+count+"后替換體長度"+after);
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
}
分別輸入一個(gè)字符刷喜、二個(gè)字符残制、刪除一個(gè)字符的截圖
這樣理解:
這個(gè)方法執(zhí)行獲取的狀態(tài)是在你輸入前光標(biāo)所在位置:
輸入一個(gè)字符:s字符串也就是當(dāng)前EditText中的內(nèi)容為空,所以輸出空吱肌;
開始處:0痘拆,司空見慣,從0計(jì)數(shù)氮墨;
替換長度:0纺蛆,這個(gè)怎么理解呢吐葵?理解成將被替換長度即可,你要在光標(biāo)處往后替換然而往后并沒有
字符桥氏;
后替換體長度:1温峭,雖然他光標(biāo)沒動(dòng),這里表示他將要改變的長度字支,等于你輸入字符長度1凤藏。
輸入二個(gè)字符:s字符串是什么?我們剛剛輸入的你字是不是還在堕伪,這就是s的內(nèi)容揖庄;
開始處:光標(biāo)所在位置1;
替換長度:0欠雌,為什么還是0蹄梢?實(shí)話說這個(gè)是一直為0的,因?yàn)樵谀爿斎肭皥?zhí)行富俄,你所做的操作時(shí)
一直往后增加禁炒,而增加操作相當(dāng)于用輸入字符替換了一個(gè)長度為0的字符,也就是空霍比,所以一直為0幕袱;
后替換體長度:等于替換字符長度。
刪除一個(gè)字符:刪除前執(zhí)行悠瞬,所以內(nèi)容為“你你好”们豌;
開始處:2,光標(biāo)所在位阁危;
替換體長度:1玛痊,這個(gè)這里就變了,為什么變了呢狂打?因?yàn)槲覀冏隽藙h除操作擂煞,被替換的長度是刪除的
那個(gè)字符長度也就是1;
后替換體的長度:0趴乡,這個(gè)又是一直為0的对省,為什么呢,和前邊那個(gè)一直為0的原因一樣晾捏,我們做刪除操作
等于用空來替換一個(gè)字符蒿涎,所以替換的長度為空的長度,也就是0惦辛;
這個(gè)原理理解了的話劳秋,對于void onTextChanged(CharSequence s, int start, int before, int count); 和這個(gè)類似,官方文檔如下:
void onTextChanged (CharSequence s,
int start,
int before,
int count)
This method is called to notify you that, within s, the count characters beginning at start have just replaced old text that had length before. It is an error to attempt to make changes to s from this callback.
意思大概是:這個(gè)方法是用來告訴你,在字符串s里玻淑,光標(biāo)start開始處的count個(gè)字符剛剛把原來的before長度的字符替換嗽冒。理解為通知你剛剛做,或正在做补履,主要與后邊afterTextChanged()方法區(qū)分添坊;
代碼更改如下:
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
toast("s字符串為:"+s+",開始處:"+start+"箫锤,替換體長度:"+count+"贬蛙,前替換體長度"+before);
}
@Override
public void afterTextChanged(Editable s) {
}
分別輸入一個(gè)字符、二個(gè)字符谚攒、刪除一個(gè)字符的截圖:
結(jié)合第一個(gè)理解:這個(gè)方法在你剛剛操作后提示你:
輸入一個(gè)字符:s替換后后執(zhí)行此方法阳准,所以可以讀取到字符串“你”;
開始處0:下標(biāo)位馏臭,接下來不說了這個(gè)溺职。
替換體:也就是你輸入的字符長度,“你”的長度為1位喂;
前替換體:0,你用“你”這個(gè)字符替換了長度為0
的字符乱灵。
輸入二個(gè)字符:替換體為你輸入的“你好”的長度2塑崖;
前替換體:0,同上痛倚。
刪除一個(gè)字符:s字符為“你你”规婆;
替換體長度:0,好比你用長度為0的字符代替了“你”字蝉稳;
前替換體:1抒蚜,“你”的長度。
對于 void afterTextChanged(Editable s):
官方解釋:
This method is called to notify you that, somewhere within s, the text has been changed. It is legitimate to make further changes to s from this callback, but be careful not to get yourself into an infinite loop, because any changes you make will cause this method to be called again recursively. (You are not told where the change took place because other afterTextChanged() methods may already have made other changes and invalidated the offsets. But if you need to know here, you can use setSpan(Object, int, int, int) in onTextChanged(CharSequence, int, int, int) to mark your place and then look up from here where the span ended up.
意思是:這個(gè)方法告訴你耘戚,在字符串s內(nèi)的某處嗡髓,一些地方已經(jīng)改變了,在這個(gè)方法里可以對s做一些改變收津,但是注意別讓你陷入反復(fù)調(diào)用它的問題上饿这,因?yàn)榭赡苣阕龅娜魏胃淖儠?huì)讓他遞歸調(diào)用本身。(這個(gè)方法沒有告訴你哪里改變了撞秋,或許其他afterTextChanged()可能已經(jīng)改變它了并使這個(gè)改變失效长捧,但是如果你確定知道他是否起作用了,你可以在onTextChanged()里調(diào)用setSpan(Object, int, int, int)方法去標(biāo)記并在此驗(yàn)證是否在這結(jié)束了))
來吧我們來驗(yàn)證一下這個(gè)方法做了什么事:
修改代碼:
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
s.append("hello");
toast(s.toString());
}
假如我們輸入“你”字吻贿,預(yù)測結(jié)果是不是:
你hello
然而結(jié)果是:
.......竟然ANR了串结。也就是程序無響應(yīng)了 -_-!
修改EditText的輸入長度為15再試試:
android:maxLength="15"
運(yùn)行截圖:
達(dá)到最大長度才顯示了一下,我們可以推測到肌割,他竟然遞歸調(diào)用了卧蜓。。声功。所以文檔中說到謹(jǐn)慎一點(diǎn)烦却,小心陷入遞歸自身的問題。所以這個(gè)方法是在你輸入完后才調(diào)用的先巴,你輸入一個(gè)字符其爵,然后以后是不是一直處于輸入完成狀態(tài),所以他一直在調(diào)用這個(gè)方法伸蚯。
原
詳解EditText輸入監(jiān)聽TextWatcher
2017年03月18日 18:18:35鼎鼎浩閱讀數(shù) 16291文章標(biāo)簽:EditText監(jiān)聽 android TextWatche 更多
分類專欄:Android基礎(chǔ)
<article class="baidu_pl" style="caret-color: rgb(0, 0, 0); color: rgb(0, 0, 0); font-family: -webkit-standard; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; text-decoration: none;">
版權(quán)聲明:本文為博主原創(chuàng)文章摩渺,遵循CC 4.0 BY-SA 版權(quán)協(xié)議,轉(zhuǎn)載請附上原文出處鏈接和本聲明剂邮。
本文鏈接:https://blog.csdn.net/Z_DingHao/article/details/63263129
日常開發(fā)中摇幻,我們可能會(huì)遇到需要監(jiān)聽EditText輸入,比如判斷輸入是否為電話號(hào)碼挥萌,獲取輸入的數(shù)據(jù)長度來限定字?jǐn)?shù)等绰姻。這就需要監(jiān)聽EditText的輸入狀態(tài)。EditText使用TextWatcher實(shí)現(xiàn)類似按鈕監(jiān)聽事件:
使用方法
效果圖:
MainActivity.java
public class MainActivity extends AppCompatActivity {
private EditText mNumber;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mNumber = (EditText) findViewById(R.id.phone_number);
//為EditText設(shè)置監(jiān)聽引瀑,注意監(jiān)聽類型為TextWatcher
mNumber.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
toast("您輸入的數(shù)據(jù)為:"+s.toString());
}
@Override
public void afterTextChanged(Editable s) {
}
});
}
private void toast(String s){
Toast.makeText(getApplication(),s,Toast.LENGTH_SHORT).show();
}
}
Activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:padding="10dp"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.alphathink.myapplication.MainActivity">
<EditText
android:id="@+id/phone_number"
android:layout_width="368dp"
android:layout_height="wrap_content"
android:hint="@string/number"
android:inputType="number"
tools:layout_editor_absoluteY="0dp"
tools:layout_editor_absoluteX="8dp" />
</LinearLayout>
TextWatcher詳解
注意:
CharSequence是一個(gè)接口狂芋,比較常見的String、StringBuilder憨栽、StringBuffer都實(shí)現(xiàn)了這個(gè)接口帜矾。當(dāng)我們看到一個(gè)API里面有CharSequence的時(shí)候,它也是可以被其子類代替的屑柔,一般用String代替即可屡萤。
我們看到TextWatcher監(jiān)聽里覆寫了3個(gè)方法:
void beforeTextChanged(CharSequence s, int start, int count, int after);
void onTextChanged(CharSequence s, int start, int before, int count);
void afterTextChanged(Editable s);
執(zhí)行順序來說是:beforeTextChanged()>>>onTextChanged()>>>afterTextChanged()
請勿在afterTextChanged();內(nèi)加入代碼進(jìn)行驗(yàn)證掸宛,這個(gè)會(huì)進(jìn)入死循環(huán)的死陆,后邊講原因。
關(guān)于beforeTextChanged(CharSequence s, int start, int count, int after);
官方文檔解釋:
void beforeTextChanged (CharSequence s,
int start,
int count,
int after)
This method is called to notify you that, within s, the count characters beginning at start are about to be replaced by new text with length after. It is an error to attempt to make changes to s from this callback.
意思大概是:
這個(gè)方法用來通知你唧瘾,在字符串s里翔曲,光標(biāo)start開始處的count個(gè)字符將要被after長的字符代替,禁止在這個(gè)回調(diào)里改字符串s劈愚⊥椋可以理解成提醒你你做了什么操作。
操作》》》系統(tǒng)提醒你做了什么事(還沒做)》》》》系統(tǒng)開始做
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
toast("s字符串為:"+s+"開始處:"+start+"菌羽,替換體的長度:"+count+"后替換體長度"+after);
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
}
分別輸入一個(gè)字符掠械、二個(gè)字符、刪除一個(gè)字符的截圖
這樣理解:
這個(gè)方法執(zhí)行獲取的狀態(tài)是在你輸入前光標(biāo)所在位置:
輸入一個(gè)字符:s字符串也就是當(dāng)前EditText中的內(nèi)容為空,所以輸出空猾蒂;
開始處:0均唉,司空見慣,從0計(jì)數(shù)肚菠;
替換長度:0舔箭,這個(gè)怎么理解呢?理解成將被替換長度即可蚊逢,你要在光標(biāo)處往后替換然而往后并沒有
字符层扶;
后替換體長度:1,雖然他光標(biāo)沒動(dòng)烙荷,這里表示他將要改變的長度镜会,等于你輸入字符長度1。
輸入二個(gè)字符:s字符串是什么终抽?我們剛剛輸入的你字是不是還在戳表,這就是s的內(nèi)容;
開始處:光標(biāo)所在位置1昼伴;
替換長度:0匾旭,為什么還是0?實(shí)話說這個(gè)是一直為0的圃郊,因?yàn)樵谀爿斎肭皥?zhí)行季率,你所做的操作時(shí)
一直往后增加,而增加操作相當(dāng)于用輸入字符替換了一個(gè)長度為0的字符描沟,也就是空,所以一直為0鞭光;
后替換體長度:等于替換字符長度吏廉。
刪除一個(gè)字符:刪除前執(zhí)行,所以內(nèi)容為“你你好”惰许;
開始處:2席覆,光標(biāo)所在位;
替換體長度:1汹买,這個(gè)這里就變了佩伤,為什么變了呢?因?yàn)槲覀冏隽藙h除操作晦毙,被替換的長度是刪除的
那個(gè)字符長度也就是1生巡;
后替換體的長度:0,這個(gè)又是一直為0的见妒,為什么呢孤荣,和前邊那個(gè)一直為0的原因一樣,我們做刪除操作
等于用空來替換一個(gè)字符,所以替換的長度為空的長度盐股,也就是0钱豁;
這個(gè)原理理解了的話,對于void onTextChanged(CharSequence s, int start, int before, int count); 和這個(gè)類似疯汁,官方文檔如下:
void onTextChanged (CharSequence s,
int start,
int before,
int count)
This method is called to notify you that, within s, the count characters beginning at start have just replaced old text that had length before. It is an error to attempt to make changes to s from this callback.
意思大概是:這個(gè)方法是用來告訴你牲尺,在字符串s里,光標(biāo)start開始處的count個(gè)字符剛剛把原來的before長度的字符替換幌蚊。理解為通知你剛剛做谤碳,或正在做,主要與后邊afterTextChanged()方法區(qū)分霹肝;
代碼更改如下:
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
toast("s字符串為:"+s+"估蹄,開始處:"+start+",替換體長度:"+count+"沫换,前替換體長度"+before);
}
@Override
public void afterTextChanged(Editable s) {
}
分別輸入一個(gè)字符臭蚁、二個(gè)字符、刪除一個(gè)字符的截圖:
結(jié)合第一個(gè)理解:這個(gè)方法在你剛剛操作后提示你:
輸入一個(gè)字符:s替換后后執(zhí)行此方法讯赏,所以可以讀取到字符串“你”垮兑;
開始處0:下標(biāo)位,接下來不說了這個(gè)漱挎。
替換體:也就是你輸入的字符長度系枪,“你”的長度為1;
前替換體:0磕谅,你用“你”這個(gè)字符替換了長度為0
的字符私爷。
輸入二個(gè)字符:替換體為你輸入的“你好”的長度2;
前替換體:0膊夹,同上衬浑。
刪除一個(gè)字符:s字符為“你你”;
替換體長度:0放刨,好比你用長度為0的字符代替了“你”字工秩;
前替換體:1,“你”的長度进统。
對于 void afterTextChanged(Editable s):
官方解釋:
This method is called to notify you that, somewhere within s, the text has been changed. It is legitimate to make further changes to s from this callback, but be careful not to get yourself into an infinite loop, because any changes you make will cause this method to be called again recursively. (You are not told where the change took place because other afterTextChanged() methods may already have made other changes and invalidated the offsets. But if you need to know here, you can use setSpan(Object, int, int, int) in onTextChanged(CharSequence, int, int, int) to mark your place and then look up from here where the span ended up.
意思是:這個(gè)方法告訴你助币,在字符串s內(nèi)的某處,一些地方已經(jīng)改變了螟碎,在這個(gè)方法里可以對s做一些改變眉菱,但是注意別讓你陷入反復(fù)調(diào)用它的問題上,因?yàn)榭赡苣阕龅娜魏胃淖儠?huì)讓他遞歸調(diào)用本身掉分。(這個(gè)方法沒有告訴你哪里改變了倍谜,或許其他afterTextChanged()可能已經(jīng)改變它了并使這個(gè)改變失效迈螟,但是如果你確定知道他是否起作用了,你可以在onTextChanged()里調(diào)用setSpan(Object, int, int, int)方法去標(biāo)記并在此驗(yàn)證是否在這結(jié)束了))
來吧我們來驗(yàn)證一下這個(gè)方法做了什么事:
修改代碼:
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
s.append("hello");
toast(s.toString());
}
假如我們輸入“你”字尔崔,預(yù)測結(jié)果是不是:
你hello
然而結(jié)果是:
.......竟然ANR了答毫。也就是程序無響應(yīng)了 -_-!
修改EditText的輸入長度為15再試試:
android:maxLength="15"
運(yùn)行截圖:
達(dá)到最大長度才顯示了一下季春,我們可以推測到洗搂,他竟然遞歸調(diào)用了。载弄。耘拇。所以文檔中說到謹(jǐn)慎一點(diǎn),小心陷入遞歸自身的問題宇攻。所以這個(gè)方法是在你輸入完后才調(diào)用的惫叛,你輸入一個(gè)字符,然后以后是不是一直處于輸入完成狀態(tài)逞刷,所以他一直在調(diào)用這個(gè)方法嘉涌。
五、總結(jié)
一般我們在onTextChanged()夸浅;方法里做一些自己要做的事仑最,比如監(jiān)聽輸入的字符長度,或者應(yīng)用在驗(yàn)證輸入一個(gè)手機(jī)號(hào)就設(shè)置按鈕可點(diǎn)擊等等帆喇。
beforeTextChanged();在View改變之前執(zhí)行警医,好比你輸入了字符,系統(tǒng)先統(tǒng)計(jì)你輸入的信息坯钦,在這里可以提前獲取你的動(dòng)機(jī)预皇。
onTextChanged();在View改變之后短時(shí)間內(nèi)執(zhí)行,也就是區(qū)別afterTextChanged();的一直執(zhí)行狀態(tài)婉刀,他只調(diào)用一次吟温。我們做自己的操作一般在這里;
afterTextChanged();在你輸入完成后執(zhí)行路星,我們輸入完后處于完成狀態(tài),他就監(jiān)測到完成了就不斷的執(zhí)行诱桂,因?yàn)槲覀儾徊僮餮筘ぃ遣皇且恢碧幱谕瓿蔂顟B(tài)?所以就處于死循環(huán)了挥等。切記在此做操作友绝。
參考鏈接:https://blog.csdn.net/z_dinghao/article/details/63263129