Bob*_*obs 59 android filter textwatcher textchanged android-edittext
我正在使用EditText过滤我的列表.我想在用户输入EditText后0.5秒过滤列表.我为此目的使用了这个afterTextChanged事件TextWatcher.但是,对于EditText中的每个字符更改,此事件都会增加.
我该怎么办?
Ber*_*ťák 145
editText.addTextChangedListener(
new TextWatcher() {
@Override public void onTextChanged(CharSequence s, int start, int before, int count) { }
@Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { }
private Timer timer=new Timer();
private final long DELAY = 1000; // milliseconds
@Override
public void afterTextChanged(final Editable s) {
timer.cancel();
timer = new Timer();
timer.schedule(
new TimerTask() {
@Override
public void run() {
// TODO: do what you need here (refresh list)
// you will probably need to use runOnUiThread(Runnable action) for some specific actions
}
},
DELAY
);
}
}
);
Run Code Online (Sandbox Code Playgroud)
Timer当文本输入EditText发生变化时,诀窍在于每次取消和重新安排.祝好运!
更新 对于有兴趣设置延迟时间的人,请参阅此文章.
Naz*_*arK 45
最好使用Handler和postDelayed()方法.在android的实现中,Timer每次都会创建新线程来运行任务.然而,Handler有自己的Looper可以连接到我们想要的任何线程,因此我们不会支付额外的费用来创建线程.
例
Handler handler = new Handler(Looper.getMainLooper() /*UI thread*/);
Runnable workRunnable;
@Override public void afterTextChanged(Editable s) {
handler.removeCallbacks(workRunnable);
workRunnable = () -> doSmth(s.toString());
handler.postDelayed(workRunnable, 500 /*delay*/);
}
private final void doSmth(String str) {
//
}
Run Code Online (Sandbox Code Playgroud)
小智 13
您可以使用RxBindings,这是最好的解决方案.请参阅RxJava操作员debounce指南,我相信在您的情况下会做得很好.
RxTextView.textChanges(editTextVariableName)
.debounce(500, TimeUnit.MILLISECONDS)
.subscribe(new Action1<String>() {
@Override
public void call(String value) {
// do some work with the updated text
}
});
Run Code Online (Sandbox Code Playgroud)
http://reactivex.io/documentation/operators/debounce.html
小智 11
使用 Kotlin 扩展函数和协程:
fun AppCompatEditText.afterTextChangedDebounce(delayMillis: Long, input: (String) -> Unit) {
var lastInput = ""
var debounceJob: Job? = null
val uiScope = CoroutineScope(Dispatchers.Main + SupervisorJob())
this.addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(editable: Editable?) {
if (editable != null) {
val newtInput = editable.toString()
debounceJob?.cancel()
if (lastInput != newtInput) {
lastInput = newtInput
debounceJob = uiScope.launch {
delay(delayMillis)
if (lastInput == newtInput) {
input(newtInput)
}
}
}
}
}
override fun beforeTextChanged(cs: CharSequence?, start: Int, count: Int, after: Int) {}
override fun onTextChanged(cs: CharSequence?, start: Int, before: Int, count: Int) {}
})}
Run Code Online (Sandbox Code Playgroud)
没有上述解决方案适合我.
我需要一种方法让TextWatcher不会触发我在搜索视图中输入的每个字符并显示一些进度,这意味着我需要访问UI线程.
private final TextWatcher textWatcherSearchListener = new TextWatcher() {
final android.os.Handler handler = new android.os.Handler();
Runnable runnable;
public void onTextChanged(final CharSequence s, int start, final int before, int count) {
handler.removeCallbacks(runnable);
}
@Override
public void afterTextChanged(final Editable s) {
//show some progress, because you can access UI here
runnable = new Runnable() {
@Override
public void run() {
//do some work with s.toString()
}
};
handler.postDelayed(runnable, 500);
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
};
Run Code Online (Sandbox Code Playgroud)
在每个onTextChanged上删除Handler(在用户输入新字符时调用).在输入字段内更改文本之后调用afterTextChanged,我们可以在其中启动新的Runnable,但如果用户输入更多字符,将取消它(有关更多信息,调用这些回调时,请参阅此内容).如果用户不再输入字符,则间隔将在postDelayed中传递,并且它将调用您应该对该文本执行的工作.
此代码每个间隔仅运行一次,而不是每个关键用户输入.希望它能帮助将来的某个人.
在 Kotlin 语言中,你可以这样做:
tv_search.addTextChangedListener(mTextWatcher)
private val mTextWatcher: TextWatcher = object : TextWatcher {
private var timer = Timer()
private val DELAY: Long = 1000L
override fun afterTextChanged(s: Editable?) {
timer.cancel()
timer = Timer()
timer.schedule(object : TimerTask() {
override fun run() {
// Do your stuff here
}
}, DELAY)
}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
}
}
Run Code Online (Sandbox Code Playgroud)
观察文本更改事件的另一种方法是使用协程通道。
lifecycleScope.launchWhenCreated {
editText.afterTextChanged {
// do something
}
}
Run Code Online (Sandbox Code Playgroud)
创建扩展函数以从流中收集数据
suspend fun EditText.afterTextChanged(afterTextChanged: suspend (String) -> Unit) {
val watcher = Watcher()
this.addTextChangedListener(watcher)
watcher.asFlow()
.debounce(500)
.collect { afterTextChanged(it) }
}
Run Code Online (Sandbox Code Playgroud)
创建一个 Watcher 类以在更改后提供文本
class Watcher : TextWatcher {
private val channel = ConflatedBroadcastChannel<String>()
override fun afterTextChanged(editable: Editable?) {
channel.offer(editable.toString())
}
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {}
fun asFlow(): Flow<String> {
return channel.asFlow()
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
33317 次 |
| 最近记录: |