EditText onClickListener in Android

85

Ich möchte einen EditText, der beim Drücken einen DatePicker erstellt. Also schreibe ich folgenden Code:

    mEditInit = (EditText) findViewById(R.id.date_init);
    mEditInit.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            showDialog(DATEINIT_DIALOG);
        }

    });

Wenn ich jedoch den EditText drücke, ist die Aktion typisch: Ein Cursor, der auf die Eingabe von Text wartet, zeigt stattdessen den gewünschten Dialog an.

xger86x
quelle
Sie sollten einen Drehfeld anstelle eines EditText-Dialogfelds verwenden.
Ryan R

Antworten:

129

Die Tastatur scheint zu erscheinen, wenn der EditText den Fokus erhält. Um dies zu verhindern, setzen Sie focusable auf false:

<EditText
    ...
    android:focusable="false"
    ... />

Dieses Verhalten kann je nach Android-Betriebssystem der verschiedenen Hersteller variieren, aber auf den von mir getesteten Geräten hat sich dies als ausreichend erwiesen. Wenn die Tastatur immer noch angezeigt wird, scheint es auch hilfreich zu sein, Hinweise anstelle von Text zu verwenden:

myEditText.setText("My text");    // instead of this...
myEditText.setHint("My text");    // try this

Sobald Sie dies getan haben, sollte Ihr On-Click-Listener wie gewünscht funktionieren:

myEditText.setOnClickListener(new OnClickListener() {...});
Dillon Kearns
quelle
Dies scheint zu funktionieren, aber wenn Sie ein Feld eingeben und auf der Tastatur auf Weiter klicken, wird das Feld mit dem Fokus auf false übersprungen.
Sterling Diaz
58

Normalerweise möchten Sie maximale Kompatibilität mit EditTextdem normalen Verhalten.

Sie sollten also nicht verwenden, android:focusable="false"da die Ansicht einfach nicht mehr fokussierbar ist, was schlecht aussieht. Der Hintergrund, der gezeichnet werden kann, zeigt beispielsweise nicht mehr den Status "gedrückt" an.

Was Sie stattdessen tun sollten, ist Folgendes:

myEditText.setInputType(InputType.TYPE_NULL);
myEditText.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        // showMyDialog();
    }
});
myEditText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
    @Override
    public void onFocusChange(View v, boolean hasFocus) {
        if (hasFocus) {
            // showMyDialog();
        }
    }
});

Durch Setzen des Eingabetyps auf TYPE_NULLverhindern Sie, dass die Softwaretastatur auftaucht.

Durch Setzen von OnClickListenerund stellen OnFocusChangeListenerSie sicher, dass Ihr Dialogfeld immer geöffnet wird, wenn der Benutzer in das EditTextFeld klickt , sowohl wenn er den Fokus erhält (erster Klick) als auch bei nachfolgenden Klicks.

Nur einstellen android:inputType="none"oder setInputType(InputType.TYPE_NULL)ist nicht immer genug. Bei einigen Geräten sollten Sie auch android:editable="false"XML festlegen , obwohl dies veraltet ist. Wenn es nicht mehr funktioniert, wird es einfach ignoriert (wie alle XML-Attribute, die nicht unterstützt werden).

krächzen
quelle
Wenn ich dies tue, wird der Dialog nach dem Schließen wieder geöffnet, da der Edittext wieder fokussiert wird. Wie kann man das umgehen?
AdamMc331
@ McAdam331 Ist diese EditTextKomponente vielleicht das einzige Widget in Ihrem Layout? Können Sie versuchen android:focusable="true", Ihr übergeordnetes Layout zu erweitern?
Caw
1
@caw Danke für die Antwort, aber am Ende habe ich es mit onTouch zum Laufen gebracht. Vielen Dank!
AdamMc331
31

Ich hatte das gleiche Problem. Der Code ist in Ordnung, aber stellen Sie sicher, dass Sie den fokussierbaren Wert des EditText in false ändern.

<EditText
android:id="@+id/date"
android:focusable="false"/>

Ich hoffe das hilft jedem, der ein ähnliches Problem hatte!

