EditText: отключить всплывающее меню Вставить/заменить в обработчике выбора текста нажмите событие
моя цель-иметь EditText
Это не имеет причудливых функций, просто обработчик выбора текста для перемещения курсора более легко - так что нет контекстных меню или всплывающих окон.
Я отключил внешний вид функции редактирования текста actionbar (copy / Paste и т. д.), используя событие обратного вызова ActionMode, согласно данное решение.
средний Средний текст выберите дескриптор (см. изображение ниже) по-прежнему появляется, когда текст существует в поле и происходит щелчок в тексте. Здорово! Я хочу сохранить такое поведение. Я не хочу, чтобы меню "Вставить"появлялось при нажатии на сам текстовый дескриптор.
Я также отключил длинный щелчок ввода для EditText, установив android:longClickable="false"
в XML стилей. Отключение длинного щелчка предотвращает появление меню" Вставить/заменить " при нажатии и удержании мыши (т. е. длинное касание), однако при нажатии мыши (одно касание) в тексте текст появится дескриптор выбора, и когда будет щелкнут сам дескриптор выбора текста, появится пункт меню "Вставить" (когда есть текст в буфере обмена). Это то, что я пытаюсь предотвратить.
из того, что я вижу из источника,ActionPopupWindow
это то, что появляется с параметрами вставки/замены. ActionPopupWindow-защищенная переменная (mActionPopupWindow) в частном абстрактном классе HandleView в общедоступном классе android.штучка.Редактор...
не хватает отключения служба буфера обмена или редактирование исходного кода Android, есть ли способ предотвратить это? Я попытался определить новый стиль для android:textSelectHandleWindowStyle
и set android:visibility
до gone
, но это не сработало (приложение застыло на некоторое время, когда оно в противном случае показало бы).
11 ответов
Решение: Переопределить isSuggestionsEnabled
и canPaste
на EditText
.
для быстрого решения скопируйте класс ниже - этот класс переопределяет EditText
class, и блокирует все события соответственно.
для песчаных деталей, продолжайте читать.
решение заключается в предотвращении вставки / замены меню в show()
метод (не документированный)android.widget.Editor
класса. Прежде чем появится меню, проверьте делается для if (!canPaste && !canSuggest) return;
. Два метода, которые используются в качестве основы для установки этих переменных, находятся в EditText
класс:
-
isSuggestionsEnabled()
и общественные, и, таким образом, может быть переопределен. -
canPaste()
нет, и поэтому должен быть скрыт введение функции с тем же именем в производном классе.
таким образом, включение этих обновлений в класс, который также имеет setCustomSelectionActionModeCallback и щелкните инвалидов, вот полный класс, чтобы предотвратить все редактирование (но по-прежнему отображать обработчик выбора текста) для управления курсором:
package com.cjbs.widgets;
import android.content.Context;
import android.util.AttributeSet;
import android.view.ActionMode;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.EditText;
/**
* This is a thin veneer over EditText, with copy/paste/spell-check removed.
*/
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) {}
}
}
Я проверил это в Android версии 4.4.2 и V4.4.3.
или просто использовать
yourEditText.setLongClickable(false);
или в XML
android:longClickable="false"
обновление
на самом деле пользователь хочет отключить выбор текста обрабатывать себя
1. Создайте фигуру (handle.в XML)
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<size
android:height="0dp"
android:width="0dp" />
</shape>
2. В вашем EditText
android:textSelectHandle="@drawable/handle"
найдено другое решение, когда синий Вид (Контроллер вставки) не отображается вообще. Я использовал отражение, чтобы установить целевое логическое поле класса Editor. Посмотрите на андроида.штучка.Редактор и android.штучка.TextView для более подробной информации.
добавьте следующий код в пользовательский EditText (со всем предыдущим кодом в этом разделе):
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
// setInsertionDisabled when user touches the view
this.setInsertionDisabled();
}
return super.onTouchEvent(event);
}
/**
* This method sets TextView#Editor#mInsertionControllerEnabled field to false
* to return false from the Editor#hasInsertionController() method to PREVENT showing
* of the insertionController from EditText
* The Editor#hasInsertionController() method is called in Editor#onTouchUpEvent(MotionEvent event) method.
*/
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
}
}
кроме того, возможно, вы можете найти лучшее место, чем onTouch() для вызова целевого метода.
протестировано на Android 5.1
Я не нахожу способ скрыть всплывающее меню, но вы можете отключить вставку, если пользователь нажмет на меню
создать пользовательское EditText
и переопределить onTextContextMenuItem
метод и возвращает false для android.R.id.paste
и android.R.id.pasteAsPlainText
меню идентификаторов.
@Override
public boolean onTextContextMenuItem(int id) {
switch (id){
case android.R.id.paste:
case android.R.id.pasteAsPlainText:
return false;
}
return super.onTextContextMenuItem(id);
}
вот хак, чтобы отключить всплывающее окно "вставить". Вы должны переопределить EditText
способ:
@Override
public int getSelectionStart() {
for (StackTraceElement element : Thread.currentThread().getStackTrace()) {
if (element.getMethodName().equals("canPaste")) {
return -1;
}
}
return super.getSelectionStart();
}
это решение работает и на более новых версиях Android, в отличие от принятого ответа.
Use this in java file
if (android.os.Build.VERSION.SDK_INT < 11) {
editText.setOnCreateContextMenuListener(new OnCreateContextMenuListener() {
@Override`enter code here`
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
// TODO Auto-generated method stub
menu.clear();
}
});
} else {
editText.setCustomSelectionActionModeCallback(new ActionMode.Callback() {
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
// TODO Auto-generated method stub
return false;
}
public void onDestroyActionMode(ActionMode mode) {
// TODO Auto-generated method stub
}
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
// TODO Auto-generated method stub
return false;
}
public boolean onActionItemClicked(ActionMode mode,
MenuItem item) {
// TODO Auto-generated method stub
return false;
}`enter code here`
});
}
With this code also add android:textSelectHandle="@drawable/handle"
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<size
android:height="0dp"
android:width="0dp" />
</shape>
By Using these two combinations my problem is solved.
Если вам нужно удалить предложение вставки, очистите буфер обмена перед длинным щелчком мыши.
//class
ClipboardManager clipboard;
//oncreate
clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText("","");
clipboard.setPrimaryClip(clip);
ни одно из вышеперечисленных решений не сработало для меня. Мне удалось сделать мое решение (объяснение после), которое отключило вставку чего-либо в EditText при сохранении всех других операций.
В основном, вы должны переопределить этот метод при реализации EditText:
@Override
public boolean onTextContextMenuItem (int id) {
if (id == android.R.id.paste) return false;
return super.onTextContextMenuItem(id);
}
Итак, исследуя код EditText, после всех проверок вставьте (и все ContextMenu
действия в EditText) происходят при методе onTextContextMenuItem
:
public boolean onTextContextMenuItem(int id) {
int min = 0;
int max = mText.length();
if (isFocused()) {
final int selStart = getSelectionStart();
final int selEnd = getSelectionEnd();
min = Math.max(0, Math.min(selStart, selEnd));
max = Math.max(0, Math.max(selStart, selEnd));
}
switch (id) {
case ID_SELECT_ALL:
// This does not enter text selection mode. Text is highlighted, so that it can be
// bulk edited, like selectAllOnFocus does. Returns true even if text is empty.
selectAllText();
return true;
case ID_PASTE:
paste(min, max);
return true;
case ID_CUT:
setPrimaryClip(ClipData.newPlainText(null, getTransformedText(min, max)));
deleteText_internal(min, max);
stopSelectionActionMode();
return true;
case ID_COPY:
setPrimaryClip(ClipData.newPlainText(null, getTransformedText(min, max)));
stopSelectionActionMode();
return true;
}
return false;
}
если вы заметили, оклейка произойдет только тогда, когда id == ID_PASTE
, Итак, снова, глядя на код EditText:
static final int ID_PASTE = android.R.id.paste;
Я нашел простой, но надежный способ. Идея заключается в уничтожении события касания, чтобы предотвратить достижение события касания, подчеркивая код по умолчанию.
- отключить копирования/вставки всплывающего окна.
- чтобы отключить обработчик выбора текста.
- по-прежнему отображается курсор в конце текста.
- все еще показывает клавиатуру.
maskedEditText.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
focusAndShowKeyboard(view.getContext(), maskedEditText);
// Consume the event.
return true;
}
});
private static void focusAndShowKeyboard(Context context, EditText editText) {
editText.requestFocus();
InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, InputMethodManager.HIDE_IMPLICIT_ONLY);
}
Примечание, мигающий курсор все еще отображается в конце текста. Просто скриншот не может его захватить.
просто переопределить один метод:
@Override
protected MovementMethod getDefaultMovementMethod() {
// we don't need arrow key, return null will also disable the copy/paste/cut pop-up menu.
return null;
}
Вы можете использовать этот код:
if (android.os.Build.VERSION.SDK_INT < 11) {
editText.setOnCreateContextMenuListener(new OnCreateContextMenuListener() {
@Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
// TODO Auto-generated method stub
menu.clear();
}
});
} else {
editText.setCustomSelectionActionModeCallback(new ActionMode.Callback() {
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
// TODO Auto-generated method stub
return false;
}
public void onDestroyActionMode(ActionMode mode) {
// TODO Auto-generated method stub
}
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
// TODO Auto-generated method stub
return false;
}
public boolean onActionItemClicked(ActionMode mode,
MenuItem item) {
// TODO Auto-generated method stub
return false;
}
});
}
возврат false из onCreateActionMode
отключит параметры вырезания,копирования и вставки на уровне API больше 11.