system UI预置的(QSTile),第三方应用添加的(CustiomTile 7.0 才有的)
一、 创建自定义的Tile
二、Tile加载流程
Tile中方法
handleClick() 短按
getLongClickIntent() 长按
handleUpdateState() 更新状态
handleSecondaryClick() 点击开关label显示详情页
getToggleState() 若返回null详情页不显示switch开关。
getSettingsIntent() 跟长按的intent一样进入设置对应的界面。若返回null详情页不显示详细信息。
(1) 动作的监听响应:
在handleClick() 方法里处理点击事件;打开/关闭的动画也在这里调用;
部分开关需要重写handleSecondaryClick() 方法,例如Wi-Fi和蓝牙开关,在handleSecondaryClick() 方法里打开详情页面;
还有开关需要重写handleLongClick() ,例如反色和热点开关,在这里打开询问是否要隐藏的对话框;
在setListening() 方法里添加回调监听,接受action和注册广播等。
(2) 状态的管理:
状态管理通过一个由Host提供的looper来进行。
每个快捷开关在handleUpdateState()中更新状态。回调影响状态要通过快捷开关的工作looper调用refreshState() 来触发另一个状态更新。
状态类有三种,State类以及继承自State类的BooleanState类和SignalState类。需要判断开关与否的状态的快捷开关继承QSTile<QSTile.BooleanState>,
包括飞行模式、反色、手电筒、热点、定位、自动旋转、蓝牙和屏幕投射开关等;还需要判断连接等状态的快捷开关继承QSTile<QSTile.SignalState>,例如Wi-Fi和移动数据网络开关;其他直接继承QSTile<QSTile.State>。
(3) 另外,Wi-Fi和蓝牙开关需要重写supportsDualTargets() 方法和getDetailAdapter() 方法。因为这两个开关是绘制在一排两个开关的布局上而且需要显示详情页面。
QSTile:快速设置Tile的基类,快速设置都继承自这个类。
Tile通过重载handleUpdateState方法来更新状态。如果监听到状态变化,或者点击事件需要更新状态,使用refreshState来更新State。
QSTileHost: Host的实现,管理Tile 状态的变化。它包含各种Tile的Control类,用来设置和监听Tile。
State: Tile的状态,包含图标,名称等信息。
H:继承自Handler, 通过looper跑在QSTileHost的线程里。用来处理Tile的各种事件。
Tunable: 接口,配置变化的回调。QSTileHost实现这个接口。
TunerSercice:用来监听各种配置变化。
界面的分析
QuickStatusBarHeader -- QuickQSPanel(其中加载 HeaderTileLayout) (NUM_QUICK_TILES = "sysui_qqs_count" 第一次下拉显示时,显示的tile数量)
QSContainer --
QSPanel 全部的位置
之前在 statusbar 的加载中已经写到了
createQSTileHost() --> SystenUIFactory.QSTileHost() --> QSTileHost.addTunable()
TunerService.addTunable的方法,会监听ContentProvider中的Tile的变化
private void addTunable(Tunable tunable, String key) {
if (!mTunableLookup.containsKey(key)) {
mTunableLookup.put(key, new ArraySet<Tunable>());
}
mTunableLookup.get(key).add(tunable);
Uri uri = Settings.Secure.getUriFor(key);
if (!mListeningUris.containsKey(uri)) {
mListeningUris.put(uri, key);
//listening for the tile change
mContentResolver.registerContentObserver(uri, false, mObserver, mCurrentUser);
}
// Send the first state.
String value = Settings.Secure.getStringForUser(mContentResolver, key, mCurrentUser);
//回调 onTuningChanged, 当tile 创建,变化时
tunable.onTuningChanged(key, value);
}
在QSPanel的addTile中, TileRecord就是一个普通的类(当成javabean就好)包含tile view data callback
QSPanel
HeaderTileLayout的add Tile方法,
protected void addTile(final QSTile<?> tile, boolean collapsedView) {
final TileRecord r = new TileRecord();
r.tile = tile;
r.tileView = createTileView(tile, collapsedView);
//callback
final QSTile.Callback callback = new QSTile.Callback() {
...
...
r.tile.addCallback(callback);
r.callback = callback;
//onclick
final View.OnClickListener click = new View.OnClickListener() {
@Override
public void onClick(View v) {
onTileClick(r.tile);
}
};
//onlongclick
final View.OnLongClickListener longClick = new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
r.tile.longClick();
return true;
}
};
r.tileView.init(click, longClick);
r.tile.refreshState();
//全部都给mRecords塞进去
mRecords.add(r);
if (mTileLayout != null) {
mTileLayout.addTile(r);
}
}
QSTile 的触摸点击
QSTileView extends QSTileBaseView extends QSTileView extends LinearLayout
点击事件的塞入,实际是在 QSTileBaseView.init() 和 QSTileView.init() 方法中
setOnClickListener();
setOnLongClickListener();
QSTileImpl extends QSTile
QSTileImpl.click()/QSTileImpl.secondaryClick() --> handler senMessage H.CLICK/REDERSH/SHOW_DETAIL --> handMessage/handleShowDetail/ 抽象方法 --> 实现类的
每个QSTile的子类都可以重载handleSecondaryClick方法,来区别未展开和展开的Tile点击事件。
所以,点击QuickQSPanel的Tile界面,执行的是 --> handleSecondaryClick。
QSPanel的点击事件流程。触发点击事件后,执行QSTile的handleClick方法,refreshState或0showDetail。
refreshState的流程,QSTile的子类,要在这里更新Tile的State
QSTile.Callback的onShowDetail
2.longClick事件
长按事件也是在QSPanl的addTile方法里创建的,
最后会执行到handleLongClick的方法在这里会从getLongClickIntent里面,获取一个Intent, 启动该Intent的activity。
getLongClickIntent 在每个tile具体类中实现