Android Fragment共享元素返回过渡动画不生效问题
修复Fragment返回共享元素过渡失效问题
1. 修正返回按钮逻辑,改用popBackStack替代replace
当前ShowElementFragment的返回按钮直接替换为MainFragment,破坏了Fragment栈结构,导致系统无法触发返回共享元素过渡。应改为弹出回退栈回到上一个Fragment:
showelement_backarrow.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { getActivity().getSupportFragmentManager().popBackStack(); } });
2. 保存并恢复Fragment A的RecyclerView滚动位置
ViewPager2会销毁不可见Fragment,返回时RecyclerView可能重新加载,导致共享元素位置丢失。需在tab1_anime类中添加状态保存逻辑:
// 添加成员变量保存滚动状态 private Parcelable recyclerViewState; // 保存状态 @Override public void onSaveInstanceState(@NonNull Bundle outState) { super.onSaveInstanceState(outState); recyclerViewState = recycler_view.getLayoutManager().onSaveInstanceState(); outState.putParcelable("recycler_state", recyclerViewState); } // 恢复状态 @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); if (savedInstanceState != null) { recyclerViewState = savedInstanceState.getParcelable("recycler_state"); if (recyclerViewState != null) { recycler_view.getLayoutManager().onRestoreInstanceState(recyclerViewState); } } }
3. 确保Fragment A的共享元素返回时状态正确
在tab1_anime的onViewCreated中延迟返回过渡,直到RecyclerView布局完成,避免共享元素未加载:
@Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); // ...恢复滚动状态的代码 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { postponeEnterTransition(); recycler_view.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { @Override public boolean onPreDraw() { recycler_view.getViewTreeObserver().removeOnPreDrawListener(this); startPostponedEnterTransition(); return true; } }); } }
同时在Adapter的onBindViewHolder中确保每个Item的共享元素transitionName正确:
@Override public void onBindViewHolder(@NonNull ViewHolder holder, int position) { // ...其他绑定逻辑 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { holder.itemView.findViewById(R.id.main_image).setTransitionName("transition" + position); } }
4. 调整Fragment B的过渡配置
避免直接修改Activity全局过渡,改为设置Fragment自身的返回过渡,并确保共享元素图片加载完成后启动过渡:
@Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { setSharedElementReturnTransition(TransitionInflater.from(getContext()).inflateTransition(R.transition.default_transition)); setReturnTransition(TransitionInflater.from(getContext()).inflateTransition(android.R.transition.no_transition)); } } @Override public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_show_element, parent, false); // ...其他初始化逻辑 // 修改Glide加载逻辑,确保图片加载完成后启动过渡 Glide.with(this) .load(elemento.image_url) .diskCacheStrategy(DiskCacheStrategy.AUTOMATIC) .skipMemoryCache(false) .listener(new RequestListener<Drawable>() { @Override public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) { startPostponedEnterTransition(); return false; } @Override public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) { startPostponedEnterTransition(); return false; } }) .into(showelement_image); // ...返回view的代码 } @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { postponeEnterTransition(); } }
5. 优化showFragmentWithTransition的过渡设置
确保当前Fragment和新Fragment的过渡配置正确,避免冲突:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { current.setSharedElementReturnTransition(TransitionInflater.from(this).inflateTransition(R.transition.default_transition)); current.setExitTransition(TransitionInflater.from(this).inflateTransition(android.R.transition.no_transition)); newFragment.setSharedElementEnterTransition(TransitionInflater.from(this).inflateTransition(R.transition.default_transition)); newFragment.setEnterTransition(TransitionInflater.from(this).inflateTransition(android.R.transition.no_transition)); }
内容的提问来源于stack exchange,提问作者C-Gian
相关产品推荐
相关产品推荐

