如何在 EditText 获得焦点时显示软键盘

544
我希望在EditText聚焦时(如果设备没有物理键盘),自动显示软键盘,但我有两个问题:
  1. 当我的Activity被显示时,我的EditText已经聚焦了,但是键盘没有显示出来。我需要再次点击它才能显示键盘(应该在Activity显示时就自动显示键盘)。

  2. 当我在键盘上点击完成时,键盘会消失,但是EditText仍然保持聚焦状态,这不是我想要的(因为我的编辑已经完成了)。

总之,我的问题是需要像iPhone一样,保持键盘与我的EditText状态同步(聚焦/未聚焦),并且如果有物理键盘,不要显示软键盘。

我只有一个基本的EditText,如下所示: <EditText android:id="@+id/myEditText" android:layout_width="fill_parent" android:layout_height="wrap_content" android:imeOptions="actionDone" />在我的活动中,我有这个:EditText editTxt = (EditText) findViewById(R.id.myEditText); editTxt.requestFocus(); - Ludovic Landry
2
这比这篇帖子中的任何答案都更有帮助:https://dev59.com/tHE95IYBdhLWcg3wOLQ1#2418314 - Armel Larcier
49个回答

745

要强制显示软键盘,您可以使用

EditText yourEditText= (EditText) findViewById(R.id.yourEditText);
yourEditText.requestFocus();
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.showSoftInput(yourEditText, InputMethodManager.SHOW_IMPLICIT);

要消除对 EditText 的焦点,可惜你需要一个虚拟的 View 来获取焦点。


要关闭它,您可以使用

InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(yourEditText.getWindowToken(), 0);

这个可以在对话框中使用。

public void showKeyboard(){
    InputMethodManager inputMethodManager = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
    inputMethodManager.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
}

public void closeKeyboard(){
    InputMethodManager inputMethodManager = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
    inputMethodManager.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY, 0);
}

3
如果我这样做,当该活动出现时会显示软键盘(很好),但是当我的焦点离开EditText并转到例如Button时,键盘会保持显示状态(那就不好了)。 - Ludovic Landry
181
在对话框中,如果EditText已经聚焦,那么这对我不起作用。不确定原因。 - mxk
10
@AbdellahBenhammou,在显示软键盘之前在您的编辑文本上调用requestFocus可能会解决您的问题。对我有用。 - r1k0
18
请在您的DialogFragment的onCreate()方法中执行以下操作:getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE); 该代码将使软键盘自动弹出。 - Phillip
23
只有在与yourEditText.requestFocus()一起使用时才能正常工作,详见此处:https://dev59.com/Smox5IYBdhLWcg3ww28D。 - Vivek Pandey
显示剩余12条评论

265
我遇到了同样的问题。在editText的可见性从GONE变为VISIBLE之后,我需要立即设置焦点并显示软键盘。我使用以下代码实现了这一点:
new Handler().postDelayed(new Runnable() {
            
    public void run() {
//        ((EditText) findViewById(R.id.et_find)).requestFocus();
//              
        EditText yourEditText= (EditText) findViewById(R.id.et_find);
//        InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
//        imm.showSoftInput(yourEditText, InputMethodManager.SHOW_IMPLICIT);

        yourEditText.dispatchTouchEvent(MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_DOWN, 0f, 0f, 0));
        yourEditText.dispatchTouchEvent(MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_UP, 0f, 0f, 0));                          
    }
}, 200);

对我来说,延迟100毫秒可以正常工作,但是没有任何延迟或者只有1毫秒的延迟时会失败。

代码的注释部分展示了另一种方法,但只适用于某些设备。我在2.2版本(模拟器)、2.2.1版本(真实设备)和1.6版本(模拟器)上进行了测试。


61
我不知道一件事物可以同时如此丑陋和美丽。非常感谢! - mkerley
17
@jellyfish 这模拟了对“EditText”进行的一次轻击。对于其他人,你可以直接在“yourEditText”小部件上使用“View.postDelayed()”方法,而不是创建一个新的“Handler”。 - Tony Chan
5
这是一个黑客技巧 - David Chandler提供了更好的解决方案。 - Ben Bederson
4
如果David Chandler的解决方案在所有Android版本/设备上都有效,并且适用于仅将VISIBILITY从GONE更改为VISIBLE的情况,那么是的 - 你应该使用他的解决方案。 - Mike Keskinov
3
同意。你知道一个能在所有Android版本上使用的更好的解决方案吗? - Mike Keskinov
显示剩余8条评论

168

要使键盘出现,请使用

getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);

这种方法比直接调用InputMethodManager更可靠。

要关闭它,请使用

getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);

14
有人能解释一下为什么这比直接调用“InputMethodManager”更可靠吗?(首先,它不像raukodraug的解决方案那样有效。) - Matthew Quiros
5
这种方法对我也不起作用。我使用Android 2.3.5。raukodraug的解决方案对我有效。我搜索了版本依赖,但没有找到相关内容。 - Hugo Logmans
2
这在我的Android 4.4.2上有效。本帖中选择的InputMethodManager方法对我无效。 - Phil
2
在我的Android 4.4.2上没有起作用。它显示了键盘,但没有隐藏它。 - John J Smith
对我没用。我不得不使用InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); imm.showSoftInput(searchInputBox, InputMethodManager.SHOW_IMPLICIT); - marienke
显示剩余4条评论

