简体   繁体   English

Android:对话框中的 EditText 不会拉起软键盘

[英]Android: EditText in Dialog doesn't pull up soft keyboard

So I've got what seems to be a common problem, which is that the EditText in my dialog box doesn't show up when it gets focus.所以我遇到了一个似乎很常见的问题,即我的对话框中的 EditText 在获得焦点时没有显示。 I've seen several workarounds, such as in this thread , this one and this one (and many more), but I have never seen a satisfactory explanation for why this is happening in the first place.我已经看到了几种解决方法,例如在这个线程中这个这个(以及更多),但是我从来没有看到过关于为什么会发生这种情况的令人满意的解释。

I would much prefer to have android use its own default behavior for EditTexts than to build my own, but it seems like everyone (in those threads) has accepted that the default behavior for EditTexts in Dialogs is to just give a cursor and no keyboard.我更喜欢让 android 为 EditTexts 使用它自己的默认行为,而不是构建我自己的,但似乎每个人(在那些线程中)都接受了对话框中 EditTexts 的默认行为是只提供一个光标而没有键盘。 Why would that be?为什么会这样?

For the record, none of these workarounds seem to be working for me - the closest I've been able to come is forcing a keyboard to appear underneath the dialog box (using InputMethodManager.toggleSoftKeyboard(*)).作为记录,这些解决方法似乎都对我不起作用 - 我能够来的最接近的是强制键盘出现对话框下方(使用 InputMethodManager.toggleSoftKeyboard(*))。 My particular configuration is API15, the EditText shows up in a footer on a ListView within an AlertDialog.我的特定配置是 API15,EditText 显示在 AlertDialog 中 ListView 的页脚中。 The EditText android:focusable="true" is set, and onFocusChangeListener is receiving focus events. EditText android:focusable="true" 已设置,并且 onFocusChangeListener正在接收焦点事件。

Edit:编辑:

As requested, here is the specific code snippet that I'm working with.根据要求,这是我正在使用的特定代码片段。 I won't bother with the whole layout, but in this specific application, the EditText appears in response to pressing a button on the dialog (similar to an action view ).我不会打扰整个布局,但在这个特定的应用程序中, EditText 出现以响应按下对话框上的按钮(类似于动作视图)。 It is contained in a RelativeLayout which by default has visibility "gone":它包含在默认情况下具有“消失”可见性的 RelativeLayout 中:

 <RelativeLayout 
       android:id="@+id/relLay"
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:layout_centerVertical="true"
       android:visibility="gone"
       android:layout_marginTop="5dp"
       android:layout_marginBottom="5dp">

        <ImageButton
            android:id="@+id/cancelBut"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:background="@color/transparent"
            android:src="@drawable/cancelButton" 
            android:layout_margin="5dp"/>

        <ImageButton
            android:id="@+id/okBut"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_toLeftOf="@id/cancelBut"
            android:background="@color/transparent"
            android:src="@drawable/okButton"
            android:layout_margin="5dp" />

        <EditText 
            android:id="@+id/editText"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:inputType="text"
            android:focusable="true"
            android:layout_toLeftOf="@id/okBut"/>
   </RelativeLayout>

The code which builds this sets the visibility of the relativeLayout to "Visible" (and hides the other UI elements).构建它的代码将相对布局的可见性设置为“可见”(并隐藏其他 UI 元素)。 This should be enough to pull up the keyboard when the EditText gets focused, based on my experience with EditText.根据我使用 EditText 的经验,这应该足以在 EditText 获得焦点时拉起键盘。 However, for some reason this is not the case.然而,由于某种原因,情况并非如此。 I can set the following onFocusChangeListener:我可以设置以下 onFocusChangeListener:

    edit_text.setOnFocusChangeListener(new OnFocusChangeListener() {

            @Override
            public void onFocusChange(View v, boolean hasFocus) {
                // For whatever reason we need to request a soft keyboard.
                    InputMethodManager imm = (InputMethodManager)dlg.getWindow().getContext().getSystemService(_Context.INPUT_METHOD_SERVICE);
                    if(hasFocus)
                        imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
                    Log.v("DialogProblem", "Focus requested, " + (hasFocus?"has focus.":"doesn't have focus."));
                }
            }
        });

Using this configuration, when I first enter the EditText, the onFocusChangedListener triggers, and generates a log that invariably looks like this:使用此配置,当我第一次进入 EditText 时,onFocusChangedListener 会触发,并生成一个始终如下所示的日志:

