在SystemUI中,状态栏和通知栏都是在PhoneStatusBar的makeStatusBarView方法添加进来的,这里主要说说状态栏中的QuickSettingPanel
// ================================================================================
// Constructing the view
// ================================================================================
protected PhoneStatusBarView makeStatusBarView() {
final Context context = mContext;
Resources res = context.getResources();
updateDisplaySize(); // populates mDisplayMetrics
updateResources();
mStatusBarWindow = (StatusBarWindowView) View.inflate(context,
R.layout.super_status_bar, null);
....
mStatusBarView = (PhoneStatusBarView) mStatusBarWindow.findViewById(R.id.status_bar);
mStatusBarView.setBar(this);
PanelHolder holder = (PanelHolder) mStatusBarWindow.findViewById(R.id.panel_holder);
mStatusBarView.setPanelHolder(holder);
mNotificationPanel = (NotificationPanelView) mStatusBarWindow.findViewById(
R.id.notification_panel);
mNotificationPanel.setStatusBar(this);
// Set up the quick settings tile panel
mQSPanel = (QSPanel) mStatusBarWindow.findViewById(R.id.quick_settings_panel);
if (mQSPanel != null) {
final QSTileHost qsh = new QSTileHost(mContext, this,
mBluetoothController, mLocationController, mRotationLockController,
mNetworkController, mZenModeController, mHotspotController,
mCastController, mFlashlightController,
mUserSwitcherController, mKeyguardMonitor,
mSecurityController);
mQSPanel.setHost(qsh);
mQSPanel.setTiles(qsh.getTiles());
mBrightnessMirrorController = new BrightnessMirrorController(mStatusBarWindow);
mQSPanel.setBrightnessMirror(mBrightnessMirrorController);
mHeader.setQSPanel(mQSPanel);
qsh.setCallback(new QSTileHost.Callback() {
@Override
public void onTilesChanged() {
mQSPanel.setTiles(qsh.getTiles());
}
});
}
....
return mStatusBarView;
}
下面主要说下图中QuickSetting是什么显示出来以及图中的每个控件功能是何如实现的
具体图标对应的id在这就不一一说明了,可以自己对着上面的图去看,下面主要分析下这个界面是怎么显示出来的,在PhoneStatusBar的makeStatusBarView方法中加载了super_status_bar.xml文件
mStatusBarWindow = (StatusBarWindowView) View.inflate(context,
R.layout.super_status_bar, null);
....
....
在上面这个布局文件中include了status_bar_expanded.xml,在这个文件中差不多就包含了图中所有控件,其中qs_panel.xml主要包括亮度调节框及以下的那一块,status_bar_expanded_header
主要是亮度调节框以上部分
....
....
在这个布局中包含了status_bar_expanded_header.xml,下面具体看看status_bar_expanded_header这个布局文件,这个布局文件中主要包含了亮度调节框上面那一部分
其余的控件差不多都在qs_panel.xml里了
其中QSPanel是继承自ViewGroup的一个控件,里面包含了亮度调节框,以及wifi,蓝牙这些图标
public QSPanel(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
mDetail = LayoutInflater.from(context).inflate(R.layout.qs_detail, this, false);
mDetailContent = (ViewGroup) mDetail.findViewById(android.R.id.content);
mDetailSettingsButton = (TextView) mDetail.findViewById(android.R.id.button2);
mDetailDoneButton = (TextView) mDetail.findViewById(android.R.id.button1);
updateDetailText();
mDetail.setVisibility(GONE);
mDetail.setClickable(true);
mBrightnessView = LayoutInflater.from(context).inflate(
R.layout.quick_settings_brightness_dialog, this, false);
mFooter = new QSFooter(this, context);
addView(mDetail);
addView(mBrightnessView);
addView(mFooter.getView());
mClipper = new QSDetailClipper(mDetail);
updateResources();
mBrightnessController = new BrightnessController(getContext(),
(ImageView) findViewById(R.id.brightness_icon),
(ToggleSlider) findViewById(R.id.brightness_slider));
// Set up the quick settings tile panel
mQSPanel = (QSPanel) mStatusBarWindow.findViewById(R.id.quick_settings_panel);
if (mQSPanel != null) {
final QSTileHost qsh = new QSTileHost(mContext, this,
mBluetoothController, mLocationController, mRotationLockController,
mNetworkController, mZenModeController, mHotspotController,
mCastController, mFlashlightController,
mUserSwitcherController, mKeyguardMonitor,
mSecurityController);
mQSPanel.setHost(qsh);
mQSPanel.setTiles(qsh.getTiles());
mBrightnessMirrorController = new BrightnessMirrorController(mStatusBarWindow);
mQSPanel.setBrightnessMirror(mBrightnessMirrorController);
mHeader.setQSPanel(mQSPanel);
qsh.setCallback(new QSTileHost.Callback() {
@Override
public void onTilesChanged() {
mQSPanel.setTiles(qsh.getTiles());
}
});
}
在QSTileHost.java中会去加载默认配置需要显示的图标
protected List loadTileSpecs(String tileList) {
final Resources res = mContext.getResources();
final String defaultTileList = res.getString(R.string.quick_settings_tiles_default);
if (tileList == null) {
tileList = res.getString(R.string.quick_settings_tiles);
if (DEBUG) Log.d(TAG, "Loaded tile specs from config: " + tileList);
} else {
if (DEBUG) Log.d(TAG, "Loaded tile specs from setting: " + tileList);
}
final ArrayList tiles = new ArrayList();
boolean addedDefault = false;
for (String tile : tileList.split(",")) {
tile = tile.trim();
if (tile.isEmpty()) continue;
if (tile.equals("default")) {
if (!addedDefault) {
tiles.addAll(Arrays.asList(defaultTileList.split(",")));
addedDefault = true;
}
} else {
tiles.add(tile);
}
}
return tiles;
}
wifi,bt,inversion,dnd,cell,airplane,rotation,flashlight,location,cast,hotspot
只有配置了才可能会显示wifi,bt等这些图标,这些图标都对应着一个实体类,这些类都继承自QSTile @Override
protected void handleUpdateState(BooleanState state, Object arg) {
state.visible = mFlashlightController.isAvailable();
state.label = mHost.getContext().getString(R.string.quick_settings_flashlight_label);
if (arg instanceof UserBoolean) {
boolean value = ((UserBoolean) arg).value;
if (value == state.value) {
return;
}
state.value = value;
} else {
state.value = mFlashlightController.isEnabled();
}
final AnimationIcon icon = state.value ? mEnable : mDisable;
icon.setAllowAnimation(arg instanceof UserBoolean && ((UserBoolean) arg).userInitiated);
state.icon = icon;
int onOrOffId = state.value
? R.string.accessibility_quick_settings_flashlight_on
: R.string.accessibility_quick_settings_flashlight_off;
state.contentDescription = mContext.getString(onOrOffId);
}
其中反色和热点两个图标会根据是不是最近使用过mUsageTracker.isRecentlyUsed(),来动态显示或隐藏
HotspotTile.java
@Override
protected void handleUpdateState(BooleanState state, Object arg) {
state.visible = mController.isHotspotSupported() && mUsageTracker.isRecentlyUsed();
state.label = mContext.getString(R.string.quick_settings_hotspot_label);
if (arg instanceof Boolean) {
state.value = (boolean) arg;
} else {
state.value = mController.isHotspotEnabled();
}
state.icon = state.visible && state.value ? mEnable : mDisable;
}
ColorInversionTile.java
@Override
protected void handleUpdateState(BooleanState state, Object arg) {
final int value = arg instanceof Integer ? (Integer) arg : mSetting.getValue();
final boolean enabled = value != 0;
state.visible = enabled || mUsageTracker.isRecentlyUsed();
state.value = enabled;
state.label = mContext.getString(R.string.quick_settings_inversion_label);
state.icon = enabled ? mEnable : mDisable;
}
其它几个控件就不在详细说明了,可以对着第一张图看。另外提一点就是自己最近遇到的问题,亮度条不能拖动调节,只能点击调节。
如果遇到通知栏里的控件不能click或move事件没有效果,可以在NotificationPanelView.java和PanelView.java的onInterceptTouchEvent和onTouchEvent中添加log,
看是不是有对应event事件被拦截了,导致控件本身的event事件没有响应到。