Yusuf Hoque
quelle
4
Setzen Sie auch nicht enabled = "false", wodurch onClickListener
OatsMantou
25

Standardfunktion von EditText: Beim ersten Klicken wird fokussiert und beim zweiten Klick wird behandelt, onClickListenersodass Sie den Fokus deaktivieren müssen. Klicken Sie dann beim ersten Klicken auf das onClickListenerTestament.

Dazu müssen Sie dieses android:focusableInTouchMode="false"Attribut zu Ihrem hinzufügen EditText. Das ist es!

Etwas wie das:

    <EditText
        android:id="@+id/editText"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:focusableInTouchMode="false"
        android:inputType="text" />
Akshay Chordiya
quelle
3
Es funktioniert, EditTextwird jedoch nicht mehr bearbeitet und der Cursor wird nicht angezeigt.
CoolMind
17

Hier ist die Lösung, die ich implementiert habe

mPickDate.setOnKeyListener(new View.OnKeyListener() {

    @Override
    public boolean onKey(View v, int keyCode, KeyEvent event) {
        showDialog(DATE_DIALOG_ID);
        return false;
    }
});

ODER

mPickDate.setOnFocusChangeListener(new View.OnFocusChangeListener() {

    @Override
    public void onFocusChange(View v, boolean hasFocus) {
        showDialog(DATE_DIALOG_ID);

    }
});

Überzeugen Sie sich selbst von den Unterschieden. Das Problem ist, dass (wie RickNotFred sagte) TextView das Datum anzeigt und über den DatePicker bearbeitet. TextEdit wird nicht für den Hauptzweck verwendet. Wenn der DatePicker erneut angezeigt werden soll, müssen Sie delete (1. Fall) oder de focus (2. Fall) eingeben.

Strahl

Raymond Chenon
quelle
2
es sei denn, Sie fügen einen onClickListener hinzu, den ich gerade zusammen mit einem onFocusChangeListener erstellt habe. Dies wird funktionieren :-)
Neteinstein
Die zweite Lösung hat bei mir funktioniert, danke! :)
Celtik
9

Wenn Sie die OnClick-Aktion für EditText verwenden, wie folgt:

Java:

mEditInit = (EditText) findViewById(R.id.date_init);
mEditInit.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        showDialog(DATEINIT_DIALOG);
    }

});

oder Kotlin:

editTextChooseDate.setOnClickListener {
        showDialog(DATEINIT_DIALOG)
    }

So wird es perfekt funktionieren , wenn Sie setzen in xmlIhren EditTextfolgenden Zeilen:

android: inputType = "none"
android: focusable = "false"
android: cursorVisible = "false"

Beispielsweise:

<EditText
            android:id="@+id/date_init" 
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text=""
            android:hint="Select Date"
            android:inputType="none"
            android:focusable="false"
            android:cursorVisible="false"/>

oder für MaterialDesign

<com.google.android.material.textfield.TextInputLayout
        android:id="@+id/layoutEditTextChooseDate"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent">

    <com.google.android.material.textfield.TextInputEditText
            android:id="@+id/date_init" 
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text=""
            android:hint="Select Date"
            android:inputType="none"
            android:focusable="false"                      
            android:cursorVisible="false"/>

</com.google.android.material.textfield.TextInputLayout>
V. März
quelle
8

IMHO stimme ich der Aussage von RickNotFred nicht zu:

Das Öffnen eines Dialogfelds, wenn ein EditText den Fokus erhält, scheint eine nicht standardmäßige Oberfläche zu sein.

Das Anzeigen eines Dialogfelds zum Bearbeiten des Datums beim Drücken des EditText ist dem Standard sehr ähnlich, bei dem eine Tastatur oder ein Ziffernblock angezeigt wird. Die Tatsache, dass das Datum mit dem EditText angezeigt wird, signalisiert dem Benutzer, dass das Datum geändert werden kann. Das Anzeigen des Datums als nicht bearbeitbare Textansicht signalisiert dem Benutzer, dass das Datum möglicherweise nicht geändert wird.

fishjd
quelle
7

Schönes Thema. Nun, ich habe es getan. In der XML-Datei:

