共享元素转换不适用于 Picasso 的首次加载

Shared Element Transition not working on first load with Picasso

我正在尝试使用毕加索将 URL 中的图像加载到 ImageView 中。

用于共享过渡的图像在 RecyclerView 中的 CardView 内,第二个仅在 LinearLayout 中。 第一次发出请求时,元素没有动画,因为毕加索需要将图像加载到视图中,但在后续请求中没问题。

如何确保 ImageView 在开始转换之前已成功填充?

解决方案是使用 postponeEnterTransition() and startPostponedEnterTransition() 调用来确保 picasso 在 activity 开始之前将图像加载到视图中。

This 是一篇关于此的精彩博客文章。

下面是您可以在 onCreate

中使用的示例
ActivityCompat.postponeEnterTransition(this);
Picasso.with(this.getApplicationContext())
    .load("https://goo.gl/oiyTor")
    .noFade()
    .fit()
    .centerInside()
    .error(R.drawable.user_placeholder_error)
    .into(((ImageView) findViewById(R.id.game_view_image)), new Callback() {
        @Override
        public void onSuccess() {
            ActivityCompat.startPostponedEnterTransition(targetActivity);
        }

        @Override
        public void onError() {
            ActivityCompat.startPostponedEnterTransition(targetActivity);
        }
    });

如果你想避免延迟进入过渡造成的影响,你可以强制 Picasso 使用缓存中已有的任何内容:

Target target = new Target() {
      @Override public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
        this.imageView.setImageBitmap(bitmap);
      }
      @Override public void onBitmapFailed(Drawable errorDrawable) {}
      @Override public void onPrepareLoad(Drawable placeHolderDrawable) {}
};
Picasso.with(context)
       .load(url)
       .networkPolicy(NetworkPolicy.OFFLINE)
       .into(target);

通过传递 Target 实例而不是您的 ImageView 实例,您将迫使 Picasso 交付它为 URL 缓存的任何内容。如果您改为传递 ImageView,您将不会立即加载图像。

请注意,您应该将目标对象保存在一个成员变量中,因为它被 Picasso 保存为弱引用,所以您不希望它被垃圾收集。

您可以将 Picasso 替换为 Universal Image Loader,它可以很好地解决这个问题

DisplayImageOptions options = new DisplayImageOptions.Builder()
                .showImageOnLoading(drawable) 
                .showImageForEmptyUri(emptyDrawable) 
                .showImageOnFail(errorDrawable) 
                .resetViewBeforeLoading(false)  
                .cacheInMemory(true) 
                .cacheOnDisk(true) 
                .imageScaleType(ImageScaleType.IN_SAMPLE_POWER_OF_2)
                .build();
        imageLoader.displayImage(url, iv, options);