使用Picasso时,共享元素转换在首次加载时无效。

7

我正在尝试使用Picasso从URL加载图像到ImageView

共享动画的图像位于RecyclerView中的CardView中,第二个图像位于LinearLayout中。 第一次请求时,由于Picasso需要将图像加载到视图中,因此元素不会执行动画,但在后续请求中就可以了。

如何确保在启动过渡之前ImageView已成功填充?

3个回答

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

这篇文章对此进行了很好的阐述。

下面是一个在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);
        }
    });

然而,这会减慢输入新活动的速度,特别是当图像加载缓慢时。 - jiawen
我刚刚实现了同样的事情并遇到了同样的问题。我认为共享元素转换不应该像这样使用。转换最适合使用可绘制对象和本地文本。它可以与快速HTTP调用一起使用,但如果图像质量高,则不容易快速处理。实际上,我在此动画中遇到了OOM错误,因此我将放弃它并寻找其他动画。看起来它会在内存中保存多个相同活动的实例,以便在第一次之后提供更快的转换。 - RED_
最好在过渡之前使用像Picasso的fetch(http://square.github.io/picasso/2.x/picasso/com/squareup/picasso/RequestCreator.html#fetch-com.squareup.picasso.Callback-)这样的东西来填充缓存。 - Duncan Hoggan
你如何使用“android.support.v4.app.Fragment”来实现这个? - SwingerDinger
2
@SingerDinger,你需要使用supportPostponeEnterTransition(https://developer.android.com/reference/android/support/v4/app/FragmentActivity.html#supportPostponeEnterTransition())和supportStartPostponedEnterTransition(https://developer.android.com/reference/android/support/v4/app/FragmentActivity.html#supportStartPostponedEnterTransition())。希望这能帮到你。 - Francisco Junior
显示剩余2条评论

6

如果您想避免由于推迟进入转换而引起的影响,您可以强制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 将其保留为弱引用,所以您不希望它被垃圾回收。

0

你可以用Universal Image Loader替换Picasso,它能很好地解决这个问题。

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);

1
但是维护工作从2015年11月27日停止。因此,从Picasso切换到UIL是一个不好的主意。更多信息请参阅:https://github.com/nostra13/Android-Universal-Image-Loader - Shashanth
1
是的,没错。但是唯一能很好地与共享元素活动过渡兼容的图像库就是UIL。 - N.Baltaji

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接