Отключить контекстное меню EditText
Я делаю вертикаль EditText для традиционного монгольского языка. Я успешно реализовал его, вложив слегка модифицированный EditText внутрь повернутого ViewGroup. Мне нужно создать полностью настраиваемое контекстное меню, потому что система не поддерживает вертикальный текст и также не поворачивается при повороте ViewGroup. Поэтому я хочу полностью отключить системное контекстное меню.
Обратите внимание, что это отличается от этих вопросов, которые просто пытаются отключить копировать / вставить / и т.д.:
Как отключить копирование / вставку из / в EditText
EditText: отключить всплывающее меню Вставить / заменить на обработчике выбора текста нажмите событие
Как отключить опцию вставки в Android EditText
Android: как полностью отключить функцию копирования и вставки в Edittext
Хотя я не получаю контекстное меню, появляющееся в симуляторе, я получаю его в моем Android 5.0.2 Xiaomi телефон.
Я пробовал:
setCustomSelectionActionModeCallback"Решение"
setLongClickable(false);"решение"
onTouchEvent"решение"
Я открыт для взломов, но мне нужно, чтобы он последовательно работал на разных устройствах. Марк Мерфи (парень из Commons) написал некоторое время назад в ответ на попытку другого пользователя сделать что-то подобное:
Я подозреваю, что даже если вы придумаете ответ, он не будет работать.
через устройства. Устройство производители имели тенденцию сворачивать свои
собственное "контекстное меню" для EditText, побеждающее попытки разработчиков добавить
пункты этого контекстного меню. Мое предположение заключается в том, что пытаются блокировать, что
контекстное меню будет иметь аналогичные результаты.
Мне не повезло?
Единственное, что я могу сейчас придумать, это полностью переписать
TextView и EditText с нуля (ну, изменив исходный код Android). Я знаю еще кое-кого, кто сделал нечто подобное, но его код не является открытым исходным кодом. Прежде чем я сделаю этот важный шаг, я хочу попробовать попросить более простое решение здесь, на переполнении стека. Update: я пытался изменить исходный код TextView в течение последних двух дней, и это выглядит как 6-месячный проект. Это масса взаимосвязанных классов. Мне нужно другое решение, но у меня нет идей.
MVCE
Это самый простой способ, который я мог придумать, чтобы воссоздать проблему. Нет ничего необходимого от моего обычая
EditText. Макет имеет один EditText сделан путем замены проекта Hello World по умолчанию TextView. Я изменил min API на 11, чтобы избежать работы с устаревшими методами.public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
EditText editText = (EditText) findViewById(R.id.edit_text);
editText.setCustomSelectionActionModeCallback(new ActionMode.Callback() {
@Override
public boolean onCreateActionMode(ActionMode actionMode, Menu menu) { return false; }
@Override
public boolean onPrepareActionMode(ActionMode actionMode, Menu menu) { return false; }
@Override
public boolean onActionItemClicked(ActionMode actionMode, MenuItem menuItem) { return false; }
@Override
public void onDestroyActionMode(ActionMode actionMode) { }
});
}
}
Контекстное меню в симуляторе (работает API 24) по-прежнему отображается, когда я нажимаю на ручку курсора (но не при длительном щелчке или двойном щелчке). Вот образ:
На моем телефоне Xiaomi MIUI под управлением Android 5.0 я получаю контекстное меню во всех ситуациях (щелчок курсора, длинный щелчок, двойной щелчок).
Обновление
Решение Аритры Роя работает в симуляторе, на некоторых других устройствах, которые он тестировал, и на моем устройстве. Я принял его ответ, потому что он решает мою первоначальную проблему. Единственным негативным побочным эффектом является то, что выделение текста также отключено.
6 ответов:
Есть три вещи, которые вам нужно сделать.
Шаг 1
Вы можете отключить отображение контекстных меню, вернув false из этих методов,
mEditEext.setCustomSelectionActionModeCallback(new ActionMode.Callback() { public boolean onPrepareActionMode(ActionMode mode, Menu menu) { return false; } public void onDestroyActionMode(ActionMode mode) { } public boolean onCreateActionMode(ActionMode mode, Menu menu) { return false; } public boolean onActionItemClicked(ActionMode mode, MenuItem item) { return false; } });Шаг 2
Необходимо также отключить длинный клик в редактируемом тексте.
mEditText.setLongClickable(false);Или делать это,
android:longClickable="false"в XML.Шаг 3
Теперь вам нужно предотвратить появление меню при нажатии на маркеры. Решение таково просто,
1) расширить класс
EditText,2) переопределить
3) Создайте методisSuggestionsEnabled()и вернутьfalse,canPaste()и верните методfalse. Это метод сокрытия.БЫСТРОЕ РЕШЕНИЕ
Если вы не хотите делать все это вручную. Вот пользовательский класс EditText, который можно использовать для быстрого выполнения этой задачи. Но я все же рекомендую вам пройти через эти шаги один раз, чтобы понять, как все работает.
public class MenuHidingEditText extends EditText { private final Context mContext; public MenuHidingEditText(Context context) { super(context); this.mContext = context; blockContextMenu(); } public MenuHidingEditText(Context context, AttributeSet attrs) { super(context, attrs); this.mContext = context; blockContextMenu(); } public MenuHidingEditText(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); this.mContext = context; blockContextMenu(); } private void blockContextMenu() { this.setCustomSelectionActionModeCallback(new BlockedActionModeCallback()); this.setLongClickable(false); this.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { MenuHidingEditText.this.clearFocus(); return false; } }); } @Override public boolean onTouchEvent(MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { // setInsertionDisabled when user touches the view this.setInsertionDisabled(); } return super.onTouchEvent(event); } private void setInsertionDisabled() { try { Field editorField = TextView.class.getDeclaredField("mEditor"); editorField.setAccessible(true); Object editorObject = editorField.get(this); Class editorClass = Class.forName("android.widget.Editor"); Field mInsertionControllerEnabledField = editorClass.getDeclaredField("mInsertionControllerEnabled"); mInsertionControllerEnabledField.setAccessible(true); mInsertionControllerEnabledField.set(editorObject, false); } catch (Exception ignored) { // ignore exception here } } @Override public boolean isSuggestionsEnabled() { return false; } private class BlockedActionModeCallback implements ActionMode.Callback { public boolean onCreateActionMode(ActionMode mode, Menu menu) { return false; } public boolean onPrepareActionMode(ActionMode mode, Menu menu) { return false; } public boolean onActionItemClicked(ActionMode mode, MenuItem item) { return false; } public void onDestroyActionMode(ActionMode mode) { } } }
Я сделал этот код для
EditText, и он отлично работал для такой проблемы.try { edtName.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { edtName.setSelection(0); } }); edtName.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View v) { return true; } }); edtName.setCustomSelectionActionModeCallback(new ActionMode.Callback() { @Override public boolean onCreateActionMode(ActionMode actionMode, Menu menu) { return false; } @Override public boolean onPrepareActionMode(ActionMode actionMode, Menu menu) { return false; } @Override public boolean onActionItemClicked(ActionMode actionMode, MenuItem menuItem) { return false; } @Override public void onDestroyActionMode(ActionMode actionMode) { } }); } catch (Exception e) { e.printStackTrace(); }
Решение очень простое
public class MainActivity extends AppCompatActivity { EditText et_0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); et_0 = findViewById(R.id.et_0); et_0.setCustomSelectionActionModeCallback(new ActionMode.Callback() { @Override public boolean onCreateActionMode(ActionMode mode, Menu menu) { //to keep the text selection capability available ( selection cursor) return true; } @Override public boolean onPrepareActionMode(ActionMode mode, Menu menu) { //to prevent the menu from appearing menu.clear(); return false; } @Override public boolean onActionItemClicked(ActionMode mode, MenuItem item) { return false; } @Override public void onDestroyActionMode(ActionMode mode) { } }); } }
Таким образом вы блокируете меню copy paste от появления в любом виде, форме или форме. Эта ошибка действительно свела меня с ума, и как с любой ошибкой Samsung, вы знаете ее в своем коде, но вы также знаете, что они не исправят ее в ближайшее время. В любом случае, вот стена чудес...
Проверьте, если андроид.Строить.Модель.toLowerCase ().startsWith ('sm-g930'). Не совпадайте со всей строкой, последняя буква является младшим идентификатором версии. Я сохранил это логическое значение в переменной shouldBlockCopyPaste, которая появляется позже.
Если он соответствует, вы хотите заблокировать отображение меню copy paste. Вот как вы на самом деле это делаете!!!
Переопределите эти 2 функции, вы заметите мой shouldBlockCopyPaste boolean, это так, что другие устройства не блокируются.
@Override public ActionMode StartActionMode (ActionMode.Callback callback){ if (shouldBlockCopyPaste) { return null; } else { return super.StartActionMode(callback); } } @Override public ActionMode StartActionMode (ActionMode.Callback callback, int type){ if (shouldBlockCopyPaste) { return null; } else { return super.StartActionMode(callback, type); } }
Попробуйте это
mEditText.setClickable(false); mEditText.setEnabled(false);Обновить
Попробуйте это решение, расширив Edittext,
import android.content.Context; import android.util.AttributeSet; import android.view.ActionMode; import android.view.Menu; import android.view.MenuItem; import android.widget.EditText; public class NoMenuEditText extends EditText { private final Context context; /** This is a replacement method for the base TextView class' method of the same name. This * method is used in hidden class android.widget.Editor to determine whether the PASTE/REPLACE popup * appears when triggered from the text insertion handle. Returning false forces this window * to never appear. * @return false */ boolean canPaste() { return false; } /** This is a replacement method for the base TextView class' method of the same name. This method * is used in hidden class android.widget.Editor to determine whether the PASTE/REPLACE popup * appears when triggered from the text insertion handle. Returning false forces this window * to never appear. * @return false */ @Override public boolean isSuggestionsEnabled() { return false; } public NoMenuEditText(Context context) { super(context); this.context = context; init(); } public NoMenuEditText(Context context, AttributeSet attrs) { super(context, attrs); this.context = context; init(); } public NoMenuEditText(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); this.context = context; init(); } private void init() { this.setCustomSelectionActionModeCallback(new ActionModeCallbackInterceptor()); this.setLongClickable(false); } /** * Prevents the action bar (top horizontal bar with cut, copy, paste, etc.) from appearing * by intercepting the callback that would cause it to be created, and returning false. */ private class ActionModeCallbackInterceptor implements ActionMode.Callback { private final String TAG = NoMenuEditText.class.getSimpleName(); public boolean onCreateActionMode(ActionMode mode, Menu menu) { return false; } public boolean onPrepareActionMode(ActionMode mode, Menu menu) { return false; } public boolean onActionItemClicked(ActionMode mode, MenuItem item) { return false; } public void onDestroyActionMode(ActionMode mode) {} } }


Comments