折叠CardView动画无法正常工作

时间:2018-03-01 17:01:01

标签: android android-recyclerview kotlin android-animation android-transitions

我正在尝试做什么

我有一个RecyclerView,其中有很多项基本上都是CardView

这些卡片在其正文中间有一个支持文字,默认情况下其可见性设置为GONE,当我点击卡片右侧的箭头时,它会显示VISIBLE

我试图在文字显示时以及在文本崩溃时为卡片制作动画。

下图显示了扩展卡和折叠卡:

cards

CardView布局(为了便于阅读,我删除了一些部分):

<android.support.v7.widget.CardView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    card_view:cardCornerRadius="3dp"
    card_view:cardElevation="4dp"
    card_view:cardUseCompatPadding="true"
    android:id="@+id/root">

    <LinearLayout
        android:id="@+id/item_ll"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:padding="@dimen/activity_vertical_margin">

        <!-- The header with the title and the item -->


        <TextView
            android:id="@+id/body_content"
            style="@style/TextAppearance.AppCompat.Medium"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:padding="8dp"
            android:layout_marginBottom="8dp"
            android:text="@string/about_page_description"
            android:textColor="@color/secondaryText"
            android:visibility="gone"/>

        <!-- The divider, and the footer with the timestamp -->

    </LinearLayout>
</android.support.v7.widget.CardView>

问题

当卡片展开并露出身体TextView时,动画正在工作,但是,当我尝试将其折叠回来时,动画片下方的卡片与第一张卡片重叠。

示例:

card animation

到目前为止我尝试了什么

我之前已经问过similar question about this behavior here,但该解决方案不适用于卡片中间的TextView

负责动画部分的代码位于RecyclerView适配器内。箭头有一个点击监听器,可以调用以下方法:

private fun toggleVisibility() {
    if (bodyContent.visibility == View.GONE || bodyContent.visibility == View.INVISIBLE) {
        btSeeMore.animate().rotation(180f).start()
        TransitionManager.beginDelayedTransition(root, AutoTransition())
        bodyContent.visibility = View.VISIBLE
    }
    else {
        btSeeMore.animate().rotation(0f).start()

        TransitionManager.beginDelayedTransition(root, AutoTransition())
        bodyContent.visibility = View.GONE
    }
}

root是我的CardView

我还尝试使用LinearLayout代替卡本身进行延迟转换,但这也无效。

如何为布局实现这种行为?

5 个答案:

答案 0 :(得分:2)

您必须在RecyclerView上执行转换,而不是在单个项目上执行转换。否则,自动转换不会考虑RecyclerView布局更改,因为它只会查看该子视图中的更改,即使事实上其他ViewHolders也会间接受到影响(布局参数也在发生变化)。

因此,不是将“root”(项目视图)传递给TransitionManager#beginDelayedTransition,而是将引用传递给RecyclerView

答案 1 :(得分:0)

我建议你使用Animator框架并将高度动画应用到TextView。

这是一个很好的库,你可以使用:https://github.com/cachapa/ExpandableLayout

我还建议您检查source code,它使用动画师

答案 2 :(得分:0)

如果他的物品在RecyclerViews回调之外调整大小,那么RecyclerView确实表现得很奇怪。尝试使用adapter.notifyItemChanged(位置,有效负载)并更新项目:

用以下方法替换适配器的on:

adapter.notifyItemChanged(adapterPosition, true) // needs adapter reference, can use more meaningful payload

然后在你的适配器里面:

override fun onBindViewHolder(holder: Holder, position: Int, payloads: List<Any>) {
    if (payloads.isEmpty())
        onBindViewHolder(holder, position)
    else
        holder.toggleVisibility()
}

您还可以看到在LinearLayout而不是Card本身上运行delayedTransition时会发生什么。

这不是完美的,但会触发以下项目的动画,而不是跳跃和剪辑。

答案 3 :(得分:0)

也许这太迟了。 在onBindViewHolder()里面包含这个

holder.view.btSeeMore.setOnClickListener { view ->
    val seeMore = (bodyContent.visibility != View.VISIBLE)
    view.animate().rotation(if (seeMore) 180f else 0f).start()
    bodyContent.visibility = if (seeMore) View.VISIBLE else View.GONE
}

答案 4 :(得分:0)

您必须在包含Cardview的根视图上应用TransitionManager.beginDelayedTransition

您必须从整个布局中删除android:animateLayoutChanges="true"

TransitionManager.beginDelayedTransition(the_root_view_where_card_view_exist, new AutoTransition());