【移动应用开发技术】自定义View系列之kotlin绘制手势设置温度控件的示例分析_第1页
【移动应用开发技术】自定义View系列之kotlin绘制手势设置温度控件的示例分析_第2页
【移动应用开发技术】自定义View系列之kotlin绘制手势设置温度控件的示例分析_第3页
【移动应用开发技术】自定义View系列之kotlin绘制手势设置温度控件的示例分析_第4页
【移动应用开发技术】自定义View系列之kotlin绘制手势设置温度控件的示例分析_第5页
已阅读5页,还剩7页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

【移动应用开发技术】自定义View系列之kotlin绘制手势设置温度控件的示例分析

这篇文章将为大家详细讲解有关自定义View系列之kotlin绘制手势设置温度控件的示例分析,在下觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。引言最近公司接了一个车联网的项目,主要是新能源汽车的一些控制功能,其中涉及到一个是温度的调节功能,产品的意思是做一个手势滑动调节温度,大概意思我是明白的。就是要手势调节呗,没办法,谁让我是搬砖的呢,人为刀俎,我为鱼肉,只有搞了;最后搞出来的效果大概如下,不过还没确定,思路在这里我先说下自己的实现思路,这个控件的难点主要是手势控制,其他的都很简单,没有什么好说的,控制的一些具体的数值我是写死的,没有做自定义拓展,主要是闲麻烦,如果有需要可以自己的实现;具体的实现步奏首先绘制圆盘,刻度,阴影(需要关闭硬件加速),文字然后根据划过的角度绘制进度条最后根绝touch事件重新绘制,并设置数据回调代码实现1,绘制前的准备首先kotlin提供了init方法,我们需要在这个方法里面初始化我们需要的画笔和一些数据注:这里涉及到阴影的绘制,所以必须关闭硬件加速

init

{

//关闭硬件加速

setLayerType(View.LAYER_TYPE_SOFTWARE,

null)

mInCirclePaint.color

=

Color.WHITE

mInCirclePaint.strokeWidth

=

1f

mInCirclePaint.style

=

Paint.Style.FILL

mInCirclePaint.setShadowLayer(25f,

0f,

0f,

Color.GRAY)

mGrayLinePaint.color

=

Color.parseColor("#00EEEE")

mGrayLinePaint.strokeWidth

=

dp2px(1f).toFloat()

mGrayLinePaint.style

=

Paint.Style.STROKE

mGrayLinePaint.setShadowLayer(15f,

0f,

0f,

Color.GRAY)

mTempTextPaint.textSize

=

sp2px(32f).toFloat()

mTempTextPaint.style

=

Paint.Style.FILL

mTempTextPaint.color

=

Color.parseColor("#7CCD7C")

mTempTextPaint.textAlign

=

Paint.Align.CENTER

mTempTextPaint.isFakeBoldText

=

true

mTempTextPaint.setShadowLayer(5f,

0f,

0f,

Color.GRAY)

mTextPaint.textSize

=

sp2px(18f).toFloat()

mTextPaint.style

=

Paint.Style.FILL

mTextPaint.color

=

Color.parseColor("#aaaaaa")

mTextPaint.textAlign

=

Paint.Align.CENTER

//

mTextPaint.setShadowLayer(5f,

0f,

0f,

Color.GRAY)

mLineProgressPaint.style

=

Paint.Style.STROKE

mLineProgressPaint.strokeWidth

=

dp2px(10f).toFloat()

mLineProgressPaint.color

=

Color.parseColor("#7CCD7C")

//

mLineProgressPaint.setShadowLayer(5f,

0f,

0f,

Color.GRAY)

mProgressCirclePaint.style

=

Paint.Style.FILL

//

mProgressCirclePaint.setShadowLayer(15f,

0f,

0f,

Color.GRAY)

mProgressPaint.style

=

Paint.Style.FILL

mProgressPaint.color

=

Color.parseColor("#436EEE")

mProgressPaint.strokeCap

=

Paint.Cap.ROUND

//

mProgressPaint.setShadowLayer(5f,

0f,

0f,

Color.GRAY)

mPaintTriangle.style

=

Paint.Style.FILL

mPaintTriangle.color

=

Color.parseColor("#436EEE")

}然后我们需要重写onMeasure()方法,因为这个控件必须是正方形的,所以我们必须保证宽和高一致;

