RecyclerView memperluas / menciutkan item

145

Saya ingin memperluas / menciutkan item dari recyclerView saya untuk menampilkan lebih banyak info. Saya ingin mencapai efek yang sama dengan SlideExpandableListView .

Pada dasarnya di viewHolder saya, saya memiliki tampilan yang tidak terlihat dan saya ingin melakukan animasi yang diperluas / runtuh daripada mengatur visibilitas ke VISIBLE / GONE saja. Saya hanya perlu item untuk diperluas pada satu waktu dan itu akan keren untuk memiliki beberapa ketinggian untuk menunjukkan bahwa item tersebut dipilih.

Ini adalah efek yang sama dari daftar riwayat panggilan terakhir Android baru. Opsi "CALL BACK" dan "DETAILS" hanya terlihat ketika item dipilih.

RecyclerView item yang dapat diperluas

stanete
sumber
Saya punya pertanyaan terkait. Di aplikasi Jam, aktivitas pengaturan alarm memiliki fitur serupa. Apakah ini dilakukan dengan cara yang sama?
user2731584
Hei, apakah Anda punya solusinya? saya juga mencari solusi yang sama untuk aplikasi saya.
Arpit Patel
Apakah Anda menemukan solusi?
Armin Ghoreishi
1
Saya telah memperbarui cara yang disarankan untuk melakukannya sesuai dengan Google I / O 2016. Lihat jawaban saya stackoverflow.com/questions/27203817/…
Heisenberg
periksa jawaban saya di sini solusi stackoverflow.com/a/48092441/5962715
Kiran Benny Joseph

Jawaban:

192

Tolong jangan gunakan perpustakaan apa pun untuk efek ini, sebaliknya gunakan cara yang disarankan untuk melakukannya sesuai dengan Google I / O. Dalam metode onBindViewHolder recyclerView Anda lakukan ini:

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();
    }
});
  • Di mana detail adalah pandangan saya yang akan ditampilkan pada sentuhan (detail panggilan dalam kasus Anda. Visibilitas Default. PERGI).
  • mExpandedPosition adalah variabel int diinisialisasi ke -1

Dan untuk efek keren yang Anda inginkan, gunakan ini sebagai atribut list_item Anda:

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

di mana comment_background berada:

<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>

dan comment_selection adalah:

<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>
Heisenberg
sumber
22
Saat menggunakan kode ini, perluasan-animasi terlihat aneh. Setiap kali item teratas menghilang dan semuanya bergeser satu posisi. Pernahkah Anda mengalami hal serupa?
chris-pollux
6
Saya mencoba melakukan animasi tetapi saya menerapkan ini pada adaptor, tetapi apa yang akan menjadi solusi TransitionManager.beginDelayedTransition(recyclerView);jika saya tidak dapat menyembunyikan referensi tampilan pendaur ulang.
Martín Serrano
2
@Ranveer Ini berfungsi dengan baik. Saya memiliki dua recyclerViews yang sangat mirip, tetapi hanya berfungsi dengan benar untuk satu. Tidak tahu kenapa. @ MartínDaniel Anda harus memasukkan recyclerViewsebagai parameter dalam konstruktor untuk adaptor
chris-pollux
26
Ini adalah pendekatan yang mengerikan. Saya tidak percaya itu direkomendasikan di Google I / O. Bahkan setelah menyelidiki proyek Plaid dan mengimplementasikan semua solusi yang diperlukan darinya, animasi masih menyebabkan beberapa gangguan utama di RecyclerView, misalnya item pertama / terakhir yang terlihat menghilang sebelum waktunya. Juga menggulir saat animasi berjalan mengacaukan semua hal. Secara umum, saya tidak berpikir memperbaiki semua masalah yang disebabkan oleh pendekatan ini dapat disebut "hanya meletakkan satu baris dan semuanya akan berfungsi" seperti yang diiklankan.
Vitali Olshevski
6
Apakah kita memiliki cara yang lebih segar & mudah di tahun 2019 untuk masalah ini?
Ponomarenko Oleh
76

Untuk ini, hanya perlu garis-garis sederhana tidak rumit

dalam metode onBindViewHolder Anda tambahkan kode di bawah ini

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 adalah variabel global int diinisialisasi ke -1

Bagi mereka yang ingin hanya satu item yang diperluas dan yang lain akan runtuh. Gunakan ini

pertama mendeklarasikan variabel global dengan beforeExpandedPosition = -1

