折叠 CardView 动画无法正常工作

Posted

技术标签:

【中文标题】折叠 CardView 动画无法正常工作【英文标题】:Collapsing CardView Animation not working correctly 【发布时间】:2018-08-09 19:59:40 【问题描述】:

我想要做什么

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

这些卡片在它们的正文中间有一个支持文本,默认情况下它的可见性设置为GONE,当我点击卡片右侧的箭头时,它变成了VISIBLE

我正在尝试在文本显示和折叠时为卡片设置动画。

下图显示了展开的卡片和折叠的卡片:

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

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

    <LinearLayout
        android:id="@+id/item_ll"
        android:layout_
        android:layout_
        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_
            android:layout_
            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 时,动画正在工作,但是,当我尝试将其折叠回来时,动画下方的卡片与第一个卡片重叠。

示例:

到目前为止我已经尝试过什么

我之前已经问过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 而不是卡本身来延迟转换,但这也不起作用。

我怎样才能为我的布局实现这种行为?

【问题讨论】:

您是否尝试过手动为文本视图的高度设置动画? 我没有。由于delayedTransition是为之前的布局工作的,我觉得没必要,直到现在…… 【参考方案1】:

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

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

【讨论】:

【参考方案2】:

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

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

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

【讨论】:

【参考方案3】:

如果他的项目在 RecyclerViews 回调之外调整大小,RecyclerView 的行为确实很奇怪。尝试使用 adapter.notifyItemChanged(position, payload) 然后更新项目:

将适配器的 onclick 替换为:

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 本身上运行延迟转换时会发生什么。

这并不完美,但它会触发跟随项目的动画,而不是它们的跳跃和剪辑。

【讨论】:

【参考方案4】:

我建议您使用 Animator 框架并将高度动画应用于您的 TextView。

这是一个不错的库,您可以使用:https://github.com/cachapa/ExpandableLayout

我也建议你检查它是source code,它使用了动画师

【讨论】:

【参考方案5】:

也许为时已晚。 在 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

【讨论】:

以上是关于折叠 CardView 动画无法正常工作的主要内容,如果未能解决你的问题,请参考以下文章

如何在Android中加载带有动画的cardview GridView?

通过单击或滑动手势(Android)展开/折叠 CardView?

dev gridcontrol CardView 如何禁止折叠

引导下拉菜单在悬停时无法正常工作

GridLayout 和 CardView 无法在所有设备上完美运行

ImageView 没有形成卡片视图,在它工作正常之前,现在出了点问题,我无法弄清楚