尊重原作者:此篇文章是借鑒原作者地址 的博文 並進行修改和增加補充說明,我只是補充和修改:
我感覺這篇文章經過我的補充 市面多少文本操作變化 你都知道怎么做了.並且感覺是非常詳細關於 android 文本編輯框的文本變化 並且通俗易懂(內含動態圖),
為了大家方便查看 我這里復制作者博文內容 並且修正部分內容 后面在補充
我正參加CSDN明日之星比賽 還希望您投我一票
原作者部分(修改部分)
由於最近做項目要檢測EditText中輸入的字數長度,從而接觸到了Android中EditText的監聽接口,TextWatcher。
它有三個成員方法,第一個after很簡單,這個方法就是在EditText內容已經改變之后調用,重點看下面兩個方法:
beforeTextChanged(CharSequence s, int start, int count, int after)
這個方法是在Text改變之前被調用,它的意思就是說在原有的文本s中,從start開始的count個字符將會被一個新的長度為after的文本替換,注意這里是將被替換,還沒有被替換。
onTextChanged(CharSequence s, int start, int before, int count)
這個方法是在Text改變過程中觸發調用的,它的意思就是說在原有的文本s中,從start開始的count個字符替換長度為before的舊文本,注意這里沒有將要之類的字眼,也就是說一句執行了替換動作。
可能說起來比較抽象,我舉個簡單的例子,比如說我們監聽一個EditText,默認開始的時候EditText中沒有文本,當我們輸入LOVE四個字母的時候,在打印信息中我輸出各個參數看一下參數的變化。
10-18 16:40:21.528: D/Debug(4501): beforeTextChanged 被執行----> s=----start=0----after=1----count=0
10-18 16:40:21.528: D/Debug(4501): onTextChanged 被執行---->s=L----start=0----before=0----count=1
10-18 16:40:21.532: D/Debug(4501): afterTextChanged 被執行---->L
10-18 16:40:29.304: D/Debug(4501): beforeTextChanged 被執行----> s=L----start=1----after=1----count=0
10-18 16:40:29.308: D/Debug(4501): onTextChanged 被執行---->s=LO----start=1----before=0----count=1
10-18 16:40:29.308: D/Debug(4501): afterTextChanged 被執行---->LO
10-18 16:40:32.772: D/Debug(4501): beforeTextChanged 被執行----> s=LO----start=2----after=1----count=0
10-18 16:40:32.772: D/Debug(4501): onTextChanged 被執行---->s=LOV----start=2----before=0----count=1
10-18 16:40:32.776: D/Debug(4501): afterTextChanged 被執行---->LOV
10-18 16:40:34.772: D/Debug(4501): beforeTextChanged 被執行----> s=LOV----start=3----after=1----count=0
10-18 16:40:34.772: D/Debug(4501): onTextChanged 被執行---->s=LOVE----start=3----before=0----count=1
10-18 16:40:34.776: D/Debug(4501): afterTextChanged 被執行---->LOVE
通過上面的打印信息我們可以發現在輸入L之前beforeTextChanged被執行,s為空,所以s輸入空,start=0,也就是從位置0開始,count=0,也就是0個字符將會被替換,after=1,也就是說0個字符將會被一個新的長度為after=1的文本(也就是L)替換。
當輸入發生改變的時候onTextChanged被執行,此時s=L也就是輸入的字母L,從start=0開始,count=1個字符替換了長度為before=0的舊文本。通俗點將就是字母L從位置0開始替換了原來的空文本,下面的就可以依次類推了。那么我們如何利用這個接口監聽EditText的文本變化來實現限制輸入字數的功能呢,我相信大家都有自己的想法了,這里我給出自己的一個簡單實現,主要代碼如下:
source_des.addTextChangedListener(new TextWatcher() {
private CharSequence temp;
private int selectionStart;
private int selectionEnd;
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
Log.d(TAG, "onTextChanged 被執行---->s=" + s + "----start="+ start
+ "----before="+before + "----count" +count); temp = s;
}
public void beforeTextChanged(CharSequence s, int start, int count,int after) {
Log.d(TAG, "beforeTextChanged 被執行----> s=" + s+"----start="+ start
+ "----after="+after + "----count" +count);
}
public void afterTextChanged(Editable s) {
Log.d(TAG, "afterTextChanged 被執行---->" + s);
//獲取光標開始的位置
selectionStart = source_des.getSelectionStart();
//獲取光標結束的位置
selectionEnd = source_des.getSelectionEnd();
//這里其實selectionStart == selectionEnd
// 大家可以把獲取的位置放入beforeTextChanged 然后選擇部分文字(選擇部分位置用光標選擇2個以上) 刪除可以看到效果 我后面做實驗
if (temp.length() > MAX_LENGTH) {
Toast.makeText(MainActivity.this, "只能輸入九個字",
Toast.LENGTH_SHORT).show();
//刪除部分字符串 為[x,y) 包含x位置不包含y
//也就是說刪除 位置x到y-1
s.delete(selectionStart - 1, selectionEnd);
int tempSelection = selectionEnd;
//這里我修改了原作者 不需要這部
//source_des.setText(s);
//如果你setText 傳入s 的話會將編輯框的光標移到文本框最前面 所以這里我也注釋了原作者
//source_des.setSelection(tempSelection);
}
}
});
補充部分
好了大家看到了增加文本動態監聽 那么我們看看刪除會怎么觸發事件
實驗代碼:
editText.addTextChangedListener(new TextWatcher() {
private CharSequence temp;
private int selectionStart;
private int selectionEnd;
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
Log.d(TAG, "onTextChanged 被執行---->s=" + s + "----start="+ start
+ "----before="+before + "----count" +count); temp = s;
Log.e(TAG, "onTextChanged--getSelectionStart: " + editText.getSelectionStart());
Log.e(TAG, "onTextChanged---getSelectionEnd: " + editText.getSelectionEnd());
}
public void beforeTextChanged(CharSequence s, int start, int count,int after) {
Log.d(TAG, "beforeTextChanged 被執行----> s=" + s+"----start="+ start
+ "----after="+after + "----count" +count);
Log.e(TAG, "beforeTextChanged---getSelectionStart: " + editText.getSelectionStart());
Log.e(TAG, "beforeTextChanged---getSelectionEnd: " + editText.getSelectionEnd());
}
public void afterTextChanged(Editable s) {
Log.d(TAG, "afterTextChanged 被執行---->" + s);
selectionStart = editText.getSelectionStart();
selectionEnd = editText.getSelectionEnd();
Log.e(TAG, "afterTextChanged---getSelectionStart: " + editText.getSelectionStart());
Log.e(TAG, "afterTextChanged---getSelectionEnd: " + editText.getSelectionEnd());
}
});
我們這里輸入LOVE然后刪除’ov’兩個字母看看會發生
動態圖顯示步驟:

