我已经在我的旧项目中实现了这一点。
检查以下内容中您缺少什么:
1.在您的 SourceFragment 中添加以下代码行。这里的关键点是在 onViewCreated() 方法中,您必须使用推迟EnterTransition() and startPostponedEnterTransition()当用户返回到源片段时,需要正确地设置动画。另外,在 onCreate() 方法中设置 Exit Transition 和 ReenterTransition 以使项目列表在退出时横向扩展并在重新进入时返回:
public class SourceFragment extends Fragment {
private RecyclerView recyclerView;
private LinearLayoutManager mLayoutManager;
public static int index = -1;
public static int top = -1;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//set the below transitions so as the source list scale out when exiting and back in when reentering
setExitTransition(new MaterialElevationScale(false));
setReenterTransition(new MaterialElevationScale(true));
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_source, container, false);
recyclerView = view.findViewById(R.id.recycler_view);
mLayoutManager = new LinearLayoutManager(getContext());
recyclerView.setLayoutManager(mLayoutManager);
recyclerView.setAdapter(new SourceAdapter(this, getFragmentManager()));
return view;
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
//the below code is required to animate correctly when the user returns to the source fragment
//gives a chance for the layout to be fully laid out before animating it
postponeEnterTransition();
((ViewGroup) view.getParent()).getViewTreeObserver()
.addOnPreDrawListener(() -> {
startPostponedEnterTransition();
return true;
});
}
@Override
public void onPause() {
super.onPause();
//Save the current state of recycle view position
index = mLayoutManager.findFirstVisibleItemPosition();
View startView = recyclerView.getChildAt(0);
top = (startView == null) ? 0 : (startView.getTop() - recyclerView.getPaddingTop());
}
@Override
public void onResume()
{
super.onResume();
//Scrolls the recycler view to the clicked item position when navigating back
if(index != -1) {
mLayoutManager.scrollToPositionWithOffset(index, top);
}
}
}
2.设置转换名称以映射共享元素,例如:图像项(开始视图)到其目标片段图像(结束视图)。在 SourceAdapter 的 onBindViewHolder() 中为每个图像项设置唯一标识符。根据你的代码将是:
thumbnail.setTransitionName(result.getVin());
3.将此唯一标识符传递到您的 DestinationFragment (DetailFragment) 并在 onCreateView() 中完成映射。根据你的代码将是:
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View v = inflater.inflate(R.layout.fragment_detail, container, false);
// Set transitionName exactly same as the recyclerview item which was clicked
v.findViewById(R.id.detail_image_thumbnail).setTransitionName(result.getVin());
return v;
}
4.在 DestinationFragment (DetailFragment) 的 onCreate() 方法中添加 Enter Transition,如下所示:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//prepare the EnterTransition
MaterialContainerTransform transform = new MaterialContainerTransform();
transform.setScrimColor(Color.TRANSPARENT);
setSharedElementEnterTransition(transform);
//get your arguments according to your code
if (getArguments() != null) {
result = Parcels.unwrap(getArguments().getParcelable("RESULT"));
searchId = getArguments().getString("SEARCH_ID");
}
}
5.最后根据您的代码从SourceFragment切换到DestinationFragment:
Bundle args = new Bundle();
args.putParcelable("RESULT", Parcels.wrap(result));
args.putString("SEARCH_ID", searchId);
DetailFragment fragment = new DetailFragment();
fragment.setArguments(args);
fragmentManager
.beginTransaction()
.setReorderingAllowed(true)
.addSharedElement(thumbnail, thumbnail.getTransitionName()) // Shared element!
.replace(R.id.main_fragment_container,
fragment,
DetailFragment.class.getSimpleName())
.addToBackStack(null)
.commit();