如何禁用从/到EditText的复制/粘贴

时间:2011-06-08 07:05:12

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

在我的应用程序中,有一个注册屏幕,我不希望用户能够将文本复制/粘贴到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默认设置之外的第三方键盘,可能有一个复制/粘贴按钮,或者可能显示相同的上下文菜单。那么如何在该场景中禁用复制/粘贴?

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

任何帮助都将不胜感激。

26 个答案:

答案 0 :(得分:115)

最好的方法是使用:

etUsername.setLongClickable(false);

答案 1 :(得分:104)

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

答案 2 :(得分:35)

您可以通过禁用长按EditText

来执行此操作

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

android:longClickable="false"

答案 3 :(得分:30)

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

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

希望它适合你; - )

答案 4 :(得分:12)

这是在所有版本中禁用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;
            }
        });
    }

答案 5 :(得分:7)

setCustomSelectionActionModeCallbackdisabled long-click解决方案外,点击文字选择句柄时还需要显示prevent the PASTE/REPLACE menus,如下图所示:

Text selection handle with paste menu

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

更完整的答案是available here

答案 6 :(得分:6)

使用其他解决方案时,API 26(Oreo)仍然可以通过单击输入的文本来显示光标手柄,然后可以显示菜单。只有解决方案的组合才能解决我的问题。

public class CustomEditText extends EditText {

    public CustomEditText(Context context) {
        super(context);
        init();
    }

    public CustomEditText(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public CustomEditText(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

    private void init() {
        this.setCustomSelectionActionModeCallback(new BlockedActionModeCallback());
        this.setLongClickable(false);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            this.setInsertionDisabled();
        }
        return super.onTouchEvent(event);
    }

    /**
    * This method sets TextView#Editor#mInsertionControllerEnabled field to false
    * to return false from the Editor#hasInsertionController() method to PREVENT showing
    * of the insertionController from EditText
    * The Editor#hasInsertionController() method is called in  Editor#onTouchUpEvent(MotionEvent event) method.
    */
    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) {
        }
    }
}

答案 7 :(得分:4)

Kotlin解决方案:

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

答案 8 :(得分:4)

如果您不想禁用长按,因为您需要在长时间点击时执行某些功能而不是返回true,这样做是更好的选择。

您的edittext长按会像这样。

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

根据documentation 返回&#34; True&#34;将表明已经处理了长按,因此无需执行默认操作。

我在API级别16,22和25上对此进行了测试。它对我来说很好。希望这会有所帮助。

答案 9 :(得分:3)

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

myEditText.disableCopyAndPaste()

它适用于旧API

答案 10 :(得分:2)

我以 Kotlin 语言添加了扩展功能

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"

答案 11 :(得分:2)

这是一个禁用&#34;粘贴&#34;弹出。您必须覆盖EditText方法:

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

其他行动也可以这样做。

答案 12 :(得分:1)

对于带剪贴板的智能手机,可以防止这种情况。

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

答案 13 :(得分:1)

尝试以下定制类,以进行优先复制并粘贴到 var request = URLRequest(url: url) request.httpMethod = "GET" request.setValue("cookie1=\(val1);cookie2=\(val2);", forHTTPHeaderField: "Cookie") request.httpShouldHandleCookies = true webView.loadRequest(request)

Edittext

}

答案 14 :(得分:1)

解决方案非常简单

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

答案 15 :(得分:1)

我已经测试了该解决方案,并且可以正常工作

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

答案 16 :(得分: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;
    }

答案 17 :(得分:1)

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

答案 18 :(得分:0)

谁正在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
    }
}

}

答案 19 :(得分:0)

如果要禁用.png进行复制/粘贴,则需要覆盖2个回调。这适用于ActionModeTextView(或EditText

TextInputEditText

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

答案 20 :(得分:0)

广泛兼容的解决方案(从 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;
}

答案 21 :(得分:0)

尝试使用。

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

}

答案 23 :(得分:0)

您可以尝试android:focusableInTouchMode =“false”。

答案 24 :(得分:0)

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

答案 25 :(得分:0)

与GnrlKnowledge类似,您可以清除剪贴板

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

如果需要,保留剪贴板中的文本,在onDestroy上,您可以再次设置它。