Skip to content

Commit

Permalink
Merge pull request #124 from ancient-mystic-wonder/master
Browse files Browse the repository at this point in the history
Added option to use circular reveal for API >= 21.
  • Loading branch information
deano2390 authored Jun 15, 2017
2 parents 43ecf95 + add180e commit 25b345b
Show file tree
Hide file tree
Showing 5 changed files with 148 additions and 28 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package uk.co.deanwild.materialshowcaseview;

import android.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.annotation.TargetApi;
import android.graphics.Point;
import android.os.Build;
import android.view.View;
import android.view.ViewAnimationUtils;
import android.view.animation.AccelerateDecelerateInterpolator;


public class CircularRevealAnimationFactory implements IAnimationFactory {

private static final String ALPHA = "alpha";
private static final float INVISIBLE = 0f;
private static final float VISIBLE = 1f;

private final AccelerateDecelerateInterpolator interpolator;

public CircularRevealAnimationFactory() {
interpolator = new AccelerateDecelerateInterpolator();
}

@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Override
public void animateInView(View target, Point point, long duration, final AnimationStartListener listener) {
Animator animator = ViewAnimationUtils.createCircularReveal(target, point.x, point.y, 0,
target.getWidth() > target.getHeight() ? target.getWidth() : target.getHeight());
animator.setDuration(duration).addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
listener.onAnimationStart();
}

@Override
public void onAnimationEnd(Animator animation) {

}

@Override
public void onAnimationCancel(Animator animation) {

}

@Override
public void onAnimationRepeat(Animator animation) {

}
});

animator.start();
}

@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Override
public void animateOutView(View target, Point point, long duration, final AnimationEndListener listener) {
Animator animator = ViewAnimationUtils.createCircularReveal(target, point.x, point.y,
target.getWidth() > target.getHeight() ? target.getWidth() : target.getHeight(), 0);
animator.setDuration(duration).addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {

}

@Override
public void onAnimationEnd(Animator animation) {
listener.onAnimationEnd();
}

@Override
public void onAnimationCancel(Animator animation) {

}

@Override
public void onAnimationRepeat(Animator animation) {

}
});

animator.start();
}

