java - 数据更改时的 Activity 转换

标签 java android animation android-animation activity-transition

我有图像适配器,其中每个项目都是用户图像,单击它会打开一个包含所选用户图像的新 Activity ,因此我将图像标记为共享元素并使用 Activity 转换。

我对第二个 Activity 执行的部分操作会影响所有用户,因此适配器调用 notifyDataSetChanged 并将位置重置为列表顶部。

发生这种情况时,它会弄乱返回动画,当我关闭第二个 Activity 并返回到列表时,其中的数据已更改,因此图像会动画到错误的单元格。

我有两个问题:

  1. 如何将动画重新映射到正确的单元格?所有的单元格都有相同的共享 id...
  2. 如果我的用户不再出现在列表中,我该如何用不同的动画替换返回动画?

最佳答案

What can I do to remap the animation to the right cell? All the cells got the same shared id.

在第一个 Activity 中,您应该有一些键来指定启动第二个 Activity 的项目。假设您有一个 Map独特的userId s 和 User s,即 Map<Integer, User> .

  1. 启动第二个 Activity 时传递此 User map 中的键,假设它是 42 . (在 map 42 -> John Doe 中,您正在为 John Doe 启动第二个 Activity )。
  2. setExitSharedElementCallback() 在第一个 Activity 中覆盖 onMapSharedElements() .

    override fun onMapSharedElements(names: MutableList<String>?,
                                 sharedElements: MutableMap<String, View>?) {
        // we will implement this in step 6                            
    }
    
  3. 覆盖 onActivityReenter() 在第一个 Activity 中并使用 supportPostponeEnterTransition() 推迟过渡,以便在我们执行某些操作之前不显示过渡(例如,我们想要滚动列表以显示该项目)。

  4. onActivityReenter() 保存 Bundle你已经通过 Intent 从第二个 Activity 中通过了(我们将在第 7 步中看到)。
  5. onActivityReenter() 中推迟过渡之后根据您添加到此包中的信息对 UI 进行一些更改。特别是,在我们的例子中,这个包将包括原始的 Integer User 的关键启动第二个 Activity 。您可能会找到 User 的当前位置按此键在列表中,然后滚动 RecyclerView到那个新位置。使此项目可见后,您可以按下触发器并让系统通过 supportStartPostponedEnterTransition() 开始转换。 .
  6. SharedElementCallback::onMapSharedElements() 检查天气 Bundle您在步骤 4 中保存的是否为空。如果它不为空,则意味着您在第二个 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
        }                            
    }
    
  7. 在第二个 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 太多,以至于您的 View 变得可见),或者您可以通过清除 names 来删除步骤 6 中的共享元素过渡。和 sharedElements并且不向其中添加任何东西。

我希望你已经了解了它的工作原理,尽管它看起来有点困惑。但作为对您的帮助,我可以分享我编写的应用程序中的一些代码:

MainActivity - MainPresenter

DetailActivity

关于java - 数据更改时的 Activity 转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42509345/

相关文章:

android - 为 AS3 android Air App Flash cs6 创建扩展文件

javascript - 流畅的javascript动画

java - 如何在 Java 客户端中存储服务器密码以供以后重新连接?

java - jar.libs.dir 没有被正确覆盖吗?

java - println 的 Junit 测试

javascript - html 5 canvas javascript 下雨动画(如何高效轻松地实现!)

iphone - jQuery插件,类似iphone app页面滑动动画

java - 微调器的数组适配器保持错误

java - 将 HashMap 转换为数组

android - Android 中的流式 MIDI API