RecyclerView आइटमों का विस्तार / पतन करता है


145

मैं अधिक जानकारी दिखाने के लिए अपने recyclerView की वस्तुओं का विस्तार / पतन करना चाहता हूं। मैं SlideExpandableListView के समान प्रभाव को प्राप्त करना चाहता हूं

मूल रूप से मेरे दृश्य फ़ोल्डर में मेरा एक दृश्य है जो दृश्यमान नहीं है और मैं केवल विज़िबिल / GONE की दृश्यता सेट करने के बजाय एक सुगम विस्तार / पतन एनीमेशन करना चाहता हूं। मुझे केवल एक आइटम को एक समय में विस्तारित करने की आवश्यकता है और यह दिखाने के लिए कि यह आइटम चयनित है, कुछ ऊँचाई होना अच्छा होगा।

यह नए एंड्रॉइड हाल की कॉल हिस्ट्री की सूची का समान प्रभाव है। विकल्प "कॉल बैक" और "विवरण" केवल तभी दिखाई देते हैं जब कोई आइटम चुना जाता है।

RecyclerView विस्तार योग्य आइटम


मेरा एक संबंधित प्रश्न है। क्लॉक ऐप में, अलार्म सेट गतिविधि में एक समान विशेषता है। क्या यह उसी तरह से किया जाता है?
user2731584

अरे आपको समाधान मिल गया है? मैं भी अपने अनुप्रयोग के लिए एक ही समाधान के लिए देख रहा हूँ।
अर्पित पटेल

क्या आपको कोई समाधान मिला?
अर्मिन घोराशि

1
मैंने Google I / O 2016 के अनुसार इसे करने का अनुशंसित तरीका अपडेट किया है। मेरे उत्तर में देखें stackoverflow.com/questions/27203817/…
Heisenberg

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

जवाबों:


192

कृपया इस आशय की किसी भी लाइब्रेरी का उपयोग न करें, इसके बजाय Google I / O के अनुसार करने के अनुशंसित तरीके का उपयोग करें। अपने recyclerView के onBindViewHolder विधि में यह करें:

final boolean isExpanded = position==mExpandedPosition;
holder.details.setVisibility(isExpanded?View.VISIBLE:View.GONE);
holder.itemView.setActivated(isExpanded);
holder.itemView.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        mExpandedPosition = isExpanded ? -1:position;
        TransitionManager.beginDelayedTransition(recyclerView);
        notifyDataSetChanged();
    }
});
  • जहां विवरण मेरा दृष्टिकोण है जो स्पर्श पर प्रदर्शित किया जाएगा (आपके मामले में कॉल विवरण। डिफ़ॉल्ट दृश्यता। GONE)।
  • mExpandedPosition -1 का आरंभिक चर है

और आपके द्वारा चाहने वाले शांत प्रभावों के लिए, इन्हें अपनी list_item विशेषताओं के रूप में उपयोग करें:

android:background="@drawable/comment_background"
android:stateListAnimator="@animator/comment_selection"

जहां टिप्पणी_बैकग्राउंड है:

<selector
xmlns:android="http://schemas.android.com/apk/res/android"
android:constantSize="true"
android:enterFadeDuration="@android:integer/config_shortAnimTime"
android:exitFadeDuration="@android:integer/config_shortAnimTime">

<item android:state_activated="true" android:drawable="@color/selected_comment_background" />
<item android:drawable="@color/comment_background" />
</selector>

और comment_selection है:

<selector xmlns:android="http://schemas.android.com/apk/res/android">

<item android:state_activated="true">
    <objectAnimator
        android:propertyName="translationZ"
        android:valueTo="@dimen/z_card"
        android:duration="2000"
        android:interpolator="@android:interpolator/fast_out_slow_in" />
</item>

<item>
    <objectAnimator
        android:propertyName="translationZ"
        android:valueTo="0dp"
        android:duration="2000"
        android:interpolator="@android:interpolator/fast_out_slow_in" />
</item>
</selector>

