【问题标题】:How to disable copy/paste from/to EditText如何禁用从/到 EditText 的复制/粘贴
【发布时间】:2011-09-10 15:27:13
【问题描述】:

在我的应用程序中,有一个注册屏幕,我不希望用户能够将文本复制/粘贴到 EditText 字段中。我在每个EditText 上设置了一个onLongClickListener,因此不会显示显示复制/粘贴/输入方法和其他选项的上下文菜单。因此用户将无法复制/粘贴到编辑字段中。

 OnLongClickListener mOnLongClickListener = new OnLongClickListener() {

        @Override
        public boolean onLongClick(View v) {
            // prevent context menu from being popped up, so that user
            // cannot copy/paste from/into any EditText fields.
            return true;
        }
    };

但是,如果用户启用了除 Android 默认设置之外的第三方键盘(可能具有复制/粘贴按钮或可能显示相同的上下文菜单),则会出现问题。那么在这种情况下如何禁用复制/粘贴呢?

如果还有其他方法可以复制/粘贴,请告诉我。 (以及如何禁用它们)

任何帮助将不胜感激。

【问题讨论】:

  • 如果“粘贴”操作来自 IME,那么您没有标准方法可以将其与普通击键区分开来。一个尝试的想法是测量每个角色到达之间的时间,如果时间太短,那么这些角色来自“粘贴”操作。
  • 似乎是肮脏的解决方案!不过值得一看。
  • 使用 android:longClickable="false"
  • 给大家的结论似乎是:你真的做不好。但是,出于我个人的目的,我想禁用粘贴,因为我无法处理存在的某些字符,并且粘贴可以允许它们进入我的 EditText。然后一个解决方案是添加一个文本更改侦听器,并在 afterTextChanged 方法中,如果它们在那里,则删除这些字符。您可以添加多个侦听器,从而创建一个来防止文本太长、无效字符等。这是可取的。但如果有人正在寻找一个半体面的解决方法,我想就是这样。

标签: android-widget android-edittext android android-keypad


【解决方案1】:

最好的方法是使用:

etUsername.setLongClickable(false);

【讨论】:

  • 或者,只是在 xml 中 android:longClickable="false" :)
  • 点击蓝色光标指示器会出现粘贴按钮。
  • 这样肯定会阻止视图长按,但是也可以通过双击文本来请求编辑控件,也就是说这个方案并不完整。为了您的目的,请记住这一点。
  • 此外,键盘快捷键仍然可以使用外部键盘 (Ctrl+C)。
  • 这不适用于冰淇淋三明治,因为剪贴板选项可以通过双击文本以及长按来打开。
【解决方案2】:

如果您使用的是 API 级别 11 或更高级别,那么您可以阻止复制、粘贴、剪切和自定义上下文菜单的出现。

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

从 onCreateActionMode(ActionMode, Menu) 返回 false 将阻止启动操作模式(全选、剪切、复制和粘贴操作)。

【讨论】:

  • 13以下的api级别怎么办?
  • 不了解 cmets,此示例工作 api11+,pre-api11 没有复制和粘贴 IIRC
  • 不适合我。点击蓝色光标指示器会出现粘贴按钮。
  • 也不适合我。双击显示复制粘贴菜单。
  • 这在 android 6.0 上不再工作,检查这个答案stackoverflow.com/questions/27869983/…
【解决方案3】:

您可以通过禁用长按 EditText 来做到这一点

要实现它,只需在 xml 中添加以下行 -

android:longClickable="false"

【讨论】:

  • 问题是我的应用用户有一个第三方键盘,它有一个复制和粘贴按钮。
  • 另一个问题是你可以通过双击选择文本,它会再次显示复制/粘贴
【解决方案4】:

我可以通过以下方式禁用复制和粘贴功能:

textField.setCustomSelectionActionModeCallback(new ActionMode.Callback() {

    public boolean onCreateActionMode(ActionMode actionMode, Menu menu) {
        return false;
    }

    public boolean onPrepareActionMode(ActionMode actionMode, Menu menu) {
        return false;
    }

    public boolean onActionItemClicked(ActionMode actionMode, MenuItem item) {
        return false;
    }

    public void onDestroyActionMode(ActionMode actionMode) {
    }
});