可以看到我把光標放入ov外面 那么光標開始位置為1 ,結束位置為3.然后刪除
我們看看日志
12-03 12:20:22.355 21082-21082/a.fmy.com.test D/FMY: beforeTextChanged 被執行----> s=love----start=1----after=0----count2
12-03 12:20:22.355 21082-21082/a.fmy.com.test E/FMY: beforeTextChanged---getSelectionStart: 1
12-03 12:20:22.355 21082-21082/a.fmy.com.test E/FMY: beforeTextChanged---getSelectionEnd: 3
12-03 12:20:22.359 21082-21082/a.fmy.com.test D/FMY: onTextChanged 被執行---->s=le----start=1----before=2----count0
12-03 12:20:22.359 21082-21082/a.fmy.com.test E/FMY: onTextChanged--getSelectionStart: 1
12-03 12:20:22.359 21082-21082/a.fmy.com.test E/FMY: onTextChanged---getSelectionEnd: 1
12-03 12:20:22.412 21082-21082/a.fmy.com.test D/FMY: afterTextChanged 被執行---->le
12-03 12:20:22.412 21082-21082/a.fmy.com.test E/FMY: afterTextChanged---getSelectionStart: 1
12-03 12:20:22.412 21082-21082/a.fmy.com.test E/FMY: afterTextChanged---getSelectionEnd: 1
這里我放一張有顏色區分圖片 (和上面一樣的 只不過方便大家查看)

