Android: EditText in Dialog ruft keine Softtastatur auf

82

Ich habe also ein scheinbar häufiges Problem: Der EditText in meinem Dialogfeld wird nicht angezeigt, wenn er fokussiert wird. Ich habe mehrere Problemumgehungen gesehen, wie in diesem Thread , diesem und diesem (und vielen weiteren), aber ich habe nie eine zufriedenstellende Erklärung dafür gesehen, warum dies überhaupt geschieht.

Ich würde es vorziehen, wenn Android sein eigenes Standardverhalten für EditTexts verwendet, als mein eigenes zu erstellen, aber es scheint, dass jeder (in diesen Threads) akzeptiert hat, dass das Standardverhalten für EditTexts in Dialogen darin besteht, nur einen Cursor und keine Tastatur anzugeben. Warum sollte das so sein?

Für die Aufzeichnung scheint keine dieser Problemumgehungen für mich zu funktionieren - die nächste Möglichkeit, die ich erreichen konnte, besteht darin, eine Tastatur unter dem Dialogfeld anzuzeigen (mithilfe von InputMethodManager.toggleSoftKeyboard (*)). Meine spezielle Konfiguration ist API15. Der EditText wird in einer Fußzeile in einer ListView in einem AlertDialog angezeigt. Die EditText Android - Version: fokussierbarem = „true“ gesetzt ist, und onFocusChangeListener wird empfängt Fokus - Ereignisse.

Bearbeiten:

Wie angefordert, ist hier das spezifische Code-Snippet, mit dem ich arbeite. Ich werde mich nicht um das gesamte Layout kümmern, aber in dieser speziellen Anwendung wird der EditText als Reaktion auf das Drücken einer Schaltfläche im Dialogfeld angezeigt (ähnlich einer Aktionsansicht ). Es ist in einem RelativeLayout enthalten, dessen Sichtbarkeit standardmäßig "weg" ist:

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

Der Code, der dies erstellt, setzt die Sichtbarkeit des relativen Layouts auf "Sichtbar" (und verbirgt die anderen UI-Elemente). Dies sollte ausreichen, um die Tastatur hochzuziehen, wenn der EditText fokussiert wird, basierend auf meinen Erfahrungen mit EditText. Aus irgendeinem Grund ist dies jedoch nicht der Fall. Ich kann den folgenden onFocusChangeListener einstellen:

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

Wenn ich in dieser Konfiguration den EditText zum ersten Mal eingebe, wird der onFocusChangedListener ausgelöst und generiert ein Protokoll, das immer so aussieht:

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

Die Tastatur wird angezeigt und verschwindet dann, wahrscheinlich weil ich sie zweimal umschalte. Aber selbst wenn ich sicher bin, dass sie aktiv bleibt, befindet sie sich hinter dem Dialogfenster (in einem ausgegrauten Bereich), und es gibt keine Möglichkeit, dorthin zu gelangen, ohne den Dialog zu schließen .

Trotzdem möchte ich betonen, dass ich, obwohl ich diese Problemumgehung möglicherweise zum Laufen bringen kann, in erster Linie daran interessiert bin , einen einfachen Grund zu finden, warum der EditText überhaupt nicht ausgelöst wird und warum dies so ist scheint so alltäglich zu sein!

Paul
quelle
Würde es Ihnen etwas ausmachen, das entsprechende Code-Snippet zu veröffentlichen (wo Sie den Fokus setzen, einen Fokus-Listener hinzufügen usw.)?
Alexander Lucas
Ich kann (und werde, wenn ich wieder an einen Computer komme), aber ich denke, meine umfassendere Frage betrifft keinen Fokus-Listener. Ich frage mich, warum es ein häufiges Problem zu sein scheint, dass das Bearbeiten von Text in einem Dialogfeld die Tastatur nicht öffnet. Ich würde zwar gerne eine Kluge benutzen, wenn das so ist, aber ich würde gerne wissen, warum so etwas notwendig ist.
Paul

