Android:对话框中的EditText不能拉起软键盘
所以我得到了什么似乎是一个常见的问题,这是我的对话框中的EditText不会显示时,它得到的焦点。 我已经看到了几个解决方法,比如在这个线程中 , 这个和这个 (还有更多),但是我从来没有看到一个令人满意的解释, 为什么这首先发生。
我更喜欢让android自己使用EditTexts的默认行为,而不是构build我自己的,但似乎每个人(在这些线程中)已经接受了对话框中的EditTexts的默认行为是只给一个游标,没有键盘。 为什么会这样?
对于logging,这些解决方法似乎没有任何工作对我来说 – 最近我已经能够迫使键盘出现在对话框下面 (使用InputMethodManager.toggleSoftKeyboard(*))。 我的特定configuration是API15,EditText显示在AlertDialog中的ListView的页脚上。 EditText android:focusable =“true”已设置,onFocusChangeListener 正在接收焦点事件。
编辑:
根据要求,这里是我正在使用的特定的代码片段。 我不打扰整个布局,但在这个特定的应用程序中,EditText出现在响应按下对话框上的button(类似于一个动作视图 )。 它包含在一个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>
构build它的代码将relativeLayout的可见性设置为“可见”(并隐藏了其他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.")); } } });
使用这个configuration,当我第一次inputEditText时,onFocusChangedListener会触发,并生成一个总是如下所示的日志:
Focus requested, has focus. Focus requested, doesn't have focus. Focus requested, has focus.
键盘出现,然后消失,可能是因为我切换了两次,但即使当我确保它保持在对话框窗口的后面 (在灰色的区域),并且没有办法得到它,没有closures对话框。
这就是说,我想强调的是,即使我可能能够得到这个解决方法,我主要是find一个简单的原因, 为什么 EditText不是首先触发,为什么这似乎是如此平常!
好的,所以在阅读了很多内容之后,我已经知道为什么这是一个问题,我不需要使用任何解决方法。
这个问题似乎是(至less在我的情况下),因为你input文本的地方最初是隐藏的(或嵌套或某事),AlertDialog自动设置标志WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM(或某种组合的WindowManager .LayoutParams.FLAG_NOT_FOCUSABLE)这样的东西不会触发一个软input来显示。
我发现解决这个问题的方法是在创build对话框后添加下面一行:
dialog.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
一旦完成,EditText的行为就像一个正常的EditText,没有必要的解决方法或解决方法。
我在自己的应用程序中有同样的问题。 如果您正在开发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); } });
我还没有find一个较低的API级别的解决scheme…
顺便说一句:这段代码并不总是在模拟器上工作。 我不知道为什么。
如果您阅读AlertDialog文档,您可以在其中find:
AlertDialog类负责根据对话框中的任何视图是否从View.onCheckIsTextEditor()返回true来自动设置* WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM *。 一般而言,您需要将此设置设置为不带文本编辑器的对话框 ,以便将其放置在当前input法UI的顶部。 调用onCreate之后,可以通过将标志强制为所需的模式来修改此行为。
我遇到了在ListView中使用EditText在Dialog中提到的问题。 我通过用自己的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,它应该工作。
上面的代码是非常有用的。 但是你必须在“create”方法之后调用“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; }
谢谢! 在警报对话框片段中embedded的ListView的最后一行中embedded了TextEdit。 我用你的解决scheme清除标志作为后可运行,现在它完美的作品。
@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; }
以下是一种方法:
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);
我想补充保罗的答复和亚历山大的评论 。
我自己有一个在onCreateDialog()
方法中创build的对话框,似乎需要返回dialog.show();
因此,您不能将layoutparams添加到创build对话框的对话框中。 要解决这个问题,只要保持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); }
这应该做的伎俩,谢天谢地对我有用。 这个案子已经有一段时间了。
这是为我工作。 创buildAlertDialog.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();
。
在对话框中显示键盘的完整代码:
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); } });