我的布局中有一个EditText字段。我想在用户停止输入该edittext字段时执行操作。我已经实现了TextWatcher并使用了它的函数
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) { }
@Override
public void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) { }
@Override
public void afterTextChanged(Editable editable) {
}
函数onTextChanged
和afterTextChanged
在输入任何字符后立即被调用,但是我希望在用户完成在该edittext字段中输入后执行操作,就像facebook上所做的那样' s"登记入住"页。
我该如何实现?
答案 0 :(得分:33)
这就是我为我所做的工作!
long delay = 1000; // 1 seconds after user stops typing
long last_text_edit = 0;
Handler handler = new Handler();
private Runnable input_finish_checker = new Runnable() {
public void run() {
if (System.currentTimeMillis() > (last_text_edit + delay - 500)) {
// TODO: do what you need here
// ............
// ............
DoStaff();
}
}
};
EditText editText = (EditText) findViewById(R.id.editTextStopId);
editText.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged (CharSequence s,int start, int count,
int after){
}
@Override
public void onTextChanged ( final CharSequence s, int start, int before,
int count){
//You need to remove this to run only once
handler.removeCallbacks(input_finish_checker);
}
@Override
public void afterTextChanged ( final Editable s){
//avoid triggering event when text is empty
if (s.length() > 0) {
last_text_edit = System.currentTimeMillis();
handler.postDelayed(input_finish_checker, delay);
} else {
}
}
}
);
答案 1 :(得分:12)
有一种非常简单易用的方法,可以使用RxBindings
for Android,
如果您还没有,请获取图书馆
compile 'com.jakewharton.rxbinding:rxbinding:0.4.0'
根据您的需要添加和修改此代码段,
RxTextView.textChanges(mEditText)
.debounce(3, TimeUnit.SECONDS)
.subscribe(textChanged -> {
Log.d("TAG", "Stopped typing!");
});
什么是去抖操作符? - Learn more about it here
在我们的上下文中,debounce只会在EditText
内发生的最后一次文字更改过去一段时间后通知您EditText
内的文字更改。
在这里,我等待 3秒,直到最后一次文本更改结束用户已停止输入为止。您可以根据需要进行修改。
答案 2 :(得分:6)
您可以使用焦点更改侦听器。如果edittext具有焦点,则假设用户仍在编辑,否则他们已停止并且您可以执行操作:
EditText et = new EditText(mContext);
et.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View view, boolean hasFocus) {
if (hasFocus) {
//user has focused
} else {
//focus has stopped perform your desired action
}
}
});
答案 3 :(得分:2)
这是一种不同的方法。但是你可以做这样的事情
我假设在用户开始输入edittext后,并且他没有输入特定时间段,因此可以认为他已停止输入。
editText.addTextChangedListener(new TextWatcher() {
boolean isTyping = false;
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {}
private Timer timer = new Timer();
private final long DELAY = 5000; // milliseconds
@Override
public void afterTextChanged(final Editable s) {
Log.d("", "");
if(!isTyping) {
Log.d(TAG, "started typing");
// Send notification for start typing event
isTyping = true;
}
timer.cancel();
timer = new Timer();
timer.schedule(
new TimerTask() {
@Override
public void run() {
isTyping = false;
Log.d(TAG, "stopped typing");
//send notification for stopped typing event
}
},
DELAY
);
}
});
基本上你在这里做的是,每当用户开始输入时,如果在更改edittext中的文本时存在5000毫秒的时间间隔,则考虑用户已停止输入。当然,您可以将时间更改为您想要的任何内容
答案 4 :(得分:2)
我使用CountDownTimer查看用户是否在一段时间后停止输入。我希望能提供帮助。
yourEditText.addTextChangedListener(new TextWatcher() {
CountDownTimer timer = null;
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if (timer != null) {
timer.cancel();
}
timer = new CountDownTimer(1500, 1000) {
public void onTick(long millisUntilFinished) {
}
public void onFinish() {
//do what you wish
}
}.start();
}
@Override
public void afterTextChanged(Editable s) {
}
});
答案 5 :(得分:2)
如果您使用Kotlin,请使用以下扩展功能:
fun TextView.afterTextChangedDelayed(afterTextChanged: (String) -> Unit) {
this.addTextChangedListener(object : TextWatcher {
var timer: CountDownTimer? = null
override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
override fun afterTextChanged(editable: Editable?) {
timer?.cancel()
timer = object : CountDownTimer(1000, 1500) {
override fun onTick(millisUntilFinished: Long) {}
override fun onFinish() {
afterTextChanged.invoke(editable.toString())
}
}.start()
}
})
}
使用示例:
editTextPassword.afterTextChangedDelayed {
registerViewModel.addUserPassword(it)
}
答案 6 :(得分:2)
import android.os.Handler
import android.text.Editable
import android.text.TextWatcher
class EndTypingWatcher(
var delayMillis: Long = DELAY,
val action: () -> Unit
) : Handler(), TextWatcher {
companion object {
private const val DELAY: Long = 1000
}
var lastEditTime: Long = 0
private val finishCheckerRunnable = Runnable {
if (System.currentTimeMillis() > lastEditTime + delayMillis - 500) {
action.invoke()
}
}
override fun afterTextChanged(s: Editable?) {
afterTextChanged()
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
onTextChanged()
}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
}
private fun afterTextChanged() {
lastEditTime = System.currentTimeMillis()
postDelayed(finishCheckerRunnable, delayMillis)
}
private fun onTextChanged() {
removeCallbacks(finishCheckerRunnable)
}
}
用法:
private const val DELAY_AFTER_STOP_TYPING = 2000
...
editText.addTextChangedListener(EndTypingWatcher(delayMillis = DELAY_AFTER_STOP_TYPING) {
//Some end action
})
答案 7 :(得分:0)
您可以使用协程代替计时器或处理程序来实现这一点,例如 RxTextView 您还可以观察用户何时开始输入
import android.text.Editable
import android.text.TextWatcher
import kotlinx.coroutines.*
class TypingListener(private val onTyping: (Boolean) -> Unit) : TextWatcher {
companion object {
private const val DEBOUNCE_PERIOD = 1000L
}
private val coroutineScope = CoroutineScope(Dispatchers.Main)
private var typingJob: Job? = null
private var isNotTyping = true
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
if (isNotTyping){
onTyping(isNotTyping)
isNotTyping = false
}
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) { }
override fun afterTextChanged(s: Editable?) {
typingJob?.cancel()
s?.let {
typingJob = coroutineScope.launch {
delay(DEBOUNCE_PERIOD)
onTyping(isNotTyping)
isNotTyping = true
}
}
}
<块引用>
像这样将它与您的编辑文本一起使用,因为您获得了 TypingStatus 布尔值以了解输入状态
edit_text.addTextChangedListener(TypingListener{ typingStatus-> })