I want to expand/collapse the items of my recyclerView in order to show more info. I want to achieve the same effect of the SlideExpandableListView.

Basically in my viewHolder I have a view that is not visible and I want to do a smooth expand/collapse animation rather than set the visibility to VISIBLE/GONE only. I only need an item to be expanded at a time and it would be cool to have some elevation to show that the item is selected.

It is the same effect of the new Android recent calls history list. The options "CALL BACK" and "DETAILS" are visible only when an item is selected.

RecyclerView expandable items


Please don't use any library for this effect instead use the recommended way of doing it according to Google I/O. In your recyclerView's onBindViewHolder method do this:

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();
    }
});
  • Where details is my view that will be displayed on touch (call details in your case. Default Visibility.GONE).
  • mExpandedPosition is an int variable initialized to -1

And for the cool effects that you wanted, use these as your list_item attributes:

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

where comment_background is:

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

and comment_selection is:

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

For this, just needed simple lines not complicated

in your onBindViewHolder method add below code

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 is an int global variable initialized to -1

For those who want only one item expanded and others get collapsed. Use this

first declare a global variable with previousExpandedPosition = -1

then

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