在片段启动时显示用于EditText的键盘

71
当我的片段开始时,我希望我的EditText获得焦点并让用户可以在其中直接开始输入。我使用requestFocus()方法可以将其设为焦点,但是我无法让键盘弹出。
我已经尝试了以下方法:
edit = (EditText) view.findViewById(R.id.search);
edit.requestFocus();
InputMethodManager imgr = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
imgr.showSoftInput(edit, 0);

edit = (EditText) view.findViewById(R.id.search);
InputMethodManager imgr = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
imgr.showSoftInput(edit, 0);
edit.requestFocus();

如何使EditText出现键盘?


这是对我有效的方法 - https://dev59.com/BmUq5IYBdhLWcg3wJNBA#39658629 - v01d
我的声望太低了,无法对这个问题进行评论。我在这里回答了一个方法来控制何时显示或隐藏键盘(链接:https://dev59.com/543da4cB1Zd3GeqP6u4q#43807917)。 - Catapimba
请查看推荐答案:https://dev59.com/eLnoa4cB1Zd3GeqPXMcU#60666198 - Logo
16个回答

108

这个有效吗?

imgr.toggleSoftInput(InputMethodManager.SHOW_FORCED, InputMethodManager.HIDE_IMPLICIT_ONLY);

如果你无法关闭它,可以使用其他这些方法之一。 - Sam
5
这感觉像是一个变通方法。正确的程序应该是要么按照 OP 建议的方法,要么调用 imgr.showSoftInput(getView(), InputMethodManager.SHOW_IMPLICIT)。如果键盘已经打开,Toggle 实际上会将其 关闭。虽然所描述的解决方案是我使用过的唯一有效的方法,但这是框架中的一个 bug 吗?更好的解决方案或说明将不胜感激。 - Nilzor
@Nilzor,我知道你的评论有点旧了,但最近我也遇到了相同的问题,并找到了这个错误报告https://code.google.com/p/android/issues/detail?id=25812。可能是相关的,尽管我还没有从Android团队那里得到太多回应,所以不确定它是否优先考虑。 - MikeIsrael
@Nilzor - 我尝试了你的代码,对我来说,当我第一次打开片段时它不起作用,但第二次就可以了。有什么提示吗?谢谢! - Patric
每次片段进入屏幕时,在Fragment.onCreateView上确认它是否有效。谢谢! - baskInEminence

18

你可以尝试这个

@Override
public void onResume() {
    super.onResume();
    edit.post(new Runnable() {
        @Override
        public void run() {
            edit.requestFocus();
            InputMethodManager imgr = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
            imgr.showSoftInput(edit, InputMethodManager.SHOW_IMPLICIT);
        }
    });
}

这个解决方案对我有用,尽管我不需要做edit.post的事情,我只是直接将你run()中的3行代码添加到resume方法中。 - A.Alqadomi

15

由于使用 showSoftInput 并不能解决所有情况,经过尝试这里提到的一些解决方案:

if (binding.account.requestFocus()) {
  requireActivity().getWindow()
      .setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
}

最终我使用了以下方法使其工作:

if (binding.account.requestFocus()) {
  ((InputMethodManager) requireActivity().getSystemService(Context.INPUT_METHOD_SERVICE)).toggleSoftInput(
      InputMethodManager.SHOW_FORCED,
      InputMethodManager.HIDE_IMPLICIT_ONLY
  );
}

自从:

 binding.account.requestFocus()

仅请求EditText的焦点(不打开键盘)

((InputMethodManager) requireActivity().getSystemService(Context.INPUT_METHOD_SERVICE)).toggleSoftInput(
      InputMethodManager.SHOW_FORCED,
      InputMethodManager.HIDE_IMPLICIT_ONLY
  );

这似乎是唯一一个能正确显示键盘的解决方案(也是得票最高的方案)

祝好运!:-)


1
这个可以工作,它打开了键盘。但是当我关闭我的DialogFragment时,如何关闭键盘呢? - Drunken Daddy
现在我无法给你答案,因为代码在另一个项目中。但我相信你会在StackOverflow上找到一些有用的东西 :-) - cesards