@Override
public void animateTargetToPoint(MaterialShowcaseView showcaseView, Point point) {
AnimatorSet set = new AnimatorSet();
ObjectAnimator xAnimator = ObjectAnimator.ofInt(showcaseView, "showcaseX", point.x);
ObjectAnimator yAnimator = ObjectAnimator.ofInt(showcaseView, "showcaseY", point.y);
set.playTogether(xAnimator, yAnimator);
set.setInterpolator(interpolator);
set.start();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,28 @@
import android.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.annotation.TargetApi;
import android.graphics.Point;
import android.os.Build;
import android.view.View;
import android.view.ViewAnimationUtils;
import android.view.animation.AccelerateDecelerateInterpolator;


public class AnimationFactory implements IAnimationFactory{
public class FadeAnimationFactory implements IAnimationFactory{

private static final String ALPHA = "alpha";
private static final float INVISIBLE = 0f;
private static final float VISIBLE = 1f;

private final AccelerateDecelerateInterpolator interpolator;

public AnimationFactory() {
public FadeAnimationFactory() {
interpolator = new AccelerateDecelerateInterpolator();
}

@Override
public void fadeInView(View target, long duration, final AnimationStartListener listener) {
public void animateInView(View target, Point point, long duration, final AnimationStartListener listener) {
ObjectAnimator oa = ObjectAnimator.ofFloat(target, ALPHA, INVISIBLE, VISIBLE);
oa.setDuration(duration).addListener(new Animator.AnimatorListener() {
@Override
Expand All @@ -45,7 +48,7 @@ public void onAnimationRepeat(Animator animator) {
}

@Override
public void fadeOutView(View target, long duration, final AnimationEndListener listener) {
public void animateOutView(View target, Point point, long duration, final AnimationEndListener listener) {
ObjectAnimator oa = ObjectAnimator.ofFloat(target, ALPHA, INVISIBLE);
oa.setDuration(duration).addListener(new Animator.AnimatorListener() {
@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@

public interface IAnimationFactory {

void fadeInView(View target, long duration, AnimationStartListener listener);
void animateInView(View target, Point point, long duration, AnimationStartListener listener);

void fadeOutView(View target, long duration, AnimationEndListener listener);
void animateOutView(View target, Point point, long duration, AnimationEndListener listener);

void animateTargetToPoint(MaterialShowcaseView showcaseView, Point point);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,9 @@ public class MaterialShowcaseView extends FrameLayout implements View.OnTouchLis
private boolean mShouldRender = false; // flag to decide when we should actually render
private boolean mRenderOverNav = false;
private int mMaskColour;
private AnimationFactory mAnimationFactory;
private IAnimationFactory mAnimationFactory;
private boolean mShouldAnimate = true;
private boolean mUseFadeAnimation = false;
private long mFadeDurationInMillis = ShowcaseConfig.DEFAULT_FADE_TIME;
private Handler mHandler;
private long mDelayInMillis = ShowcaseConfig.DEFAULT_DELAY;
Expand Down Expand Up @@ -103,9 +104,6 @@ public MaterialShowcaseView(Context context, AttributeSet attrs, int defStyleAtt
private void init(Context context) {
setWillNotDraw(false);

// create our animation factory
mAnimationFactory = new AnimationFactory();

mListeners = new ArrayList<>();

// make sure we add a global layout listener so we can adapt to changes
Expand Down Expand Up @@ -146,8 +144,8 @@ protected void onDraw(Canvas canvas) {
final int width = getMeasuredWidth();
final int height = getMeasuredHeight();

// don't bother drawing if there is nothing to draw on
if(width <= 0 || height <= 0) return;
// don't bother drawing if there is nothing to draw on
if(width <= 0 || height <= 0) return;

// build a new canvas if needed i.e first pass or new dimensions
if (mBitmap == null || mCanvas == null || mOldHeight != height || mOldWidth != width) {
Expand Down Expand Up @@ -219,11 +217,11 @@ public boolean onTouch(View v, MotionEvent event) {

private void notifyOnDisplayed() {

if(mListeners != null){
for (IShowcaseListener listener : mListeners) {
listener.onShowcaseDisplayed(this);
}
}
if(mListeners != null){
for (IShowcaseListener listener : mListeners) {
listener.onShowcaseDisplayed(this);
}
}
}

private void notifyOnDismissed() {
Expand Down Expand Up @@ -426,17 +424,21 @@ private void setDismissOnTargetTouch(boolean dismissOnTargetTouch){
mDismissOnTargetTouch = dismissOnTargetTouch;
}

private void setUseFadeAnimation(boolean useFadeAnimation) {
mUseFadeAnimation = useFadeAnimation;
}

public void addShowcaseListener(IShowcaseListener showcaseListener) {

if(mListeners != null)
mListeners.add(showcaseListener);
if(mListeners != null)
mListeners.add(showcaseListener);
}

public void removeShowcaseListener(MaterialShowcaseSequence showcaseListener) {

if ((mListeners != null) && mListeners.contains(showcaseListener)) {
mListeners.remove(showcaseListener);
}
if ((mListeners != null) && mListeners.contains(showcaseListener)) {
mListeners.remove(showcaseListener);
}
}

void setDetachedListener(IDetachedListener detachedListener) {
Expand All @@ -447,6 +449,10 @@ public void setShape(Shape mShape) {
this.mShape = mShape;
}

public void setAnimationFactory(IAnimationFactory animationFactory) {
this.mAnimationFactory = animationFactory;
}

/**
* Set properties based on a config object
*
Expand Down Expand Up @@ -663,6 +669,11 @@ public Builder renderOverNavigationBar() {
return this;
}

public Builder useFadeAnimation() {
showcaseView.setUseFadeAnimation(true);
return this;
}

public MaterialShowcaseView build() {
if (showcaseView.mShape == null) {
switch (shapeType) {
Expand All @@ -683,6 +694,16 @@ public MaterialShowcaseView build() {
}
}

if (showcaseView.mAnimationFactory == null) {
// create our animation factory
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && !showcaseView.mUseFadeAnimation) {
showcaseView.setAnimationFactory(new CircularRevealAnimationFactory());
}
else {
showcaseView.setAnimationFactory(new FadeAnimationFactory());
}
}

return showcaseView;
}

Expand Down Expand Up @@ -754,7 +775,7 @@ public boolean show(final Activity activity) {
public void run() {

if (mShouldAnimate) {
fadeIn();
animateIn();
} else {
setVisibility(VISIBLE);
notifyOnDisplayed();
Expand All @@ -776,16 +797,16 @@ public void hide() {
mWasDismissed = true;

if (mShouldAnimate) {
fadeOut();
animateOut();
} else {
removeFromWindow();
}
}

public void fadeIn() {
public void animateIn() {
setVisibility(INVISIBLE);

mAnimationFactory.fadeInView(this, mFadeDurationInMillis,
mAnimationFactory.animateInView(this, mTarget.getPoint(), mFadeDurationInMillis,
new IAnimationFactory.AnimationStartListener() {
@Override
public void onAnimationStart() {
Expand All @@ -796,9 +817,9 @@ public void onAnimationStart() {
);
}

public void fadeOut() {
public void animateOut() {

mAnimationFactory.fadeOutView(this, mFadeDurationInMillis, new IAnimationFactory.AnimationEndListener() {
mAnimationFactory.animateOutView(this, mTarget.getPoint(), mFadeDurationInMillis, new IAnimationFactory.AnimationEndListener() {
@Override
public void onAnimationEnd() {
setVisibility(INVISIBLE);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ private void presentShowcaseView(int withDelay) {
.setContentText("This is some amazing feature you should know about")
.setDelay(withDelay) // optional but starting animations immediately in onCreate can make them choppy
.singleUse(SHOWCASE_ID) // provide a unique ID used to ensure it is only shown once
// .useFadeAnimation() // remove comment if you want to use fade animations for Lollipop & up
.show();
}

Expand Down

0 comments on commit 25b345b

Please sign in to comment.