import android.graphics.Color;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
// 聲明一個圓形抖動(縮放)視圖
private CircleShakeView circleShakeView;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 控件的大小(寬/高)
float size = getResources().getDimension(R.dimen.width34px);
// 抖動縮放距離
float shakeDistance = getResources().getDimension(R.dimen.width8px);
// 外圓半徑與內圓半徑直接的距離
float circleDistance = getResources().getDimension(R.dimen.width6px);
// 獲取自定義圓形抖動(縮放)視圖
circleShakeView = findViewById(R.id.circle_shake_view);
// 設置延遲顯示時間(單位:毫秒) 例如延遲20s後再顯示紅點縮放抖動效果
circleShakeView.setDelayTime(1000 * 20);
// 設置圓的抖動(縮放)距離
circleShakeView.setShakeDistance(shakeDistance);
// 設置內圓顏色
circleShakeView.setInsideColor(Color.RED);
// 設置外圓顏色
circleShakeView.setOuterColor(Color.WHITE);
// 設置內圓半徑
circleShakeView.setInsideRadius(size / 2 - circleDistance);
// 設置外圓半徑
circleShakeView.setOuterRadius(size / 2);
}
@Override
protected void onResume() {
super.onResume();
// 開始
circleShakeView.start();
}
@Override
protected void onStop() {
super.onStop();
// 停止
circleShakeView.stop();
}
}
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;
/**
* 自定義圓形抖動(縮放)視圖
*/
public class CircleShakeView extends View {
public CircleShakeView(Context context) {
super(context);
init();
}
public CircleShakeView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public CircleShakeView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
// 外圓半徑
private float outerRadius;
// 內圓半徑(小於外圓半徑)
private float insideRadius;
// 抖動縮放的距離
private float shakeDistance;
// 當前抖動縮放的距離
private float curDistance;
// 外圓顏色
private int outerColor;
// 內圓顏色
private int insideColor;
// 畫筆
private Paint mPaint;
// 延遲抖動時間
private long delayTime;
// 是否允許繪製
private boolean isDraw;
// 是否開始運行
private volatile boolean isRun;
// 聲明一個線程
private Thread mThread;
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (isInEditMode()) {
return;
}
if (!isDraw) {
return;
}
if (outerRadius > insideRadius) {
// 繪製外圓(圓心不變,半徑發生變化)
RectF outerRectF = new RectF();
outerRectF.left = curDistance;
outerRectF.right = outerRadius * 2 - curDistance;
outerRectF.top = curDistance;
outerRectF.bottom = outerRadius * 2 - curDistance;
mPaint.setColor(outerColor);
canvas.drawRoundRect(outerRectF, outerRadius, outerRadius, mPaint);
// 繪製內圓(內圓心跟外圓心保持同一個圓心座標,半徑發生變化)
float size = outerRadius - insideRadius;
RectF insideRectF = new RectF();
insideRectF.left = outerRectF.left + size;
insideRectF.right = outerRectF.right - size;
insideRectF.top = outerRectF.top + size;
insideRectF.bottom = outerRectF.bottom - size;
mPaint.setColor(insideColor);
canvas.drawRoundRect(insideRectF, outerRadius, outerRadius, mPaint);
} else {
// 繪製內圓(圓心不變,半徑發生變化)
RectF rectF = new RectF();
rectF.left = curDistance;
rectF.right = insideRadius * 2 - curDistance;
rectF.top = curDistance;
rectF.bottom = insideRadius * 2 - curDistance;
mPaint.setColor(insideColor);
canvas.drawRoundRect(rectF, insideRadius, insideRadius, mPaint);
}
}
/**
* 初始化數據
*/
private void init() {
isDraw = false;
isRun = false;
curDistance = 0;
delayTime = 0;
insideRadius = 0;
outerRadius = 0;
if (mPaint == null) {
mPaint = new Paint();
// 防抖動
mPaint.setDither(true);
// 抗鋸齒
mPaint.setAntiAlias(true);
// 設置繪畫的連接
mPaint.setStrokeJoin(Paint.Join.ROUND);
}
}
/**
* 開始
*/
public synchronized void start() {
if (isRun == false) {
isRun = true;
mThread = new Thread(new Runnable() {
@Override
public void run() {
if (delayTime > 0) {
// 如果有延遲顯示時間
try {
Thread.sleep(delayTime);
} catch (Exception e) {
e.printStackTrace();
}
delayTime = 0;
}
isDraw = true;
// 如果不想優先顯示最大抖動縮放距離,可省略此句
curDistance = shakeDistance;
while (isRun) {
postInvalidate();
if (curDistance > 0) {
curDistance = 0;
} else {
curDistance = shakeDistance;
}
try {
Thread.sleep(500);
} catch (Exception e) {
e.printStackTrace();
}
}
}
});
mThread.start();
}
}
/**
* 停止
*/
public synchronized void stop() {
try {
isRun = false;
isDraw = false;
// 如果當前Thread不爲空,並且存活,並且還沒有被中斷
if (mThread != null && mThread.isAlive() && !mThread.isInterrupted()) {
mThread.interrupt();
}
} catch (Exception ex) {
} finally {
mThread = null;
}
}
/**
* 設置外圓半徑
*
* @param outerRadius
*/
public void setOuterRadius(float outerRadius) {
this.outerRadius = outerRadius;
}
/**
* 設置內圓半徑
*
* @param insideRadius
*/
public void setInsideRadius(float insideRadius) {
this.insideRadius = insideRadius;
}
/**
* 設置圓的抖動(縮放)距離
*
* @param shakeDistance
*/
public void setShakeDistance(float shakeDistance) {
this.shakeDistance = shakeDistance;
}
/**
* 設置外圓顏色
*
* @param outerColor
*/
public void setOuterColor(int outerColor) {
this.outerColor = outerColor;
}
/**
* 設置內圓顏色
*
* @param insideColor
*/
public void setInsideColor(int insideColor) {
this.insideColor = insideColor;
}
/**
* 設置延遲顯示時間
*
* @param delayTime
*/
public void setDelayTime(long delayTime) {
this.delayTime = delayTime;
}
}
運行效果圖 :