ฉันต้องการจับเหตุการณ์เมื่อผู้ใช้แก้ไข EditText เสร็จแล้ว
ทำได้ยังไง?
override fun afterTextChanged(s: Editable?) { if (s.toString().length == 5) { val enteredString = s.toString() }
ฉันต้องการจับเหตุการณ์เมื่อผู้ใช้แก้ไข EditText เสร็จแล้ว
ทำได้ยังไง?
override fun afterTextChanged(s: Editable?) { if (s.toString().length == 5) { val enteredString = s.toString() }
คำตอบ:
เมื่อผู้ใช้แก้ไขเสร็จแล้วเขาจะกดDone
หรือEnter
((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.
}
}
);
วิธีที่ดีกว่าคุณยังสามารถใช้ EditText onFocusChange listener เพื่อตรวจสอบว่าผู้ใช้ทำการแก้ไขแล้วหรือไม่: (ไม่จำเป็นต้องพึ่งพาผู้ใช้ที่กดปุ่ม Done หรือ Enter บนคีย์บอร์ดแบบนุ่ม)
((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
}
}
});
หมายเหตุ: สำหรับ EditText มากกว่าหนึ่งรายการคุณยังสามารถให้ชั้นเรียนของคุณนำไปใช้View.OnFocusChangeListener
จากนั้นตั้งค่าผู้ฟังให้กับ EditText ของคุณแต่ละคนและตรวจสอบความถูกต้องดังต่อไปนี้
((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
ได้ มันจะไม่สูญเสียโฟกัส
EditText
? ต้องใช้onEditorAction
ไหม?
EditText
คุณจะตรวจสอบสิ่งที่ผู้ใช้ทำเพื่อออกจากหน้าจอ
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 }
แม้ว่าฉันจะพิมพ์อะไรลงไปก็ตามนี่เป็นข้อความแก้ไขที่ยอมรับเฉพาะตัวเลขเท่านั้น
โดยส่วนตัวแล้วฉันชอบการส่งอัตโนมัติหลังจากสิ้นสุดการพิมพ์ วิธีตรวจจับเหตุการณ์นี้มีดังนี้
การประกาศและการเริ่มต้น:
private Timer timer = new Timer();
private final long DELAY = 1000; // in ms
Listener ในเช่น 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);
}
}
});
ดังนั้นเมื่อข้อความถูกเปลี่ยนตัวจับเวลาจะเริ่มรอให้การเปลี่ยนแปลงครั้งต่อไปเกิดขึ้น เมื่อเกิดขึ้นตัวจับเวลาจะถูกยกเลิกและเริ่มต้นใหม่อีกครั้ง
Handler
แทน
คุณสามารถทำได้โดยใช้ setOnKeyListener หรือใช้ textWatcher เช่น:
ตั้งค่าตัวเฝ้าดูข้อความ editText.addTextChangedListener(textWatcher);
แล้วโทร
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) {
}
};
แม้ว่าคำตอบจำนวนมากจะชี้ไปในทิศทางที่ถูกต้อง แต่ฉันคิดว่าไม่มีคำตอบใดที่ตอบได้ว่าผู้เขียนคำถามกำลังคิดอย่างไร หรืออย่างน้อยฉันก็เข้าใจคำถามต่างออกไปเพราะฉันกำลังมองหาคำตอบสำหรับปัญหาที่คล้ายกัน ปัญหาคือ "จะรู้ได้อย่างไรว่าผู้ใช้หยุดพิมพ์โดยไม่ต้องกดปุ่ม" และทริกเกอร์การทำงานบางอย่าง (เช่นการเติมข้อความอัตโนมัติ) หากคุณต้องการเริ่มตัวจับเวลาใน onTextChanged ด้วยความล่าช้าที่คุณจะถือว่าผู้ใช้หยุดพิมพ์ (เช่น 500-700 มิลลิวินาที) สำหรับตัวอักษรใหม่แต่ละตัวเมื่อคุณเริ่มตัวจับเวลาจะยกเลิกตัวจับเวลาก่อนหน้านี้ (หรืออย่างน้อยก็ใช้บางประเภท ตั้งค่าสถานะว่าเมื่อพวกเขาทำเครื่องหมายพวกเขาจะไม่ทำอะไรเลย) นี่คือรหัสที่คล้ายกับสิ่งที่ฉันใช้:
new Timer().schedule(new TimerTask() {
@Override
public void run() {
if (!running) {
new DoPost().execute(s.toString());
});
}
}, 700);
โปรดทราบว่าฉันแก้ไขการรันแฟล็กบูลีนภายในงาน async ของฉัน (งานรับ json จากเซิร์ฟเวอร์สำหรับการทำให้สมบูรณ์อัตโนมัติ)
โปรดทราบว่าสิ่งนี้จะสร้างงานจับเวลาจำนวนมาก (ฉันคิดว่าพวกเขาถูกกำหนดไว้ในเธรดเดียวกันคุณ แต่จะต้องตรวจสอบสิ่งนี้) ดังนั้นอาจมีหลายสถานที่ที่ต้องปรับปรุง แต่วิธีนี้ก็ใช้ได้เช่นกันและสิ่งที่สำคัญที่สุดคือคุณควร ใช้ตัวจับเวลาเนื่องจากไม่มี "เหตุการณ์ที่ผู้ใช้หยุดพิมพ์"
ทั้ง @Reno และ @Vinayak B ตอบพร้อมกันหากคุณต้องการซ่อนแป้นพิมพ์หลังจากดำเนินการ
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
}
}
});
วิธีการอื่น ... นี่คือตัวอย่าง: หากผู้ใช้มีความล่าช้า 600-1000 มิลลิวินาทีเมื่อกำลังพิมพ์คุณอาจคิดว่าเขาหยุด
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();
}
}
});
โอเคนี่จะได้ผลแน่นอน 100%
ก่อนอื่นคุณจะต้องตั้งค่าตัวรับฟังหากแป้นพิมพ์แสดงหรือซ่อน หากแป้นพิมพ์แสดงขึ้นแสดงว่าผู้ใช้กำลังพิมพ์อยู่หรือพิมพ์เสร็จแล้ว
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
สิ่งที่น่ากลัวคือ imho
ฉันแก้ปัญหานี้ด้วยวิธีนี้ ฉันใช้โคตลิน
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.
}
})
ฉันมีปัญหาเดียวกันและไม่ต้องการพึ่งพาผู้ใช้ที่กด Done หรือ Enter
ความพยายามครั้งแรกของฉันคือใช้ตัวฟัง onFocusChange แต่เกิดขึ้นว่า EditText ของฉันได้รับโฟกัสตามค่าเริ่มต้น เมื่อผู้ใช้กดมุมมองอื่น ๆ onFocusChange จะถูกทริกเกอร์โดยที่ผู้ใช้ไม่เคยกำหนดโฟกัส
วิธีแก้ปัญหาถัดไปทำเพื่อฉันโดยที่ onFocusChange ถูกแนบมาหากผู้ใช้แตะ 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
}
}
}
}
}
ในกรณีของฉันเมื่อผู้ใช้แก้ไขเสร็จสิ้นแล้วหน้าจอถูกแสดงผลใหม่ดังนั้นการต่ออายุวัตถุ myEditText หากวัตถุเดียวกันถูกเก็บไว้คุณควรลบตัวฟัง onFocusChange ใน onFocusChange เพื่อป้องกันปัญหา onFocusChange ที่อธิบายไว้ในตอนต้นของโพสต์นี้
ฉันมีปัญหาเดียวกันเมื่อพยายามใช้ "ตอนนี้พิมพ์" ในแอปแชท ลองขยาย EditText ดังนี้:
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) { }
}
ฉันทำให้เธอจบลงด้วยปัญหาเดียวกันและฉันไม่สามารถใช้วิธีแก้ปัญหากับ onEditorAction หรือ onFocusChange และไม่ต้องการลองจับเวลา ตัวจับเวลาอันตรายเกินไปสำหรับอาจลิ้มรสเนื่องจากเธรดทั้งหมดและคาดเดาไม่ได้มากเกินไปเนื่องจากคุณไม่รู้ว่าโค้ดของคุณถูกเรียกใช้งานเมื่อใด
onEditorAction ไม่จับเมื่อผู้ใช้ออกไปโดยไม่ใช้ปุ่มและหากคุณใช้โปรดสังเกตว่า KeyEvent อาจเป็นโมฆะ โฟกัสไม่น่าเชื่อถือที่ปลายทั้งสองข้างผู้ใช้สามารถรับโฟกัสและออกไปโดยไม่ต้องป้อนข้อความใด ๆ หรือเลือกฟิลด์และผู้ใช้ไม่จำเป็นต้องออกจากฟิลด์ EditText สุดท้าย
โซลูชันของฉันใช้ onFocusChange และตั้งค่าสถานะเมื่อผู้ใช้เริ่มแก้ไขข้อความและฟังก์ชันเพื่อรับข้อความจากมุมมองที่โฟกัสล่าสุดซึ่งฉันเรียกใช้เมื่อต้องการ
ฉันเพียงแค่ล้างโฟกัสในช่องข้อความทั้งหมดของฉันเพื่อหลอกล่อรหัสมุมมองข้อความลา, โค้ด clearFocus จะทำงานก็ต่อเมื่อฟิลด์นั้นมีโฟกัส ฉันเรียกใช้ฟังก์ชันใน onSaveInstanceState ดังนั้นฉันจึงไม่ต้องบันทึกแฟล็ก (mEditing) เป็นสถานะของมุมมอง EditText และเมื่อมีการคลิกปุ่มสำคัญและเมื่อปิดกิจกรรม
โปรดใช้ความระมัดระวังกับ TexWatcher เนื่องจากมีการเรียกใช้บ่อยครั้งฉันใช้เงื่อนไขในการโฟกัสเพื่อไม่ตอบสนองเมื่อรหัส onRestoreInstanceState ป้อนข้อความ ผม
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();
}
}
ฉันได้ทำอะไรบางอย่างเช่นคลาสนามธรรมนี้ที่สามารถใช้แทนประเภท TextView.OditorActionListener ได้
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
}
ง่ายต่อการเรียกใช้การพิมพ์เสร็จสิ้นใน EditText
ได้ผลสำหรับฉันถ้าคุณใช้ java แปลงมัน
ตั้งอยู่ใน Kotlin
youredittext.doAfterTextChanged { searchTerm ->
val currentTextLength = searchTerm?.length
Handler().postDelayed({
if (currentTextLength == searchTerm?.length) {
// your code
Log.d("aftertextchange", "ON FINISH TRIGGER")
}
}, 3000)
}