本文实例为大家分享了Android实现光点模糊渐变的自旋转圆环效果,供大家参考,具体内容如下
项目中需要实现的效果图如下:
可以这个表盘看到中间部分都是没有什么难点的,主要是周围圆环的三种效果:
1.渐变色
2.尖端的白点模糊效果
3.路径绘制
最终实现的效果图如下:
完美实现了三点要求。
实现思路:
1.首先是黑色底色圆环的绘制(黑色圈是固定不变的)。
2.在绘制好黑色底色圆环之后再绘制渐变色圆弧(蓝绿部分)。
3.最后绘制小星星部分,使用一张模糊图片得到bitmap,并通过PathMeasure进行路径绘制。
代码实现:
/** * Created by jiangzn on 17/2/3. */ public class RoundLightBarView extends ImageView { private int mTotalWidth, mTotalHeight; private int mCenterX, mCenterY; //底色画笔 private Paint mCirclePaint; //进度条画笔 private Paint mProgressPaint; //圆点画笔 private Paint mbitmapPaint; private Matrix mMatrix; // 矩阵,用于对图片进行一些操作 private float[] pos; // 当前点的实际位置 private float[] tan; // 当前点的tangent值,用于计算图片所需旋转的角度 private int mCircleR; private Context mContext; //距离外围的边距 private float interval ; private int startAngle = 1; //球 private Bitmap mLititleBitmap; // 圆点图片 public RoundLightBarView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } public RoundLightBarView(Context context, AttributeSet attrs) { super(context, attrs); mContext = context; interval = DensityUtils.px2dip(mContext, 50); //初始化画笔 initPaint(); //初始化bitmap initBitmap(); } private void initBitmap() { mMatrix=new Matrix(); pos = new float[2]; tan = new float[2]; mLititleBitmap= ((BitmapDrawable) getResources() .getDrawable(R.mipmap.white_round)) .getBitmap(); } private void initPaint() { //画黑底的深色圆画笔 mCirclePaint = new Paint(); //抗锯齿 mCirclePaint.setAntiAlias(true); // 防抖动 mCirclePaint.setDither(true); // 开启图像过滤,对位图进行滤波处理。 mCirclePaint.setFilterBitmap(true); mCirclePaint.setColor(Color.BLACK); //空心圆 mCirclePaint.setStyle(Paint.Style.STROKE); //圆半径 mCircleR = DensityUtils.px2dip(mContext, 20); mCirclePaint.setStrokeWidth(mCircleR); //画彩色圆弧的画笔 mProgressPaint = new Paint(); //抗锯齿 mProgressPaint.setAntiAlias(true); // 防抖动 mProgressPaint.setDither(true); // 开启图像过滤,对位图进行滤波处理。 mProgressPaint.setFilterBitmap(true); mProgressPaint.setColor(Color.BLUE); //空心圆 mProgressPaint.setStyle(Paint.Style.STROKE); //设置笔刷样式为原型 mProgressPaint.setStrokeCap(Paint.Cap.ROUND); //设置圆弧粗 mProgressPaint.setStrokeWidth(mCircleR); //将绘制的内容显示在第一次绘制内容之上 mProgressPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP)); //圆点画笔 mbitmapPaint = new Paint(); mbitmapPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP)); mbitmapPaint.setStyle(Paint.Style.FILL); mbitmapPaint.setAntiAlias(true); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); //canvas去锯齿 canvas.setDrawFilter( new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG)); //画底色圆 canvas.drawCircle(mCenterX, mCenterY, mCenterX - mCircleR - interval, mCirclePaint); //画进度条 int colorSweep[] = {Color.TRANSPARENT, Color.parseColor("#3bbaea"),Color.parseColor("#7ac9d3"),Color.parseColor("#7cc9d0")}; //设置渐变色 sweepGradient = new SweepGradient(mCenterX, mCenterY, colorSweep, null); //按照圆心旋转 Matrix matrix = new Matrix(); matrix.setRotate(startAngle, mCenterX, mCenterY); sweepGradient.setLocalMatrix(matrix); mProgressPaint.setShader(sweepGradient); canvas.drawArc( new RectF(0 + mCircleR + interval, 0 + mCircleR + interval, mTotalWidth - mCircleR - interval, mTotalHeight - mCircleR - interval), 2 + startAngle, 350, false, mProgressPaint); startAngle++; if (startAngle == 360) { startAngle = 1; } //绘制白色小星星 Path orbit = new Path(); //通过Path类画一个90度(180—270)的内切圆弧路径 orbit.addArc( new RectF(0 + mCircleR + interval, 0 + mCircleR + interval, mTotalWidth - mCircleR - interval, mTotalHeight - mCircleR - interval) , 2 + startAngle, 350); // 创建 PathMeasure PathMeasure measure = new PathMeasure(orbit, false); measure.getPosTan(measure.getLength() * 1, pos, tan); mMatrix.reset(); mMatrix.postScale(2,2); mMatrix.postTranslate(pos[0] - mLititleBitmap.getWidth() , pos[1] - mLititleBitmap.getHeight() ); // 将图片绘制中心调整到与当前点重合 canvas.drawBitmap(mLititleBitmap, mMatrix, mbitmapPaint);//绘制球 mbitmapPaint.setColor(Color.WHITE); //绘制实心小圆圈 canvas.drawCircle(pos[0], pos[1], 5, mbitmapPaint); //启动绘制 postInvalidateDelayed(10); } SweepGradient sweepGradient; @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); mTotalWidth = w; mTotalHeight = h; mCenterX = mTotalWidth / 2; mCenterY = mTotalHeight / 2; } }
总结:
总体实现难度并不大,复习了自定义View和canvas的知识点。
其中需要重视的点在绘图层需要注意给画笔添加覆盖模式:setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP)),将绘制的内容显示在第一次绘制的内容之上,还有一个比较难的点是PathMeasure进行对bitmap的路径收集和方向控制并绘制小星星的过程:
// 创建 PathMeasure PathMeasure measure = new PathMeasure(orbit, false); measure.getPosTan(measure.getLength() * 1, pos, tan); mMatrix.reset(); mMatrix.postScale(2,2); mMatrix.postTranslate(pos[0] - mLititleBitmap.getWidth() , pos[1] - mLititleBitmap.getHeight() ); // 将图片绘制中心调整到与当前点重合 canvas.drawBitmap(mLititleBitmap, mMatrix, mbitmapPaint);//绘制球 mbitmapPaint.setColor(Color.WHITE); //绘制实心小圆圈 canvas.drawCircle(pos[0], pos[1], 5, mbitmapPaint);