Created
March 8, 2019 14:01
-
-
Save piyush-malaviya/350a0d1b6265958ae7c7aeaa3208edfa to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import android.animation.ObjectAnimator; | |
import android.animation.TypeEvaluator; | |
import android.content.Context; | |
import android.graphics.Canvas; | |
import android.graphics.Color; | |
import android.graphics.Paint; | |
import android.support.annotation.NonNull; | |
import android.support.annotation.Nullable; | |
import android.util.AttributeSet; | |
import android.view.animation.LinearInterpolator; | |
import android.widget.FrameLayout; | |
public class RadarView extends FrameLayout { | |
private static final int DEFAULT_RIPPLE_COLOR = Color.parseColor("#C21923"); | |
private static final int DEFAULT_RIPPLE_NUM = 4; | |
/** | |
* The default minimum diameter | |
*/ | |
private static final int MINE_SIZE = 900; | |
/** | |
* The color of the ripple in the animation | |
*/ | |
private int mRippleColor; | |
/** | |
* The number of ripples in the animation | |
*/ | |
private int mRippleNum; | |
private int currentProgress = 0; | |
/** | |
* Animation execution time | |
*/ | |
private int mTotalTime = 100 * 1000; | |
private int mPeriod = 40; | |
/** | |
* Custom estimator | |
*/ | |
private TypeEvaluator mProgressEvaluator = new TypeEvaluator() { | |
@Override | |
public Object evaluate(float fraction, Object startValue, Object endValue) { | |
fraction = (fraction * mTotalTime / mPeriod) % 100; | |
return fraction; | |
} | |
}; | |
/** | |
* Is the ripple animation effect in progress? | |
*/ | |
private boolean isAnimationRunning = false; | |
private int mCenterX; | |
private int mCenterY; | |
private int mRadius; | |
private Paint mPaint; | |
private ObjectAnimator mAnimator; | |
public RadarView(@NonNull Context context) { | |
this(context, null); | |
} | |
public RadarView(@NonNull Context context, @Nullable AttributeSet attrs) { | |
this(context, attrs, 0); | |
} | |
public RadarView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { | |
super(context, attrs, defStyleAttr); | |
this.setWillNotDraw(false); | |
mRippleColor = DEFAULT_RIPPLE_COLOR; | |
mRippleNum = DEFAULT_RIPPLE_NUM; | |
init(); | |
initAnimation(); | |
} | |
private void init() { | |
mPaint = new Paint(); | |
mPaint.setAntiAlias(true); | |
mPaint.setStyle(Paint.Style.FILL); | |
mPaint.setColor(mRippleColor); | |
} | |
private void initAnimation() { | |
mAnimator = ObjectAnimator.ofInt(this, "currentProgress", 0, 100); | |
// Cycle times, wireless loop | |
mAnimator.setRepeatCount(ObjectAnimator.INFINITE); | |
mAnimator.setRepeatMode(ObjectAnimator.RESTART); | |
mAnimator.setInterpolator(new LinearInterpolator()); | |
mAnimator.setEvaluator(mProgressEvaluator); | |
mAnimator.setDuration(mTotalTime); | |
startRippleAnimation(); | |
} | |
public int getCurrentProgress() { | |
return currentProgress; | |
} | |
public void setCurrentProgress(int currentProgress) { | |
this.currentProgress = currentProgress; | |
this.invalidate(); | |
} | |
public void startRippleAnimation() { | |
if (!isAnimationRunning) { | |
mAnimator.start(); | |
isAnimationRunning = true; | |
} | |
} | |
public void stopRippleAnimation() { | |
if (isAnimationRunning) { | |
mAnimator.end(); | |
isAnimationRunning = false; | |
} | |
} | |
@Override | |
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { | |
//super.onMeasure(widthMeasureSpec, heightMeasureSpec); | |
int resultWidth = 0; | |
int modeWidth = MeasureSpec.getMode(widthMeasureSpec); | |
int sizeWidth = MeasureSpec.getSize(widthMeasureSpec); | |
if (modeWidth == MeasureSpec.EXACTLY) { | |
resultWidth = sizeWidth; | |
} else { | |
resultWidth = MINE_SIZE; | |
if (modeWidth == MeasureSpec.AT_MOST) { | |
resultWidth = Math.min(resultWidth, sizeWidth); | |
} | |
} | |
int resultHeight = 0; | |
int modeHeight = MeasureSpec.getMode(heightMeasureSpec); | |
int sizeHeight = MeasureSpec.getSize(heightMeasureSpec); | |
if (modeHeight == MeasureSpec.EXACTLY) { | |
resultHeight = sizeHeight; | |
} else { | |
resultHeight = MINE_SIZE; | |
if (modeHeight == MeasureSpec.AT_MOST) { | |
resultHeight = Math.min(resultHeight, sizeHeight); | |
} | |
} | |
mCenterX = resultWidth / 2; | |
mCenterY = resultHeight / 2; | |
mRadius = Math.max(resultWidth, resultHeight) / 3; | |
setMeasuredDimension(resultWidth, resultHeight); | |
} | |
@Override | |
protected void onDraw(Canvas canvas) { | |
int progress = 0; | |
//canvas.drawColor(mPaint.getColor()); | |
for (int i = 0; i < mRippleNum; i++) { | |
progress = (currentProgress + i * 100 / (mRippleNum)) % 100; | |
//if (mode == 1) | |
//progress = 100 - progress; | |
int alpha = 255 - 255 * (progress) / 100 - 50; | |
if (alpha < 10) { | |
alpha = 10; | |
} | |
mPaint.setAlpha(alpha); | |
canvas.drawCircle(mCenterX, mCenterY, mRadius * progress / 100, mPaint); | |
} | |
mPaint.setAlpha(255); | |
super.onDraw(canvas); | |
} | |
@Override | |
protected void onDetachedFromWindow() { | |
super.onDetachedFromWindow(); | |
if (isAnimationRunning) stopRippleAnimation(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment