दिलचस्प पोस्ट
सीधे डेटाबेस में या आधार64 डेटा के रूप में छवि को संग्रहीत करना? छवि टैग के नीचे रहस्य सफेद स्थान भारतीय नंबरिंग प्रारूप में मुद्रा प्रदर्शित स्काला में प्रकार के लम्ब्दास क्या हैं और उनके लाभ क्या हैं? पायथन 3 आयात इरर: 'मॉड्यूल' नामक कोई मॉड्यूल 'कॉन्फ़िगरपर्स' JQuery या जावास्क्रिप्ट के साथ एक डबल करने के लिए एक मुद्रा स्ट्रिंग कैसे परिवर्तित करें? टीसीपी क्लाइंट से सर्वर संचार .text, .value, और .value2 में अंतर क्या है? मैं जावास्क्रिप्ट के साथ iframe तत्वों का उपयोग कैसे कर सकता हूं? पायथन ने व्याख्या की है, या संकलित, या दोनों? Mysql से रिमोट कनेक्शन को कैसे अनुमति दें जावास्क्रिप्ट में मैं UTC टाइमस्टैम्प कैसे प्राप्त करूं? आप Java या C # में कुशल परिपत्र बफर कैसे कोड करेंगे पायथन – आयातित मॉड्यूल में वैश्विक चर की दृश्यता पोस्ट अनुरोध json डेटा java HttpUrlConnection भेजें

एकाधिक दृश्य प्रकार के साथ रीसाइक्लियर दृश्य कैसे बनाएं?

Https://developer.android.com/preview/material/ui-widgets.html से

जब हम RecyclerView.Adapter ViewHolder । एडेप्टर बनाते हैं तो हमें उस ViewHolder को निर्दिष्ट करना होगा जो उस एडाप्टर के साथ बाँध लेंगे।

 public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> { private String[] mDataset; public MyAdapter(String[] myDataset) { mDataset = myDataset; } public static class ViewHolder extends RecyclerView.ViewHolder { public TextView mTextView; public ViewHolder(TextView v) { super(v); mTextView = v; } } @Override public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.some_layout, parent, false); //findViewById... ViewHolder vh = new ViewHolder(v); return vh; } @Override public void onBindViewHolder(ViewHolder holder, int position) { holder.mTextView.setText(mDataset[position]); } @Override public int getItemCount() { return mDataset.length; } } 

तो, क्या एकाधिक दृश्य प्रकार के साथ RecyclerView दृश्य बनाना संभव है?

वेब के समाधान से एकत्रित समाधान "एकाधिक दृश्य प्रकार के साथ रीसाइक्लियर दृश्य कैसे बनाएं?"

हाँ, यह मुमकिन है। बस getItemViewType () को लागू करें, और onCreateViewHolder () में viewType पैरामीटर का ख्याल रखना।

