最近重新设计了一遍项目中的搜索栏,但是目前这个输入框每次填完搜索内容,都需要去按下右边的搜索按钮,感觉比较麻烦。但是看到很多应用,填完内容后输入框右下角按钮直接会变成搜索按钮。平时对这方面了解比较少,故在此总结下 Android 软键盘响应事件。
要想实现这个小功能,就不得不说这个属性,对应代码中的方法是:
imeOptions 常用的有以下几种取值:
- void setImeOptions(int imeOptions)
意思都很好理解 ,其中默认动作是 actionUnspecified, 在代码中这些值存储在 EditorInfo 类中,以 IME 开头,如
。所以上面我们需要实现的搜索功能只是这些动作中的一种。另外还需要设置一个属性,不然无法生效:
- EditorInfo.IME_ACTION_GO
- android:singleLine="true"
我的理解是,如果不设置限制单行,那么右下角会被换行按钮占用,这个功能是高于键盘动作事件优先级的。 另外可能有些输入法还要求设置:
- android:inputType="text"
不过我实测不设置也可以(当然为了兼容性还是建议设一下)。好了,这样设完之后我们就可以在代码中监听这个动作的事件了:
- mEditText.setOnEditorActionListener(new EditText.OnEditorActionListener() {
- @Override
- public
- boolean
- onEditorAction
- (TextView v, int actionId, KeyEvent event)
- {
- if (actionId == EditorInfo.IME_ACTION_SEARCH) {
- String text = mEditText.getText().toString();
- if (TextUtils.isEmpty(text)) {
- Toast.makeText(MainActivity.this, "请输入关键字", Toast.LENGTH_SHORT).show();
- } else {
- Toast.makeText(MainActivity.this, "输入了" + text, Toast.LENGTH_SHORT).show();
- }
- return true;
- }
- return false;
- }
- });
看下效果:
返回 true 说明消耗了这个事件,不然会继续执行这个动作默认的操作,这点在源码上很容易体现:
- public void onEditorAction(int actionCode) {
- final Editor.InputContentType ict = mEditor == null ? null : mEditor.mInputContentType;
- if (ict != null) {
- if (ict.onEditorActionListener != null) {
- if (ict.onEditorActionListener.onEditorAction(this,
- actionCode, null)) {
- return;
- }
- }
- ......执行默认动作
在源码中看出,系统实现的默认动作只有三个:
- if (actionCode == EditorInfo.IME_ACTION_NEXT) {
- View v = focusSearch(FOCUS_FORWARD);
- if (v != null) {
- if (!v.requestFocus(FOCUS_FORWARD)) {
- throw new IllegalStateException("focus search returned a view " + "that wasn't able to take focus!");
- }
- }
- return;
- } else if (actionCode == EditorInfo.IME_ACTION_PREVIOUS) {
- View v = focusSearch(FOCUS_BACKWARD);
- if (v != null) {
- if (!v.requestFocus(FOCUS_BACKWARD)) {
- throw new IllegalStateException("focus search returned a view " + "that wasn't able to take focus!");
- }
- }
- return;
- } else if (actionCode == EditorInfo.IME_ACTION_DONE) {
- InputMethodManager imm = InputMethodManager.peekInstance();
- if (imm != null && imm.isActive(this)) {
- imm.hideSoftInputFromWindow(getWindowToken(), 0);
- }
- return;
- }
- }
有一点需要提一下:上面代码这么设置,点完搜索按钮,事件响应了但输入框是不会消失的,所以这里我们可以取巧下:处理完我们的动作后直接把动作设置为 IME_ACTION_DONE, 然后返回 false,这样就可以继续执行
中的代码,从而实现在点完搜索按钮后隐藏输入框:
- EditorInfo.IME_ACTION_DONE
- mEditText.setOnEditorActionListener(new EditText.OnEditorActionListener() {
- @Override
- public
- boolean
- onEditorAction
- (TextView v, int actionId, KeyEvent event)
- {
- if (actionId == EditorInfo.IME_ACTION_SEARCH) {
- String text = mEditText.getText().toString();
- if (TextUtils.isEmpty(text)) {
- //如果没输入内容就不隐藏了
- Toast.makeText(MainActivity.this, "请输入关键字", Toast.LENGTH_SHORT).show();
- return true;
- } else {
- Toast.makeText(MainActivity.this, "输入了" + text, Toast.LENGTH_SHORT).show();
- mEditText.setImeOptions(EditorInfo.IME_ACTION_DONE);
- return false;
- }
- }
- return false;
- }
- });
最后记得在搜索完重置下动作:
。
- mEditText.setImeOptions(EditorInfo.IME_ACTION_SEARCH);
,但是我们想换行怎么办? 在代码中这样设置就行了:
- android:singleLine="true"
- mEditText.setHorizontallyScrolling(false);
- mEditText.setMaxLines(4);
在布局文件中设置是无效的,应该也是优先级的问题。加第一行代码是因为 EditTextview 内容超过一行是不会换行的而是左右滚动。
来源: https://juejin.im/post/5a3b93f6f265da4324809ef0