android虚线如何定义xml,「Do.023」为啥用XML定义的虚线显示成了实线
首发公众号:Android程序员日记
作者:贤榆的榆
如果喜欢,请 关注 | 赞赏 | 点在看
阅读时间:4978字 8分钟
前言
今天刚好是《千与千寻》在中国首映的日子。所以放一张《千与千寻》的海报,我也没想到过去这么久了,其实都都已经看过很多遍了。但还是想要在大屏幕上再看一次。小时候看动画片,妈妈会说,这动画片有什么好看的,你能看一辈子呀!真是一语成真,估计这辈子是逃不出动漫的坑了。(杠精就别纠结动画片和动漫的不同了,在妈妈眼里,那都是一样一样的!),好了,娱乐休闲之前先学习一波儿!
正文
前几天做一个界面的时候,再一次出现了虚线显式成实现的问题,我没出息的又去搜解决方案了,为了记忆深刻,狠了狠心,深挖了一下。一起来看看吧:
我在xml布局文件中通过给一个View设置一个背景画了一条虚线分割线代码如下:
android:id="@+id/view3"
android:layout_width="match_parent"
android:layout_height="2dp"
android:background="@drawable/common_line_draw_dash"/>
view中引用的common_line_draw_dash.xml代码如下:
android:shape="line">
android:width="1dp"
android:color="#DDDDDD"
android:dashGap="2dp"
android:dashWidth="4dp"/>
可是设备上的实际效果也预期效果并不一致,见下图:
可能很多开发小伙伴都碰到过这个问题,也知道只需要在View的xml布局中添加如下一行代码即可解决问题。
android:layerType="software"
古话说“知其然知其所以然”
从谷歌官方提供的关于硬件加速的资料显示:
从Android 3.0(API级别11)开始,Android 2D渲染管道支持硬件加速,这意味着在View的画布上执行的所有绘图操作都使用GPU。 由于启用硬件加速所需的资源增加,您的应用程序将消耗更多RAM。
并且文章中还讲到Android 4.0(API级别14)开始默认开启了硬件加速;但是
再往上找了一些关于硬件加速的文章比如这篇《关于硬件加速那点事儿》
地址:https://www.jianshu.com/p/9cd...
这是一篇Android硬件加速官方文章的译文
里面介绍了不支持硬件加速的一些操作:
在里面看了一下之后就去扫View的源码了,果然不出五分钟就找了上图中倒数第三的方法saveLayer();
看到background.draw(canvas)方法时,你可能想问我怎么知道这个虚线xml文件,最后实例化之后的Drawble对象对应的GradientDrawble的对象。看下面这张图,你就明白了:
按照平常,文章写道这里就已经结束了,一切都已经说通了。但是作为一名程序员,严谨是一种良好职业操守,于是我又去了google官网看了英文原版关于硬件加速的介绍。
地址:https://developer.android.com...
然后这一看,就看出问题了。当我看到上面这张图的时候,我特么就尴尬了。怎么和之前我看到的那张图不一样了?saveLayer方法支持硬件加速?还是不支持?后来又用google搜索了一些资料,确实没有一项有力的证件证明saveLayer方法是不支持硬件加速的;
既然这样我们就需要重新去须按照其他的证据来证明View在画虚线时,无法使用硬件加速,虽然上面图中找到的saveLayer方法不能证明是需要关闭硬件加速的原因。但是这个View绘制背景的流程是没有问题的,并且我们知道用标签定义的xml文件在膨胀后得到的是一个GradientDrawable对象。
既然在绘制背景流程中没有可疑的不支持硬件加速的方法,那么在生成Drawable对象的过程是否能找得到一些可疑的方法呢?上面流程图中的mBackground对象又是怎么来的?
带着这两个问题,思考了一下。这个View是通过xml膨胀生成的,那么应该会调用View的2各参数或3个参数的构造方法,然后我就顺着这思路找了一下mBackground对象是怎么生成:
一路找下去找到了,上图中蓝色框部分的代码
final Drawable.ConstantState cs;
if (isColorDrawable) {
cs = sPreloadedColorDrawables.get(key);
} else {
cs = sPreloadedDrawables[mConfiguration.getLayoutDirection()].get(key);
}
Drawable dr;
boolean needsNewDrawableAfterCache = false;
if (cs != null) {
if (TRACE_FOR_DETAILED_PRELOAD) {
// Log only framework resources
if (((id >>> 24) == 0x1) && (android.os.Process.myUid() != 0)) {
final String name = getResourceName(id);
if (name != null) {
Log.d(TAG_PRELOAD, "Hit preloaded FW drawable #"
+ Integer.toHexString(id) + " " + name);
}
}
}
dr = cs.newDrawable(wrapper);
} else if (isColorDrawable) {
dr = new ColorDrawable(value.data);
} else {
dr = loadDrawableForCookie(wrapper, value, id, density, null);
}
然后大概可以看明白当cs不为null时,Drawable是通过cs.newDrawable()方法生成的。cs在上面代码中的第一行已经定义了,它是一个Drawable的静态内部类Drawable.ConstantState;
既然前面我们已经知道用标签定义的虚线XML文件膨胀后是一个GradientDrawable对象。那么GradientDrawable也应该有自己的ConstantState内部类。点进GradientDrawable的源码拉到底部,果然就看到了一个继承自ConstantState的GradientState类。借着又是一招顺藤摸瓜:
GradientState类重写了ConstantState的newDrawable方法,在该方法中通过调用GradientDrawable的构造方法构建了一个GradientDrawable实例。
在GradientDrawable构造方法中则进行了一些初始动作,其中调用的updateLocalState方法中的一段代码(上图蓝色框)引起了我注意,最引人注目的还是那段红色框里的的方法。这个方法好像在不支持硬件加速的操作表中。喜极而泣!明了,明了...。
这里再粘一下这段代码:
if (state.mStrokeDashWidth != 0.0f) {
final DashPathEffect e = new DashPathEffect(
new float[] { state.mStrokeDashWidth, state.mStrokeDashGap }, 0);
mStrokePaint.setPathEffect(e);
}
它判断了StrokeDashWidth是否有值,如果有这则根据虚线的的两个重要属性state.mStrokeDashWidth和state.mStrokeDashGap构造一个DashPathEffect对象,然后在通过Paint的setPathEffect(e)方法来绘制虚线。
到这里一切都水落石出了。之所以虚线会在大部分手机上绘制成实现是因为就是因为Paint的setPathEffect()方法不支持硬件加速。其实通过上表可以看到,在Android 9(API级别28)以后,就可以不用关闭硬件加速也可以绘制XML定义的虚线了。
后记
好了这篇文章就写到这里吧,大家在追源码的时候给大家一个提醒:
晚上10点以后不宜阅读源,因为你根本停不下来。
虽然有些滑稽,但却是真是的哈哈。
另外,如果你是初学者,到没有必要花费太多精力去探索。毕竟初学者完成一个App,对知识和技术的广度认知比深度要重要的多。但是到了一定时候(我也说不清是什么时候,你自己应该会有感觉)——我个人觉得是做了两三年吧,当你遇到问题时,就不应仅仅只停留在解决问题的层面,还应该深入了解一下为什么。哪怕一开始你就知道导致这个问题的原因是某个方法。但是找出这个方法,这一探索,研究的过程才是这个阶段你成长的最大助力。与君共勉!
如果有想法可以留言;觉得有帮助,可以关注我的公众号
推荐阅读
android虚线如何定义xml,「Do.023」为啥用XML定义的虚线显示成了实线相关推荐
- java 字符串数组定义_「string数组」string 数组怎么定义 - seo实验室
string数组 string数组的定义有三种: String arr[] = new String[10]; //创建一个长度为10的String 类型数组. String arr[] = {&qu ...
- Java 字符串数组定义_「string数组」string 数组怎么定义
前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家.点击跳转到网站 点击跳转浏览. string数组的定义有三种: String arr[] = new String[1 ...
- android 抓log暗码,「有用功」强大的安卓暗码命令 你都知道吗?
「暗码命令」其实就是安卓工程模式的指令,它可以通过手机拨号盘输入那些相关隐藏代码,让设备快速进入工程测试模式,从而了解那些不为人知的手机硬件信息.它可以直观反映手机的使用情况,这对于购机,或是买二手机 ...
- 130亿参数开源模型「小羊驼-Vicuna」来了!复刻ChatGPT九成功力,GPT-4亲自监考
源|机器之心 OpenAI 的强大模型们,被开源社区复刻得差不多了. 过去几个月,OpenAI 的 ChatGPT 彻底改变了聊天机器人领域的格局,也成为其他研究赶超的对象. 以 Meta 开源 LL ...
- [车联网安全自学篇] Android安全之Android 如何生成APP(APK)「详解」
也许每个人出生的时候都以为这世界都是为他一个人而存在的,当他发现自己错的时候,他便开始长大 少走了弯路,也就错过了风景,无论如何,感谢经历 0x01 前言 面向移动终端的操作系统有:Symbian.P ...
- 百度重新定义「智能屏」,瞄准10后
加入「公开课」交流群,获取更多学习资料.课程及热招岗位等信息 记者 | 阿司匹林 作为中国智能音箱主力推手中的一员,百度从 2017 年已经开始布局.根据数据机构Strategy Analytics发 ...
- 谷歌等揭露「AI任务疑难」:存在局限的ImageNet等基准,就像无法代表「整个世界」的博物馆...
来源:AI科技评论 作者:杏花 编辑:青暮 在日常生活中,我们需要一些「标准」来衡量个人的行为. 而在科研工作中,研究人员也需要一些「基准」来评估模型的性能. 因此,不管是普遍的「标准」还是特定的「基 ...
- 怎么通过id渲染页面_「快页面」动态配置化页面渲染器原理介绍
引言 「快页面」是知乎内部一个快速搭建后台管理页面的平台,使用者仅用半小时即可将一个常规复杂度的后台页面开发完成. 「快页面」平台的基石是它的「渲染器」,一个能将 JSON 配置渲染成页面的 Reac ...
- python羊车门问题_「羊车门」经典概率题中不换门选中车的概率是多少?
今天用Python求解「羊车门」经典的概率问题,对概率学基础和Python语法的灵活运用有所收货. 本次「羊车门」求解过程采用的是:穷举法计算概率已验证概率学基础理论.期间重点借鉴了'奥卡姆剃刀的博客 ...
最新文章
- 推荐一位玩自动化的 Python 爱好者
- PCA--主成分分析(Principal components analysis)-最小平方误差解释
- Dubbo 稳定性案例:Nacos 注册中心可用性问题复盘
- c++成员运算符的重载
- php+js实现弹幕,jquery.barrager.js-专业的网页弹幕插件
- 移动端rem单位用法
- 发生服务器错误 显示预览,我的电脑为何在做asp的时候按F12键不能预览!预览就出错!错误代码500说服务器或者DNS错误...
- Java线程执行native方法时程序计数器为空,如何确保native执行完后的程序执行的位置
- c语言判断算符优先级,C语言算符优先级(精华)
- oracle实验7 pl/sql编程基础
- 201671010406 词频统计软件项目报告
- 讨论实现Windows资源管理器的简单方式
- Error “Client wants topic A to have B, but our version has C. Dropping connection.“
- php 导出多个excel并输出压缩文件
- imagemagick替换图片指定区域颜色
- 2014秋冬季校招时间表,持续更新
- JetsonNano国产套件成功部署YoloV5手把手图解教程
- (转载)Bro NIDS的规则
- Java中都是值传递 pass-by-value
- 奈何桥上经过的地方,看醒了多少人
热门文章
- 手把手之如何写一个抢课脚本
- 高贵抑或低俗——《诸子时代的秩序追寻》读后感范文4300字
- cmpp2.0如何实现网关短信发送
- 父组件调用子组件的方法
- 小陈学前端-bootstrap-案例:美联英语在线VIP微电影页面
- 共绘信创蓝图,中睿天下正式加入同心生态联盟
- Excel数据可视化图形
- c语言Dvv实验报告,电视新闻摄像实验课程的基本教学方案
- Failed to introspect Class...from ClassLoader...java.lang.ClassNotFoundException,IDEA启动没问题,jar包启动报错
- 第7章 Photo Gallery