QSTile 的一點變化 Android O 與 Android N 相比
起因
Android O 點選QSPanel 中的資料圖示沒法展開詳情檢視資料使用量,而在Android N 上可以的,所以想調檢視看O 上有什麼不同。
注:本文不涉及任何流程分析,只是單純的想找回個功能,並藉此描述一下O 和N 在tile 上的一點點不同。
現象差異
我們都知道在Android N 上QSTile 有兩種展示形式:
1. QSPanel 半展開是點選icon 即開關,執行的方法為handleSecondaryClick();
2. QSPanel 全展開時,點選icon 有些tile 有detai展示,比如下圖中的wifi tile,此時執行的方法是handleClick(),之後呼叫showDetail() 方法顯示詳細資訊;
但是到了Android O 上變的有點不一樣了:
1. 半展開時點選icon 和Android N 上效果一樣,但執行的方法是handleClick();
2. 全展開時有兩種情況,點選icon還是開關,此時執行的方法也是handleClick();
3. 全展開時點選label 會展示detail(如果有的話),有detail 的tile 在label 旁邊會有一個indicator,而且注意觀察的話,會發現點選icon 和點選label 水波紋的中心會不一樣(如果沒有detail 的話,點選label 也是上一種效果)。此時執行的方法是handleSecondaryClick()
那麼Android O 上是怎麼會有icon 和label 兩種點選事件的呢?
Tile 佈局
我們要想label 可以點選,那我們先看看這個indicator 是怎麼回事,從佈局看起。
找到幾個和tile,layout 相關的類,並沒有發現線索,直到在qs_tile_label.xml 中看到了下面的程式碼:
<!-- tile label -->
<TextView
android:id="@+id/tile_label"
...
android:textAppearance ="@style/TextAppearance.QS.TileLabel"
android:textColor="?android:attr/textColorPrimary"/>
<!-- 下面這個暫時不知道是做什麼的 -->
<ImageView android:id="@+id/restricted_padlock"
...
android:visibility="gone" />
<!-- 像是旁邊的indicator,且預設不可見,懷疑是這個了 -->
<ImageView
android:id="@+id/expand_indicator"
android:layout_marginStart="4dp"
android:layout_width="18dp"
android:layout_height="match_parent"
android:src="@drawable/qs_dual_tile_caret"
android:tint="?android:attr/textColorPrimary"
android:visibility="gone" />
之後在QSTileView.java 類中找到使用的地方:
protected void createLabel() {
mLabelContainer = (ViewGroup) LayoutInflater.from(getContext())
.inflate(R.layout.qs_tile_label, this, false);
...
mExpandIndicator = mLabelContainer.findViewById(R.id.expand_indicator); // here
mExpandSpace = mLabelContainer.findViewById(R.id.expand_space);
addView(mLabelContainer);
}
以及控制顯示的地方
@Override
protected void handleStateChanged(QSTile.State state) {
super.handleStateChanged(state);
...
mExpandIndicator.setVisibility(state.dualTarget ? View.VISIBLE : View.GONE); // 顯示與否依賴於 state.dualTarget
mExpandSpace.setVisibility(state.dualTarget ? View.VISIBLE : View.GONE);
mLabelContainer.setContentDescription(state.dualTarget ? state.dualLabelContentDescription
: null);
if (state.dualTarget != mLabelContainer.isClickable()) {
mLabelContainer.setClickable(state.dualTarget); // 設定是否可以點選
mLabelContainer.setLongClickable(state.dualTarget);
mLabelContainer.setBackground(state.dualTarget ? newTileBackground() : null);
}
mLabel.setEnabled(!state.disabledByPolicy);
mPadLock.setVisibility(state.disabledByPolicy ? View.VISIBLE : View.GONE);
}
可以看到indicator 的顯示受state.dualTarget 的控制。
考慮到另外也有幾個可以展開detail 的tile,比如Bluetooth等,我猜想state.dualTarget 一定會在那幾個tile 裡面賦值為true。我們搜一下,果然:
那我們在CellularTile 對應的位置也給dualTarget 賦值為true 應該就能達到我們最初想要的效果了。
結論和效果
新增state.dualTarget = true;
到CellularTile.java 的handleUpdateState() 方法後,效果如下:
state.dualTarget 控制了是否顯示indicator 以及label 是否可以點選,但點選有沒有反應要看有沒有實現相應的方法了。
點選mobile date 這裡並不是憑空多出來一個功能哈,是我知道有這個功能,只是沒顯示出來。
注:文中程式碼基於mko-mr1,一個基於aosp 的android 8.1 分支。