RecyclerView के साथ विस्तार योग्य सूची?


95

नए RecyclerView के साथ विस्तार योग्य सूची आइटम का उपयोग करना संभव है? एक्सपेंडेबल लाइस्ट व्यू की तरह?


1
आप एंड्रॉइड पर एंड्रॉइड घड़ी को एंड्रॉइड 6.0
zys

@zys मुझे यह एंड्रॉइड घड़ी उदाहरण स्रोत कोड कहां मिल सकता है?
AppiDevo

1
जब आप विस्तार बटन पर क्लिक करते हैं, तो आप अलग-अलग लेआउट को लोड करने के लिए अलग-अलग
व्यू टाइप

मेरा सरल उत्तर देखें stackoverflow.com/a/48092441/5962715
किरण बेनी जोसेफ

दो स्तरों के लिए: thoughtbot.com/blog/introducing-expandablerecyclerview । तीन और अधिक स्तरों के लिए: blog.usejournal.com/… , github.com/bmelnychuk/AndroidTreeView , karthicandroid.blogspot.com/2016/08/…
कूलमाइंड

जवाबों:


121

यह स्टॉक लेआउट मैनेजर के साथ करना आसान है, यह सब इस बात पर निर्भर करता है कि आप अपने एडेप्टर का प्रबंधन कैसे करते हैं।

जब आप किसी अनुभाग का विस्तार करना चाहते हैं तो आप हेडर के बाद अपने एडेप्टर में नए आइटम जोड़ते हैं। जब आप ऐसा करते हैं तो InformItemRangeInserted पर कॉल करना याद रखें। किसी अनुभाग को संक्षिप्त करने के लिए आप संबंधित आइटम हटा दें, और InformItemRangeRemoved () को कॉल करें। उचित रूप से अधिसूचित किए गए किसी भी डेटा परिवर्तन के लिए, रिसाइकलर दृश्य को चेतन करेगा। वस्तुओं को जोड़ते समय, नई वस्तुओं से भरा जाने वाला क्षेत्र बनाया जाता है, जिसमें नई वस्तुएं लुप्त होती हैं। निष्कासन विपरीत होता है। एडेप्टर सामान के अलावा आपको बस इतना करना है कि उपयोगकर्ता को तार्किक संरचना को व्यक्त करने के लिए अपने विचारों को शैली दें।

अपडेट: रयान ब्रूक्स ने अब यह कैसे करना है पर एक लेख लिखा है ।


शानदार सुझाव। आश्चर्य है कि किसी और ने इस उत्तर को क्यों नहीं उतारा !!
x-treme

मैं इसे अगले रिलीज के एक भाग के रूप में SuperSLiM के उदाहरण के रूप में जोड़कर देखूंगा।
टॉनिक आर्टोस

रेयान ब्रूक्स ने अब यह कैसे करना है पर एक लेख लिखा है ।
टॉनिक Artos

शानदार सुझाव। यह उत्तर पृष्ठ से इतना नीचे क्यों है कि मुझे इसे खोजने के लिए नीचे स्क्रॉल करना होगा? इसे बहुत ऊपर दिखाया जाना चाहिए ताकि अधिक लोग इस सुंदर उत्तर को और अधिक आसानी से जान सकें।
रेस्टइंपीस

1
रयान ब्रूक्स ने अपने पुस्तकालय को पदावनत के रूप में चिह्नित किया। मुझे आश्चर्य है कि यह सिर्फ इतना है कि उसने इसका समर्थन करना बंद कर दिया है या यह पता चला है कि यह दृष्टिकोण किसी चीज को तोड़ता है या मेमोरी लीक या sth बनाता है ...
वरवर कालिना

6

यहां से नमूना कोड कार्यान्वयन प्राप्त करें

ViewHolder के onClick के अंदर ValueAnimator सेट करें

@Override
public void onClick(final View view) {
    if (mOriginalHeight == 0) {
        mOriginalHeight = view.getHeight();
    }
    ValueAnimator valueAnimator;
    if (!mIsViewExpanded) {
        mIsViewExpanded = true;
        valueAnimator = ValueAnimator.ofInt(mOriginalHeight, mOriginalHeight + (int) (mOriginalHeight * 1.5));
    } else {
        mIsViewExpanded = false;
        valueAnimator = ValueAnimator.ofInt(mOriginalHeight + (int) (mOriginalHeight * 1.5), mOriginalHeight);
    }
    valueAnimator.setDuration(300);
    valueAnimator.setInterpolator(new LinearInterpolator());
    valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        public void onAnimationUpdate(ValueAnimator animation) {
            Integer value = (Integer) animation.getAnimatedValue();
            view.getLayoutParams().height = value.intValue();
            view.requestLayout();
        }
    });
    valueAnimator.start();

}

यहाँ अंतिम कोड है

