Подтвердить что ты не робот

Отключить контекстное меню 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 работает в симуляторе, на некоторых других устройствах, которые он тестировал, и на моем устройстве. Я принял его ответ, потому что он решает мою оригинальную проблему. Единственным отрицательным побочным эффектом является то, что выбор текста также отключен.

4b9b3361

Ответ 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/...