角度大小,以此图为标准
当然中间的圆环可能看起来是两个圆之间的区域,开始我以为是要画2个园,没想到只要把画笔设置一下就好了
circlePaint.setStrokeWidth(60.0f);
上面就是两个圆与圆之间(圆环)的区域。
值得一提的是canvas的这个画圆的方法设计的很强大,还可以画椭圆的,就看你圆外接的矩形的宽高了。
2)而中间的那个刻度线,采用的是
Canvas.drawLine(float startX, float startY, float stopX, float stopY, Paint paint)方法
其中参数的意义为
startX:线起始点的x轴位置
startY:线起始点的y轴位置
stopX:线结束点的x轴位置
stopY:线结束点的y轴位置
paint:画线的画笔
画了一根刻度线后,采用旋转的是
Canvas.rotate(float degrees, float px, float py)方法
其中参数意义为
degrees: 每次要旋转的角度
px: 旋转的圆心x轴坐标
py: 旋转的圆心y轴坐标
3)圆盘中间的文字的采用的是
canvas的Canvas.drawText(String text, float x, float y, Paint paint)方法
参数意义这里就不说了,应该猜的出的。
4)中间的指示针采用的是一个小实心圆,采用的是
drawCircle(float cx, float cy, float radius,Paint paint)方法
参数意义
cx: 中心点的x轴
cy: 中心点的y轴
radius: 半径
paint: Paint画笔对象
5)中间的颜色渐变,采用的是SweepGradient
SweepGradient(float cx, float cy, int[] colors, float[] positions)
参数意义
cx:渐变圆心的x轴坐标
cy:渐变圆心的y轴坐标
colors[]: 颜色数组
positions: 颜色分隔的位置数组,可以为null,系统自己分
2. 绘制的计算过程
好了,基本的绘制内容就是这么多了,其他的就是计算过程了,这些都是在onDraw()内完成的。
先说圆环的绘制的计算过程吧。
0)在绘制之前,你首先得准备好笔
工欲善其事必先利其器。初始化画笔的工作是在两个参数的构造方法里的,因为只需初始化一次,而onDraw()方法会随着绘制过程很可能会不断的调用,所以初始化的工作放在构造方法里
public MyCircleView(Context context, AttributeSet attrs) {
super(context, attrs);
screenWidth=MeasureUtil.getScreenWidth(context);
screenHeight=MeasureUtil.getScreenHeight(context);
Log.e("My----->", "2 "+screenWidth+" "+screenHeight);
initPaint();
}
private void initPaint() {
linePaint = new Paint();
linePaint.setColor(Color.CYAN);
linePaint.setStyle(Style.FILL);
linePaint.setAntiAlias(true);
linePaint.setStrokeWidth(1.0f);
textPaint = new Paint();
textPaint.setColor(Color.BLACK);
textPaint.setTextAlign(Paint.Align.CENTER);
textPaint.setAntiAlias(true);
textPaint.setTextSize(30);
centerTextPaint = new Paint();
centerTextPaint.setColor(Color.BLUE);
centerTextPaint.setTextAlign(Paint.Align.CENTER);
centerTextPaint.setAntiAlias(true);
centerTextPaint.setTextSize(80);
circlePaint = new Paint();
circlePaint.setColor(Color.WHITE);
circlePaint.setAntiAlias(true);
circlePaint.setStyle(Paint.Style.STROKE);
circlePaint.setStrokeCap(Cap.ROUND);//实现末端圆弧
circlePaint.setStrokeWidth(60.0f);
indicatorPaint=new Paint();
indicatorPaint.setColor(0xFFF7F709);
indicatorPaint.setAntiAlias(true);
indicatorPaint.setStyle(Paint.Style.FILL);
// 着色的共有270度,这里设置了12个颜色均分360度s
int[] colors = { 0xFFD52B2B, 0xFFf70101, 0xFFFFFFFF, 0xFFFFFFFF,
0xFF6AE2FD, 0xFF8CD0E5, 0xFFA3CBCB, 0xFFD1C299, 0xFFE5BD7D,
0xFFAA5555, 0xFFBB4444, 0xFFC43C3C };
mCenter = screenWidth / 2;
mRadius = screenWidth/ 2 - 100;
// 渐变色
mSweepGradient = new SweepGradient(mCenter, mCenter, colors, null);
// 构建圆的外切矩形
mRectF = new RectF(mCenter - mRadius, mCenter - mRadius, mCenter
+ mRadius, mCenter + mRadius);
}
1)圆环设计的宽度为wrap_content,故需要重写onMeasure方法,告诉画笔它的外接圆矩形的宽度
// 因为自定义的空间的高度设置的是wrap_content,所以我们必须要重写onMeasure方法去测量高度,否则布局界面看不到
// 其他控件(被覆盖)
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(measureWidth(widthMeasureSpec),
measureHeight(heightMeasureSpec));
}
测量方法
/**
* 测量宽度
*
* @param widthMeasureSpec
* @return
*/
private int measureWidth(int widthMeasureSpec) {
int mode = MeasureSpec.getMode(widthMeasureSpec);
int size = MeasureSpec.getSize(widthMeasureSpec);
// 默认宽高;
defaultValue=screenWidth;
switch (mode) {
case MeasureSpec.AT_MOST:
// 最大值模式 当控件的layout_Width或layout_height属性指定为wrap_content时
Log.e("cmos---->", "size " + size + " screenWidth " + screenWidth);
size = Math.min(defaultValue, size);
break;
case MeasureSpec.EXACTLY:
// 精确值模式
// 当控件的android:layout_width=”100dp”或android:layout_height=”match_parent”时
break;
default:
size = defaultValue;
break;
}
defaultValue = size;
return size;
}
圆环的外接矩形
mCenter = screenWidth / 2;//圆心坐标
mRadius = screenWidth/ 2 - 100;//圆的半径 留了100dp,是为了给绘制文字留空间
// 构建圆的外切矩形
mRectF = new RectF(mCenter - mRadius, mCenter - mRadius, mCenter+ mRadius, mCenter + mRadius);
canvas.drawArc(mRectF, 135, 270, false, circlePaint);
这样,圆环就绘制计算完成。
2)刻度值的计算绘制
因为整个圆盘是270度,设置每3度画一刻度线,故要绘制90根,这里选择的是以圆盘正上方的刻度线为基准刻度,将其绘制好后,然后进行旋转绘制,这样绘制过程就Ok了
for (int i = 0; i < 120; i++) {
if (i <= 45 || i >= 75) {//空白部分不用绘制刻度
canvas.drawLine(mCenter, mCenter - mRadius - 30, mCenter,
mCenter - mRadius + 30, linePaint);//30是因为设置的填充圆环的宽度为60的原因
}
canvas.rotate(3, mCenter, mCenter);
}
3)圆盘刻度值计算绘制
这个就稍微复杂一点了,不过也还好,计算过程无非就是高中三角值公式的使用过程,在此之前,你先要了解角度的起始值和象限。
其中黄线的长度即是圆环的半径
// x代表文字的x轴距离圆心x轴的距离 因为刚好是45度,所以文字x轴值和y值相等
int x = 0;
// 三角形的斜边
int c = mRadius + 60 / 2 + 40;// 40代表这个字距离圆外边的距离</span>
// 因为是每45度写一次文字,故根据到圆心的位置,利用三角形的公式,可以算出文字的坐标值
x = (int) Math.sqrt((c * c / 2));
canvas.drawText("10", mCenter - x, mCenter + x, textPaint);
canvas.drawText("15", mCenter - c, mCenter,
textPaint);
canvas.drawText("20", mCenter - x, mCenter - x,
textPaint);
canvas.drawText("25", mCenter, mCenter - c,
textPaint);
canvas.drawText( "30", mCenter + x, mCenter - x,
textPaint);
canvas.drawText( "35", mCenter + c, mCenter,
textPaint);
canvas.drawText( "40", mCenter + x, mCenter + x,
textPaint);
可以看出,这里刻度值我把它写死了,当然,你也可以暴露一个方法,让调用者去设置起始值和结束值。
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
更多学习和讨论,欢迎加入我们!
有许多来自一线的技术大牛,也有在小厂或外包公司奋斗的码农,我们致力打造一个平等,高质量的Android交流圈子,不一定能短期就让每个人的技术突飞猛进,但从长远来说,眼光,格局,长远发展的方向才是最重要的。
这里有2000+小伙伴,让你的学习不寂寞~·
一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!
AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算
也有在小厂或外包公司奋斗的码农,我们致力打造一个平等,高质量的Android交流圈子,不一定能短期就让每个人的技术突飞猛进,但从长远来说,眼光,格局,长远发展的方向才是最重要的。
这里有2000+小伙伴,让你的学习不寂寞~·
一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!
AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算