如何检测用户是否在EditText android中停止输入

时间:2016-02-05 12:37:19

标签: android android-edittext

我的布局中有一个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) {

    }

函数onTextChangedafterTextChanged在输入任何字符后立即被调用,但是我希望在用户完成在该edittext字段中输入后执行操作,就像facebook上所做的那样' s"登记入住"页。

我该如何实现?

8 个答案:

答案 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-> })