java - 如何像在 Notification 中一样展开和折叠 RecyclerView 中的项目

标签 java android android-recyclerview

enter image description here

我想在RecyclerView中实现展开和折叠,如gif中所说。通过轻敲和上下滑动。 我在下面尝试过, https://stackoverflow.com/a/13381228/11630822 那很好,但不是我所期望的。 我已使用 RecyclerView 列出应用内的所有通知。如果有人有任何想法或经验,请与我分享。任何帮助将不胜感激。提前致谢。

在大多数网站中,能够找到实现左右滑动的方法,但无法实现上下滑动。我想实现像左滑和右滑一样上下滑动。 在 gif 中我没有使用箭头来展开和折叠,我只是上下滑动。我想在应用程序内的 recyclerview 中实现相同的目的。

最佳答案

您可以使用 TransitionAnimator 更改要展开/折叠的部分的可见性,或使用具有不同布局的 ConstraintSet

enter image description here

最简单的方法是使用与布局和约束集不同的 motionLayout,以便在单击按钮时从一种布局更改为另一种布局。您可以使用

在布局之间切换
val constraintSet = ConstraintSet()
constraintSet.clone(this, R.layout.layout_collapsed)

val transition = ChangeBounds()
transition.interpolator = AccelerateInterpolator(1.0f)
transition.setDuration(300)

TransitionManager.beginDelayedTransition(YOUR_VIEW, transition)
constraintSet.applyTo(YOUR_VIEW)

gif 中的展开/折叠动画,使用通过旋转 x 改变按钮方向的转换,展开/折叠设置项目可见性和启动 TransitionManager.beginDelayed 转换

RotateX.kt

class RotateX : Transition {

    @Keep
    constructor() : super()

    @Keep
    constructor(context: Context, attrs: AttributeSet) : super(context, attrs)

    override fun getTransitionProperties(): Array<String> {
        return TRANSITION_PROPERTIES
    }

    override fun captureStartValues(transitionValues: TransitionValues) {
        captureValues(transitionValues)
    }

    override fun captureEndValues(transitionValues: TransitionValues) {
        captureValues(transitionValues)
    }

    override fun createAnimator(
        sceneRoot: ViewGroup,
        startValues: TransitionValues?,
        endValues: TransitionValues?
    ): Animator? {

        if (startValues == null || endValues == null) return null

        val startRotation = startValues.values[PROP_ROTATION] as Float
        val endRotation = endValues.values[PROP_ROTATION] as Float
        if (startRotation == endRotation) return null

        val view = endValues.view
        // ensure the pivot is set
        view.pivotX = view.width / 2f
        view.pivotY = view.height / 2f
        return ObjectAnimator.ofFloat(view, View.ROTATION_X, startRotation, endRotation)
    }

    private fun captureValues(transitionValues: TransitionValues) {
        val view = transitionValues.view
        if (view == null || view.width <= 0 || view.height <= 0) return
        transitionValues.values[PROP_ROTATION] = view.rotationX
    }

    companion object {

        private const val PROP_ROTATION = "iosched:rotate:rotation"
        private val TRANSITION_PROPERTIES = arrayOf(PROP_ROTATION)
    }
}

创建以展开按钮为目标的 xml 文件

    <?xml version="1.0" encoding="utf-8"?>
    <transitionSet
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:interpolator="@android:interpolator/fast_out_slow_in">
    
        <transition class="com.smarttoolfactory.tutorial3_1transitions.transition.RotateX">
            <targets>
                <target android:targetId="@id/ivExpand" />
            </targets>
        </transition>
    
        <autoTransition android:duration="200" />
    
    </transitionSet>

My layout to be expanded or collapsed


