2011-06-08 88 views
80

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

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的默认以外的第三方键盘,它可以有一个按钮,复制/粘贴或可以显示相同的上下文菜单中就会出现问题。那么,我该如何禁用复制/粘贴在这种情况下?

请让我知道是否有其他方法复制/粘贴。 (并可能如何禁用它们)

任何帮助,将不胜感激。

+0

如果“粘贴”操作来自IME,那么您没有将其与正常击键区分的标准方法。要尝试的一个想法是衡量每个角色到达之间的时间,如果时间太短,则角色来自“粘贴”操作。 – BitBank 2011-11-13 17:10:16

+0

似乎是肮脏的soloution!值得一看,但。 – rDroid 2011-11-14 08:10:12

回答

77

如果您使用的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,菜单)返回false将阻止启动的动作模式(全选,剪切,复制和粘贴操作)。

+0

API级别高于13的智能手机的任何东西。这与平板电脑 – Unknown 2012-12-27 05:13:00

+1

罚款如何关于api级别低于13? – jonney 2013-02-08 11:05:02

+1

不理解任何意见,这个样本作品api11 +,pre-api11没有复制和粘贴IIRC – scottyab 2013-09-11 12:56:32

1

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

0

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

20

我可以用下面的禁用复制和粘贴功能:

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

希望它为你工作;-)

1

@Zain Ali,你的答案适用于API 11.我只是想提出一种在API 10中做的方法。由于我必须在该版本上维护我的项目API,因此我一直在玩2.3.3中提供的功能,并有可能做到这一点。我已经分享下面的代码片段。我测试了代码,它为我工作。我在紧急情况下做了这个片段。随意提高代码是否有可以做任何改变..

// 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; 
    } 
84

最好的方法是使用:

etUsername.setLongClickable(false); 
+40

或者,只需在xml'android:longClickable =“false”':) – lomza 2014-01-24 10:12:53

+13

点击蓝色光标指示器时,会出现粘贴按钮。 – void 2014-03-13 05:08:01

+10

这肯定会阻止视图长时间点击,但编辑控件也可以通过双击文本来请求,这意味着此解决方案不完整。记住你的目的。 – 2014-04-22 19:09:28

3

https://github.com/neopixl/PixlUI提供了一种方法

myEditText.disableCopyAndPaste()EditText

而且它是在旧的API

+1

这与http://stackoverflow.com/a/22756538/3063884提供的半解决方案完全相同。请参阅代码:https://github.com/neopixl/PixlUI/blob/master/Library/src/com/neopixl/pixlui/components/edittext/EditText.java#L304 ...这种方法仍然无法阻止文本选择处理程序显示“PASTE”,如果剪贴板中有文本。 – CJBS 2015-02-28 08:54:10

11

这里是禁止的EditText的长按来禁用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; 
      } 
     }); 
    } 
+0

这为我工作,我不得不添加 @TargetApi(Build.VERSION_CODES.HONEYCOMB) – Sheepdogsheep 2014-04-24 11:53:55

23

你可以这样做一个最好的方式工作

要实现它,只需添加以下行的XML -

android:longClickable="false" 
+3

的问题是,我的应用程序用户具有复制和粘贴按钮第三方键盘。 – rDroid 2015-04-16 07:49:42

+0

另一个问题是您可以通过双击选择文本,并显示复制/粘贴 – Nikola 2018-01-24 14:19:46

8

除了setCustomSelectionActionModeCallbackdisabled long-click解决方案,有必要prevent the PASTE/REPLACE menus出现单击该文本选择手柄时,按照下面的图片:

Text selection handle with paste menu

解决之道在于防止粘贴/替换菜单从出现在(未记录)android.widget.Editor类的show()方法中。在菜单出现之前,将对if (!canPaste && !canSuggest) return;进行检查。被用作基础来设置这些变量的两种方法都处于EditText类:

更完整的答案是available here

+0

这是正确和完整的解决方案 – FireZenk 2016-01-26 15:29:40

0

您可以尝试android:focusableInTouchMode =“false”。为我工作

0

的解决方案是创建自定义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); 
} 

}

1

这里是禁用“粘贴”弹出黑客攻击。你必须重写EditText方法:

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

类似可以其他的操作来完成。

1

科特林解决方案:

fun TextView.disableCopyPaste() { 
    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?) {} 
    } 
    isLongClickable = false 
    setTextIsSelectable(false) 
} 

然后,你可以简单地调用这个方法对你TextView

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

如果不wan't禁用长按,因为你需要执行一些长时间点击而不是返回true功能是一个更好的选择。

你的edittext长按就会是这样。

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

documentation 返回“真”将表明,长按已处理所以没有必要进行默认操作。

我在API等级16,22和25上测试了它。它对我来说工作得很好。希望这会有所帮助。

1

尝试使用。

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