2010-08-18 15 views
46

Farklı öğeler için farklı düzenler içeren bir ListViewim var. Bazı öğeler ayırıcılar. Bazı öğeler farklıdır, çünkü bunlar farklı türde verileri barındırırlar, vb.Farklı öğe düzenleriyle ListViews için ViewHolders oluşturma

GetView işlemini hızlandırmak için ViewHolders'ı uygulamak istiyorum, ancak bunun nasıl yapılacağından emin değilim. Farklı düzenler farklı veri parçaları (adlandırma zorlaştırır) ve kullanmak istediğim farklı Sayılarda görünümleri vardır.

Bunu yapmak için nasıl gitmeliyim?

En iyi fikir, X öğelerini içeren X öğesi içeren genel bir ViewHolder oluşturmaktır; burada X, bir öğe düzeninde en yüksek sayıya sahip Görünüm sayısıdır. Az sayıda Görüntülenme ile diğer görünümler için, yalnızca ViewHolder'daki bu değişkenlerin alt bölümlerini kullanacağım. Yani 2 farklı öğe için kullandığım 2 düzenim var. Biri 3 TextViews ve diğeri 1'dir. 3 TextView değişkenine sahip bir ViewHolder yaratacağım ve sadece diğer öğem için bunlardan sadece birini kullanacağım. Benim sorunum, bu gerçekten çirkin görünümlü ve gerçekten hacky hissediyor olabilir; özellikle bir öğe düzeninde birçok farklı türde birçok Görüntülenme olduğunda.

Ben satır düzenlerinin farklı türde vardı
@Override 
public View getView(int position, View convertView, ViewGroup parent) { 

    MyHolder holder; 

    View v = convertView; 
    if (v == null) { 
     LayoutInflater vi = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
     v = vi.inflate(R.layout.layout_mylistlist_item, parent, false); 

     holder = new MyHolder(); 
     holder.text = (TextView) v.findViewById(R.id.mylist_itemname); 
     v.setTag(holder); 
    } 
    else { 
     holder = (MyHolder)v.getTag(); 
    } 

    MyListItem myItem = m_items.get(position); 

    // set up the list item 
    if (myItem != null) { 
     // set item text 
     if (holder.text != null) { 
      holder.text.setText(myItem.getItemName()); 
     } 
    } 

    // return the created view 
    return v; 
} 

varsayalım, ben sıranın her türü için bir ViewHolder olabilir:

Burada çok temel GetView olduğunu. Ama en üstte "sahibi" olarak ne tür bir tür ilan edeyim? Ya da her bir tip için bir tutucu ilan edip, üzerinde olduğum satırın türü için birini kullanır mıyım?

cevap

105

ListView, yerleşik bir tür yönetim sistemine sahiptir. Bağdaştırıcınızda, her biri kendi görünümü ve düzenine sahip çeşitli türde öğeleriniz vardır. Belirli bir konumun veri türünü döndürmek için getItemViewType'u geçersiz kılarak, ListView bu veri türü için doğru dönüştürmeyi iletmek üzere çağrıştırılır. Daha sonra, getView yönteminizde veri tipini kontrol edin ve her türü farklı bir şekilde işlemek için bir anahtar ifadesi kullanın. Netlik ve kolaylık sağlamak için her bir Düzen türünün kendi görüntüleyicisi olmalıdır. Her şeyi düz tutmak için ViewHolders'a her veri türü ile ilgili bir şey verin.

Her şeyi bir ViewHolder uygulamasında çakışmaya çalışmak sadece çabaya değmez.

düzenleme Örnek

@Override 
public View getView(int position, View convertView, ViewGroup parent) { 
    int viewType = this.getItemViewType(position); 

    switch(viewType) 
    { 
     case TYPE1: 

     Type1Holder holder1; 

     View v = convertView; 
     if (v == null) { 
      LayoutInflater vi = (LayoutInflater)getContext().getSystemService  (Context.LAYOUT_INFLATER_SERVICE); 
      v = vi.inflate(R.layout.layout_mylistlist_item_type_1, parent, false); 

      holder1 = new Type1Holder(); 
      holder1.text = (TextView) v.findViewById(R.id.mylist_itemname); 
      v.setTag(holder1); 
     } 
     else { 
      holder1 = (Type1Holder)v.getTag(); 
     } 

     MyListItem myItem = m_items.get(position); 

     // set up the list item 
     if (myItem != null) { 
      // set item text 
      if (holder1.text != null) { 
       holder1.text.setText(myItem.getItemName()); 
      } 
     } 

     // return the created view 
     return v; 


    case TYPE2: 
      Type2Holder holder2; 

     View v = convertView; 
     if (v == null) { 
      LayoutInflater vi = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
      v = vi.inflate(R.layout.layout_mylistlist_item_type_2, parent, false); 

      holder2 = new Type2Holder(); 
      holder2.text = (TextView) v.findViewById(R.id.mylist_itemname); 
      holder2.icon = (ImageView) v.findViewById(R.id.mylist_itemicon); 
      v.setTag(holder1); 
     } 
     else { 
      holder2 = (Type2Holder)v.getTag(); 
     } 

     MyListItem myItem = m_items.get(position); 

     // set up the list item 
     if (myItem != null) { 
      // set item text 
      if (holder2.text != null) { 
       holder2.text.setText(myItem.getItemName()); 
      } 

      if(holder2.icon != null) 
       holder2.icon.setDrawable(R.drawable.icon1); 
     } 


     // return the created view 
     return v; 


     default: 
      //Throw exception, unknown data type 
    } 
} 
+0

