Android-- 自定義圓線圓環縮放

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;

import com.xtc.uvmeasure.util.DensityUtil;

import java.util.ArrayList;
import java.util.List;

public class RippleView extends View {

    private Context mContext;

    // 畫筆對象
    private Paint mPaint;

    // View寬
    private float mWidth;

    // View高
    private float mHeight;

    // 聲波的圓圈集合
    private List<Circle> mRipples;

    private int sqrtNumber;

    // 圓圈擴散的速度
    private int mSpeed;

    // 圓圈之間的密度
    private int mDensity;

    // 圓圈的顏色
    private int mColor;

    // 圓圈是否爲填充模式
    private boolean mIsFill;

    // 圓圈是否爲漸變模式
    private boolean mIsAlpha;

    public RippleView(Context context) {
        this(context, null);
    }

    public RippleView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public RippleView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        // 獲取用戶配置屬性
        TypedArray tya = context.obtainStyledAttributes(attrs, R.styleable.mRippleView);
        mColor = tya.getColor(R.styleable.mRippleView_cColor, Color.BLUE);
        mSpeed = 2;
        mDensity = tya.getInt(R.styleable.mRippleView_cDensity, 10);
        mIsFill = tya.getBoolean(R.styleable.mRippleView_cIsFill, false);
        mIsAlpha = tya.getBoolean(R.styleable.mRippleView_cIsAlpha, false);
        tya.recycle();

        init();
    }

    private void init() {
        mContext = getContext();

        // 設置畫筆樣式
        mPaint = new Paint();
        mPaint.setColor(mColor);
        mPaint.setStrokeWidth(DensityUtil.dip2px(mContext, 1));
        if (mIsFill) {
            mPaint.setStyle(Paint.Style.FILL);
        } else {
            mPaint.setStyle(Paint.Style.STROKE);
        }
        mPaint.setStrokeCap(Paint.Cap.ROUND);
        mPaint.setAntiAlias(true);

        // 添加第一個圓圈
        mRipples = new ArrayList<>();
        Circle c = new Circle(120, 255);
        mRipples.add(c);

        mDensity = DensityUtil.dip2px(mContext, mDensity);

        // 設置View的圓爲半透明
        setBackgroundColor(Color.TRANSPARENT);
    }

    private boolean isDrow ;

    public boolean isDrow() {
        return isDrow;
    }

    public void setDrow(boolean drow) {
        isDrow = drow;
    }

    public List<Circle> getmRipples() {
        return mRipples;
    }

    @Override
    public void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        // 內切正方形
        drawInCircle(canvas);

        // 外切正方形
//         drawOutCircle(canvas);
    }

    /**
     * 圓到寬度
     *
     * @param canvas
     */
    private void drawInCircle(Canvas canvas) {

        if (isDrow()) {
            canvas.save();

            // 處理每個圓的寬度和透明度
            for (int i = 0; i < mRipples.size(); i++) {
                Circle c = mRipples.get(i);
                mPaint.setAlpha(c.alpha);// (透明)0~255(不透明)
                canvas.drawCircle(mWidth / 2, mHeight / 2, c.width - mPaint.getStrokeWidth(), mPaint);

                // 當圓超出View的寬度後刪除
                if (c.width > mWidth/2) {
                    mRipples.remove(i);
                } else {
                    // 計算不透明的數值,這裏有個小知識,就是如果不加上double的話,255除以一個任意比它大的數都將是0
                    if (mIsAlpha) {
                        double alpha = 255 - c.width * (255 / ((double) mWidth / 2));
                        c.alpha = (int) alpha;
                    }
             
                        // 修改這個值控制速度
                        c.width += mSpeed;
                }
            }

            // 裏面添加圓
            if (mRipples.size() > 0) {
                // 控制第二個圓出來的間距
                if (mRipples.get(mRipples.size() - 1).width > DensityUtil.dip2px(mContext, mDensity)) {
                    mRipples.add(new Circle(0, 255));
                }
            }

            invalidate();

            canvas.restore();

        }
    }

    /**
     * 圓到對角線
     *
     * @param canvas
     */
    private void drawOutCircle(Canvas canvas) {
        canvas.save();

        // 使用勾股定律求得一個外切正方形中心點離角的距離
        sqrtNumber = (int) (Math.sqrt(mWidth * mWidth + mHeight * mHeight) / 2);

        // 變大
        for (int i = 0; i < mRipples.size(); i++) {

            // 啓動圓圈
            Circle c = mRipples.get(i);
            mPaint.setAlpha(c.alpha);// (透明)0~255(不透明)
            canvas.drawCircle(mWidth / 2, mHeight / 2, c.width - mPaint.getStrokeWidth(), mPaint);

            // 當圓超出對角線後刪掉
            if (c.width > sqrtNumber) {
                mRipples.remove(i);
            } else {
                // 計算不透明的度數
                double degree = 255 - c.width * (255 / (double) sqrtNumber);
                c.alpha = (int) degree;
                c.width += 1;
            }
        }

        // 裏面添加圓
        if (mRipples.size() > 0) {
            // 控制第二個圓出來的間距
            if (mRipples.get(mRipples.size() - 1).width == 50) {
                mRipples.add(new Circle(0, 255));
            }
        }
        invalidate();
        canvas.restore();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int myWidthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
        int myWidthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
        int myHeightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
        int myHeightSpecSize = MeasureSpec.getSize(heightMeasureSpec);

        // 獲取寬度
        if (myWidthSpecMode == MeasureSpec.EXACTLY) {
            // match_parent
            mWidth = myWidthSpecSize;
        } else {
            // wrap_content
            mWidth = DensityUtil.dip2px(mContext, 120);
        }

        // 獲取高度
        if (myHeightSpecMode == MeasureSpec.EXACTLY) {
            mHeight = myHeightSpecSize;
        } else {
            // wrap_content
            mHeight = DensityUtil.dip2px(mContext, 120);
        }

        // 設置該view的寬高
        setMeasuredDimension((int) mWidth, (int) mHeight);
    }

    class Circle {
        Circle(int width, int alpha) {
            this.width = width;
            this.alpha = alpha;
        }

        int width;

        int alpha;
    }

}

自定義屬性


    <!--漣漪控件屬性-->
    <declare-styleable name="mRippleView">
        <attr name="cColor" format="color"/>
        <attr name="cSpeed" format="integer"/>
        <attr name="cDensity" format="integer"/>
        <attr name="cIsFill" format="boolean"/>
        <attr name="cIsAlpha" format="boolean"/>
    </declare-styleable>

佈局文件使用

 <com.xxx.xxx.RippleView
            android:id="@+id/rpv_ripple"
            android:layout_width="155dp"
            android:layout_height="155dp"
            android:layout_centerInParent="true"
            app:cColor="@color/q"
            app:cDensity="8"
            app:cIsAlpha="false" />

頁面調用

RippleView diffuseView = (RippleView) findViewById(R.id.rpv_ripple);
// 點擊則開始縮放  自己寫點擊事件吧...
boolean drow = diffuseView.isDrow();
  if (drow) {
      diffuseView.setDrow(false);
  }else{
	diffuseView.setDrow(true);
	diffuseView.invalidate();
  }

原文地址:https://blog.csdn.net/zhuwentao2150/article/details/79452735

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章