我們先來看看beforeTextChanged的日志部分
12-03 12:20:22.355 21082-21082/a.fmy.com.test D/FMY: beforeTextChanged 被執行----> s=love----start=1----after=0----count2
12-03 12:20:22.355 21082-21082/a.fmy.com.test E/FMY: beforeTextChanged---getSelectionStart: 1
12-03 12:20:22.355 21082-21082/a.fmy.com.test E/FMY: beforeTextChanged---getSelectionEnd: 3
s:文字沒有改變前字符串
start:准備要變化文本的位置下標 ,我們這里選擇’ov’位置 所以這里相對應’love’位置為1
count:相對沒改變前舊文本文本減少數量 因為我們這里要刪除’ov’所以為2
after:新文本新加入的字符數量 這里沒有增加反而減少 所以為0
getSelectionStart:我們光標的位置不是o的左邊嗎?所以為1
getSelectionEnd:光標位置在v右邊 所以為3 大家回去看下動態圖
我們最后來看一下另外onTextChanged
這部分的日志如下:
12-03 12:20:22.359 21082-21082/a.fmy.com.test D/FMY: onTextChanged 被執行---->s=le----start=1----before=2----count0
12-03 12:20:22.359 21082-21082/a.fmy.com.test E/FMY: onTextChanged--getSelectionStart: 1
12-03 12:20:22.359 21082-21082/a.fmy.com.test E/FMY: onTextChanged---getSelectionEnd: 1
s:被改變后的文本 因為我們這里刪除刪除’ov’ 所以為le
start:文本開始改變的位置 ‘ov’相對原本文本的開始位置1,所以這里返回1
before:改變之前舊文本減少的數量 這里 ‘love’減少 ‘ov’相當於減少了2
count:新文本添加數量 這里是減少2所以返回0
getSelectionStart 這里刪除后的光標狀態 所以等於1
getSelectionEnd 這里刪除后的光標狀態 所以開始坐標等結束坐標 因此等於1
補充部分2
我們假設剪切板內容’12’ (意思是說我們賦值了12字符串在剪切板,只要一粘貼就會出現’12’)
那么我們做一個實驗 在love上 用光標選擇’ov’ 然后粘貼’12’
動態圖(大家耐心等下):

這里日志為:
12-03 12:51:25.347 21082-21082/a.fmy.com.test D/FMY: beforeTextChanged 被執行----> s=love----start=1----after=2----count2
12-03 12:51:25.347 21082-21082/a.fmy.com.test E/FMY: beforeTextChanged---getSelectionStart: 3
12-03 12:51:25.347 21082-21082/a.fmy.com.test E/FMY: beforeTextChanged---getSelectionEnd: 3
12-03 12:51:25.348 21082-21082/a.fmy.com.test D/FMY: onTextChanged 被執行---->s=l12e----start=1----before=2----count2
12-03 12:51:25.348 21082-21082/a.fmy.com.test E/FMY: onTextChanged--getSelectionStart: 3
12-03 12:51:25.348 21082-21082/a.fmy.com.test E/FMY: onTextChanged---getSelectionEnd: 3
12-03 12:51:25.378 21082-21082/a.fmy.com.test D/FMY: afterTextChanged 被執行---->l12e
12-03 12:51:25.378 21082-21082/a.fmy.com.test E/FMY: afterTextChanged---getSelectionStart: 3
12-03 12:51:25.379 21082-21082/a.fmy.com.test E/FMY: afterTextChanged---getSelectionEnd: 3
這里我就簡單說下光標位置的問題:因為替換相同長度的文本 所以光標並沒有移動 位於選擇的字符串+1的 位置 ,我們這里選擇’ov’ 所以開始和結束為:3 (o的位置)
beforeTextChanged 日志解釋:
12-03 12:51:25.347 21082-21082/a.fmy.com.test D/FMY: beforeTextChanged 被執行----> s=love----start=1----after=2----count2
12-03 12:51:25.347 21082-21082/a.fmy.com.test E/FMY: beforeTextChanged---getSelectionStart: 3
12-03 12:51:25.347 21082-21082/a.fmy.com.test E/FMY: beforeTextChanged---getSelectionEnd: 3
start:文本開始位置,因為我們從’ov’的’o’開始改變所以為1(love中o不是相對是1嘛)
after:新文本增加的數量 因為增加了12所以兩個字符就是2
count:原本舊字符串減少的數量 減少’ov’所以是2
其他的同學們可以自己推斷
補充部分3
這里我們再看看替換不同長度的文本
我們這里 光標選擇’ov’ 替換為’12345’(剪切板以保存)