Focus requested, has focus.
Focus requested, doesn't have focus.
Focus requested, has focus.

The keyboard shows up and then disappears, probably because I toggle it twice, but even when I make sure it stays up, it's behind the dialog window (in a greyed out area), and there's no way to get to it without closing the dialog.键盘出现然后消失,可能是因为我切换了两次,但即使我确保它保持打开状态,它也位于对话框窗口后面(在灰色区域),并且不关闭对话框就无法访问它.

That said, I'd like to emphasize that even though I may be able to get this work-around to work, I'm primarily interested in finding a simple reason why the EditText isn't triggering in the first place, and why this seems to be so commonplace!也就是说,我想强调的是,即使我可以让这个变通办法起作用,我主要感兴趣的是找到一个简单的原因,为什么EditText 没有首先触发,以及为什么这个好像太普通了!

OK, so after reading a lot, I have figured out why this is a problem, and I do not need to use any workarounds.好了,读了很多之后,我想通了为什么这是一个问题,我不需要用任何变通办法。

The problem seems to be (at least in my case), that since the place where you enter text is hidden initially (or nested or something), AlertDialog is automatically setting the flag WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM (or some combination of that and WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) so that things don't trigger a soft input to show up.问题似乎是(至少在我的情况下),由于您输入文本的位置最初是隐藏的(或嵌套或其他),因此 AlertDialog 会自动设置标志 WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM (或该标志和 WindowManager 的某种组合) .LayoutParams.FLAG_NOT_FOCUSABLE),这样事情就不会触发软输入显示。

The way that I've found to fix this is to add the following line after the dialog has been created:我发现解决此问题的方法是在创建对话框后添加以下行:

dialog.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);

Once this is done, the EditText acts like a normal EditText, no kludges or workarounds necessary.一旦完成,EditText 就像一个普通的 EditText,不需要杂乱无章或变通方法。

If you read the AlertDialog documentation you'll find there:如果您阅读 AlertDialog 文档,您会在那里找到:

The AlertDialog class takes care of automatically setting *WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM* for you based on whether any views in the dialog return true from View.onCheckIsTextEditor() . AlertDialog类负责根据对话框中的任何视图是否从View.onCheckIsTextEditor()返回 true 为您自动设置 *WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM* 。 Generally you want this set for a Dialog without text editors, so that it will be placed on top of the current input method UI.通常,您希望为没有文本编辑器的Dialog设置此设置,以便将其放置在当前输入法 UI 的顶部。 You can modify this behavior by forcing the flag to your desired mode after calling onCreate .您可以通过在调用onCreate后将标志强制为所需模式来修改此行为。

I had the problem you've mentioned with EditText in ListView inside a Dialog.我遇到了您在对话框内的 ListView 中的 EditText 中提到的问题。 I fixed it by overwriting the custom view class (in my case ListView) with my own FocusableListView, with just one method overwritten:我通过用我自己的 FocusableListView 覆盖自定义视图类(在我的例子中为 ListView)来修复它,只覆盖了一个方法:

public class FocusableListView extends ListView {

    public FocusableListView(Context context) {
        super(context);
    }

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

    public FocusableListView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    public boolean onCheckIsTextEditor() {
        // this is where the magic happens
        return true;
    }
}

Then I'm using it in the layout file as:然后我在布局文件中使用它:

<?xml version="1.0" encoding="UTF-8"?>
<com.myexample.wiget.FocusableListView 
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:descendantFocusability="beforeDescendants"
android:layout_height="wrap_content" />

You can overwrite the RelativeLayout in your case the same way and it should work.您可以在您的情况下以相同的方式覆盖 RelativeLayout 并且它应该可以工作。

I have the same problem in my own app.我在自己的应用程序中遇到了同样的问题。 If you are developing for API level >= 8 you can use this snippet:如果您正在为 API 级别 >= 8 进行开发,则可以使用以下代码段:

dialog.setOnShowListener(new OnShowListener() {
    @Override
     public void onShow(DialogInterface dialog) {
         InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
         imm.showSoftInput(textEdit, InputMethodManager.SHOW_IMPLICIT);
    }
});

I haven't found a solution for lower API levels...我还没有找到较低 API 级别的解决方案......

BTW: This snippet doesn't always work on emulator.顺便说一句:这个片段并不总是适用于模拟器。 I don't know why.我不知道为什么。

