EditText onClickListener in Android


85

Voglio un EditText che crea un DatePicker quando viene premuto. Quindi scrivo il seguente codice:

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

    });

Ma quando premo EditText l'azione è quella tipica: un cursore in attesa di digitare del testo mostra invece la finestra di dialogo che desidero.


Dovresti usare una casella di selezione invece di una finestra di dialogo Modifica testo.
Ryan R

Risposte:


129

La tastiera sembra apparire quando l'EditText diventa attivo. Per evitare ciò, imposta focusable su false:

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

Questo comportamento può variare a seconda delle versioni del sistema operativo Android di produttori diversi, ma sui dispositivi che ho testato ho trovato che ciò sia sufficiente. Se la tastiera si apre ancora, anche l'uso dei suggerimenti al posto del testo sembra aiutare:

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

Dopo averlo fatto, il tuo ascoltatore al clic dovrebbe funzionare come desiderato:

myEditText.setOnClickListener(new OnClickListener() {...});

Sembra funzionare, ma quando si digita un campo e si fa clic su Avanti sulla tastiera, si salta il campo con focusable su false.
Sterling Diaz

59

Normalmente, si desidera la massima compatibilità con EditTextil normale comportamento di.

Così si dovrebbe non usare android:focusable="false"come, sì, la vista sarà semplicemente non essere attivabile più che sembra male. Lo sfondo disegnabile non mostrerà più il suo stato "premuto", per esempio.

Quello che dovresti fare invece è il seguente:

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

Impostando il tipo di input su TYPE_NULL, si impedisce la visualizzazione della tastiera del software.

Impostando OnClickListenere OnFocusChangeListener, ti assicuri che la tua finestra di dialogo si apra sempre quando l'utente fa clic nel EditTextcampo, sia quando ottiene il focus (primo clic) che ai clic successivi.

Basta impostare android:inputType="none"o setInputType(InputType.TYPE_NULL)non è sempre sufficiente. Per alcuni dispositivi, è necessario impostare anche android:editable="false"in XML, sebbene sia deprecato. Se non funziona più, verrà semplicemente ignorato (come tutti gli attributi XML che non sono supportati).


Quando eseguo questa operazione, la finestra di dialogo si riapre dopo la chiusura perché l'edittext riacquista il focus. Qualche modo per aggirare questo?
AdamMc331

@ McAdam331 Quel EditTextcomponente è forse l'unico widget nel layout, forse? Puoi provare ad aggiungere android:focusable="true"al layout del tuo genitore?
caw

1
@caw Grazie per aver risposto, ma ho finito per farlo funzionare utilizzando onTouch. Grazie!
AdamMc331

Questo è tutto. Funziona bene.
XueQing

31

Ho avuto lo stesso problema. Il codice va bene, ma assicurati di modificare il valore attivabile di EditText in false.

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

Spero che questo aiuti chiunque abbia avuto un problema simile!


4
Inoltre, non impostare enabled = "false", che disabiliterà onClickListener
OatsMantou

25

Funzionamento predefinito di EditText: al primo clic si concentra e al secondo si gestisce, onClickListenerquindi è necessario disabilitare lo stato attivo. Quindi al primo clic onClickListenerverrà gestito.

Per farlo devi aggiungere questo android:focusableInTouchMode="false"attributo al tuo file EditText. Questo è tutto!

Qualcosa come questo:

    <EditText
        android:id="@+id/editText"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:focusableInTouchMode="false"
        android:inputType="text" />

4
Funziona, ma EditTextdiventa non modificabile e il cursore non viene visualizzato.
CoolMind

17

Ecco la soluzione che ho implementato

mPickDate.setOnKeyListener(new View.OnKeyListener() {

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

O

mPickDate.setOnFocusChangeListener(new View.OnFocusChangeListener() {

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

    }
});

Guarda le differenze da solo. Il problema è poiché (come ha detto RickNotFred) TextView per visualizzare la data e modificare tramite DatePicker. TextEdit non viene utilizzato per il suo scopo principale. Se si desidera che il DatePicker venga visualizzato nuovamente, è necessario immettere delete (primo caso) o de focus (secondo caso).

Ray


2
a meno che tu non aggiunga un onClickListener che ho appena fatto insieme a un onFocusChangeListener.
Funzionerà

La seconda soluzione ha funzionato per me, grazie! :)
Celtik

9

Se utilizzi l'azione Al clic su Modifica testo come:

Giava:

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

});

o kotlin:

editTextChooseDate.setOnClickListener {
        showDialog(DATEINIT_DIALOG)
    }

Così, funzionerà perfettamente se si mette in xmldei vostri EditTextle seguenti righe:

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

Per esempio:

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

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

8

IMHO non sono d'accordo con l'affermazione di RickNotFred:

Aprire una finestra di dialogo quando un EditText viene attivato sembra un'interfaccia non standard.

La visualizzazione di una finestra di dialogo per modificare la data quando l'utente preme un EditText è molto simile a quella predefinita, che consiste nel visualizzare una tastiera o un tastierino numerico. Il fatto che la data venga visualizzata con EditText segnala all'utente che la data può essere modificata. La visualizzazione della data come TextView non modificabile segnala all'utente che la data non può essere modificata.


7

Bel argomento. Bene, l'ho fatto. Nel file XML:

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

In codice Java:

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

6

Quanto segue funziona perfettamente per me.

Per prima cosa imposta l'input del widget del selettore di date su "nessuno" per evitare che la tastiera virtuale venga visualizzata:

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

Quindi aggiungi questi listener di eventi per mostrare la finestra di dialogo contenente il selettore di date:

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

Un'ultima cosa. Per assicurarti che i giorni, i mesi o gli anni digitati vengano copiati correttamente dal selettore di date, chiama datePicker.clearFocus()prima di recuperare i valori, ad esempio tramite getMonth().


Soluzione semplice: dismissDialog prima di ogni showDialog, solo per sicurezza.
Lukas Batteau

5

Questo funziona per me:

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

});

3

Ecco cosa ha funzionato per me

Imposta modificabile su 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"

/>

Quindi aggiungi un listener di eventi per OnFocusChange

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

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

3
Fai attenzione ai telefoni Motorola con Android 2.3.x. Se l'EditText si trova da qualche parte in un'area scorrevole, Motorola sposterà automaticamente lo stato attivo durante lo scorrimento. Ciò significa che puoi scorrere verso il basso e quando l'EditText diventa attivo, viene visualizzata la finestra di dialogo della data, il che è sorprendente e brutto.
Eric Burke

2

Come suggerito da Dillon Kearns, l'impostazione del focusable su false funziona bene. Ma se il tuo obiettivo è annullare la tastiera quando fai clic su EditText, potresti voler utilizzare:

mEditText.setInputType(0);

2

Perché nessuno l'ha menzionato setOnTouchListener? L'uso setOnTouchListenerè facile e corretto e restituisce solo true se l'ascoltatore ha consumato l'evento, false in caso contrario.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.