override

fun

onMeasure(widthMeasureSpec:

Int,

heightMeasureSpec:

Int)

{

val

width

=

View.MeasureSpec.getSize(widthMeasureSpec)

val

height

=

View.MeasureSpec.getSize(heightMeasureSpec)

val

imageSize

=

if

(width

<

height)

width

else

height

setMeasuredDimension(imageSize,

imageSize)

}再之后我们需要知道一些具体的宽高值,从而设置半径的大小,一般是在onSizeChanged()方法里面拿到

override

fun

onSizeChanged(w:

Int,

h:

Int,

oldw:

Int,

oldh:

Int)

{

super.onSizeChanged(w,

h,

oldw,

oldh)

mHeight

=

Math.min(h,

w)

mWidth

=

height

dialRadius

=

(width

/

2

-

dp2px(10f))

arcRadius

=

dialRadius

/

2

mBgRectf

=

RectF(-dialRadius

*

1f

/

2

-

dp2px(5f),

-dialRadius

*

1f

/

2

-

dp2px(5f),

dialRadius

*

1f

/

2

+

dp2px(5f),

dialRadius

*

1f

/

2

+

dp2px(5f))

}2,绘制接下来就开始绘制视图了,绘制之前需要把视图的原心移动到中心位置

canvas.translate(mWidth

*

1f

/

2,

mHeight

*

1f

/

2);接着就开始绘制,首先我们绘制最外边源的线,这里绘制180根线,其中30根长线

private

var

beginAngle

=

0f

private

val

drawLine

=

{

canvas:

Canvas

->

beginAngle

=

0f

canvas.save()

for

(i

in

0..180)

{

canvas.save()

canvas.rotate(beginAngle)

mGrayLinePaint.setARGB(180,

(0.7

*

i

*

2).toInt(),

((255

-

0.7

*

i

*

2).toInt()),

((255

-

0.7

*

i

*

2).toInt()))

if

(beginAngle

%

12

==

0f)

{

canvas.drawLine(dialRadius

*

7f

/

9

-

dp2px(5f),

0f,

dialRadius

*

8f

/

9,

0f,

mGrayLinePaint)

}

else

{

canvas.drawLine(dialRadius

*

7f

/

9,

0f,

dialRadius

*

8f

/

9,

0f,

mGrayLinePaint)

}

beginAngle

+=

2f

canvas.restore()

}

canvas.restore()

}效果如下接着开始绘制中心的文字,如果如下

private

val

drawText

=

{

canvas:

Canvas

->

val

baseLineY

=

Math.abs(mTempTextPaint.ascent()

+

mTempTextPaint.descent())

/

2

mTempTextPaint.setARGB(180,

(0.7

*

currentAngle).toInt(),

(255

-

0.7

*

currentAngle).toInt(),

(255

-

0.7

*

currentAngle).toInt())

if

(temText

==

30

||

temText

==

29)

{

mTempTextPaint.setARGB(255,

255,

0,

0)

}

else

if

(temText

==

15)

{

mTempTextPaint.setARGB(255,

0,

255,

255)

}

canvas.drawText("${temText}°",

0f,

baseLineY

+

dp2px(20f),

mTempTextPaint)

canvas.drawText("最大温度设置",

0f,

baseLineY

-

dp2px(20f),

mTextPaint)

}接下来就开始绘制进度条和阴影部分

private

val

drawPointCircle

=