22
इस कोड का उपयोग करते समय विस्तार-एनीमेशन अजीब लगता है। हर बार शीर्ष वस्तु गायब हो जाती है और सब कुछ एक स्थिति में बदल जाता है। क्या आपने कभी ऐसा ही कुछ अनुभव किया है?
क्रिस-पोलक्स

6
मैं एनीमेशन करने की कोशिश करता हूं, लेकिन मैं इसे एडॉप्टर पर लागू करता हूं, लेकिन TransitionManager.beginDelayedTransition(recyclerView);अगर मैं रिसायकल व्यू रेफरेंस को हेस नहीं कर सकता तो इसका क्या समाधान होगा ।
मार्टिन सेरानो

2
@ रणवीर यह काम करता है। मेरे पास दो समान पुनर्नवीनीकरण दृश्य हैं, लेकिन यह केवल एक के लिए सही ढंग से काम करता है। पता नहीं क्यों। @ MartínDaniel आपको recyclerViewएडॉप्टर के लिए कंस्ट्रक्टर में एक पैरामीटर के रूप में पास करने की आवश्यकता है
chris-pollux

26
यह एक भयानक दृष्टिकोण है। मुझे विश्वास नहीं हो रहा है कि यह Google I / O में अनुशंसित था। प्लेड परियोजना की जांच करने और उसमें से सभी आवश्यक कार्यपट्टों को लागू करने के बाद भी, एनीमेशन अभी भी RecyclerView में कुछ प्रमुख ग्लिच का कारण बनता है, उदाहरण के लिए समय से पहले गायब / पहले दिखाई देने वाली वस्तु। एनीमेशन चलाते समय स्क्रॉल करना भी सभी चीजों को बुरी तरह से गड़बड़ करता है। सामान्य तौर पर, मुझे नहीं लगता कि इस दृष्टिकोण के कारण होने वाले सभी मुद्दों को ठीक करने के लिए "बस एक पंक्ति और सब कुछ बस काम करेगा" कहा जा सकता है।
विटाली ओल्शेव्स्की

6
क्या हमारे पास इस मुद्दे के लिए 2019 में कुछ और ताजा और आसान तरीका है?
पोनोमारेंको ओलेह

76

इसके लिए, बस सरल लाइनों की जरूरत है जो जटिल नहीं है

अपने onBindViewHolder मेथड में कोड के नीचे जोड़ें

final boolean isExpanded = position==mExpandedPosition;
holder.details.setVisibility(isExpanded?View.VISIBLE:View.GONE);
holder.itemView.setActivated(isExpanded);
holder.itemView.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        mExpandedPosition = isExpanded ? -1:position;
        notifyItemChanged(position);
    }
});

mExpandedPosition -1 का आरंभिक वैश्विक चर है

उन लोगों के लिए जो केवल एक वस्तु का विस्तार चाहते हैं और अन्य ढह जाते हैं। इसे इस्तेमाल करो

पहले पिछलेExpededPosition = -1 के साथ एक वैश्विक चर घोषित करें

फिर

    final boolean isExpanded = position==mExpandedPosition;
    holder.details.setVisibility(isExpanded?View.VISIBLE:View.GONE);
    holder.itemView.setActivated(isExpanded);

    if (isExpanded)
       previousExpandedPosition = position;

    holder.itemView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            mExpandedPosition = isExpanded ? -1:position;
            notifyItemChanged(previousExpandedPosition);
            notifyItemChanged(position);
        }
    });

किया हुआ!!!। सरल और विनम्र .. :)


महान समाधान। इसके अलावा, मैं ले जाने के लिए सेटिंग की सलाह देते हैं OnClickListenerकरने के लिए रों onCreateViewHolderबजायonBindViewHolder
YTerle

1
बहुत अच्छी तरह से काम करता है, समय के साथ एक सभ्य समाधान था जो बस RecyclerViewकाम करने देता है , मेरा मतलब है, LayoutManagerअन्यथा बिंदुओं का क्या मतलब है अगर यह लेआउट का प्रबंधन नहीं करता है! यह समाधान शीर्ष मतदान समाधान से बेहतर है क्योंकि इसमें कम कोड है, RecyclerViewचीजों को संभालने और बेहतर काम करने देता है!
मार्क कीन

