2010-08-18 18 views
46

मेरे पास अलग-अलग आइटमों के लिए अलग-अलग लेआउट के साथ एक सूची दृश्य है। कुछ आइटम विभाजक हैं। कुछ आइटम अलग-अलग होते हैं क्योंकि वे विभिन्न प्रकार के डेटा, आदिविभिन्न आइटम लेआउट के साथ ListViews के लिए ViewHolders बनाना

मैं GetView प्रक्रिया को तेज़ करने के लिए व्यूहोल्डर्स को कार्यान्वित करना चाहता हूं, लेकिन मुझे पूरा यकीन नहीं है कि इसके बारे में कैसे जाना है। विभिन्न लेआउट में डेटा के अलग-अलग टुकड़े होते हैं (जो नामकरण को मुश्किल बनाते हैं) और विभिन्न दृश्यों का उपयोग करना जिन्हें मैं उपयोग करना चाहता हूं।

मुझे यह करने के बारे में कैसे जाना चाहिए?

एक्स के साथ एक सामान्य व्यूहोल्डर बनाने के लिए सबसे अच्छा विचार है, जहां एक्स सबसे अधिक संख्या वाले आइटम लेआउट में दृश्यों की संख्या है। दृश्यों की एक छोटी संख्या के साथ अन्य विचारों के लिए, मैं केवल व्यूहोल्डर में उन चर के उपखंड का उपयोग करूंगा। तो कहें कि मेरे पास 2 लेआउट हैं जो मैं 2 अलग-अलग वस्तुओं के लिए उपयोग करता हूं। एक में 3 टेक्स्ट व्यू हैं और दूसरे के पास 1 है। मैं 3 टेक्स्ट व्यू चर के साथ एक व्यूहोल्डर बनाउंगा और केवल अपने अन्य आइटम के लिए उनमें से 1 का उपयोग करूंगा। मेरी समस्या यह है कि यह वास्तव में बदसूरत लग रहा है और वास्तव में हैकी लगता है; खासकर जब किसी आइटम लेआउट में कई अलग-अलग प्रकार के कई दृश्य हो सकते हैं।

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

मान लीजिए मैं पंक्ति लेआउट के विभिन्न प्रकार थी, मैं पंक्ति के प्रत्येक प्रकार के लिए एक ViewHolder हो सकता है:

यहाँ एक बहुत ही बुनियादी getView है। लेकिन मैं किस प्रकार "धारक" को शीर्ष पर घोषित करूंगा? या मैं प्रत्येक प्रकार के लिए धारक घोषित करता हूं और फिर उस पंक्ति के प्रकार के लिए उपयोग करता हूं जिस पर मैं हूं।

उत्तर

105

ListView में एक प्रकार का प्रबंधन प्रणाली है। अपने एडाप्टर में, आपके पास कई प्रकार के आइटम होते हैं, जिनमें से प्रत्येक अपने स्वयं के दृश्य और लेआउट के साथ होता है। किसी दिए गए स्थान के डेटा प्रकार को वापस करने के लिए getItemViewType ओवरराइड करके, सूची दृश्य उस प्रकार के डेटा के लिए सही कन्वर्टव्यू में पास करने के लिए स्वयंसेवी है। फिर, अपनी getView विधि में बस डेटाटाइप की जांच करें और प्रत्येक प्रकार को अलग-अलग संभालने के लिए स्विच स्टेटमेंट का उपयोग करें।

प्रत्येक लेआउट प्रकार में स्पष्टता नामकरण और बनाए रखने में आसानी के लिए अपना स्वयं का व्यूअर होना चाहिए। सब कुछ सीधे रखने के लिए प्रत्येक डेटा प्रकार से संबंधित व्यूहोल्डर्स को कुछ नाम दें।

एक व्यूहोल्डर में सबकुछ ओवरलैप करने का प्रयास करना केवल प्रयास के लायक नहीं है।

संपादित उदाहरण

@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

फैली शायद मैं तो मेरे जावा पर कुछ ब्रश करने की जरूरत है। मेरी ListActivities में getView फ़ंक्शंस की शुरुआत में, मैं उस सूची दृश्य के लिए अपने परिभाषित धारक को तुरंत चालू करता हूं। मैं फिर कन्वर्ट व्यू को नल के लिए जांचता हूं और या तो GetTag प्राप्त करता हूं या धारक बनाता हूं और आइटम सेट करता हूं। यदि मैं आइटम प्रकारों के लिए अलग-अलग धारकों का उपयोग करने जा रहा हूं, तो मुझे GetView की शुरुआत में अपने धारक को क्या घोषित करना चाहिए? या क्या मुझे अपने सभी आइटम प्रकारों के लिए 1 को चालू करने और पंक्ति के प्रकार से मेल खाने वाले किसी व्यक्ति को प्रारंभ करने और उपयोग करने की आवश्यकता है? – Andrew

+0

कृपया मेरे संपादित पोस्ट को शीर्ष – Andrew

+0

@Andrew देखें, प्रत्येक धारक को व्यक्तिगत विवरणों में से एक में व्यक्तिगत रूप से परिभाषित किया जाएगा। अपने सभी मौजूदा कोड को इक्का केस कथन में रखें, लेकिन प्रत्येक के लिए व्यूल्डर प्रकार और डेटा हैंडलिंग बदलें। मैं थोड़ा सा उदाहरण के साथ अपना जवाब संपादित करूंगा। – CodeFusionMobile

0

एक अन्य उदाहरण है।

सार्वजनिक वर्ग CardArrayAdapter 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

मुझे लगता है, यह काम करेगा, लेकिन यह दर्शक को कम उपयोग करने योग्य बनाता है, क्योंकि हर बार जब यह बदलता है, तो आप नया लेआउट बढ़ाते हैं – hakim

संबंधित मुद्दे