<EditText
    ...
    android:editable="false"
    android:inputType="none" />

Im Java-Code:

txtDay.setOnClickListener(onOnClickEvent);
txtDay.setOnFocusChangeListener(onFocusChangeEvent);

private View.OnClickListener onOnClickEvent = new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        dpDialog.show();
    }
};
private View.OnFocusChangeListener onFocusChangeEvent = new View.OnFocusChangeListener() {
    @Override
    public void onFocusChange(View v, boolean hasFocus) {
        if (hasFocus)
            dpDialog.show();
    }
};
CoolMind
quelle
6

Das Folgende funktioniert perfekt für mich.

Setzen Sie zuerst die Eingabe Ihres Datumsauswahl-Widgets auf "Keine", um zu verhindern, dass die Softtastatur auftaucht:

<EditText android:inputType="none" ... ></EditText>

Fügen Sie dann diese Ereignis-Listener hinzu, um den Dialog mit der Datumsauswahl anzuzeigen:

// Date picker
EditText dateEdit = (EditText) findViewById(R.id.date);
dateOfBirthEdit.setOnTouchListener(new OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_UP) {
            showDialog(DIALOG_DATE_PICKER);
        }
        return false;
    }
});

dateEdit.setOnFocusChangeListener(new OnFocusChangeListener() {

    @Override
    public void onFocusChange(View v, boolean hasFocus) {
        if (hasFocus) {
            showDialog(DIALOG_DATE_PICKER);
        } else {
            dismissDialog(DIALOG_DATE_PICKER);
        }
    }
});

Eine letzte Sache. Um sicherzustellen, dass eingegebene Tage, Monate oder Jahre korrekt aus der Datumsauswahl kopiert wurden, rufen Sie an, datePicker.clearFocus()bevor Sie die Werte abrufen , z. B. über getMonth().

Lukas Batteau
quelle
Einfache Lösung: Entlassen Sie Dialog vor jedem showDialog, nur um sicherzugehen.
Lukas Batteau
5

Das funktioniert bei mir:

mEditInit = (EditText) findViewById(R.id.date_init);
mEditInit.setKeyListener(null);
mEditInit.setOnFocusChangeListener(new View.OnFocusChangeListener() {
        @Override
        public void onFocusChange(View v, boolean hasFocus) {
            if(hasFocus)
            {
                mEditInit.callOnClick();
            }
        }
    });
mEditInit.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        showDialog(DATEINIT_DIALOG);
    }

});
Rahim Rahimov
quelle
3

Hier ist, was für mich funktioniert hat

Setzen Sie editierbar auf false

<EditText android:id="@+id/dob"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="Date of Birth"
android:inputType="none"
android:editable="false"

/>

Fügen Sie dann einen Ereignis-Listener für OnFocusChange hinzu

private  View.OnFocusChangeListener onFocusChangeDOB= new View.OnFocusChangeListener() {

@Override
 public void onFocusChange(View v, boolean hasFocus) {
   if (hasFocus){
     showDialog(DATE_DIALOG_ID);
   }
 }
};
Matt
quelle
3
Vorsicht vor Motorola-Handys mit Android 2.3.x. Befindet sich der EditText irgendwo in einem scrollbaren Bereich, verschiebt Motorola beim Scrollen automatisch den Fokus. Dies bedeutet, dass Sie nach unten scrollen können und wenn der EditText den Fokus erhält, wird Ihr Datumsdialog angezeigt, was überraschend und schlecht ist.
Eric Burke
2

Wie Dillon Kearns vorschlug, funktioniert es gut, wenn man sich auf falsch fokussiert. Wenn Sie jedoch die Tastatur abbrechen möchten, wenn Sie auf EditText klicken, möchten Sie möglicherweise Folgendes verwenden:

mEditText.setInputType(0);
imbrizi
quelle
2

Warum hat niemand erwähnt setOnTouchListener? Die Verwendung setOnTouchListenerist einfach und in Ordnung und gibt nur true zurück, wenn der Listener das Ereignis konsumiert hat, andernfalls false.

Drakeet
quelle