RecyclerView Shared Element Transition Not Working

762 views Asked by At

My aim : GIF

I followed this guide to implement shared element transitions in my app

My Result : Screen Capture

Problem : The shared animation is happening. But the image in the ItemMovieFragment is coming from top left corner of container.

Cannot figure out the solution.

Please suggest some solution

Here is the code :

ItemMovieFragment : complete code

   class ItemMovieFragment  : Fragment() {

    private lateinit var itemMovieViewModel: ItemMovieViewModel
    private lateinit var args : ItemMovieFragmentArgs

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val binding = FragmentItemMovieBinding.inflate(inflater)


      //  (activity as AppCompatActivity).supportActionBar?.hide()

        sharedElementEnterTransition =    TransitionInflater.from(context).inflateTransition(android.R.transition.move)

      
     // rest of the code
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        ViewCompat.setTransitionName(image_poster,args.itemiId.toString())
        Toast.makeText(context,"id: ${args.itemiId}", Toast.LENGTH_SHORT).show()

    }
}

ItemMovieFragment - Layout : complete code

  <androidx.cardview.widget.CardView
            android:id="@+id/poster"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="32dp"
            app:cardCornerRadius="4dp"
            app:cardElevation="10dp"
            app:cardMaxElevation="10dp"
            app:layout_constraintBottom_toTopOf="@+id/scrollView2"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="@+id/scrollView2">


            <ImageView
                android:id="@+id/image_poster"
                android:layout_width="120dp"
                android:layout_height="170dp"
                android:layout_margin="0dp"
                android:padding="0dp"
                android:scaleType="centerCrop"
                app:imageUrl="@{itemMovieViewModel.movieInf.posterPath}"
                app:srcCompat="@drawable/stp" />

        </androidx.cardview.widget.CardView>

CompletedFragment : complete code

       class CompletedFragment(private var type : String) : Fragment() {
    
    
        //firebase
        private lateinit var firebaseDatabase: FirebaseDatabase
        private lateinit var dbReference: DatabaseReference
        private lateinit var firebaseAdapter: FirebaseRVAdapter
        private lateinit var auth: FirebaseAuth
    
        override fun onCreateView(
            inflater: LayoutInflater,
            container: ViewGroup?,
            savedInstanceState: Bundle?
        ): View? {
            val binding = FragmentCompletedBinding.inflate(inflater)
    
    
    
    
    // rest of the code...
    
    
    
            firebaseAdapter = FirebaseRVAdapter(FirebaseRVAdapter.ItemClickListener { item ->
    
                val id : Int = item.id!!.toInt()
                val extras = FragmentNavigatorExtras(
                    poster to item.id!!
                )
    
                if(type == TV)
                findNavController().navigate(MyWatchlistFragmentDirections.actionGlobalItemTvFragment(id))
               else
                findNavController().navigate(MyWatchlistFragmentDirections.actionMyWatchlistFragmentToItemMovieFragment(id),extras)  // this is the navigation line for shared animation
    
            }, optionss)
    
            binding.myfirebaseList.adapter = firebaseAdapter
    
            return binding.root
        }
//rest of the code
}

FirebaseRVAdapter :

 package com.utkarsh.fxn.ui.mywatchlist


class FirebaseRVAdapter(private val clickListener: ItemClickListener , options: FirebaseRecyclerOptions<TvFirebase>)
    : FirebaseRecyclerAdapter<TvFirebase, FirebaseRVAdapter.tvFirebaseViewHolder>(options) {
    class tvFirebaseViewHolder ( private var binding: MywatchlistListItemBinding) : RecyclerView.ViewHolder(binding.root) {


        fun bind(
            tvfirebase: TvFirebase,
            clickListener: ItemClickListener
        ){
            ViewCompat.setTransitionName(binding.poster,tvfirebase.id)  //setting transition name
            binding.tvFirebase=tvfirebase
            binding.clickListener=clickListener
        }

    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): tvFirebaseViewHolder {
        return tvFirebaseViewHolder(MywatchlistListItemBinding.inflate(LayoutInflater.from(parent.context)))
    }

    override fun onBindViewHolder(holder: tvFirebaseViewHolder, position: Int, model: TvFirebase) {
        return holder.bind(model!!,clickListener)
    }

    class ItemClickListener(val listener : (tvfirebase: TvFirebase) -> Unit){

        fun OnClick(tvfirebase: TvFirebase) = listener(tvfirebase)
    }


}

XML of image of item of Completed Fragment : complete file

<ImageView
            android:id="@+id/poster"
            android:layout_width="114dp"
            android:layout_height="170dp"
            android:layout_marginStart="4dp"
            android:layout_marginTop="4dp"
            android:layout_marginBottom="4dp"
            app:imageUrl="@{tvFirebase.poster_path}"
            android:scaleType="centerCrop"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_bias="0.013"
            tools:srcCompat="@drawable/smol" />
1

There are 1 answers

0
Vishal Pawar On

You must have same transitionName for item and details screen.

<ImageView
            android:id="@+id/poster"
            android:layout_width="114dp"
            android:layout_height="170dp"
            android:layout_marginStart="4dp"
            android:layout_marginTop="4dp"
            android:layout_marginBottom="4dp"
            android:transitionName="image_poster"
            app:imageUrl="@{tvFirebase.poster_path}"
            android:scaleType="centerCrop"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_bias="0.013"
            tools:srcCompat="@drawable/smol" />