Activity 数据变化时的转换
Activity transition when data changes
我得到了图像适配器,其中每个项目都是用户图像,单击它会打开一个新的 activity 和选定的用户图像,所以我将图像标记为共享元素并使用 activity 转换。
我在第二个 activity 上执行的部分操作会影响所有用户,因此适配器调用 notifyDataSetChanged
并将位置重置为列表顶部。
发生这种情况时,它会弄乱 return 动画,当我将第二个 activity 和 return 关闭到列表中时,其中的数据已更改,因此图像动画化为单元格错误。
我有两个问题:
- 如何将动画重新映射到正确的单元格?所有单元格都有相同的共享 ID...
- 如果我的用户不再出现在列表中,我该如何用不同的动画替换 return 动画?
What can I do to remap the animation to the right cell? All the cells got the same shared id.
在第一个 activity 中,您应该有一些键来指定第二个 activity 启动的项目。假设您有 Map
个独特的 userId
和 User
,即 Map<Integer, User>
.
- 当您启动第二个 activity 时,在地图中传递这个
User
的键,假设它是 42
。 (在地图 42 -> John Doe
中,您正在为 John Doe
发射第二个 activity。
setExitSharedElementCallback()
在第一个 activity 中覆盖 onMapSharedElements()
.
override fun onMapSharedElements(names: MutableList<String>?,
sharedElements: MutableMap<String, View>?) {
// we will implement this in step 6
}
覆盖 onActivityReenter()
in first activity and postpone transition with supportPostponeEnterTransition()
,以便在我们执行某些操作之前不显示转换(例如,我们想要滚动列表以显示项目)。
- 在
onActivityReenter()
中保存你从第二个activity通过Intent
传递的Bundle
(我们将在第7步中看到)。
- 在
onActivityReenter()
中推迟过渡后,根据您添加到此捆绑包中的信息对 UI 进行一些更改。特别是,在我们的例子中,这个包将包含 User
的原始 Integer
密钥,它启动了第二个 activity。您可以通过此键找到 User
在列表中的当前位置,然后滚动 RecyclerView
到该新位置。使此项目可见后,您可以按下触发器并让系统通过 supportStartPostponedEnterTransition()
. 开始转换
在SharedElementCallback::onMapSharedElements()
中检查你在第4步中保存的Bundle
是否为空。如果它不为空,则意味着您在秒 activity 中做了一些事情并且您希望重新映射共享元素。这意味着你必须做这样的事情:
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
}
}
秒activity覆盖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()
}
In case that my user is no longer visible on the list, how can I replace the return animation with different animation?
您可以使其可见(例如,通过滚动 RecyclerView
太多,您的视图变得可见),或者您可以通过清除 names
和sharedElements
并且不向其中添加任何内容。
我希望你已经了解了它的工作原理,尽管它看起来有点混乱。但作为对您的帮助,我可以分享我编写的应用程序中的一些代码:
我得到了图像适配器,其中每个项目都是用户图像,单击它会打开一个新的 activity 和选定的用户图像,所以我将图像标记为共享元素并使用 activity 转换。
我在第二个 activity 上执行的部分操作会影响所有用户,因此适配器调用 notifyDataSetChanged
并将位置重置为列表顶部。
发生这种情况时,它会弄乱 return 动画,当我将第二个 activity 和 return 关闭到列表中时,其中的数据已更改,因此图像动画化为单元格错误。
我有两个问题:
- 如何将动画重新映射到正确的单元格?所有单元格都有相同的共享 ID...
- 如果我的用户不再出现在列表中,我该如何用不同的动画替换 return 动画?
What can I do to remap the animation to the right cell? All the cells got the same shared id.
在第一个 activity 中,您应该有一些键来指定第二个 activity 启动的项目。假设您有 Map
个独特的 userId
和 User
,即 Map<Integer, User>
.
- 当您启动第二个 activity 时,在地图中传递这个
User
的键,假设它是42
。 (在地图42 -> John Doe
中,您正在为John Doe
发射第二个 activity。 setExitSharedElementCallback()
在第一个 activity 中覆盖onMapSharedElements()
.override fun onMapSharedElements(names: MutableList<String>?, sharedElements: MutableMap<String, View>?) { // we will implement this in step 6 }
覆盖
onActivityReenter()
in first activity and postpone transition withsupportPostponeEnterTransition()
,以便在我们执行某些操作之前不显示转换(例如,我们想要滚动列表以显示项目)。- 在
onActivityReenter()
中保存你从第二个activity通过Intent
传递的Bundle
(我们将在第7步中看到)。 - 在
onActivityReenter()
中推迟过渡后,根据您添加到此捆绑包中的信息对 UI 进行一些更改。特别是,在我们的例子中,这个包将包含User
的原始Integer
密钥,它启动了第二个 activity。您可以通过此键找到User
在列表中的当前位置,然后滚动RecyclerView
到该新位置。使此项目可见后,您可以按下触发器并让系统通过supportStartPostponedEnterTransition()
. 开始转换
在
SharedElementCallback::onMapSharedElements()
中检查你在第4步中保存的Bundle
是否为空。如果它不为空,则意味着您在秒 activity 中做了一些事情并且您希望重新映射共享元素。这意味着你必须做这样的事情: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 } }
秒activity覆盖
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() }
In case that my user is no longer visible on the list, how can I replace the return animation with different animation?
您可以使其可见(例如,通过滚动 RecyclerView
太多,您的视图变得可见),或者您可以通过清除 names
和sharedElements
并且不向其中添加任何内容。
我希望你已经了解了它的工作原理,尽管它看起来有点混乱。但作为对您的帮助,我可以分享我编写的应用程序中的一些代码: