禁用的EditText上下文菜单禁用的EditText上下文菜单(Disable EditText

2019-05-11 22:46发布

我想提出一个垂直EditText传统蒙古。 我已经成功地通过嵌入略加修改实现了它EditText一个旋转的内部ViewGroup 。 我需要创建一个完全自定义的快捷菜单,因为系统中的一个不支持垂直文本;当也没有转动ViewGroup旋转。 所以我想完全禁用系统的上下文菜单。

请注意,这是比这些问题,这只是试图禁用复制/粘贴/等不同:

  • 如何禁用复制/粘贴/到的EditText
  • EditText上:禁止粘贴/替换菜单弹出的文本选择处理程序click事件
  • 如何禁用的Android EditText上粘贴选项
  • 安卓:如何TOTALLY禁止复制和粘贴功能EDITTEXT

虽然我没有得到上下文菜单中出现的模拟器,我把它在我的Android 5.0.2小蜜手机出现。

我试过了:

  • setCustomSelectionActionModeCallback “解决方案”
  • 所述setLongClickable(false); “解”
  • onTouchEvent “解决方案”

我打开黑客,但我需要它在任何设备上工作。 马克·墨菲(下议院人) 写了一段时间,早在回答其他用户试图做同样的事情:

我怀疑,即使你想出一个答案,它不会跨设备使用。 设备制造商不得不打滚的EditText自己的“上下文菜单”的倾向,击败开发者试图将项目添加到该上下文菜单。 我的猜测是,试图阻止上下文菜单中都会有类似的结果。

难道我的运气?

我现在能想到的唯一的事情是完全重写TextViewEditText从头开始(当然,通过修改Android的源)。 我知道别人谁做了类似的事情,但他的代码是不是开源。 之前我借此大步,我想试着问这里一个简单的解决方案堆栈溢出。

更新:我一直在试图修改TextView源代码,在过去的两天,它看起来像一个6个月的项目。 这是相互关联的类的质量。 我需要另一种解决方案,但我的想法。

MVCE

这是我能想到的重现问题的最简单方法。 有没有必要从我的自定义EditText 。 布局有一个单一EditText通过更换默认的项目你好世界作出TextView 。 我改变了API分至11免处理过时的方法。

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)的上下文菜单仍然显示,当我上的光标手柄单击(但不是在长按或双击)。 以下是图像:

在我运行的是Android 5.0小米MIUI手机,我得到在所有情况下(光标句柄点击,长按,双击)的上下文菜单。

更新

Aritra罗伊的解决方案是工作在模拟器上,他已经测试了一些其他的设备,我的设备上。 我已经接受了他的答案,因为它解决了我原来的问题。 唯一的负面副作用是文本的选择也将被禁用。

Answer 1:

有你需要做三件事情。

步骤1

您可以通过这些方法返回false禁止从出现的上下文菜单,

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

第2步

有必要禁止在EditText上长点击为好。

mEditText.setLongClickable(false);

或者这样, android:longClickable="false"的XML。

STEP 3

现在,你需要防止菜单从被点击手柄时出现。 解决方法很简单,

1)扩展EditText类,

2)覆盖isSuggestionsEnabled()并返回false

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

快速解决方案

如果你不想手动做这些。 这里是你可以用它来得到这个快速完成定制的EditText类。 不过我还是建议你去完成这些步骤一下子明白事情是如何工作的。

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


Answer 2:

我已经为这个代码EditText ,而且对这一问题工作的罚款。

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


Answer 3:

解决的方法很简单

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

        }
    });
   }
}



Answer 4:

mEditText.setLongClickable(false);

它禁用编辑文本的最简单方法。



Answer 5:

这是怎么出现在任何方式,形状或形式阻止复制粘贴菜单。 这个错误真的让我抓狂,而且与任何三星的bug,你在他们的代码知道它,但你也知道,他们不会很快修复它的任何时间。 不管怎么说,这里的奇迹墙...

  1. 检查Android.Build.Model.toLowerCase()。startsWith( 'SM-G930')。 不要将整个字符串匹配,最后一个字母是次要版本标识符。 我保存这个布尔在shouldBlockCopyPaste变量后来出现。

  2. 如果匹配要从显示阻止复制粘贴菜单。 这是你如何真正做到这一点!

覆盖这些2个功能,你会发现我的shouldBlockCopyPaste布尔,这是如此的其他设备不被阻塞。

   @Override
   public ActionMode StartActionMode (ActionMode.Callback callback){
      if (shouldBlockCopyPaste) {
        return null;
      } else {
        return super.StartActionMode(callback);
      }
    }

   @Override
   public ActionMode StartActionMode (ActionMode.Callback callback, int type){
      if (shouldBlockCopyPaste) {
        return null;
      } else {
        return super.StartActionMode(callback, type);
      }
    }


Answer 6:

试试这个

mEditText.setClickable(false);
mEditText.setEnabled(false);

UPDATE

通过扩展EDITTEXT尝试这种解决方案,

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

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

参考: https://stackoverflow.com/a/28893714/5870896



文章来源: Disable EditText context menu