35 votes

Désactiver le menu contextuel EditText

Je suis faire une verticale EditText traditionnelle mongole. J'ai mis en œuvre avec succès par l'incorporation d'un peu modifié EditText à l'intérieur d'une zone de ViewGroup. J'ai besoin de créer un tout menu contextuel personnalisé parce que le système ne prend pas en charge le texte vertical et est également de ne pas faire pivoter lorsque l' ViewGroup est en rotation. Je tiens donc à désactiver le système de menu de contexte tout à fait.

Notez que ceci est différent de ces questions qui sont juste essayer de désactiver le copier/coller, etc.:

Bien que je n'ai pas le menu contextuel apparaissant dans le simulateur, je reçois il apparaît dans mon Android 5.0.2 Xiaomi téléphone.

J'ai essayé:

Je suis ouvert à des hacks, mais j'en ai besoin pour travailler à travers les dispositifs. Mark Murphy (une des Communes du Gars) a écrit il y a quelque temps en réponse à un autre utilisateur essaie de faire quelque chose de similaire:

Je pense que même si vous avez une réponse, il ne fonctionnera pas à travers les dispositifs. Les fabricants d'appareils ont eu tendance à rouler leurs propre "menu contextuel" pour EditText, en battant des développeurs tente d'ajouter les éléments dans le menu contextuel. Ma conjecture est que d'essayer d'empêcher que le menu contextuel avoir des résultats similaires.

Suis-je de la chance?

La seule chose que je peux penser maintenant est de réécrire complètement TextView et EditText à partir de zéro (ainsi, en modifiant la source Android). Je connais quelqu'un qui fait quelque chose de similaire, mais son code n'est pas open source. Avant de prendre cette étape importante, je veux essayer de demander pour une solution plus simple ici, sur un Débordement de Pile.

Mise à jour: j'ai essayé de modifier l' TextView code source pour les deux derniers jours et il ressemble à 6 mois de projet. C'est une masse de l'interdépendance des classes. J'ai besoin d'une autre solution, mais je suis à court d'idées.

MVCE

C'est le moyen le plus simple je pense de recréer le problème. Il n'y a rien de nécessaire à partir de mon personnalisée EditText. A la mise en page d'un seul EditText faites en remplaçant la valeur par défaut du projet Bonjour du Monde TextView. J'ai changé le min de l'API à 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 dans le simulateur (en exécution de l'API 24) montre encore quand je clique sur le curseur de la manche (mais pas sur une longue cliquez ou double-cliquez). Voici une image:

enter image description here

Sur mon Xiaomi MIUI téléphone fonctionnant sous Android 5.0, je obtenir le menu contextuel dans toutes les situations (curseur poignée de clic, clic, double clic).

Mise à jour

Aritra Roy solution est de travailler dans le simulateur, sur certains autres appareils qu'il a testé, et sur mon appareil. J'ai accepté sa réponse, car il résout mon problème d'origine. Le seul effet secondaire est que la sélection de texte est également désactivée.

27voto

Aritra Points 47

Il y a trois choses que vous devez faire.

ÉTAPE 1

Vous pouvez désactiver les menus contextuels apparaissent en retournant 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 nécessaire de désactiver le long-cliquez dans l'EditText ainsi.

mEditText.setLongClickable(false);

ou en faisant cela, android:longClickable="false" en XML.

ÉTAPE 3

Maintenant, vous avez besoin pour prévenir les menus apparaissent lorsque les poignées sont cliqués. La solution est simple,

1) Étendre l' EditText classe,

2) Remplacer isSuggestionsEnabled() et retour false,

3) Créer un canPaste() méthode et retour false. C'est une méthode de masquage.

SOLUTION RAPIDE

Si vous ne voulez pas faire tout manuellement. Ici, la coutume EditText classe que vous pouvez utiliser pour obtenir ce fait rapidement. Mais je continue à vous recommander 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) {
        }
    }
}

6voto

Muhammad Ali Points 31

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

        }
    });
   }
}
 

entrez la description de l'image ici

5voto

Rjz Satvara Points 1890

J'ai créé 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();
}
 

2voto

udayatom Points 102
 mEditText.setLongClickable(false);
 

C'est le moyen le plus simple de désactiver le texte d'édition.

1voto

self.name Points 773

C'est une façon de bloquer le copier coller à partir du menu apparaissant en aucune manière, la forme ou la forme. Ce bug vraiment me rendait fou, et comme avec n'importe quel Samsung bug, vous connaissez sa dans leur code, mais vous savez aussi qu'ils ne répare pas n'importe quand bientôt. De toute façon, ici wonder mur...

  1. Vérifier si Android.Construire.De modèle.toLowerCase().startsWith('sm-g930'). Ne correspondent pas à l'ensemble de la chaîne, la dernière lettre est un mineur identificateur de version. Je stocke cette valeur dans shouldBlockCopyPaste variable qui vient plus tard.

  2. Si elle correspond à celle que vous souhaitez bloquer le copier coller à partir du menu affichage. C'est la façon dont vous avez RÉELLEMENT le FAIRE!!!

Remplacer ces 2 fonctions, vous remarquerez mon shouldBlockCopyPaste boolean, c'est si d'autres appareils ne soyez pas bloqué.

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X