Update SizeSpec attributes to accept max size threshold
Add maxSize attribute to SizeSpec to limit the cell size up to a max size when matchWorkspace is true. The same validation was added when using fixedSize, ofAvailableSpace and ofRemainderSpace, so they could have a maxSize as a threshold.
Bug: 284155638
Flag: ENABLE_RESPONSIVE_WORKSPACE
Test: SizeSpecTest
Test: WorkspaceSpecsTest
Change-Id: I113657c241e6618eb3e501243412d8c5626fc3d5
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index 1be1a1a..0ffe37b 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -257,6 +257,7 @@
<attr name="ofAvailableSpace" format="float" />
<attr name="ofRemainderSpace" format="float" />
<attr name="matchWorkspace" format="boolean" />
+ <attr name="maxSize" format="dimension" />
</declare-styleable>
<declare-styleable name="FolderSpec">
diff --git a/src/com/android/launcher3/responsive/SizeSpec.kt b/src/com/android/launcher3/responsive/SizeSpec.kt
index 407a212..3d618f9 100644
--- a/src/com/android/launcher3/responsive/SizeSpec.kt
+++ b/src/com/android/launcher3/responsive/SizeSpec.kt
@@ -15,22 +15,27 @@
* @param ofAvailableSpace a percentage of the available space
* @param ofRemainderSpace a percentage of the remaining space (available space minus used space)
* @param matchWorkspace indicates whether the workspace value will be used or not.
+ * @param maxSize restricts the maximum value allowed for the [SizeSpec].
*/
data class SizeSpec(
val fixedSize: Float = 0f,
val ofAvailableSpace: Float = 0f,
val ofRemainderSpace: Float = 0f,
- val matchWorkspace: Boolean = false
+ val matchWorkspace: Boolean = false,
+ val maxSize: Int = Int.MAX_VALUE
) {
/** Retrieves the correct value for [SizeSpec]. */
fun getCalculatedValue(availableSpace: Int, workspaceValue: Int): Int {
- return when {
- fixedSize > 0 -> fixedSize.roundToInt()
- ofAvailableSpace > 0 -> (ofAvailableSpace * availableSpace).roundToInt()
- matchWorkspace -> workspaceValue
- else -> 0
- }
+ val calculatedValue =
+ when {
+ fixedSize > 0 -> fixedSize.roundToInt()
+ matchWorkspace -> workspaceValue
+ ofAvailableSpace > 0 -> (ofAvailableSpace * availableSpace).roundToInt()
+ else -> 0
+ }
+
+ return calculatedValue.coerceAtMost(maxSize)
}
/**
@@ -38,11 +43,14 @@
* is 0, returns a default value.
*/
fun getRemainderSpaceValue(remainderSpace: Int, defaultValue: Int): Int {
- return if (ofRemainderSpace > 0) {
- (ofRemainderSpace * remainderSpace).roundToInt()
- } else {
- defaultValue
- }
+ val remainderSpaceValue =
+ if (ofRemainderSpace > 0) {
+ (ofRemainderSpace * remainderSpace).roundToInt()
+ } else {
+ defaultValue
+ }
+
+ return remainderSpaceValue.coerceAtMost(maxSize)
}
fun isValid(): Boolean {
@@ -69,12 +77,17 @@
return false
}
- // Invalid fixed size
- if (fixedSize < 0f) {
+ // Invalid fixed or max size
+ if (fixedSize < 0f || maxSize < 0f) {
Log.e(TAG, "SizeSpec#isValid - values should be bigger or equal to zero.")
return false
}
+ if (fixedSize > 0f && fixedSize > maxSize) {
+ Log.e(TAG, "SizeSpec#isValid - fixed size should be smaller than the max size.")
+ return false
+ }
+
return true
}
@@ -96,10 +109,12 @@
val ofAvailableSpace = getValue(styledAttrs, R.styleable.SizeSpec_ofAvailableSpace)
val ofRemainderSpace = getValue(styledAttrs, R.styleable.SizeSpec_ofRemainderSpace)
val matchWorkspace = styledAttrs.getBoolean(R.styleable.SizeSpec_matchWorkspace, false)
+ val maxSize =
+ styledAttrs.getDimensionPixelSize(R.styleable.SizeSpec_maxSize, Int.MAX_VALUE)
styledAttrs.recycle()
- return SizeSpec(fixedSize, ofAvailableSpace, ofRemainderSpace, matchWorkspace)
+ return SizeSpec(fixedSize, ofAvailableSpace, ofRemainderSpace, matchWorkspace, maxSize)
}
}
}
diff --git a/tests/res/values/attrs.xml b/tests/res/values/attrs.xml
index 54f0381..32bc550 100644
--- a/tests/res/values/attrs.xml
+++ b/tests/res/values/attrs.xml
@@ -31,6 +31,7 @@
<attr name="ofAvailableSpace" format="float" />
<attr name="ofRemainderSpace" format="float" />
<attr name="matchWorkspace" format="boolean" />
+ <attr name="maxSize" format="dimension" />
</declare-styleable>
<declare-styleable name="FolderSpec">
diff --git a/tests/src/com/android/launcher3/responsive/SizeSpecTest.kt b/tests/src/com/android/launcher3/responsive/SizeSpecTest.kt
index 5db86ff..088cae1 100644
--- a/tests/src/com/android/launcher3/responsive/SizeSpecTest.kt
+++ b/tests/src/com/android/launcher3/responsive/SizeSpecTest.kt
@@ -45,7 +45,12 @@
SizeSpec(0f, 1f, 0f, false),
SizeSpec(0f, 0f, 1f, false),
SizeSpec(0f, 0f, 0f, false),
- SizeSpec(0f, 0f, 0f, true)
+ SizeSpec(0f, 0f, 0f, true),
+ SizeSpec(100f, 0f, 0f, false, 100),
+ SizeSpec(0f, 1f, 0f, false, 100),
+ SizeSpec(0f, 0f, 1f, false, 100),
+ SizeSpec(0f, 0f, 0f, false, 100),
+ SizeSpec(0f, 0f, 0f, true, 100)
)
for (instance in combinations) {
@@ -62,7 +67,12 @@
SizeSpec(100f) to 100,
SizeSpec(ofAvailableSpace = .5f) to (availableSpace * .5f).roundToInt(),
SizeSpec(ofRemainderSpace = .5f) to 0,
- SizeSpec(matchWorkspace = true) to matchWorkspaceValue
+ SizeSpec(matchWorkspace = true) to matchWorkspaceValue,
+ // Restricts max size up to 10 (calculated value > 10)
+ SizeSpec(100f, maxSize = 10) to 10,
+ SizeSpec(ofAvailableSpace = .5f, maxSize = 10) to 10,
+ SizeSpec(ofRemainderSpace = .5f, maxSize = 10) to 0,
+ SizeSpec(matchWorkspace = true, maxSize = 10) to 10
)
for ((sizeSpec, expectedValue) in combinations) {
@@ -74,13 +84,18 @@
@Test
fun validate_getRemainderSpaceValue() {
val remainderSpace = 100
- val defaultValue = 10
+ val defaultValue = 50
val combinations =
listOf(
SizeSpec(100f) to defaultValue,
SizeSpec(ofAvailableSpace = .5f) to defaultValue,
SizeSpec(ofRemainderSpace = .5f) to (remainderSpace * .5f).roundToInt(),
- SizeSpec(matchWorkspace = true) to defaultValue
+ SizeSpec(matchWorkspace = true) to defaultValue,
+ // Restricts max size up to 10 (defaultValue > 10)
+ SizeSpec(100f, maxSize = 10) to 10,
+ SizeSpec(ofAvailableSpace = .5f, maxSize = 10) to 10,
+ SizeSpec(ofRemainderSpace = .5f, maxSize = 10) to 10,
+ SizeSpec(matchWorkspace = true, maxSize = 10) to 10,
)
for ((sizeSpec, expectedValue) in combinations) {
@@ -111,11 +126,13 @@
fun invalid_values() {
val combinations =
listOf(
+ SizeSpec(-1f, 0f, 0f, false),
SizeSpec(0f, 1.1f, 0f, false),
SizeSpec(0f, -0.1f, 0f, false),
SizeSpec(0f, 0f, 1.1f, false),
SizeSpec(0f, 0f, -0.1f, false),
- SizeSpec(-1f, 0f, 0f, false)
+ SizeSpec(0f, 0f, 0f, false, -10),
+ SizeSpec(50f, 0f, 0f, false, 10)
)
for (instance in combinations) {
diff --git a/tests/src/com/android/launcher3/workspace/WorkspaceSpecsTest.kt b/tests/src/com/android/launcher3/workspace/WorkspaceSpecsTest.kt
index 51808e3..8b99a3a 100644
--- a/tests/src/com/android/launcher3/workspace/WorkspaceSpecsTest.kt
+++ b/tests/src/com/android/launcher3/workspace/WorkspaceSpecsTest.kt
@@ -51,19 +51,23 @@
"startPadding=SizeSpec(fixedSize=0.0, " +
"ofAvailableSpace=0.0, " +
"ofRemainderSpace=0.0, " +
- "matchWorkspace=false), " +
+ "matchWorkspace=false, " +
+ "maxSize=2147483647), " +
"endPadding=SizeSpec(fixedSize=84.0, " +
"ofAvailableSpace=0.0, " +
"ofRemainderSpace=0.0, " +
- "matchWorkspace=false), " +
+ "matchWorkspace=false, " +
+ "maxSize=2147483647), " +
"gutter=SizeSpec(fixedSize=42.0, " +
"ofAvailableSpace=0.0, " +
"ofRemainderSpace=0.0, " +
- "matchWorkspace=false), " +
+ "matchWorkspace=false, " +
+ "maxSize=2147483647), " +
"cellSize=SizeSpec(fixedSize=0.0, " +
"ofAvailableSpace=0.15808, " +
"ofRemainderSpace=0.0, " +
- "matchWorkspace=false)" +
+ "matchWorkspace=false, " +
+ "maxSize=2147483647)" +
")"
)
assertThat(workspaceSpecs.workspaceHeightSpecList[1].toString())
@@ -74,19 +78,23 @@
"startPadding=SizeSpec(fixedSize=0.0, " +
"ofAvailableSpace=0.0, " +
"ofRemainderSpace=0.0, " +
- "matchWorkspace=false), " +
+ "matchWorkspace=false, " +
+ "maxSize=2147483647), " +
"endPadding=SizeSpec(fixedSize=0.0, " +
"ofAvailableSpace=0.0, " +
"ofRemainderSpace=1.0, " +
- "matchWorkspace=false), " +
+ "matchWorkspace=false, " +
+ "maxSize=2147483647), " +
"gutter=SizeSpec(fixedSize=42.0, " +
"ofAvailableSpace=0.0, " +
"ofRemainderSpace=0.0, " +
- "matchWorkspace=false), " +
+ "matchWorkspace=false, " +
+ "maxSize=2147483647), " +
"cellSize=SizeSpec(fixedSize=273.0, " +
"ofAvailableSpace=0.0, " +
"ofRemainderSpace=0.0, " +
- "matchWorkspace=false)" +
+ "matchWorkspace=false, " +
+ "maxSize=2147483647)" +
")"
)
assertThat(workspaceSpecs.workspaceHeightSpecList[2].toString())
@@ -97,19 +105,23 @@
"startPadding=SizeSpec(fixedSize=21.0, " +
"ofAvailableSpace=0.0, " +
"ofRemainderSpace=0.0, " +
- "matchWorkspace=false), " +
+ "matchWorkspace=false, " +
+ "maxSize=2147483647), " +
"endPadding=SizeSpec(fixedSize=0.0, " +
"ofAvailableSpace=0.0, " +
"ofRemainderSpace=1.0, " +
- "matchWorkspace=false), " +
+ "matchWorkspace=false, " +
+ "maxSize=2147483647), " +
"gutter=SizeSpec(fixedSize=42.0, " +
"ofAvailableSpace=0.0, " +
"ofRemainderSpace=0.0, " +
- "matchWorkspace=false), " +
+ "matchWorkspace=false, " +
+ "maxSize=2147483647), " +
"cellSize=SizeSpec(fixedSize=273.0, " +
"ofAvailableSpace=0.0, " +
"ofRemainderSpace=0.0, " +
- "matchWorkspace=false)" +
+ "matchWorkspace=false, " +
+ "maxSize=2147483647)" +
")"
)
assertThat(workspaceSpecs.workspaceWidthSpecList.size).isEqualTo(1)
@@ -121,19 +133,23 @@
"startPadding=SizeSpec(fixedSize=58.0, " +
"ofAvailableSpace=0.0, " +
"ofRemainderSpace=0.0, " +
- "matchWorkspace=false), " +
+ "matchWorkspace=false, " +
+ "maxSize=2147483647), " +
"endPadding=SizeSpec(fixedSize=58.0, " +
"ofAvailableSpace=0.0, " +
"ofRemainderSpace=0.0, " +
- "matchWorkspace=false), " +
+ "matchWorkspace=false, " +
+ "maxSize=2147483647), " +
"gutter=SizeSpec(fixedSize=42.0, " +
"ofAvailableSpace=0.0, " +
"ofRemainderSpace=0.0, " +
- "matchWorkspace=false), " +
+ "matchWorkspace=false, " +
+ "maxSize=2147483647), " +
"cellSize=SizeSpec(fixedSize=0.0, " +
"ofAvailableSpace=0.0, " +
"ofRemainderSpace=0.25, " +
- "matchWorkspace=false)" +
+ "matchWorkspace=false, " +
+ "maxSize=2147483647)" +
")"
)
}