kemudian

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

Selesai !!!. Sederhana dan rendah hati .. :)

Kiran Benny Joseph
sumber
solusi hebat Saya juga merekomendasikan untuk memindahkan pengaturan OnClickListenerke onCreateViewHolderbukanonBindViewHolder
YTerle
1
Bekerja dengan sangat baik, tentang waktu ada solusi yang layak yang hanya memungkinkan RecyclerViewmelakukan pekerjaan, maksud saya, apa gunanya LayoutManagerjika tidak mengelola tata letak! Solusi ini lebih baik daripada solusi pilihan teratas karena memiliki lebih sedikit kode, memungkinkan RecyclerViewmenangani hal-hal dan bekerja lebih baik!
Mark Keen
1
tidak begitu mengerti bagaimana cara menambahkan tampilan "detail". Haruskah itu statis untuk setiap dudukan? Bagaimana jika untuk setiap item daftar saya perlu menambahkan tampilan yang berbeda?
BekaBot
@BekaBot itu adalah pandangan yang ingin Anda sembunyikan selama barang yang runtuh
Kiran Benny Joseph
@KiranBennyJoseph ya, saya mengerti. Dalam hal ini tampilan harus sama untuk semua item? Bagaimana jika saya ingin tampilan berbeda untuk item yang berbeda?
BekaBot
72

Bukan mengatakan ini adalah pendekatan terbaik, tetapi tampaknya berhasil bagi saya.

Kode lengkap dapat ditemukan di: Kode contoh di: https://github.com/dbleicher/recyclerview-grid-quickreturn

Pertama, tambahkan area yang diperluas ke tata letak sel / item Anda, dan buat tata letak sel terlampir animateLayoutChanges = "true". Ini akan memastikan bahwa perluasan / keruntuhan dianimasikan:

<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>

Kemudian, buat kelas Adapter RV Anda mengimplementasikan View.OnClickListener sehingga Anda dapat bertindak pada item yang diklik. Tambahkan bidang int untuk menahan posisi tampilan yang diperluas, dan inisialisasi ke nilai negatif:

private int expandedPosition = -1;

Terakhir, terapkan metode ViewHolder, onBindViewHolder () Anda dan ganti metode onClick (). Anda akan memperluas tampilan di onBindViewHolder jika posisinya sama dengan "ExpandPosition", dan menyembunyikannya jika tidak. Anda menetapkan nilai diperluasPosisi di pendengar onClick:

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

Ini harus diperluas hanya satu item setiap kali, menggunakan animasi sistem-default untuk perubahan tata letak. Setidaknya itu bekerja untuk saya. Semoga ini bisa membantu.

MojoTosh
sumber
Saya tahu cara menjaga hanya satu item yang dipilih. Saya tidak benar-benar tahu bagaimana melakukan animasi pada item itu. Animasi rentangkan / runtuh dengan animasi sistem default tidak terlihat sangat mulus.
stanete
1
Saya belum mencoba yang berikut, tapi sepertinya itu akan berhasil. Lihatlah jawabannya di: stackoverflow.com/a/26443762/2259418
MojoTosh
2
@ user2731584 - Saya rasa tidak. Melihat (apa yang saya yakini) sumber mereka, tampaknya jam Lollipop menggunakan ListView untuk menampilkan daftar alarm. Layout: android.googlesource.com/platform/packages/apps/DeskClock/+/… Mereka tampaknya memiliki kode khusus untuk menganimasikan item ekspansi / runtuh dalam daftar ini. Lihat sumber berikut: android.googlesource.com/platform/packages/apps/DeskClock/+/…
MojoTosh
1
@ MojoTosh kamu benar. Mereka menggunakan ListView dan melakukan animasi menggunakan kode. expandAlarmfungsi dalam AlarmClockFragment.javafile mengeksekusi bagian ekspansi.
user2731584
4
Mana yang onClick()harus saya timpa? Tidak ada onClickdalam Adaptor.
Vicky Leong
15

Ada perpustakaan yang sangat mudah digunakan dengan dukungan gradle: https://github.com/cachapa/ExpandableLayout .

Langsung dari dokumen perpustakaan:

<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>

Setelah Anda menandai Anda diupgrade pandangan, sebut saja salah satu metode ini pada wadah: expand(), collapse()atautoggle()

Laurențiu Onac
sumber
Apakah ini masih cara terbaik untuk melakukannya? Saya mencoba mengikuti apa yang Anda tulis. Saya memiliki beberapa pandangan daur ulang yang ingin saya kembangkan untuk menampilkan grafik ketika diklik
sourlemonaid
10