तो आप ऐसा कुछ करते हैं:

 public class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { class ViewHolder0 extends RecyclerView.ViewHolder { ... public ViewHolder0(View itemView){ ... } } class ViewHolder2 extends RecyclerView.ViewHolder { ... public ViewHolder2(View itemView){ ... } @Override public int getItemViewType(int position) { // Just as an example, return 0 or 2 depending on position // Note that unlike in ListView adapters, types don't have to be contiguous return position % 2 * 2; } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { switch (viewType) { case 0: return new ViewHolder0(...); case 2: return new ViewHolder2(...); ... } } @Override public void onBindViewHolder(final RecyclerView.ViewHolder holder, final int position) { switch (holder.getItemViewType()) { case 0: ViewHolder0 viewHolder0 = (ViewHolder0)holder; ... break; case 2: ViewHolder2 viewHolder2 = (ViewHolder2)holder; ... break; } } } 

यदि दृश्य प्रकारों के लिए लेआउट केवल कुछ ही हैं और बाइंडिंग लॉजिक सरल हैं, तो एंटोन के समाधान का पालन करें।
लेकिन अगर आपको जटिल लेआउट और बाइंडिंग लॉजिक का प्रबंधन करने की आवश्यकता है तो कोड गन्दा होगा।

मेरा मानना ​​है कि निम्न समाधान किसी ऐसे व्यक्ति के लिए उपयोगी होगा जो जटिल दृश्य प्रकारों को संभालना चाहते हैं।

बेस डाटाबिन्डर क्लास

 abstract public class DataBinder<T extends RecyclerView.ViewHolder> { private DataBindAdapter mDataBindAdapter; public DataBinder(DataBindAdapter dataBindAdapter) { mDataBindAdapter = dataBindAdapter; } abstract public T newViewHolder(ViewGroup parent); abstract public void bindViewHolder(T holder, int position); abstract public int getItemCount(); ...... } 

इस वर्ग में परिभाषित करने के लिए आवश्यक कार्यों को एडेप्टर वर्ग के समान ही देखा जा सकता है, जब एकल दृश्य प्रकार बनाते हैं।
प्रत्येक दृश्य प्रकार के लिए, इस डेटाबिन्डर को बढ़ाकर वर्ग बनाएं।

नमूना डेटाबिन्डर वर्ग

 public class Sample1Binder extends DataBinder<Sample1Binder.ViewHolder> { private List<String> mDataSet = new ArrayList(); public Sample1Binder(DataBindAdapter dataBindAdapter) { super(dataBindAdapter); } @Override public ViewHolder newViewHolder(ViewGroup parent) { View view = LayoutInflater.from(parent.getContext()).inflate( R.layout.layout_sample1, parent, false); return new ViewHolder(view); } @Override public void bindViewHolder(ViewHolder holder, int position) { String title = mDataSet.get(position); holder.mTitleText.setText(title); } @Override public int getItemCount() { return mDataSet.size(); } public void setDataSet(List<String> dataSet) { mDataSet.addAll(dataSet); } static class ViewHolder extends RecyclerView.ViewHolder { TextView mTitleText; public ViewHolder(View view) { super(view); mTitleText = (TextView) view.findViewById(R.id.title_type1); } } } 

डेटाबेंडर वर्गों का प्रबंधन करने के लिए, एडेप्टर क्लास बनाएं।

बेस डेटाबिंड एडेप्टर क्लास

 abstract public class DataBindAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { return getDataBinder(viewType).newViewHolder(parent); } @Override public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) { int binderPosition = getBinderPosition(position); getDataBinder(viewHolder.getItemViewType()).bindViewHolder(viewHolder, binderPosition); } @Override public abstract int getItemCount(); @Override public abstract int getItemViewType(int position); public abstract <T extends DataBinder> T getDataBinder(int viewType); public abstract int getPosition(DataBinder binder, int binderPosition); public abstract int getBinderPosition(int position); ...... } 

इस बेस क्लास का विस्तार करके कक्षा बनाएं, और फिर डेटाबैंकर कक्षाएं इन्स्तांत करें और सार विधियों को ओवरराइड करें

  1. getItemCount
    डेटाबंडर्स की कुल आइटम संख्या वापस लौटें

  2. getItemViewType
    एडेप्टर स्थिति और दृश्य प्रकार के बीच मानचित्रण तर्क को परिभाषित करें

  3. getDataBinder
    दृश्य प्रकार के आधार पर DataBinder उदाहरण लौटें

  4. getPosition
    निर्दिष्ट डेटाबिंदर में स्थिति से एडेप्टर स्थिति में तर्क परिवर्तित करें

  5. getBinderPosition
    एडेप्टर स्थिति से डेटाबिंदर में स्थिति में तर्क परिवर्तित करें

आशा है कि यह समाधान उपयोगी होगा
मैंने गिटहब में अधिक विस्तार समाधान और नमूनों को छोड़ दिया है, इसलिए यदि आपको इसकी आवश्यकता है तो निम्न लिंक देखें
https://github.com/yqritc/RecyclerView-MultipleViewTypesAdapter

नीचे स्यूडोकोड नहीं है और मैंने इसे परीक्षण किया है और यह मेरे लिए काम किया है

मैं अपने रीसाइक्लिव्यू में एक हेडर्व्हीव बनाना चाहता था और फिर शीर्षलेख के नीचे चित्रों की एक सूची प्रदर्शित करना चाहता था, जिस पर उपयोगकर्ता क्लिक कर सकता है।

मैंने अपने कोड में कुछ स्विच इस्तेमाल किए, पता नहीं कि यह ऐसा करने का सबसे कारगर तरीका है, तो अपनी टिप्पणी देने में संकोच करें:

  public class ViewHolder extends RecyclerView.ViewHolder{ //These are the general elements in the RecyclerView public TextView place; public ImageView pics; //This is the Header on the Recycler (viewType = 0) public TextView name, description; //This constructor would switch what to findViewBy according to the type of viewType public ViewHolder(View v, int viewType) { super(v); if (viewType == 0) { name = (TextView) v.findViewById(R.id.name); decsription = (TextView) v.findViewById(R.id.description); } else if (viewType == 1) { place = (TextView) v.findViewById(R.id.place); pics = (ImageView) v.findViewById(R.id.pics); } } } @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View v; ViewHolder vh; // create a new view switch (viewType) { case 0: //This would be the header view in my Recycler v = LayoutInflater.from(parent.getContext()) .inflate(R.layout.recyclerview_welcome, parent, false); vh = new ViewHolder(v,viewType); return vh; default: //This would be the normal list with the pictures of the places in the world v = LayoutInflater.from(parent.getContext()) .inflate(R.layout.recyclerview_picture, parent, false); vh = new ViewHolder(v, viewType); v.setOnClickListener(new View.OnClickListener(){ @Override public void onClick(View v) { Intent intent = new Intent(mContext, nextActivity.class); intent.putExtra("ListNo",mRecyclerView.getChildPosition(v)); mContext.startActivity(intent); } }); return vh; } } //Overriden so that I can display custom rows in the recyclerview @Override public int getItemViewType(int position) { int viewType = 1; //Default is 1 if (position == 0) viewType = 0; //if zero, it will be a header view return viewType; } @Override public void onBindViewHolder(ViewHolder holder, int position) { //position == 0 means its the info header view on the Recycler if (position == 0) { holder.name.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(mContext,"name clicked", Toast.LENGTH_SHORT).show(); } }); holder.description.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(mContext,"description clicked", Toast.LENGTH_SHORT).show(); } }); //this means it is beyond the headerview now as it is no longer 0. For testing purposes, I'm alternating between two pics for now } else if (position > 0) { holder.place.setText(mDataset[position]); if (position % 2 == 0) { holder.pics.setImageDrawable(mContext.getResources().getDrawable(R.drawable.pic1)); } if (position % 2 == 1) { holder.pics.setImageDrawable(mContext.getResources().getDrawable(R.drawable.pic2)); } } } 

हाँ यह संभव है।

एक सामान्य दृश्य धारक लिखें:

  public abstract class GenericViewHolder extends RecyclerView.ViewHolder { public GenericViewHolder(View itemView) { super(itemView); } public abstract void setDataOnView(int position); } 

फिर अपने दृश्य धारकों को बनाएं और उन्हें जेनेरिक व्ह्यूहॉल्डर का विस्तार करें उदाहरण के लिए, यह एक:

  public class SectionViewHolder extends GenericViewHolder{ public final View mView; public final TextView dividerTxtV; public SectionViewHolder(View itemView) { super(itemView); mView = itemView; dividerTxtV = (TextView) mView.findViewById(R.id.dividerTxtV); } @Override public void setDataOnView(int position) { try { String title= sections.get(position); if(title!= null) this.dividerTxtV.setText(title); }catch (Exception e){ new CustomError("Error!"+e.getMessage(), null, false, null, e); } } } 

तो RecyclerView.Adapter वर्ग इस तरह दिखेगा:

 public class MyClassRecyclerViewAdapter extends RecyclerView.Adapter<MyClassRecyclerViewAdapter.GenericViewHolder> { @Override public int getItemViewType(int position) { // depends on your problem switch (position) { case : return VIEW_TYPE1; case : return VIEW_TYPE2; ... } } @Override public GenericViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view; if(viewType == VIEW_TYPE1){ view = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout1, parent, false); return new SectionViewHolder(view); }else if( viewType == VIEW_TYPE2){ view = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout2, parent, false); return new OtherViewHolder(view); } // Cont. other view holders ... return null; } @Override public void onBindViewHolder(GenericViewHolder holder, int position) { holder.setDataOnView(position); } 

एंटोन के समाधान के बाद, इस ViewHolder साथ आते हैं जो विभिन्न प्रकार के लेआउट रखता है / प्रतिनिधि हैं। लेकिन सुनिश्चित नहीं है कि नए लेआउट की जगह काम करने पर रीसाइक्लिंग व्यू के ViewHolder डेटा रोल का प्रकार नहीं है।

तो मूलतः, onCreateViewHolder(ViewGroup parent, int viewType) व्यू onCreateViewHolder(ViewGroup parent, int viewType) केवल तब ही कहा जाता है जब नए दृश्य लेआउट की आवश्यकता होती है;

getItemViewType(int position) को getItemViewType(int position) लिए बुलाया जाएगा;

onBindViewHolder(ViewHolder holder, int position) को हमेशा दृश्य में रीसाइक्लिंग करते समय कहा जाता है (नया डेटा लाया जाता है और उस ViewHolder साथ प्रदर्शित करने का प्रयास करता है)

इसलिए जब onBindViewHolder को कहा जाता है, तो उसे सही दृश्य लेआउट में डाल दिया जाना चाहिए और ViewHolder अपडेट करना होगा।

क्या उस व्यू- ViewHolder को किसी भी समस्या में ले जाने के लिए दृश्य लेआउट की जगह सही है? किसी भी टिप्पणी की सराहना!

 public int getItemViewType(int position) { TypedData data = mDataSource.get(position); return data.type; } public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { return ViewHolder.makeViewHolder(parent, viewType); } public void onBindViewHolder(ViewHolder holder, int position) { TypedData data = mDataSource.get(position); holder.updateData(data); } /// public static class ViewHolder extends RecyclerView.ViewHolder { ViewGroup mParentViewGroup; View mCurrentViewThisViewHolderIsFor; int mDataType; public TypeOneViewHolder mTypeOneViewHolder; public TypeTwoViewHolder mTypeTwoViewHolder; static ViewHolder makeViewHolder(ViewGroup vwGrp, int dataType) { View v = getLayoutView(vwGrp, dataType); return new ViewHolder(vwGrp, v, viewType); } static View getLayoutView(ViewGroup vwGrp, int dataType) { int layoutId = getLayoutId(dataType); return LayoutInflater.from(vwGrp.getContext()) .inflate(layoutId, null); } static int getLayoutId(int dataType) { if (dataType == TYPE_ONE) { return R.layout.type_one_layout; } else if (dataType == TYPE_TWO) { return R.layout.type_two_layout; } } public ViewHolder(ViewGroup vwGrp, View v, int dataType) { super(v); mDataType = dataType; mParentViewGroup = vwGrp; mCurrentViewThisViewHolderIsFor = v; if (data.type == TYPE_ONE) { mTypeOneViewHolder = new TypeOneViewHolder(v); } else if (data.type == TYPE_TWO) { mTypeTwoViewHolder = new TypeTwoViewHolder(v); } } public void updateData(TypeData data) { mDataType = data.type; if (data.type == TYPE_ONE) { mTypeTwoViewHolder = null; if (mTypeOneViewHolder == null) { View newView = getLayoutView(mParentViewGroup, data.type); /** * how to replace new view with the view in the parent view container ??? */ replaceView(mCurrentViewThisViewHolderIsFor, newView); mCurrentViewThisViewHolderIsFor = newView; mTypeOneViewHolder = new TypeOneViewHolder(newView); } mTypeOneViewHolder.updateDataTypeOne(data); } else if (data.type == TYPE_TWO){ mTypeOneViewHolder = null; if (mTypeTwoViewHolder == null) { View newView = getLayoutView(mParentViewGroup, data.type); /** * how to replace new view with the view in the parent view container ??? */ replaceView(mCurrentViewThisViewHolderIsFor, newView); mCurrentViewThisViewHolderIsFor = newView; mTypeTwoViewHolder = new TypeTwoViewHolder(newView); } mTypeTwoViewHolder.updateDataTypeOne(data); } } } public static void replaceView(View currentView, View newView) { ViewGroup parent = (ViewGroup)currentView.getParent(); if(parent == null) { return; } final int index = parent.indexOfChild(currentView); parent.removeView(currentView); parent.addView(newView, index); } 

संपादित करें: दृश्य को देखने के लिए ViewHolder के सदस्य mItemViewType है

संपादित करें: onBindViewHolder (ViewHolder धारक, इंट की स्थिति) की तरह दिखता है, इसे देखने के लिए getItemViewType (इंट की स्थिति) पर देखा गया है (या बनाया गया), वोह मैच है, इसलिए इसमें चिंता करने की आवश्यकता नहीं हो सकती है कि व्यूहाल्डर्स प्रकार डेटा [स्थिति] के प्रकार से मेल नहीं खाती क्या किसी को भी पता है कि onBindViewHolder () में ViewHolder कैसे उठाया गया है?

संपादित करें: ऐसा लगता है कि रीसायकल ViewHolder को प्रकार से चुना गया है, इसलिए कोई योद्धा नहीं है

संपादित करें: http://wiresareobsolete.com/2014/09/building-a-recyclerview-layoutmanager-part-1/ इस सवाल का जवाब

इसे रीसायकल ViewHolder तरह मिलता है:

 holder = getRecycledViewPool().getRecycledView(mAdapter.getItemViewType(offsetPosition)); 

या एक नया बनाने के लिए यदि सही प्रकार के ViewHolder नहीं मिलते

 public ViewHolder getRecycledView(int viewType) { final ArrayList<ViewHolder> scrapHeap = mScrap.get(viewType); if (scrapHeap != null && !scrapHeap.isEmpty()) { final int index = scrapHeap.size() - 1; final ViewHolder scrap = scrapHeap.get(index); scrapHeap.remove(index); return scrap; } return null; } View getViewForPosition(int position, boolean dryRun) { ...... if (holder == null) { final int offsetPosition = mAdapterHelper.findPositionOffset(position); if (offsetPosition < 0 || offsetPosition >= mAdapter.getItemCount()) { throw new IndexOutOfBoundsException("Inconsistency detected. Invalid item " + "position " + position + "(offset:" + offsetPosition + ")." + "state:" + mState.getItemCount()); } final int type = mAdapter.getItemViewType(offsetPosition); // 2) Find from scrap via stable ids, if exists if (mAdapter.hasStableIds()) { holder = getScrapViewForId(mAdapter.getItemId(offsetPosition), type, dryRun); if (holder != null) { // update position holder.mPosition = offsetPosition; fromScrap = true; } } if (holder == null && mViewCacheExtension != null) { // We are NOT sending the offsetPosition because LayoutManager does not // know it. final View view = mViewCacheExtension .getViewForPositionAndType(this, position, type); if (view != null) { holder = getChildViewHolder(view); if (holder == null) { throw new IllegalArgumentException("getViewForPositionAndType returned" + " a view which does not have a ViewHolder"); } else if (holder.shouldIgnore()) { throw new IllegalArgumentException("getViewForPositionAndType returned" + " a view that is ignored. You must call stopIgnoring before" + " returning this view."); } } } if (holder == null) { // fallback to recycler // try recycler. // Head to the shared pool. if (DEBUG) { Log.d(TAG, "getViewForPosition(" + position + ") fetching from shared " + "pool"); } holder = getRecycledViewPool() .getRecycledView(mAdapter.getItemViewType(offsetPosition)); if (holder != null) { holder.resetInternal(); if (FORCE_INVALIDATE_DISPLAY_LIST) { invalidateDisplayListInt(holder); } } } if (holder == null) { holder = mAdapter.createViewHolder(RecyclerView.this, mAdapter.getItemViewType(offsetPosition)); if (DEBUG) { Log.d(TAG, "getViewForPosition created new ViewHolder"); } } } boolean bound = false; if (mState.isPreLayout() && holder.isBound()) { // do not update unless we absolutely have to. holder.mPreLayoutPosition = position; } else if (!holder.isBound() || holder.needsUpdate() || holder.isInvalid()) { if (DEBUG && holder.isRemoved()) { throw new IllegalStateException("Removed holder should be bound and it should" + " come here only in pre-layout. Holder: " + holder); } final int offsetPosition = mAdapterHelper.findPositionOffset(position); mAdapter.bindViewHolder(holder, offsetPosition); attachAccessibilityDelegate(holder.itemView); bound = true; if (mState.isPreLayout()) { holder.mPreLayoutPosition = position; } } final ViewGroup.LayoutParams lp = holder.itemView.getLayoutParams(); final LayoutParams rvLayoutParams; if (lp == null) { rvLayoutParams = (LayoutParams) generateDefaultLayoutParams(); holder.itemView.setLayoutParams(rvLayoutParams); } else if (!checkLayoutParams(lp)) { rvLayoutParams = (LayoutParams) generateLayoutParams(lp); holder.itemView.setLayoutParams(rvLayoutParams); } else { rvLayoutParams = (LayoutParams) lp; } rvLayoutParams.mViewHolder = holder; rvLayoutParams.mPendingInvalidate = fromScrap && bound; return holder.itemView; } 

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

सभी आवश्यक दृश्य प्रकारों के लिए सरल दृश्य धारक

 class ViewHolderMedium(itemView: View) : RecyclerView.ViewHolder(itemView) { val icon: ImageView = itemView.findViewById(R.id.icon) as ImageView val label: TextView = itemView.findViewById(R.id.label) as TextView } 

एडेप्टर डेटा आइटम का एक अमूर्त चिह्न है ध्यान दें कि एक व्यू प्रकार को विशेष रूप से देखने वाले वर्ग (केटलस इन कोटलिन) के हैशोड द्वारा दर्शाया गया है

 trait AdapterItem { val viewType: Int fun bindViewHolder(viewHolder: RecyclerView.ViewHolder) } abstract class AdapterItemBase<T>(val viewHolderClass: KClass<T>) : AdapterItem { override val viewType: Int = viewHolderClass.hashCode() abstract fun bindViewHolder(viewHolder: T) override fun bindViewHolder(viewHolder: RecyclerView.ViewHolder) { bindViewHolder(viewHolder as T) } } 

कंक्रीट एडेप्टर मद वर्गों (प्रकार सुरक्षित तरीके) में केवल bindViewHolder को ओवरराइड करने की आवश्यकता है

 class AdapterItemMedium(val icon: Drawable, val label: String, val onClick: () -> Unit) : AdapterItemBase<ViewHolderMedium>(ViewHolderMedium::class) { override fun bindViewHolder(viewHolder: ViewHolderMedium) { viewHolder.icon.setImageDrawable(icon) viewHolder.label.setText(label) viewHolder.itemView.setOnClickListener { onClick() } } } 

ऐसे AdapterItemMedium ऑब्जेक्ट की List<AdapterItem> एडेप्टर के लिए एक डेटा स्रोत है, जो वास्तव में List<AdapterItem> नीचे देखता है।

इस समाधान का महत्वपूर्ण हिस्सा एक दृश्य धारक कारखाना है जो विशिष्ट दृश्यहोल्डर के ताजा उदाहरण प्रदान करेगा

 class ViewHolderProvider { private val viewHolderFactories = hashMapOf<Int, Pair<Int, Any>>() fun provideViewHolder(viewGroup: ViewGroup, viewType: Int): RecyclerView.ViewHolder { val (layoutId: Int, f: Any) = viewHolderFactories.get(viewType) val viewHolderFactory = f as (View) -> RecyclerView.ViewHolder val view = LayoutInflater.from(viewGroup.getContext()).inflate(layoutId, viewGroup, false) return viewHolderFactory(view) } fun registerViewHolderFactory<T>(key: KClass<T>, layoutId: Int, viewHolderFactory: (View) -> T) { viewHolderFactories.put(key.hashCode(), Pair(layoutId, viewHolderFactory)) } } 

और सरल एडेप्टर वर्ग इस तरह दिखता है

 public class MultitypeAdapter(val items: List<AdapterItem>) : RecyclerView.Adapter<RecyclerView.ViewHolder>() { val viewHolderProvider = ViewHolderProvider() // inject ex Dagger2 init { viewHolderProvider!!.registerViewHolderFactory(ViewHolderMedium::class, R.layout.item_medium, { itemView -> ViewHolderMedium(itemView) }) } override fun getItemViewType(position: Int): Int { return items[position].viewType } override fun getItemCount(): Int { return items.size() } override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): RecyclerView.ViewHolder? { return viewHolderProvider!!.provideViewHolder(viewGroup, viewType) } override fun onBindViewHolder(viewHolder: RecyclerView.ViewHolder, position: Int) { items[position].bindViewHolder(viewHolder) } } 

एक नया दृश्य प्रकार बनाने के लिए केवल 3 कदम:

  1. एक दृश्य धारक वर्ग बनाएँ
  2. एक एडेप्टर आइटम क्लास बनाएं (एडाप्टरआईटीमेबेस से विस्तार)
  3. ViewHolderProvider में दृश्य धारक वर्ग को पंजीकृत करें

यहां इस अवधारणा का एक उदाहरण है: एंड्रॉइड-ड्रॉवर-टेम्पलेट यह आगे भी जाता है – देखें प्रकार जो एक स्पिनर घटक के रूप में कार्य करता है, चयन योग्य एडाप्टर आइटम।

यह बहुत सरल और सीधे आगे है।

बस अपने एडाप्टर में getItemViewType () विधि को ओवरराइड करें। डेटा के आधार पर अलग आइटम उल्लिखित मान लौटाएं। जैसे कि एक सदस्य के साथ व्यक्ति के प्रकार के एक वस्तु पर विचार करें, मॉल, अगर है, तो सत्य है, 1 लौट आओ और मैला गलत है, getItemViewType () विधि में 2 लौटें।

अब अलग दृश्य प्रकार के आधार पर createViewHolder (ViewGroup पैरेंट, इंट व्यू टाइप) के लिए आता है, टाइप करें भिन्न लेआउट फ़ाइल फुला सकते हैं। जैसे निम्नलिखित

  if (viewType ==1){ View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.male,parent,false); return new AdapterMaleViewHolder(view); } else{ View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.female,parent,false); return new AdapterFemaleViewHolder(view); } 

onBindViewHolder (VH धारक, इंट की स्थिति) जांचें कि कहां धारक AdapterFemaleViewHolder या AdapterMaleViewHolder instanceof अनुसार और उसके अनुसार मूल्यों को असाइन करते हैं।

देखेंहोल्डर इस तरह हो सकता है

  class AdapterMaleViewHolder extends RecyclerView.ViewHolder { ... public AdapterMaleViewHolder(View itemView){ ... } } class AdapterFemaleViewHolder extends RecyclerView.ViewHolder { ... public AdapterFemaleViewHolder(View itemView){ ... } } 

दरअसल, मैं एंटोन के जवाब में सुधार करना चाहता हूं।

चूंकि getItemViewType(int position) एक पूर्णांक मान देता है, आप लेआउट संसाधन आईडी आपको बढ़ाना चाहते हैं। इस तरह से आप कुछ तर्क onCreateViewHolder(ViewGroup parent, int viewType) विधि को सहेजते हैं।

साथ ही, मैं getItemCount() में गहन गणना करने का सुझाव नहीं देता क्योंकि उस विशेष फ़ंक्शन को सूची प्रदान करते समय कम से कम 5 बार कहा जाता है, साथ ही साथ प्रत्येक आइटम को दृश्य वस्तुओं से परे प्रदान करते हुए दुर्भाग्य से notifyDatasetChanged() बाद से notifyDatasetChanged() विधि अंतिम है, आप वास्तव में इसे ओवरराइड नहीं कर सकते, लेकिन आप इसे एडेप्टर के भीतर किसी अन्य फ़ंक्शन से कॉल कर सकते हैं।

आप लाइब्रेरी का उपयोग कर सकते हैं: https://github.com/vivchar/RendererRecyclerViewAdapter

 mRecyclerViewAdapter = new RendererRecyclerViewAdapter(); /* included from library */ mRecyclerViewAdapter.registerRenderer(new SomeViewRenderer(SomeModel.TYPE, this)); mRecyclerViewAdapter.registerRenderer(...); /* you can use several types of cells */ 

`

प्रत्येक आइटम के लिए, आपको व्यू रेंडरर, व्यूहाल्डर, कुछ मॉडल को कार्यान्वित करना चाहिए:

ViewHolder – यह रीसाइक्लर दृश्य के एक सरल दृश्य धारक है।

कुछ मॉडेल – यह मद मॉडल ItemModel साथ आपका मॉडल है

 public class SomeViewRenderer extends ViewRenderer<SomeModel, SomeViewHolder> { public SomeViewRenderer(final int type, final Context context) { super(type, context); } @Override public void bindView(@NonNull final SomeModel model, @NonNull final SomeViewHolder holder) { holder.mTitle.setText(model.getTitle()); } @NonNull @Override public SomeViewHolder createViewHolder(@Nullable final ViewGroup parent) { return new SomeViewHolder(LayoutInflater.from(getContext()).inflate(R.layout.some_item, parent, false)); } } 

अधिक जानकारी के लिए आप दस्तावेज़ीकरण देख सकते हैं।

यहां बहुत सारे समाधान प्रस्तुत किए जा रहे हैं … रीसाइक्लर दृश्य में एकाधिक लेआउट बनाने के लिए इसे बहुत आसान और त्वरित समाधान आज़माएं

 public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { if(ChatFragment.isMe) { // isMe is boolean static field in ChatFragment class View view = inflater.inflate(R.layout.my_chat_layout, parent, false); MyViewHolder holder = new MyViewHolder(view); return holder; } else{ View view = inflater.inflate(R.layout.other_chat_layout, parent, false); MyViewHolder holder = new MyViewHolder(view); return holder; } }` 

इसका उपयोग तब करें जब आपको लेआउट बदलना होगा

 public static Boolean isMe; 

परिवर्तन आईएमई (सही है या गलत) आप तक है