在Android7.0之后,任何程序都可以设置屏幕顶部下拉的设置了,为应用的快捷设置提供了极大的方便。
什么设置适合作为Quick settings tile,有两个关键要素:紧迫性和高频。
大家注意,因为这是一个常驻的设置,所以并不适合那些一次性的设置。
咱们首先需要定义一个继承TileService的服务,TileService是一个特殊的服务,在7.0系统中会自动识别并开启,这也就解决了低版本适配的问题。然后和其他的自定义服务一样,需要在manifest中配置:
<service
android:name=".AwesomeTileService"
android:icon="@drawable/ic_tile_default"
android:label="快速设置"
android:permission="android.permission.BIND_QUICK_SETTINGS_TILE">
<intent-filter>
<action
android:name="android.service.quicksettings.action.QS_TILE"/>
intent-filter>
service>
这里咱们需要配置Tile的名字,icon。以及对应的permission.
Tile多余18个字符会被截断,icon需要使用一张透明背景的白色矢量图,图片的着色是由当前系统决定的。
我们可以实现TileService的几个生命周期函数:
public class QuickSettingService extends TileService{
//当用户从Edit栏添加到快速设置中调用
@Override
public void onTileAdded() {
Log.d(LOG_TAG, "onTileAdded");
}
//当用户从快速设置栏中移除的时候调用
@Override
public void onTileRemoved() {
Log.d(LOG_TAG, "onTileRemoved");
}
// 点击的时候
@Override
public void onClick() {
Log.d(LOG_TAG, "onClick");
}
// 打开下拉菜单的时候调用,当快速设置按钮并没有在编辑栏拖到设置栏中不会调用
//在TleAdded之后会调用一次
@Override
public void onStartListening () {
Log.d(LOG_TAG, "onStartListening");
}
// 关闭下拉菜单的时候调用,当快速设置按钮并没有在编辑栏拖到设置栏中不会调用
// 在onTileRemoved移除之前也会调用移除
@Override
public void onStopListening () {
Log.d(LOG_TAG, "onStopListening");
}
}
如果咱们需要在非点击情况下改变Tile的状态,可以将Tile的Mode改为主动模式:
...
"android.service.quicksettings.ACTIVE_TILE"
android:value="true" />
可以在程序中的其他地方调用TileService.requestListeningState() 来触发 onStartListening函数
如下代码:
public class QuickSettingService extends TileService {
private final String LOG_TAG = "QuickSettingService";
//当用户从Edit栏添加到快速设定中调用
@Override
public void onTileAdded() {
Log.d(LOG_TAG, "onTileAdded");
}
//当用户从快速设定栏中移除的时候调用
@Override
public void onTileRemoved() {
Log.d(LOG_TAG, "onTileRemoved");
}
// 点击的时候
@Override
public void onClick() {
int state = getQsTile().getState();
Log.d(LOG_TAG, "onClick state = " + Integer.toString(getQsTile().getState()));
Icon icon;
if (state == Tile.STATE_INACTIVE) {
icon = Icon.createWithResource(getApplicationContext(), R.drawable.activeon);
getQsTile().setState(Tile.STATE_INACTIVE);// 更改成非活跃状态
} else {
icon = Icon.createWithResource(getApplicationContext(), R.drawable.add_photo);
getQsTile().setState(Tile.STATE_ACTIVE);//更改成活跃状态
}
getQsTile().setIcon(icon);//设置图标
getQsTile().updateTile();//更新Tile
}
// 打开下拉菜单的时候调用,当快速设置按钮并没有在编辑栏拖到设置栏中不会调用
//在TleAdded之后会调用一次
@Override
public void onStartListening() {
Log.d(LOG_TAG, "onStartListening");
}
// 关闭下拉菜单的时候调用,当快速设置按钮并没有在编辑栏拖到设置栏中不会调用
// 在onTileRemoved移除之前也会调用移除
@Override
public void onStopListening() {
Log.d(LOG_TAG, "onStopListening");
}
}
我们可以通过getQsTile来获得Tile对象,通过getState() 来获得Tile当前状态。
- STATE_ACTIVE 开启状态
- STATE_INACTIVE 关闭状态
- STATE_UNAVAILABLE 非可点击状态
最后必须调用updateTile() 来触发刷新。
在OnClick() 中,我们可以在UI线程上处理业务逻辑,耗时操作请交给另一个线程或IntentService执行。
其中我们可以开启Dialog或通过startActivityAndCollapse()开启一个Actvitiy。
但是在锁屏,也就是isLocked()返回true时,将不能打开Dialog,而Activity则需要增加FLAG_SHOW_WHEN_LOCKED这个Flag。
我们也可以使用unlockAndRun(Runnable) 来异步设置用户解锁后的工作。
用户长按Tile会默认打开app的app info页面,我们可以给Activity加上ACTION_QS_TILE_PREFERENCES 来重载此行为。
参考文献