11

我有一个有用的扩展可以帮助你:

fun EditText.showKeyboard() {
    if (requestFocus()) {
        (getActivity()?.getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager)
            .showSoftInput(this, SHOW_IMPLICIT)
        setSelection(text.length)
    }
}

你还需要这个:

fun View.getActivity(): AppCompatActivity?{
    var context = this.context
    while (context is ContextWrapper) {
        if (context is AppCompatActivity) {
            return context
        }
        context = context.baseContext
    }
    return null
}

哦,爱上 Kotlin 扩展! :) - Serg Burlaka

5

在尝试了这里和其他相关问题的所有解决方案之后,以下是对我有效的方法:

editText.postDelayed(Runnable { showKeyboard(activity, editText)} , 50)


fun showKeyboard(activity: Activity, editText: EditText) {
    val inputMethodManager = activity.getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager
    editText.requestFocus()
    inputMethodManager.showSoftInput(this, 0)
}

有趣的是,如果你没有使用postDelayed进行调用,它是不会起作用的,即使你只延迟了1毫秒,它仍然无法工作:D
你还可以像这样将其用作扩展:
fun EditText.showKeyboard(activity: Activity) {
    val inputMethodManager = activity.getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager
    requestFocus()
    inputMethodManager.showSoftInput(this, 0)
}

如果你不喜欢将活动(activity)作为参数传递,你可以使用@Rafols建议的这个扩展函数:

fun View.getActivity(): AppCompatActivity? {
    var context = this.context
    while (context is ContextWrapper) {
        if (context is AppCompatActivity) {
            return context
        }
        context = context.baseContext
    }
    return null
}

接着,您的方法会变成这样:

fun EditText.showKeyboard() {
    val inputMethodManager = getActivity()!!.getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager
    requestFocus()
    inputMethodManager.showSoftInput(this, 0)
}

此外,如果您的EditText中已经有文本,最好将光标设置在现有文本的末尾:
fun EditText.showKeyboard() {
    val inputMethodManager = getActivity()!!.getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager
    requestFocus()
    inputMethodManager.showSoftInput(this, 0)
    setSelection(length())
}

如果您希望在片段启动时启动它:

override fun onResume() {
    super.onResume()
    editText.postDelayed(Runnable { editText.showKeyboard()} , 50)
}

4
    @Override
public void onHiddenChanged (boolean hidden)
{
    super.onHiddenChanged(hidden);

    if(hidden)
    {
        hideKeyboard(yourView);
    }
    else
    {
        toggleKeyboard(yourView);
    }
}

    public static void toggleKeyboard(View v)
{
    InputMethodManager imm = (InputMethodManager) v.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
    v.requestFocus();

    imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, InputMethodManager.HIDE_NOT_ALWAYS);
}

public static void hideKeyboard(View v)
{
    InputMethodManager imm = (InputMethodManager) v.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);

    imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
}

2

EditText.requestFocus() + InputMethodManager.showSoftInput() = 显示 EditText 的输入法

在 Fragment.onViewCreated() 中使用 EditText.performAccessibilityAction(AccessibilityNodeInfo.ACTION_CLICK, null) 代替。

    void maybeShowInputMethod() {
        // use addOnPreDrawListener instead of addOnGlobalLayoutListener
        // because execute sequence: onGlobalLayout-> Restore focus -> onPreDraw
        getView().getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {

            @Override
            public boolean onPreDraw() {
                // TODO Auto-generated method stub
                getView().getViewTreeObserver().removeOnPreDrawListener(this);

                // always requestFocus when fragment enter or show
                getView().requestFocus();
                final View currentFocus = getView().findFocus();
                if ((currentFocus != null) && currentFocus.onCheckIsTextEditor()) {
                    Log.d(TAG, "maybeShowInputMethod:: currentFocus=" + currentFocus);
                    currentFocus.performAccessibilityAction(AccessibilityNodeInfo.ACTION_CLICK, null);
                }
                return true;
            }
        });
    }