Saya tahu ini sudah lama sejak pertanyaan awal diposting. Tetapi saya pikir untuk yang lambat seperti saya sedikit penjelasan tentang jawaban @ Heisenberg akan membantu.

Deklarasikan dua variabel dalam kelas adaptor sebagai

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

Kemudian di onBindViewHolder berikut seperti yang diberikan dalam jawaban asli.

      // 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();
            }
        });

Dan terakhir untuk mendapatkan objek recyclerView dalam penggantian adaptor

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

    this.recyclerView = recyclerView;
}

Semoga ini membantu.

shahroz butt
sumber
3
Solusi hebat dan sederhana. Perbaikan kecil, gunakan RecyclerView.NO_POSITION daripada angka ajaib -1.
Casper Bang
8

Tidak perlu menggunakan perpustakaan pihak ketiga. Sebuah tweak dalam metode ditunjukkan dalam Google I / O 2016 dan Heisenberg tentang topik ini, melakukan trik.

Karena notifyDataSetChanged() menggambar ulang yang lengkapRecyclerView , notifyDataItemChanged()adalah pilihan yang lebih baik (bukan yang terbaik) karena kita memiliki posisi dan kemampuan yang ViewHolderkita miliki, dan notifyDataItemChanged()hanya menggambar ulang yang khusus ViewHolderpada posisi tertentu .

Tetapi masalahnya adalah bahwa hilangnya prematur ViewHolderpada mengklik dan kemunculannya tidak dihilangkan bahkan jika notifyDataItemChanged()digunakan.

Kode berikut ini tidak menggunakan notifyDataSetChanged()atau notifyDataItemChanged()dan Diuji pada API 23 dan berfungsi seperti pesona ketika digunakan pada RecyclerView di mana setiap ViewHolder memiliki CardViewelemen root seperti itu:

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_positionadalah integer global yang diinisialisasi ke -1. detailsadalah tampilan lengkap yang ditampilkan saat diperluas dan terselubung saat diciutkan.

Seperti yang dikatakan, elemen root dari ViewHolderadalah CardViewdengan foregrounddan stateListAnimatoratribut didefinisikan persis seperti yang dikatakan oleh Heisenberg pada topik ini.

UPDATE: Demonstrasi di atas akan runtuh item yang sudah diperluas sebelumnya jika salah satu dari mereka di diperluas. Untuk memodifikasi perilaku ini dan menjaga item yang diperluas seperti ketika item lain diperluas, Anda akan memerlukan kode berikut.

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);

UPDATE: Ketika memperluas item terakhir dalam daftar, itu mungkin tidak dibawa ke visibilitas penuh karena bagian yang diperluas berada di bawah layar. Untuk mendapatkan item lengkap di layar gunakan kode berikut.

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);

PENTING: Agar demonstrasi di atas berfungsi, seseorang harus menyimpan dalam kode mereka instance dari RecyclerView & itu LayoutManager (nanti untuk fleksibilitas)

Koushik Shom Choudhury
sumber
Terima kasih solusi ini berfungsi untuk saya. Saya mencoba menghindari menggunakan notifyItemChangedkarena saya ImageViewmemuat gambar dari url. notifyItemChangedmemuat ulang gambar saya membuatnya tampak aneh
Tam Huynh
Garis yang tepat TransitionManager.beginDelayedTransition(recycler);, sangat bagus. Tetapi saya menemukan bahwa dengan menggunakan metode ini, jika saya mengklik-spam beberapa baris secara berurutan, pada akhirnya memicu crash internal The specified child already has a parent. You must call removeView() on the child's parent first. Saya membayangkan ini karena tampilan daur ulang pada batas tampilan pendaur ulang, tetapi saya tidak bisa memastikannya. Adakah yang memiliki masalah yang sama?
Roger Oba
Apakah ini masih cara terbaik untuk melakukannya? Saya mencoba mengikuti apa yang Anda tulis. Saya memiliki beberapa tampilan daur ulang yang ingin saya kembangkan untuk memperlihatkan grafik ketika diklik. Saya mengalami kesulitan memahami apa yang harus dilakukan
sourlemonaid
Adakah yang punya contoh lengkap dari implementasi ini? Maksud saya contoh kode kerja. Tolong bantu. Saya tidak dapat mengerti bagaimana melakukannya?
Munazza
7

