EditText onClickListener в Android

86

Мне нужен EditText, который создает DatePicker при нажатии. Итак, я пишу следующий код:

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

    });

Но когда я нажимаю EditText, действие является типичным: курсор, ожидающий ввода текста, вместо этого показывает диалог, который я хочу.

xger86x
источник
Вы должны использовать счетчик вместо диалогового окна 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.
Стерлинг Диаз,
60

Обычно требуется максимальная совместимость с EditTextобычным поведением пользователя.

Так что вы не должны использовать android:focusable="false"as, да, вид больше не будет фокусироваться, что выглядит плохо. Например, фоновый рисунок больше не будет показывать свое «нажатое» состояние.

Вместо этого вам следует сделать следующее:

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-й случай) или de focus (2-й случай).

Луч

Раймон Шенон
источник
2
если вы не добавите onClickListener, который я только что сделал вместе с onFocusChangeListener. Это сработает :-)
neteinstein
Второе решение сработало для меня, спасибо! :)
Celtik
9

Если вы используете действие OnClick в EditText, например:

Ява:

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

});

или котлин:

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

ИМХО я не согласен с утверждением RickNotFred:

Появление диалогового окна, когда EditText получает фокус, кажется нестандартным интерфейсом.

Отображение диалогового окна для редактирования даты, когда пользователь нажимает EditText, очень похоже на значение по умолчанию, которое заключается в отображении клавиатуры или цифровой клавиатуры. Тот факт, что дата отображается с EditText, сигнализирует пользователю, что дату можно изменить. Отображение даты в виде недоступного для редактирования TextView сигнализирует пользователю, что дату нельзя изменить.

Fishjd
источник
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();
    }
};
CoolMind
источник
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

Как предположил Диллон Кернс, установка фокусировки на ложь работает нормально. Но если ваша цель - отключить клавиатуру при нажатии EditText, вы можете использовать:

mEditText.setInputType(0);
Imbrizi
источник
2

Почему никто не упомянул setOnTouchListener? Использовать setOnTouchListenerлегко и нормально, просто верните true, если слушатель обработал событие, иначе false.

селезень
источник