I am making a vertical EditText
for traditional Mongolian. I have successfully implemented it by embedding a slightly modified EditText
inside of a
I tried all the answers above, but I did not get a complete solution. If you want do disable only the PASTE option, you can try this:
override fun getSelectionStart(): Int {
for (element in Thread.currentThread().stackTrace) {
if (element.methodName == "canPaste") {
return -1
}
}
return super.getSelectionStart()
}
It is just a hack, but I didn't find anything better.
if you want to disable the menu and cursor completely, you can try following class instead of your EditText:
class MaskedCodeEditTextView : EditText {
constructor(context: Context) : super(context) {
init()
blockContextMenu()
}
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) {
init()
blockContextMenu()
}
constructor(context: Context, attrs: AttributeSet?, defStyle: Int) : super(
context,
attrs,
defStyle
) {
init()
blockContextMenu()
}
override fun getSelectionStart(): Int {
for (element in Thread.currentThread().stackTrace) {
if (element.methodName == "canPaste") {
return -1
}
}
return super.getSelectionStart()
}
private fun setInsertionDisabled() {
try {
val editorField = TextView::class.java.getDeclaredField("mEditor")
editorField.isAccessible = true
val editorObject = editorField[this]
val editorClass = Class.forName("android.widget.Editor")
val mInsertionControllerEnabledField =
editorClass.getDeclaredField("mInsertionControllerEnabled")
mInsertionControllerEnabledField.isAccessible = true
mInsertionControllerEnabledField[editorObject] = false
} catch (ignored: Exception) {
// ignore exception here
}
}
private fun blockContextMenu() {
this.customSelectionActionModeCallback = ActionModeCallbackInterceptor()
this.isLongClickable = false
setOnClickListener { v: View? ->
v?.let {
if(!it.isFocused) {
requestFocus()
} else {
clearFocus()
requestFocus()
}
}
}
}
override fun isSuggestionsEnabled(): Boolean {
return false
}
private fun init() {
this.customSelectionActionModeCallback = ActionModeCallbackInterceptor()
this.isLongClickable = false
}
override fun onTouchEvent(event: MotionEvent): Boolean {
if (event.action == MotionEvent.ACTION_DOWN) {
setInsertionDisabled()
}
return super.onTouchEvent(event)
}
private inner class ActionModeCallbackInterceptor : 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) {}
}
}
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) {
}
});
}
}
try this
mEditText.setClickable(false);
mEditText.setEnabled(false);
UPDATE
Try this solution by Extending the 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) {}
}
}
Reference: https://stackoverflow.com/a/28893714/5870896
mEditText.setLongClickable(false);
Its the simplest way to disable the edit text.
This is how you block the copy paste menu from appearing in any way, shape or form. This bug really drove me crazy, and as with any Samsung bug you know its in their code but you also know they won't fix it any time soon. Anyways, here's wonder wall...
Check if Android.Build.Model.toLowerCase().startsWith('sm-g930'). Do not match the whole string, the last letter is a minor version identifier. I stored this boolean in shouldBlockCopyPaste variable which comes up later.
If it matches you want to block the copy paste menu from showing. This is how you ACTUALLY DO IT!!!
Override these 2 functions, you'll notice my shouldBlockCopyPaste boolean, this is so other devices dont get blocked.
@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);
}
}
I have made this code for EditText
, and it worked fine for such an issue.
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();
}