或者创建EditText的子类并覆盖 public InputConnection onCreateInputConnection(EditorInfo editorInfo) 方法。
public class ImeAwareEditText extends EditText {
private boolean mHasPendingShowSoftInputRequest;
final Runnable mRunShowSoftInputIfNecessary = () -> showSoftInputIfNecessary();

public ImeAwareEditText(Context context) {
    super(context, null);
}

public ImeAwareEditText(Context context, AttributeSet attrs) {
    super(context, attrs);
}

public ImeAwareEditText(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
}

public ImeAwareEditText(Context context, AttributeSet attrs, int defStyleAttr,
        int defStyleRes) {
    super(context, attrs, defStyleAttr, defStyleRes);
}

/**
 * This method is called back by the system when the system is about to establish a connection
 * to the current input method.
 *
 * <p>This is a good and reliable signal to schedule a pending task to call
                                                                                                                                                                                                                     52,6          Top
 *
 * <p>This is a good and reliable signal to schedule a pending task to call
 * {@link InputMethodManager#showSoftInput(View, int)}.</p>
 *
 * @param editorInfo context about the text input field.
 * @return {@link InputConnection} to be passed to the input method.
 */
@Override
public InputConnection onCreateInputConnection(EditorInfo editorInfo) {
    final InputConnection ic = super.onCreateInputConnection(editorInfo);
    if (mHasPendingShowSoftInputRequest) {
        removeCallbacks(mRunShowSoftInputIfNecessary);
        post(mRunShowSoftInputIfNecessary);
    }
    return ic;
}

private void showSoftInputIfNecessary() {
    if (mHasPendingShowSoftInputRequest) {
        final InputMethodManager imm =
                getContext().getSystemService(InputMethodManager.class);
        imm.showSoftInput(this, 0);
        mHasPendingShowSoftInputRequest = false;
    }
}

public void scheduleShowSoftInput() {
    final InputMethodManager imm = getContext().getSystemService(InputMethodManager.class);
    if (imm.isActive(this)) {
        // This means that ImeAwareEditText is already connected to the IME.
        // InputMethodManager#showSoftInput() is guaranteed to pass client-side focus check.
        mHasPendingShowSoftInputRequest = false;
        removeCallbacks(mRunShowSoftInputIfNecessary);
        imm.showSoftInput(this, 0);
        return;
    }

    // Otherwise, InputMethodManager#showSoftInput() should be deferred after
    // onCreateInputConnection().
    mHasPendingShowSoftInputRequest = true;
}
}

1
现在有新的SDK用于显示和隐藏键盘/系统栏:WindowCompat.getInsetsController 问题的简短原因是:在生命周期方法仍在完成时,您将无法显示键盘。
这里有一个有用的扩展函数,使用最新推荐的SDK来显示系统组件,并使用post { }调用来解决在Fragment启动期间显示键盘的问题:
fun EditText.showKeyboard(activity: Activity) {
    requestFocus()
    post {
        WindowCompat.getInsetsController(activity.window, this).show(WindowInsetsCompat.Type.ime())
    }
}

然后只需要使用yourEditText.showKeyboard(requireActivity())即可解决问题。


1

Kotlin

在Fragment中自动显示/隐藏键盘...

override fun onResume() {
    super.onResume()

    requireView().edit_text_ID.showKeyboard()

    requireView().edit_text_ID.setOnFocusChangeListener { _, hasFocus ->
     if (!hasFocus){
        hideKeyboardFrom(requireContext(), requireView())
     }
    }
}

fun EditText.showKeyboard() {
    if (requestFocus()) {
        (activity?.getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager)
            .showSoftInput(this, SHOW_IMPLICIT)
        setSelection(text.length)
    }
}

fun hideKeyboardFrom(context: Context, view: View) {
    val imm =
        context.getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager
    imm.hideSoftInputFromWindow(view.windowToken, 0)
}

一点信息 在这里

1
以下延迟代码适用于我:
editTextLabel.postDelayed(new Runnable() {
                @Override
                public void run() {
                    InputMethodManager keyboard = (InputMethodManager) activity
                            .getSystemService(Context.INPUT_METHOD_SERVICE);
                    keyboard.showSoftInput(editTextLabel, 0);
                }
            }, 1000);

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