日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

android TextWatcher 学习

發(fā)布時(shí)間:2023/12/9 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 android TextWatcher 学习 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

1.簡(jiǎn)介

主要用來(lái)監(jiān)聽用戶輸入,然后剪裁輸入。

比如輸入框只能輸入8個(gè)字節(jié)的內(nèi)容,就可以用TextWatcher來(lái)實(shí)現(xiàn)。

public interface TextWatcher extends NoCopySpan {/*** This method is called to notify you that, within <code>s</code>,* the <code>count</code> characters beginning at <code>start</code>* are about to be replaced by new text with length <code>after</code>.* It is an error to attempt to make changes to <code>s</code> from* this callback.*/public void beforeTextChanged(CharSequence s, int start,int count, int after);/*** This method is called to notify you that, within <code>s</code>,* the <code>count</code> characters beginning at <code>start</code>* have just replaced old text that had length <code>before</code>.* It is an error to attempt to make changes to <code>s</code> from* this callback.*/public void onTextChanged(CharSequence s, int start, int before, int count);/*** This method is called to notify you that, somewhere within* <code>s</code>, the text has been changed.* It is legitimate to make further changes to <code>s</code> 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 {@link Spannable#setSpan} in {@link #onTextChanged}* to mark your place and then look up from here where the span* ended up.*/public void afterTextChanged(Editable s); }

想要了解方法的參數(shù)什么意思,把注釋看一下,然后把參數(shù)全部打印一遍就行。

這三個(gè)方法很簡(jiǎn)單,值得注意的地方:

每當(dāng)輸入一次,就會(huì)調(diào)用一次 before-on-after。每當(dāng)調(diào)用setText("xxx")也會(huì)如此,那么在on方法中調(diào)用setText("xxx")就會(huì)形成遞歸,然后就可能死循環(huán)。

但畢竟監(jiān)聽這個(gè)就是要修改內(nèi)容的,根據(jù)源碼注釋,可以在after中修改字符。

2.使用

val input1 = findViewById<EditText>(R.id.input1) input1.addTextChangedListener(Watcher1(input1, 8, TAG))

先簡(jiǎn)單嘗試,限制8個(gè)數(shù)字或字母

class Watcher1(private val editText: EditText, private val limit: Int, private val TAG: String): TextWatcher {private var suitable = trueprivate val what = "luo"private val editable = editText.editableTextoverride fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {Log.d(TAG, "beforeTextChanged")}override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {Log.d(MainActivity.TAG,"onTextChanged: s = $s, start = $start, before = $before, count = $count")s?.let {suitable = s.length <= limitif (!suitable) {editable.setSpan(what, start, start + count, 1)}}}override fun afterTextChanged(s: Editable?) {Log.d(TAG, "afterTextChanged")if (!suitable) {s?.let {// 注意substring的參數(shù)范圍Log.d(TAG, "afterTextChanged: ${editable.getSpanStart(what)}")val start = s.substring(0, editable.getSpanStart(what))Log.d(TAG, "afterTextChanged: start = $start")val end = s.substring(editable.getSpanEnd(what), s.length)Log.d(TAG, "afterTextChanged: end = $end")val text = start + end// 會(huì)繼續(xù)調(diào)用before、on、aftereditText.setText(text)editText.setSelection(editable.getSpanStart(what))}}} }

思路:在on中,字符串是已經(jīng)被修改了的,所以在on中判斷,如果字符串不符合要求,就記錄這次的輸入詳情,然后在after中截取字符串。

值得注意的是,如果你使用了after回調(diào)的參數(shù) "s",也許會(huì)有bug,因?yàn)閍fter中調(diào)用setText(),就會(huì)形成遞歸:因?yàn)閟是第一次的,還未修改,調(diào)用setText()修改后會(huì)有第二次after,第二次的參數(shù)才是真正想要的。所以最好是不用這個(gè)參數(shù),而是使用editText的get方法。

混合輸入時(shí),限制長(zhǎng)度

由于數(shù)字、漢字、表情的byte各不相同。如果我們想要保證輸入的byte總數(shù)不超過(guò)定值,那就需要監(jiān)聽輸入,然后剪裁。

class Watcher2(private val editText: EditText, private val limit: Int, private val TAG: String) :TextWatcher {private val change = IntArray(2)override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {Log.d(TAG, "beforeTextChanged")}override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {Log.d(TAG, "onTextChanged s = $s, start = $start, before = $before, count = $count")if (!suitable(s.toString())) {change[0] = startchange[1] = start + count}}override fun afterTextChanged(s: Editable?) {Log.d(TAG, "afterTextChanged")if (!suitable(s.toString())) {s?.let {// 注意substring的參數(shù)范圍val start = s.substring(0, change[0])Log.d(TAG, "afterTextChanged: start = $start")val end = s.substring(change[1], s.length)Log.d(TAG, "afterTextChanged: end = $end")val text = start + end// 會(huì)繼續(xù)調(diào)用before、on、aftereditText.setText(text)editText.setSelection(change[0])handler.removeCallbacks(runnable)handler.postDelayed(runnable, 100)}}Log.d(TAG, "afterTextChanged: s = $s")}/*** Determine whether the current input is legal*/private fun suitable(str: String): Boolean {val size = str.toByteArray().sizeLog.d(TAG, "suitable: size = $size")return size <= limit}private val handler = object : Handler(Looper.getMainLooper()) {}private val runnable =Runnable {Toast.makeText(editText.context, "限制 $limit byte!", Toast.LENGTH_SHORT).show() } }

在第一個(gè)案例中,我使用setSpan來(lái)記錄輸入詳情,在這個(gè)案例中有點(diǎn)不好使,主要原因是長(zhǎng)度不同的。

在after中截取了字符串后記得把輸入光標(biāo)挪個(gè)位置。

3.總結(jié)

1.弄清楚方法里的參數(shù)

2.根據(jù)需求,在on中記錄輸入,在after中截取字符串

3.避免無(wú)限遞歸

代碼https://gitee.com/luoccxyz/text-watcher-test

總結(jié)

以上是生活随笔為你收集整理的android TextWatcher 学习的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。