【问题标题】:Activity transition when data changes数据变化时的活动过渡
【发布时间】:2017-07-21 17:34:27
【问题描述】:
我有图像适配器,其中每个项目都是用户图像,单击它会打开一个带有所选用户图像的新活动,因此我将图像标记为共享元素并使用活动转换。
我对第二个活动执行的部分操作会影响所有用户,因此适配器调用notifyDataSetChanged 并将位置重置为列表顶部。
当发生这种情况时,返回动画会混乱,当我关闭第二个活动并返回列表时,其中的数据已更改,因此图像被动画到错误的单元格。
我有两个问题:
- 如何将动画重新映射到正确的单元格?所有单元格都有相同的共享 ID...
- 如果我的用户在列表中不再可见,如何将返回动画替换为不同的动画?
【问题讨论】:
标签:
java
android
animation
android-animation
activity-transition
【解决方案1】:
如何将动画重新映射到正确的单元格?所有单元格都有相同的共享 ID。
在第一个活动中,您应该有一些键来指定启动第二个活动的项目。假设您有一个独特的userIds 和Users 的Map,即Map<Integer, User>。
- 当您启动第二个活动时,请在地图中传递此
User 的键,假设它是42。 (在地图42 -> John Doe 中,您正在为John Doe 启动第二个活动。
-
setExitSharedElementCallback() 在第一个活动中并覆盖 onMapSharedElements()。
override fun onMapSharedElements(names: MutableList<String>?,
sharedElements: MutableMap<String, View>?) {
// we will implement this in step 6
}
在第一个活动中覆盖 onActivityReenter() 并使用 supportPostponeEnterTransition() 推迟转换,以便在我们执行某些操作之前不显示转换(例如,我们想要滚动列表以显示项目)。
- 在
onActivityReenter() 中保存您从第二个活动通过Intent 传递的Bundle(我们将在第7 步中看到)。
- 在
onActivityReenter() 中推迟转换后,根据您添加到此捆绑包的信息对 UI 进行一些更改。特别是,在我们的例子中,这个包将包含启动第二个活动的User 的原始Integer 键。您可以通过此键在列表中找到User 的当前位置,并将RecyclerView 滚动到该新位置。使该项目可见后,您可以按下触发器并让系统通过supportStartPostponedEnterTransition() 开始过渡。
-
在SharedElementCallback::onMapSharedElements() 中检查天气,您在步骤4 中保存的Bundle 是否为空。如果它不为空,则意味着您在第二个活动中做了一些事情,并且您希望重新映射共享元素。这意味着您必须执行以下操作:
override fun onMapSharedElements(names: MutableList<String>?,
sharedElements: MutableMap<String, View>?) {
// `reenterBundle` is the `Bundle` you have saved in step 3
if (null != reenterBundle
&& reenterBundle!!.containsKey("KEY_FROM_ACTIVITY_2")
&& null != view) {
val key = reenterBundle!!.getInt("KEY_FROM_ACTIVITY_2");
val newSharedElement = ... // find corresponding view with the `key`
val newTransitionName = ... // transition name of the view
// clear previous mapping and add new one
names?.clear()
names?.add(newTransitionName)
sharedElements?.clear()
sharedElements?.put(newTransitionName, newSharedElement)
reenterBundle = null
} else {
// The activity is exiting
}
}
-
在第二个活动覆盖finishAfterTransition():
override fun finishAfterTransition() {
val data = Intent()
data.putExtra("KEY_FROM_ACTIVITY_2", 42) // `42` is the original position that we passed to this activity via Intent when launching it
setResult(RESULT_OK, data)
super.finishAfterTransition()
}
如果我的用户在列表中不再可见,如何将返回动画替换为不同的动画?
您可以使其可见(例如,通过滚动RecyclerView 使您的视图变得可见),或者您可以在步骤 6 中通过清除 names 和 sharedElements 而不是添加来删除共享元素转换任何东西。
我希望您已经了解了它的工作原理,尽管它看起来有点混乱。但作为对您的帮助,我可以分享一些我编写的应用程序的代码:
MainActivity - MainPresenter
DetailActivity