Context menu(select all, copy, cut, etc) – Disabling

While implementing one of the features in the project I was working on, I was asked to disable the context menu which shows up on Edit text when the user either double tap on the text written in it or through the long press.Generally, such functionality comes into picture if the application being developed wants to keep user data safe and is limited to selected form fields such as Email, Password etc.

In order to implement the above approach, the first thing which might have popped into your mind would be to set the XML attribute value and you are done, BUT

android:longClickable="false"

Although by setting the above attribute value to false, you would not see any context menu being displayed however you still need to figure out the solution for handling double click scenario as Android doesn’t provide any native function to handle this case.

Hence in order to implement the above feature, you need to create your custom type Widget(Edit Text) to handle both the cases.So Let’s do it:

package com.sample.uikit.widget;

import android.content.Context;
import android.os.Handler;
import android.support.v7.widget.AppCompatEditText;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

import android.view.inputmethod.InputMethodManager;

/**
 * custom edit text
 */
public class McDEditText extends AppCompatEditText {

    private static final String EDITTEXT_ATTRIBUTE_COPY_AND_PASTE = "isCopyPasteDisabled";
    private static final String PACKAGE_NAME = "http://schemas.android.com/apk/res-auto";

    public CustomEditText(Context context) {
        super(context);
    }

    public CustomEditText(Context context, AttributeSet attrs) {
        super(context, attrs);
        EnableDisableCopyAndPaste(context, attrs);
    }

    /**
     * Enable/Disable Copy and Paste functionality on EditText
     *
     * @param context Context object
     * @param attrs   AttributeSet Object
     */
    private void EnableDisableCopyAndPaste(Context context, AttributeSet attrs) {
        boolean isDisableCopyAndPaste = attrs.getAttributeBooleanValue(PACKAGE_NAME,
                EDITTEXT_ATTRIBUTE_COPY_AND_PASTE, false);
        if (isDisableCopyAndPaste && !isInEditMode()) {
            InputMethodManager inputMethodManager = (InputMethodManager) 
            context.getSystemService(Context.INPUT_METHOD_SERVICE);
            this.setLongClickable(false);
            this.setOnTouchListener(new BlockContextMenuTouchListener
                                    (inputMethodManager));
        }
    }

   /**
    * Perform Focus Enabling Task to the widget with the help of handler object 
    * with some delay
    */
    private void performHandlerAction(final InputMethodManager inputMethodManager) {
        int postDelayedIntervalTime = 25;
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                McDEditText.this.setSelected(true);
                McDEditText.this.requestFocusFromTouch();
                inputMethodManager.showSoftInput(McDEditText.this, 
                              InputMethodManager.RESULT_SHOWN);
            }
        }, postDelayedIntervalTime);
    }

    /**
     * Class to Block Context Menu on double Tap
     * A custom TouchListener is being implemented which will clear out the focus
     * and gain the focus for the EditText, in few milliseconds so the selection
     * will be cleared and hence the copy paste option wil not pop up.
     * the respective EditText should be set with this listener
     */
    private class BlockContextMenuTouchListener implements View.OnTouchListener {
        private static final int TIME_INTERVAL_BETWEEN_DOUBLE_TAP = 30;
        private InputMethodManager inputMethodManager;
        private long lastTapTime = 0;

        BlockContextMenuTouchListener(InputMethodManager inputMethodManager) {
            this.inputMethodManager = inputMethodManager;
        }

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            if (event.getAction() == MotionEvent.ACTION_DOWN) {
                long currentTapTime = System.currentTimeMillis();
                if (lastTapTime != 0 && (currentTapTime - lastTapTime)
                                        < TIME_INTERVAL_BETWEEN_DOUBLE_TAP) {
                    McDEditText.this.setSelected(false);
                    performHandlerAction(inputMethodManager);
                    return true;
                } else {
                    if (lastTapTime == 0) {
                        lastTapTime = currentTapTime;
                    } else {
                        lastTapTime = 0;
                    }
                    performHandlerAction(inputMethodManager);
                    return true;
                }
            } else if (event.getAction() == MotionEvent.ACTION_MOVE) {
                McDEditText.this.setSelected(false);
                performHandlerAction(inputMethodManager);
            }
            return false;
        }
    }
}

Step2: Create an attrs.xml file if it does not exist in your project or make an entry in attrs.xml file with following lines:

<?xml version="1.0" encoding="UTF-8"?>
<resources>
      <declare-styleable name="CustomEditText">
        <attr name="isCopyPasteDisabled" format="boolean" />
    </declare-styleable>
</resources>

Step 3: Create a drawable file(disable_copy_paste_handler.xml), to disable the Text Selection Handler which one can see below the blinking cursor when text is written in the Edit Text.

<!--Disable the Text Selection Handle-->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <size
        android:width="0dp"
        android:height="0dp" />
</shape>

Step4: Now Your XML file, where you would be using this custom widget(CustomEditText) would look something like this:

< com.sample.uikit.widget.CustomEditText
    android:id="@+id/email"
    android:layout_width= "match_parent"
    android:layout_height= "50dp"
    android:layout_marginTop="5dp"
    android:hint="@string/email"
    app:isCopyPasteDisabled="true"
    android:textSelectHandle="@drawable/disable_copy_paste_handler"
    android:inputType="textEmailAddress" />

Bingo !! You are done, following the above steps you would not see the context menu popping up when user double tap / Long Press on the Custom Editext we developed in this blog post.

Note: For any suggestion or guidance feel free to contact me.

4 thoughts on “Context menu(select all, copy, cut, etc) – Disabling”

  1. Context menu(select all, copy, cut, etc) – Disabling – Sarabjit’s Blog, working on, I was asked to disable the context menu which shows up on Edit text package com.sample.uikit.widget; import android.content. 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.

Leave a Reply

Your email address will not be published. Required fields are marked *