Actualizar GridView / ListView sin volver a rellenar

notifyDatasetChanged vez que actualice un GridView / ListView llama a notifyDatasetChanged en el adaptador que vuelve a llenar la lista con los nuevos datos quitando todo lo que estaba actualmente en la lista.

Ahora tome este pequeño video por ejemplo de las directrices de diseño de L Preview

¿Es posible lograr este mismo efecto donde el único cambio que ves son los nuevos elementos que entran sin ningún "parpadeo" cuando el adaptador se vuelve a cargar o es algo que solo se puede hacer en L ahora mismo?

Este efecto también se puede encontrar en la aplicación Google Keep al agregar nuevas notas

Me temo que todo es truco visual, también conocido como animación.

… quitando todo lo que estaba actualmente en la lista.

En realidad no.

notifyDataSetChanged sólo indica a los observadores subyacentes que los datos han cambiado. Eso es. En respuesta, getView(...) se llama para cada vista visible – el número accesible por ListView#getChildCount() . Puesto que cualquiera de los dos índices ha cambiado (añadiendo o eliminando elementos), o los datos contenidos en los objetos en esos índices han cambiado (^) (uno o más elementos han cambiado), los datos son (^) actualizados visualmente mediante llamadas posteriores a ListView#getView(...) .

Hay un interesante video de 'Android Developers' que explica cómo puedes producir el efecto que buscas: DevBytes: ListView Cell Insertion Animation .

El video / ejemplo sólo habla de la inserción de un único elemento. Pero debe ser extensible a todas las operaciones de datos con un poco de tiempo y habilidades matemáticas.

He podido ampliar el código de ejemplo para insertar varios elementos. Cambié la animación a un alpha-fade-in más simple. Al hacer clic en el botón Add row se agrega un número aleatorio (entre 1 y 3 inclusive) de elementos a la vista de lista. Esto es lo que parece:

Introduzca aquí la descripción de la imagen

Psuedo-flujo de trabajo:

  • Antes de pasar los nuevos elementos al adaptador, recorrer todos los elementos visibles de la vista de lista y guardar sus límites (en Rect ) y la instantánea (en BitmapDrawables )

  • Pasar los elementos al adaptador

  • Agregue un OnPreDrawListener al OnPreDrawListener de ListView.

  • Cuando onPreDraw(...) es llamado, los nuevos elementos están listos para ser dibujados. Podemos acceder a sus views usando ListView#getChildAt(...) con los respectivos índices.

  • Todos los elementos nuevos se configuran como invisibles y se asignan animadores alfa

  • Todos los elementos antiguos están asignados a la traducción_y animadores

  • Los elementos que ya no serán accesibles a través de getChildAt(..) – debido a la adición de nuevos elementos – se asignan traducción_y animadores – para sacarlos de la pantalla (o fuera de los límites de vista)

  • Los animadores de la traducción son despedidos. Cuando estos animadores se ejecutan, animadores alfa se inician.

Observe que el tipo de animación (alfa, traducción, escala o cualquier combinación de estos) es relativamente insignificante. Supongo que esto será mucho más difícil en el caso de un GridView o StaggeredGridView (mantener) – sólo porque la matemática implicará traducciones en X e Y Sin embargo, el flujo de trabajo debe ser el mismo.

(^) – gramaticalmente incorrecto, pero IMO natural.

Esto se pudo lograr agarrando la vista y cambiando los datos allí adentro. He incluido un ejemplo donde en el tecleo largo usted cambia los datos sin refrescar los artículos visibles y sin llamar notifyDataSetChanged ().

Esta pregunta se ha hecho en la I / O de Google 2010, puedes verla aquí:

El mundo de ListView, tiempo 52:30

Código adaptado de Vogella

 package com.example.stableids; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import android.os.Build; import android.os.Bundle; import android.annotation.SuppressLint; import android.annotation.TargetApi; import android.app.Activity; import android.content.Context; import android.database.DataSetObserver; import android.util.Log; import android.view.Menu; import android.view.View; import android.view.ViewGroup; import android.widget.Adapter; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.ListView; import android.widget.TextView; @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1) @SuppressLint("NewApi") public class MainActivity extends Activity { @TargetApi(Build.VERSION_CODES.HONEYCOMB) @SuppressLint("NewApi") @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); final ListView listview = (ListView) findViewById(R.id.listview); String[] values = new String[] { "Android", "iPhone", "WindowsMobile", "Blackberry", "WebOS", "Ubuntu", "Windows7", "Max OS X", "Linux", "OS/2", "Ubuntu", "Windows7", "Max OS X", "Linux", "OS/2", "Ubuntu", "Windows7", "Max OS X", "Linux", "OS/2", "Android", "iPhone", "WindowsMobile" }; final ArrayList<String> list = new ArrayList<String>(); for (int i = 0; i < values.length; ++i) { list.add(values[i]); } final StableArrayAdapter adapter = new StableArrayAdapter(this, android.R.layout.simple_list_item_1, list); listview.setAdapter(adapter); listview.setOnItemClickListener(new AdapterView.OnItemClickListener() { @SuppressLint("NewApi") @Override public void onItemClick(AdapterView<?> parent, final View view, final int position, long id) { final String item = (String) parent.getItemAtPosition(position); view.animate().setDuration(2000).alpha(0) .withEndAction(new Runnable() { @Override public void run() { int i = list.indexOf(item); list.remove(item); list.add(i, "MODIFIED"); adapter.mIdMap.put("MODIFIED", position); TextView tv = (TextView)view.findViewById(android.R.id.text1); tv.setText("MODIFIED"); //adapter.notifyDataSetChanged(); view.setAlpha(1); } }); } }); } private class StableArrayAdapter extends ArrayAdapter<String> { HashMap<String, Integer> mIdMap = new HashMap<String, Integer>(); public StableArrayAdapter(Context context, int textViewResourceId, List<String> objects) { super(context, textViewResourceId, objects); for (int i = 0; i < objects.size(); ++i) { mIdMap.put(objects.get(i), i); } } @Override public View getView(int position, View convertView, ViewGroup parent) { Log.d("STABLE ID", "getView called for " + position + " position"); return super.getView(position, convertView, parent); } @Override public long getItemId(int position) { String item = getItem(position); return mIdMap.get(item); } @Override public boolean hasStableIds() { return true; } } } 

Actualizar GridView / ListView sin repoblar

Si utiliza la misma lista de arrays para cada vez que actualiza y elimina el tiempo sin crear ArrayList nuevo, entonces su trabajo con el método adapter.notifyDatasetChanged (). Por favor, usted mismo arrayList cada vez y no crear nueva Instancia de la clase de adaptador

  • Obtener contexto de actividad en un adaptador de un fragmento
  • ¿Cómo colocar un ProgressBar dentro del ListView?
  • ListView para la aplicación de mensajería muestra un diseño incorrecto listItem después de desplazarse
  • Listview en el lado de rleft y tabhost en el lado derecho con la proporción de 20:80 compartir pantalla
  • Android - Formato de la marca de tiempo en ListView con el adaptador de cursor
  • Biblioteca de cargador de imágenes universal está actuando lento en Android 5.0 en comparación con Android 4.4.4
  • ¿Cómo aplicar una transparencia (enfoque?) Al pulsar cualquier elemento (como lo hace Google)?
  • Establecimiento de diferentes colores de divisor para cada elemento en la vista de lista
  • ¿Resplandor de encargo del color del resplandor / del borde para ListView?
  • Lista de visualización de Android usando expandibleListView
  • Cómo reemplazar completamente listView / GridView con RecyclerView?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.