共享元素转换:activity 到嵌套在另一个 activity 中的片段

Shared element transition : activity into fragment nested in another activity

我正在尝试将共享元素转换添加到我的应用程序中。

场景是用户单击图像缩略图,然后打开另一个 activity 全屏图像视图。

如果共享视图直接托管在目标 activity 的布局中,则此方法工作正常。 enter/exit 动画效果流畅。 但是当我试图在 fragment 中实现类似的效果时 nested in target activity 这种方法 doesn没用。有趣的是没有显示进入动画,但退出动画工作正常。

另一个更复杂的视图层次结构是,如果目标视图 (ImageView) 托管在视图寻呼机中,而视图寻呼机托管在目标 activity 的框架布局中。

有人遇到同样的问题吗?

编辑: 我的点击监听代码

public class OnClickPicture extends OnClickBase {
  private ObjectPicture object;

  public OnClickPicture(Activity_Parent activity, ObjectPicture object) {
    super(activity);
    this.object = object;
  }

  public void onClick(View v) {

    picasso.load(object.getFullUrl()).fetch();
    Intent intent = new Intent(activity, ActivityPicture.class);
    intent.putExtra("picture_object", helper.gson.toJson(object));

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && v != null) {
      Pair<View, String> p1 = Pair.create(v, "image");
      ActivityOptionsCompat options = ActivityOptionsCompat.makeSceneTransitionAnimation(activity, p1);
      activity.startActivity(intent, options.toBundle());
    } else {
      activity.startActivity(intent);
    }

  }

}

转换工作的方式需要在任何动画发生之前创建、测量和布局新的 Activity。这样它就可以找到您想要设置动画的视图并创建适当的动画。

在您的情况下,这不会发生,因为 stated in the docs,FragmentTransaction.commit() 所做的只是安排要完成的工作。它不会立即发生。因此,当框架创建您的 Activity 时,它无法找到您想要设置动画的视图。这就是为什么您看不到进入动画但看到退出动画的原因。当您离开 activity.

时,视图就在那里

解决方法很简单。首先你可以试试FragmentManager.executePendingTransactions()。这可能还不够。 transitions framework 有另一种解决方案:

在 Activity postponeEnterTransition(). This tells the framework to wait until you tell it that its safe to create the animation. That does mean that you need to tell it that its safe (via calling startPostponedEnterTransition()) 的 onCreate 中的某个时刻。在您的情况下,可能会在 Fragments onCreateView 中。

下面是一个示例:

Activity B

@Override
protected void onCreate(Bundle savedInstanceState) {
    // etc
    postponeEnterTransition();
}

片段 B

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View sharedView = root.findViewById(R.id.shared_view);
    sharedview.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
        @Override
        public boolean onPreDraw() {
            sharedview.getViewTreeObserver().removeOnPreDrawListener(this);
            getActivity().startPostponedEnterTransition();
            return true;
        }
    });
}

感谢 Alex Lockwood 的 detailed blog posts about the Transitions framework