web-dev-qa-db-fra.com

Comment utiliser les transitions d'éléments partagés dans le contrôleur de navigation

J'aimerais ajouter une transition d'éléments partagés à l'aide des composants de l'architecture de navigation lors de la navigation vers un autre fragment. Mais je ne sais pas comment. Aussi dans les documentations il n'y a rien à ce sujet. Est-ce que quelqu'un peut m'aider?

29
sativa

J'ai pris référence à cet exemple de 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)

Cela fonctionne correctement.

2
Akash Patel

Premier Fragment

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

first_fragment.xml

<ImageView
    Android:id="@+id/imageView"
    Android:transitionName="firstTransitionName"
    ...
 />

Deuxième Fragment

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)
}

second_fragment.xml

<ImageView
    Android:transitionName="secondTransitionName"
    ...
 />

Je l'ai testé. C'est travaillé.

15
Xzin

Depuis 1.0.0-alpha06 , le composant de navigation prend en charge l’ajout de transitions d’éléments partagés entre les destinations. Ajoutez simplement FragmentNavigatorExtras pour naviguer (). Plus de détails: https://developer.Android.com/guide/navigation/navigation-animate-transitions#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)
13
Bruno Milhan

Pour que cela fonctionne à partir d'une image recyclerView, procédez comme suit:

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

dans l'adaptateur, cela fait l'affaire:

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

Il n'est pas nécessaire de spécifier le nom de la transition dans le fichier XML de l'élément de l'adaptateur, mais simplement de le définir à partir du code dès que l'élément est cliqué.

L'action onClickedAction ressemble à ceci:

private val onClickedAction: ((transitionView: View, post: Post) -> Unit)?

et vous le transmettez à votre ViewHolder.

Dans le deuxième fragment, définissez le nom de la transition sur ImageView en xml:

Android:transitionName="@string/transition_image"

et assigner la transition comme

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    val transition = TransitionInflater.from(context).inflateTransition(Android.R.transition.move)
    sharedElementEnterTransition = transition
    sharedElementReturnTransition = transition
}
4
luckyhandler

J'ai finalement réussi à faire fonctionner ceci: Sur le fragment B:

val transition = TransitionInflater.from(this.activity).inflateTransition(Android.R.transition.move)

sharedElementEnterTransition = ChangeBounds().apply {
            enterTransition = transition
        }

Assurez-vous simplement que vos noms de transition sont corrects dans vos vues et que vous n'avez PAS entertTransition sur le fragment B

2
LuchoG

Alors disons que vous avez deux fragments, FragmentSecond et FragmentThird. Les deux ont ImageView avec le même nom de transition, disons: "imageView"

Android:transitionName="imageView"

Il suffit de définir une action normale entre ces fragments.

Dans FragmentSecond, ajoutons nos extras

val extras = FragmentNavigatorExtras( binding.image to "imageView")

findNavController().navigate(R.id.action_secondFragment_to_thirdFragment , null, null , extras)

Nous disons donc que nous voulons partager cette ImageView, avec ce nom de transition, avec ThirdFragment

Et puis dans ThirdFragment:

override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        sharedElementEnterTransition = TransitionInflater.from(context).inflateTransition(Android.R.transition.move)
        setHasOptionsMenu(true)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        Glide.with(this).load(IMAGE_URI).into(binding.headerImage)
    }

La seule chose à faire est de charger l'image dans les deux fragments à partir de la même URL. L'URL peut être transmise entre des fragments à l'aide d'un objet Bundle et transmise dans l'appel de navigation ou en tant qu'argument de destination dans le graphique de navigation.

Si vous en avez besoin, je prépare un exemple sur la navigation. Il existe également SharedElementTransition:

https://github.com/matteopasotti/navigation-sample

2
Matteo Pasotti

Avec la dernière version de la bibliothèque, vous pouvez simplement écrire ce qui suit:

view.findNavController().navigate(
    R.id.action_firstFragment_to_secondFragment, 
    null,  
    null,
    FragmentNavigator.Extras.Builder().addSharedElements(
        mapOf(
           firstSharedElementView to "firstSharedElementName",
           secondSharedElementView to "secondSharedElementName"
        )
    ).build()
)

Pour que la transition fonctionne, vous devez également spécifier le sharedElementEnterTransition et/ou le sharedElementReturnTransition dans la méthode de destination Fragments onCreateView, comme Xzin l'a expliqué dans sa réponse.

0
monkey