android - 如何使用 Android 导航组件实现从 RecyclerView 项目到 Fragment 的共享过渡元素?
问题描述
我有一个非常简单的案例。我想在recyclerView
和中的项目之间实现共享元素转换fragment
。我在我的应用程序中使用 android 导航组件。
在developer.android上有一篇关于共享转换的文章和关于stackoverflow的主题,但此解决方案仅适用于位于fragment
开始转换的布局中的视图,不适用于RecyclerView
. github上也有一个库,但我不想依赖 3rd 方库并自己做。
有什么解决办法吗?也许它应该工作,这只是一个错误?但是我没有找到任何关于它的信息。
代码示例:
过渡开始
class TransitionStartFragment: Fragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_transition_start, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val testData = listOf("one", "two", "three")
val adapter = TestAdapter(testData, View.OnClickListener { transitionWithTextViewInRecyclerViewItem(it) })
val recyclerView = view.findViewById<RecyclerView>(R.id.test_list)
recyclerView.adapter = adapter
val button = view.findViewById<Button>(R.id.open_transition_end_fragment)
button.setOnClickListener { transitionWithTextViewInFragment() }
}
private fun transitionWithTextViewInFragment(){
val destination = TransitionStartFragmentDirections.openTransitionEndFragment()
val extras = FragmentNavigatorExtras(transition_start_text to "transitionTextEnd")
findNavController().navigate(destination, extras)
}
private fun transitionWithTextViewInRecyclerViewItem(view: View){
val destination = TransitionStartFragmentDirections.openTransitionEndFragment()
val extras = FragmentNavigatorExtras(view to "transitionTextEnd")
findNavController().navigate(destination, extras)
}
}
布局
<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"
android:orientation="vertical">
<TextView
android:id="@+id/transition_start_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="transition"
android:transitionName="transitionTextStart"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/open_transition_end_fragment"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@id/transition_start_text"
android:text="open transition end fragment" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/test_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@id/open_transition_end_fragment"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
recyclerView 的适配器
class TestAdapter(
private val items: List<String>,
private val onItemClickListener: View.OnClickListener
) : RecyclerView.Adapter<TestAdapter.ViewHodler>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHodler {
return ViewHodler(LayoutInflater.from(parent.context).inflate(R.layout.item_test, parent, false))
}
override fun getItemCount(): Int {
return items.size
}
override fun onBindViewHolder(holder: ViewHodler, position: Int) {
val item = items[position]
holder.transitionText.text = item
holder.itemView.setOnClickListener { onItemClickListener.onClick(holder.transitionText) }
}
class ViewHodler(itemView: View) : RecyclerView.ViewHolder(itemView) {
val transitionText = itemView.findViewById<TextView>(R.id.item_test_text)
}
}
在 onItemClick 我通过 recyclerView 中的 textView 表单项进行转换
过渡结束
class TransitionEndFragment : Fragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
setUpTransition()
return inflater.inflate(R.layout.fragment_transition_end, container, false)
}
private fun setUpTransition(){
sharedElementEnterTransition = TransitionInflater.from(context).inflateTransition(android.R.transition.move)
}
}
布局
<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:orientation="vertical">
<TextView
android:id="@+id/transition_end_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="transition"
android:transitionName="transitionTextEnd"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
有趣的 transitionWithTextViewInFragment() - 有过渡。
有趣的 transitionWithTextViewInRecyclerViewItem(view: View) - 没有过渡。
解决方案
要解决返回转换问题,您需要在初始化回收器视图的源片段(具有回收器视图的片段)上添加此行
// your recyclerView
recyclerView.apply {
...
adapter = myAdapter
postponeEnterTransition()
viewTreeObserver
.addOnPreDrawListener {
startPostponedEnterTransition()
true
}
}
推荐阅读
- vue.js - 如何使用 vue.js 和 window.getSelection()?
- xpath - 使用 XPath Google 表格 importxml 函数从字典中获取单词的含义
- python-3.x - 使用条件打印数据帧的索引
- mongodb - 为什么wekan对mongodb的调用无法连接?
- python - 如何在python中更改文件的所有者
- apache-spark - Structure Streaming 和 Stateful Streaming 中静态数据的周期性刷新
- scala - 为什么scalac在重载'andThen'时会混淆我的SAM类型没有实现Function?
- pyinstaller - 有关使 pyinstaller 编译使用 sympy 的 python 文件的任何更新?
- typescript - EntityMetadataNotFound:找不到“BusinessApplication”的元数据
- php - 切换后PHP变量不可用