Antworten:

187

OK, nachdem ich viel gelesen habe, habe ich herausgefunden, warum dies ein Problem ist, und ich muss keine Problemumgehungen verwenden.

Das Problem scheint (zumindest in meinem Fall) zu sein, dass AlertDialog das Flag WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM (oder eine Kombination aus diesem und WindowManager) automatisch setzt, da der Ort, an dem Sie Text eingeben, zunächst ausgeblendet ist (oder verschachtelt ist oder so) .LayoutParams.FLAG_NOT_FOCUSABLE), damit keine weiche Eingabe ausgelöst wird.

Um dies zu beheben, füge ich nach dem Erstellen des Dialogfelds die folgende Zeile hinzu:

dialog.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);

Sobald dies erledigt ist, verhält sich der EditText wie ein normaler EditText, ohne dass Kludges oder Problemumgehungen erforderlich sind.

Paul
quelle
83
Als ich versuchte, die Flags nach dem Erstellen zu löschen, funktionierte es nicht. Es hat nur funktioniert, wenn ich es so verwendet habe: 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
1
@AlexanderFragotsis Nachdem Sie so viele verschiedene Lösungen für Stackoverflow ausprobiert haben, ist Ihr Kommentar der einzige, der funktioniert! Danke dir!
Bruce
20
SOFT_INPUT_STATE_‌ VISIBLE hat bei mir nicht funktioniert. Ich habe SOFT_INPUT_STATE_ALWAYS_VISIBLE verwendet und dann hat es funktioniert.
Stellen
Ja, ich konnte SOFT_INPUT_STATE_VISIBLE auch nicht zum Laufen bringen, aber _ALWAYS_VISIBLE funktioniert. Weiß jemand, was dort los ist?
Bwoogie
Sehr wichtig , das zu tun , clearFlags()nachdem show()dank @AlexanderFragotsis
Javier Mendonça
17

Ich habe das gleiche Problem in meiner eigenen App. Wenn Sie für API-Level> = 8 entwickeln, können Sie dieses Snippet verwenden:

dialog.setOnShowListener(new OnShowListener() {
    @Override
     public void onShow(DialogInterface dialog) {
         InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
         imm.showSoftInput(textEdit, InputMethodManager.SHOW_IMPLICIT);
    }
});

Ich habe keine Lösung für niedrigere API-Ebenen gefunden ...

Übrigens: Dieses Snippet funktioniert nicht immer mit dem Emulator. Ich weiß nicht warum.

Gian U.
quelle
2
Ich bin nicht so sehr an dieser speziellen Problemumgehung interessiert, sondern daran, warum sie überhaupt nicht funktioniert. Außerdem möchte ich nicht, dass die Tastatur mit dem Dialogfeld angezeigt wird. Ich möchte, dass sie angezeigt wird, wenn der EditText den Fokus erhält, wie das Verhalten eines normalen EditText.
Paul
1
Das hat bei mir funktioniert. Verwenden Sie einfach AlertDialog dialog = builder.create();vor und dialog.show();nach dem oben genannten, wenn Sie AlertDialog.Builder
Matt Connolly
1
Dies ist der einzige, der für mich gearbeitet hat. Ich denke auch nicht, dass es eine Problemumgehung ist. Es ist sinnvoll, wenn Sie es mit der folgenden Antwort lesen und aus den Android-Dokumenten zitieren, warum Sie keinen Fokus anfordern können, bis der Dialog tatsächlich angezeigt wird.
Mick Byrne
17

Wenn Sie die AlertDialog-Dokumentation lesen, finden Sie dort:

