Android: 如何完全禁用Edittext的复制和粘贴功能

7

我是一名新手,刚涉足安卓开发领域,最近遇到了一个棘手的问题。

我正在尝试创建一个Edittext,它不应允许用户从其中复制或粘贴内容。我查阅了很多资料,发现有两种常见方法:

第一种方法是在布局文件中设置:

android:longClickable="false"

第二种设置方式,可以通过编程实现:

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

但是我发现无论我选择哪种方式,编辑文本区域只能从长按可点击禁用,这会防止用户通过长按访问“全选、复制和粘贴”菜单。但是这两种解决方案都不能防止用户仅通过光标的简单点击来访问“粘贴”功能。

所以我的问题是:如何完全阻止用户在某个特定的Edittext中进行复制和粘贴功能呢?有人能帮忙吗?非常感谢。


1
可能是重复问题。如何禁用EditText中的复制粘贴? - Dhinakaran Thennarasu
1
@Dhina OP已经提到了在重复链接中使用的代码。他/她仍然有问题。 - The Holy Coder
嗨@Dhina。我已经尝试了你给我的链接中的所有答案,但正如我上面提到的,所有方法都不能防止用户通过轻敲光标来使用“粘贴”功能。因此,我需要更好的解决方案。 - jinnancun
嗨@jinnancun,你找到解决方案了吗? - Sundeep Badhotiya
4个回答

6
你可以完全隐藏“全选、复制和粘贴”菜单,以及在光标上简单点击时弹出的“粘贴”功能。
为此,你需要创建一个自定义的EditText类。以下是一个示例...
// Custom EditText class
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) {}
    }
} 

将此EditText放入您的布局中。现在,它将不会显示任何复制/粘贴菜单。它只会显示蓝色句柄,但是当您点击它时,您将不会得到任何粘贴选项的弹出窗口。

希望这可以帮助...


5
最佳的编程方式是:
myEdittext.setLongClickable(false);

或者,只是在xml中。
android:longClickable="false"

考虑通过提供最少的解释来改进您的答案。即使它可能回答了问题,但这是一个低质量的答案。 - HDJEMAI
这已经被OP尝试过了,它在问题中 - 只是从那里复制并列为答案?这本身并不能满足用户所遇到的问题。 - Lunchbox

0

解决方案非常简单

public class MainActivity extends AppCompatActivity {

EditText et_0;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    et_0 = findViewById(R.id.et_0);

    et_0.setCustomSelectionActionModeCallback(new ActionMode.Callback() {
        @Override
        public boolean onCreateActionMode(ActionMode mode, Menu menu) {
            //to keep the text selection capability available ( selection cursor)
            return true;
        }

        @Override
        public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
            //to prevent the menu from appearing
            menu.clear();
            return false;
        }

        @Override
        public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
            return false;
        }

        @Override
        public void onDestroyActionMode(ActionMode mode) {

        }
    });
   }
}

示例预览


-1

有一种可能性,就是禁用光标处理程序。您将无法获得粘贴按钮,但也无法使用触摸移动光标。

@Override
public boolean onTouchEvent(MotionEvent event) {
    if (event.getActionMasked() == MotionEvent.ACTION_UP && mDisableCursorHandle) {
        // Hack to prevent keyboard and insertion handle from showing.
        cancelLongPress();
    }
    return super.onTouchEvent(event);
}

1
嗨,Ricardo,感谢您提供的简洁解决方案。但是我确实需要显示光标。所以也许我仍然需要找其他的解决方案。无论如何还是谢谢。 - jinnancun
3
Ricardo,你从哪里获取mDisableCursorHandle - nicoqueijo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接