public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
    private TextView mFriendName;
    private int mOriginalHeight = 0;
    private boolean mIsViewExpanded = false;


    public ViewHolder(RelativeLayout v) {
        super(v);
        mFriendName = (TextView) v.findViewById(R.id.friendName);
        v.setOnClickListener(this);
    }

    @Override
    public void onClick(final View view) {
        if (mOriginalHeight == 0) {
            mOriginalHeight = view.getHeight();
        }
        ValueAnimator valueAnimator;
        if (!mIsViewExpanded) {
            mIsViewExpanded = true;
            valueAnimator = ValueAnimator.ofInt(mOriginalHeight, mOriginalHeight + (int) (mOriginalHeight * 1.5));
        } else {
            mIsViewExpanded = false;
            valueAnimator = ValueAnimator.ofInt(mOriginalHeight + (int) (mOriginalHeight * 1.5), mOriginalHeight);
        }
        valueAnimator.setDuration(300);
        valueAnimator.setInterpolator(new LinearInterpolator());
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            public void onAnimationUpdate(ValueAnimator animation) {
                Integer value = (Integer) animation.getAnimatedValue();
                view.getLayoutParams().height = value.intValue();
                view.requestLayout();
            }
        });
        valueAnimator.start();

    }
}

11
यह "जैसे ExpandableListView" काम नहीं करता है , क्योंकि उस मामले में विस्तारित सामग्री एडॉप्टर से आने वाली वस्तुओं के साथ एक सूची है। यह एक पतित समाधान है जिसमें समूह के अंदर बच्चों के रूप में केवल 1 आइटम की अनुमति है।
ट्वीस्टेरोब

और न ही यह देखा गया है कि सभी पर पुनर्नवीनीकरण हो साथ ठीक से काम करता है
TakeCare

यह ठीक से काम नहीं करता है क्योंकि RecyclerList में एक दृश्य को कई बार दोहराया जा सकता है, इसलिए जब आप एक आइटम का विस्तार करते हैं, तो आप देखते हैं कि सूची में कई आइटम विस्तारित हैं
होशिन शाहदोस्त

3

https://github.com/gabrielemariotti/cardslib

इस लाइब्रेरी में एक recyclerview के साथ एक विस्तार योग्य सूची का कार्यान्वयन है ("CardViewNative" के तहत डेमो ऐप का संदर्भ लें -> "सूची, ग्रिड और RecyclerView" -> "विस्तार योग्य कार्ड")। इसमें कार्डों / सूचियों के कई अन्य अच्छे संयोजन भी हैं।


2
यह एक्सपेंडेबल कार्ड सूची RecyclerView का बच्चा नहीं है (यह RecyclerView का विस्तार नहीं करता है, यह केवल विस्तार योग्य सूची का विस्तार कर रहा है)
व्हिज्की

0

किसी ने शिकायत की कि उपर्युक्त समाधान विस्तार योग्य सामग्री के रूप में सूची के साथ प्रयोग करने योग्य नहीं है। लेकिन एक सरल समाधान है: एक सूची बनाएं और इस सूची को मैन्युअल रूप से अपनी पंक्तियों के साथ भरें

आलसी लोगों के लिए समाधान: यदि आप अपना कोड बहुत अधिक नहीं बदलना चाहते हैं तो एक सरल उपाय है। बस अपने एडेप्टर का उपयोग विचारों को बनाने और उन्हें जोड़ने के लिए करें LinearLayout

यहाँ उदाहरण है:

if (mIsExpanded)
{
    // llExpandable... is the expandable nested LinearLayout
    llExpandable.removeAllViews();
    final ArrayAdapter<?> adapter = ... // create your adapter as if you would use it for a ListView
    for (int i = 0; i < adapter.getCount(); i++)
    {
        View item = adapter.getView(i, null, null);
        // if you want the item to be selectable as if it would be in a default ListView, then you can add following code as well:
        item.setBackgroundResource(Functions.getThemeReference(context, android.R.attr.selectableItemBackground));
        item.setTag(i);
        item.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // item would be retrieved with: 
                // adapter.getItem((Integer)v.getTag())
            }
        });
        llExpandable.addView(item);
    }
    ExpandUtils.expand(llExpandable, null, 500);
}
else
{
    ExpandUtils.collapse(llExpandable, null, 500);
}

सहायक कार्य: getThemeReference

public static int getThemeReference(Context context, int attribute)
{
    TypedValue typeValue = new TypedValue();
    context.getTheme().resolveAttribute(attribute, typeValue, false);
    if (typeValue.type == TypedValue.TYPE_REFERENCE)
    {
        int ref = typeValue.data;
        return ref;
    }
    else
    {
        return -1;
    }
}

सहायक वर्ग: विस्तारक

Kavin Varnan पहले से ही एक लेआउट को एनिमेट करने का तरीका ... लेकिन अगर आप मेरी कक्षा का उपयोग करना चाहते हैं, तो बेझिझक ऐसा करें, मैंने एक जिस्ट पोस्ट किया: https://gist.github.com/MichaelFlisar/738dfa0a1579cc7338a


9
"आलसी समाधान" एक बहुत बुरा विचार है। स्क्रॉल करने योग्य दृश्य के अंदर एक रेखीय ताल के दृश्य जोड़ना इतना अक्षम है।
मैथ्यू

