web-dev-qa-db-fra.com

Réutilisation des vues dans Android Listview avec 2 dispositions différentes

J'ai appris que pour maximiser l'efficacité avec Android listviews, vous ne devriez avoir que le nombre de vues "lignes" gonflées nécessaires pour tenir sur l'écran. Une fois qu'une vue a quitté l'écran, vous devez le réutiliser dans votre méthode getView, en vérifiant si convertView est nul ou non.

Cependant, comment pouvez-vous mettre en œuvre cette idée lorsque vous avez besoin de 2 dispositions différentes pour la liste? Disons que c'est une liste de commandes et 1 mise en page est pour les commandes terminées et l'autre mise en page est pour les commandes en cours.

Ceci est un exemple de tutoriel de l'idée que mon code utilise. Dans mon cas, j'aurais deux dispositions de ligne: R.layout.listview_item_product_complete et 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;
}
39
jamis0n

Vous devez indiquer au recycleur de vues de l'adaptateur qu'il existe plusieurs mises en page et savoir comment les distinguer pour chaque ligne. Remplacez simplement ces méthodes:

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

Incorporez getItemViewType() à l'intérieur de getView(), comme ceci:

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...

Regardez Romain Guy d'Android discutez du recycleur de vues sur Google Talks.

84
Sam

Pas besoin de concevoir une solution vous-même, remplacez simplement getItemViewType () et getViewTypeCount ().

Voir le billet de blog suivant pour un exemple http://sparetimedev.blogspot.co.uk/2012/10/recycling-of-views-with-heterogeneous.html

Comme l'explique le blog, Android ne garantit pas réellement que getView recevra le bon type de vue.

9
Andy