EditText onClickListener en Android

85

Quiero un EditText que crea un DatePicker cuando se presiona. Entonces escribo el siguiente código:

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

    });

Pero cuando presiono EditText, la acción es la típica: un cursor esperando para escribir texto muestra el diálogo que quiero.

xger86x
fuente
Debería utilizar una ruleta en lugar de un cuadro de diálogo Editar texto.
Ryan R

Respuestas:

129

El teclado parece aparecer cuando EditText gana el foco. Para evitar esto, establezca focusable en falso:

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

Este comportamiento puede variar en los sabores del sistema operativo Android de diferentes fabricantes, pero en los dispositivos que he probado, he encontrado que esto es suficiente. Si el teclado aún aparece, el uso de sugerencias en lugar de texto también parece ayudar:

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

Una vez que haya hecho esto, su oyente de clic debería funcionar como desee:

myEditText.setOnClickListener(new OnClickListener() {...});
Dillon Kearns
fuente
Esto parece funcionar, pero cuando escribe en un campo y hace clic en Siguiente en el teclado, se salta el campo con foco en falso.
Sterling Diaz
59

Normalmente, desea la máxima compatibilidad con EditTextel comportamiento normal.

Por lo que debe no utilizar android:focusable="false"como, sí, la vista no sea más enfocable, que se ve mal. El elemento de diseño de fondo ya no mostrará su estado "presionado", por ejemplo.

Lo que debería hacer en su lugar es lo siguiente:

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

Al establecer el tipo de entrada en TYPE_NULL, evita que aparezca el teclado del software.

Al configurar OnClickListenery OnFocusChangeListener, se asegura de que su cuadro de diálogo siempre se abra cuando el usuario haga clic en el EditTextcampo, tanto cuando se enfoque (primer clic) como en los clics posteriores.

Solo configurar android:inputType="none"o setInputType(InputType.TYPE_NULL)no siempre es suficiente. Para algunos dispositivos, también debe configurar android:editable="false"XML, aunque está obsoleto. Si ya no funciona, simplemente se ignorará (como todos los atributos XML que no son compatibles).

graznar
fuente
Cuando hago esto, el cuadro de diálogo se vuelve a abrir después de que se cierra porque el texto de edición vuelve a enfocarse. ¿Alguna forma de evitar esto?
AdamMc331
@ McAdam331 ¿Es ese EditTextcomponente el único widget en su diseño, quizás? ¿Puedes intentar agregarlo android:focusable="true"a tu diseño principal?
caw
1
@caw Gracias por responder, pero terminé haciéndolo funcionar con onTouch. ¡Gracias!
AdamMc331
Eso es. Funcionando bien.
XueQing
31

Yo tuve el mísmo problema. El código está bien, pero asegúrese de cambiar el valor enfocable de EditText a falso.

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

¡Espero que esto ayude a cualquiera que haya tenido un problema similar!

Yusuf Hoque
fuente
4
Tampoco configure enabled = "false", que desactivará onClickListener
OatsMantou
25

Funcionamiento predeterminado de EditText: en el primer clic, se enfoca y en el segundo clic se maneja, onClickListenerpor lo que debe deshabilitar el enfoque. Luego, en el primer clic, onClickListenerse manejará.

Para hacer eso, debe agregar este android:focusableInTouchMode="false"atributo a su EditText. ¡Eso es!

Algo como esto:

    <EditText
        android:id="@+id/editText"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:focusableInTouchMode="false"
        android:inputType="text" />
Akshay Chordiya
fuente
4
Funciona, pero no EditTextse puede editar y el cursor no aparece.
CoolMind
17

Aquí está la solución que implementé

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

    }
});

Vea las diferencias usted mismo. El problema es que (como dijo RickNotFred) TextView para mostrar la fecha y editar a través de DatePicker. TextEdit no se utiliza para su propósito principal. Si desea que el selector de fecha vuelva a aparecer, debe ingresar eliminar (primer caso) o desenfocar (segundo caso).

Rayo

Raymond Chenon
fuente
2
a menos que agregue un onClickListener que acabo de hacer junto con un onFocusChangeListener. Esto funcionará :-)
neteinstein
La segunda solución me ha funcionado, ¡gracias! :)
Celtik
9

Si usa la acción OnClick en EditText como:

Java:

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

Entonces, funcionará perfectamente si pones en xmltus EditTextsiguientes líneas:

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

Por ejemplo:

<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 para 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.marzo
fuente
8

En mi humilde opinión, no estoy de acuerdo con la declaración de RickNotFred:

Abrir un cuadro de diálogo cuando se enfoca un EditText parece una interfaz no estándar.

Mostrar un cuadro de diálogo para editar la fecha cuando el usuario presiona un EditText es muy similar al predeterminado, que es mostrar un teclado o un teclado numérico. El hecho de que la fecha se muestre con EditText le indica al usuario que la fecha puede cambiar. Mostrar la fecha como un TextView no editable indica al usuario que la fecha no se puede cambiar.

Fishjd
fuente
7

Buen tema. Bueno, lo he hecho. En archivo XML:

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

En código 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();
    }
};
CoolMind
fuente
6

Lo siguiente funciona perfectamente para mí.

Primero configure la entrada de su widget selector de fecha en 'none' para evitar que aparezca el teclado virtual:

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

Luego agregue estos detectores de eventos para mostrar el diálogo que contiene el selector de fecha:

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

Una última cosa. Para asegurarse de que los días, meses o años escritos se hayan copiado correctamente del selector de fechas, llame datePicker.clearFocus()antes de recuperar los valores, por ejemplo mediante getMonth().

Lukas Batteau
fuente
Solución simple: DesestimeDialog antes de cada showDialog, solo para estar seguro.
Lukas Batteau
5

Esto funciona para mí:

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

Esto es lo que funcionó para mí

Establecer editable en falso

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

/>

Luego agregue un detector de eventos para OnFocusChange

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

@Override
 public void onFocusChange(View v, boolean hasFocus) {
   if (hasFocus){
     showDialog(DATE_DIALOG_ID);
   }
 }
};
Mate
fuente
3
Tenga cuidado con los teléfonos Motorola que ejecutan Android 2.3.x. Si EditText está en algún lugar de un área desplazable, Motorola moverá automáticamente el enfoque cuando se desplace. Esto significa que puede desplazarse hacia abajo y cuando EditText gana el foco, aparece su cuadro de diálogo de fecha, lo cual es sorprendente y malo.
Eric Burke
2

Como sugirió Dillon Kearns, configurar enfocable en falso funciona bien. Pero si su objetivo es cancelar el teclado cuando se hace clic en EditarTexto, es posible que desee utilizar:

mEditText.setInputType(0);
imbrizi
fuente
2

¿Por qué nadie lo mencionó setOnTouchListener? Usar setOnTouchListeneres fácil y está bien, y solo devuelve verdadero si el oyente ha consumido el evento, falso en caso contrario.

drakeet
fuente