In my application, there is a registration screen, where i do not want the user to be able to copy/paste text into the EditText
field. I have set an onLongClickListener
on each EditText
so that the context menu showing copy/paste/inputmethod and other options does not show up. So the user won't be able to copy/ paste into the Edit fields.
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;
}
};
But the problem arises if the user has enabled a third-party keyboard other than the Android default, which may have a button to copy/paste or which may show the same context menu. So how do i disable copy/paste in that scenario ?
Please let me know if there are other ways to copy/paste as well. (and possibly how to disable them)
Any help would be appreciated.
This question is related to
android-widget
android-edittext
android
android-keypad
I've tested this solution and this works
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;
}
});
i added Extension Function in Kotlin language :
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?) {
}
})
}
you can use it like this :
edit_text.disableTextSelection()
also added below line in your xml :
android:longClickable="false"
android:textIsSelectable="false"
@Zain Ali, your answer works on API 11. I just wanted to suggest a way to do in on API 10 as well. Since I had to maintain my project API on that version, I was constantly playing with the functions available in 2.3.3 and got a possibility to do it. I have share the snippet below. I tested the code and it was working for me. I did this snippet on an urgency. Feel free to improve the code if there are any changes that can be done..
// 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;
}
Read the Clipboard, check against the input and the time the input is "typed". If the Clipboard has the same text and it is too fast, delete the pasted input.
Try to use.
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;
}
});
Here is a hack to disable "paste" popup. You have to override EditText
method:
@Override
public int getSelectionStart() {
for (StackTraceElement element : Thread.currentThread().getStackTrace()) {
if (element.getMethodName().equals("canPaste")) {
return -1;
}
}
return super.getSelectionStart();
}
Similar can be done for the other actions.
Solution that worked for me was to create custom Edittext and override following method:
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);
}
}
Who is looking for a solution in Kotlin use the below class as a custom widget and use it in the xml.
class 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 {
[email protected](true)
[email protected]()
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) {
[email protected](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) {
[email protected](false)
performHandlerAction(inputMethodManager)
}
return false
}
}
}
If you want to disable ActionMode
for copy/pasting, you need to override 2 callbacks. This works for both TextView
and EditText
(or 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?) {}
}
}
}
This extension is based off above @Alexandr solution and worked fine for me.
I am able to disable copy-and-paste functionality with the following:
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);
Hope it works for you ;-)
Try Following custome class for prevant copy and paste in 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) {
}
}
}
the solution is very simple
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) {
}
});
}
}
You may try android:focusableInTouchMode="false".
In addition to the setCustomSelectionActionModeCallback, and disabled long-click solutions, it's necessary to prevent the PASTE/REPLACE menus from appearing when the text selection handle is clicked, as per the image below:
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.A more complete answer is available here.
If you don't wan't to disable long click because you need to perform some functionality on long click than returning true is a better option to do so.
Your edittext long click will be like this.
edittext.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
// Do Something or Don't
return true;
}
});
As per documentation Returning "True" will indicate that long click have been handled so no need to perform default operations.
I tested this on API level 16, 22 and 25. Its working fine for me. Hope this will help.
I found that when you create an input filter to avoid entry of unwanted characters, pasting such characters into the edit text is having no effect. So this sort of solves my problem as well.
For smartphone with clipboard, is possible prevent like this.
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;
}
}});
You can do this by disabling the long press of the EditText
To implement it, just add the following line in the xml -
android:longClickable="false"
Similar to GnrlKnowledge, you can clear the Clipboard
http://developer.android.com/reference/android/text/ClipboardManager.html
If you want, preserve the text in the Clipboard, and on onDestroy, you can set it again.
Best method is to use:
etUsername.setLongClickable(false);
https://github.com/neopixl/PixlUI provides an EditText
with a method
myEditText.disableCopyAndPaste()
.
And it's works on the old API
here is a best way to disable cut copy paste of editText work in all version
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;
}
});
}
Kotlin solution:
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?) {}
}
}
Then you can simply call this method on your TextView
:
override fun onCreate() {
priceEditText.disableCopyPaste()
}
Source: Stackoverflow.com