1
काफी समझ में नहीं आया कि "विवरण" को कैसे जोड़ा जाए। क्या यह प्रत्येक धारक के लिए स्थिर होना चाहिए? क्या होगा यदि प्रत्येक सूची आइटम के लिए मुझे अलग-अलग विचार जोड़ने होंगे?
बेकाबू

@ बेकाबू यह वह दृश्य है जिसे आप ढहने के दौरान छिपाना चाहते हैं
किरण बेनी जोसेफ

@KiranBennyJoseph हाँ, मैं समझता हूँ। इस मामले में सभी वस्तुओं के लिए दृश्य समान होना चाहिए? अगर मुझे अलग-अलग वस्तुओं के लिए अलग-अलग विचार चाहिए तो क्या होगा?
बेकाबू

72

यह नहीं कहना कि यह सबसे अच्छा तरीका है, लेकिन यह मेरे लिए काम करता है।

पूरा कोड यहां पाया जा सकता है: उदाहरण कोड यहां: https://github.com/dbleicher/recyclerview-grid-quickreturn

सबसे पहले, अपने सेल / आइटम लेआउट में विस्तारित क्षेत्र को जोड़ें, और एन्क्लोजिंग सेल लेआउट को animateLayoutChanges = "true" करें। यह सुनिश्चित करेगा कि विस्तार / पतन एनिमेटेड है:

<LinearLayout
    android:id="@+id/llCardBack"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:background="@android:color/white"
    android:animateLayoutChanges="true"
    android:padding="4dp"
    android:orientation="vertical">

    <TextView
        android:id="@+id/tvTitle"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center|fill_horizontal"
        android:padding="10dp"
        android:gravity="center"
        android:background="@android:color/holo_green_dark"
        android:text="This is a long title to show wrapping of text in the view."
        android:textColor="@android:color/white"
        android:textSize="16sp" />

    <TextView
        android:id="@+id/tvSubTitle"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center|fill_horizontal"
        android:background="@android:color/holo_purple"
        android:padding="6dp"
        android:text="My subtitle..."
        android:textColor="@android:color/white"
        android:textSize="12sp" />

    <LinearLayout
        android:id="@+id/llExpandArea"
        android:visibility="gone"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:orientation="horizontal">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="6dp"
            android:text="Item One" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="6dp"
            android:text="Item Two" />

    </LinearLayout>
</LinearLayout>

फिर, अपने RV एडॉप्टर क्लास को View.OnClickListener को लागू करें ताकि आप क्लिक की जा रही वस्तु पर कार्य कर सकें। एक विस्तृत क्षेत्र को एक विस्तारित दृश्य की स्थिति में रखने के लिए जोड़ें, और इसे एक नकारात्मक मान के साथ आरंभ करें:

private int expandedPosition = -1;

अंत में, अपने ViewHolder, onBindViewHolder () विधियों को लागू करें और onClick () विधि को ओवरराइड करें। यदि यह स्थिति "विस्तारित स्थिति" के बराबर है, और आप इसे छिपा सकते हैं, तो आप onBindViewHolder में दृश्य का विस्तार करेंगे। आपने ऑनक्लिक श्रोता में एक्सपेंशनपोस्ट का मान सेट किया है:

@Override
public void onBindViewHolder(RVAdapter.ViewHolder holder, int position) {

    int colorIndex = randy.nextInt(bgColors.length);
    holder.tvTitle.setText(mDataset.get(position));
    holder.tvTitle.setBackgroundColor(bgColors[colorIndex]);
    holder.tvSubTitle.setBackgroundColor(sbgColors[colorIndex]);

    if (position == expandedPosition) {
        holder.llExpandArea.setVisibility(View.VISIBLE);
    } else {
        holder.llExpandArea.setVisibility(View.GONE);
    }
}

@Override
public void onClick(View view) {
    ViewHolder holder = (ViewHolder) view.getTag();
    String theString = mDataset.get(holder.getPosition());

    // Check for an expanded view, collapse if you find one
    if (expandedPosition >= 0) {
        int prev = expandedPosition;
        notifyItemChanged(prev);
    }
    // Set the current position to "expanded"
    expandedPosition = holder.getPosition();
    notifyItemChanged(expandedPosition);

    Toast.makeText(mContext, "Clicked: "+theString, Toast.LENGTH_SHORT).show();
}

