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)圆盘刻度值计算绘制
这个就稍微复杂一点了,不过也还好,计算过程无非就是高中三角值公式的使用过程,在此之前,你先要了解角度的起始值和象限。
![](https://img-blog.csdn.net/20160730192029110?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
其中黄线的长度即是圆环的半径
// 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);
可以看出,这里刻度值我把它写死了,当然,你也可以暴露一个方法,让调用者去设置起始值和结束值。
4)中间的小圆点指示器
了解了文字的计算过程后,再来算这个的画,就相对容易了很多。
currentScanDegree=(getCurrentDegree()-10)*3;
int insideIndicator=mRadius-60;//离圆环的距离
if (currentScanDegree<=45) {//第三象限
canvas.drawCircle((float)(mCenter-insideIndicator*Math.sin(Math.PI*(currentScanDegree+45)/180)),(float)(mCenter+insideIndicator*Math.cos(Math.PI*(currentScanDegree+45)/180)), 10, indicatorPaint);
}else if(45<currentScanDegree&¤tScanDegree<=135) {//第二象限
canvas.drawCircle((float)(mCenter-insideIndicator*Math.cos(Math.PI*(currentScanDegree-45)/180)),(float)(mCenter-insideIndicator*Math.sin(Math.PI*(currentScanDegree-45)/180)), 10, indicatorPaint);
}else if (135<currentScanDegree&¤tScanDegree<=225) {//第一象限
canvas.drawCircle((float)(mCenter+insideIndicator*Math.sin(Math.PI*(currentScanDegree-135)/180)),(float)(mCenter-insideIndicator*Math.cos(Math.PI*(currentScanDegree-135)/180)), 10, indicatorPaint);
}else if(225<currentScanDegree&¤tScanDegree<=270){//第四象限
canvas.drawCircle((float)(mCenter+insideIndicator*Math.cos(Math.PI*(currentScanDegree-225)/180)),(float)(mCenter+insideIndicator*Math.sin(Math.PI*(currentScanDegree-225)/180)), 10, indicatorPaint);
}
过程也就不解释了,同3的过程一致
5)中间文字的具体温度值
这个是根据扫描的角度值进行换算的
canvas.drawText((currentScanDegree/9+10)+“℃”, mCenter, mCenter, centerTextPaint);
相信了解了上面的过程,这个就很简单了吧。
到此整个计算过程就全部完成了。
那么,怎么让我们的view动起来呢,有点动态感,对此,我们只要不断的改变扫描的度数就好,对此我设定了3个值,最低温度值(起始)、最高温度值(结束)、当前温度。
点击按钮让其重绘。具体代码如下
private void showDegree(final int minDegree, final int maxDegree, final int currentDegree) {
myCircleView.setMinDegree(minDegree);
new Thread(new Runnable() {
@Override
public void run() {
for (int i = minDegree; i < (maxDegree-minDegree)*3+minDegree; i++) {
try {
Thread.sleep(30);
} catch (InterruptedException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
myCircleView.setMaxDegree(i);
myCircleView.postInvalidate();
}
for (int j = 10; j<=(currentDegree-10)*3+10; j++) {
if (j<=(currentDegree-10)*3+10) {//23*3+10=79
myCircleView.setCurrentDegree(j);
}
myCircleView.postInvalidate();
}
}
}).start();
}
上面要注意的地方是要注意使用postInvalidata()方法,因为我们是在子线程操控UI线程,所以不能单纯的用invalidata()方法。
**3\. view添加滑动触摸事件**
最后作为扩展,我为此控件添加了滑动触摸事件
代码如下:
@Override
public boolean onTouchEvent(MotionEvent event) {
// TODO 自动生成的方法存根
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
isCanMove = true;
break;
case MotionEvent.ACTION_MOVE:
float x = event.getX();
float y = event.getY();
float StartX = event.getX();
float StartY = event.getY();
// 判断当前手指距离圆心的距离 如果大于mCenter代表在圆心的右侧
if (x > mCenter) {
x = x - mCenter;
} else {
x = mCenter - x;
}
if (y > mCenter) {
y = y - mCenter;
} else {
y = mCenter - y;
}
// 判断当前手指是否在圆环上的(30+10多加了10个像素)
if ((mRadius + 40) < Math.sqrt(x * x + y * y)
|| Math.sqrt(x * x + y * y) < (mRadius - 40)) {
Log.e("cmos---->", "终止滑动");
isCanMove = false;
return false;
}
float cosValue = x / (float) Math.sqrt(x * x + y * y);
// 根据cosValue求角度值
double acos = Math.acos(cosValue);// 弧度值
acos = Math.toDegrees(acos);// 角度值
if (StartX > mCenter && StartY < mCenter) {
acos = 360 - acos;// 第一象限
Log.e("象限---->", "第一象限");
} else if (StartX < mCenter && StartY < mCenter) {
acos = 180 + acos;// 第二象限
Log.e("象限---->", "第二象限");
} else if (StartX < mCenter && StartY > mCenter) {
acos = 180 - acos;// 第三象限
Log.e("象限---->", "第三象限");
} else {
// acos=acos;
Log.e("象限---->", "第四象限");
}
Log.e("旋转的角度---->", acos + "");
scanDegree = (int) acos;
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
学习分享
在当下这个信息共享的时代,很多资源都可以在网络上找到,只取决于你愿不愿意找或是找的方法对不对了
很多朋友不是没有资料,大多都是有几十上百个G,但是杂乱无章,不知道怎么看从哪看起,甚至是看后就忘
如果大家觉得自己在网上找的资料非常杂乱、不成体系的话,我也分享一套给大家,比较系统,我平常自己也会经常研读。
2021最新上万页的大厂面试真题
七大模块学习资料:如NDK模块开发、Android框架体系架构…
2021大厂面试真题:
只有系统,有方向的学习,才能在短时间内迅速提高自己的技术,只有不断地学习,不懈的努力才能拥有更好的技术,才能在互联网行业中立于不败之地。
一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
)]
学习分享
在当下这个信息共享的时代,很多资源都可以在网络上找到,只取决于你愿不愿意找或是找的方法对不对了
很多朋友不是没有资料,大多都是有几十上百个G,但是杂乱无章,不知道怎么看从哪看起,甚至是看后就忘
如果大家觉得自己在网上找的资料非常杂乱、不成体系的话,我也分享一套给大家,比较系统,我平常自己也会经常研读。
2021最新上万页的大厂面试真题
[外链图片转存中…(img-5OErinA9-1712779255178)]
七大模块学习资料:如NDK模块开发、Android框架体系架构…
[外链图片转存中…(img-OUR1bIGc-1712779255178)]
2021大厂面试真题:
[外链图片转存中…(img-UO3MvD5b-1712779255178)]
只有系统,有方向的学习,才能在短时间内迅速提高自己的技术,只有不断地学习,不懈的努力才能拥有更好的技术,才能在互联网行业中立于不败之地。
一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
[外链图片转存中…(img-H80ZaHOP-1712779255179)]