前言
- 好久没输出点有价值的东西了。恰巧刚刚在酷市场看见有酷基在求助MIUI状态栏时间居中的问题,所以我们今天的主角就是它了。虽说算不上干货,不过也可以当做对 Android 布局的复习与巩固,希望给刚入Android开发坑的基友们一点帮助。
- 本文侧重过程,旨在“授之以渔”,对市面上这类app的基本原理有一点了解。
- 不保证我的文件与您的完全通用。不过思想和原理都是一样的。
- 这里我提供了一个修改后的
status_bar_simple.xml
文件。它是文本形式,也就是并没有编译,因此您不能直接替换掉您对应的文件。如果实例环境与我的测试不同,请谨慎。不管如何,备份最重要。
链接:百度网盘 https://pan.baidu.com/s/12lri3Xgin9lMLFzHsCKWdA 密码:a1i2 -
预览图
实现原理
- Android app大概可分为两部分:界面部分与逻辑部分。前者负责直接与用户交互,是整个app最直观的部分。而后者则负责处理前者传递过来的大量数据与事件,之后再展示给用户。
- Android 系统的状态栏由包名为
com.android.systemui
的app负责。它一般是/system/priv-app/SystemUI/SystemUI.apk
,其内部layout/status_bar.xml
负责状态栏各个组件的布局。 - 我们仅仅修改这个布局文件就可以了,并不需要修改具体的 Java 层实现,因此有没有
odex
没有影响。
工具
- 已经 root 的 Android 手机一台。
- 支持查看并修改
zip
的app。 - 支持反编译与回编译的app。
测试环境
- 机型:红米 Note4X 骁龙版
- ROM:MIUI 9.2.1 稳定版
- Android 版本:7.0
- 工具:
MT管理器
点击下载
具体步骤
找到具体的apk。
这一步应该没问题。需要注意的是,MIUI 把SystemUI
放到了
/system/priv-app/MiuiSystemUI/MiuiSystemUI.apk
而不是
/system/priv-app/SystemUI/SystemUI.apk
-
找到布局文件。
找到layout/status_bar.xml
。然而并没有发现负责时钟部分的组件
com.android.systemui.statusbar.policy.Clock
。不过这里我们发现了一处引用
include layout="@layout/status_bar_simple.xml"
。跟进并搜索
com.android.systemui.statusbar.policy.Clock
发现需要修改的文件就是这个。 -
我们首先来分析一下这个布局文件。整个布局大约如图所示。
-
我们需要把时钟的位置调到中央,即放到
通知栏
和系统图标栏
之间,所以新的布局结构如下图。
- 打开
MT管理器
,把以下部分剪切掉:
<com.android.systemui.statusbar.policy.Clock
android:textAppearance="@style/TextAppearance.StatusBar.Clock"
android:gravity="center|start"
android:id="@id/clock"
android:paddingBottom="@dimen/statusbar_text_bottom_padding"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:singleLine="true"
android:paddingStart="3dp"
android:paddingEnd="3dp" />
搜索
<com.android.systemui.statusbar.phone.StatusBarIcons
并把上面的时钟部分剪切到这上面。
- 到这里其实还不够。因为这是个相对布局,我们得重新把组件的相对位置调整好,否则会出现混乱。
找到刚刚你剪切好的是时钟部分,在
android:id="@id/clock"
下面添加一行
android:layout_centerInParent="true"
用来使时钟在父组件中央。
- 搜索
android:layout_toEndOf="@id/clock"
并删除。作用是取消通知图标在时钟右面。
注意:如果这一条后面存在>
的话千万不要把 >
也删掉!否则会回编译失败。
- 经过上面几个步骤,如果仅仅要实现时间居中已经可以了。但这样的话如果没有通知时左侧会很不好看,光秃秃一片。所以下面的步骤是把
Wifi和信号
图标移动到左侧。布局结构如下
- 找到下面的信号部分
<LinearLayout
android:gravity="center_vertical"
android:id="@id/signal_cluster_container"
android:layout_width="0dp"
android:layout_height="match_parent"
android:baselineAligned="false"
android:layout_weight="1">
<include
android:id="@id/signal_cluster"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
layout="@layout/signal_cluster_view" />
<include
android:id="@id/signal_cluster2"
android:visibility="gone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
layout="@layout/signal_cluster_view" />
</LinearLayout>
把
android:layout_width="0dp"
改为
android:layout_width="wrap_content"
并删掉
android:baselineAligned="false"
之后把这一大块信号部分剪切掉。
- 找到
<LinearLayout
android:gravity="center|start"
android:id="@id/notification_icon_area"
android:layout_width="wrap_content"
android:layout_height="match_parent" >
并把上面的信号部分剪切到这里上方。再在
android:id="@id/notification_icon_area"
下添加一行
android:layout_toEndOf="@id/signal_cluster_container"
完成后像下面这样子:
<LinearLayout
android:gravity="center_vertical"
android:id="@id/signal_cluster_container"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="1">
<include
android:id="@id/signal_cluster"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
layout="@layout/signal_cluster_view" />
<include
android:id="@id/signal_cluster2"
android:visibility="gone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
layout="@layout/signal_cluster_view" />
</LinearLayout>
<LinearLayout
android:gravity="center|start"
android:id="@id/notification_icon_area"
android:layout_toEndOf="@id/signal_cluster_container"
android:layout_width="wrap_content"
android:layout_height="match_parent" >
.........
- 其实经过上面的部分,我们的布局已经修改完成了。接下来就是右上角菜单,编译,在apk里更新文件。注意,如果直接在
/system
操作的话可能不会成功,建议先把这个apk移动到sdcard
,操作后再覆盖回去。修改权限为0644,设置用户和组为root, root,重启生效。