Bug现象
Bug 1、QSPanel布局中 wifi 和 飞行模式对应的 QSTile 显示不全
先看布局,QuickQSPanel 对应快速访问 QSTile,每一个 QSTile 对应 QSTileBaseView,中间对应 Space 间隔
看bug现象,猜想和 space 宽度有关系,density 改变会引起 dp 和 px 的变换。
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 中
状态栏下拉展开对应布局文件
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 保持同步,始终从中间展开显示。