facebook / fresco

An Android library for managing images and the memory they use.
https://frescolib.org/
MIT License
17.07k stars 3.75k forks source link

Circular reveal animation with Fresco #992

Closed shareyourlocationsite closed 6 years ago

shareyourlocationsite commented 8 years ago

I need to make a circular reveal animation after the image is loaded by fresco in my android app. I listen to the download events as described here; http://frescolib.org/docs/listening-download-events.html#_ In the onFinalImageSet event I run the reveal effect as described here; http://developer.android.com/training/material/animations.html

The image is not shown. When I put a debug log to the onFinalImageSet event, I see that it's calling repeatedly. When I comment out the reveal function it's only called once, and works as expected. Somehow reveal effect triggers fresco to load the image over and over.

IanChilds commented 8 years ago

can you share the code that you're using? or some logs to show what's happening? http://frescolib.org/docs/troubleshooting.html#setting-up-logcat

shareyourlocationsite commented 8 years ago

Well I've changed my image loading library for that part of the project. I tried to reproduce it in a sample project and found out a similar problem. I created two activites. First one has a button to start the second one. In the second activity I've the image view with the circular reveal animation. When I start the second activity for the first time, it works fine. But when I press back and start the activity again the image view stays invisible until the animation ends, and just flashes and became visible. Here is the sample code;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button btnCircularReveal = (Button)findViewById(R.id.btnCircularReveal);
        btnCircularReveal.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(getApplicationContext(), CircularRevealActivity.class);
                startActivity(intent);
            }
        });
    }
}
public class CircularRevealActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_circular_reveal);

        setImage();
    }

    private void setImage()
    {
        String url ="http://www.gstatic.com/webp/gallery/1.jpg";
        SimpleDraweeView simpleDraweeView = (SimpleDraweeView)findViewById(R.id.my_image_view);

        ControllerListener controllerListener = new BaseControllerListener<ImageInfo>() {
            @Override
            public void onFinalImageSet(
                    String id,
                    @Nullable ImageInfo imageInfo,
                    @Nullable Animatable anim) {

                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                    revealImage();
                }
            }

            @Override
            public void onIntermediateImageSet(String id, @Nullable ImageInfo imageInfo) {

            }

            @Override
            public void onFailure(String id, Throwable throwable) {

            }
        };

        DraweeController controller = Fresco.newDraweeControllerBuilder()
                .setControllerListener(controllerListener)
                .setUri(Uri.parse(url))
                .build();
        simpleDraweeView.setController(controller);
    }

    private void revealImage() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            final SimpleDraweeView simpleDraweeView = (SimpleDraweeView)findViewById(R.id.my_image_view);

            simpleDraweeView.setVisibility(View.INVISIBLE);
            int cx = simpleDraweeView.getWidth() / 2;
            int cy = simpleDraweeView.getHeight() / 2;

            int finalRadius = Math.max(simpleDraweeView.getWidth(), simpleDraweeView.getHeight());

            Animator animator = ViewAnimationUtils.createCircularReveal(simpleDraweeView, cx, cy, 0, finalRadius);
            animator.setDuration(3000);
            animator.addListener(new Animator.AnimatorListener() {
                @Override
                public void onAnimationStart(Animator animation) {
                    simpleDraweeView.setVisibility(View.VISIBLE);
                }

                @Override
                public void onAnimationEnd(Animator animation) {

                }

                @Override
                public void onAnimationCancel(Animator animation) {

                }

                @Override
                public void onAnimationRepeat(Animator animation) {

                }
            });
            animator.start();
        }
    }

}
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:fresco="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:context="com.test.frescocircularreveal.CircularRevealActivity">

    <com.facebook.drawee.view.SimpleDraweeView
        android:id="@+id/my_image_view"
        android:layout_width="match_parent"
        android:layout_height="240dp" />

</android.support.design.widget.CoordinatorLayout>
IanChilds commented 8 years ago

Given it works the first time you try, why do you think it's a problem with Fresco? Are you not resetting things properly or something like that? Are you able to try and get a bit closer to knowing what the issue is?

shareyourlocationsite commented 8 years ago

Should I reset anything? It's just a simple app showing an image. I used Glide with this and it worked fine. I think the issue is something about cached images in fresco.

wogenhaosini commented 6 years ago

Yes, I also met. I used Glide with this and it worked fine

private static class MirroredView extends AppCompatImageView {

    private final SimpleDraweeView mSource;

    public MirroredView(SimpleDraweeView source) {
      super(source.getContext());
      setImageDrawable(source.getDrawable());
      setScaleType(source.getScaleType());
      mSource = source;
    }

    @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
      int w = MeasureSpec.getSize(mSource.getMeasuredWidth());
      int h = MeasureSpec.getSize(mSource.getMeasuredHeight());
      setMeasuredDimension(w, h);
    }
  }

GIF : https://user-images.githubusercontent.com/10138880/38365432-df918aaa-390e-11e8-9505-b839badb803d.gif

oprisnik commented 6 years ago

The following code just works for me (changing https://github.com/facebook/fresco/blob/master/samples/showcase/src/main/java/com/facebook/fresco/samples/showcase/drawee/DraweeSimpleFragment.java:


  @Override
  public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
    final ImageUriProvider imageUriProvider = ImageUriProvider.getInstance(getContext());
    final Uri uri = imageUriProvider.createSampleUri(ImageUriProvider.ImageSize.M);

    final SimpleDraweeView simpleDraweeView = (SimpleDraweeView) view.findViewById(R.id.drawee_view);
    simpleDraweeView.setController(Fresco.newDraweeControllerBuilder().setUri(uri).setControllerListener(new BaseControllerListener<ImageInfo>() {
      @Override
      public void onFinalImageSet(
          String id,
          @javax.annotation.Nullable ImageInfo imageInfo,
          @javax.annotation.Nullable Animatable animatable) {
        reveal(simpleDraweeView);
      }
    }).build());
  }

  private void reveal(final SimpleDraweeView simpleDraweeView) {
      simpleDraweeView.setVisibility(View.INVISIBLE);
      int cx = simpleDraweeView.getWidth() / 2;
      int cy = simpleDraweeView.getHeight() / 2;

      int finalRadius = Math.max(simpleDraweeView.getWidth(), simpleDraweeView.getHeight());

      Animator animator = ViewAnimationUtils
          .createCircularReveal(simpleDraweeView, cx, cy, 0, finalRadius);
      animator.setDuration(3000);
      animator.addListener(new Animator.AnimatorListener() {
        @Override
        public void onAnimationStart(Animator animation) {
          simpleDraweeView.setVisibility(View.VISIBLE);
        }

        @Override
        public void onAnimationEnd(Animator animation) {}

        @Override
        public void onAnimationCancel(Animator animation) {}

        @Override
        public void onAnimationRepeat(Animator animation) {}
      });
      animator.start();
    }