首页 文章

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

提问于
浏览
70

因此,当它获得焦点时,我会显示出来 . 我已经看过几个变通方法,例如this threadthis onethis one(还有更多),但我从来没有见过令人满意的解释,为什么会发生这种情况 .

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

为了记录,这些解决方法似乎都没有对我有用 - 我最接近的是强制键盘出现在对话框下面(使用InputMethodManager.toggleSoftKeyboard(*)) . 我的特殊配置是API15,EditText显示在AlertDialog中ListView的页脚中 . 设置了EditText android:focusable = "true",并且onFocusChangeListener正在接收焦点事件 .

Edit:

根据要求,这里是我对整个布局感到困扰的具体代码片段,但在此特定应用程序中,EditText响应于按下对话框上的按钮而出现(类似于an action view) . 它包含在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没有首先触发,为什么这似乎是如此平常!

10 回答

  • 1

    好的,所以经过阅读后,我已经弄清楚为什么这是一个问题,我不需要使用任何变通方法 .

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

  • 7

    我在自己的应用程序中遇到同样的问题 . 如果您正在为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级别的解决方案......

    顺便说一句:这个代码片段并不总是适用于模拟器 . 我不知道为什么 .

  • 17

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

    AlertDialog类根据对话框中的任何视图是否从View.onCheckIsTextEditor()返回true,自动为您设置* WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM * . 通常,您希望将此集设置为没有文本编辑器的Dialog,以便将其置于当前输入法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,它应该工作 .

  • 0

    上面的代码非常有用 . 但是你必须在“创建”方法之后调用“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;
    }
    
  • 7

    谢谢!我在嵌入警报对话框片段的ListView的最后一行中有一个嵌入的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

    这对我有用 . 创建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(); .

  • 13

    这是一种方法:

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

    我想补充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);
    }
    

    这应该是诀窍,它对我有用,谢天谢地 . 已经有很长一段时间了 .

  • 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;
            }
        }
    }
    
  • 3
    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);
    }
    });
    

相关问题