Android: RecyclerView 和 Fragment 之间没有共享元素转换
Android: No shared element transition between RecyclerView and Fragment
我有以下设置:一个 MainActivity、一个具有 RecyclerView 的 AFragment 和一个用于包含 AFragment 中元素详细信息的 BFragment。当用户点击 AFragment 中的项目时,会将他们带到 BFragment。
我想要创建的效果是获取 AFragment 中项目的 ImageView 并将其转换为 BFragment。
问题是,目前,对于 RecyclerView 的“第一页”上的所有项目(“第一页”我指的是当您第一次输入 AFragment 时您可以在屏幕上看到的所有项目),输入转换进入 BFragment 根本不起作用。但是,当从 BFragment 返回到 AFragment 时,过渡播放正常。对于 RecyclerView 中的所有其他项目(即不在“第一页”上的项目),进入和退出过渡都可以完美播放。
我的代码
片段
public class AFragment extends Fragment {
...
public static class ItemAdapter extends RecyclerView.Adapter<ViewHolder> {
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
final Item info = items.get(position);
ViewCompat.setTransitionName(holder.imageView, "shared_image_" + info.getId());
holder.imageView.setImageDrawable(info.getIcon());
holder.name.setText(info.getName());
holder.rootView.setTag(info.getId());
holder.rootView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
BFragment frag = BFragment.newInstance((Integer) v.getTag());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
frag.setSharedElementEnterTransition(new ComboTransition());
frag.setEnterTransition(new Fade());
setExitTransition(new Fade());
frag.setSharedElementReturnTransition(new ComboTransition());
Log.d(TAG, "Name: " + imageView.getTransitionName());
}
getFragmentManager().beginTransaction()
.addSharedElement(imageView, "shared_image")
.replace(R.id.content, frag)
.addToBackStack(null)
.commit();
}
});
}
}
...
}
B片段
public class BFragment extends Fragment {
...
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
...
ImageView imageView = (ImageView) findViewById(R.id.image_view);
ViewCompat.setTransitionName(imageView, "shared_image");
...
}
...
}
求教。我发现了这个问题,这是我的应用程序独有的。问题是我忘记了我在 BFragment 中有另一个 RecyclerView 副本(原因是我希望用户能够在 BFragment 中搜索 AFragment 中的所有项目,这样用户体验会好一点)。所以发生的事情是,当用户退出 AFragment 并进入 BFragment 时,BFragment 中的 recyclerview 将被初始化,因此 "first page" 上的所有项目也将使用与 AFragment 中的项目相同的转换名称进行初始化(因此奇数"first page" 上项目的行为)。当然,这真的很糟糕,因为现在两个项目具有相同的转换名称。
我通过更改 ItemAdapter 的构造函数以接受创建者独有的密钥并将该密钥添加到所有转换名称中来解决这个问题。
我有以下设置:一个 MainActivity、一个具有 RecyclerView 的 AFragment 和一个用于包含 AFragment 中元素详细信息的 BFragment。当用户点击 AFragment 中的项目时,会将他们带到 BFragment。
我想要创建的效果是获取 AFragment 中项目的 ImageView 并将其转换为 BFragment。
问题是,目前,对于 RecyclerView 的“第一页”上的所有项目(“第一页”我指的是当您第一次输入 AFragment 时您可以在屏幕上看到的所有项目),输入转换进入 BFragment 根本不起作用。但是,当从 BFragment 返回到 AFragment 时,过渡播放正常。对于 RecyclerView 中的所有其他项目(即不在“第一页”上的项目),进入和退出过渡都可以完美播放。
我的代码
片段
public class AFragment extends Fragment {
...
public static class ItemAdapter extends RecyclerView.Adapter<ViewHolder> {
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
final Item info = items.get(position);
ViewCompat.setTransitionName(holder.imageView, "shared_image_" + info.getId());
holder.imageView.setImageDrawable(info.getIcon());
holder.name.setText(info.getName());
holder.rootView.setTag(info.getId());
holder.rootView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
BFragment frag = BFragment.newInstance((Integer) v.getTag());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
frag.setSharedElementEnterTransition(new ComboTransition());
frag.setEnterTransition(new Fade());
setExitTransition(new Fade());
frag.setSharedElementReturnTransition(new ComboTransition());
Log.d(TAG, "Name: " + imageView.getTransitionName());
}
getFragmentManager().beginTransaction()
.addSharedElement(imageView, "shared_image")
.replace(R.id.content, frag)
.addToBackStack(null)
.commit();
}
});
}
}
...
}
B片段
public class BFragment extends Fragment {
...
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
...
ImageView imageView = (ImageView) findViewById(R.id.image_view);
ViewCompat.setTransitionName(imageView, "shared_image");
...
}
...
}
求教。我发现了这个问题,这是我的应用程序独有的。问题是我忘记了我在 BFragment 中有另一个 RecyclerView 副本(原因是我希望用户能够在 BFragment 中搜索 AFragment 中的所有项目,这样用户体验会好一点)。所以发生的事情是,当用户退出 AFragment 并进入 BFragment 时,BFragment 中的 recyclerview 将被初始化,因此 "first page" 上的所有项目也将使用与 AFragment 中的项目相同的转换名称进行初始化(因此奇数"first page" 上项目的行为)。当然,这真的很糟糕,因为现在两个项目具有相同的转换名称。
我通过更改 ItemAdapter 的构造函数以接受创建者独有的密钥并将该密钥添加到所有转换名称中来解决这个问题。