Android 自定义扩散圆

package com.example.cloud;

import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.drawable.BitmapDrawable;
import android.util.AttributeSet;
import android.view.View;

import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;

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

public class SpreadView extends View {
    private Paint centerPaint; //中心圆paint
    private Paint paint; //图片白框
    private int radius = 100; //中心圆半径
    private Paint spreadPaint; //扩散圆paint
    private float centerX;//圆心x
    private float centerY;//圆心y
    private int distance = 1; //每次圆递增间距
    private int maxRadius = 80; //最大圆半径
    private int delayMilliseconds = 30;//扩散延迟间隔,越大扩散越慢
    private List<Integer> spreadRadius = new ArrayList<>();//扩散圆层级数,元素为扩散的距离
    private List<Integer> alphas = new ArrayList<>();//对应每层圆的透明度
    public SpreadView(Context context) {
        this(context, null, 0);
    }
    public SpreadView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }
    public SpreadView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SpreadView, defStyleAttr, 0);
        radius = a.getInt(R.styleable.SpreadView_spread_radius, radius);
        maxRadius = a.getInt(R.styleable.SpreadView_spread_max_radius, maxRadius);
        //中心园的颜色
        int centerColor = a.getColor(R.styleable.SpreadView_spread_center_color, ContextCompat.getColor(context, R.color.a_195092));
        //渐变的颜色
        int spreadColor = a.getColor(R.styleable.SpreadView_spread_spread_color, ContextCompat.getColor(context, R.color.a_496696));
        distance = a.getInt(R.styleable.SpreadView_spread_distance, distance);
        a.recycle();
        centerPaint = new Paint();
        centerPaint.setColor(centerColor);
        centerPaint.setAntiAlias(true);
        //最开始不透明且扩散距离为0
        alphas.add(255);
        spreadRadius.add(0);
        spreadPaint = new Paint();
        spreadPaint.setAntiAlias(true);
        spreadPaint.setAlpha(255);
        spreadPaint.setColor(spreadColor);
        //白色边框
        paint = new Paint();
        paint.setAntiAlias(true);
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(5);
        paint.setColor(Color.WHITE);
    }
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        //圆心位置
        centerX = w / 2;
        centerY = h / 2;
    }
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        for (int i = 0; i < spreadRadius.size(); i++) {
            int alpha = alphas.get(i);
            spreadPaint.setAlpha(alpha);
            int width = spreadRadius.get(i);
            //绘制扩散的圆
            canvas.drawCircle(centerX, centerY, radius + width, spreadPaint);
            //每次扩散圆半径递增,圆透明度递减
            if (alpha > 0 && width < 300) {
                alpha = alpha - distance > 0 ? alpha - distance : 1;
                alphas.set(i, alpha);
                spreadRadius.set(i, width + distance);
            }
        }
        //当最外层扩散圆半径达到最大半径时添加新扩散圆
        if (spreadRadius.get(spreadRadius.size() - 1) > maxRadius) {
            spreadRadius.add(0);
            alphas.add(255);
        }
        //超过8个扩散圆,删除最先绘制的圆,即最外层的圆
        if (spreadRadius.size() >= 8) {
            alphas.remove(0);
            spreadRadius.remove(0);
        }
        //中间的圆
//        canvas.drawCircle(centerX, centerY, radius, centerPaint);
        // 获取资源流

        Resources rec = getResources();
        BitmapDrawable bitmapDrawable = (BitmapDrawable) rec.getDrawable(R.drawable.img);
        Bitmap bitmap = bitmapDrawable.getBitmap();
//        canvas.drawBitmap(bitmap,centerX-(bitmap.getWidth()/2),centerY-(bitmap.getHeight()/2),centerPaint);
        //TODO 可以在中间圆绘制文字或者图片


        //获得图片的宽度
        int width=bitmap.getWidth();
        //获得图片的高度
        int height=bitmap.getHeight();
        //短的二分之一作为半径
        int radius=height>width?width/2:height/2;

        //重新定义的一个画布,这一步很关键
        Paint mPaint = new Paint();
        //抗锯齿
        mPaint.setAntiAlias(true);
//        Bitmap bitmap1 = Bitmap.createBitmap(width,height,
//                Bitmap.Config.ARGB_8888);
//        Canvas bitmapCanvas = new Canvas(bitmap1);
//        super.onDraw(bitmapCanvas);

        //圆形的框
        Bitmap cB = Bitmap.createBitmap(width, height,
                Bitmap.Config.ARGB_8888);
        Canvas cCanv = new Canvas(cB);
        //在控件中间画一个
        cCanv.drawCircle(width/ 2, height/ 2, radius,
                mPaint);
        canvas.drawBitmap(bitmap, centerX-(bitmap.getWidth()/2),centerY-(bitmap.getHeight()/2), mPaint);
        //dst是后画的图形
        mPaint.setXfermode(new PorterDuffXfermode(
                PorterDuff.Mode.DST_IN));
        //一定要用之前的画布,不然会出现边角是黑色
        cCanv.drawBitmap(cB, centerX-(bitmap.getWidth()/2),centerY-(bitmap.getHeight()/2), mPaint);
        //给图形加边框
        canvas.drawCircle(centerX, centerY, radius,
                paint);
        //延迟更新,达到扩散视觉差效果
        postInvalidateDelayed(delayMilliseconds);
    }
}
<declare-styleable name="SpreadView">
    <!--中心圆颜色-->
    <attr name="spread_center_color" format="color" />
    <!--中心圆半径-->
    <attr name="spread_radius" format="integer" />
    <!--扩散圆颜色-->
    <attr name="spread_spread_color" format="color" />
    <!--扩散间距-->
    <attr name="spread_distance" format="integer" />
    <!--扩散最大半径-->
    <attr name="spread_max_radius" format="integer" />
    <!--扩散延迟间隔-->
    <attr name="spread_delay_milliseconds" format="integer" />
</declare-styleable>

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值