Disable EditText context menu

Suragch picture Suragch · Jan 16, 2017 · Viewed 8.9k times · Source

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.:

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

I have tried:

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:

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.

Am I out of luck?

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.

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

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

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:

enter image description here

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

Update

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.

Answer

Rjz Satvara picture Rjz Satvara · Jan 23, 2017

I have made this code for EditText, and it worked fine for such an issue.

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