SystemUI开发总结-状态栏、下拉栏

最近的新活是把MTKSystemUI改成我们自己的SystemUI,在前辈们的帮助下忙了两周终于搞定啦~做个小总结,个人经验,如有误解请不吝指出(鞠躬)。

前排提醒:
1 个人经验,个人经验,个人经验!也有前辈的指导,不保证最优解。
2 目前的需求只需要制作状态栏和下拉栏部分,导航栏锁屏等没有的,如果后面要做另外开个帖子总结
3 帖中不含UI图、具体代码、效果图等

需求

状态栏:左边显示天气,中间显示特色图标,右边显示时间、原生状态
下拉栏:调整声音和亮度,wifi、热点、蓝牙的快捷开关

分析

UI有切图并不难做(虽然也应领导要求前前后后改了几版),功能也和设置模块的差不多(有经验),难的是作为一个必须源码编译的应用,面对浩如烟海的文件树,如何把自己的页面替换进去呢?
蓝色部分也展开就太长了,可以自行搜索源码查看
我们能确定的就是尽量不要动这个庞大的源码,因为文件太多非常难定位,而且每次都要写注释表示“这个部分我改了”,很折磨人。
经过对SystemUI的启动原理阅读,我找到了它页面的具体部署地方,可以说是七零八落:启动在statusbar.java中,绘制在statusbarwindowview中,下拉栏?没看明白怎么出来的,资源文件位于super_status_bar中。
简单制定了以下流程

  • 建立自己的包,分为java lib res
  • 在android.mk中声明编译以上文件
  • 把自己包里的view加入super_status_bar
  • 防止原生内容出现,把super_status_bar其它的子视图设置为gone

实战

建立自己的包

这部分和自定义view差不多,java视图和layout联动,其它的也是为之服务,因为状态栏是嵌入在super_status_bar中,下拉栏是一个窗口(window),所以不需要写activity,不用在manifest里面注册。
有了视图之后,添加各种功能,有包导包,没包自己写。
这部分的开发和普通app相似,遇到的问题也是功能层面的,例如信号值的转换,sim卡的检测,麦克风打开标志之类,不再赘述。

声明编译

对mk文件没有太深入了解的我,在前辈的帮助下对原先的android.mk做了以下修改:

  • MTK前缀全部更换,更换包名
    – 包名更换是因为mtk已经存在这样的路径,合在一起编译会报错
    – MTK前缀更换也是相似的道理,在mk中这样的暂时名字重复也会造成报错
  • LOCAL_OVERRIDES_PACKAGES项最后加上MTKSystemUI
    – 这个据说也是为了防止报错,不过宏控文件里也定义了类似的东西,不知道这个是否多余了
  • 加上自己的资源目录和java目录,编译导入的外部包

改造完成了,其它的很多语句,不懂的就先放着吧。

植入自己的view

状态栏很方便放进去,那么下拉栏怎么做呢?
目前知道下拉栏是一个长宽和屏幕一样的窗口(因为是车机项目,应用都是内置的,没有第二次下拉的通知页,只有快捷设置),我们可以先把它藏在屏幕上方(改变绘制窗口的y值)。
按照一般的思路,下拉栏和状态栏都属于SystemUI,statusbar管状态栏,用quicksetting管下拉栏才对。但是按照尽量集中修改的思路,在statusbar中加入下拉栏,让我们的两个视图关联更加紧密。
在statusbar.java中把下拉栏实例化,然后使用windowsmanager为它注册窗口。
我们知道下拉栏平时是隐藏的,只有按住状态栏下滑才会出来,因此下拉栏和状态栏是存在联系的。因此把实例化的下拉栏传值给状态栏的类,并设计了当状态栏接受滑动事件时调用下拉栏的显示方法。
这里给出了一个下拉阈值:当下拉超过屏幕四分之一的时候,下拉栏显示。在手指在屏幕上时我们获取触摸的高度,并把下拉栏底部绘制到该高度,就会产生一种“正在拉动”的感觉。如果没有超过四分之一,手指松开则需要回弹:设计一个状态动画计时器,改变绘制的高度直到它缩回去为止。状态栏的上划隐藏也同样遵循该逻辑。
这个动画设计了很久,一开始怎么也想不出来跟随下拉怎么做到,后来发现只要dispatchdraw的时候改变canvas的坐标就可以了,自动滑动动画也就水到渠成。

隐藏不属于自己的view

把super_status_bar.xml其他的view用个framelayout装起来,然后一键gone就行了。
这部分关注的是另一个问题:view的重绘。
状态栏中我用的普通imageview在隐藏时不会消失,因此触发各种bug混乱,还出现了图像残影重叠问题。
本来以为是imageview内部的重绘逻辑有问题,于是在ondraw中加入一行代码使它每次重绘都清空画布,这倒好imageview显示的时候正常了,没有视图的空白区域却无法得到重绘(也就是说仍然不能隐藏,仅能解决重叠问题)。
我又在根布局中加入类似代码,但是没有效果。咨询前辈得知状态栏有特殊的绘制方式,具体在statusbarwindowview中,凝望着大几千行代码,我选择了将类中的所有方法全部注释,再在statusbar调用相关方法的地方也做屏蔽。这样问题神奇地消失了,只是也许会有隐患。

开发过程的吐槽

  • 感谢前辈们的教导,很多都是千锤百炼的经验,不用摸黑走弯路的感觉太好了!
  • 犹记得本来开开心心地在做设置模块,搞到一半领导说整设置太简单了,给我换上SystemUI开发。在我对着源码留下不学无术泪水的时候,领导轻轻来到我身后说:“你要熟悉这部分,要做到看见bug就知道是哪一行的问题哦!”,我木讷地思索着……过了一个星期,领导催进度:怎么开发这么慢,别人的已经上线在测咯!
  • 原先的设置模块尽量做了高内聚低耦合,标签页都特别写了个管理类就为了拆分开activity和标签的紧密联系,转给和我一样新来的小妹妹后,她偶尔会呼叫我求讲解哪个功能在哪个位置。浏览着妹妹直接在activity中做的跳转和各种括号强制转类型,脑海中划过看过的各种代码笑话。
  • 源码编译绷不住了,android studio什么时候能适配一下,急急急。

最后,如果有疑问或者指正欢迎在评论区留言!

阅读推荐

什么是SystemUI?-大神的简介
SystemUI启动原理-大神的讲解,丝丝入扣

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值