/**
 * Create a ViewHolder to represent your cell layout
 * and data element structure
 */
public static class ViewHolder extends RecyclerView.ViewHolder {
    TextView tvTitle;
    TextView tvSubTitle;
    LinearLayout llExpandArea;

    public ViewHolder(View itemView) {
        super(itemView);

        tvTitle = (TextView) itemView.findViewById(R.id.tvTitle);
        tvSubTitle = (TextView) itemView.findViewById(R.id.tvSubTitle);
        llExpandArea = (LinearLayout) itemView.findViewById(R.id.llExpandArea);
    }
}

लेआउट परिवर्तन के लिए सिस्टम-डिफॉल्ट एनीमेशन का उपयोग करके एक समय में केवल एक आइटम का विस्तार करना चाहिए। कम से कम यह मेरे लिए काम करता है। आशा करता हूँ की ये काम करेगा।


मुझे पता है कि केवल एक आइटम को कैसे चुना जाता है। मैं वास्तव में उस आइटम पर एनीमेशन कैसे करना है पता नहीं है। डिफ़ॉल्ट सिस्टम एनीमेशन के साथ विस्तार / पतन एनीमेशन बहुत चिकना नहीं दिखता है।
श्लोक

1
मैंने अभी तक निम्नलिखित की कोशिश नहीं की है, लेकिन यह निश्चित है कि यह काम करेगा। इसका उत्तर देखें: stackoverflow.com/a/26443762/2259418
MojoTosh

2
@ user2731584 - मुझे ऐसा नहीं लगता। उनके स्रोत को देखते हुए (जो मैं मानता हूं कि वह है), ऐसा प्रतीत होता है कि लॉलीपॉप घड़ी सूची का उपयोग करने के लिए सूची का उपयोग कर रही है। लेआउट: android.googlesource.com/platform/packages/apps/DeskClock/+/… वे इस सूची में विस्तार / पतन आइटम को एनिमेट करने के लिए कस्टम कोड प्रकट करते हैं। निम्नलिखित स्रोत देखें: android.googlesource.com/platform/packages/apps/DeskClock/+/…
MojoTosh

1
@ मोहजो तुम सही हो। वे ListView का उपयोग कर रहे हैं और कोड का उपयोग करके एनीमेशन कर रहे हैं। फ़ाइलों expandAlarmमें फ़ंक्शन AlarmClockFragment.javaविस्तार भाग को निष्पादित करता है।
user2731584

4
onClick()मुझे कौन सा ओवरराइड करना चाहिए? onClickएडेप्टर में कोई नहीं है।
विक्की लेओंग

15

लाइब्रेरी को ग्रेडेल सपोर्ट के साथ उपयोग करने के लिए बहुत सरल है: https://github.com/cachapa/ExpandableLayout

लाइब्रेरी डॉक्स से अधिकार:

<net.cachapa.expandablelayout.ExpandableLinearLayout
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:el_duration="1000"
    app:el_expanded="true">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Click here to toggle expansion" />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:text="Fixed height"
        app:layout_expandable="true" />

 </net.cachapa.expandablelayout.ExpandableLinearLayout>

आप अपने को चिह्नित करने के बाद विस्तार देखा गया, बस कंटेनर पर इनमें से किसी भी फोन: expand(), collapse()याtoggle()


क्या यह अभी भी इसे करने का सबसे अच्छा तरीका है? आपने जो लिखा है, उसका अनुसरण करने की कोशिश कर रहा हूं। मेरे पास कुछ रीसायकल विचार हैं जिन्हें मैं एक ग्राफ दिखाने के लिए विस्तारित करना चाहता हूं जब क्लिक किया जाता है
sourlemonaid

10

मुझे पता है कि मूल प्रश्न पोस्ट किए जाने में काफी समय हो गया है। लेकिन मुझे लगता है कि मेरे जैसे धीमे लोगों के लिए @ हाइजेनबर्ग के जवाब की थोड़ी व्याख्या करने में मदद मिलेगी।

