Android文本框:通过编程设置焦点和软键盘输入

89

在我的看法中,我有一个搜索EditText,并且我想通过编程方式触发字段上的单击事件的行为,即聚焦于该文本字段并在必要时(如果没有物理键盘)显示软键盘。

我尝试使用field.requestFocus()。该字段实际上获得了焦点,但软键盘未显示。

我尝试使用field.performClick()。但这只调用了该字段的OnClickListener。

有什么建议吗?

8个回答

155

尊敬的先生,请试试这个:

edittext.setFocusableInTouchMode(true);
edittext.requestFocus();

我不确定,但是这可能在一些手机上是必需的(一些旧设备):

final InputMethodManager inputMethodManager = (InputMethodManager) context
                .getSystemService(Context.INPUT_METHOD_SERVICE);
inputMethodManager.showSoftInput(edittext, InputMethodManager.SHOW_IMPLICIT);

3
与单独使用requestFocus()相同的结果......字段获得焦点,但软键盘不会被触发。 - sdabet
12
我在 onResume() 方法中调用 field.requestFocus() 来解决问题,而不是在 onCreate() 中。我不太清楚为什么这样做有效... - sdabet
31
在屏幕上布局完成之前,视图无法获得焦点。由于onCreate()占用了UI线程,因此无法在此期间执行此操作。因此,在onCreate()之后和onResume()之前直接对视图进行布局。 :) - pgsandstrom
@fiddler 它在 onResume 中工作是因为 onResumeonCreate 之后调用,所以 field 直到运行 onCreate 后才存在。请参见此处:http://developer.android.com/reference/android/app/Activity.html#ActivityLifecycle - Randy
3
好的建议,老朋友。我得说,这真值得点赞! - MW.
显示剩余2条评论

66

以下是对我有用的代码。

edittext.post(new Runnable() {
    public void run() {
        edittext.requestFocusFromTouch();
        InputMethodManager lManager = (InputMethodManager)getActivity().getSystemService(Context.INPUT_METHOD_SERVICE); 
        lManager.showSoftInput(edittext, 0);
    }
});

就这样了!享受吧 ;)


2
谢谢,这个对我有用。当用户点击按钮时,我会动态添加EditText - dumbfingers
我从对话框模态中添加了一个 EditText。由于 Android 设置了一些标志,导致该控件无法接收任何触摸事件。如果您在可运行的代码块中添加该字段,则不会设置这些标志。 - JeffRegan
зЬЛиµЈжЭ• EditText зЪД InputType 襀 Android иЃЊзљЃдЄЇдЇЖ nullгАВе¶ВжЮЬдљ†иЃЊзљЃ InputTypeпЉМеЃГеЇФиѓ•еПѓдї•еЈ•дљЬгАВ - JeffRegan
对我来说唯一可行的解决方案是(如果我使用InputMethodManager强制显示键盘,那么我就无法隐藏它)。 - Pavel
其他方法都没用,但这个方法起作用了。我想为用户提供一个框,让他们点击以打开编辑对话视图,而不是为EditText视图单独提供一个编辑行。在手机上,编辑行失去了大部分功能,因为编辑对话视图覆盖整个屏幕,所以用户无法看到编辑行,包括他们正在输入的字母。 - Androidcoder

7

其他两个答案 对我没用,但是以下代码对我有用

@Override
public void onResume() {
    super.onResume();
    SingletonBus.INSTANCE.getBus().register(this);
    //passwordInput.requestFocus(); <-- that doesn't work
    passwordInput.postDelayed(new ShowKeyboard(), 300); //250 sometimes doesn't run if returning from LockScreen
}

ShowKeyboard 是什么

private class ShowKeyboard implements Runnable {
    @Override
    public void run() {
        passwordInput.setFocusableInTouchMode(true);
  //      passwordInput.requestFocusFromTouch();
        passwordInput.requestFocus();            
        getActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
        ((InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE)).showSoftInput(passwordInput, 0);
    }
}

在成功输入后,我还会确保隐藏键盘。

getActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
((InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE))
                    .hideSoftInputFromWindow(getView().getWindowToken(), 0);

从技术上讲,我只是在运行软键盘显示请求之前增加了300毫秒的延迟。很奇怪,对吧?还将requestFocus()更改为requestFocusFromTouch()

编辑:不要使用requestFocusFromTouch(),它会给启动器发送一个触摸事件。坚持使用requestFocus()

编辑2:在对话框(DialogFragment)中,请使用以下内容

getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);

替代

getActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);

requestFocusFromTouch() 似乎会在启动器上触发一个触摸事件。这很奇怪。 - EpicPandaForce
隐藏键盘时,((InputMethodManager) getActivity()..." 代码行在 DialogFragment 中使用时是否也需要更改,还是您上面提到的代码行就足够了? - AJW
它很可能会工作,但你可以尝试一下看看。 - EpicPandaForce

2
在我的情况下,我想要显示虚拟键盘而不引用特定的文本框,所以我使用了接受答案的第一部分来“聚焦”:最初的回答。
edittext.setFocusableInTouchMode(true);
edittext.requestFocus();

然后我展示了虚拟键盘
InputMethodManager inputMethodManager = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
inputMethodManager.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);

1

对于 Kotlin,可以使用扩展函数实现如下:

fun View.showSoftKeyboard() {
    this.requestFocus()
    val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
    imm.showSoftInput(this, InputMethodManager.SHOW_IMPLICIT)
}

0

val mAlertDialog = mBuilder.show()

变量 mAlertDialog = mBuilder.show()

        //Coloca o foo no txtDlgQuantidade e então chama o teclado
        mDialogView.txtDlgQuantidade.isFocusable = true
        mDialogView.txtDlgQuantidade.isFocusableInTouchMode = true
        mDialogView.txtDlgQuantidade.requestFocus()
        mAlertDialog.window?.clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM)
        mAlertDialog.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE)

0
在我的情况下,只有这个解决了所有的问题:
val inputMethodManager: InputMethodManager = 
   context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
inputMethodManager.showSoftInput(edittext, InputMethodManager.SHOW_IMPLICIT)

我把它放在RecyclerView Adapter中,因为我使用数据绑定。 另外,我没有使用edittext.setFocusableInTouchMode(true),因为在我的布局中,默认情况下是true。 而且不要使用这一行:edittext.requestFocus()。当我将其删除时,它开始工作了 :)


0
        field.post(new Runnable() {
            @Override
            public void run() {
                field.requestFocus();
                field.onKeyUp(KeyEvent.KEYCODE_DPAD_CENTER, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DPAD_CENTER));
            }
        });

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接