android - programacion - Desactivar el menú contextual de EditText
manual de android en pdf (5)
Estoy haciendo un EditText
vertical para mongol tradicional. Lo he implementado exitosamente al EditText
un ViewGroup
ligeramente modificado dentro de un ViewGroup
rotado. Necesito crear un menú contextual completamente personalizado porque el sistema no admite texto vertical y tampoco se rota cuando se gira el grupo de ViewGroup
. Por lo tanto, quiero deshabilitar el menú contextual del sistema por completo.
Tenga en cuenta que esto es diferente a estas preguntas que simplemente intentan deshabilitar copiar / pegar / etc .:
- Cómo deshabilitar copiar / pegar desde / hacia EditText
- EditText: deshabilita la ventana emergente del menú Pegar / Reemplazar en el evento de clic del controlador de selección de texto
- cómo deshabilitar la opción pegar en android EditText
- Android: Cómo deshabilitar TOTALMENTE la función copiar y pegar en Edittext
Aunque no aparece el menú contextual en el simulador, aparece en mi teléfono Android 5.0.2 Xiaomi.
Yo he tratado:
- la "solución"
setCustomSelectionActionModeCallback
-
setLongClickable(false);
"solución" - la "solución"
onTouchEvent
Estoy abierto a hacks, pero lo necesito para trabajar de manera consistente en todos los dispositivos. Mark Murphy (un chico de los comunes) escribió hace tiempo en respuesta a otro usuario que intentaba hacer algo similar:
Sospecho que incluso si se te ocurre una respuesta, no funcionará en todos los dispositivos. Los fabricantes de dispositivos han tenido la tendencia de desplegar su propio "menú de contexto" para EditText, derrotando los intentos de los desarrolladores de agregar elementos en ese menú contextual. Mi suposición es que tratar de bloquear ese menú contextual tendrá resultados similares.
¿No tengo suerte?
Lo único que se me ocurre ahora es reescribir completamente TextView
y EditText
desde cero (bueno, modificando la fuente de Android). Conozco a alguien más que hizo algo similar, pero su código no es de código abierto. Antes de dar este gran paso, quiero intentar pedir una solución más simple aquí en Stack Overflow.
Actualización: he intentado modificar el código fuente de TextView
durante los últimos dos días y parece un proyecto de 6 meses. Es una masa de clases interrelacionadas. Necesito otra solución, pero estoy sin ideas.
MVCE
Esta es la manera más simple que se me ocurre para recrear el problema. No hay nada necesario de mi EditText
personalizado. El diseño tiene un solo EditText
creado reemplazando el proyecto predeterminado Hello World''s TextView
. Cambié la API mínima a 11 para evitar tener que lidiar con métodos obsoletos.
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) { }
});
}
}
El menú contextual en el simulador (que ejecuta la API 24) aún se muestra cuando hago clic en el controlador del cursor (pero no en un clic largo o doble clic). Aquí hay una imagen:
En mi teléfono Xiaomi MIUI con Android 5.0, obtengo el menú de contexto en todas las situaciones (clic del cursor, clic largo, doble clic).
Actualizar
La solución de Aritra Roy está funcionando en el simulador, en algunos otros dispositivos que ha probado y en mi dispositivo. He aceptado su respuesta porque resuelve mi problema original. El único efecto secundario negativo es que la selección de texto también está deshabilitada.
Así es como se bloquea el menú copiar pegar para que no aparezca de ninguna manera, forma o forma. Este error realmente me volvió loco, y como con cualquier error de Samsung, usted sabe que está en su código, pero también sabe que no lo arreglarán en el corto plazo. De todos modos, aquí está la pared de la maravilla ...
Compruebe si Android.Build.Model.toLowerCase (). StartsWith (''sm-g930''). No haga coincidir toda la cadena, la última letra es un identificador de versión menor. Almacé este booleano en la variable shouldBlockCopyPaste que aparece más adelante.
Si coincide, quiere bloquear la visualización del menú de copiar y pegar. Así es como REALMENTE LO HACES!
Sobreescriba estas 2 funciones, notará mi shouldBlockCopyPaste boolean, esto es para que otros dispositivos no se bloqueen.
@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);
}
}
Hay tres cosas que debes hacer.
PASO 1
Puede deshabilitar los menús contextuales al devolver falso de estos métodos,
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;
}
});
PASO 2
También es necesario desactivar el clic largo en EditText.
mEditText.setLongClickable(false);
o haciendo esto, android:longClickable="false"
en XML.
PASO 3
Ahora, debe evitar que los menús aparezcan cuando se hace clic en los controles. La solución es simple,
1) Extienda la clase EditText
,
2) Anular isSuggestionsEnabled()
y devolver false
3) Crea un método canPaste()
y devuelve false
. Este es un método escondido.
SOLUCIÓN RÁPIDA
Si no quiere hacer todo esto manualmente. Aquí hay una clase personalizada de EditText que puede usar para hacer esto rápidamente. Pero aún así te recomiendo que sigas los pasos una vez para entender cómo funcionan las cosas.
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) {
}
}
}
He hecho este código para EditText
, y funcionó bien para un problema así.
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();
}
prueba esto
mEditText.setClickable(false);
mEditText.setEnabled(false);
ACTUALIZAR
Pruebe esta solución ampliando 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) {}
}
}
Referencia: https://.com/a/28893714/5870896
mEditText.setLongClickable(false);
Es la forma más sencilla de desactivar el texto de edición.