web-dev-qa-db-ja.com

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

だから、よくある問題と思われるものがあります。つまり、ダイアログボックスのEditTextがフォーカスを取得しても表示されないということです。 this threadthis one 、および this one (など)など、いくつかの回避策を見てきましたが、見たことがないwhyの満足のいく説明は、そもそも起こっています。

私はAndroid私自身を構築するよりもEditTextsに独自のデフォルトの動作を使用することを望んでいますが、ダイアログ内のEditTextsのデフォルトの動作はカーソルだけを与え、キーボードを与えません。なぜでしょうか?

記録のために、これらの回避策はどれも私にとってうまく機能していないようです-最も近いのは、キーボードを強制的に表示することですダイアログボックス(InputMethodManager.toggleSoftKeyboard(*)を使用) 。私の特定の構成はAPI15で、EditTextはAlertDialog内のListViewのフッターに表示されます。 EditText Android:focusable = "true"が設定され、onFocusChangeListener isフォーカスイベントを受信します。

編集:

要求されたように、ここに私が取り組んでいる特定のコードスニペットがあります。レイアウト全体に煩わされることはありませんが、この特定のアプリケーションでは、ダイアログ上のボタンを押すと、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要素を非表示にします)。このshouldは、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."));
                }
            }
        });

この構成を使用して、I first EditTextを入力すると、onFocusChangedListenerがトリガーされ、常に次のようなログが生成されます。

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

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

そうは言っても、この回避策を機能させることはできるかもしれませんが、単純な理由を見つけるのに主に興味があるですwhy EditTextはそもそもトリガーされておらず、なぜこれが非常にありふれているように見えるのでしょう!

78
Paul

OK、それでたくさん読んだ後、なぜこれが問題なのかを理解しました。そして、私はnot回避策を使用する必要があります。

問題は(少なくとも私の場合)、テキストを入力する場所が最初は隠されている(またはネストされているか何か)ため、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のように機能し、手間や回避策は必要ありません。

171
Paul

自分のアプリにも同じ問題があります。 8以上のAPIレベルで開発している場合は、次のスニペットを使用できます。

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
Gian U.

AlertDialogのドキュメントを読むと、そこにあります:

AlertDialogクラスは、ダイアログ内のビューがView.onCheckIsTextEditor()からtrueを返すかどうかに基づいて、自動的に* WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM *を設定します。通常、このセットは、テキストエディタのないDialogに設定して、現在のインプットメソッドUIの上に配置されるようにします。 onCreateを呼び出した後、フラグを目的のモードに強制することで、この動作を変更できます。

Dialog内の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を同じ方法で上書きすることができ、それが機能するはずです。

16
philips77

ありがとうございました!アラートダイアログフラグメントに埋め込まれた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;
}
7
farid_z

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

これは私のために働いたものです。 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();を使用する必要はありません。

5

これを行う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);
3

ポールの答えアレクサンダーのコメント に追加したいと思います。

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

これでうまくいくはずです。ありがたいことに、うまくいきます。かなり長い間、このケースについていました。

1
Timmiej93

ダイアログにキーボードを表示するための完全なコード:

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;
        }
    }
}
0
angelsmiling
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
Manish Sain