IOS के UITableView के समान पंक्तियों / अनुभागों के तर्क को हैंडल करना Android में उतना सरल नहीं है जितना कि iOS में है, हालाँकि, जब आप RecyclerView का उपयोग करते हैं - तो आप जो कर सकते हैं उसका लचीलापन कहीं अधिक है।
अंत में, यह सब है कि आप कैसे पता लगाते हैं कि आप एडेप्टर में किस प्रकार का दृश्य प्रदर्शित कर रहे हैं। एक बार जब आप समझ गए कि यह आसान नौकायन होना चाहिए (वास्तव में नहीं, लेकिन कम से कम आपके पास इसका हल होगा)।
एडाप्टर दो तरीकों को उजागर करता है जिन्हें आपको ओवरराइड करना चाहिए:
getItemViewType(int position)
इस पद्धति का डिफ़ॉल्ट कार्यान्वयन हमेशा 0 लौटाएगा, यह दर्शाता है कि केवल 1 प्रकार का दृश्य है। आपके मामले में, ऐसा नहीं है, और इसलिए आपको यह पता लगाने की आवश्यकता होगी कि कौन सी पंक्ति किस प्रकार के दृश्य से मेल खाती है। IOS के विपरीत, जो इसे आपके लिए पंक्तियों और अनुभागों के साथ प्रबंधित करता है, यहां आपके पास भरोसा करने के लिए केवल एक सूचकांक होगा, और आपको यह जानने के लिए अपने डेवलपर कौशल का उपयोग करने की आवश्यकता होगी कि कोई स्थिति किसी शीर्ष लेख से संबंधित है, और जब यह संबंधित है एक सामान्य पंक्ति।
createViewHolder(ViewGroup parent, int viewType)
आपको वैसे भी इस पद्धति को ओवरराइड करने की आवश्यकता है, लेकिन आमतौर पर लोग केवल व्यू टाइप पैरामीटर की उपेक्षा करते हैं। दृश्य प्रकार के अनुसार, आपको सही लेआउट संसाधन को बढ़ाने और तदनुसार अपना व्यू धारक बनाने की आवश्यकता होगी। RecyclerView अलग-अलग प्रकार के व्यूज़ को एक तरह से रीसाइकिल करने का काम करेगा, जो अलग-अलग व्यू टाइप्स के क्लैशिंग से बचा जाता है।
यदि आप एक डिफ़ॉल्ट LayoutManager का उपयोग करने की योजना बना रहे हैं, जैसे कि LinearLayoutManager
, आपको जाना अच्छा होना चाहिए। यदि आप अपना स्वयं का लेआउट प्रबंधन लागू करने की योजना बना रहे हैं, तो आपको थोड़ी सी मेहनत करने की आवश्यकता होगी। एकमात्र एपीआई जिसे आपको वास्तव में काम करना है, findViewByPosition(int position)
जो एक निश्चित स्थिति पर एक दिया गया दृश्य देता है। चूंकि आप शायद इसे अलग तरीके से रखना चाहते हैं, इसलिए यह देखने के लिए कि यह किस प्रकार का है, आपके पास कुछ विकल्प हैं:
आमतौर पर ViewHolder पैटर्न का उपयोग करते समय, आप व्यू होल्डर के साथ व्यू का टैग सेट करते हैं। आप लेआउट प्रबंधक में रनटाइम के दौरान इसका उपयोग यह पता लगाने के लिए कर सकते हैं कि व्यू होल्डर में एक फ़ील्ड जोड़कर किस प्रकार का दृश्य व्यक्त किया गया है।
चूँकि आपको एक फ़ंक्शन की आवश्यकता होगी जो यह निर्धारित करता है कि कौन सी स्थिति किस प्रकार के दृश्य से संबंधित है, आप इस विधि को विश्व स्तर पर किसी भी तरह सुलभ कर सकते हैं (शायद एक एकल वर्ग जो डेटा का प्रबंधन करता है?), और फिर आप बस उसी विधि के अनुसार क्वेरी कर सकते हैं? स्थिति।
यहाँ एक कोड नमूना है:
// in this sample, I use an object array to simulate the data of the list.
// I assume that if the object is a String, it means I should display a header with a basic title.
// If not, I assume it's a custom model object I created which I will use to bind my normal rows.
private Object[] myData;
public static final int ITEM_TYPE_NORMAL = 0;
public static final int ITEM_TYPE_HEADER = 1;
public class MyAdapter extends Adapter<ViewHolder> {
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == ITEM_TYPE_NORMAL) {
View normalView = LayoutInflater.from(getContext()).inflate(R.layout.my_normal_row, null);
return new MyNormalViewHolder(normalView); // view holder for normal items
} else if (viewType == ITEM_TYPE_HEADER) {
View headerRow = LayoutInflater.from(getContext()).inflate(R.layout.my_header_row, null);
return new MyHeaderViewHolder(headerRow); // view holder for header items
}
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
final int itemType = getItemViewType(position);
if (itemType == ITEM_TYPE_NORMAL) {
((MyNormalViewHolder)holder).bindData((MyModel)myData[position]);
} else if (itemType == ITEM_TYPE_HEADER) {
((MyHeaderViewHolder)holder).setHeaderText((String)myData[position]);
}
}
@Override
public int getItemViewType(int position) {
if (myData[position] instanceof String) {
return ITEM_TYPE_HEADER;
} else {
return ITEM_TYPE_NORMAL;
}
}
@Override
public int getItemCount() {
return myData.length;
}
}
यहाँ एक नमूना है कि ये देखने वाले को कैसा दिखना चाहिए:
public MyHeaderViewHolder extends ViewHolder {
private TextView headerLabel;
public MyHeaderViewHolder(View view) {
super(view);
headerLabel = (TextView)view.findViewById(R.id.headerLabel);
}
public void setHeaderText(String text) {
headerLabel.setText(text);
}
}
public MyNormalViewHolder extends ViewHolder {
private TextView titleLabel;
private TextView descriptionLabel;
public MyNormalViewHolder(View view) {
super(view);
titleLabel = (TextView)view.findViewById(R.id.titleLabel);
descriptionLabel = (TextView)view.findViewById(R.id.descriptionLabel);
}
public void bindData(MyModel model) {
titleLabel.setText(model.getTitle());
descriptionLabel.setText(model.getDescription());
}
}
बेशक, यह नमूना मानता है कि आपने अपने डेटा स्रोत (myData) का निर्माण इस तरह से किया है कि इस तरह से एडॉप्टर को लागू करना आसान हो जाता है। एक उदाहरण के रूप में, मैं आपको दिखाता हूं कि मैं एक डेटा स्रोत का निर्माण कैसे करूंगा जो नामों की एक सूची दिखाता है, और हर बार हेडर में नाम का पहला अक्षर बदलता है (मान लें कि सूची वर्णानुक्रम में है) - एक संपर्क के समान सूची इस तरह दिखाई देगी:
// Assume names & descriptions are non-null and have the same length.
// Assume names are alphabetized
private void processDataSource(String[] names, String[] descriptions) {
String nextFirstLetter = "";
String currentFirstLetter;
List<Object> data = new ArrayList<Object>();
for (int i = 0; i < names.length; i++) {
currentFirstLetter = names[i].substring(0, 1); // get the 1st letter of the name
// if the first letter of this name is different from the last one, add a header row
if (!currentFirstLetter.equals(nextFirstLetter)) {
nextFirstLetter = currentFirstLetter;
data.add(nextFirstLetter);
}
data.add(new MyModel(names[i], descriptions[i]));
}
myData = data.toArray();
}
यह उदाहरण काफी विशिष्ट मुद्दे को हल करने के लिए आता है, लेकिन मुझे आशा है कि यह आपको एक पुनर्नवीनीकरण में विभिन्न पंक्ति प्रकारों को संभालने के लिए एक अच्छा अवलोकन देता है, और आपको अपनी आवश्यकताओं को फिट करने के लिए अपने स्वयं के कोड में आवश्यक अनुकूलन करने की अनुमति देता है।