两个RecyclerView之间的活动转换

4

我从一个带有GridLayoutRecyclerView动画到另一个RecyclerView。它像一个画廊展示图片。

父级RecyclerView显示文件夹的前3个元素,子级RecyclerView以网格形式显示完整内容...

主适配器

@Override
public void onBindViewHolder(FolderViewHolder holder, int position) {
    holder.transitionPairs.clear();
    for (int i = 0; i < 3; i++) {
        ImageView iv = holder.getIconView(i);
        Image image = mItems.get(position).getImages().get(i);
        holder.transitionPairs.add(new Pair(iv, image.getTransitionName()));
    }

child adapter

@Override
public void onBindViewHolder(ImageViewHolder holder, int position) {

    ViewCompat.setTransitionName(holder.icon, mItems.get(position).getTransitionName());
}
  • 两个适配器设置相同的转换名称,它是从图像URI生成的,因此一定是唯一的

我按照以下方式启动子视图:

Intent intent = new Intent(getActivity(), ImagesActivity.class);
        intent.putExtra("folderIndex", pos);
        intent.putExtra("folder", item);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
            ActivityOptionsCompat options = ActivityOptionsCompat.makeSceneTransitionAnimation(getActivity(), vh.getTransitionPairs().toArray(new Pair[vh.getTransitionPairs().size()]));
            getActivity().startActivity(intent, options.toBundle());
        }
       else
            getActivity().startActivity(intent);

转换对在ViewHolder中保存,并且在每次绑定ViewHolder时生成,正如您可以在上面的ViewHolders代码中看到的那样。 问题 子视图的显示没有动画效果,返回时有动画效果...
2个回答

4
抱歉,但这是过渡框架的已记录限制。

https://developer.android.com/intl/es/training/transitions/overview.html#Limitations

限制

这一部分列出了转换框架的一些已知限制: - 扩展AdapterView(如ListView)的类以不兼容转换框架的方式管理其子视图。如果您尝试基于AdapterView动画化视图,则设备显示可能会挂起。

我知道它指的是ListView,但对于RecyclerView也是一样的。动画框架必须在视图布局完成后立即捕获transitionName值,而ListViewRecyclerView需要额外的时间来获取适配器、创建子视图、将这些子视图布局到屏幕上,然后将它们绑定到数据。转换框架无法“看到”这些视图。

我最好的建议是,在实际活动中展开您的适配器的“虚假”项,仅用于过渡运行,然后在onStart时将此视图设置为GONE

编辑:

根据OP提供的链接(使用带有ViewPager的Android 5.0 Activity过渡遇到问题),我已经开发了自己的非常相似的解决方案。

在我的项目中,我使用了GridLayoutManager,每屏大约有7个元素,并且动画效果是LinearLayoutManager,每个视图中通常只有1个元素(但有时可以看到前一个或后一个元素的角落)。
在链接的响应中,解决方案是使用Activity.postponeEnterTransition()Activity.startPostponedEnterTransition()以及OnPreDrawListener来正确传递所有转换。
重要的事实要记住的是,为了使转换框架捕获视图,该视图必须附加到窗口。因此,我使用OnAttachStateChangeListener来分派转换,而不是OnPreDraw。这应该使它成为一个微妙平滑的过渡。
// somewhere on the `onBind` code I put that
itemView.addOnAttachStateChangeListener(listener);

// and this is the listener
private final View.OnAttachStateChangeListener listener = new View.OnAttachStateChangeListener() {
         @Override public void onViewAttachedToWindow(View v) {
            activity.startPostponedEnterTransition();
            v.removeOnAttachStateChangeListener(this);
         }

         @Override public void onViewDetachedFromWindow(View v) {
            v.removeOnAttachStateChangeListener(this);
         }
      };

对我来说工作得很好。


不知道呢,谢谢提供信息。实际上,在这种情况下,我将坚持仅对后退转换进行动画处理,并暂时忘记显示动画...虽然在详细视图上构建第一个视图不需要太多工作...目前只是一个小美化问题,如果不支持也可以接受。 - prom85
只有一件事,这对于ViewPager也应该有效,不是吗? - prom85
我从未测试过,但我相信ViewPager会有同样的问题。 - Budius
1
实际上,我刚找到了一种推迟转换的方法...这使得使用viewpager和RecyclerView也成为可能。 - prom85
1
这个线程展示了如何使用Android 5.0的Activity转场,但是对于我来说,由于我在CoordinatorLayout中使用RecyclerView,它目前并不完美。 - prom85
显示剩余5条评论

0

1 - 确保您的RecyclerView已经正确地填充了视图。

2 - 使用setEnterSharedElementCallback添加一个SharedElementCallback,并覆盖“onMapSharedElements”方法。

3 - 将缺失的视图添加到sharedElements映射中(从适配器或RecyclerView直接获取它们)。

    setEnterSharedElementCallback(new SharedElementCallback() {
        @Override
        public void onMapSharedElements(List<String> names, Map<String, View> sharedElements) {
            sharedElements.put("bla", recyclerView.findViewWithTag("bla"));
            super.onMapSharedElements(names, sharedElements);
        }
    });

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