12-03 13:01:25.735 21082-21082/a.fmy.com.test D/FMY: beforeTextChanged 被執行----> s=love----start=1----after=5----count2
12-03 13:01:25.735 21082-21082/a.fmy.com.test E/FMY: beforeTextChanged---getSelectionStart: 3
12-03 13:01:25.735 21082-21082/a.fmy.com.test E/FMY: beforeTextChanged---getSelectionEnd: 3
12-03 13:01:25.737 21082-21082/a.fmy.com.test D/FMY: onTextChanged 被執行---->s=l12345e----start=1----before=2----count5
12-03 13:01:25.737 21082-21082/a.fmy.com.test E/FMY: onTextChanged--getSelectionStart: 6
12-03 13:01:25.737 21082-21082/a.fmy.com.test E/FMY: onTextChanged---getSelectionEnd: 6
12-03 13:01:25.770 21082-21082/a.fmy.com.test D/FMY: afterTextChanged 被執行---->l12345e
12-03 13:01:25.770 21082-21082/a.fmy.com.test E/FMY: afterTextChanged---getSelectionStart: 6
12-03 13:01:25.770 21082-21082/a.fmy.com.test E/FMY: afterTextChanged---getSelectionEnd: 6
可以 替換字符串的時候光標 開始等於結束的
補充部分4 Editable
我們想直接操作文本編輯框的文本的時候 想快速插入和添加 可以考慮這個方法
我們看看兩個例子 獲取 文本編輯框中的字符串並且添加 ‘你好’在后面;
不使用Editable
String s = editText.getText().toString();
s +="你好";
editText.setText(s);
來我們看看使用Editable
editText.getText().append("你好");
我們看看怎么獲取Editable
非常簡單只需要用文本編輯框調用getText()方法Editable text = editText.getText();相關API
在文本編輯框后面添加字符串Editable editable = editText.getText(); editable.append("你好");刪除文本編輯框部分內容,假設你此時文本編輯框的內容’love’你想刪除中間的ov
Editable editable = editText.getText(); //start為要刪除文本的開始下標 end為結束下標(不包括) //也就是說 [start,end) //editable.delete(start,end); //注意end必須等於start 不然奔潰 // 也就是 end>=start //我們看看刪除love 中的ov editable.delete(1,3);在文本編輯框中字符串的某個部分插入字符,假設我們的文本編輯框內容為’love’那么我們想插入 ‘a’到’o’后面也就是’loave’
Editable editable = editText.getText();
String a = "a";
//love 插入o后面 o位置相對於字符的1
//第一個參數 插入 的位置
// 第二個參數 要插入字符串
// 第三個參數 插入的字符串的開始位置
// 第四個參數 插入的字符串的結束位置(不包含)
editable.insert(1,"a",0,a.length());
// 下面方法和上面的等價
//editable.insert(1,"a");
刪除文本編輯框所有內容
Editable editable = editText.getText();
editable.clear();
替換文本編輯框部分內容
假設我們將文本框 ‘love’中”o”替換為”a” 也就是說’lave’
Editable editable = editText.getText();
//第一個參數 替換位置
//第二個 替換結束為止(不包含)
//第三個 替換的字符串
editable.replace(1,2,"a");
String a = "a";
//第一個參數 替換位置
//第二個 替換結束為止(不包含)
//第三個 替換的字符串
//第四個 替換文本的開始位置
//第五個 替換文本結束位置 不包含
editable.replace(1,2,"a",0,a.length());
