【问题标题】:Activity transition when data changes数据变化时的活动过渡
【发布时间】:2017-07-21 17:34:27
【问题描述】:

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

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

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

我有两个问题:

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

【问题讨论】:

    标签: java android animation android-animation activity-transition


    【解决方案1】:

    如何将动画重新映射到正确的单元格?所有单元格都有相同的共享 ID。

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

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

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

    4. onActivityReenter() 中保存您从第二个活动通过Intent 传递的Bundle(我们将在第7 步中看到)。
    5. onActivityReenter() 中推迟转换后,根据您添加到此捆绑包的信息对 UI 进行一些更改。特别是,在我们的例子中,这个包将包含启动第二个活动的User 的原始Integer 键。您可以通过此键在列表中找到User 的当前位置,并将RecyclerView 滚动到该新位置。使该项目可见后,您可以按下触发器并让系统通过supportStartPostponedEnterTransition() 开始过渡。
    6. 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
          }                            
      }
      
    7. 在第二个活动覆盖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 中通过清除 namessharedElements 而不是添加来删除共享元素转换任何东西。

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

    MainActivity - MainPresenter

    DetailActivity

    【讨论】:

      猜你喜欢
      • 2018-12-12
      • 1970-01-01
      • 2011-05-05
      • 1970-01-01
      • 1970-01-01
      • 2019-07-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多