Отключить контекстное меню EditText
Я делаю вертикальный EditText
для традиционного монгольского. Я успешно реализовал его, введя слегка измененный EditText
внутри повернутого ViewGroup
. Мне нужно создать полностью настраиваемое контекстное меню, потому что система не поддерживает вертикальный текст и не поворачивается при повороте ViewGroup
. Поэтому я хочу полностью отключить контекстное меню системы.
Обратите внимание, что это отличается от этих вопросов, которые просто пытаются отключить copy/paste/etc.:
Хотя я не получаю контекстное меню, появляющееся в симуляторе, я получаю его на моем Android 5.0.2 Xiaomi.
Я пробовал:
Я открыт для взлома, но мне нужно, чтобы он постоянно работал на разных устройствах. Марк Мерфи (Commons Guy) написал некоторое время назад в ответ другому пользователю, пытающемуся сделать что-то подобное:
Я подозреваю, что даже если вы придумаете ответ, это не сработает через устройства. У производителей устройств была склонность собственное "контекстное меню" для EditText, победив попытки разработчиков добавить элементов в это контекстное меню. Я предполагаю, что попытка блокировать контекстное меню будет иметь похожие результаты.
Мне повезло?
Единственное, что я могу сейчас подумать, - полностью переписать TextView
и EditText
с нуля (ну, изменив исходный код Android). Я знаю кого-то другого, кто сделал что-то подобное, но его код не является открытым исходным кодом. Прежде чем я сделаю этот важный шаг, я хочу попытаться попросить более простое решение здесь в Stack Overflow.
Обновление: Я пытался изменить исходный код 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 я получаю контекстное меню во всех ситуациях (щелчок курсора, длинный щелчок, двойной щелчок).
Update
Решение Aritra Roy работает в симуляторе, на некоторых других устройствах, которые он тестировал, и на моем устройстве. Я принял его ответ, потому что он решает мою оригинальную проблему. Единственным отрицательным побочным эффектом является то, что выбор текста также отключен.
Ответы
Ответ 1
Есть три вещи, которые вам нужно сделать.
ШАГ 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
Необходимо также отключить длинный щелчок в EditText.
mEditText.setLongClickable(false);
или сделать это, android:longClickable="false"
в XML.
ШАГ 3
Теперь вам нужно запретить появлению меню при щелчке по ручкам. Решение прост,
1) Расширьте класс EditText
,
2) Отмените isSuggestionsEnabled()
и верните false
,
3) Создайте метод 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) {
}
}
}
Ответ 2
Я сделал этот код для 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();
}
Ответ 3
mEditText.setLongClickable(false);
Его самый простой способ отключить редактируемый текст.
Ответ 4
Вот как вы блокируете меню копирования пасты в любом виде, форме или форме. Эта ошибка действительно сводила меня с ума, и, как и с любой ошибкой Samsung, вы знаете ее в своем коде, но вы также знаете, что они не исправит ее в ближайшее время. В любом случае, здесь чудесная стена...
-
Убедитесь, что Android.Build.Model.toLowerCase(). startWith ('sm-g930'). Не совпадают со всей строкой, последняя буква - это младший идентификатор версии. Я сохранил эту логическую переменную в переменной shouldBlockCopyPaste, которая появляется позже.
-
Если это соответствует, вы хотите заблокировать меню копирования вставки. Вот как вы НАСТОЯТЕЛЬНО ДЕЛАЕМ ЭТО!!!
Отмените эти 2 функции, вы увидите, что мой mustBlockCopyPaste логический, это значит, что другие устройства не блокируются.
@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);
}
}
Ответ 5
попробуйте это
mEditText.setClickable(false);
mEditText.setEnabled(false);
UPDATE
Попробуйте это решение, расширив 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) {}
}
}
Ссылка: fooobar.com/info/72552/...