Setelah menggunakan cara yang direkomendasikan melaksanakan diupgrade / item dilipat berada di RecyclerViewatas RecyclerView memperluas / item runtuhnya dijawab oleh Heisenberg , saya telah melihat beberapa artefak terlihat setiap kali RecyclerViewrefresh dengan menerapkan TransitionManager.beginDelayedTransition(ViewGroup)dan kemudian notifyDatasetChanged().

Jawaban aslinya:

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();
    }
});

Diubah:

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());
    }
}
  • Perincian adalah tampilan yang ingin Anda tampilkan / sembunyikan selama item diperluas / diciutkan
  • mExpandedPosition adalah intyang melacak item yang diperluas
  • mExpandedHolder adalah ViewHolderdigunakan selama barang runtuhnya

Perhatikan bahwa metode TransitionManager.beginDelayedTransition(ViewGroup)dan notifyDataSetChanged()diganti dengan notifyItemChanged(int)menargetkan item tertentu dan beberapa penyesuaian kecil.

Setelah modifikasi, efek yang tidak diinginkan sebelumnya harus hilang. Namun, ini mungkin bukan solusi yang sempurna. Itu hanya melakukan apa yang saya inginkan, menghilangkan pemandangan.

:: EDIT ::

Untuk klarifikasi, baik mExpandedPositiondan mExpandedHolderyang GLOBALS.

Chan Teck Wei
sumber
Tolong jelaskan bagaimana dan di mana mExpandedHolder dideklarasikan dan digunakan?
Werner
1
@ Werner Saya telah mengedit jawaban untuk menunjukkan di mana dinyatakan. Penggunaannya ada dalam snippet itu sendiri dan juga tujuannya. Ini digunakan untuk menghidupkan runtuh, item diperluas.
Chan Teck Wei
Saya suka pendekatan ini sejauh menyangkut animasinya, tapi saya mengalami "pudar" kecil ini saat mengklik item. Apakah Anda memiliki itu juga atau dengan kata lain, apakah ini karena menggunakan notifyItemChanged ()? drive.google.com/file/d/1GaU1fcjHEfSErYF50otQGLGsIWkSyQSe/…
kazume
Iya. Seperti yang sudah Anda duga, itu disebabkan oleh notifyItemChanged(). Anda dapat menghidupkan dan mengubah ketinggian item secara manual dan menambahkan tampilan ke dalamnya.
Chan Teck Wei
@ChanTeckWei: solusi Anda berfungsi dengan baik tetapi gambar baris berkedip setiap kali saya menutup atau memperluas baris item recyclerview .. Apakah ada solusi untuk ini?
Pragya Mendiratta
3

Lakukan hal berikut setelah Anda mengatur pendengar onClick ke kelas 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();
    }
}

Saya pikir itu akan membantu, itulah cara saya menerapkan dan melakukan google yang sama tidak dalam tampilan panggilan terakhir.

Rensodarwin
sumber
2

Saya terkejut bahwa belum ada jawaban yang ringkas, meskipun animasi yang diperluas / runtuh sangat mudah dicapai hanya dengan 2 baris kode:

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

bersama dengan

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

Jadi bagi saya, penjelasan dalam tautan di bawah ini sangat bermanfaat: https://medium.com/@nikola.jakshic/how-to-expand-collapse-items-in-recyclerview-49a648a403a6

Bianca Daniciuc
sumber
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);
        }
}

masukkan deskripsi gambar di sini

Keshav Gera
sumber
0

Gunakan dua jenis tampilan di layar Anda RVAdapter. Satu untuk tata letak diperluas dan lainnya untuk diciutkan. Dan keajaiban terjadi dengan pengaturan android:animateLayoutChanges="true"untuk RecyclerView Checkout efek yang dicapai menggunakan ini pada 0:42 di video ini

penduDev
sumber
keberatan menjelaskan ini lebih baik? Sepertinya saya tidak bisa membuatnya bekerja
sourlemonaid
@sourlemonaid pada dasarnya Anda membuat beberapa jenis tampilan untuk daftar seperti yang dijelaskan dalam stackoverflow.com/a/26245463/3731795 ... Anda menyimpan indeks yang itemnya diperluas, dan item lainnya diciutkan pada waktu itu . Sekarang jika (current_item_index == diperluas_item_index) {return VIEW_TYPE_EXPANDED} lain {reutrn VIEW_TYPE_COLLAPSED}
penduDev