com.android.systemui.statusbar.phone.StatusBar.java
该文件布局文件为R.layout.status_bar_expanded,其中包含了statusBar的布局

创建绑定QSFragment.java
// Set up the quick settings tile panel
View container = mStatusBarWindow.findViewById(R.id.qs_frame);
if (container != null) {
FragmentHostManager fragmentHostManager = FragmentHostManager.get(container);
ExtensionFragmentListener.attachExtensonToFragment(container, QS.TAG, R.id.qs_frame,
Dependency.get(ExtensionController.class)
.newExtension(QS.class)
.withPlugin(QS.class)
.withDefault(this::createDefaultQSFragment)
.build());
mBrightnessMirrorController = new BrightnessMirrorController(mStatusBarWindow,
(visible) -> {
mBrightnessMirrorVisible = visible;
updateScrimController();
});
fragmentHostManager.addTagListener(QS.TAG, (tag, f) -> {
QS qs = (QS) f;
if (qs instanceof QSFragment) {
mQSPanel = ((QSFragment) qs).getQsPanel();
mQSPanel.setBrightnessMirror(mBrightnessMirrorController);
}
});
}
R.layout.qs_pannel即是你要找的布局,而其中QSPannel.java类就是一个自定义view,这就需要在这里面添加东西
在QSFragment.java中就定义了头部中间部分和尾部

public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mQSPanel = view.findViewById(R.id.quick_settings_panel);
mQSDetail = view.findViewById(R.id.qs_detail);
mHeader = view.findViewById(R.id.header);
mFooter = view.findViewById(R.id.qs_footer);
mContainer = view.findViewById(id.quick_settings_container);
mQSDetail.setQsPanel(mQSPanel, mHeader, (View) mFooter);
mQSAnimator = new QSAnimator(this,
mHeader.findViewById(R.id.quick_qs_panel), mQSPanel);
mQSCustomizer = view.findViewById(R.id.qs_customize);
mQSCustomizer.setQs(this);
if (savedInstanceState != null) {
setExpanded(savedInstanceState.getBoolean(EXTRA_EXPANDED));
setListening(savedInstanceState.getBoolean(EXTRA_LISTENING));
setEditLocation(view);
mQSCustomizer.restoreInstanceState(savedInstanceState);
if (mQsExpanded) {
mQSPanel.getTileLayout().restoreInstanceState(savedInstanceState);
}
}
setHost(mHost);
}
这里是QSFragment控制展开还是不展开的状态控制
然后我们就可以去QSPannel.java类中看其展开的状态

其中就有一个PagedTileLayout类,这是一个继承与ViewPager的自定义view,所以展开选项一般分几个界面,其中就需要进里面查看这个对象mTileLayout如何初始化的了,其中选中其中adapte中的数据TilePage类mPages

这就发现实际加载的界面布局为 com.android.systemui.qs.PagedTileLayout.TilePage该类
其中就发现该对象的添加数据对象是TileRecord这个类,响应事件应该是com.android.systemui.qs.QSPanel.QSTileLayout这个接口实现的,然后我们在返回去,查看是哪里的数据加载了这个界面

发现还是查看com/android/systemui/qs/PagedTileLayout.java这个文件中的mPages,而这个加载又指向了其中的mTiles,所以只需要找这个数据是谁给的就行了

之后发现是QSPannel.java类中的addTile()方法添加的TileRecord对象

此时就有两个一个是QSTile.java这个是数据对象,另一个是QSTileView.java这个是UI对象,先现就一下UI对象QSTileView,

从而跳转到了QSTileHost.java中,
之后具体实现在QSFactoryImpl.java中,然而这两种情况,都指向了QSTileBaseView.java中的构造函数

其中QSTileBaseView.java中

所以这个又转回QSIconView中,而QSIconView是个abstract类,转向了QSIconViewImpl.java类中
其中QSPannel.java中的数据指向

其中这个setTiles在com/android/systemui/qs/QuickQSPanel.java类中以及QSPannel.java类中都指向QSTileHost的mHost对象了,这就需要找mHost的getTiles中赋值在哪了

从而在QSTileHost.java中发现,其中的值来自mTiles,而这个mTiles中的赋值只有一处

就是在QSTileHost.java中的onTuningChanged()函数中,而这个函数调用实现是在TunerServiceImpl.java中的addTunable调用的,到这就可以结束了,这个onTuningChanged是通知
这边刷新UI的,具体就看QSTileHost这里的onTuningChanged内容;

这里有两个关键的方法,一个是获取config里面的字符串信息,

一个是实例化Tile的creatTile(titleSpecs)

然后指向QSFactoryImpl.java对象中的createTile()

最后根据字符串实例化对象

所以添加QSTile就只需要添加对应字符串,然后添加对应对象实例化就行;
到这就应该如何添加自定义QSTile按键了,然后如何自定义案件的布局就需要找到对应控件了,
其中在com/android/systemui/qs/TileLayout.java中的layoutTileRecords()方法中就有添加单独对象的方法

从这里看出,就是将之前添加中TileRecord对象里面的tileView自定义就行,而这个tileView创建就在之前提及的QSFactoryImpl.java中

从而自定义布局就是更改这个QSTileBaseView的布局,而这个QSTileBaseView中添加了一个QSIconView,更改这个就可以达到目的了,

而这个QSIconView更改只覆盖掉QSTileImpl中的createTileView()返回的QSIconView对象就行,所以要在自定义继承QSTileImpl类中重写createTileView()方法就行,其中可以参考com/android/systemui/qs/SignalTileView.java方式重写。
adb shell settings get secure sysui_qs_tiles
可以查看实际qs_tiles读取的字符串,这样子看实际有没有更改加载到内容
文章详细介绍了在AndroidSystemUI中,如何创建、定制QSFragment和QSPanel的布局,涉及PagedTileLayout、TileRecord、QSTileView等关键组件的使用和数据加载过程。重点在于自定义QSTile和QSIconView的实现方法,以及设置和管理UI元素的逻辑。
1981

被折叠的 条评论
为什么被折叠?



