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.


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

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


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!


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

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


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>

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.


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

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


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

});

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

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

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.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.