掌握Android 7.0 新增特性 Quick Settings
作者简介
本文由 强波 原创并授权发布,未经原作者允许请勿转载。
本文介绍 Quick Settings ,方便你在 Quick Settings 里定制你 App 的专属 Setting,写的很好,希望你喜欢。
强波 的博客地址:
http://qiangbo.space/2017-08-01/AndroidAnatomy_QuickSettings
本文中,我们详细了解一下 Android N(7.0)上的新增特性:Quick Settings。
Quick Settings 功能如下图所示:
该功能位于下拉的通知面板中,在用户单手指下拉通知面板的时候,Quick Settings 区域显示成一个长条,用户可以点击右上角的尖号展开这个区域。
Quick Settings 提供给用户非常便捷的按钮,用户甚至无需解锁就可以操作这个区域,通过点击 Quick Settings 中的 Tile 来切换某个功能的状态,例如:打开/关闭手电筒,蓝牙,Wifi 等功能。这对于用户来说是非常便捷的。
开发者API
使用 Quick Settings 功能非常的简单,只需要与 Tile 和 TileService 两个类打交道即可。它们的类图如下图所示:
TileService 是 android.app.Service 的子类,开发者通过继承 TileService 并覆写其对应的方法来完成功能的实现。TileService 中提供的状态回调方法如下:
在这些状态变更的时候,开发者可以根据状态的不同来调整 Tile 的状态。调整的方法就是:先通过 TileService.getQsTile() 获取到当前 Tile ,然后通过 Tile 的 setXxx 方法来修改。最后调用 Tile.updateTile() 来使刚刚的设置生效。
下面是一段代码示例。这段代码的功能是根据用户点击来将 Tile 在 Active 和非 Active 状态之间进行切换。
这段代码说明如下:
处理用户的点击事件
获取自身的Tile对象
设置 Tile 的状态,包括:Label,Icon,State
设置完成之后真正让状态生效
在实现完成这个 TileService 之后,我们还需要将其注册到 AndroidManifest.xml
中。TileService 需要设置一个特殊的权限和 Intent-Filter 的 Action ,如下所示:
当我们将包含这个 TileService 的应用安装到设备上之后,下划通知面板然后展开 Quick Settings 区域便可以看到我们开发的 Tile 了。
系统实现
我们可以通过 Layout Inspector 来分析 Quick Settings 的结构。
Quick Settings 位于下拉的通知面板中。在布局上,这个部分通过 QSContainer 作为外部的容器,其中包含了一个 QSPanel 。
QSPanel 中,包含了一个调节屏幕亮度的控件,这是通过一个 LinearLayout 来进行布局的,接下来就是PagedTileLayout 中包含的多个 Tile 了,每个 Tile 用一个 QSTileView 来进行布局。 PagedTileLayout 正如其名称所示,这是一个可以分页的 Layout 。
QSContainer 中包含的元素如下图所示:
在 Android 系统中,包含两类 Tile :
一类是系统预置的
另一类的第三方应用中包含的
Quick Settings 功能实现主要位于这个目录中: /frameworks/base/packages/SystemUI/src/com/android/systemui/qs。
系统预置Tile
qs 目录下,包含了布局结构中用到的几个元素的实现类,包括:QSContainer,QSPanel,PagedTileLayout,QSTileView,QSIconView 等。
系统本身包含了一些预装的 Tile ,例如:飞行模式的开关,位置信息的开关,热点功能的开关,手电筒功能开关等等。这些Tile的实现位于 qs/tiles 目录下,包含下面这些:
AirplaneModeTile.java
BatteryTile.java
BluetoothTile.java
CastTile.java
CellularTile.java
ColorInversionTile.java
DataSaverTile.java
DndTile.java
FlashlightTile.java
HotspotTile.java
IntentTile.java
LocationTile.java
NightDisplayTile.java
RotationLockTile.java
UserTile.java
WifiTile.java
WorkModeTile.java
在 res 目录下,有一个名称为 quick_settings_tiles_stock
的字符串列出了所有系统内置的 Quick Setting 的名称,它们通过逗号进行分隔。
<string name="quick_settings_tiles_stock" translatable="false">
wifi,cell,battery,dnd,flashlight,rotation,bt,airplane,location,hotspot,inversion,saver,work,cast,night
</string>
QSTileHost 中为这里的名称和实现类做了映射:
TileQueryHelper 负责了 Tile 的初始化工作。在这个类中,会读取 R.string.quick_settings_tiles_stock
中的值,然后根据配置来初始化系统内置的 Quick Setting :
这段代码应该很简单,这里就不多做说明了。
第三方应用中包含的 Tile
对于 SystemUI 来说,除了要列出系统内置的 Quick Setting 之外,还有开发者开发的 Quick Setting 也需要读取。这部分逻辑通过 QueryTilesTask 以一个异步的Task来完成,这在这个异步任务中,会通过 PackageManager 查询所有开发者开发的 Quick Setting。
这段代码说明如下:
通过 PackageManager 查询所有设置了 TileService.ACTION_QS_TILE 的组件。 PackageManager 负责了所有应用包信息的管理。
遍历查询到的所有组件
跳过系统预置的 Tile
为每个Tile读取标签和图标
相关资料:
Android N Quick Settings:
https://codelabs.developers.google.com/codelabs/android-n-quick-settings/index.html
Android 7.0 开发者版本:
https://developer.android.com/about/versions/nougat/android-7.0.html
android.service.quicksettings:
https://developer.android.com/reference/android/service/quicksettings/package-summary.html
推荐阅读: