EditText onClickListener в Android


85

Я хочу EditText, який створює DatePicker при натисканні. Тому я пишу такий код:

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

    });

Але коли я натискаю EditText, дія типова: курсор, який чекає набору тексту, замість цього показує діалогове вікно, яке я хочу.


Вам слід використовувати обертання замість діалогового вікна EditText.
Ryan R

Відповіді:


129

Здається, клавіатура спливає, коли EditText набуває фокусу. Щоб запобігти цьому, встановіть focusable на false:

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

Ця поведінка може відрізнятися залежно від версій ОС Android різних виробників, але на тестованих пристроях я виявив, що цього достатньо. Якщо клавіатура все-таки вискакує, здається, також допомагає використання підказок замість тексту:

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

Після того, як ви це зробите, ваш прослуховувач на клік повинен працювати за бажанням:

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

Здається, це працює, але коли ви вводите поле та натискаєте кнопку Далі на клавіатурі, воно пропускає поле з фокусуванням на false.
Стерлінг Діаз,

59

Зазвичай вам потрібна максимальна сумісність з EditText нормальною поведінкою.

Таким чином , ви повинні НЕ використовувати в android:focusable="false"якості, так, вид просто не буде фокусування більше , що погано виглядає. Наприклад, фон, який можна малювати, більше не відображатиметься у своєму "натиснутому" стані.

Натомість вам слід зробити наступне:

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

Установивши тип введення на TYPE_NULL, ви запобігаєте спливаючій клавіатурі програмного забезпечення.

Встановивши OnClickListenerі OnFocusChangeListener, ви переконуєтесь, що ваше діалогове вікно завжди відкриватиметься, коли користувач клацає в EditTextполе, як коли він фокусується (перший клік), так і під час наступних клацань.

Просто налаштування android:inputType="none"або setInputType(InputType.TYPE_NULL)недостатньо завжди. Для деяких пристроїв слід також встановити android:editable="false"XML, хоча він застарілий. Якщо він більше не працює, його буде просто проігноровано (як і всі не підтримувані атрибути XML).


Коли я це роблю, діалогове вікно знову відкривається після його закриття, тому що редагування тексту знову фокусується. Будь-який спосіб обійти це?
AdamMc331

@ McAdam331 Чи EditText, можливо, цей компонент - єдиний віджет у вашому макеті? Чи можете ви спробувати додати android:focusable="true"до батьківського макета?
caw

1
@caw Дякую за відповідь, але в підсумку я змусив його працювати за допомогою onTouch. Дякую!
AdamMc331

Це воно. Працює нормально.
XueQing

31

У мене була така сама проблема. Код чудовий, але переконайтеся, що ви змінили значення фокусування EditText на false.

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

Сподіваюся, це допоможе кожному, хто мав подібну проблему!


4
Також не встановлюйте enabled = "false", що вимкне onClickListener
OatsMantou

25

Працює за замовчуванням EditText: При першому клацанні воно фокусується, а при другому клацанні обробляється, onClickListenerтому вам потрібно вимкнути фокусування. Потім спочатку клацніть на onClickListenerручку обробки.

Для цього вам потрібно додати цей android:focusableInTouchMode="false"атрибут до вашого EditText. Це воно!

Щось на зразок цього:

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

4
Він працює, але EditTextстає неможливим для редагування, а курсор не відображається.
CoolMind

17

Ось рішення, яке я реалізував

mPickDate.setOnKeyListener(new View.OnKeyListener() {

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

АБО

mPickDate.setOnFocusChangeListener(new View.OnFocusChangeListener() {

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

    }
});

Побачте відмінності самі. Проблема в тому, що (як сказав RickNotFred) TextView відображає дату та редагує за допомогою DatePicker. TextEdit не використовується з основною метою. Якщо ви хочете, щоб DatePicker знову з’явився, вам потрібно ввести видалення (1-й регістр) або де-фокус (2-й регістр).

Рей


2
якщо ви не додасте onClickListener, що я щойно зробив разом з onFocusChangeListener. Це буде працювати :-)
neteinstein

Друге рішення для мене спрацювало, дякую! :)
Селтік,

9

Якщо ви використовуєте дію OnClick на EditText, наприклад:

java:

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

});

або kotlin:

editTextChooseDate.setOnClickListener {
        showDialog(DATEINIT_DIALOG)
    }

Таким чином, він буде працювати прекрасно , якщо ви вкладаєте в xmlваші EditTextнаступні рядки:

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

Наприклад:

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

або для 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

ІМХО Я не погоджуюсь із твердженням РікНотФреда:

Виникнення діалогового вікна, коли EditText фокусується, здається нестандартним інтерфейсом.

Відображення діалогового вікна для редагування дати, коли користувач натискає EditText, дуже нагадує стандартний, тобто відображення клавіатури або цифрової клавіатури. Той факт, що дата відображається разом із EditText, сигналізує користувачеві про те, що дату може бути змінено. Відображення дати як нередагованого TextView сигналізує користувачеві, що дату не можна змінити.


7

Приємна тема. Ну, я так зробив. У файлі XML:

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

У 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

Наступне мені ідеально підходить.

Спочатку встановіть для введення віджета вибору дати значення "none", щоб запобігти появі м'якої клавіатури:

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

Потім додайте ці прослуховувачі подій, щоб показати діалогове вікно, що містить вибір дати:

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

Останнє. Щоб переконатися, що набрані дні, місяці чи роки правильно скопійовані із засобу вибору дати, зателефонуйте datePicker.clearFocus()перед тим, як отримувати значення, наприклад через getMonth().


Просте виправлення: робіть dismissDialog перед кожним showDialog, щоб бути впевненим.
Лукас Батто,

5

Це працює для мене:

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

Ось, що у мене вийшло

Встановити для редагування значення 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"

/>

Потім додайте прослуховувач подій для OnFocusChange

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

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

3
Остерігайтеся телефонів Motorola під управлінням Android 2.3.x. Якщо EditText знаходиться десь у прокручуваній області, Motorola автоматично переміщає фокус під час прокрутки. Це означає, що ви можете прокручувати вниз, і коли EditText фокусується, з’являється діалогове вікно дати, що дивно і погано.
Ерік Берк,

2

Як запропонував Діллон Кернс, встановлення фокусу на false не працює. Але якщо ваша мета - скасувати клавіатуру, натиснувши EditText, ви можете скористатися:

mEditText.setInputType(0);

2

Чому ніхто не згадав setOnTouchListener? Використовувати setOnTouchListenerпросто і добре, і просто повернути true, якщо слухач спожив подію, false - інакше.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.