Android RecyclerView共享元素过渡启动延迟问题优化求助
RecyclerView共享元素过渡启动延迟优化方案
问题描述
在RecyclerView中使用Shared Element Transition时,过渡启动阶段存在明显延迟:跳转时背景先消失,仅图片留存片刻后才开始过渡动画,影响流畅度。
现有代码
适配器中处理过渡的代码
holder.image.setTransitionName("example_transition"); Intent intent = new Intent(context, ShowElementActivity.class); intent.putExtra("Element", elemento); ActivityOptionsCompat options = ActivityOptionsCompat.makeSceneTransitionAnimation( (AnimeActivity)context, holder.image, ViewCompat.getTransitionName(holder.image)); context.startActivity(intent, options.toBundle());
目标页面处理过渡的代码
postponeEnterTransition(); Glide.with(this) .load(elemento.image_url) .listener(new RequestListener<Drawable>() { @Override public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) { supportStartPostponedEnterTransition(); return false; } @Override public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) { startPostponedEnterTransition(); return false; } }) .into(showelement_image); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { getWindow().getSharedElementEnterTransition().setDuration(200); getWindow().getSharedElementReturnTransition().setDuration(200) .setInterpolator(new DecelerateInterpolator()); } Fade fade = new Fade(); fade.excludeTarget(android.R.id.statusBarBackground, true); fade.excludeTarget(android.R.id.navigationBarBackground, true); getWindow().setEnterTransition(fade); getWindow().setExitTransition(fade);
优化步骤
1. 给共享元素设置唯一TransitionName
当前所有列表item的图片使用同一个TransitionName,会导致系统识别混乱,必须为每个item的图片分配唯一标识:
// 适配器中设置 holder.image.setTransitionName("example_transition_" + elemento.getId()); // 目标页面中对应设置 showelement_image.setTransitionName("example_transition_" + elemento.getId());
2. 优化Glide加载逻辑
- 强制优先使用内存缓存,减少图片加载等待时间:
Glide.with(this) .load(elemento.image_url) .diskCacheStrategy(DiskCacheStrategy.ALL) // 同时缓存到内存和磁盘 .listener(new RequestListener<Drawable>() { @Override public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) { supportStartPostponedEnterTransition(); return false; } @Override public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) { startPostponedEnterTransition(); return false; } }) .into(showelement_image);
- 添加超时机制,避免因图片加载过久卡住过渡:
postponeEnterTransition(); // 300ms后强制启动过渡,防止加载阻塞 getWindow().getDecorView().postDelayed(() -> supportStartPostponedEnterTransition(), 300); // 原有Glide加载逻辑...
3. 调整窗口过渡配置时机
将过渡配置代码提前到onCreate最开始,确保窗口初始化时就完成过渡配置:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 先配置过渡动画 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { getWindow().getSharedElementEnterTransition().setDuration(200); getWindow().getSharedElementReturnTransition().setDuration(200) .setInterpolator(new DecelerateInterpolator()); // 禁用过渡重叠,避免视觉混乱 getWindow().getSharedElementEnterTransition().setAllowEnterTransitionOverlap(false); } Fade fade = new Fade(); fade.excludeTarget(android.R.id.statusBarBackground, true); fade.excludeTarget(android.R.id.navigationBarBackground, true); getWindow().setEnterTransition(fade); getWindow().setExitTransition(fade); setContentView(R.layout.activity_show_element); // 后续处理Glide加载和数据解析... }
4. 确保列表item已完成布局再启动过渡
点击列表item时,先判断View是否完成布局,避免因item未绘制完成导致延迟:
holder.image.setOnClickListener(v -> { if (v.isLaidOut()) { launchDetailActivity(elemento, v); } else { v.post(() -> launchDetailActivity(elemento, v)); } }); // 抽离启动逻辑 private void launchDetailActivity(Element elemento, View sharedView) { Intent intent = new Intent(context, ShowElementActivity.class); intent.putExtra("Element", elemento); ActivityOptionsCompat options = ActivityOptionsCompat.makeSceneTransitionAnimation( (AnimeActivity)context, sharedView, ViewCompat.getTransitionName(sharedView)); context.startActivity(intent, options.toBundle()); }
内容的提问来源于stack exchange,提问作者C-Gian
相关产品推荐
相关产品推荐

