【问题标题】:Android multiple shared elements not working with fragmentsAndroid多个共享元素不适用于片段
【发布时间】:2021-06-29 07:01:54
【问题描述】:

我想在具有两个共享元素的片段之间进行转换。但问题是:只有一个动画。

共享元素取自第一个片段列表中的 viewHolder。我使用的过渡来自 Material 库,正是这些 https://medium.com/androiddevelopers/material-motion-with-mdc-c1f09bb90bf9

片段 A:

fragmentManager.commit {
            replace([...])
            setReorderingAllowed(true)
            addSharedElement(viewA, viewA.transitionName)
            addSharedElement(viewB, viewB.transitionName)
            addToBackStack(fragmentClass.qualifiedName)
        }

片段 B:

 sharedElementReturnTransition = MaterialContainerTransform().apply {
            scrimColor = Color.TRANSPARENT
            duration = 3000L
            interpolator = DecelerateInterpolator()
        }
 binding.headerContainer.header.cover.transitionName = arguments?.getString("firstTrName") ?: return
 binding.headerContainer.title.cover.transitionName = arguments?.getString("secondTrName") ?: return
 binding.headerContainer.header.setImageResource(arguments?.getString("image") ?: return)
 binding.headerContainer.title.text = arguments?.getString("title") ?: return

似乎只有我在 commit{} 中添加的最后一个元素是转换的元素。我检查了所有内容,转换名称是唯一的,所有数据都在第二个片段中,所有转换名称,这不是参数问题。有任何想法吗?非常感谢您的帮助,这是一个非常重要的客户请求。

【问题讨论】:

    标签: android kotlin fragment shared-element-transition fragment-transitions


    【解决方案1】:

    https://material.io/develop/android/theming/motion

    与传统的 Android 共享元素不同,它不是围绕 要移动的单个共享内容,例如图像 两个场景之间。相反,这里的共享元素是指 起始视图或视图组的边界容器(例如,整行 列表中项目的布局)将其大小和形状转换为 结束 View 或 ViewGroup(例如,全屏的根 ViewGroup 分段)。这些开始和结束容器视图是“共享的 容器变换的元素”。虽然这些容器正在 转换后,它们的内容被交换以创建过渡。

    两个共享元素不能正常工作。当从列表顶部选择开始视图时,imageView 成为一个容器。从底部选择时,textView 成为一个容器。 (从下面的 gif 中查看 example1 和 example5 之间的区别)

    您可以使用传统的共享元素过渡来代替 Material Motion。


    示例和 GIF

    fragmentEnd.sharedElementEnterTransition = MaterialContainerTransform().apply {
        scrimColor = Color.TRANSPARENT
        containerColor = Color.TRANSPARENT
        duration = 1000L
        interpolator = DecelerateInterpolator()
    }
    
    fragmentEnd.sharedElementReturnTransition = MaterialContainerTransform().apply {
        scrimColor = Color.TRANSPARENT
        containerColor = Color.TRANSPARENT
        duration = 1000L
        isElevationShadowEnabled = false
        interpolator = DecelerateInterpolator()
    }
    
    val manager: FragmentManager = activity.supportFragmentManager
    manager.beginTransaction()
            .setReorderingAllowed(true)
            .addSharedElement(imageView, imageView.transitionName)
            .addSharedElement(textView, textView.transitionName)
            .addToBackStack(null)
            .replace([...])
            .commit()
    


    解决方案

    你可以像这样改变过渡:

    fragmentEnd.sharedElementEnterTransition = getTransition() 
    fragmentEnd.sharedElementReturnTransition = getTransition() 
    
    private fun getTransition(): Transition{
        val set = TransitionSet()
        set.ordering = TransitionSet.ORDERING_TOGETHER
        set.addTransition(ChangeBounds())
        set.addTransition(ChangeImageTransform())
        set.addTransition(ChangeTransform())
        return set
    }
    

    使用 MaterialContainerTransform 的正确方法:

    • 分享一个元素

        fragmentEnd.sharedElementEnterTransition = MaterialContainerTransform().apply {
            scrimColor = Color.TRANSPARENT
            containerColor = ResourcesCompat.getColor(activity.resources,R.color.purple_amethyst,null)
            duration = 1000L
            startShapeAppearanceModel = ShapeAppearanceModel().withCornerSize(100f)
            interpolator = DecelerateInterpolator()
        }
      
      
       fragmentEnd.sharedElementReturnTransition = MaterialContainerTransform().apply {
            scrimColor = Color.TRANSPARENT
            containerColor = ResourcesCompat.getColor(activity.resources,R.color.purple_amethyst,null)
            duration = 1000L
            endShapeAppearanceModel = ShapeAppearanceModel().withCornerSize(100f)
            interpolator = DecelerateInterpolator()
        }
      
      
        val manager: FragmentManager = activity.supportFragmentManager
        manager.beginTransaction()
                .setReorderingAllowed(true)
                .addSharedElement(imageView, imageView.transitionName)
                .addToBackStack(null)
                .replace([...])
                .commit()
      
    • FragmentEnd 布局:

        <androidx.constraintlayout.widget.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:id="@+id/container"
            android:background="@color/purple_amethyst">
      
           <....../>
      
        </androidx.constraintlayout.widget.ConstraintLayout>
      
    • 将过渡名称设置为fragmentEnd的顶部布局

      ViewCompat.setTransitionName(binding.container, getArguments().getString("imageViewTransitionName"));
      

    结果

    【讨论】:

      猜你喜欢
      • 2015-08-18
      • 1970-01-01
      • 1970-01-01
      • 2020-12-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-06
      • 1970-01-01
      相关资源
      最近更新 更多