Повторное использование представлений в Android Listview с 2 различными макетами

Я узнал, что для максимизации эффективности с помощью списков просмотра 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;
}

2 ответа

Решение

Вам нужно сообщить представителю адаптера представления о том, что существует более одного макета и как различать два для каждого ряда. Просто переопределите эти методы:

@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
}

инкорпорировать 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 обсуждает вопрос об утилизации в Google Talks.

Не нужно самостоятельно разрабатывать решение, просто переопределите getItemViewType() и getViewTypeCount().

См. Следующий пост в блоге для примера http://sparetimedev.blogspot.co.uk/2012/10/recycling-of-views-with-heterogeneous.html

Как объясняется в блоге, Android фактически не гарантирует, что getView получит правильный тип просмотра.

Другие вопросы по тегам