android9.0 density 改为 200 后 SystemUI 两个bug

简介: android9.0 density 改为 200 后 SystemUI 两个bug

Bug现象


aHR0cHM6Ly9zMi5heDF4LmNvbS8yMDIwLzAyLzE0LzFYR3hTSi5wbmc.png

Bug 1、QSPanel布局中 wifi 和 飞行模式对应的 QSTile 显示不全


先看布局,QuickQSPanel 对应快速访问 QSTile,每一个 QSTile 对应 QSTileBaseView,中间对应 Space 间隔


看bug现象,猜想和 space 宽度有关系,density 改变会引起 dp 和 px 的变换。


aHR0cHM6Ly9zMi5heDF4LmNvbS8yMDIwLzAyLzE0LzFYR2pXNC5wbmc.png

vendor\mediatek\proprietary\packages\apps\SystemUI\src\com\android\systemui\qs\QuickQSPanel.java

    private static class HeaderTileLayout extends LinearLayout implements QSTileLayout {
        protected final ArrayList<TileRecord> mRecords = new ArrayList<>();
        private boolean mListening;
        /** Size of the QS tile (width & height). */
        private int mTileDimensionSize;
       ....
    /**
         * Returns {@link LayoutParams} based on the given {@code spaceWidth}. If the width is 0,
         * then we're going to have the space expand to take up as much space as possible. If the
         * width is non-zero, we want the inter-tile spacers to be fixed.
         */
        private LayoutParams generateSpaceLayoutParams(int spaceWidth) {
            //cczheng add  spaceWidth = 0; for QSPanel pull out show incompliment,small space width
            spaceWidth = 0;
            LayoutParams lp = new LayoutParams(spaceWidth, mTileDimensionSize);
            if (spaceWidth == 0) {
                lp.weight = 1;
            }
            lp.gravity = Gravity.CENTER;
            return lp;
        }
    @Override
        public void addTile(TileRecord tile) {
            if (getChildCount() != 0) {
                // Add a spacer between tiles. We want static-width spaces if we're in landscape to
                // keep the tiles close. For portrait, we stick with spaces that fill up any
                // available space.
                LayoutParams spaceLayoutParams = generateSpaceLayoutParams(
                        mContext.getResources().getDimensionPixelSize(
                                R.dimen.qs_quick_tile_space_width));
                addView(new Space(mContext), getChildCount(), spaceLayoutParams);
                log("addTile()"+mContext.getResources().getDimensionPixelSize(
                            R.dimen.qs_quick_tile_space_width));
            }
            addView(tile.tileView, getChildCount(), generateTileLayoutParams());
            mRecords.add(tile);
            tile.tile.setListening(this, mListening);
        }
        private LayoutParams generateTileLayoutParams() {
            LayoutParams lp = new LayoutParams(mTileDimensionSize, mTileDimensionSize);
            lp.gravity = Gravity.CENTER;
            return lp;
        }
    ......
}

看到 addTile() 方法中,第一次添加先添加第一个 tile,第二次添加,先添加一个 space,再增加tile…

qs_quick_tile_space_width 对应值为,我们这里是平板,对应 38dp

./res/values-land/dimens.xml:    <dimen name="qs_quick_tile_space_width">38dp</dimen>
./res/values/dimens.xml:    <dimen name="qs_quick_tile_space_width">0dp</dimen>


generateSpaceLayoutParams() 中接收 spcace 宽度,当宽度为0时,采用 weight 均分,那我们将 spaceWidth = 0; 即可


Bug 2、状态栏下拉 qs_frame 和 NotificationStackScrollLayout 位置错位


这个问题可不好找,还是先来分析布局,qs_frame 和 NotificationStackScrollLayout 都包含在 NotificationsQuickSettingsContainer 中


aHR0cHM6Ly9zMi5heDF4LmNvbS8yMDIwLzAyLzE0LzFYR1hZRi5wbmc.png

状态栏下拉展开对应布局文件

vendor\mediatek\proprietary\packages\apps\SystemUI\res\layout\status_bar_expanded.xml

<com.android.systemui.statusbar.phone.NotificationPanelView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:systemui="http://schemas.android.com/apk/res-auto"
    android:id="@+id/notification_panel"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/transparent" >
    <include
        layout="@layout/keyguard_status_view"
        android:visibility="gone" />
    <com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="@integer/notification_panel_layout_gravity"
        android:id="@+id/notification_container_parent"
        android:clipToPadding="false"
        android:clipChildren="false">
        <FrameLayout
            android:id="@+id/qs_frame"
            android:layout="@layout/qs_panel"
            android:layout_width="@dimen/qs_panel_width"
            android:layout_height="match_parent"
            android:layout_gravity="@integer/notification_panel_layout_gravity"
            android:clipToPadding="false"
            android:clipChildren="false"
            systemui:viewType="com.android.systemui.plugins.qs.QS" />
        <com.android.systemui.statusbar.stack.NotificationStackScrollLayout
            android:id="@+id/notification_stack_scroller"
            android:layout_marginTop="@dimen/notification_panel_margin_top"
            android:layout_width="@dimen/notification_panel_width"
            android:layout_height="match_parent"
            android:layout_gravity="@integer/notification_panel_layout_gravity"
            android:layout_marginBottom="@dimen/close_handle_underlap" />

notification_panel_layout_gravity 对应 center_horizontal|top,开始一直以为是从不同的地方手指下拉修改了布局的 gravity 属性,