Die AlertDialog- Klasse sorgt dafür, dass * WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM * automatisch für Sie festgelegt wird, je nachdem, ob Ansichten im Dialogfeld von View.onCheckIsTextEditor () true zurückgeben . Im Allgemeinen möchten Sie diesen Satz für einen Dialog ohne Texteditoren, damit er über der aktuellen Benutzeroberfläche der Eingabemethode platziert wird. Sie können dieses Verhalten ändern, indem Sie das Flag nach dem Aufruf von onCreate in den gewünschten Modus versetzen .

Ich hatte das Problem, das Sie mit EditText in ListView in einem Dialog erwähnt haben. Ich habe es behoben, indem ich die benutzerdefinierte Ansichtsklasse (in meinem Fall ListView) mit meiner eigenen FocusableListView überschrieben habe, wobei nur eine Methode überschrieben wurde:

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

Dann verwende ich es in der Layoutdatei als:

<?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" />

Sie können das RelativeLayout in Ihrem Fall auf die gleiche Weise überschreiben, und es sollte funktionieren.

philips77
quelle
funktioniert perfekt, aber Android Studio (Version 1.5.1)
rendert
9

Das hat bei mir funktioniert. Erstellen Sie den AlertDialog.Builder, setzen Sie title, positiveButton, negativeButton. Danach machen Sie Folgendes:

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

Sie müssen nicht verwenden builder.show();.

André Luiz Reis
quelle
Danke André, du bist der Mann. Ich habe hier auf SO so viele Lösungen ausprobiert. Dies ist die einzige, die funktioniert
Produktionscodierer
8

Der obige Code ist sehr hilfreich. Sie müssen jedoch die "show" -Methode nach der "create" -Methode aufrufen (ich weiß nicht warum, aber nur dies funktioniert in meinem Dialog mit EditText in ListView). In der Methode 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;
}
iLya2IK
quelle
Funktioniert dieser Code tatsächlich? a wird als AlertDialog initialisiert, der Konstruktor ist jedoch ein Builder. Builder haben eine Erstellungsmethode, die einen Dialog zurückgibt. Dialoge haben eine Show-Methode, um sie anzuzeigen.
Paul
@ Paul Entschuldigung. Der Code war im Teil einer Dialogerstellung durch einen Builder wirklich falsch. Ich habe es korrigiert.
iLya2IK
7

Danke dir! Ich habe ein eingebettetes TextEdit in der letzten Zeile von ListView, das in das Fragment des Warnungsdialogs eingebettet ist. Ich habe Ihre Lösung zum Löschen der Flags als Post-Runnable verwendet und jetzt funktioniert es perfekt.

    @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;
}
farid_z
quelle
4

Hier ist eine Möglichkeit, dies zu tun:

    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);
Android-Entwickler
quelle
2

Ich möchte die Antwort von Paulus und den Kommentar von Alexander ergänzen .

Ich selbst habe ein Dialogfeld, das in der onCreateDialog()Methode erstellt wurde und das (anscheinend) zurückgegeben werden dialog.show();muss. Daher können Sie die Layoutparameter nicht zu dem Dialogfeld hinzufügen, in dem das Dialogfeld erstellt wird. Um dies zu umgehen, behalten Sie einfach Ihre onCreateDialog()Methode bei und fügen Sie eine onResume()Methode wie folgt hinzu:

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

Dies sollte den Trick tun, es funktioniert für mich zum Glück. Ich bin schon eine ganze Weile in diesem Fall.

Timmiej93
quelle
0

vollständiger Code zum Anzeigen der Tastatur im Dialogfeld:

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;
        }
    }
}
Engelslächeln
quelle
1
versuche deine Antwort zu erklären. Geben Sie nicht nur Code ein. Geben Sie eine spezifische Antwort und Erklärung zum jeweiligen Code ...
Sandip Armal Patil
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);
}
});
Manish Sain
quelle
0

Fügen Sie einfach die folgende CodeLine hinzu:

// um die Tastatur automatisch anzuzeigen, während sich editText im Dialogfeld befindet dialog.getWindow (). setSoftInputMode (WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);

Mosayeb Masoumi
quelle