QSTile 的一点变化 Android O 与 Android N 相比

本文探讨了Android N与O版本中QSPanel数据图标点击行为的变化,特别是针对Android O版本中tile布局和点击事件处理的不同。通过分析源代码,揭示了如何在Android O上实现数据图标详情展示的功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

起因

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 分支。

### 设置 Android 状态栏图标显示顺序 在 Android 中,状态栏图标的显示顺序主要受 `SystemUI` 组件控制。对于自定义或修改状态栏中图标的排列方式,通常涉及以下几个方面: #### 1. 修改配置文件中的图标组定义 为了调整状态栏内各个图标的位置,可以在 `config.xml` 文件里重新指定各组图标及其优先级。此操作需针对特定设备制造商提供的源码进行编辑[^4]。 ```xml <item name="status_bar_icons">wifi,bt,signal_battery</item> ``` 上述 XML 片段展示了如何通过更改资源数组来影响不同服务对应的小部件展示次序。 #### 2. 自定义 `StatusBarIconController` 如果希望更灵活地管理这些图形元素,则可以考虑继承并扩展官方 API 提供的 `StatusBarIconController` 接口。这允许开发者创建自己的逻辑用于动态更新 UI 布局以及响应来自系统的广播消息等事件[^1]。 ```java public class CustomStatusBarIconController extends StatusBarIconController { @Override protected void addIconGroup(DynamicIconManager manager) { // 定制化添加图标分组逻辑 super.addIconGroup(manager); List<String> customOrder = Arrays.asList("custom_wifi", "custom_bt"); Collections.sort(currentIcons, (a, b) -> Integer.compare( customOrder.indexOf(a.slot), customOrder.indexOf(b.slot))); } } ``` 这段 Java 代码片段给出了一个简单的例子,说明怎样利用子类覆盖方法实现对原有行为的增强——即按照预设列表重排已加载项之间的相对位置关系。 #### 3. 调整快捷设置面板(Quick Settings Panel) 除了常规的通知区域外,用户还可以经由下拉菜单访问到更多实用工具按钮组成的面板。要改变其中各项功能入口所处的具体地点,同样依赖于深入研究框架内部结构,并适当介入相关处理过程以达成预期效果[^3]。 ```diff // frameworks/base/packages/SystemUI/src/com/android/systemui/qstile/BleTile.java private static final int TILE_ORDERING = 7; // 更改数值可移动蓝牙开关至其他地方 ... mQsTileView.setZ(TILE_ORDERING); ``` 以上是对原生组件属性的一次简单改动示范;实际应用时或许还需要同步修正配套样式表及其他关联部分才能确保整体协调一致。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值