加了日志发现并没有走对应的地方,后来继续找,其实改变的是 X 的位置。


vendor\mediatek\proprietary\packages\apps\SystemUI\src\com\android\systemui\statusbar\phone\NotificationPanelView.java

  @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (mBlockTouches || (mQs != null && mQs.isCustomizing())) {
            return false;
        }
        initDownStates(event);
        if (mListenForHeadsUp && !mHeadsUpTouchHelper.isTrackingHeadsUp()
                && mHeadsUpTouchHelper.onInterceptTouchEvent(event)) {
            mIsExpansionFromHeadsUp = true;
            MetricsLogger.count(mContext, COUNTER_PANEL_OPEN_PEEK, 1);
        }
        boolean handled = false;
        if ((!mIsExpanding || mHintAnimationRunning)
                && !mQsExpanded
                && mStatusBar.getBarState() != StatusBarState.SHADE
                && !mDozing) {
            handled |= mAffordanceHelper.onTouchEvent(event);
        }
        if (mOnlyAffordanceInThisMotion) {
            return true;
        }
        handled |= mHeadsUpTouchHelper.onTouchEvent(event);
        if (!mHeadsUpTouchHelper.isTrackingHeadsUp() && handleQsTouch(event)) {
            return true;
        }
        if (event.getActionMasked() == MotionEvent.ACTION_DOWN && isFullyCollapsed()) {
            MetricsLogger.count(mContext, COUNTER_PANEL_OPEN, 1);
            updateVerticalPanelPosition(event.getX());
            handled = true;
        }
        handled |= super.onTouchEvent(event);
        return mDozing ? handled : true;
    }
  protected void updateVerticalPanelPosition(float x) {
        if (mNotificationStackScroller.getWidth() * 1.75f > getWidth()) {
            resetVerticalPanelPosition();
            return;
        }
        float leftMost = mPositionMinSideMargin + mNotificationStackScroller.getWidth() / 2;
        float rightMost = getWidth() - mPositionMinSideMargin
                - mNotificationStackScroller.getWidth() / 2;
        if (Math.abs(x - getWidth() / 2) < mNotificationStackScroller.getWidth() / 4) {
            x = getWidth() / 2;
        }
        x = Math.min(rightMost, Math.max(leftMost, x));
        setVerticalPanelTranslation(x -
                (mNotificationStackScroller.getLeft() + mNotificationStackScroller.getWidth() / 2));
     }
    private void resetVerticalPanelPosition() {
        setVerticalPanelTranslation(0f);
    }
    public void loge(String msg){
        android.util.Log.e("NotificationPanelView", msg);
    }
    protected void setVerticalPanelTranslation(float translation) {
        loge("setVerticalPanelTranslation() translation="+translation);
        mNotificationStackScroller.setTranslationX(translation);
        //cczheng annotaion pull out qsFrame and stackScroll don't sycn
        //mQsFrame.setTranslationX(translation);
        int size = mVerticalTranslationListener.size();
        for (int i = 0; i < size; i++) {
            mVerticalTranslationListener.get(i).run();
        }
    }


onTouchEvent 中手指按下事件,调用 updateVerticalPanelPosition() 改变位置,最终通过平移 mQsFrame 和 mNotificationStackScroller x值

从目前的bug现象来看,mQSFrame 平移的位置跟随手指有左、中、右三个位置,而 mNotificationStackScroller 始终在中间,最简单的办法就是

注释 mQSFrame 的平移,这样就能和 mNotificationStackScroller 保持同步,始终从中间展开显示。

目录
相关文章
|
Android开发 数据安全/隐私保护 容器
Android10.0 SystemUI—锁屏加载分析
Android10.0 SystemUI—锁屏加载分析
1003 0
Android10.0 SystemUI—锁屏加载分析
|
1月前
|
XML 存储 测试技术
Android系统 添加动态控制SystemUI状态栏、导航栏和下拉菜单
Android系统 添加动态控制SystemUI状态栏、导航栏和下拉菜单
196 1
|
1月前
|
XML Android开发 数据格式
android 9 Systemui 动态隐藏导航栏
android 9 Systemui 动态隐藏导航栏
38 0
|
1月前
|
Android开发
Android SystemUI去掉拖动亮度条QSPanel界面隐藏功能
Android SystemUI去掉拖动亮度条QSPanel界面隐藏功能
34 0
|
11月前
|
XML Java 测试技术
车载Android应用开发与分析 - SystemUI 「功能」与「源码结构」分析
本期内容开始,我们将介绍原生Android Automotive中车载应用的实现方式和它的原理。首先要介绍的就是车载应用开发中非常重要的一个系统应用,Android系统的UI - SystemUI。
682 1
车载Android应用开发与分析 - SystemUI 「功能」与「源码结构」分析
|
Android开发
Android9.0 SystemUI 网络信号栏定制修改
Android9.0 SystemUI 网络信号栏定制修改
178 0
|
XML Java Android开发
Android8.1 MTK平台 SystemUI源码分析之 网络信号栏显示刷新(下)
Android8.1 MTK平台 SystemUI源码分析之 网络信号栏显示刷新(下)
184 0
|
XML 数据库 网络虚拟化
Android8.1 MTK平台 SystemUI源码分析之 网络信号栏显示刷新(上)
Android8.1 MTK平台 SystemUI源码分析之 网络信号栏显示刷新
237 0