textField.setLongClickable(false);
textField.setTextIsSelectable(false);

希望它对你有用 ;-)

【讨论】:

  • 这与我根据上面的其他答案最终得到的解决方案完全相同。这应该被标记为正确的解决方案,因为它处理了其他人不处理的边缘情况
  • 此选项会阻止复制,但您仍然可以通过单击光标进行粘贴。
【解决方案5】:

Kotlin 解决方案:

fun TextView.disableCopyPaste() {
    isLongClickable = false
    setTextIsSelectable(false)
    customSelectionActionModeCallback = object : ActionMode.Callback {
        override fun onCreateActionMode(mode: ActionMode?, menu: Menu): Boolean {
            return false
        }

        override fun onPrepareActionMode(mode: ActionMode?, menu: Menu): Boolean {
            return false
        }

        override fun onActionItemClicked(mode: ActionMode?, item: MenuItem): Boolean {
            return false
        }

        override fun onDestroyActionMode(mode: ActionMode?) {}
    }
}

然后你可以简单地在你的TextView上调用这个方法:

override fun onCreate() {
    priceEditText.disableCopyPaste()
}

【讨论】:

  • 嗨,我正在使用这种方法,但在此部分 object: ActionMode.Callback 上,此描述 Required:ActionMode.Callback! Found: 出现 Type mismatch 错误。知道为什么它可能不起作用吗?
  • 改用object : android.view.ActionMode.Callback
【解决方案6】:

这是在所有版本中禁用editText工作的剪切复制粘贴的最佳方法

if (android.os.Build.VERSION.SDK_INT < 11) {
        editText.setOnCreateContextMenuListener(new OnCreateContextMenuListener() {

            @Override
            public void onCreateContextMenu(ContextMenu menu, View v,
                    ContextMenuInfo menuInfo) {
                // TODO Auto-generated method stub
                menu.clear();
            }
        });
    } else {
        editText.setCustomSelectionActionModeCallback(new ActionMode.Callback() {

            public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
                // TODO Auto-generated method stub
                return false;
            }

            public void onDestroyActionMode(ActionMode mode) {
                // TODO Auto-generated method stub

            }

            public boolean onCreateActionMode(ActionMode mode, Menu menu) {
                // TODO Auto-generated method stub
                return false;
            }

            public boolean onActionItemClicked(ActionMode mode,
                    MenuItem item) {
                // TODO Auto-generated method stub
                return false;
            }
        });
    }

【讨论】:

  • 这对我有用,我只需要添加@TargetApi(Build.VERSION_CODES.HONEYCOMB)
【解决方案7】:

除了setCustomSelectionActionModeCallbackdisabled long-click解决方案外,点击文本选择句柄时需要prevent the PASTE/REPLACE menus不出现,如下图所示:

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

更完整的答案是available here

【讨论】:

  • 这是正确且完整的解决方案
  • 在某些设备中,粘贴剪贴板选项不可见,仅用作粘贴。我检查了链接,但我能够阻止粘贴但不能阻止剪贴板。有什么想法吗?
【解决方案8】:

如果您不想禁用长按,因为您需要在长按时执行某些功能,那么返回 true 是一个更好的选择。

你的edittext长按会是这样的。

edittext.setOnLongClickListener(new View.OnLongClickListener() {
      @Override
      public boolean onLongClick(View v) {
            //  Do Something or Don't
            return true;
      }
});

根据documentation 返回“True”表示长按已处理,无需执行默认操作。

我在 API 级别 16、22 和 25 上对此进行了测试。它对我来说工作正常。希望这会有所帮助。

【讨论】:

  • 好一个。或者,只需在 XML 中设置 android:longClickable="false"
【解决方案9】:

这是一个禁用“粘贴”弹出窗口的技巧。你必须重写EditText 方法:

@Override
public int getSelectionStart() {
    for (StackTraceElement element : Thread.currentThread().getStackTrace()) {
        if (element.getMethodName().equals("canPaste")) {
            return -1;
        }
    }
    return super.getSelectionStart();
}

