package com.joker.rxweather.ui.widget;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Path;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.View;
import android.widget.FrameLayout;
import com.joker.rxweather.ui.animation.RevealAnimator;
import com.joker.rxweather.ui.animation.SupportAnimator;
import com.joker.rxweather.ui.animation.ViewAnimationUtils;
public class RevealFrameLayout extends FrameLayout implements RevealAnimator {
private Path mRevealPath;
private final Rect mTargetBounds = new Rect();
private RevealAnimator.RevealInfo mRevealInfo;
private boolean mRunning;
private float mRadius;
public RevealFrameLayout(Context context) {
this(context, null);
}
public RevealFrameLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public RevealFrameLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mRevealPath = new Path();
}
@Override public void onRevealAnimationStart() {
this.mRunning = true;
}
@Override public void onRevealAnimationEnd() {
this.mRunning = false;
RevealFrameLayout.this.invalidate(mTargetBounds);
}
@Override public void onRevealAnimationCancel() {
RevealFrameLayout.this.onRevealAnimationEnd();
}
/**
* Circle radius size
*
* @hide
*/
@Override public void setRevealRadius(float radius) {
this.mRadius = radius;
mRevealInfo.getTarget().getHitRect(mTargetBounds);
/*只刷新固定区域,其他区域不变*/
RevealFrameLayout.this.invalidate(mTargetBounds);
}
/**
* Circle radius size
*
* @hide
*/
@Override public float getRevealRadius() {
return mRadius;
}
/**
* @hide
*/
@Override public void initRevealInfo(RevealInfo info) {
mRevealInfo = info;
}
/**
* @hide
*/
@Override public SupportAnimator startReverseAnimation() {
if (mRevealInfo != null && mRevealInfo.hasTarget() && !mRunning) {
return ViewAnimationUtils.createCircularReveal(mRevealInfo.getTarget(), mRevealInfo.centerX,
mRevealInfo.centerY, mRevealInfo.endRadius, mRevealInfo.startRadius);
}
return null;
}
@Override protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
if (mRunning && child == mRevealInfo.getTarget()) {
final int state = canvas.save();
mRevealPath.reset();
mRevealPath.addCircle(mRevealInfo.centerX, mRevealInfo.centerY, mRadius, Path.Direction.CW);
canvas.clipPath(mRevealPath);
boolean isInvalided = super.drawChild(canvas, child, drawingTime);
/*恢复为之前堆栈保存的编号为int的Canvas状态*/
canvas.restoreToCount(state);
return isInvalided;
}
return super.drawChild(canvas, child, drawingTime);
}
}