私のアプリケーションには、ユーザーがEditText
フィールドにテキストをコピー/貼り付けできないようにする登録画面があります。各onLongClickListener
にEditText
を設定したため、コピー/貼り付け/ inputmethodおよびその他のオプションを表示するコンテキストメニューが表示されません。そのため、ユーザーは[編集]フィールドにコピー/貼り付けできません。
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デフォルト以外のサードパーティのキーボードを有効にしている場合、問題は発生します。そのシナリオでコピー/貼り付けを無効にするにはどうすればよいですか?
他にもコピー/貼り付けの方法があるかどうかを教えてください。 (そしておそらくそれらを無効にする方法)
任意の助けをいただければ幸いです。
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を返すと、アクションモードが開始されなくなります(すべて選択、切り取り、コピー、貼り付けアクション)。
最適な方法は次を使用することです。
etUsername.setLongClickable(false);
これを行うには、EditTextの長押しを無効にします。
実装するには、次の行をxmlに追加するだけです-
Android:longClickable="false"
次の方法でコピーアンドペースト機能を無効にできます。
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);
それがあなたのために働くことを望みます;-)
これは、すべてのバージョンで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;
}
});
}
setCustomSelectionActionModeCallback 、および 無効化されたロングクリック ソリューションに加えて、 PASTE/REPLACEメニューが表示されないようにする がテキスト選択の処理時に表示されないようにする必要があります下の画像のようにクリックされます:
解決策は、(ドキュメント化されていない)Android.widget.Editor
クラスの show()
メソッドにPASTE/REPLACEメニューが表示されないようにすることです。メニューが表示される前に、if (!canPaste && !canSuggest) return;
のチェックが行われます。これらの変数を設定する基礎として使用される2つのメソッドは、両方ともEditText
クラスにあります。
isSuggestionsEnabled()
は public であるため、オーバーライドできます。canPaste()
はそうではないため、派生クラスで 同じ名前の関数を導入 によって非表示にする必要があります。より完全な答えは こちらから入手可能 です。
他のソリューションを使用しても、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) {
}
}
}
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()
}
ロングクリックを無効にしない場合は、trueを返すよりもロングクリックでいくつかの機能を実行する必要があるため、これを行うのがより良いオプションです。
編集テキストのロングクリックは次のようになります。
edittext.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
// Do Something or Don't
return true;
}
});
ドキュメント のように「True」を返すと、ロングクリックが処理されたため、デフォルトの操作を実行する必要がなくなります。
APIレベル16、22、25でこれをテストしました。私にとっては問題なく動作します。これが役立つことを願っています。
https://github.com/neopixl/PixlUI は、メソッドでEditText
を提供します
myEditText.disableCopyAndPaste()
。
そして、それは古いAPIで動作します
「貼り付け」ポップアップを無効にするハックを次に示します。 EditText
メソッドをオーバーライドする必要があります。
@Override
public int getSelectionStart() {
for (StackTraceElement element : Thread.currentThread().getStackTrace()) {
if (element.getMethodName().equals("canPaste")) {
return -1;
}
}
return super.getSelectionStart();
}
他のアクションでも同様のことができます。
@Zain ALi、あなたの答えはAPI 11で機能します。API10でも同様の方法を提案したかったのです。私はそのバージョンでプロジェクト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;
}
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) {
}
}
}
私はこのソリューションをテストしましたが、これは動作します
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;
}
});
クリップボード付きのスマートフォンの場合、このように防ぐことは可能です。
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;
}
}});
解決策は非常に簡単です
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) {
}
});
}
}
クリップボードを読み取り、入力と入力が「入力」されている時間を確認します。クリップボードに同じテキストがあり、速すぎる場合は、貼り付けた入力を削除します。
使用してみてください。
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;
}
});
GnrlKnowledgeと同様に、クリップボードをクリアできます
http://developer.Android.com/reference/Android/text/ClipboardManager.html
必要に応じて、テキストをクリップボードに保存し、onDestroyで再度設定できます。
私のために働いた解決策は、カスタム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);
}
}
不要な文字の入力を避けるために入力フィルターを作成すると、そのような文字を編集テキストに貼り付けても効果がないことがわかりました。したがって、この種の問題も私の問題を解決します。
Android:focusableInTouchMode = "false"を試すことができます。