1

I'm building a UI that consists of multiple CardViews inside a RecyclerView.

<?xml version="1.0" encoding="utf-8"?>

<android.support.v7.widget.CardView
    android:id="@+id/card"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    app:cardCornerRadius="5dp"
    app:cardElevation="1dp"
    app:cardBackgroundColor="#ddffca"
    android:animateLayoutChanges="true"
    xmlns:android="http://schemas.android.com/apk/res/android"
    >
<android.support.constraint.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:animateLayoutChanges="true"
    android:padding="10dp"
    >
    <TextView
        android:id="@+id/tvHello"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:text="Hello there!"
        />

  <TextView
      android:id="@+id/test"
      android:layout_width="wrap_content"
      android:layout_height="50dp"
      android:visibility="gone"
      android:gravity="center"
      app:layout_constraintStart_toStartOf="parent"
      app:layout_constraintTop_toBottomOf="@id/tvHello"
      android:text="GENERAL KENOBI!"
      />
</android.support.constraint.ConstraintLayout>
  </android.support.v7.widget.CardView>

Inside I have specified that on click even I will have my test text animated to appear. It's working great and I'm mostly happy with the results. But as soon as I add a few cards inside the RecyclerView the animation starts working a bit strange. What I mean is views that are not touched are not animating properly considering the other views have changed their size. Instead I see another view jumping to its new position without any animation. How can I make it animate according to other views?

EDIT I have also provided my code from onBindViewHolder. It's in Kotlin though:

override fun onBindViewHolder(
    holder: OperationsViewHolder,
    position: Int
  ) {

    var card: CardView = holder.cardView
    card.setOnClickListener {
      if (!operations.get(position).selected!!) {
        ObjectAnimator.ofFloat(card, "translationZ", 1f, 10f)
            .start()
        holder.test.visibility = View.VISIBLE;
        operations.get(position)
            .selected = true
      } else {
        ObjectAnimator.ofFloat(card, "translationZ", 10f, 1f)
            .start()
        holder.test.visibility = View.GONE;
        operations.get(position)
            .selected = false
      }

    }
  }

EDIT 2 I have also tried adding android:animateLayoutChanges="true" to all elements, didn't help

Vendetta8247
  • 592
  • 1
  • 5
  • 30

1 Answers1

1

Not sure if this fits the constraints of your question but you don't necessarily have to animate the expanding/collapsing manually. The RecyclerView can provide that to you out-of-the-box by using notifyItemChanged() properly in your Adapter.

override fun onBindViewHolder(
    holder: OperationsViewHolder,
    position: Int
  ) {

    var card: CardView = holder.cardView

    if (operations.get(position).selected!!) {
        holder.test.visibility = View.VISIBLE;
    } else {
        holder.test.visibility = View.GONE;
    }

    card.setOnClickListener {
      if (!operations.get(position).selected!!) {
        operations.get(position)
            .selected = true
      } else {
        operations.get(position)
            .selected = false
      }
      notifyItemChanged(position)
    }
  }

The above code removes the animation logic and instead calls notifyItemChanged every time the CardView is clicked. This tells the RecyclerView to re-render the item at that particular position and gives you an animation for the re-render for free.

crymson
  • 1,170
  • 7
  • 12
  • Thank you for the answer my friend. It looks like it fixed the issue so I think I will accept your answer. Before that I wanted to mention though that the animation is kind of a bit different than it was before. Now it is somewhat of a fade out animation while previously it was something like a slide-expand. Additionally I wanted to know if it's possible to change the animation speed or any other param? Thanks again – Vendetta8247 Aug 23 '18 at 06:55
  • Yes, unfortunately that is the downside of this solution in that since you get the animation for free, it's kind of hard to customize the duration and the kind of animation (translation instead of fade) without adding some extra things. Here's a link to a potential solution where the you mostly define all your animations in XML and run then using a TransitionManager and is quite similar to this solution minus the custom animations: https://stackoverflow.com/a/38623873/3090173 – crymson Aug 23 '18 at 18:17