android - 5秒后Android返回过渡不起作用
问题描述
使用 AndroidX 导航组件,我在两个片段之间创建了共享元素转换。第一个片段有一个 RecyclerView,第二个片段显示点击元素的详细信息。enter 转换总是按预期工作。如果我立即按下后退按钮,则返回过渡有效。但是,如果我在点击后退按钮之前等待超过 5 秒,动画将无法正常工作。
在那种情况下,根本没有动画。没有移动,没有褪色,片段中的一切都立即出现在原地。
这是主要片段中的导航代码:
override fun onClick(deck: SlideDeck, sourceView: View) {
viewModel.activeDeck = deck
val extras = FragmentNavigatorExtras(sourceView to "deck_details")
findNavController().navigate(
R.id.action_deckListFragment2_to_deckDetailsFragment,
null,
null,
extras
)
}
这是在第二个片段中设置共享元素转换的代码:
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val animation = TransitionInflater.from(requireContext()).inflateTransition(
android.R.transition.move
)
sharedElementEnterTransition = animation
sharedElementReturnTransition = animation
binding = FragmentDeckDetailsBinding.inflate(inflater, container, false)
return binding.root
}
最后,回到主片段,我不得不推迟进入转换:
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
binding = FragmentDeckListBinding.inflate(inflater, container, false)
postponeEnterTransition()
binding.root.doOnPreDraw {
startPostponedEnterTransition()
}
return binding.root
}
我还必须确保 RecyclerView 中的每个元素都有一个唯一且一致的 transitionName ,如下所示:
<androidx.cardview.widget.CardView
android:id="@+id/deckDetailsCard"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:layout_marginBottom="0dp"
android:layout_marginLeft="4dp"
android:layout_marginRight="4dp"
app:cardCornerRadius="4dp"
android:transitionName="@{String.format(@string/transition_name_string, deck.id)}"
android:onClick="@{() -> itemClickListener.onClick(deck, deckDetailsCard)}">
...
</androidx.cardview.widget.CardView>
同样,这一切都按预期进行,除非我在返回主片段之前等待超过约 5 秒。我已经在 2 个仿真器(SDK 21 和 28)和一个物理设备(Galaxy S10E)上对此进行了测试。都表现出相同的行为。
解决方案
我想到了。问题出在主要片段中onViewCreated
:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val deckObserver = Observer<List<SlideDeck>> { deckList ->
val listener: DeckListOnItemClickListener = this
val deckListAdapter = DeckListAdapter(requireContext(), deckList,
listener)
deckListAdapter.dataSet = deckList
binding.deckRecyclerView.adapter = deckListAdapter
deckListAdapter.notifyDataSetChanged()
}
viewModel.deckList.observe(viewLifecycleOwner, deckObserver)
}
你看到了吗?
在收到来自 ViewModel 的更改通知之前,我没有为 RecyclerView 创建适配器。我认为问题在于 RecyclerView 直到动画运行后才设置适配器。
所以我将适配器设置为 Fragment 的成员,adapter
直接在 中设置 RecyclerView 的成员onViewCreated
,然后在观察到更改时更新适配器的列表。这似乎已经解决了它。
推荐阅读
- elasticsearch - 如何从 AppSync 解析器执行批量 ElasticSearch 操作?
- c - VS2019 - stdbool.h 包含在被 stdio.h 包围时被禁用包含
- arrays - 就执行时间而言,哪个函数更快?贝塔()还是阿尔法()?
- c++ - 示例代码:如何将宽度固定为不等于 0?
- go - 无限for循环内的goroutine。这是一个好习惯吗?
- asynchronous - Tornado 异步端点不起作用
- wcf - 如何执行 ssl 用户身份验证
- android - 如何实现谷歌登录
- android - Android - 为什么我需要完整的活动名称才能访问我的可绘制对象和 XML 文件?
- c# - 在 Asp.Net Core 5 Identity 中未调用自定义 UserConfirmation