This is what worked for me.这对我有用。 Create the AlertDialog.Builder, set title, positiveButton, negativeButton.创建AlertDialog.Builder,设置title、positiveButton、negativeButton。 After do this:执行此操作后:

    AlertDialog dialog = builder.create();
    dialog.getWindow().clearFlags( WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
    dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
    dialog.show();
    editText.requestFocus();

You don't need to use builder.show();你不需要使用builder.show(); . .

The code above is very helpfull.上面的代码很有帮助。 But you must call the "show" method after the "create" method (I don't know why, but only this works in my dialog with EditText in ListView).但是您必须在“create”方法之后调用“show”方法(我不知道为什么,但只有这在我的 ListView 中的 EditText 对话框中才有效)。 In method onCreateDialog:在方法 onCreateDialog 中:

@Override
protected Dialog onCreateDialog(int id) {
  switch (id) {
    case YOUR_DIALOG_ID: {
        //...
        AlertDialog a = new AlertDialog.Builder(this)./*
        ... set the properties here
        */
        .create();
        a.show(); //!!! this is very important to call the "show" method
        a.getWindow().clearFlags(
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
        return a;
    }
  //...
  }
  return null;
}

Thank you!谢谢! I have an embedded TextEdit in the last row of ListView embedded in the alert dialog fragment.我在警报对话框片段中嵌入的 ListView 的最后一行中有一个嵌入的 TextEdit。 I used your solution of clearing the flags as a post runnable and now it works perfectly.我使用您清除标志的解决方案作为可运行的后处理,现在它可以完美运行。

    @Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
    builder.setTitle("My Title");
    m_adapter = new MyAdapter(getContext());
    builder.setAdapter(m_adapter, new OnClickListener() {

        @Override
        public void onClick(DialogInterface dialog, int which) {
            // TODO Auto-generated method stub

        }
    }); 

    final AlertDialog dialog = builder.create();
    final ListView listView = dialog.getListView();
    listView.setOnItemClickListener(new OnItemClickListener() {

        @Override
        public void onItemClick(AdapterView<?> parent, View view,
                int position, long id) {

        }
    });

    listView.post(new Runnable() {

        @Override
        public void run() {
            dialog.getWindow().clearFlags(
                    WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
                    WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);              
        }
    });
    return dialog;
}

Here's one way to do it:这是一种方法:

    final Window dialogWindow = dialog.getWindow();
    dialogWindow.clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
    dialogWindow.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);

I would like to add on to Paul's answer and Alexander's comment .我想补充保罗的回答亚历山大的评论

I myself have a dialog that's created in the onCreateDialog() method, which (seems to) require returning dialog.show();我自己有一个在onCreateDialog()方法中创建的对话框,它(似乎)需要返回dialog.show(); , wherefore you can not add the layoutparams to the dialog where the dialog is created. ,因此您不能将 layoutparams 添加到创建对话框的对话框中。 To work around this, just keep your onCreateDialog() method the same, and add an onResume() method as follows:要解决此问题,只需保持您的onCreateDialog()方法相同,并添加一个onResume()方法,如下所示:

@Override
public void onResume() {
    super.onResume();
    Dialog dialog = getDialog();
    dialog.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
    dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
}

This should do the trick, it works for me, thankfully.这应该可以解决问题,谢天谢地,它对我有用。 Have been on this case for quite some while.处理这个案子已经有一段时间了。

full code for showing the keyboard in dialog:在对话框中显示键盘的完整代码:

public void onFocusChange(View v, boolean hasFocus) {
    Log.v("onFocusChange", hasFocus + " " + showkeyboard);
    if (hasFocus) {
        if (showkeyboard++ == 0) {
            alertDialog.getWindow().clearFlags(
                    WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                    | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
            alertDialog.getWindow().setSoftInputMode(
                    WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
        } else {
            showkeyboard = 1;
        }
    }
}
This worked for me ----
editText.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
//dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
//dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
//dialog.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
InputMethodManager mgr = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
mgr.showSoftInput(v, InputMethodManager.SHOW_FORCED);
editText.setFocusable(true);
}
});

just add below codeLine:只需添加以下代码行:

// to show keyboard automatically while editText is in dialog dialog.getWindow().setSoftInputMode (WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE); // 当editText 在对话框中时自动显示键盘 dialog.getWindow().setSoftInputMode (WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM