Reutilizando vistas en Android Listview con 2 diseños diferentes

Aprendí que para maximizar la eficiencia con las listas de Android, solo debe tener tantas vistas infladas de “fila” como sean necesarias para que quepan en la pantalla. Una vez que una vista se ha movido de la pantalla, debe reutilizarla en su método getView , verificando si convertView es nulo o no.

Sin embargo, ¿cómo puede implementar esta idea cuando necesita 2 diseños diferentes para la lista? Digamos que es una lista de pedidos y 1 diseño es para pedidos completados y el otro diseño es para órdenes de proceso.

Este es un tutorial de ejemplo de la idea que mi código está usando. En mi caso, tendría 2 diseños de filas: R.layout.listview_item_product_complete y R.layout.listview_item_product_inprocess

 public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder = null; if (convertView == null) { holder = new ViewHolder(); if(getItemViewType(position) == COMPLETE_TYPE_INDEX) { convertView = mInflator.inflate(R.layout.listview_item_product_complete, null); holder.mNameTextView = (TextView) convertView.findViewById(R.list.text_complete); holder.mImgImageView = (ImageView) convertView.findViewById(R.list.img_complete); } else { // must be INPROCESS_TYPE_INDEX convertView = mInflator.inflate(R.layout.listview_item_product_inprocess, null); holder.mNameTextView = (TextView) convertView.findViewById(R.list.text_inprocess); holder.mImgImageView = (ImageView) convertView.findViewById(R.list.img_inprocess); } convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } thisOrder = (Order) myOrders.getOrderList().get(position); // If using different views for each type, use an if statement to test for type, like above holder.mNameTextView.setText(thisOrder.getNameValue()); holder.mImgImageView.setImageResource(thisOrder.getIconValue()); return convertView; } public static class ViewHolder { public TextView mNameTextView; public ImageView mImgImageView; } 

Debe dejar que el reciclador de vistas del adaptador sepa que hay más de un diseño y cómo distinguirlos para cada fila. Simplemente anule estos métodos:

 @Override public int getItemViewType(int position) { // Define a way to determine which layout to use, here it's just evens and odds. return position % 2; } @Override public int getViewTypeCount() { return 2; // Count of different layouts } 

Incorpora getItemViewType() dentro de getView() , así:

 if (convertView == null) { // You can move this line into your constructor, the inflater service won't change. mInflater = (LayoutInflater) mContext.getSystemService(LAYOUT_INFLATER_SERVICE); if(getItemViewType(position) == 0) convertView = mInflater.inflate(R.layout.listview_item_product_complete, parent, false); else convertView = mInflater.inflate(R.layout.listview_item_product_inprocess, parent, false); // etc, etc... 

Mira a Romain Guy de Android hablar sobre el reciclador de vistas en Google Talks.

No es necesario diseñar una solución usted mismo, simplemente anule getItemViewType () y getViewTypeCount ().

Consulte la siguiente publicación de blog para ver un ejemplo http://sparetimedev.blogspot.co.uk/2012/10/recycling-of-views-with-heterogeneous.html

Como explica el blog, Android en realidad no garantiza que getView reciba el tipo de vista correcto.