Android:Dialog中的EditText不会拉起软键盘

时间:2012-02-01 19:36:49

标签: android dialog android-edittext android-softkeyboard

所以我有一个似乎常见的问题,就是我的对话框中的EditText在获得焦点时不会显示。我见过几种解决方法,例如this threadthis onethis one(还有更多),但我从未见过为什么的令人满意的解释这首先发生了。

我更倾向于让Android使用自己的EditTexts默认行为而不是构建我自己的行为,但似乎每个人(在那些线程中)已经接受了Dialogs中EditTexts的默认行为只是给出一个游标,没有键盘。为什么会这样?

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

修改

根据要求,这是我正在使用的特定代码段。我不打算整个布局,但在这个特定的应用程序中,EditText响应于按下对话框上的按钮而出现(类似于an action view)。它包含在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>

构建它的代码将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."));
                }
            }
        });

使用此配置,当我 first 进入EditText时,onFocusChangedListener会触发,并生成一个总是如下所示的日志:

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

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

那就是说,我想强调的是,尽管我可能能够解决这个问题,但我主要感兴趣找到一个简单的理由为什么< / em> EditText首先没有触发,为什么这似乎是如此普遍!

11 个答案:

答案 0 :(得分:166)

好的,所以在阅读了很多之后,我已经弄明白为什么这是一个问题,而我需要使用任何解决方法。

问题似乎是(至少在我的情况下),因为你输入文本的地方最初是隐藏的(或嵌套的东西),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,没有必要的kludges或变通办法。

答案 1 :(得分:17)

我在自己的应用中遇到同样的问题。如果您正在开发API级别&gt; = 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级别的解决方案......

BTW:此代码段并不总是在模拟器上运行。我不知道为什么。

答案 2 :(得分:14)

如果您阅读了AlertDialog文档,您可以在那里找到:

  

AlertDialog 类根据对话框中的任何视图是否从 View.onCheckIsTextEditor()返回true来自动设置* WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM * 。通常,您希望将此集设置为没有文本编辑器的对话框,以便将其置于当前输入法UI的顶部。您可以在调用 onCreate 后强制将标志置于所需模式,从而修改此行为。

我遇到了你在Dialog里面的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,它应该可以工作。

答案 3 :(得分:7)

上面的代码非常有用。但是你必须在“创建”方法之后调用“show”方法(我不知道为什么,但只有这个在我与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;
}

答案 4 :(得分: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;
}

答案 5 :(得分:5)

这对我有用。创建AlertDialog.Builder,设置title,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();

答案 6 :(得分:3)

以下是一种方法:

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

答案 7 :(得分:1)

我想添加到Paul's answerAlexander's comment

我自己有一个在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);
}

这应该可以解决问题,谢天谢地,它对我有用。已经有很长一段时间了。

答案 8 :(得分: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;
        }
    }
}

答案 9 :(得分: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);
}
});

答案 10 :(得分:0)

只需在codeLine下面添加

//在对话框中显示editText时自动显示键盘 dialog.getWindow()。setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);