मुझे लगता है कि यह प्रयोज्य से कम से कम अधिक है। उन सभी उपकरणों पर तेजी से काम करता है, जिनका मैंने परीक्षण किया था। वैसे, दृश्य तब जोड़े जाते हैं जब सूची दृश्यमान नहीं होती है ... केवल पहले से भरी गई सूची दृश्य बाद में दिखाई जाएगी ...
prom85

यह साफ था! धन्यवाद एक टन
पवन कुमार

1
जैसा कि @ मैथ्यू ने उल्लेख किया है, यह वास्तव में एक अच्छा विचार नहीं है। एकल बड़े स्क्रॉल योग्य दृश्य w / LinearLayouts के पास कोई अच्छा पैमाना नहीं है। RecyclerView / ListView और इसी तरह के अन्य विचारों में से एक सबसे बड़ा कारण अज्ञात आकार के बड़े डेटा-समर्थित सूचियों का अनुकूलन करना था। एक ही दृश्य w / बिल्डिंग को देखते हुए जोड़े जाने वाले सभी अनुकूलन प्रदान करता है। पुनर्चक्रण दृश्य एक बहुत बड़ा लाभ है, और यह आपके ऐप की मेमोरी को कुशल बनाता है। जब तक वस्तुओं की संख्या छोटी नहीं होती, दृश्य बंधन को संभालने के लिए सूचियों का उपयोग करके बहुत सारे काम बचाए जाते हैं।
मुनके

आप पूरी तरह से सही हैं, निश्चित रूप से यह सही नहीं है और कुछ भी अनुकूलन नहीं करता है ... मेरे usecases के लिए, मेरे पास हमेशा केवल कुछ आइटम थे ... इसलिए यह कोई समस्या नहीं थी ... Btw, इस बीच में मुझे एक रास्ता मिल गया नेस्टेड रिसाइकलर विचारों के लिए ... बस एक निश्चित ऊंचाई क्षैतिज पुनर्नवीनीकरण दृश्य का उपयोग करें (प्रत्येक usecase के लिए एकदम सही नहीं है, लेकिन अभी भी) एक नेस्टेड के रूप में recyclerviewऔर आप इस नेस्टेड एक का विस्तार / छिपा सकते हैं औरrecyclerview
प्रोमोन

0

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

https://github.com/KyoSherlock/ExpandableLayout


0

यह आइटमों को जोड़ने और हटाने के लिए @TonicArtos द्वारा बताए गए और इसे करते समय चेतन करने के लिए नमूना कोड है , यह RecyclerView एनिमेशन और GitHub नमूना से लिया गया है

1) अपने onCreateViewHolder के अंदर श्रोता जोड़ें () onClick के लिए रजिस्टर करने के लिए

2) अपने एडाप्टर के अंदर अपने कस्टम OnClickListener बनाएँ

private View.OnClickListener mItemListener = new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        TextView tv = (TextView) v.findViewById(R.id.tvItems);
        String selected = tv.getText().toString();
        boolean checked = itemsList.get(recyclerView.getChildAdapterPosition(v)).isChecked();

        switch (selected){
            case "Item1":
                if(checked){
                    deleteItem(v);
                    itemsList.get(recyclerView.getChildAdapterPosition(v)).setChecked(false);
                }else {
                    addItem(v);
                    itemsList.get(recyclerView.getChildAdapterPosition(v)).setChecked(true);
                }
                break;
            case "Item2":
                if(checked){
                    deleteItem(v);
                    itemsList.get(recyclerView.getChildAdapterPosition(v)).setChecked(false);
                }else {
                    addItem(v);
                    itemsList.get(recyclerView.getChildAdapterPosition(v)).setChecked(true);
                }
                break;                 
            default:
                //In my case I have checkList in subItems,
                //checkItem(v);
                break;
        }
    }
};

3) अपना AddItem () और DeleteItem () जोड़ें

private void addItem(View view){
    int position = recyclerView.getChildLayoutPosition(view);
    if (position != RecyclerView.NO_POSITION){
        navDrawItems.add(position+1,new mObject());
        navDrawItems.add(position+2,new mObject());
        notifyItemRangeInserted(position+1,2);
    }
}


private void deleteItem(View view) {
    int position = recyclerView.getChildLayoutPosition(view);
    if (position != RecyclerView.NO_POSITION) {
        navDrawItems.remove(position+2);
        navDrawItems.remove(position+1);
        notifyItemRangeRemoved(position+1,2);
    }
}

4) यदि आपका RecyclerViewAdapter पुनर्नवीनीकरण दृश्य के समान गतिविधि में नहीं है , तो बनाने के दौरान एडाप्टर को recyclerView का उदाहरण दें

5) आइटम लिस्ट एक प्रकार का mObject का ArrayList है जो आइटम की स्थिति (ओपन / क्लोज), नाम, आइटम का प्रकार (सबटाइम्स / mainItem) बनाए रखने में मदद करता है और मूल्यों पर आधारित थीम सेट करता है

public class mObject{
    private String label;
    private int type;
    private boolean checked;
} 
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.