ユーザーが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リスナーを使用して、ユーザーが編集を完了したかどうかを確認することもできます(ユーザーがソフトキーボードの[完了]ボタンまたは[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
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) {
}
};
多くの回答は正しい方向を指していますが、質問の作成者が考えていたものに回答するものはないと思います。あるいは、私は同様の問題への回答を探していたので、少なくとも私は質問を別様に理解しました。問題は、「ユーザーがボタンを押さずに入力を停止したことを知る方法」であり、何らかのアクション(オートコンプリートなど)をトリガーします。これを行う場合は、タイマーを開始するときにユーザーが入力を停止したと見なす遅延(たとえば500〜700ミリ秒)でタイマーをonTextChangedで開始します。チェックマークを付けると何もしないことをフラグで示します)。ここに私が使用したものと同様のコードがあります:
new Timer().schedule(new TimerTask() {
@Override
public void run() {
if (!running) {
new DoPost().execute(s.toString());
});
}
}, 700);
非同期タスク内で実行中のブールフラグを変更していることに注意してください(タスクはオートコンプリートのためにサーバーから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
ものは怖い私見です。
私はこの方法でこの問題を解決しました。コトリンを使いました。
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.
}
})
私は同じ問題を抱えていて、ユーザーが[完了]または[Enter]を押すことに依存したくありませんでした。
私の最初の試みはonFocusChangeリスナーを使用することでしたが、EditTextがデフォルトでフォーカスを取得することが発生しました。ユーザーが他のビューを押すと、ユーザーがフォーカスを割り当てることなく、onFocusChangeがトリガーされました。
次の解決策は私のためにそれを行いました、そこでユーザーがEditTextに触れた場合にonFocusChangeがアタッチされます:
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がnullになる可能性があることに注意してください。フォーカスは両端で信頼できず、ユーザーはフォーカスを取得してテキストを入力したりフィールドを選択したりせずに離れることができ、ユーザーは最後のEditTextフィールドを離れる必要はありません。
私のソリューションでは、onFocusChangeと、ユーザーがテキストの編集を開始したときに設定されるフラグと、必要なときに呼び出す最後にフォーカスされたビューからテキストを取得する関数を使用しています。
すべてのテキストフィールドのフォーカスをクリアして、Leave Textビューコードをだまします。フィールドにフォーカスがある場合のみ、clearFocusコードが実行されます。onSaveInstanceStateで関数を呼び出すので、フラグ(mEditing)をEditTextビューの状態として保存したり、重要なボタンがクリックされたり、アクティビティが閉じられたりする必要がありません。
onRestoreInstanceStateコードがテキストを入力するときに反応しないようにフォーカスの条件を使用することが多いため、TexWatcherには注意してください。私
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.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
}
EditTextでの入力完了をトリガーするのは簡単
私のために働いた、あなたがそれを変換するJavaを使用しているなら
コトリンで
youredittext.doAfterTextChanged { searchTerm ->
val currentTextLength = searchTerm?.length
Handler().postDelayed({
if (currentTextLength == searchTerm?.length) {
// your code
Log.d("aftertextchange", "ON FINISH TRIGGER")
}
}, 3000)
}