एडॉप्टर वर्ग में दो चर को घोषित करें

private int mExpandedPosition= -1;
private RecyclerView recyclerView = null;

फिर मूल उत्तर में दिए गए अनुसार onBindViewHolder का पालन ​​करें।

      // This line checks if the item displayed on screen 
      // was expanded or not (Remembering the fact that Recycler View )
      // reuses views so onBindViewHolder will be called for all
      // items visible on screen.
    final boolean isExpanded = position==mExpandedPosition;

        //This line hides or shows the layout in question
        holder.details.setVisibility(isExpanded?View.VISIBLE:View.GONE);

        // I do not know what the heck this is :)
        holder.itemView.setActivated(isExpanded);

        // Click event for each item (itemView is an in-built variable of holder class)
        holder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

 // if the clicked item is already expaned then return -1 
//else return the position (this works with notifyDatasetchanged )
                mExpandedPosition = isExpanded ? -1:position;
    // fancy animations can skip if like
                TransitionManager.beginDelayedTransition(recyclerView);
    //This will call the onBindViewHolder for all the itemViews on Screen
                notifyDataSetChanged();
            }
        });

और अंत में एडेप्टर ओवरराइड में recyclerView ऑब्जेक्ट प्राप्त करने के लिए

@Override
public void onAttachedToRecyclerView(@NonNull RecyclerView recyclerView) {
    super.onAttachedToRecyclerView(recyclerView);

    this.recyclerView = recyclerView;
}

उम्मीद है की यह मदद करेगा।


3
महान और सरल उपाय। छोटे सुधार, जादू नंबर -1 के बजाय RecyclerView.NO_POSITION का उपयोग करें।
कैस्पर बैंग

8

बस तीसरे पक्ष के पुस्तकालयों का उपयोग करने की कोई आवश्यकता नहीं है। इस विषय पर Google I / O 2016 में प्रदर्शित विधि और हाइजेनबर्ग में एक छोटा सा मोड़ , चाल करता है।

चूंकि notifyDataSetChanged() पूर्ण को फिरRecyclerView से परिभाषित करता है , notifyDataItemChanged()इसलिए एक बेहतर विकल्प है (सबसे अच्छा नहीं) क्योंकि हमारे पास स्थिति और ViewHolderहमारे निपटान में है, और notifyDataItemChanged()केवल किसी दिए गए स्थान पर विशेष ViewHolderको फिर से बनाता है

लेकिन समस्या यह है कि ViewHolderक्लिक करने पर समय से पहले गायब हो जाना और इसका उभरना भी समाप्त हो notifyDataItemChanged()जाता है, भले ही इसका उपयोग किया जाता हो।

निम्न कोड का समर्थन नहीं करता है notifyDataSetChanged()या notifyDataItemChanged()एपीआई 23 पर परीक्षण किया जाता है और एक पुनर्नवीनीकरण दृश्य पर उपयोग किए जाने पर एक आकर्षण की तरह काम करता है जहां प्रत्येक ViewHolder CardViewका मूल तत्व है:

holder.itemView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            final boolean visibility = holder.details.getVisibility()==View.VISIBLE;

            if (!visibility)
            {
                holder.itemView.setActivated(true);
                holder.details.setVisibility(View.VISIBLE);
                if (prev_expanded!=-1 && prev_expanded!=position)
                {
                    recycler.findViewHolderForLayoutPosition(prev_expanded).itemView.setActivated(false);
                    recycler.findViewHolderForLayoutPosition(prev_expanded).itemView.findViewById(R.id.cpl_details).setVisibility(View.GONE);
                }
                prev_expanded = position;
            }
            else
            {
                holder.itemView.setActivated(false);
                holder.details.setVisibility(View.GONE);
            }
            TransitionManager.beginDelayedTransition(recycler);              
        }
});

prev_position एक वैश्विक पूर्णांक -1 से आरंभिक है। detailsपूरा दृश्य जो विस्तारित और ढह जाने पर दिखाई देता है।

