Повторное использование просмотров в Android Listview с двумя различными макетами
Я узнал, что для максимальной эффективности с помощью списков Android вы должны иметь столько раздутых "рядовых" представлений, сколько необходимо для установки на экран. Когда представление переместилось с экрана, вы должны повторно использовать его в методе getView
, проверяя, является ли convertView
нулевым или нет.
Однако, как вы можете реализовать эту идею, когда вам нужны 2 разных макета для списка? Допустим, что его список заказов и 1 макет для завершенных заказов, а другой макет - в технологических заказах.
Это пример учебника, который использует мой код. В моем случае у меня было бы 2 строковых макета: R.layout.listview_item_product_complete
и 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;
}
Ответы
Ответ 1
Вы должны позволить адаптеру просмотреть recycler, чтобы знать, что существует более одного макета и как различать два для каждой строки. Просто переопределите эти методы:
@Override
public int getItemViewType(int position) {
// Define a way to determine which layout to use, here it just evens and odds.
return position % 2;
}
@Override
public int getViewTypeCount() {
return 2; // Count of different layouts
}
Включите getItemViewType()
внутри getView()
, например:
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...
Наблюдайте за Android Romain Guy обсудите ресайклинг просмотров в Google Talks.
Ответ 2
Не нужно самостоятельно разрабатывать решение, просто переопределите getItemViewType() и getViewTypeCount().
См. следующее сообщение в блоге для примера http://sparetimedev.blogspot.co.uk/2012/10/recycling-of-views-with-heterogeneous.html
Как поясняет блог, Android фактически не гарантирует, что getView получит правильный тип представления.