#android #kotlin #shared-element-transition
Вопрос:
Я пытаюсь сделать переход общего элемента между фрагментами из представления переработчика и не знаю, где я ошибаюсь.
В переходе ввода он вводится как обычная навигация по фрагментам. При обратном переходе он анимируется, но неправильно, и он всегда анимируется до последнего индекса представления переработчика.
Как я могу это исправить?
class HomeFragment : Fragment(R.layout.fragment_home) { private var _binding: FragmentHomeBinding? = null private val binding: FragmentHomeBinding get() = _binding!! private val viewModel: CloudViewModel by viewModel() override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { _binding = FragmentHomeBinding.inflate(inflater, container, false) return binding.root } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) val adapter = GridAdapter(cloudList, cloudListener) val recyclerView = binding.rvGrid recyclerView.adapter = adapter postponeEnterTransition() recyclerView.doOnPreDraw { startPostponedEnterTransition() } } private val cloudListener = GridAdapter.CloudListener { cloud, image -> val directions = HomeFragmentDirections.actionHomeFragmentToCloudDetailsFragment(cloud) val extras = FragmentNavigatorExtras( image to "image_big", ) findNavController().navigate( directions, extras ) } }
class CloudDetailsFragment : Fragment(R.layout.fragment_cloud_details) { private var _binding: FragmentCloudDetailsBinding? = null private val binding: FragmentCloudDetailsBinding get() = _binding!! val args: CloudDetailsFragmentArgs by navArgs() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val animation = TransitionInflater.from(requireContext()).inflateTransition( android.R.transition.move ) sharedElementEnterTransition = animation sharedElementReturnTransition = animation } override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { _binding = FragmentCloudDetailsBinding.inflate(inflater, container, false) return binding.root } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) val cloudName = binding.textDetails cloudName.text = args.cloud.cloudName val cloudImage = binding.imageDetails Glide .with(this) .load(args.cloud.cloudImage) .centerCrop() .placeholder(R.drawable.ic_stat_name) .into(cloudImage) } }
class GridAdapter( private val cloudList: List<Cloud>, private val clickListener: CloudListener ) : RecyclerView.Adapter<GridAdapter.ViewHolder>() { class ViewHolder(view: View) : RecyclerView.ViewHolder(view) { private val image: ImageView = view.findViewById(R.id.image_grid)!! private val text: TextView = view.findViewById(R.id.text_grid) fun bind( item: Cloud, clickListener: CloudListener ) { fun ImageView.load(imageAddress: String) { Glide.with(this) .load(imageAddress) .centerCrop() .placeholder(R.drawable.ic_stat_name) .into(this) } image.load(item.cloudImage!!) text.text = item.cloudName itemView.setOnClickListener { clickListener.onClick(item, image) } } } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { return ViewHolder( LayoutInflater.from(parent.context).inflate( R.layout.grid_adapter, parent, false ) ) } override fun onBindViewHolder(holder: ViewHolder, position: Int) { val item = cloudList[position] holder.bind(item, clickListener) } override fun getItemCount(): Int { return cloudList.size } class CloudListener(val clickListener: (cloud: Cloud, image: ImageView) -> Unit) { fun onClick( cloud: Cloud, image: ImageView ) = clickListener(cloud, image) } }
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout 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" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="16dp"> <ImageView android:id="@ id/imageView" android:layout_width="112dp" android:layout_height="112dp" android:src="@drawable/iag_logo" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <TextView android:id="@ id/textView" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="8dp" android:text="Cloud Identifier" android:textSize="48sp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toEndOf="@ id/imageView" app:layout_constraintTop_toTopOf="parent" /> <androidx.recyclerview.widget.RecyclerView android:id="@ id/rv_grid" android:layout_width="match_parent" android:layout_height="0dp" android:orientation="vertical" app:layoutManager="androidx.recyclerview.widget.GridLayoutManager" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@ id/textView" app:spanCount="2" tools:listitem="@layout/grid_adapter" /> </androidx.constraintlayout.widget.ConstraintLayout>
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent"> <ImageView android:id="@ id/image_details" android:layout_width="match_parent" android:layout_height="400dp" android:transitionName="image_big" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <TextView android:id="@ id/text_details" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="16dp" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@ id/image_details" /> </androidx.constraintlayout.widget.ConstraintLayout>