Désactiver le menu contextuel EditText
Je fais une verticale EditText
pour le mongol traditionnel. Je l'ai implémenté avec succès en intégrant un EditText
légèrement modifié à l'intérieur d'un ViewGroup
pivoté. J'ai besoin de créer un menu contextuel complètement personnalisé car le système ne supporte pas le texte vertical et n'est pas non plus pivoté lorsque le ViewGroup
est pivoté. Donc, je veux désactiver complètement le menu contextuel du système.
Notez que ceci est différent de ces questions qui essaient juste de désactiver copier/coller/etc.:
- Comment faire pour désactiver le copier/coller depuis/vers EditText
- EditText: désactiver coller / remplacer menu pop-up sur le Gestionnaire de sélection de texte cliquez sur l'événement
- comment désactiver l'option Coller dans Android EditText
- Android: comment désactiver totalement la fonction copier-coller dans Edittext
Bien que je ne reçois pas le menu contextuel apparaissant dans le simulateur, je l'obtiens apparaissant dans mon Android 5.0.2 Xiaomi téléphone.
J'ai essayé:
- le
setCustomSelectionActionModeCallback
"solution" - le
setLongClickable(false);
"solution" - le
onTouchEvent
"solution"
Je suis ouvert aux hacks mais j'en ai besoin pour fonctionner de manière cohérente sur tous les appareils. Mark Murphy (un gars de Commons) a écrit quelque temps en réponse à un autre utilisateur essayant de faire quelque chose de similaire:
Je soupçonne que même si vous venez avec une réponse, il ne fonctionnera pas à travers les dispositifs. Appareil les fabricants ont eu tendance à rouler leurs propre "menu contextuel" pour EditText, battant les tentatives des développeurs d'ajouter éléments dans ce menu contextuel. Je suppose que d'essayer de bloquer cela menu contextuel aura des résultats similaires.
Je Suis hors de la chance?
La seule chose à laquelle je peux penser maintenant est de réécrire complètement TextView
et EditText
à partir de zéro (enfin, en modifiant la source Android). Je connais quelqu'un d'autre qui a fait quelque chose de similaire, mais son code n'est pas open source. Avant de prendre cette étape majeure, je veux essayer de demander une solution plus simple ici sur Stack Overflow.
Update: j'essaie de modifier le code source TextView
depuis deux jours et cela ressemble à un projet de 6 mois. C'est une masse de classes interdépendantes. J'ai besoin d'une autre solution, mais je suis à court d'idées.
MVCE
C'est la façon la plus simple de recréer le problème. Il n'y a rien de nécessaire de ma coutume EditText
. A la mise en page un seul EditText
fait en remplaçant le projet par défaut de Hello World TextView
. J'ai changé l'API min à 11 pour éviter de traiter avec des méthodes obsolètes.
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
EditText editText = (EditText) findViewById(R.id.edit_text);
editText.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) { }
});
}
}
Le menu contextuel du simulateur (exécutant API 24) s'affiche toujours lorsque je clique sur la poignée du curseur (mais pas sur un clic long ou un double clic). Voici une image:
Sur mon téléphone Xiaomi MIUI fonctionnant sous Android 5.0, je reçois le menu contextuel dans toutes les situations (clic de la poignée du curseur, clic long, double cliquer).
Mise à jour
La solution D'Aritra Roy fonctionne dans le simulateur, sur d'autres appareils qu'il a testés, et sur mon appareil. J'ai accepté sa réponse car elle résout mon problème initial. Le seul effet secondaire est que la sélection de texte est également désactivée.
6 réponses
, Il y a trois choses que vous devez faire.
ÉTAPE 1
Vous pouvez désactiver l'affichage des menus contextuels en renvoyant false à partir de ces méthodes,
mEditEext.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;
}
});
ÉTAPE 2
Il est également nécessaire de désactiver le clic long dans EditText.
mEditText.setLongClickable(false);
Ou faire ceci, {[3] } en XML.
ÉTAPE 3
Maintenant, vous devez empêcher les menus d'apparaître lorsque vous cliquez sur les poignées. La solution est simple,
1) étendre la classe EditText
,
2) Remplacer isSuggestionsEnabled()
et retour false
,
3) créez une méthode canPaste()
et renvoyez false
. C'est une méthode de masquage.
SOLUTION RAPIDE
Si vous ne voulez pas faire tout manuellement. Voici une classe EditText personnalisée que vous pouvez utiliser pour cela rapidement. Mais je vous recommande toujours de passer par les étapes une fois pour comprendre comment les choses fonctionnent.
public class MenuHidingEditText extends EditText {
private final Context mContext;
public MenuHidingEditText(Context context) {
super(context);
this.mContext = context;
blockContextMenu();
}
public MenuHidingEditText(Context context, AttributeSet attrs) {
super(context, attrs);
this.mContext = context;
blockContextMenu();
}
public MenuHidingEditText(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
this.mContext = context;
blockContextMenu();
}
private void blockContextMenu() {
this.setCustomSelectionActionModeCallback(new BlockedActionModeCallback());
this.setLongClickable(false);
this.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
MenuHidingEditText.this.clearFocus();
return false;
}
});
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
// setInsertionDisabled when user touches the view
this.setInsertionDisabled();
}
return super.onTouchEvent(event);
}
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) {
}
}
}
J'ai fait ce code pour EditText
, et cela a bien fonctionné pour un tel problème.
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();
}
mEditText.setLongClickable(false);
C'est le moyen le plus simple de désactiver le texte d'édition.
, La solution est très 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) {
}
});
}
}
C'est ainsi que vous empêchez le menu copier coller d'apparaître de quelque manière que ce soit. Ce bug m'a vraiment rendu fou, et comme avec tout bug Samsung, vous le savez dans leur code, mais vous savez aussi qu'ils ne le répareront pas de sitôt. Quoi qu'il en soit, voici Wonder wall...
Vérifiez si Android.Construire.Modèle.toLowerCase().commence avec ('sm-g930'). Ne correspond pas à la chaîne entière, la dernière lettre est un identifiant de version mineur. J'ai stocké ce booléen dans la variable shouldBlockCopyPaste qui apparaît tard.
Si elle correspond, vous voulez bloquer le menu copier coller de l'affichage. C'est la façon dont vous avez RÉELLEMENT le FAIRE!!!
Remplacer ces 2 fonctions, vous remarquerez mon booléen shouldBlockCopyPaste, c'est donc d'autres appareils ne sont pas bloqués.
@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);
}
}
Essayez ceci
mEditText.setClickable(false);
mEditText.setEnabled(false);
Mise à jour
Essayez cette solution en étendant 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) {}
}
}
Référence: https://stackoverflow.com/a/28893714/5870896