जैसा कि कहा गया है, का मूल तत्व ViewHolderएक CardViewहैforeground और stateListAnimatorइस विषय पर हाइजेनबर्ग द्वारा बिल्कुल के रूप में परिभाषित विशेषताओं कहा।

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

if (row.details.getVisibility()!=View.VISIBLE)
    {
        row.details.setVisibility(View.VISIBLE);
        row.root.setActivated(true);
        row.details.animate().alpha(1).setStartDelay(500);
    }
    else
    {
        row.root.setActivated(false);
        row.details.setVisibility(View.GONE);
        row.details.setAlpha(0);
    }
    TransitionManager.beginDelayedTransition(recycler);

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

LinearLayoutManager manager = (LinearLayoutManager) recycler.getLayoutManager();
    int distance;
    View first = recycler.getChildAt(0);
    int height = first.getHeight();
    int current = recycler.getChildAdapterPosition(first);
    int p = Math.abs(position - current);
    if (p > 5) distance = (p - (p - 5)) * height;
    else       distance = p * height;
    manager.scrollToPositionWithOffset(position, distance);

महत्वपूर्ण: काम करने के लिए उपर्युक्त प्रदर्शनों के लिए, किसी को अपने कोड में RecyclerView का एक उदाहरण रखना होगा और यह लेआउट प्रबंधक (लचीलेपन के लिए बाद में) है


धन्यवाद यह समाधान मेरे लिए काम करता है। मैं उपयोग करने से बचने की कोशिश करता notifyItemChangedहूं क्योंकि मेरे पास ImageViewएक url से लोड छवि है। notifyItemChangedमेरी छवि को फिर से लोड करने पर यह अजीब लग रहा है
ताम हुइन्ह

यह नाखून है कि लाइन TransitionManager.beginDelayedTransition(recycler);, महान पाते हैं। लेकिन मुझे पता चला कि इस पद्धति का उपयोग करके, अगर मैं कई पंक्तियों को क्रमिक रूप से स्पैम करता हूं, तो यह अंततः एक आंतरिक दुर्घटना को ट्रिगर करता है The specified child already has a parent. You must call removeView() on the child's parent first। मुझे लगता है कि यह पुनर्नवीनीकरण दृश्य सीमा पर रीसाइक्लिंग के कारण है, लेकिन मैं निश्चित रूप से नहीं बता सकता। क्या किसी के पास एक ही मुद्दा था?
रोजर Oba

क्या यह अभी भी इसे करने का सबसे अच्छा तरीका है? आपने जो लिखा है, उसका अनुसरण करने की कोशिश कर रहा हूं। मेरे पास कुछ रीसायकल विचार हैं जिन्हें मैं क्लिक करने पर एक ग्राफ दिखाने के लिए विस्तारित करना चाहता हूं। मुझे यह समझने में कठिन समय मिल रहा है कि मुझे क्या करना है
खटमल का समय

क्या किसी के पास इस कार्यान्वयन का पूरा उदाहरण है? मेरा मतलब है एक काम कोड उदाहरण। कृपया मदद कीजिए। मैं यह समझने में असमर्थ हूं कि यह कैसे किया जाए?
मुंजाजा

7

RecyclerViewRecyclerView पर विस्तार करने योग्य / ढहने वाली वस्तुओं को लागू करने के अनुशंसित तरीके का उपयोग करने के बाद , HeisenBerg द्वारा उत्तर दिए गए / विस्तारित आइटम का विस्तार करें , मैंने कुछ ध्यान देने योग्य कलाकृतियों को देखा है जब भी आह्वान करके और बाद में ताज़ा किया जाता है ।RecyclerViewTransitionManager.beginDelayedTransition(ViewGroup)notifyDatasetChanged()

उसका मूल उत्तर:

final boolean isExpanded = position==mExpandedPosition;
holder.details.setVisibility(isExpanded?View.VISIBLE:View.GONE);
holder.itemView.setActivated(isExpanded);
holder.itemView.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        mExpandedPosition = isExpanded ? -1 : position;
        TransitionManager.beginDelayedTransition(recyclerView);
        notifyDataSetChanged();
    }
});

संशोधित:

