Android:对话框中的EditText不会弹出软键盘


82

因此,我遇到了一个常见问题,那就是对话框中的EditText在获得焦点时没有显示。我已经看到了几种变通方法,例如在该线程这个这个(以及更多)中,但是我从来没有见过令人满意的解释,为什么会首先发生这种情况。

我更希望让android使用自己的默认行为来编辑文本而不是构建自己的默认行为,但是似乎每个人(在那些线程中)都已经接受了Dialogs中的EditTexts的默认行为是仅提供光标而没有键盘。为什么会这样呢?

记录下来,这些变通办法似乎都不对我有用-我能够获得的最接近的结果是强制键盘出现对话框下面(使用InputMethodManager.toggleSoftKeyboard(*))。我的特定配置是API15,EditText显示在AlertDialog中ListView的页脚中。设置了EditText android:focusable =“ true”,并且onFocusChangeListener正在接收焦点事件。

编辑:

根据要求,这是我正在使用的特定代码段。我不会打扰整个布局,但是在这个特定的应用程序中,EditText的出现是响应按下对话框上的按钮(类似于动作视图)。它包含在RelativeLayout中,默认情况下其可见性为“ gone”:

 <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>

生成此代码的代码将relativeLayout的可见性设置为“ Visible”(并隐藏其他UI元素)。这应该是足够的,当得到的EditText重点,根据我的EditText经验拉起键盘。但是,由于某些原因,情况并非如此。我可以设置以下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."));
                }
            }
        });

使用此配置,当我第一次输入EditText时,onFocusChangedListener会触发,并生成一个始终如下所示的日志:

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

键盘先出现然后消失,这可能是因为我两次将其切换了,但是即使我确定它保持不动,它也位于对话框窗口的后面(在灰色区域中),并且没有关闭对话框就无法进入它的方法。 。

就是说,我想强调一点,即使我可以使该变通办法起作用,但我主要是想寻找一个简单的原因,即为什么首先不会触发EditText,以及为什么这似乎很平常!


您介意发布相关的代码片段(在其中设置焦点,添加焦点侦听器等)吗?
亚历山大·卢卡斯

我可以(当我回到计算机时也可以),但是我认为我的更广泛的问题不涉及焦点监听器。我想知道为什么在对话框中编辑文本无法打开键盘似乎是一个常见问题。虽然我很乐意使用kluge,但我想知道为什么这样的事情是必要的。
保罗

Answers:


188

好了,读了很多之后,我已经想通了,为什么这是一个问题,我也没有需要使用任何变通办法。

问题似乎是(至少在我看来是这样),因为最初输入文本的位置是隐藏的(或嵌套的),所以AlertDialog自动设置了标志WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM(或该标志和WindowManager的某种组合) .LayoutParams.FLAG_NOT_FOCUSABLE),这样事情就不会触发显示软输入。

我发现解决此问题的方法是在创建对话框后添加以下行:

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

完成此操作后,EditText的行为就像普通的EditText一样,不需要任何麻烦或解决方法。


83
当我尝试在创建后清除标志时,它不起作用。只有当我这样使用它时,它才起作用:Dialog = builder.create(); Dialog.show(); Dialog.getWindow()。clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM); Dialog.getWindow()。setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
Alex Fragotsis

1
在尝试了许多关于stackoverflow的不同解决方案后,@ AlexanderFragotsis,您的评论是唯一可行的!谢谢!
2013年

20
SOFT_INPUT_STATE_‌VISIBLE对我不起作用。我使用了SOFT_INPUT_STATE_ALWAYS_VISIBLE,然后它起作用了。如果有人
遇到

是的,我也无法使SOFT_INPUT_STATE_VISIBLE正常工作,但_ALWAYS_VISIBLE正常工作。有人知道那里发生了什么吗?
bwoogie

非常重要的做clearFlags()show(),由于@AlexanderFragotsis
哈维尔·门多萨

17

我在自己的应用中遇到了同样的问题。如果您正在开发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);
    }
});

我还没有找到降低API级别的解决方案...

顺便说一句:此代码段并不总是在模拟器上起作用。我不知道为什么


2
我对这种特定的解决方法并不太感兴趣,而对为什么它首先不起作用很感兴趣。另外,我实际上不希望键盘与对话框一起显示,而是希望它在EditText获得焦点时显示,例如普通EditText的行为。
保罗

1
这对我有用。只需使用AlertDialog dialog = builder.create();前,dialog.show();上述如果你使用AlertDialog.Builder后
马特·康诺利

1
这是唯一为我工作的人。我也不认为这是一种解决方法,当您阅读下面的答案(引用Android文档中关于为什么直到对话框真正显示之前无法请求焦点)的答案时,它才有意义。
米克·伯恩

17

如果您阅读AlertDialog文档,则会在这里找到:

AlertDialog类需要自动设置护理* WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM *您根据是否在对话框返回从真有什么看法View.onCheckIsTextEditor() 。通常,您希望此设置用于没有文本编辑器的Dialog,以便将其放置在当前输入法UI的顶部。您可以在调用onCreate之后通过将标志强制为所需的模式来修改此行为。

我遇到了对话框中ListView中EditText提到的问题。我通过使用自己的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;
    }
}

然后我在布局文件中将其用作:

<?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" />

您可以用相同的方式覆盖RelativeLayout,它应该可以工作。


工作正常,但是Android Studio(版本1.5.1)无法呈现预览布局
Choletski 2015年

9

这对我有用。创建AlertDialog.Builder,设置标题,positiveButton,negativeButton。之后,请执行以下操作:

    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();

您无需使用builder.show();


谢谢安德烈,你是男人。我在这里尝试了很多解决方案。这是唯一正在工作的产品
Productioncoder

8

上面的代码非常有帮助。但是您必须在“创建”方法之后调用“显示”方法(我不知道为什么,但是只有在ListView中带有EditText的对话框中才能使用此方法)。在方法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;
}

该代码实际上有效吗?将a初始化为AlertDialog,但构造函数为生成器。生成器有一个create方法,该方法返回一个对话框,对话框有一个show方法来显示它们。
保罗

@保罗对不起。在构建器创建对话框的过程中,代码确实是错误的。我纠正了。
iLya2IK 2012年

7

谢谢!我在警报对话框片段的Lis​​tView的最后一行中嵌入了TextEdit。我使用了将标志清除为可运行的帖子的解决方案,现在它可以完美运行。

    @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;
}

4

这是一种实现方法:

    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);

2

我想补充一下保罗的回答亚历山大的评论

我自己有一个在onCreateDialog()方法中创建的对话框,(似乎)需要返回dialog.show();,因此您不能将layoutparams添加到创建该对话框的对话框中。要解决此问题,只需保持您的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);
}

这应该可以解决问题,对我有用。在这种情况下已经存在了一段时间。


0

在对话框中显示键盘的完整代码:

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;
        }
    }
}

1
试图解释你的答案。不要只放代码。给出相应代码的具体答案和解释...
Sandip Armal Patil

0
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);
}
});

0

只需在codeLine下面添加:

//在对话框中的editText对话框中显示键盘时自动显示键盘。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.