webentwicklung-frage-antwort-db.com.de

Android: EditText im Dialog ruft die Tastatur nicht auf

Es scheint also ein häufiges Problem zu sein, nämlich dass der EditText in meinem Dialogfeld nicht angezeigt wird, wenn er den Fokus erhält. Ich habe verschiedene Problemumgehungen gesehen, z. B. in dieser Thread , dieser und dieser (und viele weitere), aber ich habe sie noch nie gesehen eine befriedigende Erklärung für , warum dies überhaupt geschieht.

Ich würde Android lieber dazu bringen, sein eigenes Standardverhalten für EditTexts zu verwenden, 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 - das Nächste, was ich tun konnte, ist das Erzwingen, dass eine Tastatur unter dem Dialogfeld angezeigt wird (mithilfe von InputMethodManager). toggleSoftKeyboard (*)). Meine spezielle Konfiguration ist API15, der EditText wird in einer Fußzeile einer ListView in einem AlertDialog angezeigt. Der EditText Android: focusable = "true" ist gesetzt und onFocusChangeListener empfängt Fokusereignisse.

Bearbeiten:

Wie angefordert, ist hier das spezifische Codefragment, 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 wie eine 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 relativeLayouts auf "Visible" (und blendet die anderen UI-Elemente aus). 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."));
                }
            }
        });

Bei Verwendung dieser Konfiguration wird, wenn ich zum ersten Mal den EditText eingebe, der onFocusChangedListener ausgelöst und ein Protokoll generiert, das ausnahmslos 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 umgeschaltet habe. Aber selbst wenn ich sicher gehe, dass sie geöffnet 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 in erster Linie daran interessiert bin , einen einfachen Grund zu finden warum der EditText überhaupt nicht ausgelöst wird und warum dies so alltäglich erscheint!

76
Paul

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

Das Problem scheint zu sein (zumindest in meinem Fall), dass AlertDialog automatisch das Flag WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM (oder eine Kombination davon und WindowManager) setzt, da der Ort, an dem Sie Text eingeben, anfangs ausgeblendet ist (oder verschachtelt ist) .LayoutParams.FLAG_NOT_FOCUSABLE), damit keine weichen Eingaben ausgelöst werden.

Ich habe das Problem behoben, indem Sie nach dem Erstellen des Dialogs folgende Zeile hinzufügen:

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

Sobald dies geschehen ist, verhält sich der EditText wie ein normaler EditText, es sind keine Kludges oder Workarounds erforderlich.

159
Paul

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-Levels gefunden ...

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

17
Gian U.

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 true von View.onCheckIsTextEditor () zurückgeben. Normalerweise möchten Sie dieses Set für einen Dialog ohne Texteditor, damit es auf der aktuellen Eingabemethoden-Benutzeroberfläche platziert wird. Sie können dieses Verhalten ändern, indem Sie das Flag nach dem Aufruf von onCreate in den gewünschten Modus setzen. 

Ich hatte das Problem, das Sie in ListView in einem Dialog mit EditText erwähnt haben. Ich habe es behoben, indem ich die benutzerdefinierte Ansichtsklasse (in meinem Fall ListView) mit meiner eigenen FocusableListView überschrieb, 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.

13
philips77

Vielen Dank! Ich habe ein eingebettetes TextEdit in der letzten Zeile von ListView, das im Alert-Dialogfragment eingebettet ist. Ich habe Ihre Lösung zum Löschen der Flaggen als Nachlauf verwendet und funktioniert jetzt 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;
}
7
farid_z

Der obige Code ist sehr hilfreich. Sie müssen jedoch die "show" -Methode nach der "create" -Methode aufrufen (ich weiß nicht warum, aber dies funktioniert nur 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;
}
7
iLya2IK

Das hat bei mir funktioniert. Erstellen Sie den AlertDialog.Builder, setzen Sie Titel, positiveButton, negativeButton. Danach mache das: 

    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 builder.show(); nicht verwenden.

5

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

Ich möchte auf Pauls Antwort und Alexanders Kommentar eingehen.

Ich selbst habe einen Dialog, der in der onCreateDialog()-Methode erstellt wurde, der (scheinbar) die Rückgabe von dialog.show(); erfordert, weshalb Sie die Layout-Parameter nicht dem Dialog hinzufügen können, in dem der Dialog erstellt wird. Um dies zu umgehen, belassen Sie einfach Ihre onCreateDialog()-Methode und fügen 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);
}

Das sollte den Trick tun, es funktioniert bei mir zum Glück. Ich war schon einige Zeit in diesem Fall.

1
Timmiej93

vollständiger Code zum Anzeigen der Tastatur im Dialog: 

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