如何在 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个回答

1
我曾遇到过类似的问题,使用视图动画。所以我添加了一个动画监听器来确保在尝试请求显示的edittext上的键盘访问之前,我会等待动画结束。
    bottomUp.setAnimationListener(new Animation.AnimationListener() {
        @Override
        public void onAnimationStart(Animation animation) {
        }

        @Override
        public void onAnimationEnd(Animation animation) {
            if (textToFocus != null) {
                // Position cursor at the end of the text
                textToFocus.setSelection(textToFocus.getText().length());
                // Show keyboard
                InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
                imm.showSoftInput(textToFocus, InputMethodManager.SHOW_IMPLICIT);
            }
        }

        @Override
        public void onAnimationRepeat(Animation animation) {
        }
    });

1
你可以创建一个扩展EditText的自定义扩展,使其在接收到焦点时打开软键盘。这就是我最终所做的。以下是对我有用的方法:
public class WellBehavedEditText extends EditText {
    private InputMethodManager inputMethodManager;
    private boolean showKeyboard = false;

    public WellBehavedEditText(Context context) {
        super(context);
        this.initializeWellBehavedEditText(context);
    }

    public WellBehavedEditText(Context context, AttributeSet attributes) {
        super(context, attributes);
        this.initializeWellBehavedEditText(context);
    }

    public WellBehavedEditText(Context context, AttributeSet attributes, int defStyleAttr) {
        super(context, attributes, defStyleAttr);
        this.initializeWellBehavedEditText(context);
    }

    public WellBehavedEditText(Context context, AttributeSet attributes, int defStyleAttr, int defStyleRes) {
        super(context, attributes, defStyleAttr, defStyleRes);
        this.initializeWellBehavedEditText(context);
    }

    private void initializeWellBehavedEditText(Context context) {
        this.inputMethodManager = (InputMethodManager)context.getSystemService(Context.INPUT_METHOD_SERVICE);

        final WellBehavedEditText editText = this;
        this.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                if(showKeyboard) {
                    showKeyboard = !(inputMethodManager.showSoftInput(editText, InputMethodManager.SHOW_FORCED));
                }
            }
        });
    }

    @Override
    protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
        if(!focused) this.showKeyboard = false;
        super.onFocusChanged(focused, direction, previouslyFocusedRect);
    }

    @Override
    public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
        boolean result = super.requestFocus(direction, previouslyFocusedRect);
        this.showKeyboard = true;
        final WellBehavedEditText self = this;
        this.post(new Runnable() {
            @Override
            public void run() {
                showKeyboard = !(inputMethodManager.showSoftInput(self, InputMethodManager.SHOW_FORCED));
            }
        });
        return result;
    }
}

哦天啊,终于成功了!addOnGlobalLayoutListener完成了任务!我不必使用丑陋的输入方法。谢谢!虽然日志里还是有一些警告。 - vctls

1
根据此处的回答,我使用了setSoftInputMode方法,并在DialogFragment中重写了这些方法:
@Override
public void onCancel(@NonNull DialogInterface dialog) {
    super.onCancel(dialog);
    requireDialog().getWindow().setSoftInputMode(InputMethodManager.HIDE_IMPLICIT_ONLY);
}

@Override
public void onStart() {
    super.onStart();
    requireDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
}

@Override
public void onStop() {
    super.onStop();
    requireDialog().getWindow().setSoftInputMode(InputMethodManager.HIDE_IMPLICIT_ONLY);
}

我还创建了自己的DialogFragment子类,其中包含这些方法,因此当您创建另一个对话框并从此类继承时,软键盘将自动显示,无需进行任何其他编辑。希望对某些人有用。


0

我做了这个帮助类。 只需传递上下文和要聚焦并显示键盘的视图,然后隐藏键盘。 希望能有所帮助。

public class FocusKeyboardHelper {

private View view;
private Context context;
private InputMethodManager imm;

public FocusKeyboardHelper(Context context, View view){
    this.view = view;
    this.context = context;
    imm = (InputMethodManager) context.getSystemService(context.INPUT_METHOD_SERVICE);
}

public void focusAndShowKeyboard(){

    view.requestFocus();
    imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, InputMethodManager.HIDE_IMPLICIT_ONLY);

}

public void hideKeyBoard(){
    imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}

}


0

view.requestFocus() 可能因为不同的原因而无法工作。因此,键盘将不会显示。

如果视图不可聚焦(isFocusable返回false),或者由于其他条件而无法聚焦(在触摸模式下不可聚焦(isFocusableInTouchMode),而设备处于触摸模式下,不可见,未启用或没有大小),则视图实际上不会获得焦点。

我使用了这个解决方案:

 @Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main_layout);
    EditText searchView = findViewById(R.id.searchView);
    
    new Handler().postDelayed(new Runnable() {
        @Override
        public void run() {
            showSoftKeyboard(searchView);
        }
    }, 300);
}

public void showSoftKeyboard(View view) {
    if (view.requestFocus()) {
        InputMethodManager imm = (InputMethodManager)
                view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.showSoftInput(view, InputMethodManager.SHOW_IMPLICIT);
    }
}

0
 void requestFocus(View editText, Activity activity)
{
    try {
        editText.requestFocus();
        InputMethodManager imm = (InputMethodManager) a.getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.showSoftInput(editText, InputMethodManager.SHOW_IMPLICIT);
        activity.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
    } catch (Exception e) {
        e.printStackTrace();
    }

}

也别忘了添加这一行

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

0

使用 Xamarin,在 Fragment 中,这对我有效:

using Android.Views.InputMethods;
using Android.Content;

...

if ( _txtSearch.RequestFocus() ) {
  var inputManager = (InputMethodManager) Activity.GetSystemService( Context.InputMethodService );
  inputManager.ShowSoftInput( _txtSearch, ShowFlags.Implicit );
}

0

在添加了这些行之后,对我有用。

globalSearchBarMainActivity.setEnabled(true);
globalSearchBarMainActivity.requestFocus();

由于我的自动完成文本视图方法被隐藏了,即 VISIBLE: GONE

因此需要添加上述两行代码

InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.showSoftInput(globalSearchBarMainActivity, InputMethodManager.SHOW_IMPLICIT);

0
这个问题的另一个答案是在 API 级别 30 之后,可以这样做:
 binding.myEditText.windowInsetsController?.show(WindowInsets.Type.ime())

PS:在api 32上,旧的toggleSoftInput调用正常工作,但在api 33上完全不起作用。至少根据我的三星设备是这样的。 这里是源代码(有点) 这个人在提到一个11年前的stackoverflow问题!

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