Update default alignment for base Button overload for consistency with other overloads.
Without this change, `Button(onClick = {}) { Text("ABC") }` and `Button(onClick = {}, label = { Text("ABC") } )` had different alignments, because they resolved to the 1-slot and 3-slot Button overloads respectively. The previous behavior can be restored if needed by using `modifier = Modifier.align(Alignment.Top)` in the content passed via the trialing lambda.
Bug: 346772362
Test: Added integration demos for base Button overload
Relnote: "We have changed the base Button overloads to be vertically center aligned for consistency with other overloads. To restore the previous behavior, use Modifier.align from the RowScope."
Change-Id: I66e572d7a2c0f41343cb94276f5bcab1b194b18b
diff --git a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/ButtonDemo.kt b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/ButtonDemo.kt
index 1f5758e..2adb6af 100644
--- a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/ButtonDemo.kt
+++ b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/ButtonDemo.kt
@@ -24,6 +24,7 @@
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.platform.LocalContext
@@ -38,6 +39,7 @@
import androidx.wear.compose.material3.FilledTonalButton
import androidx.wear.compose.material3.Icon
import androidx.wear.compose.material3.ListHeader
+import androidx.wear.compose.material3.ListSubheader
import androidx.wear.compose.material3.OutlinedButton
import androidx.wear.compose.material3.Text
import androidx.wear.compose.material3.samples.ButtonSample
@@ -58,6 +60,25 @@
import androidx.wear.compose.material3.samples.SimpleOutlinedButtonSample
@Composable
+fun BaseButtonDemo() {
+ // This demo shows how to use the Base Button overload, which has a single content slot
+ // that can be used with a trailing lambda. It should vertically center content by default,
+ // but that can easily be changed by using Modifier.align from RowScope in whatever is passed
+ // to the content slot.
+ ScalingLazyDemo {
+ item { ListHeader { Text("Base Button") } }
+ item { ListSubheader { Text("Default alignment") } }
+ item { Button(onClick = {}, modifier = Modifier.fillMaxWidth()) { Text("Base Button") } }
+ item { ListSubheader { Text("Top Alignment") } }
+ item {
+ Button(onClick = {}, modifier = Modifier.fillMaxWidth()) {
+ Text("Base Button", modifier = Modifier.align(Alignment.Top))
+ }
+ }
+ }
+}
+
+@Composable
fun ButtonDemo() {
val context = LocalContext.current
ScalingLazyDemo {
diff --git a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/WearMaterial3Demos.kt b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/WearMaterial3Demos.kt
index 2f9ce14..c7d5e37 100644
--- a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/WearMaterial3Demos.kt
+++ b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/WearMaterial3Demos.kt
@@ -43,17 +43,10 @@
Material3DemoCategory(
"Material 3",
listOf(
- ComposableDemo("Color Scheme") { ColorSchemeDemos() },
- Material3DemoCategory("Curved Text", CurvedTextDemos),
- Material3DemoCategory("Alert Dialog", AlertDialogs),
- Material3DemoCategory("Confirmation", Comfirmations),
- Material3DemoCategory("Open on phone Dialog", OpenOnPhoneDialogDemos),
- ComposableDemo("Scaffold") { ScaffoldSample() },
- Material3DemoCategory("ScrollAway", ScrollAwayDemos),
- ComposableDemo("Haptics") { Centralize { HapticsDemos() } },
Material3DemoCategory(
"Button",
listOf(
+ ComposableDemo("Base Button") { BaseButtonDemo() },
ComposableDemo("Filled Button") { ButtonDemo() },
ComposableDemo("Filled Tonal Button") { FilledTonalButtonDemo() },
ComposableDemo("Filled Variant Button") { FilledVariantButtonDemo() },
@@ -64,6 +57,14 @@
ComposableDemo("Button (Image Background)") { ButtonBackgroundImageDemo() },
)
),
+ ComposableDemo("Color Scheme") { ColorSchemeDemos() },
+ Material3DemoCategory("Curved Text", CurvedTextDemos),
+ Material3DemoCategory("Alert Dialog", AlertDialogs),
+ Material3DemoCategory("Confirmation", Comfirmations),
+ Material3DemoCategory("Open on phone Dialog", OpenOnPhoneDialogDemos),
+ ComposableDemo("Scaffold") { ScaffoldSample() },
+ Material3DemoCategory("ScrollAway", ScrollAwayDemos),
+ ComposableDemo("Haptics") { Centralize { HapticsDemos() } },
ComposableDemo("Compact Button") { CompactButtonDemo() },
ComposableDemo("Icon Button") { IconButtonDemo() },
ComposableDemo("Image Button") { ImageButtonDemo() },
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ButtonScreenshotTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ButtonScreenshotTest.kt
index 4b23eab..a440cbd 100644
--- a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ButtonScreenshotTest.kt
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ButtonScreenshotTest.kt
@@ -24,6 +24,7 @@
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.testutils.assertAgainstGolden
+import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.platform.LocalLayoutDirection
@@ -65,9 +66,25 @@
@get:Rule val testName = TestName()
- @Test fun button_enabled() = verifyScreenshot() { BaseButton() }
+ @Test fun button_enabled() = verifyScreenshot { BaseButton() }
- @Test fun button_disabled() = verifyScreenshot() { BaseButton(enabled = false) }
+ @Test fun button_disabled() = verifyScreenshot { BaseButton(enabled = false) }
+
+ @Test
+ fun button_default_alignment() = verifyScreenshot {
+ // Uses the base Button overload, should be vertically centered by default
+ Button(onClick = {}, modifier = Modifier.fillMaxWidth().testTag(TEST_TAG)) {
+ Text("Button")
+ }
+ }
+
+ @Test
+ fun button_top_alignment() = verifyScreenshot {
+ // Uses RowScope to override the default vertical alignment to be top
+ Button(onClick = {}, modifier = Modifier.fillMaxWidth().testTag(TEST_TAG)) {
+ Text("Button", modifier = Modifier.align(Alignment.Top))
+ }
+ }
@Test
fun three_slot_button_ltr() =
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Button.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Button.kt
index 0cf422b..885ad65 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Button.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Button.kt
@@ -1778,8 +1778,12 @@
val borderModifier =
if (border != null) modifier.border(border = border, shape = shape) else modifier
Row(
+ verticalAlignment = Alignment.CenterVertically,
+ // Fill the container height but not its width as buttons have fixed size height but we
+ // want them to be able to fit their content
modifier =
borderModifier
+ .fillMaxHeight()
.clip(shape = shape)
.width(intrinsicSize = IntrinsicSize.Max)
.paint(
@@ -1834,25 +1838,18 @@
contentPadding = contentPadding,
interactionSource = interactionSource,
) {
- Row(
- verticalAlignment = Alignment.CenterVertically,
- // Fill the container height but not its width as buttons have fixed size height but we
- // want them to be able to fit their content
- modifier = Modifier.fillMaxHeight()
- ) {
- if (icon != null) {
- Box(
- modifier = Modifier.wrapContentSize(align = Alignment.Center),
- content = provideScopeContent(colors.iconColor(enabled), icon)
- )
- Spacer(modifier = Modifier.size(ButtonDefaults.IconSpacing))
- }
- Column {
- Row(content = labelContent)
- if (secondaryLabelContent != null) {
- Spacer(modifier = Modifier.size(2.dp))
- Row(content = secondaryLabelContent)
- }
+ if (icon != null) {
+ Box(
+ modifier = Modifier.wrapContentSize(align = Alignment.Center),
+ content = provideScopeContent(colors.iconColor(enabled), icon)
+ )
+ Spacer(modifier = Modifier.size(ButtonDefaults.IconSpacing))
+ }
+ Column {
+ Row(content = labelContent)
+ if (secondaryLabelContent != null) {
+ Spacer(modifier = Modifier.size(2.dp))
+ Row(content = secondaryLabelContent)
}
}
}