Shared Element Transition not working on first load with Picasso
Asked Answered
A

3

7

I am trying to load an image from a URL into an ImageView using Picasso.

The image for the shared transition is inside a CardView in a RecyclerView and the second it just in a LinearLayout. The first time the request is made the element doesn't animate as picasso needs to load the image into the view, but on subsequent requests it is fine.

How can I ensure that the ImageView has been successfully populated before initiating the transition?

Araiza answered 22/10, 2015 at 14:5 Comment(0)
A
27

The solution was in using the postponeEnterTransition() and startPostponedEnterTransition() calls to ensure that picasso has finished loading the image into the view before the activity starts.

This is a great blog entry about this.

Below is an example of what you might use in 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);
        }
    });
Araiza answered 22/10, 2015 at 14:5 Comment(4)
this however slows down the entering of the new activity, especially when the image is slow to load.Poppycock
I've just implemented the same thing and come to the same issue. I don't think the shared element transition is meant to be used like this. The transition works best with drawables and local text. It can work with quick HTTP calls but images don't tend to be quick if they are high quality. I'm actually getting OOM errors with this animation so I'm going to ditch it and find a different animation. It seems like it's holding multiple instances of the same activity in memory to provide quicker transitions after the first time.Pulver
Its best to seed the cache before you do the transition using something like Picasso's fetch square.github.io/picasso/2.x/picasso/com/squareup/picasso/….Araiza
Not sure if it applies for everyone but solution above wasn' fully working for me. I was using Picasso to load a header image in CollapsingToolbarLayout and sometimes layout was huge mess when user entered activity - some views were clipped or visible even with visibility set to View.GONE. I've found solution to it here: androiddesignpatterns.com/2015/03/…Lindane
U
6

If you want to avoid the effect caused by postponing the enter transition, you can force Picasso to use whatever it already has in cache:

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

By passing a Target instance rather than your ImageView one, you'll be forcing Picasso to deliver whatever it has cached for that URL. If you pass the ImageView instead, you won't get the image loaded immediately.

Please note that you should hold your target object in a member variable, since it is held as a weak reference by Picasso, so you don't want it to be garbage collected.

Unintelligent answered 26/7, 2016 at 20:35 Comment(0)
J
0

You can replace Picasso with Universal Image Loader which deals pretty well with this problem

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);
Janiculum answered 11/11, 2016 at 15:38 Comment(2)
But the maintenance stopped from Nov 27 2015. So, it's a bad idea to switch from Picasso to UIL. For more seeVerify
Yes that's true, but the only image library which works well with the shared element activity transition is the UILJaniculum

© 2022 - 2024 — McMap. All rights reserved.