主要代码: com.android.systemui.qs 包下
一. 基本布局
1.0 super_status_bar.xml
包括很多,其中有 include/status_bar.xml
include/status_bar_expand.xml 是2个最主要经常修改的
1.1 status_bar.xml
status_bar.xml
notification_lights_out id/status_bar_contents
| |
| |
id/notification_icon_area(左边,通知图标) id/system_icon_area(右边)
(CollapsedStatusBarFragment中getView, | |
add notification_icon_area.xml) | |
| id/clcok (时间)
include/system_icons.xml
| | |
| | |
id/statusicon include/signal_cluster_view.xml id/battery(BatteryMeterView)
(网速,蓝牙,蓝牙、闹钟、耳机插入等) ( 信号) (电量百分比,电池图标)
1.2 status_bar_expand.xml
NotificationPanelView.java
| | | |
include/keyguard_status_view NotificationsQuickSettingsContainer 之前 include layou/status_bar_expand_header include/keguard_button_area
(id/notification_container_parent) 8.0 include layout/quick_status_bar_expand_header
(锁屏时,大时间的显示) (展开通知栏以后 QS + notification 的父布局) (下拉状态栏之后, QSpanel顶部的所有部分) (锁屏后底部的区块)
| | |
id/QS_frame NotificationStackScrollLayout.java id/keyguard_status_bar
layout/qs_palel.xml id/notification_stack_scroller (锁屏后的状态栏)
(通知栏折叠下拉的通知部分)
二. statusbar,qspanel 界面的加载流程
Statusbar.java {
//比较重要的一些元素
mBluetoothController, //蓝牙
mLocationController, //地址
mRotationLockController,//自动旋转
mNetworkController, //数据开关
mZenModeController, //勿扰模式
mHotspotController, //热点
mCastController, //投射
mFlashlightController,//手电筒
mBatteryController, // 电池管理
mHotKnotController, // 热点
mRingController, //铃声模式
mNfcController //NFC
....
private StatusBarWindowManager mStatusBarWindowManager; // 对mStatusBarWindow statusbar的管理
private StatusBarWindowView mStatusBarWindow; // R.layout.super_status_bar
private PhoneStatusBarView mStatusBarView;
private int mStatusBarWindowState = WINDOW_STATE_SHOWING; // statusbar 的状态标识符
private IStatusBarService mBarService; // StatusBarManagerService 主要 registerStatusBar
public void setQsExpand(boolean expand){
mStatusBarWindowManager.setQsExpand(expand);
.....
}
start(){
}
createAndAddWindows(){
}
addStatusBarWinodw(){
makeStatusBarView();
...
...
//***实际在 mStatusBarWindowManager 中的 windowManager.add() ***//
mStatusBarWindowManager.add( mStatusBarWindow , getStatusBarHeight());
}
makeStatusBarView(){
// 加载StatusBarWindowView视图,该视图包括Status bar/Quick Settings/Notification Panel
mStatusBarWindow = (StatusBarWindowView) View.inflate(context,R.layout.super_status_bar, null)
// 监听OnTouch事件,当下拉时展开Notification Panel
mStatusBarWindow.setOnTouchListener(......
// 获取Status bar视图
//old -- mStatusBarView = (PhoneStatusBarView) mStatusBarWindow.findViewById(R.id.status_bar);
//8.0
mStatusBarView = (PhoneStatusBarView)fragment.getView();
mStatusBarView.setBar(this);
// 实例化IStatusBarService
mBarService = IStatusBarService.Stub.asInterface(
ServiceManager.getService(Context.STATUS_BAR_SERVICE));
// Connect in to the status bar manager service
mCommandQueue = new CommandQueue(this);
try {
// register后,
// StatusBar通过CommandQuene间接将自己注册到StatusBarManagerService,
// 而StatusBarManagerService会把操作状态栏和导航栏的请求通过CommandQuene再转发给StatusBar
//
mBarService.registerStatusBar(mCommandQueue, iconSlots, icons, switches, binders,
fullscreenStackBounds, dockedStackBounds);
} catch (RemoteException ex) {
// If the system process isn't there we're doomed anyway.
}
createAndAddWindows();
.........
很多其他的system ui 组件创建
.........
//主要就是 mStatusBarWindow(super_status_bar.xml)中的 status_bar_container 加载 CollapsedStatusBarFragment
//addTagListener 回调方法
FragmentHostManager.get(mStatusBarWindow)
.addTagListener(CollapsedStatusBarFragment.TAG, (tag, fragment) -> {
//在replace之后回调
CollapsedStatusBarFragment statusBarFragment =
(CollapsedStatusBarFragment) fragment;
statusBarFragment.initNotificationIconArea(mNotificationIconAreaController);
mStatusBarView = (PhoneStatusBarView) fragment.getView();
mStatusBarView.setBar(this);
mStatusBarView.setPanel(mNotificationPanel);
mStatusBarView.setScrimController(mScrimController);
setAreThereNotifications();
checkBarModes();
}).getFragmentManager()
.beginTransaction()
//加载 CollapsedStatusBarFragment
.replace(R.id.status_bar_container, new CollapsedStatusBarFragment(),
CollapsedStatusBarFragment.TAG)
.commit();
//**** 接下来看看CollapsedStatusBarFragment
CollapsedStatusBarFragment.java{
oncreateView(){
return inflate.inflate(R.layout.status_bar, container , null);
}
onViewCrewate(){
//对状态栏个状态,图标等进行初始化
}
}****//
.....
.....
//set up quick settings tile panel
//下拉栏的总区域
View container = mStatusBarWindow.findViewbyID(R.id.qs_frame);
if (container != null) {
// (可以搜索关键字 QSHost)获取默认显示的快捷按钮,并添加到qsh对象的mTiles变量中,createQSTileHost 方法
final QSTileHost qsh = SystemUIFactory.getInstance().createQSTileHost(mContext, this,..
//***
走到
QSTileHost.java{ 的初始化方法中
public QSTileHost(){
Dependecy.get(TunerService.class).addTunable();
//****** 然后走到 TunerServiceImpl addTunable ******//
TunerServiceImpl.java{
private void addTunable(Tunable tunable, String key) {
// 回调到QSTileHost,key = sysui_qs_tiles
tunable.onTuningChanged(key, value);
}
}
//****** ****** ******//
}
@Override
public void onTuningChanged(String key, String newValue) {
...
// 返回分割好的QSTile名字list
final List<String> tileSpecs = loadTileSpecs(mContext, newValue);
...
// 根据名字创建具体的QSTile, 然后回调用QSFactoryI
tile = createTile(tileSpec);
//createTile 实际最后走到了
//**********
QSFactoryImpl.java{
public QSTile<?> createTile(String tileSpec) {
if (tileSpec.equals("wifi")) return new WifiTile(this);
else if (tileSpec.equals("bt")) return new BluetoothTile(this);
else if (tileSpec.equals("cell")) return new CellularTile(this);
else if (tileSpec.equals("dnd")) return new DndTile(this);
else if (tileSpec.equals("inversion")) return new ColorInversionTile(this);
else if (tileSpec.equals("airplane")) return new AirplaneModeTile(this);
...
...
}
*****//
}
}
}
***/
//将对象 qsh 放入,从qsh对象获取mTiles中保存的所有默认显示的快捷按钮并且添加到布局中显示
//进行具体的add view方法
((QSFragment)f).setHost(qsh);
QSFragment //qs_panel.xml
QSFragment.setHost --> QSPanel: setHost --> setTitles --> addTile 去把所有的 title add上
}
}
}
QSPanel.java
QSPanel.java{
public QSPanel(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
setOrientation(VERTICAL);
mBrightnessView = LayoutInflater.from(context).inflate(
R.layout.quick_settings_brightness_dialog, this, false);
//调节亮度
addView(mBrightnessView);
//加载mTileLayout对应的布局
setupTileLayout();
mPageIndicator = LayoutInflater.from(context).inflate(
R.layout.mTileLayoutqs_page_indicator, this, false);
addView(mPageIndicator);
// 快捷栏一页显示不全,添加滑动显示的标识圆点
if (mTileLayout instanceof PagedTileLayout) {
((PagedTileLayout) mTileLayout).setPageIndicator((PageIndicator) mPageIndicator);
}
addDivider(); // 分割线
mFooter = new QSSecurityFooter(this, context);
addView(mFooter.getView()); // 底部编辑
updateResources();
mBrightnessController = new BrightnessController(getContext(),
findViewById(R.id.brightness_icon),
findViewById(R.id.brightness_slider));
}
/**
* collapsedView = false 展开显示全部快捷键
* collapsedView = true 收起 显示5个快捷键
*/
public void setTiles(Collection> tiles, boolean collapsedView) { }
protected void addTile(final QSTile<?> tile, boolean collapsedView) {
final TileRecord r = new TileRecord();
r.tile = tile;
r.tileView = createTileView(tile, collapsedView);
final QSTile.Callback callback = new QSTile.Callback() {
//一些 QSTile的回调方法
public void onStateChanged(QSTile.State state)
public void onShowDetail(boolean show)
public void onToggleStateChanged(boolean state)
public void onScanStateChanged(boolean state)
}
r.tile.addCallback(callback);
r.callback = callback;
//为每个快捷键添加点击+长按
r.tileView.init(click, longClick);
r.tile.refreshState();
mRecords.add(r);
//将刚创建的快捷键添加到可滑动页面板区,即可显示在下拉通知栏中
//mTileLayout(PagedTileLayout)是QSPanel的child,
if (mTileLayout != null) {
mTileLayout.addTile(r);
}
PagedTileLayout.java extends ViewPager implements QSTileLayout,TunserService.Tunable{
@Override
public void addTile(TileRecord tile) {
mTiles.add(tile);
postDistributeTiles();
}
private void postDistributeTiles() {
removeCallbacks(mDistribute);
post(mDistribute);
}
private final Runnable mDistribute = new Runnable() {
@Override
public void run() {
distributeTiles();
}
};
private void distributeTiles() {
final int NP = mPages.size();
for (int i = 0; i < NP; i++) {
mPages.get(i).removeAllViews();
}
int index = 0;
final int NT = mTiles.size();
for (int i = 0; i < NT; i++) {
TileRecord tile = mTiles.get(i);
if (mPages.get(index).isFull()) {
if (++index == mPages.size()) {
if (DEBUG) Log.d(TAG, "Adding page for "
+ tile.tile.getClass().getSimpleName());
// list数据集添加 TilePage
mPages.add((TilePage) LayoutInflater.from(mContext)
.inflate(R.layout.qs_paged_page, this, false));
//****** TilePage.java , PagedTileLayout 的每一页 ******
public static class TilePage extends TileLayout {
//add 每一个子项
public void addTile(TileRecord tile) {
mRecords.add(tile);
tile.tile.setListening(this, mListening);
addView(tile.tileView); // 加载tile视图
}
public boolean updateResources(){
//3 * 3 布局各种修改
//4 * 3 布局各种修改
}
}
****/
}
}
// add tile,给adapter的数据mPages 添加数据
mPages.get(index).addTile(tile);
}
if (mNumPages != index + 1) {
mNumPages = index + 1;
while (mPages.size() > mNumPages) {
mPages.remove(mPages.size() - 1);
}
mPageIndicator.setNumPages(mNumPages);
mDecorGroup.setVisibility(mNumPages > 1 ? View.VISIBLE : View.GONE);
//设置adapter
setAdapter(mAdapter);
//刷新显示
mAdapter.notifyDataSetChanged();
setCurrentItem(0, false);
}
}
}
}
}