final boolean isExpanded = position == mExpandedPosition;
holder.details.setVisibility(isExpanded ? View.VISIBLE : View.GONE);
holder.view.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        if (mExpandedHolder != null) {
            mExpandedHolder.details.setVisibility(View.GONE);
            notifyItemChanged(mExpandedPosition);
        }
        mExpandedPosition = isExpanded ? -1 : holder.getAdapterPosition();
        mExpandedHolder = isExpanded ? null : holder;
        notifyItemChanged(holder.getAdapterPosition());
    }
}
  • विवरण यह है कि आप आइटम विस्तार / पतन के दौरान दिखाना / छिपाना चाहते हैं
  • mExpandedPosition एक intऐसा है जो विस्तारित आइटम का ट्रैक रखता है
  • mExpandedHolder एक है ViewHolderआइटम पतन के दौरान इस्तेमाल किया

ध्यान दें कि विधि TransitionManager.beginDelayedTransition(ViewGroup)और विशिष्ट आइटम और कुछ छोटे टिक्स को लक्षित करने के लिए notifyDataSetChanged()प्रतिस्थापित किए जाते हैं notifyItemChanged(int)

संशोधन के बाद, पिछले अवांछित प्रभाव को हटा दिया जाना चाहिए। हालाँकि, यह सही समाधान नहीं हो सकता है। यह केवल वही हुआ जो मैं चाहता था, आंखों के कोरों को खत्म करना।

:: संपादित ::

स्पष्टीकरण के लिए, दोनों mExpandedPositionऔर mExpandedHolderवैश्विक हैं।


कृपया बताएं कि कैसे और कहाँ mExpandedHolder घोषित और उपयोग किया जाता है?
वर्नर

1
@Werner मैंने यह दिखाने के लिए उत्तर संपादित किया है कि यह कहाँ घोषित किया गया है। उपयोग स्निपेट के भीतर और साथ ही उद्देश्य के भीतर है। इसका उपयोग चेतन के टूटने, विस्तारित होने वाली वस्तु के लिए किया जाता है।
चन टेक वी

मुझे यह दृष्टिकोण सबसे अधिक पसंद है जहाँ तक एनिमेशन का संबंध है, लेकिन आइटम पर क्लिक करते समय मुझे यह छोटा "फीका" हो रहा है। क्या आपके पास ऐसा है या अलग-अलग तरह से डाला गया है, क्या यह नोटिफिकेशनइन्चार्ज () का उपयोग करने के कारण है? drive.google.com/file/d/1GaU1fcjHEfSErYF50otQGLGsIWkSyQSe/...
Kazume

हाँ। जैसे आपने अनुमान लगाया है, यह कारण है notifyItemChanged()। आप मैन्युअल रूप से चेतन कर सकते हैं और आइटम की ऊँचाई को बदल सकते हैं और उसमें विचार जोड़ सकते हैं।
चैन टेक वी

@ChanTeckWei: आपका समाधान ठीक काम कर रहा है लेकिन पंक्ति चित्र झिलमिलाहट जब भी मैं संक्षिप्त करता हूं या recyclerview आइटम पंक्ति का विस्तार करता हूं..इसके लिए कोई समाधान नहीं है?
प्रज्ञा मेंदिरत्त १६'१

3

निम्न श्रोता को ViewHolder वर्ग पर सेट करने के बाद निम्न कार्य करें:

