1. 程式人生 > >android自定義圓形抖動(縮放)檢視

android自定義圓形抖動(縮放)檢視

轉載請註明出處:https://blog.csdn.net/u011038298/article/details/84786307 

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;
    }

}

 

效果圖 :    

關於文中所取的px值,詳情參見android解析度適配