如何在Navigation Controller中使用共享元素转换

sat*_*iva 31 android navigationcontroller android-architecture-components

我想在导航到其他片段时使用导航架构组件添加共享元素转换.但我不知道怎么做.在文件中也没有任何关于它的内容.有人能帮我吗?

Xzi*_*zin 16

FirstFragment

val extras = FragmentNavigatorExtras(
    imageView to "secondTransitionName")
view.findNavController().navigate(R.id.confirmationAction,
    null, // Bundle of args
    null, // NavOptions
    extras)
Run Code Online (Sandbox Code Playgroud)

first_fragment.xml

<ImageView
    android:id="@+id/imageView"
    android:transitionName="firstTransitionName"
    ...
 />
Run Code Online (Sandbox Code Playgroud)

SecondFragment

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                          savedInstanceState: Bundle?): View {
    sharedElementEnterTransition = ChangeBounds().apply {
        duration = 750
    }
    sharedElementReturnTransition= ChangeBounds().apply {
        duration = 750
    }
    return inflater.inflate(R.layout.second_fragment, container, false)
}
Run Code Online (Sandbox Code Playgroud)

second_fragment.xml

<ImageView
    android:transitionName="secondTransitionName"
    ...
 />
Run Code Online (Sandbox Code Playgroud)

我测试了它.这是有效的.

  • 它适用于片段A中的元素。我想在recyclerView(片段A中)的项目与片段B之间进行转换,这种方法行不通。如何适应我的情况? (2认同)

小智 13

1.0.0-alpha06开始,导航组件支持在目标之间添加共享元素转换.只需将FragmentNavigatorExtras添加到navigate()调用即可.更多详细信息:https://developer.android.com/topic/libraries/architecture/navigation/navigation-implementing#shared-element

val extras = FragmentNavigatorExtras(
    imageView to "header_image",
    titleView to "header_title")
view.findNavController().navigate(R.id.confirmationAction,
    null, // Bundle of args
    null, // NavOptions
    extras)
Run Code Online (Sandbox Code Playgroud)

  • 这适用于任何人吗?我的似乎没有做任何事情. (8认同)
  • 实际上,有FragmentNavigatorExtras,但它们似乎对共享动画没有任何影响,尽管它们确实得到了处理,因为我在源视图中没有转换名称时遇到异常. (6认同)
  • 我有这个工作,但退出过渡似乎没有工作 (2认同)

luc*_*ler 6

要从 recyclerView 的 ImageView 进行这项工作,请设置如下所示的所有内容:

val adapter = PostAdapter() { transitionView, post ->
    findNavController().navigate(
        R.id.action_postsFragment_to_postsDetailFragment,
        null,
        null,
        FragmentNavigatorExtras(transitionView to getString(R.string.transition_image)))
}
Run Code Online (Sandbox Code Playgroud)

在适配器中,这可以解决问题:

itemView.setOnClickListener {
    ViewCompat.setTransitionName(imageView, itemView.context.getString(R.string.transition_image))
    onClickedAction?.invoke(imageView, post)
}
Run Code Online (Sandbox Code Playgroud)

您不必在适配器的项目的 xml 中指定转换名称,只需在单击项目后立即从代码中设置它。

onClickedAction 看起来像:

private val onClickedAction: ((transitionView: View, post: Post) -> Unit)?
Run Code Online (Sandbox Code Playgroud)

然后你把它传递给你的 ViewHolder。

在第二个 Fragment 中,您将转换名称设置为 xml 中的 ImageView:

android:transitionName="@string/transition_image"
Run Code Online (Sandbox Code Playgroud)

并分配过渡像

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    val transition = TransitionInflater.from(context).inflateTransition(android.R.transition.move)
    sharedElementEnterTransition = transition
    sharedElementReturnTransition = transition
}
Run Code Online (Sandbox Code Playgroud)

  • 返回转换仍然不起作用。即当点击详情页面的向上按钮并返回到recyclerView时。有什么线索我可以让它发挥作用吗? (2认同)
  • 这样做的原因是因为您通过仅在单击后设置它来确保 recyclerview 项的“transitionName”在该片段中是唯一的(这很重要!)。我发现这也很有帮助:https://medium.com/@rajnishsuryavanshi223/navigation-component-shared-element-transition-with-recyclerview-8562ea24b3 (2认同)

Aka*_*tel 5

我从这个github示例https://github.com/serbelga/android_navigation_shared_elements中引用了

cardView.setOnClickListener{
  val extras = FragmentNavigatorExtras(
    imageView to "imageView"
  )
  findNavController().navigate(R.id.detailAction, null, null, extras)
}

override fun onCreate(savedInstanceState: Bundle?) {
  super.onCreate(savedInstanceState)
  sharedElementEnterTransition = TransitionInflater.from(context).inflateTransition(android.R.transition.move)
Run Code Online (Sandbox Code Playgroud)

它工作正常。

  • 我应该如何在java中使用它? (8认同)

小智 5

对于 Java

要使共享元素创建一个方法,如:

void sharedNavigation(int id, View... views) {
        FragmentNavigator.Extras.Builder extras = new FragmentNavigator.Extras.Builder();
        for (View view : views)
            extras.addSharedElement(view, view.getTransitionName());
        FragmentNavigator.Extras build = extras.build();
        Navigation.findNavController(getView()).navigate(id,
                null,
                null,
                build);
    }
Run Code Online (Sandbox Code Playgroud)

在目标类或基类中,您必须在 onCreate() 中添加以下代码。

@Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setSharedElementEnterTransition(TransitionInflater.from(getContext())
                .inflateTransition(android.R.transition.move));
    }
Run Code Online (Sandbox Code Playgroud)

并制作过渡动画,将 id 和视图提供给 sharedNavigation() ,如下所示:

sharedNavigation(R.id.action_splashFragment_to_loginFragment,
                        getView().findViewById(R.id.logo));
Run Code Online (Sandbox Code Playgroud)