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

Posted

技术标签:

【中文标题】共享元素转换:活动到嵌套在另一个活动中的片段【英文标题】:Shared element transition : activity into fragment nested in another activity 【发布时间】:2016-11-30 11:57:58 【问题描述】:

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

场景是用户点击图像缩略图,然后打开另一个全屏图像视图的活动。

如果共享视图直接托管在目标 Activity 的布局中,这可以正常工作。适用于进入/退出动画。 但是,当我试图在目标活动中嵌套片段中实现类似的效果时,这种方法不起作用。有趣的是没有显示进入动画,但退出动画工作正常。

另一个更复杂的视图层次结构是,如果目标视图 (ImageView) 托管在视图分页器中,而分页器托管在目标活动的框架布局中。

有人有同样的问题吗?

编辑: 我的点击监听代码

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);
    

  


【问题讨论】:

【参考方案1】:

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

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

解决方案很简单。首先你可以试试FragmentManager.executePendingTransactions()。那可能还不够。过渡框架还有另一种解决方案:

在ActivitypostponeEnterTransition()的onCreate中。这告诉框架等到你告诉它创建动画是安全的。这确实意味着您需要在某个时候告诉它它是安全的(通过调用startPostponedEnterTransition())。在您的情况下,这可能在 Fragments onCreateView 中。

下面是一个示例:

活动 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。

【讨论】:

您也可以在不添加 OnPreDrawObserver 的情况下实现此目的。只需覆盖片段中的 onViewCreated 并在其中调用 startPostponedEnterTransition() 完美简洁的解释。谢谢 @Daveloper87 这取决于共享视图的性质。如果它在 xml 中静态膨胀,您的建议应该有效。如果它需要一个长时间运行的任务来设置它,或者如果它以编程方式添加到根目录,则需要 OnPreDetawListener

以上是关于共享元素转换:活动到嵌套在另一个活动中的片段的主要内容,如果未能解决你的问题,请参考以下文章

不同活动的片段之间的共享元素转换

不同活动的片段之间的共享元素转换

跨活动的片段之间的共享元素转换不一致

共享元素转换在父片段和子片段之间不起作用(嵌套片段)

视图之间的共享元素转换(不是活动或片段)

片段转换:共享元素