{

canvas:

Canvas

->

canvas.save()

canvas.rotate(rotateAngle

+

2)

mProgressPaint.setARGB(255,

(0.7

*

currentAngle).toInt(),

(260

-

0.7

*

currentAngle).toInt(),

(260

-

0.7

*

currentAngle).toInt())

mPaintTriangle.setARGB(255,

(0.7

*

currentAngle).toInt(),

(260

-

0.7

*

currentAngle).toInt(),

(260

-

0.7

*

currentAngle).toInt())

if

(temText

==

30

||

temText

==

29)

{

mProgressPaint.setARGB(255,

255,

0,

0)

mPaintTriangle.setARGB(255,

255,

0,

0)

}

else

if

(temText

==

15)

{

mProgressPaint.setARGB(255,

0,

255,

255)

mPaintTriangle.setARGB(255,

0,

255,

255)

}

val

path

=

Path()

path.moveTo(dialRadius

*

1f

/

2

+

dp2px(5f),

(-dp2px(10f)).toFloat())

path.lineTo(dialRadius

*

1f

/

2

+

dp2px(5f),

dp2px(10f).toFloat())

path.lineTo(dialRadius

*

1f

/

2

-

dp2px(10f),

0f)

path.close()

canvas.drawPath(path,

mPaintTriangle)

val

point

=

dialRadius

*

1f

/

2

+

dp2px(5f)

canvas.drawCircle(point,

0f,

dp2px(10f).toFloat(),

mProgressPaint)

canvas.restore()

}

private

val

drawProgress

=

{

canvas:

Canvas

->

if

(rotateAngle

>

0)

{

mProgressCirclePaint.color

=

Color.parseColor("#00ffff")

canvas.drawCircle(dialRadius

*

1f

/

2

+

dp2px(5f),

0f,

dp2px(5f).toFloat(),

mProgressCirclePaint)

}

val

colors

=

intArrayOf(Color.parseColor("#00ffff"),

Color.parseColor("#ff0000"))

val

mShader

=

SweepGradient(0f,

0f,

colors,

null)

mLineProgressPaint.shader

=

mShader

canvas.drawArc(mBgRectf,

0f,

rotateAngle,

false,

mLineProgressPaint)

}2,手势绘制视图结束,现在开始手势的处理,主要就是处理touch事件,我们以圆心为坐标圆点,建立坐标系,求出(targetX,targetY)坐标与x轴的夹角,显现代码如下private

val

calcAngle

=

{

targetX:

Float,

targetY:

Float

->

val

x

=

targetX

-

width

/

2

val

y

=

targetY

-

height

/

2

val

radian:

Double

if

(x

!=

0f)

{

val

tan

=

Math.abs(y

/

x)

if

(x

>

0)

{

if

(y

>=

0)

{

radian

=

Math.atan(tan.toDouble())

}

else

{

radian

=

2

*

Math.PI

-

Math.atan(tan.toDouble())

}

}

else

{

if

(y

>=

0)

{

radian

=

Math.PI

-

Math.atan(tan.toDouble())

}

else

{

radian

=

Math.PI

+

Math.atan(tan.toDouble())

}

}

}

else

{

if

(y

>

0)

{

radian

=

Math.PI

/

2

}

else

{

radian

=

-Math.PI

/

2

}

}

(radian

*

180

/

Math.PI).toFloat()

}然后在touch事件中进行处理,主要代码如下override

fun

onTouchEvent(event:

MotionEvent):

Boolean

{

when

(event.action)

{

MotionEvent.ACTION_DOWN

->

{

isDown

=

true

downX

=

event.x

downY

=

event.y

currentAngle

=

calcAngle(downX,

downY)

}

MotionEvent.ACTION_MOVE

->

{

isMove

=

true

val

targetX:

Float

=

event.x

val

targetY:

Float

=

event.y

val

angle

=

calcAngle(targetX,

targetY)

//

滑过的角度增量

var

angleIncreased

=

angle

-

currentAngle

if

(angleIncreased

<

-180)

{

angleInc

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论