EditText:禁用文本选择处理程序单击事件上的粘贴

时间:2023-03-30
本文介绍了EditText:禁用文本选择处理程序单击事件上的粘贴/替换菜单弹出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的目标是拥有一个没有花哨功能的 EditText,只是用于更轻松地移动光标的文本选择处理程序——因此没有上下文菜单或弹出窗口.

根据 类,并相应地阻止所有事件.

有关坚韧不拔的细节,请继续阅读.

解决办法在于防止PASTE/REPLACE菜单出现在show() 方法的(未记录)android.widget.Editor 类.在菜单出现之前,会检查 if (!canPaste && !canSuggest) return;.作为设置这些变量的基础的两个方法都在 EditText 类中:

  • isSuggestionsEnabled() 是 public,因此可能会被覆盖.
  • canPaste() 不是,因此必须被 在派生类中引入同名函数.

因此,将这些更新合并到一个类中,该类也具有 setCustomSelectionActionModeCallback 和 禁用长按,这里是防止所有编辑的完整类(但仍然显示文本选择处理程序) 用于控制光标:

包 com.cjbs.widgets;导入android.content.Context;导入android.util.AttributeSet;导入android.view.ActionMode;导入 android.view.Menu;导入android.view.MenuItem;导入 android.widget.EditText;/*** 这是 EditText 上的薄薄的一层,删除了复制/粘贴/拼写检查.*/公共类 NoMenuEditText 扩展 EditText{私有最终上下文上下文;/** 这是基本 TextView 类的同名方法的替换方法.这* 在隐藏类android.widget.Editor中使用方法来判断PASTE/REPLACE是否弹出* 从文本插入句柄触发时出现.返回 false 强制此窗口*永远不会出现.* @return 假*/布尔值 canPaste(){返回假;}/** 这是基本 TextView 类的同名方法的替换方法.这种方法* 用于隐藏类android.widget.Editor 判断PASTE/REPLACE 是否弹出* 从文本插入句柄触发时出现.返回 false 强制此窗口*永远不会出现.* @return 假*/@覆盖公共布尔 isSuggestionsEnabled(){返回假;}公共 NoMenuEditText(上下文上下文){超级(上下文);this.context = 上下文;在里面();}public NoMenuEditText(上下文上下文,AttributeSet attrs){超级(上下文,属性);this.context = 上下文;在里面();}public NoMenuEditText(上下文上下文,AttributeSet attrs,int defStyle){超级(上下文,属性,defStyle);this.context = 上下文;在里面();}私人无效初始化(){this.setCustomSelectionActionModeCallback(new ActionModeCallbackInterceptor());this.setLongClickable(false);}/*** 防止出现操作栏(带有剪切、复制、粘贴等的顶部水平栏)* 通过拦截将导致它被创建的回调,并返回 false.*/私有类 ActionModeCallbackInterceptor 实现 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;}公共无效 onDestroyActionMode(ActionMode 模式) {}}}

我已经在 Android v4.4.2 和 v4.4.3 中对此进行了测试.

My goal is to have an EditText that has no fancy features, just the Text Selection Handler for moving the cursor more easily -- so no context menus or pop-ups.

I've disabled the appearance of the text editing function actionbar (copy/Paste etc.) by consuming the ActionMode Callback event, as per this solution.

The middle Middle Text Select Handle (see image below) still appears when text exists in the field and a click occurs within the text. Great! I want to keep this behaviour. What I DON'T want is the "PASTE" menu to appear when the Text Select Handle itself is clicked.

I have also disabled long-click input for the EditText by setting android:longClickable="false" in the styles XML. Disabling the long click prevents the "Paste/Replace" menu from appearing when the mouse is clicked and held (i.e. long touch), however when the mouse is clicked (single touch) within the text, the text selection handle appears, and when the text selection handle itself is clicked, then the "paste" menu option appears (when there's text in the clipboard). This is what I'm trying to prevent.

From what I can see from the source, the ActionPopupWindow is what pops up with the PASTE/REPLACE options. ActionPopupWindow is a protected variable (mActionPopupWindow) in the private abstract class HandleView within public class android.widget.Editor...

Short of disabling the clipboard service or editing the Android Source code, is there a way that I can prevent this from showing? I tried to define a new style for android:textSelectHandleWindowStyle, and set android:visibility to gone, but it didn't work (app froze for a while when it would otherwise have shown).

解决方案

Solution: Override isSuggestionsEnabled and canPaste in EditText.

For the quick solution, copy the class below - this class overrides the EditText class, and blocks all events accordingly.

For the gritty details, keep reading.

The solution lies in preventing PASTE/REPLACE menu from appearing in the show() method of the (non-documented) android.widget.Editor class. Before the menu appears, a check is done to if (!canPaste && !canSuggest) return;. The two methods that are used as the basis to set these variables are both in the EditText class:

  • isSuggestionsEnabled() is public, and may thus be overridden.
  • canPaste() is not, and thus must be hidden by introducing a function of the same name in the derived class.

So incorporating these updates into a class that also has the setCustomSelectionActionModeCallback, and the disabled long-click, here is the full class to prevent all editing (but still display the text selection handler) for controlling the cursor:

package com.cjbs.widgets;

import android.content.Context;
import android.util.AttributeSet;
import android.view.ActionMode;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.EditText;


/**
 *  This is a thin veneer over EditText, with copy/paste/spell-check removed.
 */
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) {}
    }
} 

I've tested this in Android v4.4.2 and v4.4.3.

这篇关于EditText:禁用文本选择处理程序单击事件上的粘贴/替换菜单弹出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持html5模板网!

上一篇:2.3 上带有完成 SoftInput 操作标签的多行 EditText 下一篇:没有了

相关文章

最新文章