Ответ 1
Используйте
editText.setImeOptions(EditorInfo.IME_ACTION_DONE);
editText.setRawInputType(InputType.TYPE_CLASS_TEXT);
и в XML:
android:inputType="textMultiLine"
Возможно ли иметь виджет EditText
с android:inputType="textMultiLine"
и android:imeOptions="actionDone"
в то же время?
Мне нужно многострочное окно редактирования, при этом кнопка действия на клавиатуре будет выполнена, а не Enter (возврат каретки), но она, похоже, не работает.
Заранее спасибо
Используйте
editText.setImeOptions(EditorInfo.IME_ACTION_DONE);
editText.setRawInputType(InputType.TYPE_CLASS_TEXT);
и в XML:
android:inputType="textMultiLine"
Из документации по android: ' "textMultiLine" Обычная текстовая клавиатура, которая позволяет пользователям вводить длинные строки текста, содержащие разрывы строк (возврат каретки). ' Поэтому атрибут textMultiLine не подходит, если вы хотите иметь кнопку "Готово" на клавиатуре.
Простой способ получить многострочное (в данном случае 3 строки) поле ввода с помощью сделанной кнопки - использовать EditText с
android:lines="3"
android:scrollHorizontally="false"
Однако по какой-то причине это работает только для меня, если я сделаю эти настройки в коде вместо файла макета (в onCreate) на
TextView tv = (TextView)findViewById(R.id.editText);
if (tv != null) {
tv.setHorizontallyScrolling(false);
tv.setLines(3);
}
Я надеюсь, что это поможет кому-то, так как потребовалось довольно много времени, чтобы разобраться. Если вы найдете способ заставить его работать из манифеста, сообщите нам об этом.
Рабочий пример! Создайте следующий пользовательский класс EditText, который поддерживает эту функцию, и используйте класс в XML файле. Рабочий код:
package com.example;
import android.content.Context;
import android.util.AttributeSet;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
import android.widget.EditText;
public class ActionEditText extends EditText
{
public ActionEditText(Context context)
{
super(context);
}
public ActionEditText(Context context, AttributeSet attrs)
{
super(context, attrs);
}
public ActionEditText(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
}
@Override
public InputConnection onCreateInputConnection(EditorInfo outAttrs)
{
InputConnection conn = super.onCreateInputConnection(outAttrs);
outAttrs.imeOptions &= ~EditorInfo.IME_FLAG_NO_ENTER_ACTION;
return conn;
}
}
<com.example.ActionEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:imeOptions="actionDone"
android:inputType="textAutoCorrect|textCapSentences|textMultiLine" />
Я думаю, что это способ сделать то, что вам нужно. Имея android:inputType="textMultiLine"
, android:imeOptions="actionDone"
делает android:imeOptions="actionDone"
функциональность ввода ключа. Просто имейте в виду, что вы можете использовать android:lines="10"
и, возможно, удалить android:inputType="textMultiLine"
, но зависит от того, чего вы хотите достичь, иногда вам просто нужен android:inputType="textMultiLine"
и нет замены для этого.
EditText ed=new EditText(this);
ed.setOnKeyListener(new OnKeyListener() {
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if(keyCode==66){
//do your stuff here
}
return false;
}
});
Это, кажется, отлично работает для меня.
int lineNum = 2;
mEditText.setHorizontallyScrolling(false);
mEditText.setLines(3);
Короткий ответ: Нет, я считаю, что это невозможно до уровня API 11 (3.0).
Эта же проблема возникла здесь (обсуждается в комментариях к принятому ответу):
Кнопка Android Soft для клавиатуры
Из заключительного комментария:
Если посмотреть на несколько приложений на моем телефоне, кажется, что для этого есть многострочный блок с видимой надписью "Готово" или "Отправить" (например, приложение электронной почты).
Если речь идет не о внешнем виде экранной клавиатуры, вы можете просто добавить слушателя на клавиатуру и запустить "done" -status, если пользователь вводит новую строку.
если вы используете параметр ввода textImeMultiline с помощью imeoptions flagnext и actionnext, вы получаете следующую кнопку вместо возврата кариеса
Я на 4.x и попытался вызвать setHorizontallyScrolling() (с или без setLine() или setMaxLines()), а также множество различных конфигураций XML, чтобы показать кнопку Готово. Ни один из них не работал. Суть в том, что если ваш EditText является многострочным, Android всегда будет хотеть показывать возврат каретки вместо кнопки "Готово", если вы не вложите в нее какой-то хак.
Самое меньшее решение для осложнений, которое я обнаружил, не включает переназначение поведения возврата каретки: fooobar.com/questions/20296/.... Это решение аннулирует нежелательное желание Android принудительно установить флаг IME_FLAG_NO_ENTER_ACTION для многострочных представлений, что приводит к исчезновению кнопки "Готово".
Простой способ обойти эту ситуацию:
сохраните эти атрибуты в EditText:
android:inputType="textMultiLine"
android:scrollHorizontally="false"
затем добавьте этот код, чтобы скрыть клавиатуру только при нажатии ENTER:
editText.setOnEditorActionListener(new OnEditorActionListener()
{
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (event.getKeyCode() == KeyEvent.KEYCODE_ENTER)
{
editText.setSelection(0);
InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(editText.getWindowToken(), 0);
return true;
}
else
{
return false;
}
}
});
Я слишком долго боролся, но наконец нашел решение!
Просто создайте собственный класс EditText как таковой:
public class EditTextImeMultiline extends EditText {
public void init() {
addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
for (int i = s.length(); i > 0; i--)
if (s.subSequence(i - 1, i).toString().equals("\n"))
s.replace(i - 1, i, "");
}
});
setSingleLine();
setHorizontallyScrolling(false);
this.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
EditTextImeMultiline.this.setLines(EditTextImeMultiline.this.getLineCount());
}
});
}
public EditTextImeMultiline(Context context) {
super(context);
init();
}
public EditTextImeMultiline(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public EditTextImeMultiline(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public EditTextImeMultiline(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init();
}
}
Этот класс удаляет lineBreaks (\n), обертывает текст, как textMultiline, и позволяет вам заменить кнопку Enter на ImeAction;).
Вам просто нужно вызвать его в XML вместо классического класса EditText.
Чтобы объяснить логику здесь:
Рабочее решение здесь, создайте свой собственный EditTextView (просто расширьте текстовое представление) и переопределите onInputConnection с частью кода, который вы найдете в принятом ответе здесь: Многострочный EditText с Done SoftInput Action Label на 2.3
Несмотря на то, что ни одно из других решений для меня никогда не работало, работало красиво и спасло меня от нескольких дней и дней от поиска в Google, конечно же, с небольшими завихрениями. К сожалению, не помню, откуда я получил код, и поэтому не могу дать автору кредит, который он заслуживает.
В коде Java:
////////////Code to Hide SoftKeyboard on Enter (DONE) Press///////////////
editText.setRawInputType(InputType.TYPE_CLASS_TEXT|InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD|InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
editText.setImeActionLabel("DONE",EditorInfo.IME_ACTION_DONE); //Set Return Carriage as "DONE"
editText.setImeOptions(EditorInfo.IME_ACTION_DONE);
editText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event)
{
if (event == null) {
if (actionId == EditorInfo.IME_ACTION_DONE) {
// Capture soft enters in a singleLine EditText that is the last EditText
// This one is useful for the new list case, when there are no existing ListItems
editText.clearFocus();
InputMethodManager inputMethodManager = (InputMethodManager) getActivity().getSystemService(Activity.INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow(getActivity().getCurrentFocus().getWindowToken(), 0);
}
else if (actionId == EditorInfo.IME_ACTION_NEXT) {
// Capture soft enters in other singleLine EditTexts
} else if (actionId == EditorInfo.IME_ACTION_GO) {
} else {
// Let the system handle all other null KeyEvents
return false;
}
}
else if (actionId == EditorInfo.IME_NULL) {
// Capture most soft enters in multi-line EditTexts and all hard enters;
// They supply a zero actionId and a valid keyEvent rather than
// a non-zero actionId and a null event like the previous cases.
if (event.getAction() == KeyEvent.ACTION_DOWN) {
// We capture the event when the key is first pressed.
} else {
// We consume the event when the key is released.
return true;
}
}
else {
// We let the system handle it when the listener is triggered by something that
// wasn't an enter.
return false;
}
return true;
}
});
Пример функции расширения Kotlin для включения действия Done и конкретной комбинации типов ввода в EditTextExt.kt:
// To use this, do NOT set inputType on the EditText in the XML layout
fun EditText.setMultiLineCapSentencesAndDoneAction() {
imeOptions = EditorInfo.IME_ACTION_DONE
setRawInputType(InputType.TYPE_TEXT_FLAG_CAP_SENTENCES or InputType.TYPE_TEXT_FLAG_MULTI_LINE)
}
Затем использование:
myEditText.setMultiLineCapSentencesAndDoneAction()
Чтобы сделать это в Kotlin (а также, возможно, примените другие конфигурации, такие как textCapSentences
вы можете использовать эту функцию расширения:
// To use this, do NOT set inputType on the EditText in the layout
fun EditText.setMultiLineCapSentencesAndDoneAction() {
imeOptions = EditorInfo.IME_ACTION_DONE
setRawInputType(InputType.TYPE_TEXT_FLAG_CAP_SENTENCES or InputType.TYPE_TEXT_FLAG_MULTI_LINE)
}
Использование:
myEditText.setMultiLineCapSentencesAndDoneAction()
Простой способ обойти эту ситуацию:
изменить атрибуты в EditText:
android:inputType="textMultiLine"
android:scrollHorizontally="false"
в
android:inputType="textImeMultiLine"
android:scrollHorizontally="false"