其他动作也可以这样做。

【讨论】:

  • 你可以告诉剪贴板禁用
【解决方案10】:

我已经测试过这个解决方案,并且可以正常工作

    mSubdomainEditText.setLongClickable(false);
    mSubdomainEditText.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;
      }
    });

【讨论】:

  • 我用这个代码防止剪贴板,复制选项。谢谢
【解决方案11】:

https://github.com/neopixl/PixlUIEditText 提供了一个方法

myEditText.disableCopyAndPaste().

它适用于旧 API

【讨论】:

【解决方案12】:

我在 Kotlin 语言中添加了 Extension Function

fun EditText.disableTextSelection() {
    this.setCustomSelectionActionModeCallback(object : android.view.ActionMode.Callback {
        override fun onActionItemClicked(mode: android.view.ActionMode?, item: MenuItem?): Boolean {
            return false
        }
        override fun onCreateActionMode(mode: android.view.ActionMode?, menu: Menu?): Boolean {
            return false
        }
        override fun onPrepareActionMode(mode: android.view.ActionMode?, menu: Menu?): Boolean {
            return false
        }
        override fun onDestroyActionMode(mode: android.view.ActionMode?) {
        }
    })
}

你可以这样使用它:

edit_text.disableTextSelection()

还在您的 xml 中添加以下行:

                android:longClickable="false"
                android:textIsSelectable="false"

