Saya ingin melihat acara ketika pengguna selesai mengedit EditText.
Bagaimana caranya?
override fun afterTextChanged(s: Editable?) { if (s.toString().length == 5) { val enteredString = s.toString() }
Saya ingin melihat acara ketika pengguna selesai mengedit EditText.
Bagaimana caranya?
override fun afterTextChanged(s: Editable?) { if (s.toString().length == 5) { val enteredString = s.toString() }
Jawaban:
Setelah pengguna selesai mengedit, dia akan menekan Done
atauEnter
((EditText)findViewById(R.id.youredittext)).setOnEditorActionListener(
new EditText.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_SEARCH ||
actionId == EditorInfo.IME_ACTION_DONE ||
event != null &&
event.getAction() == KeyEvent.ACTION_DOWN &&
event.getKeyCode() == KeyEvent.KEYCODE_ENTER) {
if (event == null || !event.isShiftPressed()) {
// the user is done typing.
return true; // consume.
}
}
return false; // pass on to other listeners.
}
}
);
Cara yang lebih baik, Anda juga dapat menggunakan pendengar EditText onFocusChange untuk memeriksa apakah pengguna telah melakukan pengeditan: (Tidak perlu bergantung pada pengguna yang menekan tombol Selesai atau Enter pada Soft keyboard)
((EditText)findViewById(R.id.youredittext)).setOnFocusChangeListener(new OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
// When focus is lost check that the text field has valid values.
if (!hasFocus) { {
// Validate youredittext
}
}
});
Catatan: Untuk lebih dari satu EditText, Anda juga dapat membiarkan kelas Anda mengimplementasikan View.OnFocusChangeListener
lalu menyetel listener untuk Anda masing-masing EditText dan memvalidasinya seperti di bawah ini
((EditText)findViewById(R.id.edittext1)).setOnFocusChangeListener(this);
((EditText)findViewById(R.id.edittext2)).setOnFocusChangeListener(this);
@Override
public void onFocusChange(View v, boolean hasFocus) {
// When focus is lost check that the text field has valid values.
if (!hasFocus) {
switch (view.getId()) {
case R.id.edittext1:
// Validate EditText1
break;
case R.id.edittext2:
// Validate EditText2
break;
}
}
}
EditText
. Itu tidak akan pernah kehilangan fokus.
EditText
? Apakah saya harus menggunakan onEditorAction
?
EditText
, Anda memvalidasi apa pun yang dilakukan pengguna untuk meninggalkan layar.
W/ViewRootImpl: Cancelling event due to no window focus: MotionEvent { action=ACTION_CANCEL, actionButton=0, id[0]=0, x[0]=605.52246, y[0]=969.4336, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=238238, downTime=235422, deviceId=0, source=0x1002 }
Meskipun saya mengetik sesuatu. Ini adalah teks edit yang hanya menerima angka.
Saya pribadi lebih suka pengiriman otomatis setelah pengetikan berakhir. Inilah cara Anda mendeteksi peristiwa ini.
Deklarasi dan inisialisasi:
private Timer timer = new Timer();
private final long DELAY = 1000; // in ms
Pendengar di misalnya onCreate ()
EditText editTextStop = (EditText) findViewById(R.id.editTextStopId);
editTextStop.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) {
if(timer != null)
timer.cancel();
}
@Override
public void afterTextChanged(final Editable s) {
//avoid triggering event when text is too short
if (s.length() >= 3) {
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
serviceConnector.getStopPoints(s.toString());
}
}, DELAY);
}
}
});
Jadi, ketika teks diubah, pengatur waktu mulai menunggu perubahan berikutnya terjadi. Ketika terjadi, pengatur waktu dibatalkan dan kemudian dimulai sekali lagi.
Handler
saja
Anda dapat melakukannya menggunakan setOnKeyListener atau menggunakan textWatcher seperti:
Atur pengamat teks editText.addTextChangedListener(textWatcher);
lalu panggil
private TextWatcher textWatcher = new TextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
//after text changed
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}
@Override
public void afterTextChanged(Editable s) {
}
};
Meskipun banyak jawaban memang menunjuk ke arah yang benar, saya pikir tidak ada dari mereka yang menjawab apa yang dipikirkan oleh penulis pertanyaan itu. Atau setidaknya saya memahami pertanyaan itu secara berbeda karena saya sedang mencari jawaban untuk masalah serupa. Masalahnya adalah "Bagaimana mengetahui kapan pengguna berhenti mengetik tanpa dia menekan tombol" dan memicu beberapa tindakan (misalnya pelengkapan otomatis). Jika Anda ingin melakukan ini, mulailah Timer di onTextChanged dengan penundaan yang Anda anggap pengguna berhenti mengetik (misalnya 500-700ms), untuk setiap huruf baru saat Anda memulai timer, batalkan yang sebelumnya (atau setidaknya gunakan semacam tandai bahwa ketika mereka mencentang mereka tidak melakukan apa-apa). Berikut kode yang mirip dengan yang saya gunakan:
new Timer().schedule(new TimerTask() {
@Override
public void run() {
if (!running) {
new DoPost().execute(s.toString());
});
}
}, 700);
Perhatikan bahwa saya memodifikasi menjalankan bendera boolean di dalam tugas async saya (Tugas mendapatkan json dari server untuk pelengkapan otomatis).
Juga perlu diingat bahwa ini menciptakan banyak tugas pengatur waktu (saya pikir mereka dijadwalkan pada Thread yang sama tetapi Anda harus memeriksanya), jadi mungkin ada banyak tempat untuk diperbaiki tetapi pendekatan ini juga berfungsi dan intinya adalah Anda harus gunakan Pewaktu karena tidak ada "Pengguna berhenti mengetik acara"
@Reno dan @Vinayak B menjawab bersama jika Anda ingin menyembunyikan keyboard setelah tindakan
textView.setOnEditorActionListener(new EditText.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_SEARCH || actionId == EditorInfo.IME_ACTION_DONE) {
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(textView.getWindowToken(), 0);
return true;
}
return false;
}
});
textView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus) {
// your action here
}
}
});
Pendekatan yang berbeda ... berikut ini contohnya: Jika pengguna mengalami penundaan 600-1000ms saat mengetik, Anda mungkin menganggap dia berhenti.
myEditText.addTextChangedListener(new TextWatcher() {
private String s;
private long after;
private Thread t;
private Runnable runnable_EditTextWatcher = new Runnable() {
@Override
public void run() {
while (true) {
if ((System.currentTimeMillis() - after) > 600)
{
Log.d("Debug_EditTEXT_watcher", "(System.currentTimeMillis()-after)>600 -> " + (System.currentTimeMillis() - after) + " > " + s);
// Do your stuff
t = null;
break;
}
}
}
};
@Override
public void onTextChanged(CharSequence ss, int start, int before, int count) {
s = ss.toString();
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void afterTextChanged(Editable ss) {
after = System.currentTimeMillis();
if (t == null)
{
t = new Thread(runnable_EditTextWatcher);
t.start();
}
}
});
Oke, ini pasti berhasil 100%.
Pertama, Anda perlu menyiapkan pendengar jika keyboard ditampilkan atau disembunyikan. Jika keyboard ditampilkan maka kemungkinan pengguna sedang mengetik, jika tidak selesai mengetik.
final View activityRootView = findViewById(android.R.id.content);
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
Rect r = new Rect();
//r will be populated with the coordinates of your view that area still visible.
activityRootView.getWindowVisibleDisplayFrame(r);
int heightDiff = activityRootView.getRootView().getHeight() - (r.bottom - r.top);
if (heightDiff > 100) { // if more than 100 pixels, its probably a keyboard...
isTyping = true;
} else {
//to make sure this will call only once when keyboard is hide.
if(isTyping){
isTyping = false;
}
}
}
});
heightDiff > 100
barangnya menakutkan imho.
Saya memecahkan masalah ini dengan cara ini. Saya menggunakan kotlin.
var timer = Timer()
var DELAY:Long = 2000
editText.addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(s: Editable?) {
Log.e("TAG","timer start")
timer = Timer()
timer.schedule(object : TimerTask() {
override fun run() {
//do something
}
}, DELAY)
}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
Log.e("TAG","timer cancel ")
timer.cancel() //Terminates this timer,discarding any currently scheduled tasks.
timer.purge() //Removes all cancelled tasks from this timer's task queue.
}
})
Saya memiliki masalah yang sama dan tidak ingin bergantung pada pengguna yang menekan Selesai atau Enter.
Upaya pertama saya adalah menggunakan pendengar onFocusChange, tetapi ternyata EditText saya mendapatkan fokus secara default. Saat pengguna menekan beberapa tampilan lain, onFocusChange dipicu tanpa pengguna pernah menetapkannya sebagai fokus.
Solusi berikutnya melakukannya untuk saya, di mana onFocusChange dilampirkan jika pengguna menyentuh EditText:
final myEditText = new EditText(myContext); //make final to refer in onTouch
myEditText.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
myEditText.setOnFocusChangeListener(new OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if(!hasFocus){
// user is done editing
}
}
}
}
}
Dalam kasus saya, ketika pengguna selesai mengedit layar dirender, dengan demikian memperbarui objek myEditText. Jika objek yang sama disimpan, Anda mungkin harus menghapus listener onFocusChange di onFocusChange untuk mencegah masalah onFocusChange yang dijelaskan di awal posting ini.
Saya mengalami masalah yang sama saat mencoba menerapkan 'sekarang mengetik' di aplikasi obrolan. coba untuk memperluas EditText sebagai berikut:
public class TypingEditText extends EditText implements TextWatcher {
private static final int TypingInterval = 2000;
public interface OnTypingChanged {
public void onTyping(EditText view, boolean isTyping);
}
private OnTypingChanged t;
private Handler handler;
{
handler = new Handler();
}
public TypingEditText(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.addTextChangedListener(this);
}
public TypingEditText(Context context, AttributeSet attrs) {
super(context, attrs);
this.addTextChangedListener(this);
}
public TypingEditText(Context context) {
super(context);
this.addTextChangedListener(this);
}
public void setOnTypingChanged(OnTypingChanged t) {
this.t = t;
}
@Override
public void afterTextChanged(Editable s) {
if(t != null){
t.onTyping(this, true);
handler.removeCallbacks(notifier);
handler.postDelayed(notifier, TypingInterval);
}
}
private Runnable notifier = new Runnable() {
@Override
public void run() {
if(t != null)
t.onTyping(TypingEditText.this, false);
}
};
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) { }
@Override
public void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) { }
}
Saya mengakhirinya dengan masalah yang sama dan saya tidak dapat menggunakan solusi dengan onEditorAction atau onFocusChange dan tidak ingin mencoba pengatur waktu. Timer terlalu berbahaya untuk rasa, karena semua utas dan terlalu tidak terduga, karena Anda tidak tahu kapan kode Anda dijalankan.
OnEditorAction tidak menangkap saat pengguna pergi tanpa menggunakan tombol dan jika Anda menggunakannya harap perhatikan bahwa KeyEvent bisa menjadi null. Fokus tidak dapat diandalkan di kedua ujungnya, pengguna bisa mendapatkan fokus dan keluar tanpa memasukkan teks apa pun atau memilih bidang dan pengguna tidak perlu meninggalkan bidang EditText terakhir.
Solusi saya menggunakan onFocusChange dan sebuah flag disetel ketika pengguna mulai mengedit teks dan sebuah fungsi untuk mendapatkan teks dari tampilan fokus terakhir, yang saya panggil saat dibutuhkan.
Saya hanya menghapus fokus pada semua bidang teks saya untuk mengelabui kode tampilan teks cuti, Kode clearFocus hanya dijalankan jika bidang memiliki fokus. Saya memanggil fungsi di onSaveInstanceState jadi saya tidak perlu menyimpan bendera (mEditing) sebagai status tampilan EditText dan saat tombol penting diklik dan saat aktivitas ditutup.
Hati-hati dengan TexWatcher karena sering dipanggil saya menggunakan kondisi fokus agar tidak bereaksi ketika kode onRestoreInstanceState memasukkan teks. saya
final EditText mEditTextView = (EditText) getView();
mEditTextView.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
if (!mEditing && mEditTextView.hasFocus()) {
mEditing = true;
}
}
});
mEditTextView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus && mEditing) {
mEditing = false;
///Do the thing
}
}
});
protected void saveLastOpenField(){
for (EditText view:getFields()){
view.clearFocus();
}
}
Saya telah melakukan sesuatu seperti kelas abstrak ini yang dapat digunakan untuk menggantikan tipe TextView.OnEditorActionListener.
abstract class OnTextEndEditingListener : TextView.OnEditorActionListener {
override fun onEditorAction(textView: TextView?, actionId: Int, event: KeyEvent?): Boolean {
if(actionId == EditorInfo.IME_ACTION_SEARCH ||
actionId == EditorInfo.IME_ACTION_DONE ||
actionId == EditorInfo.IME_ACTION_NEXT ||
event != null &&
event.action == KeyEvent.ACTION_DOWN &&
event.keyCode == KeyEvent.KEYCODE_ENTER) {
if(event == null || !event.isShiftPressed) {
// the user is done typing.
return onTextEndEditing(textView, actionId, event)
}
}
return false // pass on to other listeners
}
abstract fun onTextEndEditing(textView: TextView?, actionId: Int, event: KeyEvent?) : Boolean
}
Sederhana untuk memicu selesai mengetik di EditText
bekerja untuk saya, jika Anda menggunakan java mengubahnya
Di Kotlin
youredittext.doAfterTextChanged { searchTerm ->
val currentTextLength = searchTerm?.length
Handler().postDelayed({
if (currentTextLength == searchTerm?.length) {
// your code
Log.d("aftertextchange", "ON FINISH TRIGGER")
}
}, 3000)
}