禁用EditText上下文菜单 [英] Disable EditText context menu

查看:124
本文介绍了禁用EditText上下文菜单的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为传统蒙古语制作垂直EditText.我已经通过在旋转的ViewGroup内嵌入稍微修改的EditText来成功实现了它.我需要创建一个完全自定义的上下文菜单,因为系统之一不支持垂直文本,并且在旋转ViewGroup时也不旋转.所以我想完全禁用系统上下文菜单.

I am making a vertical EditText for traditional Mongolian. I have successfully implemented it by embedding a slightly modified EditText inside of a rotated ViewGroup. I need to create a completely custom context menu because the system one does not support vertical text and is also not rotated when the ViewGroup is rotated. So I want to disable the system context menu altogether.

请注意,这与仅尝试禁用复制/粘贴/等的以下问题不同:

Note that this is different than these questions that are just trying to disable copy/paste/etc.:

  • How to disable copy/paste from/to EditText
  • EditText: Disable Paste/Replace menu pop-up on Text Selection Handler click event
  • how to disable paste option in android EditText
  • Android: How to TOTALLY disable copy and paste function in Edittext

尽管我没有在模拟器中显示上下文菜单,但是却在我的Android 5.0.2小米手机中显示了上下文菜单.

Although I don't get the context menu appearing in the simulator, I get it appearing in my Android 5.0.2 Xiaomi phone.

我尝试过:

  • the setCustomSelectionActionModeCallback "solution"
  • the setLongClickable(false); "solution"
  • the onTouchEvent "solution"

我愿意接受黑客攻击,但我需要它来在各种设备上保持一致的工作.马克·墨菲(下议院议员)前一段时间回覆另一个试图做类似事情的用户:

I'm open to hacks but I need it to consistently work across devices. Mark Murphy (a Commons Guy) wrote some time back in reply to another user trying to do something similar:

我怀疑即使您想出答案,也无法解决问题 跨设备.设备制造商倾向于将他们的产品推向市场 自己的EditText的上下文菜单",击败了开发人员添加的尝试 项目进入该上下文菜单.我的猜测是试图阻止 上下文菜单也会有类似的结果.

I suspect that even if you come up with an answer, it will not work across devices. Device manufacturers have had a tendency to roll their own "context menu" for EditText, defeating developers' attempts to add items into that context menu. My guess is that trying to block that context menu will have similar results.

我不走运吗?

我现在唯一想到的就是从头开始完全重写TextViewEditText(通过修改Android源代码).我知道其他人也做了类似的事情,但是他的代码不是开源的.在迈出这一重要步骤之前,我想尝试在Stack Overflow上寻求一个更简单的解决方案.

The only thing I can think of now is to completely rewrite TextView and EditText from scratch (well, by modifying the Android source). I know someone else who did something similar, but his code isn't open source. Before I take this major step, I want to try asking for a simpler solution here on Stack Overflow.

更新:在过去的两天里,我一直在尝试修改TextView源代码,它看起来像一个6个月的项目.它是大量相互关联的类.我需要其他解决方案,但是我没有主意.

Update: I've been trying modify the TextView source code for the past two days and it looks like a 6 month project. It is a mass of interrelated classes. I need another solution, but I am out of ideas.

MVCE

这是我想到的最简单的方法来重现问题.我的自定义EditText没有任何必要.通过替换默认项目Hello World的TextView,布局中只有一个EditText.我将min API更改为11,以避免处理不赞成使用的方法.

This is the simplest way I could think of to recreate the problem. There is nothing necessary from my custom EditText. The layout has a single EditText made by replacing the default project Hello World's TextView. I changed the min API to 11 to avoid dealing with deprecated methods.

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)中的上下文菜单.这是一张图片:

The context menu in the simulator (running API 24) still shows when I click on the cursor handle (but not on a long click or double click). Here is an image:

在运行Android 5.0的小米MIUI手机上,在所有情况下(光标单击,长按,双击),都会显示上下文菜单.

On my Xiaomi MIUI phone running Android 5.0, I get the context menu in all situations (cursor handle click, long click, double click).

Aritra Roy的解决方案可在模拟器,他测试过的其他设备以及我的设备上使用.我接受了他的回答,因为它可以解决我原来的问题.唯一的负面影响是文本选择也被禁用​​.

Aritra Roy's solution is working in the simulator, on some other devices that he has tested, and on my device. I have accepted his answer because it solves my original problem. The only negative side effect is that text selection is also disabled.

推荐答案

您需要做三件事.

STEP 1

您可以通过从这些方法返回false来禁用上下文菜单的显示,

You can disable the context menus from appearing by returning false from these methods,

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;
            }
        });

STEP 2

也必须在EditText中禁用长按.

It is necessary to disable the long-click in the EditText as well.

mEditText.setLongClickable(false);

或执行此操作,以XML格式android:longClickable="false".

or doing this, android:longClickable="false" in XML.

第3步

现在,您需要防止在单击手柄时出现菜单.解决方案很简单,

Now, you need to prevent the menus from appearing when the handles are clicked. The solution is simple,

1)扩展EditText类,

2)覆盖isSuggestionsEnabled()并返回false

3)创建一个canPaste()方法并返回false.这是方法隐藏.

3) Create a canPaste() method and return false. This is method hiding.

快速解决方案

如果您不想手动执行所有这些操作.这是一个自定义EditText类,您可以使用它来快速完成此操作.但是我仍然建议您一次完成这些步骤,以了解事情的工作原理.

If you don't want to do all these manually. Here is a custom EditText class you can use to get this done quickly. But I still recommend you to go through the steps once to understand how things work.

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上下文菜单的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