RecyclerView中的共享元素过渡 - Android

4
我想让共享元素过渡与recycler view内部的元素一起工作。当用户单击recycler view项中的textview时,会打开详细活动。在详细活动中,我显示了一些信息,并且我还有一个选项卡布局,使用picasso从url加载一些图像。详细活动的转换正在工作,但是如果用户在加载所有图像之前返回到主活动,则主活动中的recycler view将在反向动画后消失!禁用共享元素转换后,问题消失了。
两个活动都使用片段进行操作。因此,我正在尝试在不同活动中创建两个片段之间的转换。
在RecyclerViewAdapter中,我设置了转换名称:
public void onBindViewHolder(final ViewHolder viewHolder, int position) {
  ... 
 viewHolder.profileImage.setTransitionName("profile"+position);

我的TextView的onClickListener(在MainActivity的一个fragment中):

Intent i = new Intent(getCurrentActivity(), DetailActivity.class);
        ActivityOptionsCompat options = ActivityOptionsCompat.
               makeSceneTransitionAnimation(getCurrentActivity(), (View) profileImage, "profile"+position);
        getCurrentActivity().startActivity(i, options.toBundle());

在具有共享元素的 Detail Activity 片段中(在 onCreateView 中):
profileImage.setTransitionName("profile"+position);

当Intent发生时,我已经检查过两个活动中的转换名称,并且它们是相同的。

我已经被这个问题困扰了两天,不知道出了什么问题。如果您需要更多有关此问题的信息或代码,请随时询问。

谢谢!


我不知道这是否重要,但是这两个活动(主活动和详细活动)都有片段,因此从主活动的片段调用到详细活动的意图,并且第二个活动的setTransitionName()在其片段的onCreateView()中被调用。 - G_comp
当然你会遇到这个问题。Picasso是在后台进行异步调用的,如果它的任务还没有完成,你就切换到另一个活动,也就是你的MainActivity。来自Picasso的异步调用将被暂停。@G_comp. 我觉得他没有使用片段,因为你在FragmentTransactions上设置了过渡效果。 - Aizen
这不是 Picasso 的问题,只是 Picasso 也会停止它的调用。主要问题在于转换。您故意停止 MainActivity 进程并转到 Detail,因此当您返回到 Main 时,它是不完整的。您需要使用适当的 Fragment 处理。不要让 MainActivity 关闭其进程,当有人点击它时。您只需要获取片段事务并添加详细信息活动,这样就可以避免停止主活动。Intent i = new Intent(getCurrentActivity(), DetailActivity.class) 不会创建片段。 - Aizen
当您创建一个Intent时,创建Intent的Activity仍在运行。然而,当您调用startActivity时,当前Activity将被停止并替换为另一个Activity。在Fragments中,它们将同时运行,因为它们是由FragmentManager持有的Activity的一部分。希望您能理解我的意思。 - Aizen
是的,我理解。但我正在尝试在两个活动之间创建一个过渡(它们都有片段)。在主活动片段中,我使用带有过渡到详细活动的意图进行调用。然后,在详细活动片段中处理它(其中包含共享元素)。 - G_comp
显示剩余4条评论
1个回答

8
问题在于共享元素转换是由框架在Activity生命周期的早期启动的。转换必须捕获其目标视图的起始和结束状态,以构建一个正常运行的动画。因此,如果框架在共享元素在被调用的Activity中得到最终大小和位置之前启动共享元素转换,则转换将捕获其共享元素的不正确的结束值,并且结果动画将完全失败。

如果共享元素依赖于异步加载的数据,例如AsyncTask、AsyncQueryHandler、Loader或类似的东西,在它们在被调用的活动中的最终外观可以确定之前,框架可能会在该数据传递回主线程之前启动转换。
因此,解决方案如下:
  1. 在被调用的Activity的onCreate()方法中调用postponeEnterTransition()。
  2. 当您确信所有共享元素已正确定位和调整大小时,请调用startPostponedEnterTransition()以恢复转换。您会发现有用的一个常见模式是在OnPreDrawListener中启动延迟的转换,在共享元素测量和布局完成后将被调用。

您使用Picasso,据我所知,Picasso有一个名为RequestCreator的回调函数,用于加载图片。 例如:

private final Callback callBack = new Callback() {
    @Override
    public void onSuccess() {
        imageView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
            @Override
            public boolean onPreDraw() {
                imageView.getViewTreeObserver().removeOnPreDrawListener(this);
                MainActivity.this.startPostponedEnterTransition();
                return true;
            }
        });
    }

    @Override
    public void onError() {

    }
};

RequestCreator requestCreator = Picasso.with(this).load(imageUrl);
requestCreator.into(imageView, callback);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接