¿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.

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?

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

Introduzca aquí la descripción de la imagen

¿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!

  • Strike html tag no renderizado en EditText con TextFormatted
  • Obtener una cadena de texto de EditText?
  • obtener el valor entero de EditText Android
  • Android EditText setText no actualizar el texto
  • Cómo establecer el tipo de entrada como contraseña a edittext programatically
  • cómo insertar la imagen en un editText
  • Cómo agregar texto con formato en el texto de edición?
  • Formato android edittext para mostrar espacios después de cada 4 caracteres
  • Cómo eliminar Android auto-sugiere subrayar en EditText?
  • Android: cómo capturar el evento de prensa larga en soft input / keyboard?
  • Android EditText: ¿Cómo crear un párrafo de viñeta vacío de BulletSpan?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.