当前位置: 首页 > news >正文

自我绘制四

一,自我绘制的步骤

由上边三篇文章,我们可以对自我绘制有个大概的思路:

第一步:开发者确定使用者在用包裹内容时候的默认View的整体大小

第二步:把这个默认的宽高在onMeasure中告诉父布局

第三步:为了防止使用者空间不够,需要在onSizeChanged方法中去矫正可以绘制的宽高。或者不去矫正,而是计算一个缩放比例,通过canvas.scale(scal, scal)去整体缩放绘制。怎么方便怎么来

第四步:分析需要绘制的内部所有元素需要用哪些绘制方法去绘制,开发者设置每个元素的默认大小,然后也去矫正一下,根据矫正后的整体大小和每个元素的大小,计算出每个元素的位置坐标(这里的计算全部以控件左上为坐标原点),然后绘制一个静态的效果。

以上四步:开发者确定了整体View的大小,内部元素的大小,通过这些确定的值,算出来内部元素的坐标。并且通过绘制方法绘制了静态的View。

第五步:添加属性动画(本质就是对值改变的操作),然后根据这些值的变化去实现动态绘制内部元素实现动画。(这里的动画是对View内部元素做改变)

到此一个完美的自定义View出来了!

当你看到需要绘制一个复杂的View的时候,很可能一开始没有思路,但是按照上边的步骤走,就可以快速定位到不会的地方,然后准确击破,完成自定义。

二绘制贝塞尔曲线

按照步骤来

步骤1:确定默认大小:

defult_Widht = 屏幕的宽度

defult_Height= 随便写,这里给150dp

步骤2:把这个宽高告诉父控件

setMeasuredDimension(resolveSize(defult_Widht.toInt(), widthMeasureSpec), resolveSize(defult_Height.toInt(), heightMeasureSpec))复制代码

步骤3:获取真正能绘制的区域

override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
    //去矫正宽度和高度
    defult_Widht = w.toFloat()
    defult_Height = h.toFloat()
}复制代码

步骤4:看绘制效果,分析元素的使用的绘制方法



这里只有一个元素,绘制曲线,填充即可,绘制类似这种曲线我们可以使用sin cos,或者贝塞尔曲线。这里线确定用贝塞尔曲线去画。

看完对贝塞尔曲线原理文章的讲解之后我们知道我们需要计算起始点,控制点和终点,并且google给我们提供了绘制贝塞尔曲线的方法。

quadTo(float x1, float y1, float x2, float y2) 
这条二次贝塞尔曲线的起点就是当前位置,而参数中的 x1, y1 和 x2, y2 则分别是控制点和终点的坐标。

现在就开始计算点。观察需要两个波形是从中心点去改变的,画个坐标图


蓝色的点坐标很轻易的算出来,分别是:

//起始点
var startX1 = 0F
var startY1 = defult_Height/2
//控制点
var controlX1 = defult_Widht/4
var controlY1 = 0F
//结束点,也是第二个曲线的起点
var endX1 = defult_Widht/2
var endY1 = defult_Height/2
//控制点2
var controlX2 = defult_Widht*3/4
var controlY2 =defult_Height
//结束点2
var endX2 = defult_Widht
var endY2= defult_Height/2复制代码
然后设置绘制出来的效果如下图:


这是和什么鬼?为什么后半部分没有凹陷下去?

圆心是你画笔用的填充模式,只是填充的方向不对而已,我们可以把下半部分做成一个封闭的path,它就会填充下边

mWavePath.lineTo(width.toFloat(), height.toFloat())
mWavePath.lineTo(0F,defult_Height)复制代码
之后再运行,就会出现上边静态效果。

步骤5:添加动画,让它动起来

改变哪些值能让他动起来呢?上边的曲线上的点,但是曲线上的路径我只给了系统关键点坐标,想要改变也不可能。

换个思维想一下,我们再屏幕外边也去绘制一个一模一样的一个,然后平移一次是一个动画周期怎么样?我觉得可以,那就试试。

类似这样的坐标图:


然后又是一些简单的计算:

注意

这里坐标原点的位置不变,屏幕的交点为坐标原点

每次绘制都需要吧path恢复到初始状态

源码地址:github.com/XiFanYin/Cu…
















相关文章:

  • 路飞学城-Python爬虫集训-第二章
  • 正则之从dom字符串中提取url
  • CSS面试复习(二):CSS的使用
  • ACM博弈
  • nginx File not found 错误
  • 微商代理系统APP软件
  • YAML基础语法
  • Spring深入理解(一)
  • MongoDB备份与恢复
  • Linux 用户 用户组 相关命令
  • Unity获取Android平台音量
  • 人工智能技术在中小学课堂中的应用
  • 设计模式入门:工厂方法模式
  • 作为app运营,你需要get的技能有哪些? 总结七项APP运营技能
  • Java分布式锁之数据库实现
  • 【Linux系统编程】快速查找errno错误码信息
  • 【MySQL经典案例分析】 Waiting for table metadata lock
  • 【Redis学习笔记】2018-06-28 redis命令源码学习1
  • Bootstrap JS插件Alert源码分析
  • CentOS7 安装JDK
  • Git初体验
  • JAVA 学习IO流
  • java中具有继承关系的类及其对象初始化顺序
  • Object.assign方法不能实现深复制
  • PAT A1092
  • Python_OOP
  • SOFAMosn配置模型
  • vue从入门到进阶:计算属性computed与侦听器watch(三)
  • Windows Containers 大冒险: 容器网络
  • WinRAR存在严重的安全漏洞影响5亿用户
  • zookeeper系列(七)实战分布式命名服务
  • 思维导图—你不知道的JavaScript中卷
  • 自动记录MySQL慢查询快照脚本
  • 《天龙八部3D》Unity技术方案揭秘
  • gunicorn工作原理
  • 说说我为什么看好Spring Cloud Alibaba
  • ​linux启动进程的方式
  • ###C语言程序设计-----C语言学习(6)#
  • ###项目技术发展史
  • #Spring-boot高级
  • (pt可视化)利用torch的make_grid进行张量可视化
  • (保姆级教程)Mysql中索引、触发器、存储过程、存储函数的概念、作用,以及如何使用索引、存储过程,代码操作演示
  • (介绍与使用)物联网NodeMCUESP8266(ESP-12F)连接新版onenet mqtt协议实现上传数据(温湿度)和下发指令(控制LED灯)
  • *ST京蓝入股力合节能 着力绿色智慧城市服务
  • .dat文件写入byte类型数组_用Python从Abaqus导出txt、dat数据
  • .dwp和.webpart的区别
  • .gitignore
  • .gitignore文件_Git:.gitignore
  • .NET面试题(二)
  • .sh
  • @DateTimeFormat 和 @JsonFormat 注解详解
  • []FET-430SIM508 研究日志 11.3.31
  • [20161214]如何确定dbid.txt
  • [Angular 基础] - 数据绑定(databinding)
  • [BZOJ1010] [HNOI2008] 玩具装箱toy (斜率优化)