You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 15:20:36