<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <com.google.android.material.card.MaterialCardView
        android:id="@+id/cardView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginHorizontal="4dp"
        android:layout_marginVertical="2dp"
        android:clickable="true"
        android:focusable="true"
        android:transitionName="@string/transition_card_view"
        app:cardCornerRadius="0dp"
        app:cardElevation="0dp"
        app:cardPreventCornerOverlap="false">


        <androidx.constraintlayout.widget.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:paddingTop="16dp"
            android:paddingBottom="16dp">

            <androidx.appcompat.widget.AppCompatImageView
                android:id="@+id/ivAvatar"
                android:layout_width="40dp"
                android:layout_height="40dp"
                android:layout_marginStart="16dp"
                android:layout_marginTop="8dp"
                android:scaleType="centerCrop"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="parent"
                tools:src="@drawable/avatar_1_raster" />

            <androidx.appcompat.widget.AppCompatImageView
                android:id="@+id/ivExpand"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginEnd="8dp"
                android:padding="8dp"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintTop_toTopOf="parent"
                app:srcCompat="@drawable/ic_baseline_expand_more_24" />

            <TextView
                android:id="@+id/tvTitle"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginStart="12dp"
                android:layout_marginTop="6dp"
                android:text="Some Title"
                android:textSize="20sp"
                android:textStyle="bold"
                app:layout_constraintStart_toEndOf="@+id/ivAvatar"
                app:layout_constraintTop_toTopOf="parent" />


            <TextView
                android:id="@+id/tvDate"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="4dp"
                android:textColor="?android:textColorSecondary"
                android:textSize="12sp"
                app:layout_constraintStart_toStartOf="@+id/tvTitle"
                app:layout_constraintTop_toBottomOf="@id/tvTitle"
                tools:text="Tuesday 7pm" />

            <TextView
                android:id="@+id/tvBody"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_marginTop="8dp"
                android:layout_marginEnd="16dp"
                android:ellipsize="end"
                android:lines="1"
                android:text="@string/bacon_ipsum_short"
                android:textSize="16sp"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="@+id/ivAvatar"
                app:layout_constraintTop_toBottomOf="@id/tvDate" />


            <androidx.recyclerview.widget.RecyclerView
                android:id="@+id/recyclerView"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginStart="16dp"
                android:layout_marginTop="16dp"
                android:layout_marginEnd="16dp"
                android:orientation="horizontal"
                android:overScrollMode="never"
                android:visibility="gone"
                app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@id/tvBody"
                tools:listitem="@layout/item_image_destination" />

        </androidx.constraintlayout.widget.ConstraintLayout>

    </com.google.android.material.card.MaterialCardView>

</layout>

更改要折叠或展开的项目的可见性

private fun setUpExpandedStatus() {
    if (isExpanded) {
        binding.recyclerView.visibility = View.VISIBLE
        binding.ivExpand.rotationX = 180f
    } else {
        binding.recyclerView.visibility = View.GONE
        binding.ivExpand.rotationX = 0f
    }
}

开始动画

val parent = (itemView.parent as? ViewGroup)
    
val transition = TransitionInflater.from(itemView.context)
                .inflateTransition(R.transition.icon_expand_toggle)
    
TransitionManager.beginDelayedTransition(parent, transition)
    
isExpanded = !isExpanded
    
setUpExpandedStatus()

我创建了动画和过渡示例,包括 gif 上的示例,您可以查看它们 there .

关于java - 如何像在 Notification 中一样展开和折叠 RecyclerView 中的项目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64610131/

相关文章:

android - 从 DialogFragment 返回值

java - 如何将一个@Test方法中生成的数据访问到另一个测试方法但在不同的类中

java - Jupyter Scala 笔记本无法识别使用 Java 列表的 Scala 匿名函数

java - Git 管理环境特定配置

java - drawable 不是可序列化的异常

java - 如何在 Firebase 中获取父节点的嵌套节点数

android - 更改 recyclerview 中所有其他元素的背景

java - ArrayList 还是 Map?还帮助如何存放 child

java - 切换按钮元素消失但在动画完成后突然重新出现

android - 根据自定义 View 适配器的TAG值获取Item的位置