uzanır. ListActivities'imdaki getView işlevlerinin başında, tanımlanmış olan bu tutucu için ListView'ı başlatıyorum. Sonra null ve getTag için convertView kontrol edin veya tutucu oluşturmak ve öğeleri ayarlayın. Öğe türleri için farklı tutucular kullanacaksam, getView'ın başlangıcında sahip olduğumu nasıl bildirmeliyim? Veya tüm öğe türlerim için 1'i başlatmam ve satırın türüne karşılık gelen değeri başlatıp kullanmam gerekir mi? – Andrew

+0

Lütfen editörümüzü en güncel – Andrew

+0

@Andrew adresli web sitemize bakın, her bir tutucu durum ifadelerinden birinde ayrı ayrı tanımlanacaktır. Varolan kodunuzun tümünü ecah durum beyanına getirin, ancak her biri için görüntüleyici türünü ve veri işlemeyi değiştirin. Cevabımı bir örnekle biraz düzenleyeceğim. – CodeFusionMobile

0

başka örnek.

public class CardArrayAdapter Belki o zaman benim Java bazı fırçalama kadar ihtiyaç ArrayAdapter {

public CardArrayAdapter(Context context) { 
    super(context, R.layout.adapter_card); 
} 

@Override 
public View getView(int position, View view, ViewGroup parent) { 

    final Card card = getItem(position); 
    ViewHolder holder; 

    //if (view != null) { 
     //holder = (ViewHolder) view.getTag(); 
    //} else { 
    Log.d("card.important?", card.name + " = " + Boolean.toString(card.important)); 
    if(card.important) { 
     view = LayoutInflater.from(getContext()).inflate(R.layout.adapter_card_important, parent, false); 
    }else { 
     view = LayoutInflater.from(getContext()).inflate(R.layout.adapter_card, parent, false); 
    } 
    holder = new ViewHolder(view); 
    view.setTag(holder); 
    //} 

    // IMG 
    Picasso.with(getContext()) 
      .load(card.logo) 
      .placeholder(R.drawable.ic_phonebook) 
      .error(R.drawable.ic_phonebook) 
      .fit() 
      .centerCrop() 
      .transform(new CircleTransform()) 
      .into(holder.logo); 

    holder.name.setText(card.name); 

    if(card.important) { 
     holder.category.setVisibility(View.VISIBLE); 
     if (card.category.equals("airline")) { 
      card.category = "airlines"; 
     } 
     int id = getContext().getResources().getIdentifier(card.category, "string", getContext().getPackageName()); 
     holder.category.setText(getContext().getResources().getString(id)); 
    }else { 
     holder.category.setVisibility(View.GONE); 
    } 

    holder.tagline.setText(card.tagline); 
    holder.favorite.setChecked(card.favorite); 

    holder.favorite.setOnClickListener(new View.OnClickListener() { 
     @Override 
     public void onClick(View v) { 
      card.favorite = ((CheckBox) v).isChecked(); 
      card.save(); 
     } 
    }); 

    return view; 

} 

static class ViewHolder { 
    @InjectView(R.id.logo) ImageView logo; 
    @InjectView(R.id.name) TextView name; 
    @InjectView(R.id.category) TextView category; 
    @InjectView(R.id.tagline) TextView tagline; 
    @InjectView(R.id.favorite) CheckBox favorite; 
    public ViewHolder(View view) { 
     ButterKnife.inject(this, view); 
    } 
} 

}

+0

Sanırım, bu işe yarayacak, ancak görüntüleyiciyi daha az kullanılabilir hale getiriyor, çünkü türünü her değiştirdiğinde yeni düzeni şişiriyorsunuz – hakim

İlgili konular