@Override
    public void onClick(View v) {
        final int originalHeight = yourLinearLayout.getHeight();
        animationDown(YourLinearLayout, originalHeight);//here put the name of you layout that have the options to expand.
    }

    //Animation for devices with kitkat and below
    public void animationDown(LinearLayout billChoices, int originalHeight){

        // Declare a ValueAnimator object
        ValueAnimator valueAnimator;
        if (!billChoices.isShown()) {
            billChoices.setVisibility(View.VISIBLE);
            billChoices.setEnabled(true);
            valueAnimator = ValueAnimator.ofInt(0, originalHeight+originalHeight); // These values in this method can be changed to expand however much you like
        } else {
            valueAnimator = ValueAnimator.ofInt(originalHeight+originalHeight, 0);

            Animation a = new AlphaAnimation(1.00f, 0.00f); // Fade out

            a.setDuration(200);
            // Set a listener to the animation and configure onAnimationEnd
            a.setAnimationListener(new Animation.AnimationListener() {
                @Override
                public void onAnimationStart(Animation animation) {

                }

                @Override
                public void onAnimationEnd(Animation animation) {
                    billChoices.setVisibility(View.INVISIBLE);
                    billChoices.setEnabled(false);
                }

                @Override
                public void onAnimationRepeat(Animation animation) {

                }
            });
            // Set the animation on the custom view
            billChoices.startAnimation(a);
        }
        valueAnimator.setDuration(200);
        valueAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            public void onAnimationUpdate(ValueAnimator animation) {
                Integer value = (Integer) animation.getAnimatedValue();
                billChoices.getLayoutParams().height = value.intValue();
                billChoices.requestLayout();
            }
        });


        valueAnimator.start();
    }
}

मुझे लगता है कि मुझे मदद करनी चाहिए, यह है कि मैंने कैसे लागू किया और हाल ही के कॉल दृश्य में वही Google करता है।


2

मुझे आश्चर्य है कि अभी तक कोई संक्षिप्त जवाब नहीं है, हालांकि इस तरह के एक विस्तार / पतन एनीमेशन कोड की सिर्फ 2 लाइनों के साथ हासिल करना बहुत आसान है:

(recycler.itemAnimator as SimpleItemAnimator).supportsChangeAnimations = false // called once

के साथ साथ

notifyItemChanged(position) // in adapter, whenever a child view in item's recycler gets hidden/shown

तो मेरे लिए, नीचे दिए गए लिंक में स्पष्टीकरण वास्तव में उपयोगी थे: https://medium.com/@nikola.jakshic/how-to-expand-collapse-items-in-recyclerview-49a648a403b6


1
//Global Variable

private int selectedPosition = -1;

 @Override
    public void onBindViewHolder(final CustomViewHolder customViewHolder, final int i) {

        final int position = i;
        final GetProductCatalouge.details feedItem = this.postBeanses.get(i);
        customViewHolder.lly_main.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                selectedPosition = i;
                notifyDataSetChanged();
            }
        });
        if (selectedPosition == i) {

          if (customViewHolder.lly_hsn_code.getVisibility() == View.VISIBLE) {

            customViewHolder.lly_hsn_code.setVisibility(View.GONE);
            customViewHolder.lly_sole.setVisibility(View.GONE);
            customViewHolder.lly_sole_material.setVisibility(View.GONE);

        } else {

            customViewHolder.lly_hsn_code.setVisibility(View.VISIBLE);
            customViewHolder.lly_sole.setVisibility(View.VISIBLE);
            customViewHolder.lly_sole_material.setVisibility(View.VISIBLE);
        }


        } else {
            customViewHolder.lly_hsn_code.setVisibility(View.GONE);
            customViewHolder.lly_sole.setVisibility(View.GONE);
            customViewHolder.lly_sole_material.setVisibility(View.GONE);
        }
}

यहाँ छवि विवरण दर्ज करें


0

अपने में दो दृश्य प्रकारों का उपयोग करें RVAdapter। विस्तारित लेआउट के लिए एक और ध्वस्त के लिए अन्य। और जादू इस वीडियो में 0:42 पर इसका उपयोग करके प्राप्त किए गए चेकआउट के android:animateLayoutChanges="true"लिए सेटिंग के साथ होता हैRecyclerView


यह बेहतर समझा मन? मैं यह काम करना आरंभ नहीं कर पा रहे
sourlemonaid

@sourlemonaid मूल रूप से आप सूची के लिए कई दृश्य प्रकार बनाते हैं जैसा कि stackoverflow.com/a/26245463/3731795 में बताया गया है ... आप उस अनुक्रमणिका का ट्रैक रखते हैं जिसके लिए आइटम का विस्तार किया जाता है, और बाकी आइटम उस समय ध्वस्त हो जाते हैं । अब अगर (current_item_index == विस्तारित_item_index) {रिटर्न VIEW_TYPE_EXPANDED} और {{reutrn VIEW_TYPE_COLLAPSED}
penduevev
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.