// Do not restart System UI when the bugreport flag changes. mFeatureFlags.addListener(Flags.LEAVE_SHADE_OPEN_FOR_BUGREPORT,event->{ event.requestNoRestart(); }); ......
mQSCustomizerController = qsFragmentComponent.getQSCustomizerController(); mQSCustomizerController.init(); mQSCustomizerController.setQs(this); if (savedInstanceState != null) { setQsVisible(savedInstanceState.getBoolean(EXTRA_VISIBLE)); setExpanded(savedInstanceState.getBoolean(EXTRA_EXPANDED)); setListening(savedInstanceState.getBoolean(EXTRA_LISTENING)); setEditLocation(view); mQSCustomizerController.restoreInstanceState(savedInstanceState); if (mQsExpanded) { mQSPanelController.getTileLayout().restoreInstanceState(savedInstanceState); } } mStatusBarStateController.addCallback(this); onStateChanged(mStatusBarStateController.getState()); view.addOnLayoutChangeListener( (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> { booleansizeChanged= (oldTop - oldBottom) != (top - bottom); if (sizeChanged) { setQsExpansion(mLastQSExpansion, mLastPanelFraction, mLastHeaderTranslation, mSquishinessFraction); } }); mQSPanelController.setUsingHorizontalLayoutChangeListener( () -> { // The hostview may be faded out in the horizontal layout. Let's make sure to // reset the alpha when switching layouts. This is fine since the animator will // update the alpha if it's not supposed to be 1.0f mQSPanelController.getMediaHost().getHostView().setAlpha(1.0f); mQSAnimator.requestAnimatorUpdate(); });
// class QSPanelControllerBase booleanswitchTileLayout(boolean force) { /* Whether or not the panel currently contains a media player. */ booleanhorizontal= shouldUseHorizontalLayout(); if (horizontal != mUsingHorizontalLayout || force) { mQSLogger.logSwitchTileLayout(horizontal, mUsingHorizontalLayout, force, mView.getDumpableTag()); mUsingHorizontalLayout = horizontal; mView.setUsingHorizontalLayout(mUsingHorizontalLayout, mMediaHost.getHostView(), force); updateMediaDisappearParameters(); if (mUsingHorizontalLayoutChangedListener != null) { mUsingHorizontalLayoutChangedListener.run(); } returntrue; } returnfalse; }
// class QSFactoryImpl publicfinal QSTile createTile(String tileSpec) { QSTileImpltile= createTileInternal(tileSpec); if (tile != null) { tile.initialize(); tile.postStale(); // Tile was just created, must be stale. } return tile; }
protected QSTileImpl createTileInternal(String tileSpec) { // Stock tiles. if (mTileMap.containsKey(tileSpec) // We should not return a Garbage Monitory Tile if the build is not Eng && (!tileSpec.equals(GarbageMonitor.MemoryTile.TILE_SPEC) || Build.IS_ENG)) { return mTileMap.get(tileSpec).get(); }
staticvoidswitchToParent(View child, ViewGroup parent, int index, String tag) { if (parent == null) { Log.w(tag, "Trying to move view to null parent", newIllegalStateException()); return; } ViewGroupcurrentParent= (ViewGroup) child.getParent(); if (currentParent != parent) { if (currentParent != null) { currentParent.removeView(child); } parent.addView(child, index); return; } // Same parent, we are just changing indices intcurrentIndex= parent.indexOfChild(child); if (currentIndex == index) { // We want to be in the same place. Nothing to do here return; } parent.removeView(child); parent.addView(child, index); }
addTile()
调用 addTile() 添加磁贴。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
// class QSPanel voidaddTile(QSPanelControllerBase.TileRecord tileRecord) { final QSTile.Callbackcallback=newQSTile.Callback() { @Override publicvoidonStateChanged(QSTile.State state) { drawTile(tileRecord, state); } };
// class PagedTileLayout protectedvoidonFinishInflate() { super.onFinishInflate(); mPages.add(createTileLayout()); mAdapter.notifyDataSetChanged(); }
protectedvoidonMeasure(int widthMeasureSpec, int heightMeasureSpec) {
finalintnTiles= mTiles.size(); // If we have no reason to recalculate the number of rows, skip this step. In particular, // if the height passed by its parent is the same as the last time, we try not to remeasure. if (mDistributeTiles || mLastMaxHeight != MeasureSpec.getSize(heightMeasureSpec) || mLastExcessHeight != mExcessHeight){
mLastMaxHeight=MeasureSpec.getSize(heightMeasureSpec); mLastExcessHeight=mExcessHeight; // Only change the pages if the number of rows or columns (from updateResources) has // changed or the tiles have changed int availableHeight=mLastMaxHeight-mExcessHeight; if(mPages.get(0).updateMaxRows(availableHeight,nTiles)||mDistributeTiles){ mDistributeTiles=false; distributeTiles(); } ...... }
// class PagedTileLayout privatevoidemptyAndInflateOrRemovePages() { finalintnumPages= getNumPages(); finalintNP= mPages.size(); for (inti=0; i < NP; i++) { mPages.get(i).removeAllViews(); } if (NP == numPages) { return; } while (mPages.size() < numPages) { mLogger.d("Adding new page"); mPages.add(createTileLayout()); } while (mPages.size() > numPages) { mLogger.d("Removing page"); mPages.remove(mPages.size() - 1); } mPageIndicator.setNumPages(mPages.size()); setAdapter(mAdapter); mAdapter.notifyDataSetChanged(); if (mPageToRestore != NO_PAGE) { setCurrentItem(mPageToRestore, false); mPageToRestore = NO_PAGE; } }
这里调用 getNumPages() 计算所需的 page 数。
1 2 3 4 5 6 7 8 9 10 11 12 13
// class PagedTileLayout publicintgetNumPages() { finalintnTiles= mTiles.size(); // We should always have at least one page, even if it's empty. intnumPages= Math.max(nTiles / mPages.get(0).maxTiles(), 1);
// Add one more not full page if needed if (nTiles > numPages * mPages.get(0).maxTiles()) { numPages++; }
return numPages; }
SideLabelTileLayout 的 maxTiles():
1 2 3 4 5 6 7
// class SideLabelTileLayout publicintmaxTiles() { // Each layout should be able to hold at least one tile. If there's not enough room to // show even 1 or there are no tiles, it probably means we are in the middle of setting // up. return Math.max(mColumns * mRows, 1); }
// class TileLayout protectedvoidonMeasure(int widthMeasureSpec, int heightMeasureSpec) { // If called with AT_MOST, it will limit the number of rows. If called with UNSPECIFIED // it will show all its tiles. In this case, the tiles have to be entered before the // container is measured. Any change in the tiles, should trigger a remeasure. finalintnumTiles= mRecords.size(); finalintwidth= MeasureSpec.getSize(widthMeasureSpec); finalintavailableWidth= width - getPaddingStart() - getPaddingEnd(); finalintheightMode= MeasureSpec.getMode(heightMeasureSpec); if (heightMode == MeasureSpec.UNSPECIFIED) { mRows = (numTiles + mColumns - 1) / mColumns; } finalintgaps= mColumns - 1; mCellWidth = (availableWidth - (mCellMarginHorizontal * gaps) - mSidePadding * 2) / mColumns;
// Measure each QS tile. ViewpreviousView=this; intverticalMeasure= exactly(getCellHeight()); for (TileRecord record : mRecords) { if (record.tileView.getVisibility() == GONE) continue; record.tileView.measure(exactly(mCellWidth), verticalMeasure); previousView = record.tileView.updateAccessibilityOrder(previousView); mCellHeight = record.tileView.getMeasuredHeight(); }
// Layout each QS tile. finalinttilesToLayout= Math.min(numRecords, mRows * mColumns); for (inti=0; i < tilesToLayout; i++, column++) { // If we reached the last column available to layout a tile, wrap back to the next row. if (column == mColumns) { column = 0; row++; }
// Set the bottom to the unoverriden squished bottom. This is to avoid fake bottoms that // are only used for QQS -> QS expansion animations floatscale= QSTileViewImplKt.constrainSquishiness(mSquishinessFraction); mLastTileBottom = top + (int) (record.tileView.getMeasuredHeight() * scale); } }