標籤:ionic hdp 手電筒 通過 擷取 成員變數 context protected cloc
快速設定面板上快捷開關的載入流程,包括表徵圖等的載入和點擊事件等的處理過程,以及建立一個快捷開關的主要過程(以增加一個鎖屏開關為例)。本文所討論的Android版本為5.1。
資源模組的載入
config.xml是程式的一些配置資訊。在建立快捷開關時需要按照參數設定檔config.xml來載入快捷開關資訊。參考源碼QSTileHost.java的實現,主要過程:
(1) QSTileHost類在建構函式裡調用recreateTiles() 方法;
(2) 在recreateTiles() 方法裡loadTileSpecs();
(3) loadTileSpecs() 方法裡通過mContext.getResources().getString(R.string.quick_settings _tiles_default) 從config.xml中載入快捷開關規 格”quick_settings_tiles_default” 這個配置項便確定了預設情況下快速設定面板上顯示哪些開關以及開關的顯示順序;
(4) 接下來建立快捷開關createTile() ,通過從config.xml檔案中擷取的配置資訊執行個體化每個快捷開關;
(5) 最後將建立的快捷開關儲存在成員變數mTiles列表裡,通過調用QSTileHost.getTiles() 可以擷取到所有的快捷開關。
字元資源儲存在各個value檔案夾下的String.xml檔案內。表徵圖使用的是向量圖片,儲存在drawable檔案夾下。字元和表徵圖的載入在每個快捷開關類檔案的handleUpdateState() 方 法裡進行。
每個快捷開關類都需要繼承QSTile<TState extends State>類(詳細的說明在2.3節討論)。這裡的TState是快捷開關的狀態,會作為參數傳到handleUpdateState() 方法。在 handleUpdateState() 方法裡將字元和表徵圖資源賦值給state.label和state.icon即可。
動畫資源與表徵圖一起儲存在drawable檔案夾下,一般都是開啟和關閉成對存在的。動畫的載入是通過在每個快捷開關類裡執行個體化AnimationIcon類,資源id將作為參數,然後會在點 擊事件處理中調用。
PhoneStatusBar建立view
前面提到在QSTileHost.createTile() 方法裡建立了快捷開關,並且可以通過調用getTiles() 方法得到所有的快捷開關,接下來看快捷開關載入到快速設定面板的實現。參考 PhoneStatusBar. makeStatusBarView() 方法的實現,主要完成的部分:
(1) 首先初始化快捷開關面板mQSPanel,mQSPanel判空後執行個體化QSTileHost儲存在對象qsh上;
(2) 通過調用mQSPanel.setTiles(qsh.getTiles()) 將每個快捷開關添加到mQSPanel上。另外,在配置有變化時,在PhoneStatusBar.updateResources() 方法裡通過調用 mQSPanel. updateResources() 更新快捷開關面板;在解鎖屏時,在PhoneStatusBar. hideKeyguard () 方法裡通過調用mQSPanel. refreshAllTiles () 重新整理快捷開關面板。
使用者互動的處理
對使用者動作的監聽響應是在每個快捷開關類裡處理。
前面提到,每個快捷開關類都需要繼承QSTile<TState extends State>類。
QSTile<TState extends State> implements Listenable是快捷開關的基類,通過繼承它來建立一個快捷開關。需要實現兩個抽象方法handleClick() 和handleUpdateState() 。所以可以看出QSTile主要負責點擊事件的處理和快捷開關狀態的管理。訊息的傳遞通過Handler機制完成。
(1) 動作的監聽響應:
1) 在handleClick() 方法裡處理點擊事件;開啟/關閉的動畫也在這裡調用;
2) 部分開關需要重寫handleSecondaryClick() 方法,例如Wi-Fi和藍芽開關,在handleSecondaryClick() 方法裡開啟詳情頁面;
3) 還有開關需要重寫handleLongClick() ,例如反色和熱點開關,在這裡開啟詢問是否要隱藏的對話方塊;
4) 在setListening() 方法裡添加回調監聽,接受action和註冊廣播等。
(2) 狀態的管理:
1) 狀態管理通過一個由Host提供的looper來進行。每個快捷開關在handleUpdateState()中更新狀態。回調影響狀態要通過快捷開關的工作looper調用refreshState() 來觸 發另一個狀態更新。
2) 狀態類有三種,State類以及繼承自State類的BooleanState類和SignalState類。需要判斷開關與否的狀態的快捷開關繼承QSTile<QSTile.BooleanState>,包括飛行 模式、反色、手電筒、熱點、定位、自動旋轉、藍芽和螢幕投射開關等;還需要判斷串連等狀態的快捷開關繼承QSTile<QSTile.SignalState>,例如Wi-Fi和移動資料網 絡開關;其他直接繼承QSTile<QSTile.State>。
(3) 另外,Wi-Fi和藍芽開關需要重寫supportsDualTargets() 方法和getDetailAdapter() 方法。因為這兩個開關是繪製在一排兩個開關的布局上而且需要顯示詳情頁面。
以增加一個鎖屏的快捷開關為例。
資源模組的增加
通過2.1節的討論可以知道,需要修改config.xml檔案、String.xml檔案和添加向量圖xml檔案或添加一張png圖片。鎖屏開關點擊時不需要動畫,因此不添加動畫xml檔案
(1) 在\frameworks\base\packages\SystemUI\res\values\config.xml裡找到 "quick_settings_ tiles_default",添加lockscreen,用“,”隔開:
<string name="quick_settings_tiles_default" translatable="false">
wifi,bt,inversion,cell,airplane,rotation,flashlight,location,cast,hotspot,lockscreen
</string>
(2) 在\frameworks\base\packages\SystemUI\res\values\string.xml裡添加:
<string name="quick_settings_lockscreen_label">
"lockscreen"
</string>
(3) 在\frameworks\base\packages\SystemUI\res\values values-zh-rCN\string.xml裡添加:
<string name="quick_settings_lockscreen_label">"鎖屏"</string>
其他語言在相應的values檔案夾下對應的string.xml檔案裡添加。
(4) 在\frameworks\base\packages\SystemUI\res\drawable-hdpi檔案夾裡添加圖片ic_qs_locks- creen.png,也可以在drawable檔案夾下添加向量圖xml檔案;
建立LockScreenTile類
在/frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles目錄下建立LockScreenTile.java。
(1) 建立鎖屏快捷開關類LockScreenTile extends QSTile<QSTile.BooleanState>,繼承QSTile類;
(2) newTileState() 方法直接返回一個BooleanState的執行個體;
@Override
protected BooleanState newTileState() {
return new BooleanState();
}
(3) handleClick() 方法裡響應點擊事件進行鎖屏,調用PowerManager.goToSleep() 方法;
@Override
protected void handleClick() {
setEnabled(!mState.value);
}
private void setEnabled(boolean enable) {
if (enable) {
final PowerManager pmr = (PowerManager) mContext
.getSystemService(Context.POWER_SERVICE);
pmr.goToSleep(SystemClock.uptimeMillis());
}
}
(4) handleUpdateState() 方法裡設定鎖屏開關的狀態,包括表徵圖和字元;
@Override
protected void handleUpdateState(BooleanState state, Object arg) {
state.icon = ResourceIcon.get(R.drawable.ic_qs_lockscreen);
state.visible = true;
state.label = mContext.getString(R.string.quick_settings_lockscreen_label);
}
(5) 執行個體化LockScreenTile,在QSTileHost. createTile() 方法裡添加:
private 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("lockscreen"))
return new LockScreenTile(this);
else if (tileSpec.startsWith(IntentTile.PREFIX))
return IntentTile.create(this, tileSpec);
else
throw new IllegalArgumentException("Bad tile spec: "+ tileSpec);
}
Android下拉快捷設定面板添加快捷開關流程