簡體   English   中英

Android:對話框中的 EditText 不會拉起軟鍵盤

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

所以我遇到了一個似乎很常見的問題,即我的對話框中的 EditText 在獲得焦點時沒有顯示。 我已經看到了幾種解決方法,例如在這個線程中這個這個(以及更多),但是我從來沒有看到過關於為什么會發生這種情況的令人滿意的解釋。

我更喜歡讓 android 為 EditTexts 使用它自己的默認行為,而不是構建我自己的,但似乎每個人(在那些線程中)都接受了對話框中 EditTexts 的默認行為是只提供一個光標而沒有鍵盤。 為什么會這樣?

作為記錄,這些解決方法似乎都對我不起作用 - 我能夠來的最接近的是強制鍵盤出現對話框下方(使用 InputMethodManager.toggleSoftKeyboard(*))。 我的特定配置是 API15,EditText 顯示在 AlertDialog 中 ListView 的頁腳中。 EditText android:focusable="true" 已設置,並且 onFocusChangeListener正在接收焦點事件。

編輯:

根據要求,這是我正在使用的特定代碼片段。 我不會打擾整個布局,但在這個特定的應用程序中, EditText 出現以響應按下對話框上的按鈕(類似於動作視圖)。 它包含在默認情況下具有“消失”可見性的 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>

構建它的代碼將相對布局的可見性設置為“可見”(並隱藏其他 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 沒有首先觸發,以及為什么這個好像太普通了!

好了,讀了很多之后,我想通了為什么這是一個問題,我不需要用任何變通辦法。

問題似乎是(至少在我的情況下),由於您輸入文本的位置最初是隱藏的(或嵌套或其他),因此 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,不需要雜亂無章或變通方法。

如果您閱讀 AlertDialog 文檔,您會在那里找到:

AlertDialog類負責根據對話框中的任何視圖是否從View.onCheckIsTextEditor()返回 true 為您自動設置 *WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM* 。 通常,您希望為沒有文本編輯器的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 並且它應該可以工作。

我在自己的應用程序中遇到了同樣的問題。 如果您正在為 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 級別的解決方案......

順便說一句:這個片段並不總是適用於模擬器。 我不知道為什么。

這對我有用。 創建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(); .

上面的代碼很有幫助。 但是您必須在“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;
}

謝謝! 我在警報對話框片段中嵌入的 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;
}

這是一種方法:

    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()方法中創建的對話框,它(似乎)需要返回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);
}

這應該可以解決問題,謝天謝地,它對我有用。 處理這個案子已經有一段時間了。

在對話框中顯示鍵盤的完整代碼:

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

只需添加以下代碼行:

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