android 水波圆形,Android项目实战手把手教你画圆形水波纹loadingview

本文介绍了如何利用贝塞尔曲线和PorterDuffXfermode实现一个动态的圆形波纹LoadingView,通过模式切换和贝塞尔曲线模拟水波效果,适用于内存使用进度显示等场景。步骤包括设置属性、绘制圆和矩形、使用Xfermode、以及结合百分比展示复杂效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文实例讲解的是如何画一个满满圆形水波纹loadingview,这类效果应用场景很多,比如内存占用百分比之类的,分享给大家供大家参考,具体内容如下

效果图如下:

49e056d5b284e28beb7d0e9d41d8c50d.gif

预备的知识:

1.贝塞尔曲线    如果你不了解,可以来这里进行基础知识储备:神奇的贝塞尔曲线

2.Paint.setXfermode()  以及PorterDuffXfermode

千万不要被这个b的名字吓到,不熟悉看到可能会认为很难记,其实 只要站在巨人的丁丁上 还是很简单的。

好了 废话不多说 ,跟我一步步来做一个炫酷的view吧。

首先给一些属性,在构造器里初始化(不要再ondraw new东西不要再ondraw new东西不要再ondraw new东西不要再ondraw new东西)

//绘制波纹

private Paint mWavePaint;

private PorterDuffXfermode mMode = new PorterDuffXfermode(PorterDuff.Mode.XOR);//设置mode 为XOR

//绘制圆

private Paint mCirclePaint;

private Canvas mCanvas;//我们自己的画布

private Bitmap mBitmap;

private int mWidth;

private int mHeight;

public WaveLoadingView(Context context) {

this(context,null);

}

public WaveLoadingView(Context context, AttributeSet attrs) {

this(context, attrs,0);

}

public WaveLoadingView(Context context, AttributeSet attrs, int defStyleAttr) {

super(context, attrs, defStyleAttr);

mWavePaint = new Paint();

mWavePaint.setColor(Color.parseColor("#33b5e5"));

mCirclePaint = new Paint();

mCirclePaint.setColor(Color.parseColor("#99cc00"));

}

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

int widthSize = MeasureSpec.getSize(widthMeasureSpec);

int widthMode = MeasureSpec.getMode(widthMeasureSpec);

int heightSize = MeasureSpec.getSize(heightMeasureSpec);

int heightMode = MeasureSpec.getMode(heightMeasureSpec);

if (widthMode == MeasureSpec.EXACTLY) {

mWidth = widthSize;

}

if (heightMode == MeasureSpec.EXACTLY) {

mHeight = heightSize;

}

setMeasuredDimension(mWidth, mHeight);

mBitmap = Bitmap.createBitmap(300,300, Bitmap.Config.ARGB_8888); //生成一个bitmap

mCanvas = new Canvas(mBitmap);//讲bitmp放在我们自己的画布上,实际上mCanvas.draw的时候 改变的是这个bitmap对象

}

然后,我们给他绘制一点东西,用来介绍PorterDuffXfermode

@Override

protected void onDraw(Canvas canvas) {

mCanvas.drawCircle(100,100,50,mCirclePaint);

mCanvas.drawRect(100,100,200,200,mWavePaint);

canvas.drawBitmap(mBitmap,0,0,null);

super.onDraw(canvas);

}

嗯,可以看到 是我们现在自己的画布上铺了一个bitmap(这里可以理解canvas为桌子  bitmap为画纸,我们在bimap上画画), 然后在bitmap上画了 一个圆,和一个矩形。最后把我们的mBitmap画到系统的画布上(显示到屏幕上),得到了以下效果。

然后我们用setXfermode()方法给他设置一个mode,这里设置XOR。

534683473ec04f6cc042e1c16f59b113.png

可以发现! 相交的地方消失了! 是不是很神奇。

在改一个mode 试试

private PorterDuffXfermode mMode = new PorterDuffXfermode(PorterDuff.Mode.DST_OVER);

5f3f91c1ae2e0480a27eb03c722daeaf.png

可以看到 圆形跑到了矩形上面来。  然后巨人给我们总结各个模式如了下图,这里给一个说明dst为先画的 src为后画的:.

af6b6582a5b47f3611fe3fba805e1fdd.png

大家可以根据这个规律试一下。

现在,我们把圆和矩形重叠。模式去掉。

protected void onDraw(Canvas canvas) {

//dst

mCanvas.drawCircle(150,150,50,mCirclePaint);

/ mWavePaint.setXfermode(mMode);

//src

mCanvas.drawRect(100,100,200,200,mWavePaint);

canvas.drawBitmap(mBitmap,0,0,null);

super.onDraw(canvas);

}

我的圆怎么没了。。  其实圆是被覆盖掉了。 然后我们想实现一个效果,就是在圆的范围内,显示矩形的内容,该怎么做呢。自己照着图找找吧哈哈。

我们要实现的是一个圆形的水波纹那种loadingview。。首要就是实现这个水波纹。

这时候贝塞尔曲线就派上用场了。这里采用三阶贝塞尔, 不停地改变X 模拟水波效果。

if (x > 50) {

isLeft = true;

} else if (x < 0) {

isLeft = false;

}

if (y > -50) { //大于-50是因为辅助点是50 为了让他充满整个屏幕

y--;

} if (isLeft) {

x = x - 1;

} else {

x = x + 1;

}

mPath.reset();

mPath.moveTo(0, y);

mPath.cubicTo(100 + x*2, 50 + y, 100 + x*2, y-50, mWidth, y);//前两个参数是辅助点

mPath.lineTo(mWidth, mHeight);//充满整个画布

mPath.lineTo(0, mHeight);//充满整个画布

mPath.close();

之后用mCanvas来绘制这个bitmap,要注意的是 绘制之前要清空mBitmap,不然path会重叠

mBitmap.eraseColor(Color.parseColor("#00000000"));

//dst

mCanvas.drawPath(mPath, mPaint);

canvas.drawBitmap(mBitmap, 0, 0, null);

postInvalidateDelayed(10);

哈,水波效果出来了。   接着想办法让他画到一个圆形中。 首先绘制一个圆

mCanvas.drawCircle(mWidth / 2, mHeight / 2, mWidth / 2, mSRCPaint);

现在让我们回到刚才的问题,如何在dst的范围内绘制src呢。。。答案是。。SRC_IN 你找对了吗。添加模式

//dst

mCanvas.drawCircle(mWidth / 2, mHeight / 2, mWidth / 2, mSRCPaint);

mPaint.setXfermode(mMode);

//src

mCanvas.drawPath(mPath, mPaint);

canvas.drawBitmap(mBitmap, 0, 0, null);

是不是有点感觉了。如果不这样做 就需要考虑好多问题。动态计算沿着圆弧x,y坐标  计算arcTo的范围。

完善一下,添加一个percent来代表进度,让y来根据percent动态改变

y = (int) ((1-mPercent /100f) *mHeight);

添加setPercent方法

public void setPercent(int percent){

mPercent = percent;

}

画上百分比的文字。

String str = mPercent + "%";

float txtLength = mTextPaint.measureText(str);

canvas.drawText(mPercent + "%", mWidth / 2-txtLength/2, mHeight / 2, mTextPaint);

然后配合seekBar,最后改改字体大小  画笔透明度。 添加个背景图 就成了效果图上的效果。

是不是很有趣,大家可以动手实现一下!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值