106

当其他方法都无法解决问题时,强制显示它

editText.requestFocus();
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, InputMethodManager.HIDE_IMPLICIT_ONLY);

如果您希望稍后关闭它,比如在onPause()中,您可以调用以下方法:

InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(editText.getWindowToken(), 0);

5
你是正确的,@Bolling!当其他方法都无法解决时,你的代码拯救了我。谢谢! - Willian Paixao
3
你的代码是我唯一一个可用的选择,我尝试了这个页面上的每个解决方案!非常感谢! - Mattia Ruggiero
10
不要强制操作。在有些情况下,当你从前台切换到后台时,键盘会一直保留在屏幕上,因为你进行了强制操作。这是一个分段问题,但我在三星Duos手机上也遇到过类似情况。 - j2emanue
我通常总是有代码在onPause()中关闭键盘,因为我曾经看到它会卡住,即使你没有强制打开它。 - Bolling
"toggleSoftInput"已被弃用。 - Akito
显示剩余2条评论

77
以下代码是从Google的4.1源代码中获取的SearchView。在较低版本的Android上也能正常工作。
private Runnable mShowImeRunnable = new Runnable() {
    public void run() {
        InputMethodManager imm = (InputMethodManager) getContext()
                .getSystemService(Context.INPUT_METHOD_SERVICE);

        if (imm != null) {
            imm.showSoftInput(editText, 0);
        }
    }
};

private void setImeVisibility(final boolean visible) {
    if (visible) {
        post(mShowImeRunnable);
    } else {
        removeCallbacks(mShowImeRunnable);
        InputMethodManager imm = (InputMethodManager) getContext()
                .getSystemService(Context.INPUT_METHOD_SERVICE);

        if (imm != null) {
            imm.hideSoftInputFromWindow(getWindowToken(), 0);
        }
    }
}

然后,除此之外,以下代码需要在创建控件/活动时添加(在我的情况下,它是一个组合控件,而不是活动)。

this.editText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
    public void onFocusChange(View v, boolean hasFocus) {
        setImeVisibility(hasFocus);
    }
});

37
这段代码的意思是:根据是否获得焦点来设置输入法的可见性。 - mxk
我尝试了这种方法,因为我实际上是在“自己滚动搜索视图”(不想这样做,但有原因)。这对我有效,除了活动启动时。我在活动中添加了android:windowSoftInputMode="alwaysVisible",并且已经调用了requestFocus()来编辑文本。像冠军一样工作。 - javahead76
这个解决方案对我不起作用。我的情况是:编辑文本已经消失了,当我将其设置为可见时,我想显示软键盘。有人可以分享一下,在这种情况下是否应该起作用。谢谢。 - Sandra
2
在尝试了几种变化后,这是唯一一个对我有效的(Android 4.42)。谢谢。 - John J Smith
1
+1 - 关于确切的问题,这是最完整和正确的答案,应该被接受为答案。 - greyhairredbear
显示剩余5条评论

36

android:windowSoftInputMode="stateAlwaysVisible" -> 在清单文件中使用。

edittext.requestFocus(); -> 在代码中使用。

当活动出现时,此操作将在请求焦点的编辑文本上打开软键盘。


4
在Activity创建时打开键盘。 - Idemax
没有回答问题,但是帮了我 :) - S.Thiongane
在API 22中,可以在没有请求焦点的情况下打开键。 - David
对于我的情况来说运行良好。我想知道为什么仅从xml中请求焦点属性也需要在“清单”中进行提及! - sud007

32

我最近在一些简单情况下使用了以下代码,运气不错。我还没有完成所有测试,但......

EditText input = (EditText) findViewById(R.id.Input);
input.requestFocus();    
input.dispatchTouchEvent(MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_DOWN, 0f, 0f, 0));
input.dispatchTouchEvent(MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_UP, 0f, 0f, 0));

然后,键盘就会出现。


对于我的情况,我有一个按钮来添加一些可选信息。在按钮的onClick处理程序中,上述代码被添加以强制软键盘出现以输入可选信息。Droid 2.2.2 - Dent
这是一个很好的解决方案,但不要忘记在使用后创建一个MotionEvent对象并调用recycle()方法,以便稍后的调用者可以重复使用它们。 - jimbob
你只需要一个dispatchTouchEvent(),并将其参数设置为ACTION_UP。 - Mohammed Junaid

20

你可以尝试强制显示软键盘,这对我有效:

...
dialog.show();
input.requestFocus();
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);

1
这对我有用... 我曾尝试过这些:InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); imm.showSoftInput(name, inputMethodManager.SHOW_IMPLICIT); 或者 getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE); 但它们都没有起作用。 - Günay Gültekin

17

对于 Kotlin,只需使用以下扩展:

fun EditText.showKeyboard() {
    val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
    imm.showSoftInput(this, InputMethodManager.SHOW_IMPLICIT)
}

fun EditText.hideKeyboard() {
    val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
    imm.hideSoftInputFromWindow(this.windowToken, 0)
}

1
正是我所寻找的。 - lasec0203

11

对于片段,确保它正常工作:

 displayName = (EditText) view.findViewById(R.id.displayName);
    InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
    imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);

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