¿Cómo evitar el reajuste total de la jerarquía de vista cuando se utiliza EditText?
Fondo
Tengo un diseño bastante complejo que se muestra al usuario en una actividad.
Una de las vistas es un EditText.
- ¿Cómo eliminar a EditText drawable padding?
- En EditText, aparece un diálogo al hacer clic en un subconjunto específico de texto
- Android: ¿Cómo crear un cuadro de texto personalizado de edición como este?
- Conexión de TextWatcher con un adaptador personalizado para filtrar texto a través de EditText
- Android: El tipo de letra se cambia cuando se aplica la contraseña. Escriba en EditarTexto
Dado que tenía que hacer una de las vistas de permanecer detrás del teclado suave, pero el resto por encima de él, tuve que escuchar los cambios de vista-disposición (escrito sobre él aquí ).
El problema
He notado que cada vez que EditText tiene el foco y muestra su caret, toda la jerarquía de vista obtiene re-layout.
Puede verlo ya sea mirando el registro del oyente que he creado o habilitando "mostrar las actualizaciones de la superficie" a través de la configuración de los desarrolladores.
Esto provoca un mal rendimiento en algunos dispositivos, especialmente si el diseño de la actividad es complejo o tiene fragmentos que tienen diseños complejos.
El código
No voy a mostrar el código original, pero hay una manera sencilla de reproducir el problema:
activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.example.user.myapplication.MainActivity"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="just some text"/> <EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:inputType="phone" android:text="write here" android:textSize="18dp"/> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="just some text 2"/> </LinearLayout> </FrameLayout>
MainActivity.java
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); findViewById(android.R.id.content).getViewTreeObserver().addOnPreDrawListener(new OnPreDrawListener() { @Override public boolean onPreDraw() { Log.d("AppLog", "onPreDraw"); return true; } }); } }
Lo que he intentado
Al desactivar el cursor (usando "cursorVisible", que por alguna razón se llama un "cursor" en su lugar), puedo ver que el problema no existe.
He intentado encontrar una alternativa al comportamiento integrado del cursor, pero no puedo encontrarlo. Lo único que he encontrado es este post , pero parece que es estático y no estoy seguro de lo bien que se realiza (rendimiento y compatibilidad vs normal caret).
He intentado fijar el tamaño del EditText con fuerza, de modo que no necesite causar la invalidación del diseño que lo contiene. No funcionó.
También he notado que en la aplicación original, los registros pueden (por alguna razón) seguir escribiendo incluso cuando la aplicación va al fondo.
He informado sobre este problema (incluyendo ejemplos y videos) aquí , con la esperanza de que Google muestre lo que está mal o una solución para esto.
La pregunta
¿Hay alguna manera de evitar el re-diseño de toda la jerarquía de vista? ¿Una manera que todavía dejará el EditText tener la misma mirada y sensación de normal EditText?
Tal vez una manera de personalizar la forma en que el EditText se comporta con el cursor?
- Android EditText: Hecho en lugar de Enter o Word Wrap en lugar de Multi Line
- Android: Visualización de WhiteSpace al cerrar Soft Keyboard
- Android - EditText se superpone con Softkeyboard
- EditText pierde el foco en el clic
- Mis opiniones se están restableciendo en el cambio de orientación
- Editar texto dentro de la vista de desplazamiento no se puede desplazar
- Editado
- Editor simple de RichText en Android
He notado que siempre que el EditText tiene el foco y muestra su caret, toda la jerarquía de vista obtiene re-layout.
Esto no es verdad. El tamaño y la posición de EditText es constante – no hay re-layouting. Puede comprobarlo utilizando el código siguiente.
findViewById(android.R.id.content).getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { Log.d("AppLog", "Layout phase"); } });
Debido a parpadeo caret – EditText averly llama invalidate()
. Esto obliga a la GPU a dibujar EditText de nuevo.
En mi Nexus 5 (marshmallow) veo que sólo EditText beeing redesenhado (Mostrar GPU ver actualizaciones – habilitado).
¿Qué hay sobre la sustitución de dispatchOnPreDraw () todas las vies que utiliza en la actividad y tener bandera para comprobar si esa vista específica necesita volver a dibujar?
Como es necesario deshabilitar el redibujo de todas las demás vistas sólo cuando una vista de texto está enfocada. Por lo tanto, cuando una vista de texto está enfocada tiene un indicador para desactivar el redibujo de otras vistas.
si el método dispatchOnPreDraw () devuelve false, entonces la actualización de la vista continuará si no. No sé cómo es complejo su diseño y cuántas vistas se utilizan, pero aquí una clase separada debe extender una vista usada y substituir ese método, y también necesitar un mecanismo / variable para distinguir el objeto en foco actual.
Espero que este método ayuda!
- mapFragment.getMapAsync (this) – NullPointerException
- Problema con Proguard de Android: sigue recibiendo error "java.io.IOException: No se puede procesar la clase …" cuando se oculta la obfuscación