Activity 两个 RecyclerView 之间的过渡

Activity Transition between two RecyclerViews

我用 GridLayout 从一个 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()));
    }

子适配器

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

    ViewCompat.setTransitionName(holder.icon, mItems.get(position).getTransitionName());
}

我启动子视图如下:

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 代码中看到的那样

问题

显示子视图不是动画,返回是动画...

抱歉,这是转换框架的记录限制。

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

Limitations

This section lists some known limitations of the transitions framework: - Classes that extend AdapterView, such as ListView, manage their child views in ways that are incompatible with the transitions framework. If you try to animate a view based on AdapterView, the device display may hang.

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

我最好的建议是让适配器中的 "fake" 项目在实际 activity 布局上充气,只是为了过渡到 运行 上,然后 onStart您将此视图设置为 GONE.

编辑:

基于 OP (Having issues using Android 5.0 Activity transitions onto an activity with a ViewPager) 提供的 link,我已经结束了自己的开发,但非常相似的解决方案。

在我自己的项目中,我有一个 GridLayoutManager,每个屏幕大约有 7 个元素,并且动画化为一个 LinearLayoutManager,每个视图主要有 1 个(但有时您可以看到之前或之后的角)。

在 linked 响应中,解决方案是使用 Activity.postponeEnterTransition()Activity.startPostponedEnterTransition()OnPreDrawListener 来正确交付所有过渡。

要记住的重要事实是,视图必须附加到 window 以便过渡框架捕获它。所以我使用 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);
         }
      };

它对我来说很好用。

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