From 6b3f02e2fe8ff88d60d28f454e50a1afc7ca7637 Mon Sep 17 00:00:00 2001 From: Fabian Kozynski Date: Wed, 25 Mar 2020 13:49:18 -0400 Subject: [PATCH] Fix layout of DoubleLineTileLayout With this CL, the layout calculates how many columns it can safely show given the available space and distributes the tiles accordingly. This prevents the tiles from going out of the bounds of the container (happening even in Default Display Size). With the change in the minimum horizontal margin, the three lowest Display Size will show three columns and the others will show 2. Showing two columns has not great expansion animations. Opening a bug to explore UI. Fixes: 151810573 Bug: 152429614 Test: manual Change-Id: I8e123c4497f51f0d5c83b8eb14319f488a96bc9a --- packages/SystemUI/res/values/dimens.xml | 1 + .../systemui/qs/DoubleLineTileLayout.kt | 77 ++++++++++++------- 2 files changed, 52 insertions(+), 26 deletions(-) diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index 23be78bd6a77f..a9e5fa9cf4ae8 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -477,6 +477,7 @@ 106dp 6dp 18dp + 2dp 24dp 12dp -12dp diff --git a/packages/SystemUI/src/com/android/systemui/qs/DoubleLineTileLayout.kt b/packages/SystemUI/src/com/android/systemui/qs/DoubleLineTileLayout.kt index f710f7fc47e2b..448531a132df1 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/DoubleLineTileLayout.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/DoubleLineTileLayout.kt @@ -25,13 +25,18 @@ import com.android.systemui.qs.TileLayout.exactly class DoubleLineTileLayout(context: Context) : ViewGroup(context), QSPanel.QSTileLayout { + companion object { + private const val NUM_LINES = 2 + } + protected val mRecords = ArrayList() private var _listening = false private var smallTileSize = 0 private val twoLineHeight - get() = smallTileSize * 2 + cellMarginVertical + get() = smallTileSize * NUM_LINES + cellMarginVertical * (NUM_LINES - 1) private var cellMarginHorizontal = 0 private var cellMarginVertical = 0 + private var tilesToShow = 0 init { isFocusableInTouchMode = true @@ -68,7 +73,7 @@ class DoubleLineTileLayout(context: Context) : ViewGroup(context), QSPanel.QSTil override fun updateResources(): Boolean { with(mContext.resources) { smallTileSize = getDimensionPixelSize(R.dimen.qs_quick_tile_size) - cellMarginHorizontal = getDimensionPixelSize(R.dimen.qs_tile_margin_horizontal) + cellMarginHorizontal = getDimensionPixelSize(R.dimen.qs_tile_margin_horizontal_two_line) cellMarginVertical = getDimensionPixelSize(R.dimen.new_qs_vertical_margin) } requestLayout() @@ -83,11 +88,12 @@ class DoubleLineTileLayout(context: Context) : ViewGroup(context), QSPanel.QSTil } } - override fun getNumVisibleTiles() = mRecords.size + override fun getNumVisibleTiles() = tilesToShow override fun onConfigurationChanged(newConfig: Configuration) { super.onConfigurationChanged(newConfig) updateResources() + postInvalidate() } override fun onFinishInflate() { @@ -95,39 +101,58 @@ class DoubleLineTileLayout(context: Context) : ViewGroup(context), QSPanel.QSTil } override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { - var previousView: View = this - var tiles = 0 mRecords.forEach { - val tileView = it.tileView - if (tileView.visibility != View.GONE) { - tileView.updateAccessibilityOrder(previousView) - previousView = tileView - tiles++ - tileView.measure(exactly(smallTileSize), exactly(smallTileSize)) - } + it.tileView.measure(exactly(smallTileSize), exactly(smallTileSize)) } val height = twoLineHeight - val columns = tiles / 2 - val width = paddingStart + paddingEnd + - columns * smallTileSize + - (columns - 1) * cellMarginHorizontal - setMeasuredDimension(width, height) + setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), height) } - override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) { - val tiles = mRecords.filter { it.tileView.visibility != View.GONE } - tiles.forEachIndexed { - index, tile -> - val column = index % (tiles.size / 2) - val left = getLeftForColumn(column) - val top = if (index < tiles.size / 2) 0 else getTopBottomRow() - tile.tileView.layout(left, top, left + smallTileSize, top + smallTileSize) + private fun calculateMaxColumns(availableWidth: Int): Int { + if (smallTileSize + cellMarginHorizontal == 0) { + return 0 + } else { + return (availableWidth - smallTileSize) / (smallTileSize + cellMarginHorizontal) + 1 } } - private fun getLeftForColumn(column: Int) = column * (smallTileSize + cellMarginHorizontal) + override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) { + val availableWidth = r - l - paddingLeft - paddingRight + val maxColumns = calculateMaxColumns(availableWidth) + val actualColumns = Math.min(maxColumns, mRecords.size / NUM_LINES) + if (actualColumns == 0) { + // No tileSize or horizontal margin + return + } + tilesToShow = actualColumns * NUM_LINES + + val interTileSpace = if (actualColumns <= 2) { + // Extra "column" of padding to be distributed on each end + (availableWidth - actualColumns * smallTileSize) / actualColumns + } else { + (availableWidth - actualColumns * smallTileSize) / (actualColumns - 1) + } + + for (index in 0 until mRecords.size) { + val tileView = mRecords[index].tileView + if (index >= tilesToShow) { + tileView.visibility = View.GONE + } else { + tileView.visibility = View.VISIBLE + if (index > 0) tileView.updateAccessibilityOrder(mRecords[index - 1].tileView) + val column = index % actualColumns + val left = getLeftForColumn(column, interTileSpace, actualColumns <= 2) + val top = if (index < actualColumns) 0 else getTopBottomRow() + tileView.layout(left, top, left + smallTileSize, top + smallTileSize) + } + } + } + + private fun getLeftForColumn(column: Int, interSpace: Int, sideMargin: Boolean): Int { + return (if (sideMargin) interSpace / 2 else 0) + column * (smallTileSize + interSpace) + } private fun getTopBottomRow() = smallTileSize + cellMarginVertical } \ No newline at end of file