android EditText - 完成的输入事件

时间:2011-11-09 10:13:57

标签: android android-edittext

我想在用户完成编辑EditText时捕获一个事件。

怎么做?

16 个答案:

答案 0 :(得分:163)

更好的方法是,您还可以使用EditText onFocusChange侦听器来检查用户是否已完成编辑:(无需依赖用户按下软键盘上的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) {
       validateInput(v);
      }
    }
 });

答案 1 :(得分:105)

用户完成编辑后,他/她将按DoneEnter

((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. 
        }
    }
);

答案 2 :(得分:45)

我个人更喜欢在打字结束后自动提交。以下是检测此事件的方法。

声明和初始化:

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);
            }
        }
    });

因此,当文本被更改时,计时器开始等待任何下一次更改发生。当它们发生时,计时器被取消,然后再次启动。

答案 3 :(得分:19)

您可以使用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) {

        }
    };

答案 4 :(得分:4)

虽然许多答案确实指向了正确的方向,但我认为它们都没有回答问题的作者在想什么。或者至少我不同地理解这个问题,因为我正在寻找类似问题的答案。 问题是“如何在没有按下按钮的情况下知道用户何时停止输入”并触发某些操作(例如自动完成)。如果你想这样做,启动onTextChanged中的定时器,你会考虑用户停止输入的延迟(例如500-700ms),当你启动定时器时每个新字母取消前一个(或至少使用某种类型的标记,当他们打勾他们什么都不做)。这是与我使用的代码相似的代码:

new Timer().schedule(new TimerTask() {
  @Override
  public void run() {
     if (!running) {                            
        new DoPost().execute(s.toString());
  });
 }
}, 700);

请注意,我在异步任务中修改了运行boolean标志(Task从服务器获取json以进行自动完成)。

另外请记住,这会创建许多计时器任务(我认为它们是在同一个线程上安排的,但是必须检查一下),所以可能有很多地方需要改进,但这种方法也有效,底线是你应该使用一个Timer,因为没有“用户停止输入事件”

答案 5 :(得分:4)

如果你想在动作后隐藏键盘,@ 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
        }
    }
});

答案 6 :(得分:4)

我以这种方式解决了这个问题。我用过科特林。

        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.
            }
        })

答案 7 :(得分:2)

好的,这肯定会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;
                        }
                    }
            }
        });

答案 8 :(得分:2)

一种不同的方法......这是一个例子: 如果用户在打字时有600-1000ms的延迟,您可能会认为他已经停止了。



 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();
                }
            }
        });




答案 9 :(得分:0)

我遇到了同样的问题,并且不想依赖用户按Done或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问​​题。

答案 10 :(得分:0)

我在尝试在聊天应用上实现“正在输入”时遇到了同样的问题。 尝试按如下方式扩展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) { }

}

答案 11 :(得分:0)

我以同样的问题结束了她,我无法使用onEditorAction或onFocusChange的解决方案,并且不想尝试计时器。一个计时器太危险了,因为所有的线程都太难以预测,因为你不知道你的代码何时被执行。

当用户不使用按钮离开时,onEditorAction不会捕获,如果您使用它,请注意KeyEvent可以为null。焦点在两端都不可靠,用户可以获得焦点并离开而无需输入任何文本或选择字段,用户无需离开最后的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();
    }
}

答案 12 :(得分:0)

我已经做了类似此类抽象类的操作,可以用来代替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
}

答案 13 :(得分:0)

易于触发完成在EditText中键入

为我工作,如果您使用java将其转换

在科特林

youredittext.doAfterTextChanged { searchTerm ->
val currentTextLength = searchTerm?.length
    Handler().postDelayed({
        if (currentTextLength == searchTerm?.length) {
            // your code 
           Log.d("aftertextchange", "ON FINISH TRIGGER")
          }
       }, 3000)
}

答案 14 :(得分:0)

使用这个类

DelayedTextWatcher.java

   symbol     variable      value
0    TDOC   returns_7d  -0.210839
1    EXAS   returns_7d  -4.649067
2    PACB   returns_7d  -2.953760
3    REGN   returns_7d   0.465364
4    TWST   returns_7d   6.707956
5    TDOC  returns_30d -17.712095
6    EXAS  returns_30d  -6.439275
7    PACB  returns_30d  11.886232
8    REGN  returns_30d   5.803325
9    TWST  returns_30d   3.619967
10   TDOC  returns_ytd  -3.922423
11   EXAS  returns_ytd  -1.415680
12   PACB  returns_ytd  37.815711
13   REGN  returns_ytd  -0.629814
14   TWST  returns_ytd  10.404300

答案 15 :(得分:0)

您可以使用 raise exception_class(message, screen, stacktrace) selenium.common.exceptions.WebDriverException: Message: unknown command: unknown command: session/c0ce2c2bc668f869e914f24ca168eab9/se/file Stacktrace: Backtrace: Ordinal0 [0x00503733+2504499] Ordinal0 [0x0049C401+2081793] Ordinal0 [0x003A2628+1058344] Ordinal0 [0x003E3BEE+1326062] Ordinal0 [0x003E39D8+1325528] Ordinal0 [0x003850CF+938191] Ordinal0 [0x003855D6+939478] Ordinal0 [0x003858B1+940209] GetHandleVerifier [0x0067FB8C+1512252] GetHandleVerifier [0x0072B0DF+2214031] GetHandleVerifier [0x00584BC3+484211] GetHandleVerifier [0x00583E69+480793] Ordinal0 [0x004A218D+2105741] Ordinal0 [0x00384E65+937573] Ordinal0 [0x00384830+935984] GetHandleVerifier [0x0075152C+2370780] BaseThreadInitThunk [0x76D4FA29+25] RtlGetAppContainerNamedObjectPath [0x77297A9E+286] RtlGetAppContainerNamedObjectPath [0x77297A6E+238] 来延迟。出现此问题是由于多次调用过滤器和使用 Handler 来停止多次调用处理程序。

count