2024年最全Android自定义View实战---圆盘温度计,2024年最新面试官不讲武德

最后

我一直以来都有整理练习大厂面试题的习惯,有随时跳出舒服圈的准备,也许求职者已经很满意现在的工作,薪酬,觉得习惯而且安逸。

不过如果公司突然倒闭,或者部门被裁减,还能找到这样或者更好的工作吗?

我建议各位,多刷刷面试题,知道最新的技术,每三个月可以去面试一两家公司,因为你已经有不错的工作了,所以可以带着轻松的心态去面试,同时也可以增加面试的经验。

我可以将最近整理的一线互联网公司面试真题+解析分享给大家,大概花了三个月的时间整理2246页,帮助大家学习进步。

由于篇幅限制,文档的详解资料太全面,细节内容太多,所以只把部分知识点截图出来粗略的介绍,每个小节点里面都有更细化的内容!以下是部分内容截图:

部分目录截图

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

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);

可以看出,这里刻度值我把它写死了,当然,你也可以暴露一个方法,让调用者去设置起始值和结束值。

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++) {


### 最后

最后为了帮助大家深刻理解Android相关知识点的原理以及面试相关知识,这里放上相关的我搜集整理的24套腾讯、字节跳动、阿里、百度**2019-2021BAT 面试真题解析**,我把大厂面试中**常被问到的技术点**整理成了视频和PDF(实际上比预期多花了不少精力),包知识脉络 + 诸多细节。

还有 高级架构技术进阶脑图 帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。

**Android 基础知识点**

**Java 基础知识点**

**Android 源码相关分析**

**常见的一些原理性问题**

![](https://img-blog.csdnimg.cn/img_convert/b72ae38cce4a0014c57fabf61ee5d825.webp?x-oss-process=image/format,png)

希望大家在今年一切顺利,进到自己想进的公司,共勉!



**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**[需要这份系统化学习资料的朋友,可以戳这里获取](https://bbs.csdn.net/topics/618156601)**

**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**



### 最后

最后为了帮助大家深刻理解Android相关知识点的原理以及面试相关知识,这里放上相关的我搜集整理的24套腾讯、字节跳动、阿里、百度**2019-2021BAT 面试真题解析**,我把大厂面试中**常被问到的技术点**整理成了视频和PDF(实际上比预期多花了不少精力),包知识脉络 + 诸多细节。

还有 高级架构技术进阶脑图 帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。

**Android 基础知识点**

**Java 基础知识点**

**Android 源码相关分析**

**常见的一些原理性问题**

[外链图片转存中...(img-w9YEfTcX-1715855495377)]

希望大家在今年一切顺利,进到自己想进的公司,共勉!



**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**[需要这份系统化学习资料的朋友,可以戳这里获取](https://bbs.csdn.net/topics/618156601)**

**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值