Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Shared Element Transition not working on first load with Picasso

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?

like image 248
Duncan Hoggan Avatar asked Oct 22 '15 14:10

Duncan Hoggan


2 Answers

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);
        }
    });
like image 166
Duncan Hoggan Avatar answered Oct 22 '22 13:10

Duncan Hoggan


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.

like image 32
Flávio Faria Avatar answered Oct 22 '22 12:10

Flávio Faria