Android Listview Custom Sección Encabezado

¿Cómo puedo implementar la sección o encabezado personalizado de ListView como la aplicación Instagram en android.

Http://prsarahevans.com/wp-content/uploads/2011/06/photo.PNG

Cuando se desplaza hacia arriba la barra que tiene userpic, nombre y tiempo todavía estar allí y cuando otra barra de encabezado ir cerca de ella luego animar como empujar hacia arriba.

Gracias.

Fui capaz de resolver este problema mediante el uso de scroll escucha en el listview. (Probado en 2.1)

Digamos que para cada fila de lista tengo un diseño como el de abajo. Hay una parte de contenido y una parte de encabezado. No importa el tipo de vista que utilice para el encabezado o el contenido.

<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" android:background="#FFFFFF"> <ImageView android:id="@+id/content" android:layout_width="fill_parent" android:layout_height="300dp" android:scaleType="centerCrop" android:src="@drawable/pic" android:background="#aaaaff" android:layout_marginTop="40dp"/> <TextView android:id="@+id/header" android:layout_width="fill_parent" android:layout_height="40dp" android:padding="12dp" android:text="Deneme Row" android:textColor="#000000" android:background="#99ffffff"/> </RelativeLayout> 

El diseño de la prueba para la actividad es como en los siguientes:

 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <ListView android:id="@+id/list" android:layout_width="fill_parent" android:layout_height="fill_parent" > </ListView> </LinearLayout> 

Finalmente el código para la actividad se da a continuación. Aquí tuve que tener un adaptador que usa ViewHolder para almacenar la vista de cabecera y también una variable para mantener un registro del cambio en el desplazamiento de cada evento de desplazamiento sucesivo (anteriorTop). Esto es debido al hecho de que offsetTopAndBottom () cambia el desplazamiento de la vista relacionada con la ubicación anterior del mismo.

 public class TestActivity extends Activity implements AbsListView.OnScrollListener{ ListView list; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); list = (ListView) findViewById(R.id.list); list.setAdapter(new Adapter(this)); list.setOnScrollListener(this); } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { //the listview has only few children (of course according to the height of each child) who are visible for(int i=0; i < list.getChildCount(); i++){ View child = list.getChildAt(i); ViewHolder holder = (ViewHolder) child.getTag(); //if the view is the first item at the top we will do some processing if(i == 0){ boolean isAtBottom = child.getHeight() <= holder.header.getBottom(); int offset = holder.previousTop - child.getTop(); if(!(isAtBottom && offset > 0)){ holder.previousTop = child.getTop(); holder.header.offsetTopAndBottom(offset); holder.header.invalidate(); } } //if the view is not the first item it "may" need some correction because of view re-use else if (holder.header.getTop() != 0) { int offset = -1 * holder.header.getTop(); holder.header.offsetTopAndBottom(offset); holder.previousTop = 0; holder.header.invalidate(); } } } @Override public void onScrollStateChanged(AbsListView view, int scrollState) {} private static class Adapter extends ArrayAdapter<String> { public Adapter(Context context) { super(context, R.layout.row, R.id.header); for(int i=0; i < 50; i++){ add(Integer.toString(i)); } } @Override public View getView(int position, View convertView, ViewGroup parent) { if(convertView == null){ convertView = LayoutInflater.from(getContext()).inflate(R.layout.row, parent, false); ViewHolder holder = new ViewHolder(); holder.header = (TextView) convertView.findViewById(R.id.header); convertView.setTag(holder); } ViewHolder holder = (ViewHolder) convertView.getTag(); holder.header.setText(getItem(position)); return convertView; } } private static class ViewHolder { TextView header; int previousTop = 0; } } 

He mejorado la pregunta de Siyamed un poco para que el encabezado no se ha ido cuando la vista se vuelve a dibujar, por ejemplo, si un mapa de bits en el elemento de vista de lista se cambia.

En lugar de utilizar coordenadas con respecto a la última posición, utilizo coordenadas relativas a la parte superior de la vista y uso relleno en lugar de desplazamientos.

 @Override public void onScroll(AbsListView absListView, int firstVisibleItem, int visibleItemCount, int totalItemCount) { for(int i=0; i < list.getChildCount(); i++){ View child = list.getChildAt(i); ViewHolder holder = (ViewHolder) child.getTag(); if(i == 0){ try { boolean isAtBottom = child.getHeight() <= holder.movingHeader.getBottom(); if(!(isAtBottom)){ if (child.getTop() >= 0){} else if (child.getHeight() - movingHeader.getHeight() - 1 > -child.getTop()) { holder.movingHeader.setPadding(0, -child.getTop(), 0, 0); holder.movingHeader.invalidate(); } else { holder.movingHeader.setPadding(0, child.getHeight() - movingHeader.getHeight(), 0, 0); holder.movingHeader.invalidate(); } } } catch (Exception e) { e.printStackTrace(); } } else if (holder.movingHeader.getPaddingTop() != 0) { holder.movingHeader.setPadding(0, 0, 0, 0); holder.movingHeader.invalidate(); } } } 

Si está usando la vista de lista, entonces tiene 2 vistas dentro de su elemento de lista. Uno es encabezado y otro es en realidad elemento.

Ocultar la vista del encabezado inicialmente y cuando el estado de desplazamiento cambia o el usuario toca el elemento de la lista cambia la visibilidad del encabezado.

Después de su setcontentview hacer algo como el siguiente código.

  ListView list = getListView(); View footer = getLayoutInflater().inflate(R.layout.footerlayout, list, false); View header = getLayoutInflater().inflate(R.layout.headerlayout, list, false); list.addHeaderView(header); list.addFooterView(footer); 

Sé que esta pregunta es un poco antigua, pero logró encontrar la biblioteca StickyListHeaders, que hace un trabajo bastante bueno de abstraer la creación de los encabezados de sección.

https://github.com/emilsjolander/StickyListHeaders

  • ScrollBar en un listView ... personalizándolo.
  • Personalización del spinner de Actionbar
  • Android: Crear un botón de alternancia con imagen y sin texto
  • Cambiar la fuente PreferenceFragment a través de fuentes de activos
  • Cómo personalizar la carta de vista previa de desplazamiento rápido
  • Cambiar color de texto y selector en TabWidget
  • ¿Cómo puedo cambiar el código predeterminado de la pantalla de inicio de Android y reemplazar mi código fuente de aplicación de la pantalla de inicio personalizada?
  • Android ListView con encabezado y pie de página fijos
  • Personalizar la lista de sugerencias de AutoCompletar vista de texto
  • ¿Cómo implementar la vista de pila personalizada en android?
  • Android: evita el truncamiento de texto en las sugerencias de SearchView?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.