Как правильно отобразить переход общего элемента из RecyclerView в ViewPager динамически? - PullRequest
0 голосов
/ 12 октября 2019

У меня есть действие, в котором находятся оба фрагмента: SourceFragment и DestinationFragment. SourceFragment содержит RecyclerView, а DestinationFragment содержит ViewPager. Я использовал менеджер фрагментов, чтобы переключаться между фрагментом «Источник» и «Место назначения».

Проблема:

Обратный переход работает нормально до тех пор, пока я не проведу по другомуПосмотреть на ViewPager. Чтобы решить эту проблему, я переопределил onMapSharedElements в DestinationFragment и SourceFragment, чтобы убедиться, что представления совпадают друг с другом, когда выполняется просмотр страницы. По какой-то причине смахивание и возврат к SourceFragment не работают и анимация перехода не происходит. Я даже отладил функции onMapSharedElements, чтобы убедиться, что представления отображаются правильно.

Это то, что я пытаюсь реализовать.

Моя реализация

Я предоставил приведенный ниже код для рассматриваемых фрагментов, но вот репо для моей реализации. Я целую неделю мучился, пытаясь понять это, надеюсь, я смогу понять, почему это происходит.

SourceFragment:

class SourceFragment : Fragment() {
private lateinit var sharedViewModel: SharedViewModel
private lateinit var itemRecyclerView: RecyclerView
private lateinit var adapter: SourceAdapter
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    setExitSharedElementCallback(object : SharedElementCallback() {
        override fun onMapSharedElements(names: MutableList<String>?, sharedElements: MutableMap<String, View>?) {
            val view = itemRecyclerView.findViewHolderForAdapterPosition(sharedViewModel.currentPos)
                ?.itemView?.findViewById<TextView>(R.id.source_text)
            val item = sharedViewModel.itemList[sharedViewModel.currentPos]
            if (view == null) return
            names?.clear()
            sharedElements?.clear()
            names?.add(item)
            sharedElements?.put(item, view)
        }
    })

    sharedViewModel = ViewModelProviders.of(requireActivity()).get(SharedViewModel::class.java)

    adapter = SourceAdapter(object : onClickItem {
        override fun onClick(position: Int, view: View) {
            // Save the position of the item that was clicked.
            sharedViewModel.currentPos = position

            // Setup shared element transition
            val transitionName = ViewCompat.getTransitionName(view) ?: ""

            // Start fragment transaction along with shared element transition.
            fragmentManager?.apply {
                beginTransaction()
                    .setReorderingAllowed(true)
                    .addSharedElement(view, transitionName)
                    .replace(
                        R.id.fragment_container,
                        DestinationFragment(),
                        DestinationFragment::class.java.simpleName
                    )
                    .addToBackStack(null)
                    .commit()
            }
        }
    })

    val list = sharedViewModel.itemList
    adapter.submitList(list)
}

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
    val view = inflater.inflate(R.layout.source_layout, container, false)
    postponeEnterTransition()
    return view
}

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

    // Setup recycler view here
    itemRecyclerView = item_recycler_view
    itemRecyclerView.layoutManager = GridLayoutManager(requireContext(), 2)
    itemRecyclerView.adapter = adapter

    // Start enter transition on pre draw.
    itemRecyclerView.viewTreeObserver.addOnPreDrawListener(object : ViewTreeObserver.OnPreDrawListener {
        override fun onPreDraw(): Boolean {
            itemRecyclerView.viewTreeObserver.removeOnPreDrawListener(this)
            startPostponedEnterTransition()
            return true
        }
    })

    // Scroll to the position of the item that was selected in the Destination Fragment.
    itemRecyclerView.addOnLayoutChangeListener { p0, p1, p2, p3, p4, p5, p6, p7, p8 ->
        val layoutMan = itemRecyclerView.layoutManager
        val viewAtPos = layoutMan?.findViewByPosition(sharedViewModel.currentPos)
        if (viewAtPos == null ||
            layoutMan.isViewPartiallyVisible(viewAtPos, false, true)
        ) {
            itemRecyclerView.post {
                layoutMan?.scrollToPosition(sharedViewModel.currentPos)
            }
        }
    }
}

DestinationFragment

class DestinationFragment : Fragment(), MainActivityListener {
lateinit var sharedViewModel: SharedViewModel
lateinit var destPager : ViewPager
lateinit var itemAdapter : ItemPagerAdapter
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    postponeEnterTransition()
    setEnterSharedElementCallback(object : androidx.core.app.SharedElementCallback(){
        override fun onMapSharedElements(names: MutableList<String>?, sharedElements: MutableMap<String, View>?) {
            val item = sharedViewModel.itemList[destPager.currentItem]
            val itemView = (itemAdapter.instantiateItem(destPager, destPager.currentItem) as Fragment).view?.findViewById<TextView>(R.id.item_fragment_textview) as View
            names?.clear()
            names?.add(item)
            sharedElements?.clear()
            sharedElements?.put(item, itemView)
        }
    })

    sharedElementEnterTransition = TransitionInflater.from(requireContext()).inflateTransition(android.R.transition.move)
    sharedViewModel = ViewModelProviders.of(requireActivity()).get( SharedViewModel::class.java)
}

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
    return inflater.inflate(R.layout.destination_layout, container ,false)
}

override fun onBackPressed(): Boolean {
    sharedViewModel.currentPos = destPager.currentItem
    return false
}

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

    destPager = destination_pager
    itemAdapter = ItemPagerAdapter(sharedViewModel.itemList, childFragmentManager)
    destination_pager.adapter = itemAdapter
    destination_pager.currentItem = sharedViewModel.currentPos
}
...