Android:ダイアログのEditTextがソフトキーボードをプルアップしない


82

そのため、一般的な問題と思われる問題が発生しました。これは、ダイアログボックスの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>

これを構築するコードは、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.

キーボードが表示されてから消えるのは、おそらく2回切り替えたためですが、キーボードが上がったままであることを確認しても、ダイアログウィンドウの後ろ(灰色の領域)にあり、ダイアログを閉じずにキーボードにアクセスする方法はありません。 。

とはいえ、この回避策を機能させることはできるかもしれませんが、EditTextが最初にトリガーされない単純な理由、これがなぜ発生するのかを見つけることに主に関心があることを強調したいと思います。当たり前のようです!


関連するコードスニペット(フォーカスを設定したり、フォーカスリスナーを追加したりする場所)を投稿していただけませんか?
アレクサンダールーカス

私はできます(そして私がコンピューターに戻ったときにそうします)が、私のより広い質問はフォーカスリスナーを含まないと思います。ダイアログのテキストを編集してもキーボードが開かないことが一般的な問題のように思われるのはなぜだろうか。そうすればクルーゲを使ってもいいのですが、なぜそんなことが必要なのか知りたいです。
ポール

回答:


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 2013

1
@AlexanderFragotsisは、stackoverflowで非常に多くの異なるソリューションを試した後、あなたのコメントだけが機能します!ありがとうございました!
ブルース

20
SOFT_INPUT_STATE_‌VISIBLEが機能しませんでした。SOFT_INPUT_STATE_ALWAYS_VISIBLEを使用したところ、機能しました。他の誰かが同じ問題を抱えているなら、それをそこに出すだけです
kb_14 2014

ええ、私はSOFT_INPUT_STATE_VISIBLEも機能させることができませんでしたが、_ALWAYS_VISIBLEは機能します。誰かがそこで何が起こっているのか知っていますか?
bwoogie 2015

行うことは非常に重要なclearFlags()の後にshow()、感謝@AlexanderFragotsis
ハビエルMendonça

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ドキュメントから引用した以下の回答を読んだときに意味があります。
ミック・バーン2014年

17

AlertDialogのドキュメントを読むと、次のことがわかります。

AlertDialogのクラスはからの真の対話の見返りにするかどうかの任意のビューに基づいて自動的に* WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM *設定の世話をする)(View.onCheckIsTextEditor。通常、このセットはテキストエディタのないダイアログに設定して、現在の入力方式のUIの上に配置する必要があります。onCreateを呼び出した後、フラグを目的のモードに強制することで、この動作を変更できます

ダイアログ内のListViewのEditTextでおっしゃった問題がありました。カスタムビュークラス(私の場合はListView)を独自のFocusableListViewで上書きし、1つのメソッドだけを上書きすることで修正しました。

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を作成し、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();


アンドレに感謝します、あなたは男です。私はここSOで非常に多くの解決策を試しました。これは、働いている唯一のものです
productioncoder

8

上記のコードは非常に役立ちます。ただし、「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;
}

そのコードは実際に機能しますか?aはAlertDialogとして初期化されますが、コンストラクターはビルダーです。ビルダーにはダイアログを返すcreateメソッドがあり、ダイアログにはそれらを表示するshowメソッドがあります。
ポール

@ポールすみません。ビルダーによるダイアログ作成の一部で、コードは本当に間違っていました。修正しました。
iLya2IK 2012年

7

ありがとうございました!アラートダイアログフラグメントに埋め込まれたListViewの最後の行に埋め込まれたテキストエディットがあります。フラグをクリアするソリューションをポストランナブルとして使用しましたが、今では完全に機能します。

    @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

これを行う1つの方法は次のとおりです。

    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 2012

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がダイアログにあるときにキーボードを自動的に表示するdialog.getWindow()。setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.