Android共享元素过渡在具有RecyclerView和详情视图的片段之间

10
我有两个片段:片段1包含RecyclerView和片段2包含所选项目的详细视图。这两个片段之间有一个共享元素ImageView。当从片段1转换到片段2时,我希望看到标准的共享元素过渡效果,但是在RecyclerView中似乎无法工作。因为如果我在第一个片段中只使用另一个单独的视图,而不是RecyclerView,则会展示正确的过渡效果。请注意,我已为RecyclerView项图像分配基于位置的唯一过渡名称。 以下是代码: MyActivity.java
public class MyActivity extends Activity {

private static final String TAG = MyActivity.class.getSimpleName();

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_my);
    if (savedInstanceState == null) {
        getFragmentManager().beginTransaction()
                .add(R.id.main_container, new PlaceholderFragment())
                .commit();
    }
}

public static class ImageAdapter extends RecyclerView.Adapter<ImageAdapter.ViewHolder> {
    public interface OnItemClickListener {
        void onItemClick(View view, int position);
    }

    private OnItemClickListener mItemClickListener;

    List<Integer> items = new ArrayList<Integer>();
    public void setOnItemClickListener(OnItemClickListener listener) {
        this.mItemClickListener = listener;
    }


    public ImageAdapter() {
        items.add(1);
        items.add(1);
        items.add(1);
        items.add(1);
        items.add(1);
        items.add(1);
        items.add(1);
        items.add(1);
        items.add(1);
        items.add(1);
        items.add(1);
        items.add(1);
        items.add(1);
        items.add(1);
        items.add(1);
        items.add(1);
        items.add(1);
        items.add(1);
    }

    @Override
    public ImageAdapter.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
        View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item, null);
        ViewHolder viewHolder = new ViewHolder(view);
        return viewHolder;
    }

    @Override
    public void onBindViewHolder(ViewHolder viewHolder, final int i) {
        viewHolder.container.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View view) {
                if (mItemClickListener != null) {
                    mItemClickListener.onItemClick(view, i);
                }
            }
        });
        viewHolder.imgDummy.setTransitionName("test" + i);
    }

    @Override
    public int getItemCount() {
        return items.size();
    }

    public static class ViewHolder extends RecyclerView.ViewHolder {
        public View container;
        public View imgDummy;

        public ViewHolder(View itemView) {
            super(itemView);
            container = itemView.findViewById(R.id.container);
            imgDummy = itemView.findViewById(R.id.imgDummy);
        }
    }
}
/**
 * A placeholder fragment containing a simple view.
 */
@SuppressLint("ValidFragment")
public class PlaceholderFragment extends Fragment {

    private RelativeLayout.LayoutParams lp;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_my, container, false);
        final View imgDummy2 = rootView.findViewById(R.id.imgDummy2);
        imgDummy2.setTransitionName("test");

        RecyclerView list = (RecyclerView) rootView.findViewById(R.id.streams_list);
        list.setLayoutManager(new LinearLayoutManager(getActivity()));
        ImageAdapter adapter = new ImageAdapter();
        adapter.setOnItemClickListener(new ImageAdapter.OnItemClickListener() {
            @Override
            public void onItemClick(View view, int position) {                  
                View imgDummy = view.findViewById(R.id.imgDummy);

                SecondFragment secondFragment = new SecondFragment();
                secondFragment.setSharedElementEnterTransition(TransitionInflater.from(getActivity()).inflateTransition(R.transition.trans_move));

                secondFragment.setId(imgDummy.getTransitionName());
                android.app.FragmentTransaction trans = getFragmentManager().beginTransaction();
                trans.replace(R.id.main_container, secondFragment);
                trans.addToBackStack(null);
                trans.addSharedElement(imgDummy, imgDummy.getTransitionName());
                trans.commit();
            }
        });
        list.setAdapter(adapter);

        return rootView;
    }
}

public static class SecondFragment extends Fragment {
    private String mId;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.second_fragment, container, false);
        rootView.findViewById(R.id.imgDummy).setTransitionName(mId);
        return rootView;
    }

    public void setId(String id) {
        mId = id;
    }
}
}

如果我改变以下两行:

secondFragment.setId(imgDummy.getTransitionName());
trans.addSharedElement(imgDummy, imgDummy.getTransitionName());
secondFragment.setId(imgDummy2.getTransitionName());
trans.addSharedElement(imgDummy2, imgDummy2.getTransitionName());

那么我就可以看到imgDummy2图像过渡得很好,可能是因为它在recyclerview之外。

有什么办法可以在recyclerview内也实现同样的效果吗?


你读过这篇文章吗?http://www.androiddesignpatterns.com/2015/01/activity-fragment-shared-element-transitions-in-depth-part3a.html - pskink
2
@pskink,是的,我花了整整一天的时间寻找确切的解决方案,但没有找到与我的要求完全匹配的工作解决方案。你发布的链接通常很好地理解了转换基础知识,但它对于recyclerview没有任何具体的东西,因此它无法正常工作。 - Ankur
如果这是你需要的,请尝试使用以下链接:http://pastebin.com/yEh2urqp - pskink
我是移动设备,所以不想下载2.5 MB的源码,我的代码只有80行,所以请你也尽量简洁一些。另外,你试过在官方V5 AVD模拟器上运行它吗? - pskink
@pskink,您在第1个和第2个片段中使用了不同的共享元素。我认为两个片段必须具有相同的共享元素(在我们的情况下是TextView),因此我尝试在子TextView上设置转换名称,并将此TextView添加为共享元素,但是您直接将recyclerview项的父视图添加为共享元素,尽管在itemfragment中只有一个简单的TextView。但是在返回按下时,反向转换动画仍然存在问题,对吧? - Ankur
显示剩余8条评论
1个回答

1
我知道现在已经很晚了,但是我一直在努力解决这个问题,最终成功实现了从Fragment A中的RecyclerView到Fragment B的转换动画。
请尝试更改以下行中的imgDummy.getTransitionName()。
    trans.addSharedElement(imgDummy, imgDummy.getTransitionName());

将fragmentB中ImageView的过渡名称转换为对应的文本。


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