【讨论】:

    【解决方案13】:

    @Zain Ali,您的答案适用于 API 11。我只是想建议一种方法也适用于 API 10。由于我必须在那个版本上维护我的项目 API,我一直在使用 2.3.3 中可用的功能并且有可能做到这一点。我在下面分享了sn-p。我测试了代码,它对我有用。我紧急做了这个sn-p。如果可以进行任何更改,请随时改进代码..

    // 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 
    // tmpEditText.setOnTouchListener(new MyTouchListener(tmpEditText, tmpImm));
    
    public class MyTouchListener implements View.OnTouchListener {
    
        long click = 0;
        EditText mEtView;
        InputMethodManager imm;
    
        public MyTouchListener(EditText etView, InputMethodManager im) {
            mEtView = etView;
            imm = im;
        }
    
        @Override
        public boolean onTouch(View v, MotionEvent event) {
    
            if (event.getAction() == MotionEvent.ACTION_DOWN) {
                long curr = System.currentTimeMillis();
                if (click !=0 && ( curr - click) < 30) {
    
                    mEtView.setSelected(false);
                    new Handler().postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            mEtView.setSelected(true);
                            mEtView.requestFocusFromTouch();
                            imm.showSoftInput(mEtView, InputMethodManager.RESULT_SHOWN);
                        }
                    },25);
    
                return true;
                }
                else {
                    if (click == 0)
                        click = curr;
                    else
                        click = 0;
                    new Handler().postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            mEtView.requestFocusFromTouch();
                            mEtView.requestFocusFromTouch();
                            imm.showSoftInput(mEtView, InputMethodManager.RESULT_SHOWN);
                        }
                    },25);
                return true;
                }
    
            } else if (event.getAction() == MotionEvent.ACTION_MOVE) {
                mEtView.setSelected(false);
                new Handler().postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        mEtView.setSelected(true);
                        mEtView.requestFocusFromTouch();
                        mEtView.requestFocusFromTouch();
                        imm.showSoftInput(mEtView, InputMethodManager.RESULT_SHOWN);
                    }
                },25);
                return true;
            }
            return false;
        }
    

    【讨论】:

      【解决方案14】:

      如果您想禁用 ActionMode 进行复制/粘贴,您需要覆盖 2 个回调。这适用于TextViewEditText(或TextInputEditText

      import android.view.ActionMode
      
      fun TextView.disableCopyPaste() {
        isLongClickable = false
        setTextIsSelectable(false)
        customSelectionActionModeCallback = object : ActionMode.Callback {
          override fun onCreateActionMode(mode: ActionMode?, menu: Menu) = false
          override fun onPrepareActionMode(mode: ActionMode?, menu: Menu) = false
          override fun onActionItemClicked(mode: ActionMode?, item: MenuItem) = false
          override fun onDestroyActionMode(mode: ActionMode?) {}
        }
        //disable action mode when edittext gain focus at first
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
          customInsertionActionModeCallback = object : ActionMode.Callback {
            override fun onCreateActionMode(mode: ActionMode?, menu: Menu) = false
            override fun onPrepareActionMode(mode: ActionMode?, menu: Menu) = false
            override fun onActionItemClicked(mode: ActionMode?, item: MenuItem) = false
            override fun onDestroyActionMode(mode: ActionMode?) {}
          }
        }
      }
      

      这个扩展基于@Alexandr 解决方案,对我来说效果很好。

      【讨论】:

      • 这个方案比较全面
      【解决方案15】:

      读取剪贴板,检查输入内容和“键入”输入内容的时间。如果剪贴板有相同的文本并且速度太快,请删除粘贴的输入。

      【讨论】:

        【解决方案16】:

        解决方法很简单

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

        --------> preview <---------

        【讨论】:

          【解决方案17】:

          尝试在Edittext 中复制和粘贴以下客户类

          public class SegoeUiEditText extends AppCompatEditText {
          private final Context context;
          
          
          @Override
          public boolean isSuggestionsEnabled() {
              return false;
          }
          public SegoeUiEditText(Context context) {
              super(context);
              this.context = context;
              init();
          }
          
          public SegoeUiEditText(Context context, AttributeSet attrs) {
              super(context, attrs);
              this.context = context;
              init();
          }
          
          public SegoeUiEditText(Context context, AttributeSet attrs, int defStyle) {
              super(context, attrs, defStyle);
              this.context = context;
              init();
          }
          
          
          private void setFonts(Context context) {
              this.setTypeface(Typeface.createFromAsset(context.getAssets(), "Fonts/Helvetica-Normal.ttf"));
          }
          
          private void init() {
          
                  setTextIsSelectable(false);
                  this.setCustomSelectionActionModeCallback(new ActionModeCallbackInterceptor());
                  this.setLongClickable(false);
          
          }
          @Override
          public int getSelectionStart() {
          
              for (StackTraceElement element : Thread.currentThread().getStackTrace()) {
                  if (element.getMethodName().equals("canPaste")) {
                      return -1;
                  }
              }
              return super.getSelectionStart();
          }
          /**
           * 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, android.view.ActionMode.Callback {
              private final String TAG = SegoeUiEditText.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) {}
          
              @Override
              public boolean onCreateActionMode(android.view.ActionMode mode, Menu menu) {
                  return false;
              }
          
              @Override
              public boolean onPrepareActionMode(android.view.ActionMode mode, Menu menu) {
                  menu.clear();
                  return false;
              }
          
              @Override
              public boolean onActionItemClicked(android.view.ActionMode mode, MenuItem item) {
                  return false;
              }
          
              @Override
              public void onDestroyActionMode(android.view.ActionMode mode) {
          
              }
          }
          

          }

          【讨论】:

            【解决方案18】:

            对于带有剪贴板的智能手机,可以这样防止。

            editText.setFilters(new InputFilter[]{new InputFilter() {
                    @Override
                    public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
                        if (source.length() > 1) {
                            return "";
                        }  return null;
                    }
                }});
            

            【讨论】:

            • 这失败了,因为自动更正,至少在我的设备上,有时想要在添加新输入的字符的同时替换字符。发生这种情况时,此代码认为它是一个粘贴,整个自动更正(下划线)字被删除。解决方法是查看源长度是否是目标长度加一 - 在这种情况下,可以接受字符。但这是一个杂项,并且还具有禁用“点击一个单词”以进行自动完成的效果,因为这与粘贴操作完全一样。
            【解决方案19】:

            我发现当您创建输入过滤器以避免输入不需要的字符时,将这些字符粘贴到编辑文本中没有任何效果。所以这种方式也解决了我的问题。

            【讨论】:

              【解决方案20】:

              对我有用的解决方案是创建自定义 Edittext 并覆盖以下方法:

              public class MyEditText extends EditText {
              
              private int mPreviousCursorPosition;
              
              @Override
              protected void onSelectionChanged(int selStart, int selEnd) {
                  CharSequence text = getText();
                  if (text != null) {
                      if (selStart != selEnd) {
                          setSelection(mPreviousCursorPosition, mPreviousCursorPosition);
                          return;
                      }
                  }
                  mPreviousCursorPosition = selStart;
                  super.onSelectionChanged(selStart, selEnd);
              }
              

              }

              【讨论】:

                【解决方案21】:

                尝试使用。

                myEditext.setCursorVisible(false);
                
                       myEditext.setCustomSelectionActionModeCallback(new ActionMode.Callback() {
                
                        public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
                            // TODO Auto-generated method stub
                            return false;
                        }
                
                        public void onDestroyActionMode(ActionMode mode) {
                            // TODO Auto-generated method stub
                
                        }
                
                        public boolean onCreateActionMode(ActionMode mode, Menu menu) {
                            // TODO Auto-generated method stub
                            return false;
                        }
                
                        public boolean onActionItemClicked(ActionMode mode,
                                MenuItem item) {
                            // TODO Auto-generated method stub
                            return false;
                        }
                    });
                

                【讨论】:

                  【解决方案22】:

                  谁在 Kotlin 中寻找解决方案,使用下面的类作为自定义小部件并在 xml 中使用它。

                  类 SecureEditText : TextInputEditText {

                  /** 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 fun isSuggestionsEnabled(): Boolean {
                      return false
                  }
                  
                  override fun getSelectionStart(): Int {
                      for (element in Thread.currentThread().stackTrace) {
                          if (element.methodName == "canPaste") {
                              return -1
                          }
                      }
                      return super.getSelectionStart()
                  }
                  
                  public override fun onSelectionChanged(start: Int, end: Int) {
                  
                      val text = text
                      if (text != null) {
                          if (start != text.length || end != text.length) {
                              setSelection(text.length, text.length)
                              return
                          }
                      }
                  
                      super.onSelectionChanged(start, end)
                  }
                  
                  companion object {
                      private val EDITTEXT_ATTRIBUTE_COPY_AND_PASTE = "isCopyPasteDisabled"
                      private val PACKAGE_NAME = "http://schemas.android.com/apk/res-auto"
                  }
                  
                  constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
                      disableCopyAndPaste(context, attrs)
                  }
                  
                  /**
                   * Disable Copy and Paste functionality on EditText
                   *
                   * @param context Context object
                   * @param attrs   AttributeSet Object
                   */
                  private fun disableCopyAndPaste(context: Context, attrs: AttributeSet) {
                      val isDisableCopyAndPaste = attrs.getAttributeBooleanValue(
                          PACKAGE_NAME,
                          EDITTEXT_ATTRIBUTE_COPY_AND_PASTE, true
                      )
                      if (isDisableCopyAndPaste && !isInEditMode()) {
                          val inputMethodManager =
                              context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
                          this.setLongClickable(false)
                          this.setOnTouchListener(BlockContextMenuTouchListener(inputMethodManager))
                      }
                  }
                  
                  /**
                   * Perform Focus Enabling Task to the widget with the help of handler object
                   * with some delay
                   * @param inputMethodManager is used to show the key board
                   */
                  private fun performHandlerAction(inputMethodManager: InputMethodManager) {
                      val postDelayedIntervalTime: Long = 25
                      Handler().postDelayed(Runnable {
                          this@SecureEditText.setSelected(true)
                          this@SecureEditText.requestFocusFromTouch()
                          inputMethodManager.showSoftInput(
                              this@SecureEditText,
                              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
                   *
                   * @param inputMethodManager is used to show the key board
                   */
                  private inner class BlockContextMenuTouchListener internal constructor(private val inputMethodManager: InputMethodManager) :
                      View.OnTouchListener {
                      private var lastTapTime: Long = 0
                      val TIME_INTERVAL_BETWEEN_DOUBLE_TAP = 30
                      override fun onTouch(v: View, event: MotionEvent): Boolean {
                          if (event.getAction() === MotionEvent.ACTION_DOWN) {
                              val currentTapTime = System.currentTimeMillis()
                              if (lastTapTime != 0L && currentTapTime - lastTapTime < TIME_INTERVAL_BETWEEN_DOUBLE_TAP) {
                                  this@SecureEditText.setSelected(false)
                                  performHandlerAction(inputMethodManager)
                                  return true
                              } else {
                                  if (lastTapTime == 0L) {
                                      lastTapTime = currentTapTime
                                  } else {
                                      lastTapTime = 0
                                  }
                                  performHandlerAction(inputMethodManager)
                                  return true
                              }
                          } else if (event.getAction() === MotionEvent.ACTION_MOVE) {
                              this@SecureEditText.setSelected(false)
                              performHandlerAction(inputMethodManager)
                          }
                          return false
                      }
                  }
                  

                  }

                  【讨论】:

                    【解决方案23】:

                    一个广泛兼容的解决方案(从 Android 1.5 开始)是

                    @Override
                    public boolean onTextContextMenuItem(int id) {
                        switch (id){
                            case android.R.id.cut:
                                onTextCut();
                                return false;
                            case android.R.id.paste:
                                onTextPaste();
                                return false;
                            case android.R.id.copy:
                                onTextCopy();
                                return false;
                        }
                        return true;
                    }
                    

                    【讨论】:

                      【解决方案24】:

                      花了很多时间,在 EditText 的 ContextMenu 中删除粘贴选项后,我在 Java 中遵循了以下代码。

                      NoMenuEditText.Java

                      import android.content.Context;
                      import android.os.Handler;
                      import android.util.AttributeSet;
                      import android.view.MotionEvent;
                      import android.view.View;
                      import android.view.inputmethod.InputMethodManager;
                      import androidx.appcompat.widget.AppCompatEditText;
                      
                      /**
                       * custom edit text
                       */
                      
                      
                      public class NoMenuEditText 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 NoMenuEditText(Context context) {
                              super(context);
                          }
                      
                          public NoMenuEditText(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() {
                                      NoMenuEditText.this.setSelected(true);
                                      NoMenuEditText.this.requestFocusFromTouch();
                                      inputMethodManager.showSoftInput(NoMenuEditText.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) {
                                          NoMenuEditText.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) {
                                      NoMenuEditText.this.setSelected(false);
                                      performHandlerAction(inputMethodManager);
                                  }
                                  return false;
                              }
                          }
                      
                          @Override
                          protected void onSelectionChanged(int selStart, int selEnd) {
                              CharSequence text = getText();
                              if (text != null) {
                                  if (selStart != text.length() || selEnd != text.length()) {
                                      setSelection(text.length(), text.length());
                                      return;
                                  }
                              }
                              super.onSelectionChanged(selStart, selEnd);
                          }
                      
                      
                          @Override
                          public boolean isSuggestionsEnabled() {
                              return false;
                          }
                      
                          @Override
                          public int getSelectionStart() {
                              for (StackTraceElement element : Thread.currentThread().getStackTrace()) {
                                  if (element.getMethodName().equals("canPaste")) {
                                      return -1;
                                  }
                              }
                              return super.getSelectionStart();
                          }
                      
                      
                      
                      }
                      

                      MainActivity

                      import androidx.appcompat.app.AppCompatActivity;
                      import android.content.ClipboardManager;
                      import android.content.Context;
                      import android.os.Bundle;
                      import android.view.ActionMode;
                      import android.view.Menu;
                      import android.view.MenuItem;
                      import android.view.View;
                      
                      public class MainActivity extends AppCompatActivity {
                      
                          NoMenuEditText edt_username;
                      
                          @Override
                          protected void onCreate(Bundle savedInstanceState) {
                              super.onCreate(savedInstanceState);
                              setContentView(R.layout.activity_main);
                      
                              edt_username = (NoMenuEditText) findViewById(R.id.edt_username);
                      
                         
                              edt_username.setLongClickable(false);
                              edt_username.setTextIsSelectable(false);
                      
                              edt_username.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) {
                      
                                  }
                              });
                              
                          }
                      
                      }
                      

                      drawable-zeropx.xml

                      <?xml version="1.0" encoding="utf-8"?>
                      <shape xmlns:android="http://schemas.android.com/apk/res/android"
                          android:shape="rectangle">
                      
                          <size
                              android:width="0dp"
                              android:height="0dp"/>
                      
                      </shape>
                      

                      attrs.xml

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

                      最后,我终于从EditText上下文菜单中删除了粘贴选项

                      谢谢StackOverflow 帖子http://androidinformative.com/disabling-context-menu/

                      【讨论】:

                        【解决方案25】:
                         editText.apply {
                                setOnTouchListener { v, event ->
                                       if (event.action == KeyEvent.ACTION_DOWN) {
                                              requestFocus()
                                              setSelection(text.toString().length)
                                              showKeyboard()
                                              return@setOnTouchListener true
                                       }
                                }
                         }
                        
                        fun View.showKeyboard() {
                                val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
                                imm.showSoftInput(this, 0)
                         }
                        

                        【讨论】:

                          【解决方案26】:

                          上述解决方案未考虑使用硬件键盘 (Ctrl+v) 进行粘贴。最简单的解决方案是在您的 EditText 上设置一个 TextWatcher,并在 afterTextChanged 方法中过滤您想要或不想要的字符。这适用于所有情况,即输入字符、粘贴、自动建议和自动更正。

                          【讨论】:

                            【解决方案27】:

                            实际上,在我的情况下,我必须为 selectioninsertion 设置回调,然后我才让复制/粘贴弹出窗口不再出现。 像这样:

                             private void disableCopyPaste() {
                                input.setLongClickable(false);
                                input.setTextIsSelectable(false);
                                final ActionMode.Callback disableCopyPasteCallback = 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) {
                                    }
                                };
                                input.setCustomSelectionActionModeCallback(disableCopyPasteCallback);
                                input.setCustomInsertionActionModeCallback(disableCopyPasteCallback);
                            }
                            

                            【讨论】:

                              【解决方案28】:

                              您可能只想阻止某些操作(如剪切/复制,但不粘贴),而不是完全禁用 EditText 上的所有操作:

                              /**
                               * Prevent copy/cut of the (presumably sensitive) contents of this TextView.
                               */
                              fun TextView.disableCopyCut() {
                                  setCustomSelectionActionModeCallback(
                                      object : Callback {
                                          override fun onActionItemClicked(mode: ActionMode?, item: MenuItem?) = false
                              
                                          override fun onCreateActionMode(mode: ActionMode?, menu: Menu?): Boolean {
                                              menu?.apply {
                                                  removeItem(android.R.id.copy)
                                                  removeItem(android.R.id.cut)
                                              }
                                              return true
                                          }
                              
                                          override fun onPrepareActionMode(mode: ActionMode?, menu: Menu?) = false
                              
                                          override fun onDestroyActionMode(mode: ActionMode?) {
                                              // no-op
                                          }
                                      }
                                  )
                              }
                              

                              可以选择性删除的操作:

                              removeItem(android.R.id.copy)
                              removeItem(android.R.id.cut)
                              removeItem(android.R.id.paste)
                              removeItem(android.R.id.shareText) // Share
                              removeItem(android.R.id.textAssist) // Open with Chrome
                              

                              【讨论】:

                                【解决方案29】:

                                它很晚,但它可以帮助某人。

                                在你的edittext xml中添加这些行

                                android:longClickable="false"
                                android:textIsSelectable="false"
                                android:importantForAutofill="no"
                                

                                【讨论】:

                                  【解决方案30】:

                                  类似于GnrlKnowledge,可以清除剪贴板

                                  http://developer.android.com/reference/android/text/ClipboardManager.html

                                  如果需要,请将文本保留在剪贴板中,并在 onDestroy 上重新设置。

                                  【讨论】:

                                    猜你喜欢
                                    • 2018-02-24
                                    • 1970-01-01
                                    • 2013-02-16
                                    • 1970-01-01
                                    • 1970-01-01
                                    • 2014-11-28
                                    • 1970-01-01
                                    • 1970-01-01
                                    • 1970-01-01
                                    相关资源
                                    最近更新 更多