Migrate wear to use ktfmt
See go/why-ktfmt
BUG: 319663977
Change-Id: Ib14cea2a662264c578d0a353f5328b2bc8aad66b
diff --git a/gradle.properties b/gradle.properties
index 5d08ad2..f2c6920 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -48,7 +48,7 @@
androidx.unpinComposeCompiler=false
# Prefix of projects that are opted-in to use ktfmt
-androidx.ktfmt.optin=:a,:b,:camera,:car,:collection,:concurrent,:constraintlayout,:core,:customview,:d,:e,:f,:g,:h,:i,:j,:k,:l,:n,:p,:s,:t,:viewpager
+androidx.ktfmt.optin=:a,:b,:camera,:car,:collection,:concurrent,:constraintlayout,:core,:customview,:d,:e,:f,:g,:h,:i,:j,:k,:l,:n,:p,:s,:t,:viewpager,:wear
# Disable features we do not use
android.defaults.buildfeatures.aidl=false
android.defaults.buildfeatures.buildconfig=false
diff --git a/wear/benchmark/integration-tests/macrobenchmark-target/src/main/java/androidx/wear/benchmark/integration/macrobenchmark/target/ScrollActivity.kt b/wear/benchmark/integration-tests/macrobenchmark-target/src/main/java/androidx/wear/benchmark/integration/macrobenchmark/target/ScrollActivity.kt
index 7878ee9..a6b525d2 100644
--- a/wear/benchmark/integration-tests/macrobenchmark-target/src/main/java/androidx/wear/benchmark/integration/macrobenchmark/target/ScrollActivity.kt
+++ b/wear/benchmark/integration-tests/macrobenchmark-target/src/main/java/androidx/wear/benchmark/integration/macrobenchmark/target/ScrollActivity.kt
@@ -36,9 +36,7 @@
recycler.adapter = adapter
}
- private fun entries(size: Int) = List(size) {
- Entry("Item $it")
- }
+ private fun entries(size: Int) = List(size) { Entry("Item $it") }
}
data class Entry(val contents: String)
diff --git a/wear/benchmark/integration-tests/macrobenchmark/src/main/java/androidx/wear/benchmark/integration/macrobenchmark/Common.kt b/wear/benchmark/integration-tests/macrobenchmark/src/main/java/androidx/wear/benchmark/integration/macrobenchmark/Common.kt
index ecb54e2..a158bdcc 100644
--- a/wear/benchmark/integration-tests/macrobenchmark/src/main/java/androidx/wear/benchmark/integration/macrobenchmark/Common.kt
+++ b/wear/benchmark/integration-tests/macrobenchmark/src/main/java/androidx/wear/benchmark/integration/macrobenchmark/Common.kt
@@ -22,15 +22,19 @@
internal fun disableChargingExperience() {
val instrumentation = InstrumentationRegistry.getInstrumentation()
val device = UiDevice.getInstance(instrumentation)
- device.executeShellCommand("am broadcast -a " +
- "com.google.android.clockwork.sysui.charging.ENABLE_CHARGING_EXPERIENCE " +
- "--ez value \"false\" com.google.android.wearable.sysui")
+ device.executeShellCommand(
+ "am broadcast -a " +
+ "com.google.android.clockwork.sysui.charging.ENABLE_CHARGING_EXPERIENCE " +
+ "--ez value \"false\" com.google.android.wearable.sysui"
+ )
}
internal fun enableChargingExperience() {
val instrumentation = InstrumentationRegistry.getInstrumentation()
val device = UiDevice.getInstance(instrumentation)
- device.executeShellCommand("am broadcast -a " +
- "com.google.android.clockwork.sysui.charging.ENABLE_CHARGING_EXPERIENCE " +
- "--ez value \"true\" com.google.android.wearable.sysui")
+ device.executeShellCommand(
+ "am broadcast -a " +
+ "com.google.android.clockwork.sysui.charging.ENABLE_CHARGING_EXPERIENCE " +
+ "--ez value \"true\" com.google.android.wearable.sysui"
+ )
}
diff --git a/wear/benchmark/integration-tests/macrobenchmark/src/main/java/androidx/wear/benchmark/integration/macrobenchmark/ScrollBenchmark.kt b/wear/benchmark/integration-tests/macrobenchmark/src/main/java/androidx/wear/benchmark/integration/macrobenchmark/ScrollBenchmark.kt
index 350f23c..6d05de6 100644
--- a/wear/benchmark/integration-tests/macrobenchmark/src/main/java/androidx/wear/benchmark/integration/macrobenchmark/ScrollBenchmark.kt
+++ b/wear/benchmark/integration-tests/macrobenchmark/src/main/java/androidx/wear/benchmark/integration/macrobenchmark/ScrollBenchmark.kt
@@ -33,11 +33,8 @@
@LargeTest
@RunWith(Parameterized::class)
-class ScrollBenchmark(
- private val compilationMode: CompilationMode
-) {
- @get:Rule
- val benchmarkRule = MacrobenchmarkRule()
+class ScrollBenchmark(private val compilationMode: CompilationMode) {
+ @get:Rule val benchmarkRule = MacrobenchmarkRule()
@Before
fun setUp() {
diff --git a/wear/benchmark/integration-tests/macrobenchmark/src/main/java/androidx/wear/benchmark/integration/macrobenchmark/StartupBenchmark.kt b/wear/benchmark/integration-tests/macrobenchmark/src/main/java/androidx/wear/benchmark/integration/macrobenchmark/StartupBenchmark.kt
index c2b35b8..b523037 100644
--- a/wear/benchmark/integration-tests/macrobenchmark/src/main/java/androidx/wear/benchmark/integration/macrobenchmark/StartupBenchmark.kt
+++ b/wear/benchmark/integration-tests/macrobenchmark/src/main/java/androidx/wear/benchmark/integration/macrobenchmark/StartupBenchmark.kt
@@ -35,8 +35,7 @@
private val startupMode: StartupMode,
private val compilationMode: CompilationMode
) {
- @get:Rule
- val benchmarkRule = MacrobenchmarkRule()
+ @get:Rule val benchmarkRule = MacrobenchmarkRule()
@Before
fun setUp() {
@@ -49,13 +48,15 @@
}
@Test
- fun startup() = benchmarkRule.measureStartup(
- compilationMode = compilationMode,
- startupMode = startupMode,
- packageName = "androidx.wear.benchmark.integration.macrobenchmark.target"
- ) {
- action = "androidx.wear.benchmark.integration.macrobenchmark.target" + ".STARTUP_ACTIVITY"
- }
+ fun startup() =
+ benchmarkRule.measureStartup(
+ compilationMode = compilationMode,
+ startupMode = startupMode,
+ packageName = "androidx.wear.benchmark.integration.macrobenchmark.target"
+ ) {
+ action =
+ "androidx.wear.benchmark.integration.macrobenchmark.target" + ".STARTUP_ACTIVITY"
+ }
companion object {
@Parameterized.Parameters(name = "startup={0},compilation={1}")
diff --git a/wear/benchmark/integration-tests/macrobenchmark/src/main/java/androidx/wear/benchmark/integration/macrobenchmark/SwipeBenchmark.kt b/wear/benchmark/integration-tests/macrobenchmark/src/main/java/androidx/wear/benchmark/integration/macrobenchmark/SwipeBenchmark.kt
index 78720be..a2f7ff5 100644
--- a/wear/benchmark/integration-tests/macrobenchmark/src/main/java/androidx/wear/benchmark/integration/macrobenchmark/SwipeBenchmark.kt
+++ b/wear/benchmark/integration-tests/macrobenchmark/src/main/java/androidx/wear/benchmark/integration/macrobenchmark/SwipeBenchmark.kt
@@ -33,11 +33,8 @@
@LargeTest
@RunWith(Parameterized::class)
-class SwipeBenchmark(
- private val compilationMode: CompilationMode
-) {
- @get:Rule
- val benchmarkRule = MacrobenchmarkRule()
+class SwipeBenchmark(private val compilationMode: CompilationMode) {
+ @get:Rule val benchmarkRule = MacrobenchmarkRule()
@Before
fun setUp() {
@@ -81,5 +78,6 @@
@JvmStatic
fun parameters() = createCompilationParams()
}
+
private val SWIPE_SPEED = 500
}
diff --git a/wear/compose/compose-foundation/benchmark/src/androidTest/java/androidx/wear/compose/foundation/benchmark/ScalingLazyColumnBenchmark.kt b/wear/compose/compose-foundation/benchmark/src/androidTest/java/androidx/wear/compose/foundation/benchmark/ScalingLazyColumnBenchmark.kt
index 4930439..b2aed06 100644
--- a/wear/compose/compose-foundation/benchmark/src/androidTest/java/androidx/wear/compose/foundation/benchmark/ScalingLazyColumnBenchmark.kt
+++ b/wear/compose/compose-foundation/benchmark/src/androidTest/java/androidx/wear/compose/foundation/benchmark/ScalingLazyColumnBenchmark.kt
@@ -49,15 +49,12 @@
import org.junit.Test
import org.junit.runner.RunWith
-/**
- * Benchmark for Wear Compose ScalingLazyColumn.
- */
+/** Benchmark for Wear Compose ScalingLazyColumn. */
@LargeTest
@RunWith(AndroidJUnit4::class)
class ScalingLazyColumnBenchmark {
- @get:Rule
- val benchmarkRule = ComposeBenchmarkRule()
+ @get:Rule val benchmarkRule = ComposeBenchmarkRule()
private val scalingLazyColumnCaseFactory = { ScalingLazyColumnTestCase() }
@@ -100,16 +97,13 @@
override fun MeasuredContent() {
ScalingLazyColumn(
state = rememberScalingLazyListState(),
- modifier = Modifier.requiredSize(
- itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f
- ),
+ modifier = Modifier.requiredSize(itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f),
) {
items(10) { it ->
Box(Modifier.requiredSize(itemSizeDp)) {
- BasicText(text = "Item $it",
- Modifier
- .background(Color.White)
- .padding(2.dp),
+ BasicText(
+ text = "Item $it",
+ Modifier.background(Color.White).padding(2.dp),
TextStyle(
color = Color.Black,
fontSize = 16.sp,
diff --git a/wear/compose/compose-foundation/samples/src/main/java/androidx/wear/compose/foundation/samples/CurvedWorldSample.kt b/wear/compose/compose-foundation/samples/src/main/java/androidx/wear/compose/foundation/samples/CurvedWorldSample.kt
index ef16532..a449893 100644
--- a/wear/compose/compose-foundation/samples/src/main/java/androidx/wear/compose/foundation/samples/CurvedWorldSample.kt
+++ b/wear/compose/compose-foundation/samples/src/main/java/androidx/wear/compose/foundation/samples/CurvedWorldSample.kt
@@ -63,26 +63,18 @@
curvedComposable {
BasicText(
"Simple",
- Modifier
- .background(Color.White)
- .padding(2.dp),
+ Modifier.background(Color.White).padding(2.dp),
TextStyle(
color = Color.Black,
fontSize = 16.sp,
)
)
}
- curvedComposable {
- Box(modifier = Modifier
- .size(20.dp)
- .background(Color.Gray))
- }
+ curvedComposable { Box(modifier = Modifier.size(20.dp).background(Color.Gray)) }
curvedComposable {
BasicText(
"CurvedWorld",
- Modifier
- .background(Color.White)
- .padding(2.dp),
+ Modifier.background(Color.White).padding(2.dp),
TextStyle(
color = Color.Black,
fontSize = 16.sp,
@@ -96,20 +88,14 @@
@Composable
fun CurvedRowAndColumn() {
CurvedLayout(modifier = Modifier.fillMaxSize()) {
- curvedComposable {
- Box(modifier = Modifier
- .size(20.dp)
- .background(Color.Red))
- }
+ curvedComposable { Box(modifier = Modifier.size(20.dp).background(Color.Red)) }
curvedColumn(angularAlignment = CurvedAlignment.Angular.End) {
repeat(3) {
curvedRow {
curvedComposable {
BasicText(
"Row #$it",
- Modifier
- .background(Color.White)
- .padding(2.dp),
+ Modifier.background(Color.White).padding(2.dp),
TextStyle(
color = Color.Black,
fontSize = 14.sp,
@@ -117,16 +103,12 @@
)
}
curvedComposable {
- Box(modifier = Modifier
- .size(10.dp)
- .background(Color.Green))
+ Box(modifier = Modifier.size(10.dp).background(Color.Green))
}
curvedComposable {
BasicText(
"More",
- Modifier
- .background(Color.Yellow)
- .padding(2.dp),
+ Modifier.background(Color.Yellow).padding(2.dp),
TextStyle(
color = Color.Black,
fontSize = 14.sp,
@@ -136,11 +118,7 @@
}
}
}
- curvedComposable {
- Box(modifier = Modifier
- .size(20.dp)
- .background(Color.Red))
- }
+ curvedComposable { Box(modifier = Modifier.size(20.dp).background(Color.Red)) }
}
}
@@ -152,27 +130,15 @@
"Curved Text",
CurvedModifier.padding(10.dp),
style = {
- CurvedTextStyle(
- fontSize = 16.sp,
- color = Color.Black,
- background = Color.White
- )
+ CurvedTextStyle(fontSize = 16.sp, color = Color.Black, background = Color.White)
}
)
- curvedComposable {
- Box(modifier = Modifier
- .size(20.dp)
- .background(Color.Gray))
- }
+ curvedComposable { Box(modifier = Modifier.size(20.dp).background(Color.Gray)) }
curvedComposable {
BasicText(
"Normal Text",
Modifier.padding(5.dp),
- TextStyle(
- fontSize = 16.sp,
- color = Color.Black,
- background = Color.White
- )
+ TextStyle(fontSize = 16.sp, color = Color.Black, background = Color.White)
)
}
}
@@ -184,28 +150,15 @@
CurvedLayout(modifier = Modifier.fillMaxSize()) {
basicCurvedText(
"45 deg",
- style = {
- CurvedTextStyle(
- fontSize = 16.sp,
- color = Color.Black
- )
- },
- modifier = CurvedModifier
- .background(Color.White)
- .size(sweepDegrees = 45f, thickness = 40.dp),
+ style = { CurvedTextStyle(fontSize = 16.sp, color = Color.Black) },
+ modifier =
+ CurvedModifier.background(Color.White).size(sweepDegrees = 45f, thickness = 40.dp),
)
basicCurvedText(
"40 dp",
- style = {
- CurvedTextStyle(
- fontSize = 16.sp,
- color = Color.Black
- )
- },
- modifier = CurvedModifier
- .background(Color.Yellow)
- .radialSize(40.dp)
- .angularSizeDp(40.dp),
+ style = { CurvedTextStyle(fontSize = 16.sp, color = Color.Black) },
+ modifier =
+ CurvedModifier.background(Color.Yellow).radialSize(40.dp).angularSizeDp(40.dp),
)
}
}
@@ -216,27 +169,17 @@
CurvedLayout(modifier = Modifier.fillMaxSize()) {
basicCurvedText(
"Radial",
- style = {
- CurvedTextStyle(
- fontSize = 16.sp,
- color = Color.Black
- )
- },
- modifier = CurvedModifier
- .radialGradientBackground(0f to Color.White, 1f to Color.Black)
- .padding(5.dp)
+ style = { CurvedTextStyle(fontSize = 16.sp, color = Color.Black) },
+ modifier =
+ CurvedModifier.radialGradientBackground(0f to Color.White, 1f to Color.Black)
+ .padding(5.dp)
)
basicCurvedText(
"Angular",
- style = {
- CurvedTextStyle(
- fontSize = 16.sp,
- color = Color.Black
- )
- },
- modifier = CurvedModifier
- .angularGradientBackground(0f to Color.White, 1f to Color.Black)
- .padding(5.dp)
+ style = { CurvedTextStyle(fontSize = 16.sp, color = Color.Black) },
+ modifier =
+ CurvedModifier.angularGradientBackground(0f to Color.White, 1f to Color.Black)
+ .padding(5.dp)
)
}
}
@@ -244,21 +187,17 @@
@Sampled
@Composable
fun CurvedWeight() {
- CurvedLayout(modifier = Modifier
- .fillMaxSize()
- .background(Color.White)) {
+ CurvedLayout(modifier = Modifier.fillMaxSize().background(Color.White)) {
// Evenly spread A, B & C in a 90 degree angle.
- curvedRow(
- modifier = CurvedModifier.angularSize(90f)
- ) {
+ curvedRow(modifier = CurvedModifier.angularSize(90f)) {
basicCurvedText("A")
curvedRow(
modifier = CurvedModifier.weight(1f),
- ) { }
+ ) {}
basicCurvedText("B")
curvedRow(
modifier = CurvedModifier.weight(1f),
- ) { }
+ ) {}
basicCurvedText("C")
}
}
@@ -275,22 +214,14 @@
basicCurvedText(
"Bottom",
style = {
- CurvedTextStyle(
- fontSize = 16.sp,
- color = Color.Black,
- background = Color.White
- )
+ CurvedTextStyle(fontSize = 16.sp, color = Color.Black, background = Color.White)
}
)
curvedComposable { Spacer(modifier = Modifier.size(5.dp)) }
basicCurvedText(
"text",
style = {
- CurvedTextStyle(
- fontSize = 16.sp,
- color = Color.Black,
- background = Color.White
- )
+ CurvedTextStyle(fontSize = 16.sp, color = Color.Black, background = Color.White)
}
)
}
@@ -306,20 +237,10 @@
angularAlignment = CurvedAlignment.Angular.End
) {
curvedComposable {
- Box(
- modifier = Modifier
- .width(40.dp)
- .height(80.dp)
- .background(Color.Green)
- )
+ Box(modifier = Modifier.width(40.dp).height(80.dp).background(Color.Green))
}
curvedComposable {
- Box(
- modifier = Modifier
- .size(30.dp)
- .clip(CircleShape)
- .background(Color.White)
- )
+ Box(modifier = Modifier.size(30.dp).clip(CircleShape).background(Color.White))
}
}
}
@@ -333,10 +254,7 @@
(100..900 step 100).forEach {
basicCurvedText(
"W$it",
- style = CurvedTextStyle(
- color = Color.White,
- fontWeight = FontWeight(it)
- ),
+ style = CurvedTextStyle(color = Color.White, fontWeight = FontWeight(it)),
modifier = CurvedModifier.padding(5.dp)
)
}
@@ -349,20 +267,18 @@
modifier = Modifier.fillMaxSize(),
) {
listOf(
- "Serif" to FontFamily.Serif,
- "SansSerif" to FontFamily.SansSerif,
- "Monospace" to FontFamily.Monospace,
- "Cursive" to FontFamily.Cursive,
- ).forEach { (name, ff) ->
- basicCurvedText(
- "$name",
- style = CurvedTextStyle(
- color = Color.White,
- fontFamily = ff
- ),
- modifier = CurvedModifier.padding(5.dp)
+ "Serif" to FontFamily.Serif,
+ "SansSerif" to FontFamily.SansSerif,
+ "Monospace" to FontFamily.Monospace,
+ "Cursive" to FontFamily.Cursive,
)
- }
+ .forEach { (name, ff) ->
+ basicCurvedText(
+ "$name",
+ style = CurvedTextStyle(color = Color.White, fontFamily = ff),
+ modifier = CurvedModifier.padding(5.dp)
+ )
+ }
}
}
diff --git a/wear/compose/compose-foundation/samples/src/main/java/androidx/wear/compose/foundation/samples/ExpandableSample.kt b/wear/compose/compose-foundation/samples/src/main/java/androidx/wear/compose/foundation/samples/ExpandableSample.kt
index 2551474..695f4d9 100644
--- a/wear/compose/compose-foundation/samples/src/main/java/androidx/wear/compose/foundation/samples/ExpandableSample.kt
+++ b/wear/compose/compose-foundation/samples/src/main/java/androidx/wear/compose/foundation/samples/ExpandableSample.kt
@@ -41,39 +41,24 @@
val expandableState = rememberExpandableState()
val sampleItem: @Composable (String) -> Unit = { label ->
- Chip(
- label = { Text(label) },
- onClick = { },
- secondaryLabel = { Text("line 2 - Secondary") }
- )
+ Chip(label = { Text(label) }, onClick = {}, secondaryLabel = { Text("line 2 - Secondary") })
}
val items = List(10) { "Item $it" }
val top = items.take(3)
val rest = items.drop(3)
- ScalingLazyColumn(
- modifier = Modifier.fillMaxSize()
- ) {
- items(top.size) {
- sampleItem(top[it])
- }
- expandableItems(expandableState, rest.size) {
- sampleItem(rest[it])
- }
+ ScalingLazyColumn(modifier = Modifier.fillMaxSize()) {
+ items(top.size) { sampleItem(top[it]) }
+ expandableItems(expandableState, rest.size) { sampleItem(rest[it]) }
expandableButton(expandableState) {
OutlinedCompactChip(
label = {
Text("Show More")
Spacer(Modifier.size(6.dp))
- Icon(
- painterResource(R.drawable.ic_expand_more_24),
- "Expand"
- )
+ Icon(painterResource(R.drawable.ic_expand_more_24), "Expand")
},
- onClick = {
- expandableState.expanded = true
- }
+ onClick = { expandableState.expanded = true }
)
}
}
@@ -84,9 +69,7 @@
fun ExpandableTextSample() {
val expandableState = rememberExpandableState()
- ScalingLazyColumn(
- modifier = Modifier.fillMaxSize()
- ) {
+ ScalingLazyColumn(modifier = Modifier.fillMaxSize()) {
expandableItem(expandableState) { expanded ->
Text(
"Account Alert: you have made a large purchase.\n" +
@@ -105,10 +88,7 @@
label = {
Text("Show More")
Spacer(Modifier.size(6.dp))
- Icon(
- painterResource(R.drawable.ic_expand_more_24),
- "Expand"
- )
+ Icon(painterResource(R.drawable.ic_expand_more_24), "Expand")
},
onClick = { expandableState.expanded = true }
)
diff --git a/wear/compose/compose-foundation/samples/src/main/java/androidx/wear/compose/foundation/samples/HierarchicalFocusCoordinatorSample.kt b/wear/compose/compose-foundation/samples/src/main/java/androidx/wear/compose/foundation/samples/HierarchicalFocusCoordinatorSample.kt
index 2ee2e3f..f45866b 100644
--- a/wear/compose/compose-foundation/samples/src/main/java/androidx/wear/compose/foundation/samples/HierarchicalFocusCoordinatorSample.kt
+++ b/wear/compose/compose-foundation/samples/src/main/java/androidx/wear/compose/foundation/samples/HierarchicalFocusCoordinatorSample.kt
@@ -56,23 +56,27 @@
var focused by remember { mutableStateOf(false) }
HierarchicalFocusCoordinator(requiresFocus = { selected == ix }) {
val focusRequester = rememberActiveFocusRequester()
- BasicText("$ix",
- style = TextStyle(
- color = Color.White,
- fontSize = 20.sp,
- textAlign = TextAlign.Center
- ),
- modifier = Modifier
- .weight(1f)
- .clickable { selected = ix }
- .onFocusChanged { focused = it.isFocused }
- .focusRequester(focusRequester)
- .focusable()
- .then(if (focused) {
- Modifier.border(BorderStroke(2.dp, Color.Red))
- } else {
- Modifier
- })
+ BasicText(
+ "$ix",
+ style =
+ TextStyle(
+ color = Color.White,
+ fontSize = 20.sp,
+ textAlign = TextAlign.Center
+ ),
+ modifier =
+ Modifier.weight(1f)
+ .clickable { selected = ix }
+ .onFocusChanged { focused = it.isFocused }
+ .focusRequester(focusRequester)
+ .focusable()
+ .then(
+ if (focused) {
+ Modifier.border(BorderStroke(2.dp, Color.Red))
+ } else {
+ Modifier
+ }
+ )
)
}
}
diff --git a/wear/compose/compose-foundation/samples/src/main/java/androidx/wear/compose/foundation/samples/RotarySamples.kt b/wear/compose/compose-foundation/samples/src/main/java/androidx/wear/compose/foundation/samples/RotarySamples.kt
index 80428e1..ce18792 100644
--- a/wear/compose/compose-foundation/samples/src/main/java/androidx/wear/compose/foundation/samples/RotarySamples.kt
+++ b/wear/compose/compose-foundation/samples/src/main/java/androidx/wear/compose/foundation/samples/RotarySamples.kt
@@ -44,12 +44,12 @@
val scrollableState = rememberLazyListState()
val focusRequester = rememberActiveFocusRequester()
LazyColumn(
- modifier = Modifier
- .fillMaxSize()
- .rotaryScrollable(
- behavior = RotaryScrollableDefaults.behavior(scrollableState),
- focusRequester = focusRequester
- ),
+ modifier =
+ Modifier.fillMaxSize()
+ .rotaryScrollable(
+ behavior = RotaryScrollableDefaults.behavior(scrollableState),
+ focusRequester = focusRequester
+ ),
horizontalAlignment = Alignment.CenterHorizontally,
state = scrollableState
) {
@@ -70,49 +70,46 @@
val scrollableState = rememberLazyListState()
val focusRequester = rememberActiveFocusRequester()
LazyColumn(
- modifier = Modifier
- .fillMaxSize()
- .rotaryScrollable(
- behavior = RotaryScrollableDefaults.snapBehavior(
- scrollableState,
- // This sample has a custom implementation of RotarySnapLayoutInfoProvider
- // which is required for snapping behavior. ScalingLazyColumn has it built-in,
- // so it's not required there.
- remember(scrollableState) {
- object : RotarySnapLayoutInfoProvider {
+ modifier =
+ Modifier.fillMaxSize()
+ .rotaryScrollable(
+ behavior =
+ RotaryScrollableDefaults.snapBehavior(
+ scrollableState,
+ // This sample has a custom implementation of
+ // RotarySnapLayoutInfoProvider
+ // which is required for snapping behavior. ScalingLazyColumn has it
+ // built-in,
+ // so it's not required there.
+ remember(scrollableState) {
+ object : RotarySnapLayoutInfoProvider {
- override val averageItemSize: Float
- get() {
- val items = scrollableState.layoutInfo.visibleItemsInfo
- return (items.fastSumBy { it.size } / items.size).toFloat()
+ override val averageItemSize: Float
+ get() {
+ val items = scrollableState.layoutInfo.visibleItemsInfo
+ return (items.fastSumBy { it.size } / items.size)
+ .toFloat()
+ }
+
+ override val currentItemIndex: Int
+ get() = scrollableState.firstVisibleItemIndex
+
+ override val currentItemOffset: Float
+ get() =
+ scrollableState.firstVisibleItemScrollOffset.toFloat()
+
+ override val totalItemCount: Int
+ get() = scrollableState.layoutInfo.totalItemsCount
+ }
}
-
- override val currentItemIndex: Int
- get() =
- scrollableState.firstVisibleItemIndex
-
- override val currentItemOffset: Float
- get() =
- scrollableState.firstVisibleItemScrollOffset.toFloat()
-
- override val totalItemCount: Int
- get() =
- scrollableState.layoutInfo.totalItemsCount
- }
- }
+ ),
+ focusRequester = focusRequester
),
- focusRequester = focusRequester
- ),
horizontalAlignment = Alignment.CenterHorizontally,
state = scrollableState
) {
items(300) {
- BasicText(
- text = "item $it",
- modifier = Modifier
- .background(Color.Gray)
- .height(30.dp)
- )
+ BasicText(text = "item $it", modifier = Modifier.background(Color.Gray).height(30.dp))
}
}
}
diff --git a/wear/compose/compose-foundation/samples/src/main/java/androidx/wear/compose/foundation/samples/ScalingLazyColumnSample.kt b/wear/compose/compose-foundation/samples/src/main/java/androidx/wear/compose/foundation/samples/ScalingLazyColumnSample.kt
index e8dc372..70397e4 100644
--- a/wear/compose/compose-foundation/samples/src/main/java/androidx/wear/compose/foundation/samples/ScalingLazyColumnSample.kt
+++ b/wear/compose/compose-foundation/samples/src/main/java/androidx/wear/compose/foundation/samples/ScalingLazyColumnSample.kt
@@ -40,17 +40,11 @@
@Sampled
@Composable
fun SimpleScalingLazyColumn() {
- ScalingLazyColumn(
- modifier = Modifier.fillMaxWidth()
- ) {
- item {
- ListHeader {
- Text(text = "List Header")
- }
- }
+ ScalingLazyColumn(modifier = Modifier.fillMaxWidth()) {
+ item { ListHeader { Text(text = "List Header") } }
items(20) {
Chip(
- onClick = { },
+ onClick = {},
label = { Text("List item $it") },
colors = ChipDefaults.secondaryChipColors()
)
@@ -68,14 +62,10 @@
modifier = Modifier.fillMaxWidth(),
state = state,
) {
- item {
- ListHeader {
- Text(text = "List Header")
- }
- }
+ item { ListHeader { Text(text = "List Header") } }
items(20) {
Chip(
- onClick = { },
+ onClick = {},
label = { Text("List item $it") },
colors = ChipDefaults.secondaryChipColors()
)
@@ -89,13 +79,12 @@
val coroutineScope = rememberCoroutineScope()
val itemSpacing = 6.dp
// Line up the gap between the items on the center-line
- val scrollOffset = with(LocalDensity.current) {
- -(itemSpacing / 2).roundToPx()
- }
- val state = rememberScalingLazyListState(
- initialCenterItemIndex = 1,
- initialCenterItemScrollOffset = scrollOffset
- )
+ val scrollOffset = with(LocalDensity.current) { -(itemSpacing / 2).roundToPx() }
+ val state =
+ rememberScalingLazyListState(
+ initialCenterItemIndex = 1,
+ initialCenterItemScrollOffset = scrollOffset
+ )
ScalingLazyColumn(
modifier = Modifier.fillMaxWidth(),
@@ -104,11 +93,7 @@
state = state,
autoCentering = AutoCenteringParams(itemOffset = scrollOffset)
) {
- item {
- ListHeader {
- Text(text = "List Header")
- }
- }
+ item { ListHeader { Text(text = "List Header") } }
items(20) {
Chip(
onClick = {
@@ -132,14 +117,10 @@
contentPadding = PaddingValues(top = 20.dp, bottom = 20.dp),
autoCentering = null
) {
- item {
- ListHeader {
- Text(text = "List Header")
- }
- }
+ item { ListHeader { Text(text = "List Header") } }
items(20) {
Chip(
- onClick = { },
+ onClick = {},
label = { Text("List item $it") },
colors = ChipDefaults.secondaryChipColors()
)
diff --git a/wear/compose/compose-foundation/samples/src/main/java/androidx/wear/compose/foundation/samples/SwipeToDismissBoxSample.kt b/wear/compose/compose-foundation/samples/src/main/java/androidx/wear/compose/foundation/samples/SwipeToDismissBoxSample.kt
index 2e59395..f64f469e 100644
--- a/wear/compose/compose-foundation/samples/src/main/java/androidx/wear/compose/foundation/samples/SwipeToDismissBoxSample.kt
+++ b/wear/compose/compose-foundation/samples/src/main/java/androidx/wear/compose/foundation/samples/SwipeToDismissBoxSample.kt
@@ -49,23 +49,14 @@
@Sampled
@Composable
-fun SimpleSwipeToDismissBox(
- navigateBack: () -> Unit
-) {
+fun SimpleSwipeToDismissBox(navigateBack: () -> Unit) {
val state = rememberSwipeToDismissBoxState()
- BasicSwipeToDismissBox(
- state = state,
- onDismissed = navigateBack
- ) { isBackground ->
+ BasicSwipeToDismissBox(state = state, onDismissed = navigateBack) { isBackground ->
if (isBackground) {
- Box(modifier = Modifier
- .fillMaxSize()
- .background(MaterialTheme.colors.secondaryVariant))
+ Box(modifier = Modifier.fillMaxSize().background(MaterialTheme.colors.secondaryVariant))
} else {
Column(
- modifier = Modifier
- .fillMaxSize()
- .background(MaterialTheme.colors.primary),
+ modifier = Modifier.fillMaxSize().background(MaterialTheme.colors.primary),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center,
) {
@@ -101,7 +92,6 @@
backgroundKey = if (!showMainScreen) "MainKey" else "Background",
contentKey = if (showMainScreen) "MainKey" else "ItemKey",
) { isBackground ->
-
if (isBackground || showMainScreen) {
// Best practice would be to use State Hoisting and leave this composable stateless.
// Here, we want to support MainScreen being shown from different destinations
@@ -114,11 +104,10 @@
// and can be shown in foreground or background.
val checked = rememberSaveable { mutableStateOf(true) }
Column(
- modifier = Modifier
- .fillMaxSize()
- .padding(horizontal = 8.dp, vertical = 8.dp),
+ modifier =
+ Modifier.fillMaxSize().padding(horizontal = 8.dp, vertical = 8.dp),
verticalArrangement =
- Arrangement.spacedBy(4.dp, Alignment.CenterVertically),
+ Arrangement.spacedBy(4.dp, Alignment.CenterVertically),
) {
SplitToggleChip(
checked = checked.value,
@@ -128,9 +117,8 @@
onClick = { showMainScreen = false },
toggleControl = {
Icon(
- imageVector = ToggleChipDefaults.checkboxIcon(
- checked = checked.value
- ),
+ imageVector =
+ ToggleChipDefaults.checkboxIcon(checked = checked.value),
contentDescription = null,
)
}
@@ -140,9 +128,7 @@
)
} else {
Column(
- modifier = Modifier
- .fillMaxSize()
- .background(MaterialTheme.colors.primary),
+ modifier = Modifier.fillMaxSize().background(MaterialTheme.colors.primary),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center,
) {
@@ -155,33 +141,25 @@
@Sampled
@Composable
-fun EdgeSwipeForSwipeToDismiss(
- navigateBack: () -> Unit
-) {
+fun EdgeSwipeForSwipeToDismiss(navigateBack: () -> Unit) {
val state = rememberSwipeToDismissBoxState()
// When using Modifier.edgeSwipeToDismiss, it is required that the element on which the
// modifier applies exists within a SwipeToDismissBox which shares the same state.
- BasicSwipeToDismissBox(
- state = state,
- onDismissed = navigateBack
- ) { isBackground ->
+ BasicSwipeToDismissBox(state = state, onDismissed = navigateBack) { isBackground ->
val horizontalScrollState = rememberScrollState(0)
if (isBackground) {
- Box(
- modifier = Modifier
- .fillMaxSize()
- .background(MaterialTheme.colors.secondaryVariant)
- )
+ Box(modifier = Modifier.fillMaxSize().background(MaterialTheme.colors.secondaryVariant))
} else {
Box(modifier = Modifier.fillMaxSize()) {
Text(
- modifier = Modifier
- .align(Alignment.Center)
- .edgeSwipeToDismiss(state)
- .horizontalScroll(horizontalScrollState),
- text = "This text can be scrolled horizontally - to dismiss, swipe " +
- "right from the left edge of the screen (called Edge Swiping)",
+ modifier =
+ Modifier.align(Alignment.Center)
+ .edgeSwipeToDismiss(state)
+ .horizontalScroll(horizontalScrollState),
+ text =
+ "This text can be scrolled horizontally - to dismiss, swipe " +
+ "right from the left edge of the screen (called Edge Swiping)",
)
}
}
diff --git a/wear/compose/compose-foundation/samples/src/main/java/androidx/wear/compose/foundation/samples/SwipeToRevealSample.kt b/wear/compose/compose-foundation/samples/src/main/java/androidx/wear/compose/foundation/samples/SwipeToRevealSample.kt
index cc1f9ce..008a0b0 100644
--- a/wear/compose/compose-foundation/samples/src/main/java/androidx/wear/compose/foundation/samples/SwipeToRevealSample.kt
+++ b/wear/compose/compose-foundation/samples/src/main/java/androidx/wear/compose/foundation/samples/SwipeToRevealSample.kt
@@ -62,25 +62,22 @@
@Composable
fun SwipeToRevealSample() {
SwipeToReveal(
- modifier = Modifier.semantics {
- // Use custom actions to make the primary and secondary actions accessible
- customActions = listOf(
- CustomAccessibilityAction("Delete") {
- /* Add the primary action click handler */
- true
- }
- )
- },
+ modifier =
+ Modifier.semantics {
+ // Use custom actions to make the primary and secondary actions accessible
+ customActions =
+ listOf(
+ CustomAccessibilityAction("Delete") {
+ /* Add the primary action click handler */
+ true
+ }
+ )
+ },
primaryAction = {
Box(
- modifier = Modifier
- .fillMaxSize()
- .clickable { /* Add the primary action */ },
+ modifier = Modifier.fillMaxSize().clickable { /* Add the primary action */ },
) {
- Icon(
- imageVector = Icons.Outlined.Delete,
- contentDescription = "Delete"
- )
+ Icon(imageVector = Icons.Outlined.Delete, contentDescription = "Delete")
}
},
undoAction = {
@@ -107,36 +104,31 @@
fun SwipeToRevealWithDelayedText() {
val state = rememberRevealState()
SwipeToReveal(
- modifier = Modifier.semantics {
- // Use custom actions to make the primary and secondary actions accessible
- customActions = listOf(
- CustomAccessibilityAction("Delete") {
- /* Add the primary action click handler */
- true
- }
- )
- },
+ modifier =
+ Modifier.semantics {
+ // Use custom actions to make the primary and secondary actions accessible
+ customActions =
+ listOf(
+ CustomAccessibilityAction("Delete") {
+ /* Add the primary action click handler */
+ true
+ }
+ )
+ },
state = state,
primaryAction = {
Box(
- modifier = Modifier
- .fillMaxSize()
- .clickable { /* Add the primary action */ },
+ modifier = Modifier.fillMaxSize().clickable { /* Add the primary action */ },
) {
- Icon(
- imageVector = Icons.Outlined.Delete,
- contentDescription = "Delete"
- )
+ Icon(imageVector = Icons.Outlined.Delete, contentDescription = "Delete")
if (abs(state.offset) > revealOffset) {
// Delay the text appearance so that it has enough space to be displayed
- val textAlpha = animateFloatAsState(
- targetValue = 1f,
- animationSpec = tween(
- durationMillis = 250,
- delayMillis = 250
- ),
- label = "PrimaryActionTextAlpha"
- )
+ val textAlpha =
+ animateFloatAsState(
+ targetValue = 1f,
+ animationSpec = tween(durationMillis = 250, delayMillis = 250),
+ label = "PrimaryActionTextAlpha"
+ )
Box(modifier = Modifier.graphicsLayer { alpha = textAlpha.value }) {
Spacer(Modifier.size(5.dp))
Text("Clear")
@@ -175,17 +167,9 @@
val actionShape = RoundedCornerShape(corner = CornerSize(percent = 50))
val itemCount = 10
val coroutineScope = rememberCoroutineScope()
- val expandableStates = List(itemCount) {
- rememberExpandableState(initiallyExpanded = true)
- }
- ScalingLazyColumn(
- modifier = Modifier.fillMaxSize()
- ) {
- item {
- ListHeader {
- Text("Scaling Lazy Column")
- }
- }
+ val expandableStates = List(itemCount) { rememberExpandableState(initiallyExpanded = true) }
+ ScalingLazyColumn(modifier = Modifier.fillMaxSize()) {
+ item { ListHeader { Text("Scaling Lazy Column") } }
repeat(itemCount) { current ->
expandableItem(
state = expandableStates[current],
@@ -193,29 +177,31 @@
val revealState = rememberRevealState()
if (isExpanded) {
SwipeToReveal(
- modifier = Modifier.semantics {
- // Use custom actions to make the primary and secondary actions
- // accessible
- customActions = listOf(
- CustomAccessibilityAction("Delete") {
- coroutineScope.launch {
- revealState.animateTo(RevealValue.Revealed)
- }
- true
- }
- )
- },
+ modifier =
+ Modifier.semantics {
+ // Use custom actions to make the primary and secondary actions
+ // accessible
+ customActions =
+ listOf(
+ CustomAccessibilityAction("Delete") {
+ coroutineScope.launch {
+ revealState.animateTo(RevealValue.Revealed)
+ }
+ true
+ }
+ )
+ },
state = revealState,
primaryAction = {
Box(
- modifier = Modifier
- .fillMaxSize()
- .background(Color.Red, actionShape)
- .clickable {
- coroutineScope.launch {
- revealState.animateTo(RevealValue.Revealed)
- }
- },
+ modifier =
+ Modifier.fillMaxSize()
+ .background(Color.Red, actionShape)
+ .clickable {
+ coroutineScope.launch {
+ revealState.animateTo(RevealValue.Revealed)
+ }
+ },
contentAlignment = Alignment.Center
) {
Icon(
@@ -226,10 +212,10 @@
},
secondaryAction = {
Box(
- modifier = Modifier
- .fillMaxSize()
- .background(Color.Gray, actionShape)
- .clickable { /* trigger the optional action */ },
+ modifier =
+ Modifier.fillMaxSize()
+ .background(Color.Gray, actionShape)
+ .clickable { /* trigger the optional action */ },
contentAlignment = Alignment.Center
) {
Icon(
diff --git a/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/BasicCurvedTextTest.kt b/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/BasicCurvedTextTest.kt
index 5d8ba64..f17f27d 100644
--- a/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/BasicCurvedTextTest.kt
+++ b/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/BasicCurvedTextTest.kt
@@ -32,8 +32,7 @@
import org.junit.Test
class BasicCurvedTextTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
@Test
fun modifying_curved_text_forces_curved_row_remeasure() {
@@ -42,10 +41,7 @@
rule.setContent {
CurvedLayout {
curvedRow(modifier = CurvedModifier.spy(capturedInfo)) {
- basicCurvedText(
- text = text.value,
- style = CurvedTextStyle(fontSize = 14.sp)
- )
+ basicCurvedText(text = text.value, style = CurvedTextStyle(fontSize = 14.sp))
}
}
}
@@ -66,9 +62,7 @@
rule.setContent {
CompositionLocalProvider(LocalDensity provides Density(1f, 1f)) {
CurvedLayout(modifier = Modifier.size(200.dp)) {
- curvedRow(
- modifier = CurvedModifier.testTag(TEST_TAG)
- ) {
+ curvedRow(modifier = CurvedModifier.testTag(TEST_TAG)) {
basicCurvedText(
text = "Test text",
style = CurvedTextStyle(fontSize = 24.sp),
diff --git a/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/BasicSwipeToDismissBoxTest.kt b/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/BasicSwipeToDismissBoxTest.kt
index 88d3c13..1e1bf1d 100644
--- a/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/BasicSwipeToDismissBoxTest.kt
+++ b/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/BasicSwipeToDismissBoxTest.kt
@@ -64,17 +64,13 @@
import org.junit.Test
class BasicSwipeToDismissBoxTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
@Test
fun supports_testtag() {
rule.setContent {
val state = rememberSwipeToDismissBoxState()
- BasicSwipeToDismissBox(
- state = state,
- modifier = Modifier.testTag(TEST_TAG)
- ) {
+ BasicSwipeToDismissBox(state = state, modifier = Modifier.testTag(TEST_TAG)) {
BasicText("Testing")
}
}
@@ -94,21 +90,13 @@
val state = rememberSwipeToDismissBoxState()
BasicSwipeToDismissBox(
state = state,
- onDismissed = { },
+ onDismissed = {},
) { isBackground ->
innerCounter++
if (isBackground) {
- Box(
- modifier = Modifier
- .fillMaxSize()
- .background(Color.Green)
- )
+ Box(modifier = Modifier.fillMaxSize().background(Color.Green))
} else {
- Box(
- modifier = Modifier
- .fillMaxSize()
- .background(Color.Red)
- )
+ Box(modifier = Modifier.fillMaxSize().background(Color.Red))
}
}
}
@@ -137,11 +125,13 @@
// Execute a partial swipe over a longer-than-default duration so that there
// is insufficient velocity to perform a 'fling'.
verifySwipe(
- gesture = { swipeWithVelocity(
- start = Offset(0f, centerY),
- end = Offset(centerX / 2f, centerY),
- endVelocity = 1.0f
- ) },
+ gesture = {
+ swipeWithVelocity(
+ start = Offset(0f, centerY),
+ end = Offset(centerX / 2f, centerY),
+ endVelocity = 1.0f
+ )
+ },
expectedToDismiss = false
)
@@ -149,10 +139,8 @@
fun does_not_display_background_without_swipe() {
rule.setContent {
val state = rememberSwipeToDismissBoxState()
- BasicSwipeToDismissBox(
- state = state,
- modifier = Modifier.testTag(TEST_TAG)
- ) { isBackground ->
+ BasicSwipeToDismissBox(state = state, modifier = Modifier.testTag(TEST_TAG)) {
+ isBackground ->
if (isBackground) BasicText(BACKGROUND_MESSAGE) else MessageContent()
}
}
@@ -166,8 +154,7 @@
rule.setContent {
val state = rememberSwipeToDismissBoxState()
LaunchedEffect(state.currentValue) {
- dismissed =
- state.currentValue == SwipeToDismissValue.Dismissed
+ dismissed = state.currentValue == SwipeToDismissValue.Dismissed
}
BasicSwipeToDismissBox(
state = state,
@@ -180,9 +167,7 @@
rule.onNodeWithTag(TEST_TAG).performTouchInput { swipeRight() }
- rule.runOnIdle {
- assertEquals(false, dismissed)
- }
+ rule.runOnIdle { assertEquals(false, dismissed) }
}
@Test
@@ -203,10 +188,8 @@
backgroundKey = if (showCounterForContent.value) TOGGLE_SCREEN else COUNTER_SCREEN,
contentKey = if (showCounterForContent.value) COUNTER_SCREEN else TOGGLE_SCREEN,
content = { isBackground ->
- if (showCounterForContent.value xor isBackground)
- counterScreen(holder)
- else
- toggleScreen(holder)
+ if (showCounterForContent.value xor isBackground) counterScreen(holder)
+ else toggleScreen(holder)
}
)
}
@@ -243,8 +226,7 @@
rule.setContent {
val outerState = rememberSwipeToDismissBoxState()
LaunchedEffect(outerState.currentValue) {
- outerDismissed =
- outerState.currentValue == SwipeToDismissValue.Dismissed
+ outerDismissed = outerState.currentValue == SwipeToDismissValue.Dismissed
}
BasicSwipeToDismissBox(
state = outerState,
@@ -254,8 +236,7 @@
BasicText("Outer", color = { Color.Red })
val innerState = rememberSwipeToDismissBoxState()
LaunchedEffect(innerState.currentValue) {
- innerDismissed =
- innerState.currentValue == SwipeToDismissValue.Dismissed
+ innerDismissed = innerState.currentValue == SwipeToDismissValue.Dismissed
}
BasicSwipeToDismissBox(
state = innerState,
@@ -284,9 +265,7 @@
saveableStateHolder.SaveableStateProvider(TOGGLE_SCREEN) {
var toggle by rememberSaveable { mutableStateOf(false) }
Box(
- modifier = Modifier
- .testTag(TOGGLE_SCREEN)
- .toggleable(toggle) { toggle = !toggle }
+ modifier = Modifier.testTag(TOGGLE_SCREEN).toggleable(toggle) { toggle = !toggle }
) {
BasicText(text = if (toggle) TOGGLE_ON else TOGGLE_OFF)
}
@@ -297,11 +276,7 @@
fun counterScreen(saveableStateHolder: SaveableStateHolder) {
saveableStateHolder.SaveableStateProvider(COUNTER_SCREEN) {
var counter by rememberSaveable { mutableStateOf(0) }
- Box(
- modifier = Modifier
- .testTag(COUNTER_SCREEN)
- .clickable { ++counter }
- ) {
+ Box(modifier = Modifier.testTag(COUNTER_SCREEN).clickable { ++counter }) {
BasicText(text = "$counter")
}
}
@@ -312,8 +287,7 @@
verifyPartialSwipe(expectedMessage = BACKGROUND_MESSAGE)
@Test
- fun displays_content_during_swipe() =
- verifyPartialSwipe(expectedMessage = CONTENT_MESSAGE)
+ fun displays_content_during_swipe() = verifyPartialSwipe(expectedMessage = CONTENT_MESSAGE)
@Test
fun calls_ondismissed_after_swipe_when_supplied() {
@@ -329,17 +303,12 @@
rule.onNodeWithTag(TEST_TAG).performTouchInput { swipeRight() }
- rule.runOnIdle {
- assertEquals(true, dismissed)
- }
+ rule.runOnIdle { assertEquals(true, dismissed) }
}
@Test
fun edgeswipe_modifier_edge_swiped_right_dismissed() {
- verifyEdgeSwipeWithNestedScroll(
- gesture = { swipeRight() },
- expectedToDismiss = true
- )
+ verifyEdgeSwipeWithNestedScroll(gesture = { swipeRight() }, expectedToDismiss = true)
}
@Test
@@ -384,18 +353,13 @@
val state = rememberSwipeToDismissBoxState()
horizontalScrollState = rememberScrollState(initialScrollState)
- BasicSwipeToDismissBox(
- state = state,
- modifier = Modifier.testTag(TEST_TAG)
- ) {
+ BasicSwipeToDismissBox(state = state, modifier = Modifier.testTag(TEST_TAG)) {
NestedScrollContent(state, horizontalScrollState)
}
}
rule.onNodeWithTag(TEST_TAG).performTouchInput { swipeRight(0f, 200f) }
- rule.runOnIdle {
- assert(horizontalScrollState.value == initialScrollState)
- }
+ rule.runOnIdle { assert(horizontalScrollState.value == initialScrollState) }
}
@Test
@@ -406,18 +370,13 @@
val state = rememberSwipeToDismissBoxState()
horizontalScrollState = rememberScrollState(initialScrollState)
- BasicSwipeToDismissBox(
- state = state,
- modifier = Modifier.testTag(TEST_TAG)
- ) {
+ BasicSwipeToDismissBox(state = state, modifier = Modifier.testTag(TEST_TAG)) {
NestedScrollContent(state, horizontalScrollState)
}
}
rule.onNodeWithTag(TEST_TAG).performTouchInput { swipeRight(200f, 400f) }
- rule.runOnIdle {
- assert(horizontalScrollState.value < initialScrollState)
- }
+ rule.runOnIdle { assert(horizontalScrollState.value < initialScrollState) }
}
@Test
@@ -487,18 +446,18 @@
val focusRequester = rememberActiveFocusRequester()
BasicText(
BACKGROUND_MESSAGE,
- Modifier
- .onFocusChanged { focusedBackground = it.isFocused }
+ Modifier.onFocusChanged { focusedBackground = it.isFocused }
.focusRequester(focusRequester)
- .focusable())
+ .focusable()
+ )
} else {
val focusRequester = rememberActiveFocusRequester()
BasicText(
CONTENT_MESSAGE,
- Modifier
- .onFocusChanged { focusedContent = it.isFocused }
+ Modifier.onFocusChanged { focusedContent = it.isFocused }
.focusRequester(focusRequester)
- .focusable())
+ .focusable()
+ )
}
}
}
@@ -536,26 +495,20 @@
val state = rememberSwipeToDismissBoxState()
horizontalScrollState = rememberScrollState(initialScrollState)
- BasicSwipeToDismissBox(
- state = state,
- modifier = Modifier.testTag(TEST_TAG)
- ) {
+ BasicSwipeToDismissBox(state = state, modifier = Modifier.testTag(TEST_TAG)) {
NestedScrollContent(state, horizontalScrollState)
}
}
- rule.onNodeWithTag(TEST_TAG)
- .performTouchInput {
- swipeBothDirections(
- startLeft = startLeft,
- startX = initialTouch,
- amplitude = amplitude,
- duration = duration
- )
- }
- rule.runOnIdle {
- testScrollState(horizontalScrollState)
+ rule.onNodeWithTag(TEST_TAG).performTouchInput {
+ swipeBothDirections(
+ startLeft = startLeft,
+ startX = initialTouch,
+ amplitude = amplitude,
+ duration = duration
+ )
}
+ rule.runOnIdle { testScrollState(horizontalScrollState) }
}
private fun verifySwipe(gesture: TouchInjectionScope.() -> Unit, expectedToDismiss: Boolean) {
@@ -573,9 +526,7 @@
rule.onNodeWithTag(TEST_TAG).performTouchInput(gesture)
- rule.runOnIdle {
- assertEquals(expectedToDismiss, dismissed)
- }
+ rule.runOnIdle { assertEquals(expectedToDismiss, dismissed) }
}
private fun verifyEdgeSwipeWithNestedScroll(
@@ -589,31 +540,23 @@
val horizontalScrollState = rememberScrollState(initialScrollState)
LaunchedEffect(state.currentValue) {
- dismissed =
- state.currentValue == SwipeToDismissValue.Dismissed
+ dismissed = state.currentValue == SwipeToDismissValue.Dismissed
}
- BasicSwipeToDismissBox(
- state = state,
- modifier = Modifier.testTag(TEST_TAG)
- ) {
+ BasicSwipeToDismissBox(state = state, modifier = Modifier.testTag(TEST_TAG)) {
NestedScrollContent(state, horizontalScrollState)
}
}
rule.onNodeWithTag(TEST_TAG).performTouchInput(gesture)
- rule.runOnIdle {
- assertEquals(expectedToDismiss, dismissed)
- }
+ rule.runOnIdle { assertEquals(expectedToDismiss, dismissed) }
}
private fun verifyPartialSwipe(expectedMessage: String) {
rule.setContent {
val state = rememberSwipeToDismissBoxState()
- BasicSwipeToDismissBox(
- state = state,
- modifier = Modifier.testTag(TEST_TAG)
- ) { isBackground ->
+ BasicSwipeToDismissBox(state = state, modifier = Modifier.testTag(TEST_TAG)) {
+ isBackground ->
if (isBackground) BasicText(BACKGROUND_MESSAGE) else MessageContent()
}
}
@@ -647,12 +590,13 @@
) {
Box(modifier = Modifier.fillMaxSize()) {
BasicText(
- modifier = Modifier
- .align(Alignment.Center)
- .edgeSwipeToDismiss(swipeToDismissState)
- .horizontalScroll(horizontalScrollState),
- text = "This text can be scrolled horizontally - to dismiss, swipe " +
- "right from the left edge of the screen (called Edge Swiping)",
+ modifier =
+ Modifier.align(Alignment.Center)
+ .edgeSwipeToDismiss(swipeToDismissState)
+ .horizontalScroll(horizontalScrollState),
+ text =
+ "This text can be scrolled horizontally - to dismiss, swipe " +
+ "right from the left edge of the screen (called Edge Swiping)",
)
}
}
@@ -665,15 +609,17 @@
) {
val sign = if (startLeft) -1 else 1
// By using sin function for range 0.. 3pi/2 , we can achieve 0 -> 1 and 1 -> -1 values
- swipe(curve = { time ->
- val x =
- startX + sign * sin(time.toFloat() / duration.toFloat() * 3 * Math.PI / 2)
- .toFloat() * amplitude
- Offset(
- x = x,
- y = centerY
- )
- }, durationMillis = duration)
+ swipe(
+ curve = { time ->
+ val x =
+ startX +
+ sign *
+ sin(time.toFloat() / duration.toFloat() * 3 * Math.PI / 2).toFloat() *
+ amplitude
+ Offset(x = x, y = centerY)
+ },
+ durationMillis = duration
+ )
}
}
diff --git a/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/CurvedBoxTest.kt b/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/CurvedBoxTest.kt
index 55ac19f..6c4ed82 100644
--- a/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/CurvedBoxTest.kt
+++ b/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/CurvedBoxTest.kt
@@ -36,39 +36,24 @@
import org.junit.Test
class CurvedBoxTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
@RequiresApi(Build.VERSION_CODES.O)
@Test
fun first_item_covered_by_second() {
rule.setContent {
- CurvedLayout(
- modifier = Modifier.testTag(TEST_TAG)
- ) {
+ CurvedLayout(modifier = Modifier.testTag(TEST_TAG)) {
curvedBox {
- curvedComposable {
- Box(
- modifier = Modifier
- .size(40.dp)
- .background(Color.Red)
- )
- }
+ curvedComposable { Box(modifier = Modifier.size(40.dp).background(Color.Red)) }
curvedComposable {
- Box(
- modifier = Modifier
- .size(40.dp)
- .background(Color.Green)
- )
+ Box(modifier = Modifier.size(40.dp).background(Color.Green))
}
}
}
}
- rule.onNodeWithTag(TEST_TAG)
- .captureToImage()
- .assertDoesNotContainColor(Color.Red)
+ rule.onNodeWithTag(TEST_TAG).captureToImage().assertDoesNotContainColor(Color.Red)
}
@Test
@@ -197,20 +182,14 @@
val bigSpy = CapturedInfo()
// We have a big box and a small box with the specified alignment
rule.setContent {
- CurvedLayout(
- modifier = Modifier.onGloballyPositioned { rowCoords = it }
- ) {
- curvedBox(
- radialAlignment = radialAlignment,
- angularAlignment = angularAlignment
- ) {
+ CurvedLayout(modifier = Modifier.onGloballyPositioned { rowCoords = it }) {
+ curvedBox(radialAlignment = radialAlignment, angularAlignment = angularAlignment) {
curvedComposable(
modifier = CurvedModifier.spy(bigSpy),
) {
Box(
- modifier = Modifier
- .size(45.dp)
- .onGloballyPositioned { bigBoxCoords = it }
+ modifier =
+ Modifier.size(45.dp).onGloballyPositioned { bigBoxCoords = it }
)
}
@@ -218,9 +197,8 @@
modifier = CurvedModifier.spy(smallSpy),
) {
Box(
- modifier = Modifier
- .size(30.dp)
- .onGloballyPositioned { smallBoxCoords = it }
+ modifier =
+ Modifier.size(30.dp).onGloballyPositioned { smallBoxCoords = it }
)
}
}
@@ -228,18 +206,12 @@
}
rule.runOnIdle {
- val bigBoxDimensions = RadialDimensions(
- absoluteClockwise = true,
- rowCoords!!,
- bigBoxCoords!!
- )
+ val bigBoxDimensions =
+ RadialDimensions(absoluteClockwise = true, rowCoords!!, bigBoxCoords!!)
checkSpy(bigBoxDimensions, bigSpy)
- val smallBoxDimensions = RadialDimensions(
- absoluteClockwise = true,
- rowCoords!!,
- smallBoxCoords!!
- )
+ val smallBoxDimensions =
+ RadialDimensions(absoluteClockwise = true, rowCoords!!, smallBoxCoords!!)
checkSpy(smallBoxDimensions, smallSpy)
Assert.assertTrue(bigBoxDimensions.sweep > smallBoxDimensions.sweep)
diff --git a/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/CurvedLayoutTest.kt b/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/CurvedLayoutTest.kt
index fc1becc..ac01d5e 100644
--- a/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/CurvedLayoutTest.kt
+++ b/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/CurvedLayoutTest.kt
@@ -39,8 +39,7 @@
import org.junit.Test
class CurvedLayoutTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
private fun anchor_and_clockwise_test(
anchor: Float,
@@ -58,61 +57,59 @@
rule.setContent {
CompositionLocalProvider(LocalLayoutDirection provides layoutDirection) {
CurvedLayout(
- modifier = Modifier.size(200.dp)
- .onGloballyPositioned { rowCoords = it },
+ modifier = Modifier.size(200.dp).onGloballyPositioned { rowCoords = it },
anchor = anchor,
anchorType = anchorTypeState,
angularDirection = angularDirection
) {
curvedComposable(modifier = CurvedModifier.spy(capturedInfo)) {
- Box(
- modifier = Modifier
- .size(40.dp)
- .onGloballyPositioned { coords = it }
- )
+ Box(modifier = Modifier.size(40.dp).onGloballyPositioned { coords = it })
}
}
if (anchorType != initialAnchorType) {
- LaunchedEffect(true) {
- anchorTypeState = anchorType
- }
+ LaunchedEffect(true) { anchorTypeState = anchorType }
}
}
}
val isLtr = layoutDirection == LayoutDirection.Ltr
- val clockwise = when (angularDirection) {
- CurvedDirection.Angular.Normal -> isLtr
- CurvedDirection.Angular.Reversed -> !isLtr
- CurvedDirection.Angular.Clockwise -> true
- CurvedDirection.Angular.CounterClockwise -> false
- else -> throw java.lang.IllegalArgumentException(
- "Illegal AngularDirection: $angularDirection"
- )
- }
+ val clockwise =
+ when (angularDirection) {
+ CurvedDirection.Angular.Normal -> isLtr
+ CurvedDirection.Angular.Reversed -> !isLtr
+ CurvedDirection.Angular.Clockwise -> true
+ CurvedDirection.Angular.CounterClockwise -> false
+ else ->
+ throw java.lang.IllegalArgumentException(
+ "Illegal AngularDirection: $angularDirection"
+ )
+ }
rule.runOnIdle {
- val dims = RadialDimensions(
- absoluteClockwise = angularDirection == CurvedDirection.Angular.Normal ||
- angularDirection == CurvedDirection.Angular.Clockwise,
- rowCoords!!,
- coords!!
- )
+ val dims =
+ RadialDimensions(
+ absoluteClockwise =
+ angularDirection == CurvedDirection.Angular.Normal ||
+ angularDirection == CurvedDirection.Angular.Clockwise,
+ rowCoords!!,
+ coords!!
+ )
checkSpy(dims, capturedInfo)
// It's at the outer side of the CurvedRow,
assertEquals(dims.rowRadius, dims.outerRadius, FLOAT_TOLERANCE)
- val actualAngle = if (anchorType == AnchorType.Center) {
- dims.middleAngle
- } else {
- if (anchorType == AnchorType.Start == clockwise) {
- dims.startAngle
+ val actualAngle =
+ if (anchorType == AnchorType.Center) {
+ dims.middleAngle
} else {
- dims.endAngle
+ if (anchorType == AnchorType.Start == clockwise) {
+ dims.startAngle
+ } else {
+ dims.endAngle
+ }
}
- }
checkAngle(anchor, actualAngle)
}
}
@@ -222,15 +219,11 @@
var rowCoords: LayoutCoordinates? = null
val coords = Array<LayoutCoordinates?>(3) { null }
rule.setContent {
- CurvedLayout(
- modifier = Modifier.onGloballyPositioned { rowCoords = it }
- ) {
+ CurvedLayout(modifier = Modifier.onGloballyPositioned { rowCoords = it }) {
repeat(3) { ix ->
curvedComposable {
Box(
- modifier = Modifier
- .size(30.dp)
- .onGloballyPositioned { coords[ix] = it }
+ modifier = Modifier.size(30.dp).onGloballyPositioned { coords[ix] = it }
)
}
}
@@ -238,13 +231,7 @@
}
rule.runOnIdle {
- val dims = coords.map {
- RadialDimensions(
- absoluteClockwise = true,
- rowCoords!!,
- it!!
- )
- }
+ val dims = coords.map { RadialDimensions(absoluteClockwise = true, rowCoords!!, it!!) }
dims.forEach {
// They are all at the outer side of the CurvedRow,
@@ -271,44 +258,30 @@
var bigSpy = CapturedInfo()
// We have a big box and a small box with the specified alignment
rule.setContent {
- CurvedLayout(
- modifier = Modifier.onGloballyPositioned { rowCoords = it }
- ) {
+ CurvedLayout(modifier = Modifier.onGloballyPositioned { rowCoords = it }) {
curvedComposable(
modifier = CurvedModifier.spy(smallSpy),
radialAlignment = radialAlignment
) {
Box(
- modifier = Modifier
- .size(30.dp)
- .onGloballyPositioned { smallBoxCoords = it }
+ modifier = Modifier.size(30.dp).onGloballyPositioned { smallBoxCoords = it }
)
}
curvedComposable(
modifier = CurvedModifier.spy(bigSpy),
) {
- Box(
- modifier = Modifier
- .size(45.dp)
- .onGloballyPositioned { bigBoxCoords = it }
- )
+ Box(modifier = Modifier.size(45.dp).onGloballyPositioned { bigBoxCoords = it })
}
}
}
rule.runOnIdle {
- val bigBoxDimensions = RadialDimensions(
- absoluteClockwise = true,
- rowCoords!!,
- bigBoxCoords!!
- )
+ val bigBoxDimensions =
+ RadialDimensions(absoluteClockwise = true, rowCoords!!, bigBoxCoords!!)
checkSpy(bigBoxDimensions, bigSpy)
- val smallBoxDimensions = RadialDimensions(
- absoluteClockwise = true,
- rowCoords!!,
- smallBoxCoords!!
- )
+ val smallBoxDimensions =
+ RadialDimensions(absoluteClockwise = true, rowCoords!!, smallBoxCoords!!)
checkSpy(smallBoxDimensions, smallSpy)
// There are one after another
@@ -360,9 +333,7 @@
}
}
- rule.runOnIdle {
- visible.value = targetVisibility
- }
+ rule.runOnIdle { visible.value = targetVisibility }
rule.waitForIdle()
if (targetVisibility) {
@@ -372,25 +343,19 @@
}
}
- @Test
- fun showing_child_works() = visibility_change_test_setup(true)
+ @Test fun showing_child_works() = visibility_change_test_setup(true)
- @Test
- fun hiding_child_works() = visibility_change_test_setup(false)
+ @Test fun hiding_child_works() = visibility_change_test_setup(false)
@Test
fun change_elements_on_side_effect_works() {
var num by mutableStateOf(0)
rule.setContent {
- SideEffect {
- num = 2
- }
+ SideEffect { num = 2 }
CurvedLayout(modifier = Modifier.fillMaxSize()) {
repeat(num) {
- curvedComposable {
- Box(modifier = Modifier.size(20.dp).testTag("Node$it"))
- }
+ curvedComposable { Box(modifier = Modifier.size(20.dp).testTag("Node$it")) }
}
}
}
diff --git a/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/CurvedPaddingTest.kt b/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/CurvedPaddingTest.kt
index 44e155e..a953b4e 100644
--- a/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/CurvedPaddingTest.kt
+++ b/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/CurvedPaddingTest.kt
@@ -25,18 +25,11 @@
class CurvedPaddingTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
@Test
fun padding_all_works() =
- check_padding_result(
- 3.dp,
- 3.dp,
- 3.dp,
- 3.dp,
- CurvedModifier.padding(3.dp)
- )
+ check_padding_result(3.dp, 3.dp, 3.dp, 3.dp, CurvedModifier.padding(3.dp))
@Test
fun padding_angular_and_radial_works() =
@@ -55,12 +48,7 @@
innerPadding = 4.dp,
beforePadding = 5.dp,
afterPadding = 6.dp,
- CurvedModifier.padding(
- outer = 3.dp,
- inner = 4.dp,
- before = 5.dp,
- after = 6.dp
- )
+ CurvedModifier.padding(outer = 3.dp, inner = 4.dp, before = 5.dp, after = 6.dp)
)
@Test
@@ -70,9 +58,7 @@
14.dp,
18.dp,
25.dp,
- CurvedModifier
- .padding(3.dp, 4.dp, 5.dp, 6.dp)
- .padding(8.dp, 10.dp, 13.dp, 19.dp)
+ CurvedModifier.padding(3.dp, 4.dp, 5.dp, 6.dp).padding(8.dp, 10.dp, 13.dp, 19.dp)
)
private fun check_padding_result(
@@ -104,15 +90,16 @@
componentThicknessPx = componentThickness.toPx()
}
CurvedLayout {
- curvedRow(modifier = CurvedModifier
- .spy(paddedCapturedInfo)
- .then(modifier)
- .spy(componentCapturedInfo)
- .size(
- sweepDegrees = componentSweepDegrees,
- thickness = componentThickness
- )
- ) { }
+ curvedRow(
+ modifier =
+ CurvedModifier.spy(paddedCapturedInfo)
+ .then(modifier)
+ .spy(componentCapturedInfo)
+ .size(
+ sweepDegrees = componentSweepDegrees,
+ thickness = componentThickness
+ )
+ ) {}
}
}
diff --git a/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/CurvedScreenshotTest.kt b/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/CurvedScreenshotTest.kt
index 78d361f..76327cf 100644
--- a/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/CurvedScreenshotTest.kt
+++ b/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/CurvedScreenshotTest.kt
@@ -54,14 +54,11 @@
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
class CurvedScreenshotTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
- @get:Rule
- val screenshotRule = AndroidXScreenshotTestRule(SCREENSHOT_GOLDEN_PATH)
+ @get:Rule val screenshotRule = AndroidXScreenshotTestRule(SCREENSHOT_GOLDEN_PATH)
- @get:Rule
- val testName = TestName()
+ @get:Rule val testName = TestName()
@Test
fun curved_row_and_column() = verify_screenshot {
@@ -87,9 +84,8 @@
val size = 0.15f
val rgb = listOf(Color.Red, Color.Green, Color.Blue)
curvedColumn(
- CurvedModifier.size(sweepDegrees = 20f, thickness = 30.dp)
- .radialGradientBackground(rgb)
- ) { }
+ CurvedModifier.size(sweepDegrees = 20f, thickness = 30.dp).radialGradientBackground(rgb)
+ ) {}
curvedColumn(
CurvedModifier.size(sweepDegrees = 20f, thickness = 30.dp)
.radialGradientBackground(
@@ -97,11 +93,11 @@
0.5f to Color.Blue,
(0.5f + size) to Color.Red,
)
- ) { }
+ ) {}
curvedColumn(
CurvedModifier.size(sweepDegrees = 20f, thickness = 30.dp)
.angularGradientBackground(rgb)
- ) { }
+ ) {}
curvedColumn(
CurvedModifier.size(sweepDegrees = 20f, thickness = 30.dp)
.angularGradientBackground(
@@ -109,16 +105,19 @@
0.5f to Color.Blue,
(0.5f + size) to Color.Red,
)
- ) { }
+ ) {}
}
@Test
fun curved_padding() = verify_screenshot {
basicCurvedText(
"Text",
- CurvedModifier.background(Color.Red).padding(3.dp)
- .background(Color.Green).padding(angular = 5.dp)
- .background(Color.Blue).padding(radial = 4.dp)
+ CurvedModifier.background(Color.Red)
+ .padding(3.dp)
+ .background(Color.Green)
+ .padding(angular = 5.dp)
+ .background(Color.Blue)
+ .padding(radial = 4.dp)
)
}
@@ -131,63 +130,58 @@
@Suppress("DEPRECATION")
BasicText(
text = "Text",
- style = TextStyle(
- platformStyle = PlatformTextStyle(includeFontPadding = true)
- )
+ style =
+ TextStyle(platformStyle = PlatformTextStyle(includeFontPadding = true))
)
Box(Modifier.size(15.dp).background(Color.Red))
}
}
- curvedComposable {
- Box(Modifier.size(15.dp).background(Color.Blue))
- }
+ curvedComposable { Box(Modifier.size(15.dp).background(Color.Blue)) }
}
}
@Test
fun curved_alignment() = verify_screenshot {
listOf(
- CurvedAlignment.Angular.Start,
- CurvedAlignment.Angular.Center,
- CurvedAlignment.Angular.End
- ).forEachIndexed { ix, align ->
- curvedColumn(
- CurvedModifier.angularSize(45f)
- .angularGradientBackground(listOf(Color.Red, Color.Green)),
- angularAlignment = align
- ) {
- curvedComposable { Box(Modifier.size(15.dp).background(Color.Blue)) }
- basicCurvedText(listOf("Start", "Center", "End")[ix])
- }
- }
- curvedColumn(
- CurvedModifier.angularSize(45f)
- ) {
- listOf(
- CurvedAlignment.Radial.Inner,
- CurvedAlignment.Radial.Center,
- CurvedAlignment.Radial.Outer,
- ).forEachIndexed { ix, align ->
- curvedRow(
- CurvedModifier.size(45f, 20.dp)
- .radialGradientBackground(listOf(Color.Red, Color.Green)),
- radialAlignment = align
+ CurvedAlignment.Angular.Start,
+ CurvedAlignment.Angular.Center,
+ CurvedAlignment.Angular.End
+ )
+ .forEachIndexed { ix, align ->
+ curvedColumn(
+ CurvedModifier.angularSize(45f)
+ .angularGradientBackground(listOf(Color.Red, Color.Green)),
+ angularAlignment = align
) {
- curvedComposable { Box(Modifier.size(10.dp).background(Color.Blue)) }
- basicCurvedText(
- listOf("Inner", "Center", "Outer")[ix],
- style = CurvedTextStyle(fontSize = 10.sp)
- )
+ curvedComposable { Box(Modifier.size(15.dp).background(Color.Blue)) }
+ basicCurvedText(listOf("Start", "Center", "End")[ix])
}
}
+ curvedColumn(CurvedModifier.angularSize(45f)) {
+ listOf(
+ CurvedAlignment.Radial.Inner,
+ CurvedAlignment.Radial.Center,
+ CurvedAlignment.Radial.Outer,
+ )
+ .forEachIndexed { ix, align ->
+ curvedRow(
+ CurvedModifier.size(45f, 20.dp)
+ .radialGradientBackground(listOf(Color.Red, Color.Green)),
+ radialAlignment = align
+ ) {
+ curvedComposable { Box(Modifier.size(10.dp).background(Color.Blue)) }
+ basicCurvedText(
+ listOf("Inner", "Center", "Outer")[ix],
+ style = CurvedTextStyle(fontSize = 10.sp)
+ )
+ }
+ }
}
}
- @Test
- public fun layout_direction_rtl() = layout_direction(LayoutDirection.Rtl)
+ @Test public fun layout_direction_rtl() = layout_direction(LayoutDirection.Rtl)
- @Test
- public fun layout_direction_ltr() = layout_direction(LayoutDirection.Ltr)
+ @Test public fun layout_direction_ltr() = layout_direction(LayoutDirection.Ltr)
private fun layout_direction(layoutDirection: LayoutDirection) = verify_composable_screenshot {
CompositionLocalProvider(LocalLayoutDirection provides layoutDirection) {
@@ -241,7 +235,8 @@
anchor = 270f
) {
curvedRow(CurvedModifier.background(Color.Green)) {
- basicCurvedText("Top Text Goes Here",
+ basicCurvedText(
+ "Top Text Goes Here",
CurvedModifier.angularSize(45f),
overflow = TextOverflow.Ellipsis,
)
@@ -253,9 +248,11 @@
anchor = 90f
) {
curvedRow(CurvedModifier.background(Color.Green)) {
- basicCurvedText("Bottom Text Goes Here",
+ basicCurvedText(
+ "Bottom Text Goes Here",
CurvedModifier.angularSize(45f),
- overflow = TextOverflow.Ellipsis)
+ overflow = TextOverflow.Ellipsis
+ )
}
}
}
@@ -279,12 +276,11 @@
}
private fun verify_screenshot(contentBuilder: CurvedScope.() -> Unit) =
- verify_composable_screenshot(content = {
- CurvedLayout(
- modifier = Modifier.fillMaxSize(),
- contentBuilder = contentBuilder
- )
- })
+ verify_composable_screenshot(
+ content = {
+ CurvedLayout(modifier = Modifier.fillMaxSize(), contentBuilder = contentBuilder)
+ }
+ )
private fun verify_composable_screenshot(content: @Composable BoxScope.() -> Unit) {
rule.setContent {
@@ -294,7 +290,8 @@
)
}
- rule.onNodeWithTag(TEST_TAG)
+ rule
+ .onNodeWithTag(TEST_TAG)
.captureToImage()
.assertAgainstGolden(screenshotRule, testName.methodName)
}
diff --git a/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/CurvedSizeTest.kt b/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/CurvedSizeTest.kt
index 5c7f35a..bb23d51 100644
--- a/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/CurvedSizeTest.kt
+++ b/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/CurvedSizeTest.kt
@@ -24,27 +24,20 @@
import org.junit.Test
class CurvedSizeTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
- @Test
- fun proper_nested_sizes_work() = nested_size_test(60f, 30.dp, 30f, 20.dp)
+ @Test fun proper_nested_sizes_work() = nested_size_test(60f, 30.dp, 30f, 20.dp)
- @Test
- fun inverted_nested_sizes_work() = nested_size_test(30f, 20.dp, 60f, 30.dp)
+ @Test fun inverted_nested_sizes_work() = nested_size_test(30f, 20.dp, 60f, 30.dp)
- @Test
- fun equal_nested_sizes_work() = nested_size_test(30f, 20.dp, 30f, 20.dp)
+ @Test fun equal_nested_sizes_work() = nested_size_test(30f, 20.dp, 30f, 20.dp)
// TODO: Tests for both .angularSize and .radialSize calls should be added b/275532663
- @Test
- fun proper_angular_nested_sizes_in_dp_work() = nested_angular_size_test(60.dp, 30.dp)
+ @Test fun proper_angular_nested_sizes_in_dp_work() = nested_angular_size_test(60.dp, 30.dp)
- @Test
- fun inverted_angular_nested_sizes_in_dp_work() = nested_angular_size_test(30.dp, 60.dp)
+ @Test fun inverted_angular_nested_sizes_in_dp_work() = nested_angular_size_test(30.dp, 60.dp)
- @Test
- fun equal_angular_nested_sizes_in_dp_work() = nested_angular_size_test(30.dp, 30.dp)
+ @Test fun equal_angular_nested_sizes_in_dp_work() = nested_angular_size_test(30.dp, 30.dp)
private fun nested_size_test(
angle: Float,
@@ -63,12 +56,12 @@
}
CurvedLayout {
curvedRow(
- modifier = CurvedModifier
- .spy(capturedInfo)
- .size(angle, thickness)
- .spy(innerCapturedInfo)
- .size(innerAngle, innerThickness)
- ) { }
+ modifier =
+ CurvedModifier.spy(capturedInfo)
+ .size(angle, thickness)
+ .spy(innerCapturedInfo)
+ .size(innerAngle, innerThickness)
+ ) {}
}
}
@@ -95,12 +88,12 @@
}
CurvedLayout {
curvedRow(
- modifier = CurvedModifier
- .spy(capturedInfo)
- .angularSizeDp(angularSizeInDp)
- .spy(innerCapturedInfo)
- .angularSizeDp(innerAngularSizeInDp)
- ) { }
+ modifier =
+ CurvedModifier.spy(capturedInfo)
+ .angularSizeDp(angularSizeInDp)
+ .spy(innerCapturedInfo)
+ .angularSizeDp(innerAngularSizeInDp)
+ ) {}
}
}
diff --git a/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/CurvedTestTagTest.kt b/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/CurvedTestTagTest.kt
index de30899..a41b1a6 100644
--- a/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/CurvedTestTagTest.kt
+++ b/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/CurvedTestTagTest.kt
@@ -23,19 +23,13 @@
class CurvedTestTagTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
@Test
fun curvedBox_supports_testTag() {
rule.setContent {
CurvedLayout {
- curvedBox(
- modifier = CurvedModifier
- .testTag(TEST_TAG)
- ) {
- curvedComposable {}
- }
+ curvedBox(modifier = CurvedModifier.testTag(TEST_TAG)) { curvedComposable {} }
}
}
@@ -47,12 +41,7 @@
fun curvedRow_supports_testTag() {
rule.setContent {
CurvedLayout {
- curvedRow(
- modifier = CurvedModifier
- .testTag(TEST_TAG)
- ) {
- curvedComposable {}
- }
+ curvedRow(modifier = CurvedModifier.testTag(TEST_TAG)) { curvedComposable {} }
}
}
@@ -64,12 +53,7 @@
fun curvedColumn_supports_testTag() {
rule.setContent {
CurvedLayout {
- curvedColumn(
- modifier = CurvedModifier
- .testTag(TEST_TAG)
- ) {
- curvedComposable {}
- }
+ curvedColumn(modifier = CurvedModifier.testTag(TEST_TAG)) { curvedComposable {} }
}
}
@@ -80,12 +64,7 @@
@Test
fun curvedComposable_supports_testTag() {
rule.setContent {
- CurvedLayout {
- curvedComposable(
- modifier = CurvedModifier
- .testTag(TEST_TAG)
- ) {}
- }
+ CurvedLayout { curvedComposable(modifier = CurvedModifier.testTag(TEST_TAG)) {} }
}
rule.waitForIdle()
diff --git a/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/CurvedWeightTest.kt b/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/CurvedWeightTest.kt
index a7a1ac2..7996d0e 100644
--- a/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/CurvedWeightTest.kt
+++ b/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/CurvedWeightTest.kt
@@ -21,8 +21,7 @@
import org.junit.Test
class CurvedWeightTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
@Test
fun base_weight_size_test() {
@@ -32,18 +31,13 @@
// The parent row takes 90 degrees, one child takes 30 degrees, so there is 60
// degrees left for the weighted element.
curvedRow(modifier = CurvedModifier.angularSize(90f)) {
- curvedRow(modifier = CurvedModifier
- .weight(1f)
- .spy(capturedInfo)
- ) { }
- curvedRow(modifier = CurvedModifier.angularSize(30f)) { }
+ curvedRow(modifier = CurvedModifier.weight(1f).spy(capturedInfo)) {}
+ curvedRow(modifier = CurvedModifier.angularSize(30f)) {}
}
}
}
- rule.runOnIdle {
- capturedInfo.checkParentDimensions(expectedAngleDegrees = 60f)
- }
+ rule.runOnIdle { capturedInfo.checkParentDimensions(expectedAngleDegrees = 60f) }
}
@Test
@@ -56,15 +50,9 @@
// degrees left to distribute between the 2 elements, since the weights are 1 and 2,
// they get 20 and 40 degrees respectively
curvedRow(modifier = CurvedModifier.angularSize(90f)) {
- curvedRow(modifier = CurvedModifier
- .weight(1f)
- .spy(capturedInfo1)
- ) { }
- curvedRow(modifier = CurvedModifier.angularSize(30f)) { }
- curvedRow(modifier = CurvedModifier
- .weight(2f)
- .spy(capturedInfo2)
- ) { }
+ curvedRow(modifier = CurvedModifier.weight(1f).spy(capturedInfo1)) {}
+ curvedRow(modifier = CurvedModifier.angularSize(30f)) {}
+ curvedRow(modifier = CurvedModifier.weight(2f).spy(capturedInfo2)) {}
}
}
}
@@ -85,18 +73,13 @@
// so the row will take 30 degrees.
// There is no space left in the row, so the weighted child will take 0 degrees.
curvedRow {
- curvedRow(modifier = CurvedModifier
- .weight(1f)
- .spy(capturedInfo)
- ) { }
- curvedRow(modifier = CurvedModifier.angularSize(30f)) { }
+ curvedRow(modifier = CurvedModifier.weight(1f).spy(capturedInfo)) {}
+ curvedRow(modifier = CurvedModifier.angularSize(30f)) {}
}
}
}
- rule.runOnIdle {
- capturedInfo.checkParentDimensions(expectedAngleDegrees = 0f)
- }
+ rule.runOnIdle { capturedInfo.checkParentDimensions(expectedAngleDegrees = 0f) }
}
@Test
@@ -109,18 +92,14 @@
// so the row will take 40 degrees.
// There is 10 degrees left in the row, so the weighted child will take 10 degrees.
curvedRow {
- curvedRow(modifier = CurvedModifier
- .weight(1f)
- .spy(capturedInfo)
- .angularSize(10f)
- ) { }
- curvedRow(modifier = CurvedModifier.angularSize(30f)) { }
+ curvedRow(
+ modifier = CurvedModifier.weight(1f).spy(capturedInfo).angularSize(10f)
+ ) {}
+ curvedRow(modifier = CurvedModifier.angularSize(30f)) {}
}
}
}
- rule.runOnIdle {
- capturedInfo.checkParentDimensions(expectedAngleDegrees = 10f)
- }
+ rule.runOnIdle { capturedInfo.checkParentDimensions(expectedAngleDegrees = 10f) }
}
}
diff --git a/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/ExpandableTest.kt b/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/ExpandableTest.kt
index 773663d..07719bc 100644
--- a/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/ExpandableTest.kt
+++ b/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/ExpandableTest.kt
@@ -47,8 +47,7 @@
import org.junit.Test
class ExpandableTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
private val restorationTester = StateRestorationTester(rule)
@@ -57,9 +56,7 @@
fun initially_collapsed() =
verifyExpandable(
setupState = { rememberExpandableState(initiallyExpanded = false) },
- bitmapAssert = {
- assertDoesContainColor(COLLAPSED_COLOR)
- }
+ bitmapAssert = { assertDoesContainColor(COLLAPSED_COLOR) }
)
@RequiresApi(Build.VERSION_CODES.O)
@@ -67,9 +64,7 @@
fun initially_expanded() =
verifyExpandable(
setupState = { rememberExpandableState(initiallyExpanded = true) },
- bitmapAssert = {
- assertDoesContainColor(EXPANDED_COLOR)
- }
+ bitmapAssert = { assertDoesContainColor(EXPANDED_COLOR) }
)
@RequiresApi(Build.VERSION_CODES.O)
@@ -77,9 +72,7 @@
fun expand() =
verifyExpandable(
setupState = { rememberExpandableState(initiallyExpanded = false) },
- bitmapAssert = {
- assertDoesContainColor(EXPANDED_COLOR)
- }
+ bitmapAssert = { assertDoesContainColor(EXPANDED_COLOR) }
) { state ->
state.expanded = true
waitForIdle()
@@ -90,21 +83,15 @@
fun collapse() =
verifyExpandable(
setupState = { rememberExpandableState(initiallyExpanded = true) },
- bitmapAssert = {
- assertDoesContainColor(COLLAPSED_COLOR)
- }
+ bitmapAssert = { assertDoesContainColor(COLLAPSED_COLOR) }
) { state ->
state.expanded = false
waitForIdle()
}
- @RequiresApi(Build.VERSION_CODES.O)
- @Test
- fun collapsed_click() = verifyClick(false)
+ @RequiresApi(Build.VERSION_CODES.O) @Test fun collapsed_click() = verifyClick(false)
- @RequiresApi(Build.VERSION_CODES.O)
- @Test
- fun expanded_click() = verifyClick(true)
+ @RequiresApi(Build.VERSION_CODES.O) @Test fun expanded_click() = verifyClick(true)
@Test
fun restoreState_after_recomposition() {
@@ -129,13 +116,9 @@
val clicked = mutableListOf<Boolean>()
verifyExpandable(
setupState = { rememberExpandableState(initiallyExpanded = initiallyExpanded) },
- bitmapAssert = {
- assertEquals(listOf(initiallyExpanded), clicked)
- },
+ bitmapAssert = { assertEquals(listOf(initiallyExpanded), clicked) },
expandableContent = { expanded ->
- Box(modifier = Modifier.fillMaxSize().clickable {
- clicked.add(expanded)
- })
+ Box(modifier = Modifier.fillMaxSize().clickable { clicked.add(expanded) })
}
) { _ ->
onNodeWithTag(TEST_TAG).performClick()
@@ -147,35 +130,29 @@
private fun verifyExpandable(
setupState: @Composable () -> ExpandableState,
bitmapAssert: ImageBitmap.() -> Unit,
- expandableContent: @Composable (Boolean) -> Unit = { },
- act: ComposeTestRule.(ExpandableState) -> Unit = { }
+ expandableContent: @Composable (Boolean) -> Unit = {},
+ act: ComposeTestRule.(ExpandableState) -> Unit = {}
) {
// Arrange - set up the content for the test including expandable content
var slcState: ScalingLazyListState? = null
var state: ExpandableState? = null
rule.setContent {
state = setupState()
- Box(
- Modifier
- .testTag(TEST_TAG)
- .size(100.dp)) {
+ Box(Modifier.testTag(TEST_TAG).size(100.dp)) {
ScalingLazyColumn(
state = rememberScalingLazyListState().also { slcState = it },
// We can only test expandableItem inside a ScalingLazyColumn, but we can make
// it behave mostly as it wasn't there.
- scalingParams = ScalingLazyColumnDefaults
- .scalingParams(edgeScale = 1f, edgeAlpha = 1f),
+ scalingParams =
+ ScalingLazyColumnDefaults.scalingParams(edgeScale = 1f, edgeAlpha = 1f),
autoCentering = null,
verticalArrangement = Arrangement.spacedBy(space = 0.dp),
) {
expandableItem(state!!) { expanded ->
Box(
- Modifier
- .fillMaxWidth()
+ Modifier.fillMaxWidth()
.height(100.dp)
- .background(
- if (expanded) EXPANDED_COLOR else COLLAPSED_COLOR
- )
+ .background(if (expanded) EXPANDED_COLOR else COLLAPSED_COLOR)
) {
expandableContent(expanded)
}
@@ -186,14 +163,10 @@
rule.waitUntil { slcState?.initialized?.value ?: false }
// Act - exercise the expandable if required for the test.
- with(rule) {
- act(state!!)
- }
+ with(rule) { act(state!!) }
// Assert - verify the object under test worked correctly
- rule.onNodeWithTag(TEST_TAG)
- .captureToImage()
- .apply { bitmapAssert() }
+ rule.onNodeWithTag(TEST_TAG).captureToImage().apply { bitmapAssert() }
}
private val EXPANDED_COLOR = Color.Red
diff --git a/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/FoundationTest.kt b/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/FoundationTest.kt
index 33312b2..1bf61ea 100644
--- a/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/FoundationTest.kt
+++ b/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/FoundationTest.kt
@@ -42,12 +42,10 @@
/**
* Checks whether [expectedColor] does not exist in current [ImageBitmap]
*
-fun ImageBitmap.assertDoesNotContainColor(expectedColor: Color) {
- val histogram = histogram()
- if (histogram.containsKey(expectedColor)) {
- throw AssertionError("Expected color $expectedColor exists in current bitmap")
- }
-}*/
+ * fun ImageBitmap.assertDoesNotContainColor(expectedColor: Color) { val histogram = histogram() if
+ * (histogram.containsKey(expectedColor)) { throw AssertionError("Expected color $expectedColor
+ * exists in current bitmap") } }
+ */
/**
* Checks whether [expectedColor] exist in current [ImageBitmap], covering at least the given ratio
@@ -57,8 +55,9 @@
val histogram = histogram()
val ratio = (histogram.getOrDefault(expectedColor, 0L)).toFloat() / (width * height)
if (ratio < expectedRatio) {
- throw AssertionError("Expected color $expectedColor with ratio $expectedRatio." +
- " Actual ratio = $ratio")
+ throw AssertionError(
+ "Expected color $expectedColor with ratio $expectedRatio." + " Actual ratio = $ratio"
+ )
}
}
@@ -83,22 +82,14 @@
*
* @param tag The tag to apply to the curved container.
*/
-public fun CurvedModifier.testTag(
- tag: String
-) = this.then { child ->
- TestTagWrapper(child, tag)
-}
+public fun CurvedModifier.testTag(tag: String) = this.then { child -> TestTagWrapper(child, tag) }
-private class TestTagWrapper(
- val child: CurvedChild,
- val tag: String
-) : BaseCurvedChildWrapper(child) {
+private class TestTagWrapper(val child: CurvedChild, val tag: String) :
+ BaseCurvedChildWrapper(child) {
@Composable
override fun SubComposition() {
- Box(modifier = Modifier.testTag(tag)) {
- super.SubComposition()
- }
+ Box(modifier = Modifier.testTag(tag)) { super.SubComposition() }
}
}
@@ -133,6 +124,7 @@
val outerRadius: Float
val centerRadius
get() = (innerRadius + outerRadius) / 2
+
val sweep: Float
val startAngle: Float
val middleAngle: Float
@@ -143,9 +135,7 @@
// Find the radius and center of the CurvedRow, all radial coordinates are relative to this
// center
rowRadius = min(rowCoords.size.width, rowCoords.size.height) / 2f
- rowCenter = rowCoords.localToRoot(
- Offset(rowRadius, rowRadius)
- )
+ rowCenter = rowCoords.localToRoot(Offset(rowRadius, rowRadius))
// Compute the radial coordinates (relative to the center of the CurvedRow) of the found
// corners of the component's box and its center
@@ -179,19 +169,17 @@
}
middleAngle = center.angle.toDegrees()
- sweep = if (endAngle > startAngle) {
- endAngle - startAngle
- } else {
- endAngle + 360f - startAngle
- }
+ sweep =
+ if (endAngle > startAngle) {
+ endAngle - startAngle
+ } else {
+ endAngle + 360f - startAngle
+ }
thickness = outerRadius - innerRadius
// All sweep angles are well between 0 and 90
- assertTrue(
- (FLOAT_TOLERANCE..90f - FLOAT_TOLERANCE).contains(sweep),
- "sweep = $sweep"
- )
+ assertTrue((FLOAT_TOLERANCE..90f - FLOAT_TOLERANCE).contains(sweep), "sweep = $sweep")
// The outerRadius is greater than the innerRadius
assertTrue(
@@ -202,14 +190,15 @@
// TODO: When we finalize CurvedLayoutInfo's API, eliminate the RadialDimensions class and
// inline this function to directly convert between LayoutCoordinates and CurvedLayoutInfo.
- fun asCurvedLayoutInfo() = CurvedLayoutInfo(
- sweepRadians = sweep.toRadians(),
- outerRadius = outerRadius,
- thickness = outerRadius - innerRadius,
- centerOffset = rowCenter,
- measureRadius = (outerRadius + innerRadius) / 2,
- startAngleRadians = startAngle.toRadians()
- )
+ fun asCurvedLayoutInfo() =
+ CurvedLayoutInfo(
+ sweepRadians = sweep.toRadians(),
+ outerRadius = outerRadius,
+ thickness = outerRadius - innerRadius,
+ centerOffset = rowCenter,
+ measureRadius = (outerRadius + innerRadius) / 2,
+ startAngleRadians = startAngle.toRadians()
+ )
fun toRadialCoordinates(coords: LayoutCoordinates, x: Float, y: Float): RadialPoint {
val vector = coords.localToRoot(Offset(x, y)) - rowCenter
diff --git a/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/HierarchicalFocusCoordinatorTest.kt b/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/HierarchicalFocusCoordinatorTest.kt
index 3d55748..d9285a1 100644
--- a/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/HierarchicalFocusCoordinatorTest.kt
+++ b/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/HierarchicalFocusCoordinatorTest.kt
@@ -35,15 +35,13 @@
@OptIn(ExperimentalWearFoundationApi::class)
class HierarchicalFocusCoordinatorTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
- @Test
- fun basic_OnFocusChange_works_1_of_3() = basic_OnFocusChange_works(0, 3)
- @Test
- fun basic_OnFocusChange_works_2_of_5() = basic_OnFocusChange_works(1, 5)
- @Test
- fun basic_OnFocusChange_works_4_of_4() = basic_OnFocusChange_works(3, 4)
+ @Test fun basic_OnFocusChange_works_1_of_3() = basic_OnFocusChange_works(0, 3)
+
+ @Test fun basic_OnFocusChange_works_2_of_5() = basic_OnFocusChange_works(1, 5)
+
+ @Test fun basic_OnFocusChange_works_4_of_4() = basic_OnFocusChange_works(3, 4)
private fun basic_OnFocusChange_works(selected: Int, numItems: Int) {
var focused = BooleanArray(numItems)
@@ -56,19 +54,14 @@
}
}
- rule.runOnIdle {
- checkFocus(selected, focused)
- }
+ rule.runOnIdle { checkFocus(selected, focused) }
}
- @Test
- fun basic_selection_works_1_of_3() = basic_selection_works(0, 3)
+ @Test fun basic_selection_works_1_of_3() = basic_selection_works(0, 3)
- @Test
- fun basic_selection_works_2_of_5() = basic_selection_works(1, 5)
+ @Test fun basic_selection_works_2_of_5() = basic_selection_works(1, 5)
- @Test
- fun basic_selection_works_4_of_4() = basic_selection_works(3, 4)
+ @Test fun basic_selection_works_4_of_4() = basic_selection_works(3, 4)
private fun basic_selection_works(selected: Int, numItems: Int) {
var focused = BooleanArray(numItems)
@@ -83,33 +76,29 @@
}
}
- rule.runOnIdle {
- checkFocus(selected, focused)
+ rule.runOnIdle { checkFocus(selected, focused) }
+ }
+
+ @Test fun nested_selection_initial() = nested_selection_works(0) { _, _ -> }
+
+ @Test fun nested_selection_switch_top() = nested_selection_works(3) { top, _ -> top.value = 1 }
+
+ @Test
+ fun nested_selection_switch_bottom() =
+ nested_selection_works(1) { _, bottom ->
+ bottom[0].value = 1
+ bottom[1].value = 2
+ bottom[2].value = 0
}
- }
@Test
- fun nested_selection_initial() = nested_selection_works(0) { _, _ -> }
-
- @Test
- fun nested_selection_switch_top() = nested_selection_works(3) { top, _ ->
- top.value = 1
- }
-
- @Test
- fun nested_selection_switch_bottom() = nested_selection_works(1) { _, bottom ->
- bottom[0].value = 1
- bottom[1].value = 2
- bottom[2].value = 0
- }
-
- @Test
- fun nested_selection_switch_both() = nested_selection_works(5) { top, bottom ->
- bottom[0].value = 1
- bottom[1].value = 2
- bottom[2].value = 0
- top.value = 1
- }
+ fun nested_selection_switch_both() =
+ nested_selection_works(5) { top, bottom ->
+ bottom[0].value = 1
+ bottom[1].value = 2
+ bottom[2].value = 0
+ top.value = 1
+ }
/*
* We have 3 top FocusControl groups, each having 3 bottom FocusControl groups, and the
@@ -144,9 +133,9 @@
HierarchicalFocusCoordinator({ topIx == topSelected.value }) {
Box {
repeat(numItems) { bottomIx ->
- HierarchicalFocusCoordinator(
- { bottomIx == bottomSelected[topIx].value }
- ) {
+ HierarchicalFocusCoordinator({
+ bottomIx == bottomSelected[topIx].value
+ }) {
FocusableTestItem { focused[topIx * numItems + bottomIx] = it }
}
}
@@ -156,13 +145,9 @@
}
}
- rule.runOnIdle {
- act(topSelected, bottomSelected)
- }
+ rule.runOnIdle { act(topSelected, bottomSelected) }
- rule.runOnIdle {
- checkFocus(expectedSelected, focused)
- }
+ rule.runOnIdle { checkFocus(expectedSelected, focused) }
}
@Test
@@ -187,10 +172,9 @@
selected.value = 1
}
- rule.runOnIdle {
- Assert.assertFalse(focused)
- }
+ rule.runOnIdle { Assert.assertFalse(focused) }
}
+
@Test
public fun add_focusable_works() {
var show by mutableStateOf(false)
@@ -205,13 +189,9 @@
}
}
- rule.runOnIdle {
- show = true
- }
+ rule.runOnIdle { show = true }
- rule.runOnIdle {
- Assert.assertTrue(focused)
- }
+ rule.runOnIdle { Assert.assertTrue(focused) }
}
@Test
@@ -219,17 +199,13 @@
var focused = false
rule.setContent {
Box {
- HierarchicalFocusCoordinator(
- requiresFocus = { false }
- ) {
+ HierarchicalFocusCoordinator(requiresFocus = { false }) {
FocusableTestItem { focused = it }
}
}
}
- rule.runOnIdle {
- Assert.assertFalse(focused)
- }
+ rule.runOnIdle { Assert.assertFalse(focused) }
}
@Test
@@ -241,34 +217,32 @@
HierarchicalFocusCoordinator(
// We switch between a lambda that always returns false and one that always
// return true given the state of lambdaUpdated.
- requiresFocus = if (lambdaUpdated) {
- { true }
- } else {
- { false }
- }
+ requiresFocus =
+ if (lambdaUpdated) {
+ { true }
+ } else {
+ { false }
+ }
) {
FocusableTestItem { focused = it }
}
}
}
- rule.runOnIdle {
- lambdaUpdated = true
- }
+ rule.runOnIdle { lambdaUpdated = true }
- rule.runOnIdle {
- Assert.assertTrue(focused)
- }
+ rule.runOnIdle { Assert.assertTrue(focused) }
}
+
@Composable
private fun FocusableTestItem(onFocusChanged: (Boolean) -> Unit) {
val focusRequester = rememberActiveFocusRequester()
Box(
- Modifier
- .size(10.dp) // View.requestFocus() will not take focus if the view has no size.
+ Modifier.size(10.dp) // View.requestFocus() will not take focus if the view has no size.
.focusRequester(focusRequester)
.onFocusChanged { onFocusChanged(it.isFocused) }
- .focusable())
+ .focusable()
+ )
}
// Ensure that the expected element, and only it, is focused.
diff --git a/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/SpyModifier.kt b/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/SpyModifier.kt
index a8c6b93..b97e74e 100644
--- a/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/SpyModifier.kt
+++ b/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/SpyModifier.kt
@@ -23,11 +23,10 @@
import org.junit.Assert
/**
- * Class used to capture information regarding measure/layout.
- * This is used through CurvedModifier.spy, and captures information on that point in the modifier
- * chain.
- * This is also the single point of access to the internals of CurvedLayout, so tests are easier to
- * refactor if we change something there.
+ * Class used to capture information regarding measure/layout. This is used through
+ * CurvedModifier.spy, and captures information on that point in the modifier chain. This is also
+ * the single point of access to the internals of CurvedLayout, so tests are easier to refactor if
+ * we change something there.
*/
internal data class CapturedInfo(
// Counters
@@ -68,11 +67,7 @@
)
}
if (expectedThicknessPx != null) {
- Assert.assertEquals(
- expectedThicknessPx,
- lastLayoutInfo!!.thickness,
- FINE_FLOAT_TOLERANCE
- )
+ Assert.assertEquals(expectedThicknessPx, lastLayoutInfo!!.thickness, FINE_FLOAT_TOLERANCE)
}
}
@@ -100,11 +95,7 @@
)
}
if (expectedThicknessPx != null) {
- Assert.assertEquals(
- expectedThicknessPx,
- parentThickness,
- FINE_FLOAT_TOLERANCE
- )
+ Assert.assertEquals(expectedThicknessPx, parentThickness, FINE_FLOAT_TOLERANCE)
}
}
@@ -184,22 +175,20 @@
): Float {
capturedInfo.parentStartAngleRadians = parentStartAngleRadians
capturedInfo.parentSweepRadians = parentSweepRadians
- return wrapped.angularPosition(
- parentStartAngleRadians,
- parentSweepRadians,
- centerOffset
- )
+ return wrapped.angularPosition(parentStartAngleRadians, parentSweepRadians, centerOffset)
}
- override fun (Placeable.PlacementScope).placeIfNeeded() = with(wrapped) {
- capturedInfo.lastLayoutInfo = layoutInfo
- capturedInfo.layoutsCount++
- placeIfNeeded()
- }
+ override fun (Placeable.PlacementScope).placeIfNeeded() =
+ with(wrapped) {
+ capturedInfo.lastLayoutInfo = layoutInfo
+ capturedInfo.layoutsCount++
+ placeIfNeeded()
+ }
- override fun DrawScope.draw() = with(wrapped) {
- capturedInfo.lastLayoutInfo = layoutInfo
- capturedInfo.drawCount++
- draw()
- }
+ override fun DrawScope.draw() =
+ with(wrapped) {
+ capturedInfo.lastLayoutInfo = layoutInfo
+ capturedInfo.drawCount++
+ draw()
+ }
}
diff --git a/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/SwipeToRevealTest.kt b/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/SwipeToRevealTest.kt
index 05186381..340ddc8 100644
--- a/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/SwipeToRevealTest.kt
+++ b/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/SwipeToRevealTest.kt
@@ -45,16 +45,11 @@
@OptIn(ExperimentalWearFoundationApi::class)
class SwipeToRevealTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
@Test
fun supports_testTag() {
- rule.setContent {
- swipeToRevealWithDefaults(
- modifier = Modifier.testTag(TEST_TAG)
- )
- }
+ rule.setContent { swipeToRevealWithDefaults(modifier = Modifier.testTag(TEST_TAG)) }
rule.onNodeWithTag(TEST_TAG).assertExists()
}
@@ -115,30 +110,19 @@
@Test
fun noSwipe_onFullSwipeRight() {
- verifyGesture(
- revealValue = RevealValue.Covered,
- gesture = { swipeRight() }
- )
+ verifyGesture(revealValue = RevealValue.Covered, gesture = { swipeRight() })
}
@Test
fun stateToSwiped_onFullSwipeLeft() {
- verifyGesture(
- revealValue = RevealValue.Revealed,
- gesture = { swipeLeft() }
- )
+ verifyGesture(revealValue = RevealValue.Revealed, gesture = { swipeLeft() })
}
@Test
fun stateToIconsVisible_onPartialSwipeLeft() {
verifyGesture(
revealValue = RevealValue.Revealing,
- gesture = {
- swipeLeft(
- startX = width / 2f,
- endX = 0f
- )
- }
+ gesture = { swipeLeft(startX = width / 2f, endX = 0f) }
)
}
@@ -146,19 +130,16 @@
fun onSwipe_whenNotAllowed_doesNotSwipe() {
lateinit var revealState: RevealState
rule.setContent {
- revealState = rememberRevealState(
- confirmValueChange = { revealValue ->
- revealValue != RevealValue.Revealing
- }
- )
+ revealState =
+ rememberRevealState(
+ confirmValueChange = { revealValue -> revealValue != RevealValue.Revealing }
+ )
swipeToRevealWithDefaults(state = revealState, modifier = Modifier.testTag(TEST_TAG))
}
rule.onNodeWithTag(TEST_TAG).performTouchInput { swipeLeft(startX = width / 2f, endX = 0f) }
- rule.runOnIdle {
- assertEquals(RevealValue.Covered, revealState.currentValue)
- }
+ rule.runOnIdle { assertEquals(RevealValue.Covered, revealState.currentValue) }
}
@Test
@@ -169,9 +150,10 @@
val testTagTwo = "testTagTwo"
rule.setContent {
revealStateOne = rememberRevealState()
- revealStateTwo = rememberRevealState(
- confirmValueChange = { revealValue -> revealValue != RevealValue.Revealing }
- )
+ revealStateTwo =
+ rememberRevealState(
+ confirmValueChange = { revealValue -> revealValue != RevealValue.Revealing }
+ )
Column {
swipeToRevealWithDefaults(
state = revealStateOne,
@@ -294,9 +276,7 @@
}
}
- rule.runOnIdle {
- assertEquals(RevealValue.Covered, revealStateOne.currentValue)
- }
+ rule.runOnIdle { assertEquals(RevealValue.Covered, revealStateOne.currentValue) }
}
@Test
@@ -317,31 +297,32 @@
}
}
- rule.runOnIdle {
- assertEquals(lastValue, revealStateOne.currentValue)
- }
+ rule.runOnIdle { assertEquals(lastValue, revealStateOne.currentValue) }
}
@Test
- fun onSecondaryActionClick_setsLastClickAction() = verifyLastClickAction(
- expectedClickType = RevealActionType.SecondaryAction,
- initialRevealValue = RevealValue.Revealing,
- secondaryActionModifier = Modifier.testTag(TEST_TAG)
- )
+ fun onSecondaryActionClick_setsLastClickAction() =
+ verifyLastClickAction(
+ expectedClickType = RevealActionType.SecondaryAction,
+ initialRevealValue = RevealValue.Revealing,
+ secondaryActionModifier = Modifier.testTag(TEST_TAG)
+ )
@Test
- fun onPrimaryActionClick_setsLastClickAction() = verifyLastClickAction(
- expectedClickType = RevealActionType.PrimaryAction,
- initialRevealValue = RevealValue.Revealing,
- primaryActionModifier = Modifier.testTag(TEST_TAG)
- )
+ fun onPrimaryActionClick_setsLastClickAction() =
+ verifyLastClickAction(
+ expectedClickType = RevealActionType.PrimaryAction,
+ initialRevealValue = RevealValue.Revealing,
+ primaryActionModifier = Modifier.testTag(TEST_TAG)
+ )
@Test
- fun onUndoActionClick_setsLastClickAction() = verifyLastClickAction(
- expectedClickType = RevealActionType.UndoAction,
- initialRevealValue = RevealValue.Revealed,
- undoActionModifier = Modifier.testTag(TEST_TAG)
- )
+ fun onUndoActionClick_setsLastClickAction() =
+ verifyLastClickAction(
+ expectedClickType = RevealActionType.UndoAction,
+ initialRevealValue = RevealValue.Revealed,
+ undoActionModifier = Modifier.testTag(TEST_TAG)
+ )
@Test
fun onRightSwipe_dispatchEventsToParent() {
@@ -358,12 +339,8 @@
}
}
}
- Box(
- modifier = Modifier.nestedScroll(nestedScrollConnection)
- ) {
- swipeToRevealWithDefaults(
- modifier = Modifier.testTag(TEST_TAG)
- )
+ Box(modifier = Modifier.nestedScroll(nestedScrollConnection)) {
+ swipeToRevealWithDefaults(modifier = Modifier.testTag(TEST_TAG))
}
}
@@ -387,12 +364,8 @@
}
}
}
- Box(
- modifier = Modifier.nestedScroll(nestedScrollConnection)
- ) {
- swipeToRevealWithDefaults(
- modifier = Modifier.testTag(TEST_TAG)
- )
+ Box(modifier = Modifier.nestedScroll(nestedScrollConnection)) {
+ swipeToRevealWithDefaults(modifier = Modifier.testTag(TEST_TAG))
}
}
@@ -416,60 +389,53 @@
state = revealState,
primaryAction = {
actionContent(
- modifier = primaryActionModifier.clickable {
- coroutineScope.launch {
- revealState.snapTo(RevealValue.Covered)
- revealState.lastActionType = RevealActionType.PrimaryAction
+ modifier =
+ primaryActionModifier.clickable {
+ coroutineScope.launch {
+ revealState.snapTo(RevealValue.Covered)
+ revealState.lastActionType = RevealActionType.PrimaryAction
+ }
}
- }
)
},
secondaryAction = {
actionContent(
- modifier = secondaryActionModifier.clickable {
- coroutineScope.launch {
- revealState.snapTo(RevealValue.Covered)
- revealState.lastActionType = RevealActionType.SecondaryAction
+ modifier =
+ secondaryActionModifier.clickable {
+ coroutineScope.launch {
+ revealState.snapTo(RevealValue.Covered)
+ revealState.lastActionType = RevealActionType.SecondaryAction
+ }
}
- }
)
},
undoAction = {
actionContent(
- modifier = undoActionModifier.clickable {
- coroutineScope.launch {
- revealState.animateTo(RevealValue.Covered)
- revealState.lastActionType = RevealActionType.UndoAction
+ modifier =
+ undoActionModifier.clickable {
+ coroutineScope.launch {
+ revealState.animateTo(RevealValue.Covered)
+ revealState.lastActionType = RevealActionType.UndoAction
+ }
}
- }
)
}
)
}
rule.onNodeWithTag(TEST_TAG).performClick()
- rule.runOnIdle {
- assertEquals(expectedClickType, revealState.lastActionType)
- }
+ rule.runOnIdle { assertEquals(expectedClickType, revealState.lastActionType) }
}
- private fun verifyGesture(
- revealValue: RevealValue,
- gesture: TouchInjectionScope.() -> Unit
- ) {
+ private fun verifyGesture(revealValue: RevealValue, gesture: TouchInjectionScope.() -> Unit) {
lateinit var revealState: RevealState
rule.setContent {
revealState = rememberRevealState()
- swipeToRevealWithDefaults(
- state = revealState,
- modifier = Modifier.testTag(TEST_TAG)
- )
+ swipeToRevealWithDefaults(state = revealState, modifier = Modifier.testTag(TEST_TAG))
}
rule.onNodeWithTag(TEST_TAG).performTouchInput(gesture)
- rule.runOnIdle {
- assertEquals(revealValue, revealState.currentValue)
- }
+ rule.runOnIdle { assertEquals(revealValue, revealState.currentValue) }
}
@Composable
@@ -492,20 +458,13 @@
}
@Composable
- private fun getBoxContent(
- onClick: () -> Unit = {},
- modifier: Modifier = Modifier
- ) {
- Box(modifier = modifier
- .size(width = 200.dp, height = 50.dp)
- .clickable { onClick() }) {}
+ private fun getBoxContent(onClick: () -> Unit = {}, modifier: Modifier = Modifier) {
+ Box(modifier = modifier.size(width = 200.dp, height = 50.dp).clickable { onClick() }) {}
}
@Composable
- private fun actionContent(
- modifier: Modifier = Modifier
- ) {
- Box(modifier = modifier.size(50.dp)) {}
+ private fun actionContent(modifier: Modifier = Modifier) {
+ Box(modifier = modifier.size(50.dp)) {}
}
@Composable
@@ -514,10 +473,6 @@
modifier: Modifier = Modifier,
content: @Composable () -> Unit = { actionContent(modifier) }
) {
- Box(
- modifier = modifier.clickable { onClick() }
- ) {
- content()
- }
+ Box(modifier = modifier.clickable { onClick() }) { content() }
}
}
diff --git a/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/SwipeableV2Test.kt b/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/SwipeableV2Test.kt
index 5c8e950..8972941 100644
--- a/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/SwipeableV2Test.kt
+++ b/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/SwipeableV2Test.kt
@@ -62,16 +62,14 @@
// supports property nested scrolling, but the tests should all still be valid.
@OptIn(ExperimentalWearFoundationApi::class)
class SwipeableV2Test {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
@Test
fun hasHorizontalScrollSemantics_atMaxValue_whenUnswiped() {
val state = SwipeableV2State(false)
rule.setContent {
SimpleSwipeableV2Box { size ->
- Modifier
- .swipeableV2(
+ Modifier.swipeableV2(
state = state,
orientation = Orientation.Horizontal,
)
@@ -87,7 +85,8 @@
}
}
- rule.onNodeWithTag(TEST_TAG)
+ rule
+ .onNodeWithTag(TEST_TAG)
.assert(hasScrollRangeCloseTo(Orientation.Horizontal, value = 1f, maxValue = 1f))
.assert(SemanticsMatcher.keyNotDefined(VerticalScrollAxisRange))
}
@@ -97,8 +96,7 @@
val state = SwipeableV2State(false)
rule.setContent {
SimpleSwipeableV2Box { size ->
- Modifier
- .swipeableV2(
+ Modifier.swipeableV2(
state = state,
orientation = Orientation.Vertical,
)
@@ -114,7 +112,8 @@
}
}
- rule.onNodeWithTag(TEST_TAG)
+ rule
+ .onNodeWithTag(TEST_TAG)
.assert(hasScrollRangeCloseTo(Orientation.Vertical, value = 1f, maxValue = 1f))
.assert(SemanticsMatcher.keyNotDefined(HorizontalScrollAxisRange))
}
@@ -124,8 +123,7 @@
val state = SwipeableV2State(false)
rule.setContent {
SimpleSwipeableV2Box { size ->
- Modifier
- .swipeableV2(
+ Modifier.swipeableV2(
state = state,
orientation = Orientation.Horizontal,
)
@@ -141,19 +139,17 @@
}
}
- rule.onNodeWithTag(TEST_TAG)
- .performTouchInput {
- down(centerLeft)
- moveTo(centerLeft + percentOffset(.25f, 0f))
- }
- rule.onNodeWithTag(TEST_TAG)
+ rule.onNodeWithTag(TEST_TAG).performTouchInput {
+ down(centerLeft)
+ moveTo(centerLeft + percentOffset(.25f, 0f))
+ }
+ rule
+ .onNodeWithTag(TEST_TAG)
.assert(hasScrollRangeCloseTo(Orientation.Horizontal, value = 0.75f, maxValue = 1f))
- rule.onNodeWithTag(TEST_TAG)
- .performTouchInput {
- moveTo(center)
- }
- rule.onNodeWithTag(TEST_TAG)
+ rule.onNodeWithTag(TEST_TAG).performTouchInput { moveTo(center) }
+ rule
+ .onNodeWithTag(TEST_TAG)
.assert(hasScrollRangeCloseTo(Orientation.Horizontal, value = 0.5f, maxValue = 1f))
}
@@ -162,8 +158,7 @@
val state = SwipeableV2State(false)
rule.setContent {
SimpleSwipeableV2Box { size ->
- Modifier
- .swipeableV2(
+ Modifier.swipeableV2(
state = state,
orientation = Orientation.Horizontal,
reverseDirection = true
@@ -180,12 +175,12 @@
}
}
- rule.onNodeWithTag(TEST_TAG)
- .performTouchInput {
- down(centerRight)
- moveTo(centerRight - percentOffset(.25f, 0f))
- }
- rule.onNodeWithTag(TEST_TAG)
+ rule.onNodeWithTag(TEST_TAG).performTouchInput {
+ down(centerRight)
+ moveTo(centerRight - percentOffset(.25f, 0f))
+ }
+ rule
+ .onNodeWithTag(TEST_TAG)
.assert(
hasScrollRangeCloseTo(
orientation = Orientation.Horizontal,
@@ -195,11 +190,9 @@
)
)
- rule.onNodeWithTag(TEST_TAG)
- .performTouchInput {
- moveTo(center)
- }
- rule.onNodeWithTag(TEST_TAG)
+ rule.onNodeWithTag(TEST_TAG).performTouchInput { moveTo(center) }
+ rule
+ .onNodeWithTag(TEST_TAG)
.assert(
hasScrollRangeCloseTo(
orientation = Orientation.Horizontal,
@@ -215,8 +208,7 @@
val state = SwipeableV2State(false)
rule.setContent {
SimpleSwipeableV2Box { size ->
- Modifier
- .swipeableV2(
+ Modifier.swipeableV2(
state = state,
orientation = Orientation.Horizontal,
enabled = false
@@ -233,7 +225,8 @@
}
}
- rule.onNodeWithTag(TEST_TAG)
+ rule
+ .onNodeWithTag(TEST_TAG)
.assert(SemanticsMatcher.keyNotDefined(HorizontalScrollAxisRange))
.assert(SemanticsMatcher.keyNotDefined(VerticalScrollAxisRange))
}
@@ -243,14 +236,10 @@
var delta = 0f
rule.testSwipe(
touchInput = { swipeLeft() },
- consumePreScrollDelta = { offset ->
- delta = offset.x
- }
+ consumePreScrollDelta = { offset -> delta = offset.x }
)
- assert(delta < 0) {
- "Expected delta to be negative, was $delta"
- }
+ assert(delta < 0) { "Expected delta to be negative, was $delta" }
}
@Test
@@ -258,14 +247,10 @@
var delta = 0f
rule.testSwipe(
touchInput = { swipeRight() },
- consumePreScrollDelta = { offset ->
- delta = offset.x
- }
+ consumePreScrollDelta = { offset -> delta = offset.x }
)
- assert(delta > 0) {
- "Expected delta to be positive, was $delta"
- }
+ assert(delta > 0) { "Expected delta to be positive, was $delta" }
}
@Test
@@ -273,15 +258,11 @@
var delta = 0f
rule.testSwipe(
touchInput = { swipeUp() },
- consumePreScrollDelta = { offset ->
- delta = offset.y
- },
+ consumePreScrollDelta = { offset -> delta = offset.y },
orientation = Orientation.Vertical
)
- assert(delta < 0) {
- "Expected delta to be negative, was $delta"
- }
+ assert(delta < 0) { "Expected delta to be negative, was $delta" }
}
@Test
@@ -289,15 +270,11 @@
var delta = 0f
rule.testSwipe(
touchInput = { swipeDown() },
- consumePreScrollDelta = { offset ->
- delta = offset.y
- },
+ consumePreScrollDelta = { offset -> delta = offset.y },
orientation = Orientation.Vertical
)
- assert(delta > 0) {
- "Expected delta to be positive, was $delta"
- }
+ assert(delta > 0) { "Expected delta to be positive, was $delta" }
}
@Test
@@ -305,14 +282,10 @@
var delta = 0f
rule.testSwipe(
touchInput = { swipeLeft() },
- consumePostScrollDelta = { offset ->
- delta = offset.x
- }
+ consumePostScrollDelta = { offset -> delta = offset.x }
)
- assert(delta < 0) {
- "Expected delta to be negative, was $delta"
- }
+ assert(delta < 0) { "Expected delta to be negative, was $delta" }
}
@Test
@@ -320,15 +293,11 @@
var delta = 0f
rule.testSwipe(
touchInput = { swipeRight() },
- consumePostScrollDelta = { offset ->
- delta = offset.x
- },
+ consumePostScrollDelta = { offset -> delta = offset.x },
reverseAnchors = true // reverse anchors or else swipeable consumes whole delta
)
- assert(delta > 0) {
- "Expected delta to be positive, was $delta"
- }
+ assert(delta > 0) { "Expected delta to be positive, was $delta" }
}
@Test
@@ -336,15 +305,11 @@
var delta = 0f
rule.testSwipe(
touchInput = { swipeUp() },
- consumePostScrollDelta = { offset ->
- delta = offset.y
- },
+ consumePostScrollDelta = { offset -> delta = offset.y },
orientation = Orientation.Vertical
)
- assert(delta < 0) {
- "Expected delta to be negative, was $delta"
- }
+ assert(delta < 0) { "Expected delta to be negative, was $delta" }
}
@Test
@@ -352,16 +317,12 @@
var delta = 0f
rule.testSwipe(
touchInput = { swipeDown() },
- consumePostScrollDelta = { offset ->
- delta = offset.y
- },
+ consumePostScrollDelta = { offset -> delta = offset.y },
orientation = Orientation.Vertical,
reverseAnchors = true // reverse anchors or else swipeable consumes whole delta
)
- assert(delta > 0) {
- "Expected delta to be positive, was $delta"
- }
+ assert(delta > 0) { "Expected delta to be positive, was $delta" }
}
@Test
@@ -369,15 +330,11 @@
var delta = 0f
rule.testSwipe(
touchInput = { swipeLeft() },
- consumePreScrollDelta = { offset ->
- delta = offset.x
- },
+ consumePreScrollDelta = { offset -> delta = offset.x },
testTag = CHILD_TEST_TAG
)
- assert(delta < 0) {
- "Expected delta to be negative, was $delta"
- }
+ assert(delta < 0) { "Expected delta to be negative, was $delta" }
}
@Test
@@ -385,15 +342,11 @@
var delta = 0f
rule.testSwipe(
touchInput = { swipeRight() },
- consumePreScrollDelta = { offset ->
- delta = offset.x
- },
+ consumePreScrollDelta = { offset -> delta = offset.x },
testTag = CHILD_TEST_TAG
)
- assert(delta > 0) {
- "Expected delta to be positive, was $delta"
- }
+ assert(delta > 0) { "Expected delta to be positive, was $delta" }
}
private fun ComposeContentTestRule.testSwipe(
@@ -431,16 +384,18 @@
reverseAnchors = reverseAnchors,
modifier = Modifier.testTag(TEST_TAG)
) {
- Box(modifier = Modifier
- .fillMaxSize()
- .testTag(CHILD_TEST_TAG)
- .nestedScroll(remember { object : NestedScrollConnection {} })
- .scrollable(
- state = rememberScrollableState { _ ->
- 0f // Do not consume any delta, just return it
- },
- orientation = orientation
- )
+ Box(
+ modifier =
+ Modifier.fillMaxSize()
+ .testTag(CHILD_TEST_TAG)
+ .nestedScroll(remember { object : NestedScrollConnection {} })
+ .scrollable(
+ state =
+ rememberScrollableState { _ ->
+ 0f // Do not consume any delta, just return it
+ },
+ orientation = orientation
+ )
)
}
}
@@ -461,33 +416,28 @@
// To participate as a consumer of scroll events
val nestedScrollConnection = remember { object : NestedScrollConnection {} }
val swipeableV2State = remember {
- SwipeableV2State(
- initialValue = false,
- nestedScrollDispatcher = nestedScrollDispatcher
- )
+ SwipeableV2State(initialValue = false, nestedScrollDispatcher = nestedScrollDispatcher)
}
val factor = if (reverseAnchors) -1 else 1
Box(
- modifier = modifier
- .fillMaxSize()
- .nestedScroll(nestedScrollConnection)
- .swipeableV2(
- swipeableV2State,
- orientation
- )
- .swipeAnchors(
- state = swipeableV2State,
- possibleValues = setOf(false, true)
- ) { value, layoutSize ->
- when (value) {
- false -> 0f
- true -> factor * (
- if (orientation == Orientation.Horizontal) layoutSize.width.toFloat()
- else layoutSize.height.toFloat()
- )
+ modifier =
+ modifier
+ .fillMaxSize()
+ .nestedScroll(nestedScrollConnection)
+ .swipeableV2(swipeableV2State, orientation)
+ .swipeAnchors(state = swipeableV2State, possibleValues = setOf(false, true)) {
+ value,
+ layoutSize ->
+ when (value) {
+ false -> 0f
+ true ->
+ factor *
+ (if (orientation == Orientation.Horizontal)
+ layoutSize.width.toFloat()
+ else layoutSize.height.toFloat())
+ }
}
- }
- .nestedScroll(nestedScrollConnection, nestedScrollDispatcher),
+ .nestedScroll(nestedScrollConnection, nestedScrollDispatcher),
content = content
)
}
@@ -499,11 +449,12 @@
@Composable
private fun SimpleSwipeableV2Box(swipeableV2Modifier: (Size) -> Modifier) {
val originalViewConfiguration = LocalViewConfiguration.current
- val viewConfiguration = remember(originalViewConfiguration) {
- object : ViewConfiguration by originalViewConfiguration {
- override val touchSlop: Float = 0f
+ val viewConfiguration =
+ remember(originalViewConfiguration) {
+ object : ViewConfiguration by originalViewConfiguration {
+ override val touchSlop: Float = 0f
+ }
}
- }
with(LocalDensity.current) {
val size = 100.dp
@@ -511,8 +462,7 @@
CompositionLocalProvider(LocalViewConfiguration provides viewConfiguration) {
Box(
- Modifier
- .testTag(TEST_TAG)
+ Modifier.testTag(TEST_TAG)
.requiredSize(size)
.then(remember { swipeableV2Modifier(Size(sizePx, sizePx)) })
)
@@ -529,19 +479,22 @@
value: Float,
maxValue: Float,
reverseScrolling: Boolean = false
- ): SemanticsMatcher = SemanticsMatcher(
- "has $orientation scroll range [0,$maxValue] with " +
- "value=$value" + if (reverseScrolling) " (reversed)" else ""
- ) { node ->
- val threshold = .1f
- val property = when (orientation) {
- Orientation.Horizontal -> HorizontalScrollAxisRange
- Orientation.Vertical -> VerticalScrollAxisRange
+ ): SemanticsMatcher =
+ SemanticsMatcher(
+ "has $orientation scroll range [0,$maxValue] with " +
+ "value=$value" +
+ if (reverseScrolling) " (reversed)" else ""
+ ) { node ->
+ val threshold = .1f
+ val property =
+ when (orientation) {
+ Orientation.Horizontal -> HorizontalScrollAxisRange
+ Orientation.Vertical -> VerticalScrollAxisRange
+ }
+ node.config.getOrNull(property)?.let { range ->
+ (range.value() - value).absoluteValue <= threshold &&
+ range.maxValue() == maxValue &&
+ range.reverseScrolling == reverseScrolling
+ } ?: false
}
- node.config.getOrNull(property)?.let { range ->
- (range.value() - value).absoluteValue <= threshold &&
- range.maxValue() == maxValue &&
- range.reverseScrolling == reverseScrolling
- } ?: false
- }
}
diff --git a/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/lazy/ScalingLazyColumnIndexedTest.kt b/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/lazy/ScalingLazyColumnIndexedTest.kt
index 9246678..b2efb82 100644
--- a/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/lazy/ScalingLazyColumnIndexedTest.kt
+++ b/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/lazy/ScalingLazyColumnIndexedTest.kt
@@ -36,8 +36,7 @@
class ScalingLazyColumnIndexedTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
@Test
fun scalingLazyColumnShowsIndexedItems() {
@@ -50,21 +49,19 @@
rule.setContent {
ScalingLazyColumn(
- state = rememberScalingLazyListState(initialCenterItemIndex = 0)
- .also { state = it },
+ state =
+ rememberScalingLazyListState(initialCenterItemIndex = 0).also { state = it },
modifier = Modifier.height(viewPortHeight),
verticalArrangement = Arrangement.spacedBy(gapBetweenItems),
- scalingParams = ScalingLazyColumnDefaults.scalingParams(
- edgeScale = 1.0f,
- // Create some extra composables to check that extraPadding works.
- viewportVerticalOffsetResolver = { (it.maxHeight / 10f).toInt() }
- )
+ scalingParams =
+ ScalingLazyColumnDefaults.scalingParams(
+ edgeScale = 1.0f,
+ // Create some extra composables to check that extraPadding works.
+ viewportVerticalOffsetResolver = { (it.maxHeight / 10f).toInt() }
+ )
) {
itemsIndexed(items) { index, item ->
- Spacer(
- Modifier.height(itemHeight).width(itemWidth)
- .testTag("$index-$item")
- )
+ Spacer(Modifier.height(itemHeight).width(itemWidth).testTag("$index-$item"))
}
}
}
@@ -72,20 +69,16 @@
// TODO(b/210654937): Remove the waitUntil once we no longer need 2 stage initialization
rule.waitUntil { state.initialized.value }
// Fully visible
- rule.onNodeWithTag("0-1")
- .assertIsDisplayed()
+ rule.onNodeWithTag("0-1").assertIsDisplayed()
// Partially visible
- rule.onNodeWithTag("1-2")
- .assertIsDisplayed()
+ rule.onNodeWithTag("1-2").assertIsDisplayed()
// Will have been composed but should not be visible
- rule.onNodeWithTag("2-3")
- .assertIsNotDisplayed()
+ rule.onNodeWithTag("2-3").assertIsNotDisplayed()
// Should not have been composed
- rule.onNodeWithTag("3-4")
- .assertDoesNotExist()
+ rule.onNodeWithTag("3-4").assertDoesNotExist()
}
@Test
@@ -95,27 +88,23 @@
rule.setContent {
ScalingLazyColumn(
- state = rememberScalingLazyListState(initialCenterItemIndex = 0)
- .also { state = it },
+ state =
+ rememberScalingLazyListState(initialCenterItemIndex = 0).also { state = it },
modifier = Modifier.height(200.dp),
autoCentering = null,
scalingParams = ScalingLazyColumnDefaults.scalingParams(edgeScale = 1.0f)
) {
itemsIndexed(items) { index, item ->
- BasicText(
- "${index}x$item", Modifier.requiredHeight(100.dp)
- )
+ BasicText("${index}x$item", Modifier.requiredHeight(100.dp))
}
}
}
// TODO(b/210654937): Remove the waitUntil once we no longer need 2 stage initialization
rule.waitUntil { state.initialized.value }
- rule.onNodeWithText("0x0")
- .assertTopPositionInRootIsEqualTo(0.dp)
+ rule.onNodeWithText("0x0").assertTopPositionInRootIsEqualTo(0.dp)
- rule.onNodeWithText("1x1")
- .assertTopPositionInRootIsEqualTo(104.dp)
+ rule.onNodeWithText("1x1").assertTopPositionInRootIsEqualTo(104.dp)
}
@Test
@@ -127,8 +116,8 @@
val gapBetweenItems = 2.dp
rule.setContent {
ScalingLazyColumn(
- state = rememberScalingLazyListState(initialCenterItemIndex = 0)
- .also { state = it },
+ state =
+ rememberScalingLazyListState(initialCenterItemIndex = 0).also { state = it },
modifier = Modifier.height(viewPortHeight),
autoCentering = AutoCenteringParams(itemIndex = 0),
verticalArrangement = Arrangement.spacedBy(gapBetweenItems),
@@ -136,9 +125,7 @@
scalingParams = ScalingLazyColumnDefaults.scalingParams(edgeScale = 1.0f)
) {
itemsIndexed(items) { index, item ->
- BasicText(
- "${index}x$item", Modifier.requiredHeight(itemHeight)
- )
+ BasicText("${index}x$item", Modifier.requiredHeight(itemHeight))
}
}
}
@@ -147,11 +134,11 @@
rule.waitUntil { state.initialized.value }
// Check that first item is in the center of the viewport
val firstItemStart = viewPortHeight / 2f - itemHeight / 2f
- rule.onNodeWithText("0x0")
- .assertTopPositionInRootIsEqualTo(firstItemStart)
+ rule.onNodeWithText("0x0").assertTopPositionInRootIsEqualTo(firstItemStart)
// And that the second item is item height + gap between items below it
- rule.onNodeWithText("1x1")
+ rule
+ .onNodeWithText("1x1")
.assertTopPositionInRootIsEqualTo(firstItemStart + itemHeight + gapBetweenItems)
}
}
diff --git a/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/lazy/ScalingLazyColumnTest.kt b/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/lazy/ScalingLazyColumnTest.kt
index a13ef306..b25dc9d 100644
--- a/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/lazy/ScalingLazyColumnTest.kt
+++ b/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/lazy/ScalingLazyColumnTest.kt
@@ -68,8 +68,7 @@
private val scalingLazyColumnTag = "scalingLazyColumnTag"
private val firstItemTag = "firstItemTag"
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
private var itemSizePx: Int = 50
private var itemSizeDp: Dp = Dp.Infinity
@@ -125,9 +124,7 @@
state = rememberScalingLazyListState().also { state = it },
modifier = Modifier.testTag(TEST_TAG).requiredSize(listSize),
) {
- items(itemCount) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(itemCount) { Box(Modifier.requiredSize(itemSizeDp)) }
}
}
}
@@ -149,9 +146,7 @@
// also for the gap between items to be needed.
verticalArrangement = Arrangement.spacedBy(itemSizeDp * 0.25f * 0.75f),
) {
- items(5) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(5) { Box(Modifier.requiredSize(itemSizeDp)) }
}
}
}
@@ -170,12 +165,8 @@
modifier = Modifier.testTag(TEST_TAG).requiredSize(listSize),
scalingParams = ScalingLazyColumnDefaults.scalingParams(edgeScale = 1f),
) {
- item {
- Box(Modifier.requiredSize(itemSizeDp * 2))
- }
- items(5) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ item { Box(Modifier.requiredSize(itemSizeDp * 2)) }
+ items(5) { Box(Modifier.requiredSize(itemSizeDp)) }
}
}
}
@@ -195,15 +186,14 @@
anchorType = ScalingLazyListAnchorType.ItemCenter,
autoCentering = AutoCenteringParams(),
verticalArrangement = Arrangement.spacedBy(0.dp),
- scalingParams = ScalingLazyColumnDefaults.scalingParams(
- edgeScale = 0f,
- minTransitionArea = 0.5f,
- maxTransitionArea = 0.5f
- )
+ scalingParams =
+ ScalingLazyColumnDefaults.scalingParams(
+ edgeScale = 0f,
+ minTransitionArea = 0.5f,
+ maxTransitionArea = 0.5f
+ )
) {
- items(5) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(5) { Box(Modifier.requiredSize(itemSizeDp)) }
}
}
}
@@ -211,9 +201,7 @@
rule.waitUntil { state.initialized.value }
rule.waitForIdle()
- val listSizePx = with(rule.density) {
- listSize.roundToPx()
- }
+ val listSizePx = with(rule.density) { listSize.roundToPx() }
rule.runOnIdle {
// Make sure that the edge items have been scaled
assertThat(state.layoutInfo.visibleItemsInfo.first().scale).isLessThan(1.0f)
@@ -223,9 +211,7 @@
assertThat(state.lazyListState.layoutInfo.visibleItemsInfo.first().size)
.isEqualTo((listSizePx / 2) - (itemSizePx + itemSizePx / 2))
}
- rule.onNodeWithTag(TEST_TAG).performTouchInput {
- swipeUp()
- }
+ rule.onNodeWithTag(TEST_TAG).performTouchInput { swipeUp() }
rule.runOnIdle {
// Check that the last item has been scrolled into view
assertThat(state.lazyListState.layoutInfo.visibleItemsInfo.last().index)
@@ -248,15 +234,14 @@
anchorType = ScalingLazyListAnchorType.ItemStart,
autoCentering = AutoCenteringParams(),
verticalArrangement = Arrangement.spacedBy(0.dp),
- scalingParams = ScalingLazyColumnDefaults.scalingParams(
- edgeScale = 0f,
- minTransitionArea = 0.5f,
- maxTransitionArea = 0.5f
- )
+ scalingParams =
+ ScalingLazyColumnDefaults.scalingParams(
+ edgeScale = 0f,
+ minTransitionArea = 0.5f,
+ maxTransitionArea = 0.5f
+ )
) {
- items(5) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(5) { Box(Modifier.requiredSize(itemSizeDp)) }
}
}
}
@@ -264,9 +249,7 @@
rule.waitUntil { state.initialized.value }
rule.waitForIdle()
- val listSizePx = with(rule.density) {
- listSize.roundToPx()
- }
+ val listSizePx = with(rule.density) { listSize.roundToPx() }
rule.runOnIdle {
// Make sure that the edge items have been scaled
@@ -276,9 +259,7 @@
assertThat(state.lazyListState.layoutInfo.visibleItemsInfo.first().size)
.isEqualTo((listSizePx / 2) - itemSizePx)
}
- rule.onNodeWithTag(TEST_TAG).performTouchInput {
- swipeUp(endY = top)
- }
+ rule.onNodeWithTag(TEST_TAG).performTouchInput { swipeUp(endY = top) }
rule.runOnIdle {
// Check that the last item has been scrolled into view
assertThat(state.lazyListState.layoutInfo.visibleItemsInfo.last().index)
@@ -296,14 +277,12 @@
WithTouchSlop(0f) {
ScalingLazyColumn(
state = rememberScalingLazyListState().also { state = it },
- modifier = Modifier.testTag(TEST_TAG).requiredSize(
- itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f
- ),
+ modifier =
+ Modifier.testTag(TEST_TAG)
+ .requiredSize(itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f),
autoCentering = null
) {
- items(5) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(5) { Box(Modifier.requiredSize(itemSizeDp)) }
}
}
}
@@ -328,15 +307,13 @@
WithTouchSlop(0f) {
ScalingLazyColumn(
state = rememberScalingLazyListState().also { state = it },
- modifier = Modifier.testTag(TEST_TAG).requiredSize(
- itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f
- ),
+ modifier =
+ Modifier.testTag(TEST_TAG)
+ .requiredSize(itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f),
autoCentering = null,
userScrollEnabled = false
) {
- items(5) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(5) { Box(Modifier.requiredSize(itemSizeDp)) }
}
}
}
@@ -361,16 +338,16 @@
rule.setContent {
WithTouchSlop(0f) {
ScalingLazyColumn(
- state = rememberScalingLazyListState(initialCenterItemIndex = 0)
- .also { state = it },
- modifier = Modifier.testTag(TEST_TAG).requiredSize(
- itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f
- ),
+ state =
+ rememberScalingLazyListState(initialCenterItemIndex = 0).also {
+ state = it
+ },
+ modifier =
+ Modifier.testTag(TEST_TAG)
+ .requiredSize(itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f),
autoCentering = AutoCenteringParams(itemIndex = 0)
) {
- items(5) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(5) { Box(Modifier.requiredSize(itemSizeDp)) }
}
}
}
@@ -394,17 +371,17 @@
rule.setContent {
WithTouchSlop(0f) {
ScalingLazyColumn(
- state = rememberScalingLazyListState(initialCenterItemIndex = 0)
- .also { state = it },
- modifier = Modifier.testTag(TEST_TAG).requiredSize(
- itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f
- ),
+ state =
+ rememberScalingLazyListState(initialCenterItemIndex = 0).also {
+ state = it
+ },
+ modifier =
+ Modifier.testTag(TEST_TAG)
+ .requiredSize(itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f),
autoCentering = AutoCenteringParams(itemIndex = 0),
flingBehavior = ScalingLazyColumnDefaults.snapFlingBehavior(state)
) {
- items(5) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(5) { Box(Modifier.requiredSize(itemSizeDp)) }
}
}
}
@@ -440,20 +417,21 @@
snapOffsetPx = with(LocalDensity.current) { snapOffset.roundToPx() }
ScalingLazyColumn(
- state = rememberScalingLazyListState(initialCenterItemIndex = 0)
- .also { state = it },
- modifier = Modifier.testTag(TEST_TAG).requiredSize(
- itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f
- ),
+ state =
+ rememberScalingLazyListState(initialCenterItemIndex = 0).also {
+ state = it
+ },
+ modifier =
+ Modifier.testTag(TEST_TAG)
+ .requiredSize(itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f),
autoCentering = AutoCenteringParams(itemIndex = 0),
- flingBehavior = ScalingLazyColumnDefaults.snapFlingBehavior(
- state = state,
- snapOffset = snapOffset
- )
+ flingBehavior =
+ ScalingLazyColumnDefaults.snapFlingBehavior(
+ state = state,
+ snapOffset = snapOffset
+ )
) {
- items(5) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(5) { Box(Modifier.requiredSize(itemSizeDp)) }
}
}
}
@@ -485,15 +463,13 @@
WithTouchSlop(0f) {
ScalingLazyColumn(
state = rememberScalingLazyListState().also { state = it },
- modifier = Modifier.testTag(TEST_TAG).requiredSize(
- itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f
- ),
+ modifier =
+ Modifier.testTag(TEST_TAG)
+ .requiredSize(itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f),
reverseLayout = true,
autoCentering = null
) {
- items(5) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(5) { Box(Modifier.requiredSize(itemSizeDp)) }
}
}
}
@@ -516,17 +492,17 @@
rule.setContent {
WithTouchSlop(0f) {
ScalingLazyColumn(
- state = rememberScalingLazyListState(initialCenterItemIndex = 0)
- .also { state = it },
- modifier = Modifier.testTag(TEST_TAG).requiredSize(
- itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f
- ),
+ state =
+ rememberScalingLazyListState(initialCenterItemIndex = 0).also {
+ state = it
+ },
+ modifier =
+ Modifier.testTag(TEST_TAG)
+ .requiredSize(itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f),
scalingParams = ScalingLazyColumnDefaults.scalingParams(1.0f, 1.0f),
autoCentering = AutoCenteringParams(itemIndex = 0)
) {
- items(5) {
- Box(Modifier.requiredSize(itemSizeDp).testTag("Item:" + it))
- }
+ items(5) { Box(Modifier.requiredSize(itemSizeDp).testTag("Item:" + it)) }
}
}
}
@@ -553,15 +529,13 @@
WithTouchSlop(0f) {
ScalingLazyColumn(
state = rememberScalingLazyListState(8).also { state = it },
- modifier = Modifier.testTag(TEST_TAG).requiredSize(
- itemSizeDp * 4f + defaultItemSpacingDp * 3f
- ),
+ modifier =
+ Modifier.testTag(TEST_TAG)
+ .requiredSize(itemSizeDp * 4f + defaultItemSpacingDp * 3f),
scalingParams = ScalingLazyColumnDefaults.scalingParams(1.0f, 1.0f),
reverseLayout = true
) {
- items(15) {
- Box(Modifier.requiredSize(itemSizeDp).testTag("Item:" + it))
- }
+ items(15) { Box(Modifier.requiredSize(itemSizeDp).testTag("Item:" + it)) }
}
}
}
@@ -598,14 +572,12 @@
WithTouchSlop(0f) {
ScalingLazyColumn(
state = rememberScalingLazyListState().also { state = it },
- modifier = Modifier
- .testTag(TEST_TAG)
- .requiredSize(itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f),
+ modifier =
+ Modifier.testTag(TEST_TAG)
+ .requiredSize(itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f),
autoCentering = null
) {
- items(6) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(6) { Box(Modifier.requiredSize(itemSizeDp)) }
}
ObservingFun(state, currentInfo)
}
@@ -669,9 +641,7 @@
// TODO(b/210654937): Remove the waitUntil once we no longer need 2 stage initialization
rule.waitUntil { state.initialized.value }
- rule.onNodeWithTag(firstItemTag)
- .assertWidthIsEqualTo(100.dp)
- .assertHeightIsEqualTo(50.dp)
+ rule.onNodeWithTag(firstItemTag).assertWidthIsEqualTo(100.dp).assertHeightIsEqualTo(50.dp)
}
@Test
@@ -693,9 +663,7 @@
// TODO(b/210654937): Remove the waitUntil once we no longer need 2 stage initialization
rule.waitUntil { state.initialized.value }
- rule.onNodeWithTag(firstItemTag)
- .assertWidthIsEqualTo(50.dp)
- .assertHeightIsEqualTo(150.dp)
+ rule.onNodeWithTag(firstItemTag).assertWidthIsEqualTo(50.dp).assertHeightIsEqualTo(150.dp)
}
@Test
@@ -708,17 +676,13 @@
contentPadding = PaddingValues(horizontal = 0.dp),
scalingParams = ScalingLazyColumnDefaults.scalingParams(1.0f, 1.0f)
) {
- items(listOf(0)) {
- Spacer(Modifier.fillParentMaxSize().testTag(firstItemTag))
- }
+ items(listOf(0)) { Spacer(Modifier.fillParentMaxSize().testTag(firstItemTag)) }
}
}
// TODO(b/210654937): Remove the waitUntil once we no longer need 2 stage initialization
rule.waitUntil { state.initialized.value }
- rule.onNodeWithTag(firstItemTag)
- .assertWidthIsEqualTo(100.dp)
- .assertHeightIsEqualTo(150.dp)
+ rule.onNodeWithTag(firstItemTag).assertWidthIsEqualTo(100.dp).assertHeightIsEqualTo(150.dp)
}
@Test
@@ -743,9 +707,7 @@
// TODO(b/210654937): Remove the waitUntil once we no longer need 2 stage initialization
rule.waitUntil { state.initialized.value }
- rule.onNodeWithTag(firstItemTag)
- .assertWidthIsEqualTo(70.dp)
- .assertHeightIsEqualTo(50.dp)
+ rule.onNodeWithTag(firstItemTag).assertWidthIsEqualTo(70.dp).assertHeightIsEqualTo(50.dp)
}
@Test
@@ -768,9 +730,7 @@
// TODO(b/210654937): Remove the waitUntil once we no longer need 2 stage initialization
rule.waitUntil { state.initialized.value }
- rule.onNodeWithTag(firstItemTag)
- .assertWidthIsEqualTo(50.dp)
- .assertHeightIsEqualTo(45.dp)
+ rule.onNodeWithTag(firstItemTag).assertWidthIsEqualTo(50.dp).assertHeightIsEqualTo(45.dp)
}
@Test
@@ -782,17 +742,13 @@
modifier = Modifier.requiredSize(width = 100.dp, height = 150.dp),
contentPadding = PaddingValues(horizontal = 0.dp)
) {
- items(listOf(0)) {
- Spacer(Modifier.fillParentMaxSize(0.5f).testTag(firstItemTag))
- }
+ items(listOf(0)) { Spacer(Modifier.fillParentMaxSize(0.5f).testTag(firstItemTag)) }
}
}
// TODO(b/210654937): Remove the waitUntil once we no longer need 2 stage initialization
rule.waitUntil { state.initialized.value }
- rule.onNodeWithTag(firstItemTag)
- .assertWidthIsEqualTo(50.dp)
- .assertHeightIsEqualTo(75.dp)
+ rule.onNodeWithTag(firstItemTag).assertWidthIsEqualTo(50.dp).assertHeightIsEqualTo(75.dp)
}
@Test
@@ -805,21 +761,15 @@
modifier = Modifier.requiredSize(parentSize),
contentPadding = PaddingValues(horizontal = 0.dp),
) {
- items(listOf(0)) {
- Spacer(Modifier.fillParentMaxSize().testTag(firstItemTag))
- }
+ items(listOf(0)) { Spacer(Modifier.fillParentMaxSize().testTag(firstItemTag)) }
}
}
// TODO(b/210654937): Remove the waitUntil once we no longer need 2 stage initialization
rule.waitUntil { state.initialized.value }
- rule.runOnIdle {
- parentSize = 150.dp
- }
+ rule.runOnIdle { parentSize = 150.dp }
- rule.onNodeWithTag(firstItemTag)
- .assertWidthIsEqualTo(150.dp)
- .assertHeightIsEqualTo(150.dp)
+ rule.onNodeWithTag(firstItemTag).assertWidthIsEqualTo(150.dp).assertHeightIsEqualTo(150.dp)
}
@Test
@@ -832,31 +782,22 @@
modifier = Modifier.testTag(scalingLazyColumnTag),
contentPadding = PaddingValues(horizontal = 0.dp),
) {
- items(listOf(0)) {
- Spacer(Modifier.size(itemSize).testTag(firstItemTag))
- }
+ items(listOf(0)) { Spacer(Modifier.size(itemSize).testTag(firstItemTag)) }
}
}
// TODO(b/210654937): Remove the waitUntil once we no longer need 2 stage initialization
rule.waitUntil { state.initialized.value }
- rule.onNodeWithTag(scalingLazyColumnTag)
- .assertWidthIsEqualTo(itemSize)
+ rule.onNodeWithTag(scalingLazyColumnTag).assertWidthIsEqualTo(itemSize)
- rule.runOnIdle {
- itemSize = 150.dp
- }
+ rule.runOnIdle { itemSize = 150.dp }
- rule.onNodeWithTag(scalingLazyColumnTag)
- .assertWidthIsEqualTo(itemSize)
+ rule.onNodeWithTag(scalingLazyColumnTag).assertWidthIsEqualTo(itemSize)
- rule.runOnIdle {
- itemSize = 50.dp
- }
+ rule.runOnIdle { itemSize = 50.dp }
- rule.onNodeWithTag(scalingLazyColumnTag)
- .assertWidthIsEqualTo(itemSize)
+ rule.onNodeWithTag(scalingLazyColumnTag).assertWidthIsEqualTo(itemSize)
}
@Test
@@ -893,19 +834,18 @@
if (showList.value) {
ScalingLazyColumn(
state = state,
- modifier = Modifier.testTag(TEST_TAG).requiredSize(
- itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f
- ),
+ modifier =
+ Modifier.testTag(TEST_TAG)
+ .requiredSize(itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f),
autoCentering = AutoCenteringParams()
) {
- items(25) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(25) { Box(Modifier.requiredSize(itemSizeDp)) }
}
} else {
- Box(modifier = Modifier.requiredSize(
- itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f
- ))
+ Box(
+ modifier =
+ Modifier.requiredSize(itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f)
+ )
}
}
// TODO(b/210654937): Remove the waitUntil once we no longer need 2 stage initialization
@@ -919,11 +859,7 @@
rule.waitForIdle()
rule.onNodeWithTag(TEST_TAG).assertDoesNotExist()
- rule.runOnIdle {
- runBlocking {
- state.scrollToItem(10)
- }
- }
+ rule.runOnIdle { runBlocking { state.scrollToItem(10) } }
rule.waitForIdle()
showList.value = true
@@ -943,24 +879,18 @@
state = rememberScalingLazyListState()
ScalingLazyColumn(
state = state,
- modifier = Modifier.testTag(TEST_TAG).requiredSize(
- itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f
- ),
+ modifier =
+ Modifier.testTag(TEST_TAG)
+ .requiredSize(itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f),
autoCentering = AutoCenteringParams()
) {
- items(25) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(25) { Box(Modifier.requiredSize(itemSizeDp)) }
}
}
// TODO(b/210654937): Remove the waitUntil once we no longer need 2 stage initialization
rule.waitUntil { state.initialized.value }
- rule.runOnIdle {
- runBlocking {
- state.scrollToItem(50)
- }
- }
+ rule.runOnIdle { runBlocking { state.scrollToItem(50) } }
state.layoutInfo.assertVisibleItems(count = 3, startIndex = 22)
assertThat(state.centerItemIndex).isEqualTo(24)
@@ -981,14 +911,12 @@
ScalingLazyColumn(
state = state,
- modifier = Modifier.testTag(TEST_TAG).requiredSize(
- itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f
- ),
+ modifier =
+ Modifier.testTag(TEST_TAG)
+ .requiredSize(itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f),
autoCentering = AutoCenteringParams(itemIndex = 0)
) {
- items(5) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(5) { Box(Modifier.requiredSize(itemSizeDp)) }
}
}
}
@@ -1010,9 +938,7 @@
Box(
modifier = Modifier.horizontalScroll(horizontalScrollState),
) {
- ScalingLazyColumn {
- item { Box(Modifier.size(10.dp)) }
- }
+ ScalingLazyColumn { item { Box(Modifier.size(10.dp)) } }
}
}
}
@@ -1023,7 +949,5 @@
internal fun ComposeContentTestRule.setContentWithTestViewConfiguration(
composable: @Composable () -> Unit
) {
- this.setContent {
- WithTouchSlop(TestTouchSlop, composable)
- }
+ this.setContent { WithTouchSlop(TestTouchSlop, composable) }
}
diff --git a/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/lazy/ScalingLazyListLayoutInfoTest.kt b/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/lazy/ScalingLazyListLayoutInfoTest.kt
index cf0399d..b5e1b02 100644
--- a/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/lazy/ScalingLazyListLayoutInfoTest.kt
+++ b/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/lazy/ScalingLazyListLayoutInfoTest.kt
@@ -54,8 +54,7 @@
@MediumTest
@RunWith(AndroidJUnit4::class)
public class ScalingLazyListLayoutInfoTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
private var itemSizePx: Int = 50
private var itemSizeDp: Dp = Dp.Infinity
@@ -76,14 +75,10 @@
rule.setContent {
ScalingLazyColumn(
state = rememberScalingLazyListState().also { state = it },
- modifier = Modifier.requiredSize(
- itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f
- ),
+ modifier = Modifier.requiredSize(itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f),
autoCentering = AutoCenteringParams()
) {
- items(5) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(5) { Box(Modifier.requiredSize(itemSizeDp)) }
}
}
@@ -107,15 +102,11 @@
itemSpacingPx = with(LocalDensity.current) { itemSpacingDp.roundToPx() }
ScalingLazyColumn(
state = rememberScalingLazyListState().also { state = it },
- modifier = Modifier.requiredSize(
- itemSizeDp * 3.5f + itemSpacingDp * 2.5f
- ),
+ modifier = Modifier.requiredSize(itemSizeDp * 3.5f + itemSpacingDp * 2.5f),
verticalArrangement = Arrangement.spacedBy(itemSpacingDp),
autoCentering = AutoCenteringParams()
) {
- items(5) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(5) { Box(Modifier.requiredSize(itemSizeDp)) }
}
}
@@ -130,9 +121,7 @@
// Scroll so that the center item is just above the center line and check that it is still
// the correct center item
val scrollDistance = (itemSizePx / 2) + 1
- scope!!.launch {
- state.animateScrollBy(scrollDistance.toFloat())
- }
+ scope!!.launch { state.animateScrollBy(scrollDistance.toFloat()) }
rule.runOnIdle {
assertThat(state.centerItemIndex).isEqualTo(1)
@@ -146,24 +135,18 @@
rule.setContent {
ScalingLazyColumn(
state = rememberScalingLazyListState().also { state = it },
- modifier = Modifier.requiredSize(
- itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f
- ),
+ modifier = Modifier.requiredSize(itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f),
autoCentering = AutoCenteringParams(),
contentPadding = PaddingValues(all = 0.dp)
) {
- items(5) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(5) { Box(Modifier.requiredSize(itemSizeDp)) }
}
}
// TODO(b/210654937): Remove the waitUntil once we no longer need 2 stage initialization
rule.waitUntil { state.initialized.value }
- rule.runOnIdle {
- assertThat(state.layoutInfo.orientation).isEqualTo(Orientation.Vertical)
- }
+ rule.runOnIdle { assertThat(state.layoutInfo.orientation).isEqualTo(Orientation.Vertical) }
}
@Test
@@ -172,24 +155,18 @@
rule.setContent {
ScalingLazyColumn(
state = rememberScalingLazyListState().also { state = it },
- modifier = Modifier.requiredSize(
- itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f
- ),
+ modifier = Modifier.requiredSize(itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f),
autoCentering = AutoCenteringParams(),
contentPadding = PaddingValues(all = 0.dp)
) {
- items(5) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(5) { Box(Modifier.requiredSize(itemSizeDp)) }
}
}
// TODO(b/210654937): Remove the waitUntil once we no longer need 2 stage initialization
rule.waitUntil { state.initialized.value }
- rule.runOnIdle {
- assertThat(state.layoutInfo.reverseLayout).isEqualTo(false)
- }
+ rule.runOnIdle { assertThat(state.layoutInfo.reverseLayout).isEqualTo(false) }
}
@Test
@@ -198,25 +175,19 @@
rule.setContent {
ScalingLazyColumn(
state = rememberScalingLazyListState().also { state = it },
- modifier = Modifier.requiredSize(
- itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f
- ),
+ modifier = Modifier.requiredSize(itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f),
autoCentering = AutoCenteringParams(),
contentPadding = PaddingValues(all = 0.dp),
reverseLayout = true
) {
- items(5) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(5) { Box(Modifier.requiredSize(itemSizeDp)) }
}
}
// TODO(b/210654937): Remove the waitUntil once we no longer need 2 stage initialization
rule.waitUntil { state.initialized.value }
- rule.runOnIdle {
- assertThat(state.layoutInfo.reverseLayout).isEqualTo(true)
- }
+ rule.runOnIdle { assertThat(state.layoutInfo.reverseLayout).isEqualTo(true) }
}
@Test
@@ -224,16 +195,12 @@
lateinit var state: ScalingLazyListState
rule.setContent {
ScalingLazyColumn(
- state = rememberScalingLazyListState(initialCenterItemIndex = 0)
- .also { state = it },
- modifier = Modifier.requiredSize(
- itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f
- ),
+ state =
+ rememberScalingLazyListState(initialCenterItemIndex = 0).also { state = it },
+ modifier = Modifier.requiredSize(itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f),
autoCentering = AutoCenteringParams(itemIndex = 0)
) {
- items(5) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(5) { Box(Modifier.requiredSize(itemSizeDp)) }
}
}
@@ -252,22 +219,16 @@
rule.setContent {
ScalingLazyColumn(
state = rememberScalingLazyListState().also { state = it },
- modifier = Modifier.requiredSize(
- itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f
- ),
+ modifier = Modifier.requiredSize(itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f),
autoCentering = null
) {
- items(5) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(5) { Box(Modifier.requiredSize(itemSizeDp)) }
}
}
// TODO(b/210654937): Remove the waitUntil once we no longer need 2 stage initialization
rule.waitUntil { state.initialized.value }
- rule.runOnIdle {
- state.layoutInfo.assertVisibleItems(count = 4)
- }
+ rule.runOnIdle { state.layoutInfo.assertVisibleItems(count = 4) }
}
@Test
@@ -276,15 +237,11 @@
rule.setContent {
ScalingLazyColumn(
state = rememberScalingLazyListState().also { state = it },
- modifier = Modifier.requiredSize(
- itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f
- ),
+ modifier = Modifier.requiredSize(itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f),
reverseLayout = true,
autoCentering = null
) {
- items(5) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(5) { Box(Modifier.requiredSize(itemSizeDp)) }
}
}
@@ -301,17 +258,13 @@
lateinit var state: ScalingLazyListState
rule.setContent {
ScalingLazyColumn(
- state = rememberScalingLazyListState(initialCenterItemIndex = 0)
- .also { state = it },
- modifier = Modifier.requiredSize(
- itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f
- ),
+ state =
+ rememberScalingLazyListState(initialCenterItemIndex = 0).also { state = it },
+ modifier = Modifier.requiredSize(itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f),
reverseLayout = true,
autoCentering = AutoCenteringParams(itemIndex = 0)
) {
- items(5) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(5) { Box(Modifier.requiredSize(itemSizeDp)) }
}
}
@@ -330,23 +283,17 @@
rule.setContent {
ScalingLazyColumn(
state = rememberScalingLazyListState().also { state = it },
- modifier = Modifier.requiredSize(
- itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f
- ),
+ modifier = Modifier.requiredSize(itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f),
autoCentering = null
) {
- items(5) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(5) { Box(Modifier.requiredSize(itemSizeDp)) }
}
}
// TODO(b/210654937): Remove the waitUntil once we no longer need 2 stage initialization
rule.waitUntil { state.initialized.value }
rule.runOnIdle {
- runBlocking {
- state.scrollBy(itemSizePx.toFloat() + defaultItemSpacingPx.toFloat())
- }
+ runBlocking { state.scrollBy(itemSizePx.toFloat() + defaultItemSpacingPx.toFloat()) }
state.layoutInfo.assertVisibleItems(count = 4, startIndex = 1)
}
}
@@ -406,17 +353,14 @@
if (viewPortSizeEven) 0 else 1
scope = rememberCoroutineScope()
ScalingLazyColumn(
- state = rememberScalingLazyListState(
- initialCenterItemIndex = autoCenterItem
- ).also { state = it },
- modifier = Modifier.requiredSize(
- viewportSizePx.toDp()
- ),
+ state =
+ rememberScalingLazyListState(initialCenterItemIndex = autoCenterItem).also {
+ state = it
+ },
+ modifier = Modifier.requiredSize(viewportSizePx.toDp()),
autoCentering = AutoCenteringParams(itemIndex = autoCenterItem)
) {
- items(5) {
- Box(Modifier.requiredSize(localItemSizePx.toDp()))
- }
+ items(5) { Box(Modifier.requiredSize(localItemSizePx.toDp())) }
}
}
}
@@ -424,18 +368,14 @@
// TODO(b/210654937): Remove the waitUntil once we no longer need 2 stage initialization
rule.waitUntil { state.initialized.value }
- scope.launch {
- state.animateScrollBy(localItemSizePx.toFloat() * 10)
- }
+ scope.launch { state.animateScrollBy(localItemSizePx.toFloat() * 10) }
rule.mainClock.advanceTimeBy(milliseconds = 1000)
assert(!state.isScrollInProgress)
assertThat(state.centerItemIndex).isEqualTo(4)
assertThat(state.centerItemScrollOffset).isEqualTo(0)
- scope.launch {
- state.animateScrollBy(- localItemSizePx.toFloat() * 10)
- }
+ scope.launch { state.animateScrollBy(-localItemSizePx.toFloat() * 10) }
rule.mainClock.advanceTimeBy(milliseconds = 1000)
assert(!state.isScrollInProgress)
@@ -449,23 +389,17 @@
rule.setContent {
ScalingLazyColumn(
state = rememberScalingLazyListState().also { state = it },
- modifier = Modifier.requiredSize(
- itemSizeDp
- ),
+ modifier = Modifier.requiredSize(itemSizeDp),
autoCentering = null
) {
- items(5) {
- Box(Modifier.requiredSize(itemSizeDp * 5))
- }
+ items(5) { Box(Modifier.requiredSize(itemSizeDp * 5)) }
}
}
// TODO(b/210654937): Remove the waitUntil once we no longer need 2 stage initialization
rule.waitUntil { state.initialized.value }
rule.runOnIdle {
- runBlocking {
- state.scrollBy(itemSizePx.toFloat() + defaultItemSpacingPx.toFloat())
- }
+ runBlocking { state.scrollBy(itemSizePx.toFloat() + defaultItemSpacingPx.toFloat()) }
val firstItem = state.layoutInfo.visibleItemsInfo.first()
assertThat(firstItem.offset).isLessThan(0)
assertThat(firstItem.offset + firstItem.size).isGreaterThan(itemSizePx)
@@ -480,13 +414,9 @@
rule.setContent {
ScalingLazyColumn(
state = rememberScalingLazyListState(centerItemIndex).also { state = it },
- modifier = Modifier.requiredSize(
- itemSizeDp * 3
- ),
+ modifier = Modifier.requiredSize(itemSizeDp * 3),
) {
- items(5) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(5) { Box(Modifier.requiredSize(itemSizeDp)) }
}
}
@@ -510,13 +440,9 @@
rule.setContent {
ScalingLazyColumn(
state = rememberScalingLazyListState(centerItemIndex).also { state = it },
- modifier = Modifier.requiredSize(
- itemSizeDp * 4 + defaultItemSpacingDp * 3
- ),
+ modifier = Modifier.requiredSize(itemSizeDp * 4 + defaultItemSpacingDp * 3),
) {
- items(6) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(6) { Box(Modifier.requiredSize(itemSizeDp)) }
}
}
@@ -524,8 +450,7 @@
rule.waitUntil { state.initialized.value }
rule.runOnIdle {
// Get the middle item on the screen
- val edgeScreenItem =
- state.layoutInfo.visibleItemsInfo.find { it.index == 0 }
+ val edgeScreenItem = state.layoutInfo.visibleItemsInfo.find { it.index == 0 }
// And that it is it scaled
assertThat(edgeScreenItem!!.scale).isLessThan(1.0f)
@@ -538,24 +463,18 @@
rule.setContent {
ScalingLazyColumn(
state = rememberScalingLazyListState().also { state = it },
- modifier = Modifier.requiredSize(
- itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f
- ),
+ modifier = Modifier.requiredSize(itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f),
reverseLayout = true,
autoCentering = null
) {
- items(5) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(5) { Box(Modifier.requiredSize(itemSizeDp)) }
}
}
// TODO(b/210654937): Remove the waitUntil once we no longer need 2 stage initialization
rule.waitUntil { state.initialized.value }
rule.runOnIdle {
- runBlocking {
- state.scrollBy(itemSizePx.toFloat() + defaultItemSpacingPx.toFloat())
- }
+ runBlocking { state.scrollBy(itemSizePx.toFloat() + defaultItemSpacingPx.toFloat()) }
state.layoutInfo.assertVisibleItems(count = 4, startIndex = 1)
}
}
@@ -566,14 +485,10 @@
rule.setContent {
ScalingLazyColumn(
state = rememberScalingLazyListState(2).also { state = it },
- modifier = Modifier.requiredSize(
- itemSizeDp * 2f + defaultItemSpacingDp * 1f
- ),
+ modifier = Modifier.requiredSize(itemSizeDp * 2f + defaultItemSpacingDp * 1f),
scalingParams = ScalingLazyColumnDefaults.scalingParams(1.0f, 1.0f)
) {
- items(5) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(5) { Box(Modifier.requiredSize(itemSizeDp)) }
}
}
@@ -592,14 +507,10 @@
rule.setContent {
ScalingLazyColumn(
state = rememberScalingLazyListState(2, -5).also { state = it },
- modifier = Modifier.requiredSize(
- itemSizeDp * 2f + defaultItemSpacingDp * 1f
- ),
+ modifier = Modifier.requiredSize(itemSizeDp * 2f + defaultItemSpacingDp * 1f),
scalingParams = ScalingLazyColumnDefaults.scalingParams(1.0f, 1.0f)
) {
- items(5) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(5) { Box(Modifier.requiredSize(itemSizeDp)) }
}
}
@@ -618,15 +529,11 @@
rule.setContent {
ScalingLazyColumn(
state = rememberScalingLazyListState(2).also { state = it },
- modifier = Modifier.requiredSize(
- itemSizeDp * 2f + defaultItemSpacingDp * 1f
- ),
+ modifier = Modifier.requiredSize(itemSizeDp * 2f + defaultItemSpacingDp * 1f),
scalingParams = ScalingLazyColumnDefaults.scalingParams(1.0f, 1.0f),
reverseLayout = true
) {
- items(5) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(5) { Box(Modifier.requiredSize(itemSizeDp)) }
}
}
@@ -645,15 +552,11 @@
rule.setContent {
ScalingLazyColumn(
state = rememberScalingLazyListState(2, -5).also { state = it },
- modifier = Modifier.requiredSize(
- itemSizeDp * 2f + defaultItemSpacingDp * 1f
- ),
+ modifier = Modifier.requiredSize(itemSizeDp * 2f + defaultItemSpacingDp * 1f),
scalingParams = ScalingLazyColumnDefaults.scalingParams(1.0f, 1.0f),
reverseLayout = true
) {
- items(5) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(5) { Box(Modifier.requiredSize(itemSizeDp)) }
}
}
@@ -672,15 +575,11 @@
rule.setContent {
ScalingLazyColumn(
state = rememberScalingLazyListState(8).also { state = it },
- modifier = Modifier.requiredSize(
- itemSizeDp * 4f + defaultItemSpacingDp * 3f
- ),
+ modifier = Modifier.requiredSize(itemSizeDp * 4f + defaultItemSpacingDp * 3f),
scalingParams = ScalingLazyColumnDefaults.scalingParams(1.0f, 1.0f),
reverseLayout = true
) {
- items(15) {
- Box(Modifier.requiredSize(itemSizeDp).testTag("Item:$it"))
- }
+ items(15) { Box(Modifier.requiredSize(itemSizeDp).testTag("Item:$it")) }
}
}
@@ -691,9 +590,7 @@
// Assert that items are being shown at the end of the parent as this is reverseLayout
rule.onNodeWithTag(testTag = "Item:8").assertIsDisplayed()
- rule.runOnIdle {
- state.layoutInfo.assertVisibleItems(count = 5, startIndex = 6)
- }
+ rule.runOnIdle { state.layoutInfo.assertVisibleItems(count = 5, startIndex = 6) }
}
@Test
@@ -701,20 +598,13 @@
lateinit var state: ScalingLazyListState
rule.setContent {
ScalingLazyColumn(
- state = rememberScalingLazyListState(initialCenterItemIndex = 0)
- .also { state = it },
- modifier = Modifier.requiredSize(
- itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f
- ),
+ state =
+ rememberScalingLazyListState(initialCenterItemIndex = 0).also { state = it },
+ modifier = Modifier.requiredSize(itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f),
scalingParams = ScalingLazyColumnDefaults.scalingParams(1.0f, 1.0f),
autoCentering = AutoCenteringParams(itemIndex = 0)
) {
- items(5) {
- Box(
- Modifier
- .requiredSize(itemSizeDp)
- .testTag("Item:$it"))
- }
+ items(5) { Box(Modifier.requiredSize(itemSizeDp).testTag("Item:$it")) }
}
}
@@ -729,17 +619,13 @@
assertThat(state.centerItemIndex).isEqualTo(0)
assertThat(state.centerItemScrollOffset).isEqualTo(0)
- runBlocking {
- state.scrollBy(scrollAmount.toFloat())
- }
+ runBlocking { state.scrollBy(scrollAmount.toFloat()) }
state.layoutInfo.assertVisibleItems(count = 4)
assertThat(state.layoutInfo.visibleItemsInfo.first().offset).isEqualTo(-scrollAmount)
}
rule.runOnIdle {
- runBlocking {
- state.scrollBy(-scrollAmount.toFloat())
- }
+ runBlocking { state.scrollBy(-scrollAmount.toFloat()) }
state.layoutInfo.assertVisibleItems(count = 3)
assertThat(state.layoutInfo.visibleItemsInfo.first().offset).isEqualTo(0)
}
@@ -751,15 +637,11 @@
rule.setContent {
ScalingLazyColumn(
state = rememberScalingLazyListState(8).also { state = it },
- modifier = Modifier.requiredSize(
- itemSizeDp * 4f + defaultItemSpacingDp * 3f
- ),
+ modifier = Modifier.requiredSize(itemSizeDp * 4f + defaultItemSpacingDp * 3f),
scalingParams = ScalingLazyColumnDefaults.scalingParams(1.0f, 1.0f),
reverseLayout = true
) {
- items(15) {
- Box(Modifier.requiredSize(itemSizeDp).testTag("Item:$it"))
- }
+ items(15) { Box(Modifier.requiredSize(itemSizeDp).testTag("Item:$it")) }
}
}
@@ -775,16 +657,12 @@
assertThat(state.centerItemIndex).isEqualTo(8)
assertThat(state.centerItemScrollOffset).isEqualTo(0)
- runBlocking {
- state.scrollBy(scrollAmount.toFloat())
- }
+ runBlocking { state.scrollBy(scrollAmount.toFloat()) }
state.layoutInfo.assertVisibleItems(count = 5, startIndex = 7)
}
rule.runOnIdle {
- runBlocking {
- state.scrollBy(-scrollAmount.toFloat())
- }
+ runBlocking { state.scrollBy(-scrollAmount.toFloat()) }
state.layoutInfo.assertVisibleItems(count = 5, startIndex = 6)
}
}
@@ -794,17 +672,13 @@
lateinit var state: ScalingLazyListState
rule.setContent {
ScalingLazyColumn(
- state = rememberScalingLazyListState(initialCenterItemIndex = 0)
- .also { state = it },
- modifier = Modifier.requiredSize(
- itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f
- ),
+ state =
+ rememberScalingLazyListState(initialCenterItemIndex = 0).also { state = it },
+ modifier = Modifier.requiredSize(itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f),
scalingParams = ScalingLazyColumnDefaults.scalingParams(1.0f, 1.0f),
autoCentering = AutoCenteringParams(itemIndex = 0)
) {
- items(5) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(5) { Box(Modifier.requiredSize(itemSizeDp)) }
}
}
@@ -812,18 +686,14 @@
rule.waitUntil { state.initialized.value }
val scrollAmount = itemSizePx.toFloat() + defaultItemSpacingPx.toFloat()
rule.runOnIdle {
- runBlocking {
- state.dispatchRawDelta(scrollAmount)
- }
+ runBlocking { state.dispatchRawDelta(scrollAmount) }
state.layoutInfo.assertVisibleItems(count = 4, startIndex = 0)
assertThat(state.layoutInfo.visibleItemsInfo.first().offset)
.isEqualTo(-scrollAmount.roundToInt())
}
rule.runOnIdle {
- runBlocking {
- state.dispatchRawDelta(-scrollAmount)
- }
+ runBlocking { state.dispatchRawDelta(-scrollAmount) }
state.layoutInfo.assertVisibleItems(count = 3, startIndex = 0)
assertThat(state.layoutInfo.visibleItemsInfo.first().offset).isEqualTo(0)
}
@@ -835,16 +705,12 @@
rule.setContent {
ScalingLazyColumn(
state = rememberScalingLazyListState().also { state = it },
- modifier = Modifier.requiredSize(
- itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f
- ),
+ modifier = Modifier.requiredSize(itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f),
scalingParams = ScalingLazyColumnDefaults.scalingParams(1.0f, 1.0f),
reverseLayout = true,
autoCentering = null
) {
- items(5) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(5) { Box(Modifier.requiredSize(itemSizeDp)) }
}
}
// TODO(b/210654937): Remove the waitUntil once we no longer need 2 stage initialization
@@ -878,22 +744,15 @@
verticalArrangement = Arrangement.spacedBy(spacing),
autoCentering = null
) {
- items(5) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(5) { Box(Modifier.requiredSize(itemSizeDp)) }
}
}
// TODO(b/210654937): Remove the waitUntil once we no longer need 2 stage initialization
rule.waitUntil { state.initialized.value }
rule.runOnIdle {
- val spacingPx = with(rule.density) {
- spacing.roundToPx()
- }
- state.layoutInfo.assertVisibleItems(
- count = 4,
- spacing = spacingPx
- )
+ val spacingPx = with(rule.density) { spacing.roundToPx() }
+ state.layoutInfo.assertVisibleItems(count = 4, spacing = spacingPx)
}
}
@@ -915,9 +774,7 @@
modifier = Modifier.requiredSize(itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f),
autoCentering = null
) {
- items(6) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(6) { Box(Modifier.requiredSize(itemSizeDp)) }
}
ObservingFun(state, currentInfo)
}
@@ -927,9 +784,7 @@
rule.runOnIdle {
// empty it here and scrolling should invoke observingFun again
currentInfo.value = null
- runBlocking {
- state.scrollBy(itemSizePx.toFloat() + defaultItemSpacingPx.toFloat())
- }
+ runBlocking { state.scrollBy(itemSizePx.toFloat() + defaultItemSpacingPx.toFloat()) }
}
rule.runOnIdle {
@@ -948,9 +803,7 @@
modifier = Modifier.requiredSize(itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f),
autoCentering = null
) {
- items(6) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(6) { Box(Modifier.requiredSize(itemSizeDp)) }
}
ObservingFun(state, currentInfo)
}
@@ -993,9 +846,7 @@
state = rememberScalingLazyListState().also { state = it },
modifier = Modifier.requiredSize(itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f)
) {
- items(6) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(6) { Box(Modifier.requiredSize(itemSizeDp)) }
}
ObservingIsScrollInProgressTrueFun(state, currentInfo)
}
@@ -1015,10 +866,7 @@
}
@Composable
- fun ObservingCentralItemIndexFun(
- state: ScalingLazyListState,
- currentInfo: StableRef<Int?>
- ) {
+ fun ObservingCentralItemIndexFun(state: ScalingLazyListState, currentInfo: StableRef<Int?>) {
currentInfo.value = state.centerItemIndex
}
@@ -1034,9 +882,7 @@
modifier = Modifier.requiredSize(itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f),
autoCentering = null
) {
- items(6) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(6) { Box(Modifier.requiredSize(itemSizeDp)) }
}
ObservingCentralItemIndexFun(state, currentInfo)
}
@@ -1065,12 +911,8 @@
currentInfo = state.layoutInfo
}
rule.setContent {
- ScalingLazyColumn(
- state = rememberScalingLazyListState().also { state = it }
- ) {
- item {
- Box(Modifier.requiredSize(size))
- }
+ ScalingLazyColumn(state = rememberScalingLazyListState().also { state = it }) {
+ item { Box(Modifier.requiredSize(size)) }
}
observingFun()
}
@@ -1100,9 +942,7 @@
Modifier.requiredSize(sizeDp),
state = rememberScalingLazyListState().also { state = it }
) {
- items(4) {
- Box(Modifier.requiredSize(sizeDp))
- }
+ items(4) { Box(Modifier.requiredSize(sizeDp)) }
}
}
@@ -1134,9 +974,7 @@
contentPadding = PaddingValues(top = topPaddingDp, bottom = bottomPaddingDp),
state = rememberScalingLazyListState().also { state = it }
) {
- items(4) {
- Box(Modifier.requiredSize(sizeDp))
- }
+ items(4) { Box(Modifier.requiredSize(sizeDp)) }
}
}
@@ -1163,14 +1001,11 @@
rule.setContent {
ScalingLazyColumn(
Modifier.requiredSize(viewPortSizeDp),
- state = rememberScalingLazyListState(
- initialCenterItemIndex = 0
- ).also { state = it },
+ state =
+ rememberScalingLazyListState(initialCenterItemIndex = 0).also { state = it },
autoCentering = AutoCenteringParams()
) {
- items(7) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(7) { Box(Modifier.requiredSize(itemSizeDp)) }
}
}
@@ -1184,15 +1019,11 @@
assertThat(state.layoutInfo.beforeAutoCenteringPadding).isGreaterThan(0)
assertThat(state.layoutInfo.afterAutoCenteringPadding).isEqualTo(0)
- runBlocking {
- state.scrollToItem(3)
- }
+ runBlocking { state.scrollToItem(3) }
assertThat(state.layoutInfo.beforeAutoCenteringPadding).isEqualTo(0)
assertThat(state.layoutInfo.afterAutoCenteringPadding).isEqualTo(0)
- runBlocking {
- state.scrollToItem(5)
- }
+ runBlocking { state.scrollToItem(5) }
assertThat(state.layoutInfo.beforeAutoCenteringPadding).isEqualTo(0)
assertThat(state.layoutInfo.afterAutoCenteringPadding).isGreaterThan(0)
}
@@ -1203,12 +1034,8 @@
var count by mutableStateOf(10)
lateinit var state: ScalingLazyListState
rule.setContent {
- ScalingLazyColumn(
- state = rememberScalingLazyListState().also { state = it }
- ) {
- items(count) {
- Box(Modifier.requiredSize(10.dp))
- }
+ ScalingLazyColumn(state = rememberScalingLazyListState().also { state = it }) {
+ items(count) { Box(Modifier.requiredSize(10.dp)) }
}
}
@@ -1219,9 +1046,7 @@
count = 20
}
- rule.runOnIdle {
- assertThat(state.layoutInfo.totalItemsCount).isEqualTo(20)
- }
+ rule.runOnIdle { assertThat(state.layoutInfo.totalItemsCount).isEqualTo(20) }
}
private fun ScalingLazyListLayoutInfo.assertVisibleItems(
@@ -1247,5 +1072,4 @@
}
}
-@Stable
-public class StableRef<T>(var value: T)
+@Stable public class StableRef<T>(var value: T)
diff --git a/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/rotary/RotaryTest.kt b/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/rotary/RotaryTest.kt
index 03f2177..2ade292 100644
--- a/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/rotary/RotaryTest.kt
+++ b/wear/compose/compose-foundation/src/androidTest/kotlin/androidx/wear/compose/foundation/rotary/RotaryTest.kt
@@ -50,8 +50,7 @@
// TODO(b/278705775): Add more tests to check Rotary Snap behavior
class RotaryScrollTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
private var itemSizePx: Float = 50f
private var itemSizeDp: Dp = Dp.Infinity
@@ -61,9 +60,7 @@
@Before
fun before() {
- with(rule.density) {
- itemSizeDp = itemSizePx.toDp()
- }
+ with(rule.density) { itemSizeDp = itemSizePx.toDp() }
}
@Test
@@ -71,17 +68,11 @@
var itemIndex = 0
testScroll(
- beforeScroll = {
- itemIndex = state.firstVisibleItemIndex
- },
- rotaryAction = {
- rotateToScrollVertically(itemSizePx)
- }
+ beforeScroll = { itemIndex = state.firstVisibleItemIndex },
+ rotaryAction = { rotateToScrollVertically(itemSizePx) }
)
- rule.runOnIdle {
- Truth.assertThat(state.firstVisibleItemIndex).isEqualTo(itemIndex + 1)
- }
+ rule.runOnIdle { Truth.assertThat(state.firstVisibleItemIndex).isEqualTo(itemIndex + 1) }
}
@Test
@@ -89,9 +80,7 @@
var itemIndex = 0
testScroll(
- beforeScroll = {
- itemIndex = state.firstVisibleItemIndex
- },
+ beforeScroll = { itemIndex = state.firstVisibleItemIndex },
rotaryAction = {
rotateToScrollVertically(itemSizePx)
advanceEventTime(20)
@@ -106,9 +95,7 @@
}
)
- rule.runOnIdle {
- Truth.assertThat(state.firstVisibleItemIndex).isEqualTo(itemIndex + 2)
- }
+ rule.runOnIdle { Truth.assertThat(state.firstVisibleItemIndex).isEqualTo(itemIndex + 2) }
}
@Test
@@ -116,9 +103,7 @@
var itemIndex = 0
testScroll(
- beforeScroll = {
- itemIndex = state.firstVisibleItemIndex
- },
+ beforeScroll = { itemIndex = state.firstVisibleItemIndex },
rotaryAction = {
// Quickly scroll up and down - we should scroll only by 1 item forward
rotateToScrollVertically(itemSizePx)
@@ -135,9 +120,7 @@
lowRes = true
)
- rule.runOnIdle {
- Truth.assertThat(state.firstVisibleItemIndex).isEqualTo(itemIndex + 1)
- }
+ rule.runOnIdle { Truth.assertThat(state.firstVisibleItemIndex).isEqualTo(itemIndex + 1) }
}
@Test
@@ -145,9 +128,7 @@
var itemIndex = 0
testScroll(
- beforeScroll = {
- itemIndex = state.firstVisibleItemIndex
- },
+ beforeScroll = { itemIndex = state.firstVisibleItemIndex },
rotaryAction = {
rotateToScrollVertically(itemSizePx)
advanceEventTime(300)
@@ -155,9 +136,7 @@
}
)
- rule.runOnIdle {
- Truth.assertThat(state.firstVisibleItemIndex).isEqualTo(itemIndex + 2)
- }
+ rule.runOnIdle { Truth.assertThat(state.firstVisibleItemIndex).isEqualTo(itemIndex + 2) }
}
@Test
@@ -165,9 +144,7 @@
var itemIndex = 0
testScroll(
- beforeScroll = {
- itemIndex = state.firstVisibleItemIndex
- },
+ beforeScroll = { itemIndex = state.firstVisibleItemIndex },
rotaryAction = {
// Scroll forwards by 2 items
rotateToScrollVertically(itemSizePx)
@@ -192,9 +169,7 @@
var itemIndex = 0
testScroll(
- beforeScroll = {
- itemIndex = state.firstVisibleItemIndex
- },
+ beforeScroll = { itemIndex = state.firstVisibleItemIndex },
rotaryAction = {
// To produce fling we need to send 3 events,
// which will be increasing the scroll velocity.
@@ -220,9 +195,7 @@
var itemIndex = 0
testScroll(
- beforeScroll = {
- itemIndex = state.firstVisibleItemIndex
- },
+ beforeScroll = { itemIndex = state.firstVisibleItemIndex },
rotaryAction = {
// Fling will not be produced when scroll velocity decreases with each event
// By decreasing the distance with each event we're
@@ -251,9 +224,7 @@
var itemIndex = 0
testScroll(
- beforeScroll = {
- itemIndex = state.firstVisibleItemIndex
- },
+ beforeScroll = { itemIndex = state.firstVisibleItemIndex },
rotaryAction = {
// Fling will not be produced when scroll velocity decreases with each event
// By decreasing the distance with each event we're
@@ -291,10 +262,8 @@
// Mocking low-res flag
val mockContext = spy(context)
val mockPackageManager = spy(context.packageManager)
- `when`(
- mockPackageManager
- .hasSystemFeature("android.hardware.rotaryencoder.lowres")
- ).thenReturn(lowRes)
+ `when`(mockPackageManager.hasSystemFeature("android.hardware.rotaryencoder.lowres"))
+ .thenReturn(lowRes)
doReturn(mockPackageManager).`when`(mockContext).packageManager
@@ -312,9 +281,7 @@
}
rule.runOnIdle { focusRequester.requestFocus() }
beforeScroll()
- rule.onNodeWithTag(TEST_TAG).performRotaryScrollInput {
- rotaryAction()
- }
+ rule.onNodeWithTag(TEST_TAG).performRotaryScrollInput { rotaryAction() }
}
@Composable
@@ -325,18 +292,11 @@
scrollableState: LazyListState,
) {
LazyColumn(
- modifier = Modifier
- .size(200.dp)
- .testTag(TEST_TAG)
- .rotaryScrollable(behavior, focusRequester),
+ modifier =
+ Modifier.size(200.dp).testTag(TEST_TAG).rotaryScrollable(behavior, focusRequester),
state = scrollableState,
) {
- items(300) {
- BasicText(
- modifier = Modifier.height(itemSize),
- text = "Item #$it"
- )
- }
+ items(300) { BasicText(modifier = Modifier.height(itemSize), text = "Item #$it") }
}
}
diff --git a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/BasicCurvedText.kt b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/BasicCurvedText.kt
index 733322a..39b120d 100644
--- a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/BasicCurvedText.kt
+++ b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/BasicCurvedText.kt
@@ -55,21 +55,20 @@
import kotlin.math.sqrt
/**
- * [basicCurvedText] is a component allowing developers to easily write curved text following
- * the curvature a circle (usually at the edge of a circular screen).
- * [basicCurvedText] can be only created within a [CurvedLayout] since it's not a composable.
+ * [basicCurvedText] is a component allowing developers to easily write curved text following the
+ * curvature a circle (usually at the edge of a circular screen). [basicCurvedText] can be only
+ * created within a [CurvedLayout] since it's not a composable.
*
* @sample androidx.wear.compose.foundation.samples.CurvedAndNormalText
*
* @param text The text to display
* @param modifier The [CurvedModifier] to apply to this curved text.
- * @param angularDirection Specify if the text is laid out clockwise or anti-clockwise, and if
- * those needs to be reversed in a Rtl layout.
- * If not specified, it will be inherited from the enclosing [curvedRow] or [CurvedLayout]
- * See [CurvedDirection.Angular].
+ * @param angularDirection Specify if the text is laid out clockwise or anti-clockwise, and if those
+ * needs to be reversed in a Rtl layout. If not specified, it will be inherited from the enclosing
+ * [curvedRow] or [CurvedLayout] See [CurvedDirection.Angular].
* @param overflow How visual overflow should be handled.
* @param style A @Composable factory to provide the style to use. This composable SHOULDN'T
- * generate any compose nodes.
+ * generate any compose nodes.
*/
public fun CurvedScope.basicCurvedText(
text: String,
@@ -77,27 +76,30 @@
angularDirection: CurvedDirection.Angular? = null,
overflow: TextOverflow = TextOverflow.Clip,
style: @Composable () -> CurvedTextStyle = { CurvedTextStyle() }
-) = add(CurvedTextChild(
- text,
- curvedLayoutDirection.copy(overrideAngular = angularDirection).absoluteClockwise(),
- style,
- overflow
-), modifier)
+) =
+ add(
+ CurvedTextChild(
+ text,
+ curvedLayoutDirection.copy(overrideAngular = angularDirection).absoluteClockwise(),
+ style,
+ overflow
+ ),
+ modifier
+ )
/**
- * [basicCurvedText] is a component allowing developers to easily write curved text following
- * the curvature a circle (usually at the edge of a circular screen).
- * [basicCurvedText] can be only created within a [CurvedLayout] since it's not a composable.
+ * [basicCurvedText] is a component allowing developers to easily write curved text following the
+ * curvature a circle (usually at the edge of a circular screen). [basicCurvedText] can be only
+ * created within a [CurvedLayout] since it's not a composable.
*
* @sample androidx.wear.compose.foundation.samples.CurvedAndNormalText
*
* @param text The text to display
* @param style A style to use.
* @param modifier The [CurvedModifier] to apply to this curved text.
- * @param angularDirection Specify if the text is laid out clockwise or anti-clockwise, and if
- * those needs to be reversed in a Rtl layout.
- * If not specified, it will be inherited from the enclosing [curvedRow] or [CurvedLayout]
- * See [CurvedDirection.Angular].
+ * @param angularDirection Specify if the text is laid out clockwise or anti-clockwise, and if those
+ * needs to be reversed in a Rtl layout. If not specified, it will be inherited from the enclosing
+ * [curvedRow] or [CurvedLayout] See [CurvedDirection.Angular].
* @param overflow How visual overflow should be handled.
*/
public fun CurvedScope.basicCurvedText(
@@ -136,14 +138,8 @@
Box(Modifier.semantics { contentDescription = text })
}
- override fun CurvedMeasureScope.initializeMeasure(
- measurables: Iterator<Measurable>
- ) {
- delegate.updateIfNeeded(
- text,
- clockwise,
- actualStyle.fontSize.toPx()
- )
+ override fun CurvedMeasureScope.initializeMeasure(measurables: Iterator<Measurable>) {
+ delegate.updateIfNeeded(text, clockwise, actualStyle.fontSize.toPx())
// Size the compose-ui node reasonably.
@@ -166,9 +162,17 @@
val width = delegate.textWidth.coerceAtMost(maxWidth).roundToInt()
// Measure the corresponding measurable.
- placeable = measurables.next().measure(Constraints(
- minWidth = width, maxWidth = width, minHeight = height, maxHeight = height
- ))
+ placeable =
+ measurables
+ .next()
+ .measure(
+ Constraints(
+ minWidth = width,
+ maxWidth = width,
+ minHeight = height,
+ maxHeight = height
+ )
+ )
}
override fun doEstimateThickness(maxRadius: Float): Float = delegate.textHeight
@@ -214,9 +218,7 @@
place(placeable, layoutInfo!!, parentSweepRadians, clockwise = false)
}
-/**
- * Used to cache computations and objects with expensive construction (Android's Paint & Path)
- */
+/** Used to cache computations and objects with expensive construction (Android's Paint & Path) */
internal class CurvedTextDelegate {
private var text: String = ""
private var clockwise: Boolean = true
@@ -235,16 +237,8 @@
var lastLayoutInfo: CurvedLayoutInfo? = null
var lastParentSweepRadians: Float = 0f
- fun updateIfNeeded(
- text: String,
- clockwise: Boolean,
- fontSizePx: Float
- ) {
- if (
- text != this.text ||
- clockwise != this.clockwise ||
- fontSizePx != this.fontSizePx
- ) {
+ fun updateIfNeeded(text: String, clockwise: Boolean, fontSizePx: Float) {
+ if (text != this.text || clockwise != this.clockwise || fontSizePx != this.fontSizePx) {
this.text = text
this.clockwise = clockwise
this.fontSizePx = fontSizePx
@@ -262,16 +256,19 @@
fontSynthesis: FontSynthesis?
) {
val fontFamilyResolver = LocalFontFamilyResolver.current
- typeFace = remember(fontFamily, fontWeight, fontStyle, fontSynthesis, fontFamilyResolver) {
- derivedStateOf {
- fontFamilyResolver.resolveAsTypeface(
- fontFamily,
- fontWeight ?: FontWeight.Normal,
- fontStyle ?: FontStyle.Normal,
- fontSynthesis ?: FontSynthesis.All
- ).value
+ typeFace =
+ remember(fontFamily, fontWeight, fontStyle, fontSynthesis, fontFamilyResolver) {
+ derivedStateOf {
+ fontFamilyResolver
+ .resolveAsTypeface(
+ fontFamily,
+ fontWeight ?: FontWeight.Normal,
+ fontStyle ?: FontStyle.Normal,
+ fontSynthesis ?: FontSynthesis.All
+ )
+ .value
+ }
}
- }
updateTypeFace()
}
@@ -281,8 +278,7 @@
textWidth = rect.width().toFloat()
textHeight = -paint.fontMetrics.top + paint.fontMetrics.bottom
- baseLinePosition =
- if (clockwise) -paint.fontMetrics.top else paint.fontMetrics.bottom
+ baseLinePosition = if (clockwise) -paint.fontMetrics.top else paint.fontMetrics.bottom
}
private fun updateTypeFace() {
@@ -295,16 +291,17 @@
}
private fun updatePathsIfNeeded(layoutInfo: CurvedLayoutInfo, parentSweepRadians: Float) {
- if (layoutInfo != lastLayoutInfo ||
- abs(lastParentSweepRadians - parentSweepRadians) > 1e-4) {
+ if (
+ layoutInfo != lastLayoutInfo || abs(lastParentSweepRadians - parentSweepRadians) > 1e-4
+ ) {
lastLayoutInfo = layoutInfo
lastParentSweepRadians = parentSweepRadians
with(layoutInfo) {
val clockwiseFactor = if (clockwise) 1f else -1f
- val sweepDegree = min(sweepRadians, parentSweepRadians)
- .toDegrees().coerceAtMost(360f)
+ val sweepDegree =
+ min(sweepRadians, parentSweepRadians).toDegrees().coerceAtMost(360f)
val centerX = centerOffset.x
val centerY = centerOffset.y
@@ -317,7 +314,8 @@
centerX + outerRadius,
centerY + outerRadius,
startAngleRadians.toDegrees(),
- sweepDegree, false
+ sweepDegree,
+ false
)
backgroundPath.arcTo(
centerX - innerRadius,
@@ -325,7 +323,8 @@
centerX + innerRadius,
centerY + innerRadius,
startAngleRadians.toDegrees() + sweepDegree,
- -sweepDegree, false
+ -sweepDegree,
+ false
)
backgroundPath.close()
@@ -335,8 +334,7 @@
centerY - measureRadius,
centerX + measureRadius,
centerY + measureRadius,
- startAngleRadians.toDegrees() +
- (if (clockwise) 0f else sweepDegree),
+ startAngleRadians.toDegrees() + (if (clockwise) 0f else sweepDegree),
clockwiseFactor * sweepDegree
)
}
@@ -360,18 +358,21 @@
}
paint.color = color.toArgb()
- val actualText = if (
- // Float arithmetic can make the parentSweepRadians slightly smaller
- layoutInfo.sweepRadians <= parentSweepRadians + 0.001f ||
- overflow == TextOverflow.Visible
- ) {
- text
- } else {
- ellipsize(
- text, TextPaint(paint), overflow == TextOverflow.Ellipsis,
- (parentSweepRadians * layoutInfo.measureRadius).roundToInt()
- )
- }
+ val actualText =
+ if (
+ // Float arithmetic can make the parentSweepRadians slightly smaller
+ layoutInfo.sweepRadians <= parentSweepRadians + 0.001f ||
+ overflow == TextOverflow.Visible
+ ) {
+ text
+ } else {
+ ellipsize(
+ text,
+ TextPaint(paint),
+ overflow == TextOverflow.Ellipsis,
+ (parentSweepRadians * layoutInfo.measureRadius).roundToInt()
+ )
+ }
canvas.nativeCanvas.drawTextOnPath(actualText, textPath, 0f, 0f, paint)
}
}
@@ -384,18 +385,19 @@
): String {
if (addEllipsis) {
return TextUtils.ellipsize(
- text,
- paint,
- ellipsizedWidth.toFloat(),
- TextUtils.TruncateAt.END
- ).toString()
+ text,
+ paint,
+ ellipsizedWidth.toFloat(),
+ TextUtils.TruncateAt.END
+ )
+ .toString()
}
- val layout = StaticLayout.Builder
- .obtain(text, 0, text.length, paint, ellipsizedWidth)
- .setEllipsize(null)
- .setMaxLines(1)
- .build()
+ val layout =
+ StaticLayout.Builder.obtain(text, 0, text.length, paint, ellipsizedWidth)
+ .setEllipsize(null)
+ .setMaxLines(1)
+ .build()
// Cut text that it's too big when in TextOverFlow.Clip mode.
return text.substring(0, layout.getLineEnd(0))
diff --git a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/BasicSwipeToDismissBox.kt b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/BasicSwipeToDismissBox.kt
index 009334f..2e079b3 100644
--- a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/BasicSwipeToDismissBox.kt
+++ b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/BasicSwipeToDismissBox.kt
@@ -69,9 +69,11 @@
* background (only displayed during the swipe gesture) and the foreground content.
*
* Example of a [BasicSwipeToDismissBox] with stateful composables:
+ *
* @sample androidx.wear.compose.foundation.samples.StatefulSwipeToDismissBox
*
* Example of using [Modifier.edgeSwipeToDismiss] with [BasicSwipeToDismissBox]
+ *
* @sample androidx.wear.compose.foundation.samples.EdgeSwipeForSwipeToDismiss
*
* For more information, see the
@@ -84,19 +86,19 @@
*
* @param state [State] containing information about ongoing swipe or animation.
* @param modifier [Modifier] for this component.
- * @param backgroundKey [key] which identifies the content currently composed in
- * the [content] block when isBackground == true. Provide the backgroundKey if your background
- * content will be displayed as a foreground after the swipe animation ends
- * (as is common when [BasicSwipeToDismissBox] is used for the navigation). This allows
- * remembered state to be correctly moved between background and foreground.
- * @param contentKey [key] which identifies the content currently composed in the
- * [content] block when isBackground == false. See [backgroundKey].
- * @param userSwipeEnabled Whether the swipe gesture is enabled.
- * (e.g. when there is no background screen, set userSwipeEnabled = false)
- * @param content Slot for content, with the isBackground parameter enabling content to be
- * displayed behind the foreground content - the background is normally hidden, is shown behind a
- * scrim during the swipe gesture, and is shown without scrim once the finger passes the
- * swipe-to-dismiss threshold.
+ * @param backgroundKey [key] which identifies the content currently composed in the [content] block
+ * when isBackground == true. Provide the backgroundKey if your background content will be
+ * displayed as a foreground after the swipe animation ends (as is common when
+ * [BasicSwipeToDismissBox] is used for the navigation). This allows remembered state to be
+ * correctly moved between background and foreground.
+ * @param contentKey [key] which identifies the content currently composed in the [content] block
+ * when isBackground == false. See [backgroundKey].
+ * @param userSwipeEnabled Whether the swipe gesture is enabled. (e.g. when there is no background
+ * screen, set userSwipeEnabled = false)
+ * @param content Slot for content, with the isBackground parameter enabling content to be displayed
+ * behind the foreground content - the background is normally hidden, is shown behind a scrim
+ * during the swipe gesture, and is shown without scrim once the finger passes the
+ * swipe-to-dismiss threshold.
*/
@OptIn(ExperimentalWearFoundationApi::class)
@Composable
@@ -110,51 +112,47 @@
content: @Composable BoxScope.(isBackground: Boolean) -> Unit
) {
val density = LocalDensity.current
- val maxWidthPx = with(density) {
- LocalConfiguration.current.screenWidthDp.dp.toPx()
- }
+ val maxWidthPx = with(density) { LocalConfiguration.current.screenWidthDp.dp.toPx() }
SideEffect {
- val anchors = mapOf(
- SwipeToDismissValue.Default to 0f,
- SwipeToDismissValue.Dismissed to maxWidthPx
- )
+ val anchors =
+ mapOf(SwipeToDismissValue.Default to 0f, SwipeToDismissValue.Dismissed to maxWidthPx)
state.swipeableState.density = density
state.swipeableState.updateAnchors(anchors)
}
Box(
- modifier = modifier
- .fillMaxSize()
- .then(
- if (userSwipeEnabled && Build.VERSION.SDK_INT > Build.VERSION_CODES.TIRAMISU) {
- Modifier.systemGestureExclusion()
- } else {
- Modifier
- }
- )
- .swipeableV2(
- state = state.swipeableState,
- orientation = Orientation.Horizontal,
- enabled = userSwipeEnabled
- )
+ modifier =
+ modifier
+ .fillMaxSize()
+ .then(
+ if (userSwipeEnabled && Build.VERSION.SDK_INT > Build.VERSION_CODES.TIRAMISU) {
+ Modifier.systemGestureExclusion()
+ } else {
+ Modifier
+ }
+ )
+ .swipeableV2(
+ state = state.swipeableState,
+ orientation = Orientation.Horizontal,
+ enabled = userSwipeEnabled
+ )
) {
val isRound = isRoundDevice()
val backgroundScrimColor = LocalSwipeToDismissBackgroundScrimColor.current
val contentScrimColor = LocalSwipeToDismissContentScrimColor.current
- val progress by remember(state) {
- derivedStateOf {
- if (state.swipeableState.offset?.isNaN() == true || maxWidthPx == 0f) {
- 0f
- } else {
- ((state.swipeableState.offset ?: 0f) / maxWidthPx).coerceIn(0f, 1f)
+ val progress by
+ remember(state) {
+ derivedStateOf {
+ if (state.swipeableState.offset?.isNaN() == true || maxWidthPx == 0f) {
+ 0f
+ } else {
+ ((state.swipeableState.offset ?: 0f) / maxWidthPx).coerceIn(0f, 1f)
+ }
}
}
- }
val isSwiping by remember { derivedStateOf { progress > 0 } }
- var squeezeMode by remember {
- mutableStateOf(true)
- }
+ var squeezeMode by remember { mutableStateOf(true) }
LaunchedEffect(state.isAnimationRunning) {
if (state.targetValue == SwipeToDismissValue.Dismissed) {
squeezeMode = false
@@ -172,39 +170,39 @@
key(if (isBackground) backgroundKey else contentKey) {
if (!isBackground || (userSwipeEnabled && isSwiping)) {
HierarchicalFocusCoordinator(requiresFocus = { !isBackground }) {
- Box(Modifier
- .fillMaxSize()
- .then(
- if (!isBackground) {
- Modifier
- .graphicsLayer {
- val scale = lerp(SCALE_MAX, SCALE_MIN, progress)
- .coerceIn(SCALE_MIN, SCALE_MAX)
- val squeezeOffset =
- max(0f, (1f - scale) * maxWidthPx / 2f)
+ Box(
+ Modifier.fillMaxSize()
+ .then(
+ if (!isBackground) {
+ Modifier.graphicsLayer {
+ val scale =
+ lerp(SCALE_MAX, SCALE_MIN, progress)
+ .coerceIn(SCALE_MIN, SCALE_MAX)
+ val squeezeOffset =
+ max(0f, (1f - scale) * maxWidthPx / 2f)
- val translationX =
- if (squeezeMode) {
- // Squeeze
- squeezeOffset
- } else {
- // slide
- lerp(
- squeezeOffset,
- maxWidthPx,
- max(0f, progress - 0.7f) / 0.3f
- )
- }
+ val translationX =
+ if (squeezeMode) {
+ // Squeeze
+ squeezeOffset
+ } else {
+ // slide
+ lerp(
+ squeezeOffset,
+ maxWidthPx,
+ max(0f, progress - 0.7f) / 0.3f
+ )
+ }
- this.translationX = translationX
- scaleX = scale
- scaleY = scale
- clip = isRound && translationX > 0
- shape = if (isRound) CircleShape else RectangleShape
- }
- .background(backgroundScrimColor)
- } else Modifier
- )
+ this.translationX = translationX
+ scaleX = scale
+ scaleY = scale
+ clip = isRound && translationX > 0
+ shape = if (isRound) CircleShape else RectangleShape
+ }
+ .background(backgroundScrimColor)
+ } else Modifier
+ )
) {
// We use the repeat loop above and call content at this location
// for both background and foreground so that any persistence
@@ -213,19 +211,20 @@
content(isBackground)
Canvas(Modifier.fillMaxSize()) {
- val color = if (isBackground) {
- backgroundScrimColor
- .copy(
- alpha = (MAX_BACKGROUND_SCRIM_ALPHA * (1 - progress))
- .coerceIn(0f, 1f)
+ val color =
+ if (isBackground) {
+ backgroundScrimColor.copy(
+ alpha =
+ (MAX_BACKGROUND_SCRIM_ALPHA * (1 - progress))
+ .coerceIn(0f, 1f)
)
- } else {
- contentScrimColor
- .copy(
- alpha = min(MAX_CONTENT_SCRIM_ALPHA, progress / 2f)
- .coerceIn(0f, 1f)
+ } else {
+ contentScrimColor.copy(
+ alpha =
+ min(MAX_CONTENT_SCRIM_ALPHA, progress / 2f)
+ .coerceIn(0f, 1f)
)
- }
+ }
drawRect(color = color)
}
}
@@ -237,14 +236,16 @@
}
/**
- * [BasicSwipeToDismissBox] that handles the swipe-to-dismiss gesture.
- * This overload takes an [onDismissed] parameter which is used to execute a command when the
- * swipe to dismiss has completed, such as navigating to another screen.
+ * [BasicSwipeToDismissBox] that handles the swipe-to-dismiss gesture. This overload takes an
+ * [onDismissed] parameter which is used to execute a command when the swipe to dismiss has
+ * completed, such as navigating to another screen.
*
* Example of a simple SwipeToDismissBox:
+ *
* @sample androidx.wear.compose.foundation.samples.SimpleSwipeToDismissBox
*
* Example of using [Modifier.edgeSwipeToDismiss] with [BasicSwipeToDismissBox]
+ *
* @sample androidx.wear.compose.foundation.samples.EdgeSwipeForSwipeToDismiss
*
* For more information, see the
@@ -258,19 +259,19 @@
* @param onDismissed Executes when the swipe to dismiss has completed.
* @param modifier [Modifier] for this component.
* @param state [State] containing information about ongoing swipe or animation.
- * @param backgroundKey [key] which identifies the content currently composed in
- * the [content] block when isBackground == true. Provide the backgroundKey if your background
- * content will be displayed as a foreground after the swipe animation ends
- * (as is common when [BasicSwipeToDismissBox] is used for the navigation). This allows
- * remembered state to be correctly moved between background and foreground.
- * @param contentKey [key] which identifies the content currently composed in the
- * [content] block when isBackground == false. See [backgroundKey].
- * @param userSwipeEnabled Whether the swipe gesture is enabled.
- * (e.g. when there is no background screen, set userSwipeEnabled = false)
- * @param content Slot for content, with the isBackground parameter enabling content to be
- * displayed behind the foreground content - the background is normally hidden, is shown behind a
- * scrim during the swipe gesture, and is shown without scrim once the finger passes the
- * swipe-to-dismiss threshold.
+ * @param backgroundKey [key] which identifies the content currently composed in the [content] block
+ * when isBackground == true. Provide the backgroundKey if your background content will be
+ * displayed as a foreground after the swipe animation ends (as is common when
+ * [BasicSwipeToDismissBox] is used for the navigation). This allows remembered state to be
+ * correctly moved between background and foreground.
+ * @param contentKey [key] which identifies the content currently composed in the [content] block
+ * when isBackground == false. See [backgroundKey].
+ * @param userSwipeEnabled Whether the swipe gesture is enabled. (e.g. when there is no background
+ * screen, set userSwipeEnabled = false)
+ * @param content Slot for content, with the isBackground parameter enabling content to be displayed
+ * behind the foreground content - the background is normally hidden, is shown behind a scrim
+ * during the swipe gesture, and is shown without scrim once the finger passes the
+ * swipe-to-dismiss threshold.
*/
@OptIn(ExperimentalWearFoundationApi::class)
@Composable
@@ -323,23 +324,20 @@
/**
* The target value of the state.
*
- * If a swipe is in progress, this is the value that the state would animate to if the
- * swipe finished. If an animation is running, this is the target value of that animation.
- * Finally, if no swipe or animation is in progress, this is the same as the [currentValue].
+ * If a swipe is in progress, this is the value that the state would animate to if the swipe
+ * finished. If an animation is running, this is the target value of that animation. Finally, if
+ * no swipe or animation is in progress, this is the same as the [currentValue].
*/
val targetValue: SwipeToDismissValue
get() = swipeableState.targetValue
- /**
- * Whether the state is currently animating.
- */
+ /** Whether the state is currently animating. */
val isAnimationRunning: Boolean
get() = swipeableState.isAnimationRunning
internal fun edgeNestedScrollConnection(
edgeSwipeState: State<EdgeSwipeState>
- ): NestedScrollConnection =
- swipeableState.edgeNestedScrollConnection(edgeSwipeState)
+ ): NestedScrollConnection = swipeableState.edgeNestedScrollConnection(edgeSwipeState)
/**
* Set the state without any animation and suspend until it's set
@@ -358,8 +356,9 @@
val delta = available.x
// If swipeState = SwipeState.SWIPING_TO_DISMISS - perform swipeToDismiss
// drag and consume everything
- return if (edgeSwipeState.value == EdgeSwipeState.SwipingToDismiss &&
- source == NestedScrollSource.Drag
+ return if (
+ edgeSwipeState.value == EdgeSwipeState.SwipingToDismiss &&
+ source == NestedScrollSource.Drag
) {
dispatchRawDelta(delta)
available
@@ -377,13 +376,13 @@
override suspend fun onPreFling(available: Velocity): Velocity {
val toFling = available.x
// Consumes fling by SwipeToDismiss
- return if (edgeSwipeState.value == EdgeSwipeState.SwipingToDismiss ||
- edgeSwipeState.value == EdgeSwipeState.SwipeToDismissInProgress
+ return if (
+ edgeSwipeState.value == EdgeSwipeState.SwipingToDismiss ||
+ edgeSwipeState.value == EdgeSwipeState.SwipeToDismissInProgress
) {
settle(velocity = toFling)
available
- } else
- Velocity.Zero
+ } else Velocity.Zero
}
override suspend fun onPostFling(
@@ -396,12 +395,13 @@
}
}
- internal val swipeableState = SwipeableV2State(
- initialValue = SwipeToDismissValue.Default,
- animationSpec = animationSpec,
- confirmValueChange = confirmStateChange,
- positionalThreshold = fractionalPositionalThreshold(SWIPE_THRESHOLD)
- )
+ internal val swipeableState =
+ SwipeableV2State(
+ initialValue = SwipeToDismissValue.Default,
+ animationSpec = animationSpec,
+ confirmValueChange = confirmStateChange,
+ positionalThreshold = fractionalPositionalThreshold(SWIPE_THRESHOLD)
+ )
}
/**
@@ -420,9 +420,7 @@
}
}
-/**
- * Contains defaults for [BasicSwipeToDismissBox].
- */
+/** Contains defaults for [BasicSwipeToDismissBox]. */
object SwipeToDismissBoxDefaults {
/**
* The default animation that will be used to animate to a new state after the swipe gesture.
@@ -431,52 +429,43 @@
val AnimationSpec = SwipeableV2Defaults.AnimationSpec
/**
- * The default width of the area which might trigger a swipe
- * with [edgeSwipeToDismiss] modifier
+ * The default width of the area which might trigger a swipe with [edgeSwipeToDismiss] modifier
*/
val EdgeWidth = 30.dp
}
-/**
- * Keys used to persistent state in [BasicSwipeToDismissBox].
- */
+/** Keys used to persistent state in [BasicSwipeToDismissBox]. */
enum class SwipeToDismissKeys {
/**
- * The default background key to identify the content displayed by the content block
- * when isBackground == true. Specifying a background key instead of using the default
- * allows remembered state to be correctly moved between background and foreground.
+ * The default background key to identify the content displayed by the content block when
+ * isBackground == true. Specifying a background key instead of using the default allows
+ * remembered state to be correctly moved between background and foreground.
*/
Background,
/**
- * The default content key to identify the content displayed by the content block
- * when isBackground == false. Specifying a background key instead of using the default
- * allows remembered state to be correctly moved between background and foreground.
+ * The default content key to identify the content displayed by the content block when
+ * isBackground == false. Specifying a background key instead of using the default allows
+ * remembered state to be correctly moved between background and foreground.
*/
Content
}
-/**
- * States used as targets for the anchor points for swipe-to-dismiss.
- */
+/** States used as targets for the anchor points for swipe-to-dismiss. */
enum class SwipeToDismissValue {
- /**
- * The state of the SwipeToDismissBox before the swipe started.
- */
+ /** The state of the SwipeToDismissBox before the swipe started. */
Default,
- /**
- * The state of the SwipeToDismissBox after the swipe passes the swipe-to-dismiss threshold.
- */
+ /** The state of the SwipeToDismissBox after the swipe passes the swipe-to-dismiss threshold. */
Dismissed
}
/**
- * Limits swipe to dismiss to be active from the edge of the viewport only. Used when the center
- * of the screen needs to be able to handle horizontal paging, such as 2-d scrolling a Map
- * or swiping horizontally between pages. Swipe to the right is intercepted on the left
- * part of the viewport with width specified by [edgeWidth], with other touch events
- * ignored - vertical scroll, click, long click, etc.
+ * Limits swipe to dismiss to be active from the edge of the viewport only. Used when the center of
+ * the screen needs to be able to handle horizontal paging, such as 2-d scrolling a Map or swiping
+ * horizontally between pages. Swipe to the right is intercepted on the left part of the viewport
+ * with width specified by [edgeWidth], with other touch events ignored - vertical scroll, click,
+ * long click, etc.
*
* Currently Edge swipe, like swipe to dismiss, is only supported on the left part of the viewport
* regardless of layout direction as content is swiped away from left to right.
@@ -485,10 +474,11 @@
* [BasicSwipeToDismissBox] which is using the same [SwipeToDismissBoxState] instance.
*
* Example of a modifier usage with SwipeToDismiss
+ *
* @sample androidx.wear.compose.foundation.samples.EdgeSwipeForSwipeToDismiss
*
* @param swipeToDismissBoxState State of [BasicSwipeToDismissBox]. Used to trigger swipe gestures
- * on SwipeToDismissBox.
+ * on SwipeToDismissBox.
* @param edgeWidth Width of the edge zone in which the swipe will be recognised.
*/
fun Modifier.edgeSwipeToDismiss(
@@ -496,11 +486,12 @@
edgeWidth: Dp = SwipeToDismissBoxDefaults.EdgeWidth
): Modifier =
composed(
- inspectorInfo = debugInspectorInfo {
- name = "edgeSwipeToDismiss"
- properties["swipeToDismissBoxState"] = swipeToDismissBoxState
- properties["edgeWidth"] = edgeWidth
- }
+ inspectorInfo =
+ debugInspectorInfo {
+ name = "edgeSwipeToDismiss"
+ properties["swipeToDismissBoxState"] = swipeToDismissBoxState
+ properties["edgeWidth"] = edgeWidth
+ }
) {
// Tracks the current swipe status
val edgeSwipeState = remember { mutableStateOf(EdgeSwipeState.WaitingForTouch) }
@@ -527,18 +518,14 @@
edgeSwipeState.value =
if (change.position.x < edgeWidth.toPx())
EdgeSwipeState.EdgeClickedWaitingForDirection
- else
- EdgeSwipeState.SwipingToPage
+ else EdgeSwipeState.SwipingToPage
}
-
EdgeSwipeState.EdgeClickedWaitingForDirection -> {
edgeSwipeState.value =
if (change.position.x < change.previousPosition.x)
EdgeSwipeState.SwipingToPage
- else
- EdgeSwipeState.SwipingToDismiss
+ else EdgeSwipeState.SwipingToDismiss
}
-
else -> {} // Do nothing
}
// When finger is up - reset swipeState to WaitingForTouch
@@ -548,21 +535,17 @@
edgeSwipeState.value =
if (edgeSwipeState.value == EdgeSwipeState.SwipingToDismiss)
EdgeSwipeState.SwipeToDismissInProgress
- else
- EdgeSwipeState.WaitingForTouch
+ else EdgeSwipeState.WaitingForTouch
}
}
}
}
}
}
- pointerInput(edgeWidth, nestedPointerInput)
- .nestedScroll(nestedScrollConnection)
+ pointerInput(edgeWidth, nestedPointerInput).nestedScroll(nestedScrollConnection)
}
-/**
- * An enum which represents a current state of swipe action.
- */
+/** An enum which represents a current state of swipe action. */
internal enum class EdgeSwipeState {
// Waiting for touch, edge was not touched before.
WaitingForTouch,
@@ -586,5 +569,4 @@
private const val SCALE_MIN = 0.7f
private const val MAX_CONTENT_SCRIM_ALPHA = 0.3f
private const val MAX_BACKGROUND_SCRIM_ALPHA = 0.5f
-private val SWIPE_TO_DISMISS_BOX_ANIMATION_SPEC =
- TweenSpec<Float>(200, 0, LinearOutSlowInEasing)
+private val SWIPE_TO_DISMISS_BOX_ANIMATION_SPEC = TweenSpec<Float>(200, 0, LinearOutSlowInEasing)
diff --git a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/CompositionLocals.kt b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/CompositionLocals.kt
index ba80a25e..5723b19 100644
--- a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/CompositionLocals.kt
+++ b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/CompositionLocals.kt
@@ -41,8 +41,8 @@
import kotlinx.coroutines.launch
/**
- * CompositionLocal for global reduce-motion setting, which turns off animations and
- * screen movements. To use, call LocalReduceMotion.current.enabled(), which returns a Boolean.
+ * CompositionLocal for global reduce-motion setting, which turns off animations and screen
+ * movements. To use, call LocalReduceMotion.current.enabled(), which returns a Boolean.
*/
@get:ExperimentalWearFoundationApi
@Suppress("OPT_IN_MARKER_ON_WRONG_TARGET")
@@ -61,24 +61,26 @@
* Defaults to [Color.Black] if not explicitly set.
*/
val LocalSwipeToDismissBackgroundScrimColor: ProvidableCompositionLocal<Color> =
- compositionLocalOf { Color.Black }
+ compositionLocalOf {
+ Color.Black
+ }
/**
* CompositionLocal containing the content scrim color of [BasicSwipeToDismissBox].
*
* Defaults to [Color.Black] if not explicitly set.
*/
-val LocalSwipeToDismissContentScrimColor: ProvidableCompositionLocal<Color> =
- compositionLocalOf { Color.Black }
+val LocalSwipeToDismissContentScrimColor: ProvidableCompositionLocal<Color> = compositionLocalOf {
+ Color.Black
+}
/**
- * ReduceMotion provides a means for callers to determine whether an app should turn off
- * animations and screen movement.
+ * ReduceMotion provides a means for callers to determine whether an app should turn off animations
+ * and screen movement.
*/
@ExperimentalWearFoundationApi
fun interface ReduceMotion {
- @Composable
- fun enabled(): Boolean
+ @Composable fun enabled(): Boolean
}
private val reduceMotionCache = AtomicReference<StateFlow<Boolean>>()
@@ -92,44 +94,41 @@
val coroutineScope = rememberCoroutineScope()
return reduceMotionCache.updateAndGet {
- it ?: callbackFlow {
- val contentObserver =
- object : ContentObserver(HandlerCompat.createAsync(Looper.getMainLooper())) {
- override fun deliverSelfNotifications(): Boolean {
- // Returning true to receive change notification so that
- // the flow sends new value after it is initialized.
- return true
+ it
+ ?: callbackFlow {
+ val contentObserver =
+ object :
+ ContentObserver(HandlerCompat.createAsync(Looper.getMainLooper())) {
+ override fun deliverSelfNotifications(): Boolean {
+ // Returning true to receive change notification so that
+ // the flow sends new value after it is initialized.
+ return true
+ }
+
+ override fun onChange(selfChange: Boolean, uri: Uri?) {
+ super.onChange(selfChange, uri)
+ trySend(getReducedMotionSettingValue(resolver))
+ }
+ }
+
+ coroutineScope.launch {
+ resolver.registerContentObserver(reduceMotionUri, false, contentObserver)
+ // Force send value when flow is initialized
+ resolver.notifyChange(reduceMotionUri, contentObserver)
}
- override fun onChange(selfChange: Boolean, uri: Uri?) {
- super.onChange(selfChange, uri)
- trySend(getReducedMotionSettingValue(resolver))
- }
+ awaitClose { resolver.unregisterContentObserver(contentObserver) }
}
-
- coroutineScope.launch {
- resolver.registerContentObserver(reduceMotionUri, false, contentObserver)
- // Force send value when flow is initialized
- resolver.notifyChange(reduceMotionUri, contentObserver)
- }
-
- awaitClose {
- resolver.unregisterContentObserver(contentObserver)
- }
- }.stateIn(
- MainScope(),
- SharingStarted.WhileSubscribed(5000),
- getReducedMotionSettingValue(resolver)
- )
+ .stateIn(
+ MainScope(),
+ SharingStarted.WhileSubscribed(5000),
+ getReducedMotionSettingValue(resolver)
+ )
}
}
private fun getReducedMotionSettingValue(resolver: ContentResolver): Boolean {
- return Settings.Global.getInt(
- resolver,
- REDUCE_MOTION,
- REDUCE_MOTION_DEFAULT
- ) == 1
+ return Settings.Global.getInt(resolver, REDUCE_MOTION, REDUCE_MOTION_DEFAULT) == 1
}
// See framework's Settings.Global.Wearable#REDUCE_MOTION.
diff --git a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/CurvedAlignment.kt b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/CurvedAlignment.kt
index 0ef9315..c74a34a 100644
--- a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/CurvedAlignment.kt
+++ b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/CurvedAlignment.kt
@@ -28,14 +28,10 @@
@kotlin.jvm.JvmInline
public value class Radial internal constructor(internal val ratio: Float) {
companion object {
- /**
- * Put the child closest to the center of the container, within the available space
- */
+ /** Put the child closest to the center of the container, within the available space */
val Inner = Radial(1f)
- /**
- * Put the child in the middle point of the available space.
- */
+ /** Put the child in the middle point of the available space. */
val Center = Radial(0.5f)
/**
@@ -43,9 +39,7 @@
*/
val Outer = Radial(0f)
- /**
- * Align the child in a custom position, 0 means Outer, 1 means Inner
- */
+ /** Align the child in a custom position, 0 means Outer, 1 means Inner */
fun Custom(ratio: Float): Radial {
return Radial(ratio)
}
@@ -65,9 +59,7 @@
*/
val Start = Angular(0f)
- /**
- * Put the child in the middle point of the available space.
- */
+ /** Put the child in the middle point of the available space. */
val Center = Angular(0.5f)
/**
@@ -76,9 +68,7 @@
*/
val End = Angular(1f)
- /**
- * Align the child in a custom position, 0 means Start, 1 means End
- */
+ /** Align the child in a custom position, 0 means Start, 1 means End */
fun Custom(ratio: Float): Angular {
return Angular(ratio)
}
diff --git a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/CurvedBox.kt b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/CurvedBox.kt
index a360536..7e8597e 100644
--- a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/CurvedBox.kt
+++ b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/CurvedBox.kt
@@ -22,44 +22,40 @@
import androidx.compose.ui.util.fastMaxOfOrNull
/**
- * A layout composable that places its children on top of each other and on an arc. This is
- * similar to a [Box] layout, but curved into a segment of an annulus.
+ * A layout composable that places its children on top of each other and on an arc. This is similar
+ * to a [Box] layout, but curved into a segment of an annulus.
*
- * The thickness of the layout (the difference between the outer and inner radius) will be the
- * same as the thickest child, and the angle taken will be the biggest angle of the
- * children.
+ * The thickness of the layout (the difference between the outer and inner radius) will be the same
+ * as the thickest child, and the angle taken will be the biggest angle of the children.
*
* Example usage:
+ *
* @sample androidx.wear.compose.foundation.samples.CurvedBoxSample
*
* @param modifier The [CurvedModifier] to apply to this curved row.
* @param radialAlignment Radial alignment specifies where to lay down children that are thinner
- * than the CurvedBox, either closer to the center [CurvedAlignment.Radial.Inner], apart from
- * the center [CurvedAlignment.Radial.Outer] or in the
- * middle point [CurvedAlignment.Radial.Center]. If unspecified, they can choose for themselves.
+ * than the CurvedBox, either closer to the center [CurvedAlignment.Radial.Inner], apart from the
+ * center [CurvedAlignment.Radial.Outer] or in the middle point [CurvedAlignment.Radial.Center].
+ * If unspecified, they can choose for themselves.
* @param angularAlignment Angular alignment specifies where to lay down children that are thinner
- * than the CurvedBox, either at the [CurvedAlignment.Angular.Start] of the layout,
- * at the [CurvedAlignment.Angular.End], or [CurvedAlignment.Angular.Center].
- * If unspecified or null, they can choose for themselves.
+ * than the CurvedBox, either at the [CurvedAlignment.Angular.Start] of the layout, at the
+ * [CurvedAlignment.Angular.End], or [CurvedAlignment.Angular.Center]. If unspecified or null,
+ * they can choose for themselves.
* @param contentBuilder Specifies the content of this layout, currently there are 5 available
- * elements defined in foundation for this DSL: the sub-layouts [curvedBox], [curvedRow]
- * and [curvedColumn], [basicCurvedText] and [curvedComposable]
- * (used to add normal composables to curved layouts)
+ * elements defined in foundation for this DSL: the sub-layouts [curvedBox], [curvedRow] and
+ * [curvedColumn], [basicCurvedText] and [curvedComposable] (used to add normal composables to
+ * curved layouts)
*/
public fun CurvedScope.curvedBox(
modifier: CurvedModifier = CurvedModifier,
radialAlignment: CurvedAlignment.Radial? = null,
angularAlignment: CurvedAlignment.Angular? = null,
contentBuilder: CurvedScope.() -> Unit
-) = add(
- CurvedBoxChild(
- curvedLayoutDirection,
- radialAlignment,
- angularAlignment,
- contentBuilder
- ),
- modifier
-)
+) =
+ add(
+ CurvedBoxChild(curvedLayoutDirection, radialAlignment, angularAlignment, contentBuilder),
+ modifier
+ )
internal class CurvedBoxChild(
curvedLayoutDirection: CurvedLayoutDirection,
@@ -76,21 +72,20 @@
parentThickness: Float,
): PartialLayoutInfo {
// position children, take max sweep.
- val maxSweep = children.fastMaxOfOrNull { child ->
- var childRadialPosition = parentOuterRadius
- var childThickness = parentThickness
- if (radialAlignment != null) {
- childRadialPosition = parentOuterRadius - radialAlignment.ratio *
- (parentThickness - child.estimatedThickness)
- childThickness = child.estimatedThickness
- }
+ val maxSweep =
+ children.fastMaxOfOrNull { child ->
+ var childRadialPosition = parentOuterRadius
+ var childThickness = parentThickness
+ if (radialAlignment != null) {
+ childRadialPosition =
+ parentOuterRadius -
+ radialAlignment.ratio * (parentThickness - child.estimatedThickness)
+ childThickness = child.estimatedThickness
+ }
- child.radialPosition(
- childRadialPosition,
- childThickness
- )
- child.sweepRadians
- } ?: 0f
+ child.radialPosition(childRadialPosition, childThickness)
+ child.sweepRadians
+ } ?: 0f
return PartialLayoutInfo(
maxSweep,
parentOuterRadius,
@@ -108,16 +103,13 @@
var childAngularPosition = parentStartAngleRadians
var childSweep = parentSweepRadians
if (angularAlignment != null) {
- childAngularPosition = parentStartAngleRadians + angularAlignment.ratio *
- (parentSweepRadians - child.sweepRadians)
+ childAngularPosition =
+ parentStartAngleRadians +
+ angularAlignment.ratio * (parentSweepRadians - child.sweepRadians)
childSweep = child.sweepRadians
}
- child.angularPosition(
- childAngularPosition,
- childSweep,
- centerOffset
- )
+ child.angularPosition(childAngularPosition, childSweep, centerOffset)
}
return parentStartAngleRadians
}
diff --git a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/CurvedColumn.kt b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/CurvedColumn.kt
index 3ab85ce..4e5ec4f 100644
--- a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/CurvedColumn.kt
+++ b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/CurvedColumn.kt
@@ -27,23 +27,23 @@
/**
* A curved layout composable that places its children stacked as part of an arc (the first child
- * will be the outermost). This is similar to a [Column] layout, but curved into a segment of
- * an annulus.
+ * will be the outermost). This is similar to a [Column] layout, but curved into a segment of an
+ * annulus.
*
- * The thickness of the layout (the difference between the outer and inner radius) will be the
- * sum of the thickness of its children, and the angle taken will be the biggest angle of the
- * children.
+ * The thickness of the layout (the difference between the outer and inner radius) will be the sum
+ * of the thickness of its children, and the angle taken will be the biggest angle of the children.
*
* Example usage:
+ *
* @sample androidx.wear.compose.foundation.samples.CurvedRowAndColumn
*
* @param modifier The [CurvedModifier] to apply to this curved column.
* @param radialDirection Order to lay out components, outside in or inside out. The default is to
- * inherit from the containing [curvedColumn] or [CurvedLayout]
+ * inherit from the containing [curvedColumn] or [CurvedLayout]
* @param angularAlignment Angular alignment specifies where to lay down children that are thinner
- * than the curved column, either at the [CurvedAlignment.Angular.Start] of the layout,
- * at the [CurvedAlignment.Angular.End], or [CurvedAlignment.Angular.Center].
- * If unspecified or null, they can choose for themselves.
+ * than the curved column, either at the [CurvedAlignment.Angular.Start] of the layout, at the
+ * [CurvedAlignment.Angular.End], or [CurvedAlignment.Angular.Center]. If unspecified or null,
+ * they can choose for themselves.
* @param contentBuilder Scope used to provide the content for this column.
*/
public fun CurvedScope.curvedColumn(
@@ -51,14 +51,15 @@
radialDirection: CurvedDirection.Radial? = null,
angularAlignment: CurvedAlignment.Angular? = null,
contentBuilder: CurvedScope.() -> Unit
-) = add(
- CurvedColumnChild(
- curvedLayoutDirection.copy(overrideRadial = radialDirection),
- angularAlignment,
- contentBuilder
- ),
- modifier
-)
+) =
+ add(
+ CurvedColumnChild(
+ curvedLayoutDirection.copy(overrideRadial = radialDirection),
+ angularAlignment,
+ contentBuilder
+ ),
+ modifier
+ )
internal class CurvedColumnChild(
curvedLayoutDirection: CurvedLayoutDirection,
@@ -66,40 +67,44 @@
contentBuilder: CurvedScope.() -> Unit
) : ContainerChild(curvedLayoutDirection, !curvedLayoutDirection.outsideIn(), contentBuilder) {
override fun doEstimateThickness(maxRadius: Float): Float =
- maxRadius - children.fastFold(maxRadius) { currentMaxRadius, node ->
- currentMaxRadius - node.estimateThickness(currentMaxRadius)
- }
+ maxRadius -
+ children.fastFold(maxRadius) { currentMaxRadius, node ->
+ currentMaxRadius - node.estimateThickness(currentMaxRadius)
+ }
override fun doRadialPosition(
parentOuterRadius: Float,
parentThickness: Float,
): PartialLayoutInfo {
// Compute space used by weighted children and space left
- val weights = childrenInLayoutOrder.fastMap { node ->
- (node.computeParentData() as? CurvedScopeParentData)?.weight ?: 0f
- }
- val sumWeights = weights.sum()
- val extraSpace = parentThickness - childrenInLayoutOrder.fastMapIndexed { ix, node ->
- if (weights[ix] == 0f) {
- node.estimatedThickness
- } else {
- 0f
+ val weights =
+ childrenInLayoutOrder.fastMap { node ->
+ (node.computeParentData() as? CurvedScopeParentData)?.weight ?: 0f
}
- }.sum()
+ val sumWeights = weights.sum()
+ val extraSpace =
+ parentThickness -
+ childrenInLayoutOrder
+ .fastMapIndexed { ix, node ->
+ if (weights[ix] == 0f) {
+ node.estimatedThickness
+ } else {
+ 0f
+ }
+ }
+ .sum()
// position children
var outerRadius = parentOuterRadius
childrenInLayoutOrder.fastForEachIndexed { ix, node ->
- val actualThickness = if (weights[ix] > 0f) {
+ val actualThickness =
+ if (weights[ix] > 0f) {
extraSpace * weights[ix] / sumWeights
} else {
node.estimatedThickness
}
- node.radialPosition(
- outerRadius,
- actualThickness
- )
+ node.radialPosition(outerRadius, actualThickness)
outerRadius -= actualThickness
}
var maxSweep = childrenInLayoutOrder.fastMaxOfOrNull { it.sweepRadians } ?: 0f
@@ -121,16 +126,13 @@
var childAngularPosition = parentStartAngleRadians
var childSweep = parentSweepRadians
if (angularAlignment != null) {
- childAngularPosition = parentStartAngleRadians + angularAlignment.ratio *
- (parentSweepRadians - child.sweepRadians)
+ childAngularPosition =
+ parentStartAngleRadians +
+ angularAlignment.ratio * (parentSweepRadians - child.sweepRadians)
childSweep = child.sweepRadians
}
- child.angularPosition(
- childAngularPosition,
- childSweep,
- centerOffset
- )
+ child.angularPosition(childAngularPosition, childSweep, centerOffset)
}
return parentStartAngleRadians
}
diff --git a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/CurvedComposable.kt b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/CurvedComposable.kt
index 22a6db3..e312a1d 100644
--- a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/CurvedComposable.kt
+++ b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/CurvedComposable.kt
@@ -38,17 +38,17 @@
* @param modifier The [CurvedModifier] to apply to this curved composable.
* @param radialAlignment How to align this component if it's thinner than the container.
* @param content The composable(s) that will be wrapped and laid out as part of the parent
- * container. This has a [BoxScope], since it's wrapped inside a Box.
+ * container. This has a [BoxScope], since it's wrapped inside a Box.
*/
public fun CurvedScope.curvedComposable(
modifier: CurvedModifier = CurvedModifier,
radialAlignment: CurvedAlignment.Radial = CurvedAlignment.Radial.Center,
content: @Composable BoxScope.() -> Unit
-) = add(CurvedComposableChild(
- curvedLayoutDirection.absoluteClockwise(),
- radialAlignment,
- content
-), modifier)
+) =
+ add(
+ CurvedComposableChild(curvedLayoutDirection.absoluteClockwise(), radialAlignment, content),
+ modifier
+ )
internal class CurvedComposableChild(
val clockwise: Boolean,
@@ -63,9 +63,7 @@
Box(content = content)
}
- override fun CurvedMeasureScope.initializeMeasure(
- measurables: Iterator<Measurable>
- ) {
+ override fun CurvedMeasureScope.initializeMeasure(measurables: Iterator<Measurable>) {
// TODO: check that we actually match adding a parent data modifier to the Box in
// composeIfNeeded and verifying this measurable has it?
placeable = measurables.next().measure(Constraints())
@@ -85,10 +83,11 @@
val parentInnerRadius = parentOuterRadius - parentThickness
// We know where we want it and the radial alignment, so we can compute it's positioning now
- val (myInnerRadius, myOuterRadius) = computeAnnulusRadii(
- lerp(parentOuterRadius, parentInnerRadius, radialAlignment.ratio),
- radialAlignment.ratio
- )
+ val (myInnerRadius, myOuterRadius) =
+ computeAnnulusRadii(
+ lerp(parentOuterRadius, parentInnerRadius, radialAlignment.ratio),
+ radialAlignment.ratio
+ )
val sweepRadians = 2f * asin(placeable.width / 2f / myInnerRadius)
return PartialLayoutInfo(
@@ -105,9 +104,7 @@
parentStartAngleRadians: Float,
parentSweepRadians: Float,
centerOffset: Offset
- ): Float = parentStartAngleRadians.also {
- this.parentSweepRadians = parentSweepRadians
- }
+ ): Float = parentStartAngleRadians.also { this.parentSweepRadians = parentSweepRadians }
override fun (Placeable.PlacementScope).placeIfNeeded() =
place(placeable, layoutInfo!!, parentSweepRadians, clockwise)
@@ -116,12 +113,11 @@
* Compute the inner and outer radii of the annulus sector required to fit the given box.
*
* @param targetRadius The distance we want, from the center of the circle the annulus is part
- * of, to a point on the side of the box (which point is determined with the radiusAlpha
- * parameter.)
+ * of, to a point on the side of the box (which point is determined with the radiusAlpha
+ * parameter.)
* @param radiusAlpha Which point on the side of the box we are measuring the radius to. 0 means
- * radius is to the outer point in the box, 1 means that it's to the inner point.
- * (And interpolation in-between)
- *
+ * radius is to the outer point in the box, 1 means that it's to the inner point. (And
+ * interpolation in-between)
*/
private fun computeAnnulusRadii(targetRadius: Float, radiusAlpha: Float): Pair<Float, Float> {
// The top side of the triangles we use, squared.
@@ -133,8 +129,8 @@
// Move to the top/bottom of the child box, then project back
val outerRadius = sqrt(topSquared + pow2(radiusInBox + radiusAlpha * placeable.height))
- val innerRadius = sqrt(topSquared +
- pow2(radiusInBox - (1 - radiusAlpha) * placeable.height))
+ val innerRadius =
+ sqrt(topSquared + pow2(radiusInBox - (1 - radiusAlpha) * placeable.height))
return innerRadius to outerRadius
}
@@ -151,9 +147,8 @@
val radiusToTopLeft = outerRadius
// Distance from the center of the CurvedRow to the top center of the component.
- val radiusToTopCenter = sqrt(
- (pow2(radiusToTopLeft) - pow2(placeable.width / 2f)).coerceAtLeast(0f)
- )
+ val radiusToTopCenter =
+ sqrt((pow2(radiusToTopLeft) - pow2(placeable.width / 2f)).coerceAtLeast(0f))
// To position this child, we move its center rotating it around the CurvedRow's center.
val radiusToCenter = radiusToTopCenter - placeable.height / 2f
diff --git a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/CurvedContainer.kt b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/CurvedContainer.kt
index 32e7a1f..a0421f1 100644
--- a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/CurvedContainer.kt
+++ b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/CurvedContainer.kt
@@ -24,52 +24,50 @@
import androidx.compose.ui.util.fastForEach
/**
- * Layout scope used for curved containers.
- * This is the base of a DSL that specifies what components can be added to a curved layout.
+ * Layout scope used for curved containers. This is the base of a DSL that specifies what components
+ * can be added to a curved layout.
*/
@LayoutScopeMarker
-public class CurvedScope internal constructor(
- internal val curvedLayoutDirection: CurvedLayoutDirection
-) {
+public class CurvedScope
+internal constructor(internal val curvedLayoutDirection: CurvedLayoutDirection) {
internal val nodes = mutableListOf<CurvedChild>()
+
internal fun add(node: CurvedChild, modifier: CurvedModifier) {
nodes.add(modifier.wrap(node))
}
}
-/**
- * Base class for sub-layouts
- */
+/** Base class for sub-layouts */
internal abstract class ContainerChild(
curvedLayoutDirection: CurvedLayoutDirection,
internal val reverseLayout: Boolean,
contentBuilder: CurvedScope.() -> Unit
) : CurvedChild() {
private val curvedContainerScope = CurvedScope(curvedLayoutDirection).apply(contentBuilder)
- internal val children get() = curvedContainerScope.nodes
+ internal val children
+ get() = curvedContainerScope.nodes
- internal val childrenInLayoutOrder get() = children.indices.map { ix ->
- children[if (reverseLayout) children.size - 1 - ix else ix]
- }
+ internal val childrenInLayoutOrder
+ get() =
+ children.indices.map { ix ->
+ children[if (reverseLayout) children.size - 1 - ix else ix]
+ }
@Composable
override fun SubComposition() {
- children.fastForEach {
- it.SubComposition()
- }
+ children.fastForEach { it.SubComposition() }
}
- override fun CurvedMeasureScope.initializeMeasure(
- measurables: Iterator<Measurable>
- ) = children.fastForEach { node ->
- with(CurvedMeasureScope(
- subDensity = this,
- curvedContainerScope.curvedLayoutDirection,
- radius
- )) {
- with(node) {
- initializeMeasure(measurables)
- }
+ override fun CurvedMeasureScope.initializeMeasure(measurables: Iterator<Measurable>) =
+ children.fastForEach { node ->
+ with(
+ CurvedMeasureScope(
+ subDensity = this,
+ curvedContainerScope.curvedLayoutDirection,
+ radius
+ )
+ ) {
+ with(node) { initializeMeasure(measurables) }
}
}
diff --git a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/CurvedDirection.kt b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/CurvedDirection.kt
index 716be35..83ad754 100644
--- a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/CurvedDirection.kt
+++ b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/CurvedDirection.kt
@@ -24,6 +24,7 @@
* The direction in which components are laid out on a [curvedRow] or [CurvedLayout]
*
* Example:
+ *
* @sample androidx.wear.compose.foundation.samples.CurvedBottomLayout
*/
@Immutable
@@ -48,45 +49,39 @@
companion object {
/**
- * Go in Clockwise direction for Ltr layout and Counter Clockwise for Rtl.
- * This is generally used for curved layouts on the top of the screen.
+ * Go in Clockwise direction for Ltr layout and Counter Clockwise for Rtl. This is
+ * generally used for curved layouts on the top of the screen.
*/
val Normal = Angular(0)
/**
- * Go in Counter Clockwise direction for Ltr layout and Clockwise for Rtl.
- * This is generally used for curved layouts on the bottom of the screen.
+ * Go in Counter Clockwise direction for Ltr layout and Clockwise for Rtl. This is
+ * generally used for curved layouts on the bottom of the screen.
*/
val Reversed = Angular(1)
- /**
- * Go in Clockwise direction, independently of [LayoutDirection].
- */
+ /** Go in Clockwise direction, independently of [LayoutDirection]. */
val Clockwise = Angular(2)
- /**
- * Go in Counter Clockwise direction, independently of [LayoutDirection].
- */
+ /** Go in Counter Clockwise direction, independently of [LayoutDirection]. */
val CounterClockwise = Angular(3)
}
}
- /**
- * The direction in which components are lay down on a [curvedColumn]
- */
+ /** The direction in which components are lay down on a [curvedColumn] */
@Immutable
@kotlin.jvm.JvmInline
public value class Radial internal constructor(internal val value: Int) {
companion object {
/**
- * Lay components starting farther away from the center and going inwards.
- * This is generally used for curved layouts on the top of the screen.
+ * Lay components starting farther away from the center and going inwards. This is
+ * generally used for curved layouts on the top of the screen.
*/
val OutsideIn = Radial(0)
/**
- * Go in Counter Clockwise direction for Ltr layout and Clockwise for Rtl.
- * This is generally used for curved layouts on the bottom of the screen.
+ * Go in Counter Clockwise direction for Ltr layout and Clockwise for Rtl. This is
+ * generally used for curved layouts on the bottom of the screen.
*/
val InsideOut = Radial(1)
}
diff --git a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/CurvedDraw.kt b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/CurvedDraw.kt
index c9ad3fb..e35f08e 100644
--- a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/CurvedDraw.kt
+++ b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/CurvedDraw.kt
@@ -41,33 +41,35 @@
* Specifies a radial gradient background for a curved element.
*
* Example usage:
+ *
* @sample androidx.wear.compose.foundation.samples.CurvedBackground
*
- * @param colorStops Colors and their offset in the gradient area.
- * Note that the offsets should be in ascending order. 0 means the outer curve and
- * 1 means the inner curve of the curved element.
+ * @param colorStops Colors and their offset in the gradient area. Note that the offsets should be
+ * in ascending order. 0 means the outer curve and 1 means the inner curve of the curved element.
* @param cap How to start and end the background.
*/
public fun CurvedModifier.radialGradientBackground(
vararg colorStops: Pair<Float, Color>,
cap: StrokeCap = StrokeCap.Butt
-) = background(cap) { layoutInfo ->
- val radiusRatio = layoutInfo.innerRadius / layoutInfo.outerRadius
- @Suppress("ListIterator")
- Brush.radialGradient(
- *(colorStops.map { (step, color) ->
- 1f - step * (1f - radiusRatio) to color
- }.reversed().toTypedArray()),
- center = layoutInfo.centerOffset,
- radius = layoutInfo.outerRadius
- )
-}
+) =
+ background(cap) { layoutInfo ->
+ val radiusRatio = layoutInfo.innerRadius / layoutInfo.outerRadius
+ @Suppress("ListIterator")
+ Brush.radialGradient(
+ *(colorStops
+ .map { (step, color) -> 1f - step * (1f - radiusRatio) to color }
+ .reversed()
+ .toTypedArray()),
+ center = layoutInfo.centerOffset,
+ radius = layoutInfo.outerRadius
+ )
+ }
/**
* Specifies a radial gradient background for a curved element.
*
- * @param colors Colors in the gradient area. Gradient goes from the outer curve to the
- * inner curve of the curved element.
+ * @param colors Colors in the gradient area. Gradient goes from the outer curve to the inner curve
+ * of the curved element.
* @param cap How to start and end the background.
*/
public fun CurvedModifier.radialGradientBackground(
@@ -79,24 +81,28 @@
* Specifies a sweep gradient background for a curved element.
*
* Example usage:
+ *
* @sample androidx.wear.compose.foundation.samples.CurvedBackground
*
- * @param colorStops Colors and their offset in the gradient area.
- * Note that the offsets should be in ascending order. 0 means where the curved element starts
- * laying out, 1 means the end
+ * @param colorStops Colors and their offset in the gradient area. Note that the offsets should be
+ * in ascending order. 0 means where the curved element starts laying out, 1 means the end
* @param cap How to start and end the background.
*/
public fun CurvedModifier.angularGradientBackground(
vararg colorStops: Pair<Float, Color>,
cap: StrokeCap = StrokeCap.Butt
-) = background(cap) { layoutInfo ->
- @Suppress("ListIterator")
- val actualStops = colorStops.map { (step, color) ->
- (layoutInfo.startAngleRadians + layoutInfo.sweepRadians * step) /
- (2 * PI).toFloat() to color
- }.sortedBy { it.first }
- Brush.sweepGradient(*(actualStops.toTypedArray()))
-}
+) =
+ background(cap) { layoutInfo ->
+ @Suppress("ListIterator")
+ val actualStops =
+ colorStops
+ .map { (step, color) ->
+ (layoutInfo.startAngleRadians + layoutInfo.sweepRadians * step) /
+ (2 * PI).toFloat() to color
+ }
+ .sortedBy { it.first }
+ Brush.sweepGradient(*(actualStops.toTypedArray()))
+ }
/**
* Specifies a sweep gradient background for a curved element.
@@ -110,9 +116,7 @@
) = angularGradientBackground(*colorsToColorStops(colors), cap = cap)
private fun colorsToColorStops(colors: List<Color>): Array<Pair<Float, Color>> =
- Array(colors.size) {
- it.toFloat() / (colors.size - 1) to colors[it]
- }
+ Array(colors.size) { it.toFloat() / (colors.size - 1) to colors[it] }
internal fun CurvedModifier.background(
cap: StrokeCap = StrokeCap.Butt,
@@ -163,26 +167,21 @@
/* We want the background to fill the space that our parent assigned us (outerLayoutInfo),
* as opposed to the size of or wrapped child (layoutInfo).
*/
- outerLayoutInfo = CurvedLayoutInfo(
- sweepRadians = parentSweepRadians,
- outerRadius = parentOuterRadius,
- thickness = parentThickness,
- centerOffset = centerOffset,
- measureRadius = parentOuterRadius - parentThickness / 2f,
- startAngleRadians = parentStartAngleRadians
- )
- return wrapped.angularPosition(
- parentStartAngleRadians,
- parentSweepRadians,
- centerOffset
- )
+ outerLayoutInfo =
+ CurvedLayoutInfo(
+ sweepRadians = parentSweepRadians,
+ outerRadius = parentOuterRadius,
+ thickness = parentThickness,
+ centerOffset = centerOffset,
+ measureRadius = parentOuterRadius - parentThickness / 2f,
+ startAngleRadians = parentStartAngleRadians
+ )
+ return wrapped.angularPosition(parentStartAngleRadians, parentSweepRadians, centerOffset)
}
override fun DrawScope.draw() {
if (drawBefore) customDraw(outerLayoutInfo)
- with(wrapped) {
- draw()
- }
+ with(wrapped) { draw() }
if (!drawBefore) customDraw(outerLayoutInfo)
}
}
diff --git a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/CurvedLayout.kt b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/CurvedLayout.kt
index cbeebfa..6b06ddf 100644
--- a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/CurvedLayout.kt
+++ b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/CurvedLayout.kt
@@ -37,25 +37,17 @@
import kotlin.math.min
import kotlin.math.sin
-/**
- * Specifies how components will be laid down with respect to the anchor.
- */
+/** Specifies how components will be laid down with respect to the anchor. */
@kotlin.jvm.JvmInline
public value class AnchorType internal constructor(internal val ratio: Float) {
companion object {
- /**
- * Start the content of the [CurvedLayout] on the anchor
- */
+ /** Start the content of the [CurvedLayout] on the anchor */
val Start = AnchorType(0f)
- /**
- * Center the content of the [CurvedLayout] around the anchor
- */
+ /** Center the content of the [CurvedLayout] around the anchor */
val Center = AnchorType(0.5f)
- /**
- * End the content of the [CurvedLayout] on the anchor
- */
+ /** End the content of the [CurvedLayout] on the anchor */
val End = AnchorType(1f)
}
@@ -70,30 +62,31 @@
}
/**
- * A layout composable that places its children in an arc, rotating them as needed.
- * This will layout children using a [curvedRow], that similar to a [Row] layout,
- * that it's curved into a segment of an annulus.
+ * A layout composable that places its children in an arc, rotating them as needed. This will layout
+ * children using a [curvedRow], that similar to a [Row] layout, that it's curved into a segment of
+ * an annulus.
*
* Example usage:
+ *
* @sample androidx.wear.compose.foundation.samples.SimpleCurvedWorld
*
* @param modifier The modifier to be applied to the CurvedRow.
* @param anchor The angle at which children are laid out relative to, in degrees. An angle of 0
- * corresponds to the right (3 o'clock on a watch), 90 degrees is bottom (6 o'clock), and so on.
- * Default is 270 degrees (top of the screen)
+ * corresponds to the right (3 o'clock on a watch), 90 degrees is bottom (6 o'clock), and so on.
+ * Default is 270 degrees (top of the screen)
* @param anchorType Specify how the content is drawn with respect to the anchor. Default is to
- * center the content on the anchor.
+ * center the content on the anchor.
* @param radialAlignment Specifies the radial alignment for children, if not specified, children
- * can choose their own radial Alignment. Alignment specifies where to lay down children that are
- * thiner than the CurvedRow, either closer to the center (INNER), apart from the center (OUTER) or
- * in the middle point (CENTER).
+ * can choose their own radial Alignment. Alignment specifies where to lay down children that are
+ * thiner than the CurvedRow, either closer to the center (INNER), apart from the center (OUTER)
+ * or in the middle point (CENTER).
* @param angularDirection Specify the direction the children are laid on. See
- * [CurvedDirection.Angular]. The default is [CurvedDirection.Angular.Normal], which is clockwise
- * under a LtR layout and counter clockwise on a RtL layout.
+ * [CurvedDirection.Angular]. The default is [CurvedDirection.Angular.Normal], which is clockwise
+ * under a LtR layout and counter clockwise on a RtL layout.
* @param contentBuilder Specifies the content of this layout, currently there are 5 available
- * elements defined in foundations for this DSL: the sub-layouts [curvedBox], [curvedRow]
- * and [curvedColumn], [basicCurvedText] and [curvedComposable]
- * (used to add normal composables to curved layouts)
+ * elements defined in foundations for this DSL: the sub-layouts [curvedBox], [curvedRow] and
+ * [curvedColumn], [basicCurvedText] and [curvedComposable] (used to add normal composables to
+ * curved layouts)
*/
@Composable
public fun CurvedLayout(
@@ -115,23 +108,22 @@
val curvedRowChild = CurvedRowChild(curvedLayoutDirection, radialAlignment, contentBuilder)
Layout(
- modifier = modifier.drawWithContent {
- with(curvedRowChild) { draw() }
- drawContent()
- },
-
- content = {
- curvedRowChild.SubComposition()
- }
+ modifier =
+ modifier.drawWithContent {
+ with(curvedRowChild) { draw() }
+ drawContent()
+ },
+ content = { curvedRowChild.SubComposition() }
) { measurables, constraints ->
require(constraints.hasBoundedHeight || constraints.hasBoundedWidth) {
"either height or width should be bounded"
}
// We take as much room as possible, the same in both dimensions, within the constraints
- val diameter = min(
- if (constraints.hasBoundedWidth) constraints.maxWidth else Int.MAX_VALUE,
- if (constraints.hasBoundedHeight) constraints.maxHeight else Int.MAX_VALUE,
- )
+ val diameter =
+ min(
+ if (constraints.hasBoundedWidth) constraints.maxWidth else Int.MAX_VALUE,
+ if (constraints.hasBoundedHeight) constraints.maxHeight else Int.MAX_VALUE,
+ )
val radius = diameter / 2f
// Give the curved row scope the information needed to measure and map measurables
@@ -154,16 +146,15 @@
val totalSweep = curvedRowChild.sweepRadians
// Apply anchor & anchorType
- var layoutAngleStart = anchor.toRadians() -
- (if (curvedLayoutDirection.clockwise()) anchorType.ratio else
- 1f - anchorType.ratio) * totalSweep
+ var layoutAngleStart =
+ anchor.toRadians() -
+ (if (curvedLayoutDirection.clockwise()) anchorType.ratio
+ else 1f - anchorType.ratio) * totalSweep
curvedRowChild.angularPosition(layoutAngleStart, totalSweep, Offset(radius, radius))
// Place the composable children
- layout(diameter, diameter) {
- with(curvedRowChild) { placeIfNeeded() }
- }
+ layout(diameter, diameter) { with(curvedRowChild) { placeIfNeeded() } }
}
}
@@ -179,19 +170,14 @@
// Check if the angular direction is clockwise, ignoring layoutDirection
fun absoluteClockwise(): Boolean =
- angular == CurvedDirection.Angular.Normal ||
- angular == CurvedDirection.Angular.Clockwise
+ angular == CurvedDirection.Angular.Normal || angular == CurvedDirection.Angular.Clockwise
fun outsideIn(): Boolean = radial == CurvedDirection.Radial.OutsideIn
fun copy(
overrideRadial: CurvedDirection.Radial? = null,
overrideAngular: CurvedDirection.Angular? = null
- ) = CurvedLayoutDirection(
- overrideRadial ?: radial,
- overrideAngular ?: angular,
- layoutDirection
- )
+ ) = CurvedLayoutDirection(overrideRadial ?: radial, overrideAngular ?: angular, layoutDirection)
override fun equals(other: Any?): Boolean {
if (this === other) return true
@@ -208,13 +194,14 @@
@Composable
internal fun initialCurvedLayoutDirection(angular: CurvedDirection.Angular): CurvedLayoutDirection {
val layoutDirection = LocalLayoutDirection.current
- val radialDirection = when (angular) {
- CurvedDirection.Angular.Normal, CurvedDirection.Angular.Clockwise ->
- CurvedDirection.Radial.OutsideIn
- CurvedDirection.Angular.Reversed, CurvedDirection.Angular.CounterClockwise ->
- CurvedDirection.Radial.InsideOut
- else -> throw RuntimeException("Unexpected CurvedDirection.Angular: $angular")
- }
+ val radialDirection =
+ when (angular) {
+ CurvedDirection.Angular.Normal,
+ CurvedDirection.Angular.Clockwise -> CurvedDirection.Radial.OutsideIn
+ CurvedDirection.Angular.Reversed,
+ CurvedDirection.Angular.CounterClockwise -> CurvedDirection.Radial.InsideOut
+ else -> throw RuntimeException("Unexpected CurvedDirection.Angular: $angular")
+ }
return CurvedLayoutDirection(radialDirection, angular, layoutDirection)
}
@@ -222,16 +209,17 @@
* Class representing the dimensions of an annulus segment. Used for [CurvedLayout] and its
* children.
*
- * @param outerRadius The distance from the center of the root CurvedLayout to the outer curve
- * of the segment
+ * @param outerRadius The distance from the center of the root CurvedLayout to the outer curve of
+ * the segment
* @param thickness The distance between inner and outer radius of the segment.
* @param centerOffset The center of the circle this segment is part of.
* @param measureRadius The radius to be used if there is a need to transform between angles and
- * curved widths.
+ * curved widths.
* @param startAngleRadians The angle at which the segment starts. In radians.
*/
@Immutable
-internal class CurvedLayoutInfo internal constructor(
+internal class CurvedLayoutInfo
+internal constructor(
val sweepRadians: Float,
val outerRadius: Float,
val thickness: Float,
@@ -242,19 +230,20 @@
val innerRadius = outerRadius - thickness
/**
- * Maps a point in the component, specified in radial coordinates, into the offset of the
- * point in the [CurvedLayout].
+ * Maps a point in the component, specified in radial coordinates, into the offset of the point
+ * in the [CurvedLayout].
*
* @param radialRatio The radial position of the point we want to specify, 0 being the
- * innerRadius, 1 meaning outerRadius
- * @param angleRatio The angle of the point we want to specify, 0 being the start of layout,
- * 1 meaning the end.
+ * innerRadius, 1 meaning outerRadius
+ * @param angleRatio The angle of the point we want to specify, 0 being the start of layout, 1
+ * meaning the end.
*/
fun computePointOffset(radialRatio: Float, angleRatio: Float) =
- centerOffset + offsetFromDistanceAndAngle(
- distance = outerRadius - thickness * (1f - radialRatio),
- angle = startAngleRadians + angleRatio * sweepRadians
- )
+ centerOffset +
+ offsetFromDistanceAndAngle(
+ distance = outerRadius - thickness * (1f - radialRatio),
+ angle = startAngleRadians + angleRatio * sweepRadians
+ )
}
// Partially computed CurvedLayoutInfo
@@ -277,9 +266,8 @@
* Base class for children of a [CurvedLayout].
*
* It has similarities with a LayoutNode in the compose-ui world, but needs several changes to work
- * on curved elements:
- * Still uses the basic compose phases: composition, measurement, placement & draw, but
- * measurement is split into sub-phases:
+ * on curved elements: Still uses the basic compose phases: composition, measurement, placement &
+ * draw, but measurement is split into sub-phases:
* <pre>
* 1. During composition [CurvedChild#ComposeIfNeeded] is called.
* 2. During measurement [CurvedChild#initializeMeasure], [CurvedChild#estimateThickness],
@@ -315,16 +303,15 @@
* initializeMeasure's matching behavior (initializeMeasure should return the index parameter +
* the number of nodes generated, and ideally check that they are the right measurable(s))
*/
- @Composable
- open fun SubComposition() {}
+ @Composable open fun SubComposition() {}
/**
* Initialize the Child to do a measure pass.
*
* @param measurables: The measurables on the CurvedLayout, used to map to the compose-ui nodes
- * we generated in [SubComposition] as we walk the tree.
+ * we generated in [SubComposition] as we walk the tree.
*/
- open fun CurvedMeasureScope.initializeMeasure(measurables: Iterator<Measurable>) { }
+ open fun CurvedMeasureScope.initializeMeasure(measurables: Iterator<Measurable>) {}
/**
* Compute the parent data required to give to the parent layout to properly size and position
@@ -332,11 +319,9 @@
*/
open fun computeParentData(): Any? = null
- /**
- * Estimate the thickness of this component given the maximus radius it can take.
- */
- fun estimateThickness(maxRadius: Float): Float = doEstimateThickness(maxRadius)
- .also { estimatedThickness = it }
+ /** Estimate the thickness of this component given the maximus radius it can take. */
+ fun estimateThickness(maxRadius: Float): Float =
+ doEstimateThickness(maxRadius).also { estimatedThickness = it }
abstract fun doEstimateThickness(maxRadius: Float): Float
@@ -349,20 +334,17 @@
* differently on radius 50 to 100 than on radius 300 to 350.
*
* @param parentOuterRadius The outer radius of the space we have in the parent container
- * @param parentThickness The thickness of the space we have in the parent container
- * Return A [PartialLayoutInfo] representing most of the information needed to layout this
- * component (all except it's angular position)
+ * @param parentThickness The thickness of the space we have in the parent container Return A
+ * [PartialLayoutInfo] representing most of the information needed to layout this component
+ * (all except it's angular position)
*/
abstract fun doRadialPosition(
parentOuterRadius: Float,
parentThickness: Float
): PartialLayoutInfo
- fun radialPosition(
- parentOuterRadius: Float,
- parentThickness: Float
- ): PartialLayoutInfo = doRadialPosition(parentOuterRadius, parentThickness)
- .also { partialLayoutInfo = it }
+ fun radialPosition(parentOuterRadius: Float, parentThickness: Float): PartialLayoutInfo =
+ doRadialPosition(parentOuterRadius, parentThickness).also { partialLayoutInfo = it }
/**
* Called by the parent during angular layout to compute our starting angle (relative to the
@@ -370,27 +352,25 @@
*
* @param parentStartAngleRadians The start angle we have available in our parent.
* @param parentSweepRadians The sweep we have available in our parent.
- * @param centerOffset The center of the circle this curved component is a part of.
- * return This [CurvedChild] absolute angular position, in radians.
+ * @param centerOffset The center of the circle this curved component is a part of. return This
+ * [CurvedChild] absolute angular position, in radians.
*/
fun angularPosition(
parentStartAngleRadians: Float,
parentSweepRadians: Float,
centerOffset: Offset
): Float {
- val angularPosition = doAngularPosition(
- parentStartAngleRadians,
- parentSweepRadians,
- centerOffset
- )
- layoutInfo = CurvedLayoutInfo(
- sweepRadians,
- partialLayoutInfo.outerRadius,
- partialLayoutInfo.thickness,
- centerOffset,
- partialLayoutInfo.measureRadius,
- angularPosition
- )
+ val angularPosition =
+ doAngularPosition(parentStartAngleRadians, parentSweepRadians, centerOffset)
+ layoutInfo =
+ CurvedLayoutInfo(
+ sweepRadians,
+ partialLayoutInfo.outerRadius,
+ partialLayoutInfo.thickness,
+ centerOffset,
+ partialLayoutInfo.measureRadius,
+ angularPosition
+ )
return angularPosition
}
@@ -400,19 +380,18 @@
centerOffset: Offset
): Float = parentStartAngleRadians
- /**
- * If this component generated a child composable, this is the opportunity to place it.
- */
+ /** If this component generated a child composable, this is the opportunity to place it. */
open fun (Placeable.PlacementScope).placeIfNeeded() {}
- /**
- * A chance for this component to draw itself.
- */
+ /** A chance for this component to draw itself. */
open fun DrawScope.draw() {}
}
internal fun Float.toRadians() = this * PI.toFloat() / 180f
+
internal fun Float.toDegrees() = this * 180f / PI.toFloat()
+
internal fun <T> Iterable<T>.sumOf(selector: (T) -> Float): Float = map(selector).sum()
+
internal fun offsetFromDistanceAndAngle(distance: Float, angle: Float) =
Offset(distance * cos(angle), distance * sin(angle))
diff --git a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/CurvedModifier.kt b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/CurvedModifier.kt
index fd7d85d..f7ab906 100644
--- a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/CurvedModifier.kt
+++ b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/CurvedModifier.kt
@@ -41,8 +41,8 @@
CurvedModifierImpl(elements() + other.elements())
/**
- * The companion object `CurvedModifier` is the empty, default, or starter [CurvedModifier]
- * that contains no Elements.
+ * The companion object `CurvedModifier` is the empty, default, or starter [CurvedModifier] that
+ * contains no Elements.
*/
companion object : CurvedModifier {
override fun toString() = "CurvedModifier"
@@ -54,9 +54,7 @@
internal open class CurvedModifierImpl(internal val elements: List<Element>) : CurvedModifier
-/**
- * A single element contained within a [CurvedModifier] chain.
- */
+/** A single element contained within a [CurvedModifier] chain. */
internal fun interface Element {
abstract fun wrap(child: CurvedChild): CurvedChild
}
@@ -69,27 +67,22 @@
internal infix fun CurvedModifier.then(other: Element): CurvedModifier =
CurvedModifierImpl(elements() + other)
-/**
- * Create a chain of CurvedChild, one for each modifier, wrapping each other.
- */
-internal fun CurvedModifier.wrap(child: CurvedChild) = elements().foldRight(child) { elem, acc ->
- elem.wrap(acc)
-}
+/** Create a chain of CurvedChild, one for each modifier, wrapping each other. */
+internal fun CurvedModifier.wrap(child: CurvedChild) =
+ elements().foldRight(child) { elem, acc -> elem.wrap(acc) }
/**
- * Base class to implement a CurvedChild in a chain.
- * Forwards all calls to the wrapped CurvedChild.
+ * Base class to implement a CurvedChild in a chain. Forwards all calls to the wrapped CurvedChild.
*/
internal open class BaseCurvedChildWrapper(val wrapped: CurvedChild) : CurvedChild() {
@Composable
- override fun SubComposition() { wrapped.SubComposition() }
-
- override fun CurvedMeasureScope.initializeMeasure(
- measurables: Iterator<Measurable>
- ) = with(wrapped) {
- initializeMeasure(measurables)
+ override fun SubComposition() {
+ wrapped.SubComposition()
}
+ override fun CurvedMeasureScope.initializeMeasure(measurables: Iterator<Measurable>) =
+ with(wrapped) { initializeMeasure(measurables) }
+
override fun computeParentData(): Any? = wrapped.computeParentData()
override fun doEstimateThickness(maxRadius: Float) = wrapped.estimateThickness(maxRadius)
@@ -97,20 +90,17 @@
override fun doRadialPosition(
parentOuterRadius: Float,
parentThickness: Float,
- ) = wrapped.radialPosition(
- parentOuterRadius,
- parentThickness,
- )
+ ) =
+ wrapped.radialPosition(
+ parentOuterRadius,
+ parentThickness,
+ )
override fun doAngularPosition(
parentStartAngleRadians: Float,
parentSweepRadians: Float,
centerOffset: Offset
- ) = wrapped.angularPosition(
- parentStartAngleRadians,
- parentSweepRadians,
- centerOffset
- )
+ ) = wrapped.angularPosition(parentStartAngleRadians, parentSweepRadians, centerOffset)
override fun (Placeable.PlacementScope).placeIfNeeded() = with(wrapped) { placeIfNeeded() }
diff --git a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/CurvedPadding.kt b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/CurvedPadding.kt
index 98044ff..eaace08 100644
--- a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/CurvedPadding.kt
+++ b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/CurvedPadding.kt
@@ -27,8 +27,8 @@
/**
* Apply additional space along the edges of the content.
*
- * @param paddingValues The [ArcPaddingValues] to use. See that class and factory methods to see
- * how paddings can be specified.
+ * @param paddingValues The [ArcPaddingValues] to use. See that class and factory methods to see how
+ * paddings can be specified.
*/
public fun CurvedModifier.padding(paddingValues: ArcPaddingValues) =
this.then { child -> PaddingWrapper(child, paddingValues) }
@@ -39,13 +39,13 @@
* between dimension and angle).
*
* @param outer The space to add to the outer edge of the content (away from the center of the
- * containing CurvedLayout)
+ * containing CurvedLayout)
* @param inner The space to add to the inner edge of the content (towards the center of the
- * containing CurvedLayout)
+ * containing CurvedLayout)
* @param before The space added before the component, if it was draw clockwise. This is the edge of
- * the component with the "smallest" angle.
+ * the component with the "smallest" angle.
* @param after The space added after the component, if it was draw clockwise. This is the edge of
- * the component with the "biggest" angle.
+ * the component with the "biggest" angle.
*/
public fun CurvedModifier.padding(outer: Dp, inner: Dp, before: Dp, after: Dp) =
padding(ArcPaddingValuesImpl(outer, inner, before, after))
@@ -68,20 +68,15 @@
public fun CurvedModifier.padding(all: Dp = 0.dp) = padding(all, all, all, all)
/**
- * Apply additional space along each edge of the content in [Dp].
- * See the [ArcPaddingValues] factories for convenient ways to
- * build [ArcPaddingValues].
+ * Apply additional space along each edge of the content in [Dp]. See the [ArcPaddingValues]
+ * factories for convenient ways to build [ArcPaddingValues].
*/
@Stable
public interface ArcPaddingValues {
- /**
- * Padding in the outward direction from the center of the [CurvedLayout]
- */
+ /** Padding in the outward direction from the center of the [CurvedLayout] */
fun calculateOuterPadding(radialDirection: CurvedDirection.Radial): Dp
- /**
- * Padding in the inwards direction towards the center of the [CurvedLayout]
- */
+ /** Padding in the inwards direction towards the center of the [CurvedLayout] */
fun calculateInnerPadding(radialDirection: CurvedDirection.Radial): Dp
/**
@@ -107,8 +102,7 @@
* Apply additional space along each edge of the content in [Dp]. Note that that all dimensions are
* applied to a concrete edge, indepenend on layout direction and curved layout direction.
*
- * @param outer Padding in the outward direction from the center of the
- * [CurvedLayout]
+ * @param outer Padding in the outward direction from the center of the [CurvedLayout]
* @param inner Padding in the inwards direction towards the center of the [CurvedLayout]
* @param before Padding added before the component, if it was draw clockwise.
* @param after Padding added after the component, if it was draw clockwise.
@@ -118,12 +112,9 @@
inner: Dp = 0.dp,
before: Dp = 0.dp,
after: Dp = 0.dp
-): ArcPaddingValues =
- ArcPaddingValuesImpl(outer, inner, before, after)
+): ArcPaddingValues = ArcPaddingValuesImpl(outer, inner, before, after)
-/**
- * Apply [all] dp of additional space along each edge of the content.
- */
+/** Apply [all] dp of additional space along each edge of the content. */
public fun ArcPaddingValues(all: Dp): ArcPaddingValues = ArcPaddingValuesImpl(all, all, all, all)
/**
@@ -144,63 +135,65 @@
after == other.after
}
- override fun hashCode() = ((outer.hashCode() * 31 + inner.hashCode()) * 31 +
- before.hashCode()) * 31 + after.hashCode()
+ override fun hashCode() =
+ ((outer.hashCode() * 31 + inner.hashCode()) * 31 + before.hashCode()) * 31 +
+ after.hashCode()
override fun toString(): String {
return "ArcPaddingValuesImpl(outer=$outer, inner=$inner, before=$before, after=$after)"
}
override fun calculateOuterPadding(radialDirection: CurvedDirection.Radial) = outer
+
override fun calculateInnerPadding(radialDirection: CurvedDirection.Radial) = inner
+
override fun calculateBeforePadding(
layoutDirection: LayoutDirection,
angularDirection: CurvedDirection.Angular
) = before
+
override fun calculateAfterPadding(
layoutDirection: LayoutDirection,
angularDirection: CurvedDirection.Angular
) = after
}
-internal class PaddingWrapper(
- child: CurvedChild,
- val paddingValues: ArcPaddingValues
-) : BaseCurvedChildWrapper(child) {
+internal class PaddingWrapper(child: CurvedChild, val paddingValues: ArcPaddingValues) :
+ BaseCurvedChildWrapper(child) {
private var outerPx = 0f
private var innerPx = 0f
private var beforePx = 0f
private var afterPx = 0f
- override fun CurvedMeasureScope.initializeMeasure(
- measurables: Iterator<Measurable>
- ) {
+ override fun CurvedMeasureScope.initializeMeasure(measurables: Iterator<Measurable>) {
outerPx = paddingValues.calculateOuterPadding(curvedLayoutDirection.radial).toPx()
innerPx = paddingValues.calculateInnerPadding(curvedLayoutDirection.radial).toPx()
- beforePx = paddingValues.calculateBeforePadding(
- curvedLayoutDirection.layoutDirection,
- curvedLayoutDirection.angular
- ).toPx()
- afterPx = paddingValues.calculateAfterPadding(
- curvedLayoutDirection.layoutDirection,
- curvedLayoutDirection.angular
- ).toPx()
- with(wrapped) {
- initializeMeasure(measurables)
- }
+ beforePx =
+ paddingValues
+ .calculateBeforePadding(
+ curvedLayoutDirection.layoutDirection,
+ curvedLayoutDirection.angular
+ )
+ .toPx()
+ afterPx =
+ paddingValues
+ .calculateAfterPadding(
+ curvedLayoutDirection.layoutDirection,
+ curvedLayoutDirection.angular
+ )
+ .toPx()
+ with(wrapped) { initializeMeasure(measurables) }
}
- override fun doEstimateThickness(maxRadius: Float) = wrapped.estimateThickness(maxRadius) +
- outerPx + innerPx
+ override fun doEstimateThickness(maxRadius: Float) =
+ wrapped.estimateThickness(maxRadius) + outerPx + innerPx
override fun doRadialPosition(
parentOuterRadius: Float,
parentThickness: Float
): PartialLayoutInfo {
- val partialLayoutInfo = wrapped.radialPosition(
- parentOuterRadius - outerPx,
- parentThickness - outerPx - innerPx
- )
+ val partialLayoutInfo =
+ wrapped.radialPosition(parentOuterRadius - outerPx, parentThickness - outerPx - innerPx)
val angularPadding = (beforePx + afterPx) / partialLayoutInfo.measureRadius
return PartialLayoutInfo(
partialLayoutInfo.sweepRadians + angularPadding,
diff --git a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/CurvedParentData.kt b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/CurvedParentData.kt
index 14d4b39..75ee3c2 100644
--- a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/CurvedParentData.kt
+++ b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/CurvedParentData.kt
@@ -19,43 +19,38 @@
import androidx.annotation.FloatRange
/**
- * A [CurvedModifier] that provides data to the parent layout.
- * The parent data is commonly used to inform the parent how the child Layout should be measured
- * and positioned.
+ * A [CurvedModifier] that provides data to the parent layout. The parent data is commonly used to
+ * inform the parent how the child Layout should be measured and positioned.
*
* @param modifyParentData provides a parentData, given the parentData provided through the
- * modifier's chain.
+ * modifier's chain.
*/
-public fun CurvedModifier.parentDataModifier(
- modifyParentData: (Any?) -> Any?
-) = this.then { child -> ParentDataWrapper(child, modifyParentData) }
+public fun CurvedModifier.parentDataModifier(modifyParentData: (Any?) -> Any?) =
+ this.then { child -> ParentDataWrapper(child, modifyParentData) }
/**
- * Size the element's proportional to its [weight] relative to other weighted sibling
- * elements in the container (this will be the height in a [curvedColumn] and the width in a
- * [curvedRow]). The parent will divide the space remaining after measuring unweighted child
- * elements and distribute it according to this weight.
+ * Size the element's proportional to its [weight] relative to other weighted sibling elements in
+ * the container (this will be the height in a [curvedColumn] and the width in a [curvedRow]). The
+ * parent will divide the space remaining after measuring unweighted child elements and distribute
+ * it according to this weight.
*
* Example usage:
+ *
* @sample androidx.wear.compose.foundation.samples.CurvedWeight
*
- * @param weight The proportional size to give to this element, as related to the total of
- * all weighted siblings. Must be positive.
+ * @param weight The proportional size to give to this element, as related to the total of all
+ * weighted siblings. Must be positive.
*/
-public fun CurvedModifier.weight(
- @FloatRange(from = 0.0, fromInclusive = false)
- weight: Float
-) = parentDataModifier { parentData ->
- require(weight > 0f) { "Weights must be positive." }
- ((parentData as? CurvedScopeParentData) ?: CurvedScopeParentData()).also {
- it.weight = weight
+public fun CurvedModifier.weight(@FloatRange(from = 0.0, fromInclusive = false) weight: Float) =
+ parentDataModifier { parentData ->
+ require(weight > 0f) { "Weights must be positive." }
+ ((parentData as? CurvedScopeParentData) ?: CurvedScopeParentData()).also {
+ it.weight = weight
+ }
}
-}
-internal class ParentDataWrapper(
- child: CurvedChild,
- val modifyParentData: (Any?) -> Any?
-) : BaseCurvedChildWrapper(child) {
+internal class ParentDataWrapper(child: CurvedChild, val modifyParentData: (Any?) -> Any?) :
+ BaseCurvedChildWrapper(child) {
override fun computeParentData(): Any? = modifyParentData(wrapped.computeParentData())
}
diff --git a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/CurvedRow.kt b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/CurvedRow.kt
index 4f5daea..765f9d4 100644
--- a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/CurvedRow.kt
+++ b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/CurvedRow.kt
@@ -24,24 +24,24 @@
import androidx.compose.ui.util.fastMaxOfOrNull
/**
- * A layout composable that places its children in an arc, rotating them as needed. This is
- * similar to a [Row] layout, but curved into a segment of an annulus.
+ * A layout composable that places its children in an arc, rotating them as needed. This is similar
+ * to a [Row] layout, but curved into a segment of an annulus.
*
- * The thickness of the layout (the difference between the outer and inner radius) will be the
- * same as the thickest child, and the total angle taken is the sum of the children's angles.
+ * The thickness of the layout (the difference between the outer and inner radius) will be the same
+ * as the thickest child, and the total angle taken is the sum of the children's angles.
*
* Example usage:
+ *
* @sample androidx.wear.compose.foundation.samples.CurvedRowAndColumn
*
* @param modifier The [CurvedModifier] to apply to this curved row.
* @param radialAlignment Radial alignment specifies where to lay down children that are thinner
- * than the CurvedRow, either closer to the center [CurvedAlignment.Radial.Inner], apart from
- * the center [CurvedAlignment.Radial.Outer] or in the
- * middle point [CurvedAlignment.Radial.Center]. If unspecified, they can choose for themselves.
- * @param angularDirection Specify if the children are laid out clockwise or anti-clockwise,
- * and if those needs to be reversed in a Rtl layout.
- * If not specified, it will be inherited from the enclosing [curvedRow] or [CurvedLayout]
- * See [CurvedDirection.Angular].
+ * than the CurvedRow, either closer to the center [CurvedAlignment.Radial.Inner], apart from the
+ * center [CurvedAlignment.Radial.Outer] or in the middle point [CurvedAlignment.Radial.Center].
+ * If unspecified, they can choose for themselves.
+ * @param angularDirection Specify if the children are laid out clockwise or anti-clockwise, and if
+ * those needs to be reversed in a Rtl layout. If not specified, it will be inherited from the
+ * enclosing [curvedRow] or [CurvedLayout] See [CurvedDirection.Angular].
* @param contentBuilder Scope used to provide the content for this row.
*/
public fun CurvedScope.curvedRow(
@@ -49,14 +49,15 @@
radialAlignment: CurvedAlignment.Radial? = null,
angularDirection: CurvedDirection.Angular? = null,
contentBuilder: CurvedScope.() -> Unit
-) = add(
- CurvedRowChild(
- curvedLayoutDirection.copy(overrideAngular = angularDirection),
- radialAlignment,
- contentBuilder
- ),
- modifier
-)
+) =
+ add(
+ CurvedRowChild(
+ curvedLayoutDirection.copy(overrideAngular = angularDirection),
+ radialAlignment,
+ contentBuilder
+ ),
+ modifier
+ )
internal class CurvedRowChild(
curvedLayoutDirection: CurvedLayoutDirection,
@@ -73,21 +74,20 @@
): PartialLayoutInfo {
// position children, sum angles.
@Suppress("ListIterator")
- var totalSweep = children.sumOf { child ->
- var childRadialPosition = parentOuterRadius
- var childThickness = parentThickness
- if (radialAlignment != null) {
- childRadialPosition = parentOuterRadius - radialAlignment.ratio *
- (parentThickness - child.estimatedThickness)
- childThickness = child.estimatedThickness
- }
+ var totalSweep =
+ children.sumOf { child ->
+ var childRadialPosition = parentOuterRadius
+ var childThickness = parentThickness
+ if (radialAlignment != null) {
+ childRadialPosition =
+ parentOuterRadius -
+ radialAlignment.ratio * (parentThickness - child.estimatedThickness)
+ childThickness = child.estimatedThickness
+ }
- child.radialPosition(
- childRadialPosition,
- childThickness
- )
- child.sweepRadians
- }
+ child.radialPosition(childRadialPosition, childThickness)
+ child.sweepRadians
+ }
return PartialLayoutInfo(
totalSweep,
@@ -102,31 +102,33 @@
parentSweepRadians: Float,
centerOffset: Offset
): Float {
- val weights = childrenInLayoutOrder.fastMap { node ->
- (node.computeParentData() as? CurvedScopeParentData)?.weight ?: 0f
- }
- val sumWeights = weights.sum()
- val extraSpace = parentSweepRadians - childrenInLayoutOrder.fastMapIndexed { ix, node ->
- if (weights[ix] == 0f) {
- node.sweepRadians
- } else {
- 0f
+ val weights =
+ childrenInLayoutOrder.fastMap { node ->
+ (node.computeParentData() as? CurvedScopeParentData)?.weight ?: 0f
}
- }.sum()
+ val sumWeights = weights.sum()
+ val extraSpace =
+ parentSweepRadians -
+ childrenInLayoutOrder
+ .fastMapIndexed { ix, node ->
+ if (weights[ix] == 0f) {
+ node.sweepRadians
+ } else {
+ 0f
+ }
+ }
+ .sum()
var currentStartAngle = parentStartAngleRadians
childrenInLayoutOrder.fastForEachIndexed { ix, node ->
- val actualSweep = if (weights[ix] > 0f) {
+ val actualSweep =
+ if (weights[ix] > 0f) {
extraSpace * weights[ix] / sumWeights
} else {
node.sweepRadians
}
- node.angularPosition(
- currentStartAngle,
- actualSweep,
- centerOffset
- )
+ node.angularPosition(currentStartAngle, actualSweep, centerOffset)
currentStartAngle += actualSweep
}
return parentStartAngleRadians
diff --git a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/CurvedSize.kt b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/CurvedSize.kt
index 6c90d7a..5c1e187 100644
--- a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/CurvedSize.kt
+++ b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/CurvedSize.kt
@@ -31,21 +31,20 @@
* @param maxThickness the maximum thickness (radial size) for the content.
*/
public fun CurvedModifier.sizeIn(
- @FloatRange(from = 0.0, to = 360.0)
- minSweepDegrees: Float = 0f,
- @FloatRange(from = 0.0, to = 360.0)
- maxSweepDegrees: Float = 360f,
+ @FloatRange(from = 0.0, to = 360.0) minSweepDegrees: Float = 0f,
+ @FloatRange(from = 0.0, to = 360.0) maxSweepDegrees: Float = 360f,
minThickness: Dp = 0.dp,
maxThickness: Dp = Dp.Infinity,
-) = this.then { child ->
- SweepSizeWrapper(
- child,
- minSweepDegrees = minSweepDegrees,
- maxSweepDegrees = maxSweepDegrees,
- minThickness = minThickness,
- maxThickness = maxThickness
- )
-}
+) =
+ this.then { child ->
+ SweepSizeWrapper(
+ child,
+ minSweepDegrees = minSweepDegrees,
+ maxSweepDegrees = maxSweepDegrees,
+ minThickness = minThickness,
+ maxThickness = maxThickness
+ )
+ }
/**
* Specify the dimensions (sweep and thickness) for the content.
@@ -56,54 +55,50 @@
* @param thickness Indicates the thickness (radial size) of the content.
*/
public fun CurvedModifier.size(
- @FloatRange(from = 0.0, to = 360.0)
- sweepDegrees: Float,
+ @FloatRange(from = 0.0, to = 360.0) sweepDegrees: Float,
thickness: Dp
-) = sizeIn(
- minSweepDegrees = sweepDegrees,
- maxSweepDegrees = sweepDegrees,
- minThickness = thickness,
- maxThickness = thickness
-)
+) =
+ sizeIn(
+ minSweepDegrees = sweepDegrees,
+ maxSweepDegrees = sweepDegrees,
+ minThickness = thickness,
+ maxThickness = thickness
+ )
/**
- * Specify the sweep (arc length) for the content in Dp. The arc length will be measured
- * at the center of the item, except for [basicCurvedText], where it will be
- * measured at the text baseline.
+ * Specify the sweep (arc length) for the content in Dp. The arc length will be measured at the
+ * center of the item, except for [basicCurvedText], where it will be measured at the text baseline.
*
* @sample androidx.wear.compose.foundation.samples.CurvedFixedSize
*
* @param angularWidth Indicates the arc length of the content in Dp.
*/
-public fun CurvedModifier.angularSizeDp(angularWidth: Dp) = this.then { child ->
- AngularWidthSizeWrapper(
- child,
- minAngularWidth = angularWidth,
- maxAngularWidth = angularWidth,
- minThickness = 0.dp,
- maxThickness = Dp.Infinity
- )
-}
+public fun CurvedModifier.angularSizeDp(angularWidth: Dp) =
+ this.then { child ->
+ AngularWidthSizeWrapper(
+ child,
+ minAngularWidth = angularWidth,
+ maxAngularWidth = angularWidth,
+ minThickness = 0.dp,
+ maxThickness = Dp.Infinity
+ )
+ }
/**
* Specify the sweep (angular size) for the content.
*
* @param sweepDegrees Indicates the sweep (angular size) of the content.
*/
-public fun CurvedModifier.angularSize(sweepDegrees: Float) = sizeIn(
- minSweepDegrees = sweepDegrees,
- maxSweepDegrees = sweepDegrees
-)
+public fun CurvedModifier.angularSize(sweepDegrees: Float) =
+ sizeIn(minSweepDegrees = sweepDegrees, maxSweepDegrees = sweepDegrees)
/**
* Specify the radialSize (thickness) for the content.
*
* @param thickness Indicates the thickness of the content.
*/
-public fun CurvedModifier.radialSize(thickness: Dp) = sizeIn(
- minThickness = thickness,
- maxThickness = thickness
-)
+public fun CurvedModifier.radialSize(thickness: Dp) =
+ sizeIn(minThickness = thickness, maxThickness = thickness)
internal class SweepSizeWrapper(
child: CurvedChild,
@@ -112,9 +107,7 @@
minThickness: Dp,
maxThickness: Dp,
) : BaseSizeWrapper(child, minThickness, maxThickness) {
- override fun CurvedMeasureScope.initializeMeasure(
- measurables: Iterator<Measurable>
- ) {
+ override fun CurvedMeasureScope.initializeMeasure(measurables: Iterator<Measurable>) {
baseInitializeMeasure(measurables)
}
@@ -135,9 +128,8 @@
private var minAngularWidthPx = 0f
private var maxAngularWidthPx = 0f
- override fun CurvedMeasureScope.initializeMeasure(
- measurables: Iterator<Measurable>
- ) {
+
+ override fun CurvedMeasureScope.initializeMeasure(measurables: Iterator<Measurable>) {
minAngularWidthPx = minAngularWidth.toPx()
maxAngularWidthPx = maxAngularWidth.toPx()
@@ -159,9 +151,7 @@
private var minThicknessPx = 0f
private var maxThicknessPx = 0f
- protected fun CurvedMeasureScope.baseInitializeMeasure(
- measurables: Iterator<Measurable>
- ) {
+ protected fun CurvedMeasureScope.baseInitializeMeasure(measurables: Iterator<Measurable>) {
minThicknessPx = minThickness.toPx()
maxThicknessPx = maxThickness.toPx()
with(wrapped) {
@@ -174,6 +164,7 @@
wrapped.estimateThickness(maxRadius).coerceIn(minThicknessPx, maxThicknessPx)
protected abstract fun calculateSweepRadians(partialLayoutInfo: PartialLayoutInfo): Float
+
override fun doAngularPosition(
parentStartAngleRadians: Float,
parentSweepRadians: Float,
@@ -191,16 +182,13 @@
parentOuterRadius: Float,
parentThickness: Float
): PartialLayoutInfo {
- val partialLayoutInfo = wrapped.radialPosition(
- parentOuterRadius,
- estimatedThickness
- )
+ val partialLayoutInfo = wrapped.radialPosition(parentOuterRadius, estimatedThickness)
return PartialLayoutInfo(
calculateSweepRadians(partialLayoutInfo),
parentOuterRadius,
thickness = estimatedThickness,
- measureRadius = partialLayoutInfo.measureRadius +
- partialLayoutInfo.outerRadius - parentOuterRadius
+ measureRadius =
+ partialLayoutInfo.measureRadius + partialLayoutInfo.outerRadius - parentOuterRadius
)
}
}
diff --git a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/CurvedTextStyle.kt b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/CurvedTextStyle.kt
index 313a881..50e6726 100644
--- a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/CurvedTextStyle.kt
+++ b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/CurvedTextStyle.kt
@@ -28,14 +28,15 @@
import androidx.compose.ui.unit.sp
/** The default values to use if they are not specified. */
-internal val DefaultCurvedTextStyles = CurvedTextStyle(
- color = Color.Black,
- fontSize = 14.sp,
- background = Color.Transparent,
- fontWeight = FontWeight.Normal,
- fontStyle = FontStyle.Normal,
- fontSynthesis = FontSynthesis.All
-)
+internal val DefaultCurvedTextStyles =
+ CurvedTextStyle(
+ color = Color.Black,
+ fontSize = 14.sp,
+ background = Color.Transparent,
+ fontWeight = FontWeight.Normal,
+ fontStyle = FontStyle.Normal,
+ fontSynthesis = FontSynthesis.All
+ )
/**
* Styling configuration for a curved text.
@@ -44,13 +45,13 @@
*
* @param background The background color for the text.
* @param color The text color.
- * @param fontSize The size of glyphs (in logical pixels) to use when painting the text. This
- * may be [TextUnit.Unspecified] for inheriting from another [CurvedTextStyle].
+ * @param fontSize The size of glyphs (in logical pixels) to use when painting the text. This may be
+ * [TextUnit.Unspecified] for inheriting from another [CurvedTextStyle].
* @param fontFamily The font family to be used when rendering the text.
* @param fontWeight The thickness of the glyphs, in a range of [1, 1000]. see [FontWeight]
* @param fontStyle The typeface variant to use when drawing the letters (e.g. italic).
- * @param fontSynthesis Whether to synthesize font weight and/or style when the requested weight
- * or style cannot be found in the provided font family.
+ * @param fontSynthesis Whether to synthesize font weight and/or style when the requested weight or
+ * style cannot be found in the provided font family.
*/
class CurvedTextStyle(
val background: Color = Color.Unspecified,
@@ -69,11 +70,13 @@
* @param background The background color for the text.
* @param color The text color.
* @param fontSize The size of glyphs (in logical pixels) to use when painting the text. This
- * may be [TextUnit.Unspecified] for inheriting from another [CurvedTextStyle].
+ * may be [TextUnit.Unspecified] for inheriting from another [CurvedTextStyle].
*/
- @Deprecated("This overload is provided for backwards compatibility with Compose for " +
- "Wear OS 1.0. A newer overload is available with additional font parameters.",
- level = DeprecationLevel.HIDDEN)
+ @Deprecated(
+ "This overload is provided for backwards compatibility with Compose for " +
+ "Wear OS 1.0. A newer overload is available with additional font parameters.",
+ level = DeprecationLevel.HIDDEN
+ )
constructor(
background: Color = Color.Unspecified,
color: Color = Color.Unspecified,
@@ -84,10 +87,12 @@
* Create a curved text style from the given text style.
*
* Note that not all parameters in the text style will be used, only [TextStyle.color],
- * [TextStyle.fontSize], [TextStyle.background], [TextStyle.fontFamily],
- * [TextStyle.fontWeight], [TextStyle.fontStyle] and [TextStyle.fontSynthesis].
+ * [TextStyle.fontSize], [TextStyle.background], [TextStyle.fontFamily], [TextStyle.fontWeight],
+ * [TextStyle.fontStyle] and [TextStyle.fontSynthesis].
*/
- constructor(style: TextStyle) : this(
+ constructor(
+ style: TextStyle
+ ) : this(
style.background,
style.color,
style.fontSize,
@@ -98,8 +103,8 @@
)
/**
- * Returns a new curved text style that is a combination of this style and the given
- * [other] style.
+ * Returns a new curved text style that is a combination of this style and the given [other]
+ * style.
*
* [other] curved text style's null or inherit properties are replaced with the non-null
* properties of this curved text style. Another way to think of it is that the "missing"
@@ -121,13 +126,13 @@
)
}
- /**
- * Plus operator overload that applies a [merge].
- */
+ /** Plus operator overload that applies a [merge]. */
operator fun plus(other: CurvedTextStyle): CurvedTextStyle = this.merge(other)
- @Deprecated("This overload is provided for backwards compatibility with Compose for " +
- "Wear OS 1.0. A newer overload is available with additional font parameters.")
+ @Deprecated(
+ "This overload is provided for backwards compatibility with Compose for " +
+ "Wear OS 1.0. A newer overload is available with additional font parameters."
+ )
fun copy(
background: Color = this.background,
color: Color = this.color,
diff --git a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/Expandable.kt b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/Expandable.kt
index 4a6c60c..78163f3 100644
--- a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/Expandable.kt
+++ b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/Expandable.kt
@@ -41,9 +41,11 @@
* Create and [remember] an [ExpandableState]
*
* Example of an expandable list:
+ *
* @sample androidx.wear.compose.foundation.samples.ExpandableWithItemsSample
*
* Example of an expandable text:
+ *
* @sample androidx.wear.compose.foundation.samples.ExpandableTextSample
*
* @param initiallyExpanded The initial value of the state.
@@ -58,21 +60,21 @@
): ExpandableState {
val scope = rememberCoroutineScope()
return rememberSaveable(
- saver = ExpandableState.saver(
- expandAnimationSpec = expandAnimationSpec,
- collapseAnimationSpec = collapseAnimationSpec,
- )
+ saver =
+ ExpandableState.saver(
+ expandAnimationSpec = expandAnimationSpec,
+ collapseAnimationSpec = collapseAnimationSpec,
+ )
) {
ExpandableState(initiallyExpanded, scope, expandAnimationSpec, collapseAnimationSpec)
}
}
/**
- * Create and [remember] a mapping from keys to [ExpandableState]s
- * [ExpandableState]s can be requested by key, and we will created with the parameters given here
- * when a mapping didn't exist before.
- * This is mainly useful when you want to have a variable number of expandables, that can change at
- * runtime (for example, elements on a ScalingLazyColumn)
+ * Create and [remember] a mapping from keys to [ExpandableState]s [ExpandableState]s can be
+ * requested by key, and we will created with the parameters given here when a mapping didn't exist
+ * before. This is mainly useful when you want to have a variable number of expandables, that can
+ * change at runtime (for example, elements on a ScalingLazyColumn)
*
* @param initiallyExpanded A function to compute the initial state given the key.
* @param expandAnimationSpec The [AnimationSpec] to use when showing the extra information.
@@ -95,16 +97,17 @@
* Adds a series of items, that will be expanded/collapsed according to the [ExpandableState]
*
* Example of an expandable list:
+ *
* @sample androidx.wear.compose.foundation.samples.ExpandableWithItemsSample
*
* @param state The [ExpandableState] connected to these items.
* @param count The number of items
- * @param key a factory of stable and unique keys representing the item. Using the same key
- * for multiple items in the list is not allowed. Type of the key should be saveable
- * via Bundle on Android. If null is passed the position in the list will represent the key.
- * When you specify the key the scroll position will be maintained based on the key, which
- * means if you add/remove items before the current visible item the item with the given key
- * will be kept as the first visible one.
+ * @param key a factory of stable and unique keys representing the item. Using the same key for
+ * multiple items in the list is not allowed. Type of the key should be saveable via Bundle on
+ * Android. If null is passed the position in the list will represent the key. When you specify
+ * the key the scroll position will be maintained based on the key, which means if you add/remove
+ * items before the current visible item the item with the given key will be kept as the first
+ * visible one.
* @param itemContent the content displayed by a single item
*/
public fun ScalingLazyListScope.expandableItems(
@@ -116,8 +119,7 @@
repeat(count) { itemIndex ->
// Animations for each item start in inverse order, the first item animates last.
val animationStart = count - 1 - itemIndex
- val animationProgress =
- (state.expandProgress * count - animationStart).coerceIn(0f, 1f)
+ val animationProgress = (state.expandProgress * count - animationStart).coerceIn(0f, 1f)
if (animationProgress > 0) {
item(key = key?.invoke(itemIndex)) {
Layout(
@@ -140,18 +142,18 @@
* Adds a single item, that will be expanded/collapsed according to the [ExpandableState].
*
* Example of an expandable text:
+ *
* @sample androidx.wear.compose.foundation.samples.ExpandableTextSample
*
* The item should support two levels of information display (for example, a text showing a few
* lines in the collapsed state, and more in the expanded state)
*
* @param state The [ExpandableState] connected to this item.
- * @param key A stable and unique key representing the item. Using the same key
- * for multiple items in the list is not allowed. Type of the key should be saveable
- * via Bundle on Android. If null is passed the position in the list will represent the key.
- * When you specify the key the scroll position will be maintained based on the key, which
- * means if you add/remove items before the current visible item the item with the given key
- * will be kept as the first visible one.
+ * @param key A stable and unique key representing the item. Using the same key for multiple items
+ * in the list is not allowed. Type of the key should be saveable via Bundle on Android. If null
+ * is passed the position in the list will represent the key. When you specify the key the scroll
+ * position will be maintained based on the key, which means if you add/remove items before the
+ * current visible item the item with the given key will be kept as the first visible one.
* @param content the content displayed by the item, according to its expanded/collapsed state.
*/
public fun ScalingLazyListScope.expandableItem(
@@ -165,15 +167,15 @@
* out when the corresponding expandables are expanded.
*
* Example of an expandable text:
+ *
* @sample androidx.wear.compose.foundation.samples.ExpandableTextSample
*
* @param state The [ExpandableState] to connect this button to.
- * @param key A stable and unique key representing the item. Using the same key
- * for multiple items in the list is not allowed. Type of the key should be saveable
- * via Bundle on Android. If null is passed the position in the list will represent the key.
- * When you specify the key the scroll position will be maintained based on the key, which
- * means if you add/remove items before the current visible item the item with the given key
- * will be kept as the first visible one.
+ * @param key A stable and unique key representing the item. Using the same key for multiple items
+ * in the list is not allowed. Type of the key should be saveable via Bundle on Android. If null
+ * is passed the position in the list will represent the key. When you specify the key the scroll
+ * position will be maintained based on the key, which means if you add/remove items before the
+ * current visible item the item with the given key will be kept as the first visible one.
* @param content the content displayed, this should usually be a CompactChip or OutlineCompactChip.
*/
public fun ScalingLazyListScope.expandableButton(
@@ -227,7 +229,8 @@
* It's used to control the showing/hiding of extra information either directly or connecting it
* with something like a button.
*/
-public class ExpandableState internal constructor(
+public class ExpandableState
+internal constructor(
initiallyExpanded: Boolean,
private val coroutineScope: CoroutineScope,
private val expandAnimationSpec: AnimationSpec<Float>,
@@ -236,10 +239,9 @@
private val _expandProgress = Animatable(if (initiallyExpanded) 1f else 0f)
/**
- * While in the middle of the animation, this represents the progress from 0f (collapsed) to
- * 1f (expanded), or the other way around.
- * If no animation is running, it's either 0f if the extra content is not showing, or 1f if
- * the extra content is showing.
+ * While in the middle of the animation, this represents the progress from 0f (collapsed) to 1f
+ * (expanded), or the other way around. If no animation is running, it's either 0f if the extra
+ * content is not showing, or 1f if the extra content is showing.
*/
val expandProgress
get() = _expandProgress.value
@@ -252,8 +254,7 @@
* Modifying this value triggers a change to show/hide the extra information.
*/
var expanded
- @JvmName("isExpanded")
- get() = _expandProgress.targetValue == 1f
+ @JvmName("isExpanded") get() = _expandProgress.targetValue == 1f
set(newValue) {
if (expanded != newValue) {
coroutineScope.launch {
@@ -267,9 +268,7 @@
}
companion object {
- /**
- * The default [Saver] implementation for [ExpandableState].
- */
+ /** The default [Saver] implementation for [ExpandableState]. */
@Composable
fun saver(
expandAnimationSpec: AnimationSpec<Float>,
@@ -292,11 +291,12 @@
}
/**
- * A class that maps from keys of the given type to [ExpandableState].
- * An instance can be created and remembered with [rememberExpandableStateMapping]
+ * A class that maps from keys of the given type to [ExpandableState]. An instance can be created
+ * and remembered with [rememberExpandableStateMapping]
*/
@ExperimentalWearFoundationApi
-public class ExpandableStateMapping<T> internal constructor(
+public class ExpandableStateMapping<T>
+internal constructor(
private val initiallyExpanded: (key: T) -> Boolean,
private val coroutineScope: CoroutineScope,
private val expandAnimationSpec: AnimationSpec<Float>,
@@ -307,27 +307,26 @@
/**
* Returns the [ExpandableState] for the given key if the value is present and not null.
- * Otherwise, creates a new one, puts it into the map under the given key and returns it.
- * The parameters used to create the new [ExpandableState] are the ones passed to
+ * Otherwise, creates a new one, puts it into the map under the given key and returns it. The
+ * parameters used to create the new [ExpandableState] are the ones passed to
* [rememberExpandableStateMapping]
*/
- public fun getOrPutNew(key: T) = states.getOrPut(key) {
- ExpandableState(initiallyExpanded(key), coroutineScope,
- expandAnimationSpec, collapseAnimationSpec)
- }
+ public fun getOrPutNew(key: T) =
+ states.getOrPut(key) {
+ ExpandableState(
+ initiallyExpanded(key),
+ coroutineScope,
+ expandAnimationSpec,
+ collapseAnimationSpec
+ )
+ }
}
-/**
- * Contains the default values used by Expandable components.
- */
+/** Contains the default values used by Expandable components. */
public object ExpandableItemsDefaults {
- /**
- * Default animation used to show extra information.
- */
+ /** Default animation used to show extra information. */
val expandAnimationSpec: AnimationSpec<Float> = TweenSpec(1000)
- /**
- * Default animation used to hide extra information.
- */
+ /** Default animation used to hide extra information. */
val collapseAnimationSpec: AnimationSpec<Float> = TweenSpec(1000)
}
diff --git a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/HierarchicalFocusCoordinator.kt b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/HierarchicalFocusCoordinator.kt
index 4a7a3dc..8b4f00f 100644
--- a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/HierarchicalFocusCoordinator.kt
+++ b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/HierarchicalFocusCoordinator.kt
@@ -34,23 +34,22 @@
/**
* Coordinates focus for any composables in [content] and determines which composable will get
- * focus.
- * [HierarchicalFocusCoordinator]s can be nested, and form a tree, with an implicit root.
+ * focus. [HierarchicalFocusCoordinator]s can be nested, and form a tree, with an implicit root.
* Focus-requiring components (i.e. components using [OnFocusChange] or [RequestFocusWhenActive])
* should only be in the leaf [HierarchicalFocusCoordinator]s, and there should be at most one per
- * [HierarchicalFocusCoordinator].
- * For [HierarchicalFocusCoordinator] elements sharing a parent (or at the top level, sharing the
- * implicit root parent), only one should have focus enabled.
- * The selected [HierarchicalFocusCoordinator] is the one that has focus enabled for itself and all
+ * [HierarchicalFocusCoordinator]. For [HierarchicalFocusCoordinator] elements sharing a parent (or
+ * at the top level, sharing the implicit root parent), only one should have focus enabled. The
+ * selected [HierarchicalFocusCoordinator] is the one that has focus enabled for itself and all
* ancestors, it will pass focus to its focus-requiring component if it has one, or call
- * FocusManager#clearFocus() otherwise.
- * If no [HierarchicalFocusCoordinator] is selected, there will be no change on the focus state.
+ * FocusManager#clearFocus() otherwise. If no [HierarchicalFocusCoordinator] is selected, there will
+ * be no change on the focus state.
*
* Example usage:
+ *
* @sample androidx.wear.compose.foundation.samples.HierarchicalFocusCoordinatorSample
*
- * @param requiresFocus a function that returns true when the [content] is active in the
- * composition and requires the focus
+ * @param requiresFocus a function that returns true when the [content] is active in the composition
+ * and requires the focus
* @param content The content of this component.
*/
@Composable
@@ -68,45 +67,38 @@
}
/**
- * Use as part of a focus-requiring component to register a callback to be notified when the
- * focus state changes.
+ * Use as part of a focus-requiring component to register a callback to be notified when the focus
+ * state changes.
*
* @param onFocusChanged callback to be invoked when the focus state changes, the parameter is the
- * new state (if true, we are becoming active and should request focus).
+ * new state (if true, we are becoming active and should request focus).
*/
@Composable
@ExperimentalWearFoundationApi
public fun OnFocusChange(onFocusChanged: CoroutineScope.(Boolean) -> Unit) {
- FocusComposableImpl(
- focusEnabled = { true },
- onFocusChanged = onFocusChanged,
- content = {}
- )
+ FocusComposableImpl(focusEnabled = { true }, onFocusChanged = onFocusChanged, content = {})
}
/**
- * Use as part of a focus-requiring component to register a callback to automatically request
- * focus when this component is active.
- * Note that this may call requestFocus in the provided FocusRequester, so that focusRequester
- * should be used in a .focusRequester modifier on a Composable that is part of the composition.
+ * Use as part of a focus-requiring component to register a callback to automatically request focus
+ * when this component is active. Note that this may call requestFocus in the provided
+ * FocusRequester, so that focusRequester should be used in a .focusRequester modifier on a
+ * Composable that is part of the composition.
*
* @param focusRequester The associated [FocusRequester] to request focus on.
*/
@Composable
@ExperimentalWearFoundationApi
public fun RequestFocusWhenActive(focusRequester: FocusRequester) {
- OnFocusChange {
- if (it) focusRequester.requestFocus()
- }
+ OnFocusChange { if (it) focusRequester.requestFocus() }
}
/**
- * Creates, remembers and returns a new [FocusRequester], that will have .requestFocus called
- * when the enclosing [HierarchicalFocusCoordinator] becomes active.
- * Note that the location you call this is important, in particular, which
- * [HierarchicalFocusCoordinator] is enclosing it. Also, this may call requestFocus in the returned
- * FocusRequester, so that focusRequester should be used in a .focusRequester modifier on a
- * Composable that is part of the composition.
+ * Creates, remembers and returns a new [FocusRequester], that will have .requestFocus called when
+ * the enclosing [HierarchicalFocusCoordinator] becomes active. Note that the location you call this
+ * is important, in particular, which [HierarchicalFocusCoordinator] is enclosing it. Also, this may
+ * call requestFocus in the returned FocusRequester, so that focusRequester should be used in a
+ * .focusRequester modifier on a Composable that is part of the composition.
*/
@Composable
@ExperimentalWearFoundationApi
@@ -115,11 +107,11 @@
/**
* Implements a node in the Focus control tree (either a [HierarchicalFocusCoordinator] or
- * [OnFocusChange]).
- * Each [FocusComposableImpl] maps to a [FocusNode] in our internal representation, this is used to:
+ * [OnFocusChange]). Each [FocusComposableImpl] maps to a [FocusNode] in our internal
+ * representation, this is used to:
* 1) Check that our parent is focused (or we have no explicit parent), to see if we can be focused.
* 2) See if we have children. If not, we are a leaf node and will forward focus status updates to
- * the onFocusChanged callback.
+ * the onFocusChanged callback.
*/
@Composable
internal fun FocusComposableImpl(
@@ -131,18 +123,18 @@
val parent by rememberUpdatedState(LocalFocusNodeParent.current)
// Node in our internal tree representation of the FocusComposableImpl
- val node = remember { FocusNode(focused = derivedStateOf {
- (parent?.focused?.value ?: true) && updatedFocusEnabled()
- }) }
+ val node = remember {
+ FocusNode(
+ focused = derivedStateOf { (parent?.focused?.value ?: true) && updatedFocusEnabled() }
+ )
+ }
// Attach our node to our parent's (and remove if we leave the composition).
parent?.let {
DisposableEffect(it) {
it.children.add(node)
- onDispose {
- it.children.remove(node)
- }
+ onDispose { it.children.remove(node) }
}
}
diff --git a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/InternalMutatorMutex.kt b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/InternalMutatorMutex.kt
index e5717fc..bfdf78f 100644
--- a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/InternalMutatorMutex.kt
+++ b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/InternalMutatorMutex.kt
@@ -31,16 +31,16 @@
/**
* Mutual exclusion for UI state mutation over time.
*
- * [mutate] permits interruptible state mutation over time using a standard [MutatePriority].
- * A [InternalMutatorMutex] enforces that only a single writer can be active at a time for a particular
- * state resource. Instead of queueing callers that would acquire the lock like a traditional
- * [Mutex], new attempts to [mutate] the guarded state will either cancel the current mutator or
- * if the current mutator has a higher priority, the new caller will throw [CancellationException].
+ * [mutate] permits interruptible state mutation over time using a standard [MutatePriority]. A
+ * [InternalMutatorMutex] enforces that only a single writer can be active at a time for a
+ * particular state resource. Instead of queueing callers that would acquire the lock like a
+ * traditional [Mutex], new attempts to [mutate] the guarded state will either cancel the current
+ * mutator or if the current mutator has a higher priority, the new caller will throw
+ * [CancellationException].
*
- * [InternalMutatorMutex] should be used for implementing hoisted state objects that many mutators may
- * want to manipulate over time such that those mutators can coordinate with one another. The
+ * [InternalMutatorMutex] should be used for implementing hoisted state objects that many mutators
+ * may want to manipulate over time such that those mutators can coordinate with one another. The
* [InternalMutatorMutex] instance should be hidden as an implementation detail. For example:
- *
*/
@Stable
internal class InternalMutatorMutex {
@@ -71,14 +71,14 @@
* If [mutate] is called while another call to [mutate] or [mutateWith] is in progress, their
* [priority] values are compared. If the new caller has a [priority] equal to or higher than
* the call in progress, the call in progress will be cancelled, throwing
- * [CancellationException] and the new caller's [block] will be invoked. If the call in
- * progress had a higher [priority] than the new caller, the new caller will throw
+ * [CancellationException] and the new caller's [block] will be invoked. If the call in progress
+ * had a higher [priority] than the new caller, the new caller will throw
* [CancellationException] without invoking [block].
*
- * @param priority the priority of this mutation; [MutatePriority.Default] by default.
- * Higher priority mutations will interrupt lower priority mutations.
+ * @param priority the priority of this mutation; [MutatePriority.Default] by default. Higher
+ * priority mutations will interrupt lower priority mutations.
* @param block mutation code to run mutually exclusive with any other call to [mutate],
- * [mutateWith] or [tryMutate].
+ * [mutateWith] or [tryMutate].
*/
suspend fun <R> mutate(
priority: MutatePriority = MutatePriority.Default,
@@ -101,22 +101,22 @@
* Enforce that only a single caller may be active at a time.
*
* If [mutateWith] is called while another call to [mutate] or [mutateWith] is in progress,
- * their [priority] values are compared. If the new caller has a [priority] equal to or
- * higher than the call in progress, the call in progress will be cancelled, throwing
- * [CancellationException] and the new caller's [block] will be invoked. If the call in
- * progress had a higher [priority] than the new caller, the new caller will throw
+ * their [priority] values are compared. If the new caller has a [priority] equal to or higher
+ * than the call in progress, the call in progress will be cancelled, throwing
+ * [CancellationException] and the new caller's [block] will be invoked. If the call in progress
+ * had a higher [priority] than the new caller, the new caller will throw
* [CancellationException] without invoking [block].
*
- * This variant of [mutate] calls its [block] with a [receiver], removing the need to create
- * an additional capturing lambda to invoke it with a receiver object. This can be used to
- * expose a mutable scope to the provided [block] while leaving the rest of the state object
- * read-only. For example:
+ * This variant of [mutate] calls its [block] with a [receiver], removing the need to create an
+ * additional capturing lambda to invoke it with a receiver object. This can be used to expose a
+ * mutable scope to the provided [block] while leaving the rest of the state object read-only.
+ * For example:
*
* @param receiver the receiver `this` that [block] will be called with
- * @param priority the priority of this mutation; [MutatePriority.Default] by default.
- * Higher priority mutations will interrupt lower priority mutations.
+ * @param priority the priority of this mutation; [MutatePriority.Default] by default. Higher
+ * priority mutations will interrupt lower priority mutations.
* @param block mutation code to run mutually exclusive with any other call to [mutate],
- * [mutateWith] or [tryMutate].
+ * [mutateWith] or [tryMutate].
*/
suspend fun <T, R> mutateWith(
receiver: T,
@@ -137,18 +137,17 @@
}
/**
- * Attempt to mutate synchronously if there is no other active caller.
- * If there is no other active caller, the [block] will be executed in a lock. If there is
- * another active caller, this method will return false, indicating that the active caller
- * needs to be cancelled through a [mutate] or [mutateWith] call with an equal or higher
- * mutation priority.
+ * Attempt to mutate synchronously if there is no other active caller. If there is no other
+ * active caller, the [block] will be executed in a lock. If there is another active caller,
+ * this method will return false, indicating that the active caller needs to be cancelled
+ * through a [mutate] or [mutateWith] call with an equal or higher mutation priority.
*
* Calls to [mutate] and [mutateWith] will suspend until execution of the [block] has finished.
*
* @param block mutation code to run mutually exclusive with any other call to [mutate],
- * [mutateWith] or [tryMutate].
+ * [mutateWith] or [tryMutate].
* @return true if the [block] was executed, false if there was another active caller and the
- * [block] was not executed.
+ * [block] was not executed.
*/
fun tryMutate(block: () -> Unit): Boolean {
val didLock = mutex.tryLock()
diff --git a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/Resources.kt b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/Resources.kt
index 1ffc795..ac32e2f 100644
--- a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/Resources.kt
+++ b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/Resources.kt
@@ -23,7 +23,5 @@
@Composable
internal fun isRoundDevice(): Boolean {
val configuration = LocalConfiguration.current
- return remember(configuration) {
- configuration.isScreenRound
- }
+ return remember(configuration) { configuration.isScreenRound }
}
diff --git a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/SwipeToReveal.kt b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/SwipeToReveal.kt
index ba4c233..e2331bb 100644
--- a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/SwipeToReveal.kt
+++ b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/SwipeToReveal.kt
@@ -65,48 +65,36 @@
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
-/**
- * Short animation in milliseconds.
- */
+/** Short animation in milliseconds. */
internal const val SHORT_ANIMATION = 50
-/**
- * Flash animation length in milliseconds.
- */
+/** Flash animation length in milliseconds. */
internal const val FLASH_ANIMATION = 100
-/**
- * Rapid animation length in milliseconds.
- */
+/** Rapid animation length in milliseconds. */
internal const val RAPID_ANIMATION = 200
-/**
- * Quick animation length in milliseconds.
- */
+/** Quick animation length in milliseconds. */
internal const val QUICK_ANIMATION = 250
-/**
- * Standard easing for Swipe To Reveal.
- */
+/** Standard easing for Swipe To Reveal. */
internal val STANDARD_IN_OUT = CubicBezierEasing(0.20f, 0.0f, 0.0f, 1.00f)
-/**
- * Different values which the swipeable modifier can be configured to.
- */
+/** Different values which the swipeable modifier can be configured to. */
@ExperimentalWearFoundationApi
@JvmInline
public value class RevealValue private constructor(val value: Int) {
companion object {
/**
- * The default first value which generally represents the state where the revealable
- * actions have not been revealed yet. In this state, none of the actions have been
- * triggered or performed yet.
+ * The default first value which generally represents the state where the revealable actions
+ * have not been revealed yet. In this state, none of the actions have been triggered or
+ * performed yet.
*/
val Covered = RevealValue(0)
/**
- * The value which represents the state in which all the actions are revealed and the
- * top content is not being swiped. In this state, none of the actions have been
- * triggered or performed yet.
+ * The value which represents the state in which all the actions are revealed and the top
+ * content is not being swiped. In this state, none of the actions have been triggered or
+ * performed yet.
*/
val Revealing = RevealValue(1)
@@ -120,9 +108,9 @@
}
/**
- * Different values which can trigger the state change from one [RevealValue] to another.
- * These are not set by themselves and need to be set appropriately with [RevealState.snapTo]
- * and [RevealState.animateTo].
+ * Different values which can trigger the state change from one [RevealValue] to another. These are
+ * not set by themselves and need to be set appropriately with [RevealState.snapTo] and
+ * [RevealState.animateTo].
*/
@ExperimentalWearFoundationApi
@JvmInline
@@ -146,17 +134,15 @@
*/
val UndoAction = RevealActionType(2)
- /**
- * Default value when none of the above are applicable.
- */
+ /** Default value when none of the above are applicable. */
val None = RevealActionType(-1)
}
}
/**
- * Creates the required anchors to which the top content can be swiped, to reveal the actions.
- * Each value should be in the range [0..1], where 0 represents right most end and 1 represents the
- * full width of the top content starting from right and ending on left.
+ * Creates the required anchors to which the top content can be swiped, to reveal the actions. Each
+ * value should be in the range [0..1], where 0 represents right most end and 1 represents the full
+ * width of the top content starting from right and ending on left.
*
* @param coveredAnchor Anchor for the [RevealValue.Covered] value
* @param revealingAnchor Anchor for the [RevealValue.Revealing] value
@@ -176,13 +162,14 @@
}
/**
- * A class to keep track of the state of the composable. It can be used to customise
- * the behaviour and state of the composable.
+ * A class to keep track of the state of the composable. It can be used to customise the behaviour
+ * and state of the composable.
*
* @constructor Create a [RevealState].
*/
@ExperimentalWearFoundationApi
-public class RevealState internal constructor(
+public class RevealState
+internal constructor(
initialValue: RevealValue,
animationSpec: AnimationSpec<Float>,
confirmValueChange: (RevealValue) -> Boolean,
@@ -191,21 +178,17 @@
internal val coroutineScope: CoroutineScope,
internal val nestedScrollDispatcher: NestedScrollDispatcher
) {
- /**
- * [SwipeableV2State] internal instance for the state.
- */
- internal val swipeableState = SwipeableV2State(
- initialValue = initialValue,
- animationSpec = animationSpec,
- confirmValueChange = { revealValue ->
- confirmValueChangeAndReset(
- confirmValueChange,
- revealValue
- )
- },
- positionalThreshold = positionalThreshold,
- nestedScrollDispatcher = nestedScrollDispatcher
- )
+ /** [SwipeableV2State] internal instance for the state. */
+ internal val swipeableState =
+ SwipeableV2State(
+ initialValue = initialValue,
+ animationSpec = animationSpec,
+ confirmValueChange = { revealValue ->
+ confirmValueChangeAndReset(confirmValueChange, revealValue)
+ },
+ positionalThreshold = positionalThreshold,
+ nestedScrollDispatcher = nestedScrollDispatcher
+ )
public var lastActionType by mutableStateOf(RevealActionType.None)
@@ -218,8 +201,8 @@
get() = swipeableState.currentValue
/**
- * The target [RevealValue] based on the status of the component. This will be equal to
- * the [currentValue] if there is no animation running or swiping has stopped. Otherwise, this
+ * The target [RevealValue] based on the status of the component. This will be equal to the
+ * [currentValue] if there is no animation running or swiping has stopped. Otherwise, this
* returns the next [RevealValue] based on the animation/swipe direction.
*
* @see Modifier.swipeableV2
@@ -244,9 +227,9 @@
get() = swipeableState.offset ?: 0f
/**
- * Defines the anchors for revealable content. These anchors are used to determine
- * the width at which the revealable content can be revealed to and stopped without requiring
- * any input from the user.
+ * Defines the anchors for revealable content. These anchors are used to determine the width at
+ * which the revealable content can be revealed to and stopped without requiring any input from
+ * the user.
*
* @see Modifier.swipeableV2
*/
@@ -256,9 +239,7 @@
/**
* Snaps to the [targetValue] without any animation.
*
- * @param targetValue The target [RevealValue] where the [currentValue] will be changed
- * to.
- *
+ * @param targetValue The target [RevealValue] where the [currentValue] will be changed to.
* @see Modifier.swipeableV2
*/
public suspend fun snapTo(targetValue: RevealValue) {
@@ -272,8 +253,7 @@
/**
* Animates to the [targetValue] with the animation spec provided.
*
- * @param targetValue The target [RevealValue] where the [currentValue] will animate
- * to.
+ * @param targetValue The target [RevealValue] where the [currentValue] will animate to.
*/
public suspend fun animateTo(targetValue: RevealValue) {
// Cover the previously open component if revealing a different one
@@ -297,32 +277,25 @@
val canChangeValue = confirmValueChange.test(revealValue)
val currentState = this
// Update the state if the reveal value is changing to a different value than Covered.
- if (canChangeValue &&
- revealValue != RevealValue.Covered) {
- coroutineScope.launch {
- resetLastState(currentState)
- }
+ if (canChangeValue && revealValue != RevealValue.Covered) {
+ coroutineScope.launch { resetLastState(currentState) }
}
return canChangeValue
}
/**
- * Resets last state if a different SwipeToReveal is being moved to new anchor and the
- * last state is in [RevealValue.Revealing] mode which represents no action has been performed
- * yet. In [RevealValue.Revealed], the action has been performed and it will not be reset.
+ * Resets last state if a different SwipeToReveal is being moved to new anchor and the last
+ * state is in [RevealValue.Revealing] mode which represents no action has been performed yet.
+ * In [RevealValue.Revealed], the action has been performed and it will not be reset.
*/
- private suspend fun resetLastState(
- currentState: RevealState
- ) {
+ private suspend fun resetLastState(currentState: RevealState) {
val oldState = SingleSwipeCoordinator.lastUpdatedState.getAndSet(currentState)
if (currentState != oldState && oldState?.currentValue == RevealValue.Revealing) {
oldState.animateTo(RevealValue.Covered)
}
}
- /**
- * A singleton instance to keep track of the [RevealState] which was modified the last time.
- */
+ /** A singleton instance to keep track of the [RevealState] which was modified the last time. */
private object SingleSwipeCoordinator {
var lastUpdatedState: AtomicReference<RevealState?> = AtomicReference(null)
}
@@ -335,12 +308,12 @@
* @param animationSpec The animation which will be applied on the top content.
* @param confirmValueChange Optional callback invoked to confirm or veto a pending state change.
* @param positionalThreshold The positional threshold to be used when calculating the target state
- * while the reveal is in progress and when settling after the revealing ends. This is the distance
- * from the start of a transition. It will be, depending on the direction of the interaction, added
- * or subtracted from/to the origin offset. It should always be a positive value.
- * @param anchors A map of [RevealValue] to the fraction where the content can be revealed to
- * reach that value. Each anchor should be between [0..1] which will be adjusted based on total
- * width.
+ * while the reveal is in progress and when settling after the revealing ends. This is the
+ * distance from the start of a transition. It will be, depending on the direction of the
+ * interaction, added or subtracted from/to the origin offset. It should always be a positive
+ * value.
+ * @param anchors A map of [RevealValue] to the fraction where the content can be revealed to reach
+ * that value. Each anchor should be between [0..1] which will be adjusted based on total width.
*/
@ExperimentalWearFoundationApi
@Composable
@@ -369,39 +342,42 @@
/**
* A composable that can be used to add extra actions to a composable (up to two) which will be
- * revealed when the original composable is swiped to the left. This composable requires
- * a primary swipe/click action, a secondary optional click action can also be provided.
+ * revealed when the original composable is swiped to the left. This composable requires a primary
+ * swipe/click action, a secondary optional click action can also be provided.
*
- * When the composable reaches the state where all the actions are revealed and the swipe
- * continues beyond the positional threshold defined in [RevealState], the primary action is
- * automatically triggered.
+ * When the composable reaches the state where all the actions are revealed and the swipe continues
+ * beyond the positional threshold defined in [RevealState], the primary action is automatically
+ * triggered.
*
* An optional undo action can also be added. This undo action will be visible to users once the
* [RevealValue] becomes [RevealValue.Revealed].
*
- * It is strongly recommended to have icons represent the actions and maybe a text and icon for
- * the undo action.
+ * It is strongly recommended to have icons represent the actions and maybe a text and icon for the
+ * undo action.
*
* Example of SwipeToReveal with primary action and undo action
+ *
* @sample androidx.wear.compose.foundation.samples.SwipeToRevealSample
*
* Example of SwipeToReveal using [RevealScope] to delay the appearance of primary action text
+ *
* @sample androidx.wear.compose.foundation.samples.SwipeToRevealWithDelayedText
*
* Example of SwipeToReveal used with Expandables
+ *
* @sample androidx.wear.compose.foundation.samples.SwipeToRevealWithExpandables
*
* @param primaryAction The primary action that will be triggered in the event of a completed swipe.
- * We also strongly recommend to trigger the action when it is clicked.
+ * We also strongly recommend to trigger the action when it is clicked.
* @param modifier Optional [Modifier] for this component.
* @param onFullSwipe An optional lambda which will be triggered when a full swipe from either of
- * the anchors is performed.
- * @param state The [RevealState] of this component. It can be used to customise the anchors
- * and threshold config of the swipeable modifier which is applied.
+ * the anchors is performed.
+ * @param state The [RevealState] of this component. It can be used to customise the anchors and
+ * threshold config of the swipeable modifier which is applied.
* @param secondaryAction An optional action that can be added to the component. We strongly
- * recommend triggering the action when it is clicked.
- * @param undoAction The optional undo action that will be applied to the component once the
- * the [RevealState.currentValue] becomes [RevealValue.Revealed].
+ * recommend triggering the action when it is clicked.
+ * @param undoAction The optional undo action that will be applied to the component once the the
+ * [RevealState.currentValue] becomes [RevealValue.Revealed].
* @param content The content that will be initially displayed over the other actions provided.
*/
@ExperimentalWearFoundationApi
@@ -419,33 +395,33 @@
// A no-op NestedScrollConnection which does not consume scroll/fling events
val noOpNestedScrollConnection = remember { object : NestedScrollConnection {} }
Box(
- modifier = modifier
- .swipeableV2(
- state = state.swipeableState,
- orientation = Orientation.Horizontal,
- enabled = state.currentValue != RevealValue.Revealed,
- )
- .swipeAnchors(
- state = state.swipeableState,
- possibleValues = state.swipeAnchors.keys
- ) { value, layoutSize ->
- val swipeableWidth = layoutSize.width.toFloat()
- // Update the total width which will be used to calculate the anchors
- revealScope.width.floatValue = swipeableWidth
- // Multiply the anchor with -1f to get the actual swipeable anchor
- -state.swipeAnchors[value]!! * swipeableWidth
- }
- // NestedScrollDispatcher sends the scroll/fling events from the node to its parent
- // and onwards including the modifier chain. Apply it in the end to let nested scroll
- // connection applied before this modifier consume the scroll/fling events.
- .nestedScroll(noOpNestedScrollConnection, state.nestedScrollDispatcher)
+ modifier =
+ modifier
+ .swipeableV2(
+ state = state.swipeableState,
+ orientation = Orientation.Horizontal,
+ enabled = state.currentValue != RevealValue.Revealed,
+ )
+ .swipeAnchors(
+ state = state.swipeableState,
+ possibleValues = state.swipeAnchors.keys
+ ) { value, layoutSize ->
+ val swipeableWidth = layoutSize.width.toFloat()
+ // Update the total width which will be used to calculate the anchors
+ revealScope.width.floatValue = swipeableWidth
+ // Multiply the anchor with -1f to get the actual swipeable anchor
+ -state.swipeAnchors[value]!! * swipeableWidth
+ }
+ // NestedScrollDispatcher sends the scroll/fling events from the node to its parent
+ // and onwards including the modifier chain. Apply it in the end to let nested
+ // scroll
+ // connection applied before this modifier consume the scroll/fling events.
+ .nestedScroll(noOpNestedScrollConnection, state.nestedScrollDispatcher)
) {
val swipeCompleted = state.currentValue == RevealValue.Revealed
val lastActionIsSecondary = state.lastActionType == RevealActionType.SecondaryAction
val isWithinRevealOffset by remember {
- derivedStateOf {
- abs(state.offset) <= revealScope.revealOffset
- }
+ derivedStateOf { abs(state.offset) <= revealScope.revealOffset }
}
// Determines whether the secondary action will be visible based on the current
@@ -456,9 +432,7 @@
// when secondary action is clicked
val hideActions = !isWithinRevealOffset && lastActionIsSecondary
- val shouldDrawActions by remember {
- derivedStateOf { abs(state.offset) > 0 }
- }
+ val shouldDrawActions by remember { derivedStateOf { abs(state.offset) > 0 } }
// Draw the buttons only when offset is greater than zero.
if (shouldDrawActions) {
@@ -478,68 +452,73 @@
label = "AnimatedContentS2R"
) { displayUndo ->
if (displayUndo && undoAction != null) {
- val undoActionAlpha = animateFloatAsState(
- targetValue = if (swipeCompleted) 1f else 0f,
- animationSpec = tween(
- durationMillis = RAPID_ANIMATION,
- delayMillis = FLASH_ANIMATION,
- easing = STANDARD_IN_OUT,
- ),
- label = "UndoActionAlpha"
- )
+ val undoActionAlpha =
+ animateFloatAsState(
+ targetValue = if (swipeCompleted) 1f else 0f,
+ animationSpec =
+ tween(
+ durationMillis = RAPID_ANIMATION,
+ delayMillis = FLASH_ANIMATION,
+ easing = STANDARD_IN_OUT,
+ ),
+ label = "UndoActionAlpha"
+ )
Row(
- modifier = Modifier
- .graphicsLayer { alpha = undoActionAlpha.value }
- .fillMaxWidth(),
+ modifier =
+ Modifier.graphicsLayer { alpha = undoActionAlpha.value }
+ .fillMaxWidth(),
horizontalArrangement = Arrangement.Center
) {
ActionSlot(revealScope, content = undoAction)
}
} else {
// Animate weight for secondary action slot.
- val secondaryActionWeight = animateFloatAsState(
- targetValue = if (showSecondaryAction) 1f else 0f,
- animationSpec = tween(durationMillis = QUICK_ANIMATION),
- label = "SecondaryActionAnimationSpec"
- )
- val secondaryActionAlpha = animateFloatAsState(
- targetValue = if (!showSecondaryAction || hideActions) 0f else 1f,
- animationSpec = tween(
- durationMillis = QUICK_ANIMATION,
- easing = LinearEasing
- ),
- label = "SecondaryActionAlpha"
- )
- val primaryActionAlpha = animateFloatAsState(
- targetValue = if (hideActions) 0f else 1f,
- animationSpec = tween(durationMillis = 100, easing = LinearEasing),
- label = "PrimaryActionAlpha"
- )
- val revealedContentAlpha = animateFloatAsState(
- targetValue = if (swipeCompleted) 0f else 1f,
- animationSpec = tween(
- durationMillis = FLASH_ANIMATION,
- easing = LinearEasing
- ),
- label = "RevealedContentAlpha"
- )
+ val secondaryActionWeight =
+ animateFloatAsState(
+ targetValue = if (showSecondaryAction) 1f else 0f,
+ animationSpec = tween(durationMillis = QUICK_ANIMATION),
+ label = "SecondaryActionAnimationSpec"
+ )
+ val secondaryActionAlpha =
+ animateFloatAsState(
+ targetValue = if (!showSecondaryAction || hideActions) 0f else 1f,
+ animationSpec =
+ tween(durationMillis = QUICK_ANIMATION, easing = LinearEasing),
+ label = "SecondaryActionAlpha"
+ )
+ val primaryActionAlpha =
+ animateFloatAsState(
+ targetValue = if (hideActions) 0f else 1f,
+ animationSpec = tween(durationMillis = 100, easing = LinearEasing),
+ label = "PrimaryActionAlpha"
+ )
+ val revealedContentAlpha =
+ animateFloatAsState(
+ targetValue = if (swipeCompleted) 0f else 1f,
+ animationSpec =
+ tween(durationMillis = FLASH_ANIMATION, easing = LinearEasing),
+ label = "RevealedContentAlpha"
+ )
Row(
- modifier = Modifier
- .graphicsLayer { alpha = revealedContentAlpha.value }
- .layout { measurable, constraints ->
- val placeable = measurable.measure(
- constraints.copy(
- maxWidth = if (hideActions) {
- revealScope.revealOffset
- } else {
- abs(state.offset)
- }.roundToInt()
- )
- )
- layout(placeable.width, placeable.height) {
- placeable.placeRelative(0, 0)
- }
- },
+ modifier =
+ Modifier.graphicsLayer { alpha = revealedContentAlpha.value }
+ .layout { measurable, constraints ->
+ val placeable =
+ measurable.measure(
+ constraints.copy(
+ maxWidth =
+ if (hideActions) {
+ revealScope.revealOffset
+ } else {
+ abs(state.offset)
+ }
+ .roundToInt()
+ )
+ )
+ layout(placeable.width, placeable.height) {
+ placeable.placeRelative(0, 0)
+ }
+ },
horizontalArrangement = Arrangement.Absolute.Right
) {
// weight cannot be 0 so remove the composable when weight becomes 0
@@ -564,18 +543,18 @@
}
}
Row(
- modifier = Modifier.absoluteOffset {
- IntOffset(
- x = state.requireOffset().roundToInt().coerceAtMost(0),
- y = 0
- )
- }
+ modifier =
+ Modifier.absoluteOffset {
+ IntOffset(x = state.requireOffset().roundToInt().coerceAtMost(0), y = 0)
+ }
) {
content()
}
LaunchedEffect(state.currentValue) {
- if (state.currentValue == RevealValue.Revealed &&
- state.lastActionType == RevealActionType.None) {
+ if (
+ state.currentValue == RevealValue.Revealed &&
+ state.lastActionType == RevealActionType.None
+ ) {
onFullSwipe()
}
}
@@ -588,27 +567,28 @@
/**
* The offset, in pixels, where the revealed actions are fully visible but the existing content
* would be left in place if the reveal action was stopped. This offset is used to create the
- * anchor for [RevealValue.Revealing].
- * If there is no such anchor defined for [RevealValue.Revealing], it returns 0.0f.
+ * anchor for [RevealValue.Revealing]. If there is no such anchor defined for
+ * [RevealValue.Revealing], it returns 0.0f.
*/
/* @FloatRange(from = 0.0) */
public val revealOffset: Float
/**
- * The last [RevealActionType] that was set in [RevealState]. This may not be set if
- * the state changed via interaction and not through API call.
+ * The last [RevealActionType] that was set in [RevealState]. This may not be set if the state
+ * changed via interaction and not through API call.
*/
public val lastActionType: RevealActionType
}
@OptIn(ExperimentalWearFoundationApi::class)
-private class RevealScopeImpl constructor(
+private class RevealScopeImpl
+constructor(
val revealState: RevealState,
) : RevealScope {
/**
- * The total width of the overlay content in pixels. Initialise to zero,
- * updated when the width changes.
+ * The total width of the overlay content in pixels. Initialise to zero, updated when the width
+ * changes.
*/
val width = mutableFloatStateOf(0.0f)
@@ -619,19 +599,13 @@
get() = revealState.lastActionType
}
-/**
- * An internal object containing some defaults used across the Swipe to reveal component.
- */
+/** An internal object containing some defaults used across the Swipe to reveal component. */
@OptIn(ExperimentalWearFoundationApi::class)
internal object SwipeToRevealDefaults {
- /**
- * Default animation spec used when moving between states.
- */
+ /** Default animation spec used when moving between states. */
internal val animationSpec = SwipeableV2Defaults.AnimationSpec
- /**
- * Default padding space between action slots.
- */
+ /** Default padding space between action slots. */
internal val padding = 2.dp
/**
@@ -645,8 +619,8 @@
* Default position threshold that needs to be swiped in order to transition to the next state.
* Used in conjunction with [revealingRatio]; for example, a threshold of 0.5 with a revealing
* ratio of 0.7 means that the user needs to swipe at least 35% (0.5 * 0.7) of the component
- * width to go from [RevealValue.Covered] to [RevealValue.Revealing] and at least 85%
- * (0.7 + 0.5 * (1 - 0.7)) of the component width to go from [RevealValue.Revealing] to
+ * width to go from [RevealValue.Covered] to [RevealValue.Revealing] and at least 85% (0.7 +
+ * 0.5 * (1 - 0.7)) of the component width to go from [RevealValue.Revealing] to
* [RevealValue.Revealed].
*/
internal val positionalThreshold = fractionalPositionalThreshold(0.5f)
@@ -662,59 +636,46 @@
content: @Composable RevealScope.() -> Unit
) {
Box(
- modifier = modifier
- .fillMaxHeight()
- .weight(weight)
- .graphicsLayer { alpha = opacity.value },
+ modifier = modifier.fillMaxHeight().weight(weight).graphicsLayer { alpha = opacity.value },
contentAlignment = Alignment.Center
) {
- with(revealScope) {
- content()
- }
+ with(revealScope) { content() }
}
}
private fun fadeInUndo(): ContentTransform =
ContentTransform(
// animation spec for the fading in undo action (fadeIn + scaleIn)
- targetContentEnter = fadeIn(
- animationSpec = tween(
- durationMillis = RAPID_ANIMATION,
- delayMillis = FLASH_ANIMATION,
- easing = LinearEasing,
- )
- ) + scaleIn(
- initialScale = 1.2f,
- animationSpec = tween(
- durationMillis = RAPID_ANIMATION,
- delayMillis = FLASH_ANIMATION,
- easing = STANDARD_IN_OUT
- )
- ),
+ targetContentEnter =
+ fadeIn(
+ animationSpec =
+ tween(
+ durationMillis = RAPID_ANIMATION,
+ delayMillis = FLASH_ANIMATION,
+ easing = LinearEasing,
+ )
+ ) +
+ scaleIn(
+ initialScale = 1.2f,
+ animationSpec =
+ tween(
+ durationMillis = RAPID_ANIMATION,
+ delayMillis = FLASH_ANIMATION,
+ easing = STANDARD_IN_OUT
+ )
+ ),
// animation spec for the fading out content and actions (fadeOut)
- initialContentExit = fadeOut(
- animationSpec = tween(
- durationMillis = FLASH_ANIMATION,
- easing = LinearEasing
- )
- )
+ initialContentExit =
+ fadeOut(animationSpec = tween(durationMillis = FLASH_ANIMATION, easing = LinearEasing))
)
private fun fadeOutUndo(): ContentTransform =
ContentTransform(
// No animation, fade-in in 0 milliseconds since enter transition is mandatory
- targetContentEnter = fadeIn(
- animationSpec = tween(
- durationMillis = 0,
- delayMillis = SHORT_ANIMATION
- )
- ),
+ targetContentEnter =
+ fadeIn(animationSpec = tween(durationMillis = 0, delayMillis = SHORT_ANIMATION)),
// animation spec for the fading out undo action (fadeOut + scaleOut)
- initialContentExit = fadeOut(
- animationSpec = tween(
- durationMillis = SHORT_ANIMATION,
- easing = LinearEasing
- )
- )
+ initialContentExit =
+ fadeOut(animationSpec = tween(durationMillis = SHORT_ANIMATION, easing = LinearEasing))
)
diff --git a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/SwipeableV2.kt b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/SwipeableV2.kt
index 2087c5c3..c4ffe24 100644
--- a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/SwipeableV2.kt
+++ b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/SwipeableV2.kt
@@ -72,8 +72,8 @@
* Enable swipe gestures between a set of predefined values.
*
* When a swipe is detected, the offset of the [SwipeableV2State] will be updated with the swipe
- * delta. You should use this offset to move your content accordingly (see [Modifier.offset]).
- * When the swipe ends, the offset will be animated to one of the anchors and when that anchor is
+ * delta. You should use this offset to move your content accordingly (see [Modifier.offset]). When
+ * the swipe ends, the offset will be animated to one of the anchors and when that anchor is
* reached, the value of the [SwipeableV2State] will also be updated to the value corresponding to
* the new anchor.
*
@@ -82,10 +82,10 @@
* @param state The associated [SwipeableV2State].
* @param orientation The orientation in which the swipeable can be swiped.
* @param enabled Whether this [swipeableV2] is enabled and should react to the user's input.
- * @param reverseDirection Whether to reverse the direction of the swipe, so a top to bottom
- * swipe will behave like bottom to top, and a left to right swipe will behave like right to left.
- * @param interactionSource Optional [MutableInteractionSource] that will passed on to
- * the internal [Modifier.draggable].
+ * @param reverseDirection Whether to reverse the direction of the swipe, so a top to bottom swipe
+ * will behave like bottom to top, and a left to right swipe will behave like right to left.
+ * @param interactionSource Optional [MutableInteractionSource] that will passed on to the internal
+ * [Modifier.draggable].
*/
@ExperimentalWearFoundationApi
@RestrictTo(LIBRARY_GROUP)
@@ -105,43 +105,50 @@
// should be gone anyway. Also note that the regular Android swipe-to-go-back gesture works very
// differently than the wear gesture so we don't need this workaround to support it.
// TODO(b/201009199): Modifier.swipeableV2 should coordinate with the nested scrolling system.
- val semantics = if (!enabled) Modifier else Modifier.semantics {
- // Set a fake scroll range axis so that the AndroidComposeView can correctly report whether
- // scrolling is supported via canScroll{Horizontally,Vertically}.
- val range = ScrollAxisRange(
- value = {
- // Avoid dividing by 0.
- if (state.minOffset == state.maxOffset) {
- 0f
- } else {
- val clampedOffset = (state.offset ?: 0f)
- .coerceIn(state.minOffset, state.maxOffset)
- // [0f, 1f] representing the fraction between the swipe bounds.
- // Return the remaining fraction available to swipe.
- (state.maxOffset - clampedOffset) / (state.maxOffset - state.minOffset)
+ val semantics =
+ if (!enabled) Modifier
+ else
+ Modifier.semantics {
+ // Set a fake scroll range axis so that the AndroidComposeView can correctly report
+ // whether
+ // scrolling is supported via canScroll{Horizontally,Vertically}.
+ val range =
+ ScrollAxisRange(
+ value = {
+ // Avoid dividing by 0.
+ if (state.minOffset == state.maxOffset) {
+ 0f
+ } else {
+ val clampedOffset =
+ (state.offset ?: 0f).coerceIn(state.minOffset, state.maxOffset)
+ // [0f, 1f] representing the fraction between the swipe bounds.
+ // Return the remaining fraction available to swipe.
+ (state.maxOffset - clampedOffset) /
+ (state.maxOffset - state.minOffset)
+ }
+ },
+ maxValue = { 1f },
+ reverseScrolling = reverseDirection
+ )
+ when (orientation) {
+ Orientation.Horizontal -> horizontalScrollAxisRange = range
+ Orientation.Vertical -> verticalScrollAxisRange = range
}
- },
- maxValue = { 1f },
- reverseScrolling = reverseDirection
- )
- when (orientation) {
- Orientation.Horizontal -> horizontalScrollAxisRange = range
- Orientation.Vertical -> verticalScrollAxisRange = range
- }
- }
+ }
// Update the orientation in the swipeable state
state.orientation = orientation
- return this.then(semantics).draggable(
- state = state.swipeDraggableState,
- orientation = orientation,
- enabled = enabled,
- interactionSource = interactionSource,
- reverseDirection = reverseDirection,
- startDragImmediately = state.isAnimationRunning,
- onDragStopped = { velocity -> launch { state.settle(velocity) } }
- )
+ return this.then(semantics)
+ .draggable(
+ state = state.swipeDraggableState,
+ orientation = orientation,
+ enabled = enabled,
+ interactionSource = interactionSource,
+ reverseDirection = reverseDirection,
+ startDragImmediately = state.isAnimationRunning,
+ onDragStopped = { velocity -> launch { state.settle(velocity) } }
+ )
}
/**
@@ -150,12 +157,12 @@
*
* @param state The associated [SwipeableV2State]
* @param possibleValues All possible values the [SwipeableV2State] could be in.
- * @param anchorChangeHandler A callback to be invoked when the anchors have changed,
- * `null` by default. Components with custom reconciliation logic should implement this callback,
- * i.e. to re-target an in-progress animation.
+ * @param anchorChangeHandler A callback to be invoked when the anchors have changed, `null` by
+ * default. Components with custom reconciliation logic should implement this callback, i.e. to
+ * re-target an in-progress animation.
* @param calculateAnchor This method will be invoked to calculate the position of all
- * [possibleValues], given this node's layout size. Return the anchor's offset from the initial
- * anchor, or `null` to indicate that a value does not have an anchor.
+ * [possibleValues], given this node's layout size. Return the anchor's offset from the initial
+ * anchor, or `null` to indicate that a value does not have an anchor.
*/
@ExperimentalWearFoundationApi
@RestrictTo(LIBRARY_GROUP)
@@ -164,56 +171,60 @@
possibleValues: Set<T>,
anchorChangeHandler: AnchorChangeHandler<T>? = null,
calculateAnchor: (value: T, layoutSize: IntSize) -> Float?,
-) = this.then(SwipeAnchorsModifier(
- onDensityChanged = { state.density = it },
- onSizeChanged = { layoutSize ->
- val previousAnchors = state.anchors
- val newAnchors = mutableMapOf<T, Float>()
- possibleValues.forEach {
- val anchorValue = calculateAnchor(it, layoutSize)
- if (anchorValue != null) {
- newAnchors[it] = anchorValue
- }
- }
- if (previousAnchors != newAnchors) {
- val previousTarget = state.targetValue
- val stateRequiresCleanup = state.updateAnchors(newAnchors)
- if (stateRequiresCleanup) {
- anchorChangeHandler?.onAnchorsChanged(
- previousTarget,
- previousAnchors,
- newAnchors
- )
- }
- }
- },
- inspectorInfo = debugInspectorInfo {
- name = "swipeAnchors"
- properties["state"] = state
- properties["possibleValues"] = possibleValues
- properties["anchorChangeHandler"] = anchorChangeHandler
- properties["calculateAnchor"] = calculateAnchor
- }
-))
+) =
+ this.then(
+ SwipeAnchorsModifier(
+ onDensityChanged = { state.density = it },
+ onSizeChanged = { layoutSize ->
+ val previousAnchors = state.anchors
+ val newAnchors = mutableMapOf<T, Float>()
+ possibleValues.forEach {
+ val anchorValue = calculateAnchor(it, layoutSize)
+ if (anchorValue != null) {
+ newAnchors[it] = anchorValue
+ }
+ }
+ if (previousAnchors != newAnchors) {
+ val previousTarget = state.targetValue
+ val stateRequiresCleanup = state.updateAnchors(newAnchors)
+ if (stateRequiresCleanup) {
+ anchorChangeHandler?.onAnchorsChanged(
+ previousTarget,
+ previousAnchors,
+ newAnchors
+ )
+ }
+ }
+ },
+ inspectorInfo =
+ debugInspectorInfo {
+ name = "swipeAnchors"
+ properties["state"] = state
+ properties["possibleValues"] = possibleValues
+ properties["anchorChangeHandler"] = anchorChangeHandler
+ properties["calculateAnchor"] = calculateAnchor
+ }
+ )
+ )
/**
* State of the [swipeableV2] modifier.
*
- * This contains necessary information about any ongoing swipe or animation and provides methods
- * to change the state either immediately or by starting an animation. To create and remember a
+ * This contains necessary information about any ongoing swipe or animation and provides methods to
+ * change the state either immediately or by starting an animation. To create and remember a
* [SwipeableV2State] use [rememberSwipeableV2State].
*
* @param initialValue The initial value of the state.
* @param animationSpec The default animation that will be used to animate to a new state.
* @param confirmValueChange Optional callback invoked to confirm or veto a pending state change.
* @param positionalThreshold The positional threshold to be used when calculating the target state
- * while a swipe is in progress and when settling after the swipe ends. This is the distance from
- * the start of a transition. It will be, depending on the direction of the interaction, added or
- * subtracted from/to the origin offset. It should always be a positive value. See the
- * [fractionalPositionalThreshold] and [fixedPositionalThreshold] methods.
+ * while a swipe is in progress and when settling after the swipe ends. This is the distance from
+ * the start of a transition. It will be, depending on the direction of the interaction, added or
+ * subtracted from/to the origin offset. It should always be a positive value. See the
+ * [fractionalPositionalThreshold] and [fixedPositionalThreshold] methods.
* @param velocityThreshold The velocity threshold (in dp per second) that the end velocity has to
- * exceed in order to animate to the next state, even if the [positionalThreshold] has not been
- * reached.
+ * exceed in order to animate to the next state, even if the [positionalThreshold] has not been
+ * reached.
*/
@Stable
@ExperimentalWearFoundationApi
@@ -230,33 +241,31 @@
private val swipeMutex = InternalMutatorMutex()
- internal val swipeDraggableState = object : DraggableState {
- private val dragScope = object : DragScope {
- override fun dragBy(pixels: Float) {
- [email protected](pixels)
+ internal val swipeDraggableState =
+ object : DraggableState {
+ private val dragScope =
+ object : DragScope {
+ override fun dragBy(pixels: Float) {
+ [email protected](pixels)
+ }
+ }
+
+ override suspend fun drag(
+ dragPriority: MutatePriority,
+ block: suspend DragScope.() -> Unit
+ ) {
+ swipe(dragPriority) { dragScope.block() }
+ }
+
+ override fun dispatchRawDelta(delta: Float) {
+ [email protected](delta)
}
}
- override suspend fun drag(
- dragPriority: MutatePriority,
- block: suspend DragScope.() -> Unit
- ) {
- swipe(dragPriority) { dragScope.block() }
- }
-
- override fun dispatchRawDelta(delta: Float) {
- [email protected](delta)
- }
- }
-
- /**
- * The orientation in which the swipeable can be swiped.
- */
+ /** The orientation in which the swipeable can be swiped. */
internal var orientation = Orientation.Horizontal
- /**
- * The current value of the [SwipeableV2State].
- */
+ /** The current value of the [SwipeableV2State]. */
var currentValue: T by mutableStateOf(initialValue)
private set
@@ -266,24 +275,24 @@
* will be the current value.
*/
val targetValue: T by derivedStateOf {
- animationTarget ?: run {
- val currentOffset = offset
- if (currentOffset != null) {
- computeTarget(currentOffset, currentValue, velocity = 0f)
- } else currentValue
- }
+ animationTarget
+ ?: run {
+ val currentOffset = offset
+ if (currentOffset != null) {
+ computeTarget(currentOffset, currentValue, velocity = 0f)
+ } else currentValue
+ }
}
/**
* The current offset, or null if it has not been initialized yet.
*
* The offset will be initialized during the first measurement phase of the node that the
- * [swipeableV2] modifier is attached to. These are the phases:
- * Composition { -> Effects } -> Layout { Measurement -> Placement } -> Drawing
- * During the first composition, the offset will be null. In subsequent compositions, the offset
- * will be derived from the anchors of the previous pass.
- * Always prefer accessing the offset from a LaunchedEffect as it will be scheduled to be
- * executed the next frame, after layout.
+ * [swipeableV2] modifier is attached to. These are the phases: Composition { -> Effects } ->
+ * Layout { Measurement -> Placement } -> Drawing During the first composition, the offset will
+ * be null. In subsequent compositions, the offset will be derived from the anchors of the
+ * previous pass. Always prefer accessing the offset from a LaunchedEffect as it will be
+ * scheduled to be executed the next frame, after layout.
*
* To guarantee stricter semantics, consider using [requireOffset].
*/
@@ -296,15 +305,15 @@
*
* @throws IllegalStateException If the offset has not been initialized yet
*/
- fun requireOffset(): Float = checkNotNull(offset) {
- "The offset was read before being initialized. Did you access the offset in a phase " +
- "before layout, like effects or composition?"
- }
+ fun requireOffset(): Float =
+ checkNotNull(offset) {
+ "The offset was read before being initialized. Did you access the offset in a phase " +
+ "before layout, like effects or composition?"
+ }
- /**
- * Whether an animation is currently in progress.
- */
- val isAnimationRunning: Boolean get() = animationTarget != null
+ /** Whether an animation is currently in progress. */
+ val isAnimationRunning: Boolean
+ get() = animationTarget != null
/**
* The fraction of the progress going from [currentValue] to [targetValue], within [0f..1f]
@@ -324,9 +333,8 @@
/**
* The velocity of the last known animation. Gets reset to 0f when an animation completes
- * successfully, but does not get reset when an animation gets interrupted.
- * You can use this value to provide smooth reconciliation behavior when re-targeting an
- * animation.
+ * successfully, but does not get reset when an animation gets interrupted. You can use this
+ * value to provide smooth reconciliation behavior when re-targeting an animation.
*/
var lastVelocity: Float by mutableFloatStateOf(0f)
private set
@@ -350,56 +358,52 @@
internal var density: Density? = null
/**
- * Update the anchors.
- * If the previous set of anchors was empty, attempt to update the offset to match the initial
- * value's anchor.
+ * Update the anchors. If the previous set of anchors was empty, attempt to update the offset to
+ * match the initial value's anchor.
*
* @return true if the state needs to be adjusted after updating the anchors, e.g. if the
- * initial value is not found in the initial set of anchors. false if no further updates are
- * needed.
+ * initial value is not found in the initial set of anchors. false if no further updates are
+ * needed.
*/
internal fun updateAnchors(newAnchors: Map<T, Float>): Boolean {
val previousAnchorsEmpty = anchors.isEmpty()
anchors = newAnchors
- val initialValueHasAnchor = if (previousAnchorsEmpty) {
- val initialValue = currentValue
- val initialValueAnchor = anchors[initialValue]
- val initialValueHasAnchor = initialValueAnchor != null
- if (initialValueHasAnchor) trySnapTo(initialValue)
- initialValueHasAnchor
- } else true
+ val initialValueHasAnchor =
+ if (previousAnchorsEmpty) {
+ val initialValue = currentValue
+ val initialValueAnchor = anchors[initialValue]
+ val initialValueHasAnchor = initialValueAnchor != null
+ if (initialValueHasAnchor) trySnapTo(initialValue)
+ initialValueHasAnchor
+ } else true
return !initialValueHasAnchor || !previousAnchorsEmpty
}
- /**
- * Whether the [value] has an anchor associated with it.
- */
+ /** Whether the [value] has an anchor associated with it. */
fun hasAnchorForValue(value: T): Boolean = anchors.containsKey(value)
/**
- * Snap to a [targetValue] without any animation.
- * If the [targetValue] is not in the set of anchors, the [currentValue] will be updated to the
- * [targetValue] without updating the offset.
- *
- * @throws CancellationException if the interaction interrupted by another interaction like a
- * gesture interaction or another programmatic interaction like a [animateTo] or [snapTo] call.
+ * Snap to a [targetValue] without any animation. If the [targetValue] is not in the set of
+ * anchors, the [currentValue] will be updated to the [targetValue] without updating the offset.
*
* @param targetValue The target value of the animation
+ * @throws CancellationException if the interaction interrupted by another interaction like a
+ * gesture interaction or another programmatic interaction like a [animateTo] or [snapTo]
+ * call.
*/
suspend fun snapTo(targetValue: T) {
swipe { snap(targetValue) }
}
/**
- * Animate to a [targetValue].
- * If the [targetValue] is not in the set of anchors, the [currentValue] will be updated to the
- * [targetValue] without updating the offset.
- *
- * @throws CancellationException if the interaction interrupted by another interaction like a
- * gesture interaction or another programmatic interaction like a [animateTo] or [snapTo] call.
+ * Animate to a [targetValue]. If the [targetValue] is not in the set of anchors, the
+ * [currentValue] will be updated to the [targetValue] without updating the offset.
*
* @param targetValue The target value of the animation
* @param velocity The velocity the animation should start with, [lastVelocity] by default
+ * @throws CancellationException if the interaction interrupted by another interaction like a
+ * gesture interaction or another programmatic interaction like a [animateTo] or [snapTo]
+ * call.
*/
suspend fun animateTo(
targetValue: T,
@@ -425,10 +429,10 @@
} finally {
animationTarget = null
val endOffset = requireOffset()
- val endState = anchors
- .entries
- .firstOrNull { (_, anchorOffset) -> abs(anchorOffset - endOffset) < 0.5f }
- ?.key
+ val endState =
+ anchors.entries
+ .firstOrNull { (_, anchorOffset) -> abs(anchorOffset - endOffset) < 0.5f }
+ ?.key
this.currentValue = endState ?: currentValue
}
} else {
@@ -443,21 +447,23 @@
var availableVelocity = velocity
// Dispatch the velocity to parent nodes for consuming
nestedScrollDispatcher?.let {
- val consumedVelocity = nestedScrollDispatcher.dispatchPreFling(
- if (orientation == Orientation.Horizontal) {
- Velocity(x = velocity, y = 0f)
- } else {
- Velocity(x = 0f, y = velocity)
- }
- )
+ val consumedVelocity =
+ nestedScrollDispatcher.dispatchPreFling(
+ if (orientation == Orientation.Horizontal) {
+ Velocity(x = velocity, y = 0f)
+ } else {
+ Velocity(x = 0f, y = velocity)
+ }
+ )
availableVelocity -= (consumedVelocity.x + consumedVelocity.y)
}
val previousValue = this.currentValue
- val targetValue = computeTarget(
- offset = requireOffset(),
- currentValue = previousValue,
- velocity = availableVelocity
- )
+ val targetValue =
+ computeTarget(
+ offset = requireOffset(),
+ currentValue = previousValue,
+ velocity = availableVelocity
+ )
if (confirmValueChange(targetValue)) {
animateTo(targetValue, availableVelocity)
} else {
@@ -477,10 +483,11 @@
// Dispatch the delta as a scroll event to parent node for consuming it
nestedScrollDispatcher?.let {
- val consumedByParent = nestedScrollDispatcher.dispatchPreScroll(
- available = offsetWithOrientation(remainingDelta),
- source = NestedScrollSource.Drag
- )
+ val consumedByParent =
+ nestedScrollDispatcher.dispatchPreScroll(
+ available = offsetWithOrientation(remainingDelta),
+ source = NestedScrollSource.Drag
+ )
remainingDelta -= (consumedByParent.x + consumedByParent.y)
}
val currentDragPosition = offset ?: 0f
@@ -492,11 +499,12 @@
}
nestedScrollDispatcher?.let {
- val consumedDelta = nestedScrollDispatcher.dispatchPostScroll(
- consumed = offsetWithOrientation(deltaToConsume),
- available = offsetWithOrientation(delta - deltaToConsume),
- source = NestedScrollSource.Drag
- )
+ val consumedDelta =
+ nestedScrollDispatcher.dispatchPostScroll(
+ consumed = offsetWithOrientation(deltaToConsume),
+ available = offsetWithOrientation(delta - deltaToConsume),
+ source = NestedScrollSource.Drag
+ )
remainingDelta -= (deltaToConsume + consumedDelta.x + consumedDelta.y)
}
return remainingDelta
@@ -510,11 +518,7 @@
}
}
- private fun computeTarget(
- offset: Float,
- currentValue: T,
- velocity: Float
- ): T {
+ private fun computeTarget(offset: Float, currentValue: T, velocity: Float): T {
val currentAnchors = anchors
val currentAnchor = currentAnchors[currentValue]
val currentDensity = requireDensity()
@@ -556,10 +560,11 @@
}
}
- private fun requireDensity() = requireNotNull(density) {
- "SwipeableState did not have a density attached. Are you using Modifier.swipeable with " +
- "this=$this SwipeableState?"
- }
+ private fun requireDensity() =
+ requireNotNull(density) {
+ "SwipeableState did not have a density attached. Are you using Modifier.swipeable with " +
+ "this=$this SwipeableState?"
+ }
private suspend fun swipe(
swipePriority: MutatePriority = MutatePriority.Default,
@@ -587,27 +592,26 @@
}
companion object {
- /**
- * The default [Saver] implementation for [SwipeableV2State].
- */
+ /** The default [Saver] implementation for [SwipeableV2State]. */
@ExperimentalWearFoundationApi
fun <T : Any> Saver(
animationSpec: AnimationSpec<Float>,
confirmValueChange: (T) -> Boolean,
positionalThreshold: Density.(distance: Float) -> Float,
velocityThreshold: Dp
- ) = Saver<SwipeableV2State<T>, T>(
- save = { it.currentValue },
- restore = {
- SwipeableV2State(
- initialValue = it,
- animationSpec = animationSpec,
- confirmValueChange = confirmValueChange,
- positionalThreshold = positionalThreshold,
- velocityThreshold = velocityThreshold
- )
- }
- )
+ ) =
+ Saver<SwipeableV2State<T>, T>(
+ save = { it.currentValue },
+ restore = {
+ SwipeableV2State(
+ initialValue = it,
+ animationSpec = animationSpec,
+ confirmValueChange = confirmValueChange,
+ positionalThreshold = positionalThreshold,
+ velocityThreshold = velocityThreshold
+ )
+ }
+ )
}
}
@@ -626,13 +630,16 @@
confirmValueChange: (newValue: T) -> Boolean = { true }
): SwipeableV2State<T> {
return rememberSaveable(
- initialValue, animationSpec, confirmValueChange,
- saver = SwipeableV2State.Saver(
- animationSpec = animationSpec,
- confirmValueChange = confirmValueChange,
- positionalThreshold = SwipeableV2Defaults.PositionalThreshold,
- velocityThreshold = SwipeableV2Defaults.VelocityThreshold
- ),
+ initialValue,
+ animationSpec,
+ confirmValueChange,
+ saver =
+ SwipeableV2State.Saver(
+ animationSpec = animationSpec,
+ confirmValueChange = confirmValueChange,
+ positionalThreshold = SwipeableV2Defaults.PositionalThreshold,
+ velocityThreshold = SwipeableV2Defaults.VelocityThreshold
+ ),
) {
SwipeableV2State(
initialValue = initialValue,
@@ -665,25 +672,22 @@
*/
@ExperimentalWearFoundationApi
@RestrictTo(LIBRARY_GROUP)
-public fun fractionalPositionalThreshold(
- fraction: Float
-): Density.(distance: Float) -> Float = { distance -> distance * fraction }
+public fun fractionalPositionalThreshold(fraction: Float): Density.(distance: Float) -> Float =
+ { distance ->
+ distance * fraction
+ }
-/**
- * Contains useful defaults for [swipeableV2] and [SwipeableV2State].
- */
+/** Contains useful defaults for [swipeableV2] and [SwipeableV2State]. */
@Stable
@ExperimentalWearFoundationApi
@RestrictTo(LIBRARY_GROUP)
public object SwipeableV2Defaults {
- /**
- * The default animation that will be used to animate to a new state.
- */
+ /** The default animation that will be used to animate to a new state. */
val AnimationSpec = SpringSpec<Float>()
/**
- * The default velocity threshold (in dp per second) that the end velocity has to
- * exceed in order to animate to the next state.
+ * The default velocity threshold (in dp per second) that the end velocity has to exceed in
+ * order to animate to the next state.
*/
val VelocityThreshold: Dp = 125.dp
@@ -695,14 +699,13 @@
fixedPositionalThreshold(56.dp)
/**
- * A [AnchorChangeHandler] implementation that attempts to reconcile an in-progress animation
- * by re-targeting it if necessary or finding the closest new anchor.
- * If the previous anchor is not in the new set of anchors, this implementation will snap to the
- * closest anchor.
+ * A [AnchorChangeHandler] implementation that attempts to reconcile an in-progress animation by
+ * re-targeting it if necessary or finding the closest new anchor. If the previous anchor is not
+ * in the new set of anchors, this implementation will snap to the closest anchor.
*
- * Consider implementing a custom handler for more complex components like sheets.
- * The [animate] and [snap] lambdas hoist the animation and snap logic. Usually these will just
- * delegate to [SwipeableV2State].
+ * Consider implementing a custom handler for more complex components like sheets. The [animate]
+ * and [snap] lambdas hoist the animation and snap logic. Usually these will just delegate to
+ * [SwipeableV2State].
*
* @param state The [SwipeableV2State] the change handler will read from
* @param animate A lambda that gets invoked to start an animation to a new target
@@ -780,20 +783,20 @@
onSizeChanged(size)
}
- override fun toString() = "SwipeAnchorsModifierImpl(updateDensity=$onDensityChanged, " +
- "onSizeChanged=$onSizeChanged)"
+ override fun toString() =
+ "SwipeAnchorsModifierImpl(updateDensity=$onDensityChanged, " +
+ "onSizeChanged=$onSizeChanged)"
}
-private fun <T> Map<T, Float>.closestAnchor(
- offset: Float = 0f,
- searchUpwards: Boolean = false
-): T {
+private fun <T> Map<T, Float>.closestAnchor(offset: Float = 0f, searchUpwards: Boolean = false): T {
require(isNotEmpty()) { "The anchors were empty when trying to find the closest anchor" }
return minBy { (_, anchor) ->
- val delta = if (searchUpwards) anchor - offset else offset - anchor
- if (delta < 0) Float.POSITIVE_INFINITY else delta
- }.key
+ val delta = if (searchUpwards) anchor - offset else offset - anchor
+ if (delta < 0) Float.POSITIVE_INFINITY else delta
+ }
+ .key
}
private fun <T> Map<T, Float>.minOrNull() = minOfOrNull { (_, offset) -> offset }
+
private fun <T> Map<T, Float>.maxOrNull() = maxOfOrNull { (_, offset) -> offset }
diff --git a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/lazy/ScalingLazyColumn.kt b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/lazy/ScalingLazyColumn.kt
index 37f0321..d40e83c 100644
--- a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/lazy/ScalingLazyColumn.kt
+++ b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/lazy/ScalingLazyColumn.kt
@@ -66,20 +66,18 @@
import androidx.wear.compose.foundation.rotary.RotaryScrollableDefaults
import androidx.wear.compose.foundation.rotary.rotaryScrollable
-/**
- * Receiver scope which is used by [ScalingLazyColumn].
- */
+/** Receiver scope which is used by [ScalingLazyColumn]. */
@ScalingLazyScopeMarker
public sealed interface ScalingLazyListScope {
/**
* Adds a single item.
*
- * @param key a stable and unique key representing the item. Using the same key
- * for multiple items in the list is not allowed. Type of the key should be saveable
- * via Bundle on Android. If null is passed the position in the list will represent the key.
- * When you specify the key the scroll position will be maintained based on the key, which
- * means if you add/remove items before the current visible item the item with the given key
- * will be kept as the first visible one.
+ * @param key a stable and unique key representing the item. Using the same key for multiple
+ * items in the list is not allowed. Type of the key should be saveable via Bundle on Android.
+ * If null is passed the position in the list will represent the key. When you specify the key
+ * the scroll position will be maintained based on the key, which means if you add/remove
+ * items before the current visible item the item with the given key will be kept as the first
+ * visible one.
* @param content the content of the item
*/
fun item(key: Any? = null, content: @Composable ScalingLazyListItemScope.() -> Unit)
@@ -88,12 +86,12 @@
* Adds a [count] of items.
*
* @param count the items count
- * @param key a factory of stable and unique keys representing the item. Using the same key
- * for multiple items in the list is not allowed. Type of the key should be saveable
- * via Bundle on Android. If null is passed the position in the list will represent the key.
- * When you specify the key the scroll position will be maintained based on the key, which
- * means if you add/remove items before the current visible item the item with the given key
- * will be kept as the first visible one.
+ * @param key a factory of stable and unique keys representing the item. Using the same key for
+ * multiple items in the list is not allowed. Type of the key should be saveable via Bundle on
+ * Android. If null is passed the position in the list will represent the key. When you
+ * specify the key the scroll position will be maintained based on the key, which means if you
+ * add/remove items before the current visible item the item with the given key will be kept
+ * as the first visible one.
* @param itemContent the content displayed by a single item
*/
fun items(
@@ -107,90 +105,92 @@
* Adds a list of items.
*
* @param items the data list
- * @param key a factory of stable and unique keys representing the item. Using the same key
- * for multiple items in the list is not allowed. Type of the key should be saveable
- * via Bundle on Android. If null is passed the position in the list will represent the key.
- * When you specify the key the scroll position will be maintained based on the key, which
- * means if you add/remove items before the current visible item the item with the given key
- * will be kept as the first visible one.
+ * @param key a factory of stable and unique keys representing the item. Using the same key for
+ * multiple items in the list is not allowed. Type of the key should be saveable via Bundle on
+ * Android. If null is passed the position in the list will represent the key. When you specify
+ * the key the scroll position will be maintained based on the key, which means if you add/remove
+ * items before the current visible item the item with the given key will be kept as the first
+ * visible one.
* @param itemContent the content displayed by a single item
*/
inline fun <T> ScalingLazyListScope.items(
items: List<T>,
noinline key: ((item: T) -> Any)? = null,
crossinline itemContent: @Composable ScalingLazyListItemScope.(item: T) -> Unit
-) = items(items.size, if (key != null) { index: Int -> key(items[index]) } else null) {
- itemContent(items[it])
-}
+) =
+ items(items.size, if (key != null) { index: Int -> key(items[index]) } else null) {
+ itemContent(items[it])
+ }
/**
* Adds a list of items where the content of an item is aware of its index.
*
* @param items the data list
- * @param key a factory of stable and unique keys representing the item. Using the same key
- * for multiple items in the list is not allowed. Type of the key should be saveable
- * via Bundle on Android. If null is passed the position in the list will represent the key.
- * When you specify the key the scroll position will be maintained based on the key, which
- * means if you add/remove items before the current visible item the item with the given key
- * will be kept as the first visible one.
+ * @param key a factory of stable and unique keys representing the item. Using the same key for
+ * multiple items in the list is not allowed. Type of the key should be saveable via Bundle on
+ * Android. If null is passed the position in the list will represent the key. When you specify
+ * the key the scroll position will be maintained based on the key, which means if you add/remove
+ * items before the current visible item the item with the given key will be kept as the first
+ * visible one.
* @param itemContent the content displayed by a single item
*/
inline fun <T> ScalingLazyListScope.itemsIndexed(
items: List<T>,
noinline key: ((index: Int, item: T) -> Any)? = null,
crossinline itemContent: @Composable ScalingLazyListItemScope.(index: Int, item: T) -> Unit
-) = items(items.size, if (key != null) { index: Int -> key(index, items[index]) } else null) {
- itemContent(it, items[it])
-}
+) =
+ items(items.size, if (key != null) { index: Int -> key(index, items[index]) } else null) {
+ itemContent(it, items[it])
+ }
/**
* Adds an array of items.
*
* @param items the data array
- * @param key a factory of stable and unique keys representing the item. Using the same key
- * for multiple items in the list is not allowed. Type of the key should be saveable
- * via Bundle on Android. If null is passed the position in the list will represent the key.
- * When you specify the key the scroll position will be maintained based on the key, which
- * means if you add/remove items before the current visible item the item with the given key
- * will be kept as the first visible one.
+ * @param key a factory of stable and unique keys representing the item. Using the same key for
+ * multiple items in the list is not allowed. Type of the key should be saveable via Bundle on
+ * Android. If null is passed the position in the list will represent the key. When you specify
+ * the key the scroll position will be maintained based on the key, which means if you add/remove
+ * items before the current visible item the item with the given key will be kept as the first
+ * visible one.
* @param itemContent the content displayed by a single item
*/
inline fun <T> ScalingLazyListScope.items(
items: Array<T>,
noinline key: ((item: T) -> Any)? = null,
crossinline itemContent: @Composable ScalingLazyListItemScope.(item: T) -> Unit
-) = items(items.size, if (key != null) { index: Int -> key(items[index]) } else null) {
- itemContent(items[it])
-}
+) =
+ items(items.size, if (key != null) { index: Int -> key(items[index]) } else null) {
+ itemContent(items[it])
+ }
/**
* Adds an array of items where the content of an item is aware of its index.
*
* @param items the data array
- * @param key a factory of stable and unique keys representing the item. Using the same key
- * for multiple items in the list is not allowed. Type of the key should be saveable
- * via Bundle on Android. If null is passed the position in the list will represent the key.
- * When you specify the key the scroll position will be maintained based on the key, which
- * means if you add/remove items before the current visible item the item with the given key
- * will be kept as the first visible one.
+ * @param key a factory of stable and unique keys representing the item. Using the same key for
+ * multiple items in the list is not allowed. Type of the key should be saveable via Bundle on
+ * Android. If null is passed the position in the list will represent the key. When you specify
+ * the key the scroll position will be maintained based on the key, which means if you add/remove
+ * items before the current visible item the item with the given key will be kept as the first
+ * visible one.
* @param itemContent the content displayed by a single item
*/
public inline fun <T> ScalingLazyListScope.itemsIndexed(
items: Array<T>,
noinline key: ((index: Int, item: T) -> Any)? = null,
crossinline itemContent: @Composable ScalingLazyListItemScope.(index: Int, item: T) -> Unit
-) = items(items.size, if (key != null) { index: Int -> key(index, items[index]) } else null) {
- itemContent(it, items[it])
-}
+) =
+ items(items.size, if (key != null) { index: Int -> key(index, items[index]) } else null) {
+ itemContent(it, items[it])
+ }
@Immutable
@kotlin.jvm.JvmInline
public value class ScalingLazyListAnchorType internal constructor(internal val type: Int) {
companion object {
- /**
- * Place the center of the item on (or as close to) the center line of the viewport
- */
+ /** Place the center of the item on (or as close to) the center line of the viewport */
val ItemCenter = ScalingLazyListAnchorType(0)
/**
@@ -212,20 +212,19 @@
/**
* Parameters to determine which list item and offset to calculate auto-centering spacing for. The
* default values are [itemIndex] = 1 and [itemOffset] = 0. This will provide sufficient padding for
- * the second item (index = 1) in the list being centerable. This is to match the Wear UX
- * guidelines that a typical list will have a ListHeader item as the first item in the list
- * (index = 0) and that this should not be scrollable into the middle of the viewport, instead the
- * first list item that a user can interact with (index = 1) would be the first that would be in the
- * center.
+ * the second item (index = 1) in the list being centerable. This is to match the Wear UX guidelines
+ * that a typical list will have a ListHeader item as the first item in the list (index = 0) and
+ * that this should not be scrollable into the middle of the viewport, instead the first list item
+ * that a user can interact with (index = 1) would be the first that would be in the center.
*
* If your use case is different and you want all list items to be able to be scrolled to the
* viewport middle, including the first item in the list then set [itemIndex] = 0.
*
- * The higher the value for [itemIndex] you provide the less auto centering padding will be
- * provided as the amount of padding needed to allow that item to be centered will reduce.
- * Even for a list of short items setting [itemIndex] above 3 or 4 is likely
- * to result in no auto-centering padding being provided as items with index 3 or 4 will probably
- * already be naturally scrollable to the center of the viewport.
+ * The higher the value for [itemIndex] you provide the less auto centering padding will be provided
+ * as the amount of padding needed to allow that item to be centered will reduce. Even for a list of
+ * short items setting [itemIndex] above 3 or 4 is likely to result in no auto-centering padding
+ * being provided as items with index 3 or 4 will probably already be naturally scrollable to the
+ * center of the viewport.
*
* [itemOffset] allows adjustment of the items position relative the [ScalingLazyColumn]s
* [ScalingLazyListAnchorType]. This can be useful if you need fine grained control over item
@@ -239,17 +238,17 @@
* center.
*
* @param itemIndex Which list item index to enable auto-centering from. Space (padding) will be
- * added such that items with index [itemIndex] or greater will be able to be scrolled to the center
- * of the viewport. If the developer wants to add additional space to allow other list items to also
- * be scrollable to the center they can use contentPadding on the ScalingLazyColumn. If the
- * developer wants custom control over position and spacing they can switch off autoCentering
- * and provide contentPadding.
- *
- * @param itemOffset What offset, if any, to apply when calculating space for auto-centering
- * the [itemIndex] item. E.g. itemOffset can be used if the developer wants to align the viewport
- * center in the gap between two list items.
+ * added such that items with index [itemIndex] or greater will be able to be scrolled to the
+ * center of the viewport. If the developer wants to add additional space to allow other list
+ * items to also be scrollable to the center they can use contentPadding on the ScalingLazyColumn.
+ * If the developer wants custom control over position and spacing they can switch off
+ * autoCentering and provide contentPadding.
+ * @param itemOffset What offset, if any, to apply when calculating space for auto-centering the
+ * [itemIndex] item. E.g. itemOffset can be used if the developer wants to align the viewport
+ * center in the gap between two list items.
*
* For an example of a [ScalingLazyColumn] with an explicit itemOffset see:
+ *
* @sample androidx.wear.compose.foundation.samples.ScalingLazyColumnEdgeAnchoredAndAnimatedScrollTo
*/
@Immutable
@@ -276,62 +275,65 @@
* A scrolling scaling/fisheye list component that forms a key part of the Wear Material Design
* language. Provides scaling and transparency effects to the content items.
*
- * [ScalingLazyColumn] is designed to be able to handle potentially large numbers of content
- * items. Content items are only materialized and composed when needed.
+ * [ScalingLazyColumn] is designed to be able to handle potentially large numbers of content items.
+ * Content items are only materialized and composed when needed.
*
- * If scaling/fisheye functionality is not required then a [LazyColumn] should be considered
- * instead to avoid any overhead of measuring and calculating scaling and transparency effects for
- * the content items.
+ * If scaling/fisheye functionality is not required then a [LazyColumn] should be considered instead
+ * to avoid any overhead of measuring and calculating scaling and transparency effects for the
+ * content items.
*
- * This overload supports rotary input. Rotary input allows users to scroll the content
- * of the [ScalingLazyColumn] - by using a crown or a rotating bezel on their Wear OS device.
- * If you want to modify its behavior please use another ScalingLazyColumn overload
- * with rotaryBehavior parameter.
+ * This overload supports rotary input. Rotary input allows users to scroll the content of the
+ * [ScalingLazyColumn] - by using a crown or a rotating bezel on their Wear OS device. If you want
+ * to modify its behavior please use another ScalingLazyColumn overload with rotaryBehavior
+ * parameter.
*
* Example of a [ScalingLazyColumn] with default parameters:
+ *
* @sample androidx.wear.compose.foundation.samples.SimpleScalingLazyColumn
*
* Example of a [ScalingLazyColumn] using [ScalingLazyListAnchorType.ItemStart] anchoring, in this
* configuration the edge of list items is aligned to the center of the screen. Also this example
* shows scrolling to a clicked list item with [ScalingLazyListState.animateScrollToItem]:
+ *
* @sample androidx.wear.compose.foundation.samples.ScalingLazyColumnEdgeAnchoredAndAnimatedScrollTo
*
* Example of a [ScalingLazyColumn] with snap of items to the viewport center:
+ *
* @sample androidx.wear.compose.foundation.samples.SimpleScalingLazyColumnWithSnap
*
* Example of a [ScalingLazyColumn] where [autoCentering] has been disabled and explicit
* [contentPadding] provided to ensure there is space above the first and below the last list item
* to allow them to be scrolled into view on circular screens:
+ *
* @sample androidx.wear.compose.foundation.samples.SimpleScalingLazyColumnWithContentPadding
*
* For more information, see the
- * [Lists](https://developer.android.com/training/wearables/components/lists)
- * guide.
+ * [Lists](https://developer.android.com/training/wearables/components/lists) guide.
*
* @param modifier The modifier to be applied to the component
* @param state The state of the component
* @param contentPadding The padding to apply around the contents
* @param reverseLayout reverse the direction of scrolling and layout, when `true` items will be
- * composed from the bottom to the top
- * @param verticalArrangement The vertical arrangement of the layout's children. This allows us
- * to add spacing between items and specify the arrangement of the items when we have not enough
- * of them to fill the whole minimum size
+ * composed from the bottom to the top
+ * @param verticalArrangement The vertical arrangement of the layout's children. This allows us to
+ * add spacing between items and specify the arrangement of the items when we have not enough of
+ * them to fill the whole minimum size
* @param horizontalAlignment the horizontal alignment applied to the items
* @param flingBehavior Logic describing fling behavior. If snapping is required use
- * [ScalingLazyColumnDefaults.snapFlingBehavior].
- * @param userScrollEnabled whether the scrolling via the user gestures or accessibility actions
- * is allowed. You can still scroll programmatically using the state even when it is disabled.
+ * [ScalingLazyColumnDefaults.snapFlingBehavior].
+ * @param userScrollEnabled whether the scrolling via the user gestures or accessibility actions is
+ * allowed. You can still scroll programmatically using the state even when it is disabled.
* @param scalingParams The parameters to configure the scaling and transparency effects for the
- * component
+ * component
* @param anchorType How to anchor list items to the center-line of the viewport
* @param autoCentering AutoCenteringParams parameter to control whether space/padding should be
- * automatically added to make sure that list items can be scrolled into the center of the viewport
- * (based on their [anchorType]). If non-null then space will be added before the first list item,
- * if needed, to ensure that items with indexes greater than or equal to the itemIndex (offset by
- * itemOffset pixels) will be able to be scrolled to the center of the viewport. Similarly space
- * will be added at the end of the list to ensure that items can be scrolled up to the center. If
- * null no automatic space will be added and instead the developer can use [contentPadding] to
- * manually arrange the items.
+ * automatically added to make sure that list items can be scrolled into the center of the
+ * viewport (based on their [anchorType]). If non-null then space will be added before the first
+ * list item, if needed, to ensure that items with indexes greater than or equal to the itemIndex
+ * (offset by itemOffset pixels) will be able to be scrolled to the center of the viewport.
+ * Similarly space will be added at the end of the list to ensure that items can be scrolled up to
+ * the center. If null no automatic space will be added and instead the developer can use
+ * [contentPadding] to manually arrange the items.
* @param content The content of the [ScalingLazyColumn]
*/
@Deprecated(
@@ -378,87 +380,88 @@
* A scrolling scaling/fisheye list component that forms a key part of the Wear Material Design
* language. Provides scaling and transparency effects to the content items.
*
- * [ScalingLazyColumn] is designed to be able to handle potentially large numbers of content
- * items. Content items are only materialized and composed when needed.
+ * [ScalingLazyColumn] is designed to be able to handle potentially large numbers of content items.
+ * Content items are only materialized and composed when needed.
*
- * If scaling/fisheye functionality is not required then a [LazyColumn] should be considered
- * instead to avoid any overhead of measuring and calculating scaling and transparency effects for
- * the content items.
+ * If scaling/fisheye functionality is not required then a [LazyColumn] should be considered instead
+ * to avoid any overhead of measuring and calculating scaling and transparency effects for the
+ * content items.
*
- * This overload supports rotary input. Rotary input allows users to scroll the content
- * of the [ScalingLazyColumn] - by using a crown or a rotating bezel on their Wear OS device.
- * It can be modified with [rotaryScrollableBehavior] param. If scroll with fling is required
- * use [RotaryScrollableDefaults.behavior]. If snapping is required use
+ * This overload supports rotary input. Rotary input allows users to scroll the content of the
+ * [ScalingLazyColumn] - by using a crown or a rotating bezel on their Wear OS device. It can be
+ * modified with [rotaryScrollableBehavior] param. If scroll with fling is required use
+ * [RotaryScrollableDefaults.behavior]. If snapping is required use
* [RotaryScrollableDefaults.snapBehavior]. Note that rotary scroll and touch scroll should be
* aligned. If [rotaryScrollableBehavior] is set for snap (using
- * [RotaryScrollableDefaults.snapBehavior]), [flingBehavior] should be set for snap as well
- * (using [ScalingLazyColumnDefaults.snapFlingBehavior]).
- * This composable uses [rememberActiveFocusRequester] as FocusRequester for rotary support.
- * It requires that this [ScalingLazyColumn] should be wrapped by [HierarchicalFocusCoordinator].
- * By default [HierarchicalFocusCoordinator] is already implemented in [BasicSwipeToDismissBox],
- * which is a part of material Scaffold - meaning that rotary will be able to request a focus
- * without any additional changes.
- * Another FocusRequester can be added through Modifier chain by adding
+ * [RotaryScrollableDefaults.snapBehavior]), [flingBehavior] should be set for snap as well (using
+ * [ScalingLazyColumnDefaults.snapFlingBehavior]). This composable uses
+ * [rememberActiveFocusRequester] as FocusRequester for rotary support. It requires that this
+ * [ScalingLazyColumn] should be wrapped by [HierarchicalFocusCoordinator]. By default
+ * [HierarchicalFocusCoordinator] is already implemented in [BasicSwipeToDismissBox], which is a
+ * part of material Scaffold - meaning that rotary will be able to request a focus without any
+ * additional changes. Another FocusRequester can be added through Modifier chain by adding
* `.focusRequester(focusRequester)`. Do not call `focusable()` or `focusTarget()` after it as this
* will reset the focusRequester chain and rotary support will not be available.
*
* Example of a [ScalingLazyColumn] with default parameters:
+ *
* @sample androidx.wear.compose.foundation.samples.SimpleScalingLazyColumn
*
* Example of a [ScalingLazyColumn] using [ScalingLazyListAnchorType.ItemStart] anchoring, in this
* configuration the edge of list items is aligned to the center of the screen. Also this example
* shows scrolling to a clicked list item with [ScalingLazyListState.animateScrollToItem]:
+ *
* @sample androidx.wear.compose.foundation.samples.ScalingLazyColumnEdgeAnchoredAndAnimatedScrollTo
*
* Example of a [ScalingLazyColumn] with snap of items to the viewport center:
+ *
* @sample androidx.wear.compose.foundation.samples.SimpleScalingLazyColumnWithSnap
*
* Example of a [ScalingLazyColumn] where [autoCentering] has been disabled and explicit
* [contentPadding] provided to ensure there is space above the first and below the last list item
* to allow them to be scrolled into view on circular screens:
+ *
* @sample androidx.wear.compose.foundation.samples.SimpleScalingLazyColumnWithContentPadding
*
* For more information, see the
- * [Lists](https://developer.android.com/training/wearables/components/lists)
- * guide.
+ * [Lists](https://developer.android.com/training/wearables/components/lists) guide.
*
* @param modifier The modifier to be applied to the component
* @param state The state of the component
* @param contentPadding The padding to apply around the contents
* @param reverseLayout reverse the direction of scrolling and layout, when `true` items will be
- * composed from the bottom to the top
- * @param verticalArrangement The vertical arrangement of the layout's children. This allows us
- * to add spacing between items and specify the arrangement of the items when we have not enough
- * of them to fill the whole minimum size
+ * composed from the bottom to the top
+ * @param verticalArrangement The vertical arrangement of the layout's children. This allows us to
+ * add spacing between items and specify the arrangement of the items when we have not enough of
+ * them to fill the whole minimum size
* @param horizontalAlignment the horizontal alignment applied to the items
* @param flingBehavior Logic describing fling behavior for touch scroll. If snapping is required
- * use [ScalingLazyColumnDefaults.snapFlingBehavior]. Note that when configuring fling or snap
- * behavior, this flingBehavior parameter and the [rotaryScrollableBehavior] parameter that controls
- * rotary scroll are expected to produce similar list scrolling. For example,
- * if [rotaryScrollableBehavior] is set for snap (using [RotaryScrollableDefaults.snapBehavior]),
- * [flingBehavior] should be set for snap as well (using
- * [ScalingLazyColumnDefaults.snapFlingBehavior])
- * @param userScrollEnabled whether the scrolling via the user gestures or accessibility actions
- * is allowed. You can still scroll programmatically using the state even when it is disabled.
+ * use [ScalingLazyColumnDefaults.snapFlingBehavior]. Note that when configuring fling or snap
+ * behavior, this flingBehavior parameter and the [rotaryScrollableBehavior] parameter that
+ * controls rotary scroll are expected to produce similar list scrolling. For example, if
+ * [rotaryScrollableBehavior] is set for snap (using [RotaryScrollableDefaults.snapBehavior]),
+ * [flingBehavior] should be set for snap as well (using
+ * [ScalingLazyColumnDefaults.snapFlingBehavior])
+ * @param userScrollEnabled whether the scrolling via the user gestures or accessibility actions is
+ * allowed. You can still scroll programmatically using the state even when it is disabled.
* @param scalingParams The parameters to configure the scaling and transparency effects for the
- * component
+ * component
* @param anchorType How to anchor list items to the center-line of the viewport
* @param autoCentering AutoCenteringParams parameter to control whether space/padding should be
- * automatically added to make sure that list items can be scrolled into the center of the viewport
- * (based on their [anchorType]). If non-null then space will be added before the first list item,
- * if needed, to ensure that items with indexes greater than or equal to the itemIndex (offset by
- * itemOffset pixels) will be able to be scrolled to the center of the viewport. Similarly space
- * will be added at the end of the list to ensure that items can be scrolled up to the center. If
- * null no automatic space will be added and instead the developer can use [contentPadding] to
- * manually arrange the items.
- * @param rotaryScrollableBehavior Parameter for changing rotary scrollable behavior.
- * Supports scroll [RotaryScrollableDefaults.behavior] and
- * snap [RotaryScrollableDefaults.snapBehavior]. Note that when configuring fling or snap behavior,
- * this rotaryBehavior parameter and the [flingBehavior] parameter that controls touch scroll are
- * expected to produce similar list scrolling. For example, if [rotaryScrollableBehavior] is set
- * for snap (using [RotaryScrollableDefaults.snapBehavior]), [flingBehavior] should be set for
- * snap as well (using [ScalingLazyColumnDefaults.snapFlingBehavior]). Can be null if rotary
- * support is not required.
+ * automatically added to make sure that list items can be scrolled into the center of the
+ * viewport (based on their [anchorType]). If non-null then space will be added before the first
+ * list item, if needed, to ensure that items with indexes greater than or equal to the itemIndex
+ * (offset by itemOffset pixels) will be able to be scrolled to the center of the viewport.
+ * Similarly space will be added at the end of the list to ensure that items can be scrolled up to
+ * the center. If null no automatic space will be added and instead the developer can use
+ * [contentPadding] to manually arrange the items.
+ * @param rotaryScrollableBehavior Parameter for changing rotary scrollable behavior. Supports
+ * scroll [RotaryScrollableDefaults.behavior] and snap [RotaryScrollableDefaults.snapBehavior].
+ * Note that when configuring fling or snap behavior, this rotaryBehavior parameter and the
+ * [flingBehavior] parameter that controls touch scroll are expected to produce similar list
+ * scrolling. For example, if [rotaryScrollableBehavior] is set for snap (using
+ * [RotaryScrollableDefaults.snapBehavior]), [flingBehavior] should be set for snap as well (using
+ * [ScalingLazyColumnDefaults.snapFlingBehavior]). Can be null if rotary support is not required.
* @param content The content of the [ScalingLazyColumn]
*/
@OptIn(ExperimentalWearFoundationApi::class)
@@ -479,19 +482,19 @@
scalingParams: ScalingParams = ScalingLazyColumnDefaults.scalingParams(),
anchorType: ScalingLazyListAnchorType = ScalingLazyListAnchorType.ItemCenter,
autoCentering: AutoCenteringParams? = AutoCenteringParams(),
- rotaryScrollableBehavior: RotaryScrollableBehavior? =
- RotaryScrollableDefaults.behavior(state),
+ rotaryScrollableBehavior: RotaryScrollableBehavior? = RotaryScrollableDefaults.behavior(state),
content: ScalingLazyListScope.() -> Unit
) {
var initialized by remember { mutableStateOf(false) }
BoxWithConstraints(
- modifier = if (rotaryScrollableBehavior != null) modifier
- .rotaryScrollable(
- behavior = rotaryScrollableBehavior,
- focusRequester = rememberActiveFocusRequester(),
- reverseDirection = reverseLayout
- )
- else modifier,
+ modifier =
+ if (rotaryScrollableBehavior != null)
+ modifier.rotaryScrollable(
+ behavior = rotaryScrollableBehavior,
+ focusRequester = rememberActiveFocusRequester(),
+ reverseDirection = reverseLayout
+ )
+ else modifier,
propagateMinConstraints = true
) {
val density = LocalDensity.current
@@ -504,10 +507,8 @@
with(density) {
val extraPadding = extraPaddingInPixels.toDp()
- val combinedPaddingValues = CombinedPaddingValues(
- contentPadding = contentPadding,
- extraPadding = extraPadding
- )
+ val combinedPaddingValues =
+ CombinedPaddingValues(contentPadding = contentPadding, extraPadding = extraPadding)
val beforeContentPaddingInPx =
if (reverseLayout) contentPadding.calculateBottomPadding().roundToPx()
@@ -520,45 +521,49 @@
val itemScope =
ScalingLazyListItemScopeImpl(
density = density,
- constraints = constraints.offset(
- horizontal = -(
- contentPadding.calculateStartPadding(layoutDirection) +
- contentPadding.calculateEndPadding(layoutDirection)
- ).toPx().toInt(),
- vertical = -(
- contentPadding.calculateTopPadding() +
- contentPadding.calculateBottomPadding()
- ).roundToPx()
- )
+ constraints =
+ constraints.offset(
+ horizontal =
+ -(contentPadding.calculateStartPadding(layoutDirection) +
+ contentPadding.calculateEndPadding(layoutDirection))
+ .toPx()
+ .toInt(),
+ vertical =
+ -(contentPadding.calculateTopPadding() +
+ contentPadding.calculateBottomPadding())
+ .roundToPx()
+ )
)
// Set up transient state
- state.config.value = ScalingLazyListState.Configuration(
- scalingParams = actualScalingParams,
- extraPaddingPx = extraPaddingInPixels,
- beforeContentPaddingPx = beforeContentPaddingInPx,
- afterContentPaddingPx = afterContentPaddingInPx,
- viewportHeightPx = constraints.maxHeight,
- gapBetweenItemsPx = verticalArrangement.spacing.roundToPx(),
- anchorType = anchorType,
- autoCentering = autoCentering,
- reverseLayout = reverseLayout,
- localInspectionMode = LocalInspectionMode.current
- )
+ state.config.value =
+ ScalingLazyListState.Configuration(
+ scalingParams = actualScalingParams,
+ extraPaddingPx = extraPaddingInPixels,
+ beforeContentPaddingPx = beforeContentPaddingInPx,
+ afterContentPaddingPx = afterContentPaddingInPx,
+ viewportHeightPx = constraints.maxHeight,
+ gapBetweenItemsPx = verticalArrangement.spacing.roundToPx(),
+ anchorType = anchorType,
+ autoCentering = autoCentering,
+ reverseLayout = reverseLayout,
+ localInspectionMode = LocalInspectionMode.current
+ )
LazyColumn(
- modifier = Modifier
- .clipToBounds()
- .verticalNegativePadding(extraPadding)
- .onGloballyPositioned {
- val layoutInfo = state.layoutInfo
- if (!initialized &&
- layoutInfo is DefaultScalingLazyListLayoutInfo &&
- layoutInfo.readyForInitialScroll
- ) {
- initialized = true
- }
- },
+ modifier =
+ Modifier.clipToBounds()
+ .verticalNegativePadding(extraPadding)
+ .onGloballyPositioned {
+ val layoutInfo = state.layoutInfo
+ if (
+ !initialized &&
+ layoutInfo is DefaultScalingLazyListLayoutInfo &&
+ layoutInfo.readyForInitialScroll
+ ) {
+ initialized = true
+ }
+ },
horizontalAlignment = horizontalAlignment,
contentPadding = combinedPaddingValues,
reverseLayout = reverseLayout,
@@ -567,45 +572,44 @@
flingBehavior = flingBehavior,
userScrollEnabled = userScrollEnabled,
) {
- val scope = ScalingLazyListScopeImpl(
- state = state,
- scope = this,
- itemScope = itemScope
- )
+ val scope =
+ ScalingLazyListScopeImpl(state = state, scope = this, itemScope = itemScope)
// Only add spacers if autoCentering == true as we have to consider the impact of
// vertical spacing between items.
if (autoCentering != null) {
item {
- Spacer(modifier = remember(state) {
- Modifier.autoCenteringHeight {
- state.topAutoCenteringItemSizePx
- }
- })
+ Spacer(
+ modifier =
+ remember(state) {
+ Modifier.autoCenteringHeight {
+ state.topAutoCenteringItemSizePx
+ }
+ }
+ )
}
}
scope.content()
if (autoCentering != null) {
item {
- Spacer(modifier = remember(state) {
- Modifier.autoCenteringHeight {
- state.bottomAutoCenteringItemSizePx
- }
- })
+ Spacer(
+ modifier =
+ remember(state) {
+ Modifier.autoCenteringHeight {
+ state.bottomAutoCenteringItemSizePx
+ }
+ }
+ )
}
}
}
if (initialized) {
- LaunchedEffect(state) {
- state.scrollToInitialItem()
- }
+ LaunchedEffect(state) { state.scrollToInitialItem() }
}
}
}
}
-/**
- * Contains the default values used by [ScalingLazyColumn]
- */
+/** Contains the default values used by [ScalingLazyColumn] */
public object ScalingLazyColumnDefaults {
/**
* Creates a [ScalingParams] that represents the scaling and alpha properties for a
@@ -625,8 +629,8 @@
* the potential for larger list items to start their transition earlier (closer to the center)
* than smaller items.
*
- * [minTransitionArea] and [maxTransitionArea] are both in the range [0f..1f] and are
- * the fraction of the distance between the edges of the viewport. E.g. a value of 0.2f for
+ * [minTransitionArea] and [maxTransitionArea] are both in the range [0f..1f] and are the
+ * fraction of the distance between the edges of the viewport. E.g. a value of 0.2f for
* minTransitionArea and 0.75f for maxTransitionArea determines that all transition lines will
* fall between 1/5th (20%) and 3/4s (75%) of the height of the viewport.
*
@@ -644,69 +648,59 @@
*
* If an item is smaller than or equal to minElementSize its transition line with be at
* minTransitionArea and if it is larger than or equal to maxElementSize its transition line
- * will be at maxTransitionArea.
+ * will be at maxTransitionArea.
*
- * For example, if we take the default values for minTransitionArea = 0.2f and
- * maxTransitionArea = 0.6f and minElementSize = 0.2f and maxElementSize= 0.8f then an item
- * with a height of 0.4f (40%) of the viewport height is one third of way between
- * minElementSize and maxElementSize, (0.4f - 0.2f) / (0.8f - 0.2f) = 0.33f. So its transition
- * line would be one third of way between 0.2f and 0.6f, transition line = 0.2f + (0.6f -
- * 0.2f) * 0.33f = 0.33f.
+ * For example, if we take the default values for minTransitionArea = 0.2f and maxTransitionArea
+ * = 0.6f and minElementSize = 0.2f and maxElementSize= 0.8f then an item with a height of 0.4f
+ * (40%) of the viewport height is one third of way between minElementSize and maxElementSize,
+ * (0.4f - 0.2f) / (0.8f - 0.2f) = 0.33f. So its transition line would be one third of way
+ * between 0.2f and 0.6f, transition line = 0.2f + (0.6f - 0.2f) * 0.33f = 0.33f.
*
- * Once the position of the transition line is established we now have a transition area
- * for the item, e.g. in the example above the item will start/finish its transitions when it
- * is 0.33f (33%) of the distance from the edge of the viewport and will start/finish its
- * transitions at the viewport edge.
+ * Once the position of the transition line is established we now have a transition area for the
+ * item, e.g. in the example above the item will start/finish its transitions when it is 0.33f
+ * (33%) of the distance from the edge of the viewport and will start/finish its transitions at
+ * the viewport edge.
*
- * The scaleInterpolator is used to determine how much of the scaling and alpha to apply
- * as the item transits through the transition area.
+ * The scaleInterpolator is used to determine how much of the scaling and alpha to apply as the
+ * item transits through the transition area.
*
- * The edge of the item furthest from the edge of the screen is used as a scaling trigger
- * point for each item.
+ * The edge of the item furthest from the edge of the screen is used as a scaling trigger point
+ * for each item.
*
- * @param edgeScale What fraction of the full size of the item to scale it by when most
- * scaled, e.g. at the edge of the viewport. A value between [0f,1f], so a value of 0.2f
- * means to scale an item to 20% of its normal size.
- *
- * @param edgeAlpha What fraction of the full transparency of the item to draw it with
- * when closest to the edge of the screen. A value between [0f,1f], so a value of
- * 0.2f means to set the alpha of an item to 20% of its normal value.
- *
- * @param minElementHeight The minimum element height as a ratio of the viewport size to use
- * for determining the transition point within ([minTransitionArea], [maxTransitionArea])
- * that a given content item will start to be transitioned. Items smaller than
- * [minElementHeight] will be treated as if [minElementHeight]. Must be less than or equal to
- * [maxElementHeight].
- *
- * @param maxElementHeight The maximum element height as a ratio of the viewport size to use
- * for determining the transition point within ([minTransitionArea], [maxTransitionArea])
- * that a given content item will start to be transitioned. Items larger than [maxElementHeight]
- * will be treated as if [maxElementHeight]. Must be greater than or equal to
- * [minElementHeight].
- *
- * @param minTransitionArea The lower bound of the transition line area, closest to the
- * edge of the viewport. Defined as a fraction (value between 0f..1f) of the distance between
- * the viewport edges. Must be less than or equal to [maxTransitionArea].
- *
- * @param maxTransitionArea The upper bound of the transition line area, closest to the
- * center of the viewport. The fraction (value between 0f..1f) of the distance
- * between the viewport edges. Must be greater than or equal to [minTransitionArea].
- *
- * @param scaleInterpolator An interpolator to use to determine how to apply scaling as a
- * item transitions across the scaling transition area.
- *
+ * @param edgeScale What fraction of the full size of the item to scale it by when most scaled,
+ * e.g. at the edge of the viewport. A value between [0f,1f], so a value of 0.2f means to
+ * scale an item to 20% of its normal size.
+ * @param edgeAlpha What fraction of the full transparency of the item to draw it with when
+ * closest to the edge of the screen. A value between [0f,1f], so a value of 0.2f means to set
+ * the alpha of an item to 20% of its normal value.
+ * @param minElementHeight The minimum element height as a ratio of the viewport size to use for
+ * determining the transition point within ([minTransitionArea], [maxTransitionArea]) that a
+ * given content item will start to be transitioned. Items smaller than [minElementHeight]
+ * will be treated as if [minElementHeight]. Must be less than or equal to [maxElementHeight].
+ * @param maxElementHeight The maximum element height as a ratio of the viewport size to use for
+ * determining the transition point within ([minTransitionArea], [maxTransitionArea]) that a
+ * given content item will start to be transitioned. Items larger than [maxElementHeight] will
+ * be treated as if [maxElementHeight]. Must be greater than or equal to [minElementHeight].
+ * @param minTransitionArea The lower bound of the transition line area, closest to the edge of
+ * the viewport. Defined as a fraction (value between 0f..1f) of the distance between the
+ * viewport edges. Must be less than or equal to [maxTransitionArea].
+ * @param maxTransitionArea The upper bound of the transition line area, closest to the center
+ * of the viewport. The fraction (value between 0f..1f) of the distance between the viewport
+ * edges. Must be greater than or equal to [minTransitionArea].
+ * @param scaleInterpolator An interpolator to use to determine how to apply scaling as a item
+ * transitions across the scaling transition area.
* @param viewportVerticalOffsetResolver The additional padding to consider above and below the
- * viewport of a [ScalingLazyColumn] when considering which items to draw in the viewport. If
- * set to 0 then no additional padding will be provided and only the items which would appear
- * in the viewport before any scaling is applied will be considered for drawing, this may
- * leave blank space at the top and bottom of the viewport where the next available item
- * could have been drawn once other items have been scaled down in size. The larger this
- * value is set to will allow for more content items to be considered for drawing in the
- * viewport, however there is a performance cost associated with materializing items that are
- * subsequently not drawn. The higher/more extreme the scaling parameters that are applied to
- * the [ScalingLazyColumn] the more padding may be needed to ensure there are always enough
- * content items available to be rendered. By default will be 5% of the maxHeight of the
- * viewport above and below the content.
+ * viewport of a [ScalingLazyColumn] when considering which items to draw in the viewport. If
+ * set to 0 then no additional padding will be provided and only the items which would appear
+ * in the viewport before any scaling is applied will be considered for drawing, this may
+ * leave blank space at the top and bottom of the viewport where the next available item could
+ * have been drawn once other items have been scaled down in size. The larger this value is
+ * set to will allow for more content items to be considered for drawing in the viewport,
+ * however there is a performance cost associated with materializing items that are
+ * subsequently not drawn. The higher/more extreme the scaling parameters that are applied to
+ * the [ScalingLazyColumn] the more padding may be needed to ensure there are always enough
+ * content items available to be rendered. By default will be 5% of the maxHeight of the
+ * viewport above and below the content.
*/
fun scalingParams(
edgeScale: Float = 0.7f,
@@ -717,16 +711,17 @@
maxTransitionArea: Float = 0.55f,
scaleInterpolator: Easing = CubicBezierEasing(0.3f, 0f, 0.7f, 1f),
viewportVerticalOffsetResolver: (Constraints) -> Int = { (it.maxHeight / 20f).toInt() }
- ): ScalingParams = DefaultScalingParams(
- edgeScale = edgeScale,
- edgeAlpha = edgeAlpha,
- minElementHeight = minElementHeight,
- maxElementHeight = maxElementHeight,
- minTransitionArea = minTransitionArea,
- maxTransitionArea = maxTransitionArea,
- scaleInterpolator = scaleInterpolator,
- viewportVerticalOffsetResolver = viewportVerticalOffsetResolver
- )
+ ): ScalingParams =
+ DefaultScalingParams(
+ edgeScale = edgeScale,
+ edgeAlpha = edgeAlpha,
+ minElementHeight = minElementHeight,
+ maxElementHeight = maxElementHeight,
+ minTransitionArea = minTransitionArea,
+ maxTransitionArea = maxTransitionArea,
+ scaleInterpolator = scaleInterpolator,
+ viewportVerticalOffsetResolver = viewportVerticalOffsetResolver
+ )
/**
* Create and remember a [FlingBehavior] that will represent natural fling curve with snap to
@@ -734,7 +729,7 @@
*
* @param state the state of the [ScalingLazyColumn]
* @param snapOffset an optional offset to be applied when snapping the item. After the snap the
- * snapped items offset will be [snapOffset].
+ * snapped items offset will be [snapOffset].
* @param decay the decay to use
*/
@Composable
@@ -765,12 +760,7 @@
override fun item(key: Any?, content: @Composable (ScalingLazyListItemScope.() -> Unit)) {
val startIndex = currentStartIndex
scope.item(key = key) {
- ScalingLazyColumnItemWrapper(
- startIndex,
- state,
- itemScope,
- content
- )
+ ScalingLazyColumnItemWrapper(startIndex, state, itemScope, content)
}
currentStartIndex++
}
@@ -782,11 +772,7 @@
) {
val startIndex = currentStartIndex
scope.items(count = count, key = key) {
- ScalingLazyColumnItemWrapper(
- startIndex + it,
- state = state,
- itemScope = itemScope
- ) {
+ ScalingLazyColumnItemWrapper(startIndex + it, state = state, itemScope = itemScope) {
itemContent(it)
}
}
@@ -802,32 +788,37 @@
content: @Composable (ScalingLazyListItemScope.() -> Unit)
) {
Box(
- modifier = Modifier.graphicsLayer {
- val config = state.config.value!!
- val reverseLayout = config.reverseLayout
- val anchorType = config.anchorType
- val items = state.layoutInfo.internalVisibleItemInfo()
- val currentItem = items.fastFirstOrNull { it.index == index }
- if (currentItem != null) {
- alpha = currentItem.alpha
- scaleX = currentItem.scale
- scaleY = currentItem.scale
- // Calculate how much to adjust/translate the position of the list item by
- // determining the different between the unadjusted start position based on the
- // underlying LazyList layout and the start position adjusted to take into account
- // scaling of the list items. Items further from the middle of the visible viewport
- // will be subject to more adjustment.
- if (currentItem.scale > 0f) {
- val offsetAdjust = currentItem.startOffset(anchorType) -
- currentItem.unadjustedStartOffset(anchorType)
- translationY = if (reverseLayout) -offsetAdjust else offsetAdjust
- transformOrigin = TransformOrigin(
- pivotFractionX = 0.5f,
- pivotFractionY = if (reverseLayout) 1.0f else 0.0f
- )
+ modifier =
+ Modifier.graphicsLayer {
+ val config = state.config.value!!
+ val reverseLayout = config.reverseLayout
+ val anchorType = config.anchorType
+ val items = state.layoutInfo.internalVisibleItemInfo()
+ val currentItem = items.fastFirstOrNull { it.index == index }
+ if (currentItem != null) {
+ alpha = currentItem.alpha
+ scaleX = currentItem.scale
+ scaleY = currentItem.scale
+ // Calculate how much to adjust/translate the position of the list item by
+ // determining the different between the unadjusted start position based on the
+ // underlying LazyList layout and the start position adjusted to take into
+ // account
+ // scaling of the list items. Items further from the middle of the visible
+ // viewport
+ // will be subject to more adjustment.
+ if (currentItem.scale > 0f) {
+ val offsetAdjust =
+ currentItem.startOffset(anchorType) -
+ currentItem.unadjustedStartOffset(anchorType)
+ translationY = if (reverseLayout) -offsetAdjust else offsetAdjust
+ transformOrigin =
+ TransformOrigin(
+ pivotFractionX = 0.5f,
+ pivotFractionY = if (reverseLayout) 1.0f else 0.0f
+ )
+ }
}
}
- }
) {
itemScope.content()
}
@@ -836,16 +827,13 @@
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
@Immutable
public class CombinedPaddingValues(
- @Stable
- val contentPadding: PaddingValues,
- @Stable
- val extraPadding: Dp
+ @Stable val contentPadding: PaddingValues,
+ @Stable val extraPadding: Dp
) : PaddingValues {
override fun calculateLeftPadding(layoutDirection: LayoutDirection): Dp =
contentPadding.calculateLeftPadding(layoutDirection)
- override fun calculateTopPadding(): Dp =
- contentPadding.calculateTopPadding() + extraPadding
+ override fun calculateTopPadding(): Dp = contentPadding.calculateTopPadding() + extraPadding
override fun calculateRightPadding(layoutDirection: LayoutDirection): Dp =
contentPadding.calculateRightPadding(layoutDirection)
@@ -884,26 +872,22 @@
) = layout { measurable, constraints ->
require(constraints.hasBoundedHeight) { "height should be bounded" }
val topAndBottomPadding = (extraPadding * 2).roundToPx()
- val placeable = measurable.measure(
- constraints.copy(
- minHeight = constraints.minHeight + topAndBottomPadding,
- maxHeight = constraints.maxHeight + topAndBottomPadding
+ val placeable =
+ measurable.measure(
+ constraints.copy(
+ minHeight = constraints.minHeight + topAndBottomPadding,
+ maxHeight = constraints.maxHeight + topAndBottomPadding
+ )
)
- )
layout(placeable.measuredWidth, constraints.maxHeight) {
placeable.place(0, -extraPadding.roundToPx())
}
}
-private fun Modifier.autoCenteringHeight(getHeight: () -> Int) =
- layout { measurable, constraints ->
- val height = getHeight()
- val placeable = measurable.measure(
- constraints.copy(minHeight = height, maxHeight = height)
- )
+private fun Modifier.autoCenteringHeight(getHeight: () -> Int) = layout { measurable, constraints ->
+ val height = getHeight()
+ val placeable = measurable.measure(constraints.copy(minHeight = height, maxHeight = height))
- layout(placeable.width, placeable.height) {
- placeable.place(IntOffset.Zero)
- }
- }
+ layout(placeable.width, placeable.height) { placeable.place(IntOffset.Zero) }
+}
diff --git a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/lazy/ScalingLazyColumnMeasure.kt b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/lazy/ScalingLazyColumnMeasure.kt
index 29de39c..15e5fd1 100644
--- a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/lazy/ScalingLazyColumnMeasure.kt
+++ b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/lazy/ScalingLazyColumnMeasure.kt
@@ -32,14 +32,14 @@
/**
* Parameters to control the scaling of the contents of a [ScalingLazyColumn].
*
- * Items in the ScalingLazyColumn have scaling and alpha effects applied to them depending on
- * their position in the viewport. The closer to the edge (top or bottom) of the viewport that
- * they are the greater the down scaling and transparency that is applied. Note that scaling and
- * transparency effects are applied from the center of the viewport (nearest to full size and normal
+ * Items in the ScalingLazyColumn have scaling and alpha effects applied to them depending on their
+ * position in the viewport. The closer to the edge (top or bottom) of the viewport that they are
+ * the greater the down scaling and transparency that is applied. Note that scaling and transparency
+ * effects are applied from the center of the viewport (nearest to full size and normal
* transparency) towards the edge (items can be smaller and more transparent).
*
- * Deciding how much scaling and alpha to apply is based on the position and size of the item
- * and on a series of properties that are used to determine the transition area for each item.
+ * Deciding how much scaling and alpha to apply is based on the position and size of the item and on
+ * a series of properties that are used to determine the transition area for each item.
*
* The transition area is defined by the edge of the screen and a transition line which is
* calculated for each item in the list. There are two symmetrical transition lines/areas one at the
@@ -55,82 +55,75 @@
* lines interact with the opposite edges of the list item top with bottom, bottom with top it is
* often desirable to have inverted transition lines for large list items.
*
- * [minTransitionArea] and [maxTransitionArea] are both in the range [0f..1f] and are
- * the fraction of the distance between the edges of the viewport. E.g. a value of 0.2f for
- * minTransitionArea and 0.75f for maxTransitionArea determines that all transition lines will fall
- * between 1/5th (20%) and 3/4s (75%) of the height of the viewport.
+ * [minTransitionArea] and [maxTransitionArea] are both in the range [0f..1f] and are the fraction
+ * of the distance between the edges of the viewport. E.g. a value of 0.2f for minTransitionArea and
+ * 0.75f for maxTransitionArea determines that all transition lines will fall between 1/5th (20%)
+ * and 3/4s (75%) of the height of the viewport.
*
* The size of the each item is used to determine where within the transition area range
- * minTransitionArea..maxTransitionArea the actual transition line will be. [minElementHeight]
- * and [maxElementHeight] are used along with the item height (as a fraction of the viewport
- * height in the range [0f..1f]) to find the transition line. So if the items size is 0.25f
- * (25%) of way between minElementSize..maxElementSize then the transition line will be 0.25f
- * (25%) of the way between minTransitionArea..maxTransitionArea.
+ * minTransitionArea..maxTransitionArea the actual transition line will be. [minElementHeight] and
+ * [maxElementHeight] are used along with the item height (as a fraction of the viewport height in
+ * the range [0f..1f]) to find the transition line. So if the items size is 0.25f (25%) of way
+ * between minElementSize..maxElementSize then the transition line will be 0.25f (25%) of the way
+ * between minTransitionArea..maxTransitionArea.
*
* A list item smaller than minElementHeight is rounded up to minElementHeight and larger than
- * maxElementHeight is rounded down to maxElementHeight. Whereabouts the items height sits
- * between minElementHeight..maxElementHeight is then used to determine where the transition
- * line sits between minTransitionArea..maxTransition area.
+ * maxElementHeight is rounded down to maxElementHeight. Whereabouts the items height sits between
+ * minElementHeight..maxElementHeight is then used to determine where the transition line sits
+ * between minTransitionArea..maxTransition area.
*
* If an item is smaller than or equal to minElementSize its transition line with be at
- * minTransitionArea and if it is larger than or equal to maxElementSize its transition line
- * will be at maxTransitionArea.
+ * minTransitionArea and if it is larger than or equal to maxElementSize its transition line will be
+ * at maxTransitionArea.
*
- * For example, if we take the default values for minTransitionArea = 0.2f and
- * maxTransitionArea = 0.6f and minElementSize = 0.2f and maxElementSize= 0.8f then an item
- * with a height of 0.4f (40%) of the viewport height is one third of way between
- * minElementSize and maxElementSize, (0.4f - 0.2f) / (0.8f - 0.2f) = 0.33f. So its transition
- * line would be one third of way between 0.2f and 0.6f, transition line = 0.2f + (0.6f -
- * 0.2f) * 0.33f = 0.33f.
+ * For example, if we take the default values for minTransitionArea = 0.2f and maxTransitionArea =
+ * 0.6f and minElementSize = 0.2f and maxElementSize= 0.8f then an item with a height of 0.4f (40%)
+ * of the viewport height is one third of way between minElementSize and maxElementSize, (0.4f -
+ * 0.2f) / (0.8f - 0.2f) = 0.33f. So its transition line would be one third of way between 0.2f and
+ * 0.6f, transition line = 0.2f + (0.6f - 0.2f) * 0.33f = 0.33f.
*
- * Once the position of the transition line is established we now have a transition area
- * for the item, e.g. in the example above the item will start/finish its transitions when it
- * is 0.33f (33%) of the distance from the edge of the viewport and will start/finish its
- * transitions at the viewport edge.
+ * Once the position of the transition line is established we now have a transition area for the
+ * item, e.g. in the example above the item will start/finish its transitions when it is 0.33f (33%)
+ * of the distance from the edge of the viewport and will start/finish its transitions at the
+ * viewport edge.
*
- * The scaleInterpolator is used to determine how much of the scaling and alpha to apply
- * as the item transits through the transition area.
+ * The scaleInterpolator is used to determine how much of the scaling and alpha to apply as the item
+ * transits through the transition area.
*
- * The edge of the item furthest from the edge of the screen is used as a scaling trigger
- * point for each item.
+ * The edge of the item furthest from the edge of the screen is used as a scaling trigger point for
+ * each item.
*/
@Stable
public interface ScalingParams {
/**
- * What fraction of the full size of the item to scale it by when most
- * scaled, e.g. at the edge of the viewport. A value between [0f,1f], so a value of 0.2f
- * means to scale an item to 20% of its normal size.
+ * What fraction of the full size of the item to scale it by when most scaled, e.g. at the edge
+ * of the viewport. A value between [0f,1f], so a value of 0.2f means to scale an item to 20% of
+ * its normal size.
*/
- @get:FloatRange(from = 0.0, to = 1.0)
- val edgeScale: Float
+ @get:FloatRange(from = 0.0, to = 1.0) val edgeScale: Float
/**
- * What fraction of the full transparency of the item to draw it with
- * when closest to the edge of the screen. A value between [0f,1f], so a value of
- * 0.2f means to set the alpha of an item to 20% of its normal value.
+ * What fraction of the full transparency of the item to draw it with when closest to the edge
+ * of the screen. A value between [0f,1f], so a value of 0.2f means to set the alpha of an item
+ * to 20% of its normal value.
*/
- @get:FloatRange(from = 0.0, to = 1.0)
- val edgeAlpha: Float
+ @get:FloatRange(from = 0.0, to = 1.0) val edgeAlpha: Float
/**
- * The maximum element height as a ratio of the viewport size to use
- * for determining the transition point within ([minTransitionArea], [maxTransitionArea])
- * that a given content item will start to be transitioned. Items larger than [maxElementHeight]
- * will be treated as if [maxElementHeight]. Must be greater than or equal to
- * [minElementHeight].
+ * The maximum element height as a ratio of the viewport size to use for determining the
+ * transition point within ([minTransitionArea], [maxTransitionArea]) that a given content item
+ * will start to be transitioned. Items larger than [maxElementHeight] will be treated as if
+ * [maxElementHeight]. Must be greater than or equal to [minElementHeight].
*/
- @get:FloatRange(from = 0.0, to = 1.0)
- val minElementHeight: Float
+ @get:FloatRange(from = 0.0, to = 1.0) val minElementHeight: Float
/**
- * The maximum element height as a ratio of the viewport size to use
- * for determining the transition point within ([minTransitionArea], [maxTransitionArea])
- * that a given content item will start to be transitioned. Items larger than [maxElementHeight]
- * will be treated as if [maxElementHeight]. Must be greater than or equal to
- * [minElementHeight].
+ * The maximum element height as a ratio of the viewport size to use for determining the
+ * transition point within ([minTransitionArea], [maxTransitionArea]) that a given content item
+ * will start to be transitioned. Items larger than [maxElementHeight] will be treated as if
+ * [maxElementHeight]. Must be greater than or equal to [minElementHeight].
*/
- @get:FloatRange(from = 0.0, to = 1.0)
- val maxElementHeight: Float
+ @get:FloatRange(from = 0.0, to = 1.0) val maxElementHeight: Float
/**
* The lower bound of the transition line area, closest to the edge of the viewport. Defined as
@@ -146,13 +139,12 @@
* list items exist. Depending on the size of the list item the specific point in the area is
* calculated.
*/
- @get:FloatRange(from = 0.0, to = 1.0)
- val minTransitionArea: Float
+ @get:FloatRange(from = 0.0, to = 1.0) val minTransitionArea: Float
/**
- * The upper bound of the transition line area, closest to the
- * center of the viewport. The fraction (value between 0f..1f) of the distance
- * between the viewport edges. Must be greater than or equal to [minTransitionArea].
+ * The upper bound of the transition line area, closest to the center of the viewport. The
+ * fraction (value between 0f..1f) of the distance between the viewport edges. Must be greater
+ * than or equal to [minTransitionArea].
*
* For transition lines a value of 0f means that the transition line is at the viewport edge,
* e.g. no transition, a value of 0.25f means that the transition line is 25% of the screen size
@@ -163,8 +155,7 @@
* list items exist. Depending on the size of the list item the specific point in the area is
* calculated.
*/
- @get:FloatRange(from = 0.0, to = 1.0)
- val maxTransitionArea: Float
+ @get:FloatRange(from = 0.0, to = 1.0) val maxTransitionArea: Float
/**
* An interpolator to use to determine how to apply scaling as a item transitions across the
@@ -173,18 +164,17 @@
val scaleInterpolator: Easing
/**
- * The additional padding to consider above and below the
- * viewport of a [ScalingLazyColumn] when considering which items to draw in the viewport. If
- * set to 0 then no additional padding will be provided and only the items which would appear
- * in the viewport before any scaling is applied will be considered for drawing, this may
- * leave blank space at the top and bottom of the viewport where the next available item
- * could have been drawn once other items have been scaled down in size. The larger this
- * value is set to will allow for more content items to be considered for drawing in the
- * viewport, however there is a performance cost associated with materializing items that are
- * subsequently not drawn. The higher/more extreme the scaling parameters that are applied to
- * the [ScalingLazyColumn] the more padding may be needed to ensure there are always enough
- * content items available to be rendered. By default will be 20% of the maxHeight of the
- * viewport above and below the content.
+ * The additional padding to consider above and below the viewport of a [ScalingLazyColumn] when
+ * considering which items to draw in the viewport. If set to 0 then no additional padding will
+ * be provided and only the items which would appear in the viewport before any scaling is
+ * applied will be considered for drawing, this may leave blank space at the top and bottom of
+ * the viewport where the next available item could have been drawn once other items have been
+ * scaled down in size. The larger this value is set to will allow for more content items to be
+ * considered for drawing in the viewport, however there is a performance cost associated with
+ * materializing items that are subsequently not drawn. The higher/more extreme the scaling
+ * parameters that are applied to the [ScalingLazyColumn] the more padding may be needed to
+ * ensure there are always enough content items available to be rendered. By default will be 20%
+ * of the maxHeight of the viewport above and below the content.
*
* @param viewportConstraints the viewports constraints
*/
@@ -204,12 +194,12 @@
) : ScalingParams {
init {
- check(
- minElementHeight <= maxElementHeight
- ) { "minElementHeight must be less than or equal to maxElementHeight" }
- check(
- minTransitionArea <= maxTransitionArea
- ) { "minTransitionArea must be less than or equal to maxTransitionArea" }
+ check(minElementHeight <= maxElementHeight) {
+ "minElementHeight must be less than or equal to maxElementHeight"
+ }
+ check(minTransitionArea <= maxTransitionArea) {
+ "minTransitionArea must be less than or equal to maxTransitionArea"
+ }
}
override fun resolveViewportVerticalOffset(viewportConstraints: Constraints): Int {
@@ -266,6 +256,7 @@
override val minTransitionArea: Float = initial.minTransitionArea
override val maxTransitionArea: Float = initial.maxTransitionArea
override val scaleInterpolator: Easing = initial.scaleInterpolator
+
override fun resolveViewportVerticalOffset(viewportConstraints: Constraints): Int {
return initial.resolveViewportVerticalOffset(viewportConstraints)
}
@@ -322,8 +313,8 @@
* @param viewPortEndPx The end position of the component's viewport in pixels
* @param itemTopPx The top of the content item in pixels.
* @param itemBottomPx The bottom of the content item in pixels.
- * @param scalingParams The parameters that determine where the item's scaling transition line
- * is, how scaling and transparency to apply.
+ * @param scalingParams The parameters that determine where the item's scaling transition line is,
+ * how scaling and transparency to apply.
*/
internal fun calculateScaleAndAlpha(
viewPortStartPx: Int,
@@ -346,16 +337,19 @@
// Work out the scaling line based on size, this is a value between 0.0..1.0
val sizeRatio =
- inverseLerp(scalingParams.minElementHeight, scalingParams.maxElementHeight,
- heightAsFractionOfViewPort)
+ inverseLerp(
+ scalingParams.minElementHeight,
+ scalingParams.maxElementHeight,
+ heightAsFractionOfViewPort
+ )
val scalingLineAsFractionOfViewPort =
lerp(scalingParams.minTransitionArea, scalingParams.maxTransitionArea, sizeRatio)
if (itemEdgeAsFractionOfViewPort < scalingLineAsFractionOfViewPort) {
// We are scaling
- val scalingProgressRaw = 1f - itemEdgeAsFractionOfViewPort /
- scalingLineAsFractionOfViewPort
+ val scalingProgressRaw =
+ 1f - itemEdgeAsFractionOfViewPort / scalingLineAsFractionOfViewPort
val scalingInterpolated = scalingParams.scaleInterpolator.transform(scalingProgressRaw)
scaleToApply = lerp(1.0f, scalingParams.edgeScale, scalingInterpolated)
@@ -368,22 +362,22 @@
/**
* Create a [ScalingLazyListItemInfo] given an unscaled start and end position for an item.
*
- * @param itemStart the x-axis position of a list item. The x-axis position takes into account
- * any adjustment to the original position based on the scaling of other list items.
- * @param item the original item info used to provide the pre-scaling position and size
- * information for the item.
- * @param verticalAdjustment the amount of vertical adjustment to apply to item positions to
- * allow for content padding in order to determine the adjusted position of the item within the
- * viewport in order to correctly calculate the scaling to apply.
+ * @param itemStart the x-axis position of a list item. The x-axis position takes into account any
+ * adjustment to the original position based on the scaling of other list items.
+ * @param item the original item info used to provide the pre-scaling position and size information
+ * for the item.
+ * @param verticalAdjustment the amount of vertical adjustment to apply to item positions to allow
+ * for content padding in order to determine the adjusted position of the item within the viewport
+ * in order to correctly calculate the scaling to apply.
* @param viewportHeightPx the height of the viewport in pixels
* @param viewportCenterLinePx the center line of the viewport in pixels
* @param scalingParams the scaling params to use for determining the scaled size of the item
* @param beforeContentPaddingPx the number of pixels of padding before the first item
* @param anchorType the type of pivot to use for the center item when calculating position and
- * offset
- * @param visible a flag to determine whether the list items should be visible or transparent.
- * Items are normally visible, but can be drawn transparently when the list is not yet initialized,
- * unless we are in preview (LocalInspectionModel) mode.
+ * offset
+ * @param visible a flag to determine whether the list items should be visible or transparent. Items
+ * are normally visible, but can be drawn transparently when the list is not yet initialized,
+ * unless we are in preview (LocalInspectionModel) mode.
*/
internal fun calculateItemInfo(
itemStart: Int,
@@ -400,33 +394,40 @@
val adjustedItemStart = itemStart - verticalAdjustment
val adjustedItemEnd = itemStart + item.size - verticalAdjustment
- val scaleAndAlpha = calculateScaleAndAlpha(
- viewPortStartPx = 0, viewPortEndPx = viewportHeightPx, itemTopPx = adjustedItemStart,
- itemBottomPx = adjustedItemEnd, scalingParams = scalingParams
- )
+ val scaleAndAlpha =
+ calculateScaleAndAlpha(
+ viewPortStartPx = 0,
+ viewPortEndPx = viewportHeightPx,
+ itemTopPx = adjustedItemStart,
+ itemBottomPx = adjustedItemEnd,
+ scalingParams = scalingParams
+ )
val isAboveLine = (adjustedItemEnd + adjustedItemStart) < viewportHeightPx
val scaledHeight = (item.size * scaleAndAlpha.scale).roundToInt()
- val scaledItemTop = if (!isAboveLine) {
- itemStart
- } else {
- itemStart + item.size - scaledHeight
- }
+ val scaledItemTop =
+ if (!isAboveLine) {
+ itemStart
+ } else {
+ itemStart + item.size - scaledHeight
+ }
- val offset = convertToCenterOffset(
- anchorType = anchorType,
- itemScrollOffset = scaledItemTop,
- viewportCenterLinePx = viewportCenterLinePx,
- beforeContentPaddingInPx = beforeContentPaddingPx,
- itemSizeInPx = scaledHeight
- )
- val unadjustedOffset = convertToCenterOffset(
- anchorType = anchorType,
- itemScrollOffset = item.offset,
- viewportCenterLinePx = viewportCenterLinePx,
- beforeContentPaddingInPx = beforeContentPaddingPx,
- itemSizeInPx = item.size
- )
+ val offset =
+ convertToCenterOffset(
+ anchorType = anchorType,
+ itemScrollOffset = scaledItemTop,
+ viewportCenterLinePx = viewportCenterLinePx,
+ beforeContentPaddingInPx = beforeContentPaddingPx,
+ itemSizeInPx = scaledHeight
+ )
+ val unadjustedOffset =
+ convertToCenterOffset(
+ anchorType = anchorType,
+ itemScrollOffset = item.offset,
+ viewportCenterLinePx = viewportCenterLinePx,
+ beforeContentPaddingInPx = beforeContentPaddingPx,
+ itemSizeInPx = item.size
+ )
return DefaultScalingLazyListItemInfo(
// Adjust index to take into account the Spacer before the first list item
index = if (autoCentering != null) item.index - 1 else item.index,
@@ -488,19 +489,16 @@
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
@Immutable
-public data class ScaleAndAlpha(
- val scale: Float,
- val alpha: Float
+public data class ScaleAndAlpha(val scale: Float, val alpha: Float) {
-) {
companion object {
internal val noScaling = ScaleAndAlpha(1.0f, 1.0f)
}
}
/**
- * Calculate the offset from the viewport center line of the Start|Center of an items unadjusted
- * or scaled size. The for items with an height that is an odd number and that have
+ * Calculate the offset from the viewport center line of the Start|Center of an items unadjusted or
+ * scaled size. The for items with an height that is an odd number and that have
* ScalingLazyListAnchorType.Center the offset will be rounded down. E.g. An item which is 19 pixels
* in height will have a center offset of 9 pixes.
*
@@ -517,7 +515,8 @@
beforeContentPaddingInPx: Int,
itemSizeInPx: Int
): Int {
- return itemScrollOffset - viewportCenterLinePx + beforeContentPaddingInPx +
+ return itemScrollOffset - viewportCenterLinePx +
+ beforeContentPaddingInPx +
if (anchorType == ScalingLazyListAnchorType.ItemStart) {
0
} else {
@@ -525,26 +524,26 @@
}
}
-/**
- * Find the start offset of the list item w.r.t. the
- */
+/** Find the start offset of the list item w.r.t. the */
internal fun ScalingLazyListItemInfo.startOffset(anchorType: ScalingLazyListAnchorType) =
- offset - if (anchorType == ScalingLazyListAnchorType.ItemCenter) {
- (size / 2f)
- } else {
- 0f
- }
+ offset -
+ if (anchorType == ScalingLazyListAnchorType.ItemCenter) {
+ (size / 2f)
+ } else {
+ 0f
+ }
/**
* Find the start position of the list item from its unadjusted offset w.r.t. the ScalingLazyColumn
* center of viewport offset = 0 coordinate model.
*/
internal fun ScalingLazyListItemInfo.unadjustedStartOffset(anchorType: ScalingLazyListAnchorType) =
- unadjustedOffset - if (anchorType == ScalingLazyListAnchorType.ItemCenter) {
- (unadjustedSize / 2f)
- } else {
- 0f
- }
+ unadjustedOffset -
+ if (anchorType == ScalingLazyListAnchorType.ItemCenter) {
+ (unadjustedSize / 2f)
+ } else {
+ 0f
+ }
/**
* Inverse linearly interpolate, return what fraction (0f..1f) that [value] is between [start] and
diff --git a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/lazy/ScalingLazyColumnSnapFlingBehavior.kt b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/lazy/ScalingLazyColumnSnapFlingBehavior.kt
index 3245cf7..2424763 100644
--- a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/lazy/ScalingLazyColumnSnapFlingBehavior.kt
+++ b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/lazy/ScalingLazyColumnSnapFlingBehavior.kt
@@ -40,51 +40,56 @@
) : FlingBehavior {
override suspend fun ScrollScope.performFling(initialVelocity: Float): Float {
- val animationState = AnimationState(
- initialValue = 0f,
- initialVelocity = initialVelocity,
- )
+ val animationState =
+ AnimationState(
+ initialValue = 0f,
+ initialVelocity = initialVelocity,
+ )
var lastValue = 0f
val visibleItemsInfo = state.layoutInfo.visibleItemsInfo
val isAFling = abs(initialVelocity) > 1f && visibleItemsInfo.size > 1
- val finalTarget = if (isAFling) {
- // Target we will land on given initialVelocity & decay
- val decayTarget = decay.calculateTargetValue(0f, initialVelocity)
- var endOfListReached = false
+ val finalTarget =
+ if (isAFling) {
+ // Target we will land on given initialVelocity & decay
+ val decayTarget = decay.calculateTargetValue(0f, initialVelocity)
+ var endOfListReached = false
- animationState.animateDecay(decay) {
- val delta = value - lastValue
- val consumed = scrollBy(delta)
- lastValue = value
+ animationState.animateDecay(decay) {
+ val delta = value - lastValue
+ val consumed = scrollBy(delta)
+ lastValue = value
- // When we are "slow" enough, switch from decay to the final snap.
- if (abs(velocity) < SNAP_SPEED_THRESHOLD) cancelAnimation()
+ // When we are "slow" enough, switch from decay to the final snap.
+ if (abs(velocity) < SNAP_SPEED_THRESHOLD) cancelAnimation()
- // If we can't consume the scroll, also stop.
- if (abs(delta - consumed) > 0.1f) {
- endOfListReached = true
- cancelAnimation()
+ // If we can't consume the scroll, also stop.
+ if (abs(delta - consumed) > 0.1f) {
+ endOfListReached = true
+ cancelAnimation()
+ }
}
- }
- if (endOfListReached) {
- // We couldn't scroll as much as we wanted, likely we reached the end of the list,
- // Snap to the current item and finish.
- scrollBy((snapOffset - state.centerItemScrollOffset).toFloat())
- return animationState.velocity
+ if (endOfListReached) {
+ // We couldn't scroll as much as we wanted, likely we reached the end of the
+ // list,
+ // Snap to the current item and finish.
+ scrollBy((snapOffset - state.centerItemScrollOffset).toFloat())
+ return animationState.velocity
+ } else {
+ // Now that scrolling slowed down, adjust the animation to land in the item
+ // closest
+ // to the original target. Note that the target may be off-screen, in that case
+ // we
+ // will land on the last visible item in that direction.
+ (state.layoutInfo.visibleItemsInfo
+ .fastMap { animationState.value + it.unadjustedOffset + snapOffset }
+ .fastMinByOrNull { abs(it - decayTarget) } ?: decayTarget)
+ }
} else {
- // Now that scrolling slowed down, adjust the animation to land in the item closest
- // to the original target. Note that the target may be off-screen, in that case we
- // will land on the last visible item in that direction.
- (state.layoutInfo.visibleItemsInfo
- .fastMap { animationState.value + it.unadjustedOffset + snapOffset }
- .fastMinByOrNull { abs(it - decayTarget) } ?: decayTarget)
+ // Not a fling, just snap to the current item.
+ (snapOffset - state.centerItemScrollOffset).toFloat()
}
- } else {
- // Not a fling, just snap to the current item.
- (snapOffset - state.centerItemScrollOffset).toFloat()
- }
// We have a velocity (animationState.velocity), and a target (finalTarget),
// Construct a cubic bezier with the given initial velocity, and ending at 0 speed,
@@ -101,10 +106,12 @@
val initialInertia = 0.5f
// Compute how much time we want to spend on the final snap, depending on the speed
- val finalSnapDuration = lerp(
- FINAL_SNAP_DURATION_MIN, FINAL_SNAP_DURATION_MAX,
- abs(initialSpeed) / SNAP_SPEED_THRESHOLD
- )
+ val finalSnapDuration =
+ lerp(
+ FINAL_SNAP_DURATION_MIN,
+ FINAL_SNAP_DURATION_MAX,
+ abs(initialSpeed) / SNAP_SPEED_THRESHOLD
+ )
// Initial control point. Has slope (velocity) adjustedSpeed and magnitude (inertia)
// initialInertia
@@ -112,13 +119,15 @@
val easingX0 = initialInertia / sqrt(1f + adjustedSpeed * adjustedSpeed)
val easingY0 = easingX0 * adjustedSpeed
- // Final control point. Has slope 0, unless that will make us accelerate then decelerate,
+ // Final control point. Has slope 0, unless that will make us accelerate then
+ // decelerate,
// in that case we set the slope to 1.
val easingX1 = 0.8f
val easingY1 = if (easingX0 > easingY0) 0.8f else 1f
animationState.animateTo(
- finalTarget, tween(
+ finalTarget,
+ tween(
(finalSnapDuration * 1000).roundToInt(),
easing = CubicBezierEasing(easingX0, easingY0, easingX1, easingY1)
)
diff --git a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/lazy/ScalingLazyListItemInfo.kt b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/lazy/ScalingLazyListItemInfo.kt
index b70ee81..e868726 100644
--- a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/lazy/ScalingLazyListItemInfo.kt
+++ b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/lazy/ScalingLazyListItemInfo.kt
@@ -21,14 +21,10 @@
* @see ScalingLazyListLayoutInfo
*/
public sealed interface ScalingLazyListItemInfo {
- /**
- * The index of the item in the list.
- */
+ /** The index of the item in the list. */
val index: Int
- /**
- * The key of the item which was passed to the item() or items() function.
- */
+ /** The key of the item which was passed to the item() or items() function. */
val key: Any
/**
@@ -40,9 +36,9 @@
* For [ScalingLazyListAnchorType.ItemCenter] the offset is from the center of the list item to
* the center-line of the viewport.
*
- * For [ScalingLazyListAnchorType.ItemStart] if is the offset
- * between the start (edge) of the item and the center-line of the viewport, for normal layout
- * this will be the top edge of the item, for reverseLayout it will be the bottom edge.
+ * For [ScalingLazyListAnchorType.ItemStart] if is the offset between the start (edge) of the
+ * item and the center-line of the viewport, for normal layout this will be the top edge of the
+ * item, for reverseLayout it will be the bottom edge.
*/
val unadjustedOffset: Int
@@ -55,9 +51,9 @@
* For [ScalingLazyListAnchorType.ItemCenter] the offset is from the center of the list item to
* the center-line of the viewport.
*
- * For [ScalingLazyListAnchorType.ItemStart] if is the offset
- * between the start (edge) of the item and the center-line of the viewport, for normal layout
- * this will be the top edge of the item, for reverseLayout it will be the bottom edge.
+ * For [ScalingLazyListAnchorType.ItemStart] if is the offset between the start (edge) of the
+ * item and the center-line of the viewport, for normal layout this will be the top edge of the
+ * item, for reverseLayout it will be the bottom edge.
*
* A positive value indicates that the item's anchor point is below the viewport center-line, a
* negative value indicates that the item anchor point is above the viewport center-line.
@@ -70,18 +66,12 @@
*/
val size: Int
- /**
- * How much scaling has been applied to the item, between 0 and 1
- */
+ /** How much scaling has been applied to the item, between 0 and 1 */
val scale: Float
- /**
- * How much alpha has been applied to the item, between 0 and 1
- */
+ /** How much alpha has been applied to the item, between 0 and 1 */
val alpha: Float
- /**
- * The original (before scaling) size of the list item
- */
+ /** The original (before scaling) size of the list item */
val unadjustedSize: Int
}
diff --git a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/lazy/ScalingLazyListItemScope.kt b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/lazy/ScalingLazyListItemScope.kt
index aac594e..c35e66d 100644
--- a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/lazy/ScalingLazyListItemScope.kt
+++ b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/lazy/ScalingLazyListItemScope.kt
@@ -25,31 +25,27 @@
import androidx.compose.ui.unit.Density
import androidx.compose.ui.unit.Dp
-/**
- * Receiver scope being used by the item content parameter of ScalingLazyColumn.
- */
+/** Receiver scope being used by the item content parameter of ScalingLazyColumn. */
@Stable
@ScalingLazyScopeMarker
public sealed interface ScalingLazyListItemScope {
/**
* Have the content fill the [Constraints.maxWidth] and [Constraints.maxHeight] of the parent
* measurement constraints by setting the [minimum width][Constraints.minWidth] to be equal to
- * the [maximum width][Constraints.maxWidth] multiplied by [fraction] and the [minimum
- * height][Constraints.minHeight] to be equal to the [maximum height][Constraints.maxHeight]
- * multiplied by [fraction]. Note that, by default, the [fraction] is 1, so the modifier will
- * make the content fill the whole available space. [fraction] must be between `0` and `1`.
+ * the [maximum width][Constraints.maxWidth] multiplied by [fraction] and the
+ * [minimum height][Constraints.minHeight] to be equal to the
+ * [maximum height][Constraints.maxHeight] multiplied by [fraction]. Note that, by default, the
+ * [fraction] is 1, so the modifier will make the content fill the whole available space.
+ * [fraction] must be between `0` and `1`.
*
* Regular [Modifier.fillMaxSize] can't work inside the scrolling layouts as the items are
* measured with [Constraints.Infinity] as the constraints for the main axis.
*/
- fun Modifier.fillParentMaxSize(
- @FloatRange(from = 0.0, to = 1.0)
- fraction: Float = 1f
- ): Modifier
+ fun Modifier.fillParentMaxSize(@FloatRange(from = 0.0, to = 1.0) fraction: Float = 1f): Modifier
/**
- * Have the content fill the [Constraints.maxWidth] of the parent measurement constraints
- * by setting the [minimum width][Constraints.minWidth] to be equal to the
+ * Have the content fill the [Constraints.maxWidth] of the parent measurement constraints by
+ * setting the [minimum width][Constraints.minWidth] to be equal to the
* [maximum width][Constraints.maxWidth] multiplied by [fraction]. Note that, by default, the
* [fraction] is 1, so the modifier will make the content fill the whole parent width.
* [fraction] must be between `0` and `1`.
@@ -58,13 +54,12 @@
* items are measured with [Constraints.Infinity] as the constraints for the main axis.
*/
fun Modifier.fillParentMaxWidth(
- @FloatRange(from = 0.0, to = 1.0)
- fraction: Float = 1f
+ @FloatRange(from = 0.0, to = 1.0) fraction: Float = 1f
): Modifier
/**
- * Have the content fill the [Constraints.maxHeight] of the incoming measurement constraints
- * by setting the [minimum height][Constraints.minHeight] to be equal to the
+ * Have the content fill the [Constraints.maxHeight] of the incoming measurement constraints by
+ * setting the [minimum height][Constraints.minHeight] to be equal to the
* [maximum height][Constraints.maxHeight] multiplied by [fraction]. Note that, by default, the
* [fraction] is 1, so the modifier will make the content fill the whole parent height.
* [fraction] must be between `0` and `1`.
@@ -73,8 +68,7 @@
* items are measured with [Constraints.Infinity] as the constraints for the main axis.
*/
fun Modifier.fillParentMaxHeight(
- @FloatRange(from = 0.0, to = 1.0)
- fraction: Float = 1f
+ @FloatRange(from = 0.0, to = 1.0) fraction: Float = 1f
): Modifier
}
@@ -85,14 +79,10 @@
private val maxWidth: Dp = with(density) { constraints.maxWidth.toDp() }
private val maxHeight: Dp = with(density) { constraints.maxHeight.toDp() }
- override fun Modifier.fillParentMaxSize(fraction: Float) = size(
- maxWidth * fraction,
- maxHeight * fraction
- )
+ override fun Modifier.fillParentMaxSize(fraction: Float) =
+ size(maxWidth * fraction, maxHeight * fraction)
- override fun Modifier.fillParentMaxWidth(fraction: Float) =
- width(maxWidth * fraction)
+ override fun Modifier.fillParentMaxWidth(fraction: Float) = width(maxWidth * fraction)
- override fun Modifier.fillParentMaxHeight(fraction: Float) =
- height(maxHeight * fraction)
+ override fun Modifier.fillParentMaxHeight(fraction: Float) = height(maxHeight * fraction)
}
diff --git a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/lazy/ScalingLazyListLayoutInfo.kt b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/lazy/ScalingLazyListLayoutInfo.kt
index ade5095..4d38856 100644
--- a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/lazy/ScalingLazyListLayoutInfo.kt
+++ b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/lazy/ScalingLazyListLayoutInfo.kt
@@ -25,9 +25,7 @@
* Use [ScalingLazyListState.layoutInfo] to retrieve this
*/
public sealed interface ScalingLazyListLayoutInfo {
- /**
- * The list of [ScalingLazyListItemInfo] representing all the currently visible items.
- */
+ /** The list of [ScalingLazyListItemInfo] representing all the currently visible items. */
val visibleItemsInfo: List<ScalingLazyListItemInfo>
/**
@@ -49,9 +47,7 @@
*/
val viewportEndOffset: Int
- /**
- * The total count of items passed to [ScalingLazyColumn].
- */
+ /** The total count of items passed to [ScalingLazyColumn]. */
val totalItemsCount: Int
/**
@@ -60,14 +56,10 @@
*/
val viewportSize: IntSize
- /**
- * The orientation of the scaling lazy list.
- */
+ /** The orientation of the scaling lazy list. */
val orientation: Orientation
- /**
- * True if the direction of scrolling and layout is reversed.
- */
+ /** True if the direction of scrolling and layout is reversed. */
val reverseLayout: Boolean
/**
@@ -78,9 +70,8 @@
val beforeContentPadding: Int
/**
- * The content padding in pixels applied after the last item in the direction of scrolling.
- * For example it is a bottom content padding for ScalingLazyColumn with reverseLayout set to
- * false.
+ * The content padding in pixels applied after the last item in the direction of scrolling. For
+ * example it is a bottom content padding for ScalingLazyColumn with reverseLayout set to false.
*/
val afterContentPadding: Int
@@ -98,8 +89,6 @@
*/
val afterAutoCenteringPadding: Int
- /**
- * How to anchor list items to the center-line of the viewport
- */
+ /** How to anchor list items to the center-line of the viewport */
val anchorType: ScalingLazyListAnchorType
}
diff --git a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/lazy/ScalingLazyListState.kt b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/lazy/ScalingLazyListState.kt
index 88368ed..c97f632 100644
--- a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/lazy/ScalingLazyListState.kt
+++ b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/lazy/ScalingLazyListState.kt
@@ -42,11 +42,10 @@
* Creates a [ScalingLazyListState] that is remembered across compositions.
*
* @param initialCenterItemIndex the initial value for [ScalingLazyListState.centerItemIndex],
- * defaults to 1. This will place the 2nd list item (index == 1) in the center of the viewport and
- * the first item (index == 0) before it.
- *
+ * defaults to 1. This will place the 2nd list item (index == 1) in the center of the viewport and
+ * the first item (index == 0) before it.
* @param initialCenterItemScrollOffset the initial value for
- * [ScalingLazyListState.centerItemScrollOffset] in pixels
+ * [ScalingLazyListState.centerItemScrollOffset] in pixels
*/
@Composable
public fun rememberScalingLazyListState(
@@ -54,10 +53,7 @@
initialCenterItemScrollOffset: Int = 0
): ScalingLazyListState {
return rememberSaveable(saver = ScalingLazyListState.Saver) {
- ScalingLazyListState(
- initialCenterItemIndex,
- initialCenterItemScrollOffset
- )
+ ScalingLazyListState(initialCenterItemIndex, initialCenterItemScrollOffset)
}
}
@@ -67,14 +63,14 @@
* In most cases, this will be created via [rememberScalingLazyListState].
*
* @param initialCenterItemIndex the initial value for [ScalingLazyListState.centerItemIndex],
- * defaults to 1. This will place the 2nd list item (index == 1) in the center of the viewport and
- * the first item (index == 0) before it.
+ * defaults to 1. This will place the 2nd list item (index == 1) in the center of the viewport and
+ * the first item (index == 0) before it.
*
* If the developer wants custom control over position and spacing they can switch off autoCentering
* and provide contentPadding.
*
* @param initialCenterItemScrollOffset the initial value for
- * [ScalingLazyListState.centerItemScrollOffset]
+ * [ScalingLazyListState.centerItemScrollOffset]
*
* Note that it is not always possible for the values provided by [initialCenterItemIndex] and
* [initialCenterItemScrollOffset] to be honored, e.g. If [initialCenterItemIndex] is set to a value
@@ -84,7 +80,8 @@
* [centerItemIndex] and [centerItemScrollOffset] can be read from the state.
*/
@Stable
-class ScalingLazyListState constructor(
+class ScalingLazyListState
+constructor(
private var initialCenterItemIndex: Int = 1,
private var initialCenterItemScrollOffset: Int = 0
) : ScrollableState {
@@ -103,6 +100,7 @@
val autoCentering: AutoCenteringParams?,
val localInspectionMode: Boolean
)
+
internal val initialized = mutableStateOf(false)
internal val config = mutableStateOf<Configuration?>(null)
@@ -111,9 +109,7 @@
private val incompleteScrollItem = mutableStateOf<Int?>(null)
private val incompleteScrollOffset = mutableStateOf<Int?>(null)
private val incompleteScrollAnimated = mutableStateOf(false)
- /**
- * The index of the item positioned closest to the viewport center
- */
+ /** The index of the item positioned closest to the viewport center */
public val centerItemIndex: Int by derivedStateOf {
(layoutInfo as? DefaultScalingLazyListLayoutInfo)?.let {
if (it.initialized) it.centerItemIndex else null
@@ -133,8 +129,8 @@
val config = config.value
if (
config == null ||
- config.autoCentering == null ||
- layoutInfo.internalVisibleItemInfo().isEmpty()
+ config.autoCentering == null ||
+ layoutInfo.internalVisibleItemInfo().isEmpty()
) {
0
} else {
@@ -161,208 +157,233 @@
* The object of [ScalingLazyListLayoutInfo] calculated during the last layout pass. For
* example, you can use it to calculate what items are currently visible.
*/
- public val layoutInfo: ScalingLazyListLayoutInfo by derivedStateOf(
- referentialEqualityPolicy()
- ) {
- val config = config.value
- if (config == null) {
- EmptyScalingLazyListLayoutInfo
- } else {
- // read list state once here to for performance reasons and to ensure consistency
- val lazyListLayoutInfo = lazyListState.layoutInfo
- val initialized = initialized.value
+ public val layoutInfo: ScalingLazyListLayoutInfo by
+ derivedStateOf(referentialEqualityPolicy()) {
+ val config = config.value
+ if (config == null) {
+ EmptyScalingLazyListLayoutInfo
+ } else {
+ // read list state once here to for performance reasons and to ensure consistency
+ val lazyListLayoutInfo = lazyListState.layoutInfo
+ val initialized = initialized.value
- val visibleItemsInfo = mutableListOf<ScalingLazyListItemInfo>()
- var newCenterItemIndex = 0
- var newCenterItemScrollOffset = 0
- val visible = initialized || config.localInspectionMode
+ val visibleItemsInfo = mutableListOf<ScalingLazyListItemInfo>()
+ var newCenterItemIndex = 0
+ var newCenterItemScrollOffset = 0
+ val visible = initialized || config.localInspectionMode
- // The verticalAdjustment is used to allow for the extraPadding that the
- // ScalingLazyColumn employs to ensure that there are sufficient list items composed
- // by the underlying LazyList even when there is extreme scaling being applied that
- // could result in additional list items be eligible to be drawn.
- // It is important to adjust for this extra space when working out the viewport
- // center-line based coordinate system of the ScalingLazyList.
- val verticalAdjustment =
- lazyListLayoutInfo.viewportStartOffset + config.extraPaddingPx
+ // The verticalAdjustment is used to allow for the extraPadding that the
+ // ScalingLazyColumn employs to ensure that there are sufficient list items composed
+ // by the underlying LazyList even when there is extreme scaling being applied that
+ // could result in additional list items be eligible to be drawn.
+ // It is important to adjust for this extra space when working out the viewport
+ // center-line based coordinate system of the ScalingLazyList.
+ val verticalAdjustment =
+ lazyListLayoutInfo.viewportStartOffset + config.extraPaddingPx
- // Find the item in the middle of the viewport
- val centralItemArrayIndex =
- findItemNearestCenter(lazyListLayoutInfo, config, verticalAdjustment)
- if (centralItemArrayIndex != null) {
- val originalVisibleItemsInfo = lazyListLayoutInfo.visibleItemsInfo
- val centralItem = originalVisibleItemsInfo[centralItemArrayIndex]
+ // Find the item in the middle of the viewport
+ val centralItemArrayIndex =
+ findItemNearestCenter(lazyListLayoutInfo, config, verticalAdjustment)
+ if (centralItemArrayIndex != null) {
+ val originalVisibleItemsInfo = lazyListLayoutInfo.visibleItemsInfo
+ val centralItem = originalVisibleItemsInfo[centralItemArrayIndex]
- // Place the center item
- val centerItemInfo: ScalingLazyListItemInfo = calculateItemInfo(
- centralItem.offset,
- centralItem,
- verticalAdjustment,
- config.viewportHeightPx,
- config.viewportCenterLinePx(),
- config.scalingParams,
- config.beforeContentPaddingPx,
- config.anchorType,
- config.autoCentering,
- visible
- )
- visibleItemsInfo.add(
- centerItemInfo
- )
-
- newCenterItemIndex = centerItemInfo.index
- newCenterItemScrollOffset = -centerItemInfo.offset
-
- // Find the adjusted position of the central item in the coordinate system of the
- // underlying LazyColumn by adjusting for any scaling
- val centralItemAdjustedUnderlyingOffset =
- centralItem.offset + ((centerItemInfo.startOffset(config.anchorType) -
- centerItemInfo.unadjustedStartOffset(config.anchorType))).roundToInt()
-
- // Go Up
- // nextItemBottomNoPadding uses the coordinate system of the underlying LazyList. It
- // keeps track of the top of the next potential list item that is a candidate to be
- // drawn in the viewport as we walk up the list items from the center. Going up
- // involved making offset smaller/negative as the coordinate system of the LazyList
- // starts at the top of the viewport. Note that the start of the lazy list
- // coordinates starts at '- start content padding in pixels' and goes beyond the
- // last visible list items to include the end content padding in pixels.
-
- // centralItem.offset is a startOffset in the coordinate system of the
- // underlying lazy list.
- var nextItemBottomNoPadding =
- centralItemAdjustedUnderlyingOffset - config.gapBetweenItemsPx
-
- (centralItemArrayIndex - 1 downTo 0).forEach { ix ->
- if (nextItemBottomNoPadding >= verticalAdjustment) {
- val currentItem =
- lazyListLayoutInfo.visibleItemsInfo[ix]
- if (
- !discardAutoCenteringListItem(config, lazyListLayoutInfo, currentItem)
- ) {
- val itemInfo = calculateItemInfo(
- nextItemBottomNoPadding - currentItem.size,
- currentItem,
- verticalAdjustment,
- config.viewportHeightPx,
- config.viewportCenterLinePx(),
- config.scalingParams,
- config.beforeContentPaddingPx,
- config.anchorType,
- config.autoCentering,
- visible
- )
- visibleItemsInfo.add(0, itemInfo)
- nextItemBottomNoPadding =
- nextItemBottomNoPadding - itemInfo.size - config.gapBetweenItemsPx
- }
- } else {
- return@forEach
- }
- }
-
- // Go Down
- // nextItemTopNoPadding uses the coordinate system of the underlying LazyList. It
- // keeps track of the top of the next potential list item that is a candidate to be
- // drawn in the viewport as we walk down the list items from the center.
- var nextItemTopNoPadding =
- centralItemAdjustedUnderlyingOffset + centerItemInfo.size +
- config.gapBetweenItemsPx
-
- (((centralItemArrayIndex + 1) until
- originalVisibleItemsInfo.size)).forEach { ix ->
- if ((nextItemTopNoPadding - config.viewportHeightPx) <= verticalAdjustment) {
- val currentItem =
- lazyListLayoutInfo.visibleItemsInfo[ix]
- if (
- !discardAutoCenteringListItem(config, lazyListLayoutInfo, currentItem)
- ) {
- val itemInfo = calculateItemInfo(
- nextItemTopNoPadding,
- currentItem,
- verticalAdjustment,
- config.viewportHeightPx,
- config.viewportCenterLinePx(),
- config.scalingParams,
- config.beforeContentPaddingPx,
- config.anchorType,
- config.autoCentering,
- visible
- )
-
- visibleItemsInfo.add(itemInfo)
- nextItemTopNoPadding += itemInfo.size + config.gapBetweenItemsPx
- }
- } else {
- return@forEach
- }
- }
- }
- val totalItemsCount =
- if (config.autoCentering != null) {
- (lazyListLayoutInfo.totalItemsCount - 2).coerceAtLeast(0)
- } else {
- lazyListLayoutInfo.totalItemsCount
- }
-
- // Decide if we are ready for the 2nd stage of initialization
- // 1. We are not yet initialized and
-
- val readyForInitialScroll =
- if (!initialized) {
- // 1. autoCentering is off or
- // 2. The list has no items or
- // 3. the before content autoCentering Spacer has been sized.
- // NOTE: It is possible, if the first real item in the list is large, that the size
- // of the Spacer is 0.
- config.autoCentering == null || (
- lazyListLayoutInfo.visibleItemsInfo.size >= 2 && (
- // or Empty list (other than the 2 spacers)
- lazyListLayoutInfo.visibleItemsInfo.size == 2 ||
- // or first item is correctly size
- topSpacerIsCorrectlySized(
- config,
- lazyListLayoutInfo.visibleItemsInfo,
- lazyListLayoutInfo.totalItemsCount
- )
- )
+ // Place the center item
+ val centerItemInfo: ScalingLazyListItemInfo =
+ calculateItemInfo(
+ centralItem.offset,
+ centralItem,
+ verticalAdjustment,
+ config.viewportHeightPx,
+ config.viewportCenterLinePx(),
+ config.scalingParams,
+ config.beforeContentPaddingPx,
+ config.anchorType,
+ config.autoCentering,
+ visible
)
- } else {
- // We are already initialized and have an incomplete scroll to finish
- incompleteScrollItem.value != null
- }
+ visibleItemsInfo.add(centerItemInfo)
- DefaultScalingLazyListLayoutInfo(
- internalVisibleItemsInfo = visibleItemsInfo,
- totalItemsCount = totalItemsCount,
- viewportStartOffset =
- lazyListLayoutInfo.viewportStartOffset + config.extraPaddingPx,
- viewportEndOffset = lazyListLayoutInfo.viewportEndOffset - config.extraPaddingPx,
- centerItemIndex = if (initialized) newCenterItemIndex else 0,
- centerItemScrollOffset = if (initialized) newCenterItemScrollOffset else 0,
- reverseLayout = config.reverseLayout,
- orientation = lazyListLayoutInfo.orientation,
- viewportSize = IntSize(
- width = lazyListLayoutInfo.viewportSize.width,
- height = lazyListLayoutInfo.viewportSize.height - config.extraPaddingPx * 2
- ),
- beforeContentPadding = config.beforeContentPaddingPx,
- afterContentPadding = config.afterContentPaddingPx,
- beforeAutoCenteringPadding = calculateTopAutoCenteringPaddingPx(
- config,
- visibleItemsInfo,
- totalItemsCount
- ),
- afterAutoCenteringPadding = calculateBottomAutoCenteringPaddingPx(
- config,
- visibleItemsInfo,
- totalItemsCount),
- readyForInitialScroll = readyForInitialScroll,
- initialized = initialized,
- anchorType = config.anchorType,
- )
+ newCenterItemIndex = centerItemInfo.index
+ newCenterItemScrollOffset = -centerItemInfo.offset
+
+ // Find the adjusted position of the central item in the coordinate system of
+ // the
+ // underlying LazyColumn by adjusting for any scaling
+ val centralItemAdjustedUnderlyingOffset =
+ centralItem.offset +
+ ((centerItemInfo.startOffset(config.anchorType) -
+ centerItemInfo.unadjustedStartOffset(config.anchorType)))
+ .roundToInt()
+
+ // Go Up
+ // nextItemBottomNoPadding uses the coordinate system of the underlying
+ // LazyList. It
+ // keeps track of the top of the next potential list item that is a candidate to
+ // be
+ // drawn in the viewport as we walk up the list items from the center. Going up
+ // involved making offset smaller/negative as the coordinate system of the
+ // LazyList
+ // starts at the top of the viewport. Note that the start of the lazy list
+ // coordinates starts at '- start content padding in pixels' and goes beyond the
+ // last visible list items to include the end content padding in pixels.
+
+ // centralItem.offset is a startOffset in the coordinate system of the
+ // underlying lazy list.
+ var nextItemBottomNoPadding =
+ centralItemAdjustedUnderlyingOffset - config.gapBetweenItemsPx
+
+ (centralItemArrayIndex - 1 downTo 0).forEach { ix ->
+ if (nextItemBottomNoPadding >= verticalAdjustment) {
+ val currentItem = lazyListLayoutInfo.visibleItemsInfo[ix]
+ if (
+ !discardAutoCenteringListItem(
+ config,
+ lazyListLayoutInfo,
+ currentItem
+ )
+ ) {
+ val itemInfo =
+ calculateItemInfo(
+ nextItemBottomNoPadding - currentItem.size,
+ currentItem,
+ verticalAdjustment,
+ config.viewportHeightPx,
+ config.viewportCenterLinePx(),
+ config.scalingParams,
+ config.beforeContentPaddingPx,
+ config.anchorType,
+ config.autoCentering,
+ visible
+ )
+ visibleItemsInfo.add(0, itemInfo)
+ nextItemBottomNoPadding =
+ nextItemBottomNoPadding -
+ itemInfo.size -
+ config.gapBetweenItemsPx
+ }
+ } else {
+ return@forEach
+ }
+ }
+
+ // Go Down
+ // nextItemTopNoPadding uses the coordinate system of the underlying LazyList.
+ // It
+ // keeps track of the top of the next potential list item that is a candidate to
+ // be
+ // drawn in the viewport as we walk down the list items from the center.
+ var nextItemTopNoPadding =
+ centralItemAdjustedUnderlyingOffset +
+ centerItemInfo.size +
+ config.gapBetweenItemsPx
+
+ (((centralItemArrayIndex + 1) until originalVisibleItemsInfo.size)).forEach { ix
+ ->
+ if (
+ (nextItemTopNoPadding - config.viewportHeightPx) <= verticalAdjustment
+ ) {
+ val currentItem = lazyListLayoutInfo.visibleItemsInfo[ix]
+ if (
+ !discardAutoCenteringListItem(
+ config,
+ lazyListLayoutInfo,
+ currentItem
+ )
+ ) {
+ val itemInfo =
+ calculateItemInfo(
+ nextItemTopNoPadding,
+ currentItem,
+ verticalAdjustment,
+ config.viewportHeightPx,
+ config.viewportCenterLinePx(),
+ config.scalingParams,
+ config.beforeContentPaddingPx,
+ config.anchorType,
+ config.autoCentering,
+ visible
+ )
+
+ visibleItemsInfo.add(itemInfo)
+ nextItemTopNoPadding += itemInfo.size + config.gapBetweenItemsPx
+ }
+ } else {
+ return@forEach
+ }
+ }
+ }
+ val totalItemsCount =
+ if (config.autoCentering != null) {
+ (lazyListLayoutInfo.totalItemsCount - 2).coerceAtLeast(0)
+ } else {
+ lazyListLayoutInfo.totalItemsCount
+ }
+
+ // Decide if we are ready for the 2nd stage of initialization
+ // 1. We are not yet initialized and
+
+ val readyForInitialScroll =
+ if (!initialized) {
+ // 1. autoCentering is off or
+ // 2. The list has no items or
+ // 3. the before content autoCentering Spacer has been sized.
+ // NOTE: It is possible, if the first real item in the list is large, that
+ // the size
+ // of the Spacer is 0.
+ config.autoCentering == null ||
+ (lazyListLayoutInfo.visibleItemsInfo.size >= 2 &&
+ (
+ // or Empty list (other than the 2 spacers)
+ lazyListLayoutInfo.visibleItemsInfo.size == 2 ||
+ // or first item is correctly size
+ topSpacerIsCorrectlySized(
+ config,
+ lazyListLayoutInfo.visibleItemsInfo,
+ lazyListLayoutInfo.totalItemsCount
+ )))
+ } else {
+ // We are already initialized and have an incomplete scroll to finish
+ incompleteScrollItem.value != null
+ }
+
+ DefaultScalingLazyListLayoutInfo(
+ internalVisibleItemsInfo = visibleItemsInfo,
+ totalItemsCount = totalItemsCount,
+ viewportStartOffset =
+ lazyListLayoutInfo.viewportStartOffset + config.extraPaddingPx,
+ viewportEndOffset =
+ lazyListLayoutInfo.viewportEndOffset - config.extraPaddingPx,
+ centerItemIndex = if (initialized) newCenterItemIndex else 0,
+ centerItemScrollOffset = if (initialized) newCenterItemScrollOffset else 0,
+ reverseLayout = config.reverseLayout,
+ orientation = lazyListLayoutInfo.orientation,
+ viewportSize =
+ IntSize(
+ width = lazyListLayoutInfo.viewportSize.width,
+ height =
+ lazyListLayoutInfo.viewportSize.height - config.extraPaddingPx * 2
+ ),
+ beforeContentPadding = config.beforeContentPaddingPx,
+ afterContentPadding = config.afterContentPaddingPx,
+ beforeAutoCenteringPadding =
+ calculateTopAutoCenteringPaddingPx(
+ config,
+ visibleItemsInfo,
+ totalItemsCount
+ ),
+ afterAutoCenteringPadding =
+ calculateBottomAutoCenteringPaddingPx(
+ config,
+ visibleItemsInfo,
+ totalItemsCount
+ ),
+ readyForInitialScroll = readyForInitialScroll,
+ initialized = initialized,
+ anchorType = config.anchorType,
+ )
+ }
}
- }
private fun findItemNearestCenter(
lazyListLayoutInfo: LazyListLayoutInfo,
@@ -386,21 +407,20 @@
}
companion object {
- /**
- * The default [Saver] implementation for [ScalingLazyListState].
- */
- val Saver = listSaver<ScalingLazyListState, Int>(
- save = {
- listOf(
- it.centerItemIndex,
- it.centerItemScrollOffset,
- )
- },
- restore = {
- val scalingLazyColumnState = ScalingLazyListState(it[0], it[1])
- scalingLazyColumnState
- }
- )
+ /** The default [Saver] implementation for [ScalingLazyListState]. */
+ val Saver =
+ listSaver<ScalingLazyListState, Int>(
+ save = {
+ listOf(
+ it.centerItemIndex,
+ it.centerItemScrollOffset,
+ )
+ },
+ restore = {
+ val scalingLazyColumnState = ScalingLazyListState(it[0], it[1])
+ scalingLazyColumnState
+ }
+ )
}
override val isScrollInProgress: Boolean
@@ -424,14 +444,15 @@
override val canScrollBackward: Boolean
get() = lazyListState.canScrollBackward
+
/**
* Instantly brings the item at [index] to the center of the viewport and positions it based on
* the [anchorType] and applies the [scrollOffset] pixels.
*
* @param index the index to which to scroll. Must be non-negative.
* @param scrollOffset the offset that the item should end up after the scroll. Note that
- * positive offset refers to forward scroll, so in a top-to-bottom list, positive offset will
- * scroll the item further upward (taking it partly offscreen).
+ * positive offset refers to forward scroll, so in a top-to-bottom list, positive offset will
+ * scroll the item further upward (taking it partly offscreen).
*/
public suspend fun scrollToItem(
/*@IntRange(from = 0)*/
@@ -443,14 +464,14 @@
}
/**
- * Brings the item at [index] to the center of the viewport and positions it based on
- * the [anchorType] and applies the [scrollOffset] pixels.
+ * Brings the item at [index] to the center of the viewport and positions it based on the
+ * [anchorType] and applies the [scrollOffset] pixels.
*
* @param animated whether to animate the scroll
* @param index the index to which to scroll. Must be non-negative.
* @param scrollOffset the offset that the item should end up after the scroll. Note that
- * positive offset refers to forward scroll, so in a top-to-bottom list, positive offset will
- * scroll the item further upward (taking it partly offscreen).
+ * positive offset refers to forward scroll, so in a top-to-bottom list, positive offset will
+ * scroll the item further upward (taking it partly offscreen).
*/
internal suspend fun scrollToItem(
animated: Boolean,
@@ -473,8 +494,7 @@
val targetIndex = index.coerceAtMost(layoutInfo.totalItemsCount)
val lazyListStateIndex = targetIndex + if (config.autoCentering != null) 1 else 0
- val offsetToCenterOfViewport =
- config.beforeContentPaddingPx - config.viewportCenterLinePx()
+ val offsetToCenterOfViewport = config.beforeContentPaddingPx - config.viewportCenterLinePx()
if (config.anchorType == ScalingLazyListAnchorType.ItemStart) {
val offset = offsetToCenterOfViewport + scrollOffset
return lazyListState.scrollToItem(animated, lazyListStateIndex, offset)
@@ -531,9 +551,8 @@
*
* @param index the index to which to scroll. Must be non-negative.
* @param scrollOffset the offset that the item should end up after the scroll (same as
- * [scrollToItem]) - note that positive offset refers to forward scroll, so in a
- * top-to-bottom list, positive offset will scroll the item further upward (taking it partly
- * offscreen)
+ * [scrollToItem]) - note that positive offset refers to forward scroll, so in a top-to-bottom
+ * list, positive offset will scroll the item further upward (taking it partly offscreen)
*/
public suspend fun animateScrollToItem(
/*@IntRange(from = 0)*/
@@ -562,8 +581,11 @@
visibleItems: List<ScalingLazyListItemInfo>,
totalItemCount: Int
): Int {
- if (params.autoCentering == null ||
- (visibleItems.isNotEmpty() && visibleItems.first().index != 0)) return 0
+ if (
+ params.autoCentering == null ||
+ (visibleItems.isNotEmpty() && visibleItems.first().index != 0)
+ )
+ return 0
// Work out the index we want to find - if there are less items in the list than would be
// needed to make initialItemIndex be visible then use the last visible item
@@ -572,8 +594,7 @@
// Find the initialCenterItem, if it is null that means it is not in view - therefore
// we have more than enough content before it to make sure it can be scrolled to the center
// of the viewport
- val initialCenterItem =
- visibleItems.fastFirstOrNull { it.index == itemIndexToFind }
+ val initialCenterItem = visibleItems.fastFirstOrNull { it.index == itemIndexToFind }
// Determine how much space we actually need
var spaceNeeded = params.spaceNeeded(initialCenterItem)
@@ -613,8 +634,7 @@
// Find the initialCenterItem, if it is null that means it is not in view - therefore
// we have more than enough content before it to make sure it can be scrolled to the center
// of the viewport
- val initialCenterItem =
- visibleItems.fastFirstOrNull { it.index == itemIndexToFind }
+ val initialCenterItem = visibleItems.fastFirstOrNull { it.index == itemIndexToFind }
// Determine how much space we actually need
var spaceNeeded = params.spaceNeeded(initialCenterItem)
@@ -635,35 +655,43 @@
}
private fun Configuration.spaceNeeded(item: ScalingLazyListItemInfo?) =
- viewportCenterLinePx() - gapBetweenItemsPx - autoCentering!!.itemOffset -
+ viewportCenterLinePx() -
+ gapBetweenItemsPx -
+ autoCentering!!.itemOffset -
(item?.unadjustedItemSizeAboveOffsetPoint(this) ?: 0)
private fun Configuration.spaceNeeded(item: LazyListItemInfo?) =
- viewportCenterLinePx() - gapBetweenItemsPx - autoCentering!!.itemOffset -
+ viewportCenterLinePx() -
+ gapBetweenItemsPx -
+ autoCentering!!.itemOffset -
(item?.itemSizeAboveOffsetPoint(this) ?: 0)
private fun calculateBottomAutoCenteringPaddingPx(
params: Configuration,
visibleItemsInfo: List<ScalingLazyListItemInfo>,
totalItemsCount: Int
- ) = if (params.autoCentering != null && visibleItemsInfo.isNotEmpty() &&
- visibleItemsInfo.last().index == totalItemsCount - 1
- ) {
- // Round any fractional part up for the bottom spacer as we round down toward zero
- // for the viewport center line and item heights working from the top of the
- // viewport and then add 1 pixel if needed (for an odd height viewport) at the end
- // spacer
- params.viewportHeightPx - params.viewportCenterLinePx() -
- visibleItemsInfo.last().unadjustedItemSizeBelowOffsetPoint(params)
- } else {
- 0
- }
+ ) =
+ if (
+ params.autoCentering != null &&
+ visibleItemsInfo.isNotEmpty() &&
+ visibleItemsInfo.last().index == totalItemsCount - 1
+ ) {
+ // Round any fractional part up for the bottom spacer as we round down toward zero
+ // for the viewport center line and item heights working from the top of the
+ // viewport and then add 1 pixel if needed (for an odd height viewport) at the end
+ // spacer
+ params.viewportHeightPx -
+ params.viewportCenterLinePx() -
+ visibleItemsInfo.last().unadjustedItemSizeBelowOffsetPoint(params)
+ } else {
+ 0
+ }
/**
* Calculate the center line of the viewport. This is half of the viewport height rounded down
* to the nearest int. This means that for a viewport with an odd number of pixels in height we
- * will have the area above the viewport being one pixel smaller, e.g. a 199 pixel high
- * viewport will be treated as having 99 pixels above and 100 pixels below the center line.
+ * will have the area above the viewport being one pixel smaller, e.g. a 199 pixel high viewport
+ * will be treated as having 99 pixels above and 100 pixels below the center line.
*/
private fun Configuration.viewportCenterLinePx(): Int = viewportHeightPx / 2
@@ -672,9 +700,7 @@
* offset point. For an edge anchored item the offset point is the top of the item. For a center
* anchored item the offset point is floor(height/2).
*/
- private fun ScalingLazyListItemInfo.unadjustedItemSizeAboveOffsetPoint(
- params: Configuration
- ) =
+ private fun ScalingLazyListItemInfo.unadjustedItemSizeAboveOffsetPoint(params: Configuration) =
if (params.anchorType == ScalingLazyListAnchorType.ItemStart) {
0
} else {
@@ -682,8 +708,8 @@
}
/**
- * How much of the items size would be above the point on the item that represents the
- * offset point. For an edge anchored item the offset point is the top of the item. For a center
+ * How much of the items size would be above the point on the item that represents the offset
+ * point. For an edge anchored item the offset point is the top of the item. For a center
* anchored item the offset point is floor(height/2).
*/
private fun LazyListItemInfo.itemSizeAboveOffsetPoint(params: Configuration) =
@@ -694,13 +720,11 @@
}
/**
- * How much of the items size would be below the point on the item that represents the
- * offset point. For an edge anchored item the offset point is the top of the item. For a center
+ * How much of the items size would be below the point on the item that represents the offset
+ * point. For an edge anchored item the offset point is the top of the item. For a center
* anchored item the offset point is floor(height/2).
*/
- private fun ScalingLazyListItemInfo.unadjustedItemSizeBelowOffsetPoint(
- params: Configuration
- ) =
+ private fun ScalingLazyListItemInfo.unadjustedItemSizeBelowOffsetPoint(params: Configuration) =
this.unadjustedSize - unadjustedItemSizeAboveOffsetPoint(params)
}
diff --git a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/lazy/ScalingLazyScopeMarker.kt b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/lazy/ScalingLazyScopeMarker.kt
index c0f85f7..6dd1cab 100644
--- a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/lazy/ScalingLazyScopeMarker.kt
+++ b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/lazy/ScalingLazyScopeMarker.kt
@@ -16,8 +16,5 @@
package androidx.wear.compose.foundation.lazy
-/**
- * DSL marker used to distinguish between lazy layout scope and the item scope.
- */
-@DslMarker
-annotation class ScalingLazyScopeMarker
+/** DSL marker used to distinguish between lazy layout scope and the item scope. */
+@DslMarker annotation class ScalingLazyScopeMarker
diff --git a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/rotary/Haptics.kt b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/rotary/Haptics.kt
index 76fc62c..d5515df 100644
--- a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/rotary/Haptics.kt
+++ b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/rotary/Haptics.kt
@@ -39,30 +39,16 @@
import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.coroutines.withContext
-/**
- * Handles haptics for rotary usage
- */
+/** Handles haptics for rotary usage */
internal interface RotaryHapticHandler {
- /**
- * Handles haptics when scroll is used
- */
- fun handleScrollHaptic(
- timestamp: Long,
- deltaInPixels: Float
- )
+ /** Handles haptics when scroll is used */
+ fun handleScrollHaptic(timestamp: Long, deltaInPixels: Float)
- /**
- * Handles haptics when scroll with snap is used
- */
- fun handleSnapHaptic(
- timestamp: Long,
- deltaInPixels: Float
- )
+ /** Handles haptics when scroll with snap is used */
+ fun handleSnapHaptic(timestamp: Long, deltaInPixels: Float)
- /**
- * Handles haptics when edge of the list is reached
- */
+ /** Handles haptics when edge of the list is reached */
fun handleLimitHaptic(isStart: Boolean)
}
@@ -80,8 +66,9 @@
/**
* Remembers custom rotary haptic handler.
- * @param scrollableState A scrollableState, used to determine whether the end of the scrollable
- * was reached or not.
+ *
+ * @param scrollableState A scrollableState, used to determine whether the end of the scrollable was
+ * reached or not.
*/
@Composable
private fun rememberCustomRotaryHapticHandler(
@@ -98,21 +85,18 @@
val hapticsThresholdPx: Long = 50
LaunchedEffect(hapticsChannel, throttleThresholdMs) {
- hapticsChannel.receiveAsFlow()
- .throttleLatest(throttleThresholdMs)
- .collect { hapticType ->
- // 'withContext' launches performHapticFeedback in a separate thread,
- // as otherwise it produces a visible lag (b/219776664)
- val currentTime = System.currentTimeMillis()
- debugLog { "Haptics started" }
- withContext(Dispatchers.Default) {
- debugLog {
- "Performing haptics, delay: " +
- "${System.currentTimeMillis() - currentTime}"
- }
- hapticsProvider.performHapticFeedback(hapticType)
+ hapticsChannel.receiveAsFlow().throttleLatest(throttleThresholdMs).collect { hapticType ->
+ // 'withContext' launches performHapticFeedback in a separate thread,
+ // as otherwise it produces a visible lag (b/219776664)
+ val currentTime = System.currentTimeMillis()
+ debugLog { "Haptics started" }
+ withContext(Dispatchers.Default) {
+ debugLog {
+ "Performing haptics, delay: " + "${System.currentTimeMillis() - currentTime}"
}
+ hapticsProvider.performHapticFeedback(hapticType)
}
+ }
}
return remember(scrollableState, hapticsChannel, hapticsProvider) {
CustomRotaryHapticHandler(scrollableState, hapticsChannel, hapticsThresholdPx)
@@ -147,57 +131,37 @@
val scrollTick: Int?,
val scrollLimit: Int?
) {
- /**
- * Rotary haptic constants from WearSDK
- */
- object WearSDKHapticConstants : HapticConstants(
- WearHapticFeedbackConstants.getScrollItemFocus(),
- WearHapticFeedbackConstants.getScrollTick(),
- WearHapticFeedbackConstants.getScrollLimit()
- )
+ /** Rotary haptic constants from WearSDK */
+ object WearSDKHapticConstants :
+ HapticConstants(
+ WearHapticFeedbackConstants.getScrollItemFocus(),
+ WearHapticFeedbackConstants.getScrollTick(),
+ WearHapticFeedbackConstants.getScrollLimit()
+ )
/**
- * Rotary haptic constants for Galaxy Watch. These constants
- * are used by Samsung for producing rotary haptics
+ * Rotary haptic constants for Galaxy Watch. These constants are used by Samsung for producing
+ * rotary haptics
*/
- object GalaxyWatchConstants : HapticConstants(
- 102, 101, 50107
- )
+ object GalaxyWatchConstants : HapticConstants(102, 101, 50107)
- /**
- * Hidden constants from HapticFeedbackConstants.java
- * API 33, Wear 4
- */
- object Wear4RotaryHapticConstants : HapticConstants(
- 19, 18, 20
- )
+ /** Hidden constants from HapticFeedbackConstants.java API 33, Wear 4 */
+ object Wear4RotaryHapticConstants : HapticConstants(19, 18, 20)
- /**
- * Hidden constants from HapticFeedbackConstants.java
- * API 30, Wear 3.5
- */
- object Wear3Point5RotaryHapticConstants : HapticConstants(
- 10003, 10002, 10003
- )
+ /** Hidden constants from HapticFeedbackConstants.java API 30, Wear 3.5 */
+ object Wear3Point5RotaryHapticConstants : HapticConstants(10003, 10002, 10003)
- object DisabledHapticConstants : HapticConstants(
- null, null, null
- )
+ object DisabledHapticConstants : HapticConstants(null, null, null)
}
@Composable
-private fun rememberHapticChannel() =
- remember {
- Channel<RotaryHapticsType>(
- capacity = 2,
- onBufferOverflow = BufferOverflow.DROP_OLDEST
- )
- }
+private fun rememberHapticChannel() = remember {
+ Channel<RotaryHapticsType>(capacity = 2, onBufferOverflow = BufferOverflow.DROP_OLDEST)
+}
/**
- * This class handles haptic feedback based
- * on the [scrollableState], scrolled pixels and [hapticsThresholdPx].
- * Haptic is not fired in this class, instead it's sent to [hapticsChannel]
+ * This class handles haptic feedback based on the [scrollableState], scrolled pixels and
+ * [hapticsThresholdPx]. Haptic is not fired in this class, instead it's sent to [hapticsChannel]
* where it'll be performed later.
*
* @param scrollableState Haptic performed based on this state
@@ -214,10 +178,7 @@
private var currScrollPosition = 0f
private var prevHapticsPosition = 0f
- override fun handleScrollHaptic(
- timestamp: Long,
- deltaInPixels: Float
- ) {
+ override fun handleScrollHaptic(timestamp: Long, deltaInPixels: Float) {
if (scrollableState.reachedTheLimit(deltaInPixels)) {
handleLimitHaptic(scrollableState.canScrollBackward)
} else {
@@ -232,10 +193,7 @@
}
}
- override fun handleSnapHaptic(
- timestamp: Long,
- deltaInPixels: Float
- ) {
+ override fun handleSnapHaptic(timestamp: Long, deltaInPixels: Float) {
if (scrollableState.reachedTheLimit(deltaInPixels)) {
handleLimitHaptic(scrollableState.canScrollBackward)
} else {
@@ -252,51 +210,41 @@
}
}
-/**
- * Rotary haptic types
- */
+/** Rotary haptic types */
@JvmInline
@VisibleForTesting
internal value class RotaryHapticsType(private val type: Int) {
companion object {
/**
- * A scroll ticking haptic. Similar to texture haptic - performed each time when
- * a scrollable content is scrolled by a certain distance
+ * A scroll ticking haptic. Similar to texture haptic - performed each time when a
+ * scrollable content is scrolled by a certain distance
*/
public val ScrollTick: RotaryHapticsType = RotaryHapticsType(1)
/**
- * An item focus (snap) haptic. Performed when a scrollable content is snapped
- * to a specific item.
+ * An item focus (snap) haptic. Performed when a scrollable content is snapped to a specific
+ * item.
*/
public val ScrollItemFocus: RotaryHapticsType = RotaryHapticsType(2)
/**
- * A limit(overscroll) haptic. Performed when a list reaches the limit
- * (start or end) and can't scroll further
+ * A limit(overscroll) haptic. Performed when a list reaches the limit (start or end) and
+ * can't scroll further
*/
public val ScrollLimit: RotaryHapticsType = RotaryHapticsType(3)
}
}
-/**
- * Remember disabled haptics handler
- */
+/** Remember disabled haptics handler */
@Composable
private fun rememberDisabledRotaryHapticHandler(): RotaryHapticHandler = remember {
object : RotaryHapticHandler {
- override fun handleScrollHaptic(
- timestamp: Long,
- deltaInPixels: Float
- ) {
+ override fun handleScrollHaptic(timestamp: Long, deltaInPixels: Float) {
// Do nothing
}
- override fun handleSnapHaptic(
- timestamp: Long,
- deltaInPixels: Float
- ) {
+ override fun handleSnapHaptic(timestamp: Long, deltaInPixels: Float) {
// Do nothing
}
@@ -306,9 +254,7 @@
}
}
-/**
- * Rotary haptic feedback
- */
+/** Rotary haptic feedback */
private class RotaryHapticFeedbackProvider(
private val view: View,
private val hapticConstants: HapticConstants
@@ -320,11 +266,9 @@
RotaryHapticsType.ScrollItemFocus -> {
hapticConstants.scrollFocus?.let { view.performHapticFeedback(it) }
}
-
RotaryHapticsType.ScrollTick -> {
hapticConstants.scrollTick?.let { view.performHapticFeedback(it) }
}
-
RotaryHapticsType.ScrollLimit -> {
hapticConstants.scrollLimit?.let { view.performHapticFeedback(it) }
}
@@ -339,25 +283,21 @@
private fun isWear3_5(context: Context): Boolean =
Build.VERSION.SDK_INT == Build.VERSION_CODES.R && getWearPlatformMrNumber(context) >= 5
-private fun isWear4(): Boolean =
- Build.VERSION.SDK_INT == Build.VERSION_CODES.TIRAMISU
+private fun isWear4(): Boolean = Build.VERSION.SDK_INT == Build.VERSION_CODES.TIRAMISU
private fun hasWearSDK(context: Context): Boolean =
context.packageManager.hasSystemFeature(PackageManager.FEATURE_WATCH) &&
- Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE
+ Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE
private fun getWearPlatformMrNumber(context: Context): Int =
- Settings.Global
- .getString(context.contentResolver, WEAR_PLATFORM_MR_NUMBER)?.toIntOrNull() ?: 0
+ Settings.Global.getString(context.contentResolver, WEAR_PLATFORM_MR_NUMBER)?.toIntOrNull() ?: 0
private const val WEAR_PLATFORM_MR_NUMBER: String = "wear_platform_mr_number"
private fun ScrollableState.reachedTheLimit(scrollDelta: Float): Boolean =
(scrollDelta > 0 && !canScrollForward) || (scrollDelta < 0 && !canScrollBackward)
-/**
- * Debug logging that can be enabled.
- */
+/** Debug logging that can be enabled. */
private const val DEBUG = false
private inline fun debugLog(generateMsg: () -> String) {
@@ -378,13 +318,13 @@
* }
* }
* ```
+ *
* With timeframe=1000 only those integers will be received: 1, 10, 20, 30 .
*/
@VisibleForTesting
-internal fun <T> Flow<T>.throttleLatest(timeframe: Long): Flow<T> =
- flow {
- conflate().collect {
- emit(it)
- delay(timeframe)
- }
+internal fun <T> Flow<T>.throttleLatest(timeframe: Long): Flow<T> = flow {
+ conflate().collect {
+ emit(it)
+ delay(timeframe)
}
+}
diff --git a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/rotary/RotaryScrollable.kt b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/rotary/RotaryScrollable.kt
index 700805f..9bfda3e 100644
--- a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/rotary/RotaryScrollable.kt
+++ b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/rotary/RotaryScrollable.kt
@@ -65,38 +65,38 @@
import kotlinx.coroutines.launch
/**
- * A modifier which connects rotary events with scrollable containers such as Column,
- * LazyList and others. [ScalingLazyColumn] has a build-in rotary support, and accepts
- * [RotaryScrollableBehavior] directly as a parameter.
+ * A modifier which connects rotary events with scrollable containers such as Column, LazyList and
+ * others. [ScalingLazyColumn] has a build-in rotary support, and accepts [RotaryScrollableBehavior]
+ * directly as a parameter.
*
* This modifier handles rotary input devices, used for scrolling. These devices can be categorized
* as high-resolution or low-resolution based on their precision.
+ * - High-res devices: Offer finer control and can detect smaller rotations. This allows for more
+ * precise adjustments during scrolling. One example of a high-res device is the crown (also known
+ * as rotating side button), located on the side of the watch.
+ * - Low-res devices: Have less granular control, registering larger rotations at a time. Scrolling
+ * behavior is adapted to compensate for these larger jumps. Examples include physical or virtual
+ * bezels, positioned around the screen.
*
- * - High-res devices: Offer finer control and can detect smaller rotations.
- * This allows for more precise adjustments during scrolling. One example of a high-res
- * device is the crown (also known as rotating side button), located on the side of the watch.
- * - Low-res devices: Have less granular control, registering larger rotations
- * at a time. Scrolling behavior is adapted to compensate for these larger jumps. Examples
- * include physical or virtual bezels, positioned around the screen.
- *
- * This modifier supports rotary scrolling and snapping.
- * The behaviour is configured by the provided [RotaryScrollableBehavior]:
- * either provide [RotaryScrollableDefaults.behavior] for scrolling with/without fling
- * or pass [RotaryScrollableDefaults.snapBehavior] when snap is required.
+ * This modifier supports rotary scrolling and snapping. The behaviour is configured by the provided
+ * [RotaryScrollableBehavior]: either provide [RotaryScrollableDefaults.behavior] for scrolling
+ * with/without fling or pass [RotaryScrollableDefaults.snapBehavior] when snap is required.
*
* Example of scrolling with fling:
+ *
* @sample androidx.wear.compose.foundation.samples.RotaryScrollSample
*
* Example of scrolling with snap:
+ *
* @sample androidx.wear.compose.foundation.samples.RotarySnapSample
*
* @param behavior Specified [RotaryScrollableBehavior] for rotary handling with snap or fling.
* @param focusRequester Used to request the focus for rotary input. Each composable with this
- * modifier should have a separate focusRequester, and only one of them at a time can be active.
- * We recommend using [rememberActiveFocusRequester] to obtain a FocusRequester, as this
- * will guarantee the proper behavior.
- * @param reverseDirection Reverse the direction of scrolling if required for consistency
- * with the scrollable state passed via [behavior].
+ * modifier should have a separate focusRequester, and only one of them at a time can be active.
+ * We recommend using [rememberActiveFocusRequester] to obtain a FocusRequester, as this will
+ * guarantee the proper behavior.
+ * @param reverseDirection Reverse the direction of scrolling if required for consistency with the
+ * scrollable state passed via [behavior].
*/
fun Modifier.rotaryScrollable(
behavior: RotaryScrollableBehavior,
@@ -104,17 +104,17 @@
reverseDirection: Boolean = false
): Modifier =
rotaryHandler(
- behavior = behavior,
- reverseDirection = reverseDirection,
- )
+ behavior = behavior,
+ reverseDirection = reverseDirection,
+ )
.focusRequester(focusRequester)
.focusTarget()
/**
- * An interface for handling scroll events. Has implementations for handling scroll
- * with/without fling [FlingRotaryScrollableBehavior] and for handling snap
- * [LowResSnapRotaryScrollableBehavior], [HighResSnapRotaryScrollableBehavior] (see
- * [Modifier.rotaryScrollable] for descriptions of low-res and high-res devices).
+ * An interface for handling scroll events. Has implementations for handling scroll with/without
+ * fling [FlingRotaryScrollableBehavior] and for handling snap [LowResSnapRotaryScrollableBehavior],
+ * [HighResSnapRotaryScrollableBehavior] (see [Modifier.rotaryScrollable] for descriptions of
+ * low-res and high-res devices).
*/
interface RotaryScrollableBehavior {
@@ -137,55 +137,47 @@
/**
* A provider which connects scrollableState to a rotary input for snapping scroll actions.
*
- * This interface defines the essential properties and methods required for a scrollable
- * to be controlled by rotary input and perform a snap action.
- *
+ * This interface defines the essential properties and methods required for a scrollable to be
+ * controlled by rotary input and perform a snap action.
*/
interface RotarySnapLayoutInfoProvider {
/**
- * The average size in pixels of an item within the scrollable. This is used to
- * estimate scrolling distances for snapping when responding to rotary input.
+ * The average size in pixels of an item within the scrollable. This is used to estimate
+ * scrolling distances for snapping when responding to rotary input.
*/
val averageItemSize: Float
- /**
- * The index of the item that is closest to the center.
- */
+ /** The index of the item that is closest to the center. */
val currentItemIndex: Int
/**
- * The offset in pixels of the currently centered item from its centered position.
- * This value can be positive or negative.
+ * The offset in pixels of the currently centered item from its centered position. This value
+ * can be positive or negative.
*/
val currentItemOffset: Float
- /**
- * The total number of items within the scrollable
- */
+ /** The total number of items within the scrollable */
val totalItemCount: Int
}
-/**
- * Defaults for rotaryScrollable modifier
- */
+/** Defaults for rotaryScrollable modifier */
object RotaryScrollableDefaults {
/**
* Implementation of [RotaryScrollableBehavior] to define scrolling behaviour with or without
* fling - used with the [rotaryScrollable] modifier when snapping is not required.
*
- * If fling is not required, set [flingBehavior] = null. In that case,
- * flinging will not happen and the scrollable content will
- * stop scrolling immediately after the user stops interacting with rotary input.
+ * If fling is not required, set [flingBehavior] = null. In that case, flinging will not happen
+ * and the scrollable content will stop scrolling immediately after the user stops interacting
+ * with rotary input.
*
- * @param scrollableState Scrollable state which will be scrolled
- * while receiving rotary events.
- * @param flingBehavior Optional rotary fling behavior, pass null to
- * turn off fling if necessary.
+ * @param scrollableState Scrollable state which will be scrolled while receiving rotary events.
+ * @param flingBehavior Optional rotary fling behavior, pass null to turn off fling if
+ * necessary.
* @param hapticFeedbackEnabled Controls whether haptic feedback is given during rotary
- * scrolling (true by default). It's recommended to keep the default value of true
- * for premium scrolling experience.
+ * scrolling (true by default). It's recommended to keep the default value of true for premium
+ * scrolling experience.
*/
@Composable
fun behavior(
@@ -208,18 +200,16 @@
}
/**
- * Implementation of [RotaryScrollableBehavior] to define scrolling behaviour with snap -
- * used with the [rotaryScrollable] modifier when snapping is required.
+ * Implementation of [RotaryScrollableBehavior] to define scrolling behaviour with snap - used
+ * with the [rotaryScrollable] modifier when snapping is required.
*
- * @param scrollableState Scrollable state which will be scrolled
- * while receiving rotary events.
- * @param layoutInfoProvider A connection between scrollable entities
- * and rotary events.
+ * @param scrollableState Scrollable state which will be scrolled while receiving rotary events.
+ * @param layoutInfoProvider A connection between scrollable entities and rotary events.
* @param snapOffset An optional offset to be applied when snapping the item. Defines the
- * distance from the center of the scrollable to the center of the snapped item.
- * @param hapticFeedbackEnabled Controls whether haptic feedback is given during
- * rotary scrolling (true by default). It's recommended to keep the default value of true
- * for premium scrolling experience.
+ * distance from the center of the scrollable to the center of the snapped item.
+ * @param hapticFeedbackEnabled Controls whether haptic feedback is given during rotary
+ * scrolling (true by default). It's recommended to keep the default value of true for premium
+ * scrolling experience.
*/
@Composable
fun snapBehavior(
@@ -231,15 +221,9 @@
val isLowRes = isLowResInput()
val snapOffsetPx = with(LocalDensity.current) { snapOffset.roundToPx() }
val rotaryHaptics: RotaryHapticHandler =
- rememberRotaryHapticHandler(
- scrollableState,
- hapticFeedbackEnabled
- )
+ rememberRotaryHapticHandler(scrollableState, hapticFeedbackEnabled)
- return remember(
- scrollableState, layoutInfoProvider,
- rotaryHaptics, snapOffset, isLowRes
- ) {
+ return remember(scrollableState, layoutInfoProvider, rotaryHaptics, snapOffset, isLowRes) {
snapBehavior(
scrollableState,
layoutInfoProvider,
@@ -258,31 +242,33 @@
*
* @param scrollableState [ScalingLazyListState] to which rotary scroll will be connected.
* @param snapOffset An optional offset to be applied when snapping the item. Defines the
- * distance from the center of the scrollable to the center of the snapped item.
- * @param hapticFeedbackEnabled Controls whether haptic feedback is given during
- * rotary scrolling (true by default). It's recommended to keep the default value of true
- * for premium scrolling experience.
+ * distance from the center of the scrollable to the center of the snapped item.
+ * @param hapticFeedbackEnabled Controls whether haptic feedback is given during rotary
+ * scrolling (true by default). It's recommended to keep the default value of true for premium
+ * scrolling experience.
*/
@Composable
fun snapBehavior(
scrollableState: ScalingLazyListState,
snapOffset: Dp = 0.dp,
hapticFeedbackEnabled: Boolean = true
- ): RotaryScrollableBehavior = snapBehavior(
- scrollableState = scrollableState,
- layoutInfoProvider = remember(scrollableState) {
- ScalingLazyColumnRotarySnapLayoutInfoProvider(scrollableState)
- },
- snapOffset = snapOffset,
- hapticFeedbackEnabled = hapticFeedbackEnabled
- )
+ ): RotaryScrollableBehavior =
+ snapBehavior(
+ scrollableState = scrollableState,
+ layoutInfoProvider =
+ remember(scrollableState) {
+ ScalingLazyColumnRotarySnapLayoutInfoProvider(scrollableState)
+ },
+ snapOffset = snapOffset,
+ hapticFeedbackEnabled = hapticFeedbackEnabled
+ )
- /**
- * Returns whether the input is Low-res (a bezel) or high-res (a crown/rsb).
- */
+ /** Returns whether the input is Low-res (a bezel) or high-res (a crown/rsb). */
@Composable
- private fun isLowResInput(): Boolean = LocalContext.current.packageManager
- .hasSystemFeature("android.hardware.rotaryencoder.lowres")
+ private fun isLowResInput(): Boolean =
+ LocalContext.current.packageManager.hasSystemFeature(
+ "android.hardware.rotaryencoder.lowres"
+ )
private const val ThresholdDivider: Float = 1.5f
private const val ResistanceFactor: Float = 3f
@@ -293,37 +279,27 @@
internal const val HighResFlingTimeframe: Long = 30L
}
-/**
- * An implementation of rotary scroll adapter for ScalingLazyColumn
- */
+/** An implementation of rotary scroll adapter for ScalingLazyColumn */
internal class ScalingLazyColumnRotarySnapLayoutInfoProvider(
private val scrollableState: ScalingLazyListState
) : RotarySnapLayoutInfoProvider {
- /**
- * Calculates the average item height by averaging the height of visible items.
- */
+ /** Calculates the average item height by averaging the height of visible items. */
override val averageItemSize: Float
get() {
val visibleItems = scrollableState.layoutInfo.visibleItemsInfo
return (visibleItems.fastSumBy { it.unadjustedSize } / visibleItems.size).toFloat()
}
- /**
- * Current (centered) item index
- */
+ /** Current (centered) item index */
override val currentItemIndex: Int
get() = scrollableState.centerItemIndex
- /**
- * The offset from the item center.
- */
+ /** The offset from the item center. */
override val currentItemOffset: Float
get() = scrollableState.centerItemScrollOffset.toFloat()
- /**
- * The total count of items in ScalingLazyColumn
- */
+ /** The total count of items in ScalingLazyColumn */
override val totalItemCount: Int
get() = scrollableState.layoutInfo.totalItemsCount
}
@@ -331,14 +307,13 @@
/**
* Handles scroll with fling.
*
- * @return A scroll with fling implementation of [RotaryScrollableBehavior] which is suitable
- * for both low-res and high-res inputs (see [Modifier.rotaryScrollable] for descriptions
- * of low-res and high-res devices).
- *
* @param scrollableState Scrollable state which will be scrolled while receiving rotary events
* @param flingBehavior Logic describing Fling behavior. If null - fling will not happen
* @param isLowRes Whether the input is Low-res (a bezel) or high-res(a crown/rsb)
* @param viewConfiguration [ViewConfiguration] for accessing default fling values
+ * @return A scroll with fling implementation of [RotaryScrollableBehavior] which is suitable for
+ * both low-res and high-res inputs (see [Modifier.rotaryScrollable] for descriptions of low-res
+ * and high-res devices).
*/
private fun flingBehavior(
scrollableState: ScrollableState,
@@ -348,15 +323,17 @@
viewConfiguration: ViewConfiguration
): RotaryScrollableBehavior {
- fun rotaryFlingHandler() = flingBehavior?.run {
- RotaryFlingHandler(
- scrollableState,
- flingBehavior,
- viewConfiguration,
- flingTimeframe = if (isLowRes) RotaryScrollableDefaults.LowResFlingTimeframe
- else RotaryScrollableDefaults.HighResFlingTimeframe
- )
- }
+ fun rotaryFlingHandler() =
+ flingBehavior?.run {
+ RotaryFlingHandler(
+ scrollableState,
+ flingBehavior,
+ viewConfiguration,
+ flingTimeframe =
+ if (isLowRes) RotaryScrollableDefaults.LowResFlingTimeframe
+ else RotaryScrollableDefaults.HighResFlingTimeframe
+ )
+ }
fun scrollHandler() = RotaryScrollHandler(scrollableState)
@@ -371,20 +348,19 @@
/**
* Handles scroll with snap.
*
- * @return A snap implementation of [RotaryScrollableBehavior] which is either suitable for low-res
- * or high-res input (see [Modifier.rotaryScrollable] for descriptions of low-res
- * and high-res devices).
- *
* @param layoutInfoProvider Implementation of [RotarySnapLayoutInfoProvider], which connects
- * scrollableState to a rotary input for snapping scroll actions.
- * @param rotaryHaptics Implementation of [RotaryHapticHandler] which handles haptics
- * for rotary usage
- * @param snapOffset An offset to be applied when snapping the item. After the snap the
- * snapped items offset will be [snapOffset]. In pixels.
+ * scrollableState to a rotary input for snapping scroll actions.
+ * @param rotaryHaptics Implementation of [RotaryHapticHandler] which handles haptics for rotary
+ * usage
+ * @param snapOffset An offset to be applied when snapping the item. After the snap the snapped
+ * items offset will be [snapOffset]. In pixels.
* @param maxThresholdDivider Factor to divide item size when calculating threshold.
- * @param scrollDistanceDivider A value which is used to slow down or
- * speed up the scroll before snap happens. The higher the value the slower the scroll.
+ * @param scrollDistanceDivider A value which is used to slow down or speed up the scroll before
+ * snap happens. The higher the value the slower the scroll.
* @param isLowRes Whether the input is Low-res (a bezel) or high-res(a crown/rsb)
+ * @return A snap implementation of [RotaryScrollableBehavior] which is either suitable for low-res
+ * or high-res input (see [Modifier.rotaryScrollable] for descriptions of low-res and high-res
+ * devices).
*/
private fun snapBehavior(
scrollableState: ScrollableState,
@@ -423,9 +399,7 @@
snapOffset,
)
},
- scrollHandlerFactory = {
- RotaryScrollHandler(scrollableState)
- }
+ scrollHandlerFactory = { RotaryScrollHandler(scrollableState) }
)
}
}
@@ -449,26 +423,20 @@
}
/**
- * This class does a smooth animation when the scroll by N pixels is done.
- * This animation works well on Rsb(high-res) and Bezel(low-res) devices.
+ * This class does a smooth animation when the scroll by N pixels is done. This animation works well
+ * on Rsb(high-res) and Bezel(low-res) devices.
*/
-internal class RotaryScrollHandler(
- private val scrollableState: ScrollableState
-) {
+internal class RotaryScrollHandler(private val scrollableState: ScrollableState) {
private var sequentialAnimation = false
private var scrollAnimation = AnimationState(0f)
private var prevPosition = 0f
private var scrollJob: Job = CompletableDeferred<Unit>()
- /**
- * Produces scroll to [targetValue]
- */
+ /** Produces scroll to [targetValue] */
fun scrollToTarget(coroutineScope: CoroutineScope, targetValue: Float) {
cancelScrollIfActive()
- scrollJob = coroutineScope.async {
- scrollTo(targetValue)
- }
+ scrollJob = coroutineScope.async { scrollTo(targetValue) }
}
fun cancelScrollIfActive() {
@@ -494,9 +462,7 @@
}
}
-/**
- * A helper class for snapping with rotary.
- */
+/** A helper class for snapping with rotary. */
internal class RotarySnapHandler(
private val scrollableState: ScrollableState,
private val layoutInfoProvider: RotarySnapLayoutInfoProvider,
@@ -516,9 +482,9 @@
*
* Snapping is done for current + [moveForElements] items.
*
- * If [sequentialSnap] is true, items are summed up together.
- * For example, if [updateSnapTarget] is called with
- * [moveForElements] = 2, 3, 5 -> then the snapping will happen to current + 10 items
+ * If [sequentialSnap] is true, items are summed up together. For example, if [updateSnapTarget]
+ * is called with [moveForElements] = 2, 3, 5 -> then the snapping will happen to current + 10
+ * items
*
* If [sequentialSnap] is false, then [moveForElements] are not summed up together.
*/
@@ -530,13 +496,10 @@
snapTarget = layoutInfoProvider.currentItemIndex + moveForElements
}
snapTargetUpdated = true
- snapTarget = snapTarget
- .coerceIn(0 until layoutInfoProvider.totalItemCount)
+ snapTarget = snapTarget.coerceIn(0 until layoutInfoProvider.totalItemCount)
}
- /**
- * Performs snapping to the closest item.
- */
+ /** Performs snapping to the closest item. */
suspend fun snapToClosestItem() {
// Perform the snapping animation
scrollableState.scroll(MutatePriority.UserInput) {
@@ -557,20 +520,13 @@
}
}
- /**
- * Returns true if top edge was reached
- */
+ /** Returns true if top edge was reached */
fun topEdgeReached(): Boolean = snapTarget <= 0
- /**
- * Returns true if bottom edge was reached
- */
- fun bottomEdgeReached(): Boolean =
- snapTarget >= layoutInfoProvider.totalItemCount - 1
+ /** Returns true if bottom edge was reached */
+ fun bottomEdgeReached(): Boolean = snapTarget >= layoutInfoProvider.totalItemCount - 1
- /**
- * Performs snapping to the specified in [updateSnapTarget] element
- */
+ /** Performs snapping to the specified in [updateSnapTarget] element */
suspend fun snapToTargetItem() {
if (!sequentialSnap) anim = AnimationState(0f)
@@ -597,10 +553,8 @@
var prevPosition = anim.value
anim.animateTo(
prevPosition + expectedDistance,
- animationSpec = spring(
- stiffness = defaultStiffness,
- visibilityThreshold = 0.1f
- ),
+ animationSpec =
+ spring(stiffness = defaultStiffness, visibilityThreshold = 0.1f),
sequentialAnimation = (anim.velocity != 0f)
) {
// Exit animation if snap target was updated
@@ -620,17 +574,14 @@
return@animateTo
}
- debugLog {
- "centerItemIndex = ${layoutInfoProvider.currentItemIndex}"
- }
+ debugLog { "centerItemIndex = ${layoutInfoProvider.currentItemIndex}" }
if (layoutInfoProvider.currentItemIndex == snapTarget) {
debugLog { "Target is near the centre. Cancelling first animation" }
debugLog {
"scrollableState.centerItemScrollOffset " +
"${layoutInfoProvider.currentItemOffset}"
}
- expectedDistance =
- -layoutInfoProvider.currentItemOffset
+ expectedDistance = -layoutInfoProvider.currentItemOffset
continueFirstScroll = false
cancelAnimation()
return@animateTo
@@ -644,10 +595,8 @@
var prevPosition = anim.value
anim.animateTo(
prevPosition + expectedDistance,
- animationSpec = SpringSpec(
- stiffness = defaultStiffness,
- visibilityThreshold = 0.1f
- ),
+ animationSpec =
+ SpringSpec(stiffness = defaultStiffness, visibilityThreshold = 0.1f),
sequentialAnimation = (anim.velocity != 0f)
) {
// Exit animation if snap target was updated
@@ -666,14 +615,14 @@
val averageSize = layoutInfoProvider.averageItemSize
val indexesDiff = index - layoutInfoProvider.currentItemIndex
debugLog { "Average size $averageSize" }
- return (averageSize * indexesDiff) +
- targetScrollOffset - layoutInfoProvider.currentItemOffset
+ return (averageSize * indexesDiff) + targetScrollOffset -
+ layoutInfoProvider.currentItemOffset
}
}
/**
- * A modifier which handles rotary events.
- * It accepts [RotaryScrollableBehavior] as the input - a class that handles the main scroll logic.
+ * A modifier which handles rotary events. It accepts [RotaryScrollableBehavior] as the input - a
+ * class that handles the main scroll logic.
*/
internal fun Modifier.rotaryHandler(
behavior: RotaryScrollableBehavior,
@@ -683,18 +632,15 @@
properties["behavior"] = behavior
properties["reverseDirection"] = reverseDirection
}
-): Modifier = this then RotaryHandlerElement(
- behavior,
- reverseDirection,
- inspectorInfo
-)
+): Modifier = this then RotaryHandlerElement(behavior, reverseDirection, inspectorInfo)
/**
- * Class responsible for Fling behaviour with rotary.
- * It tracks rotary events and produces fling when necessary.
- * @param flingTimeframe represents a time interval (in milliseconds) used to determine
- * whether a rotary input should trigger a fling. If no new events come during this interval,
- * then the fling is triggered.
+ * Class responsible for Fling behaviour with rotary. It tracks rotary events and produces fling
+ * when necessary.
+ *
+ * @param flingTimeframe represents a time interval (in milliseconds) used to determine whether a
+ * rotary input should trigger a fling. If no new events come during this interval, then the fling
+ * is triggered.
*/
internal class RotaryFlingHandler(
private val scrollableState: ScrollableState,
@@ -722,10 +668,7 @@
private var flingVelocity: Float = 0f
private var flingTimestamp: Long = 0
- /**
- * Starts a new fling tracking session
- * with specified timestamp
- */
+ /** Starts a new fling tracking session with specified timestamp */
fun startFlingTracking(timestamp: Long) {
rotaryVelocityTracker.start(timestamp)
latestEventTimestamp = timestamp
@@ -736,9 +679,7 @@
if (flingJob.isActive) flingJob.cancel()
}
- /**
- * Observing new event within a fling tracking session with new timestamp and delta
- */
+ /** Observing new event within a fling tracking session with new timestamp and delta */
fun observeEvent(timestamp: Long, delta: Float) {
rotaryVelocityTracker.move(timestamp, delta)
latestEventTimestamp = timestamp
@@ -751,9 +692,7 @@
) {
cancelFlingIfActive()
- flingJob = coroutineScope.async {
- trackFling(beforeFling, edgeReached)
- }
+ flingJob = coroutineScope.async { trackFling(beforeFling, edgeReached) }
}
/**
@@ -785,8 +724,9 @@
"Check fling: flingVelocity: $flingVelocity " +
"minFlingSpeed: $minFlingSpeed, maxFlingSpeed: $maxFlingSpeed"
}
- if (latestEventTimestamp - flingTimestamp < timeRangeToFling &&
- abs(flingVelocity) > minFlingSpeed
+ if (
+ latestEventTimestamp - flingTimestamp < timeRangeToFling &&
+ abs(flingVelocity) > minFlingSpeed
) {
// Call beforeFling because a fling will be performed
beforeFling()
@@ -806,13 +746,12 @@
}
/**
- * A scroll behavior for scrolling without snapping and with or without fling.
- * A list is scrolled by the number of pixels received from the rotary device.
+ * A scroll behavior for scrolling without snapping and with or without fling. A list is scrolled by
+ * the number of pixels received from the rotary device.
*
- * For a high-res input it has a filtering for events which are coming
- * with an opposite sign (this might happen to devices with rsb,
- * especially at the end of the scroll ) - see [Modifier.rotaryScrollable] for descriptions
- * of low-res and high-res devices.
+ * For a high-res input it has a filtering for events which are coming with an opposite sign (this
+ * might happen to devices with rsb, especially at the end of the scroll ) - see
+ * [Modifier.rotaryScrollable] for descriptions of low-res and high-res devices.
*
* This scroll behavior supports fling. It can be set with [RotaryFlingHandler].
*/
@@ -864,9 +803,7 @@
debugLog { "Calling beforeFling section" }
resetScrolling()
},
- edgeReached = { velocity ->
- rotaryHaptics.handleLimitHaptic(velocity > 0f)
- }
+ edgeReached = { velocity -> rotaryHaptics.handleLimitHaptic(velocity > 0f) }
)
}
@@ -883,16 +820,15 @@
}
private fun isOppositeValueAfterScroll(delta: Float): Boolean =
- rotaryScrollDistance * delta < 0f &&
- (abs(delta) < abs(rotaryScrollDistance))
+ rotaryScrollDistance * delta < 0f && (abs(delta) < abs(rotaryScrollDistance))
}
/**
* A scroll behavior for RSB(high-res) input with snapping and without fling (see
* [Modifier.rotaryScrollable] for descriptions of low-res and high-res devices ).
*
- * Threshold for snapping is set dynamically in ThresholdBehavior, which depends
- * on the scroll speed and the average size of the items.
+ * Threshold for snapping is set dynamically in ThresholdBehavior, which depends on the scroll speed
+ * and the average size of the items.
*
* This scroll handler doesn't support fling.
*/
@@ -959,8 +895,10 @@
// We limit a number of handled snap items per event to [maxSnapsPerEvent],
// as otherwise the snap might happen too quickly
- val snapDistanceInItems = (accumulatedSnapDelta / snapThreshold).toInt()
- .coerceIn(-maxSnapsPerEvent..maxSnapsPerEvent)
+ val snapDistanceInItems =
+ (accumulatedSnapDelta / snapThreshold)
+ .toInt()
+ .coerceIn(-maxSnapsPerEvent..maxSnapsPerEvent)
accumulatedSnapDelta -= snapThreshold * snapDistanceInItems
//
val sequentialSnap = snapJob.isActive
@@ -977,16 +915,17 @@
snapHandler.updateSnapTarget(snapDistanceInItems, sequentialSnap)
if (!snapJob.isActive) {
snapJob.cancel()
- snapJob = with(this) {
- async {
- debugLog { "Snap started" }
- try {
- snapHandler.snapToTargetItem()
- } finally {
- debugLog { "Snap called finally" }
+ snapJob =
+ with(this) {
+ async {
+ debugLog { "Snap started" }
+ try {
+ snapHandler.snapToTargetItem()
+ } finally {
+ debugLog { "Snap called finally" }
+ }
}
}
- }
}
rotaryScrollDistance = 0f
} else {
@@ -1002,22 +941,17 @@
snapHandler.updateSnapTarget(0, false)
snapJob.cancel()
- snapJob = with(this) {
- async {
- snapHandler.snapToClosestItem()
- }
- }
+ snapJob = with(this) { async { snapHandler.snapToClosestItem() } }
}
}
}
/**
- * Calculates a value based on the rotaryScrollDistance and size of snapThreshold.
- * The closer rotaryScrollDistance to snapThreshold, the lower the value.
+ * Calculates a value based on the rotaryScrollDistance and size of snapThreshold. The closer
+ * rotaryScrollDistance to snapThreshold, the lower the value.
*/
private fun calculateProximityFactor(snapThreshold: Float): Float =
- 1 - scrollProximityEasing
- .transform(rotaryScrollDistance.absoluteValue / snapThreshold)
+ 1 - scrollProximityEasing.transform(rotaryScrollDistance.absoluteValue / snapThreshold)
private fun edgeNotReached(snapDistanceInItems: Int): Boolean =
(!snapHandler.topEdgeReached() && snapDistanceInItems < 0) ||
@@ -1041,8 +975,7 @@
}
private fun isOppositeValueAfterScroll(delta: Float): Boolean =
- rotaryScrollDistance * delta < 0f &&
- (abs(delta) < abs(rotaryScrollDistance))
+ rotaryScrollDistance * delta < 0f && (abs(delta) < abs(rotaryScrollDistance))
}
/**
@@ -1095,16 +1028,17 @@
snapHandler.updateSnapTarget(snapDistanceInItems, sequentialSnap)
if (!snapJob.isActive) {
snapJob.cancel()
- snapJob = with(this) {
- async {
- debugLog { "Snap started" }
- try {
- snapHandler.snapToTargetItem()
- } finally {
- debugLog { "Snap called finally" }
+ snapJob =
+ with(this) {
+ async {
+ debugLog { "Snap started" }
+ try {
+ snapHandler.snapToTargetItem()
+ } finally {
+ debugLog { "Snap called finally" }
+ }
}
}
- }
}
accumulatedSnapDelta = 0f
}
@@ -1118,13 +1052,13 @@
}
/**
- * This class is responsible for determining the dynamic 'snapping' threshold.
- * The threshold dictates how much rotary input is required to trigger a snapping action.
+ * This class is responsible for determining the dynamic 'snapping' threshold. The threshold
+ * dictates how much rotary input is required to trigger a snapping action.
*
- * The threshold is calculated dynamically based on the user's scroll input velocity.
- * Faster scrolling results in a lower threshold, making snapping easier to achieve.
- * An exponential smoothing is also applied to the velocity readings to reduce noise
- * and provide more consistent threshold calculations.
+ * The threshold is calculated dynamically based on the user's scroll input velocity. Faster
+ * scrolling results in a lower threshold, making snapping easier to achieve. An exponential
+ * smoothing is also applied to the velocity readings to reduce noise and provide more consistent
+ * threshold calculations.
*/
internal class ThresholdHandler(
// Factor to divide item size when calculating threshold.
@@ -1145,17 +1079,15 @@
private var smoothedVelocity = 0f
/**
- * Resets tracking state in preparation for a new scroll event.
- * Initiates the velocity tracker and resets smoothed velocity.
+ * Resets tracking state in preparation for a new scroll event. Initiates the velocity tracker
+ * and resets smoothed velocity.
*/
fun startThresholdTracking(time: Long) {
rotaryVelocityTracker.start(time)
smoothedVelocity = 0f
}
- /**
- * Updates the velocity tracker with the latest rotary input data.
- */
+ /** Updates the velocity tracker with the latest rotary input data. */
fun updateTracking(timestamp: Long, delta: Float) {
rotaryVelocityTracker.move(timestamp, delta)
applySmoothing()
@@ -1170,33 +1102,26 @@
// Calculate a divider fraction based on the smoothedVelocity within the defined range.
val thresholdDividerFraction =
thresholdDividerEasing.transform(
- inverseLerp(
- minVelocity,
- maxVelocity,
- smoothedVelocity
- )
+ inverseLerp(minVelocity, maxVelocity, smoothedVelocity)
)
// Calculate the final threshold size by dividing the average item size by a dynamically
// adjusted threshold divider.
- return averageItemSize() / lerp(
- 1f,
- maxThresholdDivider,
- thresholdDividerFraction
- )
+ return averageItemSize() / lerp(1f, maxThresholdDivider, thresholdDividerFraction)
}
/**
- * Applies exponential smoothing to the tracked velocity to reduce noise
- * and provide more consistent threshold calculations.
+ * Applies exponential smoothing to the tracked velocity to reduce noise and provide more
+ * consistent threshold calculations.
*/
private fun applySmoothing() {
if (rotaryVelocityTracker.velocity != 0.0f) {
// smooth the velocity
- smoothedVelocity = exponentialSmoothing(
- currentVelocity = rotaryVelocityTracker.velocity.absoluteValue,
- prevVelocity = smoothedVelocity,
- smoothingConstant = smoothingConstant
- )
+ smoothedVelocity =
+ exponentialSmoothing(
+ currentVelocity = rotaryVelocityTracker.velocity.absoluteValue,
+ prevVelocity = smoothedVelocity,
+ smoothingConstant = smoothingConstant
+ )
}
debugLog { "rotaryVelocityTracker velocity: ${rotaryVelocityTracker.velocity}" }
debugLog { "SmoothedVelocity: $smoothedVelocity" }
@@ -1206,8 +1131,7 @@
currentVelocity: Float,
prevVelocity: Float,
smoothingConstant: Float
- ): Float =
- smoothingConstant * currentVelocity + (1 - smoothingConstant) * prevVelocity
+ ): Float = smoothingConstant * currentVelocity + (1 - smoothingConstant) * prevVelocity
}
private data class RotaryHandlerElement(
@@ -1215,10 +1139,11 @@
private val reverseDirection: Boolean,
private val inspectorInfo: InspectorInfo.() -> Unit
) : ModifierNodeElement<RotaryInputNode>() {
- override fun create(): RotaryInputNode = RotaryInputNode(
- behavior,
- reverseDirection,
- )
+ override fun create(): RotaryInputNode =
+ RotaryInputNode(
+ behavior,
+ reverseDirection,
+ )
override fun update(node: RotaryInputNode) {
debugLog { "Update launched!" }
@@ -1259,26 +1184,24 @@
override fun onAttach() {
coroutineScope.launch {
- flow
- .collectLatest { event ->
- val (orientation: Orientation, deltaInPixels: Float) =
- if (event.verticalScrollPixels != 0.0f)
- Pair(Orientation.Vertical, event.verticalScrollPixels)
- else
- Pair(Orientation.Horizontal, event.horizontalScrollPixels)
- debugLog {
- "Scroll event received: " +
- "delta:$deltaInPixels, timestamp:${event.uptimeMillis}"
- }
- with(behavior) {
- performScroll(
- timestampMillis = event.uptimeMillis,
- delta = deltaInPixels * if (reverseDirection) -1f else 1f,
- inputDeviceId = event.inputDeviceId,
- orientation = orientation,
- )
- }
+ flow.collectLatest { event ->
+ val (orientation: Orientation, deltaInPixels: Float) =
+ if (event.verticalScrollPixels != 0.0f)
+ Pair(Orientation.Vertical, event.verticalScrollPixels)
+ else Pair(Orientation.Horizontal, event.horizontalScrollPixels)
+ debugLog {
+ "Scroll event received: " +
+ "delta:$deltaInPixels, timestamp:${event.uptimeMillis}"
}
+ with(behavior) {
+ performScroll(
+ timestampMillis = event.uptimeMillis,
+ delta = deltaInPixels * if (reverseDirection) -1f else 1f,
+ inputDeviceId = event.inputDeviceId,
+ orientation = orientation,
+ )
+ }
+ }
}
}
@@ -1291,9 +1214,7 @@
}
}
-/**
- * Debug logging that can be enabled.
- */
+/** Debug logging that can be enabled. */
private const val DEBUG = false
private inline fun debugLog(generateMsg: () -> String) {
diff --git a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/rotary/RotaryVelocityTracker.kt b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/rotary/RotaryVelocityTracker.kt
index d9bf1f9..21de8e0 100644
--- a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/rotary/RotaryVelocityTracker.kt
+++ b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/rotary/RotaryVelocityTracker.kt
@@ -18,36 +18,26 @@
import androidx.compose.ui.input.pointer.util.VelocityTracker1D
-/**
- * A wrapper around VelocityTracker1D to provide support for rotary input.
- */
+/** A wrapper around VelocityTracker1D to provide support for rotary input. */
internal class RotaryVelocityTracker {
private var velocityTracker: VelocityTracker1D = VelocityTracker1D(true)
- /**
- * Retrieve the last computed velocity.
- */
+ /** Retrieve the last computed velocity. */
val velocity: Float
get() = velocityTracker.calculateVelocity()
- /**
- * Start tracking motion.
- */
+ /** Start tracking motion. */
fun start(currentTime: Long) {
velocityTracker.resetTracking()
velocityTracker.addDataPoint(currentTime, 0f)
}
- /**
- * Continue tracking motion as the input rotates.
- */
+ /** Continue tracking motion as the input rotates. */
fun move(currentTime: Long, delta: Float) {
velocityTracker.addDataPoint(currentTime, delta)
}
- /**
- * Stop tracking motion.
- */
+ /** Stop tracking motion. */
fun end() {
velocityTracker.resetTracking()
}
diff --git a/wear/compose/compose-foundation/src/test/kotlin/androidx/wear/compose/foundation/rotary/HapticsTest.kt b/wear/compose/compose-foundation/src/test/kotlin/androidx/wear/compose/foundation/rotary/HapticsTest.kt
index da6eb40..ed52c17 100644
--- a/wear/compose/compose-foundation/src/test/kotlin/androidx/wear/compose/foundation/rotary/HapticsTest.kt
+++ b/wear/compose/compose-foundation/src/test/kotlin/androidx/wear/compose/foundation/rotary/HapticsTest.kt
@@ -44,10 +44,7 @@
@Before
fun before() {
- testChannel = Channel(
- capacity = 10,
- onBufferOverflow = BufferOverflow.DROP_OLDEST
- )
+ testChannel = Channel(capacity = 10, onBufferOverflow = BufferOverflow.DROP_OLDEST)
}
@Test
diff --git a/wear/compose/compose-foundation/src/test/kotlin/androidx/wear/compose/foundation/rotary/RotaryTest.kt b/wear/compose/compose-foundation/src/test/kotlin/androidx/wear/compose/foundation/rotary/RotaryTest.kt
index 77cb843..666080e 100644
--- a/wear/compose/compose-foundation/src/test/kotlin/androidx/wear/compose/foundation/rotary/RotaryTest.kt
+++ b/wear/compose/compose-foundation/src/test/kotlin/androidx/wear/compose/foundation/rotary/RotaryTest.kt
@@ -27,9 +27,7 @@
@Test
fun testMinVelocityThreshold() {
val itemHeight = 100f
- val thresholdHandler = ThresholdHandler(
- 2.0f,
- averageItemSize = { itemHeight })
+ val thresholdHandler = ThresholdHandler(2.0f, averageItemSize = { itemHeight })
thresholdHandler.startThresholdTracking(0L)
// Simulate very slow scroll
@@ -44,9 +42,7 @@
fun testMaxVelocityThreshold() {
val itemHeight = 100f
val thresholdDivider = 2.0f
- val thresholdHandler = ThresholdHandler(
- thresholdDivider,
- averageItemSize = { itemHeight })
+ val thresholdHandler = ThresholdHandler(thresholdDivider, averageItemSize = { itemHeight })
thresholdHandler.startThresholdTracking(0L)
// Simulate very fast scroll
diff --git a/wear/compose/compose-material-core/src/androidTest/kotlin/androidx/wear/compose/materialcore/IconTest.kt b/wear/compose/compose-material-core/src/androidTest/kotlin/androidx/wear/compose/materialcore/IconTest.kt
index 7f9826e..d4694264 100644
--- a/wear/compose/compose-material-core/src/androidTest/kotlin/androidx/wear/compose/materialcore/IconTest.kt
+++ b/wear/compose/compose-material-core/src/androidTest/kotlin/androidx/wear/compose/materialcore/IconTest.kt
@@ -60,8 +60,7 @@
@LargeTest
@RunWith(AndroidJUnit4::class)
class IconTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
@Test
fun vector_materialIconSize_dimensions() {
@@ -83,10 +82,14 @@
fun vector_customIconSize_dimensions() {
val width = 35.dp
val height = 83.dp
- val vector = ImageVector.Builder(
- defaultWidth = width, defaultHeight = height,
- viewportWidth = width.value, viewportHeight = height.value
- ).build()
+ val vector =
+ ImageVector.Builder(
+ defaultWidth = width,
+ defaultHeight = height,
+ viewportWidth = width.value,
+ viewportHeight = height.value
+ )
+ .build()
rule
.setContentForSizeAssertions {
IconWithDefaults(
@@ -104,14 +107,12 @@
val height = 24.dp
rule
.setContentForSizeAssertions {
- val image = with(LocalDensity.current) {
- ImageBitmap(width.roundToPx(), height.roundToPx())
- }
+ val image =
+ with(LocalDensity.current) {
+ ImageBitmap(width.roundToPx(), height.roundToPx())
+ }
val painter = remember(image) { BitmapPainter(image) }
- IconWithDefaults(
- painter = painter,
- contentDescription = null
- )
+ IconWithDefaults(painter = painter, contentDescription = null)
}
.assertWidthIsEqualTo(width)
.assertHeightIsEqualTo(height)
@@ -124,14 +125,12 @@
rule
.setContentForSizeAssertions {
- val image = with(LocalDensity.current) {
- ImageBitmap(width.roundToPx(), height.roundToPx())
- }
+ val image =
+ with(LocalDensity.current) {
+ ImageBitmap(width.roundToPx(), height.roundToPx())
+ }
val painter = remember(image) { BitmapPainter(image) }
- IconWithDefaults(
- painter = painter,
- contentDescription = null
- )
+ IconWithDefaults(painter = painter, contentDescription = null)
}
.assertWidthIsEqualTo(width)
.assertHeightIsEqualTo(height)
@@ -144,10 +143,7 @@
val painter = ColorPainter(Color.Red)
rule
.setContentForSizeAssertions {
- IconWithDefaults(
- painter = painter,
- contentDescription = null
- )
+ IconWithDefaults(painter = painter, contentDescription = null)
}
.assertWidthIsEqualTo(width)
.assertHeightIsEqualTo(height)
@@ -160,15 +156,13 @@
rule
.setContentForSizeAssertions {
- val image = with(LocalDensity.current) {
- ImageBitmap(width.roundToPx(), height.roundToPx())
- }
+ val image =
+ with(LocalDensity.current) {
+ ImageBitmap(width.roundToPx(), height.roundToPx())
+ }
val bitmapPainter = BitmapPainter(image)
- IconWithDefaults(
- painter = bitmapPainter,
- contentDescription = null
- )
+ IconWithDefaults(painter = bitmapPainter, contentDescription = null)
}
.assertWidthIsEqualTo(width)
.assertHeightIsEqualTo(height)
@@ -184,20 +178,14 @@
rule.setContent {
val image: ImageBitmap
with(LocalDensity.current) {
- image = createBitmapWithColor(
- this,
- width.roundToPx(),
- height.roundToPx(),
- Color.Red
- )
+ image =
+ createBitmapWithColor(this, width.roundToPx(), height.roundToPx(), Color.Red)
}
val painter = remember(image) { BitmapPainter(image) }
IconWithDefaults(
painter = painter,
contentDescription = null,
- modifier = Modifier
- .requiredSize(50.dp)
- .testTag(TEST_TAG),
+ modifier = Modifier.requiredSize(50.dp).testTag(TEST_TAG),
tint = Color.Unspecified
)
@@ -207,12 +195,11 @@
}
}
- rule.onNodeWithTag(TEST_TAG)
+ rule
+ .onNodeWithTag(TEST_TAG)
.captureToImage()
// The icon should be 50x50 and fill the whole size with red pixels
- .assertPixels(expectedSize = expectedIntSize!!) {
- Color.Red
- }
+ .assertPixels(expectedSize = expectedIntSize!!) { Color.Red }
}
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
@@ -223,12 +210,8 @@
rule.setContent {
val image: ImageBitmap
with(LocalDensity.current) {
- image = createBitmapWithColor(
- this,
- width.roundToPx(),
- height.roundToPx(),
- Color.Red
- )
+ image =
+ createBitmapWithColor(this, width.roundToPx(), height.roundToPx(), Color.Red)
}
val painter = remember(image) { BitmapPainter(image) }
IconWithDefaults(
@@ -251,12 +234,8 @@
rule.setContent {
val image: ImageBitmap
with(LocalDensity.current) {
- image = createBitmapWithColor(
- this,
- width.roundToPx(),
- height.roundToPx(),
- Color.Red
- )
+ image =
+ createBitmapWithColor(this, width.roundToPx(), height.roundToPx(), Color.Red)
}
val painter = remember(image) { BitmapPainter(image) }
IconWithDefaults(
@@ -282,7 +261,8 @@
)
}
- rule.onNodeWithTag(TEST_TAG)
+ rule
+ .onNodeWithTag(TEST_TAG)
.assertContentDescriptionEquals("qwerty")
.assert(SemanticsMatcher.expectValue(SemanticsProperties.Role, Role.Image))
}
@@ -295,12 +275,7 @@
): ImageBitmap {
val size = Size(width.toFloat(), height.toFloat())
val image = ImageBitmap(width, height)
- CanvasDrawScope().draw(
- density,
- LayoutDirection.Ltr,
- Canvas(image),
- size
- ) {
+ CanvasDrawScope().draw(density, LayoutDirection.Ltr, Canvas(image), size) {
drawRect(color)
}
return image
diff --git a/wear/compose/compose-material-core/src/androidTest/kotlin/androidx/wear/compose/materialcore/MaterialCoreTest.kt b/wear/compose/compose-material-core/src/androidTest/kotlin/androidx/wear/compose/materialcore/MaterialCoreTest.kt
index b381276..564adec 100644
--- a/wear/compose/compose-material-core/src/androidTest/kotlin/androidx/wear/compose/materialcore/MaterialCoreTest.kt
+++ b/wear/compose/compose-material-core/src/androidTest/kotlin/androidx/wear/compose/materialcore/MaterialCoreTest.kt
@@ -80,13 +80,7 @@
) {
setContent {
CompositionLocalProvider(LocalLayoutDirection provides layoutDirection) {
- Box(
- Modifier
- .padding(padding)
- .background(backgroundColor)
- ) {
- content()
- }
+ Box(Modifier.padding(padding).background(backgroundColor)) { content() }
}
}
@@ -105,14 +99,12 @@
}
internal fun ComposeContentTestRule.verifyHeight(expected: Dp, content: @Composable () -> Unit) {
- setContentForSizeAssertions {
- content()
- }.assertHeightIsEqualTo(expected)
+ setContentForSizeAssertions { content() }.assertHeightIsEqualTo(expected)
}
/**
- * assertContainsColor - uses a threshold on an ImageBitmap's color distribution
- * to check that a UI element is predominantly the expected color.
+ * assertContainsColor - uses a threshold on an ImageBitmap's color distribution to check that a UI
+ * element is predominantly the expected color.
*/
internal fun ImageBitmap.assertContainsColor(expectedColor: Color, minPercent: Float = 50.0f) {
val histogram = histogram()
@@ -141,25 +133,17 @@
internal fun TestImage(modifier: Modifier = Modifier, iconLabel: String = "TestIcon") {
val testImage = Icons.Outlined.Add
Image(
- testImage, iconLabel,
- modifier = modifier
- .fillMaxSize()
- .testTag(iconLabel),
+ testImage,
+ iconLabel,
+ modifier = modifier.fillMaxSize().testTag(iconLabel),
contentScale = ContentScale.Fit,
alignment = Alignment.Center
)
}
@Composable
-internal fun TestText(
- text: String,
- modifier: Modifier = Modifier
-) {
- TextWithDefaults(
- text = AnnotatedString(text),
- modifier = modifier,
- style = TextStyle.Default
- )
+internal fun TestText(text: String, modifier: Modifier = Modifier) {
+ TextWithDefaults(text = AnnotatedString(text), modifier = modifier, style = TextStyle.Default)
}
internal fun ComposeContentTestRule.setContentForSizeAssertions(
@@ -171,11 +155,7 @@
setContent {
Box {
Box(
- Modifier
- .sizeIn(
- maxWidth = parentMaxWidth,
- maxHeight = parentMaxHeight
- )
+ Modifier.sizeIn(maxWidth = parentMaxWidth, maxHeight = parentMaxHeight)
.testTag("containerForSizeAssertion")
) {
content()
diff --git a/wear/compose/compose-material-core/src/androidTest/kotlin/androidx/wear/compose/materialcore/RepeatableClickableTest.kt b/wear/compose/compose-material-core/src/androidTest/kotlin/androidx/wear/compose/materialcore/RepeatableClickableTest.kt
index 895034c..9c61478 100644
--- a/wear/compose/compose-material-core/src/androidTest/kotlin/androidx/wear/compose/materialcore/RepeatableClickableTest.kt
+++ b/wear/compose/compose-material-core/src/androidTest/kotlin/androidx/wear/compose/materialcore/RepeatableClickableTest.kt
@@ -35,15 +35,15 @@
import org.junit.Test
public class RepeatableClickableTest {
- @get:Rule
- public val rule = createComposeRule()
+ @get:Rule public val rule = createComposeRule()
@Test
fun touch_hold_shorter_than_threshold_performs_click() {
var repeatableClickCounter = 0
var clicked = false
- boxWithRepeatableClickable(rule,
+ boxWithRepeatableClickable(
+ rule,
holdDelay = INITIAL_DELAY / 2,
onRepeatableClick = { repeatableClickCounter++ },
onClick = { clicked = true }
@@ -57,7 +57,8 @@
var repeatableClickCounter = 0
var clicked = false
- boxWithRepeatableClickable(rule,
+ boxWithRepeatableClickable(
+ rule,
holdDelay = INITIAL_DELAY,
onRepeatableClick = { repeatableClickCounter++ },
onClick = { clicked = true }
@@ -71,7 +72,8 @@
var repeatableClickCounter = 0
var clicked = false
- boxWithRepeatableClickable(rule,
+ boxWithRepeatableClickable(
+ rule,
holdDelay = INITIAL_DELAY + INCREMENTAL_DELAY * 2,
onRepeatableClick = { repeatableClickCounter++ },
onClick = { clicked = true }
@@ -86,7 +88,8 @@
var repeatableClickCounter = 0
var clicked = false
- boxWithRepeatableClickable(rule,
+ boxWithRepeatableClickable(
+ rule,
holdDelay = INITIAL_DELAY,
enabled = false,
onRepeatableClick = { repeatableClickCounter++ },
@@ -102,7 +105,8 @@
var repeatableClickCounter = 0
var clicked = false
- boxWithRepeatableClickable(rule,
+ boxWithRepeatableClickable(
+ rule,
holdDelay = INITIAL_DELAY / 2,
enabled = true,
releaseOutsideOfBox = true,
@@ -125,24 +129,21 @@
onRepeatableClick: () -> Unit
) {
rule.setContent {
- Box(
- modifier = Modifier
- .fillMaxSize()
- ) {
+ Box(modifier = Modifier.fillMaxSize()) {
Box(
- modifier = Modifier
- .testTag(TEST_TAG)
- .size(50.dp)
- .align(Alignment.Center)
- .repeatableClickable(
- enabled = enabled,
- initialDelay = initialDelay,
- incrementalDelay = incrementalDelay,
- indication = null,
- interactionSource = remember { MutableInteractionSource() },
- onClick = onClick,
- onRepeatableClick = onRepeatableClick
- )
+ modifier =
+ Modifier.testTag(TEST_TAG)
+ .size(50.dp)
+ .align(Alignment.Center)
+ .repeatableClickable(
+ enabled = enabled,
+ initialDelay = initialDelay,
+ incrementalDelay = incrementalDelay,
+ indication = null,
+ interactionSource = remember { MutableInteractionSource() },
+ onClick = onClick,
+ onRepeatableClick = onRepeatableClick
+ )
) {}
}
}
diff --git a/wear/compose/compose-material-core/src/androidTest/kotlin/androidx/wear/compose/materialcore/RoundButtonTest.kt b/wear/compose/compose-material-core/src/androidTest/kotlin/androidx/wear/compose/materialcore/RoundButtonTest.kt
index 31a9ecd..58ff8e7 100644
--- a/wear/compose/compose-material-core/src/androidTest/kotlin/androidx/wear/compose/materialcore/RoundButtonTest.kt
+++ b/wear/compose/compose-material-core/src/androidTest/kotlin/androidx/wear/compose/materialcore/RoundButtonTest.kt
@@ -61,16 +61,14 @@
import org.junit.Test
class RoundButtonTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
@Test
fun supports_testtag_on_button() {
rule.setContent {
RoundButtonWithDefaults(
modifier = Modifier.testTag(TEST_TAG),
- ) {
- }
+ ) {}
}
rule.onNodeWithTag(TEST_TAG).assertExists()
@@ -79,11 +77,7 @@
@Test
fun has_clickaction_when_enabled() {
rule.setContent {
- RoundButtonWithDefaults(
- enabled = true,
- modifier = Modifier.testTag(TEST_TAG)
- ) {
- }
+ RoundButtonWithDefaults(enabled = true, modifier = Modifier.testTag(TEST_TAG)) {}
}
rule.onNodeWithTag(TEST_TAG).assertHasClickAction()
@@ -92,11 +86,7 @@
@Test
fun has_clickaction_when_disabled() {
rule.setContent {
- RoundButtonWithDefaults(
- enabled = false,
- modifier = Modifier.testTag(TEST_TAG)
- ) {
- }
+ RoundButtonWithDefaults(enabled = false, modifier = Modifier.testTag(TEST_TAG)) {}
}
rule.onNodeWithTag(TEST_TAG).assertHasClickAction()
@@ -105,11 +95,7 @@
@Test
fun is_correctly_enabled() {
rule.setContent {
- RoundButtonWithDefaults(
- enabled = true,
- modifier = Modifier.testTag(TEST_TAG)
- ) {
- }
+ RoundButtonWithDefaults(enabled = true, modifier = Modifier.testTag(TEST_TAG)) {}
}
rule.onNodeWithTag(TEST_TAG).assertIsEnabled()
@@ -118,11 +104,7 @@
@Test
fun is_correctly_disabled() {
rule.setContent {
- RoundButtonWithDefaults(
- enabled = false,
- modifier = Modifier.testTag(TEST_TAG)
- ) {
- }
+ RoundButtonWithDefaults(enabled = false, modifier = Modifier.testTag(TEST_TAG)) {}
}
rule.onNodeWithTag(TEST_TAG).assertIsNotEnabled()
@@ -137,15 +119,12 @@
onClick = { clicked = true },
enabled = true,
modifier = Modifier.testTag(TEST_TAG)
- ) {
- }
+ ) {}
}
rule.onNodeWithTag(TEST_TAG).performClick()
- rule.runOnIdle {
- assertEquals(true, clicked)
- }
+ rule.runOnIdle { assertEquals(true, clicked) }
}
@Test
@@ -157,33 +136,21 @@
onClick = { clicked = true },
enabled = false,
modifier = Modifier.testTag(TEST_TAG)
- ) {
- }
+ ) {}
}
rule.onNodeWithTag(TEST_TAG).performClick()
- rule.runOnIdle {
- assertEquals(false, clicked)
- }
+ rule.runOnIdle { assertEquals(false, clicked) }
}
@Test
fun has_role_button_for_button() {
- rule.setContent {
- RoundButtonWithDefaults(
- modifier = Modifier.testTag(TEST_TAG)
- ) {
- }
- }
+ rule.setContent { RoundButtonWithDefaults(modifier = Modifier.testTag(TEST_TAG)) {} }
- rule.onNodeWithTag(TEST_TAG)
- .assert(
- SemanticsMatcher.expectValue(
- SemanticsProperties.Role,
- Role.Button
- )
- )
+ rule
+ .onNodeWithTag(TEST_TAG)
+ .assert(SemanticsMatcher.expectValue(SemanticsProperties.Role, Role.Button))
}
@Test
@@ -191,8 +158,7 @@
rule.isShape(CircleShape, LayoutDirection.Ltr) {
RoundButtonWithDefaults(
modifier = Modifier.testTag(TEST_TAG),
- ) {
- }
+ ) {}
}
@Test
@@ -200,56 +166,34 @@
rule.isShape(CircleShape, LayoutDirection.Rtl) {
RoundButtonWithDefaults(
modifier = Modifier.testTag(TEST_TAG),
- ) {
- }
+ ) {}
}
@Test
fun extra_small_button_meets_accessibility_tapsize() {
verifyTapSize(48.dp) {
- RoundButtonWithDefaults(
- modifier = Modifier
- .testTag(TEST_TAG)
- .size(32.dp)
- ) {
- }
+ RoundButtonWithDefaults(modifier = Modifier.testTag(TEST_TAG).size(32.dp)) {}
}
}
@Test
fun extra_small_button_has_correct_visible_size() {
verifyVisibleSize(32.dp) {
- RoundButtonWithDefaults(
- modifier = Modifier
- .testTag(TEST_TAG)
- .requiredSize(32.dp)
- ) {
- }
+ RoundButtonWithDefaults(modifier = Modifier.testTag(TEST_TAG).requiredSize(32.dp)) {}
}
}
@Test
fun default_button_has_correct_tapsize() {
// Tap size for Button should be the min button size.
- verifyTapSize(52.dp) {
- RoundButtonWithDefaults(
- modifier = Modifier
- .testTag(TEST_TAG)
- ) {
- }
- }
+ verifyTapSize(52.dp) { RoundButtonWithDefaults(modifier = Modifier.testTag(TEST_TAG)) {} }
}
@Test
fun default_button_has_correct_visible_size() {
// Tap size for Button should be the min button size.
verifyVisibleSize(52.dp) {
- RoundButtonWithDefaults(
- modifier = Modifier
- .testTag(TEST_TAG)
- .size(52.dp)
- ) {
- }
+ RoundButtonWithDefaults(modifier = Modifier.testTag(TEST_TAG).size(52.dp)) {}
}
}
@@ -258,11 +202,7 @@
val shape = CutCornerShape(4.dp)
rule.isShape(shape, LayoutDirection.Ltr) {
- RoundButtonWithDefaults(
- shape = shape,
- modifier = Modifier.testTag(TEST_TAG)
- ) {
- }
+ RoundButtonWithDefaults(shape = shape, modifier = Modifier.testTag(TEST_TAG)) {}
}
}
@@ -327,18 +267,11 @@
) {
val testBackground = Color.White
val expectedColor = { color: Color ->
- if (color != Color.Transparent)
- color.compositeOver(testBackground)
- else
- testBackground
+ if (color != Color.Transparent) color.compositeOver(testBackground) else testBackground
}
rule.setContent {
- Box(
- modifier = Modifier
- .fillMaxSize()
- .background(testBackground)
- ) {
+ Box(modifier = Modifier.fillMaxSize().background(testBackground)) {
RoundButtonWithDefaults(
backgroundColor = { enabled ->
if (enabled) enabledBackgroundColor else disabledBackgroundColor
@@ -348,43 +281,33 @@
},
enabled = status.enabled(),
modifier = Modifier.testTag(TEST_TAG)
- ) {
- }
+ ) {}
}
}
- rule.onNodeWithTag(TEST_TAG)
+ rule
+ .onNodeWithTag(TEST_TAG)
.captureToImage()
.assertContainsColor(expectedColor(expectedBackgroundColor), backgroundThreshold)
- rule.onNodeWithTag(TEST_TAG)
+ rule
+ .onNodeWithTag(TEST_TAG)
.captureToImage()
.assertContainsColor(expectedColor(expectedBorderColor), borderThreshold)
}
- private fun verifyTapSize(
- expected: Dp,
- content: @Composable () -> Unit
- ) {
- rule.setContent {
- content()
- }
+ private fun verifyTapSize(expected: Dp, content: @Composable () -> Unit) {
+ rule.setContent { content() }
- rule.onNodeWithTag(TEST_TAG)
+ rule
+ .onNodeWithTag(TEST_TAG)
.assertTouchHeightIsEqualTo(expected)
.assertTouchWidthIsEqualTo(expected)
}
- private fun verifyVisibleSize(
- expected: Dp,
- content: @Composable () -> Unit
- ) {
- rule.setContent {
- content()
- }
+ private fun verifyVisibleSize(expected: Dp, content: @Composable () -> Unit) {
+ rule.setContent { content() }
- rule.onNodeWithTag(TEST_TAG)
- .assertHeightIsEqualTo(expected)
- .assertWidthIsEqualTo(expected)
+ rule.onNodeWithTag(TEST_TAG).assertHeightIsEqualTo(expected).assertWidthIsEqualTo(expected)
}
@Composable
@@ -397,18 +320,19 @@
shape: Shape = CircleShape,
border: @Composable (enabled: Boolean) -> BorderStroke? = { null },
content: @Composable BoxScope.() -> Unit
- ) = RoundButton(
- onClick = onClick,
- modifier = modifier,
- enabled = enabled,
- backgroundColor = backgroundColor,
- interactionSource = interactionSource,
- shape = shape,
- border = border,
- buttonSize = 52.dp,
- ripple = EmptyIndication,
- content = content
- )
+ ) =
+ RoundButton(
+ onClick = onClick,
+ modifier = modifier,
+ enabled = enabled,
+ backgroundColor = backgroundColor,
+ interactionSource = interactionSource,
+ shape = shape,
+ border = border,
+ buttonSize = 52.dp,
+ ripple = EmptyIndication,
+ content = content
+ )
}
internal object EmptyIndication : IndicationNodeFactory {
diff --git a/wear/compose/compose-material-core/src/androidTest/kotlin/androidx/wear/compose/materialcore/SelectionControlsTest.kt b/wear/compose/compose-material-core/src/androidTest/kotlin/androidx/wear/compose/materialcore/SelectionControlsTest.kt
index 50772ba..82d7bd5 100644
--- a/wear/compose/compose-material-core/src/androidTest/kotlin/androidx/wear/compose/materialcore/SelectionControlsTest.kt
+++ b/wear/compose/compose-material-core/src/androidTest/kotlin/androidx/wear/compose/materialcore/SelectionControlsTest.kt
@@ -61,8 +61,7 @@
import org.junit.Test
class SelectionControlsTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
// Checkbox colors
private val boxColorChecked = Color.Green
@@ -105,9 +104,7 @@
@Test
fun checkbox_supports_testtag() {
rule.setContent {
- CheckboxWithDefaults(
- checked = true, modifier = Modifier.testTag(TEST_TAG)
- )
+ CheckboxWithDefaults(checked = true, modifier = Modifier.testTag(TEST_TAG))
}
rule.onNodeWithTag(TEST_TAG).assertExists()
@@ -118,29 +115,32 @@
val width = 32.dp
val height = 26.dp
- rule.setContentForSizeAssertions {
- CheckboxWithDefaults(
- checked = true,
- modifier = Modifier.testTag(TEST_TAG),
- width = width,
- height = height
- )
- }.assertHeightIsEqualTo(height).assertWidthIsEqualTo(width)
+ rule
+ .setContentForSizeAssertions {
+ CheckboxWithDefaults(
+ checked = true,
+ modifier = Modifier.testTag(TEST_TAG),
+ width = width,
+ height = height
+ )
+ }
+ .assertHeightIsEqualTo(height)
+ .assertWidthIsEqualTo(width)
}
@Test
fun checkbox_has_role_checkbox_when_oncheckedchange_defined() {
rule.setContent {
CheckboxWithDefaults(
- checked = true, onCheckedChange = {}, modifier = Modifier.testTag(TEST_TAG)
+ checked = true,
+ onCheckedChange = {},
+ modifier = Modifier.testTag(TEST_TAG)
)
}
- rule.onNodeWithTag(TEST_TAG).assert(
- SemanticsMatcher.expectValue(
- SemanticsProperties.Role, Role.Checkbox
- )
- )
+ rule
+ .onNodeWithTag(TEST_TAG)
+ .assert(SemanticsMatcher.expectValue(SemanticsProperties.Role, Role.Checkbox))
}
@Test
@@ -149,26 +149,22 @@
CheckboxWithDefaults(
checked = true,
onCheckedChange = {},
- modifier = Modifier
- .testTag(TEST_TAG)
- .semantics {
- role = Role.Image
- }
+ modifier = Modifier.testTag(TEST_TAG).semantics { role = Role.Image }
)
}
- rule.onNodeWithTag(TEST_TAG).assert(
- SemanticsMatcher.expectValue(
- SemanticsProperties.Role, Role.Image
- )
- )
+ rule
+ .onNodeWithTag(TEST_TAG)
+ .assert(SemanticsMatcher.expectValue(SemanticsProperties.Role, Role.Image))
}
@Test
fun checkbox_has_no_clickaction_by_default() {
rule.setContent {
CheckboxWithDefaults(
- checked = true, enabled = true, modifier = Modifier.testTag(TEST_TAG)
+ checked = true,
+ enabled = true,
+ modifier = Modifier.testTag(TEST_TAG)
)
}
@@ -207,7 +203,9 @@
fun checkbox_is_correctly_enabled() {
rule.setContent {
CheckboxWithDefaults(
- checked = true, enabled = true, modifier = Modifier.testTag(TEST_TAG)
+ checked = true,
+ enabled = true,
+ modifier = Modifier.testTag(TEST_TAG)
)
}
@@ -234,7 +232,9 @@
// This test only applies when onCheckedChange is defined.
rule.setContent {
CheckboxWithDefaults(
- checked = true, onCheckedChange = {}, modifier = Modifier.testTag(TEST_TAG)
+ checked = true,
+ onCheckedChange = {},
+ modifier = Modifier.testTag(TEST_TAG)
)
}
@@ -246,7 +246,9 @@
// This test only applies when onCheckedChange is defined.
rule.setContent {
CheckboxWithDefaults(
- checked = false, onCheckedChange = {}, modifier = Modifier.testTag(TEST_TAG)
+ checked = false,
+ onCheckedChange = {},
+ modifier = Modifier.testTag(TEST_TAG)
)
}
@@ -265,8 +267,7 @@
)
}
- rule.onNodeWithTag(TEST_TAG).assertIsOff().performClick()
- .assertIsOn()
+ rule.onNodeWithTag(TEST_TAG).assertIsOff().performClick().assertIsOn()
}
@Test
@@ -281,8 +282,7 @@
)
}
- rule.onNodeWithTag(TEST_TAG).assertIsOn().performClick()
- .assertIsOff()
+ rule.onNodeWithTag(TEST_TAG).assertIsOn().performClick().assertIsOff()
}
@RequiresApi(Build.VERSION_CODES.O)
@@ -313,10 +313,7 @@
val checkboxImage = rule.onNodeWithTag(TEST_TAG).captureToImage()
checkboxImage.assertContainsColor(boxColorDisabledChecked)
checkboxImage.assertContainsColor(
- hardLightBlend(
- boxColorDisabledChecked,
- boxColorDisabledChecked
- )
+ hardLightBlend(boxColorDisabledChecked, boxColorDisabledChecked)
)
}
@@ -333,10 +330,7 @@
@Test
fun switch_supports_testtag() {
rule.setContent {
- SwitchWithDefaults(
- checked = true,
- modifier = Modifier.testTag(TEST_TAG)
- )
+ SwitchWithDefaults(checked = true, modifier = Modifier.testTag(TEST_TAG))
}
rule.onNodeWithTag(TEST_TAG).assertExists()
@@ -352,13 +346,9 @@
)
}
- rule.onNodeWithTag(TEST_TAG)
- .assert(
- SemanticsMatcher.expectValue(
- SemanticsProperties.Role,
- Role.Switch
- )
- )
+ rule
+ .onNodeWithTag(TEST_TAG)
+ .assert(SemanticsMatcher.expectValue(SemanticsProperties.Role, Role.Switch))
}
@Test
@@ -367,21 +357,13 @@
SwitchWithDefaults(
checked = true,
onCheckedChange = {},
- modifier = Modifier
- .testTag(TEST_TAG)
- .semantics {
- role = Role.Image
- }
+ modifier = Modifier.testTag(TEST_TAG).semantics { role = Role.Image }
)
}
- rule.onNodeWithTag(TEST_TAG)
- .assert(
- SemanticsMatcher.expectValue(
- SemanticsProperties.Role,
- Role.Image
- )
- )
+ rule
+ .onNodeWithTag(TEST_TAG)
+ .assert(SemanticsMatcher.expectValue(SemanticsProperties.Role, Role.Image))
}
@Test
@@ -492,11 +474,7 @@
)
}
- rule
- .onNodeWithTag(TEST_TAG)
- .assertIsOff()
- .performClick()
- .assertIsOn()
+ rule.onNodeWithTag(TEST_TAG).assertIsOff().performClick().assertIsOn()
}
@Test
@@ -511,11 +489,7 @@
)
}
- rule
- .onNodeWithTag(TEST_TAG)
- .assertIsOn()
- .performClick()
- .assertIsOff()
+ rule.onNodeWithTag(TEST_TAG).assertIsOn().performClick().assertIsOff()
}
@Test
@@ -523,14 +497,17 @@
val width = 34.dp
val height = 26.dp
- rule.setContentForSizeAssertions {
- CheckboxWithDefaults(
- checked = true,
- modifier = Modifier.testTag(TEST_TAG),
- width = width,
- height = height
- )
- }.assertHeightIsEqualTo(height).assertWidthIsEqualTo(width)
+ rule
+ .setContentForSizeAssertions {
+ CheckboxWithDefaults(
+ checked = true,
+ modifier = Modifier.testTag(TEST_TAG),
+ width = width,
+ height = height
+ )
+ }
+ .assertHeightIsEqualTo(height)
+ .assertWidthIsEqualTo(width)
}
@RequiresApi(Build.VERSION_CODES.O)
@@ -588,10 +565,7 @@
@Test
fun radiobutton_supports_testtag() {
rule.setContent {
- RadioButtonWithDefaults(
- modifier = Modifier.testTag(TEST_TAG),
- selected = true
- )
+ RadioButtonWithDefaults(modifier = Modifier.testTag(TEST_TAG), selected = true)
}
rule.onNodeWithTag(TEST_TAG).assertExists()
@@ -602,14 +576,17 @@
val width = 30.dp
val height = 26.dp
- rule.setContentForSizeAssertions {
- RadioButtonWithDefaults(
- modifier = Modifier.testTag(TEST_TAG),
- selected = true,
- width = width,
- height = height
- )
- }.assertHeightIsEqualTo(height).assertWidthIsEqualTo(width)
+ rule
+ .setContentForSizeAssertions {
+ RadioButtonWithDefaults(
+ modifier = Modifier.testTag(TEST_TAG),
+ selected = true,
+ width = width,
+ height = height
+ )
+ }
+ .assertHeightIsEqualTo(height)
+ .assertWidthIsEqualTo(width)
}
@Test
@@ -622,36 +599,24 @@
)
}
- rule.onNodeWithTag(TEST_TAG)
- .assert(
- SemanticsMatcher.expectValue(
- SemanticsProperties.Role,
- Role.RadioButton
- )
- )
+ rule
+ .onNodeWithTag(TEST_TAG)
+ .assert(SemanticsMatcher.expectValue(SemanticsProperties.Role, Role.RadioButton))
}
@Test
fun radiobutton_can_override_role() {
rule.setContent {
RadioButtonWithDefaults(
- modifier = Modifier
- .testTag(TEST_TAG)
- .semantics {
- role = Role.Image
- },
+ modifier = Modifier.testTag(TEST_TAG).semantics { role = Role.Image },
selected = true,
onClick = {}
)
}
- rule.onNodeWithTag(TEST_TAG)
- .assert(
- SemanticsMatcher.expectValue(
- SemanticsProperties.Role,
- Role.Image
- )
- )
+ rule
+ .onNodeWithTag(TEST_TAG)
+ .assert(SemanticsMatcher.expectValue(SemanticsProperties.Role, Role.Image))
}
@Test
@@ -764,11 +729,7 @@
)
}
- rule
- .onNodeWithTag(TEST_TAG)
- .assertIsNotSelected()
- .performClick()
- .assertIsSelected()
+ rule.onNodeWithTag(TEST_TAG).assertIsNotSelected().performClick().assertIsSelected()
}
@Test
@@ -784,11 +745,7 @@
)
}
- rule
- .onNodeWithTag(TEST_TAG)
- .assertIsSelected()
- .performClick()
- .assertIsNotSelected()
+ rule.onNodeWithTag(TEST_TAG).assertIsSelected().performClick().assertIsNotSelected()
}
@RequiresApi(Build.VERSION_CODES.O)
@@ -838,15 +795,23 @@
boxColor: @Composable (enabled: Boolean, checked: Boolean) -> State<Color> =
{ isEnabled, isChecked ->
selectionControlColor(
- isEnabled, isChecked,
- Color.Blue, Color.Red, Color.Green, Color.Gray
+ isEnabled,
+ isChecked,
+ Color.Blue,
+ Color.Red,
+ Color.Green,
+ Color.Gray
)
},
checkmarkColor: @Composable (enabled: Boolean, checked: Boolean) -> State<Color> =
{ isEnabled, isChecked ->
selectionControlColor(
- isEnabled, isChecked,
- Color.Cyan, Color.Magenta, Color.White, Color.Yellow
+ isEnabled,
+ isChecked,
+ Color.Cyan,
+ Color.Magenta,
+ Color.White,
+ Color.Yellow
)
},
enabled: Boolean = true,
@@ -855,21 +820,21 @@
drawBox: FunctionDrawBox = FunctionDrawBox { _, _, _, _ -> },
width: Dp = 24.dp,
height: Dp = 24.dp
- ) = Checkbox(
- checked = checked,
- modifier = modifier,
- boxColor = boxColor,
- checkmarkColor = checkmarkColor,
- enabled = enabled,
- onCheckedChange = onCheckedChange,
- interactionSource = interactionSource,
- drawBox = drawBox,
- progressAnimationSpec =
- tween(200, 0, CubicBezierEasing(0.0f, 0.0f, 0.2f, 1.0f)),
- width = width,
- height = height,
- ripple = EmptyIndication
- )
+ ) =
+ Checkbox(
+ checked = checked,
+ modifier = modifier,
+ boxColor = boxColor,
+ checkmarkColor = checkmarkColor,
+ enabled = enabled,
+ onCheckedChange = onCheckedChange,
+ interactionSource = interactionSource,
+ drawBox = drawBox,
+ progressAnimationSpec = tween(200, 0, CubicBezierEasing(0.0f, 0.0f, 0.2f, 1.0f)),
+ width = width,
+ height = height,
+ ripple = EmptyIndication
+ )
@Composable
private fun SwitchWithDefaults(
@@ -881,29 +846,45 @@
trackFillColor: @Composable (enabled: Boolean, checked: Boolean) -> State<Color> =
{ isEnabled, isChecked ->
selectionControlColor(
- isEnabled, isChecked,
- Color.Blue, Color.Red, Color.Green, Color.Gray
+ isEnabled,
+ isChecked,
+ Color.Blue,
+ Color.Red,
+ Color.Green,
+ Color.Gray
)
},
trackStrokeColor: @Composable (enabled: Boolean, checked: Boolean) -> State<Color> =
{ isEnabled, isChecked ->
selectionControlColor(
- isEnabled, isChecked,
- Color.Blue, Color.Red, Color.Green, Color.Gray
+ isEnabled,
+ isChecked,
+ Color.Blue,
+ Color.Red,
+ Color.Green,
+ Color.Gray
)
},
thumbColor: @Composable (enabled: Boolean, checked: Boolean) -> State<Color> =
{ isEnabled, isChecked ->
selectionControlColor(
- isEnabled, isChecked,
- Color.Cyan, Color.Magenta, Color.White, Color.Yellow
+ isEnabled,
+ isChecked,
+ Color.Cyan,
+ Color.Magenta,
+ Color.White,
+ Color.Yellow
)
},
thumbIconColor: @Composable (enabled: Boolean, checked: Boolean) -> State<Color> =
{ isEnabled, isChecked ->
selectionControlColor(
- isEnabled, isChecked,
- Color.Cyan, Color.Magenta, Color.White, Color.Yellow
+ isEnabled,
+ isChecked,
+ Color.Cyan,
+ Color.Magenta,
+ Color.White,
+ Color.Yellow
)
},
trackWidth: Dp = 32.dp,
@@ -911,25 +892,25 @@
drawThumb: FunctionDrawThumb = FunctionDrawThumb { _, _, _, _, _ -> },
width: Dp = 32.dp,
height: Dp = 24.dp
- ) = Switch(
- checked = checked,
- modifier = modifier,
- enabled = enabled,
- onCheckedChange = onCheckedChange,
- interactionSource = interactionSource,
- trackFillColor = trackFillColor,
- trackStrokeColor = trackStrokeColor,
- thumbColor = thumbColor,
- thumbIconColor = thumbIconColor,
- trackWidth = trackWidth,
- trackHeight = trackHeight,
- drawThumb = drawThumb,
- progressAnimationSpec =
- tween(150, 0, CubicBezierEasing(0.0f, 0.0f, 0.2f, 1.0f)),
- width = width,
- height = height,
- ripple = EmptyIndication
- )
+ ) =
+ Switch(
+ checked = checked,
+ modifier = modifier,
+ enabled = enabled,
+ onCheckedChange = onCheckedChange,
+ interactionSource = interactionSource,
+ trackFillColor = trackFillColor,
+ trackStrokeColor = trackStrokeColor,
+ thumbColor = thumbColor,
+ thumbIconColor = thumbIconColor,
+ trackWidth = trackWidth,
+ trackHeight = trackHeight,
+ drawThumb = drawThumb,
+ progressAnimationSpec = tween(150, 0, CubicBezierEasing(0.0f, 0.0f, 0.2f, 1.0f)),
+ width = width,
+ height = height,
+ ripple = EmptyIndication
+ )
@Composable
private fun RadioButtonWithDefaults(
@@ -939,47 +920,58 @@
ringColor: @Composable (enabled: Boolean, checked: Boolean) -> State<Color> =
{ isEnabled, isChecked ->
selectionControlColor(
- isEnabled, isChecked,
- Color.Blue, Color.Red, Color.Green, Color.Gray
+ isEnabled,
+ isChecked,
+ Color.Blue,
+ Color.Red,
+ Color.Green,
+ Color.Gray
)
},
dotColor: @Composable (enabled: Boolean, checked: Boolean) -> State<Color> =
{ isEnabled, isChecked ->
selectionControlColor(
- isEnabled, isChecked,
- Color.Blue, Color.Red, Color.Green, Color.Gray
+ isEnabled,
+ isChecked,
+ Color.Blue,
+ Color.Red,
+ Color.Green,
+ Color.Gray
)
},
onClick: (() -> Unit)? = null,
interactionSource: MutableInteractionSource? = null,
dotRadiusProgressDuration: FunctionDotRadiusProgressDuration =
- FunctionDotRadiusProgressDuration { _ -> 200 },
+ FunctionDotRadiusProgressDuration { _ ->
+ 200
+ },
dotAlphaProgressDuration: Int = 200,
dotAlphaProgressDelay: Int = 100,
- progressAnimationEasing: CubicBezierEasing =
- CubicBezierEasing(0.0f, 0.0f, 0.2f, 1.0f),
+ progressAnimationEasing: CubicBezierEasing = CubicBezierEasing(0.0f, 0.0f, 0.2f, 1.0f),
width: Dp = 32.dp,
height: Dp = 24.dp
- ) = RadioButton(
- modifier = modifier,
- selected = selected,
- enabled = enabled,
- ringColor = ringColor,
- dotColor = dotColor,
- onClick = onClick,
- interactionSource = interactionSource,
- dotRadiusProgressDuration = dotRadiusProgressDuration,
- dotAlphaProgressDuration = dotAlphaProgressDuration,
- dotAlphaProgressDelay = dotAlphaProgressDelay,
- easing = progressAnimationEasing,
- width = width,
- height = height,
- ripple = EmptyIndication
- )
+ ) =
+ RadioButton(
+ modifier = modifier,
+ selected = selected,
+ enabled = enabled,
+ ringColor = ringColor,
+ dotColor = dotColor,
+ onClick = onClick,
+ interactionSource = interactionSource,
+ dotRadiusProgressDuration = dotRadiusProgressDuration,
+ dotAlphaProgressDuration = dotAlphaProgressDuration,
+ dotAlphaProgressDelay = dotAlphaProgressDelay,
+ easing = progressAnimationEasing,
+ width = width,
+ height = height,
+ ripple = EmptyIndication
+ )
private fun setupCheckBoxWithCustomColors(checked: Boolean, enabled: Boolean) {
rule.setContent {
- CheckboxWithDefaults(checked = checked,
+ CheckboxWithDefaults(
+ checked = checked,
enabled = enabled,
modifier = Modifier.testTag(TEST_TAG),
boxColor = { enabled, checked ->
@@ -1002,9 +994,8 @@
disabledUncheckedColor = checkmarkColorDisabledUnchecked
)
},
- drawBox = { drawScope, color, _, _ ->
- drawScope.drawRoundRect(color)
- })
+ drawBox = { drawScope, color, _, _ -> drawScope.drawRoundRect(color) }
+ )
}
}
@@ -1125,11 +1116,12 @@
uncheckedColor: Color,
disabledCheckedColor: Color,
disabledUncheckedColor: Color
- ) = animateColorAsState(
- if (enabled) {
- if (checked) checkedColor else uncheckedColor
- } else {
- if (checked) disabledCheckedColor else disabledUncheckedColor
- }
- )
+ ) =
+ animateColorAsState(
+ if (enabled) {
+ if (checked) checkedColor else uncheckedColor
+ } else {
+ if (checked) disabledCheckedColor else disabledUncheckedColor
+ }
+ )
}
diff --git a/wear/compose/compose-material-core/src/androidTest/kotlin/androidx/wear/compose/materialcore/SliderTest.kt b/wear/compose/compose-material-core/src/androidTest/kotlin/androidx/wear/compose/materialcore/SliderTest.kt
index 7303af4..7d67b5a 100644
--- a/wear/compose/compose-material-core/src/androidTest/kotlin/androidx/wear/compose/materialcore/SliderTest.kt
+++ b/wear/compose/compose-material-core/src/androidTest/kotlin/androidx/wear/compose/materialcore/SliderTest.kt
@@ -48,16 +48,11 @@
import org.junit.Test
public class SliderTest {
- @get:Rule
- public val rule = createComposeRule()
+ @get:Rule public val rule = createComposeRule()
@Test
public fun slider_button_supports_testtag() {
- rule.setContent {
- SliderButtonWithDefaults(
- modifier = Modifier.testTag(TEST_TAG)
- )
- }
+ rule.setContent { SliderButtonWithDefaults(modifier = Modifier.testTag(TEST_TAG)) }
rule.onNodeWithTag(TEST_TAG).assertExists()
}
@@ -65,10 +60,7 @@
@Test
public fun slider_button_has_click_action_when_enabled() {
rule.setContent {
- SliderButtonWithDefaults(
- enabled = true,
- modifier = Modifier.testTag(TEST_TAG)
- )
+ SliderButtonWithDefaults(enabled = true, modifier = Modifier.testTag(TEST_TAG))
}
rule.onNodeWithTag(TEST_TAG).assertHasClickAction()
@@ -77,10 +69,7 @@
@Test
public fun slider_button_has_click_action_when_disabled() {
rule.setContent {
- SliderButtonWithDefaults(
- enabled = false,
- modifier = Modifier.testTag(TEST_TAG)
- )
+ SliderButtonWithDefaults(enabled = false, modifier = Modifier.testTag(TEST_TAG))
}
rule.onNodeWithTag(TEST_TAG).assertHasClickAction()
@@ -89,10 +78,7 @@
@Test
public fun slider_button_is_correctly_enabled() {
rule.setContent {
- SliderButtonWithDefaults(
- enabled = true,
- modifier = Modifier.testTag(TEST_TAG)
- )
+ SliderButtonWithDefaults(enabled = true, modifier = Modifier.testTag(TEST_TAG))
}
rule.onNodeWithTag(TEST_TAG).assertIsEnabled()
@@ -101,10 +87,7 @@
@Test
public fun slider_button_is_correctly_disabled() {
rule.setContent {
- SliderButtonWithDefaults(
- enabled = false,
- modifier = Modifier.testTag(TEST_TAG)
- )
+ SliderButtonWithDefaults(enabled = false, modifier = Modifier.testTag(TEST_TAG))
}
rule.onNodeWithTag(TEST_TAG).assertIsNotEnabled()
@@ -123,9 +106,7 @@
rule.onNodeWithTag(TEST_TAG).performClick()
- rule.runOnIdle {
- Assert.assertEquals(true, clicked)
- }
+ rule.runOnIdle { Assert.assertEquals(true, clicked) }
}
@Test
@@ -141,9 +122,7 @@
rule.onNodeWithTag(TEST_TAG).performClick()
- rule.runOnIdle {
- Assert.assertEquals(false, clicked)
- }
+ rule.runOnIdle { Assert.assertEquals(false, clicked) }
}
@Test
@@ -157,18 +136,15 @@
)
}
- rule.onNodeWithTag(TEST_TAG, true)
+ rule
+ .onNodeWithTag(TEST_TAG, true)
.onChild()
.assertContentDescriptionContains(testContentDescription)
}
@Test
public fun slider_progress_bar_supports_testtag() {
- rule.setContent {
- ProgressBarWithDefaults(
- modifier = Modifier.testTag(TEST_TAG)
- )
- }
+ rule.setContent { ProgressBarWithDefaults(modifier = Modifier.testTag(TEST_TAG)) }
rule.onNodeWithTag(TEST_TAG).assertExists()
}
@@ -184,7 +160,8 @@
)
}
- rule.onNodeWithTag(TEST_TAG)
+ rule
+ .onNodeWithTag(TEST_TAG)
.captureToImage()
.assertContainsColor(expectedColor = BarSeparatorColor, 0.1f)
}
@@ -200,7 +177,8 @@
)
}
- rule.onNodeWithTag(TEST_TAG)
+ rule
+ .onNodeWithTag(TEST_TAG)
.captureToImage()
.assertDoesNotContainColor(unexpectedColor = BarSeparatorColor)
}
@@ -316,20 +294,21 @@
}
Box(
- modifier = modifier
- .height(ProgressBarHeight)
- .fillMaxWidth()
- .drawProgressBar(
- selectedBarColor = selectedBarColor,
- unselectedBarColor = unselectedBarColor,
- barSeparatorColor = barSeparatorColor,
- visibleSegments = visibleSegments,
- valueRatio = valueRatio,
- direction = layoutDirection,
- drawSelectedProgressBar = drawSelectedProgressBar,
- drawUnselectedProgressBar = drawUnselectedProgressBar,
- drawProgressBarSeparator = drawProgressBarSeparator
- )
+ modifier =
+ modifier
+ .height(ProgressBarHeight)
+ .fillMaxWidth()
+ .drawProgressBar(
+ selectedBarColor = selectedBarColor,
+ unselectedBarColor = unselectedBarColor,
+ barSeparatorColor = barSeparatorColor,
+ visibleSegments = visibleSegments,
+ valueRatio = valueRatio,
+ direction = layoutDirection,
+ drawSelectedProgressBar = drawSelectedProgressBar,
+ drawUnselectedProgressBar = drawUnselectedProgressBar,
+ drawProgressBarSeparator = drawProgressBarSeparator
+ )
)
}
@@ -340,12 +319,8 @@
) {
drawLine(
color,
- Offset(
- directedValue(direction, 0f, size.width * (1 - valueRatio)), size.height / 2
- ),
- Offset(
- directedValue(direction, size.width * valueRatio, size.width), size.height / 2
- ),
+ Offset(directedValue(direction, 0f, size.width * (1 - valueRatio)), size.height / 2),
+ Offset(directedValue(direction, size.width * valueRatio, size.width), size.height / 2),
strokeWidth = size.height
)
}
@@ -357,11 +332,10 @@
) {
drawLine(
color,
+ Offset(directedValue(direction, size.width * valueRatio, 0f), size.height / 2),
Offset(
- directedValue(direction, size.width * valueRatio, 0f), size.height / 2
- ),
- Offset(
- directedValue(direction, size.width, size.width * (1 - valueRatio)), size.height / 2
+ directedValue(direction, size.width, size.width * (1 - valueRatio)),
+ size.height / 2
),
strokeWidth = size.height
)
diff --git a/wear/compose/compose-material-core/src/androidTest/kotlin/androidx/wear/compose/materialcore/StepperTest.kt b/wear/compose/compose-material-core/src/androidTest/kotlin/androidx/wear/compose/materialcore/StepperTest.kt
index 9dbbad5..cd2c4ae 100644
--- a/wear/compose/compose-material-core/src/androidTest/kotlin/androidx/wear/compose/materialcore/StepperTest.kt
+++ b/wear/compose/compose-material-core/src/androidTest/kotlin/androidx/wear/compose/materialcore/StepperTest.kt
@@ -53,27 +53,18 @@
import org.junit.Test
public class StepperTest {
- @get:Rule
- public val rule = createComposeRule()
+ @get:Rule public val rule = createComposeRule()
@Test
public fun supports_testtag() {
- rule.setContent {
- StepperWithDefaults(
- modifier = Modifier.testTag(TEST_TAG)
- ) {}
- }
+ rule.setContent { StepperWithDefaults(modifier = Modifier.testTag(TEST_TAG)) {} }
rule.onNodeWithTag(TEST_TAG).assertExists()
}
@Test(expected = IllegalArgumentException::class)
public fun throws_when_steps_negative() {
- rule.setContent {
- StepperWithDefaults(
- steps = -1
- ) {}
- }
+ rule.setContent { StepperWithDefaults(steps = -1) {} }
}
@Test
@@ -85,9 +76,7 @@
rule.onNodeWithContentDescription(DECREASE).performClick()
- rule.runOnIdle {
- Truth.assertThat(state.value).isWithin(0.001f).of(1f)
- }
+ rule.runOnIdle { Truth.assertThat(state.value).isWithin(0.001f).of(1f) }
}
@Test
@@ -100,9 +89,7 @@
// The clickable area for an increase button takes top 35% of the screen
rule.onNodeWithTag(TEST_TAG).performTouchInput { click(Offset(width / 2f, 15f)) }
- rule.runOnIdle {
- Truth.assertThat(state.value).isWithin(0.001f).of(3f)
- }
+ rule.runOnIdle { Truth.assertThat(state.value).isWithin(0.001f).of(3f) }
}
@Test
@@ -116,9 +103,7 @@
// The clickable area for a decrease button takes bottom 35% of the screen
rule.onNodeWithTag(TEST_TAG).performTouchInput { click(Offset(width / 2f, height - 15f)) }
- rule.runOnIdle {
- Truth.assertThat(state.value).isWithin(0.001f).of(1f)
- }
+ rule.runOnIdle { Truth.assertThat(state.value).isWithin(0.001f).of(1f) }
}
@Test
@@ -132,9 +117,7 @@
// The clickable area for an increase button takes top 35% of the screen
rule.onNodeWithTag(TEST_TAG).performTouchInput { click(Offset(width / 2f, 15f)) }
- rule.runOnIdle {
- Truth.assertThat(state.value).isWithin(0.001f).of(4f)
- }
+ rule.runOnIdle { Truth.assertThat(state.value).isWithin(0.001f).of(4f) }
}
@Test
@@ -159,19 +142,15 @@
@Test
public fun checks_decrease_icon_position() {
- rule.setContent {
- StepperWithDefaults(
- modifier = Modifier.testTag(TEST_TAG)
- ) {}
- }
+ rule.setContent { StepperWithDefaults(modifier = Modifier.testTag(TEST_TAG)) {} }
val unclippedBoundsInRoot = rule.onRoot().getUnclippedBoundsInRoot()
rule.waitForIdle()
- rule.onNodeWithTag(DECREASE, true)
+ rule
+ .onNodeWithTag(DECREASE, true)
.assertExists()
.assertTopPositionInRootIsEqualTo(
- unclippedBoundsInRoot.height -
- BorderVerticalMargin - DefaultIconHeight
+ unclippedBoundsInRoot.height - BorderVerticalMargin - DefaultIconHeight
)
}
@@ -182,15 +161,12 @@
rule.setContent {
StepperWithDefaults(
modifier = Modifier.testTag(TEST_TAG),
- decreaseIcon = {
- TestImage(Modifier.size(24.dp), iconTag)
- }
+ decreaseIcon = { TestImage(Modifier.size(24.dp), iconTag) }
) {}
}
rule.waitForIdle()
- rule.onNodeWithTag(iconTag, true)
- .assertExists()
+ rule.onNodeWithTag(iconTag, true).assertExists()
}
@Test
@@ -200,13 +176,12 @@
rule.setContent {
StepperWithDefaults(
modifier = Modifier.testTag(TEST_TAG),
- increaseIcon = {
- TestImage(Modifier.size(24.dp), iconTag)
- }
+ increaseIcon = { TestImage(Modifier.size(24.dp), iconTag) }
) {}
}
rule.waitForIdle()
- rule.onNodeWithTag(iconTag, true)
+ rule
+ .onNodeWithTag(iconTag, true)
.assertExists()
.assertTopPositionInRootIsEqualTo(BorderVerticalMargin)
}
@@ -219,19 +194,15 @@
StepperWithDefaults(
modifier = Modifier.testTag(TEST_TAG),
) {
- TestText(
- "Testing",
- modifier = Modifier
- .testTag(contentTag)
- .fillMaxHeight()
- )
+ TestText("Testing", modifier = Modifier.testTag(contentTag).fillMaxHeight())
}
}
val rootHeight = rule.onRoot().getUnclippedBoundsInRoot().height
rule.waitForIdle()
- rule.onNodeWithTag(contentTag, true)
+ rule
+ .onNodeWithTag(contentTag, true)
.assertExists()
.assertTopPositionInRootIsEqualTo(
// Position of the content is a weight(35%) of (top button minus 2 spacers 8dp each)
@@ -251,7 +222,8 @@
backgroundColor = testColor
) {}
}
- rule.onNodeWithTag(TEST_TAG)
+ rule
+ .onNodeWithTag(TEST_TAG)
.captureToImage()
.assertContainsColor(testColor, backgroundThreshold)
}
@@ -265,14 +237,13 @@
modifier = Modifier.testTag(TEST_TAG),
value = 0f,
steps = 5,
- increaseIcon = {
- TestImage(Modifier.size(24.dp), testContentDescription)
- }
+ increaseIcon = { TestImage(Modifier.size(24.dp), testContentDescription) }
) {}
}
rule.waitForIdle()
- rule.onNodeWithTag(TEST_TAG, true)
+ rule
+ .onNodeWithTag(TEST_TAG, true)
// 0 is the index of increase button, 1 - decrease button, content is empty
.onChildAt(0)
.onChild()
@@ -288,14 +259,13 @@
modifier = Modifier.testTag(TEST_TAG),
value = 0f,
steps = 5,
- decreaseIcon = {
- TestImage(Modifier.size(24.dp), testContentDescription)
- }
+ decreaseIcon = { TestImage(Modifier.size(24.dp), testContentDescription) }
) {}
}
rule.waitForIdle()
- rule.onNodeWithTag(TEST_TAG, true)
+ rule
+ .onNodeWithTag(TEST_TAG, true)
// 0 is the index of increase button, 1 - decrease button, content is empty
.onChildAt(1)
.onChild()
@@ -310,12 +280,8 @@
steps = 3,
expectedIncreaseIconData = +1,
expectedDecreaseIconData = -1,
- enabledButtonProviderValues = arrayOf(
- LocalContentTestData provides +1
- ),
- disabledButtonProviderValues = arrayOf(
- LocalContentTestData provides -1
- )
+ enabledButtonProviderValues = arrayOf(LocalContentTestData provides +1),
+ disabledButtonProviderValues = arrayOf(LocalContentTestData provides -1)
)
}
@@ -327,12 +293,8 @@
steps = 3,
expectedIncreaseIconData = -1,
expectedDecreaseIconData = +1,
- enabledButtonProviderValues = arrayOf(
- LocalContentTestData provides +1
- ),
- disabledButtonProviderValues = arrayOf(
- LocalContentTestData provides -1
- )
+ enabledButtonProviderValues = arrayOf(LocalContentTestData provides +1),
+ disabledButtonProviderValues = arrayOf(LocalContentTestData provides -1)
)
}
@@ -344,12 +306,8 @@
steps = 3,
expectedIncreaseIconData = +1,
expectedDecreaseIconData = +1,
- enabledButtonProviderValues = arrayOf(
- LocalContentTestData provides +1
- ),
- disabledButtonProviderValues = arrayOf(
- LocalContentTestData provides -1
- )
+ enabledButtonProviderValues = arrayOf(LocalContentTestData provides +1),
+ disabledButtonProviderValues = arrayOf(LocalContentTestData provides -1)
)
}
@@ -365,36 +323,31 @@
onValueChange: (Float) -> Unit = {},
steps: Int = 5,
decreaseIcon: @Composable () -> Unit = {
- TestImage(
- modifier = Modifier.size(24.dp),
- iconLabel = DECREASE
- )
+ TestImage(modifier = Modifier.size(24.dp), iconLabel = DECREASE)
},
increaseIcon: @Composable () -> Unit = {
- TestImage(
- modifier = Modifier.size(24.dp),
- iconLabel = INCREASE
- )
+ TestImage(modifier = Modifier.size(24.dp), iconLabel = INCREASE)
},
valueRange: ClosedFloatingPointRange<Float> = 0f..5f,
backgroundColor: Color = Color.Black,
enabledButtonProviderValues: Array<ProvidedValue<*>> = arrayOf(),
disabledButtonProviderValues: Array<ProvidedValue<*>> = arrayOf(),
content: @Composable BoxScope.() -> Unit
- ) = Stepper(
- modifier = modifier,
- value = value,
- onValueChange = onValueChange,
- steps = steps,
- increaseIcon = increaseIcon,
- decreaseIcon = decreaseIcon,
- valueRange = valueRange,
- backgroundColor = backgroundColor,
- enabledButtonProviderValues = enabledButtonProviderValues,
- disabledButtonProviderValues = disabledButtonProviderValues,
- buttonRipple = EmptyIndication,
- content = content,
- )
+ ) =
+ Stepper(
+ modifier = modifier,
+ value = value,
+ onValueChange = onValueChange,
+ steps = steps,
+ increaseIcon = increaseIcon,
+ decreaseIcon = decreaseIcon,
+ valueRange = valueRange,
+ backgroundColor = backgroundColor,
+ enabledButtonProviderValues = enabledButtonProviderValues,
+ disabledButtonProviderValues = disabledButtonProviderValues,
+ buttonRipple = EmptyIndication,
+ content = content,
+ )
private fun verifyButtonProviderValues(
value: Float,
@@ -416,12 +369,8 @@
backgroundColor = Color.Transparent,
enabledButtonProviderValues = enabledButtonProviderValues,
disabledButtonProviderValues = disabledButtonProviderValues,
- decreaseIcon = {
- decreaseIconData = LocalContentTestData.current
- },
- increaseIcon = {
- increaseIconData = LocalContentTestData.current
- }
+ decreaseIcon = { decreaseIconData = LocalContentTestData.current },
+ increaseIcon = { increaseIconData = LocalContentTestData.current }
) {}
}
diff --git a/wear/compose/compose-material-core/src/androidTest/kotlin/androidx/wear/compose/materialcore/TextTest.kt b/wear/compose/compose-material-core/src/androidTest/kotlin/androidx/wear/compose/materialcore/TextTest.kt
index d1c8fad..e548dd9 100644
--- a/wear/compose/compose-material-core/src/androidTest/kotlin/androidx/wear/compose/materialcore/TextTest.kt
+++ b/wear/compose/compose-material-core/src/androidTest/kotlin/androidx/wear/compose/materialcore/TextTest.kt
@@ -51,20 +51,20 @@
@SmallTest
@RunWith(AndroidJUnit4::class)
class TextTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
- private val ExpectedTextStyle = TextStyle(
- color = Color.Red,
- fontSize = 32.sp,
- fontStyle = FontStyle.Italic,
- fontWeight = FontWeight.Normal,
- fontFamily = FontFamily.Default,
- letterSpacing = 1.sp,
- textDecoration = TextDecoration.Underline,
- textAlign = TextAlign.End,
- lineHeight = 10.sp,
- )
+ private val ExpectedTextStyle =
+ TextStyle(
+ color = Color.Red,
+ fontSize = 32.sp,
+ fontStyle = FontStyle.Italic,
+ fontWeight = FontWeight.Normal,
+ fontFamily = FontFamily.Default,
+ letterSpacing = 1.sp,
+ textDecoration = TextDecoration.Underline,
+ textAlign = TextAlign.End,
+ lineHeight = 10.sp,
+ )
private val TestText = "TestText"
@Test
@@ -91,9 +91,7 @@
AnnotatedString(TestText),
minLines = 1,
maxLines = 3,
- onTextLayout = {
- size1 = it.size.height
- },
+ onTextLayout = { size1 = it.size.height },
style = ExpectedTextStyle
)
@@ -101,17 +99,13 @@
AnnotatedString(TestText),
minLines = 2,
maxLines = 3,
- onTextLayout = {
- size2 = it.size.height
- },
+ onTextLayout = { size2 = it.size.height },
style = ExpectedTextStyle
)
}
}
- rule.runOnIdle {
- Truth.assertThat(size2).isGreaterThan(size1)
- }
+ rule.runOnIdle { Truth.assertThat(size2).isGreaterThan(size1) }
}
@Test(expected = IllegalArgumentException::class)
@@ -140,20 +134,12 @@
@Test
fun colorParameterOverridesStyleColor() {
- verifyTextColor(
- Color.Red,
- ExpectedTextStyle,
- Color.Red
- )
+ verifyTextColor(Color.Red, ExpectedTextStyle, Color.Red)
}
@Test
fun styleColorOverridesUnspecifiedColor() {
- verifyTextColor(
- Color.Unspecified,
- ExpectedTextStyle,
- ExpectedTextStyle.color
- )
+ verifyTextColor(Color.Unspecified, ExpectedTextStyle, ExpectedTextStyle.color)
}
@Test
@@ -233,31 +219,21 @@
}
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
- private fun verifyTextColor(
- color: Color,
- style: TextStyle,
- expectedColor: Color
- ) {
+ private fun verifyTextColor(color: Color, style: TextStyle, expectedColor: Color) {
var textColor: Color? = null
rule.setContent {
TextWithDefaults(
AnnotatedString(TestText),
color = color,
modifier = Modifier.testTag(TEST_TAG),
- onTextLayout = {
- textColor = it.layoutInput.style.color
- },
+ onTextLayout = { textColor = it.layoutInput.style.color },
style = style
)
}
- rule.onNodeWithTag(TEST_TAG)
- .captureToImage()
- .assertContainsColor(expectedColor, 0.1f)
+ rule.onNodeWithTag(TEST_TAG).captureToImage().assertContainsColor(expectedColor, 0.1f)
- rule.runOnIdle {
- Truth.assertThat(textColor).isEqualTo(expectedColor)
- }
+ rule.runOnIdle { Truth.assertThat(textColor).isEqualTo(expectedColor) }
}
}
diff --git a/wear/compose/compose-material-core/src/androidTest/kotlin/androidx/wear/compose/materialcore/ToggleButtonTest.kt b/wear/compose/compose-material-core/src/androidTest/kotlin/androidx/wear/compose/materialcore/ToggleButtonTest.kt
index d7e67c1..b3171cc 100644
--- a/wear/compose/compose-material-core/src/androidTest/kotlin/androidx/wear/compose/materialcore/ToggleButtonTest.kt
+++ b/wear/compose/compose-material-core/src/androidTest/kotlin/androidx/wear/compose/materialcore/ToggleButtonTest.kt
@@ -74,8 +74,7 @@
import org.junit.Test
class ToggleButtonTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
/* Round Toggle buttons */
@Test
@@ -92,10 +91,7 @@
@Test
fun round_toggle_button_is_toggleable() {
rule.setContent {
- RoundToggleButtonWithDefaults(
- enabled = true,
- modifier = Modifier.testTag(TEST_TAG)
- )
+ RoundToggleButtonWithDefaults(enabled = true, modifier = Modifier.testTag(TEST_TAG))
}
rule.onNode(isToggleable()).assertExists()
@@ -104,10 +100,7 @@
@Test
fun round_toggle_button_has_click_action_when_enabled() {
rule.setContent {
- RoundToggleButtonWithDefaults(
- enabled = true,
- modifier = Modifier.testTag(TEST_TAG)
- )
+ RoundToggleButtonWithDefaults(enabled = true, modifier = Modifier.testTag(TEST_TAG))
}
rule.onNodeWithTag(TEST_TAG).assertHasClickAction()
@@ -116,10 +109,7 @@
@Test
fun round_toggle_button_has_click_action_when_disabled() {
rule.setContent {
- RoundToggleButtonWithDefaults(
- enabled = false,
- modifier = Modifier.testTag(TEST_TAG)
- )
+ RoundToggleButtonWithDefaults(enabled = false, modifier = Modifier.testTag(TEST_TAG))
}
rule.onNodeWithTag(TEST_TAG).assertHasClickAction()
@@ -128,10 +118,7 @@
@Test
fun round_toggle_button_is_correctly_enabled() {
rule.setContent {
- RoundToggleButtonWithDefaults(
- enabled = true,
- modifier = Modifier.testTag(TEST_TAG)
- )
+ RoundToggleButtonWithDefaults(enabled = true, modifier = Modifier.testTag(TEST_TAG))
}
rule.onNodeWithTag(TEST_TAG).assertIsEnabled()
@@ -140,10 +127,7 @@
@Test
fun round_toggle_button_is_correctly_disabled() {
rule.setContent {
- RoundToggleButtonWithDefaults(
- enabled = false,
- modifier = Modifier.testTag(TEST_TAG)
- )
+ RoundToggleButtonWithDefaults(enabled = false, modifier = Modifier.testTag(TEST_TAG))
}
rule.onNodeWithTag(TEST_TAG).assertIsNotEnabled()
@@ -189,9 +173,7 @@
rule.onNodeWithTag(TEST_TAG).performClick()
- rule.runOnIdle {
- Assert.assertEquals(true, clicked)
- }
+ rule.runOnIdle { Assert.assertEquals(true, clicked) }
}
@Test
@@ -207,11 +189,7 @@
)
}
- rule
- .onNodeWithTag(TEST_TAG)
- .assertIsOff()
- .performClick()
- .assertIsOn()
+ rule.onNodeWithTag(TEST_TAG).assertIsOff().performClick().assertIsOn()
}
@Test
@@ -227,11 +205,7 @@
)
}
- rule
- .onNodeWithTag(TEST_TAG)
- .assertIsOn()
- .performClick()
- .assertIsOff()
+ rule.onNodeWithTag(TEST_TAG).assertIsOn().performClick().assertIsOff()
}
@Test
@@ -248,26 +222,16 @@
rule.onNodeWithTag(TEST_TAG).performClick()
- rule.runOnIdle {
- Assert.assertEquals(false, clicked)
- }
+ rule.runOnIdle { Assert.assertEquals(false, clicked) }
}
@Test
fun round_toggle_button_has_role_checkbox() {
- rule.setContent {
- RoundToggleButtonWithDefaults(
- modifier = Modifier.testTag(TEST_TAG)
- )
- }
+ rule.setContent { RoundToggleButtonWithDefaults(modifier = Modifier.testTag(TEST_TAG)) }
- rule.onNodeWithTag(TEST_TAG)
- .assert(
- SemanticsMatcher.expectValue(
- SemanticsProperties.Role,
- Role.Checkbox
- )
- )
+ rule
+ .onNodeWithTag(TEST_TAG)
+ .assert(SemanticsMatcher.expectValue(SemanticsProperties.Role, Role.Checkbox))
}
@Test
@@ -275,7 +239,7 @@
rule.isShape(CircleShape, LayoutDirection.Ltr) {
RoundToggleButtonWithDefaults(
modifier = Modifier.testTag(TEST_TAG),
- ) { }
+ ) {}
}
@Test
@@ -283,28 +247,20 @@
rule.isShape(CircleShape, LayoutDirection.Rtl) {
RoundToggleButtonWithDefaults(
modifier = Modifier.testTag(TEST_TAG),
- ) { }
+ ) {}
}
@Test
fun extra_small_round_toggle_button_meets_accessibility_tapSize() {
verifyTapSize(48.dp) {
- RoundToggleButtonWithDefaults(
- modifier = Modifier
- .testTag(TEST_TAG)
- .size(32.dp)
- )
+ RoundToggleButtonWithDefaults(modifier = Modifier.testTag(TEST_TAG).size(32.dp))
}
}
@Test
fun extra_small_round_toggle_button_has_correct_visible_size() {
verifyVisibleSize(32.dp) {
- RoundToggleButtonWithDefaults(
- modifier = Modifier
- .testTag(TEST_TAG)
- .requiredSize(32.dp)
- )
+ RoundToggleButtonWithDefaults(modifier = Modifier.testTag(TEST_TAG).requiredSize(32.dp))
}
}
@@ -312,11 +268,7 @@
fun default_round_toggle_button_has_correct_tapSize() {
// Tap size for Button should be 52.dp.
verifyTapSize(52.dp) {
- RoundToggleButtonWithDefaults(
- modifier = Modifier
- .testTag(TEST_TAG)
- .size(52.dp)
- )
+ RoundToggleButtonWithDefaults(modifier = Modifier.testTag(TEST_TAG).size(52.dp))
}
}
@@ -324,11 +276,7 @@
fun default_round_toggle_button_has_correct_visible_size() {
// Tap size for Button should be 52.dp.
verifyVisibleSize(52.dp) {
- RoundToggleButtonWithDefaults(
- modifier = Modifier
- .testTag(TEST_TAG)
- .size(52.dp)
- )
+ RoundToggleButtonWithDefaults(modifier = Modifier.testTag(TEST_TAG).size(52.dp))
}
}
@@ -337,10 +285,7 @@
val shape = CutCornerShape(4.dp)
rule.isShape(shape, LayoutDirection.Ltr) {
- RoundToggleButtonWithDefaults(
- shape = shape,
- modifier = Modifier.testTag(TEST_TAG)
- ) { }
+ RoundToggleButtonWithDefaults(shape = shape, modifier = Modifier.testTag(TEST_TAG)) {}
}
}
@@ -424,11 +369,7 @@
/* Toggle button */
@Test
fun toggle_button_supports_testTag() {
- rule.setContent {
- ToggleButtonWithDefaults(
- modifier = Modifier.testTag(TEST_TAG)
- )
- }
+ rule.setContent { ToggleButtonWithDefaults(modifier = Modifier.testTag(TEST_TAG)) }
rule.onNodeWithTag(TEST_TAG).assertExists()
}
@@ -436,10 +377,7 @@
@Test
fun toggle_button_has_click_action_when_enabled() {
rule.setContent {
- ToggleButtonWithDefaults(
- enabled = true,
- modifier = Modifier.testTag(TEST_TAG)
- )
+ ToggleButtonWithDefaults(enabled = true, modifier = Modifier.testTag(TEST_TAG))
}
rule.onNodeWithTag(TEST_TAG).assertHasClickAction()
@@ -448,10 +386,7 @@
@Test
fun toggle_button_has_click_action_when_disabled() {
rule.setContent {
- ToggleButtonWithDefaults(
- enabled = false,
- modifier = Modifier.testTag(TEST_TAG)
- )
+ ToggleButtonWithDefaults(enabled = false, modifier = Modifier.testTag(TEST_TAG))
}
rule.onNodeWithTag(TEST_TAG).assertHasClickAction()
@@ -459,11 +394,7 @@
@Test
fun toggle_button_is_toggleable() {
- rule.setContent {
- ToggleButtonWithDefaults(
- modifier = Modifier.testTag(TEST_TAG)
- )
- }
+ rule.setContent { ToggleButtonWithDefaults(modifier = Modifier.testTag(TEST_TAG)) }
rule.onNode(isToggleable()).assertExists()
}
@@ -484,10 +415,7 @@
@Test
fun toggle_button_is_correctly_disabled() {
rule.setContent {
- ToggleButtonWithDefaults(
- enabled = false,
- modifier = Modifier.testTag(TEST_TAG)
- )
+ ToggleButtonWithDefaults(enabled = false, modifier = Modifier.testTag(TEST_TAG))
}
rule.onNodeWithTag(TEST_TAG).assertIsNotEnabled()
@@ -496,10 +424,7 @@
@Test
fun toggle_button_is_correctly_enabled() {
rule.setContent {
- ToggleButtonWithDefaults(
- enabled = true,
- modifier = Modifier.testTag(TEST_TAG)
- )
+ ToggleButtonWithDefaults(enabled = true, modifier = Modifier.testTag(TEST_TAG))
}
rule.onNodeWithTag(TEST_TAG).assertIsEnabled()
@@ -508,10 +433,7 @@
@Test
fun toggle_button_is_on_when_checked() {
rule.setContent {
- ToggleButtonWithDefaults(
- checked = true,
- modifier = Modifier.testTag(TEST_TAG)
- )
+ ToggleButtonWithDefaults(checked = true, modifier = Modifier.testTag(TEST_TAG))
}
rule.onNodeWithTag(TEST_TAG).assertIsOn()
@@ -520,10 +442,7 @@
@Test
fun toggle_button_is_off_when_unchecked() {
rule.setContent {
- ToggleButtonWithDefaults(
- checked = false,
- modifier = Modifier.testTag(TEST_TAG)
- )
+ ToggleButtonWithDefaults(checked = false, modifier = Modifier.testTag(TEST_TAG))
}
rule.onNodeWithTag(TEST_TAG).assertIsOff()
@@ -555,11 +474,7 @@
)
}
- rule
- .onNodeWithTag(TEST_TAG)
- .assertIsOff()
- .performClick()
- .assertIsOn()
+ rule.onNodeWithTag(TEST_TAG).assertIsOff().performClick().assertIsOn()
}
@Test
@@ -574,11 +489,7 @@
)
}
- rule
- .onNodeWithTag(TEST_TAG)
- .assertIsOn()
- .performClick()
- .assertIsOff()
+ rule.onNodeWithTag(TEST_TAG).assertIsOn().performClick().assertIsOff()
}
@Test
@@ -595,11 +506,7 @@
)
}
- rule
- .onNodeWithTag(TEST_TAG)
- .assertIsNotSelected()
- .performClick()
- .assertIsSelected()
+ rule.onNodeWithTag(TEST_TAG).assertIsNotSelected().performClick().assertIsSelected()
}
@Test
@@ -614,11 +521,7 @@
)
}
- rule
- .onNodeWithTag(TEST_TAG)
- .assertIsOff()
- .performClick()
- .assertIsOff()
+ rule.onNodeWithTag(TEST_TAG).assertIsOff().performClick().assertIsOff()
}
@Test
@@ -629,9 +532,7 @@
ToggleButtonWithDefaults(
checked = true,
onCheckedChange = {},
- label = {
- TestText(text = textContent)
- }
+ label = { TestText(text = textContent) }
)
}
@@ -678,11 +579,7 @@
@Test
fun split_button_supports_testTag() {
- rule.setContent {
- SplitToggleButtonWithDefaults(
- modifier = Modifier.testTag(TEST_TAG)
- )
- }
+ rule.setContent { SplitToggleButtonWithDefaults(modifier = Modifier.testTag(TEST_TAG)) }
rule.onNodeWithTag(TEST_TAG).assertExists()
}
@@ -690,10 +587,7 @@
@Test
fun split_button_has_click_action_when_enabled() {
rule.setContent {
- SplitToggleButtonWithDefaults(
- enabled = true,
- modifier = Modifier.testTag(TEST_TAG)
- )
+ SplitToggleButtonWithDefaults(enabled = true, modifier = Modifier.testTag(TEST_TAG))
}
rule.onNodeWithTag(TEST_TAG).onChildAt(0).assertHasClickAction()
@@ -702,10 +596,7 @@
@Test
fun split_button_has_click_action_when_disabled() {
rule.setContent {
- SplitToggleButtonWithDefaults(
- enabled = false,
- modifier = Modifier.testTag(TEST_TAG)
- )
+ SplitToggleButtonWithDefaults(enabled = false, modifier = Modifier.testTag(TEST_TAG))
}
rule.onNodeWithTag(TEST_TAG).onChildAt(0).assertHasClickAction()
@@ -713,32 +604,21 @@
@Test
fun split_button_is_toggleable() {
- rule.setContent {
- SplitToggleButtonWithDefaults(
- modifier = Modifier.testTag(TEST_TAG)
- )
- }
+ rule.setContent { SplitToggleButtonWithDefaults(modifier = Modifier.testTag(TEST_TAG)) }
rule.onNode(isToggleable()).assertExists()
}
@Test
fun split_button_is_clickable() {
- rule.setContent {
- SplitToggleButtonWithDefaults(
- modifier = Modifier.testTag(TEST_TAG)
- )
- }
+ rule.setContent { SplitToggleButtonWithDefaults(modifier = Modifier.testTag(TEST_TAG)) }
rule.onNodeWithTag(TEST_TAG).onChildAt(0).assertHasClickAction()
}
@Test
fun split_button_is_correctly_enabled() {
rule.setContent {
- SplitToggleButtonWithDefaults(
- enabled = true,
- modifier = Modifier.testTag(TEST_TAG)
- )
+ SplitToggleButtonWithDefaults(enabled = true, modifier = Modifier.testTag(TEST_TAG))
}
rule.onNodeWithTag(TEST_TAG).assertIsEnabled()
@@ -747,10 +627,7 @@
@Test
fun split_button_is_correctly_disabled() {
rule.setContent {
- SplitToggleButtonWithDefaults(
- enabled = false,
- modifier = Modifier.testTag(TEST_TAG)
- )
+ SplitToggleButtonWithDefaults(enabled = false, modifier = Modifier.testTag(TEST_TAG))
}
rule.onNodeWithTag(TEST_TAG).onChildAt(0).assertIsNotEnabled()
@@ -759,10 +636,7 @@
@Test
fun split_button_is_off_when_unchecked() {
rule.setContent {
- SplitToggleButtonWithDefaults(
- checked = false,
- modifier = Modifier.testTag(TEST_TAG)
- )
+ SplitToggleButtonWithDefaults(checked = false, modifier = Modifier.testTag(TEST_TAG))
}
rule.onNodeWithTag(TEST_TAG).onChildAt(1).assertIsOff()
@@ -771,10 +645,7 @@
@Test
fun split_button_is_on_when_checked() {
rule.setContent {
- SplitToggleButtonWithDefaults(
- checked = true,
- modifier = Modifier.testTag(TEST_TAG)
- )
+ SplitToggleButtonWithDefaults(checked = true, modifier = Modifier.testTag(TEST_TAG))
}
rule.onNodeWithTag(TEST_TAG).onChildAt(1).assertIsOn()
@@ -792,12 +663,7 @@
)
}
- rule
- .onNodeWithTag(TEST_TAG)
- .onChildAt(1)
- .assertIsOff()
- .performClick()
- .assertIsOn()
+ rule.onNodeWithTag(TEST_TAG).onChildAt(1).assertIsOff().performClick().assertIsOn()
}
@Test
@@ -812,12 +678,7 @@
)
}
- rule
- .onNodeWithTag(TEST_TAG)
- .onChildAt(1)
- .assertIsOn()
- .performClick()
- .assertIsOff()
+ rule.onNodeWithTag(TEST_TAG).onChildAt(1).assertIsOn().performClick().assertIsOff()
}
@Test
@@ -832,29 +693,17 @@
)
}
- rule
- .onNodeWithTag(TEST_TAG)
- .onChildAt(1)
- .assertIsOff()
- .performClick()
- .assertIsOff()
+ rule.onNodeWithTag(TEST_TAG).onChildAt(1).assertIsOff().performClick().assertIsOff()
}
@Test
fun split_button_clickable_has_role_button() {
- rule.setContent {
- SplitToggleButtonWithDefaults(
- modifier = Modifier.testTag(TEST_TAG)
- )
- }
+ rule.setContent { SplitToggleButtonWithDefaults(modifier = Modifier.testTag(TEST_TAG)) }
- rule.onNodeWithTag(TEST_TAG).onChildAt(0)
- .assert(
- SemanticsMatcher.expectValue(
- SemanticsProperties.Role,
- Role.Button
- )
- )
+ rule
+ .onNodeWithTag(TEST_TAG)
+ .onChildAt(0)
+ .assert(SemanticsMatcher.expectValue(SemanticsProperties.Role, Role.Button))
}
@Test
@@ -865,9 +714,7 @@
SplitToggleButtonWithDefaults(
checked = true,
onCheckedChange = {},
- label = {
- TestText(text = textContent)
- }
+ label = { TestText(text = textContent) }
)
}
@@ -937,9 +784,7 @@
}
}
- rule.onNodeWithTag(TEST_TAG)
- .captureToImage()
- .assertContainsColor(expectedColor)
+ rule.onNodeWithTag(TEST_TAG).captureToImage().assertContainsColor(expectedColor)
}
@RequiresApi(Build.VERSION_CODES.O)
@@ -968,9 +813,7 @@
}
}
- rule.onNodeWithTag(TEST_TAG)
- .captureToImage()
- .assertContainsColor(expectedColor)
+ rule.onNodeWithTag(TEST_TAG).captureToImage().assertContainsColor(expectedColor)
}
@RequiresApi(Build.VERSION_CODES.O)
@@ -986,18 +829,11 @@
) {
val testBackground = Color.White
val expectedColor = { color: Color ->
- if (color != Color.Transparent)
- color.compositeOver(testBackground)
- else
- testBackground
+ if (color != Color.Transparent) color.compositeOver(testBackground) else testBackground
}
rule.setContent {
- Box(
- modifier = Modifier
- .fillMaxSize()
- .background(testBackground)
- ) {
+ Box(modifier = Modifier.fillMaxSize().background(testBackground)) {
val actualBorderColor = borderColor(enabled, checked).value
val border = BorderStroke(2.dp, actualBorderColor)
RoundToggleButtonWithDefaults(
@@ -1006,43 +842,33 @@
enabled = enabled,
checked = checked,
modifier = Modifier.testTag(TEST_TAG)
- ) {
- }
+ ) {}
}
}
- rule.onNodeWithTag(TEST_TAG)
+ rule
+ .onNodeWithTag(TEST_TAG)
.captureToImage()
.assertContainsColor(expectedColor(expectedBackgroundColor), backgroundThreshold)
- rule.onNodeWithTag(TEST_TAG)
+ rule
+ .onNodeWithTag(TEST_TAG)
.captureToImage()
.assertContainsColor(expectedColor(expectedBorderColor), borderThreshold)
}
- private fun verifyTapSize(
- expected: Dp,
- content: @Composable () -> Unit
- ) {
- rule.setContent {
- content()
- }
+ private fun verifyTapSize(expected: Dp, content: @Composable () -> Unit) {
+ rule.setContent { content() }
- rule.onNodeWithTag(TEST_TAG)
+ rule
+ .onNodeWithTag(TEST_TAG)
.assertTouchHeightIsEqualTo(expected)
.assertTouchWidthIsEqualTo(expected)
}
- private fun verifyVisibleSize(
- expected: Dp,
- content: @Composable () -> Unit
- ) {
- rule.setContent {
- content()
- }
+ private fun verifyVisibleSize(expected: Dp, content: @Composable () -> Unit) {
+ rule.setContent { content() }
- rule.onNodeWithTag(TEST_TAG)
- .assertHeightIsEqualTo(expected)
- .assertWidthIsEqualTo(expected)
+ rule.onNodeWithTag(TEST_TAG).assertHeightIsEqualTo(expected).assertWidthIsEqualTo(expected)
}
}
@@ -1052,16 +878,14 @@
checked: Boolean = true,
onCheckedChange: (Boolean) -> Unit = {},
enabled: Boolean = true,
- backgroundColor: @Composable (enabled: Boolean, checked: Boolean) -> State<Color> =
- { _, _ -> rememberUpdatedState(DEFAULT_SHAPE_COLOR) },
- border: @Composable (enabled: Boolean, checked: Boolean) -> BorderStroke? =
- { _, _ -> null },
+ backgroundColor: @Composable (enabled: Boolean, checked: Boolean) -> State<Color> = { _, _ ->
+ rememberUpdatedState(DEFAULT_SHAPE_COLOR)
+ },
+ border: @Composable (enabled: Boolean, checked: Boolean) -> BorderStroke? = { _, _ -> null },
toggleButtonSize: Dp = 52.dp,
interactionSource: MutableInteractionSource? = null,
shape: Shape = CircleShape,
- content: @Composable BoxScope.() -> Unit = {
- TestText(text = "Label")
- }
+ content: @Composable BoxScope.() -> Unit = { TestText(text = "Label") }
) {
ToggleButton(
checked = checked,
@@ -1083,11 +907,7 @@
modifier: Modifier = Modifier,
checked: Boolean = true,
onCheckedChange: (Boolean) -> Unit = {},
- label: @Composable RowScope.() -> Unit = {
- TestText(
- text = "Label"
- )
- },
+ label: @Composable RowScope.() -> Unit = { TestText(text = "Label") },
toggleControl: (@Composable () -> Unit)? = { TestImage() },
selectionControl: (@Composable () -> Unit)? = null,
icon: @Composable (BoxScope.() -> Unit)? = null,
@@ -1097,47 +917,45 @@
},
enabled: Boolean = true,
interactionSource: MutableInteractionSource? = null,
- contentPadding: PaddingValues = PaddingValues(
- start = CHIP_HORIZONTAL_PADDING,
- top = CHIP_VERTICAL_PADDING,
- end = CHIP_HORIZONTAL_PADDING,
- bottom = CHIP_VERTICAL_PADDING
- ),
+ contentPadding: PaddingValues =
+ PaddingValues(
+ start = CHIP_HORIZONTAL_PADDING,
+ top = CHIP_VERTICAL_PADDING,
+ end = CHIP_HORIZONTAL_PADDING,
+ bottom = CHIP_VERTICAL_PADDING
+ ),
shape: Shape = CHIP_SHAPE,
selectionControlWidth: Dp = 24.dp,
selectionControlHeight: Dp = 24.dp
-) = ToggleButton(
- checked = checked,
- onCheckedChange = onCheckedChange,
- label = label,
- toggleControl = toggleControl,
- selectionControl = selectionControl,
- modifier = modifier,
- icon = icon,
- secondaryLabel = secondaryLabel,
- background = background,
- enabled = enabled,
- interactionSource = interactionSource,
- contentPadding = contentPadding,
- shape = shape,
- toggleControlWidth = selectionControlWidth,
- toggleControlHeight = selectionControlHeight,
- labelSpacerSize = 0.dp,
- toggleControlSpacing = 6.dp,
- iconSpacing = 6.dp,
- ripple = EmptyIndication,
-)
+) =
+ ToggleButton(
+ checked = checked,
+ onCheckedChange = onCheckedChange,
+ label = label,
+ toggleControl = toggleControl,
+ selectionControl = selectionControl,
+ modifier = modifier,
+ icon = icon,
+ secondaryLabel = secondaryLabel,
+ background = background,
+ enabled = enabled,
+ interactionSource = interactionSource,
+ contentPadding = contentPadding,
+ shape = shape,
+ toggleControlWidth = selectionControlWidth,
+ toggleControlHeight = selectionControlHeight,
+ labelSpacerSize = 0.dp,
+ toggleControlSpacing = 6.dp,
+ iconSpacing = 6.dp,
+ ripple = EmptyIndication,
+ )
@Composable
private fun SplitToggleButtonWithDefaults(
modifier: Modifier = Modifier,
checked: Boolean = true,
onCheckedChange: (Boolean) -> Unit = {},
- label: @Composable RowScope.() -> Unit = {
- TestText(
- text = "Primary label"
- )
- },
+ label: @Composable RowScope.() -> Unit = { TestText(text = "Primary label") },
onClick: () -> Unit = {},
toggleControl: (@Composable BoxScope.() -> Unit)? = { TestImage() },
selectionControl: (@Composable BoxScope.() -> Unit)? = null,
@@ -1152,32 +970,34 @@
enabled: Boolean = true,
checkedInteractionSource: MutableInteractionSource? = null,
clickInteractionSource: MutableInteractionSource? = null,
- contentPadding: PaddingValues = PaddingValues(
- start = CHIP_HORIZONTAL_PADDING,
- top = CHIP_VERTICAL_PADDING,
- end = CHIP_HORIZONTAL_PADDING,
- bottom = CHIP_VERTICAL_PADDING
- ),
+ contentPadding: PaddingValues =
+ PaddingValues(
+ start = CHIP_HORIZONTAL_PADDING,
+ top = CHIP_VERTICAL_PADDING,
+ end = CHIP_HORIZONTAL_PADDING,
+ bottom = CHIP_VERTICAL_PADDING
+ ),
shape: Shape = CHIP_SHAPE
-) = SplitToggleButton(
- checked = checked,
- onCheckedChange = onCheckedChange,
- label = label,
- onClick = onClick,
- toggleControl = toggleControl,
- selectionControl = selectionControl,
- modifier = modifier,
- secondaryLabel = secondaryLabel,
- backgroundColor = backgroundColor,
- splitBackgroundColor = splitBackgroundColor,
- enabled = enabled,
- checkedInteractionSource = checkedInteractionSource,
- clickInteractionSource = clickInteractionSource,
- contentPadding = contentPadding,
- shape = shape,
- labelSpacerSize = 0.dp,
- ripple = EmptyIndication,
-)
+) =
+ SplitToggleButton(
+ checked = checked,
+ onCheckedChange = onCheckedChange,
+ label = label,
+ onClick = onClick,
+ toggleControl = toggleControl,
+ selectionControl = selectionControl,
+ modifier = modifier,
+ secondaryLabel = secondaryLabel,
+ backgroundColor = backgroundColor,
+ splitBackgroundColor = splitBackgroundColor,
+ enabled = enabled,
+ checkedInteractionSource = checkedInteractionSource,
+ clickInteractionSource = clickInteractionSource,
+ contentPadding = contentPadding,
+ shape = shape,
+ labelSpacerSize = 0.dp,
+ ripple = EmptyIndication,
+ )
private val CHIP_HORIZONTAL_PADDING = 14.dp
private val CHIP_VERTICAL_PADDING = 6.dp
diff --git a/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/BoundsLimiter.kt b/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/BoundsLimiter.kt
index e73e153..11f2db5 100644
--- a/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/BoundsLimiter.kt
+++ b/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/BoundsLimiter.kt
@@ -44,40 +44,37 @@
offset: Density.() -> IntOffset,
size: Density.() -> IntSize,
modifier: Modifier = Modifier,
- onSizeChanged: (IntSize) -> Unit = { },
+ onSizeChanged: (IntSize) -> Unit = {},
content: @Composable BoxScope.() -> Unit
-) = Box(
- modifier = Modifier
- .fillMaxSize()
- .onSizeChanged(onSizeChanged)
- .absoluteOffset(offset),
- contentAlignment = AbsoluteAlignment.TopLeft
-) {
- // This Box has the position and size we need, so any modifiers passed in should be applied
- // here. We set the size using a custom modifier (that passes the constraints transparently to
- // the content), and add a negative offset to make the content believe is drawing at the top
- // left (position 0, 0).
+) =
Box(
- modifier
- .transparentSizeModifier(size)
- .absoluteOffset { -offset() }, content = content,
+ modifier = Modifier.fillMaxSize().onSizeChanged(onSizeChanged).absoluteOffset(offset),
contentAlignment = AbsoluteAlignment.TopLeft
- )
-}
+ ) {
+ // This Box has the position and size we need, so any modifiers passed in should be applied
+ // here. We set the size using a custom modifier (that passes the constraints transparently
+ // to
+ // the content), and add a negative offset to make the content believe is drawing at the top
+ // left (position 0, 0).
+ Box(
+ modifier.transparentSizeModifier(size).absoluteOffset { -offset() },
+ content = content,
+ contentAlignment = AbsoluteAlignment.TopLeft
+ )
+ }
// Sets the size of this element, but lets the child measure using the constraints
// of the element containing this.
-private fun Modifier.transparentSizeModifier(size: Density.() -> IntSize): Modifier = this.then(
- object : LayoutModifier {
- override fun MeasureScope.measure(
- measurable: Measurable,
- constraints: Constraints
- ): MeasureResult {
- val placeable = measurable.measure(constraints)
- val actualSize = size()
- return layout(actualSize.width, actualSize.height) {
- placeable.place(0, 0)
+private fun Modifier.transparentSizeModifier(size: Density.() -> IntSize): Modifier =
+ this.then(
+ object : LayoutModifier {
+ override fun MeasureScope.measure(
+ measurable: Measurable,
+ constraints: Constraints
+ ): MeasureResult {
+ val placeable = measurable.measure(constraints)
+ val actualSize = size()
+ return layout(actualSize.width, actualSize.height) { placeable.place(0, 0) }
}
}
- }
-)
+ )
diff --git a/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/Card.kt b/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/Card.kt
index 3285a6fb..056052d 100644
--- a/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/Card.kt
+++ b/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/Card.kt
@@ -55,30 +55,30 @@
* Cards can be enabled or disabled. A disabled card will not respond to click events.
*
* For more information, see the
- * [Cards](https://developer.android.com/training/wearables/components/cards)
- * Wear OS Material design guide.
+ * [Cards](https://developer.android.com/training/wearables/components/cards) Wear OS Material
+ * design guide.
*
* @param onClick Will be called when the user clicks the card
* @param modifier Modifier to be applied to the card
- * @param border A BorderStroke object which is used for the outline drawing.
- * Can be null - then outline will not be drawn
- * @param containerPainter A painter used to paint the background of the card. A card will
- * normally have a gradient background. Use [CardDefaults.cardBackgroundPainter()] to obtain an
- * appropriate painter
+ * @param border A BorderStroke object which is used for the outline drawing. Can be null - then
+ * outline will not be drawn
+ * @param containerPainter A painter used to paint the background of the card. A card will normally
+ * have a gradient background. Use [CardDefaults.cardBackgroundPainter()] to obtain an appropriate
+ * painter
* @param containerPainter A Painter which is used for background drawing.
- * @param enabled Controls the enabled state of the card. When false, this card will not
- * be clickable and there will be no ripple effect on click. Wear cards do not have any specific
- * elevation or alpha differences when not enabled - they are simply not clickable.
+ * @param enabled Controls the enabled state of the card. When false, this card will not be
+ * clickable and there will be no ripple effect on click. Wear cards do not have any specific
+ * elevation or alpha differences when not enabled - they are simply not clickable.
* @param contentPadding The spacing values to apply internally between the container and the
- * content
+ * content
* @param shape Defines the card's shape. It is strongly recommended to use the default as this
- * shape is a key characteristic of the Wear Material Theme
+ * shape is a key characteristic of the Wear Material Theme
* @param interactionSource an optional hoisted [MutableInteractionSource] for observing and
- * emitting [Interaction]s for this card. You can use this to change the card's appearance
- * or preview the card in different states. Note that if `null` is provided, interactions will
- * still happen internally.
- * @param role The type of user interface element. Accessibility services might use this
- * to describe the element or do customizations
+ * emitting [Interaction]s for this card. You can use this to change the card's appearance or
+ * preview the card in different states. Note that if `null` is provided, interactions will still
+ * happen internally.
+ * @param role The type of user interface element. Accessibility services might use this to describe
+ * the element or do customizations
* @param ripple Ripple used for this card
* @param content A main slot for a content of this card
*/
@@ -98,25 +98,21 @@
content: @Composable ColumnScope.() -> Unit,
) {
Column(
- modifier = modifier
- .fillMaxWidth()
- .height(IntrinsicSize.Min)
- .clip(shape = shape)
- .paint(
- painter = containerPainter,
- contentScale = ContentScale.Crop
- )
- .clickable(
- enabled = enabled,
- onClick = onClick,
- role = role,
- indication = ripple,
- interactionSource = interactionSource,
- )
- .then(
- border?.let { Modifier.border(border = border, shape = shape) } ?: Modifier
- )
- .padding(contentPadding),
+ modifier =
+ modifier
+ .fillMaxWidth()
+ .height(IntrinsicSize.Min)
+ .clip(shape = shape)
+ .paint(painter = containerPainter, contentScale = ContentScale.Crop)
+ .clickable(
+ enabled = enabled,
+ onClick = onClick,
+ role = role,
+ indication = ripple,
+ interactionSource = interactionSource,
+ )
+ .then(border?.let { Modifier.border(border = border, shape = shape) } ?: Modifier)
+ .padding(contentPadding),
content = content
)
}
@@ -129,48 +125,46 @@
* application developers to show information about different parts of their application.
*
* The first row of the layout has three slots, 1) a small optional application [Image] or [Icon],
- * 2) an application name, it is expected to be a short start-aligned [Text] composable,
- * and 3) the optional time that the application activity has occurred which will be
- * shown on the top row of the card, this is expected to be an end aligned [Text] composable
- * showing a time relevant to the contents of the [Card].
+ * 2) an application name, it is expected to be a short start-aligned [Text] composable, and 3) the
+ * optional time that the application activity has occurred which will be shown on the top row of
+ * the card, this is expected to be an end aligned [Text] composable showing a time relevant to
+ * the contents of the [Card].
*
* The second row shows a title, this is expected to be a single row of start aligned [Text].
*
- * The rest of the [Card] contains the content which can be either [Text] or an [Image].
- * If the content is text it can be single or multiple line and is expected to be Top and Start
- * aligned.
+ * The rest of the [Card] contains the content which can be either [Text] or an [Image]. If the
+ * content is text it can be single or multiple line and is expected to be Top and Start aligned.
*
* If more than one composable is provided in the content slot it is the responsibility of the
* caller to determine how to layout the contents, e.g. provide either a row or a column.
*
* For more information, see the
- * [Cards](https://developer.android.com/training/wearables/components/cards)
- * guide.
+ * [Cards](https://developer.android.com/training/wearables/components/cards) guide.
*
* @param onClick Will be called when the user clicks the card
* @param modifier Modifier to be applied to the card
- * @param enabled Controls the enabled state of the card. When false, this card will not
- * be clickable and there will be no ripple effect on click. Wear cards do not have any specific
- * elevation or alpha differences when not enabled - they are simply not clickable.
- * @param border A BorderStroke object which is used for the outline drawing.
- * Can be null - then outline will not be drawn
+ * @param enabled Controls the enabled state of the card. When false, this card will not be
+ * clickable and there will be no ripple effect on click. Wear cards do not have any specific
+ * elevation or alpha differences when not enabled - they are simply not clickable.
+ * @param border A BorderStroke object which is used for the outline drawing. Can be null - then
+ * outline will not be drawn
* @param contentPadding The spacing values to apply internally between the container and the
- * content
+ * content
* @param containerPainter A Painter which is used for background drawing.
* @param interactionSource an optional hoisted [MutableInteractionSource] for observing and
- * emitting [Interaction]s for this card. You can use this to change the card's appearance
- * or preview the card in different states. Note that if `null` is provided, interactions will
- * still happen internally.
+ * emitting [Interaction]s for this card. You can use this to change the card's appearance or
+ * preview the card in different states. Note that if `null` is provided, interactions will still
+ * happen internally.
* @param shape Defines the card's shape. It is strongly recommended to use the default as this
- * shape is a key characteristic of the Wear Material Theme
+ * shape is a key characteristic of the Wear Material Theme
* @param ripple Ripple used for this card
* @param appImage A slot for a small [Image] associated with the application.
* @param appName A slot for displaying the application name, expected to be a single line of start
- * aligned text.
+ * aligned text.
* @param time A slot for displaying the time relevant to the contents of the card, expected to be a
- * short piece of end aligned text.
+ * short piece of end aligned text.
* @param title A slot for displaying the title of the card, expected to be one or two lines of
- * start aligned text.
+ * start aligned text.
* @param content A main slot for a content of this card
*/
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
@@ -215,9 +209,7 @@
appName()
Spacer(modifier = Modifier.weight(1.0f))
- time?.let {
- time()
- }
+ time?.let { time() }
}
Spacer(modifier = Modifier.height(4.dp))
Row(
diff --git a/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/HorizontalPageIndicator.kt b/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/HorizontalPageIndicator.kt
index c47701d..d5f1bc3 100644
--- a/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/HorizontalPageIndicator.kt
+++ b/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/HorizontalPageIndicator.kt
@@ -24,10 +24,7 @@
* recalculating alpha and size parameters of each indicator, and selected indicators as well.
*/
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-class PagesState(
- val totalPages: Int,
- val pagesOnScreen: Int
-) {
+class PagesState(val totalPages: Int, val pagesOnScreen: Int) {
// Sizes and alphas of first and last indicators on the screen. Used to show that there're more
// pages on the left or on the right, and also for smooth transitions
private var firstAlpha = 1f
@@ -86,8 +83,8 @@
}
/**
- * Returns a value in the range 0..1 where 0 is unselected state, and 1 is selected.
- * Used to show a smooth transition between page indicator items.
+ * Returns a value in the range 0..1 where 0 is unselected state, and 1 is selected. Used to
+ * show a smooth transition between page indicator items.
*/
fun calculateSelectedRatio(targetPage: Int, offset: Float): Float =
(1 - abs(visibleDotIndex + offset - targetPage)).coerceAtLeast(0f)
@@ -106,8 +103,8 @@
if (selectedPage > hiddenPagesToTheLeft + pagesOnScreen - 2) {
// Set an offset as a difference between current page and pages on the screen,
// except if this is not the last page - then offsetInPages is not changed
- hiddenPagesToTheLeft = (selectedPage - (pagesOnScreen - 2))
- .coerceAtMost(totalPages - pagesOnScreen)
+ hiddenPagesToTheLeft =
+ (selectedPage - (pagesOnScreen - 2)).coerceAtMost(totalPages - pagesOnScreen)
} else if (pageWithOffset <= hiddenPagesToTheLeft) {
hiddenPagesToTheLeft = (selectedPage - 1).coerceAtLeast(0)
}
@@ -115,8 +112,9 @@
// Condition for scrolling to the right. A smooth scroll to the right is only triggered
// when we have more than 2 pages to the right, and currently we're on the right edge.
// For example -> o O O O X o -> a small "o" shows that there're more pages to the right
- val scrolledToTheRight = pageWithOffset > hiddenPagesToTheLeft + pagesOnScreen - 2 &&
- pageWithOffset < totalPages - 2
+ val scrolledToTheRight =
+ pageWithOffset > hiddenPagesToTheLeft + pagesOnScreen - 2 &&
+ pageWithOffset < totalPages - 2
// Condition for scrolling to the left. A smooth scroll to the left is only triggered
// when we have more than 2 pages to the left, and currently we're on the left edge.
@@ -131,34 +129,34 @@
secondSize = 1 - 0.5f * smoothProgress
// Depending on offsetInPages we'll either show a shrinked first indicator, or full-size
- firstSize = if (hiddenPagesToTheLeft == 0 ||
- hiddenPagesToTheLeft == 1 && scrolledToTheLeft
- ) {
- 1 - smoothProgress
- } else {
- 0.5f * (1 - smoothProgress)
- }
+ firstSize =
+ if (hiddenPagesToTheLeft == 0 || hiddenPagesToTheLeft == 1 && scrolledToTheLeft) {
+ 1 - smoothProgress
+ } else {
+ 0.5f * (1 - smoothProgress)
+ }
// Depending on offsetInPages and other parameters, we'll either show a shrinked
// last indicator, or full-size
lastSize =
- if (hiddenPagesToTheLeft == totalPages - pagesOnScreen - 1 && scrolledToTheRight ||
- hiddenPagesToTheLeft == totalPages - pagesOnScreen && scrolledToTheLeft
+ if (
+ hiddenPagesToTheLeft == totalPages - pagesOnScreen - 1 && scrolledToTheRight ||
+ hiddenPagesToTheLeft == totalPages - pagesOnScreen && scrolledToTheLeft
) {
smoothProgress
} else {
0.5f * smoothProgress
}
- lastButOneSize = if (scrolledToTheRight || scrolledToTheLeft) {
- 0.5f * (1 + smoothProgress)
- } else if (hiddenPagesToTheLeft < totalPages - pagesOnScreen) 0.5f else 1f
+ lastButOneSize =
+ if (scrolledToTheRight || scrolledToTheLeft) {
+ 0.5f * (1 + smoothProgress)
+ } else if (hiddenPagesToTheLeft < totalPages - pagesOnScreen) 0.5f else 1f
// A visibleDot represents a currently selected page on the screen
// As we scroll to the left, we add an invisible indicator to the left, shifting all other
// indicators to the right. The shift is only possible when a visibleDot = 1,
// thus we have to leave it at 1 as we always add a positive offset
- visibleDotIndex = if (scrolledToTheLeft) 1
- else selectedPage - hiddenPagesToTheLeft
+ visibleDotIndex = if (scrolledToTheLeft) 1 else selectedPage - hiddenPagesToTheLeft
}
}
diff --git a/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/Icon.kt b/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/Icon.kt
index 51eed78..a52d381 100644
--- a/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/Icon.kt
+++ b/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/Icon.kt
@@ -37,43 +37,37 @@
/**
* Icon component that draws a [painter] using [tint].
- * TODO:// Add link to Chip for a clickable icon
*
* @param painter [Painter] to draw inside this Icon
* @param contentDescription Text used by accessibility services to describe what this icon
- * represents. This should always be provided unless this icon is used for decorative purposes,
- * and does not represent a meaningful action that a user can take. This text should be
- * localized, such as by using [androidx.compose.ui.res.stringResource] or similar
+ * represents. This should always be provided unless this icon is used for decorative purposes,
+ * and does not represent a meaningful action that a user can take. This text should be localized,
+ * such as by using [androidx.compose.ui.res.stringResource] or similar
* @param modifier Optional [Modifier] for this Icon
- * @param tint Tint to be applied to [painter]. If [Color.Unspecified] is provided, then no
- * tint is applied
+ * @param tint Tint to be applied to [painter]. If [Color.Unspecified] is provided, then no tint is
+ * applied
+ *
+ * TODO:// Add link to Chip for a clickable icon
*/
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
@Composable
-fun Icon(
- painter: Painter,
- contentDescription: String?,
- modifier: Modifier,
- tint: Color
-) {
- val colorFilter = remember(tint) {
- if (tint == Color.Unspecified) null else ColorFilter.tint(tint)
- }
- val semantics = if (contentDescription != null) {
- Modifier.semantics {
- this.contentDescription = contentDescription
- this.role = Role.Image
+fun Icon(painter: Painter, contentDescription: String?, modifier: Modifier, tint: Color) {
+ val colorFilter =
+ remember(tint) { if (tint == Color.Unspecified) null else ColorFilter.tint(tint) }
+ val semantics =
+ if (contentDescription != null) {
+ Modifier.semantics {
+ this.contentDescription = contentDescription
+ this.role = Role.Image
+ }
+ } else {
+ Modifier
}
- } else {
- Modifier
- }
Box(
- modifier.toolingGraphicsLayer().defaultSizeFor(painter)
- .paint(
- painter,
- colorFilter = colorFilter,
- contentScale = ContentScale.Fit
- )
+ modifier
+ .toolingGraphicsLayer()
+ .defaultSizeFor(painter)
+ .paint(painter, colorFilter = colorFilter, contentScale = ContentScale.Fit)
.then(semantics)
)
}
diff --git a/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/ImageWithScrimPainter.kt b/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/ImageWithScrimPainter.kt
index f7372b7..3e96b65 100644
--- a/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/ImageWithScrimPainter.kt
+++ b/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/ImageWithScrimPainter.kt
@@ -24,8 +24,8 @@
import androidx.compose.ui.graphics.painter.Painter
/**
- * A painter which wraps another [Painter] for drawing a background image and a [Brush] which
- * is used to create an effect over the image to ensure that text drawn over it will be legible.
+ * A painter which wraps another [Painter] for drawing a background image and a [Brush] which is
+ * used to create an effect over the image to ensure that text drawn over it will be legible.
*/
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
class ImageWithScrimPainter(
@@ -81,8 +81,6 @@
"scrimAlpha=$scrimAlpha, alpha=$alpha)"
}
- /**
- * Size of the combined painter, return Unspecified to allow us to fill the available space
- */
+ /** Size of the combined painter, return Unspecified to allow us to fill the available space */
override val intrinsicSize: Size = imagePainter.intrinsicSize
}
diff --git a/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/RangeDefaults.kt b/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/RangeDefaults.kt
index 7aff03b..6ae5ba7 100644
--- a/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/RangeDefaults.kt
+++ b/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/RangeDefaults.kt
@@ -23,59 +23,55 @@
import androidx.compose.ui.util.lerp
import kotlin.math.roundToInt
-/**
- * Icons which are used by Range controls like slider and stepper
- */
+/** Icons which are used by Range controls like slider and stepper */
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
public object RangeIcons {
- /**
- * An [ImageVector] with a minus sign.
- */
+ /** An [ImageVector] with a minus sign. */
val Minus: ImageVector
- get() = if (_minus != null) _minus!!
- else {
- _minus = materialIcon(name = "MinusIcon") {
- materialPath {
- moveTo(19.0f, 13.0f)
- horizontalLineTo(5.0f)
- verticalLineToRelative(-2.0f)
- horizontalLineToRelative(14.0f)
- verticalLineToRelative(2.0f)
- close()
- }
+ get() =
+ if (_minus != null) _minus!!
+ else {
+ _minus =
+ materialIcon(name = "MinusIcon") {
+ materialPath {
+ moveTo(19.0f, 13.0f)
+ horizontalLineTo(5.0f)
+ verticalLineToRelative(-2.0f)
+ horizontalLineToRelative(14.0f)
+ verticalLineToRelative(2.0f)
+ close()
+ }
+ }
+ _minus!!
}
- _minus!!
- }
private var _minus: ImageVector? = null
}
-/**
- * Defaults used by range controls like slider and stepper
- */
+/** Defaults used by range controls like slider and stepper */
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
public object RangeDefaults {
- /**
- * Calculates value of [currentStep] in [valueRange] depending on number of [steps]
- */
+ /** Calculates value of [currentStep] in [valueRange] depending on number of [steps] */
fun calculateCurrentStepValue(
currentStep: Int,
steps: Int,
valueRange: ClosedFloatingPointRange<Float>
- ): Float = lerp(
- valueRange.start, valueRange.endInclusive,
- currentStep.toFloat() / (steps + 1).toFloat()
- ).coerceIn(valueRange)
+ ): Float =
+ lerp(
+ valueRange.start,
+ valueRange.endInclusive,
+ currentStep.toFloat() / (steps + 1).toFloat()
+ )
+ .coerceIn(valueRange)
- /**
- * Snaps [value] to the closest [step] in the [valueRange]
- */
+ /** Snaps [value] to the closest [step] in the [valueRange] */
fun snapValueToStep(
value: Float,
valueRange: ClosedFloatingPointRange<Float>,
steps: Int
- ): Int = ((value - valueRange.start) /
- (valueRange.endInclusive - valueRange.start) * (steps + 1))
- .roundToInt().coerceIn(0, steps + 1)
+ ): Int =
+ ((value - valueRange.start) / (valueRange.endInclusive - valueRange.start) * (steps + 1))
+ .roundToInt()
+ .coerceIn(0, steps + 1)
}
diff --git a/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/RepeatableClickable.kt b/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/RepeatableClickable.kt
index 8ad068a..2718c9f 100644
--- a/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/RepeatableClickable.kt
+++ b/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/RepeatableClickable.kt
@@ -39,32 +39,31 @@
import kotlinx.coroutines.launch
/**
- * This modifier provides functionality to increment or decrement values repeatedly
- * by holding down the composable.
- * Should be used instead of clickable modifier to achieve clickable and repeatable
+ * This modifier provides functionality to increment or decrement values repeatedly by holding down
+ * the composable. Should be used instead of clickable modifier to achieve clickable and repeatable
* clickable behavior. Can't be used along with clickable modifier as it already implements it.
*
- * Callbacks [onClick] and [onRepeatableClick] are different. [onClick] is triggered only
- * when the hold duration is shorter than [initialDelay] and no repeatable clicks happened.
- * [onRepeatableClick] is repeatedly triggered when the hold duration is longer
- * than [initialDelay] with [incrementalDelay] intervals.
+ * Callbacks [onClick] and [onRepeatableClick] are different. [onClick] is triggered only when the
+ * hold duration is shorter than [initialDelay] and no repeatable clicks happened.
+ * [onRepeatableClick] is repeatedly triggered when the hold duration is longer than [initialDelay]
+ * with [incrementalDelay] intervals.
*
* @param interactionSource [MutableInteractionSource] that will be used to dispatch
- * [PressInteraction.Press] when this clickable is pressed. If `null`, an internal
- * [MutableInteractionSource] will be created when needed.
- * @param indication indication to be shown when modified element is pressed. By default,
- * indication from [LocalIndication] will be used. Pass `null` to show no indication, or
- * current value from [LocalIndication] to show theme default
- * @param enabled Controls the enabled state. When `false`, [onClick], and this modifier will
- * appear disabled for accessibility services
+ * [PressInteraction.Press] when this clickable is pressed. If `null`, an internal
+ * [MutableInteractionSource] will be created when needed.
+ * @param indication indication to be shown when modified element is pressed. By default, indication
+ * from [LocalIndication] will be used. Pass `null` to show no indication, or current value from
+ * [LocalIndication] to show theme default
+ * @param enabled Controls the enabled state. When `false`, [onClick], and this modifier will appear
+ * disabled for accessibility services
* @param onClickLabel semantic / accessibility label for the [onClick] action
- * @param role the type of user interface element. Accessibility services might use this
- * to describe the element or do customizations
+ * @param role the type of user interface element. Accessibility services might use this to describe
+ * the element or do customizations
* @param initialDelay The initial delay before the click starts repeating, in ms
* @param incrementalDelay The delay between each repeated click, in ms
* @param onClick will be called when user clicks on the element
- * @param onRepeatableClick will be called after the [initialDelay] with [incrementalDelay]
- * between each call until the touch is released
+ * @param onRepeatableClick will be called after the [initialDelay] with [incrementalDelay] between
+ * each call until the touch is released
*/
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
fun Modifier.repeatableClickable(
@@ -88,18 +87,18 @@
// Repeatable logic should always follow the clickable, as the lowest modifier finishes first,
// and we have to be sure that repeatable goes before clickable.
clickable(
- interactionSource = interactionSource,
- indication = indication,
- enabled = enabled,
- onClickLabel = onClickLabel,
- role = role,
- onClick = {
- if (!ignoreOnClick) {
- currentOnClick()
- }
- ignoreOnClick = false
- },
- )
+ interactionSource = interactionSource,
+ indication = indication,
+ enabled = enabled,
+ onClickLabel = onClickLabel,
+ role = role,
+ onClick = {
+ if (!ignoreOnClick) {
+ currentOnClick()
+ }
+ ignoreOnClick = false
+ },
+ )
.pointerInput(enabled) {
coroutineScope {
awaitEachGesture {
diff --git a/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/RoundButton.kt b/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/RoundButton.kt
index 86a7f66..ce22467 100644
--- a/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/RoundButton.kt
+++ b/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/RoundButton.kt
@@ -44,18 +44,17 @@
* [RoundButton] can be enabled or disabled. A disabled button will not respond to click events.
*
* For more information, see the
- * [Buttons](https://developer.android.com/training/wearables/components/buttons)
- * guide.
+ * [Buttons](https://developer.android.com/training/wearables/components/buttons) guide.
*
* @param onClick Will be called when the user clicks the button.
* @param modifier Modifier to be applied to the button.
- * @param enabled Controls the enabled state of the button. When `false`, this button will not
- * be clickable.
+ * @param enabled Controls the enabled state of the button. When `false`, this button will not be
+ * clickable.
* @param backgroundColor Resolves the background for this button in different states.
* @param interactionSource an optional hoisted [MutableInteractionSource] for observing and
- * emitting [Interaction]s for this button. You can use this to change the button's appearance
- * or preview the button in different states. Note that if `null` is provided, interactions will
- * still happen internally.
+ * emitting [Interaction]s for this button. You can use this to change the button's appearance or
+ * preview the button in different states. Note that if `null` is provided, interactions will
+ * still happen internally.
* @param shape Defines the button's shape.
* @param border Resolves the border for this button in different states.
* @param buttonSize The default size of the button unless overridden by Modifier.size.
@@ -79,24 +78,22 @@
val borderStroke = border(enabled)
Box(
contentAlignment = Alignment.Center,
- modifier = modifier
- .semantics { role = Role.Button }
- .size(buttonSize)
- .clip(shape) // Clip for the touch area (e.g. for Ripple).
- .clickable(
- onClick = onClick,
- enabled = enabled,
- interactionSource = interactionSource,
- indication = ripple,
- )
- .then(
- if (borderStroke != null) Modifier.border(border = borderStroke, shape = shape)
- else Modifier
- )
- .background(
- color = backgroundColor(enabled),
- shape = shape
- ),
+ modifier =
+ modifier
+ .semantics { role = Role.Button }
+ .size(buttonSize)
+ .clip(shape) // Clip for the touch area (e.g. for Ripple).
+ .clickable(
+ onClick = onClick,
+ enabled = enabled,
+ interactionSource = interactionSource,
+ indication = ripple,
+ )
+ .then(
+ if (borderStroke != null) Modifier.border(border = borderStroke, shape = shape)
+ else Modifier
+ )
+ .background(color = backgroundColor(enabled), shape = shape),
content = content
)
}
diff --git a/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/SelectionControls.kt b/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/SelectionControls.kt
index 114fd30..aa1b486 100644
--- a/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/SelectionControls.kt
+++ b/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/SelectionControls.kt
@@ -61,17 +61,16 @@
* [Checkbox] provides an animated checkbox for use in material APIs.
*
* @param checked Boolean flag indicating whether this checkbox is currently checked.
- * @param modifier Modifier to be applied to the checkbox.
- * This can be used to provide a content description for accessibility.
+ * @param modifier Modifier to be applied to the checkbox. This can be used to provide a content
+ * description for accessibility.
* @param boxColor Composable lambda from which the box color will be obtained.
* @param checkmarkColor Composable lambda from which the check mark color will be obtained.
- * @param enabled Boolean flag indicating the enabled state of the [Checkbox] (affects
- * the color).
+ * @param enabled Boolean flag indicating the enabled state of the [Checkbox] (affects the color).
* @param onCheckedChange Callback to be invoked when Checkbox is clicked. If null, then this is
- * passive and relies entirely on a higher-level component to control the state.
+ * passive and relies entirely on a higher-level component to control the state.
* @param interactionSource When also providing [onCheckedChange], the [MutableInteractionSource]
- * representing the stream of [Interaction]s for the "toggleable" tap area -
- * can be used to customise the appearance / behavior of the Checkbox.
+ * representing the stream of [Interaction]s for the "toggleable" tap area - can be used to
+ * customise the appearance / behavior of the Checkbox.
* @param progressAnimationSpec Animation spec to animate the progress.
* @param drawBox Draws the checkbox.
* @param width Width of the checkbox.
@@ -96,9 +95,12 @@
) {
val targetState = if (checked) SelectionStage.Checked else SelectionStage.Unchecked
val transition = updateTransition(targetState, label = "checkboxTransition")
- val progress = animateProgress(
- transition = transition, label = "Checkbox", animationSpec = progressAnimationSpec
- )
+ val progress =
+ animateProgress(
+ transition = transition,
+ label = "Checkbox",
+ animationSpec = progressAnimationSpec
+ )
val isRtl = isLayoutDirectionRtl()
val startXOffset = if (isRtl) 0.dp else width - height
@@ -110,57 +112,54 @@
// Canvas internally uses Spacer.drawBehind.
// Using Spacer.drawWithCache to optimize the stroke allocations.
Spacer(
- modifier = modifier
- .semantics {
- this.role = Role.Checkbox
- }
- .maybeToggleable(
- onCheckedChange,
- enabled,
- checked,
- interactionSource,
- ripple,
- width,
- height
- )
- .drawWithCache
- {
- onDrawWithContent {
- drawBox(this, boxColorState.value, progress.value, isRtl)
- animateTick(
- enabled = enabled,
- checked = checked,
- tickColor = checkmarkColorState.value,
- tickProgress = progress.value,
- startXOffset = startXOffset
- )
+ modifier =
+ modifier
+ .semantics { this.role = Role.Checkbox }
+ .maybeToggleable(
+ onCheckedChange,
+ enabled,
+ checked,
+ interactionSource,
+ ripple,
+ width,
+ height
+ )
+ .drawWithCache {
+ onDrawWithContent {
+ drawBox(this, boxColorState.value, progress.value, isRtl)
+ animateTick(
+ enabled = enabled,
+ checked = checked,
+ tickColor = checkmarkColorState.value,
+ tickProgress = progress.value,
+ startXOffset = startXOffset
+ )
+ }
}
- }
)
}
/**
* [Switch] provides an animated switch for use in material APIs.
*
- * @param modifier Modifier to be applied to the switch.
- * This can be used to provide a content description for accessibility.
+ * @param modifier Modifier to be applied to the switch. This can be used to provide a content
+ * description for accessibility.
* @param checked Boolean flag indicating whether this switch is currently toggled on.
- * @param enabled Boolean flag indicating the enabled state of the [Switch] (affects
- * the color).
+ * @param enabled Boolean flag indicating the enabled state of the [Switch] (affects the color).
* @param onCheckedChange Callback to be invoked when Switch is clicked. If null, then this is
- * passive and relies entirely on a higher-level component to control the state.
+ * passive and relies entirely on a higher-level component to control the state.
* @param interactionSource When also providing [onCheckedChange], the [MutableInteractionSource]
- * representing the stream of [Interaction]s for the "toggleable" tap area -
- * can be used to customise the appearance / behavior of the Switch.
+ * representing the stream of [Interaction]s for the "toggleable" tap area - can be used to
+ * customise the appearance / behavior of the Switch.
* @param trackFillColor Composable lambda from which the fill color of the track will be obtained.
- * @param trackStrokeColor Composable lambda from which the stroke color of the track will be obtained.
+ * @param trackStrokeColor Composable lambda from which the stroke color of the track will be
+ * obtained.
* @param thumbColor Composable lambda from which the thumb color will be obtained.
* @param thumbIconColor Composable lambda from which the icon color will be obtained.
* @param trackWidth Width of the track.
* @param trackHeight Height of the track.
- * @param drawThumb Lambda function to draw the thumb of the switch.
- * The lambda is invoked with trackFillColor as the icon color, along with the thumbColor,
- * and the progress.
+ * @param drawThumb Lambda function to draw the thumb of the switch. The lambda is invoked with
+ * trackFillColor as the icon color, along with the thumbColor, and the progress.
* @param progressAnimationSpec Animation spec to animate the progress.
* @param width Width of the switch.
* @param height Height of the switch.
@@ -190,11 +189,7 @@
val transition = updateTransition(targetState, label = "switchTransition")
val isRtl = isLayoutDirectionRtl()
- val thumbProgress = animateProgress(
- transition,
- "Switch",
- progressAnimationSpec
- )
+ val thumbProgress = animateProgress(transition, "Switch", progressAnimationSpec)
val thumbBackgroundColor = thumbColor(enabled, checked)
val iconColor = thumbIconColor(enabled, checked)
@@ -204,56 +199,56 @@
// Canvas internally uses Spacer.drawBehind.
// Using Spacer.drawWithCache to optimize the stroke allocations.
Spacer(
- modifier = modifier
- .semantics {
- this.role = Role.Switch
- }
- .maybeToggleable(
- onCheckedChange,
- enabled,
- checked,
- interactionSource,
- ripple,
- width,
- height
- )
- .drawWithCache
- {
- onDrawWithContent {
- drawTrack(
- fillColor = trackBackgroundFillColor.value,
- strokeColor = trackBackgroundStrokeColor.value,
- trackWidthPx = trackWidth.toPx(),
- trackHeightPx = trackHeight.toPx()
- )
+ modifier =
+ modifier
+ .semantics { this.role = Role.Switch }
+ .maybeToggleable(
+ onCheckedChange,
+ enabled,
+ checked,
+ interactionSource,
+ ripple,
+ width,
+ height
+ )
+ .drawWithCache {
+ onDrawWithContent {
+ drawTrack(
+ fillColor = trackBackgroundFillColor.value,
+ strokeColor = trackBackgroundStrokeColor.value,
+ trackWidthPx = trackWidth.toPx(),
+ trackHeightPx = trackHeight.toPx()
+ )
- // Draw the thumb of the switch.
- drawThumb(
- this,
- thumbBackgroundColor.value,
- thumbProgress.value,
- iconColor.value,
- isRtl
- )
+ // Draw the thumb of the switch.
+ drawThumb(
+ this,
+ thumbBackgroundColor.value,
+ thumbProgress.value,
+ iconColor.value,
+ isRtl
+ )
+ }
}
- })
+ )
}
/**
* [RadioButton] provides an animated radio button for use in material APIs.
*
- * @param modifier Modifier to be applied to the radio button. This can be used to provide a
- * content description for accessibility.
+ * @param modifier Modifier to be applied to the radio button. This can be used to provide a content
+ * description for accessibility.
* @param selected Boolean flag indicating whether this radio button is currently toggled on.
- * @param enabled Boolean flag indicating the enabled state of the [RadioButton] (affects
- * the color).
- * @param ringColor Composable lambda from which the ring color of the radio button will be obtained.
+ * @param enabled Boolean flag indicating the enabled state of the [RadioButton] (affects the
+ * color).
+ * @param ringColor Composable lambda from which the ring color of the radio button will be
+ * obtained.
* @param dotColor Composable lambda from which the dot color of the radio button will be obtained.
- * @param onClick Callback to be invoked when RadioButton is clicked. If null, then this is
- * passive and relies entirely on a higher-level component to control the state.
+ * @param onClick Callback to be invoked when RadioButton is clicked. If null, then this is passive
+ * and relies entirely on a higher-level component to control the state.
* @param interactionSource When also providing [onClick], the [MutableInteractionSource]
- * representing the stream of [Interaction]s for the "toggleable" tap area -
- * can be used to customise the appearance / behavior of the RadioButton.
+ * representing the stream of [Interaction]s for the "toggleable" tap area - can be used to
+ * customise the appearance / behavior of the RadioButton.
* @param dotRadiusProgressDuration Duration of the dot radius progress animation.
* @param dotAlphaProgressDuration Duration of the dot alpha progress animation.
* @param dotAlphaProgressDelay Delay for the dot alpha progress animation.
@@ -287,60 +282,65 @@
val radioRingColor = ringColor(enabled, selected)
val radioDotColor = dotColor(enabled, selected)
- val dotRadiusProgress = animateProgress(
- transition = transition,
- label = "dot-radius",
- animationSpec = tween(dotRadiusProgressDuration(selected), 0, easing)
- )
+ val dotRadiusProgress =
+ animateProgress(
+ transition = transition,
+ label = "dot-radius",
+ animationSpec = tween(dotRadiusProgressDuration(selected), 0, easing)
+ )
// Animation of the dot alpha only happens when toggling On to Off.
val dotAlphaProgress =
if (targetState == SelectionStage.Unchecked)
animateProgress(
transition = transition,
label = "dot-alpha",
- animationSpec = tween(
- dotAlphaProgressDuration,
- dotAlphaProgressDelay,
- easing
- )
+ animationSpec = tween(dotAlphaProgressDuration, dotAlphaProgressDelay, easing)
)
- else
- null
+ else null
// Canvas internally uses Spacer.drawBehind.
// Using Spacer.drawWithCache to optimize the stroke allocations.
Spacer(
// NB We must set the semantic role to Role.RadioButton in the parent Button,
// not here in the selection control - see b/330869742
- modifier = modifier
- .maybeSelectable(
- onClick, enabled, selected, interactionSource, ripple, width, height
- )
- .drawWithCache
- {
- // Aligning the radio to the end.
- val startXOffsetPx = if (isRtl) -(width - height).toPx() / 2 else
- (width - height).toPx() / 2
- // Outer circle has a constant radius.
- onDrawWithContent {
- val circleCenter = Offset(center.x + startXOffsetPx, center.y)
- drawCircle(
- radius = RADIO_CIRCLE_RADIUS.toPx(),
- color = radioRingColor.value,
- center = circleCenter,
- style = Stroke(RADIO_CIRCLE_STROKE.toPx()),
- )
- // Inner dot radius expands/shrinks.
- drawCircle(
- radius = dotRadiusProgress.value * RADIO_DOT_RADIUS.toPx(),
- color = radioDotColor.value.copy(
- alpha = (dotAlphaProgress?.value ?: 1f) * radioDotColor.value.alpha
- ),
- center = circleCenter,
- style = Fill,
- )
+ modifier =
+ modifier
+ .maybeSelectable(
+ onClick,
+ enabled,
+ selected,
+ interactionSource,
+ ripple,
+ width,
+ height
+ )
+ .drawWithCache {
+ // Aligning the radio to the end.
+ val startXOffsetPx =
+ if (isRtl) -(width - height).toPx() / 2 else (width - height).toPx() / 2
+ // Outer circle has a constant radius.
+ onDrawWithContent {
+ val circleCenter = Offset(center.x + startXOffsetPx, center.y)
+ drawCircle(
+ radius = RADIO_CIRCLE_RADIUS.toPx(),
+ color = radioRingColor.value,
+ center = circleCenter,
+ style = Stroke(RADIO_CIRCLE_STROKE.toPx()),
+ )
+ // Inner dot radius expands/shrinks.
+ drawCircle(
+ radius = dotRadiusProgress.value * RADIO_DOT_RADIUS.toPx(),
+ color =
+ radioDotColor.value.copy(
+ alpha =
+ (dotAlphaProgress?.value ?: 1f) * radioDotColor.value.alpha
+ ),
+ center = circleCenter,
+ style = Fill,
+ )
+ }
}
- })
+ )
}
/**
@@ -350,8 +350,10 @@
* @param checked Boolean flag checking if the selection control is checked [SelectionStage].
* @param checkedColor Color for selection control when [enabled] = true and [checked] = true.
* @param uncheckedColor Color for selection control when [enabled] = true and [checked] = false.
- * @param disabledCheckedColor Color for selection control when [enabled] = false and [checked] = true.
- * @param disabledUncheckedColor Color for selection control when [enabled] = false and [checked] = false.
+ * @param disabledCheckedColor Color for selection control when [enabled] = false and [checked] =
+ * true.
+ * @param disabledUncheckedColor Color for selection control when [enabled] = false and [checked] =
+ * false.
* @param animationSpec AnimationSpec for the color transition animations.
*/
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
@@ -364,18 +366,21 @@
disabledCheckedColor: Color,
disabledUncheckedColor: Color,
animationSpec: AnimationSpec<Color>
-): State<Color> = animateColorAsState(
- targetValue = if (enabled) {
- if (checked) checkedColor else uncheckedColor
- } else {
- if (checked) disabledCheckedColor else disabledUncheckedColor
- },
- animationSpec = animationSpec
-)
+): State<Color> =
+ animateColorAsState(
+ targetValue =
+ if (enabled) {
+ if (checked) checkedColor else uncheckedColor
+ } else {
+ if (checked) disabledCheckedColor else disabledUncheckedColor
+ },
+ animationSpec = animationSpec
+ )
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
enum class SelectionStage {
- Unchecked, Checked
+ Unchecked,
+ Checked
}
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
@@ -422,16 +427,13 @@
transition: Transition<SelectionStage>,
label: String,
animationSpec: TweenSpec<Float>,
-) = transition.animateFloat(
- transitionSpec = {
- animationSpec
- }, label = label
-) {
- when (it) {
- SelectionStage.Unchecked -> 0f
- SelectionStage.Checked -> 1f
+) =
+ transition.animateFloat(transitionSpec = { animationSpec }, label = label) {
+ when (it) {
+ SelectionStage.Unchecked -> 0f
+ SelectionStage.Checked -> 1f
+ }
}
-}
private fun Modifier.maybeToggleable(
onCheckedChange: ((Boolean) -> Unit)?,
@@ -442,9 +444,8 @@
canvasWidth: Dp,
canvasHeight: Dp
): Modifier {
- val standardModifier = this
- .wrapContentSize(Alignment.CenterEnd)
- .requiredSize(canvasWidth, canvasHeight)
+ val standardModifier =
+ this.wrapContentSize(Alignment.CenterEnd).requiredSize(canvasWidth, canvasHeight)
return if (onCheckedChange == null) {
standardModifier
@@ -470,9 +471,8 @@
canvasWidth: Dp,
canvasHeight: Dp
): Modifier {
- val standardModifier = this
- .wrapContentSize(Alignment.Center)
- .requiredSize(canvasWidth, canvasHeight)
+ val standardModifier =
+ this.wrapContentSize(Alignment.Center).requiredSize(canvasWidth, canvasHeight)
return if (onClick == null) {
standardModifier
@@ -523,16 +523,16 @@
// Move back to the start of the stick (without drawing)
path.moveTo(stickStart.rotate(angleRadians, center))
path.lineTo(
- Offset(stickStart.x + tickStickProgress, stickStart.y - tickStickProgress).rotate(
- angleRadians,
- center
- )
+ Offset(stickStart.x + tickStickProgress, stickStart.y - tickStickProgress)
+ .rotate(angleRadians, center)
)
}
// Use StrokeCap.Butt because Square adds an extension on the end of each line.
drawPath(
- path, tickColor, style = Stroke(width = 2.dp.toPx(), cap = StrokeCap.Butt), blendMode =
- if (enabled) DefaultBlendMode else BlendMode.Hardlight
+ path,
+ tickColor,
+ style = Stroke(width = 2.dp.toPx(), cap = StrokeCap.Butt),
+ blendMode = if (enabled) DefaultBlendMode else BlendMode.Hardlight
)
}
@@ -559,10 +559,11 @@
drawPath(
path = path,
color = fillColor,
- style = Stroke(
- width = trackHeightPx - 2 * SWITCH_TRACK_BORDER.toPx(),
- cap = StrokeCap.Round
- )
+ style =
+ Stroke(
+ width = trackHeightPx - 2 * SWITCH_TRACK_BORDER.toPx(),
+ cap = StrokeCap.Round
+ )
)
}
}
@@ -598,8 +599,10 @@
}
drawPath(
- path, tickColor, style = Stroke(width = 2.dp.toPx(), cap = StrokeCap.Butt), blendMode =
- if (enabled) DefaultBlendMode else BlendMode.Hardlight
+ path,
+ tickColor,
+ style = Stroke(width = 2.dp.toPx(), cap = StrokeCap.Butt),
+ blendMode = if (enabled) DefaultBlendMode else BlendMode.Hardlight
)
}
@@ -626,8 +629,7 @@
// This is duplicated from wear.compose.foundation/geometry.kt
// Any changes should be replicated there.
-@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-fun Float.toRadians() = this * PI.toFloat() / 180f
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) fun Float.toRadians() = this * PI.toFloat() / 180f
private val TICK_BASE_LENGTH = 4.dp
private val TICK_STICK_LENGTH = 8.dp
diff --git a/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/Slider.kt b/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/Slider.kt
index d88aaa0..f506730 100644
--- a/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/Slider.kt
+++ b/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/Slider.kt
@@ -42,16 +42,16 @@
content: @Composable () -> Unit
) {
Box(
- modifier = Modifier
- .width(buttonControlSize)
- .fillMaxHeight()
- .repeatableClickable(
- enabled = enabled,
- onClick = onClick,
- interactionSource = null,
- indication = LocalIndication.current
- )
- .then(modifier),
+ modifier =
+ Modifier.width(buttonControlSize)
+ .fillMaxHeight()
+ .repeatableClickable(
+ enabled = enabled,
+ onClick = onClick,
+ interactionSource = null,
+ indication = LocalIndication.current
+ )
+ .then(modifier),
contentAlignment = contentAlignment
) {
content()
diff --git a/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/Stepper.kt b/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/Stepper.kt
index 0e9ca3f..bd81b9a 100644
--- a/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/Stepper.kt
+++ b/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/Stepper.kt
@@ -41,36 +41,34 @@
import androidx.compose.ui.unit.dp
/**
- * [Stepper] allows users to make a selection from a range of values.
- * It's a full-screen control with increase button on the top, decrease button on the bottom and
- * a slot (expected to have either [Text] or [Chip]) in the middle.
- * Value can be increased and decreased by clicking on the increase and decrease buttons.
- * Buttons can have custom icons - [decreaseIcon] and [increaseIcon].
+ * [Stepper] allows users to make a selection from a range of values. It's a full-screen control
+ * with increase button on the top, decrease button on the bottom and a slot (expected to have
+ * either [Text] or [Chip]) in the middle. Value can be increased and decreased by clicking on the
+ * increase and decrease buttons. Buttons can have custom icons - [decreaseIcon] and [increaseIcon].
* Step value is calculated as the difference between min and max values divided by [steps]+1.
* Stepper itself doesn't show the current value but can be displayed via the content slot or
- * [PositionIndicator] if required.
- * If [value] is not equal to any step value, then it will be coerced to the closest step value.
- * However, the [value] itself will not be changed and [onValueChange] in this case will
- * not be triggered.
+ * [PositionIndicator] if required. If [value] is not equal to any step value, then it will be
+ * coerced to the closest step value. However, the [value] itself will not be changed and
+ * [onValueChange] in this case will not be triggered.
*
* @param value Current value of the Stepper. If outside of [valueRange] provided, value will be
- * coerced to this range.
+ * coerced to this range.
* @param onValueChange Lambda in which value should be updated
* @param steps Specifies the number of discrete values, excluding min and max values, evenly
- * distributed across the whole value range. Must not be negative. If 0, stepper will have only
- * min and max values and no steps in between
+ * distributed across the whole value range. Must not be negative. If 0, stepper will have only
+ * min and max values and no steps in between
* @param decreaseIcon A slot for an icon which is placed on the decrease (bottom) button
* @param increaseIcon A slot for an icon which is placed on the increase (top) button
* @param modifier Modifiers for the Stepper layout
* @param valueRange Range of values that Stepper value can take. Passed [value] will be coerced to
- * this range
+ * this range
* @param backgroundColor [Color] representing the background color for the stepper.
* @param enabledButtonProviderValues Values of CompositionLocal providers for enabled button such
- * as LocalContentColor, LocalContentAlpha, LocalTextStyle which are dependent on a specific
- * material design version and are not part of this material-agnostic library.
+ * as LocalContentColor, LocalContentAlpha, LocalTextStyle which are dependent on a specific
+ * material design version and are not part of this material-agnostic library.
* @param disabledButtonProviderValues Values of CompositionLocal providers for disabled button such
- * as LocalContentColor, LocalContentAlpha, LocalTextStyle which are dependent on a specific
- * material design version and are not part of this material-agnostic library.
+ * as LocalContentColor, LocalContentAlpha, LocalTextStyle which are dependent on a specific
+ * material design version and are not part of this material-agnostic library.
* @param buttonRipple Unbounded ripple used for the decrease and increase button
* @param content Content body for the Stepper.
*/
@@ -91,11 +89,10 @@
content: @Composable BoxScope.() -> Unit
) {
require(steps >= 0) { "steps should be >= 0" }
- val currentStep = remember(value, valueRange, steps) {
- RangeDefaults.snapValueToStep(
- value, valueRange, steps
- )
- }
+ val currentStep =
+ remember(value, valueRange, steps) {
+ RangeDefaults.snapValueToStep(value, valueRange, steps)
+ }
val updateValue: (Int) -> Unit = { stepDiff ->
val newValue =
@@ -104,9 +101,7 @@
}
Column(
- modifier = modifier
- .fillMaxSize()
- .background(backgroundColor),
+ modifier = modifier.fillMaxSize().background(backgroundColor),
verticalArrangement = Arrangement.spacedBy(8.dp)
) {
val increaseButtonEnabled = currentStep < steps + 1
@@ -118,15 +113,14 @@
contentAlignment = Alignment.TopCenter,
paddingValues = PaddingValues(top = StepperDefaults.BorderPadding),
enabled = increaseButtonEnabled,
- buttonProviderValues = if (increaseButtonEnabled) enabledButtonProviderValues
- else disabledButtonProviderValues,
+ buttonProviderValues =
+ if (increaseButtonEnabled) enabledButtonProviderValues
+ else disabledButtonProviderValues,
ripple = buttonRipple,
content = increaseIcon
)
Box(
- modifier = Modifier
- .fillMaxWidth()
- .weight(StepperDefaults.ContentWeight),
+ modifier = Modifier.fillMaxWidth().weight(StepperDefaults.ContentWeight),
contentAlignment = Alignment.Center,
content = content
)
@@ -136,8 +130,9 @@
contentAlignment = Alignment.BottomCenter,
paddingValues = PaddingValues(bottom = StepperDefaults.BorderPadding),
enabled = decreaseButtonEnabled,
- buttonProviderValues = if (decreaseButtonEnabled) enabledButtonProviderValues
- else disabledButtonProviderValues,
+ buttonProviderValues =
+ if (decreaseButtonEnabled) enabledButtonProviderValues
+ else disabledButtonProviderValues,
ripple = buttonRipple,
content = decreaseIcon
)
@@ -156,29 +151,25 @@
) {
val interactionSource = remember { MutableInteractionSource() }
Box(
- modifier = Modifier
- .fillMaxWidth()
- .weight(StepperDefaults.ButtonWeight)
- .repeatableClickable(
- enabled = enabled,
- onClick = onClick,
- interactionSource = interactionSource,
- indication = null
- )
- .wrapContentWidth()
- .indication(interactionSource, ripple)
- .padding(paddingValues),
+ modifier =
+ Modifier.fillMaxWidth()
+ .weight(StepperDefaults.ButtonWeight)
+ .repeatableClickable(
+ enabled = enabled,
+ onClick = onClick,
+ interactionSource = interactionSource,
+ indication = null
+ )
+ .wrapContentWidth()
+ .indication(interactionSource, ripple)
+ .padding(paddingValues),
contentAlignment = contentAlignment,
) {
- CompositionLocalProvider(
- values = buttonProviderValues, content = content
- )
+ CompositionLocalProvider(values = buttonProviderValues, content = content)
}
}
-/**
- * Defaults used by stepper
- */
+/** Defaults used by stepper */
private object StepperDefaults {
const val ButtonWeight = 0.35f
const val ContentWeight = 0.3f
diff --git a/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/Text.kt b/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/Text.kt
index e11e3fc..9f75b8e 100644
--- a/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/Text.kt
+++ b/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/Text.kt
@@ -39,42 +39,42 @@
*
* For ease of use, commonly used parameters from [TextStyle] are also present here. The order of
* precedence is as follows:
- * - If a parameter is explicitly set here (i.e, it is _not_ `null` or [TextUnit.Unspecified]),
- * then this parameter will always be used.
+ * - If a parameter is explicitly set here (i.e, it is _not_ `null` or [TextUnit.Unspecified]), then
+ * this parameter will always be used.
* - If a parameter is _not_ set, (`null` or [TextUnit.Unspecified]), then the corresponding value
- * from [style] will be used instead.
+ * from [style] will be used instead.
*
* @param text The text to be displayed, where [AnnotatedString] allows multiple styles to be used.
* @param modifier [Modifier] to apply to this layout node.
* @param color [Color] to apply to the text.
* @param fontSize The size of glyphs to use when painting the text. See [TextStyle.fontSize].
- * @param fontStyle The typeface variant to use when drawing the letters (e.g., italic).
- * See [TextStyle.fontStyle].
+ * @param fontStyle The typeface variant to use when drawing the letters (e.g., italic). See
+ * [TextStyle.fontStyle].
* @param fontWeight The typeface thickness to use when painting the text (e.g., [FontWeight.Bold]).
* @param fontFamily The font family to be used when rendering the text. See [TextStyle.fontFamily].
- * @param letterSpacing The amount of space to add between each letter.
- * See [TextStyle.letterSpacing].
- * @param textDecoration The decorations to paint on the text (e.g., an underline).
- * See [TextStyle.textDecoration].
- * @param textAlign The alignment of the text within the lines of the paragraph.
- * See [TextStyle.textAlign].
- * @param lineHeight Line height for the [Paragraph] in [TextUnit] unit, e.g. SP or EM.
- * See [TextStyle.lineHeight].
+ * @param letterSpacing The amount of space to add between each letter. See
+ * [TextStyle.letterSpacing].
+ * @param textDecoration The decorations to paint on the text (e.g., an underline). See
+ * [TextStyle.textDecoration].
+ * @param textAlign The alignment of the text within the lines of the paragraph. See
+ * [TextStyle.textAlign].
+ * @param lineHeight Line height for the [Paragraph] in [TextUnit] unit, e.g. SP or EM. See
+ * [TextStyle.lineHeight].
* @param overflow How visual overflow should be handled.
* @param softWrap Whether the text should break at soft line breaks. If false, the glyphs in the
- * text will be positioned as if there was unlimited horizontal space. If [softWrap] is false,
- * [overflow] and TextAlign may have unexpected effects.
- * @param maxLines An optional maximum number of lines for the text to span, wrapping if
- * necessary. If the text exceeds the given number of lines, it will be truncated according to
- * [overflow] and [softWrap]. If it is not null, then it must be greater than zero.
+ * text will be positioned as if there was unlimited horizontal space. If [softWrap] is false,
+ * [overflow] and TextAlign may have unexpected effects.
+ * @param maxLines An optional maximum number of lines for the text to span, wrapping if necessary.
+ * If the text exceeds the given number of lines, it will be truncated according to [overflow] and
+ * [softWrap]. If it is not null, then it must be greater than zero.
* @param minLines The minimum height in terms of minimum number of visible lines. It is required
- * that 1 <= [minLines] <= [maxLines].
- * @param inlineContent A map store composables that replaces certain ranges of the text. It's
- * used to insert composables into text layout. Check [InlineTextContent] for more information.
+ * that 1 <= [minLines] <= [maxLines].
+ * @param inlineContent A map store composables that replaces certain ranges of the text. It's used
+ * to insert composables into text layout. Check [InlineTextContent] for more information.
* @param onTextLayout Callback that is executed when a new text layout is calculated. A
- * [TextLayoutResult] object that callback provides contains paragraph information, size of the
- * text, baselines and other details. The callback can be used to add additional decoration or
- * functionality to the text. For example, to draw selection around the text.
+ * [TextLayoutResult] object that callback provides contains paragraph information, size of the
+ * text, baselines and other details. The callback can be used to add additional decoration or
+ * functionality to the text. For example, to draw selection around the text.
* @param style Style configuration for the text such as color, font, line height etc.
*/
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
@@ -102,7 +102,8 @@
BasicText(
text = text,
modifier = modifier,
- style = style.merge(
+ style =
+ style.merge(
color = color,
fontSize = fontSize,
fontWeight = fontWeight,
@@ -112,7 +113,7 @@
textDecoration = textDecoration,
fontStyle = fontStyle,
letterSpacing = letterSpacing
- ),
+ ),
onTextLayout = onTextLayout,
overflow = overflow,
softWrap = softWrap,
diff --git a/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/ToggleButton.kt b/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/ToggleButton.kt
index 82b87b9..127ad75 100644
--- a/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/ToggleButton.kt
+++ b/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/ToggleButton.kt
@@ -59,8 +59,7 @@
import androidx.compose.ui.unit.dp
/**
- * Round [ToggleButton] that offers a single slot to take any content
- * (text, icon or image).
+ * Round [ToggleButton] that offers a single slot to take any content (text, icon or image).
*
* [ToggleButton]s can be enabled or disabled. A disabled toggle button will not respond to click
* events.
@@ -72,18 +71,18 @@
* @param checked Boolean flag indicating whether this toggle button is currently checked.
* @param onCheckedChange Callback to be invoked when this toggle button is clicked.
* @param modifier Modifier to be applied to the toggle button.
- * @param enabled Controls the enabled state of the toggle button. When `false`,
- * this toggle button will not be clickable.
+ * @param enabled Controls the enabled state of the toggle button. When `false`, this toggle button
+ * will not be clickable.
* @param backgroundColor Resolves the background for this toggle button in different states.
* @param border Resolves the border for this toggle button in different states.
* @param toggleButtonSize The default size of the toggle button unless overridden by
- * [Modifier.size].
+ * [Modifier.size].
* @param interactionSource an optional hoisted [MutableInteractionSource] for observing and
- * emitting [Interaction]s for this toggle button. You can use this to change the toggle button's
- * appearance or preview the toggle button in different states. Note that if `null` is provided,
- * interactions will still happen internally.
+ * emitting [Interaction]s for this toggle button. You can use this to change the toggle button's
+ * appearance or preview the toggle button in different states. Note that if `null` is provided,
+ * interactions will still happen internally.
* @param shape Defines the shape for this toggle button. It is strongly recommended to use the
- * default as this shape is a key characteristic of the Wear Material Theme.
+ * default as this shape is a key characteristic of the Wear Material Theme.
* @param ripple Ripple used for this toggle button
* @param content The icon, image or text to be drawn inside the toggle button.
*/
@@ -106,66 +105,63 @@
val borderStroke = border(enabled, checked)
Box(
contentAlignment = Alignment.Center,
- modifier = modifier
- .semantics { role = Role.Checkbox }
- .size(toggleButtonSize)
- .clip(shape) // Clip for the touch area (e.g. for Ripple).
- .toggleable(
- value = checked,
- onValueChange = onCheckedChange,
- enabled = enabled,
- interactionSource = interactionSource,
- indication = ripple
- )
- .then(
- if (borderStroke != null) Modifier.border(border = borderStroke, shape = shape)
- else Modifier
- )
- .background(
- color = backgroundColor(enabled, checked).value,
- shape = shape
- ),
+ modifier =
+ modifier
+ .semantics { role = Role.Checkbox }
+ .size(toggleButtonSize)
+ .clip(shape) // Clip for the touch area (e.g. for Ripple).
+ .toggleable(
+ value = checked,
+ onValueChange = onCheckedChange,
+ enabled = enabled,
+ interactionSource = interactionSource,
+ indication = ripple
+ )
+ .then(
+ if (borderStroke != null) Modifier.border(border = borderStroke, shape = shape)
+ else Modifier
+ )
+ .background(color = backgroundColor(enabled, checked).value, shape = shape),
content = content
)
}
/**
- * The Stadium-shaped [ToggleButton] offers four slots and a specific layout for an icon, a
- * label, a secondaryLabel and toggle control. The icon and secondaryLabel are optional.
- * The items are laid out in a row with the optional icon at the start, a column containing the two
- * label slots in the middle and a slot for the toggle control at the end.
+ * The Stadium-shaped [ToggleButton] offers four slots and a specific layout for an icon, a label, a
+ * secondaryLabel and toggle control. The icon and secondaryLabel are optional. The items are laid
+ * out in a row with the optional icon at the start, a column containing the two label slots in the
+ * middle and a slot for the toggle control at the end.
*
- * ToggleButtons can be enabled or disabled. A disabled ToggleButton will not respond to
- * click events.
+ * ToggleButtons can be enabled or disabled. A disabled ToggleButton will not respond to click
+ * events.
*
* @param checked Boolean flag indicating whether this button is currently checked.
* @param onCheckedChange Callback to be invoked when this buttons checked status is
- * @param label A slot for providing the ToggleButton's main label. The contents are expected
- * to be text which is "start" aligned.
+ * @param label A slot for providing the ToggleButton's main label. The contents are expected to be
+ * text which is "start" aligned.
* @param toggleControl A slot for providing a toggle control - one and only one of toggleControl
- * and selectionControl must be provided.
+ * and selectionControl must be provided.
* @param selectionControl A slot for providing a selection control - one and only one of
- * toggleControl and selectionControl must be provided.
- * @param modifier Modifier to be applied to the ToggleButton. Pass Modifier.height(height)
- * or Modifier.defaultMinSize(minHeight = minHeight) to set a fixed height or a minimum height
- * for the button respectively.
+ * toggleControl and selectionControl must be provided.
+ * @param modifier Modifier to be applied to the ToggleButton. Pass Modifier.height(height) or
+ * Modifier.defaultMinSize(minHeight = minHeight) to set a fixed height or a minimum height for
+ * the button respectively.
* @param icon An optional slot for providing an icon to indicate the purpose of the ToggleButton.
- * @param secondaryLabel A slot for providing the ToggleButton's secondary label.
- * The contents are expected to be text which is "start" aligned if there is an icon preset and
- * "start" or "center" aligned if not. label and secondaryLabel contents should be
- * consistently aligned.
- * @param background Composable lambda to set the background of the toggle button.
- * This expects to return Modifier.paint or Modifier.background for the background treatment.
- * @param enabled Controls the enabled state of the ToggleButton. When `false`,
- * this ToggleButton will not be clickable
+ * @param secondaryLabel A slot for providing the ToggleButton's secondary label. The contents are
+ * expected to be text which is "start" aligned if there is an icon preset and "start" or "center"
+ * aligned if not. label and secondaryLabel contents should be consistently aligned.
+ * @param background Composable lambda to set the background of the toggle button. This expects to
+ * return Modifier.paint or Modifier.background for the background treatment.
+ * @param enabled Controls the enabled state of the ToggleButton. When `false`, this ToggleButton
+ * will not be clickable
* @param interactionSource an optional hoisted [MutableInteractionSource] for observing and
- * emitting [Interaction]s for this toggle button. You can use this to change the toggle button's
- * appearance or preview the toggle button in different states. Note that if `null` is provided,
- * interactions will still happen internally.
+ * emitting [Interaction]s for this toggle button. You can use this to change the toggle button's
+ * appearance or preview the toggle button in different states. Note that if `null` is provided,
+ * interactions will still happen internally.
* @param contentPadding The spacing values to apply internally between the container and the
- * content
- * @param shape Defines the ToggleButton's shape. It is strongly recommended to use the
- * default as this shape is a key characteristic of the Wear Material Theme
+ * content
+ * @param shape Defines the ToggleButton's shape. It is strongly recommended to use the default as
+ * this shape is a key characteristic of the Wear Material Theme
* @param toggleControlWidth Width for the toggle control.
* @param toggleControlHeight Height for the toggle control.
* @param ripple Ripple used for this toggle button
@@ -200,54 +196,45 @@
// Stadium/Chip shaped toggle button
Row(
- modifier = modifier
- .clip(shape = shape)
- .width(IntrinsicSize.Max)
- .then(background(enabled, checked))
- .then(
- if (toggleControl != null) {
- Modifier.toggleable(
- enabled = enabled,
- value = checked,
- onValueChange = onCheckedChange,
- indication = ripple,
- interactionSource = interactionSource
- )
- // For a toggleable button, the role could be Checkbox or Switch,
- // so we cannot set the semantics here. Instead,
- // we set them in the toggle control
- } else {
- Modifier.selectable(
- enabled = enabled,
- selected = checked,
- onClick = { onCheckedChange(true) },
- indication = ripple,
- interactionSource = interactionSource
- ).semantics {
- // For a selectable button, the role is always RadioButton.
- // See also b/330869742 for issue with setting the RadioButton role
- // within the selection control.
- role = Role.RadioButton
+ modifier =
+ modifier
+ .clip(shape = shape)
+ .width(IntrinsicSize.Max)
+ .then(background(enabled, checked))
+ .then(
+ if (toggleControl != null) {
+ Modifier.toggleable(
+ enabled = enabled,
+ value = checked,
+ onValueChange = onCheckedChange,
+ indication = ripple,
+ interactionSource = interactionSource
+ )
+ // For a toggleable button, the role could be Checkbox or Switch,
+ // so we cannot set the semantics here. Instead,
+ // we set them in the toggle control
+ } else {
+ Modifier.selectable(
+ enabled = enabled,
+ selected = checked,
+ onClick = { onCheckedChange(true) },
+ indication = ripple,
+ interactionSource = interactionSource
+ )
+ .semantics {
+ // For a selectable button, the role is always RadioButton.
+ // See also b/330869742 for issue with setting the RadioButton role
+ // within the selection control.
+ role = Role.RadioButton
+ }
}
- }
- )
- .padding(contentPadding),
+ )
+ .padding(contentPadding),
verticalAlignment = Alignment.CenterVertically
) {
- ToggleButtonIcon(
- spacerSize = iconSpacing,
- content = icon
- )
- Labels(
- label = label,
- secondaryLabel = secondaryLabel,
- spacerSize = labelSpacerSize
- )
- Spacer(
- modifier = Modifier.size(
- toggleControlSpacing
- )
- )
+ ToggleButtonIcon(spacerSize = iconSpacing, content = icon)
+ Labels(label = label, secondaryLabel = secondaryLabel, spacerSize = labelSpacerSize)
+ Spacer(modifier = Modifier.size(toggleControlSpacing))
ToggleControl(
width = toggleControlWidth,
height = toggleControlHeight,
@@ -257,55 +244,52 @@
}
/**
- * The [SplitToggleButton] offers three slots and a specific layout for a label,
- * secondaryLabel and toggle control. The secondaryLabel is optional. The items are laid out
- * with a column containing the two label slots and a slot for the toggle control at the
- * end.
+ * The [SplitToggleButton] offers three slots and a specific layout for a label, secondaryLabel and
+ * toggle control. The secondaryLabel is optional. The items are laid out with a column containing
+ * the two label slots and a slot for the toggle control at the end.
*
* A [SplitToggleButton] has two tappable areas, one tap area for the labels and another for the
* toggle control. The [onClick] listener will be associated with the main body of the
- * SplitToggleButton with the [onCheckedChange] listener associated with the toggle
- * control area only.
+ * SplitToggleButton with the [onCheckedChange] listener associated with the toggle control area
+ * only.
*
- * For a SplitToggleButton the background of the tappable background area behind
- * the toggle control will have a visual effect applied to provide a "divider" between the two
- * tappable areas.
+ * For a SplitToggleButton the background of the tappable background area behind the toggle control
+ * will have a visual effect applied to provide a "divider" between the two tappable areas.
*
- * SplitToggleButton can be enabled or disabled. A disabled SplitToggleButton will not
- * respond to click events.
+ * SplitToggleButton can be enabled or disabled. A disabled SplitToggleButton will not respond to
+ * click events.
*
* @param checked Boolean flag indicating whether this button is currently checked.
- * @param onCheckedChange Callback to be invoked when this buttons checked status is
- * changed.
- * @param label A slot for providing the SplitToggleButton's main label.
- * The contents are expected to be text which is "start" aligned.
- * @param onClick Click listener called when the user clicks the main body of the
- * SplitToggleButton, the area behind the labels.
+ * @param onCheckedChange Callback to be invoked when this buttons checked status is changed.
+ * @param label A slot for providing the SplitToggleButton's main label. The contents are expected
+ * to be text which is "start" aligned.
+ * @param onClick Click listener called when the user clicks the main body of the SplitToggleButton,
+ * the area behind the labels.
* @param toggleControl A slot for providing a toggle control - one and only one of toggleControl
- * and selectionControl must be provided.
- * @param selectionControl A slot for providing a selection control - one and only one of toggleControl
- * and selectionControl must be provided.
+ * and selectionControl must be provided.
+ * @param selectionControl A slot for providing a selection control - one and only one of
+ * toggleControl and selectionControl must be provided.
* @param modifier Modifier to be applied to the SplitToggleButton
- * @param secondaryLabel A slot for providing the SplitToggleButton's secondary label.
- * The contents are expected to be "start" or "center" aligned. label and secondaryLabel
- * contents should be consistently aligned.
+ * @param secondaryLabel A slot for providing the SplitToggleButton's secondary label. The contents
+ * are expected to be "start" or "center" aligned. label and secondaryLabel contents should be
+ * consistently aligned.
* @param backgroundColor Composable lambda from which the backgroundColor will be obtained.
* @param splitBackgroundColor Composable lambda from which the splitBackgroundOverlay will be
- * obtained.
- * @param enabled Controls the enabled state of the SplitToggleButton. When `false`,
- * this SplitToggleButton will not be clickable
+ * obtained.
+ * @param enabled Controls the enabled state of the SplitToggleButton. When `false`, this
+ * SplitToggleButton will not be clickable
* @param checkedInteractionSource an optional hoisted [MutableInteractionSource] for observing and
- * emitting [Interaction]s for this button's "toggleable" tap area. You can use this to change the
- * button's appearance or preview the button in different states. Note that if `null` is provided,
- * interactions will still happen internally.
+ * emitting [Interaction]s for this button's "toggleable" tap area. You can use this to change the
+ * button's appearance or preview the button in different states. Note that if `null` is provided,
+ * interactions will still happen internally.
* @param clickInteractionSource an optional hoisted [MutableInteractionSource] for observing and
- * emitting [Interaction]s for this button's "clickable" tap area. You can use this to change the
- * button's appearance or preview the button in different states. Note that if `null` is provided,
- * interactions will still happen internally.
+ * emitting [Interaction]s for this button's "clickable" tap area. You can use this to change the
+ * button's appearance or preview the button in different states. Note that if `null` is provided,
+ * interactions will still happen internally.
* @param contentPadding The spacing values to apply internally between the container and the
- * content
- * @param shape Defines the SplitToggleButton's shape. It is strongly recommended to use the
- * default as this shape is a key characteristic of the Wear Material Theme
+ * content
+ * @param shape Defines the SplitToggleButton's shape. It is strongly recommended to use the default
+ * as this shape is a key characteristic of the Wear Material Theme
* @param ripple Ripple used for this toggle button
*/
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
@@ -333,99 +317,86 @@
Row(
verticalAlignment = Alignment.CenterVertically,
- modifier = modifier
- .width(IntrinsicSize.Max)
- .clip(shape = shape)
- .background(backgroundColor(enabled, checked).value)
+ modifier =
+ modifier
+ .width(IntrinsicSize.Max)
+ .clip(shape = shape)
+ .background(backgroundColor(enabled, checked).value)
) {
Row(
- modifier = Modifier
- .clickable(
- enabled = enabled,
- onClick = onClick,
- indication = ripple,
- interactionSource = clickInteractionSource,
- )
- .semantics {
- role = Role.Button
- }
- .fillMaxHeight()
- .then(startPadding)
- .weight(1.0f),
+ modifier =
+ Modifier.clickable(
+ enabled = enabled,
+ onClick = onClick,
+ indication = ripple,
+ interactionSource = clickInteractionSource,
+ )
+ .semantics { role = Role.Button }
+ .fillMaxHeight()
+ .then(startPadding)
+ .weight(1.0f),
verticalAlignment = Alignment.CenterVertically,
) {
- Labels(
- label = label,
- secondaryLabel = secondaryLabel,
- spacerSize = labelSpacerSize
- )
- Spacer(
- modifier = Modifier
- .size(TOGGLE_CONTROL_SPACING)
- )
+ Labels(label = label, secondaryLabel = secondaryLabel, spacerSize = labelSpacerSize)
+ Spacer(modifier = Modifier.size(TOGGLE_CONTROL_SPACING))
}
- val splitBackground = splitBackgroundColor(
- enabled,
- checked,
- ).value
+ val splitBackground =
+ splitBackgroundColor(
+ enabled,
+ checked,
+ )
+ .value
val boxModifier =
if (toggleControl != null) {
- Modifier
- .toggleable(
- enabled = enabled,
- value = checked,
- onValueChange = onCheckedChange,
- indication = ripple,
- interactionSource = checkedInteractionSource
- )
- } else {
- Modifier.selectable(
+ Modifier.toggleable(
enabled = enabled,
- selected = checked,
- onClick = { onCheckedChange(true) },
+ value = checked,
+ onValueChange = onCheckedChange,
indication = ripple,
interactionSource = checkedInteractionSource
)
- .semantics {
- // For a selectable button, the role is always RadioButton.
- // See also b/330869742 for issue with setting the RadioButton role
- // within the selection control.
- role = Role.RadioButton
- }
+ } else {
+ Modifier.selectable(
+ enabled = enabled,
+ selected = checked,
+ onClick = { onCheckedChange(true) },
+ indication = ripple,
+ interactionSource = checkedInteractionSource
+ )
+ .semantics {
+ // For a selectable button, the role is always RadioButton.
+ // See also b/330869742 for issue with setting the RadioButton role
+ // within the selection control.
+ role = Role.RadioButton
+ }
}
Box(
modifier =
- boxModifier
- .fillMaxHeight()
- .drawWithCache {
- onDrawWithContent {
- drawRect(color = splitBackground)
- drawContent()
+ boxModifier
+ .fillMaxHeight()
+ .drawWithCache {
+ onDrawWithContent {
+ drawRect(color = splitBackground)
+ drawContent()
+ }
}
- }
- .align(Alignment.CenterVertically)
- .width(SPLIT_WIDTH)
- .wrapContentHeight(align = Alignment.CenterVertically)
- .wrapContentWidth(align = Alignment.End)
- .then(endPadding),
+ .align(Alignment.CenterVertically)
+ .width(SPLIT_WIDTH)
+ .wrapContentHeight(align = Alignment.CenterVertically)
+ .wrapContentWidth(align = Alignment.End)
+ .then(endPadding),
content = toggleControl ?: selectionControl!!
)
}
}
@Composable
-private fun ToggleButtonIcon(
- spacerSize: Dp,
- content: @Composable (BoxScope.() -> Unit)? = null
-) {
+private fun ToggleButtonIcon(spacerSize: Dp, content: @Composable (BoxScope.() -> Unit)? = null) {
if (content != null) {
- Box(
- modifier = Modifier.wrapContentSize(align = Alignment.Center),
- content = content
- )
+ Box(modifier = Modifier.wrapContentSize(align = Alignment.Center), content = content)
Spacer(modifier = Modifier.size(spacerSize))
}
}
@@ -446,16 +417,12 @@
}
@Composable
-private fun RowScope.ToggleControl(
- width: Dp,
- height: Dp,
- content: @Composable () -> Unit
-) {
+private fun RowScope.ToggleControl(width: Dp, height: Dp, content: @Composable () -> Unit) {
Box(
- modifier = Modifier
- .align(Alignment.CenterVertically)
- .size(width = width, height = height)
- .wrapContentWidth(align = Alignment.End),
+ modifier =
+ Modifier.align(Alignment.CenterVertically)
+ .size(width = width, height = height)
+ .wrapContentWidth(align = Alignment.End),
) {
content()
}
@@ -468,14 +435,13 @@
end = 0.dp,
top = calculateTopPadding(),
bottom = calculateBottomPadding()
- ) to Modifier.padding(
- start = 0.dp,
- end = calculateEndPadding(
- layoutDirection = LocalLayoutDirection.current
- ),
- top = calculateTopPadding(),
- bottom = calculateBottomPadding()
- )
+ ) to
+ Modifier.padding(
+ start = 0.dp,
+ end = calculateEndPadding(layoutDirection = LocalLayoutDirection.current),
+ top = calculateTopPadding(),
+ bottom = calculateBottomPadding()
+ )
private val TOGGLE_CONTROL_SPACING = 4.dp
private val SPLIT_WIDTH = 52.dp
diff --git a/wear/compose/compose-material-core/src/test/kotlin/androidx/wear/compose/materialcore/HorizontalPageIndicatorTest.kt b/wear/compose/compose-material-core/src/test/kotlin/androidx/wear/compose/materialcore/HorizontalPageIndicatorTest.kt
index c27eb62..0b422a5 100644
--- a/wear/compose/compose-material-core/src/test/kotlin/androidx/wear/compose/materialcore/HorizontalPageIndicatorTest.kt
+++ b/wear/compose/compose-material-core/src/test/kotlin/androidx/wear/compose/materialcore/HorizontalPageIndicatorTest.kt
@@ -23,15 +23,8 @@
import org.junit.runners.JUnit4
/**
- * Pager might be represented as following ASCII Art:
- * *LS* o O O X O o _ RS
- * where:
- * LS - left spacer
- * o - small dot
- * O - big dot
- * _ - invisible dot
- * RS - right spacer
- * ** - size of the spacer
+ * Pager might be represented as following ASCII Art: *LS* o O O X O o _ RS where: LS - left spacer
+ * o - small dot O - big dot _ - invisible dot RS - right spacer ** - size of the spacer
*/
@RunWith(JUnit4::class)
class HorizontalPageIndicatorTest {
@@ -44,12 +37,7 @@
pagesState.recalculateState(selectedPage = 0, offset = 0f)
pagesState.testAllDots(
- listOf(
- TestDot(selectedRatio = 1f),
- TestDot(),
- TestDot(),
- TestDot()
- ),
+ listOf(TestDot(selectedRatio = 1f), TestDot(), TestDot(), TestDot()),
offset = 0f,
leftSpacerSize = 1f,
rightSpacerSize = 0f
@@ -62,12 +50,7 @@
pagesState.recalculateState(selectedPage = 2, offset = 0f)
pagesState.testAllDots(
- listOf(
- TestDot(),
- TestDot(),
- TestDot(selectedRatio = 1f),
- TestDot()
- ),
+ listOf(TestDot(), TestDot(), TestDot(selectedRatio = 1f), TestDot()),
offset = 0f,
leftSpacerSize = 1f,
rightSpacerSize = 0f
@@ -80,12 +63,7 @@
pagesState.recalculateState(selectedPage = 3, offset = 0f)
pagesState.testAllDots(
- listOf(
- TestDot(),
- TestDot(),
- TestDot(),
- TestDot(selectedRatio = 1f)
- ),
+ listOf(TestDot(), TestDot(), TestDot(), TestDot(selectedRatio = 1f)),
offset = 0f,
leftSpacerSize = 1f,
rightSpacerSize = 0f
@@ -141,10 +119,8 @@
}
/**
- * totalPages: 12 , selected page: 4, shifting right
- * Visually :
- * *LS* O O O O X o _ RS
- * >>> LS _ o O O O X o *RS*
+ * totalPages: 12 , selected page: 4, shifting right Visually : *LS* O O O O X o _ RS >>> LS _ o
+ * O O O X o *RS*
*/
@Test
fun shift_right_when_last_on_screen_dot_shifted_right_first_shift() {
@@ -170,10 +146,8 @@
}
/**
- * totalPages: 12 , selected page: 8, shifting right
- * Visually :
- * *LS* o O O O X o _ RS
- * >>> LS _ o O O O X o *RS*
+ * totalPages: 12 , selected page: 8, shifting right Visually : *LS* o O O O X o _ RS >>> LS _ o
+ * O O O X o *RS*
*/
@Test
fun shift_right_when_last_on_screen_dot_shifted_right_mid_shift() {
@@ -200,10 +174,8 @@
}
/**
- * totalPages: 12 , selected page: 9, shifting right
- * Visually :
- * *LS* o O O O X o _ RS
- * >>> LS _ o O O O X O *RS*
+ * totalPages: 12 , selected page: 9, shifting right Visually : *LS* o O O O X o _ RS >>> LS _ o
+ * O O O X O *RS*
*/
@Test
fun shift_right_when_last_on_screen_dot_shifted_right_last_shift() {
@@ -230,10 +202,8 @@
}
/**
- * totalPages: 12 , selected page: 10, shifting right
- * Visually :
- * *LS* o O O O X O _ RS
- * >>> *LS* o O O O O X _ RS
+ * totalPages: 12 , selected page: 10, shifting right Visually : *LS* o O O O X O _ RS >>> *LS*
+ * o O O O O X _ RS
*/
@Test
fun dont_shift_right_when_last_but_one_dot_shifted_right_to_last_page() {
@@ -260,11 +230,8 @@
}
/**
- * totalPages: 12 , selected page: 7, shifting left
- * Visually :
- * *LS* o X O O O O _ RS
- * >>> LS _ x O O O O O *RS*
- * >>> *LS* o X O O O o _ RS
+ * totalPages: 12 , selected page: 7, shifting left Visually : *LS* o X O O O O _ RS >>> LS _ x
+ * O O O O O *RS* >>> *LS* o X O O O o _ RS
*/
@Test
fun shift_left_when_second_on_screen_dot_shifted_left_last_pages() {
@@ -330,11 +297,8 @@
}
/**
- * totalPages: 12 , selected page: 4, shifting left
- * Visually :
- * *LS* o X O O O o _ RS
- * >>> LS _ x O O O O o *RS*
- * >>> *LS* o X O O O o _ RS
+ * totalPages: 12 , selected page: 4, shifting left Visually : *LS* o X O O O o _ RS >>> LS _ x
+ * O O O O o *RS* >>> *LS* o X O O O o _ RS
*/
@Test
fun shift_left_when_second_on_screen_dot_shifted_left_mid_pages() {
@@ -400,11 +364,8 @@
}
/**
- * totalPages: 12 , selected page: 2, shifting left
- * Visually :
- * *LS* o X O O O o _ RS
- * >>> LS _ x O O O O o *RS*
- * >>> *LS* O X O O O o _ RS
+ * totalPages: 12 , selected page: 2, shifting left Visually : *LS* o X O O O o _ RS >>> LS _ x
+ * O O O O o *RS* >>> *LS* O X O O O o _ RS
*/
@Test
fun shift_left_when_second_on_screen_dot_shifted_left_start_pages() {
@@ -470,10 +431,8 @@
}
/**
- * Pages count: 12 , selected page: 10, shifting right
- * Visually :
- * *LS* o O O O X O _ RS
- * >>> *LS* o O O O O X _ RS
+ * Pages count: 12 , selected page: 10, shifting right Visually : *LS* o O O O X O _ RS >>> *LS*
+ * o O O O O X _ RS
*/
@Test
fun dont_shift_left_when_first_dot_shifted_left_to_zero_page() {
@@ -510,18 +469,12 @@
rightSpacerSize: Float
) {
- testDots.forEachIndexed { index, testDot ->
- testDot(index, testDot, offset)
- }
+ testDots.forEachIndexed { index, testDot -> testDot(index, testDot, offset) }
Assert.assertEquals("Left spacer:", leftSpacerSize, leftSpacerSizeRatio)
Assert.assertEquals("Right spacer", rightSpacerSize, rightSpacerSizeRatio)
}
- private fun PagesState.testDot(
- index: Int,
- testDot: TestDot,
- offset: Float
- ) {
+ private fun PagesState.testDot(index: Int, testDot: TestDot, offset: Float) {
Assert.assertEquals("Page $index, alpha:", testDot.alpha lerp offset, alpha(index))
Assert.assertEquals(
@@ -554,5 +507,4 @@
}
}
-private infix fun Pair<Float, Float>.lerp(fraction: Float): Float =
- lerp(first, second, fraction)
+private infix fun Pair<Float, Float>.lerp(fraction: Float): Float = lerp(first, second, fraction)
diff --git a/wear/compose/compose-material/benchmark/src/androidTest/java/androidx/wear/compose/material/benchmark/ButtonBenchmark.kt b/wear/compose/compose-material/benchmark/src/androidTest/java/androidx/wear/compose/material/benchmark/ButtonBenchmark.kt
index 49b256d..71bd36b 100644
--- a/wear/compose/compose-material/benchmark/src/androidTest/java/androidx/wear/compose/material/benchmark/ButtonBenchmark.kt
+++ b/wear/compose/compose-material/benchmark/src/androidTest/java/androidx/wear/compose/material/benchmark/ButtonBenchmark.kt
@@ -33,15 +33,12 @@
import org.junit.Test
import org.junit.runner.RunWith
-/**
- * Benchmark for Wear Compose Button.
- */
+/** Benchmark for Wear Compose Button. */
@LargeTest
@RunWith(AndroidJUnit4::class)
class ButtonBenchmark {
- @get:Rule
- val benchmarkRule = ComposeBenchmarkRule()
+ @get:Rule val benchmarkRule = ComposeBenchmarkRule()
private val buttonCaseFactory = { ButtonTestCase() }
@@ -80,14 +77,11 @@
@Composable
override fun MeasuredContent() {
- Button(onClick = {}) {
- }
+ Button(onClick = {}) {}
}
@Composable
override fun ContentWrappers(content: @Composable () -> Unit) {
- MaterialTheme {
- content()
- }
+ MaterialTheme { content() }
}
}
diff --git a/wear/compose/compose-material/benchmark/src/androidTest/java/androidx/wear/compose/material/benchmark/CardBenchmark.kt b/wear/compose/compose-material/benchmark/src/androidTest/java/androidx/wear/compose/material/benchmark/CardBenchmark.kt
index 28d5adc..d8df525 100644
--- a/wear/compose/compose-material/benchmark/src/androidTest/java/androidx/wear/compose/material/benchmark/CardBenchmark.kt
+++ b/wear/compose/compose-material/benchmark/src/androidTest/java/androidx/wear/compose/material/benchmark/CardBenchmark.kt
@@ -35,15 +35,12 @@
import org.junit.Test
import org.junit.runner.RunWith
-/**
- * Benchmark for Wear Compose Card.
- */
+/** Benchmark for Wear Compose Card. */
@LargeTest
@RunWith(AndroidJUnit4::class)
class CardChipBenchmark {
- @get:Rule
- val benchmarkRule = ComposeBenchmarkRule()
+ @get:Rule val benchmarkRule = ComposeBenchmarkRule()
private val cardCaseFactory = { CardTestCase() }
@@ -89,12 +86,8 @@
override fun MeasuredContent() {
TitleCard(
onClick = {},
- time = {
- Text("now")
- },
- title = {
- Text("TitleCard")
- },
+ time = { Text("now") },
+ title = { Text("TitleCard") },
) {
Text("body")
}
@@ -102,8 +95,6 @@
@Composable
override fun ContentWrappers(content: @Composable () -> Unit) {
- MaterialTheme {
- content()
- }
+ MaterialTheme { content() }
}
}
diff --git a/wear/compose/compose-material/benchmark/src/androidTest/java/androidx/wear/compose/material/benchmark/ChipBenchmark.kt b/wear/compose/compose-material/benchmark/src/androidTest/java/androidx/wear/compose/material/benchmark/ChipBenchmark.kt
index 779f4ef..bd42c0b 100644
--- a/wear/compose/compose-material/benchmark/src/androidTest/java/androidx/wear/compose/material/benchmark/ChipBenchmark.kt
+++ b/wear/compose/compose-material/benchmark/src/androidTest/java/androidx/wear/compose/material/benchmark/ChipBenchmark.kt
@@ -36,15 +36,12 @@
import org.junit.Test
import org.junit.runner.RunWith
-/**
- * Benchmark for Wear Compose Chip.
- */
+/** Benchmark for Wear Compose Chip. */
@LargeTest
@RunWith(AndroidJUnit4::class)
class ChipBenchmark {
- @get:Rule
- val benchmarkRule = ComposeBenchmarkRule()
+ @get:Rule val benchmarkRule = ComposeBenchmarkRule()
private val chipCaseFactory = { ChipTestCase() }
@@ -91,20 +88,14 @@
Chip(
onClick = {},
colors = ChipDefaults.secondaryChipColors(),
- label = {
- Text("Primary label")
- },
- secondaryLabel = {
- Text("Secondary label")
- },
+ label = { Text("Primary label") },
+ secondaryLabel = { Text("Secondary label") },
enabled = true,
)
}
@Composable
override fun ContentWrappers(content: @Composable () -> Unit) {
- MaterialTheme {
- content()
- }
+ MaterialTheme { content() }
}
}
diff --git a/wear/compose/compose-material/benchmark/src/androidTest/java/androidx/wear/compose/material/benchmark/ColorsBenchmark.kt b/wear/compose/compose-material/benchmark/src/androidTest/java/androidx/wear/compose/material/benchmark/ColorsBenchmark.kt
index 63e8507..2c06a54 100644
--- a/wear/compose/compose-material/benchmark/src/androidTest/java/androidx/wear/compose/material/benchmark/ColorsBenchmark.kt
+++ b/wear/compose/compose-material/benchmark/src/androidTest/java/androidx/wear/compose/material/benchmark/ColorsBenchmark.kt
@@ -38,8 +38,7 @@
@RunWith(AndroidJUnit4::class)
class ColorsBenchmark {
- @get:Rule
- val benchmarkRule = ComposeBenchmarkRule()
+ @get:Rule val benchmarkRule = ComposeBenchmarkRule()
private val colorsTestCaseFactory = { ColorsTestCase() }
@@ -58,46 +57,53 @@
// Primary
Box(modifier = Modifier.size(1.dp).background(MaterialTheme.colors.primary))
Box(
- modifier = Modifier.size(1.dp)
- .background(
- MaterialTheme.colors.contentColorFor(MaterialTheme.colors.primary)
- )
+ modifier =
+ Modifier.size(1.dp)
+ .background(
+ MaterialTheme.colors.contentColorFor(MaterialTheme.colors.primary)
+ )
)
// Secondary
Box(modifier = Modifier.size(1.dp).background(MaterialTheme.colors.secondary))
Box(
- modifier = Modifier.size(1.dp)
- .background(
- MaterialTheme.colors.contentColorFor(MaterialTheme.colors.secondary)
- )
+ modifier =
+ Modifier.size(1.dp)
+ .background(
+ MaterialTheme.colors.contentColorFor(MaterialTheme.colors.secondary)
+ )
)
// Background
Box(modifier = Modifier.size(1.dp).background(MaterialTheme.colors.background))
Box(
- modifier = Modifier.size(1.dp)
- .background(
- MaterialTheme.colors.contentColorFor(MaterialTheme.colors.background)
- )
+ modifier =
+ Modifier.size(1.dp)
+ .background(
+ MaterialTheme.colors.contentColorFor(
+ MaterialTheme.colors.background
+ )
+ )
)
// Surface
Box(modifier = Modifier.size(1.dp).background(MaterialTheme.colors.surface))
Box(
- modifier = Modifier.size(1.dp)
- .background(
- MaterialTheme.colors.contentColorFor(MaterialTheme.colors.surface)
- )
+ modifier =
+ Modifier.size(1.dp)
+ .background(
+ MaterialTheme.colors.contentColorFor(MaterialTheme.colors.surface)
+ )
)
// Error
Box(modifier = Modifier.size(1.dp).background(MaterialTheme.colors.error))
Box(
- modifier = Modifier.size(1.dp)
- .background(
- MaterialTheme.colors.contentColorFor(MaterialTheme.colors.error)
- )
+ modifier =
+ Modifier.size(1.dp)
+ .background(
+ MaterialTheme.colors.contentColorFor(MaterialTheme.colors.error)
+ )
)
}
}
diff --git a/wear/compose/compose-material/benchmark/src/androidTest/java/androidx/wear/compose/material/benchmark/ListHeaderBenchmark.kt b/wear/compose/compose-material/benchmark/src/androidTest/java/androidx/wear/compose/material/benchmark/ListHeaderBenchmark.kt
index 3ffa865..f44d6e8 100644
--- a/wear/compose/compose-material/benchmark/src/androidTest/java/androidx/wear/compose/material/benchmark/ListHeaderBenchmark.kt
+++ b/wear/compose/compose-material/benchmark/src/androidTest/java/androidx/wear/compose/material/benchmark/ListHeaderBenchmark.kt
@@ -33,8 +33,7 @@
@RunWith(AndroidJUnit4::class)
class ListHeaderBenchmark {
- @get:Rule
- val benchmarkRule = ComposeBenchmarkRule()
+ @get:Rule val benchmarkRule = ComposeBenchmarkRule()
private val listHeaderCaseFactory = { ListHeaderTestCase() }
@@ -46,16 +45,12 @@
internal class ListHeaderTestCase : LayeredComposeTestCase() {
@Composable
override fun MeasuredContent() {
- ListHeader {
- Text("Test")
- }
+ ListHeader { Text("Test") }
}
@Composable
override fun ContentWrappers(content: @Composable () -> Unit) {
- MaterialTheme {
- content()
- }
+ MaterialTheme { content() }
}
}
}
diff --git a/wear/compose/compose-material/benchmark/src/androidTest/java/androidx/wear/compose/material/benchmark/PickerGroupBenchmark.kt b/wear/compose/compose-material/benchmark/src/androidTest/java/androidx/wear/compose/material/benchmark/PickerGroupBenchmark.kt
index 39c595f..1175d5f 100644
--- a/wear/compose/compose-material/benchmark/src/androidTest/java/androidx/wear/compose/material/benchmark/PickerGroupBenchmark.kt
+++ b/wear/compose/compose-material/benchmark/src/androidTest/java/androidx/wear/compose/material/benchmark/PickerGroupBenchmark.kt
@@ -33,15 +33,12 @@
import org.junit.Test
import org.junit.runner.RunWith
-/**
- * Benchmark for Wear Compose PickerGroup.
- */
+/** Benchmark for Wear Compose PickerGroup. */
@LargeTest
@RunWith(AndroidJUnit4::class)
class PickerGroupBenchmark {
- @get:Rule
- val benchmarkRule = ComposeBenchmarkRule()
+ @get:Rule val benchmarkRule = ComposeBenchmarkRule()
private val pickerGroupCaseFactory = { PickerGroupTestCase() }
@@ -94,8 +91,6 @@
@Composable
override fun ContentWrappers(content: @Composable () -> Unit) {
- MaterialTheme {
- content()
- }
+ MaterialTheme { content() }
}
}
diff --git a/wear/compose/compose-material/benchmark/src/androidTest/java/androidx/wear/compose/material/benchmark/PositionIndicatorBenchmark.kt b/wear/compose/compose-material/benchmark/src/androidTest/java/androidx/wear/compose/material/benchmark/PositionIndicatorBenchmark.kt
index af76a71..404eae1 100644
--- a/wear/compose/compose-material/benchmark/src/androidTest/java/androidx/wear/compose/material/benchmark/PositionIndicatorBenchmark.kt
+++ b/wear/compose/compose-material/benchmark/src/androidTest/java/androidx/wear/compose/material/benchmark/PositionIndicatorBenchmark.kt
@@ -51,8 +51,7 @@
@LargeTest
@RunWith(AndroidJUnit4::class)
class SimplePositionIndicatorBenchmark {
- @get:Rule
- val benchmarkRule = ComposeBenchmarkRule()
+ @get:Rule val benchmarkRule = ComposeBenchmarkRule()
private val defaultPositionIndicatorCaseFactory = {
SimplePositionIndicatorBenchmarkTestCase(animate = false)
}
@@ -60,10 +59,7 @@
@Test
fun changeFraction() {
benchmarkRule.changePositionBenchmark {
- SimplePositionIndicatorBenchmarkTestCase(
- targetFraction = 0.5f,
- animate = false
- )
+ SimplePositionIndicatorBenchmarkTestCase(targetFraction = 0.5f, animate = false)
}
}
@@ -94,10 +90,7 @@
@Test
fun changeFraction_withAnimation() {
benchmarkRule.changePositionBenchmark {
- SimplePositionIndicatorBenchmarkTestCase(
- targetFraction = 0.5f,
- animate = true
- )
+ SimplePositionIndicatorBenchmarkTestCase(targetFraction = 0.5f, animate = true)
}
}
@@ -134,8 +127,7 @@
@LargeTest
@RunWith(AndroidJUnit4::class)
class PositionIndicatorWithScalingLazyColumnBenchmark {
- @get:Rule
- val benchmarkRule = ComposeBenchmarkRule()
+ @get:Rule val benchmarkRule = ComposeBenchmarkRule()
@Test
fun positionIndicator_withScalingLazyColumn_withScroll() {
@@ -180,7 +172,8 @@
CustomPositionIndicatorState(
_positionFraction = { positionFraction.value },
sizeFraction = { sizeFraction.value },
- visibility = { visibility.value })
+ visibility = { visibility.value }
+ )
}
PositionIndicator(
@@ -188,26 +181,18 @@
indicatorHeight = 50.dp,
indicatorWidth = 4.dp,
paddingHorizontal = 5.dp,
- fadeInAnimationSpec = if (animate)
- PositionIndicatorDefaults.visibilityAnimationSpec
- else
- snap(),
- fadeOutAnimationSpec = if (animate)
- PositionIndicatorDefaults.visibilityAnimationSpec
- else
- snap(),
- positionAnimationSpec = if (animate)
- PositionIndicatorDefaults.positionAnimationSpec
- else
- snap()
+ fadeInAnimationSpec =
+ if (animate) PositionIndicatorDefaults.visibilityAnimationSpec else snap(),
+ fadeOutAnimationSpec =
+ if (animate) PositionIndicatorDefaults.visibilityAnimationSpec else snap(),
+ positionAnimationSpec =
+ if (animate) PositionIndicatorDefaults.positionAnimationSpec else snap()
)
}
@Composable
override fun ContentWrappers(content: @Composable () -> Unit) {
- MaterialTheme {
- content()
- }
+ MaterialTheme { content() }
}
}
@@ -217,9 +202,7 @@
private lateinit var slcState: ScalingLazyListState
override fun onChange() {
- runBlocking {
- if (withScroll) slcState.scrollToItem(2)
- }
+ runBlocking { if (withScroll) slcState.scrollToItem(2) }
}
@Composable
@@ -233,11 +216,7 @@
// By changing the size we can also change the size of the PositionIndicator,
// which will allow us to better measure all parts of PositionIndicator math.
val height = if (it % 2 == 0) 20.dp else 40.dp
- Box(
- modifier = Modifier
- .fillMaxWidth()
- .height(height)
- )
+ Box(modifier = Modifier.fillMaxWidth().height(height))
}
}
PositionIndicator(
@@ -251,9 +230,7 @@
@Composable
override fun ContentWrappers(content: @Composable () -> Unit) {
- MaterialTheme {
- content()
- }
+ MaterialTheme { content() }
}
}
@@ -279,9 +256,7 @@
caseFactory: () -> PositionIndicatorBenchmarkTestCase
) {
runBenchmarkFor(caseFactory) {
- runOnUiThread {
- disposeContent()
- }
+ runOnUiThread { disposeContent() }
measureRepeatedOnUiThread {
runWithTimingDisabled {
setupContent()
@@ -289,9 +264,7 @@
}
getTestCase().onChange()
doFrame()
- runWithTimingDisabled {
- disposeContent()
- }
+ runWithTimingDisabled { disposeContent() }
}
}
}
diff --git a/wear/compose/compose-material/benchmark/src/androidTest/java/androidx/wear/compose/material/benchmark/SLCBasedBenchmarkHelper.kt b/wear/compose/compose-material/benchmark/src/androidTest/java/androidx/wear/compose/material/benchmark/SLCBasedBenchmarkHelper.kt
index 40257bc..a647085 100644
--- a/wear/compose/compose-material/benchmark/src/androidTest/java/androidx/wear/compose/material/benchmark/SLCBasedBenchmarkHelper.kt
+++ b/wear/compose/compose-material/benchmark/src/androidTest/java/androidx/wear/compose/material/benchmark/SLCBasedBenchmarkHelper.kt
@@ -29,9 +29,7 @@
import org.junit.Assert
// TODO (b/270318565): Remove/Update these once the necessary changes in SLC has been made.
-internal fun ComposeBenchmarkRule.benchmarkFirstMeasure(
- caseFactory: () -> LayeredComposeTestCase
-) {
+internal fun ComposeBenchmarkRule.benchmarkFirstMeasure(caseFactory: () -> LayeredComposeTestCase) {
runBenchmarkFor(LayeredCaseAdapter.of(caseFactory)) {
measureRepeatedOnUiThread {
runWithTimingDisabled {
@@ -54,9 +52,7 @@
}
// TODO (b/270318565): Remove/Update these once the necessary changes in SLC has been made.
-internal fun ComposeBenchmarkRule.benchmarkFirstLayout(
- caseFactory: () -> LayeredComposeTestCase
-) {
+internal fun ComposeBenchmarkRule.benchmarkFirstLayout(caseFactory: () -> LayeredComposeTestCase) {
runBenchmarkFor(LayeredCaseAdapter.of(caseFactory)) {
measureRepeatedOnUiThread {
runWithTimingDisabled {
@@ -80,9 +76,7 @@
}
// TODO (b/270318565): Remove/Update these once the necessary changes in SLC has been made.
-internal fun ComposeBenchmarkRule.benchmarkFirstDraw(
- caseFactory: () -> LayeredComposeTestCase
-) {
+internal fun ComposeBenchmarkRule.benchmarkFirstDraw(caseFactory: () -> LayeredComposeTestCase) {
runBenchmarkFor(LayeredCaseAdapter.of(caseFactory)) {
measureRepeatedOnUiThread {
runWithTimingDisabled {
diff --git a/wear/compose/compose-material/benchmark/src/androidTest/java/androidx/wear/compose/material/benchmark/ScalingLazyColumnBenchmark.kt b/wear/compose/compose-material/benchmark/src/androidTest/java/androidx/wear/compose/material/benchmark/ScalingLazyColumnBenchmark.kt
index 220338e..83ed677 100644
--- a/wear/compose/compose-material/benchmark/src/androidTest/java/androidx/wear/compose/material/benchmark/ScalingLazyColumnBenchmark.kt
+++ b/wear/compose/compose-material/benchmark/src/androidTest/java/androidx/wear/compose/material/benchmark/ScalingLazyColumnBenchmark.kt
@@ -37,15 +37,12 @@
import org.junit.Test
import org.junit.runner.RunWith
-/**
- * Benchmark for Wear Compose ScalingLazyColumn.
- */
+/** Benchmark for Wear Compose ScalingLazyColumn. */
@LargeTest
@RunWith(AndroidJUnit4::class)
class ScalingLazyColumnBenchmark {
- @get:Rule
- val benchmarkRule = ComposeBenchmarkRule()
+ @get:Rule val benchmarkRule = ComposeBenchmarkRule()
private val scalingLazyColumnCaseFactory = { ScalingLazyColumnTestCase() }
@@ -89,22 +86,14 @@
override fun MeasuredContent() {
ScalingLazyColumn(
state = rememberScalingLazyListState(),
- modifier = Modifier.requiredSize(
- itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f
- ),
+ modifier = Modifier.requiredSize(itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f),
) {
- items(10) { it ->
- Box(Modifier.requiredSize(itemSizeDp)) {
- Text(text = "Item $it")
- }
- }
+ items(10) { it -> Box(Modifier.requiredSize(itemSizeDp)) { Text(text = "Item $it") } }
}
}
@Composable
override fun ContentWrappers(content: @Composable () -> Unit) {
- MaterialTheme {
- content()
- }
+ MaterialTheme { content() }
}
}
diff --git a/wear/compose/compose-material/benchmark/src/androidTest/java/androidx/wear/compose/material/benchmark/SliderBenchmark.kt b/wear/compose/compose-material/benchmark/src/androidTest/java/androidx/wear/compose/material/benchmark/SliderBenchmark.kt
index 8f880d3..0193471 100644
--- a/wear/compose/compose-material/benchmark/src/androidTest/java/androidx/wear/compose/material/benchmark/SliderBenchmark.kt
+++ b/wear/compose/compose-material/benchmark/src/androidTest/java/androidx/wear/compose/material/benchmark/SliderBenchmark.kt
@@ -35,8 +35,7 @@
class SliderBenchmark {
- @get:Rule
- val benchmarkRule = ComposeBenchmarkRule()
+ @get:Rule val benchmarkRule = ComposeBenchmarkRule()
private val sliderCaseFactory = { InlineSliderTestCase() }
@@ -91,8 +90,6 @@
@Composable
override fun ContentWrappers(content: @Composable () -> Unit) {
- MaterialTheme {
- content()
- }
+ MaterialTheme { content() }
}
}
diff --git a/wear/compose/compose-material/benchmark/src/androidTest/java/androidx/wear/compose/material/benchmark/StepperBenchmark.kt b/wear/compose/compose-material/benchmark/src/androidTest/java/androidx/wear/compose/material/benchmark/StepperBenchmark.kt
index b574a8b..6fb537b 100644
--- a/wear/compose/compose-material/benchmark/src/androidTest/java/androidx/wear/compose/material/benchmark/StepperBenchmark.kt
+++ b/wear/compose/compose-material/benchmark/src/androidTest/java/androidx/wear/compose/material/benchmark/StepperBenchmark.kt
@@ -35,8 +35,7 @@
class StepperBenchmark {
- @get:Rule
- val benchmarkRule = ComposeBenchmarkRule()
+ @get:Rule val benchmarkRule = ComposeBenchmarkRule()
private val stepperCaseFactory = { StepperTestCase() }
@@ -91,8 +90,6 @@
@Composable
override fun ContentWrappers(content: @Composable () -> Unit) {
- MaterialTheme {
- content()
- }
+ MaterialTheme { content() }
}
}
diff --git a/wear/compose/compose-material/benchmark/src/androidTest/java/androidx/wear/compose/material/benchmark/SwipeToDismissBoxBenchmark.kt b/wear/compose/compose-material/benchmark/src/androidTest/java/androidx/wear/compose/material/benchmark/SwipeToDismissBoxBenchmark.kt
index 8045372..f5f0f9c5 100644
--- a/wear/compose/compose-material/benchmark/src/androidTest/java/androidx/wear/compose/material/benchmark/SwipeToDismissBoxBenchmark.kt
+++ b/wear/compose/compose-material/benchmark/src/androidTest/java/androidx/wear/compose/material/benchmark/SwipeToDismissBoxBenchmark.kt
@@ -36,11 +36,8 @@
class SwipeToDismissBoxBenchmark {
@OptIn(ExperimentalBenchmarkConfigApi::class)
@get:Rule
- val benchmarkRule = ComposeBenchmarkRule(
- MicrobenchmarkConfig(
- profiler = ProfilerConfig.MethodTracing()
- )
- )
+ val benchmarkRule =
+ ComposeBenchmarkRule(MicrobenchmarkConfig(profiler = ProfilerConfig.MethodTracing()))
@Test
fun s2dbox_benchmarkToFirstPixel() {
@@ -59,20 +56,12 @@
val state = rememberSwipeToDismissBoxState()
SwipeToDismissBox(
state = state,
- onDismissed = { },
+ onDismissed = {},
) { isBackground ->
if (isBackground) {
- Box(
- modifier = Modifier
- .fillMaxSize()
- .background(MaterialTheme.colors.onSurface)
- )
+ Box(modifier = Modifier.fillMaxSize().background(MaterialTheme.colors.onSurface))
} else {
- Box(
- modifier = Modifier
- .fillMaxSize()
- .background(MaterialTheme.colors.primary)
- )
+ Box(modifier = Modifier.fillMaxSize().background(MaterialTheme.colors.primary))
}
}
}
diff --git a/wear/compose/compose-material/benchmark/src/androidTest/java/androidx/wear/compose/material/benchmark/TimeTextBenchmark.kt b/wear/compose/compose-material/benchmark/src/androidTest/java/androidx/wear/compose/material/benchmark/TimeTextBenchmark.kt
index ced69b9..2ac1aaa 100644
--- a/wear/compose/compose-material/benchmark/src/androidTest/java/androidx/wear/compose/material/benchmark/TimeTextBenchmark.kt
+++ b/wear/compose/compose-material/benchmark/src/androidTest/java/androidx/wear/compose/material/benchmark/TimeTextBenchmark.kt
@@ -38,15 +38,12 @@
import org.junit.Test
import org.junit.runner.RunWith
-/**
- * Benchmark for Wear Compose TimeText.
- */
+/** Benchmark for Wear Compose TimeText. */
@LargeTest
@RunWith(AndroidJUnit4::class)
class TimeTextBenchmark {
- @get:Rule
- val benchmarkRule = ComposeBenchmarkRule()
+ @get:Rule val benchmarkRule = ComposeBenchmarkRule()
private val timeTextCaseFactory = { TimeTextTestCase() }
@@ -95,34 +92,20 @@
text = "Leading content",
)
},
- textLinearSeparator = {
- TimeTextDefaults.TextSeparator()
- },
+ textLinearSeparator = { TimeTextDefaults.TextSeparator() },
endLinearContent = {
Text(
text = "Trailing content",
)
},
- startCurvedContent = {
- curvedText(
- text = "Leading content"
- )
- },
- textCurvedSeparator = {
- CurvedTextSeparator()
- },
- endCurvedContent = {
- curvedText(
- text = "Trailing content"
- )
- },
+ startCurvedContent = { curvedText(text = "Leading content") },
+ textCurvedSeparator = { CurvedTextSeparator() },
+ endCurvedContent = { curvedText(text = "Trailing content") },
)
}
@Composable
override fun ContentWrappers(content: @Composable () -> Unit) {
- MaterialTheme {
- content()
- }
+ MaterialTheme { content() }
}
}
diff --git a/wear/compose/compose-material/benchmark/src/androidTest/java/androidx/wear/compose/material/benchmark/ToggleButtonBenchmark.kt b/wear/compose/compose-material/benchmark/src/androidTest/java/androidx/wear/compose/material/benchmark/ToggleButtonBenchmark.kt
index 0ed38a7..06a2bda 100644
--- a/wear/compose/compose-material/benchmark/src/androidTest/java/androidx/wear/compose/material/benchmark/ToggleButtonBenchmark.kt
+++ b/wear/compose/compose-material/benchmark/src/androidTest/java/androidx/wear/compose/material/benchmark/ToggleButtonBenchmark.kt
@@ -34,15 +34,12 @@
import org.junit.Test
import org.junit.runner.RunWith
-/**
- * Benchmark for Wear Compose ToggleButton.
- */
+/** Benchmark for Wear Compose ToggleButton. */
@LargeTest
@RunWith(AndroidJUnit4::class)
class ToggleButtonBenchmark {
- @get:Rule
- val benchmarkRule = ComposeBenchmarkRule()
+ @get:Rule val benchmarkRule = ComposeBenchmarkRule()
private val caseFactory = { ToggleButtonTestCase() }
@@ -86,14 +83,11 @@
@Composable
override fun MeasuredContent() {
- ToggleButton(checked = true, onCheckedChange = {}) {
- }
+ ToggleButton(checked = true, onCheckedChange = {}) {}
}
@Composable
override fun ContentWrappers(content: @Composable () -> Unit) {
- MaterialTheme {
- content()
- }
+ MaterialTheme { content() }
}
}
diff --git a/wear/compose/compose-material/benchmark/src/androidTest/java/androidx/wear/compose/material/benchmark/ToggleChipBenchmark.kt b/wear/compose/compose-material/benchmark/src/androidTest/java/androidx/wear/compose/material/benchmark/ToggleChipBenchmark.kt
index 0796556..f21678d 100644
--- a/wear/compose/compose-material/benchmark/src/androidTest/java/androidx/wear/compose/material/benchmark/ToggleChipBenchmark.kt
+++ b/wear/compose/compose-material/benchmark/src/androidTest/java/androidx/wear/compose/material/benchmark/ToggleChipBenchmark.kt
@@ -37,15 +37,12 @@
import org.junit.Test
import org.junit.runner.RunWith
-/**
- * Benchmark for Wear Compose ToggleChip.
- */
+/** Benchmark for Wear Compose ToggleChip. */
@LargeTest
@RunWith(AndroidJUnit4::class)
class ToggleChipBenchmark {
- @get:Rule
- val benchmarkRule = ComposeBenchmarkRule()
+ @get:Rule val benchmarkRule = ComposeBenchmarkRule()
private val toggleChipCaseFactory = { ToggleChipTestCase() }
@@ -106,8 +103,6 @@
@Composable
override fun ContentWrappers(content: @Composable () -> Unit) {
- MaterialTheme {
- content()
- }
+ MaterialTheme { content() }
}
}
diff --git a/wear/compose/compose-material/samples/src/androidTest/kotlin/androidx/wear/compose/material/samples/PickerSampleTest.kt b/wear/compose/compose-material/samples/src/androidTest/kotlin/androidx/wear/compose/material/samples/PickerSampleTest.kt
index d92abdf..d1de640 100644
--- a/wear/compose/compose-material/samples/src/androidTest/kotlin/androidx/wear/compose/material/samples/PickerSampleTest.kt
+++ b/wear/compose/compose-material/samples/src/androidTest/kotlin/androidx/wear/compose/material/samples/PickerSampleTest.kt
@@ -22,24 +22,15 @@
// Simple tests to ensure samples build and show the expected elements.
class PickerSampleTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
@Test
fun option_change_picker_builds() {
- rule.setContent {
- MaterialTheme {
- OptionChangePicker()
- }
- }
+ rule.setContent { MaterialTheme { OptionChangePicker() } }
}
@Test
fun dual_picker_builds() {
- rule.setContent {
- MaterialTheme {
- DualPicker()
- }
- }
+ rule.setContent { MaterialTheme { DualPicker() } }
}
}
diff --git a/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/ButtonSample.kt b/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/ButtonSample.kt
index 84d77cc..74ffe07 100644
--- a/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/ButtonSample.kt
+++ b/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/ButtonSample.kt
@@ -41,8 +41,9 @@
Icon(
painter = painterResource(id = R.drawable.ic_airplanemode_active_24px),
contentDescription = "airplane",
- modifier = Modifier
- .size(ButtonDefaults.DefaultIconSize).wrapContentSize(align = Alignment.Center),
+ modifier =
+ Modifier.size(ButtonDefaults.DefaultIconSize)
+ .wrapContentSize(align = Alignment.Center),
)
}
}
@@ -57,8 +58,9 @@
Icon(
painter = painterResource(id = R.drawable.ic_airplanemode_active_24px),
contentDescription = "airplane",
- modifier = Modifier
- .size(ButtonDefaults.DefaultIconSize).wrapContentSize(align = Alignment.Center),
+ modifier =
+ Modifier.size(ButtonDefaults.DefaultIconSize)
+ .wrapContentSize(align = Alignment.Center),
)
}
}
@@ -74,8 +76,9 @@
Icon(
painter = painterResource(id = R.drawable.ic_airplanemode_active_24px),
contentDescription = "airplane",
- modifier = Modifier
- .size(ButtonDefaults.LargeIconSize).wrapContentSize(align = Alignment.Center),
+ modifier =
+ Modifier.size(ButtonDefaults.LargeIconSize)
+ .wrapContentSize(align = Alignment.Center),
)
}
}
@@ -102,8 +105,9 @@
Icon(
painter = painterResource(id = R.drawable.ic_airplanemode_active_24px),
contentDescription = "airplane",
- modifier = Modifier
- .size(ButtonDefaults.SmallIconSize).wrapContentSize(align = Alignment.Center),
+ modifier =
+ Modifier.size(ButtonDefaults.SmallIconSize)
+ .wrapContentSize(align = Alignment.Center),
)
}
}
@@ -118,8 +122,9 @@
Icon(
painter = painterResource(id = R.drawable.ic_airplanemode_active_24px),
contentDescription = "airplane",
- modifier = Modifier
- .size(ButtonDefaults.SmallIconSize).wrapContentSize(align = Alignment.Center),
+ modifier =
+ Modifier.size(ButtonDefaults.SmallIconSize)
+ .wrapContentSize(align = Alignment.Center),
)
}
}
diff --git a/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/CardSample.kt b/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/CardSample.kt
index f95ab3c..e4c8cfa 100644
--- a/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/CardSample.kt
+++ b/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/CardSample.kt
@@ -51,9 +51,9 @@
Icon(
painter = painterResource(id = R.drawable.ic_airplanemode_active_24px),
contentDescription = "airplane",
- modifier = Modifier
- .size(CardDefaults.AppImageSize)
- .wrapContentSize(align = Alignment.Center),
+ modifier =
+ Modifier.size(CardDefaults.AppImageSize)
+ .wrapContentSize(align = Alignment.Center),
)
},
title = { Text("AppCard") },
@@ -74,9 +74,9 @@
Icon(
painter = painterResource(id = R.drawable.ic_airplanemode_active_24px),
contentDescription = "airplane",
- modifier = Modifier
- .size(CardDefaults.AppImageSize)
- .wrapContentSize(align = Alignment.Center),
+ modifier =
+ Modifier.size(CardDefaults.AppImageSize)
+ .wrapContentSize(align = Alignment.Center),
)
},
title = {
@@ -89,10 +89,8 @@
) {
Spacer(Modifier.height(6.dp))
Image(
- modifier = Modifier
- .padding(end = 28.dp)
- .aspectRatio(16f / 9f)
- .clip(RoundedCornerShape(16.dp)),
+ modifier =
+ Modifier.padding(end = 28.dp).aspectRatio(16f / 9f).clip(RoundedCornerShape(16.dp)),
painter = painterResource(R.drawable.card_background),
contentScale = ContentScale.Crop,
contentDescription = null
@@ -119,18 +117,17 @@
TitleCard(
onClick = { /* Do something */ },
title = { Text("TitleCard With an ImageBackground") },
- backgroundPainter = CardDefaults.imageWithScrimBackgroundPainter(
- backgroundImagePainter = painterResource(id = R.drawable.backgroundimage)
- ),
+ backgroundPainter =
+ CardDefaults.imageWithScrimBackgroundPainter(
+ backgroundImagePainter = painterResource(id = R.drawable.backgroundimage)
+ ),
contentColor = MaterialTheme.colors.onSurface,
titleColor = MaterialTheme.colors.onSurface,
) {
// Apply 24.dp padding in bottom for TitleCard with an ImageBackground.
// Already 12.dp padding exists. Ref - [CardDefaults.ContentPadding]
Column(
- modifier = Modifier
- .fillMaxSize()
- .padding(bottom = 12.dp),
+ modifier = Modifier.fillMaxSize().padding(bottom = 12.dp),
) {
Text("Text coloured to stand out on the image")
}
diff --git a/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/ChipSample.kt b/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/ChipSample.kt
index 178a5a5..d4c3e58 100644
--- a/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/ChipSample.kt
+++ b/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/ChipSample.kt
@@ -44,15 +44,16 @@
label = {
Text(
text = "Main label can span up to 3 lines",
- maxLines = 3, overflow = TextOverflow.Ellipsis
+ maxLines = 3,
+ overflow = TextOverflow.Ellipsis
)
},
icon = {
Icon(
painter = painterResource(id = R.drawable.ic_airplanemode_active_24px),
contentDescription = "airplane",
- modifier = Modifier.size(ChipDefaults.IconSize)
- .wrapContentSize(align = Alignment.Center),
+ modifier =
+ Modifier.size(ChipDefaults.IconSize).wrapContentSize(align = Alignment.Center),
)
}
)
@@ -68,15 +69,16 @@
label = {
Text(
text = "Main label can span up to 3 lines",
- maxLines = 3, overflow = TextOverflow.Ellipsis
+ maxLines = 3,
+ overflow = TextOverflow.Ellipsis
)
},
icon = {
Icon(
painter = painterResource(id = R.drawable.ic_airplanemode_active_24px),
contentDescription = "airplane",
- modifier = Modifier.size(ChipDefaults.IconSize)
- .wrapContentSize(align = Alignment.Center),
+ modifier =
+ Modifier.size(ChipDefaults.IconSize).wrapContentSize(align = Alignment.Center),
)
}
)
@@ -97,8 +99,8 @@
Icon(
painter = painterResource(id = R.drawable.ic_airplanemode_active_24px),
contentDescription = "airplane",
- modifier = Modifier.size(ChipDefaults.IconSize)
- .wrapContentSize(align = Alignment.Center),
+ modifier =
+ Modifier.size(ChipDefaults.IconSize).wrapContentSize(align = Alignment.Center),
)
}
)
@@ -111,9 +113,7 @@
onClick = { /* Do something */ },
enabled = true,
// CompactChip label should be no more than 1 line of text
- label = {
- Text("Single line label", maxLines = 1, overflow = TextOverflow.Ellipsis)
- },
+ label = { Text("Single line label", maxLines = 1, overflow = TextOverflow.Ellipsis) },
icon = {
Icon(
painter = painterResource(id = R.drawable.ic_airplanemode_active_24px),
@@ -166,9 +166,7 @@
onClick = { /* Do something */ },
enabled = true,
// CompactChip label should be no more than 1 line of text
- label = {
- Text("Single line label", maxLines = 1, overflow = TextOverflow.Ellipsis)
- },
+ label = { Text("Single line label", maxLines = 1, overflow = TextOverflow.Ellipsis) },
icon = {
Icon(
painter = painterResource(id = R.drawable.ic_airplanemode_active_24px),
diff --git a/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/CircularProgressIndicatorSample.kt b/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/CircularProgressIndicatorSample.kt
index f996e4d..e164114 100644
--- a/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/CircularProgressIndicatorSample.kt
+++ b/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/CircularProgressIndicatorSample.kt
@@ -47,10 +47,11 @@
@Composable
public fun CircularProgressIndicatorWithAnimation() {
var progress by remember { mutableStateOf(0.1f) }
- val animatedProgress by animateFloatAsState(
- targetValue = progress,
- animationSpec = ProgressIndicatorDefaults.ProgressAnimationSpec
- )
+ val animatedProgress by
+ animateFloatAsState(
+ targetValue = progress,
+ animationSpec = ProgressIndicatorDefaults.ProgressAnimationSpec
+ )
Column(horizontalAlignment = Alignment.CenterHorizontally) {
CircularProgressIndicator(
@@ -59,9 +60,7 @@
Spacer(Modifier.requiredHeight(10.dp))
CompactChip(
modifier = Modifier.width(90.dp),
- onClick = {
- if (progress < 1f) progress += 0.1f
- },
+ onClick = { if (progress < 1f) progress += 0.1f },
label = { Text("Increase") }
)
}
diff --git a/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/CurvedTextSample.kt b/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/CurvedTextSample.kt
index 90c50f8..2bff9d9 100644
--- a/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/CurvedTextSample.kt
+++ b/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/CurvedTextSample.kt
@@ -87,13 +87,10 @@
}
}
- ProvideTextStyle(value = TextStyle(
- color = Color.Green,
- background = Color.White,
- fontWeight = FontWeight.Bold
- )) {
- CurvedLayout(anchor = 90f) {
- curvedText("Green On White")
- }
+ ProvideTextStyle(
+ value =
+ TextStyle(color = Color.Green, background = Color.White, fontWeight = FontWeight.Bold)
+ ) {
+ CurvedLayout(anchor = 90f) { curvedText("Green On White") }
}
}
diff --git a/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/DialogSample.kt b/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/DialogSample.kt
index e402617db..10582f4 100644
--- a/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/DialogSample.kt
+++ b/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/DialogSample.kt
@@ -84,8 +84,7 @@
Icon(
painter = painterResource(id = R.drawable.ic_airplanemode_active_24px),
contentDescription = "airplane",
- modifier = Modifier.size(24.dp)
- .wrapContentSize(align = Alignment.Center),
+ modifier = Modifier.size(24.dp).wrapContentSize(align = Alignment.Center),
)
},
title = { Text(text = "Example Title Text", textAlign = TextAlign.Center) },
@@ -139,7 +138,8 @@
Confirmation(
onTimeout = { showDialog = false },
icon = {
- // Initially, animation is static and shown at the start position (atEnd = false).
+ // Initially, animation is static and shown at the start position (atEnd =
+ // false).
// Then, we use the EffectAPI to trigger a state change to atEnd = true,
// which plays the animation from start to end.
var atEnd by remember { mutableStateOf(false) }
@@ -173,22 +173,29 @@
)
},
title = { Text("Title text displayed here", textAlign = TextAlign.Center) },
- negativeButton = { Button(
- colors = ButtonDefaults.secondaryButtonColors(),
- onClick = {
- /* Do something e.g. navController.popBackStack()*/
- }) {
- Text("No")
- } },
- positiveButton = { Button(onClick = {
- /* Do something e.g. navController.popBackStack()*/
- }) { Text("Yes") } },
- contentPadding =
- PaddingValues(start = 10.dp, end = 10.dp, top = 24.dp, bottom = 32.dp),
+ negativeButton = {
+ Button(
+ colors = ButtonDefaults.secondaryButtonColors(),
+ onClick = {
+ /* Do something e.g. navController.popBackStack()*/
+ }
+ ) {
+ Text("No")
+ }
+ },
+ positiveButton = {
+ Button(
+ onClick = {
+ /* Do something e.g. navController.popBackStack()*/
+ }
+ ) {
+ Text("Yes")
+ }
+ },
+ contentPadding = PaddingValues(start = 10.dp, end = 10.dp, top = 24.dp, bottom = 32.dp),
) {
Text(
- text = "Body text displayed here " +
- "(swipe right to dismiss)",
+ text = "Body text displayed here " + "(swipe right to dismiss)",
textAlign = TextAlign.Center
)
}
@@ -210,8 +217,7 @@
title = { Text(text = "Example Title Text", textAlign = TextAlign.Center) },
message = {
Text(
- text = "Message content goes here " +
- "(swipe right to dismiss)",
+ text = "Message content goes here " + "(swipe right to dismiss)",
textAlign = TextAlign.Center,
style = MaterialTheme.typography.body2
)
@@ -261,8 +267,7 @@
durationMillis = animation.totalDuration * 2L,
) {
Text(
- text = "Body text displayed here " +
- "(swipe right to dismiss)",
+ text = "Body text displayed here " + "(swipe right to dismiss)",
textAlign = TextAlign.Center
)
}
diff --git a/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/HorizontalPageIndicatorSample.kt b/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/HorizontalPageIndicatorSample.kt
index 0068f90..361b539 100644
--- a/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/HorizontalPageIndicatorSample.kt
+++ b/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/HorizontalPageIndicatorSample.kt
@@ -42,18 +42,21 @@
var selectedPage by remember { mutableStateOf(0) }
var finalValue by remember { mutableStateOf(0) }
- val animatedSelectedPage by animateFloatAsState(
- targetValue = selectedPage.toFloat(),
- ) {
- finalValue = it.toInt()
- }
+ val animatedSelectedPage by
+ animateFloatAsState(
+ targetValue = selectedPage.toFloat(),
+ ) {
+ finalValue = it.toInt()
+ }
val pageIndicatorState: PageIndicatorState = remember {
object : PageIndicatorState {
override val pageOffset: Float
get() = animatedSelectedPage - finalValue
+
override val selectedPage: Int
get() = finalValue
+
override val pageCount: Int
get() = maxPages
}
@@ -68,8 +71,6 @@
valueProgression = 0 until maxPages,
onValueChange = { selectedPage = it }
)
- HorizontalPageIndicator(
- pageIndicatorState = pageIndicatorState
- )
+ HorizontalPageIndicator(pageIndicatorState = pageIndicatorState)
}
}
diff --git a/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/MaterialThemeSample.kt b/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/MaterialThemeSample.kt
index bff431d..17ab9bd 100644
--- a/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/MaterialThemeSample.kt
+++ b/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/MaterialThemeSample.kt
@@ -26,11 +26,13 @@
@Sampled
@Composable
fun FixedFontSize() {
- val typography = MaterialTheme.typography.copy(
- display1 = MaterialTheme.typography.display1.copy(
- fontSize = with(LocalDensity.current) { 40.dp.toSp() }
+ val typography =
+ MaterialTheme.typography.copy(
+ display1 =
+ MaterialTheme.typography.display1.copy(
+ fontSize = with(LocalDensity.current) { 40.dp.toSp() }
+ )
)
- )
MaterialTheme(typography = typography) {
Text(
text = "Fixed Font",
diff --git a/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/PickerGroupSample.kt b/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/PickerGroupSample.kt
index 0171773..4bec194 100644
--- a/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/PickerGroupSample.kt
+++ b/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/PickerGroupSample.kt
@@ -76,9 +76,7 @@
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
- val headingText = mapOf(
- 0 to "Hours", 1 to "Minutes", 2 to "Seconds", 3 to "Milli"
- )
+ val headingText = mapOf(0 to "Hours", 1 to "Minutes", 2 to "Seconds", 3 to "Milli")
Spacer(modifier = Modifier.size(30.dp))
Text(text = headingText[pickerGroupState.selectedIndex]!!)
Spacer(modifier = Modifier.size(10.dp))
diff --git a/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/PickerSample.kt b/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/PickerSample.kt
index 12452a9..ac4d25a 100644
--- a/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/PickerSample.kt
+++ b/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/PickerSample.kt
@@ -52,10 +52,7 @@
val items = listOf("One", "Two", "Three", "Four", "Five")
val state = rememberPickerState(items.size)
val contentDescription by remember { derivedStateOf { "${state.selectedOption + 1}" } }
- Box(
- modifier = Modifier.fillMaxSize(),
- contentAlignment = Alignment.Center
- ) {
+ Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
Text(
modifier = Modifier.align(Alignment.TopCenter).padding(top = 10.dp),
text = "Selected: ${items[state.selectedOption]}"
@@ -82,12 +79,8 @@
contentDescription = contentDescription,
) {
Chip(
- onClick = {
- coroutineScope.launch { state.scrollToOption(it) }
- },
- label = {
- Text("$it")
- }
+ onClick = { coroutineScope.launch { state.scrollToOption(it) } },
+ label = { Text("$it") }
)
}
}
@@ -99,22 +92,15 @@
val state = rememberPickerState(initialNumberOfOptions = 10)
val contentDescription by remember { derivedStateOf { "${state.selectedOption + 1}" } }
- Box(
- modifier = Modifier.fillMaxSize(),
- contentAlignment = Alignment.Center
- ) {
+ Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
Picker(
state = state,
separation = 4.dp,
contentDescription = contentDescription,
) {
Chip(
- onClick = {
- coroutineScope.launch { state.animateScrollToOption(it) }
- },
- label = {
- Text("$it")
- }
+ onClick = { coroutineScope.launch { state.animateScrollToOption(it) } },
+ label = { Text("$it") }
)
}
}
@@ -128,29 +114,29 @@
val textStyle = MaterialTheme.typography.display1
@Composable
- fun Option(column: Int, text: String) = Box(modifier = Modifier.fillMaxSize()) {
- Text(
- text = text, style = textStyle,
- color = if (selectedColumn == column) MaterialTheme.colors.secondary
- else MaterialTheme.colors.onBackground,
- modifier = Modifier
- .align(Alignment.Center).wrapContentSize()
- .pointerInteropFilter {
- if (it.action == MotionEvent.ACTION_DOWN) selectedColumn = column
- true
- }
- )
- }
+ fun Option(column: Int, text: String) =
+ Box(modifier = Modifier.fillMaxSize()) {
+ Text(
+ text = text,
+ style = textStyle,
+ color =
+ if (selectedColumn == column) MaterialTheme.colors.secondary
+ else MaterialTheme.colors.onBackground,
+ modifier =
+ Modifier.align(Alignment.Center).wrapContentSize().pointerInteropFilter {
+ if (it.action == MotionEvent.ACTION_DOWN) selectedColumn = column
+ true
+ }
+ )
+ }
Row(
modifier = Modifier.fillMaxSize(),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Center,
) {
- val hourState = rememberPickerState(
- initialNumberOfOptions = 12,
- initiallySelectedOption = 5
- )
+ val hourState =
+ rememberPickerState(initialNumberOfOptions = 12, initiallySelectedOption = 5)
val hourContentDescription by remember {
derivedStateOf { "${hourState.selectedOption + 1 } hours" }
}
diff --git a/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/PlaceholderSample.kt b/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/PlaceholderSample.kt
index 656db1b..83262e2 100644
--- a/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/PlaceholderSample.kt
+++ b/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/PlaceholderSample.kt
@@ -49,8 +49,8 @@
import kotlinx.coroutines.delay
/**
- * This sample applies placeholders directly over the content that is waiting to be loaded.
- * This approach is suitable for situations where the developer is confident that the stadium shaped
+ * This sample applies placeholders directly over the content that is waiting to be loaded. This
+ * approach is suitable for situations where the developer is confident that the stadium shaped
* placeholder will cover the content in the period between when it is loaded and when the
* placeholder visual effects will have finished.
*/
@@ -72,36 +72,29 @@
text = labelText,
maxLines = 2,
overflow = TextOverflow.Ellipsis,
- modifier = Modifier
- .fillMaxWidth()
- .placeholder(chipPlaceholderState)
+ modifier = Modifier.fillMaxWidth().placeholder(chipPlaceholderState)
)
},
icon = {
- Box(
- modifier = Modifier
- .size(ChipDefaults.IconSize)
- .placeholder(chipPlaceholderState)
- ) {
+ Box(modifier = Modifier.size(ChipDefaults.IconSize).placeholder(chipPlaceholderState)) {
if (iconResource != null) {
Icon(
painter = painterResource(id = R.drawable.ic_airplanemode_active_24px),
contentDescription = "airplane",
- modifier = Modifier
- .wrapContentSize(align = Alignment.Center)
- .size(ChipDefaults.IconSize)
- .fillMaxSize(),
+ modifier =
+ Modifier.wrapContentSize(align = Alignment.Center)
+ .size(ChipDefaults.IconSize)
+ .fillMaxSize(),
)
}
}
},
- colors = PlaceholderDefaults.placeholderChipColors(
- originalChipColors = ChipDefaults.primaryChipColors(),
- placeholderState = chipPlaceholderState
- ),
- modifier = Modifier
- .fillMaxWidth()
- .placeholderShimmer(chipPlaceholderState)
+ colors =
+ PlaceholderDefaults.placeholderChipColors(
+ originalChipColors = ChipDefaults.primaryChipColors(),
+ placeholderState = chipPlaceholderState
+ ),
+ modifier = Modifier.fillMaxWidth().placeholderShimmer(chipPlaceholderState)
)
// Simulate content loading completing in stages
LaunchedEffect(Unit) {
@@ -110,10 +103,8 @@
delay(1000)
labelText = "A label"
}
- if (! chipPlaceholderState.isShowContent) {
- LaunchedEffect(chipPlaceholderState) {
- chipPlaceholderState.startPlaceholderAnimation()
- }
+ if (!chipPlaceholderState.isShowContent) {
+ LaunchedEffect(chipPlaceholderState) { chipPlaceholderState.startPlaceholderAnimation() }
}
}
@@ -140,9 +131,7 @@
labelText.isNotEmpty() && secondaryLabelText.isNotEmpty() && iconResource != null
}
Box {
- if (chipPlaceholderState.isShowContent ||
- chipPlaceholderState.isWipeOff
- ) {
+ if (chipPlaceholderState.isShowContent || chipPlaceholderState.isWipeOff) {
Chip(
onClick = { /* Do something */ },
enabled = true,
@@ -151,8 +140,7 @@
text = labelText,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
- modifier = Modifier
- .fillMaxWidth()
+ modifier = Modifier.fillMaxWidth()
)
},
secondaryLabel = {
@@ -160,20 +148,17 @@
text = secondaryLabelText,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
- modifier = Modifier
- .fillMaxWidth()
+ modifier = Modifier.fillMaxWidth()
)
},
icon = {
if (iconResource != null) {
Icon(
- painter = painterResource(
- id = R.drawable.ic_airplanemode_active_24px
- ),
+ painter = painterResource(id = R.drawable.ic_airplanemode_active_24px),
contentDescription = "airplane",
- modifier = Modifier
- .wrapContentSize(align = Alignment.Center)
- .size(ChipDefaults.IconSize)
+ modifier =
+ Modifier.wrapContentSize(align = Alignment.Center)
+ .size(ChipDefaults.IconSize)
)
}
},
@@ -181,33 +166,32 @@
modifier = Modifier.fillMaxWidth()
)
}
- if (! chipPlaceholderState.isShowContent) {
+ if (!chipPlaceholderState.isShowContent) {
Chip(
onClick = { /* Do something */ },
enabled = true,
label = {
Box(
- modifier = Modifier
- .fillMaxWidth()
- .height(16.dp)
- .padding(top = 1.dp, bottom = 1.dp)
- .placeholder(placeholderState = chipPlaceholderState)
+ modifier =
+ Modifier.fillMaxWidth()
+ .height(16.dp)
+ .padding(top = 1.dp, bottom = 1.dp)
+ .placeholder(placeholderState = chipPlaceholderState)
)
},
secondaryLabel = {
Box(
- modifier = Modifier
- .fillMaxWidth()
- .height(16.dp)
- .padding(top = 1.dp, bottom = 1.dp)
- .placeholder(placeholderState = chipPlaceholderState)
+ modifier =
+ Modifier.fillMaxWidth()
+ .height(16.dp)
+ .padding(top = 1.dp, bottom = 1.dp)
+ .placeholder(placeholderState = chipPlaceholderState)
)
},
icon = {
Box(
- modifier = Modifier
- .size(ChipDefaults.IconSize)
- .placeholder(chipPlaceholderState)
+ modifier =
+ Modifier.size(ChipDefaults.IconSize).placeholder(chipPlaceholderState)
)
// Simulate the icon becoming ready after a period of time
LaunchedEffect(Unit) {
@@ -215,12 +199,11 @@
iconResource = R.drawable.ic_airplanemode_active_24px
}
},
- colors = PlaceholderDefaults.placeholderChipColors(
- placeholderState = chipPlaceholderState
- ),
- modifier = Modifier
- .fillMaxWidth()
- .placeholderShimmer(chipPlaceholderState)
+ colors =
+ PlaceholderDefaults.placeholderChipColors(
+ placeholderState = chipPlaceholderState
+ ),
+ modifier = Modifier.fillMaxWidth().placeholderShimmer(chipPlaceholderState)
)
}
}
@@ -231,18 +214,16 @@
delay(500)
labelText = "A label"
}
- if (! chipPlaceholderState.isShowContent) {
- LaunchedEffect(chipPlaceholderState) {
- chipPlaceholderState.startPlaceholderAnimation()
- }
+ if (!chipPlaceholderState.isShowContent) {
+ LaunchedEffect(chipPlaceholderState) { chipPlaceholderState.startPlaceholderAnimation() }
}
}
/**
* This sample applies a placeholder and placeholderShimmer directly over a single composable.
*
- * Note that the modifier ordering is important, the placeholderShimmer must be before
- * the placeholder in the modifier chain - otherwise the shimmer will be drawn underneath the
+ * Note that the modifier ordering is important, the placeholderShimmer must be before the
+ * placeholder in the modifier chain - otherwise the shimmer will be drawn underneath the
* placeholder and will not be visible.
*/
@OptIn(ExperimentalWearMaterialApi::class)
@@ -250,18 +231,16 @@
@Composable
fun TextPlaceholder() {
var labelText by remember { mutableStateOf("") }
- val chipPlaceholderState = rememberPlaceholderState {
- labelText.isNotEmpty()
- }
+ val chipPlaceholderState = rememberPlaceholderState { labelText.isNotEmpty() }
Text(
text = labelText,
overflow = TextOverflow.Ellipsis,
textAlign = TextAlign.Center,
- modifier = Modifier
- .width(90.dp)
- .placeholderShimmer(chipPlaceholderState)
- .placeholder(chipPlaceholderState)
+ modifier =
+ Modifier.width(90.dp)
+ .placeholderShimmer(chipPlaceholderState)
+ .placeholder(chipPlaceholderState)
)
// Simulate content loading
@@ -269,9 +248,7 @@
delay(3000)
labelText = "A label"
}
- if (! chipPlaceholderState.isShowContent) {
- LaunchedEffect(chipPlaceholderState) {
- chipPlaceholderState.startPlaceholderAnimation()
- }
+ if (!chipPlaceholderState.isShowContent) {
+ LaunchedEffect(chipPlaceholderState) { chipPlaceholderState.startPlaceholderAnimation() }
}
}
diff --git a/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/PreviewSample.kt b/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/PreviewSample.kt
index 7f79087..44cc16d 100644
--- a/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/PreviewSample.kt
+++ b/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/PreviewSample.kt
@@ -55,8 +55,9 @@
Icon(
painter = painterResource(id = R.drawable.ic_airplanemode_active_24px),
contentDescription = "airplane",
- modifier = Modifier
- .size(ButtonDefaults.DefaultIconSize).wrapContentSize(align = Alignment.Center),
+ modifier =
+ Modifier.size(ButtonDefaults.DefaultIconSize)
+ .wrapContentSize(align = Alignment.Center),
)
}
}
@@ -68,9 +69,10 @@
TitleCard(
onClick = { /* Do something */ },
title = { Text("TitleCard With an ImageBackground") },
- backgroundPainter = CardDefaults.imageWithScrimBackgroundPainter(
- backgroundImagePainter = painterResource(id = R.drawable.backgroundimage)
- ),
+ backgroundPainter =
+ CardDefaults.imageWithScrimBackgroundPainter(
+ backgroundImagePainter = painterResource(id = R.drawable.backgroundimage)
+ ),
contentColor = MaterialTheme.colors.onSurface,
titleColor = MaterialTheme.colors.onSurface,
) {
@@ -91,9 +93,9 @@
Icon(
painter = painterResource(id = R.drawable.ic_airplanemode_active_24px),
contentDescription = "airplane",
- modifier = Modifier
- .size(ToggleButtonDefaults.DefaultIconSize)
- .wrapContentSize(align = Alignment.Center),
+ modifier =
+ Modifier.size(ToggleButtonDefaults.DefaultIconSize)
+ .wrapContentSize(align = Alignment.Center),
)
}
}
diff --git a/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/ScaffoldSample.kt b/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/ScaffoldSample.kt
index 92c9d1f..07e70d0 100644
--- a/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/ScaffoldSample.kt
+++ b/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/ScaffoldSample.kt
@@ -46,19 +46,14 @@
Scaffold(
positionIndicator = {
- PositionIndicator(
- scalingLazyListState = listState,
- modifier = Modifier
- )
+ PositionIndicator(scalingLazyListState = listState, modifier = Modifier)
},
vignette = {
if (showVignette.value) {
Vignette(vignettePosition = vignetteState.value)
}
},
- timeText = {
- TimeText()
- }
+ timeText = { TimeText() }
) {
ScalingLazyColumn(
contentPadding = PaddingValues(top = 40.dp),
@@ -104,7 +99,7 @@
}
items(20) {
Chip(
- onClick = { },
+ onClick = {},
label = { Text("List item $it") },
colors = ChipDefaults.secondaryChipColors()
)
diff --git a/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/ScalingLazyColumnSample.kt b/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/ScalingLazyColumnSample.kt
index 1826758..4f16aa1 100644
--- a/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/ScalingLazyColumnSample.kt
+++ b/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/ScalingLazyColumnSample.kt
@@ -39,17 +39,11 @@
@Sampled
@Composable
fun SimpleScalingLazyColumn() {
- ScalingLazyColumn(
- modifier = Modifier.fillMaxWidth()
- ) {
- item {
- ListHeader {
- Text(text = "List Header")
- }
- }
+ ScalingLazyColumn(modifier = Modifier.fillMaxWidth()) {
+ item { ListHeader { Text(text = "List Header") } }
items(20) {
Chip(
- onClick = { },
+ onClick = {},
label = { Text("List item $it") },
colors = ChipDefaults.secondaryChipColors()
)
@@ -66,14 +60,10 @@
state = state,
flingBehavior = ScalingLazyColumnDefaults.snapFlingBehavior(state = state)
) {
- item {
- ListHeader {
- Text(text = "List Header")
- }
- }
+ item { ListHeader { Text(text = "List Header") } }
items(20) {
Chip(
- onClick = { },
+ onClick = {},
label = { Text("List item $it") },
colors = ChipDefaults.secondaryChipColors()
)
@@ -87,13 +77,12 @@
val coroutineScope = rememberCoroutineScope()
val itemSpacing = 6.dp
// Line up the gap between the items on the center-line
- val scrollOffset = with(LocalDensity.current) {
- -(itemSpacing / 2).roundToPx()
- }
- val state = rememberScalingLazyListState(
- initialCenterItemIndex = 1,
- initialCenterItemScrollOffset = scrollOffset
- )
+ val scrollOffset = with(LocalDensity.current) { -(itemSpacing / 2).roundToPx() }
+ val state =
+ rememberScalingLazyListState(
+ initialCenterItemIndex = 1,
+ initialCenterItemScrollOffset = scrollOffset
+ )
ScalingLazyColumn(
modifier = Modifier.fillMaxWidth(),
@@ -102,11 +91,7 @@
state = state,
autoCentering = AutoCenteringParams(itemOffset = scrollOffset)
) {
- item {
- ListHeader {
- Text(text = "List Header")
- }
- }
+ item { ListHeader { Text(text = "List Header") } }
items(20) {
Chip(
onClick = {
@@ -130,14 +115,10 @@
contentPadding = PaddingValues(top = 20.dp, bottom = 20.dp),
autoCentering = null
) {
- item {
- ListHeader {
- Text(text = "List Header")
- }
- }
+ item { ListHeader { Text(text = "List Header") } }
items(20) {
Chip(
- onClick = { },
+ onClick = {},
label = { Text("List item $it") },
colors = ChipDefaults.secondaryChipColors()
)
@@ -154,7 +135,7 @@
item { ListHeader { Text("Header1") } }
items(5) {
Chip(
- onClick = { },
+ onClick = {},
label = { Text("List item $it") },
colors = ChipDefaults.secondaryChipColors()
)
@@ -162,7 +143,7 @@
item { ListHeader { Text("Header2") } }
items(5) {
Chip(
- onClick = { },
+ onClick = {},
label = { Text("List item ${it + 5}") },
colors = ChipDefaults.secondaryChipColors()
)
diff --git a/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/StepperSample.kt b/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/StepperSample.kt
index ca2344c..e35ca68 100644
--- a/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/StepperSample.kt
+++ b/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/StepperSample.kt
@@ -45,7 +45,9 @@
increaseIcon = { Icon(StepperDefaults.Increase, "Increase") },
decreaseIcon = { Icon(StepperDefaults.Decrease, "Decrease") },
steps = 7
- ) { Text("Value: $value") }
+ ) {
+ Text("Value: $value")
+ }
}
@Sampled
@@ -58,7 +60,9 @@
increaseIcon = { Icon(StepperDefaults.Increase, "Increase") },
decreaseIcon = { Icon(StepperDefaults.Decrease, "Decrease") },
valueProgression = 1..10
- ) { Text("Value: $value") }
+ ) {
+ Text("Value: $value")
+ }
}
@Sampled
@@ -73,7 +77,9 @@
decreaseIcon = { Icon(StepperDefaults.Decrease, "Decrease") },
steps = 7,
enableRangeSemantics = false
- ) { Text("Value: $value") }
+ ) {
+ Text("Value: $value")
+ }
}
@Sampled
@@ -93,7 +99,9 @@
decreaseIcon = { Icon(StepperDefaults.Decrease, "Decrease") },
steps = steps,
enableRangeSemantics = false
- ) { Text("Value: $value") }
+ ) {
+ Text("Value: $value")
+ }
}
// Declaring the custom semantics for StepperWithCustomSemanticsSample
@@ -103,27 +111,29 @@
onValueChange: (Float) -> Unit,
valueRange: ClosedFloatingPointRange<Float>,
steps: Int
-): Modifier = semantics(mergeDescendants = true) {
+): Modifier =
+ semantics(mergeDescendants = true) {
+ if (!enabled) disabled()
+ setProgress(
+ action = { targetValue ->
+ val newStepIndex =
+ ((value - valueRange.start) / (valueRange.endInclusive - valueRange.start) *
+ (steps + 1))
+ .roundToInt()
+ .coerceIn(0, steps + 1)
- if (!enabled) disabled()
- setProgress(
- action = { targetValue ->
- val newStepIndex = ((value - valueRange.start) /
- (valueRange.endInclusive - valueRange.start) * (steps + 1))
- .roundToInt().coerceIn(0, steps + 1)
-
- if (value.toInt() == newStepIndex) {
- false
- } else {
- onValueChange(targetValue)
- true
- }
+ if (value.toInt() == newStepIndex) {
+ false
+ } else {
+ onValueChange(targetValue)
+ true
+ }
+ }
+ )
}
- )
-}.progressSemantics(
- lerp(
- valueRange.start, valueRange.endInclusive,
- value / (steps + 1).toFloat()
- ).coerceIn(valueRange),
- valueRange, steps
-)
+ .progressSemantics(
+ lerp(valueRange.start, valueRange.endInclusive, value / (steps + 1).toFloat())
+ .coerceIn(valueRange),
+ valueRange,
+ steps
+ )
diff --git a/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/SwipeToDismissBoxSample.kt b/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/SwipeToDismissBoxSample.kt
index d48b72e..db4d34e 100644
--- a/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/SwipeToDismissBoxSample.kt
+++ b/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/SwipeToDismissBoxSample.kt
@@ -49,14 +49,9 @@
@Sampled
@Composable
-fun SimpleSwipeToDismissBox(
- navigateBack: () -> Unit
-) {
+fun SimpleSwipeToDismissBox(navigateBack: () -> Unit) {
val state = rememberSwipeToDismissBoxState()
- SwipeToDismissBox(
- state = state,
- onDismissed = navigateBack
- ) { isBackground ->
+ SwipeToDismissBox(state = state, onDismissed = navigateBack) { isBackground ->
if (isBackground) {
Box(modifier = Modifier.fillMaxSize().background(MaterialTheme.colors.secondaryVariant))
} else {
@@ -97,7 +92,6 @@
backgroundKey = if (!showMainScreen) "MainKey" else "Background",
contentKey = if (showMainScreen) "MainKey" else "ItemKey",
) { isBackground ->
-
if (isBackground || showMainScreen) {
// Best practice would be to use State Hoisting and leave this composable stateless.
// Here, we want to support MainScreen being shown from different destinations
@@ -110,10 +104,10 @@
// and can be shown in foreground or background.
val checked = rememberSaveable { mutableStateOf(true) }
Column(
- modifier = Modifier
- .fillMaxSize().padding(horizontal = 8.dp, vertical = 8.dp),
+ modifier =
+ Modifier.fillMaxSize().padding(horizontal = 8.dp, vertical = 8.dp),
verticalArrangement =
- Arrangement.spacedBy(4.dp, Alignment.CenterVertically),
+ Arrangement.spacedBy(4.dp, Alignment.CenterVertically),
) {
SplitToggleChip(
checked = checked.value,
@@ -123,9 +117,8 @@
onClick = { showMainScreen = false },
toggleControl = {
Icon(
- imageVector = ToggleChipDefaults.checkboxIcon(
- checked = checked.value
- ),
+ imageVector =
+ ToggleChipDefaults.checkboxIcon(checked = checked.value),
contentDescription = null,
)
}
@@ -148,31 +141,25 @@
@Sampled
@Composable
-fun EdgeSwipeForSwipeToDismiss(
- navigateBack: () -> Unit
-) {
+fun EdgeSwipeForSwipeToDismiss(navigateBack: () -> Unit) {
val state = rememberSwipeToDismissBoxState()
// When using Modifier.edgeSwipeToDismiss, it is required that the element on which the
// modifier applies exists within a SwipeToDismissBox which shares the same state.
- SwipeToDismissBox(
- state = state,
- onDismissed = navigateBack
- ) { isBackground ->
+ SwipeToDismissBox(state = state, onDismissed = navigateBack) { isBackground ->
val horizontalScrollState = rememberScrollState(0)
if (isBackground) {
- Box(
- modifier = Modifier.fillMaxSize()
- .background(MaterialTheme.colors.secondaryVariant)
- )
+ Box(modifier = Modifier.fillMaxSize().background(MaterialTheme.colors.secondaryVariant))
} else {
Box(modifier = Modifier.fillMaxSize()) {
Text(
- modifier = Modifier.align(Alignment.Center)
- .edgeSwipeToDismiss(state)
- .horizontalScroll(horizontalScrollState),
- text = "This text can be scrolled horizontally - to dismiss, swipe " +
- "right from the left edge of the screen (called Edge Swiping)",
+ modifier =
+ Modifier.align(Alignment.Center)
+ .edgeSwipeToDismiss(state)
+ .horizontalScroll(horizontalScrollState),
+ text =
+ "This text can be scrolled horizontally - to dismiss, swipe " +
+ "right from the left edge of the screen (called Edge Swiping)",
)
}
}
diff --git a/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/SwipeToRevealSample.kt b/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/SwipeToRevealSample.kt
index 44ff9ba..1fafe95 100644
--- a/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/SwipeToRevealSample.kt
+++ b/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/SwipeToRevealSample.kt
@@ -52,23 +52,24 @@
val revealState = rememberRevealState()
SwipeToRevealChip(
revealState = revealState,
- modifier = Modifier
- .fillMaxWidth()
- // Use edgeSwipeToDismiss to allow SwipeToDismissBox to capture swipe events
- .edgeSwipeToDismiss(swipeToDismissBoxState)
- .semantics {
- // Use custom actions to make the primary and secondary actions accessible
- customActions = listOf(
- CustomAccessibilityAction("Delete") {
- /* Add the primary action click handler here */
- true
- },
- CustomAccessibilityAction("More Options") {
- /* Add the secondary click handler here */
- true
- }
- )
- },
+ modifier =
+ Modifier.fillMaxWidth()
+ // Use edgeSwipeToDismiss to allow SwipeToDismissBox to capture swipe events
+ .edgeSwipeToDismiss(swipeToDismissBoxState)
+ .semantics {
+ // Use custom actions to make the primary and secondary actions accessible
+ customActions =
+ listOf(
+ CustomAccessibilityAction("Delete") {
+ /* Add the primary action click handler here */
+ true
+ },
+ CustomAccessibilityAction("More Options") {
+ /* Add the secondary click handler here */
+ true
+ }
+ )
+ },
primaryAction = {
SwipeToRevealPrimaryAction(
revealState = revealState,
@@ -106,9 +107,7 @@
onClick = { /* Add the chip click handler here */ },
colors = ChipDefaults.primaryChipColors(),
border = ChipDefaults.outlinedChipBorder(),
- label = {
- Text("SwipeToReveal Chip", maxLines = 3)
- }
+ label = { Text("SwipeToReveal Chip", maxLines = 3) }
)
}
}
@@ -120,23 +119,24 @@
val revealState = rememberRevealState()
SwipeToRevealCard(
revealState = revealState,
- modifier = Modifier
- .fillMaxWidth()
- // Use edgeSwipeToDismiss to allow SwipeToDismissBox to capture swipe events
- .edgeSwipeToDismiss(swipeToDismissBoxState)
- .semantics {
- // Use custom actions to make the primary and secondary actions accessible
- customActions = listOf(
- CustomAccessibilityAction("Delete") {
- /* Add the primary action click handler here */
- true
- },
- CustomAccessibilityAction("More Options") {
- /* Add the secondary click handler here */
- true
- }
- )
- },
+ modifier =
+ Modifier.fillMaxWidth()
+ // Use edgeSwipeToDismiss to allow SwipeToDismissBox to capture swipe events
+ .edgeSwipeToDismiss(swipeToDismissBoxState)
+ .semantics {
+ // Use custom actions to make the primary and secondary actions accessible
+ customActions =
+ listOf(
+ CustomAccessibilityAction("Delete") {
+ /* Add the primary action click handler here */
+ true
+ },
+ CustomAccessibilityAction("More Options") {
+ /* Add the secondary click handler here */
+ true
+ }
+ )
+ },
primaryAction = {
SwipeToRevealPrimaryAction(
revealState = revealState,
@@ -176,8 +176,9 @@
Icon(
painter = painterResource(id = R.drawable.ic_airplanemode_active_24px),
contentDescription = "airplane",
- modifier = Modifier.size(CardDefaults.AppImageSize)
- .wrapContentSize(align = Alignment.Center),
+ modifier =
+ Modifier.size(CardDefaults.AppImageSize)
+ .wrapContentSize(align = Alignment.Center),
)
},
title = { Text("AppCard") },
diff --git a/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/TimeTextSample.kt b/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/TimeTextSample.kt
index c2a55c9..57c53e6 100644
--- a/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/TimeTextSample.kt
+++ b/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/TimeTextSample.kt
@@ -63,17 +63,9 @@
val leadingTextStyle = TimeTextDefaults.timeTextStyle(color = MaterialTheme.colors.primary)
TimeText(
- startLinearContent = {
- Text(
- text = "ETA 12:48",
- style = leadingTextStyle
- )
- },
+ startLinearContent = { Text(text = "ETA 12:48", style = leadingTextStyle) },
startCurvedContent = {
- curvedText(
- text = "ETA 12:48",
- style = CurvedTextStyle(leadingTextStyle)
- )
+ curvedText(text = "ETA 12:48", style = CurvedTextStyle(leadingTextStyle))
},
)
}
@@ -82,9 +74,10 @@
@Composable
fun TimeTextWithFullDateAndTimeFormat() {
TimeText(
- timeSource = TimeTextDefaults.timeSource(
- DateFormat.getBestDateTimePattern(Locale.getDefault(), "yyyy-MM-dd hh:mm")
- )
+ timeSource =
+ TimeTextDefaults.timeSource(
+ DateFormat.getBestDateTimePattern(Locale.getDefault(), "yyyy-MM-dd hh:mm")
+ )
)
}
@@ -95,35 +88,39 @@
val showTransition = updateTransition(showState)
val time = 350
- val animatedColor by showTransition.animateColor(label = "animatedColor",
- transitionSpec = {
- tween(time, easing =
- when {
- false isTransitioningTo true ->
- // Fade In
- CubicBezierEasing(0.4f, 0.0f, 1.0f, 1.0f)
- else ->
- // Fade Out
- CubicBezierEasing(0.0f, 0.0f, 0.2f, 1.0f)
- }
- )
+ val animatedColor by
+ showTransition.animateColor(
+ label = "animatedColor",
+ transitionSpec = {
+ tween(
+ time,
+ easing =
+ when {
+ false isTransitioningTo true ->
+ // Fade In
+ CubicBezierEasing(0.4f, 0.0f, 1.0f, 1.0f)
+ else ->
+ // Fade Out
+ CubicBezierEasing(0.0f, 0.0f, 0.2f, 1.0f)
+ }
+ )
+ }
+ ) { state ->
+ when (state) {
+ true -> Color.White
+ false -> Color.Transparent
+ }
}
- ) { state ->
- when (state) {
- true -> Color.White
- false -> Color.Transparent
+ val animateSize by
+ showTransition.animateFloat(
+ label = "animatedSize",
+ transitionSpec = { tween(time, easing = CubicBezierEasing(0.4f, 0.0f, 0.2f, 1.0f)) }
+ ) { state ->
+ when (state) {
+ true -> 1f
+ false -> 0f
+ }
}
- }
- val animateSize by showTransition.animateFloat(label = "animatedSize",
- transitionSpec = {
- tween(time, easing = CubicBezierEasing(0.4f, 0.0f, 0.2f, 1.0f))
- }
- ) { state ->
- when (state) {
- true -> 1f
- false -> 0f
- }
- }
val text = "Long text to animate"
@@ -137,10 +134,8 @@
val linearAnimatedSize = animateSize * (linearSeparatorSize + linearTextSize)
val linearSeparatorGap = linearAnimatedSize.coerceAtMost(linearSeparatorSize) / 2f
- val textStyle = TimeTextDefaults.timeTextStyle().copy(
- fontWeight = FontWeight.Normal,
- color = animatedColor
- )
+ val textStyle =
+ TimeTextDefaults.timeTextStyle().copy(fontWeight = FontWeight.Normal, color = animatedColor)
Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
TimeText(
// Curved
@@ -150,13 +145,16 @@
curvedColumn(modifier = CurvedModifier.angularSize(curvedSeparatorGap)) {}
},
startCurvedContent = {
- curvedRow(modifier = CurvedModifier.sizeIn(maxSweepDegrees =
- (curvedAnimatedSweep - curvedSeparatorSweep).coerceAtLeast(0f))) {
+ curvedRow(
+ modifier =
+ CurvedModifier.sizeIn(
+ maxSweepDegrees =
+ (curvedAnimatedSweep - curvedSeparatorSweep).coerceAtLeast(0f)
+ )
+ ) {
curvedText(
text,
- CurvedModifier.sizeIn(
- maxSweepDegrees = curvedTextSweep
- ),
+ CurvedModifier.sizeIn(maxSweepDegrees = curvedTextSweep),
style = CurvedTextStyle(textStyle),
overflow = TextOverflow.Ellipsis
)
@@ -169,28 +167,25 @@
Spacer(modifier = Modifier.width(linearSeparatorGap))
},
startLinearContent = {
- Box(modifier = Modifier
- .clipToBounds()
- .widthIn(
- max = (linearAnimatedSize - linearSeparatorSize).coerceAtLeast(0.dp)
- )) {
+ Box(
+ modifier =
+ Modifier.clipToBounds()
+ .widthIn(
+ max = (linearAnimatedSize - linearSeparatorSize).coerceAtLeast(0.dp)
+ )
+ ) {
Text(
text,
maxLines = 1,
style = textStyle,
- modifier = Modifier
- .wrapContentWidth(
- align = Alignment.Start,
- unbounded = true
- )
- .widthIn(max = linearTextSize),
+ modifier =
+ Modifier.wrapContentWidth(align = Alignment.Start, unbounded = true)
+ .widthIn(max = linearTextSize),
overflow = TextOverflow.Ellipsis
)
}
},
)
- Button(onClick = { showState = !showState }) {
- Text("Go!")
- }
+ Button(onClick = { showState = !showState }) { Text("Go!") }
}
}
diff --git a/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/ToggleButtonSample.kt b/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/ToggleButtonSample.kt
index d7c8c10..a29aa78 100644
--- a/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/ToggleButtonSample.kt
+++ b/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/ToggleButtonSample.kt
@@ -43,9 +43,9 @@
Icon(
painter = painterResource(id = R.drawable.ic_airplanemode_active_24px),
contentDescription = "airplane",
- modifier = Modifier
- .size(ToggleButtonDefaults.DefaultIconSize)
- .wrapContentSize(align = Alignment.Center),
+ modifier =
+ Modifier.size(ToggleButtonDefaults.DefaultIconSize)
+ .wrapContentSize(align = Alignment.Center),
)
}
}
diff --git a/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/ToggleChipSample.kt b/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/ToggleChipSample.kt
index 606231a..3e3d95a 100644
--- a/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/ToggleChipSample.kt
+++ b/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/ToggleChipSample.kt
@@ -44,9 +44,7 @@
// The primary label should have a maximum 3 lines of text
// and the secondary label should have max 2 lines of text.
ToggleChip(
- label = {
- Text("SwitchIcon", maxLines = 3, overflow = TextOverflow.Ellipsis)
- },
+ label = { Text("SwitchIcon", maxLines = 3, overflow = TextOverflow.Ellipsis) },
secondaryLabel = {
Text("With secondary label", maxLines = 2, overflow = TextOverflow.Ellipsis)
},
@@ -54,9 +52,10 @@
// For Switch toggle controls the Wear Material UX guidance is to set the
// unselected toggle control color to ToggleChipDefaults.switchUncheckedIconColor()
// rather than the default.
- colors = ToggleChipDefaults.toggleChipColors(
- uncheckedToggleControlColor = ToggleChipDefaults.SwitchUncheckedIconColor
- ),
+ colors =
+ ToggleChipDefaults.toggleChipColors(
+ uncheckedToggleControlColor = ToggleChipDefaults.SwitchUncheckedIconColor
+ ),
toggleControl = {
Switch(
checked = checked,
@@ -82,9 +81,7 @@
// The primary label should have a maximum 3 lines of text
// and the secondary label should have max 2 lines of text.
SplitToggleChip(
- label = {
- Text("Split with CheckboxIcon", maxLines = 3, overflow = TextOverflow.Ellipsis)
- },
+ label = { Text("Split with CheckboxIcon", maxLines = 3, overflow = TextOverflow.Ellipsis) },
checked = checked,
toggleControl = {
Checkbox(
diff --git a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/ButtonScreenshotTest.kt b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/ButtonScreenshotTest.kt
index 7e13a9d..7322c4f 100644
--- a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/ButtonScreenshotTest.kt
+++ b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/ButtonScreenshotTest.kt
@@ -40,29 +40,22 @@
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
class ButtonScreenshotTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
- @get:Rule
- val screenshotRule = AndroidXScreenshotTestRule(SCREENSHOT_GOLDEN_PATH)
+ @get:Rule val screenshotRule = AndroidXScreenshotTestRule(SCREENSHOT_GOLDEN_PATH)
- @get:Rule
- val testName = TestName()
+ @get:Rule val testName = TestName()
@Test
fun button_ltr() =
verifyScreenshot(LayoutDirection.Ltr) {
- Button(onClick = {}, modifier = Modifier.testTag(TEST_TAG)) {
- Text("abc")
- }
+ Button(onClick = {}, modifier = Modifier.testTag(TEST_TAG)) { Text("abc") }
}
@Test
fun button_rtl() =
verifyScreenshot(LayoutDirection.Rtl) {
- Button(onClick = {}, modifier = Modifier.testTag(TEST_TAG)) {
- Text("abc")
- }
+ Button(onClick = {}, modifier = Modifier.testTag(TEST_TAG)) { Text("abc") }
}
@Test
@@ -88,48 +81,39 @@
}
@Test
- fun button_disabled() =
- verifyScreenshot {
- Button(onClick = {}, enabled = false, modifier = Modifier.testTag(TEST_TAG)) {
- Text("abc")
- }
- }
+ fun button_disabled() = verifyScreenshot {
+ Button(onClick = {}, enabled = false, modifier = Modifier.testTag(TEST_TAG)) { Text("abc") }
+ }
@Test
fun compactbutton_ltr() =
verifyScreenshot(LayoutDirection.Ltr) {
- CompactButton(onClick = {}, modifier = Modifier.testTag(TEST_TAG)) {
- Text("xs")
- }
+ CompactButton(onClick = {}, modifier = Modifier.testTag(TEST_TAG)) { Text("xs") }
}
@Test
fun compactbutton_rtl() =
verifyScreenshot(LayoutDirection.Rtl) {
- CompactButton(onClick = {}, modifier = Modifier.testTag(TEST_TAG)) {
- Text("xs")
- }
+ CompactButton(onClick = {}, modifier = Modifier.testTag(TEST_TAG)) { Text("xs") }
}
@Test
- fun compactbutton_disabled() =
- verifyScreenshot {
- CompactButton(onClick = {}, enabled = false, modifier = Modifier.testTag(TEST_TAG)) {
- Text("xs")
- }
+ fun compactbutton_disabled() = verifyScreenshot {
+ CompactButton(onClick = {}, enabled = false, modifier = Modifier.testTag(TEST_TAG)) {
+ Text("xs")
}
+ }
private fun verifyScreenshot(
layoutDirection: LayoutDirection = LayoutDirection.Ltr,
content: @Composable () -> Unit
) {
rule.setContentWithTheme {
- CompositionLocalProvider(LocalLayoutDirection provides layoutDirection) {
- content()
- }
+ CompositionLocalProvider(LocalLayoutDirection provides layoutDirection) { content() }
}
- rule.onNodeWithTag(TEST_TAG)
+ rule
+ .onNodeWithTag(TEST_TAG)
.captureToImage()
.assertAgainstGolden(screenshotRule, testName.methodName)
}
diff --git a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/ButtonTest.kt b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/ButtonTest.kt
index 6e175d7..afe0d26 100644
--- a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/ButtonTest.kt
+++ b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/ButtonTest.kt
@@ -58,18 +58,12 @@
import org.junit.Test
public class ButtonBehaviourTest {
- @get:Rule
- public val rule = createComposeRule()
+ @get:Rule public val rule = createComposeRule()
@Test
public fun supports_testtag_on_button_for_image() {
rule.setContentWithTheme {
- Button(
- onClick = {},
- modifier = Modifier.testTag(TEST_TAG)
- ) {
- TestImage()
- }
+ Button(onClick = {}, modifier = Modifier.testTag(TEST_TAG)) { TestImage() }
}
rule.onNodeWithTag(TEST_TAG).assertExists()
@@ -78,12 +72,7 @@
@Test
public fun supports_testtag_on_button_for_text() {
rule.setContentWithTheme {
- Button(
- onClick = {},
- modifier = Modifier.testTag(TEST_TAG)
- ) {
- Text("Test")
- }
+ Button(onClick = {}, modifier = Modifier.testTag(TEST_TAG)) { Text("Test") }
}
rule.onNodeWithTag(TEST_TAG).assertExists()
@@ -92,12 +81,7 @@
@Test
public fun supports_testtag_on_compactbutton_for_image() {
rule.setContentWithTheme {
- CompactButton(
- onClick = {},
- modifier = Modifier.testTag(TEST_TAG)
- ) {
- TestImage()
- }
+ CompactButton(onClick = {}, modifier = Modifier.testTag(TEST_TAG)) { TestImage() }
}
rule.onNodeWithTag(TEST_TAG).assertExists()
@@ -106,12 +90,7 @@
@Test
public fun supports_testtag_on_compactbutton_for_text() {
rule.setContentWithTheme {
- CompactButton(
- onClick = {},
- modifier = Modifier.testTag(TEST_TAG)
- ) {
- Text("Test")
- }
+ CompactButton(onClick = {}, modifier = Modifier.testTag(TEST_TAG)) { Text("Test") }
}
rule.onNodeWithTag(TEST_TAG).assertExists()
@@ -120,11 +99,7 @@
@Test
public fun has_clickaction_when_enabled_for_image() {
rule.setContentWithTheme {
- Button(
- onClick = {},
- enabled = true,
- modifier = Modifier.testTag(TEST_TAG)
- ) {
+ Button(onClick = {}, enabled = true, modifier = Modifier.testTag(TEST_TAG)) {
TestImage()
}
}
@@ -135,11 +110,7 @@
@Test
public fun has_clickaction_when_enabled_for_text() {
rule.setContentWithTheme {
- Button(
- onClick = {},
- enabled = true,
- modifier = Modifier.testTag(TEST_TAG)
- ) {
+ Button(onClick = {}, enabled = true, modifier = Modifier.testTag(TEST_TAG)) {
Text("Test")
}
}
@@ -150,11 +121,7 @@
@Test
public fun has_clickaction_when_disabled_for_image() {
rule.setContentWithTheme {
- Button(
- onClick = {},
- enabled = false,
- modifier = Modifier.testTag(TEST_TAG)
- ) {
+ Button(onClick = {}, enabled = false, modifier = Modifier.testTag(TEST_TAG)) {
TestImage()
}
}
@@ -165,11 +132,7 @@
@Test
public fun has_clickaction_when_disabled_for_text() {
rule.setContentWithTheme {
- Button(
- onClick = {},
- enabled = false,
- modifier = Modifier.testTag(TEST_TAG)
- ) {
+ Button(onClick = {}, enabled = false, modifier = Modifier.testTag(TEST_TAG)) {
Text("Test")
}
}
@@ -180,11 +143,7 @@
@Test
public fun is_correctly_enabled() {
rule.setContentWithTheme {
- Button(
- onClick = {},
- enabled = true,
- modifier = Modifier.testTag(TEST_TAG)
- ) {
+ Button(onClick = {}, enabled = true, modifier = Modifier.testTag(TEST_TAG)) {
TestImage()
}
}
@@ -195,11 +154,7 @@
@Test
public fun is_correctly_disabled() {
rule.setContentWithTheme {
- Button(
- onClick = {},
- enabled = false,
- modifier = Modifier.testTag(TEST_TAG)
- ) {
+ Button(onClick = {}, enabled = false, modifier = Modifier.testTag(TEST_TAG)) {
Text("Test")
}
}
@@ -223,9 +178,7 @@
rule.onNodeWithTag(TEST_TAG).performClick()
- rule.runOnIdle {
- assertEquals(true, clicked)
- }
+ rule.runOnIdle { assertEquals(true, clicked) }
}
@Test
@@ -244,9 +197,7 @@
rule.onNodeWithTag(TEST_TAG).performClick()
- rule.runOnIdle {
- assertEquals(true, clicked)
- }
+ rule.runOnIdle { assertEquals(true, clicked) }
}
@Test
@@ -265,9 +216,7 @@
rule.onNodeWithTag(TEST_TAG).performClick()
- rule.runOnIdle {
- assertEquals(false, clicked)
- }
+ rule.runOnIdle { assertEquals(false, clicked) }
}
@Test
@@ -286,49 +235,29 @@
rule.onNodeWithTag(TEST_TAG).performClick()
- rule.runOnIdle {
- assertEquals(false, clicked)
- }
+ rule.runOnIdle { assertEquals(false, clicked) }
}
@Test
public fun has_role_button_for_compact_image() {
rule.setContentWithTheme {
- CompactButton(
- onClick = {},
- modifier = Modifier.testTag(TEST_TAG)
- ) {
- TestImage()
- }
+ CompactButton(onClick = {}, modifier = Modifier.testTag(TEST_TAG)) { TestImage() }
}
- rule.onNodeWithTag(TEST_TAG)
- .assert(
- SemanticsMatcher.expectValue(
- SemanticsProperties.Role,
- Role.Button
- )
- )
+ rule
+ .onNodeWithTag(TEST_TAG)
+ .assert(SemanticsMatcher.expectValue(SemanticsProperties.Role, Role.Button))
}
@Test
public fun has_role_button_for_text() {
rule.setContentWithTheme {
- Button(
- onClick = {},
- modifier = Modifier.testTag(TEST_TAG)
- ) {
- Text("Test")
- }
+ Button(onClick = {}, modifier = Modifier.testTag(TEST_TAG)) { Text("Test") }
}
- rule.onNodeWithTag(TEST_TAG)
- .assert(
- SemanticsMatcher.expectValue(
- SemanticsProperties.Role,
- Role.Button
- )
- )
+ rule
+ .onNodeWithTag(TEST_TAG)
+ .assert(SemanticsMatcher.expectValue(SemanticsProperties.Role, Role.Button))
}
@Test
@@ -411,8 +340,7 @@
}
public class ButtonSizeTest {
- @get:Rule
- public val rule = createComposeRule()
+ @get:Rule public val rule = createComposeRule()
@Test
public fun gives_compactbutton_correct_tapsize() {
@@ -439,10 +367,7 @@
@Test
public fun gives_small_button_correct_tapsize() {
rule.verifyTapSize(TapSize.Small) {
- Button(
- onClick = {},
- modifier = Modifier.size(ButtonDefaults.SmallButtonSize)
- ) {
+ Button(onClick = {}, modifier = Modifier.size(ButtonDefaults.SmallButtonSize)) {
TestImage()
}
}
@@ -451,10 +376,7 @@
@Test
public fun gives_large_button_correct_tapsize() {
rule.verifyTapSize(TapSize.Large) {
- Button(
- onClick = {},
- modifier = Modifier.size(ButtonDefaults.LargeButtonSize)
- ) {
+ Button(onClick = {}, modifier = Modifier.size(ButtonDefaults.LargeButtonSize)) {
TestImage()
}
}
@@ -462,8 +384,7 @@
}
public class ButtonShapeTest {
- @get:Rule
- public val rule = createComposeRule()
+ @get:Rule public val rule = createComposeRule()
@Test
public fun default_button_shape_is_circle() {
@@ -473,8 +394,7 @@
enabled = true,
colors = ButtonDefaults.primaryButtonColors(),
modifier = modifier
- ) {
- }
+ ) {}
}
}
@@ -489,8 +409,7 @@
colors = ButtonDefaults.primaryButtonColors(),
modifier = modifier,
shape = shape
- ) {
- }
+ ) {}
}
}
@@ -503,8 +422,7 @@
colors = ButtonDefaults.primaryButtonColors(),
backgroundPadding = 0.dp,
modifier = modifier
- ) {
- }
+ ) {}
}
}
@@ -520,15 +438,13 @@
backgroundPadding = 0.dp,
modifier = modifier,
shape = shape
- ) {
- }
+ ) {}
}
}
}
public class ButtonColorTest {
- @get:Rule
- public val rule = createComposeRule()
+ @get:Rule public val rule = createComposeRule()
@Test
public fun gives_enabled_button_primary_colors() =
@@ -621,6 +537,7 @@
{ Color.Transparent },
{ MaterialTheme.colors.primary },
)
+
@Test
public fun gives_enabled_compact_button_icon_colors() =
verifyCompactButtonColors(
@@ -647,6 +564,7 @@
{ Color.Transparent },
{ MaterialTheme.colors.primary },
)
+
@Test
public fun gives_disabled_compact_button_icon_colors() =
verifyCompactButtonColors(
@@ -667,14 +585,11 @@
colors = ButtonDefaults.buttonColors(backgroundColor = overrideColor),
enabled = true,
modifier = Modifier.testTag(TEST_TAG)
- ) {
- }
+ ) {}
}
}
- rule.onNodeWithTag(TEST_TAG)
- .captureToImage()
- .assertContainsColor(overrideColor, 50.0f)
+ rule.onNodeWithTag(TEST_TAG).captureToImage().assertContainsColor(overrideColor, 50.0f)
}
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
@@ -688,14 +603,11 @@
colors = ButtonDefaults.buttonColors(backgroundColor = overrideColor),
enabled = true,
modifier = Modifier.testTag(TEST_TAG)
- ) {
- }
+ ) {}
}
}
- rule.onNodeWithTag(TEST_TAG)
- .captureToImage()
- .assertContainsColor(overrideColor, 25.0f)
+ rule.onNodeWithTag(TEST_TAG).captureToImage().assertContainsColor(overrideColor, 25.0f)
}
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
@@ -709,14 +621,11 @@
colors = ButtonDefaults.buttonColors(disabledBackgroundColor = overrideColor),
enabled = false,
modifier = Modifier.testTag(TEST_TAG)
- ) {
- }
+ ) {}
}
}
- rule.onNodeWithTag(TEST_TAG)
- .captureToImage()
- .assertContainsColor(overrideColor, 50.0f)
+ rule.onNodeWithTag(TEST_TAG).captureToImage().assertContainsColor(overrideColor, 50.0f)
}
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
@@ -730,14 +639,11 @@
colors = ButtonDefaults.buttonColors(disabledBackgroundColor = overrideColor),
enabled = false,
modifier = Modifier.testTag(TEST_TAG)
- ) {
- }
+ ) {}
}
}
- rule.onNodeWithTag(TEST_TAG)
- .captureToImage()
- .assertContainsColor(overrideColor, 25.0f)
+ rule.onNodeWithTag(TEST_TAG).captureToImage().assertContainsColor(overrideColor, 25.0f)
}
@Test
@@ -910,25 +816,22 @@
} else {
expectedBackground =
backgroundColor()
- .copy(alpha = ContentAlpha.disabled).compositeOver(testBackground)
+ .copy(alpha = ContentAlpha.disabled)
+ .compositeOver(testBackground)
expectedContent =
if (applyAlphaForDisabledContent)
contentColor().copy(alpha = ContentAlpha.disabled)
- else
- contentColor()
+ else contentColor()
}
- Box(
- modifier = Modifier
- .fillMaxSize()
- .background(testBackground)
- ) {
+ Box(modifier = Modifier.fillMaxSize().background(testBackground)) {
actualContent = content()
}
}
assertEquals(expectedContent, actualContent)
- rule.onNodeWithTag(TEST_TAG)
+ rule
+ .onNodeWithTag(TEST_TAG)
.captureToImage()
.assertContainsColor(
if (expectedBackground != Color.Transparent) expectedBackground else testBackground,
@@ -938,8 +841,7 @@
}
public class ButtonTextStyleTest {
- @get:Rule
- public val rule = createComposeRule()
+ @get:Rule public val rule = createComposeRule()
@Test
public fun gives_button_correct_font() {
@@ -980,9 +882,7 @@
expected: TapSize,
content: @Composable () -> Unit
) {
- setContentWithThemeForSizeAssertions {
- content()
- }
+ setContentWithThemeForSizeAssertions { content() }
.assertHeightIsEqualTo(expected.size)
.assertWidthIsEqualTo(expected.size)
}
@@ -999,13 +899,7 @@
background = MaterialTheme.colors.primary
surface = MaterialTheme.colors.surface
CompositionLocalProvider(LocalLayoutDirection provides layoutDirection) {
- Box(
- Modifier
- .padding(padding)
- .background(surface)
- ) {
- content()
- }
+ Box(Modifier.padding(padding).background(surface)) { content() }
}
}
@@ -1034,11 +928,7 @@
background = MaterialTheme.colors.surface
Box(Modifier.background(background)) {
buttonColor = MaterialTheme.colors.primary
- content(
- Modifier
- .testTag(TEST_TAG)
- .padding(padding)
- )
+ content(Modifier.testTag(TEST_TAG).padding(padding))
}
}
diff --git a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/CardScreenshotTest.kt b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/CardScreenshotTest.kt
index 6edabec..d7fa8e5 100644
--- a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/CardScreenshotTest.kt
+++ b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/CardScreenshotTest.kt
@@ -50,50 +50,41 @@
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
class CardScreenshotTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
- @get:Rule
- val screenshotRule = AndroidXScreenshotTestRule(SCREENSHOT_GOLDEN_PATH)
+ @get:Rule val screenshotRule = AndroidXScreenshotTestRule(SCREENSHOT_GOLDEN_PATH)
- @get:Rule
- val testName = TestName()
+ @get:Rule val testName = TestName()
@Test
- fun app_card_ltr() = verifyScreenshot(layoutDirection = LayoutDirection.Ltr) {
- sampleAppCard()
- }
+ fun app_card_ltr() = verifyScreenshot(layoutDirection = LayoutDirection.Ltr) { sampleAppCard() }
@Test
- fun app_card_disabled() = verifyScreenshot(layoutDirection = LayoutDirection.Ltr) {
- sampleAppCard(enabled = false)
- }
+ fun app_card_disabled() =
+ verifyScreenshot(layoutDirection = LayoutDirection.Ltr) { sampleAppCard(enabled = false) }
@Test
- fun app_card_rtl() = verifyScreenshot(layoutDirection = LayoutDirection.Rtl) {
- sampleAppCard()
- }
+ fun app_card_rtl() = verifyScreenshot(layoutDirection = LayoutDirection.Rtl) { sampleAppCard() }
@Test
- fun title_card_ltr() = verifyScreenshot(layoutDirection = LayoutDirection.Ltr) {
- sampleTitleCard()
- }
+ fun title_card_ltr() =
+ verifyScreenshot(layoutDirection = LayoutDirection.Ltr) { sampleTitleCard() }
@Test
- fun title_card_disabled() = verifyScreenshot(layoutDirection = LayoutDirection.Ltr) {
- sampleTitleCard(enabled = false)
- }
+ fun title_card_disabled() =
+ verifyScreenshot(layoutDirection = LayoutDirection.Ltr) { sampleTitleCard(enabled = false) }
@Test
- fun title_card_rtl() = verifyScreenshot(layoutDirection = LayoutDirection.Rtl) {
- sampleTitleCard()
- }
+ fun title_card_rtl() =
+ verifyScreenshot(layoutDirection = LayoutDirection.Rtl) { sampleTitleCard() }
@Test
fun title_card_image_background() = verifyScreenshot {
sampleTitleCard(
- backgroundPainter = CardDefaults.imageWithScrimBackgroundPainter(
- backgroundImagePainter = painterResource(id = R.drawable.backgroundimage1))
+ backgroundPainter =
+ CardDefaults.imageWithScrimBackgroundPainter(
+ backgroundImagePainter = painterResource(id = R.drawable.backgroundimage1)
+ )
)
}
@@ -136,12 +127,11 @@
content: @Composable () -> Unit
) {
rule.setContentWithTheme {
- CompositionLocalProvider(LocalLayoutDirection provides layoutDirection) {
- content()
- }
+ CompositionLocalProvider(LocalLayoutDirection provides layoutDirection) { content() }
}
- rule.onNodeWithTag(TEST_TAG)
+ rule
+ .onNodeWithTag(TEST_TAG)
.captureToImage()
.assertAgainstGolden(screenshotRule, testName.methodName)
}
diff --git a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/CardTest.kt b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/CardTest.kt
index 63805c3..b13ab144 100644
--- a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/CardTest.kt
+++ b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/CardTest.kt
@@ -42,18 +42,12 @@
import org.junit.Test
public class CardBehaviourTest {
- @get:Rule
- public val rule: ComposeContentTestRule = createComposeRule()
+ @get:Rule public val rule: ComposeContentTestRule = createComposeRule()
@Test
public fun supports_test_tag() {
rule.setContentWithTheme {
- Card(
- onClick = {},
- modifier = Modifier.testTag(TEST_TAG)
- ) {
- TestImage()
- }
+ Card(onClick = {}, modifier = Modifier.testTag(TEST_TAG)) { TestImage() }
}
rule.onNodeWithTag(TEST_TAG).assertExists()
@@ -62,11 +56,7 @@
@Test
public fun has_clickaction_when_enabled() {
rule.setContentWithTheme {
- Card(
- onClick = {},
- enabled = true,
- modifier = Modifier.testTag(TEST_TAG)
- ) {
+ Card(onClick = {}, enabled = true, modifier = Modifier.testTag(TEST_TAG)) {
TestImage()
}
}
@@ -77,11 +67,7 @@
@Test
public fun has_clickaction_when_disabled() {
rule.setContentWithTheme {
- Card(
- onClick = {},
- enabled = false,
- modifier = Modifier.testTag(TEST_TAG)
- ) {
+ Card(onClick = {}, enabled = false, modifier = Modifier.testTag(TEST_TAG)) {
TestImage()
}
}
@@ -92,11 +78,7 @@
@Test
public fun is_correctly_enabled_when_enabled_equals_true() {
rule.setContentWithTheme {
- Card(
- onClick = {},
- enabled = true,
- modifier = Modifier.testTag(TEST_TAG)
- ) {
+ Card(onClick = {}, enabled = true, modifier = Modifier.testTag(TEST_TAG)) {
TestImage()
}
}
@@ -107,11 +89,7 @@
@Test
public fun is_correctly_disabled_when_enabled_equals_false() {
rule.setContentWithTheme {
- Card(
- onClick = {},
- enabled = false,
- modifier = Modifier.testTag(TEST_TAG)
- ) {
+ Card(onClick = {}, enabled = false, modifier = Modifier.testTag(TEST_TAG)) {
TestImage()
}
}
@@ -135,9 +113,7 @@
rule.onNodeWithTag(TEST_TAG).performClick()
- rule.runOnIdle {
- assertEquals(true, clicked)
- }
+ rule.runOnIdle { assertEquals(true, clicked) }
}
@Test
@@ -156,9 +132,7 @@
rule.onNodeWithTag(TEST_TAG).performClick()
- rule.runOnIdle {
- assertEquals(false, clicked)
- }
+ rule.runOnIdle { assertEquals(false, clicked) }
}
@Test
@@ -174,19 +148,14 @@
}
}
- rule.onNodeWithTag(TEST_TAG)
- .assert(
- SemanticsMatcher.expectValue(
- SemanticsProperties.Role,
- Role.Button
- )
- )
+ rule
+ .onNodeWithTag(TEST_TAG)
+ .assert(SemanticsMatcher.expectValue(SemanticsProperties.Role, Role.Button))
}
}
public class AppCardTest {
- @get:Rule
- public val rule: ComposeContentTestRule = createComposeRule()
+ @get:Rule public val rule: ComposeContentTestRule = createComposeRule()
@Test
public fun responds_to_click_when_enabled() {
@@ -207,9 +176,7 @@
rule.onNodeWithTag(TEST_TAG).performClick()
- rule.runOnIdle {
- assertEquals(true, clicked)
- }
+ rule.runOnIdle { assertEquals(true, clicked) }
}
@Test
@@ -231,15 +198,12 @@
rule.onNodeWithTag(TEST_TAG).performClick()
- rule.runOnIdle {
- assertEquals(false, clicked)
- }
+ rule.runOnIdle { assertEquals(false, clicked) }
}
}
public class TitleCardTest {
- @get:Rule
- public val rule: ComposeContentTestRule = createComposeRule()
+ @get:Rule public val rule: ComposeContentTestRule = createComposeRule()
@Test
public fun responds_to_click_when_enabled() {
@@ -259,9 +223,7 @@
rule.onNodeWithTag(TEST_TAG).performClick()
- rule.runOnIdle {
- assertEquals(true, clicked)
- }
+ rule.runOnIdle { assertEquals(true, clicked) }
}
@Test
@@ -282,22 +244,20 @@
rule.onNodeWithTag(TEST_TAG).performClick()
- rule.runOnIdle {
- assertEquals(false, clicked)
- }
+ rule.runOnIdle { assertEquals(false, clicked) }
}
}
public class CardSizeTest {
- @get:Rule
- public val rule: ComposeContentTestRule = createComposeRule()
+ @get:Rule public val rule: ComposeContentTestRule = createComposeRule()
@Test
public fun gives_base_card_correct_default_max_height(): Unit =
verifyHeight(
- expectedHeight = 100.dp +
- CardDefaults.ContentPadding.calculateBottomPadding() +
- CardDefaults.ContentPadding.calculateTopPadding(),
+ expectedHeight =
+ 100.dp +
+ CardDefaults.ContentPadding.calculateBottomPadding() +
+ CardDefaults.ContentPadding.calculateTopPadding(),
imageModifier = Modifier.requiredHeight(100.dp)
)
@@ -313,20 +273,23 @@
}
public class CardColorTest {
- @get:Rule
- public val rule: ComposeContentTestRule = createComposeRule()
+ @get:Rule public val rule: ComposeContentTestRule = createComposeRule()
@Test
public fun gives_enabled_default_colors(): Unit =
verifyColors(
CardStatus.Enabled,
- ) { MaterialTheme.colors.onSurfaceVariant }
+ ) {
+ MaterialTheme.colors.onSurfaceVariant
+ }
@Test
public fun gives_disabled_default_colors(): Unit =
verifyColors(
CardStatus.Disabled,
- ) { MaterialTheme.colors.onSurfaceVariant }
+ ) {
+ MaterialTheme.colors.onSurfaceVariant
+ }
@Test
public fun app_card_gives_default_colors() {
@@ -345,11 +308,7 @@
expectedTimeColor = MaterialTheme.colors.onSurfaceVariant
expectedTitleColor = MaterialTheme.colors.onSurface
expectedContentColor = MaterialTheme.colors.onSurfaceVariant
- Box(
- modifier = Modifier
- .fillMaxSize()
- .background(testBackground)
- ) {
+ Box(modifier = Modifier.fillMaxSize().background(testBackground)) {
AppCard(
onClick = {},
appName = { actualAppColor = LocalContentColor.current },
@@ -382,11 +341,7 @@
expectedTimeColor = MaterialTheme.colors.onSurfaceVariant
expectedTitleColor = MaterialTheme.colors.onSurface
expectedContentColor = MaterialTheme.colors.onSurfaceVariant
- Box(
- modifier = Modifier
- .fillMaxSize()
- .background(testBackground)
- ) {
+ Box(modifier = Modifier.fillMaxSize().background(testBackground)) {
TitleCard(
onClick = {},
time = { actualTimeColor = LocalContentColor.current },
@@ -403,21 +358,14 @@
assertEquals(expectedContentColor, actualContentColor)
}
- private fun verifyColors(
- status: CardStatus,
- contentColor: @Composable () -> Color
- ) {
+ private fun verifyColors(status: CardStatus, contentColor: @Composable () -> Color) {
var expectedContent = Color.Transparent
var actualContent = Color.Transparent
val testBackground = Color.White
rule.setContentWithTheme {
expectedContent = contentColor()
- Box(
- modifier = Modifier
- .fillMaxSize()
- .background(testBackground)
- ) {
+ Box(modifier = Modifier.fillMaxSize().background(testBackground)) {
Card(
onClick = {},
content = { actualContent = LocalContentColor.current },
@@ -432,8 +380,7 @@
}
public class CardFontTest {
- @get:Rule
- public val rule: ComposeContentTestRule = createComposeRule()
+ @get:Rule public val rule: ComposeContentTestRule = createComposeRule()
@Test
public fun gives_correct_text_style_base() {
@@ -443,9 +390,7 @@
expectedTextStyle = MaterialTheme.typography.button
Card(
onClick = {},
- content = {
- actualTextStyle = LocalTextStyle.current
- },
+ content = { actualTextStyle = LocalTextStyle.current },
enabled = true,
modifier = Modifier.testTag(TEST_TAG)
)
@@ -472,15 +417,9 @@
AppCard(
onClick = {},
- appName = {
- actualAppTextStyle = LocalTextStyle.current
- },
- time = {
- actualTimeTextStyle = LocalTextStyle.current
- },
- title = {
- actualTitleTextStyle = LocalTextStyle.current
- },
+ appName = { actualAppTextStyle = LocalTextStyle.current },
+ time = { actualTimeTextStyle = LocalTextStyle.current },
+ title = { actualTitleTextStyle = LocalTextStyle.current },
modifier = Modifier.testTag(TEST_TAG)
) {
actuaContentTextStyle = LocalTextStyle.current
@@ -508,12 +447,8 @@
TitleCard(
onClick = {},
- time = {
- actualTimeTextStyle = LocalTextStyle.current
- },
- title = {
- actualTitleTextStyle = LocalTextStyle.current
- },
+ time = { actualTimeTextStyle = LocalTextStyle.current },
+ title = { actualTitleTextStyle = LocalTextStyle.current },
modifier = Modifier.testTag(TEST_TAG)
) {
actuaContentTextStyle = LocalTextStyle.current
@@ -526,9 +461,7 @@
}
private fun ComposeContentTestRule.verifyHeight(expected: Dp, content: @Composable () -> Unit) {
- setContentWithThemeForSizeAssertions {
- content()
- }.assertHeightIsEqualTo(expected, Dp(1.0f))
+ setContentWithThemeForSizeAssertions { content() }.assertHeightIsEqualTo(expected, Dp(1.0f))
}
private enum class CardStatus {
diff --git a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/ChipScreenshotTest.kt b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/ChipScreenshotTest.kt
index 602b1754..84df7f0 100644
--- a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/ChipScreenshotTest.kt
+++ b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/ChipScreenshotTest.kt
@@ -51,90 +51,86 @@
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
class ChipScreenshotTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
- @get:Rule
- val screenshotRule = AndroidXScreenshotTestRule(SCREENSHOT_GOLDEN_PATH)
+ @get:Rule val screenshotRule = AndroidXScreenshotTestRule(SCREENSHOT_GOLDEN_PATH)
- @get:Rule
- val testName = TestName()
+ @get:Rule val testName = TestName()
+
+ @Test fun chip_ltr() = verifyScreenshot(layoutDirection = LayoutDirection.Ltr) { sampleChip() }
+
+ @Test fun chip_rtl() = verifyScreenshot(layoutDirection = LayoutDirection.Rtl) { sampleChip() }
@Test
- fun chip_ltr() = verifyScreenshot(layoutDirection = LayoutDirection.Ltr) {
- sampleChip()
- }
+ fun chip_secondary_ltr() =
+ verifyScreenshot(layoutDirection = LayoutDirection.Ltr) {
+ sampleChip(colors = ChipDefaults.secondaryChipColors())
+ }
@Test
- fun chip_rtl() = verifyScreenshot(layoutDirection = LayoutDirection.Rtl) {
- sampleChip()
- }
+ fun chip_secondary_rtl() =
+ verifyScreenshot(layoutDirection = LayoutDirection.Rtl) {
+ sampleChip(colors = ChipDefaults.secondaryChipColors())
+ }
@Test
- fun chip_secondary_ltr() = verifyScreenshot(layoutDirection = LayoutDirection.Ltr) {
- sampleChip(colors = ChipDefaults.secondaryChipColors())
- }
+ fun chip_multiline_text() =
+ verifyScreenshot(layoutDirection = LayoutDirection.Ltr) {
+ sampleChip(
+ label = "Long label to show truncation which does not fit into 1 line",
+ secondaryLabel =
+ "Long secondary label that will not fit on one single lines and " +
+ "flows onto another line"
+ )
+ }
@Test
- fun chip_secondary_rtl() = verifyScreenshot(layoutDirection = LayoutDirection.Rtl) {
- sampleChip(colors = ChipDefaults.secondaryChipColors())
- }
+ fun chip_outlined_ltr() =
+ verifyScreenshot(layoutDirection = LayoutDirection.Ltr) { sampleOutlinedChip() }
@Test
- fun chip_multiline_text() = verifyScreenshot(layoutDirection = LayoutDirection.Ltr) {
+ fun chip_outlined_rtl() =
+ verifyScreenshot(layoutDirection = LayoutDirection.Rtl) { sampleOutlinedChip() }
+
+ @Test
+ fun chip_disabled() =
+ verifyScreenshot(layoutDirection = LayoutDirection.Ltr) { sampleChip(enabled = false) }
+
+ @Test
+ fun chip_gradient_ltr() =
+ verifyScreenshot(layoutDirection = LayoutDirection.Ltr) {
+ sampleChip(colors = ChipDefaults.gradientBackgroundChipColors())
+ }
+
+ @Test
+ fun chip_gradient_rtl() =
+ verifyScreenshot(layoutDirection = LayoutDirection.Rtl) {
+ sampleChip(colors = ChipDefaults.gradientBackgroundChipColors())
+ }
+
+ @Test
+ fun chip_image_background() = verifyScreenshot {
sampleChip(
- label = "Long label to show truncation which does not fit into 1 line",
- secondaryLabel =
- "Long secondary label that will not fit on one single lines and " +
- "flows onto another line"
+ colors =
+ ChipDefaults.imageBackgroundChipColors(
+ backgroundImagePainter = painterResource(id = R.drawable.backgroundimage1)
+ )
)
}
@Test
- fun chip_outlined_ltr() = verifyScreenshot(layoutDirection = LayoutDirection.Ltr) {
- sampleOutlinedChip()
- }
+ fun compact_chip_ltr() =
+ verifyScreenshot(layoutDirection = LayoutDirection.Ltr) { sampleCompactChip() }
@Test
- fun chip_outlined_rtl() = verifyScreenshot(layoutDirection = LayoutDirection.Rtl) {
- sampleOutlinedChip()
- }
+ fun compact_chip_rtl() =
+ verifyScreenshot(layoutDirection = LayoutDirection.Rtl) { sampleCompactChip() }
@Test
- fun chip_disabled() = verifyScreenshot(layoutDirection = LayoutDirection.Ltr) {
- sampleChip(enabled = false)
- }
-
- @Test
- fun chip_gradient_ltr() = verifyScreenshot(layoutDirection = LayoutDirection.Ltr) {
- sampleChip(colors = ChipDefaults.gradientBackgroundChipColors())
- }
-
- @Test
- fun chip_gradient_rtl() = verifyScreenshot(layoutDirection = LayoutDirection.Rtl) {
- sampleChip(colors = ChipDefaults.gradientBackgroundChipColors())
- }
-
- @Test
- fun chip_image_background() = verifyScreenshot {
- sampleChip(colors = ChipDefaults.imageBackgroundChipColors(
- backgroundImagePainter = painterResource(id = R.drawable.backgroundimage1)))
- }
-
- @Test
- fun compact_chip_ltr() = verifyScreenshot(layoutDirection = LayoutDirection.Ltr) {
- sampleCompactChip()
- }
-
- @Test
- fun compact_chip_rtl() = verifyScreenshot(layoutDirection = LayoutDirection.Rtl) {
- sampleCompactChip()
- }
-
- @Test
- fun compact_chip_disabled() = verifyScreenshot(layoutDirection = LayoutDirection.Ltr) {
- sampleCompactChip(enabled = false)
- }
+ fun compact_chip_disabled() =
+ verifyScreenshot(layoutDirection = LayoutDirection.Ltr) {
+ sampleCompactChip(enabled = false)
+ }
@Composable
private fun sampleChip(
@@ -186,12 +182,11 @@
content: @Composable () -> Unit
) {
rule.setContentWithTheme {
- CompositionLocalProvider(LocalLayoutDirection provides layoutDirection) {
- content()
- }
+ CompositionLocalProvider(LocalLayoutDirection provides layoutDirection) { content() }
}
- rule.onNodeWithTag(TEST_TAG)
+ rule
+ .onNodeWithTag(TEST_TAG)
.captureToImage()
.assertAgainstGolden(screenshotRule, testName.methodName)
}
diff --git a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/ChipTest.kt b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/ChipTest.kt
index 55072d4..4caee50 100644
--- a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/ChipTest.kt
+++ b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/ChipTest.kt
@@ -66,1227 +66,1159 @@
import org.junit.Test
class ChipBehaviourTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
- @Test
- fun supports_testtag() {
- rule.setContentWithTheme {
- Chip(
- onClick = {},
- colors = ChipDefaults.primaryChipColors(),
- modifier = Modifier.testTag(TEST_TAG),
- border = ChipDefaults.chipBorder()
- ) {
- TestImage()
- }
+ @Test
+ fun supports_testtag() {
+ rule.setContentWithTheme {
+ Chip(
+ onClick = {},
+ colors = ChipDefaults.primaryChipColors(),
+ modifier = Modifier.testTag(TEST_TAG),
+ border = ChipDefaults.chipBorder()
+ ) {
+ TestImage()
+ }
+ }
+
+ rule.onNodeWithTag(TEST_TAG).assertExists()
}
- rule.onNodeWithTag(TEST_TAG).assertExists()
- }
+ @Test
+ fun has_clickaction_when_enabled() {
+ rule.setContentWithTheme {
+ Chip(
+ onClick = {},
+ colors = ChipDefaults.primaryChipColors(),
+ enabled = true,
+ modifier = Modifier.testTag(TEST_TAG),
+ border = ChipDefaults.chipBorder()
+ ) {
+ TestImage()
+ }
+ }
- @Test
- fun has_clickaction_when_enabled() {
- rule.setContentWithTheme {
- Chip(
- onClick = {},
- colors = ChipDefaults.primaryChipColors(),
- enabled = true,
- modifier = Modifier.testTag(TEST_TAG),
- border = ChipDefaults.chipBorder()
- ) {
- TestImage()
- }
+ rule.onNodeWithTag(TEST_TAG).assertHasClickAction()
}
- rule.onNodeWithTag(TEST_TAG).assertHasClickAction()
- }
+ @Test
+ fun has_clickaction_when_disabled() {
+ rule.setContentWithTheme {
+ Chip(
+ onClick = {},
+ colors = ChipDefaults.primaryChipColors(),
+ enabled = false,
+ modifier = Modifier.testTag(TEST_TAG),
+ border = ChipDefaults.chipBorder()
+ ) {
+ TestImage()
+ }
+ }
- @Test
- fun has_clickaction_when_disabled() {
- rule.setContentWithTheme {
- Chip(
- onClick = {},
- colors = ChipDefaults.primaryChipColors(),
- enabled = false,
- modifier = Modifier.testTag(TEST_TAG),
- border = ChipDefaults.chipBorder()
- ) {
- TestImage()
- }
+ rule.onNodeWithTag(TEST_TAG).assertHasClickAction()
}
- rule.onNodeWithTag(TEST_TAG).assertHasClickAction()
- }
+ @Test
+ fun is_correctly_enabled_when_enabled_equals_true() {
+ rule.setContentWithTheme {
+ Chip(
+ onClick = {},
+ colors = ChipDefaults.primaryChipColors(),
+ enabled = true,
+ modifier = Modifier.testTag(TEST_TAG),
+ border = ChipDefaults.chipBorder()
+ ) {
+ TestImage()
+ }
+ }
- @Test
- fun is_correctly_enabled_when_enabled_equals_true() {
- rule.setContentWithTheme {
- Chip(
- onClick = {},
- colors = ChipDefaults.primaryChipColors(),
- enabled = true,
- modifier = Modifier.testTag(TEST_TAG),
- border = ChipDefaults.chipBorder()
- ) {
- TestImage()
- }
+ rule.onNodeWithTag(TEST_TAG).assertIsEnabled()
}
- rule.onNodeWithTag(TEST_TAG).assertIsEnabled()
- }
+ @Test
+ fun is_correctly_disabled_when_enabled_equals_false() {
+ rule.setContentWithTheme {
+ Chip(
+ onClick = {},
+ colors = ChipDefaults.primaryChipColors(),
+ enabled = false,
+ modifier = Modifier.testTag(TEST_TAG),
+ border = ChipDefaults.chipBorder()
+ ) {
+ TestImage()
+ }
+ }
- @Test
- fun is_correctly_disabled_when_enabled_equals_false() {
- rule.setContentWithTheme {
- Chip(
- onClick = {},
- colors = ChipDefaults.primaryChipColors(),
- enabled = false,
- modifier = Modifier.testTag(TEST_TAG),
- border = ChipDefaults.chipBorder()
- ) {
- TestImage()
- }
+ rule.onNodeWithTag(TEST_TAG).assertIsNotEnabled()
}
- rule.onNodeWithTag(TEST_TAG).assertIsNotEnabled()
- }
+ @Test
+ fun responds_to_click_when_enabled() {
+ var clicked = false
- @Test
- fun responds_to_click_when_enabled() {
- var clicked = false
+ rule.setContentWithTheme {
+ Chip(
+ onClick = { clicked = true },
+ colors = ChipDefaults.primaryChipColors(),
+ enabled = true,
+ modifier = Modifier.testTag(TEST_TAG),
+ border = ChipDefaults.chipBorder()
+ ) {
+ TestImage()
+ }
+ }
- rule.setContentWithTheme {
- Chip(
- onClick = { clicked = true },
- colors = ChipDefaults.primaryChipColors(),
- enabled = true,
- modifier = Modifier.testTag(TEST_TAG),
- border = ChipDefaults.chipBorder()
- ) {
- TestImage()
- }
+ rule.onNodeWithTag(TEST_TAG).performClick()
+
+ rule.runOnIdle { assertEquals(true, clicked) }
}
- rule.onNodeWithTag(TEST_TAG).performClick()
+ @Test
+ fun does_not_respond_to_click_when_disabled() {
+ var clicked = false
- rule.runOnIdle {
- assertEquals(true, clicked)
- }
- }
+ rule.setContentWithTheme {
+ Chip(
+ onClick = { clicked = true },
+ colors = ChipDefaults.primaryChipColors(),
+ enabled = false,
+ modifier = Modifier.testTag(TEST_TAG),
+ border = ChipDefaults.chipBorder()
+ ) {
+ TestImage()
+ }
+ }
- @Test
- fun does_not_respond_to_click_when_disabled() {
- var clicked = false
+ rule.onNodeWithTag(TEST_TAG).performClick()
- rule.setContentWithTheme {
- Chip(
- onClick = { clicked = true },
- colors = ChipDefaults.primaryChipColors(),
- enabled = false,
- modifier = Modifier.testTag(TEST_TAG),
- border = ChipDefaults.chipBorder()
- ) {
- TestImage()
- }
+ rule.runOnIdle { assertEquals(false, clicked) }
}
- rule.onNodeWithTag(TEST_TAG).performClick()
+ @Test
+ fun has_role_button() {
+ rule.setContentWithTheme {
+ Chip(
+ onClick = {},
+ colors = ChipDefaults.primaryChipColors(),
+ enabled = false,
+ modifier = Modifier.testTag(TEST_TAG),
+ border = ChipDefaults.chipBorder()
+ ) {
+ TestImage()
+ }
+ }
- rule.runOnIdle {
- assertEquals(false, clicked)
- }
- }
-
- @Test
- fun has_role_button() {
- rule.setContentWithTheme {
- Chip(
- onClick = {},
- colors = ChipDefaults.primaryChipColors(),
- enabled = false,
- modifier = Modifier.testTag(TEST_TAG),
- border = ChipDefaults.chipBorder()
- ) {
- TestImage()
- }
+ rule
+ .onNodeWithTag(TEST_TAG)
+ .assert(SemanticsMatcher.expectValue(SemanticsProperties.Role, Role.Button))
}
- rule.onNodeWithTag(TEST_TAG)
- .assert(
- SemanticsMatcher.expectValue(
- SemanticsProperties.Role,
- Role.Button
- )
- )
- }
+ @Test
+ fun has_role_button_for_three_slot_chip() {
+ rule.setContentWithTheme {
+ Chip(
+ onClick = {},
+ label = {},
+ secondaryLabel = {},
+ icon = { TestImage() },
+ colors = ChipDefaults.primaryChipColors(),
+ enabled = false,
+ modifier = Modifier.testTag(TEST_TAG),
+ )
+ }
- @Test
- fun has_role_button_for_three_slot_chip() {
- rule.setContentWithTheme {
- Chip(
- onClick = {},
- label = {},
- secondaryLabel = {},
- icon = { TestImage() },
- colors = ChipDefaults.primaryChipColors(),
- enabled = false,
- modifier = Modifier.testTag(TEST_TAG),
- )
+ rule
+ .onNodeWithTag(TEST_TAG)
+ .assert(SemanticsMatcher.expectValue(SemanticsProperties.Role, Role.Button))
}
- rule.onNodeWithTag(TEST_TAG)
- .assert(
- SemanticsMatcher.expectValue(
- SemanticsProperties.Role,
- Role.Button
- )
- )
- }
+ @Test
+ fun has_role_button_for_compact_chip() {
+ rule.setContentWithTheme {
+ CompactChip(
+ onClick = {},
+ label = {},
+ icon = { TestImage() },
+ colors = ChipDefaults.primaryChipColors(),
+ enabled = false,
+ modifier = Modifier.testTag(TEST_TAG),
+ )
+ }
- @Test
- fun has_role_button_for_compact_chip() {
- rule.setContentWithTheme {
- CompactChip(
- onClick = {},
- label = {},
- icon = { TestImage() },
- colors = ChipDefaults.primaryChipColors(),
- enabled = false,
- modifier = Modifier.testTag(TEST_TAG),
- )
+ rule
+ .onNodeWithTag(TEST_TAG)
+ .assert(SemanticsMatcher.expectValue(SemanticsProperties.Role, Role.Button))
}
- rule.onNodeWithTag(TEST_TAG)
- .assert(
- SemanticsMatcher.expectValue(
- SemanticsProperties.Role,
- Role.Button
- )
- )
- }
+ @Test
+ fun is_stadium_shape_under_ltr() =
+ rule.isStadiumShape(LayoutDirection.Ltr) {
+ Chip(
+ modifier = Modifier.testTag(TEST_TAG),
+ border = ChipDefaults.chipBorder(),
+ onClick = {},
+ colors = ChipDefaults.primaryChipColors(),
+ ) { /* omit content to allow us to validate the shape by pixel checking */
+ }
+ }
- @Test
- fun is_stadium_shape_under_ltr() =
- rule.isStadiumShape(LayoutDirection.Ltr) {
- Chip(
- modifier = Modifier.testTag(TEST_TAG),
- border = ChipDefaults.chipBorder(),
- onClick = {},
- colors = ChipDefaults.primaryChipColors(),
- ) { /* omit content to allow us to validate the shape by pixel checking */ }
- }
-
- @Test
- fun is_stadium_shape_under_rtl() =
- rule.isStadiumShape(LayoutDirection.Rtl) {
- Chip(
- modifier = Modifier.testTag(TEST_TAG),
- border = ChipDefaults.chipBorder(),
- onClick = {},
- colors = ChipDefaults.primaryChipColors(),
- ) { /* omit content to allow us to validate the shape by pixel checking */ }
- }
+ @Test
+ fun is_stadium_shape_under_rtl() =
+ rule.isStadiumShape(LayoutDirection.Rtl) {
+ Chip(
+ modifier = Modifier.testTag(TEST_TAG),
+ border = ChipDefaults.chipBorder(),
+ onClick = {},
+ colors = ChipDefaults.primaryChipColors(),
+ ) { /* omit content to allow us to validate the shape by pixel checking */
+ }
+ }
}
class ChipSizeTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
- @Test
- fun gives_base_chip_correct_height() =
- verifyHeight(ChipDefaults.Height)
+ @Test fun gives_base_chip_correct_height() = verifyHeight(ChipDefaults.Height)
- @Test
- fun chip_has_adjustable_height() {
- val expectedMinHeight = ChipDefaults.Height + 1.dp
- rule.setContentWithThemeForSizeAssertions {
- Chip(
- onClick = {},
- colors = ChipDefaults.primaryChipColors(),
- border = ChipDefaults.chipBorder()
- ) {
- Text(
- text = "Chip text spanning over multiple lines of text " +
- "to test height is adjustable. This should exceed the minimum height for the chip."
- )
- }
- }.assertHeightIsAtLeast(expectedMinHeight)
- }
-
- @Test
- fun has_icon_in_correct_location_when_only_single_line_of_text() {
- val iconTag = "TestIcon"
- val chipTag = "chip"
- rule
- .setContentWithThemeForSizeAssertions(useUnmergedTree = true) {
- Chip(
- onClick = {},
- label = { Text("Blue green orange") },
- icon = { TestImage(iconTag) },
- modifier = Modifier.testTag(chipTag)
- )
- }
- val itemBounds = rule.onNodeWithTag(chipTag).getUnclippedBoundsInRoot()
- val iconBounds = rule.onNodeWithTag(iconTag, useUnmergedTree = true)
- .getUnclippedBoundsInRoot()
-
- rule.onNodeWithContentDescription(iconTag, useUnmergedTree = true)
- .assertTopPositionInRootIsEqualTo((itemBounds.height - iconBounds.height) / 2)
- }
-
- @Test
- fun icon_only_compact_chip_has_correct_default_width_and_height() {
- val iconTag = "TestIcon"
- val chipTag = "chip"
- rule
- .setContentWithThemeForSizeAssertions(useUnmergedTree = true) {
- CompactChip(
- onClick = {},
- modifier = Modifier.testTag(chipTag),
- icon = { TestImage(iconTag) }
- )
- }
-
- rule.onRoot().assertWidthIsEqualTo(ChipDefaults.IconOnlyCompactChipWidth)
- .assertHeightIsEqualTo(ChipDefaults.CompactChipHeight)
- }
-
- @Test
- fun label_only_compact_chip_has_correct_default_height() {
- val chipTag = "chip"
- rule
- .setContentWithThemeForSizeAssertions(useUnmergedTree = true) {
- CompactChip(
- onClick = {},
- modifier = Modifier.testTag(chipTag),
- label = { Text("Test") }
- )
- }
-
- rule.onRoot().assertHeightIsEqualTo(48.dp)
- }
-
- @Test
- fun no_content_compact_chip_has_correct_default_width_and_height() {
- val chipTag = "chip"
- rule
- .setContentWithThemeForSizeAssertions(useUnmergedTree = true) {
- CompactChip(
- onClick = {},
- modifier = Modifier.testTag(chipTag),
- )
- }
-
- rule.onRoot().assertWidthIsEqualTo(ChipDefaults.IconOnlyCompactChipWidth)
- .assertHeightIsEqualTo(ChipDefaults.CompactChipHeight)
- }
-
- @Test
- fun icon_only_compact_chip_can_have_width_overridden() {
- val iconTag = "TestIcon"
- val chipTag = "chip"
- rule
- .setContentWithThemeForSizeAssertions(useUnmergedTree = true) {
- CompactChip(
- onClick = {},
- modifier = Modifier
- .testTag(chipTag)
- .width(100.dp),
- icon = { TestImage(iconTag) }
- )
- }
-
- rule.onRoot().assertWidthIsEqualTo(100.dp)
- }
-
- @Test
- fun has_icon_in_correct_location_when_compact_chip() {
- val iconTag = "TestIcon"
- val chipTag = "chip"
- rule
- .setContentWithThemeForSizeAssertions(useUnmergedTree = true) {
- CompactChip(
- onClick = {},
- label = { Text("Blue green orange") },
- icon = { TestImage(iconTag) },
- modifier = Modifier.testTag(chipTag)
- )
- }
- val itemBounds = rule.onNodeWithTag(chipTag).getUnclippedBoundsInRoot()
- val iconBounds = rule.onNodeWithTag(iconTag, useUnmergedTree = true)
- .getUnclippedBoundsInRoot()
-
- rule.onNodeWithContentDescription(iconTag, useUnmergedTree = true)
- .assertTopPositionInRootIsEqualTo(
- (itemBounds.height - iconBounds.height) / 2 +
- ChipDefaults.CompactChipTapTargetPadding.calculateTopPadding()
- )
- }
-
- @Test
- fun has_icon_in_correct_location_when_icon_only_chip() {
- val iconTag = "TestIcon"
- val chipTag = "chip"
- rule
- .setContentWithThemeForSizeAssertions(useUnmergedTree = true) {
- CompactChip(
- onClick = {},
- modifier = Modifier.testTag(chipTag),
- icon = { TestImage(iconTag) }
- )
- }
- val itemBounds = rule.onNodeWithTag(chipTag).getUnclippedBoundsInRoot()
- val iconBounds = rule.onNodeWithTag(iconTag, useUnmergedTree = true)
- .getUnclippedBoundsInRoot()
-
- rule.onNodeWithContentDescription(iconTag, useUnmergedTree = true)
- .assertTopPositionInRootIsEqualTo(
- (itemBounds.height - iconBounds.height) / 2 +
- ChipDefaults.CompactChipTapTargetPadding.calculateTopPadding()
- )
- }
-
- private fun verifyHeight(expectedHeight: Dp) {
- rule.verifyHeight(expectedHeight) {
- Chip(
- onClick = {},
- colors = ChipDefaults.primaryChipColors(),
- border = ChipDefaults.chipBorder()
- ) {
- TestImage()
- }
+ @Test
+ fun chip_has_adjustable_height() {
+ val expectedMinHeight = ChipDefaults.Height + 1.dp
+ rule
+ .setContentWithThemeForSizeAssertions {
+ Chip(
+ onClick = {},
+ colors = ChipDefaults.primaryChipColors(),
+ border = ChipDefaults.chipBorder()
+ ) {
+ Text(
+ text =
+ "Chip text spanning over multiple lines of text " +
+ "to test height is adjustable. This should exceed the minimum height for the chip."
+ )
+ }
+ }
+ .assertHeightIsAtLeast(expectedMinHeight)
}
- }
+
+ @Test
+ fun has_icon_in_correct_location_when_only_single_line_of_text() {
+ val iconTag = "TestIcon"
+ val chipTag = "chip"
+ rule.setContentWithThemeForSizeAssertions(useUnmergedTree = true) {
+ Chip(
+ onClick = {},
+ label = { Text("Blue green orange") },
+ icon = { TestImage(iconTag) },
+ modifier = Modifier.testTag(chipTag)
+ )
+ }
+ val itemBounds = rule.onNodeWithTag(chipTag).getUnclippedBoundsInRoot()
+ val iconBounds =
+ rule.onNodeWithTag(iconTag, useUnmergedTree = true).getUnclippedBoundsInRoot()
+
+ rule
+ .onNodeWithContentDescription(iconTag, useUnmergedTree = true)
+ .assertTopPositionInRootIsEqualTo((itemBounds.height - iconBounds.height) / 2)
+ }
+
+ @Test
+ fun icon_only_compact_chip_has_correct_default_width_and_height() {
+ val iconTag = "TestIcon"
+ val chipTag = "chip"
+ rule.setContentWithThemeForSizeAssertions(useUnmergedTree = true) {
+ CompactChip(
+ onClick = {},
+ modifier = Modifier.testTag(chipTag),
+ icon = { TestImage(iconTag) }
+ )
+ }
+
+ rule
+ .onRoot()
+ .assertWidthIsEqualTo(ChipDefaults.IconOnlyCompactChipWidth)
+ .assertHeightIsEqualTo(ChipDefaults.CompactChipHeight)
+ }
+
+ @Test
+ fun label_only_compact_chip_has_correct_default_height() {
+ val chipTag = "chip"
+ rule.setContentWithThemeForSizeAssertions(useUnmergedTree = true) {
+ CompactChip(
+ onClick = {},
+ modifier = Modifier.testTag(chipTag),
+ label = { Text("Test") }
+ )
+ }
+
+ rule.onRoot().assertHeightIsEqualTo(48.dp)
+ }
+
+ @Test
+ fun no_content_compact_chip_has_correct_default_width_and_height() {
+ val chipTag = "chip"
+ rule.setContentWithThemeForSizeAssertions(useUnmergedTree = true) {
+ CompactChip(
+ onClick = {},
+ modifier = Modifier.testTag(chipTag),
+ )
+ }
+
+ rule
+ .onRoot()
+ .assertWidthIsEqualTo(ChipDefaults.IconOnlyCompactChipWidth)
+ .assertHeightIsEqualTo(ChipDefaults.CompactChipHeight)
+ }
+
+ @Test
+ fun icon_only_compact_chip_can_have_width_overridden() {
+ val iconTag = "TestIcon"
+ val chipTag = "chip"
+ rule.setContentWithThemeForSizeAssertions(useUnmergedTree = true) {
+ CompactChip(
+ onClick = {},
+ modifier = Modifier.testTag(chipTag).width(100.dp),
+ icon = { TestImage(iconTag) }
+ )
+ }
+
+ rule.onRoot().assertWidthIsEqualTo(100.dp)
+ }
+
+ @Test
+ fun has_icon_in_correct_location_when_compact_chip() {
+ val iconTag = "TestIcon"
+ val chipTag = "chip"
+ rule.setContentWithThemeForSizeAssertions(useUnmergedTree = true) {
+ CompactChip(
+ onClick = {},
+ label = { Text("Blue green orange") },
+ icon = { TestImage(iconTag) },
+ modifier = Modifier.testTag(chipTag)
+ )
+ }
+ val itemBounds = rule.onNodeWithTag(chipTag).getUnclippedBoundsInRoot()
+ val iconBounds =
+ rule.onNodeWithTag(iconTag, useUnmergedTree = true).getUnclippedBoundsInRoot()
+
+ rule
+ .onNodeWithContentDescription(iconTag, useUnmergedTree = true)
+ .assertTopPositionInRootIsEqualTo(
+ (itemBounds.height - iconBounds.height) / 2 +
+ ChipDefaults.CompactChipTapTargetPadding.calculateTopPadding()
+ )
+ }
+
+ @Test
+ fun has_icon_in_correct_location_when_icon_only_chip() {
+ val iconTag = "TestIcon"
+ val chipTag = "chip"
+ rule.setContentWithThemeForSizeAssertions(useUnmergedTree = true) {
+ CompactChip(
+ onClick = {},
+ modifier = Modifier.testTag(chipTag),
+ icon = { TestImage(iconTag) }
+ )
+ }
+ val itemBounds = rule.onNodeWithTag(chipTag).getUnclippedBoundsInRoot()
+ val iconBounds =
+ rule.onNodeWithTag(iconTag, useUnmergedTree = true).getUnclippedBoundsInRoot()
+
+ rule
+ .onNodeWithContentDescription(iconTag, useUnmergedTree = true)
+ .assertTopPositionInRootIsEqualTo(
+ (itemBounds.height - iconBounds.height) / 2 +
+ ChipDefaults.CompactChipTapTargetPadding.calculateTopPadding()
+ )
+ }
+
+ private fun verifyHeight(expectedHeight: Dp) {
+ rule.verifyHeight(expectedHeight) {
+ Chip(
+ onClick = {},
+ colors = ChipDefaults.primaryChipColors(),
+ border = ChipDefaults.chipBorder()
+ ) {
+ TestImage()
+ }
+ }
+ }
}
@Suppress("DEPRECATION")
class ChipColorTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
- @Test
- fun gives_primary_enabled_colors() =
- verifyColors(
- TestChipColors.Primary,
- ChipStatus.Enabled,
- { MaterialTheme.colors.primary },
- { MaterialTheme.colors.onPrimary },
- )
-
- @Test
- fun gives_primary_gradient_enabled_colors() =
- verifyContentColors(
- TestChipColors.PrimaryGradient,
- ChipStatus.Enabled,
- ) { MaterialTheme.colors.onSurface }
-
- @Test
- fun three_slot_layout_gives_primary_enabled_colors() =
- verifySlotColors(
- TestChipColors.Primary,
- ChipStatus.Enabled,
- { MaterialTheme.colors.primary },
- { MaterialTheme.colors.onPrimary },
- { MaterialTheme.colors.onPrimary },
- { MaterialTheme.colors.onPrimary }
- )
-
- @Test
- fun compact_chip_gives_primary_enabled_colors() =
- verifySlotColors(
- TestChipColors.Primary,
- ChipStatus.Enabled,
- { MaterialTheme.colors.primary },
- { MaterialTheme.colors.onPrimary },
- { MaterialTheme.colors.onPrimary },
- { MaterialTheme.colors.onPrimary },
- compactChip = true,
- )
-
- @Test
- fun three_slot_layout_gives_image_background_enabled_colors() =
- verifySlotContentColors(
- TestChipColors.ImageBackground,
- ChipStatus.Enabled,
- { MaterialTheme.colors.onBackground },
- { MaterialTheme.colors.onBackground },
- { MaterialTheme.colors.onBackground }
- )
-
- @Test
- fun gives_disabled_primary_chip_contrasting_content_color() =
- verifyColors(
- TestChipColors.Primary,
- ChipStatus.Disabled,
- { MaterialTheme.colors.primary },
- { MaterialTheme.colors.background },
- applyAlphaForDisabledContent = false,
- )
-
- @Test
- fun gives_disabled_primary_compact_chip_contrasting_content_color() =
- verifySlotColors(
- TestChipColors.Primary,
- ChipStatus.Disabled,
- { MaterialTheme.colors.primary },
- { MaterialTheme.colors.background },
- { MaterialTheme.colors.background },
- { MaterialTheme.colors.background },
- applyAlphaForDisabledContent = false,
- compactChip = true,
- )
-
- @Test
- fun three_slot_layout_gives_disabled_primary_contrasting_content_color() =
- verifySlotColors(
- TestChipColors.Primary,
- ChipStatus.Disabled,
- { MaterialTheme.colors.primary },
- { MaterialTheme.colors.background },
- { MaterialTheme.colors.background },
- { MaterialTheme.colors.background },
- applyAlphaForDisabledContent = false,
- )
-
- @Test
- fun three_slot_layout_gives_image_background_disabled_colors() =
- verifySlotContentColors(
- TestChipColors.ImageBackground,
- ChipStatus.Disabled,
- { MaterialTheme.colors.onBackground },
- { MaterialTheme.colors.onBackground },
- { MaterialTheme.colors.onBackground }
- )
-
- @Test
- fun gives_secondary_enabled_colors() =
- verifyColors(
- TestChipColors.Secondary,
- ChipStatus.Enabled,
- { MaterialTheme.colors.surface },
- { MaterialTheme.colors.onSurface }
- )
-
- @Test
- fun gives_child_enabled_colors() =
- verifyColors(
- TestChipColors.Child,
- ChipStatus.Enabled,
- { Color.Transparent },
- { MaterialTheme.colors.onSurface }
- )
-
- @Test
- fun gives_outlined_enabled_colors() =
- verifyColors(
- TestChipColors.Outlined,
- ChipStatus.Enabled,
- { Color.Transparent },
- { MaterialTheme.colors.primary }
- )
-
- @Test
- fun gives_image_background_enabled_colors() =
- verifyContentColors(
- TestChipColors.ImageBackground,
- ChipStatus.Enabled,
- ) { MaterialTheme.colors.onBackground }
-
- @Test
- fun three_slot_layout_gives_secondary_enabled_colors() =
- verifySlotColors(
- TestChipColors.Secondary,
- ChipStatus.Enabled,
- { MaterialTheme.colors.surface },
- { MaterialTheme.colors.onSurface },
- { MaterialTheme.colors.onSurface },
- { MaterialTheme.colors.onSurface }
- )
-
- @Test
- fun gives_secondary_disabled_colors() =
- verifyColors(
- TestChipColors.Secondary,
- ChipStatus.Disabled,
- { MaterialTheme.colors.surface },
- { MaterialTheme.colors.onSurface }
- )
-
- @Test
- fun gives_child_disabled_colors() =
- verifyColors(
- TestChipColors.Child,
- ChipStatus.Disabled,
- { Color.Transparent },
- { MaterialTheme.colors.onSurface },
- { Color.Transparent }
- )
-
- @Test
- fun gives_outlined_disabled_colors() =
- verifyColors(
- TestChipColors.Outlined,
- ChipStatus.Disabled,
- { Color.Transparent },
- { MaterialTheme.colors.primary },
- { Color.Transparent }
- )
-
- @Test
- fun gives_image_background_disabled_colors() =
- verifyContentColors(
- TestChipColors.ImageBackground,
- ChipStatus.Disabled,
- ) { MaterialTheme.colors.onSurface }
-
- @Test
- fun three_slot_layout_gives_secondary_disabled_colors() =
- verifySlotColors(
- TestChipColors.Secondary,
- ChipStatus.Enabled,
- { MaterialTheme.colors.surface },
- { MaterialTheme.colors.onSurface },
- { MaterialTheme.colors.onSurface },
- { MaterialTheme.colors.onSurface }
- )
-
- @Test
- fun compact_chip_gives_secondary_disabled_colors() =
- verifySlotColors(
- TestChipColors.Secondary,
- ChipStatus.Enabled,
- { MaterialTheme.colors.surface },
- { MaterialTheme.colors.onSurface },
- { MaterialTheme.colors.onSurface },
- { MaterialTheme.colors.onSurface },
- compactChip = true
- )
-
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
- @Test
- fun allows_custom_primary_enabled_background_color_override() {
- val overrideColor = Color.Yellow
- rule.setContentWithTheme {
- Box(modifier = Modifier.fillMaxSize()) {
- Chip(
- onClick = {},
- content = {},
- colors = ChipDefaults.primaryChipColors(backgroundColor = overrideColor),
- enabled = true,
- modifier = Modifier.testTag(TEST_TAG),
- border = ChipDefaults.chipBorder()
+ @Test
+ fun gives_primary_enabled_colors() =
+ verifyColors(
+ TestChipColors.Primary,
+ ChipStatus.Enabled,
+ { MaterialTheme.colors.primary },
+ { MaterialTheme.colors.onPrimary },
)
- }
- }
- rule.onNodeWithTag(TEST_TAG)
- .captureToImage()
- .assertContainsColor(overrideColor, 50.0f)
- }
+ @Test
+ fun gives_primary_gradient_enabled_colors() =
+ verifyContentColors(
+ TestChipColors.PrimaryGradient,
+ ChipStatus.Enabled,
+ ) {
+ MaterialTheme.colors.onSurface
+ }
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
- @Test
- fun allows_custom_primary_disabled_background_color_override() {
- val overrideColor = Color.Yellow
- rule.setContentWithTheme {
- Box(modifier = Modifier.fillMaxSize()) {
- Chip(
- onClick = {},
- content = {},
- colors = ChipDefaults.chipColors(disabledBackgroundColor = overrideColor),
- enabled = false,
- modifier = Modifier.testTag(TEST_TAG),
- border = ChipDefaults.chipBorder()
+ @Test
+ fun three_slot_layout_gives_primary_enabled_colors() =
+ verifySlotColors(
+ TestChipColors.Primary,
+ ChipStatus.Enabled,
+ { MaterialTheme.colors.primary },
+ { MaterialTheme.colors.onPrimary },
+ { MaterialTheme.colors.onPrimary },
+ { MaterialTheme.colors.onPrimary }
)
- }
- }
- rule.onNodeWithTag(TEST_TAG)
- .captureToImage()
- .assertContainsColor(overrideColor, 50.0f)
- }
-
- @Test
- fun allows_custom_primary_enabled_content_color_override() {
- val overrideColor = Color.Red
- var actualContentColor = Color.Transparent
- rule.setContentWithTheme {
- Chip(
- onClick = {},
- colors = ChipDefaults.primaryChipColors(
- contentColor = overrideColor
- ),
- content = {
- actualContentColor = LocalContentColor.current
- },
- enabled = true,
- modifier = Modifier.testTag(TEST_TAG),
- border = ChipDefaults.chipBorder()
- )
- }
-
- assertEquals(overrideColor, actualContentColor)
- }
-
- @Test
- fun allows_custom_primary_enabled_secondary_label_color_override() {
- val overrideColor = Color.Red
- var actualContentColor = Color.Transparent
- var actualSecondaryContentColor = Color.Transparent
- var expectedContent = Color.Transparent
- rule.setContentWithTheme {
- expectedContent = MaterialTheme.colors.onPrimary
- Chip(
- onClick = {},
- colors = ChipDefaults.chipColors(
- secondaryContentColor = overrideColor
- ),
- label = {
- actualContentColor = LocalContentColor.current
- },
- secondaryLabel = {
- actualSecondaryContentColor = LocalContentColor.current
- },
- enabled = true,
- modifier = Modifier.testTag(TEST_TAG)
- )
- }
- assertEquals(expectedContent, actualContentColor)
- assertEquals(overrideColor, actualSecondaryContentColor)
- }
-
- @Test
- fun allows_custom_primary_enabled_icon_tint_color_override() {
- val overrideColor = Color.Red
- var actualContentColor = Color.Transparent
- var actualIconColor = Color.Transparent
- var expectedContent = Color.Transparent
- rule.setContentWithTheme {
- expectedContent = MaterialTheme.colors.onPrimary
- Chip(
- onClick = {},
- colors = ChipDefaults.chipColors(
- iconColor = overrideColor
- ),
- label = {
- actualContentColor = LocalContentColor.current
- },
- icon = {
- actualIconColor = LocalContentColor.current
- },
- enabled = true,
- modifier = Modifier.testTag(TEST_TAG)
- )
- }
- assertEquals(expectedContent, actualContentColor)
- assertEquals(overrideColor, actualIconColor)
- }
-
- @Test
- fun allows_custom_primary_disabled_content_color_override() {
- val overrideColor = Color.Yellow
- var actualContentColor = Color.Transparent
- rule.setContentWithTheme {
- Chip(
- onClick = {},
- colors = ChipDefaults.chipColors(
- disabledContentColor = overrideColor
- ),
- content = {
- actualContentColor = LocalContentColor.current
- },
- enabled = false,
- modifier = Modifier.testTag(TEST_TAG),
- border = ChipDefaults.chipBorder()
- )
- }
-
- assertEquals(overrideColor, actualContentColor)
- }
-
- private fun verifyContentColors(
- testChipColors: TestChipColors,
- status: ChipStatus,
- contentColor: @Composable () -> Color,
- ) {
- var expectedContent = Color.Transparent
- var actualContent = Color.Transparent
- val testBackground = Color.White
-
- rule.setContentWithTheme {
- expectedContent = if (status.enabled()) {
- contentColor()
- } else {
- contentColor().copy(alpha = ContentAlpha.disabled)
- }
- Box(
- modifier = Modifier
- .fillMaxSize()
- .background(testBackground)
- ) {
- Chip(
- onClick = {},
- colors = testChipColors.chipColors(),
- content = { actualContent = LocalContentColor.current },
- enabled = status.enabled(),
- modifier = Modifier.testTag(TEST_TAG),
- border = ChipDefaults.chipBorder()
+ @Test
+ fun compact_chip_gives_primary_enabled_colors() =
+ verifySlotColors(
+ TestChipColors.Primary,
+ ChipStatus.Enabled,
+ { MaterialTheme.colors.primary },
+ { MaterialTheme.colors.onPrimary },
+ { MaterialTheme.colors.onPrimary },
+ { MaterialTheme.colors.onPrimary },
+ compactChip = true,
)
- }
- }
- assertEquals(expectedContent, actualContent)
- }
+ @Test
+ fun three_slot_layout_gives_image_background_enabled_colors() =
+ verifySlotContentColors(
+ TestChipColors.ImageBackground,
+ ChipStatus.Enabled,
+ { MaterialTheme.colors.onBackground },
+ { MaterialTheme.colors.onBackground },
+ { MaterialTheme.colors.onBackground }
+ )
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
- private fun verifyColors(
- testChipColors: TestChipColors,
- status: ChipStatus,
- backgroundColor: @Composable () -> Color,
- contentColor: @Composable () -> Color,
- disabledBackgroundColor: (@Composable () -> Color)? = null,
- applyAlphaForDisabledContent: Boolean = true,
- ) {
- var expectedBackground = Color.Transparent
- var expectedContent = Color.Transparent
- var actualContent = Color.Transparent
- val testBackground = Color.White
+ @Test
+ fun gives_disabled_primary_chip_contrasting_content_color() =
+ verifyColors(
+ TestChipColors.Primary,
+ ChipStatus.Disabled,
+ { MaterialTheme.colors.primary },
+ { MaterialTheme.colors.background },
+ applyAlphaForDisabledContent = false,
+ )
- rule.setContentWithTheme {
- if (status.enabled()) {
- expectedBackground = backgroundColor()
- expectedContent = contentColor()
- } else {
- expectedBackground =
- if (disabledBackgroundColor != null) {
- disabledBackgroundColor().compositeOver(testBackground)
- } else {
- backgroundColor().copy(alpha = ContentAlpha.disabled).compositeOver(testBackground)
- }
- expectedContent =
- if (applyAlphaForDisabledContent)
- contentColor().copy(alpha = ContentAlpha.disabled)
- else
- contentColor()
- }
- Box(
- modifier = Modifier
- .fillMaxSize()
- .background(testBackground)
- ) {
- if (testChipColors == TestChipColors.Outlined) {
- OutlinedChip(
- onClick = {},
- colors = testChipColors.chipColors(),
- label = { actualContent = LocalContentColor.current },
- enabled = status.enabled(),
- modifier = Modifier.testTag(TEST_TAG),
- border = ChipDefaults.chipBorder()
- )
- } else {
- Chip(
- onClick = {},
- colors = testChipColors.chipColors(),
- content = { actualContent = LocalContentColor.current },
- enabled = status.enabled(),
- modifier = Modifier.testTag(TEST_TAG),
- border = ChipDefaults.chipBorder()
- )
+ @Test
+ fun gives_disabled_primary_compact_chip_contrasting_content_color() =
+ verifySlotColors(
+ TestChipColors.Primary,
+ ChipStatus.Disabled,
+ { MaterialTheme.colors.primary },
+ { MaterialTheme.colors.background },
+ { MaterialTheme.colors.background },
+ { MaterialTheme.colors.background },
+ applyAlphaForDisabledContent = false,
+ compactChip = true,
+ )
+
+ @Test
+ fun three_slot_layout_gives_disabled_primary_contrasting_content_color() =
+ verifySlotColors(
+ TestChipColors.Primary,
+ ChipStatus.Disabled,
+ { MaterialTheme.colors.primary },
+ { MaterialTheme.colors.background },
+ { MaterialTheme.colors.background },
+ { MaterialTheme.colors.background },
+ applyAlphaForDisabledContent = false,
+ )
+
+ @Test
+ fun three_slot_layout_gives_image_background_disabled_colors() =
+ verifySlotContentColors(
+ TestChipColors.ImageBackground,
+ ChipStatus.Disabled,
+ { MaterialTheme.colors.onBackground },
+ { MaterialTheme.colors.onBackground },
+ { MaterialTheme.colors.onBackground }
+ )
+
+ @Test
+ fun gives_secondary_enabled_colors() =
+ verifyColors(
+ TestChipColors.Secondary,
+ ChipStatus.Enabled,
+ { MaterialTheme.colors.surface },
+ { MaterialTheme.colors.onSurface }
+ )
+
+ @Test
+ fun gives_child_enabled_colors() =
+ verifyColors(
+ TestChipColors.Child,
+ ChipStatus.Enabled,
+ { Color.Transparent },
+ { MaterialTheme.colors.onSurface }
+ )
+
+ @Test
+ fun gives_outlined_enabled_colors() =
+ verifyColors(
+ TestChipColors.Outlined,
+ ChipStatus.Enabled,
+ { Color.Transparent },
+ { MaterialTheme.colors.primary }
+ )
+
+ @Test
+ fun gives_image_background_enabled_colors() =
+ verifyContentColors(
+ TestChipColors.ImageBackground,
+ ChipStatus.Enabled,
+ ) {
+ MaterialTheme.colors.onBackground
}
- }
- }
- assertEquals(expectedContent, actualContent)
+ @Test
+ fun three_slot_layout_gives_secondary_enabled_colors() =
+ verifySlotColors(
+ TestChipColors.Secondary,
+ ChipStatus.Enabled,
+ { MaterialTheme.colors.surface },
+ { MaterialTheme.colors.onSurface },
+ { MaterialTheme.colors.onSurface },
+ { MaterialTheme.colors.onSurface }
+ )
- rule.onNodeWithTag(TEST_TAG)
- .captureToImage()
- .assertContainsColor(
- if (expectedBackground != Color.Transparent) expectedBackground else testBackground,
- 50.0f
- )
- }
+ @Test
+ fun gives_secondary_disabled_colors() =
+ verifyColors(
+ TestChipColors.Secondary,
+ ChipStatus.Disabled,
+ { MaterialTheme.colors.surface },
+ { MaterialTheme.colors.onSurface }
+ )
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
- private fun verifySlotColors(
- testChipColors: TestChipColors,
- status: ChipStatus,
- backgroundColor: @Composable () -> Color,
- contentColor: @Composable () -> Color,
- secondaryContentColor: @Composable () -> Color,
- iconColor: @Composable () -> Color,
- compactChip: Boolean = false,
- applyAlphaForDisabledContent: Boolean = true,
- ) {
- var expectedBackground = Color.Transparent
- var expectedContent = Color.Transparent
- var expectedSecondaryContent = Color.Transparent
- var expectedIcon = Color.Transparent
- var actualContent = Color.Transparent
- var actualSecondaryContent = Color.Transparent
- var actualIcon = Color.Transparent
- val testBackground = Color.White
+ @Test
+ fun gives_child_disabled_colors() =
+ verifyColors(
+ TestChipColors.Child,
+ ChipStatus.Disabled,
+ { Color.Transparent },
+ { MaterialTheme.colors.onSurface },
+ { Color.Transparent }
+ )
- rule.setContentWithTheme {
- if (status.enabled()) {
- expectedBackground = backgroundColor()
- expectedContent = contentColor()
- expectedSecondaryContent = secondaryContentColor()
- expectedIcon = iconColor()
- } else {
- expectedBackground =
- backgroundColor().copy(alpha = ContentAlpha.disabled)
- .compositeOver(testBackground)
- if (applyAlphaForDisabledContent) {
- expectedContent = contentColor().copy(alpha = ContentAlpha.disabled)
- expectedSecondaryContent = secondaryContentColor()
- .copy(alpha = ContentAlpha.disabled)
- expectedIcon = iconColor().copy(alpha = ContentAlpha.disabled)
- } else {
- expectedContent = contentColor()
- expectedSecondaryContent = secondaryContentColor()
- expectedIcon = iconColor()
+ @Test
+ fun gives_outlined_disabled_colors() =
+ verifyColors(
+ TestChipColors.Outlined,
+ ChipStatus.Disabled,
+ { Color.Transparent },
+ { MaterialTheme.colors.primary },
+ { Color.Transparent }
+ )
+
+ @Test
+ fun gives_image_background_disabled_colors() =
+ verifyContentColors(
+ TestChipColors.ImageBackground,
+ ChipStatus.Disabled,
+ ) {
+ MaterialTheme.colors.onSurface
}
- }
- Box(
- modifier = Modifier
- .fillMaxSize()
- .background(testBackground)
- ) {
- if (compactChip) {
- CompactChip(
- onClick = {},
- colors = testChipColors.chipColors(),
- label = { actualContent = LocalContentColor.current },
- icon = { actualIcon = LocalContentColor.current },
- enabled = status.enabled(),
- modifier = Modifier.testTag(TEST_TAG)
- )
- } else {
- Chip(
- onClick = {},
- colors = testChipColors.chipColors(),
- label = { actualContent = LocalContentColor.current },
- secondaryLabel = { actualSecondaryContent = LocalContentColor.current },
- icon = { actualIcon = LocalContentColor.current },
- enabled = status.enabled(),
- modifier = Modifier.testTag(TEST_TAG)
- )
+
+ @Test
+ fun three_slot_layout_gives_secondary_disabled_colors() =
+ verifySlotColors(
+ TestChipColors.Secondary,
+ ChipStatus.Enabled,
+ { MaterialTheme.colors.surface },
+ { MaterialTheme.colors.onSurface },
+ { MaterialTheme.colors.onSurface },
+ { MaterialTheme.colors.onSurface }
+ )
+
+ @Test
+ fun compact_chip_gives_secondary_disabled_colors() =
+ verifySlotColors(
+ TestChipColors.Secondary,
+ ChipStatus.Enabled,
+ { MaterialTheme.colors.surface },
+ { MaterialTheme.colors.onSurface },
+ { MaterialTheme.colors.onSurface },
+ { MaterialTheme.colors.onSurface },
+ compactChip = true
+ )
+
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
+ @Test
+ fun allows_custom_primary_enabled_background_color_override() {
+ val overrideColor = Color.Yellow
+ rule.setContentWithTheme {
+ Box(modifier = Modifier.fillMaxSize()) {
+ Chip(
+ onClick = {},
+ content = {},
+ colors = ChipDefaults.primaryChipColors(backgroundColor = overrideColor),
+ enabled = true,
+ modifier = Modifier.testTag(TEST_TAG),
+ border = ChipDefaults.chipBorder()
+ )
+ }
}
- }
+
+ rule.onNodeWithTag(TEST_TAG).captureToImage().assertContainsColor(overrideColor, 50.0f)
}
- assertEquals(expectedContent, actualContent)
- if (!compactChip) {
- assertEquals(expectedSecondaryContent, actualSecondaryContent)
- }
- assertEquals(expectedIcon, actualIcon)
-
- rule.onNodeWithTag(TEST_TAG)
- .captureToImage()
- .assertContainsColor(
- if (expectedBackground != Color.Transparent) expectedBackground else testBackground,
- 50.0f
- )
- }
-
- private fun verifySlotContentColors(
- testChipColors: TestChipColors,
- status: ChipStatus,
- contentColor: @Composable () -> Color,
- secondaryContentColor: @Composable () -> Color,
- iconColor: @Composable () -> Color,
- compactChip: Boolean = false,
- ) {
- var expectedContent = Color.Transparent
- var expectedSecondaryContent = Color.Transparent
- var expectedIcon = Color.Transparent
- var actualContent = Color.Transparent
- var actualSecondaryContent = Color.Transparent
- var actualIcon = Color.Transparent
- val testBackground = Color.White
-
- rule.setContentWithTheme {
- if (status.enabled()) {
- expectedContent = contentColor()
- expectedSecondaryContent = secondaryContentColor()
- expectedIcon = iconColor()
- } else {
- expectedContent = contentColor().copy(alpha = ContentAlpha.disabled)
- expectedSecondaryContent = secondaryContentColor()
- .copy(alpha = ContentAlpha.disabled)
- expectedIcon = iconColor().copy(alpha = ContentAlpha.disabled)
- }
- Box(
- modifier = Modifier
- .fillMaxSize()
- .background(testBackground)
- ) {
- if (compactChip) {
- CompactChip(
- onClick = {},
- colors = testChipColors.chipColors(),
- label = { actualContent = LocalContentColor.current },
- icon = { actualIcon = LocalContentColor.current },
- enabled = status.enabled(),
- modifier = Modifier.testTag(TEST_TAG)
- )
- } else {
- Chip(
- onClick = {},
- colors = testChipColors.chipColors(),
- label = { actualContent = LocalContentColor.current },
- secondaryLabel = { actualSecondaryContent = LocalContentColor.current },
- icon = { actualIcon = LocalContentColor.current },
- enabled = status.enabled(),
- modifier = Modifier.testTag(TEST_TAG)
- )
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
+ @Test
+ fun allows_custom_primary_disabled_background_color_override() {
+ val overrideColor = Color.Yellow
+ rule.setContentWithTheme {
+ Box(modifier = Modifier.fillMaxSize()) {
+ Chip(
+ onClick = {},
+ content = {},
+ colors = ChipDefaults.chipColors(disabledBackgroundColor = overrideColor),
+ enabled = false,
+ modifier = Modifier.testTag(TEST_TAG),
+ border = ChipDefaults.chipBorder()
+ )
+ }
}
- }
+
+ rule.onNodeWithTag(TEST_TAG).captureToImage().assertContainsColor(overrideColor, 50.0f)
}
- assertEquals(expectedContent, actualContent)
- if (!compactChip) {
- assertEquals(expectedSecondaryContent, actualSecondaryContent)
+ @Test
+ fun allows_custom_primary_enabled_content_color_override() {
+ val overrideColor = Color.Red
+ var actualContentColor = Color.Transparent
+ rule.setContentWithTheme {
+ Chip(
+ onClick = {},
+ colors = ChipDefaults.primaryChipColors(contentColor = overrideColor),
+ content = { actualContentColor = LocalContentColor.current },
+ enabled = true,
+ modifier = Modifier.testTag(TEST_TAG),
+ border = ChipDefaults.chipBorder()
+ )
+ }
+
+ assertEquals(overrideColor, actualContentColor)
}
- assertEquals(expectedIcon, actualIcon)
- }
+
+ @Test
+ fun allows_custom_primary_enabled_secondary_label_color_override() {
+ val overrideColor = Color.Red
+ var actualContentColor = Color.Transparent
+ var actualSecondaryContentColor = Color.Transparent
+ var expectedContent = Color.Transparent
+ rule.setContentWithTheme {
+ expectedContent = MaterialTheme.colors.onPrimary
+ Chip(
+ onClick = {},
+ colors = ChipDefaults.chipColors(secondaryContentColor = overrideColor),
+ label = { actualContentColor = LocalContentColor.current },
+ secondaryLabel = { actualSecondaryContentColor = LocalContentColor.current },
+ enabled = true,
+ modifier = Modifier.testTag(TEST_TAG)
+ )
+ }
+ assertEquals(expectedContent, actualContentColor)
+ assertEquals(overrideColor, actualSecondaryContentColor)
+ }
+
+ @Test
+ fun allows_custom_primary_enabled_icon_tint_color_override() {
+ val overrideColor = Color.Red
+ var actualContentColor = Color.Transparent
+ var actualIconColor = Color.Transparent
+ var expectedContent = Color.Transparent
+ rule.setContentWithTheme {
+ expectedContent = MaterialTheme.colors.onPrimary
+ Chip(
+ onClick = {},
+ colors = ChipDefaults.chipColors(iconColor = overrideColor),
+ label = { actualContentColor = LocalContentColor.current },
+ icon = { actualIconColor = LocalContentColor.current },
+ enabled = true,
+ modifier = Modifier.testTag(TEST_TAG)
+ )
+ }
+ assertEquals(expectedContent, actualContentColor)
+ assertEquals(overrideColor, actualIconColor)
+ }
+
+ @Test
+ fun allows_custom_primary_disabled_content_color_override() {
+ val overrideColor = Color.Yellow
+ var actualContentColor = Color.Transparent
+ rule.setContentWithTheme {
+ Chip(
+ onClick = {},
+ colors = ChipDefaults.chipColors(disabledContentColor = overrideColor),
+ content = { actualContentColor = LocalContentColor.current },
+ enabled = false,
+ modifier = Modifier.testTag(TEST_TAG),
+ border = ChipDefaults.chipBorder()
+ )
+ }
+
+ assertEquals(overrideColor, actualContentColor)
+ }
+
+ private fun verifyContentColors(
+ testChipColors: TestChipColors,
+ status: ChipStatus,
+ contentColor: @Composable () -> Color,
+ ) {
+ var expectedContent = Color.Transparent
+ var actualContent = Color.Transparent
+ val testBackground = Color.White
+
+ rule.setContentWithTheme {
+ expectedContent =
+ if (status.enabled()) {
+ contentColor()
+ } else {
+ contentColor().copy(alpha = ContentAlpha.disabled)
+ }
+ Box(modifier = Modifier.fillMaxSize().background(testBackground)) {
+ Chip(
+ onClick = {},
+ colors = testChipColors.chipColors(),
+ content = { actualContent = LocalContentColor.current },
+ enabled = status.enabled(),
+ modifier = Modifier.testTag(TEST_TAG),
+ border = ChipDefaults.chipBorder()
+ )
+ }
+ }
+
+ assertEquals(expectedContent, actualContent)
+ }
+
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
+ private fun verifyColors(
+ testChipColors: TestChipColors,
+ status: ChipStatus,
+ backgroundColor: @Composable () -> Color,
+ contentColor: @Composable () -> Color,
+ disabledBackgroundColor: (@Composable () -> Color)? = null,
+ applyAlphaForDisabledContent: Boolean = true,
+ ) {
+ var expectedBackground = Color.Transparent
+ var expectedContent = Color.Transparent
+ var actualContent = Color.Transparent
+ val testBackground = Color.White
+
+ rule.setContentWithTheme {
+ if (status.enabled()) {
+ expectedBackground = backgroundColor()
+ expectedContent = contentColor()
+ } else {
+ expectedBackground =
+ if (disabledBackgroundColor != null) {
+ disabledBackgroundColor().compositeOver(testBackground)
+ } else {
+ backgroundColor()
+ .copy(alpha = ContentAlpha.disabled)
+ .compositeOver(testBackground)
+ }
+ expectedContent =
+ if (applyAlphaForDisabledContent)
+ contentColor().copy(alpha = ContentAlpha.disabled)
+ else contentColor()
+ }
+ Box(modifier = Modifier.fillMaxSize().background(testBackground)) {
+ if (testChipColors == TestChipColors.Outlined) {
+ OutlinedChip(
+ onClick = {},
+ colors = testChipColors.chipColors(),
+ label = { actualContent = LocalContentColor.current },
+ enabled = status.enabled(),
+ modifier = Modifier.testTag(TEST_TAG),
+ border = ChipDefaults.chipBorder()
+ )
+ } else {
+ Chip(
+ onClick = {},
+ colors = testChipColors.chipColors(),
+ content = { actualContent = LocalContentColor.current },
+ enabled = status.enabled(),
+ modifier = Modifier.testTag(TEST_TAG),
+ border = ChipDefaults.chipBorder()
+ )
+ }
+ }
+ }
+
+ assertEquals(expectedContent, actualContent)
+
+ rule
+ .onNodeWithTag(TEST_TAG)
+ .captureToImage()
+ .assertContainsColor(
+ if (expectedBackground != Color.Transparent) expectedBackground else testBackground,
+ 50.0f
+ )
+ }
+
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
+ private fun verifySlotColors(
+ testChipColors: TestChipColors,
+ status: ChipStatus,
+ backgroundColor: @Composable () -> Color,
+ contentColor: @Composable () -> Color,
+ secondaryContentColor: @Composable () -> Color,
+ iconColor: @Composable () -> Color,
+ compactChip: Boolean = false,
+ applyAlphaForDisabledContent: Boolean = true,
+ ) {
+ var expectedBackground = Color.Transparent
+ var expectedContent = Color.Transparent
+ var expectedSecondaryContent = Color.Transparent
+ var expectedIcon = Color.Transparent
+ var actualContent = Color.Transparent
+ var actualSecondaryContent = Color.Transparent
+ var actualIcon = Color.Transparent
+ val testBackground = Color.White
+
+ rule.setContentWithTheme {
+ if (status.enabled()) {
+ expectedBackground = backgroundColor()
+ expectedContent = contentColor()
+ expectedSecondaryContent = secondaryContentColor()
+ expectedIcon = iconColor()
+ } else {
+ expectedBackground =
+ backgroundColor()
+ .copy(alpha = ContentAlpha.disabled)
+ .compositeOver(testBackground)
+ if (applyAlphaForDisabledContent) {
+ expectedContent = contentColor().copy(alpha = ContentAlpha.disabled)
+ expectedSecondaryContent =
+ secondaryContentColor().copy(alpha = ContentAlpha.disabled)
+ expectedIcon = iconColor().copy(alpha = ContentAlpha.disabled)
+ } else {
+ expectedContent = contentColor()
+ expectedSecondaryContent = secondaryContentColor()
+ expectedIcon = iconColor()
+ }
+ }
+ Box(modifier = Modifier.fillMaxSize().background(testBackground)) {
+ if (compactChip) {
+ CompactChip(
+ onClick = {},
+ colors = testChipColors.chipColors(),
+ label = { actualContent = LocalContentColor.current },
+ icon = { actualIcon = LocalContentColor.current },
+ enabled = status.enabled(),
+ modifier = Modifier.testTag(TEST_TAG)
+ )
+ } else {
+ Chip(
+ onClick = {},
+ colors = testChipColors.chipColors(),
+ label = { actualContent = LocalContentColor.current },
+ secondaryLabel = { actualSecondaryContent = LocalContentColor.current },
+ icon = { actualIcon = LocalContentColor.current },
+ enabled = status.enabled(),
+ modifier = Modifier.testTag(TEST_TAG)
+ )
+ }
+ }
+ }
+
+ assertEquals(expectedContent, actualContent)
+ if (!compactChip) {
+ assertEquals(expectedSecondaryContent, actualSecondaryContent)
+ }
+ assertEquals(expectedIcon, actualIcon)
+
+ rule
+ .onNodeWithTag(TEST_TAG)
+ .captureToImage()
+ .assertContainsColor(
+ if (expectedBackground != Color.Transparent) expectedBackground else testBackground,
+ 50.0f
+ )
+ }
+
+ private fun verifySlotContentColors(
+ testChipColors: TestChipColors,
+ status: ChipStatus,
+ contentColor: @Composable () -> Color,
+ secondaryContentColor: @Composable () -> Color,
+ iconColor: @Composable () -> Color,
+ compactChip: Boolean = false,
+ ) {
+ var expectedContent = Color.Transparent
+ var expectedSecondaryContent = Color.Transparent
+ var expectedIcon = Color.Transparent
+ var actualContent = Color.Transparent
+ var actualSecondaryContent = Color.Transparent
+ var actualIcon = Color.Transparent
+ val testBackground = Color.White
+
+ rule.setContentWithTheme {
+ if (status.enabled()) {
+ expectedContent = contentColor()
+ expectedSecondaryContent = secondaryContentColor()
+ expectedIcon = iconColor()
+ } else {
+ expectedContent = contentColor().copy(alpha = ContentAlpha.disabled)
+ expectedSecondaryContent =
+ secondaryContentColor().copy(alpha = ContentAlpha.disabled)
+ expectedIcon = iconColor().copy(alpha = ContentAlpha.disabled)
+ }
+ Box(modifier = Modifier.fillMaxSize().background(testBackground)) {
+ if (compactChip) {
+ CompactChip(
+ onClick = {},
+ colors = testChipColors.chipColors(),
+ label = { actualContent = LocalContentColor.current },
+ icon = { actualIcon = LocalContentColor.current },
+ enabled = status.enabled(),
+ modifier = Modifier.testTag(TEST_TAG)
+ )
+ } else {
+ Chip(
+ onClick = {},
+ colors = testChipColors.chipColors(),
+ label = { actualContent = LocalContentColor.current },
+ secondaryLabel = { actualSecondaryContent = LocalContentColor.current },
+ icon = { actualIcon = LocalContentColor.current },
+ enabled = status.enabled(),
+ modifier = Modifier.testTag(TEST_TAG)
+ )
+ }
+ }
+ }
+
+ assertEquals(expectedContent, actualContent)
+ if (!compactChip) {
+ assertEquals(expectedSecondaryContent, actualSecondaryContent)
+ }
+ assertEquals(expectedIcon, actualIcon)
+ }
}
class ChipFontTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
- @Test
- fun gives_correct_text_style_base() {
- var actualTextStyle = TextStyle.Default
- var expectedTextStyle = TextStyle.Default
- rule.setContentWithTheme {
- expectedTextStyle = MaterialTheme.typography.button
- Chip(
- onClick = {},
- colors = ChipDefaults.primaryChipColors(),
- content = {
- actualTextStyle = LocalTextStyle.current
- },
- enabled = true,
- modifier = Modifier.testTag(TEST_TAG),
- border = ChipDefaults.chipBorder()
- )
+ @Test
+ fun gives_correct_text_style_base() {
+ var actualTextStyle = TextStyle.Default
+ var expectedTextStyle = TextStyle.Default
+ rule.setContentWithTheme {
+ expectedTextStyle = MaterialTheme.typography.button
+ Chip(
+ onClick = {},
+ colors = ChipDefaults.primaryChipColors(),
+ content = { actualTextStyle = LocalTextStyle.current },
+ enabled = true,
+ modifier = Modifier.testTag(TEST_TAG),
+ border = ChipDefaults.chipBorder()
+ )
+ }
+ assertEquals(expectedTextStyle, actualTextStyle)
}
- assertEquals(expectedTextStyle, actualTextStyle)
- }
- @Test
- fun gives_correct_text_style_three_slot_chip() {
- var actualLabelTextStyle = TextStyle.Default
- var actualSecondaryLabelTextStyle = TextStyle.Default
- var expectedTextStyle = TextStyle.Default
- var expectedSecondaryTextStyle = TextStyle.Default
- rule.setContentWithTheme {
- expectedTextStyle = MaterialTheme.typography.button
- expectedSecondaryTextStyle = MaterialTheme.typography.caption2
- Chip(
- onClick = {},
- colors = ChipDefaults.primaryChipColors(),
- label = {
- actualLabelTextStyle = LocalTextStyle.current
- },
- secondaryLabel = {
- actualSecondaryLabelTextStyle = LocalTextStyle.current
- },
- enabled = true,
- modifier = Modifier.testTag(TEST_TAG)
- )
+ @Test
+ fun gives_correct_text_style_three_slot_chip() {
+ var actualLabelTextStyle = TextStyle.Default
+ var actualSecondaryLabelTextStyle = TextStyle.Default
+ var expectedTextStyle = TextStyle.Default
+ var expectedSecondaryTextStyle = TextStyle.Default
+ rule.setContentWithTheme {
+ expectedTextStyle = MaterialTheme.typography.button
+ expectedSecondaryTextStyle = MaterialTheme.typography.caption2
+ Chip(
+ onClick = {},
+ colors = ChipDefaults.primaryChipColors(),
+ label = { actualLabelTextStyle = LocalTextStyle.current },
+ secondaryLabel = { actualSecondaryLabelTextStyle = LocalTextStyle.current },
+ enabled = true,
+ modifier = Modifier.testTag(TEST_TAG)
+ )
+ }
+ assertEquals(expectedTextStyle, actualLabelTextStyle)
+ assertEquals(expectedSecondaryTextStyle, actualSecondaryLabelTextStyle)
}
- assertEquals(expectedTextStyle, actualLabelTextStyle)
- assertEquals(expectedSecondaryTextStyle, actualSecondaryLabelTextStyle)
- }
}
class ChipShapeTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
- @Test
- fun default_chip_shape_is_circle() {
- rule.isShape(RoundedCornerShape(corner = CornerSize(50))) { modifier ->
- Chip(
- onClick = {},
- label = {},
- enabled = true,
- colors = ChipDefaults.primaryChipColors(),
- modifier = modifier
- )
- }
- }
-
- @Test
- fun allows_custom_chip_shape_override() {
- val shape = CutCornerShape(4.dp)
-
- rule.isShape(shape) { modifier ->
- Chip(
- onClick = {},
- label = {},
- enabled = true,
- colors = ChipDefaults.primaryChipColors(),
- shape = shape,
- modifier = modifier
- )
- }
- }
-
- @Test
- fun default_compact_chip_shape_is_circle() {
- rule.isShape(RoundedCornerShape(corner = CornerSize(50))) { modifier ->
- CompactChip(
- onClick = {},
- colors = ChipDefaults.primaryChipColors(),
- enabled = true,
- modifier = modifier
- )
- }
- }
-
- @Test
- fun allows_custom_compact_chip_shape_override() {
- val shape = CutCornerShape(4.dp)
-
- rule.isShape(shape) { modifier ->
- CompactChip(
- onClick = {},
- colors = ChipDefaults.primaryChipColors(),
- enabled = true,
- shape = shape,
- modifier = modifier
- )
- }
- }
-
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
- private fun ComposeContentTestRule.isShape(
- expectedShape: Shape,
- content: @Composable (Modifier) -> Unit,
- ) {
- var background = Color.Transparent
- var chipColor = Color.Transparent
- val padding = 0.dp
-
- rule.setContentWithTheme {
- background = MaterialTheme.colors.surface
- chipColor = MaterialTheme.colors.primary
- content(
- Modifier
- .testTag(TEST_TAG)
- .padding(padding)
- .background(background))
+ @Test
+ fun default_chip_shape_is_circle() {
+ rule.isShape(RoundedCornerShape(corner = CornerSize(50))) { modifier ->
+ Chip(
+ onClick = {},
+ label = {},
+ enabled = true,
+ colors = ChipDefaults.primaryChipColors(),
+ modifier = modifier
+ )
+ }
}
- rule.onNodeWithTag(TEST_TAG)
- .captureToImage()
- .assertShape(
- density = rule.density,
- horizontalPadding = 0.dp,
- verticalPadding = 0.dp,
- shapeColor = chipColor,
- backgroundColor = background,
- shape = expectedShape
- )
- }
+ @Test
+ fun allows_custom_chip_shape_override() {
+ val shape = CutCornerShape(4.dp)
+
+ rule.isShape(shape) { modifier ->
+ Chip(
+ onClick = {},
+ label = {},
+ enabled = true,
+ colors = ChipDefaults.primaryChipColors(),
+ shape = shape,
+ modifier = modifier
+ )
+ }
+ }
+
+ @Test
+ fun default_compact_chip_shape_is_circle() {
+ rule.isShape(RoundedCornerShape(corner = CornerSize(50))) { modifier ->
+ CompactChip(
+ onClick = {},
+ colors = ChipDefaults.primaryChipColors(),
+ enabled = true,
+ modifier = modifier
+ )
+ }
+ }
+
+ @Test
+ fun allows_custom_compact_chip_shape_override() {
+ val shape = CutCornerShape(4.dp)
+
+ rule.isShape(shape) { modifier ->
+ CompactChip(
+ onClick = {},
+ colors = ChipDefaults.primaryChipColors(),
+ enabled = true,
+ shape = shape,
+ modifier = modifier
+ )
+ }
+ }
+
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
+ private fun ComposeContentTestRule.isShape(
+ expectedShape: Shape,
+ content: @Composable (Modifier) -> Unit,
+ ) {
+ var background = Color.Transparent
+ var chipColor = Color.Transparent
+ val padding = 0.dp
+
+ rule.setContentWithTheme {
+ background = MaterialTheme.colors.surface
+ chipColor = MaterialTheme.colors.primary
+ content(Modifier.testTag(TEST_TAG).padding(padding).background(background))
+ }
+
+ rule
+ .onNodeWithTag(TEST_TAG)
+ .captureToImage()
+ .assertShape(
+ density = rule.density,
+ horizontalPadding = 0.dp,
+ verticalPadding = 0.dp,
+ shapeColor = chipColor,
+ backgroundColor = background,
+ shape = expectedShape
+ )
+ }
}
private fun ComposeContentTestRule.verifyHeight(expected: Dp, content: @Composable () -> Unit) {
- setContentWithThemeForSizeAssertions {
- content()
- }
- .assertHeightIsEqualTo(expected)
+ setContentWithThemeForSizeAssertions { content() }.assertHeightIsEqualTo(expected)
}
// Determine whether the chip has stadium shape.
// https://en.wikipedia.org/wiki/Stadium_(geometry)#:~:text=A%20stadium%20is%20a%20two,%2C%20obround%2C%20or%20sausage%20body.
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
private fun ComposeContentTestRule.isStadiumShape(
- layoutDirection: LayoutDirection,
- content: @Composable () -> Unit,
+ layoutDirection: LayoutDirection,
+ content: @Composable () -> Unit,
) {
- val padding = 0.dp
- var background = Color.Transparent
- var surface = Color.Transparent
- setContentWithTheme {
- background = MaterialTheme.colors.primary
- surface = MaterialTheme.colors.surface
- CompositionLocalProvider(LocalLayoutDirection provides layoutDirection) {
- Box(
- Modifier
- .padding(padding)
- .background(surface)
- ) {
- content()
- }
+ val padding = 0.dp
+ var background = Color.Transparent
+ var surface = Color.Transparent
+ setContentWithTheme {
+ background = MaterialTheme.colors.primary
+ surface = MaterialTheme.colors.surface
+ CompositionLocalProvider(LocalLayoutDirection provides layoutDirection) {
+ Box(Modifier.padding(padding).background(surface)) { content() }
+ }
}
- }
- onNodeWithTag(TEST_TAG)
- .captureToImage()
- .assertShape(
- density = density,
- shape = RoundedCornerShape(corner = CornerSize(50)),
- horizontalPadding = padding,
- verticalPadding = padding,
- backgroundColor = surface,
- shapeColor = background
- )
+ onNodeWithTag(TEST_TAG)
+ .captureToImage()
+ .assertShape(
+ density = density,
+ shape = RoundedCornerShape(corner = CornerSize(50)),
+ horizontalPadding = padding,
+ verticalPadding = padding,
+ backgroundColor = surface,
+ shapeColor = background
+ )
}
internal enum class ChipStatus {
- Enabled,
- Disabled;
+ Enabled,
+ Disabled;
- fun enabled() = this == Enabled
+ fun enabled() = this == Enabled
}
private enum class TestChipColors {
- Primary {
- @Composable
- override fun chipColors(): ChipColors {
- return ChipDefaults.primaryChipColors()
- }
- },
- PrimaryGradient {
- @Composable
- override fun chipColors(): ChipColors {
- return ChipDefaults.gradientBackgroundChipColors()
- }
- },
- Secondary {
- @Composable
- override fun chipColors(): ChipColors {
- return ChipDefaults.secondaryChipColors()
- }
- },
- Child {
- @Composable
- override fun chipColors(): ChipColors {
- return ChipDefaults.childChipColors()
- }
- },
- Outlined {
- @Composable
- override fun chipColors(): ChipColors {
- return ChipDefaults.outlinedChipColors()
- }
- },
- ImageBackground {
- @Composable
- override fun chipColors(): ChipColors {
- return ChipDefaults.imageBackgroundChipColors(
- backgroundImagePainter = rememberVectorPainter(image = Icons.Outlined.Add)
- )
- }
- };
+ Primary {
+ @Composable
+ override fun chipColors(): ChipColors {
+ return ChipDefaults.primaryChipColors()
+ }
+ },
+ PrimaryGradient {
+ @Composable
+ override fun chipColors(): ChipColors {
+ return ChipDefaults.gradientBackgroundChipColors()
+ }
+ },
+ Secondary {
+ @Composable
+ override fun chipColors(): ChipColors {
+ return ChipDefaults.secondaryChipColors()
+ }
+ },
+ Child {
+ @Composable
+ override fun chipColors(): ChipColors {
+ return ChipDefaults.childChipColors()
+ }
+ },
+ Outlined {
+ @Composable
+ override fun chipColors(): ChipColors {
+ return ChipDefaults.outlinedChipColors()
+ }
+ },
+ ImageBackground {
+ @Composable
+ override fun chipColors(): ChipColors {
+ return ChipDefaults.imageBackgroundChipColors(
+ backgroundImagePainter = rememberVectorPainter(image = Icons.Outlined.Add)
+ )
+ }
+ };
- @Composable
- abstract fun chipColors(): ChipColors
+ @Composable abstract fun chipColors(): ChipColors
}
diff --git a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/CurvedTextTest.kt b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/CurvedTextTest.kt
index 82cc7da..63d7b7d 100644
--- a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/CurvedTextTest.kt
+++ b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/CurvedTextTest.kt
@@ -38,8 +38,7 @@
@RunWith(AndroidJUnit4::class)
@RequiresApi(Build.VERSION_CODES.O)
class CurvedTextTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
private val testText = "TestText"
@@ -51,9 +50,7 @@
curvedText(
text = testText,
color = Color.Red,
- style = CurvedTextStyle(
- color = Color.Blue
- )
+ style = CurvedTextStyle(color = Color.Blue)
)
}
}
@@ -70,12 +67,7 @@
CompositionLocalProvider(LocalContentColor provides Color.Yellow) {
CurvedLayout {
curvedRow {
- curvedText(
- text = testText,
- style = CurvedTextStyle(
- color = Color.Blue
- )
- )
+ curvedText(text = testText, style = CurvedTextStyle(color = Color.Blue))
}
}
}
@@ -100,7 +92,9 @@
}
}
- rule.onNodeWithContentDescription(testText).captureToImage()
+ rule
+ .onNodeWithContentDescription(testText)
+ .captureToImage()
.assertContainsColor(Color.Yellow)
}
}
diff --git a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/HorizontalPageIndicatorScreenshotTest.kt b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/HorizontalPageIndicatorScreenshotTest.kt
index 394bf1e..dca8b85 100644
--- a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/HorizontalPageIndicatorScreenshotTest.kt
+++ b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/HorizontalPageIndicatorScreenshotTest.kt
@@ -46,14 +46,11 @@
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
class HorizontalPageIndicatorScreenshotTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
- @get:Rule
- val screenshotRule = AndroidXScreenshotTestRule(SCREENSHOT_GOLDEN_PATH)
+ @get:Rule val screenshotRule = AndroidXScreenshotTestRule(SCREENSHOT_GOLDEN_PATH)
- @get:Rule
- val testName = TestName()
+ @get:Rule val testName = TestName()
@Test
fun horizontalPageIndicator_circular_selected_page() {
@@ -96,18 +93,15 @@
}
rule.waitForIdle()
- rule.onNodeWithTag(TEST_TAG)
+ rule
+ .onNodeWithTag(TEST_TAG)
.captureToImage()
.assertAgainstGolden(screenshotRule, testName.methodName)
}
private fun between_pages(indicatorStyle: PageIndicatorStyle) {
rule.setContentWithTheme {
- Box(
- modifier = Modifier
- .testTag(TEST_TAG)
- .size(150.dp)
- ) {
+ Box(modifier = Modifier.testTag(TEST_TAG).size(150.dp)) {
HorizontalPageIndicator(
indicatorStyle = indicatorStyle,
pageIndicatorState = pageIndicatorState(0.5f),
@@ -119,18 +113,15 @@
}
rule.waitForIdle()
- rule.onNodeWithTag(TEST_TAG)
+ rule
+ .onNodeWithTag(TEST_TAG)
.captureToImage()
.assertAgainstGolden(screenshotRule, testName.methodName)
}
@Composable
private fun defaultHorizontalPageIndicator(indicatorStyle: PageIndicatorStyle) {
- Box(
- modifier = Modifier
- .testTag(TEST_TAG)
- .size(150.dp)
- ) {
+ Box(modifier = Modifier.testTag(TEST_TAG).size(150.dp)) {
HorizontalPageIndicator(
indicatorStyle = indicatorStyle,
pageIndicatorState = pageIndicatorState(),
diff --git a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/HorizontalPageIndicatorTest.kt b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/HorizontalPageIndicatorTest.kt
index f5cc10e..d87f2ea 100644
--- a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/HorizontalPageIndicatorTest.kt
+++ b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/HorizontalPageIndicatorTest.kt
@@ -35,8 +35,7 @@
@RequiresApi(Build.VERSION_CODES.O)
class HorizontalPageIndicatorTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
@Test
public fun supports_testtag_circular() {
@@ -102,10 +101,8 @@
HorizontalPageIndicator(
modifier = Modifier.testTag(TEST_TAG),
indicatorStyle = PageIndicatorStyle.Curved,
- pageIndicatorState = pageIndicatorState(
- pageOffset = 0f,
- selectedPage = 1,
- pageCount = 9),
+ pageIndicatorState =
+ pageIndicatorState(pageOffset = 0f, selectedPage = 1, pageCount = 9),
indicatorSize = indicatorSize,
spacing = spacing
)
@@ -127,10 +124,12 @@
HorizontalPageIndicator(
modifier = Modifier.testTag(TEST_TAG),
indicatorStyle = PageIndicatorStyle.Curved,
- pageIndicatorState = pageIndicatorState(
- pageOffset = 0f,
- selectedPage = 1,
- pageCount = pagesCount),
+ pageIndicatorState =
+ pageIndicatorState(
+ pageOffset = 0f,
+ selectedPage = 1,
+ pageCount = pagesCount
+ ),
indicatorSize = indicatorSize,
spacing = spacing
)
@@ -157,11 +156,15 @@
// A selected dot with specified color should be visible on the screen, which is apprx 1.3%
// (1.3% per dot, 1 dot in total)
- rule.onNodeWithTag(TEST_TAG).captureToImage()
+ rule
+ .onNodeWithTag(TEST_TAG)
+ .captureToImage()
.assertColorInPercentageRange(selectedColor, 1.2f..1.5f)
// Unselected dots should also be visible on the screen, and should take around 4%
// (1.3% per dot, 3 dots total)
- rule.onNodeWithTag(TEST_TAG).captureToImage()
+ rule
+ .onNodeWithTag(TEST_TAG)
+ .captureToImage()
.assertColorInPercentageRange(unselectedColor, 3.8f..4.5f)
}
@@ -180,12 +183,13 @@
rule.waitForIdle()
// Selected color was blended in between of 2 dots, which made it a different color
- rule.onNodeWithTag(TEST_TAG).captureToImage()
- .assertDoesNotContainColor(selectedColor)
+ rule.onNodeWithTag(TEST_TAG).captureToImage().assertDoesNotContainColor(selectedColor)
// Unselected dots ( which doesn't participate in color merge)
// should also be visible on the screen, and should take around 2.7%
// (1.3% per dot, 2 dots in total)
- rule.onNodeWithTag(TEST_TAG).captureToImage()
+ rule
+ .onNodeWithTag(TEST_TAG)
+ .captureToImage()
.assertColorInPercentageRange(unselectedColor, 2.5f..3f)
}
@@ -206,11 +210,15 @@
// A selected item with specified color should be visible on the screen, which is
// apprx 1.8% (1.8% per item, 1 item in total)
- rule.onNodeWithTag(TEST_TAG).captureToImage()
+ rule
+ .onNodeWithTag(TEST_TAG)
+ .captureToImage()
.assertColorInPercentageRange(selectedColor, 1.6f..1.9f)
// Unselected item should also be visible on the screen, and should take around 5.8%
// (1.8% per item, 3 items in total)
- rule.onNodeWithTag(TEST_TAG).captureToImage()
+ rule
+ .onNodeWithTag(TEST_TAG)
+ .captureToImage()
.assertColorInPercentageRange(unselectedColor, 5f..6f)
}
@@ -218,17 +226,16 @@
val selectedColor = Color.Yellow
val unselectedColor = Color.Red
- fun pageIndicatorState(
- pageOffset: Float = 0f,
- selectedPage: Int = 1,
- pageCount: Int = 4
- ) = object : PageIndicatorState {
- override val pageOffset: Float
- get() = pageOffset
- override val selectedPage: Int
- get() = selectedPage
- override val pageCount: Int
- get() = pageCount
- }
+ fun pageIndicatorState(pageOffset: Float = 0f, selectedPage: Int = 1, pageCount: Int = 4) =
+ object : PageIndicatorState {
+ override val pageOffset: Float
+ get() = pageOffset
+
+ override val selectedPage: Int
+ get() = selectedPage
+
+ override val pageCount: Int
+ get() = pageCount
+ }
}
}
diff --git a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/IconTest.kt b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/IconTest.kt
index a073f25..0bde7c5 100644
--- a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/IconTest.kt
+++ b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/IconTest.kt
@@ -55,8 +55,7 @@
@LargeTest
@RunWith(AndroidJUnit4::class)
class IconTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
@Test
fun vector_materialIconSize_dimensions() {
@@ -64,9 +63,7 @@
val height = 24.dp
val vector = Icons.Filled.Menu
rule
- .setContentWithThemeForSizeAssertions {
- Icon(vector, null)
- }
+ .setContentWithThemeForSizeAssertions { Icon(vector, null) }
.assertWidthIsEqualTo(width)
.assertHeightIsEqualTo(height)
}
@@ -75,14 +72,16 @@
fun vector_customIconSize_dimensions() {
val width = 35.dp
val height = 83.dp
- val vector = ImageVector.Builder(
- defaultWidth = width, defaultHeight = height,
- viewportWidth = width.value, viewportHeight = height.value
- ).build()
+ val vector =
+ ImageVector.Builder(
+ defaultWidth = width,
+ defaultHeight = height,
+ viewportWidth = width.value,
+ viewportHeight = height.value
+ )
+ .build()
rule
- .setContentWithThemeForSizeAssertions {
- Icon(vector, null)
- }
+ .setContentWithThemeForSizeAssertions { Icon(vector, null) }
.assertWidthIsEqualTo(width)
.assertHeightIsEqualTo(height)
}
@@ -93,9 +92,10 @@
val height = 24.dp
rule
.setContentWithThemeForSizeAssertions {
- val image = with(LocalDensity.current) {
- ImageBitmap(width.roundToPx(), height.roundToPx())
- }
+ val image =
+ with(LocalDensity.current) {
+ ImageBitmap(width.roundToPx(), height.roundToPx())
+ }
Icon(image, null)
}
@@ -110,9 +110,10 @@
rule
.setContentWithThemeForSizeAssertions {
- val image = with(LocalDensity.current) {
- ImageBitmap(width.roundToPx(), height.roundToPx())
- }
+ val image =
+ with(LocalDensity.current) {
+ ImageBitmap(width.roundToPx(), height.roundToPx())
+ }
Icon(image, null)
}
@@ -126,9 +127,7 @@
val height = 24.dp
val painter = ColorPainter(Color.Red)
rule
- .setContentWithThemeForSizeAssertions {
- Icon(painter, null)
- }
+ .setContentWithThemeForSizeAssertions { Icon(painter, null) }
.assertWidthIsEqualTo(width)
.assertHeightIsEqualTo(height)
}
@@ -140,9 +139,10 @@
rule
.setContentWithThemeForSizeAssertions {
- val image = with(LocalDensity.current) {
- ImageBitmap(width.roundToPx(), height.roundToPx())
- }
+ val image =
+ with(LocalDensity.current) {
+ ImageBitmap(width.roundToPx(), height.roundToPx())
+ }
val bitmapPainter = BitmapPainter(image)
Icon(bitmapPainter, null)
@@ -162,12 +162,8 @@
rule.setContentWithTheme {
val image: ImageBitmap
with(LocalDensity.current) {
- image = createBitmapWithColor(
- this,
- width.roundToPx(),
- height.roundToPx(),
- Color.Red
- )
+ image =
+ createBitmapWithColor(this, width.roundToPx(), height.roundToPx(), Color.Red)
}
Icon(
image,
@@ -182,12 +178,11 @@
}
}
- rule.onNodeWithTag(testTag)
+ rule
+ .onNodeWithTag(testTag)
.captureToImage()
// The icon should be 50x50 and fill the whole size with red pixels
- .assertPixels(expectedSize = expectedIntSize!!) {
- Color.Red
- }
+ .assertPixels(expectedSize = expectedIntSize!!) { Color.Red }
}
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
@@ -199,12 +194,8 @@
rule.setContentWithTheme {
val image: ImageBitmap
with(LocalDensity.current) {
- image = createBitmapWithColor(
- this,
- width.roundToPx(),
- height.roundToPx(),
- Color.Red
- )
+ image =
+ createBitmapWithColor(this, width.roundToPx(), height.roundToPx(), Color.Red)
}
Icon(image, null, modifier = Modifier.testTag(testTag), tint = Color.Unspecified)
}
@@ -222,12 +213,8 @@
rule.setContentWithTheme {
val image: ImageBitmap
with(LocalDensity.current) {
- image = createBitmapWithColor(
- this,
- width.roundToPx(),
- height.roundToPx(),
- Color.Red
- )
+ image =
+ createBitmapWithColor(this, width.roundToPx(), height.roundToPx(), Color.Red)
}
Icon(image, null, modifier = Modifier.testTag(testTag), tint = Color.Blue)
}
@@ -247,7 +234,8 @@
)
}
- rule.onNodeWithTag(testTag)
+ rule
+ .onNodeWithTag(testTag)
.assertContentDescriptionEquals("qwerty")
.assert(SemanticsMatcher.expectValue(SemanticsProperties.Role, Role.Image))
}
@@ -260,12 +248,7 @@
): ImageBitmap {
val size = Size(width.toFloat(), height.toFloat())
val image = ImageBitmap(width, height)
- CanvasDrawScope().draw(
- density,
- LayoutDirection.Ltr,
- Canvas(image),
- size
- ) {
+ CanvasDrawScope().draw(density, LayoutDirection.Ltr, Canvas(image), size) {
drawRect(color)
}
return image
diff --git a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/InlineSliderTest.kt b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/InlineSliderTest.kt
index 7628477..86be878 100644
--- a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/InlineSliderTest.kt
+++ b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/InlineSliderTest.kt
@@ -42,8 +42,7 @@
import org.junit.Test
public class InlineSliderTest {
- @get:Rule
- public val rule = createComposeRule()
+ @get:Rule public val rule = createComposeRule()
@Test
public fun supports_testtag() {
@@ -73,11 +72,8 @@
modifier = Modifier.testTag(TEST_TAG)
)
}
- rule.runOnIdle {
- state.value = 20f
- }
- rule.onNodeWithTag(TEST_TAG)
- .assertRangeInfoEquals(ProgressBarRangeInfo(10f, 0f..10f, 4))
+ rule.runOnIdle { state.value = 20f }
+ rule.onNodeWithTag(TEST_TAG).assertRangeInfoEquals(ProgressBarRangeInfo(10f, 0f..10f, 4))
}
@Test
@@ -93,22 +89,14 @@
modifier = Modifier.testTag(TEST_TAG)
)
}
- rule.runOnIdle {
- state.value = -20f
- }
- rule.onNodeWithTag(TEST_TAG)
- .assertRangeInfoEquals(ProgressBarRangeInfo(0f, 0f..10f, 4))
+ rule.runOnIdle { state.value = -20f }
+ rule.onNodeWithTag(TEST_TAG).assertRangeInfoEquals(ProgressBarRangeInfo(0f, 0f..10f, 4))
}
@Test(expected = IllegalArgumentException::class)
public fun throws_when_steps_negative() {
rule.setContent {
- DefaultInlineSlider(
- value = 0f,
- valueRange = 0f..10f,
- onValueChange = {},
- steps = -1
- )
+ DefaultInlineSlider(value = 0f, valueRange = 0f..10f, onValueChange = {}, steps = -1)
}
}
@@ -127,12 +115,9 @@
)
}
- rule.runOnUiThread {
- state.value = 0.6f
- }
+ rule.runOnUiThread { state.value = 0.6f }
- rule.onNodeWithTag(TEST_TAG)
- .assertRangeInfoEquals(ProgressBarRangeInfo(0.6f, range, 4))
+ rule.onNodeWithTag(TEST_TAG).assertRangeInfoEquals(ProgressBarRangeInfo(0.6f, range, 4))
}
@Test
@@ -150,12 +135,9 @@
)
}
- rule.runOnUiThread {
- state.value = 0.65f
- }
+ rule.runOnUiThread { state.value = 0.65f }
- rule.onNodeWithTag(TEST_TAG)
- .assertRangeInfoEquals(ProgressBarRangeInfo(0.6f, range, 4))
+ rule.onNodeWithTag(TEST_TAG).assertRangeInfoEquals(ProgressBarRangeInfo(0.6f, range, 4))
}
@Test
@@ -173,12 +155,9 @@
)
}
- rule.runOnUiThread {
- state.value = 0.55f
- }
+ rule.runOnUiThread { state.value = 0.55f }
- rule.onNodeWithTag(TEST_TAG)
- .assertRangeInfoEquals(ProgressBarRangeInfo(0.6f, range, 4))
+ rule.onNodeWithTag(TEST_TAG).assertRangeInfoEquals(ProgressBarRangeInfo(0.6f, range, 4))
}
@Test
@@ -195,9 +174,7 @@
}
rule.onNodeWithTag(TEST_TAG).performTouchInput { click(Offset(15f, height / 2f)) }
- rule.runOnIdle {
- Truth.assertThat(state.value).isWithin(0.001f).of(1f)
- }
+ rule.runOnIdle { Truth.assertThat(state.value).isWithin(0.001f).of(1f) }
}
@Test
@@ -214,9 +191,7 @@
}
rule.onNodeWithTag(TEST_TAG).performTouchInput { click(Offset(width - 15f, height / 2f)) }
- rule.runOnIdle {
- Truth.assertThat(state.value).isWithin(0.001f).of(3f)
- }
+ rule.runOnIdle { Truth.assertThat(state.value).isWithin(0.001f).of(3f) }
}
@Test
@@ -236,9 +211,7 @@
}
rule.onNodeWithTag(TEST_TAG).performTouchInput { click(Offset(15f, height / 2f)) }
- rule.runOnIdle {
- Truth.assertThat(state.value).isWithin(0.001f).of(2f)
- }
+ rule.runOnIdle { Truth.assertThat(state.value).isWithin(0.001f).of(2f) }
}
@Test
@@ -258,9 +231,7 @@
}
rule.onNodeWithTag(TEST_TAG).performTouchInput { click(Offset(width - 15f, height / 2f)) }
- rule.runOnIdle {
- Truth.assertThat(state.value).isWithin(0.001f).of(2f)
- }
+ rule.runOnIdle { Truth.assertThat(state.value).isWithin(0.001f).of(2f) }
}
@Test
@@ -277,9 +248,7 @@
}
rule.onNodeWithTag(TEST_TAG).performTouchInput { click(Offset(15f, height / 2f)) }
- rule.runOnIdle {
- Truth.assertThat(state.value).isWithin(0.001f).of(1f)
- }
+ rule.runOnIdle { Truth.assertThat(state.value).isWithin(0.001f).of(1f) }
}
@Test
@@ -296,9 +265,7 @@
}
rule.onNodeWithTag(TEST_TAG).performTouchInput { click(Offset(width - 15f, height / 2f)) }
- rule.runOnIdle {
- Truth.assertThat(state.value).isWithin(0.001f).of(4f)
- }
+ rule.runOnIdle { Truth.assertThat(state.value).isWithin(0.001f).of(4f) }
}
@Test
@@ -310,7 +277,7 @@
modifier = Modifier.testTag(TEST_TAG),
value = 0f,
steps = 5,
- onValueChange = { },
+ onValueChange = {},
increaseIcon = { Icon(InlineSliderDefaults.Increase, "Increase") },
decreaseIcon = {
Icon(
@@ -323,7 +290,8 @@
}
rule.waitForIdle()
- rule.onNodeWithTag(iconTag, true)
+ rule
+ .onNodeWithTag(iconTag, true)
.assertExists()
.assertLeftPositionInRootIsEqualTo(IconsOuterHorizontalMargin)
}
@@ -337,7 +305,7 @@
modifier = Modifier.testTag(TEST_TAG),
value = 0f,
steps = 5,
- onValueChange = { },
+ onValueChange = {},
increaseIcon = {
Icon(
modifier = Modifier.testTag(iconTag),
@@ -351,11 +319,11 @@
val unclippedBoundsInRoot = rule.onRoot().getUnclippedBoundsInRoot()
rule.waitForIdle()
- rule.onNodeWithTag(iconTag, true)
+ rule
+ .onNodeWithTag(iconTag, true)
.assertExists()
.assertLeftPositionInRootIsEqualTo(
- unclippedBoundsInRoot.width -
- IconsOuterHorizontalMargin - DefaultIconWidth
+ unclippedBoundsInRoot.width - IconsOuterHorizontalMargin - DefaultIconWidth
)
}
@@ -370,12 +338,13 @@
steps = 5,
increaseIcon = { Icon(InlineSliderDefaults.Increase, "Increase") },
decreaseIcon = { Icon(InlineSliderDefaults.Decrease, testContentDescription) },
- onValueChange = { },
+ onValueChange = {},
)
}
rule.waitForIdle()
- rule.onNodeWithTag(TEST_TAG, true)
+ rule
+ .onNodeWithTag(TEST_TAG, true)
// 0 is the index of decrease button, 1 - increase button
.onChildAt(0)
.onChild()
@@ -393,12 +362,13 @@
steps = 5,
increaseIcon = { Icon(InlineSliderDefaults.Increase, testContentDescription) },
decreaseIcon = { Icon(InlineSliderDefaults.Decrease, "Decrease") },
- onValueChange = { },
+ onValueChange = {},
)
}
rule.waitForIdle()
- rule.onNodeWithTag(TEST_TAG, true)
+ rule
+ .onNodeWithTag(TEST_TAG, true)
// 0 is the index of decrease button, 1 - increase button
.onChildAt(1)
.onChild()
@@ -410,8 +380,7 @@
}
public class IntegerInlineSliderTest {
- @get:Rule
- public val rule = createComposeRule()
+ @get:Rule public val rule = createComposeRule()
@Test
public fun supports_testtag() {
@@ -438,8 +407,7 @@
)
}
- rule.onNodeWithTag(TEST_TAG)
- .assertRangeInfoEquals(ProgressBarRangeInfo(2f, 0f..10f, 9))
+ rule.onNodeWithTag(TEST_TAG).assertRangeInfoEquals(ProgressBarRangeInfo(2f, 0f..10f, 9))
}
@Test
@@ -453,8 +421,7 @@
)
}
- rule.onNodeWithTag(TEST_TAG)
- .assertRangeInfoEquals(ProgressBarRangeInfo(2f, 0f..10f, 4))
+ rule.onNodeWithTag(TEST_TAG).assertRangeInfoEquals(ProgressBarRangeInfo(2f, 0f..10f, 4))
}
@Test
@@ -468,8 +435,7 @@
)
}
- rule.onNodeWithTag(TEST_TAG)
- .assertRangeInfoEquals(ProgressBarRangeInfo(6f, 0f..12f, 1))
+ rule.onNodeWithTag(TEST_TAG).assertRangeInfoEquals(ProgressBarRangeInfo(6f, 0f..12f, 1))
}
@Test
@@ -484,11 +450,8 @@
modifier = Modifier.testTag(TEST_TAG)
)
}
- rule.runOnIdle {
- state.value = 20
- }
- rule.onNodeWithTag(TEST_TAG)
- .assertRangeInfoEquals(ProgressBarRangeInfo(10f, 0f..10f, 9))
+ rule.runOnIdle { state.value = 20 }
+ rule.onNodeWithTag(TEST_TAG).assertRangeInfoEquals(ProgressBarRangeInfo(10f, 0f..10f, 9))
}
@Test
@@ -503,11 +466,8 @@
modifier = Modifier.testTag(TEST_TAG)
)
}
- rule.runOnIdle {
- state.value = -20
- }
- rule.onNodeWithTag(TEST_TAG)
- .assertRangeInfoEquals(ProgressBarRangeInfo(0f, 0f..10f, 9))
+ rule.runOnIdle { state.value = -20 }
+ rule.onNodeWithTag(TEST_TAG).assertRangeInfoEquals(ProgressBarRangeInfo(0f, 0f..10f, 9))
}
@Test
@@ -523,12 +483,9 @@
)
}
- rule.runOnUiThread {
- state.value = 6
- }
+ rule.runOnUiThread { state.value = 6 }
- rule.onNodeWithTag(TEST_TAG)
- .assertRangeInfoEquals(ProgressBarRangeInfo(6f, 0f..12f, 3))
+ rule.onNodeWithTag(TEST_TAG).assertRangeInfoEquals(ProgressBarRangeInfo(6f, 0f..12f, 3))
}
@Test
@@ -544,12 +501,9 @@
)
}
- rule.runOnUiThread {
- state.value = 7
- }
+ rule.runOnUiThread { state.value = 7 }
- rule.onNodeWithTag(TEST_TAG)
- .assertRangeInfoEquals(ProgressBarRangeInfo(6f, 0f..12f, 3))
+ rule.onNodeWithTag(TEST_TAG).assertRangeInfoEquals(ProgressBarRangeInfo(6f, 0f..12f, 3))
}
@Test
@@ -565,12 +519,9 @@
)
}
- rule.runOnUiThread {
- state.value = 8
- }
+ rule.runOnUiThread { state.value = 8 }
- rule.onNodeWithTag(TEST_TAG)
- .assertRangeInfoEquals(ProgressBarRangeInfo(9f, 0f..12f, 3))
+ rule.onNodeWithTag(TEST_TAG).assertRangeInfoEquals(ProgressBarRangeInfo(9f, 0f..12f, 3))
}
@Test
@@ -586,9 +537,7 @@
}
rule.onNodeWithTag(TEST_TAG).performTouchInput { click(Offset(15f, height / 2f)) }
- rule.runOnIdle {
- Truth.assertThat(state.value).isEqualTo(1)
- }
+ rule.runOnIdle { Truth.assertThat(state.value).isEqualTo(1) }
}
@Test
@@ -604,9 +553,7 @@
}
rule.onNodeWithTag(TEST_TAG).performTouchInput { click(Offset(width - 15f, height / 2f)) }
- rule.runOnIdle {
- Truth.assertThat(state.value).isEqualTo(3)
- }
+ rule.runOnIdle { Truth.assertThat(state.value).isEqualTo(3) }
}
@Test
@@ -625,9 +572,7 @@
}
rule.onNodeWithTag(TEST_TAG).performTouchInput { click(Offset(15f, height / 2f)) }
- rule.runOnIdle {
- Truth.assertThat(state.value).isEqualTo(2)
- }
+ rule.runOnIdle { Truth.assertThat(state.value).isEqualTo(2) }
}
@Test
@@ -643,9 +588,7 @@
}
rule.onNodeWithTag(TEST_TAG).performTouchInput { click(Offset(15f, height / 2f)) }
- rule.runOnIdle {
- Truth.assertThat(state.value).isEqualTo(1)
- }
+ rule.runOnIdle { Truth.assertThat(state.value).isEqualTo(1) }
}
@Test
@@ -661,9 +604,7 @@
}
rule.onNodeWithTag(TEST_TAG).performTouchInput { click(Offset(width - 15f, height / 2f)) }
- rule.runOnIdle {
- Truth.assertThat(state.value).isEqualTo(4)
- }
+ rule.runOnIdle { Truth.assertThat(state.value).isEqualTo(4) }
}
}
diff --git a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/ListHeaderTest.kt b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/ListHeaderTest.kt
index 33f74ad..f1b3867 100644
--- a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/ListHeaderTest.kt
+++ b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/ListHeaderTest.kt
@@ -32,17 +32,12 @@
@LargeTest
@RunWith(AndroidJUnit4::class)
class ListHeaderTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
@Test
fun supports_testtag() {
rule.setContentWithTheme {
- ListHeader(
- modifier = Modifier.testTag(TEST_TAG)
- ) {
- Text(text = "List Header")
- }
+ ListHeader(modifier = Modifier.testTag(TEST_TAG)) { Text(text = "List Header") }
}
rule.onNodeWithTag(TEST_TAG).assertExists()
@@ -51,11 +46,7 @@
@Test
fun listHeader_has_semantic_heading_property() {
rule.setContentWithTheme {
- ListHeader(
- modifier = Modifier.testTag(TEST_TAG)
- ) {
- Text("Title")
- }
+ ListHeader(modifier = Modifier.testTag(TEST_TAG)) { Text("Title") }
}
rule.onNode(isHeading())
@@ -68,9 +59,7 @@
rule.setContentWithTheme {
expectedTextStyle = MaterialTheme.typography.button
- ListHeader {
- actualTextStyle = LocalTextStyle.current
- }
+ ListHeader { actualTextStyle = LocalTextStyle.current }
}
Assert.assertEquals(expectedTextStyle, actualTextStyle)
}
diff --git a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/MaterialTest.kt b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/MaterialTest.kt
index b2a5be2..0251357 100644
--- a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/MaterialTest.kt
+++ b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/MaterialTest.kt
@@ -65,9 +65,7 @@
import kotlin.math.round
import org.junit.Assert
-/**
- * Constant to emulate very big but finite constraints
- */
+/** Constant to emulate very big but finite constraints */
val BigTestMaxWidth = 5000.dp
val BigTestMaxHeight = 5000.dp
@@ -77,11 +75,7 @@
modifier: Modifier = Modifier,
composable: @Composable BoxScope.() -> Unit
) {
- setContent {
- MaterialTheme {
- Box(modifier = modifier, content = composable)
- }
- }
+ setContent { MaterialTheme { Box(modifier = modifier, content = composable) } }
}
fun ComposeContentTestRule.setContentWithThemeForSizeAssertions(
@@ -94,10 +88,8 @@
MaterialTheme {
Box {
Box(
- Modifier.sizeIn(
- maxWidth = parentMaxWidth,
- maxHeight = parentMaxHeight
- ).testTag("containerForSizeAssertion")
+ Modifier.sizeIn(maxWidth = parentMaxWidth, maxHeight = parentMaxHeight)
+ .testTag("containerForSizeAssertion")
) {
content()
}
@@ -110,10 +102,11 @@
fun ComposeContentTestRule.textStyleOf(text: String): TextStyle {
val textLayoutResults = mutableListOf<TextLayoutResult>()
- onNodeWithText(text, useUnmergedTree = true)
- .performSemanticsAction(SemanticsActions.GetTextLayoutResult) {
- it(textLayoutResults)
- }
+ onNodeWithText(text, useUnmergedTree = true).performSemanticsAction(
+ SemanticsActions.GetTextLayoutResult
+ ) {
+ it(textLayoutResults)
+ }
return textLayoutResults[0].layoutInput.style
}
@@ -129,7 +122,8 @@
fun TestImage(iconLabel: String = "TestIcon", modifier: Modifier = Modifier) {
val testImage = Icons.Outlined.Add
Image(
- testImage, iconLabel,
+ testImage,
+ iconLabel,
modifier = modifier.fillMaxSize().testTag(iconLabel),
contentScale = ContentScale.Fit,
alignment = Alignment.Center
@@ -140,15 +134,15 @@
fun TestIcon(modifier: Modifier = Modifier, iconLabel: String = "TestIcon") {
val testImage = Icons.Outlined.Add
Icon(
- imageVector = testImage, contentDescription = iconLabel,
- modifier = modifier
- .testTag(iconLabel)
+ imageVector = testImage,
+ contentDescription = iconLabel,
+ modifier = modifier.testTag(iconLabel)
)
}
/**
- * assertContainsColor - uses a threshold on an ImageBitmap's color distribution
- * to check that a UI element is predominantly the expected color.
+ * assertContainsColor - uses a threshold on an ImageBitmap's color distribution to check that a UI
+ * element is predominantly the expected color.
*/
fun ImageBitmap.assertContainsColor(expectedColor: Color, minPercent: Float = 50.0f) {
val histogram = histogram()
@@ -164,9 +158,7 @@
}
}
-/**
- * Checks that [expectedColor] is in the percentage [range] of an [ImageBitmap] color histogram
- */
+/** Checks that [expectedColor] is in the percentage [range] of an [ImageBitmap] color histogram */
fun ImageBitmap.assertColorInPercentageRange(
expectedColor: Color,
range: ClosedFloatingPointRange<Float> = 50.0f..100.0f
@@ -186,9 +178,7 @@
}
}
-/**
- * Checks whether [expectedColor] does not exist in current [ImageBitmap]
- */
+/** Checks whether [expectedColor] does not exist in current [ImageBitmap] */
fun ImageBitmap.assertDoesNotContainColor(expectedColor: Color) {
val histogram = histogram()
if (histogram.containsKey(expectedColor)) {
@@ -197,10 +187,9 @@
}
/**
- * printHistogramToLog - utility for writing an ImageBitmap's color distribution to debug log.
- * The histogram can be extracted using adb logcat, for example:
- * adb logcat | grep Histogram
- * This can be useful when debugging a captured image from a compose UI element.
+ * printHistogramToLog - utility for writing an ImageBitmap's color distribution to debug log. The
+ * histogram can be extracted using adb logcat, for example: adb logcat | grep Histogram This can be
+ * useful when debugging a captured image from a compose UI element.
*/
@kotlin.ExperimentalUnsignedTypes
fun ImageBitmap.printHistogramToLog(expectedColor: Color): ImageBitmap {
@@ -226,14 +215,10 @@
content: @Composable () -> Unit
) {
setContentWithTheme {
- CompositionLocalProvider(LocalLayoutDirection provides layoutDirection) {
- content()
- }
+ CompositionLocalProvider(LocalLayoutDirection provides layoutDirection) { content() }
}
- onNodeWithTag(testTag)
- .captureToImage()
- .assertAgainstGolden(screenshotRule, methodName)
+ onNodeWithTag(testTag).captureToImage().assertAgainstGolden(screenshotRule, methodName)
}
/**
@@ -254,11 +239,12 @@
assertion: (DpRect) -> Unit
): SemanticsNodeInteraction {
val node = fetchSemanticsNode("Failed to retrieve bounds of the node.")
- val bounds = with(node.root!!.density) {
- node.unclippedBoundsInRoot.let {
- DpRect(it.left.toDp(), it.top.toDp(), it.right.toDp(), it.bottom.toDp())
+ val bounds =
+ with(node.root!!.density) {
+ node.unclippedBoundsInRoot.let {
+ DpRect(it.left.toDp(), it.top.toDp(), it.right.toDp(), it.bottom.toDp())
+ }
}
- }
assertion.invoke(bounds)
return this
}
@@ -273,9 +259,9 @@
}
/**
- * Returns if this value is equal to the [reference], within a given [tolerance]. If the
- * reference value is [Float.NaN], [Float.POSITIVE_INFINITY] or [Float.NEGATIVE_INFINITY], this
- * only returns true if this value is exactly the same (tolerance is disregarded).
+ * Returns if this value is equal to the [reference], within a given [tolerance]. If the reference
+ * value is [Float.NaN], [Float.POSITIVE_INFINITY] or [Float.NEGATIVE_INFINITY], this only returns
+ * true if this value is exactly the same (tolerance is disregarded).
*/
private fun Dp.isWithinTolerance(reference: Dp, tolerance: Dp): Boolean {
return when {
@@ -296,15 +282,12 @@
* @param expected The expected value to which this one should be equal to.
* @param subject Used in the error message to identify which item this assertion failed on.
* @param tolerance The tolerance within which the values should be treated as equal.
- *
* @throws AssertionError if comparison fails.
*/
private fun Dp.assertIsEqualTo(expected: Dp, subject: String, tolerance: Dp = Dp(.5f)) {
if (!isWithinTolerance(expected, tolerance)) {
// Comparison failed, report the error in DPs
- throw AssertionError(
- "Actual $subject is $this, expected $expected (tolerance: $tolerance)"
- )
+ throw AssertionError("Actual $subject is $this, expected $expected (tolerance: $tolerance)")
}
}
@@ -320,26 +303,21 @@
return histogram
}
[email protected]
-private fun Color.toHexString() =
- this.value.toString(16)
[email protected] private fun Color.toHexString() = this.value.toString(16)
/**
- * writeToDevice - utility for writing an image bitmap to storage on the emulated device.
- * The image can be extract using adb pull, for example:
- * adb pull
- * /storage/emulated/0/Android/data/androidx.wear.compose.test/cache/screenshots/mytest.png
- * /usr/local/username/Desktop/mytest.png
+ * writeToDevice - utility for writing an image bitmap to storage on the emulated device. The image
+ * can be extract using adb pull, for example: adb pull
+ * /storage/emulated/0/Android/data/androidx.wear.compose.test/cache/screenshots/mytest.png
+ * /usr/local/username/Desktop/mytest.png
*/
fun ImageBitmap.writeToDevice(testName: String) {
this.asAndroidBitmap().writeToDevice(testName)
}
private val deviceOutputDirectory
- get() = File(
- InstrumentationRegistry.getInstrumentation().context.externalCacheDir,
- "screenshots"
- )
+ get() =
+ File(InstrumentationRegistry.getInstrumentation().context.externalCacheDir, "screenshots")
private fun Bitmap.writeToDevice(testName: String): File {
return writeToDevice(testName) {
@@ -347,10 +325,7 @@
}
}
-private fun writeToDevice(
- testName: String,
- writeAction: (FileOutputStream) -> Unit
-): File {
+private fun writeToDevice(testName: String, writeAction: (FileOutputStream) -> Unit): File {
if (!deviceOutputDirectory.exists() && !deviceOutputDirectory.mkdir()) {
throw IOException("Could not create folder $deviceOutputDirectory")
}
@@ -358,13 +333,12 @@
val file = File(deviceOutputDirectory, "$testName.png")
Log.d("Screenshot", "File path is ${file.absolutePath}")
try {
- FileOutputStream(file).use {
- writeAction(it)
- }
+ FileOutputStream(file).use { writeAction(it) }
} catch (e: Exception) {
throw IOException(
"Could not write file to storage (path: ${file.absolutePath}). " +
- " Stacktrace: " + e.stackTrace
+ " Stacktrace: " +
+ e.stackTrace
)
}
return file
diff --git a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/MaterialThemeTest.kt b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/MaterialThemeTest.kt
index 4ca03f4..5ab2bc3 100644
--- a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/MaterialThemeTest.kt
+++ b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/MaterialThemeTest.kt
@@ -40,8 +40,7 @@
import org.junit.Test
class MaterialThemeTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
@Test
@@ -56,9 +55,7 @@
)
}
- rule.onNodeWithText("Test")
- .captureToImage()
- .assertContainsColor(expectedBackground, 50.0f)
+ rule.onNodeWithText("Test").captureToImage().assertContainsColor(expectedBackground, 50.0f)
}
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
@@ -76,9 +73,7 @@
}
}
- rule.onNodeWithText("Test")
- .captureToImage()
- .assertContainsColor(Color.Cyan, 50.0f)
+ rule.onNodeWithText("Test").captureToImage().assertContainsColor(Color.Cyan, 50.0f)
}
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
@@ -92,9 +87,7 @@
)
}
- rule.onNodeWithText("Test")
- .captureToImage()
- .assertContainsColor(Color.Yellow, 50.0f)
+ rule.onNodeWithText("Test").captureToImage().assertContainsColor(Color.Yellow, 50.0f)
}
@Test
@@ -114,17 +107,15 @@
@Test
fun overrides_textstyle_when_nested() {
- val override = TextStyle(
- fontFamily = FontFamily.Default,
- fontWeight = FontWeight.Normal,
- fontSize = 16.sp,
- letterSpacing = 0.sp
- )
+ val override =
+ TextStyle(
+ fontFamily = FontFamily.Default,
+ fontWeight = FontWeight.Normal,
+ fontSize = 16.sp,
+ letterSpacing = 0.sp
+ )
rule.setContentWithTheme {
- MaterialTheme(
- typography = MaterialTheme.typography
- .copy(button = override)
- ) {
+ MaterialTheme(typography = MaterialTheme.typography.copy(button = override)) {
Chip(
onClick = {},
label = { Text("Test") },
@@ -150,11 +141,13 @@
verifyBackgroundColorIsDynamic(
initial = { MaterialTheme.colors.primaryVariant },
selectChipColors = {
- ChipDefaults
- .primaryChipColors(backgroundColor = MaterialTheme.colors.primaryVariant)
+ ChipDefaults.primaryChipColors(
+ backgroundColor = MaterialTheme.colors.primaryVariant
+ )
},
- updateThemeColors =
- { colors, primaryVariant -> colors.copy(primaryVariant = primaryVariant) }
+ updateThemeColors = { colors, primaryVariant ->
+ colors.copy(primaryVariant = primaryVariant)
+ }
)
@RequiresApi(Build.VERSION_CODES.O)
@@ -163,8 +156,7 @@
verifyBackgroundColorIsDynamic(
initial = { MaterialTheme.colors.secondary },
selectChipColors = {
- ChipDefaults
- .secondaryChipColors(backgroundColor = MaterialTheme.colors.secondary)
+ ChipDefaults.secondaryChipColors(backgroundColor = MaterialTheme.colors.secondary)
},
updateThemeColors = { colors, secondary -> colors.copy(secondary = secondary) }
)
@@ -175,11 +167,13 @@
verifyBackgroundColorIsDynamic(
initial = { MaterialTheme.colors.secondaryVariant },
selectChipColors = {
- ChipDefaults
- .secondaryChipColors(backgroundColor = MaterialTheme.colors.secondaryVariant)
+ ChipDefaults.secondaryChipColors(
+ backgroundColor = MaterialTheme.colors.secondaryVariant
+ )
},
- updateThemeColors =
- { colors, secondaryVariant -> colors.copy(secondaryVariant = secondaryVariant) }
+ updateThemeColors = { colors, secondaryVariant ->
+ colors.copy(secondaryVariant = secondaryVariant)
+ }
)
@RequiresApi(Build.VERSION_CODES.O)
@@ -188,8 +182,7 @@
verifyBackgroundColorIsDynamic(
initial = { MaterialTheme.colors.error },
selectChipColors = {
- ChipDefaults
- .secondaryChipColors(backgroundColor = MaterialTheme.colors.error)
+ ChipDefaults.secondaryChipColors(backgroundColor = MaterialTheme.colors.error)
},
updateThemeColors = { colors, error -> colors.copy(error = error) }
)
@@ -215,21 +208,16 @@
onClick = {
rememberedColors.value = colors.copy(primary = overrideBackground)
},
- label = { },
+ label = {},
modifier = Modifier.testTag("button")
)
}
}
}
- rule.onNodeWithText("Test")
- .captureToImage()
- .assertContainsColor(initialBackground, 60.0f)
- rule.onNodeWithTag("button")
- .performClick()
- rule.onNodeWithText("Test")
- .captureToImage()
- .assertContainsColor(overrideBackground, 60.0f)
+ rule.onNodeWithText("Test").captureToImage().assertContainsColor(initialBackground, 60.0f)
+ rule.onNodeWithTag("button").performClick()
+ rule.onNodeWithText("Test").captureToImage().assertContainsColor(overrideBackground, 60.0f)
}
@Test
@@ -312,12 +300,13 @@
@Test
fun sets_typography_dynamically() {
var initialStyle: TextStyle? = null
- val overrideTextStyle = TextStyle(
- fontFamily = FontFamily.Default,
- fontWeight = FontWeight.Normal,
- fontSize = 8.sp,
- letterSpacing = 0.sp
- )
+ val overrideTextStyle =
+ TextStyle(
+ fontFamily = FontFamily.Default,
+ fontWeight = FontWeight.Normal,
+ fontSize = 8.sp,
+ letterSpacing = 0.sp
+ )
rule.setContentWithTheme {
val typography = Typography()
@@ -332,10 +321,9 @@
)
Chip(
onClick = {
- rememberedTypography.value =
- typography.copy(button = overrideTextStyle)
+ rememberedTypography.value = typography.copy(button = overrideTextStyle)
},
- label = { },
+ label = {},
modifier = Modifier.testTag("button")
)
}
@@ -370,21 +358,16 @@
)
Chip(
onClick = { dynamicColor.value = overrideColor },
- label = { },
+ label = {},
modifier = Modifier.testTag("button")
)
}
}
}
- rule.onNodeWithText("Test")
- .captureToImage()
- .assertContainsColor(initialColor, 60.0f)
- rule.onNodeWithTag("button")
- .performClick()
- rule.onNodeWithText("Test")
- .captureToImage()
- .assertContainsColor(overrideColor, 60.0f)
+ rule.onNodeWithText("Test").captureToImage().assertContainsColor(initialColor, 60.0f)
+ rule.onNodeWithTag("button").performClick()
+ rule.onNodeWithText("Test").captureToImage().assertContainsColor(overrideColor, 60.0f)
}
private fun verifyContentColorIsDynamic(
@@ -417,8 +400,7 @@
}
assertEquals(initialColor, rule.textStyleOf("Test").color)
- rule.onNodeWithTag("button")
- .performClick()
+ rule.onNodeWithTag("button").performClick()
assertEquals(overrideColor, rule.textStyleOf("Test").color)
}
@@ -427,21 +409,22 @@
updateTextStyle: (Typography, TextStyle) -> Typography
) {
var initialStyle = TextStyle()
- val overrideTextStyle = TextStyle(
- fontFamily = FontFamily.Default,
- fontWeight = FontWeight.Normal,
- fontSize = 8.sp,
- letterSpacing = 0.sp
- )
+ val overrideTextStyle =
+ TextStyle(
+ fontFamily = FontFamily.Default,
+ fontWeight = FontWeight.Normal,
+ fontSize = 8.sp,
+ letterSpacing = 0.sp
+ )
val typography = Typography()
rule.setContentWithTheme {
initialStyle = selectStyle(typography)
val dynamicStyle = remember { mutableStateOf(initialStyle) }
- val rememberedTypography =
- updateTextStyle(typography, dynamicStyle.value)
+ val rememberedTypography = updateTextStyle(typography, dynamicStyle.value)
MaterialTheme(
- // WearChip always uses 'button' style for text, so assign the style under test to button.
+ // WearChip always uses 'button' style for text, so assign the style under test to
+ // button.
typography = rememberedTypography.copy(button = selectStyle(rememberedTypography))
) {
Column {
@@ -451,7 +434,7 @@
)
Chip(
onClick = { dynamicStyle.value = overrideTextStyle },
- label = { },
+ label = {},
modifier = Modifier.testTag("button")
)
}
diff --git a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/PickerGroupScreenshotTest.kt b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/PickerGroupScreenshotTest.kt
index 7a81b06..498b3ba 100644
--- a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/PickerGroupScreenshotTest.kt
+++ b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/PickerGroupScreenshotTest.kt
@@ -49,55 +49,38 @@
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
class PickerGroupScreenshotTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
- @get:Rule
- val screenshotRule = AndroidXScreenshotTestRule(SCREENSHOT_GOLDEN_PATH)
+ @get:Rule val screenshotRule = AndroidXScreenshotTestRule(SCREENSHOT_GOLDEN_PATH)
- @get:Rule
- val testName = TestName()
+ @get:Rule val testName = TestName()
private val screenHeight = 150.dp
- @Test
- fun pickerGroup() = verifyScreenshot {
- samplePickerGroup()
- }
+ @Test fun pickerGroup() = verifyScreenshot { samplePickerGroup() }
@Test
- fun pickerGroup_withAutoCentering() = verifyScreenshot {
- samplePickerGroup(autoCenter = true)
- }
+ fun pickerGroup_withAutoCentering() = verifyScreenshot { samplePickerGroup(autoCenter = true) }
@Test
fun pickerGroup_withManyColumns_withAutoCentering() = verifyScreenshot {
- samplePickerGroup(
- pickerCount = 5,
- autoCenter = true
- )
+ samplePickerGroup(pickerCount = 5, autoCenter = true)
}
@Test
fun pickerGroup_withRtlAndManyColumns_withAutoCentering() =
verifyScreenshot(layoutDirection = LayoutDirection.Rtl) {
- samplePickerGroup(
- pickerCount = 5,
- autoCenter = true
- )
- }
+ samplePickerGroup(pickerCount = 5, autoCenter = true)
+ }
@Composable
- private fun samplePickerGroup(
- pickerCount: Int = 2,
- autoCenter: Boolean = false
- ) {
+ private fun samplePickerGroup(pickerCount: Int = 2, autoCenter: Boolean = false) {
Box(
- modifier = Modifier
- .height(screenHeight)
- .fillMaxWidth()
- .background(MaterialTheme.colors.background)
- .testTag(TEST_TAG),
+ modifier =
+ Modifier.height(screenHeight)
+ .fillMaxWidth()
+ .background(MaterialTheme.colors.background)
+ .testTag(TEST_TAG),
contentAlignment = Alignment.Center
) {
PickerGroup(
@@ -117,21 +100,21 @@
content: @Composable () -> Unit
) {
rule.setContentWithTheme {
- CompositionLocalProvider(LocalLayoutDirection provides layoutDirection) {
- content()
- }
+ CompositionLocalProvider(LocalLayoutDirection provides layoutDirection) { content() }
}
rule.waitForIdle()
- rule.onNodeWithTag(TEST_TAG)
+ rule
+ .onNodeWithTag(TEST_TAG)
.captureToImage()
.assertAgainstGolden(screenshotRule, testName.methodName)
}
- private fun getPickerColumns(count: Int): Array<PickerGroupItem> = Array(count) {
- PickerGroupItem(
- pickerState = PickerState(10),
- option = { optionIndex, _ -> Text("%02d".format(optionIndex)) }
- )
- }
+ private fun getPickerColumns(count: Int): Array<PickerGroupItem> =
+ Array(count) {
+ PickerGroupItem(
+ pickerState = PickerState(10),
+ option = { optionIndex, _ -> Text("%02d".format(optionIndex)) }
+ )
+ }
}
diff --git a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/PickerGroupTest.kt b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/PickerGroupTest.kt
index e7aefd6..bbea481f 100644
--- a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/PickerGroupTest.kt
+++ b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/PickerGroupTest.kt
@@ -39,8 +39,7 @@
@LargeTest
@RunWith(AndroidJUnit4::class)
class PickerGroupTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
@Test
fun supports_test_tag() {
@@ -62,9 +61,8 @@
rule.setContentWithTheme {
PickerGroup(
pickers = getPickerColumns(2),
- pickerGroupState = rememberPickerGroupState(initiallySelectedColumn).also {
- pickerGroupState = it
- }
+ pickerGroupState =
+ rememberPickerGroupState(initiallySelectedColumn).also { pickerGroupState = it }
)
}
@@ -87,14 +85,13 @@
rule.onNodeWithText("2").assertExists()
}
+
@Test
fun pickers_are_added_to_picker_group() {
val pickerColumnZero = getPickerColumnWithTag(TEST_TAG_1)
val pickerColumnOne = getPickerColumnWithTag(TEST_TAG_2)
- rule.setContentWithTheme {
- PickerGroup(pickerColumnZero, pickerColumnOne)
- }
+ rule.setContentWithTheme { PickerGroup(pickerColumnZero, pickerColumnOne) }
rule.onNodeWithTag(TEST_TAG_1).assertExists()
rule.onNodeWithTag(TEST_TAG_2).assertExists()
@@ -124,16 +121,14 @@
assertThat(pickerGroupState.selectedIndex).isEqualTo(1)
}
- private fun getPickerColumns(count: Int): Array<PickerGroupItem> = Array(count) {
- PickerGroupItem(pickerState = PickerState(10)) { _: Int, _: Boolean ->
- Box(modifier = Modifier.size(20.dp))
+ private fun getPickerColumns(count: Int): Array<PickerGroupItem> =
+ Array(count) {
+ PickerGroupItem(pickerState = PickerState(10)) { _: Int, _: Boolean ->
+ Box(modifier = Modifier.size(20.dp))
+ }
}
- }
- private fun getPickerColumnWithTag(
- tag: String,
- onSelected: () -> Unit = {}
- ): PickerGroupItem {
+ private fun getPickerColumnWithTag(tag: String, onSelected: () -> Unit = {}): PickerGroupItem {
return PickerGroupItem(
pickerState = PickerState(10),
modifier = Modifier.testTag(tag),
diff --git a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/PickerScreenshotTest.kt b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/PickerScreenshotTest.kt
index c05dbae..72730ff 100644
--- a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/PickerScreenshotTest.kt
+++ b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/PickerScreenshotTest.kt
@@ -57,41 +57,24 @@
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
class PickerScreenshotTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
- @get:Rule
- val screenshotRule = AndroidXScreenshotTestRule(SCREENSHOT_GOLDEN_PATH)
+ @get:Rule val screenshotRule = AndroidXScreenshotTestRule(SCREENSHOT_GOLDEN_PATH)
- @get:Rule
- val testName = TestName()
+ @get:Rule val testName = TestName()
private val screenHeight = 150.dp
- @Test
- fun picker() = verifyScreenshot {
- samplePicker()
- }
+ @Test fun picker() = verifyScreenshot { samplePicker() }
+
+ @Test fun picker_without_gradient() = verifyScreenshot { samplePicker(gradientRatio = 0f) }
+
+ @Test fun picker_negative_separation() = verifyScreenshot { samplePicker(separation = -8.dp) }
+
+ @Test fun dual_picker() = verifyScreenshot { dualPicker() }
@Test
- fun picker_without_gradient() = verifyScreenshot {
- samplePicker(gradientRatio = 0f)
- }
-
- @Test
- fun picker_negative_separation() = verifyScreenshot {
- samplePicker(separation = -8.dp)
- }
-
- @Test
- fun dual_picker() = verifyScreenshot {
- dualPicker()
- }
-
- @Test
- fun dual_picker_with_readonlylabel() = verifyScreenshot {
- dualPicker(readOnlyLabel = "Min")
- }
+ fun dual_picker_with_readonlylabel() = verifyScreenshot { dualPicker(readOnlyLabel = "Min") }
@Composable
private fun samplePicker(
@@ -99,8 +82,10 @@
separation: Dp = 0.dp,
) {
Box(
- modifier = Modifier
- .height(screenHeight).fillMaxWidth().background(MaterialTheme.colors.background),
+ modifier =
+ Modifier.height(screenHeight)
+ .fillMaxWidth()
+ .background(MaterialTheme.colors.background),
contentAlignment = Alignment.Center
) {
val items = listOf("One", "Two", "Three", "Four", "Five")
@@ -123,29 +108,28 @@
val textStyle = MaterialTheme.typography.display1
@Composable
- fun Option(color: Color, text: String) = Box(modifier = Modifier.fillMaxSize()) {
- Text(
- text = text, style = textStyle, color = color,
- modifier = Modifier
- .align(Alignment.Center)
- .wrapContentSize()
- )
- }
+ fun Option(color: Color, text: String) =
+ Box(modifier = Modifier.fillMaxSize()) {
+ Text(
+ text = text,
+ style = textStyle,
+ color = color,
+ modifier = Modifier.align(Alignment.Center).wrapContentSize()
+ )
+ }
Row(
- modifier = Modifier
- .height(screenHeight)
- .fillMaxWidth()
- .background(MaterialTheme.colors.background)
- .testTag(TEST_TAG),
+ modifier =
+ Modifier.height(screenHeight)
+ .fillMaxWidth()
+ .background(MaterialTheme.colors.background)
+ .testTag(TEST_TAG),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Center,
) {
Picker(
- state = rememberPickerState(
- initialNumberOfOptions = 100,
- initiallySelectedOption = 11
- ),
+ state =
+ rememberPickerState(initialNumberOfOptions = 100, initiallySelectedOption = 11),
contentDescription = "",
readOnly = false,
modifier = Modifier.size(64.dp, 100.dp),
@@ -155,10 +139,11 @@
Text(text = ":", style = textStyle, color = MaterialTheme.colors.onBackground)
Spacer(Modifier.width(8.dp))
Picker(
- state = rememberPickerState(
- initialNumberOfOptions = 100,
- initiallySelectedOption = 100
- ),
+ state =
+ rememberPickerState(
+ initialNumberOfOptions = 100,
+ initiallySelectedOption = 100
+ ),
contentDescription = "",
readOnly = true,
readOnlyLabel = { if (readOnlyLabel != null) LabelText(readOnlyLabel) },
@@ -183,12 +168,11 @@
content: @Composable () -> Unit
) {
rule.setContentWithTheme {
- CompositionLocalProvider(LocalLayoutDirection provides layoutDirection) {
- content()
- }
+ CompositionLocalProvider(LocalLayoutDirection provides layoutDirection) { content() }
}
- rule.onNodeWithTag(TEST_TAG)
+ rule
+ .onNodeWithTag(TEST_TAG)
.captureToImage()
.assertAgainstGolden(screenshotRule, testName.methodName)
}
diff --git a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/PickerTest.kt b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/PickerTest.kt
index 74c63e1..863ebde 100644
--- a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/PickerTest.kt
+++ b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/PickerTest.kt
@@ -57,8 +57,7 @@
@LargeTest
@RunWith(AndroidJUnit4::class)
class PickerTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
private var itemSizePx: Int = 20
private var itemSizeDp: Dp = Dp.Infinity
@@ -96,8 +95,7 @@
Picker(
state = rememberPickerState(5).also { state = it },
contentDescription = CONTENT_DESCRIPTION,
- modifier = Modifier.testTag(TEST_TAG)
- .requiredSize(itemSizeDp * 3),
+ modifier = Modifier.testTag(TEST_TAG).requiredSize(itemSizeDp * 3),
) {
Box(Modifier.requiredSize(itemSizeDp))
}
@@ -115,8 +113,11 @@
lateinit var state: PickerState
rule.setContent {
- state = rememberPickerState(
- initialNumberOfOptions = 10, initiallySelectedOption = startValue)
+ state =
+ rememberPickerState(
+ initialNumberOfOptions = 10,
+ initiallySelectedOption = startValue
+ )
}
assertThat(state.selectedOption).isEqualTo(startValue)
@@ -130,8 +131,7 @@
Picker(
state = rememberPickerState(5).also { state = it },
contentDescription = CONTENT_DESCRIPTION,
- modifier = Modifier.testTag(TEST_TAG)
- .requiredSize(itemSizeDp * 3),
+ modifier = Modifier.testTag(TEST_TAG).requiredSize(itemSizeDp * 3),
) {
Box(Modifier.requiredSize(itemSizeDp))
}
@@ -151,8 +151,8 @@
assertThat(state.selectedOption).isEqualTo(1)
}
- @Test
- fun can_scroll_picker_down_on_start() {
+ @Test
+ fun can_scroll_picker_down_on_start() {
val numberOfOptions = 5
lateinit var state: PickerState
rule.setContent {
@@ -160,8 +160,7 @@
Picker(
state = rememberPickerState(numberOfOptions).also { state = it },
contentDescription = CONTENT_DESCRIPTION,
- modifier = Modifier.testTag(TEST_TAG)
- .requiredSize(itemSizeDp * 3),
+ modifier = Modifier.testTag(TEST_TAG).requiredSize(itemSizeDp * 3),
) {
Box(Modifier.requiredSize(itemSizeDp))
}
@@ -181,18 +180,14 @@
assertThat(state.selectedOption).isEqualTo(numberOfOptions - 1)
}
- @Test
- fun uses_positive_separation_correctly() =
- scroll_with_separation(1)
+ @Test fun uses_positive_separation_correctly() = scroll_with_separation(1)
- @Test
- fun uses_negative_separation_correctly() =
- scroll_with_separation(-1)
+ @Test fun uses_negative_separation_correctly() = scroll_with_separation(-1)
/**
* Test that picker is properly scrolled with scrollOffset, which equals to a half of the
- * (itemSizePx + separationPx) and minus 1 pixel
- * for making it definitely less than a half of an item
+ * (itemSizePx + separationPx) and minus 1 pixel for making it definitely less than a half of an
+ * item
*/
@Test
fun scroll_with_positive_separation_and_offset() =
@@ -200,26 +195,23 @@
/**
* Test that picker is properly scrolled with scrollOffset, which equals to a half of the
- * (itemSizePx - separationPx) and minus 1 pixel
- * for making it definitely less than a half of an item
+ * (itemSizePx - separationPx) and minus 1 pixel for making it definitely less than a half of an
+ * item
*/
@Test
fun scroll_with_negative_separation_and_offset() =
scroll_with_separation(-1, scrollOffset = (itemSizePx - separationPx) / 2 - 1)
- private fun scroll_with_separation(
- separationSign: Int,
- scrollOffset: Int = 0
- ) {
+ private fun scroll_with_separation(separationSign: Int, scrollOffset: Int = 0) {
lateinit var state: PickerState
rule.setContent {
WithTouchSlop(0f) {
Picker(
state = rememberPickerState(20).also { state = it },
contentDescription = CONTENT_DESCRIPTION,
- modifier = Modifier
- .testTag(TEST_TAG)
- .requiredSize(itemSizeDp * 11 + separationDp * 10 * separationSign),
+ modifier =
+ Modifier.testTag(TEST_TAG)
+ .requiredSize(itemSizeDp * 11 + separationDp * 10 * separationSign),
separation = separationDp * separationSign
) {
Box(Modifier.requiredSize(itemSizeDp))
@@ -235,10 +227,14 @@
// (which was added to prevent jitter around the start of the gradient).
swipeWithVelocity(
start = Offset(centerX, bottom - 5),
- end = Offset(
- centerX, bottom - 5 - scrollOffset -
- (itemSizePx + separationPx * separationSign) * itemsToScroll
- ),
+ end =
+ Offset(
+ centerX,
+ bottom -
+ 5 -
+ scrollOffset -
+ (itemSizePx + separationPx * separationSign) * itemsToScroll
+ ),
endVelocity = NOT_A_FLING_SPEED
)
}
@@ -330,10 +326,11 @@
lateinit var scope: CoroutineScope
rule.setContent {
scope = rememberCoroutineScope()
- state = rememberPickerState(
- initialNumberOfOptions = totalOptions,
- initiallySelectedOption = initialOption
- )
+ state =
+ rememberPickerState(
+ initialNumberOfOptions = totalOptions,
+ initiallySelectedOption = initialOption
+ )
SimplePicker(state)
}
val initialItemIndex = state.scalingLazyListState.centerItemIndex
@@ -344,13 +341,9 @@
// picker to its final target.
rule.runOnIdle {
scope.launch {
- async {
- state.animateScrollToOption(firstTarget)
- }
+ async { state.animateScrollToOption(firstTarget) }
delay(100) // a short delay so that the first async will be triggered first
- async {
- state.animateScrollToOption(secondTarget)
- }
+ async { state.animateScrollToOption(secondTarget) }
}
}
rule.waitForIdle()
@@ -359,26 +352,17 @@
.isEqualTo(initialItemIndex + targetDelta)
}
- @Test
- fun scrolls_with_negative_separation() = scrolls_to_index_correctly(-1, 3)
+ @Test fun scrolls_with_negative_separation() = scrolls_to_index_correctly(-1, 3)
- @Test
- fun scrolls_with_positive_separation() = scrolls_to_index_correctly(1, 7)
+ @Test fun scrolls_with_positive_separation() = scrolls_to_index_correctly(1, 7)
- @Test
- fun scrolls_with_no_separation() = scrolls_to_index_correctly(0, 13)
+ @Test fun scrolls_with_no_separation() = scrolls_to_index_correctly(0, 13)
private fun scrolls_to_index_correctly(separationSign: Int, targetIndex: Int) {
val pickerDriver = PickerDriver(separationSign = separationSign)
- rule.setContent {
- pickerDriver.DrivedPicker()
- }
+ rule.setContent { pickerDriver.DrivedPicker() }
- rule.runOnIdle {
- runBlocking {
- pickerDriver.state.scrollToOption(targetIndex)
- }
- }
+ rule.runOnIdle { runBlocking { pickerDriver.state.scrollToOption(targetIndex) } }
rule.waitForIdle()
assertThat(pickerDriver.state.selectedOption).isEqualTo(targetIndex)
@@ -392,10 +376,12 @@
rule.setContent {
WithTouchSlop(0f) {
Picker(
- state = rememberPickerState(
- initialNumberOfOptions = 28,
- initiallySelectedOption = initialOption
- ).also { state = it },
+ state =
+ rememberPickerState(
+ initialNumberOfOptions = 28,
+ initiallySelectedOption = initialOption
+ )
+ .also { state = it },
contentDescription = CONTENT_DESCRIPTION,
) {
Box(Modifier.requiredSize(itemSizeDp))
@@ -404,11 +390,7 @@
}
val initialItemIndex = state.scalingLazyListState.centerItemIndex
- rule.runOnIdle {
- runBlocking {
- state.numberOfOptions = 31
- }
- }
+ rule.runOnIdle { runBlocking { state.numberOfOptions = 31 } }
rule.waitForIdle()
@@ -424,10 +406,12 @@
rule.setContent {
WithTouchSlop(0f) {
Picker(
- state = rememberPickerState(
- initialNumberOfOptions = 25,
- initiallySelectedOption = initialOption
- ).also { state = it },
+ state =
+ rememberPickerState(
+ initialNumberOfOptions = 25,
+ initiallySelectedOption = initialOption
+ )
+ .also { state = it },
contentDescription = CONTENT_DESCRIPTION,
) {
Box(Modifier.requiredSize(itemSizeDp))
@@ -453,14 +437,14 @@
val targetIndex = 5
rule.setContent {
state = rememberPickerState(20)
- LaunchedEffect(state) {
- state.scrollToOption(targetIndex)
- }
+ LaunchedEffect(state) { state.scrollToOption(targetIndex) }
Picker(
state = state,
contentDescription = CONTENT_DESCRIPTION,
- ) { Box(Modifier.requiredSize(itemSizeDp)) }
+ ) {
+ Box(Modifier.requiredSize(itemSizeDp))
+ }
}
rule.waitForIdle()
@@ -477,7 +461,9 @@
Picker(
state = state,
contentDescription = CONTENT_DESCRIPTION,
- ) { Box(Modifier.requiredSize(itemSizeDp)) }
+ ) {
+ Box(Modifier.requiredSize(itemSizeDp))
+ }
}
rule.waitForIdle()
@@ -504,13 +490,14 @@
}
@Test
- fun small_scroll_snaps_with_separation() = scroll_snaps(separationSign = 1) {
- swipeWithVelocity(
- start = Offset(centerX, top),
- end = Offset(centerX, top + itemSizePx / 2),
- endVelocity = NOT_A_FLING_SPEED
- )
- }
+ fun small_scroll_snaps_with_separation() =
+ scroll_snaps(separationSign = 1) {
+ swipeWithVelocity(
+ start = Offset(centerX, top),
+ end = Offset(centerX, top + itemSizePx / 2),
+ endVelocity = NOT_A_FLING_SPEED
+ )
+ }
@Test
fun fast_scroll_snaps() = scroll_snaps {
@@ -522,13 +509,14 @@
}
@Test
- fun fast_scroll_with_separation_snaps() = scroll_snaps(separationSign = -1) {
- swipeWithVelocity(
- start = Offset(centerX, bottom),
- end = Offset(centerX, bottom - 300),
- endVelocity = DO_FLING_SPEED
- )
- }
+ fun fast_scroll_with_separation_snaps() =
+ scroll_snaps(separationSign = -1) {
+ swipeWithVelocity(
+ start = Offset(centerX, bottom),
+ end = Offset(centerX, bottom - 300),
+ endVelocity = DO_FLING_SPEED
+ )
+ }
@Test
fun displays_label_when_read_only() {
@@ -541,8 +529,7 @@
readOnly = true,
readOnlyLabel = { Text(text = labelText) },
contentDescription = CONTENT_DESCRIPTION,
- modifier = Modifier.testTag(TEST_TAG)
- .requiredSize(itemSizeDp * 3)
+ modifier = Modifier.testTag(TEST_TAG).requiredSize(itemSizeDp * 3)
) {
Box(Modifier.requiredSize(itemSizeDp))
}
@@ -564,8 +551,7 @@
readOnly = false,
readOnlyLabel = { Text(text = labelText) },
contentDescription = CONTENT_DESCRIPTION,
- modifier = Modifier.testTag(TEST_TAG)
- .requiredSize(itemSizeDp * 3)
+ modifier = Modifier.testTag(TEST_TAG).requiredSize(itemSizeDp * 3)
) {
Box(Modifier.requiredSize(itemSizeDp))
}
@@ -586,19 +572,19 @@
rule.setContent {
WithTouchSlop(0f) {
Picker(
- state = rememberPickerState(
- initialNumberOfOptions = 5,
- initiallySelectedOption = initialOption)
- .also { state = it },
+ state =
+ rememberPickerState(
+ initialNumberOfOptions = 5,
+ initiallySelectedOption = initialOption
+ )
+ .also { state = it },
readOnly = readOnly.value,
contentDescription = CONTENT_DESCRIPTION,
modifier = Modifier.testTag(TEST_TAG).requiredSize(itemSizeDp * 3),
) {
Box(Modifier.requiredSize(itemSizeDp))
}
- LaunchedEffect(state) {
- state.scrollToOption(selectedOption)
- }
+ LaunchedEffect(state) { state.scrollToOption(selectedOption) }
}
}
readOnly.value = true
@@ -615,10 +601,12 @@
rule.setContent {
WithTouchSlop(0f) {
Picker(
- state = rememberPickerState(
- initialNumberOfOptions = 5,
- initiallySelectedOption = initialOption)
- .also { state = it },
+ state =
+ rememberPickerState(
+ initialNumberOfOptions = 5,
+ initiallySelectedOption = initialOption
+ )
+ .also { state = it },
readOnly = true,
contentDescription = CONTENT_DESCRIPTION,
modifier = Modifier.testTag(TEST_TAG).requiredSize(itemSizeDp * 3),
@@ -682,10 +670,11 @@
lateinit var selectedOption: MutableState<Int>
rule.setContent {
selectedOption = remember { mutableStateOf(1) }
- val pickerState = rememberPickerState(
- initialNumberOfOptions = numberOfOptions,
- initiallySelectedOption = selectedOption.value
- )
+ val pickerState =
+ rememberPickerState(
+ initialNumberOfOptions = numberOfOptions,
+ initiallySelectedOption = selectedOption.value
+ )
Text(text = "${pickerState.selectedOption}")
}
@@ -707,21 +696,16 @@
lateinit var scope: CoroutineScope
rule.setContent {
scope = rememberCoroutineScope()
- state = rememberPickerState(
- initialNumberOfOptions = totalOptions,
- initiallySelectedOption = initialOption
- )
+ state =
+ rememberPickerState(
+ initialNumberOfOptions = totalOptions,
+ initiallySelectedOption = initialOption
+ )
SimplePicker(state)
}
val initialItemIndex = state.scalingLazyListState.centerItemIndex
- rule.runOnIdle {
- scope.launch {
- async {
- state.animateScrollToOption(targetOption)
- }
- }
- }
+ rule.runOnIdle { scope.launch { async { state.animateScrollToOption(targetOption) } } }
rule.waitForIdle()
assertThat(state.selectedOption).isEqualTo(targetOption)
assertThat(state.scalingLazyListState.centerItemIndex)
@@ -745,9 +729,7 @@
touchInput: (TouchInjectionScope).() -> Unit,
) {
val pickerDriver = PickerDriver(separationSign)
- rule.setContent {
- pickerDriver.DrivedPicker()
- }
+ rule.setContent { pickerDriver.DrivedPicker() }
rule.waitForIdle()
rule.onNodeWithTag(TEST_TAG).performTouchInput { touchInput() }
@@ -767,20 +749,22 @@
@Composable
fun DrivedPicker() {
- val pickerHeightDp = itemSizeDp * itemsToShow +
- separationDp * (itemsToShow - 1) * separationSign
+ val pickerHeightDp =
+ itemSizeDp * itemsToShow + separationDp * (itemsToShow - 1) * separationSign
pickerHeightPx = with(LocalDensity.current) { pickerHeightDp.toPx() }
WithTouchSlop(0f) {
Picker(
state = rememberPickerState(numberOfItems).also { state = it },
- modifier = Modifier.testTag(TEST_TAG).requiredSize(pickerHeightDp)
- .onGloballyPositioned { pickerLayoutCoordinates = it },
+ modifier =
+ Modifier.testTag(TEST_TAG)
+ .requiredSize(pickerHeightDp)
+ .onGloballyPositioned { pickerLayoutCoordinates = it },
separation = separationDp * separationSign,
readOnly = readOnly.value,
contentDescription = CONTENT_DESCRIPTION,
) { optionIndex ->
- Box(Modifier.requiredSize(itemSizeDp)
- .onGloballyPositioned {
+ Box(
+ Modifier.requiredSize(itemSizeDp).onGloballyPositioned {
// Save the layout coordinates if we are at the center
if (optionIndex == selectedOption) {
centerItemLayoutCoordinates = it
@@ -793,8 +777,10 @@
fun verifyCenterItemIsCentered() {
// Ensure that the option that ended up in the middle after the fling/scroll is centered
- assertThat(centerItemLayoutCoordinates.positionInWindow().y -
- pickerLayoutCoordinates.positionInWindow().y)
+ assertThat(
+ centerItemLayoutCoordinates.positionInWindow().y -
+ pickerLayoutCoordinates.positionInWindow().y
+ )
.isWithin(0.1f)
.of(pickerHeightPx / 2f - itemSizePx / 2f)
}
diff --git a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/PlaceholderTest.kt b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/PlaceholderTest.kt
index 55f9f33..bca637e 100644
--- a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/PlaceholderTest.kt
+++ b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/PlaceholderTest.kt
@@ -40,8 +40,7 @@
import org.junit.Test
class PlaceholderTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
@RequiresApi(Build.VERSION_CODES.O)
@OptIn(ExperimentalWearMaterialApi::class)
@@ -51,9 +50,7 @@
lateinit var placeholderState: PlaceholderState
rule.setContentWithTheme {
contentReady = remember { mutableStateOf(true) }
- placeholderState = rememberPlaceholderState {
- contentReady.value
- }
+ placeholderState = rememberPlaceholderState { contentReady.value }
}
// For testing we need to manually manage the frame clock for the placeholder animation
@@ -74,9 +71,7 @@
lateinit var placeholderState: PlaceholderState
rule.setContentWithTheme {
contentReady = remember { mutableStateOf(false) }
- placeholderState = rememberPlaceholderState {
- contentReady.value
- }
+ placeholderState = rememberPlaceholderState { contentReady.value }
}
// For testing we need to manually manage the frame clock for the placeholder animation
@@ -91,10 +86,7 @@
// Change contentReady and confirm that state is now WipeOff
contentReady.value = true
- placeholderState.advanceFrameMillisAndCheckState(
- 1L,
- PlaceholderStage.WipeOff
- )
+ placeholderState.advanceFrameMillisAndCheckState(1L, PlaceholderStage.WipeOff)
// Advance the clock by one cycle and check we have moved to ShowContent
placeholderState.advanceFrameMillisAndCheckState(
@@ -111,9 +103,7 @@
lateinit var placeholderState: PlaceholderState
rule.setContentWithTheme {
contentReady = remember { mutableStateOf(true) }
- placeholderState = rememberPlaceholderState {
- contentReady.value
- }
+ placeholderState = rememberPlaceholderState { contentReady.value }
Chip(
modifier = Modifier.fillMaxWidth(),
content = {},
@@ -162,25 +152,24 @@
lateinit var placeholderState: PlaceholderState
rule.setContentWithTheme {
contentReady = remember { mutableStateOf(false) }
- placeholderState = rememberPlaceholderState {
- contentReady.value
- }
+ placeholderState = rememberPlaceholderState { contentReady.value }
expectedPlaceholderColor =
placeholderColor
- ?: MaterialTheme.colors.onSurface.copy(alpha = 0.1f)
+ ?: MaterialTheme.colors.onSurface
+ .copy(alpha = 0.1f)
.compositeOver(MaterialTheme.colors.surface)
expectedBackgroundColor = MaterialTheme.colors.primary
Chip(
- modifier = Modifier
- .testTag("test-item")
- .then(
- if (placeholderColor != null)
- Modifier.placeholder(
- placeholderState = placeholderState,
- color = placeholderColor
- )
- else Modifier.placeholder(placeholderState = placeholderState)
- ),
+ modifier =
+ Modifier.testTag("test-item")
+ .then(
+ if (placeholderColor != null)
+ Modifier.placeholder(
+ placeholderState = placeholderState,
+ color = placeholderColor
+ )
+ else Modifier.placeholder(placeholderState = placeholderState)
+ ),
content = {},
onClick = {},
colors = ChipDefaults.primaryChipColors(),
@@ -191,18 +180,14 @@
// For testing we need to manually manage the frame clock for the placeholder animation
placeholderState.initializeTestFrameMillis()
- rule.onNodeWithTag("test-item")
+ rule
+ .onNodeWithTag("test-item")
.captureToImage()
- .assertContainsColor(
- expectedPlaceholderColor
- )
+ .assertContainsColor(expectedPlaceholderColor)
// Change contentReady and confirm that state is now WipeOff
contentReady.value = true
- placeholderState.advanceFrameMillisAndCheckState(
- 1L,
- PlaceholderStage.WipeOff
- )
+ placeholderState.advanceFrameMillisAndCheckState(1L, PlaceholderStage.WipeOff)
// Advance the clock by one cycle and check we have moved to ShowContent
placeholderState.advanceFrameMillisAndCheckState(
@@ -210,11 +195,10 @@
PlaceholderStage.ShowContent
)
- rule.onNodeWithTag("test-item")
+ rule
+ .onNodeWithTag("test-item")
.captureToImage()
- .assertContainsColor(
- expectedBackgroundColor
- )
+ .assertContainsColor(expectedBackgroundColor)
}
@RequiresApi(Build.VERSION_CODES.O)
@@ -226,16 +210,14 @@
lateinit var placeholderState: PlaceholderState
rule.setContentWithTheme {
contentReady = remember { mutableStateOf(false) }
- placeholderState = rememberPlaceholderState {
- contentReady.value
- }
+ placeholderState = rememberPlaceholderState { contentReady.value }
expectedBackgroundColor = MaterialTheme.colors.surface
Chip(
- modifier = Modifier
- .testTag("test-item")
- .fillMaxWidth()
- .placeholderShimmer(placeholderState = placeholderState),
+ modifier =
+ Modifier.testTag("test-item")
+ .fillMaxWidth()
+ .placeholderShimmer(placeholderState = placeholderState),
content = {},
onClick = {},
colors = ChipDefaults.secondaryChipColors(),
@@ -246,11 +228,10 @@
placeholderState.initializeTestFrameMillis()
// Check the background color is correct
- rule.onNodeWithTag("test-item")
+ rule
+ .onNodeWithTag("test-item")
.captureToImage()
- .assertContainsColor(
- expectedBackgroundColor, 80f
- )
+ .assertContainsColor(expectedBackgroundColor, 80f)
placeholderState.moveToStartOfNextAnimationLoop(PlaceholderStage.ShowPlaceholder)
@@ -263,23 +244,20 @@
// The placeholder shimmer effect is faint and largely transparent gradiant, but it should
// reduce the amount of the normal color.
- rule.onNodeWithTag("test-item")
+ rule
+ .onNodeWithTag("test-item")
.captureToImage()
.assertDoesNotContainColor(expectedBackgroundColor)
// Change contentReady and confirm that state is now WipeOff
contentReady.value = true
- placeholderState.advanceFrameMillisAndCheckState(
- 1L,
- PlaceholderStage.WipeOff
- )
+ placeholderState.advanceFrameMillisAndCheckState(1L, PlaceholderStage.WipeOff)
// Check the background color is correct
- rule.onNodeWithTag("test-item")
+ rule
+ .onNodeWithTag("test-item")
.captureToImage()
- .assertContainsColor(
- expectedBackgroundColor, 80f
- )
+ .assertContainsColor(expectedBackgroundColor, 80f)
// Advance the clock by one cycle and check we have moved to ShowContent
placeholderState.advanceFrameMillisAndCheckState(
@@ -288,11 +266,10 @@
)
// Check that the shimmer is no longer visible
- rule.onNodeWithTag("test-item")
+ rule
+ .onNodeWithTag("test-item")
.captureToImage()
- .assertContainsColor(
- expectedBackgroundColor, 80f
- )
+ .assertContainsColor(expectedBackgroundColor, 80f)
}
@RequiresApi(Build.VERSION_CODES.O)
@@ -305,12 +282,11 @@
var expectedBackgroundPlaceholderColor: Color = Color.Transparent
rule.setContentWithTheme {
contentReady = remember { mutableStateOf(false) }
- placeholderState = rememberPlaceholderState {
- contentReady.value
- }
- val maxScreenDimensionPx = with(LocalDensity.current) {
- Dp(max(screenHeightDp(), screenWidthDp()).toFloat()).toPx()
- }
+ placeholderState = rememberPlaceholderState { contentReady.value }
+ val maxScreenDimensionPx =
+ with(LocalDensity.current) {
+ Dp(max(screenHeightDp(), screenWidthDp()).toFloat()).toPx()
+ }
// Set the offset to be 50% of the screen
placeholderState.backgroundOffset =
Offset(maxScreenDimensionPx / 2f, maxScreenDimensionPx / 2f)
@@ -318,15 +294,14 @@
expectedBackgroundPlaceholderColor = MaterialTheme.colors.surface
Chip(
- modifier = Modifier
- .testTag("test-item")
- .fillMaxWidth(),
+ modifier = Modifier.testTag("test-item").fillMaxWidth(),
content = {},
onClick = {},
- colors = PlaceholderDefaults.placeholderChipColors(
- originalChipColors = ChipDefaults.primaryChipColors(),
- placeholderState = placeholderState,
- ),
+ colors =
+ PlaceholderDefaults.placeholderChipColors(
+ originalChipColors = ChipDefaults.primaryChipColors(),
+ placeholderState = placeholderState,
+ ),
border = ChipDefaults.chipBorder()
)
}
@@ -334,25 +309,23 @@
placeholderState.initializeTestFrameMillis()
// Check the background color is correct
- rule.onNodeWithTag("test-item")
+ rule
+ .onNodeWithTag("test-item")
.captureToImage()
.assertContainsColor(expectedBackgroundPlaceholderColor, 80f)
// Check that there is primary color showing
- rule.onNodeWithTag("test-item")
+ rule
+ .onNodeWithTag("test-item")
.captureToImage()
- .assertDoesNotContainColor(
- expectedBackgroundColor
- )
+ .assertDoesNotContainColor(expectedBackgroundColor)
// Change contentReady and confirm that state is now WipeOff
contentReady.value = true
- placeholderState.advanceFrameMillisAndCheckState(
- 1L,
- PlaceholderStage.WipeOff
- )
+ placeholderState.advanceFrameMillisAndCheckState(1L, PlaceholderStage.WipeOff)
// Check that placeholder background is still visible
- rule.onNodeWithTag("test-item")
+ rule
+ .onNodeWithTag("test-item")
.captureToImage()
.assertContainsColor(expectedBackgroundPlaceholderColor, 80f)
@@ -364,7 +337,8 @@
)
// Check that placeholder background is still visible
- rule.onNodeWithTag("test-item")
+ rule
+ .onNodeWithTag("test-item")
.captureToImage()
.assertContainsColor(expectedBackgroundPlaceholderColor, 80f)
@@ -375,7 +349,8 @@
)
// Check that normal chip background is now visible
- rule.onNodeWithTag("test-item")
+ rule
+ .onNodeWithTag("test-item")
.captureToImage()
.assertContainsColor(expectedBackgroundColor, 80f)
}
@@ -383,24 +358,20 @@
@OptIn(ExperimentalWearMaterialApi::class)
@Composable
fun TestPlaceholderChip(contents: String?, currentState: StableRef<PlaceholderState?>) {
- val placeholderState = rememberPlaceholderState {
- contents != null
- }.also { currentState.value = it }
+ val placeholderState =
+ rememberPlaceholderState { contents != null }.also { currentState.value = it }
Chip(
- modifier = Modifier
- .testTag("test-item")
- .placeholderShimmer(placeholderState),
+ modifier = Modifier.testTag("test-item").placeholderShimmer(placeholderState),
content = {},
onClick = {},
- colors = PlaceholderDefaults.placeholderChipColors(
- originalChipColors = ChipDefaults.primaryChipColors(),
- placeholderState = placeholderState,
- ),
+ colors =
+ PlaceholderDefaults.placeholderChipColors(
+ originalChipColors = ChipDefaults.primaryChipColors(),
+ placeholderState = placeholderState,
+ ),
border = ChipDefaults.chipBorder(),
)
- LaunchedEffect(placeholderState) {
- placeholderState.startPlaceholderAnimation()
- }
+ LaunchedEffect(placeholderState) { placeholderState.startPlaceholderAnimation() }
}
@RequiresApi(Build.VERSION_CODES.O)
@@ -426,12 +397,11 @@
contentsHolder.value.value = "Test"
// Trigger move to WipeOff stage
- placeholderState.value?.advanceFrameMillisAndCheckState(
- 1, PlaceholderStage.WipeOff
- )
+ placeholderState.value?.advanceFrameMillisAndCheckState(1, PlaceholderStage.WipeOff)
placeholderState.value?.advanceFrameMillisAndCheckState(
- PLACEHOLDER_WIPE_OFF_PROGRESSION_DURATION_MS, PlaceholderStage.ShowContent
+ PLACEHOLDER_WIPE_OFF_PROGRESSION_DURATION_MS,
+ PlaceholderStage.ShowContent
)
}
@@ -445,42 +415,36 @@
lateinit var placeholderState: PlaceholderState
rule.setContentWithTheme {
contentReady = remember { mutableStateOf(false) }
- placeholderState = rememberPlaceholderState {
- contentReady.value
- }
+ placeholderState = rememberPlaceholderState { contentReady.value }
expectedPlaceholderBackgroundColor = MaterialTheme.colors.surface
expectedBackgroundColor = MaterialTheme.colors.primary
Chip(
- modifier = Modifier
- .testTag("test-item")
- .fillMaxWidth()
- .placeholderShimmer(placeholderState),
+ modifier =
+ Modifier.testTag("test-item")
+ .fillMaxWidth()
+ .placeholderShimmer(placeholderState),
content = {},
onClick = {},
- colors = PlaceholderDefaults.placeholderChipColors(
- originalChipColors = ChipDefaults.primaryChipColors(),
- placeholderState = placeholderState,
- ),
+ colors =
+ PlaceholderDefaults.placeholderChipColors(
+ originalChipColors = ChipDefaults.primaryChipColors(),
+ placeholderState = placeholderState,
+ ),
border = ChipDefaults.chipBorder(),
)
- LaunchedEffect(placeholderState) {
- placeholderState.startPlaceholderAnimation()
- }
+ LaunchedEffect(placeholderState) { placeholderState.startPlaceholderAnimation() }
}
placeholderState.initializeTestFrameMillis()
- rule.onNodeWithTag("test-item")
+ rule
+ .onNodeWithTag("test-item")
.captureToImage()
- .assertContainsColor(
- expectedPlaceholderBackgroundColor
- )
+ .assertContainsColor(expectedPlaceholderBackgroundColor)
// Change contentReady and confirm that state is now WipeOff
contentReady.value = true
- placeholderState.advanceFrameMillisAndCheckState(
- 1L, PlaceholderStage.WipeOff
- )
+ placeholderState.advanceFrameMillisAndCheckState(1L, PlaceholderStage.WipeOff)
placeholderState.advanceFrameMillisAndCheckState(
PLACEHOLDER_WIPE_OFF_PROGRESSION_DURATION_MS,
@@ -488,11 +452,10 @@
)
// Check the placeholder background has gone and that we can see the chips background
- rule.onNodeWithTag("test-item")
+ rule
+ .onNodeWithTag("test-item")
.captureToImage()
- .assertContainsColor(
- expectedBackgroundColor
- )
+ .assertContainsColor(expectedBackgroundColor)
}
@OptIn(ExperimentalWearMaterialApi::class)
diff --git a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/PositionIndicatorScreenshotTest.kt b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/PositionIndicatorScreenshotTest.kt
index 31ab009..a244b3e 100644
--- a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/PositionIndicatorScreenshotTest.kt
+++ b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/PositionIndicatorScreenshotTest.kt
@@ -42,14 +42,11 @@
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
class PositionIndicatorScreenshotTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
- @get:Rule
- val screenshotRule = AndroidXScreenshotTestRule(SCREENSHOT_GOLDEN_PATH)
+ @get:Rule val screenshotRule = AndroidXScreenshotTestRule(SCREENSHOT_GOLDEN_PATH)
- @get:Rule
- val testName = TestName()
+ @get:Rule val testName = TestName()
@Test
fun left_position_indicator() =
@@ -112,9 +109,7 @@
ltr: Boolean = true,
) {
rule.setContentWithTheme {
- val actualLayoutDirection =
- if (ltr) LayoutDirection.Ltr
- else LayoutDirection.Rtl
+ val actualLayoutDirection = if (ltr) LayoutDirection.Ltr else LayoutDirection.Rtl
CompositionLocalProvider(LocalLayoutDirection provides actualLayoutDirection) {
PositionIndicator(
value = { value },
@@ -126,7 +121,8 @@
rule.waitForIdle()
- rule.onNodeWithTag(TEST_TAG)
+ rule
+ .onNodeWithTag(TEST_TAG)
.captureToImage()
.assertAgainstGolden(screenshotRule, goldenIdentifier)
}
diff --git a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/PositionIndicatorTest.kt b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/PositionIndicatorTest.kt
index a1c0393..dabf668 100644
--- a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/PositionIndicatorTest.kt
+++ b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/PositionIndicatorTest.kt
@@ -73,8 +73,7 @@
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
@RunWith(AndroidJUnit4::class)
public class PositionIndicatorTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
private var itemSizePx: Int = 50
private var itemSizeDp: Dp = Dp.Infinity
@@ -91,9 +90,7 @@
@Test
fun emptyScalingLazyColumnGivesCorrectPositionAndSize() {
- scalingLazyColumnNotLargeEnoughToScroll(
- Arrangement.spacedBy(itemSpacingDp)
- ) {}
+ scalingLazyColumnNotLargeEnoughToScroll(Arrangement.spacedBy(itemSpacingDp)) {}
}
@Test
@@ -111,23 +108,16 @@
Arrangement.spacedBy(itemSpacingDp),
autoCentering = null
) {
- items(3) {
- Box(Modifier.requiredSize(itemSize))
- }
+ items(3) { Box(Modifier.requiredSize(itemSize)) }
}
}
@Test
fun scalingLazyColumnNotLargeEnoughToScrollSwapVerticalAlignmentGivesCorrectPositionAndSize() {
scalingLazyColumnNotLargeEnoughToScroll(
- Arrangement.spacedBy(
- space = itemSpacingDp,
- alignment = Alignment.Bottom
- )
+ Arrangement.spacedBy(space = itemSpacingDp, alignment = Alignment.Bottom)
) {
- items(3) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(3) { Box(Modifier.requiredSize(itemSizeDp)) }
}
}
@@ -141,13 +131,11 @@
positionIndicatorState = remember { ScalingLazyColumnStateAdapter(state) }
ScalingLazyColumn(
state = state,
- modifier = Modifier
- .size(213.dp) // Size of large round Wear device
- .onSizeChanged { viewPortHeight = it.height }
+ modifier =
+ Modifier.size(213.dp) // Size of large round Wear device
+ .onSizeChanged { viewPortHeight = it.height }
) {
- items(5) {
- Box(modifier = Modifier.size(30.dp))
- }
+ items(5) { Box(modifier = Modifier.size(30.dp)) }
}
PositionIndicator(
state = positionIndicatorState,
@@ -158,15 +146,10 @@
}
while (state.canScrollForward) {
+ rule.runOnIdle { runBlocking { state.scrollBy(10f) } }
rule.runOnIdle {
- runBlocking {
- state.scrollBy(10f)
- }
- }
- rule.runOnIdle {
- assertThat(
- positionIndicatorState.visibility(viewPortHeight.toFloat())
- ).isNotEqualTo(PositionIndicatorVisibility.Hide)
+ assertThat(positionIndicatorState.visibility(viewPortHeight.toFloat()))
+ .isNotEqualTo(PositionIndicatorVisibility.Hide)
}
}
}
@@ -182,12 +165,9 @@
ScalingLazyColumn(
state = state,
- modifier = Modifier
- .size(213.dp) // Size of large round Wear device
+ modifier = Modifier.size(213.dp) // Size of large round Wear device
) {
- items(5) {
- Box(modifier = Modifier.size(30.dp))
- }
+ items(5) { Box(modifier = Modifier.size(30.dp)) }
}
PositionIndicator(
modifier = Modifier.testTag(TEST_TAG),
@@ -199,7 +179,9 @@
)
}
rule.waitForIdle()
- rule.onNodeWithTag(TEST_TAG).captureToImage()
+ rule
+ .onNodeWithTag(TEST_TAG)
+ .captureToImage()
.assertContainsColor(expectedColor = piColor, minPercent = 0.2f)
}
@@ -213,13 +195,9 @@
positionIndicatorState = remember { ScalingLazyColumnStateAdapter(state) }
ScalingLazyColumn(
state = state,
- modifier = Modifier
- .size(213.dp)
- .onSizeChanged { viewPortHeight = it.height }
+ modifier = Modifier.size(213.dp).onSizeChanged { viewPortHeight = it.height }
) {
- item {
- Box(modifier = Modifier.size(30.dp))
- }
+ item { Box(modifier = Modifier.size(30.dp)) }
}
PositionIndicator(
state = positionIndicatorState,
@@ -230,9 +208,8 @@
}
rule.runOnIdle {
- assertThat(
- positionIndicatorState.visibility(viewPortHeight.toFloat())
- ).isEqualTo(PositionIndicatorVisibility.Hide)
+ assertThat(positionIndicatorState.visibility(viewPortHeight.toFloat()))
+ .isEqualTo(PositionIndicatorVisibility.Hide)
}
}
@@ -246,9 +223,7 @@
positionIndicatorState = remember { ScalingLazyColumnStateAdapter(state) }
ScalingLazyColumn(
state = state,
- modifier = Modifier
- .size(213.dp)
- .onSizeChanged { viewPortHeight = it.height }
+ modifier = Modifier.size(213.dp).onSizeChanged { viewPortHeight = it.height }
) {}
PositionIndicator(
state = positionIndicatorState,
@@ -259,9 +234,8 @@
}
rule.runOnIdle {
- assertThat(
- positionIndicatorState.visibility(viewPortHeight.toFloat())
- ).isEqualTo(PositionIndicatorVisibility.Hide)
+ assertThat(positionIndicatorState.visibility(viewPortHeight.toFloat()))
+ .isEqualTo(PositionIndicatorVisibility.Hide)
}
}
@@ -281,9 +255,9 @@
state = state,
verticalArrangement = verticalArrangement,
reverseLayout = reverseLayout,
- modifier = Modifier
- .onSizeChanged { viewPortHeight = it.height }
- .requiredSize(itemSizeDp * 3.5f + itemSpacingDp * 2.5f),
+ modifier =
+ Modifier.onSizeChanged { viewPortHeight = it.height }
+ .requiredSize(itemSizeDp * 3.5f + itemSpacingDp * 2.5f),
autoCentering = autoCentering
) {
content(this)
@@ -297,21 +271,14 @@
}
rule.runOnIdle {
- assertThat(
- positionIndicatorState.positionFraction
- ).isEqualTo(0f)
- assertThat(
- positionIndicatorState.sizeFraction(viewPortHeight.toFloat())
- ).isEqualTo(1f)
+ assertThat(positionIndicatorState.positionFraction).isEqualTo(0f)
+ assertThat(positionIndicatorState.sizeFraction(viewPortHeight.toFloat())).isEqualTo(1f)
}
}
@Test
fun scrollableScalingLazyColumnGivesCorrectPositionAndSize() {
- scrollableScalingLazyColumnPositionAndSize(
- enableAutoCentering = true,
- contentPaddingPx = 0
- )
+ scrollableScalingLazyColumnPositionAndSize(enableAutoCentering = true, contentPaddingPx = 0)
}
@Test
@@ -343,26 +310,21 @@
ScalingLazyColumn(
state = state,
verticalArrangement = Arrangement.spacedBy(itemSpacingDp),
- modifier = Modifier
- .onSizeChanged { viewPortHeight = it.height }
- .requiredHeight(
- // Exactly the right size to hold 3 items with spacing
- itemSizeDp * 3f + itemSpacingDp * 2f
- )
- .background(Color.Black),
+ modifier =
+ Modifier.onSizeChanged { viewPortHeight = it.height }
+ .requiredHeight(
+ // Exactly the right size to hold 3 items with spacing
+ itemSizeDp * 3f + itemSpacingDp * 2f
+ )
+ .background(Color.Black),
scalingParams = ScalingLazyColumnDefaults.scalingParams(edgeScale = 1.0f),
- autoCentering = if (enableAutoCentering)
- AutoCenteringParams(itemIndex = 0) else null,
- contentPadding = with(LocalDensity.current) {
- PaddingValues(contentPaddingPx.toDp())
- }
+ autoCentering =
+ if (enableAutoCentering) AutoCenteringParams(itemIndex = 0) else null,
+ contentPadding =
+ with(LocalDensity.current) { PaddingValues(contentPaddingPx.toDp()) }
) {
items(5) {
- Box(
- Modifier
- .requiredSize(itemSizeDp)
- .border(BorderStroke(1.dp, Color.Green))
- )
+ Box(Modifier.requiredSize(itemSizeDp).border(BorderStroke(1.dp, Color.Green)))
}
}
PositionIndicator(
@@ -375,22 +337,19 @@
rule.runOnIdle {
// Scroll forwards so that item with index 2 is in the center of the viewport
- runBlocking {
- state.scrollBy((itemSizePx.toFloat() + itemSpacingPx.toFloat()) * 2f)
- }
+ runBlocking { state.scrollBy((itemSizePx.toFloat() + itemSpacingPx.toFloat()) * 2f) }
state.layoutInfo.assertWhollyVisibleItems(
- firstItemIndex = 1, lastItemIndex = 3,
+ firstItemIndex = 1,
+ lastItemIndex = 3,
viewPortHeight = viewPortHeight
)
// And that the indicator is at position 0.5 and of expected size
- assertThat(
- positionIndicatorState.positionFraction
- ).isWithin(0.05f).of(0.5f)
- assertThat(
- positionIndicatorState.sizeFraction(viewPortHeight.toFloat())
- ).isWithin(0.05f).of(0.6f)
+ assertThat(positionIndicatorState.positionFraction).isWithin(0.05f).of(0.5f)
+ assertThat(positionIndicatorState.sizeFraction(viewPortHeight.toFloat()))
+ .isWithin(0.05f)
+ .of(0.6f)
}
}
@@ -405,16 +364,11 @@
@Test
fun reverseLayoutScalingLazyColumnNotLargeEnoughToScrollGivesCorrectPositionAndSize() {
scalingLazyColumnNotLargeEnoughToScroll(
- Arrangement.spacedBy(
- space = itemSpacingDp,
- alignment = Alignment.Bottom
- ),
+ Arrangement.spacedBy(space = itemSpacingDp, alignment = Alignment.Bottom),
autoCentering = null,
reverseLayout = true
) {
- items(3) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(3) { Box(Modifier.requiredSize(itemSizeDp)) }
}
}
@@ -430,19 +384,17 @@
state = state,
verticalArrangement = Arrangement.spacedBy(itemSpacingDp),
reverseLayout = true,
- modifier = Modifier
- .onSizeChanged { viewPortHeight = it.height }
- .requiredHeight(
- // Exactly the right size to hold 3 items with spacing
- itemSizeDp * 3f + itemSpacingDp * 2f
- )
- .background(Color.DarkGray),
+ modifier =
+ Modifier.onSizeChanged { viewPortHeight = it.height }
+ .requiredHeight(
+ // Exactly the right size to hold 3 items with spacing
+ itemSizeDp * 3f + itemSpacingDp * 2f
+ )
+ .background(Color.DarkGray),
scalingParams = ScalingLazyColumnDefaults.scalingParams(edgeScale = 1.0f),
autoCentering = null
) {
- items(5) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(5) { Box(Modifier.requiredSize(itemSizeDp)) }
}
PositionIndicator(
state = positionIndicatorState,
@@ -453,65 +405,47 @@
}
rule.runOnIdle {
- runBlocking {
- state.scrollBy(itemSizePx.toFloat() + itemSpacingPx.toFloat())
- }
+ runBlocking { state.scrollBy(itemSizePx.toFloat() + itemSpacingPx.toFloat()) }
state.layoutInfo.assertWhollyVisibleItems(
- firstItemIndex = 1, lastItemIndex = 3,
+ firstItemIndex = 1,
+ lastItemIndex = 3,
viewPortHeight = viewPortHeight
)
// And that the indicator is at position 0.5 and of expected size
- assertThat(
- positionIndicatorState.positionFraction
- ).isWithin(0.05f).of(0.5f)
- assertThat(
- positionIndicatorState.sizeFraction(viewPortHeight.toFloat())
- ).isWithin(0.05f).of(0.6f)
+ assertThat(positionIndicatorState.positionFraction).isWithin(0.05f).of(0.5f)
+ assertThat(positionIndicatorState.sizeFraction(viewPortHeight.toFloat()))
+ .isWithin(0.05f)
+ .of(0.6f)
}
}
@Test
fun emptyLazyColumnGivesCorrectPositionAndSize() {
- lazyColumnNotLargeEnoughToScroll(
- Arrangement.spacedBy(itemSpacingDp)
- ) {}
+ lazyColumnNotLargeEnoughToScroll(Arrangement.spacedBy(itemSpacingDp)) {}
}
@Test
fun lazyColumnNotLargeEnoughToScrollGivesCorrectPositionAndSize() {
- lazyColumnNotLargeEnoughToScroll(
- Arrangement.spacedBy(itemSpacingDp)
- ) {
- items(3) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ lazyColumnNotLargeEnoughToScroll(Arrangement.spacedBy(itemSpacingDp)) {
+ items(3) { Box(Modifier.requiredSize(itemSizeDp)) }
}
}
@Test
fun lazyColumnNotLargeEnoughToScrollGivesCorrectPositionAndSizeForZeroSizeItems() {
- lazyColumnNotLargeEnoughToScroll(
- Arrangement.spacedBy(itemSpacingDp)
- ) {
- items(3) {
- Box(Modifier.requiredSize(0.dp))
- }
+ lazyColumnNotLargeEnoughToScroll(Arrangement.spacedBy(itemSpacingDp)) {
+ items(3) { Box(Modifier.requiredSize(0.dp)) }
}
}
@Test
fun lazyColumnNotLargeEnoughToScrollSwapVerticalAlignmentGivesCorrectPositionAndSize() {
lazyColumnNotLargeEnoughToScroll(
- Arrangement.spacedBy(
- space = itemSpacingDp,
- alignment = Alignment.Bottom
- )
+ Arrangement.spacedBy(space = itemSpacingDp, alignment = Alignment.Bottom)
) {
- items(3) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(3) { Box(Modifier.requiredSize(itemSizeDp)) }
}
}
@@ -530,9 +464,9 @@
state = state,
verticalArrangement = verticalArrangement,
reverseLayout = reverseLayout,
- modifier = Modifier
- .onSizeChanged { viewPortHeight = it.height }
- .requiredSize(itemSizeDp * 3.5f + itemSpacingDp * 2.5f)
+ modifier =
+ Modifier.onSizeChanged { viewPortHeight = it.height }
+ .requiredSize(itemSizeDp * 3.5f + itemSpacingDp * 2.5f)
) {
content()
}
@@ -545,12 +479,8 @@
}
rule.runOnIdle {
- assertThat(
- positionIndicatorState.positionFraction
- ).isEqualTo(0f)
- assertThat(
- positionIndicatorState.sizeFraction(viewPortHeight.toFloat())
- ).isEqualTo(1f)
+ assertThat(positionIndicatorState.positionFraction).isEqualTo(0f)
+ assertThat(positionIndicatorState.sizeFraction(viewPortHeight.toFloat())).isEqualTo(1f)
}
}
@@ -565,16 +495,14 @@
LazyColumn(
state = state,
verticalArrangement = Arrangement.spacedBy(itemSpacingDp),
- modifier = Modifier
- .onSizeChanged { viewPortHeight = it.height }
- .requiredHeight(
- // Exactly the right size to hold 3 items with spacing
- itemSizeDp * 3f + itemSpacingDp * 2f
- ),
+ modifier =
+ Modifier.onSizeChanged { viewPortHeight = it.height }
+ .requiredHeight(
+ // Exactly the right size to hold 3 items with spacing
+ itemSizeDp * 3f + itemSpacingDp * 2f
+ ),
) {
- items(5) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(5) { Box(Modifier.requiredSize(itemSizeDp)) }
}
PositionIndicator(
state = positionIndicatorState,
@@ -586,17 +514,13 @@
rule.runOnIdle {
// Scroll forwards
- runBlocking {
- state.scrollBy(itemSizePx.toFloat() + itemSpacingPx.toFloat())
- }
+ runBlocking { state.scrollBy(itemSizePx.toFloat() + itemSpacingPx.toFloat()) }
// And that the indicator is at position 0.5 and of expected size
- assertThat(
- positionIndicatorState.positionFraction
- ).isWithin(0.05f).of(0.5f)
- assertThat(
- positionIndicatorState.sizeFraction(viewPortHeight.toFloat())
- ).isWithin(0.05f).of(0.6f)
+ assertThat(positionIndicatorState.positionFraction).isWithin(0.05f).of(0.5f)
+ assertThat(positionIndicatorState.sizeFraction(viewPortHeight.toFloat()))
+ .isWithin(0.05f)
+ .of(0.6f)
}
}
@@ -611,15 +535,10 @@
@Test
fun reverseLayoutLazyColumnNotLargeEnoughToScrollGivesCorrectPositionAndSize() {
lazyColumnNotLargeEnoughToScroll(
- Arrangement.spacedBy(
- space = itemSpacingDp,
- alignment = Alignment.Bottom
- ),
+ Arrangement.spacedBy(space = itemSpacingDp, alignment = Alignment.Bottom),
reverseLayout = true
) {
- items(3) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(3) { Box(Modifier.requiredSize(itemSizeDp)) }
}
}
@@ -635,16 +554,14 @@
state = state,
verticalArrangement = Arrangement.spacedBy(itemSpacingDp),
reverseLayout = false,
- modifier = Modifier
- .onSizeChanged { viewPortHeight = it.height }
- .requiredHeight(
- // Exactly the right size to hold 3 items with spacing
- itemSizeDp * 3f + itemSpacingDp * 2f
- )
+ modifier =
+ Modifier.onSizeChanged { viewPortHeight = it.height }
+ .requiredHeight(
+ // Exactly the right size to hold 3 items with spacing
+ itemSizeDp * 3f + itemSpacingDp * 2f
+ )
) {
- items(5) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(5) { Box(Modifier.requiredSize(itemSizeDp)) }
}
PositionIndicator(
state = positionIndicatorState,
@@ -654,20 +571,14 @@
)
}
- rule.runOnIdle {
- runBlocking {
- state.scrollBy((itemSizePx + itemSpacingPx).toFloat())
- }
- }
+ rule.runOnIdle { runBlocking { state.scrollBy((itemSizePx + itemSpacingPx).toFloat()) } }
rule.waitForIdle()
// That the indicator is at position 0.5 and of expected size
- assertThat(
- positionIndicatorState.positionFraction
- ).isWithin(0.05f).of(0.5f)
- assertThat(
- positionIndicatorState.sizeFraction(viewPortHeight.toFloat())
- ).isWithin(0.05f).of(0.6f)
+ assertThat(positionIndicatorState.positionFraction).isWithin(0.05f).of(0.5f)
+ assertThat(positionIndicatorState.sizeFraction(viewPortHeight.toFloat()))
+ .isWithin(0.05f)
+ .of(0.6f)
}
@Test
@@ -729,10 +640,10 @@
state = rememberScrollState()
positionIndicatorState = ScrollStateAdapter(state)
Column(
- modifier = Modifier
- .onSizeChanged { viewPortHeight = it.height }
- .requiredSize(itemSizeDp * 3.5f + itemSpacingDp * 2.5f)
- .verticalScroll(state = state, reverseScrolling = reverseScrolling),
+ modifier =
+ Modifier.onSizeChanged { viewPortHeight = it.height }
+ .requiredSize(itemSizeDp * 3.5f + itemSpacingDp * 2.5f)
+ .verticalScroll(state = state, reverseScrolling = reverseScrolling),
verticalArrangement = verticalArrangement
) {
columnContent()
@@ -747,12 +658,8 @@
}
rule.runOnIdle {
- assertThat(
- positionIndicatorState.positionFraction
- ).isEqualTo(0f)
- assertThat(
- positionIndicatorState.sizeFraction(viewPortHeight.toFloat())
- ).isEqualTo(1f)
+ assertThat(positionIndicatorState.positionFraction).isEqualTo(0f)
+ assertThat(positionIndicatorState.sizeFraction(viewPortHeight.toFloat())).isEqualTo(1f)
}
}
@@ -765,15 +672,14 @@
state = rememberScrollState()
positionIndicatorState = ScrollStateAdapter(state)
Column(
- modifier = Modifier
- .onSizeChanged { viewPortHeight = it.height }
- .requiredHeight(itemSizeDp * 3f + itemSpacingDp * 2f)
- .fillMaxWidth()
- .verticalScroll(state = state)
- .background(Color.Black),
+ modifier =
+ Modifier.onSizeChanged { viewPortHeight = it.height }
+ .requiredHeight(itemSizeDp * 3f + itemSpacingDp * 2f)
+ .fillMaxWidth()
+ .verticalScroll(state = state)
+ .background(Color.Black),
verticalArrangement = Arrangement.spacedBy(itemSpacingDp),
-
- ) {
+ ) {
Box(Modifier.requiredSize(itemSizeDp))
Box(Modifier.requiredSize(itemSizeDp))
Box(Modifier.requiredSize(itemSizeDp))
@@ -789,17 +695,13 @@
}
rule.runOnIdle {
- runBlocking {
- state.scrollBy(itemSizePx.toFloat() + itemSpacingPx.toFloat())
- }
+ runBlocking { state.scrollBy(itemSizePx.toFloat() + itemSpacingPx.toFloat()) }
// And that the indicator is at position 0.5 and of expected size
- assertThat(
- positionIndicatorState.positionFraction
- ).isWithin(0.05f).of(0.5f)
- assertThat(
- positionIndicatorState.sizeFraction(viewPortHeight.toFloat())
- ).isWithin(0.05f).of(0.6f)
+ assertThat(positionIndicatorState.positionFraction).isWithin(0.05f).of(0.5f)
+ assertThat(positionIndicatorState.sizeFraction(viewPortHeight.toFloat()))
+ .isWithin(0.05f)
+ .of(0.6f)
}
}
@@ -812,12 +714,12 @@
state = rememberScrollState()
positionIndicatorState = ScrollStateAdapter(scrollState = state)
Column(
- modifier = Modifier
- .onSizeChanged { viewPortHeight = it.height }
- .requiredHeight(itemSizeDp * 3f + itemSpacingDp * 2f)
- .fillMaxWidth()
- .verticalScroll(state = state, reverseScrolling = true)
- .background(Color.Black),
+ modifier =
+ Modifier.onSizeChanged { viewPortHeight = it.height }
+ .requiredHeight(itemSizeDp * 3f + itemSpacingDp * 2f)
+ .fillMaxWidth()
+ .verticalScroll(state = state, reverseScrolling = true)
+ .background(Color.Black),
verticalArrangement = Arrangement.spacedBy(itemSpacingDp),
) {
Box(Modifier.requiredSize(itemSizeDp))
@@ -836,17 +738,13 @@
}
rule.runOnIdle {
- runBlocking {
- state.scrollBy(itemSizePx.toFloat() + itemSpacingPx.toFloat())
- }
+ runBlocking { state.scrollBy(itemSizePx.toFloat() + itemSpacingPx.toFloat()) }
// And that the indicator is at position 0 and of expected size
- assertThat(
- positionIndicatorState.positionFraction
- ).isWithin(0.05f).of(0.5f)
- assertThat(
- positionIndicatorState.sizeFraction(viewPortHeight.toFloat())
- ).isWithin(0.05f).of(0.6f)
+ assertThat(positionIndicatorState.positionFraction).isWithin(0.05f).of(0.5f)
+ assertThat(positionIndicatorState.sizeFraction(viewPortHeight.toFloat()))
+ .isWithin(0.05f)
+ .of(0.6f)
}
}
@@ -890,9 +788,8 @@
assertThat(visibleItemsInfo.first().index).isEqualTo(firstItemIndex)
assertThat(visibleItemsInfo.first().offset).isEqualTo(firstItemNotVisible)
assertThat(visibleItemsInfo.last().index).isEqualTo(lastItemIndex)
- assertThat(
- viewPortHeight - (visibleItemsInfo.last().offset + visibleItemsInfo.last().size)
- ).isEqualTo(lastItemNotVisible)
+ assertThat(viewPortHeight - (visibleItemsInfo.last().offset + visibleItemsInfo.last().size))
+ .isEqualTo(lastItemNotVisible)
}
private fun ScalingLazyListLayoutInfo.assertWhollyVisibleItems(
@@ -910,15 +807,14 @@
}
/**
- * Tests for PositionIndicator api which uses deprecated ScalingLazyColumn
- * from androidx.wear.compose.material package.
+ * Tests for PositionIndicator api which uses deprecated ScalingLazyColumn from
+ * androidx.wear.compose.material package.
*/
@MediumTest
@Suppress("DEPRECATION")
@RunWith(AndroidJUnit4::class)
public class PositionIndicatorWithMaterialSLCTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
private var itemSizePx: Int = 50
private var itemSizeDp: Dp = Dp.Infinity
@@ -935,9 +831,7 @@
@Test
fun emptyScalingLazyColumnGivesCorrectPositionAndSize() {
- scalingLazyColumnNotLargeEnoughToScroll(
- Arrangement.spacedBy(itemSpacingDp)
- ) {}
+ scalingLazyColumnNotLargeEnoughToScroll(Arrangement.spacedBy(itemSpacingDp)) {}
}
@Test
@@ -955,31 +849,21 @@
Arrangement.spacedBy(itemSpacingDp),
autoCentering = null
) {
- items(3) {
- Box(Modifier.requiredSize(itemSize))
- }
+ items(3) { Box(Modifier.requiredSize(itemSize)) }
}
}
@Test
fun scalingLazyColumnNotLargeEnoughToScrollSwapVerticalAlignmentGivesCorrectPositionAndSize() {
scalingLazyColumnNotLargeEnoughToScroll(
- Arrangement.spacedBy(
- space = itemSpacingDp,
- alignment = Alignment.Bottom
- )
+ Arrangement.spacedBy(space = itemSpacingDp, alignment = Alignment.Bottom)
) {
- items(3) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(3) { Box(Modifier.requiredSize(itemSizeDp)) }
}
}
fun scrollableScalingLazyColumnGivesCorrectPositionAndSize() {
- scrollableScalingLazyColumnPositionAndSize(
- enableAutoCentering = true,
- contentPaddingPx = 0
- )
+ scrollableScalingLazyColumnPositionAndSize(enableAutoCentering = true, contentPaddingPx = 0)
}
@Test
@@ -1014,29 +898,26 @@
ScalingLazyColumn(
state = state,
verticalArrangement = Arrangement.spacedBy(itemSpacingDp),
- modifier = Modifier
- .onSizeChanged { viewPortHeight = it.height }
- .requiredHeight(
- // Exactly the right size to hold 3 items with spacing
- itemSizeDp * 3f + itemSpacingDp * 2f
- )
- .background(Color.Black),
+ modifier =
+ Modifier.onSizeChanged { viewPortHeight = it.height }
+ .requiredHeight(
+ // Exactly the right size to hold 3 items with spacing
+ itemSizeDp * 3f + itemSpacingDp * 2f
+ )
+ .background(Color.Black),
scalingParams =
- androidx.wear.compose.material.ScalingLazyColumnDefaults.scalingParams(
- edgeScale = 1.0f
- ),
- autoCentering = if (enableAutoCentering)
- androidx.wear.compose.material.AutoCenteringParams(itemIndex = 0) else null,
- contentPadding = with(LocalDensity.current) {
- PaddingValues(contentPaddingPx.toDp())
- }
+ androidx.wear.compose.material.ScalingLazyColumnDefaults.scalingParams(
+ edgeScale = 1.0f
+ ),
+ autoCentering =
+ if (enableAutoCentering)
+ androidx.wear.compose.material.AutoCenteringParams(itemIndex = 0)
+ else null,
+ contentPadding =
+ with(LocalDensity.current) { PaddingValues(contentPaddingPx.toDp()) }
) {
items(5) {
- Box(
- Modifier
- .requiredSize(itemSizeDp)
- .border(BorderStroke(1.dp, Color.Green))
- )
+ Box(Modifier.requiredSize(itemSizeDp).border(BorderStroke(1.dp, Color.Green)))
}
}
PositionIndicator(
@@ -1049,22 +930,19 @@
rule.runOnIdle {
// Scroll forwards so that item with index 2 is in the center of the viewport
- runBlocking {
- state.scrollBy((itemSizePx.toFloat() + itemSpacingPx.toFloat()) * 2f)
- }
+ runBlocking { state.scrollBy((itemSizePx.toFloat() + itemSpacingPx.toFloat()) * 2f) }
state.layoutInfo.assertWhollyVisibleItems(
- firstItemIndex = 1, lastItemIndex = 3,
+ firstItemIndex = 1,
+ lastItemIndex = 3,
viewPortHeight = viewPortHeight
)
// And that the indicator is at position 0.5 and of expected size
- assertThat(
- positionIndicatorState.positionFraction
- ).isWithin(0.05f).of(0.5f)
- assertThat(
- positionIndicatorState.sizeFraction(viewPortHeight.toFloat())
- ).isWithin(0.05f).of(0.6f)
+ assertThat(positionIndicatorState.positionFraction).isWithin(0.05f).of(0.5f)
+ assertThat(positionIndicatorState.sizeFraction(viewPortHeight.toFloat()))
+ .isWithin(0.05f)
+ .of(0.6f)
}
}
@@ -1079,16 +957,11 @@
@Test
fun reverseLayoutScalingLazyColumnNotLargeEnoughToScrollGivesCorrectPositionAndSize() {
scalingLazyColumnNotLargeEnoughToScroll(
- Arrangement.spacedBy(
- space = itemSpacingDp,
- alignment = Alignment.Bottom
- ),
+ Arrangement.spacedBy(space = itemSpacingDp, alignment = Alignment.Bottom),
autoCentering = null,
reverseLayout = true
) {
- items(3) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(3) { Box(Modifier.requiredSize(itemSizeDp)) }
}
}
@@ -1109,9 +982,9 @@
state = state,
verticalArrangement = verticalArrangement,
reverseLayout = reverseLayout,
- modifier = Modifier
- .onSizeChanged { viewPortHeight = it.height }
- .requiredSize(itemSizeDp * 3.5f + itemSpacingDp * 2.5f),
+ modifier =
+ Modifier.onSizeChanged { viewPortHeight = it.height }
+ .requiredSize(itemSizeDp * 3.5f + itemSpacingDp * 2.5f),
autoCentering = autoCentering
) {
slcContent(this)
@@ -1125,12 +998,8 @@
}
rule.runOnIdle {
- assertThat(
- positionIndicatorState.positionFraction
- ).isEqualTo(0f)
- assertThat(
- positionIndicatorState.sizeFraction(viewPortHeight.toFloat())
- ).isEqualTo(1f)
+ assertThat(positionIndicatorState.positionFraction).isEqualTo(0f)
+ assertThat(positionIndicatorState.sizeFraction(viewPortHeight.toFloat())).isEqualTo(1f)
}
}
@@ -1146,20 +1015,20 @@
state = state,
verticalArrangement = Arrangement.spacedBy(itemSpacingDp),
reverseLayout = true,
- modifier = Modifier
- .onSizeChanged { viewPortHeight = it.height }
- .requiredHeight(
- // Exactly the right size to hold 3 items with spacing
- itemSizeDp * 3f + itemSpacingDp * 2f
- )
- .background(Color.DarkGray),
- scalingParams = androidx.wear.compose.material.ScalingLazyColumnDefaults
- .scalingParams(edgeScale = 1.0f),
+ modifier =
+ Modifier.onSizeChanged { viewPortHeight = it.height }
+ .requiredHeight(
+ // Exactly the right size to hold 3 items with spacing
+ itemSizeDp * 3f + itemSpacingDp * 2f
+ )
+ .background(Color.DarkGray),
+ scalingParams =
+ androidx.wear.compose.material.ScalingLazyColumnDefaults.scalingParams(
+ edgeScale = 1.0f
+ ),
autoCentering = null
) {
- items(5) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(5) { Box(Modifier.requiredSize(itemSizeDp)) }
}
PositionIndicator(
state = positionIndicatorState,
@@ -1170,22 +1039,19 @@
}
rule.runOnIdle {
- runBlocking {
- state.scrollBy(itemSizePx.toFloat() + itemSpacingPx.toFloat())
- }
+ runBlocking { state.scrollBy(itemSizePx.toFloat() + itemSpacingPx.toFloat()) }
state.layoutInfo.assertWhollyVisibleItems(
- firstItemIndex = 1, lastItemIndex = 3,
+ firstItemIndex = 1,
+ lastItemIndex = 3,
viewPortHeight = viewPortHeight
)
// And that the indicator is at position 0.5 and of expected size
- assertThat(
- positionIndicatorState.positionFraction
- ).isWithin(0.05f).of(0.5f)
- assertThat(
- positionIndicatorState.sizeFraction(viewPortHeight.toFloat())
- ).isWithin(0.05f).of(0.6f)
+ assertThat(positionIndicatorState.positionFraction).isWithin(0.05f).of(0.5f)
+ assertThat(positionIndicatorState.sizeFraction(viewPortHeight.toFloat()))
+ .isWithin(0.05f)
+ .of(0.6f)
}
}
diff --git a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/ProgressIndicatorScreenshotTest.kt b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/ProgressIndicatorScreenshotTest.kt
index 7b5e0ae..bdeae03 100644
--- a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/ProgressIndicatorScreenshotTest.kt
+++ b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/ProgressIndicatorScreenshotTest.kt
@@ -39,14 +39,11 @@
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
class ProgressIndicatorScreenshotTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
- @get:Rule
- val screenshotRule = AndroidXScreenshotTestRule(SCREENSHOT_GOLDEN_PATH)
+ @get:Rule val screenshotRule = AndroidXScreenshotTestRule(SCREENSHOT_GOLDEN_PATH)
- @get:Rule
- val testName = TestName()
+ @get:Rule val testName = TestName()
@Test
fun indeterminate_progress_indicator() {
@@ -62,7 +59,8 @@
rule.waitForIdle()
rule.mainClock.advanceTimeBy(300)
- rule.onNodeWithTag(TEST_TAG)
+ rule
+ .onNodeWithTag(TEST_TAG)
.captureToImage()
.assertAgainstGolden(screenshotRule, testName.methodName)
}
@@ -82,7 +80,8 @@
rule.waitForIdle()
rule.mainClock.advanceTimeBy(300)
- rule.onNodeWithTag(TEST_TAG)
+ rule
+ .onNodeWithTag(TEST_TAG)
.captureToImage()
.assertAgainstGolden(screenshotRule, testName.methodName)
}
@@ -98,7 +97,8 @@
)
}
- rule.onNodeWithTag(TEST_TAG)
+ rule
+ .onNodeWithTag(TEST_TAG)
.captureToImage()
.assertAgainstGolden(screenshotRule, testName.methodName)
}
@@ -116,7 +116,8 @@
)
}
- rule.onNodeWithTag(TEST_TAG)
+ rule
+ .onNodeWithTag(TEST_TAG)
.captureToImage()
.assertAgainstGolden(screenshotRule, testName.methodName)
}
@@ -133,7 +134,8 @@
)
}
- rule.onNodeWithTag(TEST_TAG)
+ rule
+ .onNodeWithTag(TEST_TAG)
.captureToImage()
.assertAgainstGolden(screenshotRule, testName.methodName)
}
diff --git a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/ProgressIndicatorTest.kt b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/ProgressIndicatorTest.kt
index 936958e..cf1c04b 100644
--- a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/ProgressIndicatorTest.kt
+++ b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/ProgressIndicatorTest.kt
@@ -33,8 +33,7 @@
class CircularIndeterminateProgressIndicatorTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
@Test
fun supports_testtag() {
@@ -68,17 +67,20 @@
rule.waitForIdle()
rule.mainClock.advanceTimeBy(300)
- rule.onNodeWithTag(TEST_TAG).captureToImage()
+ rule
+ .onNodeWithTag(TEST_TAG)
+ .captureToImage()
.assertColorInPercentageRange(Color.Yellow, 12f..20f)
- rule.onNodeWithTag(TEST_TAG).captureToImage()
+ rule
+ .onNodeWithTag(TEST_TAG)
+ .captureToImage()
.assertColorInPercentageRange(Color.Red, 5f..15f)
}
}
class CircularDeterminateProgressIndicatorTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
@Test
fun supports_testtag() {
@@ -100,15 +102,11 @@
)
}
- rule.onNodeWithTag(TEST_TAG)
- .assertRangeInfoEquals(ProgressBarRangeInfo(0f, 0f..1f))
+ rule.onNodeWithTag(TEST_TAG).assertRangeInfoEquals(ProgressBarRangeInfo(0f, 0f..1f))
- rule.runOnIdle {
- progress.value = 0.5f
- }
+ rule.runOnIdle { progress.value = 0.5f }
- rule.onNodeWithTag(TEST_TAG)
- .assertRangeInfoEquals(ProgressBarRangeInfo(0.5f, 0f..1f))
+ rule.onNodeWithTag(TEST_TAG).assertRangeInfoEquals(ProgressBarRangeInfo(0.5f, 0f..1f))
}
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
@@ -124,7 +122,9 @@
}
rule.waitForIdle()
// by default fully filled progress approximately takes 23-27% of the control
- rule.onNodeWithTag(TEST_TAG).captureToImage()
+ rule
+ .onNodeWithTag(TEST_TAG)
+ .captureToImage()
.assertColorInPercentageRange(Color.Yellow, 23f..27f)
rule.onNodeWithTag(TEST_TAG).captureToImage().assertDoesNotContainColor(Color.Red)
}
@@ -143,7 +143,9 @@
rule.waitForIdle()
rule.onNodeWithTag(TEST_TAG).captureToImage().assertDoesNotContainColor(Color.Yellow)
// by default progress track approximately takes 23-27% of the control
- rule.onNodeWithTag(TEST_TAG).captureToImage()
+ rule
+ .onNodeWithTag(TEST_TAG)
+ .captureToImage()
.assertColorInPercentageRange(Color.Red, 23f..27f)
}
@@ -163,9 +165,13 @@
rule.waitForIdle()
// Color should take approximately a quarter of what it normally takes
// (a little bit less), eg 25% / 4 ≈ 6%
- rule.onNodeWithTag(TEST_TAG).captureToImage()
+ rule
+ .onNodeWithTag(TEST_TAG)
+ .captureToImage()
.assertColorInPercentageRange(Color.Yellow, 5f..8f)
- rule.onNodeWithTag(TEST_TAG).captureToImage()
+ rule
+ .onNodeWithTag(TEST_TAG)
+ .captureToImage()
.assertColorInPercentageRange(Color.Red, 5f..8f)
}
@@ -180,12 +186,9 @@
)
}
- rule.runOnIdle {
- progress.value = 1.5f
- }
+ rule.runOnIdle { progress.value = 1.5f }
- rule.onNodeWithTag(TEST_TAG)
- .assertRangeInfoEquals(ProgressBarRangeInfo(1f, 0f..1f))
+ rule.onNodeWithTag(TEST_TAG).assertRangeInfoEquals(ProgressBarRangeInfo(1f, 0f..1f))
}
@Test
@@ -199,12 +202,9 @@
)
}
- rule.runOnIdle {
- progress.value = -1.5f
- }
+ rule.runOnIdle { progress.value = -1.5f }
- rule.onNodeWithTag(TEST_TAG)
- .assertRangeInfoEquals(ProgressBarRangeInfo(0f, 0f..1f))
+ rule.onNodeWithTag(TEST_TAG).assertRangeInfoEquals(ProgressBarRangeInfo(0f, 0f..1f))
}
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
@@ -220,9 +220,13 @@
)
}
rule.waitForIdle()
- rule.onNodeWithTag(TEST_TAG).captureToImage()
+ rule
+ .onNodeWithTag(TEST_TAG)
+ .captureToImage()
.assertColorInPercentageRange(Color.Yellow, 5f..7f)
- rule.onNodeWithTag(TEST_TAG).captureToImage()
+ rule
+ .onNodeWithTag(TEST_TAG)
+ .captureToImage()
.assertColorInPercentageRange(Color.Red, 5f..7f)
}
@@ -240,9 +244,13 @@
}
rule.waitForIdle()
// Because of the stroke cap, progress color takes a little bit more space than track color
- rule.onNodeWithTag(TEST_TAG).captureToImage()
+ rule
+ .onNodeWithTag(TEST_TAG)
+ .captureToImage()
.assertColorInPercentageRange(Color.Yellow, 24f..28f)
- rule.onNodeWithTag(TEST_TAG).captureToImage()
+ rule
+ .onNodeWithTag(TEST_TAG)
+ .captureToImage()
.assertColorInPercentageRange(Color.Red, 18f..23f)
}
}
diff --git a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/ScaffoldTest.kt b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/ScaffoldTest.kt
index c6c1ed6..306c3dd 100644
--- a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/ScaffoldTest.kt
+++ b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/ScaffoldTest.kt
@@ -34,17 +34,11 @@
@OptIn(ExperimentalAnimationApi::class)
class ScaffoldTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
@Test
fun supports_testtag() {
- rule.setContentWithTheme {
- Scaffold(
- modifier = Modifier.testTag(TEST_TAG)
- ) {
- }
- }
+ rule.setContentWithTheme { Scaffold(modifier = Modifier.testTag(TEST_TAG)) {} }
rule.onNodeWithTag(TEST_TAG).assertExists()
}
@@ -52,11 +46,7 @@
@Test
fun displays_content() {
rule.setContentWithTheme {
- Scaffold(
- modifier = Modifier.testTag(TEST_TAG)
- ) {
- Text(CONTENT_MESSAGE)
- }
+ Scaffold(modifier = Modifier.testTag(TEST_TAG)) { Text(CONTENT_MESSAGE) }
}
rule.onNodeWithText(CONTENT_MESSAGE).assertIsDisplayed()
@@ -109,9 +99,7 @@
val scrollState = rememberScalingLazyListState()
Scaffold(
- modifier = Modifier
- .testTag(TEST_TAG)
- .background(Color.Black),
+ modifier = Modifier.testTag(TEST_TAG).background(Color.Black),
timeText = { Text(TIME_TEXT_MESSAGE) },
vignette = {
if (showVignette.value) {
@@ -126,9 +114,7 @@
}
) {
ScalingLazyColumn(modifier = Modifier.testTag("ScalingLazyColumn")) {
- items(20) {
- Text("" + it, modifier = Modifier.testTag("" + it))
- }
+ items(20) { Text("" + it, modifier = Modifier.testTag("" + it)) }
}
}
}
diff --git a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/ScalingLazyColumnIndexedTest.kt b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/ScalingLazyColumnIndexedTest.kt
index 5eec897..232e5b2 100644
--- a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/ScalingLazyColumnIndexedTest.kt
+++ b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/ScalingLazyColumnIndexedTest.kt
@@ -37,8 +37,7 @@
@Suppress("DEPRECATION")
class ScalingLazyColumnIndexedTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
@Test
fun scalingLazyColumnShowsIndexedItems() {
@@ -51,21 +50,19 @@
rule.setContent {
ScalingLazyColumn(
- state = rememberScalingLazyListState(initialCenterItemIndex = 0)
- .also { state = it },
+ state =
+ rememberScalingLazyListState(initialCenterItemIndex = 0).also { state = it },
modifier = Modifier.height(viewPortHeight),
verticalArrangement = Arrangement.spacedBy(gapBetweenItems),
- scalingParams = ScalingLazyColumnDefaults.scalingParams(
- edgeScale = 1.0f,
- // Create some extra composables to check that extraPadding works.
- viewportVerticalOffsetResolver = { (it.maxHeight / 10f).toInt() }
- )
+ scalingParams =
+ ScalingLazyColumnDefaults.scalingParams(
+ edgeScale = 1.0f,
+ // Create some extra composables to check that extraPadding works.
+ viewportVerticalOffsetResolver = { (it.maxHeight / 10f).toInt() }
+ )
) {
itemsIndexed(items) { index, item ->
- Spacer(
- Modifier.height(itemHeight).width(itemWidth)
- .testTag("$index-$item")
- )
+ Spacer(Modifier.height(itemHeight).width(itemWidth).testTag("$index-$item"))
}
}
}
@@ -73,20 +70,16 @@
// TODO(b/210654937): Remove the waitUntil once we no longer need 2 stage initialization
rule.waitUntil { state.initialized.value }
// Fully visible
- rule.onNodeWithTag("0-1")
- .assertIsDisplayed()
+ rule.onNodeWithTag("0-1").assertIsDisplayed()
// Partially visible
- rule.onNodeWithTag("1-2")
- .assertIsDisplayed()
+ rule.onNodeWithTag("1-2").assertIsDisplayed()
// Will have been composed but should not be visible
- rule.onNodeWithTag("2-3")
- .assertIsNotDisplayed()
+ rule.onNodeWithTag("2-3").assertIsNotDisplayed()
// Should not have been composed
- rule.onNodeWithTag("3-4")
- .assertDoesNotExist()
+ rule.onNodeWithTag("3-4").assertDoesNotExist()
}
@Test
@@ -96,27 +89,23 @@
rule.setContent {
ScalingLazyColumn(
- state = rememberScalingLazyListState(initialCenterItemIndex = 0)
- .also { state = it },
+ state =
+ rememberScalingLazyListState(initialCenterItemIndex = 0).also { state = it },
modifier = Modifier.height(200.dp),
autoCentering = null,
scalingParams = ScalingLazyColumnDefaults.scalingParams(edgeScale = 1.0f)
) {
itemsIndexed(items) { index, item ->
- BasicText(
- "${index}x$item", Modifier.requiredHeight(100.dp)
- )
+ BasicText("${index}x$item", Modifier.requiredHeight(100.dp))
}
}
}
// TODO(b/210654937): Remove the waitUntil once we no longer need 2 stage initialization
rule.waitUntil { state.initialized.value }
- rule.onNodeWithText("0x0")
- .assertTopPositionInRootIsEqualTo(0.dp)
+ rule.onNodeWithText("0x0").assertTopPositionInRootIsEqualTo(0.dp)
- rule.onNodeWithText("1x1")
- .assertTopPositionInRootIsEqualTo(104.dp)
+ rule.onNodeWithText("1x1").assertTopPositionInRootIsEqualTo(104.dp)
}
@Test
@@ -128,8 +117,8 @@
val gapBetweenItems = 2.dp
rule.setContent {
ScalingLazyColumn(
- state = rememberScalingLazyListState(initialCenterItemIndex = 0)
- .also { state = it },
+ state =
+ rememberScalingLazyListState(initialCenterItemIndex = 0).also { state = it },
modifier = Modifier.height(viewPortHeight),
autoCentering = AutoCenteringParams(itemIndex = 0),
verticalArrangement = Arrangement.spacedBy(gapBetweenItems),
@@ -137,9 +126,7 @@
scalingParams = ScalingLazyColumnDefaults.scalingParams(edgeScale = 1.0f)
) {
itemsIndexed(items) { index, item ->
- BasicText(
- "${index}x$item", Modifier.requiredHeight(itemHeight)
- )
+ BasicText("${index}x$item", Modifier.requiredHeight(itemHeight))
}
}
}
@@ -148,11 +135,11 @@
rule.waitUntil { state.initialized.value }
// Check that first item is in the center of the viewport
val firstItemStart = viewPortHeight / 2f - itemHeight / 2f
- rule.onNodeWithText("0x0")
- .assertTopPositionInRootIsEqualTo(firstItemStart)
+ rule.onNodeWithText("0x0").assertTopPositionInRootIsEqualTo(firstItemStart)
// And that the second item is item height + gap between items below it
- rule.onNodeWithText("1x1")
+ rule
+ .onNodeWithText("1x1")
.assertTopPositionInRootIsEqualTo(firstItemStart + itemHeight + gapBetweenItems)
}
}
diff --git a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/ScalingLazyColumnTest.kt b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/ScalingLazyColumnTest.kt
index d5dfb4c..964bde7 100644
--- a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/ScalingLazyColumnTest.kt
+++ b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/ScalingLazyColumnTest.kt
@@ -66,8 +66,7 @@
private val scalingLazyColumnTag = "scalingLazyColumnTag"
private val firstItemTag = "firstItemTag"
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
private var itemSizePx: Int = 50
private var itemSizeDp: Dp = Dp.Infinity
@@ -123,9 +122,7 @@
state = rememberScalingLazyListState().also { state = it },
modifier = Modifier.testTag(TEST_TAG).requiredSize(listSize),
) {
- items(itemCount) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(itemCount) { Box(Modifier.requiredSize(itemSizeDp)) }
}
}
}
@@ -147,9 +144,7 @@
// also for the gap between items to be needed.
verticalArrangement = Arrangement.spacedBy(itemSizeDp * 0.25f * 0.75f),
) {
- items(5) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(5) { Box(Modifier.requiredSize(itemSizeDp)) }
}
}
}
@@ -168,12 +163,8 @@
modifier = Modifier.testTag(TEST_TAG).requiredSize(listSize),
scalingParams = ScalingLazyColumnDefaults.scalingParams(edgeScale = 1f),
) {
- item {
- Box(Modifier.requiredSize(itemSizeDp * 2))
- }
- items(5) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ item { Box(Modifier.requiredSize(itemSizeDp * 2)) }
+ items(5) { Box(Modifier.requiredSize(itemSizeDp)) }
}
}
}
@@ -193,15 +184,14 @@
anchorType = ScalingLazyListAnchorType.ItemCenter,
autoCentering = AutoCenteringParams(),
verticalArrangement = Arrangement.spacedBy(0.dp),
- scalingParams = ScalingLazyColumnDefaults.scalingParams(
- edgeScale = 0f,
- minTransitionArea = 0.5f,
- maxTransitionArea = 0.5f
- )
+ scalingParams =
+ ScalingLazyColumnDefaults.scalingParams(
+ edgeScale = 0f,
+ minTransitionArea = 0.5f,
+ maxTransitionArea = 0.5f
+ )
) {
- items(5) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(5) { Box(Modifier.requiredSize(itemSizeDp)) }
}
}
}
@@ -209,9 +199,7 @@
rule.waitUntil { state.initialized.value }
rule.waitForIdle()
- val listSizePx = with(rule.density) {
- listSize.roundToPx()
- }
+ val listSizePx = with(rule.density) { listSize.roundToPx() }
rule.runOnIdle {
// Make sure that the edge items have been scaled
assertThat(state.layoutInfo.visibleItemsInfo.first().scale).isLessThan(1.0f)
@@ -221,9 +209,7 @@
assertThat(state.lazyListState.layoutInfo.visibleItemsInfo.first().size)
.isEqualTo((listSizePx / 2) - (itemSizePx + itemSizePx / 2))
}
- rule.onNodeWithTag(TEST_TAG).performTouchInput {
- swipeUp()
- }
+ rule.onNodeWithTag(TEST_TAG).performTouchInput { swipeUp() }
rule.runOnIdle {
// Check that the last item has been scrolled into view
assertThat(state.lazyListState.layoutInfo.visibleItemsInfo.last().index)
@@ -246,15 +232,14 @@
anchorType = ScalingLazyListAnchorType.ItemStart,
autoCentering = AutoCenteringParams(),
verticalArrangement = Arrangement.spacedBy(0.dp),
- scalingParams = ScalingLazyColumnDefaults.scalingParams(
- edgeScale = 0f,
- minTransitionArea = 0.5f,
- maxTransitionArea = 0.5f
- )
+ scalingParams =
+ ScalingLazyColumnDefaults.scalingParams(
+ edgeScale = 0f,
+ minTransitionArea = 0.5f,
+ maxTransitionArea = 0.5f
+ )
) {
- items(5) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(5) { Box(Modifier.requiredSize(itemSizeDp)) }
}
}
}
@@ -262,9 +247,7 @@
rule.waitUntil { state.initialized.value }
rule.waitForIdle()
- val listSizePx = with(rule.density) {
- listSize.roundToPx()
- }
+ val listSizePx = with(rule.density) { listSize.roundToPx() }
rule.runOnIdle {
// Make sure that the edge items have been scaled
@@ -274,9 +257,7 @@
assertThat(state.lazyListState.layoutInfo.visibleItemsInfo.first().size)
.isEqualTo((listSizePx / 2) - itemSizePx)
}
- rule.onNodeWithTag(TEST_TAG).performTouchInput {
- swipeUp(endY = top)
- }
+ rule.onNodeWithTag(TEST_TAG).performTouchInput { swipeUp(endY = top) }
rule.runOnIdle {
// Check that the last item has been scrolled into view
assertThat(state.lazyListState.layoutInfo.visibleItemsInfo.last().index)
@@ -294,14 +275,12 @@
WithTouchSlop(0f) {
ScalingLazyColumn(
state = rememberScalingLazyListState().also { state = it },
- modifier = Modifier.testTag(TEST_TAG).requiredSize(
- itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f
- ),
+ modifier =
+ Modifier.testTag(TEST_TAG)
+ .requiredSize(itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f),
autoCentering = null
) {
- items(5) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(5) { Box(Modifier.requiredSize(itemSizeDp)) }
}
}
}
@@ -326,15 +305,13 @@
WithTouchSlop(0f) {
ScalingLazyColumn(
state = rememberScalingLazyListState().also { state = it },
- modifier = Modifier.testTag(TEST_TAG).requiredSize(
- itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f
- ),
+ modifier =
+ Modifier.testTag(TEST_TAG)
+ .requiredSize(itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f),
autoCentering = null,
userScrollEnabled = false
) {
- items(5) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(5) { Box(Modifier.requiredSize(itemSizeDp)) }
}
}
}
@@ -359,16 +336,16 @@
rule.setContent {
WithTouchSlop(0f) {
ScalingLazyColumn(
- state = rememberScalingLazyListState(initialCenterItemIndex = 0)
- .also { state = it },
- modifier = Modifier.testTag(TEST_TAG).requiredSize(
- itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f
- ),
+ state =
+ rememberScalingLazyListState(initialCenterItemIndex = 0).also {
+ state = it
+ },
+ modifier =
+ Modifier.testTag(TEST_TAG)
+ .requiredSize(itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f),
autoCentering = AutoCenteringParams(itemIndex = 0)
) {
- items(5) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(5) { Box(Modifier.requiredSize(itemSizeDp)) }
}
}
}
@@ -392,17 +369,17 @@
rule.setContent {
WithTouchSlop(0f) {
ScalingLazyColumn(
- state = rememberScalingLazyListState(initialCenterItemIndex = 0)
- .also { state = it },
- modifier = Modifier.testTag(TEST_TAG).requiredSize(
- itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f
- ),
+ state =
+ rememberScalingLazyListState(initialCenterItemIndex = 0).also {
+ state = it
+ },
+ modifier =
+ Modifier.testTag(TEST_TAG)
+ .requiredSize(itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f),
autoCentering = AutoCenteringParams(itemIndex = 0),
flingBehavior = ScalingLazyColumnDefaults.snapFlingBehavior(state)
) {
- items(5) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(5) { Box(Modifier.requiredSize(itemSizeDp)) }
}
}
}
@@ -438,20 +415,21 @@
snapOffsetPx = with(LocalDensity.current) { snapOffset.roundToPx() }
ScalingLazyColumn(
- state = rememberScalingLazyListState(initialCenterItemIndex = 0)
- .also { state = it },
- modifier = Modifier.testTag(TEST_TAG).requiredSize(
- itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f
- ),
+ state =
+ rememberScalingLazyListState(initialCenterItemIndex = 0).also {
+ state = it
+ },
+ modifier =
+ Modifier.testTag(TEST_TAG)
+ .requiredSize(itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f),
autoCentering = AutoCenteringParams(itemIndex = 0),
- flingBehavior = ScalingLazyColumnDefaults.snapFlingBehavior(
- state = state,
- snapOffset = snapOffset
- )
+ flingBehavior =
+ ScalingLazyColumnDefaults.snapFlingBehavior(
+ state = state,
+ snapOffset = snapOffset
+ )
) {
- items(5) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(5) { Box(Modifier.requiredSize(itemSizeDp)) }
}
}
}
@@ -483,15 +461,13 @@
WithTouchSlop(0f) {
ScalingLazyColumn(
state = rememberScalingLazyListState().also { state = it },
- modifier = Modifier.testTag(TEST_TAG).requiredSize(
- itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f
- ),
+ modifier =
+ Modifier.testTag(TEST_TAG)
+ .requiredSize(itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f),
reverseLayout = true,
autoCentering = null
) {
- items(5) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(5) { Box(Modifier.requiredSize(itemSizeDp)) }
}
}
}
@@ -514,17 +490,17 @@
rule.setContent {
WithTouchSlop(0f) {
ScalingLazyColumn(
- state = rememberScalingLazyListState(initialCenterItemIndex = 0)
- .also { state = it },
- modifier = Modifier.testTag(TEST_TAG).requiredSize(
- itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f
- ),
+ state =
+ rememberScalingLazyListState(initialCenterItemIndex = 0).also {
+ state = it
+ },
+ modifier =
+ Modifier.testTag(TEST_TAG)
+ .requiredSize(itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f),
scalingParams = ScalingLazyColumnDefaults.scalingParams(1.0f, 1.0f),
autoCentering = AutoCenteringParams(itemIndex = 0)
) {
- items(5) {
- Box(Modifier.requiredSize(itemSizeDp).testTag("Item:" + it))
- }
+ items(5) { Box(Modifier.requiredSize(itemSizeDp).testTag("Item:" + it)) }
}
}
}
@@ -551,15 +527,13 @@
WithTouchSlop(0f) {
ScalingLazyColumn(
state = rememberScalingLazyListState(8).also { state = it },
- modifier = Modifier.testTag(TEST_TAG).requiredSize(
- itemSizeDp * 4f + defaultItemSpacingDp * 3f
- ),
+ modifier =
+ Modifier.testTag(TEST_TAG)
+ .requiredSize(itemSizeDp * 4f + defaultItemSpacingDp * 3f),
scalingParams = ScalingLazyColumnDefaults.scalingParams(1.0f, 1.0f),
reverseLayout = true
) {
- items(15) {
- Box(Modifier.requiredSize(itemSizeDp).testTag("Item:" + it))
- }
+ items(15) { Box(Modifier.requiredSize(itemSizeDp).testTag("Item:" + it)) }
}
}
}
@@ -596,14 +570,12 @@
WithTouchSlop(0f) {
ScalingLazyColumn(
state = rememberScalingLazyListState().also { state = it },
- modifier = Modifier
- .testTag(TEST_TAG)
- .requiredSize(itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f),
+ modifier =
+ Modifier.testTag(TEST_TAG)
+ .requiredSize(itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f),
autoCentering = null
) {
- items(6) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(6) { Box(Modifier.requiredSize(itemSizeDp)) }
}
ObservingFun(state, currentInfo)
}
@@ -667,9 +639,7 @@
// TODO(b/210654937): Remove the waitUntil once we no longer need 2 stage initialization
rule.waitUntil { state.initialized.value }
- rule.onNodeWithTag(firstItemTag)
- .assertWidthIsEqualTo(100.dp)
- .assertHeightIsEqualTo(50.dp)
+ rule.onNodeWithTag(firstItemTag).assertWidthIsEqualTo(100.dp).assertHeightIsEqualTo(50.dp)
}
@Test
@@ -691,9 +661,7 @@
// TODO(b/210654937): Remove the waitUntil once we no longer need 2 stage initialization
rule.waitUntil { state.initialized.value }
- rule.onNodeWithTag(firstItemTag)
- .assertWidthIsEqualTo(50.dp)
- .assertHeightIsEqualTo(150.dp)
+ rule.onNodeWithTag(firstItemTag).assertWidthIsEqualTo(50.dp).assertHeightIsEqualTo(150.dp)
}
@Test
@@ -706,17 +674,13 @@
contentPadding = PaddingValues(horizontal = 0.dp),
scalingParams = ScalingLazyColumnDefaults.scalingParams(1.0f, 1.0f)
) {
- items(listOf(0)) {
- Spacer(Modifier.fillParentMaxSize().testTag(firstItemTag))
- }
+ items(listOf(0)) { Spacer(Modifier.fillParentMaxSize().testTag(firstItemTag)) }
}
}
// TODO(b/210654937): Remove the waitUntil once we no longer need 2 stage initialization
rule.waitUntil { state.initialized.value }
- rule.onNodeWithTag(firstItemTag)
- .assertWidthIsEqualTo(100.dp)
- .assertHeightIsEqualTo(150.dp)
+ rule.onNodeWithTag(firstItemTag).assertWidthIsEqualTo(100.dp).assertHeightIsEqualTo(150.dp)
}
@Test
@@ -741,9 +705,7 @@
// TODO(b/210654937): Remove the waitUntil once we no longer need 2 stage initialization
rule.waitUntil { state.initialized.value }
- rule.onNodeWithTag(firstItemTag)
- .assertWidthIsEqualTo(70.dp)
- .assertHeightIsEqualTo(50.dp)
+ rule.onNodeWithTag(firstItemTag).assertWidthIsEqualTo(70.dp).assertHeightIsEqualTo(50.dp)
}
@Test
@@ -766,9 +728,7 @@
// TODO(b/210654937): Remove the waitUntil once we no longer need 2 stage initialization
rule.waitUntil { state.initialized.value }
- rule.onNodeWithTag(firstItemTag)
- .assertWidthIsEqualTo(50.dp)
- .assertHeightIsEqualTo(45.dp)
+ rule.onNodeWithTag(firstItemTag).assertWidthIsEqualTo(50.dp).assertHeightIsEqualTo(45.dp)
}
@Test
@@ -780,17 +740,13 @@
modifier = Modifier.requiredSize(width = 100.dp, height = 150.dp),
contentPadding = PaddingValues(horizontal = 0.dp)
) {
- items(listOf(0)) {
- Spacer(Modifier.fillParentMaxSize(0.5f).testTag(firstItemTag))
- }
+ items(listOf(0)) { Spacer(Modifier.fillParentMaxSize(0.5f).testTag(firstItemTag)) }
}
}
// TODO(b/210654937): Remove the waitUntil once we no longer need 2 stage initialization
rule.waitUntil { state.initialized.value }
- rule.onNodeWithTag(firstItemTag)
- .assertWidthIsEqualTo(50.dp)
- .assertHeightIsEqualTo(75.dp)
+ rule.onNodeWithTag(firstItemTag).assertWidthIsEqualTo(50.dp).assertHeightIsEqualTo(75.dp)
}
@Test
@@ -803,21 +759,15 @@
modifier = Modifier.requiredSize(parentSize),
contentPadding = PaddingValues(horizontal = 0.dp),
) {
- items(listOf(0)) {
- Spacer(Modifier.fillParentMaxSize().testTag(firstItemTag))
- }
+ items(listOf(0)) { Spacer(Modifier.fillParentMaxSize().testTag(firstItemTag)) }
}
}
// TODO(b/210654937): Remove the waitUntil once we no longer need 2 stage initialization
rule.waitUntil { state.initialized.value }
- rule.runOnIdle {
- parentSize = 150.dp
- }
+ rule.runOnIdle { parentSize = 150.dp }
- rule.onNodeWithTag(firstItemTag)
- .assertWidthIsEqualTo(150.dp)
- .assertHeightIsEqualTo(150.dp)
+ rule.onNodeWithTag(firstItemTag).assertWidthIsEqualTo(150.dp).assertHeightIsEqualTo(150.dp)
}
@Test
@@ -830,31 +780,22 @@
modifier = Modifier.testTag(scalingLazyColumnTag),
contentPadding = PaddingValues(horizontal = 0.dp),
) {
- items(listOf(0)) {
- Spacer(Modifier.size(itemSize).testTag(firstItemTag))
- }
+ items(listOf(0)) { Spacer(Modifier.size(itemSize).testTag(firstItemTag)) }
}
}
// TODO(b/210654937): Remove the waitUntil once we no longer need 2 stage initialization
rule.waitUntil { state.initialized.value }
- rule.onNodeWithTag(scalingLazyColumnTag)
- .assertWidthIsEqualTo(itemSize)
+ rule.onNodeWithTag(scalingLazyColumnTag).assertWidthIsEqualTo(itemSize)
- rule.runOnIdle {
- itemSize = 150.dp
- }
+ rule.runOnIdle { itemSize = 150.dp }
- rule.onNodeWithTag(scalingLazyColumnTag)
- .assertWidthIsEqualTo(itemSize)
+ rule.onNodeWithTag(scalingLazyColumnTag).assertWidthIsEqualTo(itemSize)
- rule.runOnIdle {
- itemSize = 50.dp
- }
+ rule.runOnIdle { itemSize = 50.dp }
- rule.onNodeWithTag(scalingLazyColumnTag)
- .assertWidthIsEqualTo(itemSize)
+ rule.onNodeWithTag(scalingLazyColumnTag).assertWidthIsEqualTo(itemSize)
}
@Test
@@ -891,19 +832,18 @@
if (showList.value) {
ScalingLazyColumn(
state = state,
- modifier = Modifier.testTag(TEST_TAG).requiredSize(
- itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f
- ),
+ modifier =
+ Modifier.testTag(TEST_TAG)
+ .requiredSize(itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f),
autoCentering = AutoCenteringParams()
) {
- items(25) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(25) { Box(Modifier.requiredSize(itemSizeDp)) }
}
} else {
- Box(modifier = Modifier.requiredSize(
- itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f
- ))
+ Box(
+ modifier =
+ Modifier.requiredSize(itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f)
+ )
}
}
// TODO(b/210654937): Remove the waitUntil once we no longer need 2 stage initialization
@@ -917,11 +857,7 @@
rule.waitForIdle()
rule.onNodeWithTag(TEST_TAG).assertDoesNotExist()
- rule.runOnIdle {
- runBlocking {
- state.scrollToItem(10)
- }
- }
+ rule.runOnIdle { runBlocking { state.scrollToItem(10) } }
rule.waitForIdle()
showList.value = true
@@ -941,24 +877,18 @@
state = rememberScalingLazyListState()
ScalingLazyColumn(
state = state,
- modifier = Modifier.testTag(TEST_TAG).requiredSize(
- itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f
- ),
+ modifier =
+ Modifier.testTag(TEST_TAG)
+ .requiredSize(itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f),
autoCentering = AutoCenteringParams()
) {
- items(25) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(25) { Box(Modifier.requiredSize(itemSizeDp)) }
}
}
// TODO(b/210654937): Remove the waitUntil once we no longer need 2 stage initialization
rule.waitUntil { state.initialized.value }
- rule.runOnIdle {
- runBlocking {
- state.scrollToItem(50)
- }
- }
+ rule.runOnIdle { runBlocking { state.scrollToItem(50) } }
state.layoutInfo.assertVisibleItems(count = 3, startIndex = 22)
assertThat(state.centerItemIndex).isEqualTo(24)
@@ -979,14 +909,12 @@
ScalingLazyColumn(
state = state,
- modifier = Modifier.testTag(TEST_TAG).requiredSize(
- itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f
- ),
+ modifier =
+ Modifier.testTag(TEST_TAG)
+ .requiredSize(itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f),
autoCentering = AutoCenteringParams(itemIndex = 0)
) {
- items(5) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(5) { Box(Modifier.requiredSize(itemSizeDp)) }
}
}
}
@@ -1007,7 +935,5 @@
internal fun ComposeContentTestRule.setContentWithTestViewConfiguration(
composable: @Composable () -> Unit
) {
- this.setContent {
- WithTouchSlop(TestTouchSlop, composable)
- }
+ this.setContent { WithTouchSlop(TestTouchSlop, composable) }
}
diff --git a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/ScalingLazyListLayoutInfoTest.kt b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/ScalingLazyListLayoutInfoTest.kt
index e57f587..3f906cb 100644
--- a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/ScalingLazyListLayoutInfoTest.kt
+++ b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/ScalingLazyListLayoutInfoTest.kt
@@ -54,8 +54,7 @@
@MediumTest
@RunWith(AndroidJUnit4::class)
public class ScalingLazyListLayoutInfoTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
private var itemSizePx: Int = 50
private var itemSizeDp: Dp = Dp.Infinity
@@ -77,14 +76,10 @@
rule.setContent {
ScalingLazyColumn(
state = rememberScalingLazyListState().also { state = it },
- modifier = Modifier.requiredSize(
- itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f
- ),
+ modifier = Modifier.requiredSize(itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f),
autoCentering = AutoCenteringParams()
) {
- items(5) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(5) { Box(Modifier.requiredSize(itemSizeDp)) }
}
}
@@ -108,15 +103,11 @@
itemSpacingPx = with(LocalDensity.current) { itemSpacingDp.roundToPx() }
ScalingLazyColumn(
state = rememberScalingLazyListState().also { state = it },
- modifier = Modifier.requiredSize(
- itemSizeDp * 3.5f + itemSpacingDp * 2.5f
- ),
+ modifier = Modifier.requiredSize(itemSizeDp * 3.5f + itemSpacingDp * 2.5f),
verticalArrangement = Arrangement.spacedBy(itemSpacingDp),
autoCentering = AutoCenteringParams()
) {
- items(5) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(5) { Box(Modifier.requiredSize(itemSizeDp)) }
}
}
@@ -131,9 +122,7 @@
// Scroll so that the center item is just above the center line and check that it is still
// the correct center item
val scrollDistance = (itemSizePx / 2) + 1
- scope!!.launch {
- state.animateScrollBy(scrollDistance.toFloat())
- }
+ scope!!.launch { state.animateScrollBy(scrollDistance.toFloat()) }
rule.runOnIdle {
assertThat(state.centerItemIndex).isEqualTo(1)
@@ -147,24 +136,18 @@
rule.setContent {
ScalingLazyColumn(
state = rememberScalingLazyListState().also { state = it },
- modifier = Modifier.requiredSize(
- itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f
- ),
+ modifier = Modifier.requiredSize(itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f),
autoCentering = AutoCenteringParams(),
contentPadding = PaddingValues(all = 0.dp)
) {
- items(5) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(5) { Box(Modifier.requiredSize(itemSizeDp)) }
}
}
// TODO(b/210654937): Remove the waitUntil once we no longer need 2 stage initialization
rule.waitUntil { state.initialized.value }
- rule.runOnIdle {
- assertThat(state.layoutInfo.orientation).isEqualTo(Orientation.Vertical)
- }
+ rule.runOnIdle { assertThat(state.layoutInfo.orientation).isEqualTo(Orientation.Vertical) }
}
@Test
@@ -173,24 +156,18 @@
rule.setContent {
ScalingLazyColumn(
state = rememberScalingLazyListState().also { state = it },
- modifier = Modifier.requiredSize(
- itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f
- ),
+ modifier = Modifier.requiredSize(itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f),
autoCentering = AutoCenteringParams(),
contentPadding = PaddingValues(all = 0.dp)
) {
- items(5) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(5) { Box(Modifier.requiredSize(itemSizeDp)) }
}
}
// TODO(b/210654937): Remove the waitUntil once we no longer need 2 stage initialization
rule.waitUntil { state.initialized.value }
- rule.runOnIdle {
- assertThat(state.layoutInfo.reverseLayout).isEqualTo(false)
- }
+ rule.runOnIdle { assertThat(state.layoutInfo.reverseLayout).isEqualTo(false) }
}
@Test
@@ -199,25 +176,19 @@
rule.setContent {
ScalingLazyColumn(
state = rememberScalingLazyListState().also { state = it },
- modifier = Modifier.requiredSize(
- itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f
- ),
+ modifier = Modifier.requiredSize(itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f),
autoCentering = AutoCenteringParams(),
contentPadding = PaddingValues(all = 0.dp),
reverseLayout = true
) {
- items(5) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(5) { Box(Modifier.requiredSize(itemSizeDp)) }
}
}
// TODO(b/210654937): Remove the waitUntil once we no longer need 2 stage initialization
rule.waitUntil { state.initialized.value }
- rule.runOnIdle {
- assertThat(state.layoutInfo.reverseLayout).isEqualTo(true)
- }
+ rule.runOnIdle { assertThat(state.layoutInfo.reverseLayout).isEqualTo(true) }
}
@Test
@@ -225,16 +196,12 @@
lateinit var state: ScalingLazyListState
rule.setContent {
ScalingLazyColumn(
- state = rememberScalingLazyListState(initialCenterItemIndex = 0)
- .also { state = it },
- modifier = Modifier.requiredSize(
- itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f
- ),
+ state =
+ rememberScalingLazyListState(initialCenterItemIndex = 0).also { state = it },
+ modifier = Modifier.requiredSize(itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f),
autoCentering = AutoCenteringParams(itemIndex = 0)
) {
- items(5) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(5) { Box(Modifier.requiredSize(itemSizeDp)) }
}
}
@@ -253,22 +220,16 @@
rule.setContent {
ScalingLazyColumn(
state = rememberScalingLazyListState().also { state = it },
- modifier = Modifier.requiredSize(
- itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f
- ),
+ modifier = Modifier.requiredSize(itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f),
autoCentering = null
) {
- items(5) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(5) { Box(Modifier.requiredSize(itemSizeDp)) }
}
}
// TODO(b/210654937): Remove the waitUntil once we no longer need 2 stage initialization
rule.waitUntil { state.initialized.value }
- rule.runOnIdle {
- state.layoutInfo.assertVisibleItems(count = 4)
- }
+ rule.runOnIdle { state.layoutInfo.assertVisibleItems(count = 4) }
}
@Test
@@ -277,15 +238,11 @@
rule.setContent {
ScalingLazyColumn(
state = rememberScalingLazyListState().also { state = it },
- modifier = Modifier.requiredSize(
- itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f
- ),
+ modifier = Modifier.requiredSize(itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f),
reverseLayout = true,
autoCentering = null
) {
- items(5) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(5) { Box(Modifier.requiredSize(itemSizeDp)) }
}
}
@@ -302,17 +259,13 @@
lateinit var state: ScalingLazyListState
rule.setContent {
ScalingLazyColumn(
- state = rememberScalingLazyListState(initialCenterItemIndex = 0)
- .also { state = it },
- modifier = Modifier.requiredSize(
- itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f
- ),
+ state =
+ rememberScalingLazyListState(initialCenterItemIndex = 0).also { state = it },
+ modifier = Modifier.requiredSize(itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f),
reverseLayout = true,
autoCentering = AutoCenteringParams(itemIndex = 0)
) {
- items(5) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(5) { Box(Modifier.requiredSize(itemSizeDp)) }
}
}
@@ -331,23 +284,17 @@
rule.setContent {
ScalingLazyColumn(
state = rememberScalingLazyListState().also { state = it },
- modifier = Modifier.requiredSize(
- itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f
- ),
+ modifier = Modifier.requiredSize(itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f),
autoCentering = null
) {
- items(5) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(5) { Box(Modifier.requiredSize(itemSizeDp)) }
}
}
// TODO(b/210654937): Remove the waitUntil once we no longer need 2 stage initialization
rule.waitUntil { state.initialized.value }
rule.runOnIdle {
- runBlocking {
- state.scrollBy(itemSizePx.toFloat() + defaultItemSpacingPx.toFloat())
- }
+ runBlocking { state.scrollBy(itemSizePx.toFloat() + defaultItemSpacingPx.toFloat()) }
state.layoutInfo.assertVisibleItems(count = 4, startIndex = 1)
}
}
@@ -406,17 +353,14 @@
if (viewPortSizeEven) 0 else 1
scope = rememberCoroutineScope()
ScalingLazyColumn(
- state = rememberScalingLazyListState(
- initialCenterItemIndex = autoCenterItem
- ).also { state = it },
- modifier = Modifier.requiredSize(
- viewportSizePx.toDp()
- ),
+ state =
+ rememberScalingLazyListState(initialCenterItemIndex = autoCenterItem).also {
+ state = it
+ },
+ modifier = Modifier.requiredSize(viewportSizePx.toDp()),
autoCentering = AutoCenteringParams(itemIndex = autoCenterItem)
) {
- items(5) {
- Box(Modifier.requiredSize(localItemSizePx.toDp()))
- }
+ items(5) { Box(Modifier.requiredSize(localItemSizePx.toDp())) }
}
}
}
@@ -424,18 +368,14 @@
// TODO(b/210654937): Remove the waitUntil once we no longer need 2 stage initialization
rule.waitUntil { state.initialized.value }
- scope.launch {
- state.animateScrollBy(localItemSizePx.toFloat() * 10)
- }
+ scope.launch { state.animateScrollBy(localItemSizePx.toFloat() * 10) }
rule.mainClock.advanceTimeBy(milliseconds = 1000)
assert(!state.isScrollInProgress)
assertThat(state.centerItemIndex).isEqualTo(4)
assertThat(state.centerItemScrollOffset).isEqualTo(0)
- scope.launch {
- state.animateScrollBy(- localItemSizePx.toFloat() * 10)
- }
+ scope.launch { state.animateScrollBy(-localItemSizePx.toFloat() * 10) }
rule.mainClock.advanceTimeBy(milliseconds = 1000)
assert(!state.isScrollInProgress)
@@ -449,23 +389,17 @@
rule.setContent {
ScalingLazyColumn(
state = rememberScalingLazyListState().also { state = it },
- modifier = Modifier.requiredSize(
- itemSizeDp
- ),
+ modifier = Modifier.requiredSize(itemSizeDp),
autoCentering = null
) {
- items(5) {
- Box(Modifier.requiredSize(itemSizeDp * 5))
- }
+ items(5) { Box(Modifier.requiredSize(itemSizeDp * 5)) }
}
}
// TODO(b/210654937): Remove the waitUntil once we no longer need 2 stage initialization
rule.waitUntil { state.initialized.value }
rule.runOnIdle {
- runBlocking {
- state.scrollBy(itemSizePx.toFloat() + defaultItemSpacingPx.toFloat())
- }
+ runBlocking { state.scrollBy(itemSizePx.toFloat() + defaultItemSpacingPx.toFloat()) }
val firstItem = state.layoutInfo.visibleItemsInfo.first()
assertThat(firstItem.offset).isLessThan(0)
assertThat(firstItem.offset + firstItem.size).isGreaterThan(itemSizePx)
@@ -480,13 +414,9 @@
rule.setContent {
ScalingLazyColumn(
state = rememberScalingLazyListState(centerItemIndex).also { state = it },
- modifier = Modifier.requiredSize(
- itemSizeDp * 3
- ),
+ modifier = Modifier.requiredSize(itemSizeDp * 3),
) {
- items(5) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(5) { Box(Modifier.requiredSize(itemSizeDp)) }
}
}
@@ -510,13 +440,9 @@
rule.setContent {
ScalingLazyColumn(
state = rememberScalingLazyListState(centerItemIndex).also { state = it },
- modifier = Modifier.requiredSize(
- itemSizeDp * 4 + defaultItemSpacingDp * 3
- ),
+ modifier = Modifier.requiredSize(itemSizeDp * 4 + defaultItemSpacingDp * 3),
) {
- items(6) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(6) { Box(Modifier.requiredSize(itemSizeDp)) }
}
}
@@ -524,8 +450,7 @@
rule.waitUntil { state.initialized.value }
rule.runOnIdle {
// Get the middle item on the screen
- val edgeScreenItem =
- state.layoutInfo.visibleItemsInfo.find { it.index == 0 }
+ val edgeScreenItem = state.layoutInfo.visibleItemsInfo.find { it.index == 0 }
// And that it is it scaled
assertThat(edgeScreenItem!!.scale).isLessThan(1.0f)
@@ -538,24 +463,18 @@
rule.setContent {
ScalingLazyColumn(
state = rememberScalingLazyListState().also { state = it },
- modifier = Modifier.requiredSize(
- itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f
- ),
+ modifier = Modifier.requiredSize(itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f),
reverseLayout = true,
autoCentering = null
) {
- items(5) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(5) { Box(Modifier.requiredSize(itemSizeDp)) }
}
}
// TODO(b/210654937): Remove the waitUntil once we no longer need 2 stage initialization
rule.waitUntil { state.initialized.value }
rule.runOnIdle {
- runBlocking {
- state.scrollBy(itemSizePx.toFloat() + defaultItemSpacingPx.toFloat())
- }
+ runBlocking { state.scrollBy(itemSizePx.toFloat() + defaultItemSpacingPx.toFloat()) }
state.layoutInfo.assertVisibleItems(count = 4, startIndex = 1)
}
}
@@ -566,14 +485,10 @@
rule.setContent {
ScalingLazyColumn(
state = rememberScalingLazyListState(2).also { state = it },
- modifier = Modifier.requiredSize(
- itemSizeDp * 2f + defaultItemSpacingDp * 1f
- ),
+ modifier = Modifier.requiredSize(itemSizeDp * 2f + defaultItemSpacingDp * 1f),
scalingParams = ScalingLazyColumnDefaults.scalingParams(1.0f, 1.0f)
) {
- items(5) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(5) { Box(Modifier.requiredSize(itemSizeDp)) }
}
}
@@ -592,14 +507,10 @@
rule.setContent {
ScalingLazyColumn(
state = rememberScalingLazyListState(2, -5).also { state = it },
- modifier = Modifier.requiredSize(
- itemSizeDp * 2f + defaultItemSpacingDp * 1f
- ),
+ modifier = Modifier.requiredSize(itemSizeDp * 2f + defaultItemSpacingDp * 1f),
scalingParams = ScalingLazyColumnDefaults.scalingParams(1.0f, 1.0f)
) {
- items(5) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(5) { Box(Modifier.requiredSize(itemSizeDp)) }
}
}
@@ -618,15 +529,11 @@
rule.setContent {
ScalingLazyColumn(
state = rememberScalingLazyListState(2).also { state = it },
- modifier = Modifier.requiredSize(
- itemSizeDp * 2f + defaultItemSpacingDp * 1f
- ),
+ modifier = Modifier.requiredSize(itemSizeDp * 2f + defaultItemSpacingDp * 1f),
scalingParams = ScalingLazyColumnDefaults.scalingParams(1.0f, 1.0f),
reverseLayout = true
) {
- items(5) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(5) { Box(Modifier.requiredSize(itemSizeDp)) }
}
}
@@ -645,15 +552,11 @@
rule.setContent {
ScalingLazyColumn(
state = rememberScalingLazyListState(2, -5).also { state = it },
- modifier = Modifier.requiredSize(
- itemSizeDp * 2f + defaultItemSpacingDp * 1f
- ),
+ modifier = Modifier.requiredSize(itemSizeDp * 2f + defaultItemSpacingDp * 1f),
scalingParams = ScalingLazyColumnDefaults.scalingParams(1.0f, 1.0f),
reverseLayout = true
) {
- items(5) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(5) { Box(Modifier.requiredSize(itemSizeDp)) }
}
}
@@ -672,15 +575,11 @@
rule.setContent {
ScalingLazyColumn(
state = rememberScalingLazyListState(8).also { state = it },
- modifier = Modifier.requiredSize(
- itemSizeDp * 4f + defaultItemSpacingDp * 3f
- ),
+ modifier = Modifier.requiredSize(itemSizeDp * 4f + defaultItemSpacingDp * 3f),
scalingParams = ScalingLazyColumnDefaults.scalingParams(1.0f, 1.0f),
reverseLayout = true
) {
- items(15) {
- Box(Modifier.requiredSize(itemSizeDp).testTag("Item:$it"))
- }
+ items(15) { Box(Modifier.requiredSize(itemSizeDp).testTag("Item:$it")) }
}
}
@@ -691,9 +590,7 @@
// Assert that items are being shown at the end of the parent as this is reverseLayout
rule.onNodeWithTag(testTag = "Item:8").assertIsDisplayed()
- rule.runOnIdle {
- state.layoutInfo.assertVisibleItems(count = 5, startIndex = 6)
- }
+ rule.runOnIdle { state.layoutInfo.assertVisibleItems(count = 5, startIndex = 6) }
}
@Test
@@ -701,20 +598,13 @@
lateinit var state: ScalingLazyListState
rule.setContent {
ScalingLazyColumn(
- state = rememberScalingLazyListState(initialCenterItemIndex = 0)
- .also { state = it },
- modifier = Modifier.requiredSize(
- itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f
- ),
+ state =
+ rememberScalingLazyListState(initialCenterItemIndex = 0).also { state = it },
+ modifier = Modifier.requiredSize(itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f),
scalingParams = ScalingLazyColumnDefaults.scalingParams(1.0f, 1.0f),
autoCentering = AutoCenteringParams(itemIndex = 0)
) {
- items(5) {
- Box(
- Modifier
- .requiredSize(itemSizeDp)
- .testTag("Item:$it"))
- }
+ items(5) { Box(Modifier.requiredSize(itemSizeDp).testTag("Item:$it")) }
}
}
@@ -729,17 +619,13 @@
assertThat(state.centerItemIndex).isEqualTo(0)
assertThat(state.centerItemScrollOffset).isEqualTo(0)
- runBlocking {
- state.scrollBy(scrollAmount.toFloat())
- }
+ runBlocking { state.scrollBy(scrollAmount.toFloat()) }
state.layoutInfo.assertVisibleItems(count = 4)
assertThat(state.layoutInfo.visibleItemsInfo.first().offset).isEqualTo(-scrollAmount)
}
rule.runOnIdle {
- runBlocking {
- state.scrollBy(-scrollAmount.toFloat())
- }
+ runBlocking { state.scrollBy(-scrollAmount.toFloat()) }
state.layoutInfo.assertVisibleItems(count = 3)
assertThat(state.layoutInfo.visibleItemsInfo.first().offset).isEqualTo(0)
}
@@ -751,15 +637,11 @@
rule.setContent {
ScalingLazyColumn(
state = rememberScalingLazyListState(8).also { state = it },
- modifier = Modifier.requiredSize(
- itemSizeDp * 4f + defaultItemSpacingDp * 3f
- ),
+ modifier = Modifier.requiredSize(itemSizeDp * 4f + defaultItemSpacingDp * 3f),
scalingParams = ScalingLazyColumnDefaults.scalingParams(1.0f, 1.0f),
reverseLayout = true
) {
- items(15) {
- Box(Modifier.requiredSize(itemSizeDp).testTag("Item:$it"))
- }
+ items(15) { Box(Modifier.requiredSize(itemSizeDp).testTag("Item:$it")) }
}
}
@@ -775,16 +657,12 @@
assertThat(state.centerItemIndex).isEqualTo(8)
assertThat(state.centerItemScrollOffset).isEqualTo(0)
- runBlocking {
- state.scrollBy(scrollAmount.toFloat())
- }
+ runBlocking { state.scrollBy(scrollAmount.toFloat()) }
state.layoutInfo.assertVisibleItems(count = 5, startIndex = 7)
}
rule.runOnIdle {
- runBlocking {
- state.scrollBy(-scrollAmount.toFloat())
- }
+ runBlocking { state.scrollBy(-scrollAmount.toFloat()) }
state.layoutInfo.assertVisibleItems(count = 5, startIndex = 6)
}
}
@@ -794,17 +672,13 @@
lateinit var state: ScalingLazyListState
rule.setContent {
ScalingLazyColumn(
- state = rememberScalingLazyListState(initialCenterItemIndex = 0)
- .also { state = it },
- modifier = Modifier.requiredSize(
- itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f
- ),
+ state =
+ rememberScalingLazyListState(initialCenterItemIndex = 0).also { state = it },
+ modifier = Modifier.requiredSize(itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f),
scalingParams = ScalingLazyColumnDefaults.scalingParams(1.0f, 1.0f),
autoCentering = AutoCenteringParams(itemIndex = 0)
) {
- items(5) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(5) { Box(Modifier.requiredSize(itemSizeDp)) }
}
}
@@ -812,18 +686,14 @@
rule.waitUntil { state.initialized.value }
val scrollAmount = itemSizePx.toFloat() + defaultItemSpacingPx.toFloat()
rule.runOnIdle {
- runBlocking {
- state.dispatchRawDelta(scrollAmount)
- }
+ runBlocking { state.dispatchRawDelta(scrollAmount) }
state.layoutInfo.assertVisibleItems(count = 4, startIndex = 0)
assertThat(state.layoutInfo.visibleItemsInfo.first().offset)
.isEqualTo(-scrollAmount.roundToInt())
}
rule.runOnIdle {
- runBlocking {
- state.dispatchRawDelta(-scrollAmount)
- }
+ runBlocking { state.dispatchRawDelta(-scrollAmount) }
state.layoutInfo.assertVisibleItems(count = 3, startIndex = 0)
assertThat(state.layoutInfo.visibleItemsInfo.first().offset).isEqualTo(0)
}
@@ -835,16 +705,12 @@
rule.setContent {
ScalingLazyColumn(
state = rememberScalingLazyListState().also { state = it },
- modifier = Modifier.requiredSize(
- itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f
- ),
+ modifier = Modifier.requiredSize(itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f),
scalingParams = ScalingLazyColumnDefaults.scalingParams(1.0f, 1.0f),
reverseLayout = true,
autoCentering = null
) {
- items(5) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(5) { Box(Modifier.requiredSize(itemSizeDp)) }
}
}
// TODO(b/210654937): Remove the waitUntil once we no longer need 2 stage initialization
@@ -878,22 +744,15 @@
verticalArrangement = Arrangement.spacedBy(spacing),
autoCentering = null
) {
- items(5) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(5) { Box(Modifier.requiredSize(itemSizeDp)) }
}
}
// TODO(b/210654937): Remove the waitUntil once we no longer need 2 stage initialization
rule.waitUntil { state.initialized.value }
rule.runOnIdle {
- val spacingPx = with(rule.density) {
- spacing.roundToPx()
- }
- state.layoutInfo.assertVisibleItems(
- count = 4,
- spacing = spacingPx
- )
+ val spacingPx = with(rule.density) { spacing.roundToPx() }
+ state.layoutInfo.assertVisibleItems(count = 4, spacing = spacingPx)
}
}
@@ -915,9 +774,7 @@
modifier = Modifier.requiredSize(itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f),
autoCentering = null
) {
- items(6) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(6) { Box(Modifier.requiredSize(itemSizeDp)) }
}
ObservingFun(state, currentInfo)
}
@@ -927,9 +784,7 @@
rule.runOnIdle {
// empty it here and scrolling should invoke observingFun again
currentInfo.value = null
- runBlocking {
- state.scrollBy(itemSizePx.toFloat() + defaultItemSpacingPx.toFloat())
- }
+ runBlocking { state.scrollBy(itemSizePx.toFloat() + defaultItemSpacingPx.toFloat()) }
}
rule.runOnIdle {
@@ -948,9 +803,7 @@
modifier = Modifier.requiredSize(itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f),
autoCentering = null
) {
- items(6) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(6) { Box(Modifier.requiredSize(itemSizeDp)) }
}
ObservingFun(state, currentInfo)
}
@@ -993,9 +846,7 @@
state = rememberScalingLazyListState().also { state = it },
modifier = Modifier.requiredSize(itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f)
) {
- items(6) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(6) { Box(Modifier.requiredSize(itemSizeDp)) }
}
ObservingIsScrollInProgressTrueFun(state, currentInfo)
}
@@ -1015,10 +866,7 @@
}
@Composable
- fun ObservingCentralItemIndexFun(
- state: ScalingLazyListState,
- currentInfo: StableRef<Int?>
- ) {
+ fun ObservingCentralItemIndexFun(state: ScalingLazyListState, currentInfo: StableRef<Int?>) {
currentInfo.value = state.centerItemIndex
}
@@ -1034,9 +882,7 @@
modifier = Modifier.requiredSize(itemSizeDp * 3.5f + defaultItemSpacingDp * 2.5f),
autoCentering = null
) {
- items(6) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(6) { Box(Modifier.requiredSize(itemSizeDp)) }
}
ObservingCentralItemIndexFun(state, currentInfo)
}
@@ -1065,12 +911,8 @@
currentInfo = state.layoutInfo
}
rule.setContent {
- ScalingLazyColumn(
- state = rememberScalingLazyListState().also { state = it }
- ) {
- item {
- Box(Modifier.requiredSize(size))
- }
+ ScalingLazyColumn(state = rememberScalingLazyListState().also { state = it }) {
+ item { Box(Modifier.requiredSize(size)) }
}
observingFun()
}
@@ -1100,9 +942,7 @@
Modifier.requiredSize(sizeDp),
state = rememberScalingLazyListState().also { state = it }
) {
- items(4) {
- Box(Modifier.requiredSize(sizeDp))
- }
+ items(4) { Box(Modifier.requiredSize(sizeDp)) }
}
}
@@ -1134,9 +974,7 @@
contentPadding = PaddingValues(top = topPaddingDp, bottom = bottomPaddingDp),
state = rememberScalingLazyListState().also { state = it }
) {
- items(4) {
- Box(Modifier.requiredSize(sizeDp))
- }
+ items(4) { Box(Modifier.requiredSize(sizeDp)) }
}
}
@@ -1163,14 +1001,11 @@
rule.setContent {
ScalingLazyColumn(
Modifier.requiredSize(viewPortSizeDp),
- state = rememberScalingLazyListState(
- initialCenterItemIndex = 0
- ).also { state = it },
+ state =
+ rememberScalingLazyListState(initialCenterItemIndex = 0).also { state = it },
autoCentering = AutoCenteringParams()
) {
- items(7) {
- Box(Modifier.requiredSize(itemSizeDp))
- }
+ items(7) { Box(Modifier.requiredSize(itemSizeDp)) }
}
}
@@ -1184,15 +1019,11 @@
assertThat(state.layoutInfo.beforeAutoCenteringPadding).isGreaterThan(0)
assertThat(state.layoutInfo.afterAutoCenteringPadding).isEqualTo(0)
- runBlocking {
- state.scrollToItem(3)
- }
+ runBlocking { state.scrollToItem(3) }
assertThat(state.layoutInfo.beforeAutoCenteringPadding).isEqualTo(0)
assertThat(state.layoutInfo.afterAutoCenteringPadding).isEqualTo(0)
- runBlocking {
- state.scrollToItem(5)
- }
+ runBlocking { state.scrollToItem(5) }
assertThat(state.layoutInfo.beforeAutoCenteringPadding).isEqualTo(0)
assertThat(state.layoutInfo.afterAutoCenteringPadding).isGreaterThan(0)
}
@@ -1203,12 +1034,8 @@
var count by mutableStateOf(10)
lateinit var state: ScalingLazyListState
rule.setContent {
- ScalingLazyColumn(
- state = rememberScalingLazyListState().also { state = it }
- ) {
- items(count) {
- Box(Modifier.requiredSize(10.dp))
- }
+ ScalingLazyColumn(state = rememberScalingLazyListState().also { state = it }) {
+ items(count) { Box(Modifier.requiredSize(10.dp)) }
}
}
@@ -1219,9 +1046,7 @@
count = 20
}
- rule.runOnIdle {
- assertThat(state.layoutInfo.totalItemsCount).isEqualTo(20)
- }
+ rule.runOnIdle { assertThat(state.layoutInfo.totalItemsCount).isEqualTo(20) }
}
private fun ScalingLazyListLayoutInfo.assertVisibleItems(
diff --git a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/ScrollAwayTest.kt b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/ScrollAwayTest.kt
index 3a237cc..a18c2d3 100644
--- a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/ScrollAwayTest.kt
+++ b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/ScrollAwayTest.kt
@@ -47,8 +47,7 @@
@MediumTest
@RunWith(AndroidJUnit4::class)
public class ScrollAwayTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
@Test
fun hidesTimeTextWithScalingLazyColumn() {
@@ -138,18 +137,16 @@
) {
WithTouchSlop(0f) {
Scaffold(
- modifier = Modifier
- .fillMaxSize()
- .background(MaterialTheme.colors.background),
+ modifier = Modifier.fillMaxSize().background(MaterialTheme.colors.background),
timeText = {
TimeText(
- modifier = Modifier
- .scrollAway(
- scrollState = scrollState,
- itemIndex = itemIndex,
- offset = offset,
- )
- .testTag(TIME_TEXT_TAG)
+ modifier =
+ Modifier.scrollAway(
+ scrollState = scrollState,
+ itemIndex = itemIndex,
+ offset = offset,
+ )
+ .testTag(TIME_TEXT_TAG)
)
},
) {
@@ -159,13 +156,9 @@
autoCentering = AutoCenteringParams(itemIndex = 1, itemOffset = 0),
modifier = Modifier.testTag(SCROLL_TAG)
) {
- item {
- ListHeader { Text("Chips") }
- }
+ item { ListHeader { Text("Chips") } }
- items(5) { i ->
- ChipTest(Modifier.fillParentMaxHeight(0.5f), i)
- }
+ items(5) { i -> ChipTest(Modifier.fillParentMaxHeight(0.5f), i) }
}
}
}
@@ -180,36 +173,32 @@
) {
WithTouchSlop(0f) {
Scaffold(
- modifier = Modifier
- .fillMaxSize()
- .background(MaterialTheme.colors.background),
+ modifier = Modifier.fillMaxSize().background(MaterialTheme.colors.background),
timeText = {
TimeText(
- modifier = Modifier
- .scrollAway(
- scrollState = scrollState,
- itemIndex = itemIndex,
- offset = offset,
- )
- .testTag(TIME_TEXT_TAG)
+ modifier =
+ Modifier.scrollAway(
+ scrollState = scrollState,
+ itemIndex = itemIndex,
+ offset = offset,
+ )
+ .testTag(TIME_TEXT_TAG)
)
},
) {
ScalingLazyColumn(
contentPadding = PaddingValues(10.dp),
state = scrollState,
- autoCentering = androidx.wear.compose.material.AutoCenteringParams(
- itemIndex = 1, itemOffset = 0
- ),
+ autoCentering =
+ androidx.wear.compose.material.AutoCenteringParams(
+ itemIndex = 1,
+ itemOffset = 0
+ ),
modifier = Modifier.testTag(SCROLL_TAG)
) {
- item {
- ListHeader { Text("Chips") }
- }
+ item { ListHeader { Text("Chips") } }
- items(5) { i ->
- ChipTest(Modifier.fillParentMaxHeight(0.5f), i)
- }
+ items(5) { i -> ChipTest(Modifier.fillParentMaxHeight(0.5f), i) }
}
}
}
@@ -241,9 +230,7 @@
rememberLazyListState(
initialFirstVisibleItemIndex = 1,
)
- LazyColumnTest(
- itemIndex = scrollAwayItemIndex, offset = 0.dp, scrollState
- )
+ LazyColumnTest(itemIndex = scrollAwayItemIndex, offset = 0.dp, scrollState)
}
rule.onNodeWithTag(SCROLL_TAG).performTouchInput { swipeUp() }
@@ -254,38 +241,25 @@
}
@Composable
- private fun LazyColumnTest(
- itemIndex: Int,
- offset: Dp,
- scrollState: LazyListState
- ) {
+ private fun LazyColumnTest(itemIndex: Int, offset: Dp, scrollState: LazyListState) {
WithTouchSlop(0f) {
Scaffold(
- modifier = Modifier
- .fillMaxSize()
- .background(MaterialTheme.colors.background),
+ modifier = Modifier.fillMaxSize().background(MaterialTheme.colors.background),
timeText = {
TimeText(
- modifier = Modifier
- .scrollAway(
- scrollState = scrollState,
- itemIndex = itemIndex,
- offset = offset,
- )
- .testTag(TIME_TEXT_TAG)
+ modifier =
+ Modifier.scrollAway(
+ scrollState = scrollState,
+ itemIndex = itemIndex,
+ offset = offset,
+ )
+ .testTag(TIME_TEXT_TAG)
)
},
) {
- LazyColumn(
- state = scrollState,
- modifier = Modifier.testTag(SCROLL_TAG)
- ) {
- item {
- ListHeader { Text("Chips") }
- }
- items(5) { i ->
- ChipTest(Modifier.fillParentMaxHeight(0.5f), i)
- }
+ LazyColumn(state = scrollState, modifier = Modifier.testTag(SCROLL_TAG)) {
+ item { ListHeader { Text("Chips") } }
+ items(5) { i -> ChipTest(Modifier.fillParentMaxHeight(0.5f), i) }
}
}
}
@@ -295,7 +269,7 @@
private fun ChipTest(modifier: Modifier, i: Int) {
Chip(
modifier = modifier,
- onClick = { },
+ onClick = {},
colors = ChipDefaults.primaryChipColors(),
border = ChipDefaults.chipBorder()
) {
diff --git a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/SelectableChipTest.kt b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/SelectableChipTest.kt
index c3d34d8..bc5645a 100644
--- a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/SelectableChipTest.kt
+++ b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/SelectableChipTest.kt
@@ -53,8 +53,7 @@
import org.junit.Test
class SelectableChipTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
@Test
fun supports_testtag() {
@@ -86,6 +85,7 @@
rule.onNodeWithTag(TEST_TAG).assertExists()
}
+
@Test
fun has_clickaction_when_enabled() {
rule.setContentWithTheme {
@@ -148,13 +148,9 @@
)
}
- rule.onNodeWithTag(TEST_TAG)
- .assert(
- SemanticsMatcher.expectValue(
- SemanticsProperties.Role,
- Role.RadioButton
- )
- )
+ rule
+ .onNodeWithTag(TEST_TAG)
+ .assert(SemanticsMatcher.expectValue(SemanticsProperties.Role, Role.RadioButton))
}
@Test
@@ -362,11 +358,7 @@
)
}
- rule
- .onNodeWithTag(TEST_TAG)
- .assertIsNotSelected()
- .performClick()
- .assertIsSelected()
+ rule.onNodeWithTag(TEST_TAG).assertIsNotSelected().performClick().assertIsSelected()
}
@Test
@@ -406,11 +398,7 @@
)
}
- rule
- .onNodeWithTag(TEST_TAG)
- .assertIsNotSelected()
- .performClick()
- .assertIsNotSelected()
+ rule.onNodeWithTag(TEST_TAG).assertIsNotSelected().performClick().assertIsNotSelected()
}
@Test
@@ -449,13 +437,10 @@
)
}
- rule.onNodeWithTag(TEST_TAG).onChildAt(0)
- .assert(
- SemanticsMatcher.expectValue(
- SemanticsProperties.Role,
- Role.Button
- )
- )
+ rule
+ .onNodeWithTag(TEST_TAG)
+ .onChildAt(0)
+ .assert(SemanticsMatcher.expectValue(SemanticsProperties.Role, Role.Button))
}
@Test
@@ -491,29 +476,28 @@
rule.onNodeWithText(textContent).assertExists()
}
- @Test
- fun gives_chip_correct_height() =
- verifyChipHeight(ChipDefaults.Height)
+ @Test fun gives_chip_correct_height() = verifyChipHeight(ChipDefaults.Height)
@Test
fun gives_chip_adjustable_height() {
val expectedMinHeight = SelectableChipDefaults.Height + 1.dp
- rule.setContentWithThemeForSizeAssertions {
- SelectableChip(
- selected = true,
- onClick = {},
- label = {
- Text(
- text = "SelectableChip text spanning over multiple lines of text " +
- "to test height is adjustable. This should exceed the minimum height" +
- " for the SelectableChip."
- )
- },
- selectionControl = {
- RadioButton(selected = true)
- }
- )
- }.assertHeightIsAtLeast(expectedMinHeight)
+ rule
+ .setContentWithThemeForSizeAssertions {
+ SelectableChip(
+ selected = true,
+ onClick = {},
+ label = {
+ Text(
+ text =
+ "SelectableChip text spanning over multiple lines of text " +
+ "to test height is adjustable. This should exceed the minimum height" +
+ " for the SelectableChip."
+ )
+ },
+ selectionControl = { RadioButton(selected = true) }
+ )
+ }
+ .assertHeightIsAtLeast(expectedMinHeight)
}
private fun verifyChipHeight(expectedHeight: Dp) {
@@ -527,30 +511,29 @@
}
}
- @Test
- fun gives_split_chip_correct_height() =
- verifySplitChipHeight(ChipDefaults.Height)
+ @Test fun gives_split_chip_correct_height() = verifySplitChipHeight(ChipDefaults.Height)
@Test
fun gives_split_chip_adjustable_height() {
val expectedMinHeight = SelectableChipDefaults.Height + 1.dp
- rule.setContentWithThemeForSizeAssertions {
- SplitSelectableChip(
- selected = true,
- onSelectionClick = {},
- onContainerClick = {},
- label = {
- Text(
- text = "SplitSelectableChip text spanning over multiple lines of text " +
- "to test height is adjustable. This should exceed the minimum height " +
- "for the SplitSelectableChip."
- )
- },
- selectionControl = {
- RadioButton(selected = true)
- }
- )
- }.assertHeightIsAtLeast(expectedMinHeight)
+ rule
+ .setContentWithThemeForSizeAssertions {
+ SplitSelectableChip(
+ selected = true,
+ onSelectionClick = {},
+ onContainerClick = {},
+ label = {
+ Text(
+ text =
+ "SplitSelectableChip text spanning over multiple lines of text " +
+ "to test height is adjustable. This should exceed the minimum height " +
+ "for the SplitSelectableChip."
+ )
+ },
+ selectionControl = { RadioButton(selected = true) }
+ )
+ }
+ .assertHeightIsAtLeast(expectedMinHeight)
}
private fun verifySplitChipHeight(expectedHeight: Dp) {
@@ -652,9 +635,10 @@
selected = true,
onClick = {},
enabled = true,
- colors = SelectableChipDefaults.selectableChipColors(
- selectedContentColor = override
- ),
+ colors =
+ SelectableChipDefaults.selectableChipColors(
+ selectedContentColor = override
+ ),
label = { actualContentColor = LocalContentColor.current },
selectionControl = {},
modifier = Modifier.testTag(TEST_TAG)
@@ -676,9 +660,8 @@
selected = true,
onSelectionClick = {},
enabled = true,
- colors = SelectableChipDefaults.splitSelectableChipColors(
- contentColor = override
- ),
+ colors =
+ SelectableChipDefaults.splitSelectableChipColors(contentColor = override),
label = { actualContentColor = LocalContentColor.current },
selectionControl = {},
onContainerClick = {},
@@ -711,7 +694,8 @@
actualBackgrondColor = MaterialTheme.colors.surface
}
- rule.onNodeWithTag(TEST_TAG)
+ rule
+ .onNodeWithTag(TEST_TAG)
.captureToImage()
.assertContainsColor(actualBackgrondColor, 50.0f)
}
@@ -727,9 +711,10 @@
selected = true,
onSelectionClick = {},
enabled = true,
- colors = SelectableChipDefaults.splitSelectableChipColors(
- backgroundColor = override
- ),
+ colors =
+ SelectableChipDefaults.splitSelectableChipColors(
+ backgroundColor = override
+ ),
label = {},
selectionControl = {},
onContainerClick = {},
@@ -738,9 +723,7 @@
}
}
- rule.onNodeWithTag(TEST_TAG)
- .captureToImage()
- .assertContainsColor(override, 50.0f)
+ rule.onNodeWithTag(TEST_TAG).captureToImage().assertContainsColor(override, 50.0f)
}
private fun verifyColors(
@@ -760,11 +743,7 @@
rule.setContentWithTheme {
expectedLabel = labelColor()
expectedIcon = selectionControlColor()
- Box(
- modifier = Modifier
- .fillMaxSize()
- .background(Color.Transparent)
- ) {
+ Box(modifier = Modifier.fillMaxSize().background(Color.Transparent)) {
if (splitSelectableChip) {
SplitSelectableChip(
selected = selected,
@@ -811,8 +790,5 @@
}
private fun ComposeContentTestRule.verifyHeight(expected: Dp, content: @Composable () -> Unit) {
- setContentWithThemeForSizeAssertions {
- content()
- }
- .assertHeightIsEqualTo(expected)
+ setContentWithThemeForSizeAssertions { content() }.assertHeightIsEqualTo(expected)
}
diff --git a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/SliderScreenshotTest.kt b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/SliderScreenshotTest.kt
index 8736b21..284ae59 100644
--- a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/SliderScreenshotTest.kt
+++ b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/SliderScreenshotTest.kt
@@ -41,14 +41,11 @@
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
class SliderScreenshotTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
- @get:Rule
- val screenshotRule = AndroidXScreenshotTestRule(SCREENSHOT_GOLDEN_PATH)
+ @get:Rule val screenshotRule = AndroidXScreenshotTestRule(SCREENSHOT_GOLDEN_PATH)
- @get:Rule
- val testName = TestName()
+ @get:Rule val testName = TestName()
@Test
fun inlineslider_not_segmented() {
@@ -59,13 +56,14 @@
segmented = false,
increaseIcon = { Icon(InlineSliderDefaults.Increase, "Increase") },
decreaseIcon = { Icon(InlineSliderDefaults.Decrease, "Decrease") },
- onValueChange = { },
+ onValueChange = {},
valueRange = 1f..4f,
steps = 2
)
}
- rule.onNodeWithTag(TEST_TAG)
+ rule
+ .onNodeWithTag(TEST_TAG)
.captureToImage()
.assertAgainstGolden(screenshotRule, testName.methodName)
}
@@ -79,13 +77,14 @@
segmented = true,
increaseIcon = { Icon(InlineSliderDefaults.Increase, "Increase") },
decreaseIcon = { Icon(InlineSliderDefaults.Decrease, "Decrease") },
- onValueChange = { },
+ onValueChange = {},
valueRange = 1f..4f,
steps = 2
)
}
- rule.onNodeWithTag(TEST_TAG)
+ rule
+ .onNodeWithTag(TEST_TAG)
.captureToImage()
.assertAgainstGolden(screenshotRule, testName.methodName)
}
@@ -99,23 +98,25 @@
segmented = true,
increaseIcon = { Icon(InlineSliderDefaults.Increase, "Increase") },
decreaseIcon = { Icon(InlineSliderDefaults.Decrease, "Decrease") },
- colors = InlineSliderDefaults.colors(
- backgroundColor = Color.Green,
- spacerColor = Color.Yellow,
- selectedBarColor = Color.Magenta,
- unselectedBarColor = Color.White,
- disabledBackgroundColor = Color.DarkGray,
- disabledSpacerColor = Color.LightGray,
- disabledSelectedBarColor = Color.Red,
- disabledUnselectedBarColor = Color.Blue
- ),
- onValueChange = { },
+ colors =
+ InlineSliderDefaults.colors(
+ backgroundColor = Color.Green,
+ spacerColor = Color.Yellow,
+ selectedBarColor = Color.Magenta,
+ unselectedBarColor = Color.White,
+ disabledBackgroundColor = Color.DarkGray,
+ disabledSpacerColor = Color.LightGray,
+ disabledSelectedBarColor = Color.Red,
+ disabledUnselectedBarColor = Color.Blue
+ ),
+ onValueChange = {},
valueRange = 1f..4f,
steps = 2
)
}
- rule.onNodeWithTag(TEST_TAG)
+ rule
+ .onNodeWithTag(TEST_TAG)
.captureToImage()
.assertAgainstGolden(screenshotRule, testName.methodName)
}
@@ -126,25 +127,18 @@
InlineSlider(
modifier = Modifier.testTag(TEST_TAG),
value = 2f,
- onValueChange = { },
+ onValueChange = {},
valueRange = 1f..4f,
- decreaseIcon = {
- Icon(
- imageVector = Icons.Default.Star,
- contentDescription = ""
- )
- },
+ decreaseIcon = { Icon(imageVector = Icons.Default.Star, contentDescription = "") },
increaseIcon = {
- Icon(
- imageVector = Icons.Filled.ThumbUp,
- contentDescription = ""
- )
+ Icon(imageVector = Icons.Filled.ThumbUp, contentDescription = "")
},
steps = 2
)
}
- rule.onNodeWithTag(TEST_TAG)
+ rule
+ .onNodeWithTag(TEST_TAG)
.captureToImage()
.assertAgainstGolden(screenshotRule, testName.methodName)
}
@@ -159,23 +153,25 @@
segmented = true,
increaseIcon = { Icon(InlineSliderDefaults.Increase, "Increase") },
decreaseIcon = { Icon(InlineSliderDefaults.Decrease, "Decrease") },
- colors = InlineSliderDefaults.colors(
- backgroundColor = Color.Green,
- spacerColor = Color.Yellow,
- selectedBarColor = Color.Magenta,
- unselectedBarColor = Color.White,
- disabledBackgroundColor = Color.DarkGray,
- disabledSpacerColor = Color.LightGray,
- disabledSelectedBarColor = Color.Red,
- disabledUnselectedBarColor = Color.Blue
- ),
- onValueChange = { },
+ colors =
+ InlineSliderDefaults.colors(
+ backgroundColor = Color.Green,
+ spacerColor = Color.Yellow,
+ selectedBarColor = Color.Magenta,
+ unselectedBarColor = Color.White,
+ disabledBackgroundColor = Color.DarkGray,
+ disabledSpacerColor = Color.LightGray,
+ disabledSelectedBarColor = Color.Red,
+ disabledUnselectedBarColor = Color.Blue
+ ),
+ onValueChange = {},
valueRange = 1f..4f,
steps = 2
)
}
- rule.onNodeWithTag(TEST_TAG)
+ rule
+ .onNodeWithTag(TEST_TAG)
.captureToImage()
.assertAgainstGolden(screenshotRule, testName.methodName)
}
@@ -187,25 +183,18 @@
modifier = Modifier.testTag(TEST_TAG),
value = 2f,
enabled = false,
- onValueChange = { },
+ onValueChange = {},
valueRange = 1f..4f,
- decreaseIcon = {
- Icon(
- imageVector = Icons.Default.Star,
- contentDescription = ""
- )
- },
+ decreaseIcon = { Icon(imageVector = Icons.Default.Star, contentDescription = "") },
increaseIcon = {
- Icon(
- imageVector = Icons.Filled.ThumbUp,
- contentDescription = ""
- )
+ Icon(imageVector = Icons.Filled.ThumbUp, contentDescription = "")
},
steps = 2
)
}
- rule.onNodeWithTag(TEST_TAG)
+ rule
+ .onNodeWithTag(TEST_TAG)
.captureToImage()
.assertAgainstGolden(screenshotRule, testName.methodName)
}
diff --git a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/StepperScreenshotTest.kt b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/StepperScreenshotTest.kt
index 837e4d1..0662daa 100644
--- a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/StepperScreenshotTest.kt
+++ b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/StepperScreenshotTest.kt
@@ -47,14 +47,11 @@
@RunWith(AndroidJUnit4::class)
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
public class StepperScreenshotTest {
- @get:Rule
- public val rule = createComposeRule()
+ @get:Rule public val rule = createComposeRule()
- @get:Rule
- public val screenshotRule = AndroidXScreenshotTestRule(SCREENSHOT_GOLDEN_PATH)
+ @get:Rule public val screenshotRule = AndroidXScreenshotTestRule(SCREENSHOT_GOLDEN_PATH)
- @get:Rule
- public val testName = TestName()
+ @get:Rule public val testName = TestName()
@Test
public fun stepper_no_content() {
@@ -69,7 +66,8 @@
) {}
}
- rule.onNodeWithTag(TEST_TAG)
+ rule
+ .onNodeWithTag(TEST_TAG)
.captureToImage()
.assertAgainstGolden(screenshotRule, testName.methodName)
}
@@ -82,22 +80,15 @@
value = 2f,
steps = 3,
onValueChange = {},
- decreaseIcon = {
- Icon(
- imageVector = Icons.Default.Star,
- contentDescription = ""
- )
- },
+ decreaseIcon = { Icon(imageVector = Icons.Default.Star, contentDescription = "") },
increaseIcon = {
- Icon(
- imageVector = Icons.Filled.ThumbUp,
- contentDescription = ""
- )
+ Icon(imageVector = Icons.Filled.ThumbUp, contentDescription = "")
},
) {}
}
- rule.onNodeWithTag(TEST_TAG)
+ rule
+ .onNodeWithTag(TEST_TAG)
.captureToImage()
.assertAgainstGolden(screenshotRule, testName.methodName)
}
@@ -117,17 +108,13 @@
onClick = {},
modifier = Modifier.width(146.dp),
colors = ChipDefaults.secondaryChipColors(),
- label = {
- Text(
- text = "Demo",
- modifier = Modifier.fillMaxWidth()
- )
- }
+ label = { Text(text = "Demo", modifier = Modifier.fillMaxWidth()) }
)
}
}
- rule.onNodeWithTag(TEST_TAG)
+ rule
+ .onNodeWithTag(TEST_TAG)
.captureToImage()
.assertAgainstGolden(screenshotRule, testName.methodName)
}
@@ -150,7 +137,8 @@
}
}
- rule.onNodeWithTag(TEST_TAG)
+ rule
+ .onNodeWithTag(TEST_TAG)
.captureToImage()
.assertAgainstGolden(screenshotRule, testName.methodName)
}
@@ -159,9 +147,5 @@
private fun ComposeContentTestRule.setContentWithThemeAndBackground(
composable: @Composable () -> Unit
) {
- setContentWithTheme {
- Box(modifier = Modifier.background(Color.Black)) {
- composable()
- }
- }
+ setContentWithTheme { Box(modifier = Modifier.background(Color.Black)) { composable() } }
}
diff --git a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/StepperTest.kt b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/StepperTest.kt
index 5359636..1ae6c613 100644
--- a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/StepperTest.kt
+++ b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/StepperTest.kt
@@ -49,8 +49,7 @@
import org.junit.Test
public class StepperTest {
- @get:Rule
- public val rule = createComposeRule()
+ @get:Rule public val rule = createComposeRule()
@Test
public fun supports_testtag() {
@@ -69,22 +68,24 @@
}
@Test
- public fun coerces_value_top_limit() = rule.setNewValueAndCheck(
- range = 0f..10f,
- steps = 4,
- initialValue = 4f,
- newValue = 20f,
- expectedFinalValue = 10f
- )
+ public fun coerces_value_top_limit() =
+ rule.setNewValueAndCheck(
+ range = 0f..10f,
+ steps = 4,
+ initialValue = 4f,
+ newValue = 20f,
+ expectedFinalValue = 10f
+ )
@Test
- public fun coerces_value_lower_limit() = rule.setNewValueAndCheck(
- range = 0f..10f,
- steps = 4,
- initialValue = 4f,
- newValue = -20f,
- expectedFinalValue = 0f
- )
+ public fun coerces_value_lower_limit() =
+ rule.setNewValueAndCheck(
+ range = 0f..10f,
+ steps = 4,
+ initialValue = 4f,
+ newValue = -20f,
+ expectedFinalValue = 0f
+ )
@Test(expected = IllegalArgumentException::class)
public fun throws_when_steps_negative() {
@@ -100,34 +101,37 @@
}
@Test
- public fun coerce_value_exactly() = rule.setNewValueAndCheck(
- range = 0f..1f,
- steps = 4,
- initialValue = 0f,
- // Allowed values are only 0, 0.2, 0.4, 0.6, 0.8, 1
- newValue = 0.6f,
- expectedFinalValue = 0.6f
- )
+ public fun coerce_value_exactly() =
+ rule.setNewValueAndCheck(
+ range = 0f..1f,
+ steps = 4,
+ initialValue = 0f,
+ // Allowed values are only 0, 0.2, 0.4, 0.6, 0.8, 1
+ newValue = 0.6f,
+ expectedFinalValue = 0.6f
+ )
@Test
- public fun coerce_value_to_previous() = rule.setNewValueAndCheck(
- range = 0f..1f,
- steps = 4,
- initialValue = 0f,
- // Allowed values are only 0, 0.2, 0.4, 0.6, 0.8, 1
- newValue = 0.65f,
- expectedFinalValue = 0.6f
- )
+ public fun coerce_value_to_previous() =
+ rule.setNewValueAndCheck(
+ range = 0f..1f,
+ steps = 4,
+ initialValue = 0f,
+ // Allowed values are only 0, 0.2, 0.4, 0.6, 0.8, 1
+ newValue = 0.65f,
+ expectedFinalValue = 0.6f
+ )
@Test
- public fun coerce_value_to_next() = rule.setNewValueAndCheck(
- range = 0f..1f,
- steps = 4,
- initialValue = 0f,
- // Allowed values are only 0, 0.2, 0.4, 0.6, 0.8, 1
- newValue = 0.55f,
- expectedFinalValue = 0.6f
- )
+ public fun coerce_value_to_next() =
+ rule.setNewValueAndCheck(
+ range = 0f..1f,
+ steps = 4,
+ initialValue = 0f,
+ // Allowed values are only 0, 0.2, 0.4, 0.6, 0.8, 1
+ newValue = 0.55f,
+ expectedFinalValue = 0.6f
+ )
@Test
public fun decreases_value_by_clicking_bottom() {
@@ -139,9 +143,7 @@
// The clickable area for a decrease button takes bottom 35% of the screen
rule.onNodeWithTag(TEST_TAG).performTouchInput { click(Offset(width / 2f, height - 15f)) }
- rule.runOnIdle {
- Truth.assertThat(state.value).isWithin(0.001f).of(1f)
- }
+ rule.runOnIdle { Truth.assertThat(state.value).isWithin(0.001f).of(1f) }
}
@Test
@@ -154,9 +156,7 @@
// The clickable area for an increase button takes top 35% of the screen
rule.onNodeWithTag(TEST_TAG).performTouchInput { click(Offset(width / 2f, 15f)) }
- rule.runOnIdle {
- Truth.assertThat(state.value).isWithin(0.001f).of(3f)
- }
+ rule.runOnIdle { Truth.assertThat(state.value).isWithin(0.001f).of(3f) }
}
@Test
@@ -170,9 +170,7 @@
// The clickable area for a decrease button takes bottom 35% of the screen
rule.onNodeWithTag(TEST_TAG).performTouchInput { click(Offset(width / 2f, height - 15f)) }
- rule.runOnIdle {
- Truth.assertThat(state.value).isWithin(0.001f).of(1f)
- }
+ rule.runOnIdle { Truth.assertThat(state.value).isWithin(0.001f).of(1f) }
}
@Test
@@ -186,9 +184,7 @@
// The clickable area for an increase button takes top 35% of the screen
rule.onNodeWithTag(TEST_TAG).performTouchInput { click(Offset(width / 2f, 15f)) }
- rule.runOnIdle {
- Truth.assertThat(state.value).isWithin(0.001f).of(4f)
- }
+ rule.runOnIdle { Truth.assertThat(state.value).isWithin(0.001f).of(4f) }
}
@Test
@@ -228,7 +224,7 @@
modifier = Modifier.testTag(TEST_TAG),
value = 0f,
steps = 5,
- onValueChange = { },
+ onValueChange = {},
increaseIcon = { Icon(StepperDefaults.Increase, "Increase") },
decreaseIcon = {
Icon(
@@ -242,11 +238,11 @@
val unclippedBoundsInRoot = rule.onRoot().getUnclippedBoundsInRoot()
rule.waitForIdle()
- rule.onNodeWithTag(iconTag, true)
+ rule
+ .onNodeWithTag(iconTag, true)
.assertExists()
.assertTopPositionInRootIsEqualTo(
- unclippedBoundsInRoot.height -
- BorderVerticalMargin - DefaultIconHeight
+ unclippedBoundsInRoot.height - BorderVerticalMargin - DefaultIconHeight
)
}
@@ -259,7 +255,7 @@
modifier = Modifier.testTag(TEST_TAG),
value = 0f,
steps = 5,
- onValueChange = { },
+ onValueChange = {},
increaseIcon = {
Icon(
modifier = Modifier.testTag(iconTag),
@@ -271,7 +267,8 @@
) {}
}
rule.waitForIdle()
- rule.onNodeWithTag(iconTag, true)
+ rule
+ .onNodeWithTag(iconTag, true)
.assertExists()
.assertTopPositionInRootIsEqualTo(BorderVerticalMargin)
}
@@ -287,7 +284,7 @@
steps = 5,
increaseIcon = { Icon(StepperDefaults.Increase, "Increase") },
decreaseIcon = { Icon(StepperDefaults.Decrease, "Decrease") },
- onValueChange = { },
+ onValueChange = {},
) {
Text("Testing", modifier = Modifier.testTag(contentTag).fillMaxHeight())
}
@@ -296,7 +293,8 @@
val rootHeight = rule.onRoot().getUnclippedBoundsInRoot().height
rule.waitForIdle()
- rule.onNodeWithTag(contentTag, true)
+ rule
+ .onNodeWithTag(contentTag, true)
.assertExists()
.assertTopPositionInRootIsEqualTo(
// Position of the content is a weight(35%) of (top button minus 2 spacers 8dp each)
@@ -316,12 +314,13 @@
steps = 5,
increaseIcon = { Icon(StepperDefaults.Increase, testContentDescription) },
decreaseIcon = { Icon(StepperDefaults.Decrease, "Decrease") },
- onValueChange = { },
+ onValueChange = {},
) {}
}
rule.waitForIdle()
- rule.onNodeWithTag(TEST_TAG, true)
+ rule
+ .onNodeWithTag(TEST_TAG, true)
// 0 is the index of increase button, 1 - decrease button, content is empty
.onChildAt(0)
.onChild()
@@ -339,12 +338,13 @@
steps = 5,
increaseIcon = { Icon(StepperDefaults.Increase, "Increase") },
decreaseIcon = { Icon(StepperDefaults.Decrease, testContentDescription) },
- onValueChange = { },
+ onValueChange = {},
) {}
}
rule.waitForIdle()
- rule.onNodeWithTag(TEST_TAG, true)
+ rule
+ .onNodeWithTag(TEST_TAG, true)
// 0 is the index of increase button, 1 - decrease button, content is empty
.onChildAt(1)
.onChild()
@@ -365,14 +365,15 @@
value = value,
steps = steps,
valueRange = valueRange,
- onValueChange = { },
+ onValueChange = {},
increaseIcon = { Icon(StepperDefaults.Increase, "Increase") },
decreaseIcon = { Icon(StepperDefaults.Decrease, "Decrease") },
) {}
}
rule.waitForIdle()
- rule.onNodeWithTag(TEST_TAG, true)
+ rule
+ .onNodeWithTag(TEST_TAG, true)
.assertExists()
.assertRangeInfoEquals(ProgressBarRangeInfo(value, valueRange, steps))
}
@@ -389,7 +390,7 @@
value = value,
steps = steps,
valueRange = valueRange,
- onValueChange = { },
+ onValueChange = {},
increaseIcon = { Icon(StepperDefaults.Increase, "Increase") },
decreaseIcon = { Icon(StepperDefaults.Decrease, "Decrease") },
enableRangeSemantics = false
@@ -397,7 +398,8 @@
}
rule.waitForIdle()
// Should throw assertion error for assertRangeInfoEquals
- rule.onNodeWithTag(TEST_TAG, true)
+ rule
+ .onNodeWithTag(TEST_TAG, true)
.assertExists()
.assertRangeInfoEquals(ProgressBarRangeInfo(value, valueRange, steps))
}
@@ -445,8 +447,7 @@
}
public class IntegerStepperTest {
- @get:Rule
- public val rule = createComposeRule()
+ @get:Rule public val rule = createComposeRule()
@Test
public fun supports_testtag() {
@@ -477,49 +478,53 @@
) {}
}
- rule.onNodeWithTag(TEST_TAG)
- .assertRangeInfoEquals(ProgressBarRangeInfo(1f, 0f..10f, 9))
+ rule.onNodeWithTag(TEST_TAG).assertRangeInfoEquals(ProgressBarRangeInfo(1f, 0f..10f, 9))
}
@Test
- public fun coerces_value_top_limit() = rule.setNewValueAndCheck(
- progression = 0..10,
- initialValue = 4,
- newValue = 20,
- expectedFinalValue = 10
- )
+ public fun coerces_value_top_limit() =
+ rule.setNewValueAndCheck(
+ progression = 0..10,
+ initialValue = 4,
+ newValue = 20,
+ expectedFinalValue = 10
+ )
@Test
- public fun coerces_value_lower_limit() = rule.setNewValueAndCheck(
- progression = 0..10,
- initialValue = 4,
- newValue = -20,
- expectedFinalValue = 0
- )
+ public fun coerces_value_lower_limit() =
+ rule.setNewValueAndCheck(
+ progression = 0..10,
+ initialValue = 4,
+ newValue = -20,
+ expectedFinalValue = 0
+ )
@Test
- public fun coerce_value_exactly() = rule.setNewValueAndCheck(
- progression = IntProgression.fromClosedRange(0, 12, 3),
- initialValue = 0,
- newValue = 3,
- expectedFinalValue = 3
- )
+ public fun coerce_value_exactly() =
+ rule.setNewValueAndCheck(
+ progression = IntProgression.fromClosedRange(0, 12, 3),
+ initialValue = 0,
+ newValue = 3,
+ expectedFinalValue = 3
+ )
@Test
- public fun coerce_value_to_previous() = rule.setNewValueAndCheck(
- progression = IntProgression.fromClosedRange(0, 12, 3),
- initialValue = 0,
- newValue = 4,
- expectedFinalValue = 3
- )
+ public fun coerce_value_to_previous() =
+ rule.setNewValueAndCheck(
+ progression = IntProgression.fromClosedRange(0, 12, 3),
+ initialValue = 0,
+ newValue = 4,
+ expectedFinalValue = 3
+ )
@Test
- public fun coerce_value_to_next() = rule.setNewValueAndCheck(
- progression = IntProgression.fromClosedRange(0, 12, 3),
- initialValue = 0,
- newValue = 5,
- expectedFinalValue = 6
- )
+ public fun coerce_value_to_next() =
+ rule.setNewValueAndCheck(
+ progression = IntProgression.fromClosedRange(0, 12, 3),
+ initialValue = 0,
+ newValue = 5,
+ expectedFinalValue = 6
+ )
@Test
fun supports_stepper_range_semantics_by_default() {
@@ -538,7 +543,8 @@
}
rule.waitForIdle()
// Should throw assertion error for assertRangeInfoEquals
- rule.onNodeWithTag(TEST_TAG, true)
+ rule
+ .onNodeWithTag(TEST_TAG, true)
.assertExists()
.assertRangeInfoEquals(
ProgressBarRangeInfo(
@@ -567,7 +573,8 @@
}
rule.waitForIdle()
// Should throw assertion error for assertRangeInfoEquals
- rule.onNodeWithTag(TEST_TAG, true)
+ rule
+ .onNodeWithTag(TEST_TAG, true)
.assertExists()
.assertRangeInfoEquals(
ProgressBarRangeInfo(
diff --git a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/SwipeToDismissBoxScreenshotTest.kt b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/SwipeToDismissBoxScreenshotTest.kt
index 4136132..bd94e78 100644
--- a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/SwipeToDismissBoxScreenshotTest.kt
+++ b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/SwipeToDismissBoxScreenshotTest.kt
@@ -53,14 +53,11 @@
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
class SwipeToDismissBoxScreenshotTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
- @get:Rule
- val screenshotRule = AndroidXScreenshotTestRule(SCREENSHOT_GOLDEN_PATH)
+ @get:Rule val screenshotRule = AndroidXScreenshotTestRule(SCREENSHOT_GOLDEN_PATH)
- @get:Rule
- val testName = TestName()
+ @get:Rule val testName = TestName()
@Test
fun swiped_to_right_25_percent_ltr() {
@@ -84,26 +81,22 @@
@Test
fun on_dismiss_overload_swiped_to_right_25_percent_ltr() {
- verifySwipedScreenshot(LayoutDirection.Ltr, 0.25f, true,
- "swiped_to_right_25_percent_ltr")
+ verifySwipedScreenshot(LayoutDirection.Ltr, 0.25f, true, "swiped_to_right_25_percent_ltr")
}
@Test
fun on_dismiss_overload_swiped_to_right_25_percent_rtl() {
- verifySwipedScreenshot(LayoutDirection.Rtl, 0.25f, true,
- "swiped_to_right_25_percent_rtl")
+ verifySwipedScreenshot(LayoutDirection.Rtl, 0.25f, true, "swiped_to_right_25_percent_rtl")
}
@Test
fun on_dismiss_overload_swiped_to_right_50_percent_ltr() {
- verifySwipedScreenshot(LayoutDirection.Ltr, 0.5f, true,
- "swiped_to_right_50_percent_ltr")
+ verifySwipedScreenshot(LayoutDirection.Ltr, 0.5f, true, "swiped_to_right_50_percent_ltr")
}
@Test
fun on_dismiss_overload_swiped_to_right_50_percent_rtl() {
- verifySwipedScreenshot(LayoutDirection.Rtl, 0.5f, true,
- "swiped_to_right_50_percent_rtl")
+ verifySwipedScreenshot(LayoutDirection.Rtl, 0.5f, true, "swiped_to_right_50_percent_rtl")
}
private fun verifySwipedScreenshot(
@@ -115,12 +108,13 @@
val screenShotSizeDp = SCREENSHOT_SIZE.dp
rule.setContentWithTheme {
val originalConfiguration = LocalConfiguration.current
- val fixedScreenSizeConfiguration = remember(originalConfiguration) {
- Configuration(originalConfiguration).apply {
- screenWidthDp = SCREENSHOT_SIZE
- screenHeightDp = SCREENSHOT_SIZE
+ val fixedScreenSizeConfiguration =
+ remember(originalConfiguration) {
+ Configuration(originalConfiguration).apply {
+ screenWidthDp = SCREENSHOT_SIZE
+ screenHeightDp = SCREENSHOT_SIZE
+ }
}
- }
CompositionLocalProvider(
LocalLayoutDirection provides layoutDirection,
@@ -130,18 +124,14 @@
if (isOnDismissOverload) {
SwipeToDismissBox(
onDismissed = {},
- modifier = Modifier
- .testTag(TEST_TAG)
- .size(screenShotSizeDp),
+ modifier = Modifier.testTag(TEST_TAG).size(screenShotSizeDp),
state = state
) { isBackground ->
boxContent(isBackground = isBackground)
}
} else {
SwipeToDismissBox(
- modifier = Modifier
- .testTag(TEST_TAG)
- .size(screenShotSizeDp),
+ modifier = Modifier.testTag(TEST_TAG).size(screenShotSizeDp),
state = state
) { isBackground ->
boxContent(isBackground = isBackground)
@@ -154,7 +144,8 @@
moveTo(Offset(x = width * swipedPercentage, y = height / 2f))
}
- rule.onNodeWithTag(TEST_TAG)
+ rule
+ .onNodeWithTag(TEST_TAG)
.captureToImage()
.assertAgainstGolden(screenshotRule, goldenIdentifier)
}
diff --git a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/SwipeToDismissBoxTest.kt b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/SwipeToDismissBoxTest.kt
index 42f7b95..868e95d 100644
--- a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/SwipeToDismissBoxTest.kt
+++ b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/SwipeToDismissBoxTest.kt
@@ -59,17 +59,13 @@
import org.junit.Test
class SwipeToDismissBoxTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
@Test
fun supports_testtag() {
rule.setContentWithTheme {
val state = rememberSwipeToDismissBoxState()
- SwipeToDismissBox(
- state = state,
- modifier = Modifier.testTag(TEST_TAG)
- ) {
+ SwipeToDismissBox(state = state, modifier = Modifier.testTag(TEST_TAG)) {
Text("Testing")
}
}
@@ -88,14 +84,16 @@
@Test
fun does_not_dismiss_when_swipe_right_incomplete() =
- // Execute a partial swipe over a longer-than-default duration so that there
+ // Execute a partial swipe over a longer-than-default duration so that there
// is insufficient velocity to perform a 'fling'.
verifySwipe(
- gesture = { swipeWithVelocity(
- start = Offset(0f, centerY),
- end = Offset(centerX / 2f, centerY),
- endVelocity = 1.0f
- ) },
+ gesture = {
+ swipeWithVelocity(
+ start = Offset(0f, centerY),
+ end = Offset(centerX / 2f, centerY),
+ endVelocity = 1.0f
+ )
+ },
expectedToDismiss = false
)
@@ -120,8 +118,7 @@
rule.setContentWithTheme {
val state = rememberSwipeToDismissBoxState()
LaunchedEffect(state.currentValue) {
- dismissed =
- state.currentValue == SwipeToDismissValue.Dismissed
+ dismissed = state.currentValue == SwipeToDismissValue.Dismissed
}
SwipeToDismissBox(
state = state,
@@ -134,9 +131,7 @@
rule.onNodeWithTag(TEST_TAG).performTouchInput({ swipeRight() })
- rule.runOnIdle {
- assertEquals(false, dismissed)
- }
+ rule.runOnIdle { assertEquals(false, dismissed) }
}
@Test
@@ -157,10 +152,8 @@
backgroundKey = if (showCounterForContent.value) TOGGLE_SCREEN else COUNTER_SCREEN,
contentKey = if (showCounterForContent.value) COUNTER_SCREEN else TOGGLE_SCREEN,
content = { isBackground ->
- if (showCounterForContent.value xor isBackground)
- counterScreen(holder)
- else
- toggleScreen(holder)
+ if (showCounterForContent.value xor isBackground) counterScreen(holder)
+ else toggleScreen(holder)
}
)
}
@@ -197,8 +190,7 @@
rule.setContentWithTheme {
val outerState = rememberSwipeToDismissBoxState()
LaunchedEffect(outerState.currentValue) {
- outerDismissed =
- outerState.currentValue == SwipeToDismissValue.Dismissed
+ outerDismissed = outerState.currentValue == SwipeToDismissValue.Dismissed
}
SwipeToDismissBox(
state = outerState,
@@ -208,8 +200,7 @@
Text("Outer", color = MaterialTheme.colors.onPrimary)
val innerState = rememberSwipeToDismissBoxState()
LaunchedEffect(innerState.currentValue) {
- innerDismissed =
- innerState.currentValue == SwipeToDismissValue.Dismissed
+ innerDismissed = innerState.currentValue == SwipeToDismissValue.Dismissed
}
SwipeToDismissBox(
state = innerState,
@@ -250,10 +241,7 @@
fun counterScreen(saveableStateHolder: SaveableStateHolder) {
saveableStateHolder.SaveableStateProvider(COUNTER_SCREEN) {
var counter by rememberSaveable { mutableStateOf(0) }
- Button(
- onClick = { ++counter },
- modifier = Modifier.testTag(COUNTER_SCREEN)
- ) {
+ Button(onClick = { ++counter }, modifier = Modifier.testTag(COUNTER_SCREEN)) {
Text(text = "" + counter)
}
}
@@ -264,8 +252,7 @@
verifyPartialSwipe(expectedMessage = BACKGROUND_MESSAGE)
@Test
- fun displays_content_during_swipe() =
- verifyPartialSwipe(expectedMessage = CONTENT_MESSAGE)
+ fun displays_content_during_swipe() = verifyPartialSwipe(expectedMessage = CONTENT_MESSAGE)
@Test
fun calls_ondismissed_after_swipe_when_supplied() {
@@ -281,17 +268,12 @@
rule.onNodeWithTag(TEST_TAG).performTouchInput({ swipeRight() })
- rule.runOnIdle {
- assertEquals(true, dismissed)
- }
+ rule.runOnIdle { assertEquals(true, dismissed) }
}
@Test
fun edgeswipe_modifier_edge_swiped_right_dismissed() {
- verifyEdgeSwipeWithNestedScroll(
- gesture = { swipeRight() },
- expectedToDismiss = true
- )
+ verifyEdgeSwipeWithNestedScroll(gesture = { swipeRight() }, expectedToDismiss = true)
}
@Test
@@ -345,9 +327,7 @@
}
rule.onNodeWithTag(TEST_TAG).performTouchInput { swipeRight(0f, 200f) }
- rule.runOnIdle {
- assertThat(horizontalScrollState.value == initialScrollState).isTrue()
- }
+ rule.runOnIdle { assertThat(horizontalScrollState.value == initialScrollState).isTrue() }
}
@Test
@@ -367,9 +347,7 @@
}
rule.onNodeWithTag(TEST_TAG).performTouchInput { swipeRight(200f, 400f) }
- rule.runOnIdle {
- assertThat(horizontalScrollState.value < initialScrollState).isTrue()
- }
+ rule.runOnIdle { assertThat(horizontalScrollState.value < initialScrollState).isTrue() }
}
@Test
@@ -444,18 +422,15 @@
}
}
- rule.onNodeWithTag(TEST_TAG)
- .performTouchInput {
- swipeBothDirections(
- startLeft = startLeft,
- startX = initialTouch,
- amplitude = amplitude,
- duration = duration
- )
- }
- rule.runOnIdle {
- testScrollState(horizontalScrollState)
+ rule.onNodeWithTag(TEST_TAG).performTouchInput {
+ swipeBothDirections(
+ startLeft = startLeft,
+ startX = initialTouch,
+ amplitude = amplitude,
+ duration = duration
+ )
}
+ rule.runOnIdle { testScrollState(horizontalScrollState) }
}
private fun verifySwipe(gesture: TouchInjectionScope.() -> Unit, expectedToDismiss: Boolean) {
@@ -463,8 +438,7 @@
rule.setContentWithTheme {
val state = rememberSwipeToDismissBoxState()
LaunchedEffect(state.currentValue) {
- dismissed =
- state.currentValue == SwipeToDismissValue.Dismissed
+ dismissed = state.currentValue == SwipeToDismissValue.Dismissed
}
SwipeToDismissBox(
state = state,
@@ -476,9 +450,7 @@
rule.onNodeWithTag(TEST_TAG).performTouchInput(gesture)
- rule.runOnIdle {
- assertEquals(expectedToDismiss, dismissed)
- }
+ rule.runOnIdle { assertEquals(expectedToDismiss, dismissed) }
}
private fun verifyEdgeSwipeWithNestedScroll(
@@ -492,8 +464,7 @@
val horizontalScrollState = rememberScrollState(initialScrollState)
LaunchedEffect(state.currentValue) {
- dismissed =
- state.currentValue == SwipeToDismissValue.Dismissed
+ dismissed = state.currentValue == SwipeToDismissValue.Dismissed
}
SwipeToDismissBox(
state = state,
@@ -505,9 +476,7 @@
rule.onNodeWithTag(TEST_TAG).performTouchInput(gesture)
- rule.runOnIdle {
- assertEquals(expectedToDismiss, dismissed)
- }
+ rule.runOnIdle { assertEquals(expectedToDismiss, dismissed) }
}
private fun verifyPartialSwipe(expectedMessage: String) {
@@ -524,12 +493,12 @@
// Click down and drag across 1/4 of the screen to start a swipe,
// but don't release the finger, so that the screen can be inspected
// (note that swipeRight would release the finger and does not pause time midway).
- rule.onNodeWithTag(TEST_TAG).performTouchInput(
- {
+ rule
+ .onNodeWithTag(TEST_TAG)
+ .performTouchInput({
down(Offset(x = 0f, y = height / 2f))
moveTo(Offset(x = width / 4f, y = height / 2f))
- }
- )
+ })
rule.onNodeWithText(expectedMessage).assertExists()
}
@@ -552,11 +521,13 @@
) {
Box(modifier = Modifier.fillMaxSize()) {
Text(
- modifier = Modifier.align(Alignment.Center)
- .edgeSwipeToDismiss(swipeToDismissState)
- .horizontalScroll(horizontalScrollState),
- text = "This text can be scrolled horizontally - to dismiss, swipe " +
- "right from the left edge of the screen (called Edge Swiping)",
+ modifier =
+ Modifier.align(Alignment.Center)
+ .edgeSwipeToDismiss(swipeToDismissState)
+ .horizontalScroll(horizontalScrollState),
+ text =
+ "This text can be scrolled horizontally - to dismiss, swipe " +
+ "right from the left edge of the screen (called Edge Swiping)",
)
}
}
@@ -569,15 +540,17 @@
) {
val sign = if (startLeft) -1 else 1
// By using sin function for range 0.. 3pi/2 , we can achieve 0 -> 1 and 1 -> -1 values
- swipe(curve = { time ->
- val x =
- startX + sign * sin(time.toFloat() / duration.toFloat() * 3 * Math.PI / 2)
- .toFloat() * amplitude
- Offset(
- x = x,
- y = centerY
- )
- }, durationMillis = duration)
+ swipe(
+ curve = { time ->
+ val x =
+ startX +
+ sign *
+ sin(time.toFloat() / duration.toFloat() * 3 * Math.PI / 2).toFloat() *
+ amplitude
+ Offset(x = x, y = centerY)
+ },
+ durationMillis = duration
+ )
}
}
diff --git a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/SwipeToRevealScreenshotTest.kt b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/SwipeToRevealScreenshotTest.kt
index 68cc691..6dd1581a 100644
--- a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/SwipeToRevealScreenshotTest.kt
+++ b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/SwipeToRevealScreenshotTest.kt
@@ -46,21 +46,15 @@
@RequiresApi(Build.VERSION_CODES.O)
@OptIn(ExperimentalWearMaterialApi::class, ExperimentalWearFoundationApi::class)
class SwipeToRevealScreenshotTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
- @get:Rule
- val screenshotRule = AndroidXScreenshotTestRule(SCREENSHOT_GOLDEN_PATH)
+ @get:Rule val screenshotRule = AndroidXScreenshotTestRule(SCREENSHOT_GOLDEN_PATH)
- @get:Rule
- val testName = TestName()
+ @get:Rule val testName = TestName()
@Test
fun swipeToRevealCard_singleAction() {
- rule.verifyScreenshot(
- screenshotRule = screenshotRule,
- methodName = testName.methodName
- ) {
+ rule.verifyScreenshot(screenshotRule = screenshotRule, methodName = testName.methodName) {
swipeToRevealCard(
revealState = rememberRevealState(initialValue = RevealValue.Revealing),
secondaryAction = null
@@ -70,10 +64,7 @@
@Test
fun swipeToRevealChip_singleAction() {
- rule.verifyScreenshot(
- screenshotRule = screenshotRule,
- methodName = testName.methodName
- ) {
+ rule.verifyScreenshot(screenshotRule = screenshotRule, methodName = testName.methodName) {
swipeToRevealChip(
revealState = rememberRevealState(initialValue = RevealValue.Revealing),
secondaryAction = null
@@ -83,10 +74,7 @@
@Test
fun swipeToRevealCard_twoActions() {
- rule.verifyScreenshot(
- screenshotRule = screenshotRule,
- methodName = testName.methodName
- ) {
+ rule.verifyScreenshot(screenshotRule = screenshotRule, methodName = testName.methodName) {
swipeToRevealCard(
revealState = rememberRevealState(initialValue = RevealValue.Revealing)
)
@@ -95,10 +83,7 @@
@Test
fun swipeToRevealChip_twoActions() {
- rule.verifyScreenshot(
- screenshotRule = screenshotRule,
- methodName = testName.methodName
- ) {
+ rule.verifyScreenshot(screenshotRule = screenshotRule, methodName = testName.methodName) {
swipeToRevealChip(
revealState = rememberRevealState(initialValue = RevealValue.Revealing)
)
@@ -107,10 +92,7 @@
@Test
fun swipeToRevealChip_undoPrimaryAction() {
- rule.verifyScreenshot(
- screenshotRule = screenshotRule,
- methodName = testName.methodName
- ) {
+ rule.verifyScreenshot(screenshotRule = screenshotRule, methodName = testName.methodName) {
swipeToRevealChip(
revealState = rememberRevealState(initialValue = RevealValue.Revealed)
)
@@ -119,10 +101,7 @@
@Test
fun swipeToRevealCard_undoPrimaryAction() {
- rule.verifyScreenshot(
- screenshotRule = screenshotRule,
- methodName = testName.methodName
- ) {
+ rule.verifyScreenshot(screenshotRule = screenshotRule, methodName = testName.methodName) {
swipeToRevealCard(
revealState = rememberRevealState(initialValue = RevealValue.Revealed)
)
@@ -131,33 +110,23 @@
@Test
fun swipeToRevealChip_undoSecondaryAction() {
- rule.verifyScreenshot(
- screenshotRule = screenshotRule,
- methodName = testName.methodName
- ) {
+ rule.verifyScreenshot(screenshotRule = screenshotRule, methodName = testName.methodName) {
val revealState = rememberRevealState()
val coroutineScope = rememberCoroutineScope()
coroutineScope.launch { revealState.animateTo(RevealValue.Revealed) }
revealState.lastActionType = RevealActionType.SecondaryAction
- swipeToRevealChip(
- revealState = revealState
- )
+ swipeToRevealChip(revealState = revealState)
}
}
@Test
fun swipeToRevealCard_undoSecondaryAction() {
- rule.verifyScreenshot(
- screenshotRule = screenshotRule,
- methodName = testName.methodName
- ) {
+ rule.verifyScreenshot(screenshotRule = screenshotRule, methodName = testName.methodName) {
val revealState = rememberRevealState()
val coroutineScope = rememberCoroutineScope()
coroutineScope.launch { revealState.animateTo(RevealValue.Revealed) }
revealState.lastActionType = RevealActionType.SecondaryAction
- swipeToRevealCard(
- revealState = revealState
- )
+ swipeToRevealCard(revealState = revealState)
}
}
diff --git a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/SwipeToRevealTest.kt b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/SwipeToRevealTest.kt
index a6eeae6..80ce95b 100644
--- a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/SwipeToRevealTest.kt
+++ b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/SwipeToRevealTest.kt
@@ -45,50 +45,39 @@
@OptIn(ExperimentalWearFoundationApi::class, ExperimentalWearMaterialApi::class)
class SwipeToRevealTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
@Test
fun supports_testTag_onChip() {
- rule.setContentWithTheme {
- swipeToRevealChipDefault(modifier = Modifier.testTag(TEST_TAG))
- }
+ rule.setContentWithTheme { swipeToRevealChipDefault(modifier = Modifier.testTag(TEST_TAG)) }
rule.onNodeWithTag(TEST_TAG).assertExists()
}
@Test
fun supports_testTag_onCard() {
- rule.setContentWithTheme {
- swipeToRevealCardDefault(modifier = Modifier.testTag(TEST_TAG))
- }
+ rule.setContentWithTheme { swipeToRevealCardDefault(modifier = Modifier.testTag(TEST_TAG)) }
rule.onNodeWithTag(TEST_TAG).assertExists()
}
@Test
fun supports_testTag_onContent_onChip() {
- rule.setContentWithTheme {
- swipeToRevealChipDefault()
- }
+ rule.setContentWithTheme { swipeToRevealChipDefault() }
rule.onNodeWithTag(CONTENT_TAG).assertExists()
}
@Test
fun supports_testTag_onContent_onCard() {
- rule.setContentWithTheme {
- swipeToRevealCardDefault()
- }
+ rule.setContentWithTheme { swipeToRevealCardDefault() }
rule.onNodeWithTag(CONTENT_TAG).assertExists()
}
@Test
fun whenNotRevealed_actionsDoNotExist_inChip() {
- rule.setContentWithTheme {
- swipeToRevealChipDefault()
- }
+ rule.setContentWithTheme { swipeToRevealChipDefault() }
rule.onNodeWithTag(PRIMARY_ACTION_TAG).assertDoesNotExist()
rule.onNodeWithTag(SECONDARY_ACTION_TAG).assertDoesNotExist()
@@ -97,9 +86,7 @@
@Test
fun whenNotRevealed_actionsDoNotExist_inCard() {
- rule.setContentWithTheme {
- swipeToRevealCardDefault()
- }
+ rule.setContentWithTheme { swipeToRevealCardDefault() }
rule.onNodeWithTag(PRIMARY_ACTION_TAG).assertDoesNotExist()
rule.onNodeWithTag(SECONDARY_ACTION_TAG).assertDoesNotExist()
@@ -182,10 +169,7 @@
swipeToRevealChipDefault(
revealState = revealState,
primaryAction = {
- createPrimaryAction(
- revealState = revealState,
- onClick = { clicked = true }
- )
+ createPrimaryAction(revealState = revealState, onClick = { clicked = true })
}
)
}
@@ -202,10 +186,7 @@
swipeToRevealChipDefault(
revealState = revealState,
secondaryAction = {
- createSecondaryAction(
- revealState = revealState,
- onClick = { clicked = true }
- )
+ createSecondaryAction(revealState = revealState, onClick = { clicked = true })
}
)
}
@@ -320,9 +301,7 @@
createSecondaryAction(
revealState = revealState,
onClick = {
- coroutineScope.launch {
- revealState.animateTo(RevealValue.Revealed)
- }
+ coroutineScope.launch { revealState.animateTo(RevealValue.Revealed) }
}
)
},
@@ -366,10 +345,12 @@
)
}
- rule.onNodeWithTag(PRIMARY_ACTION_TAG)
+ rule
+ .onNodeWithTag(PRIMARY_ACTION_TAG)
.captureToImage()
.assertContainsColor(primaryActionColor, 50.0f)
- rule.onNodeWithTag(SECONDARY_ACTION_TAG)
+ rule
+ .onNodeWithTag(SECONDARY_ACTION_TAG)
.captureToImage()
.assertContainsColor(secondaryActionColor)
}
@@ -382,17 +363,20 @@
rule.setContentWithTheme {
swipeToRevealChipDefault(
revealState = rememberRevealState(initialValue = RevealValue.Revealing),
- colors = SwipeToRevealDefaults.actionColors(
- primaryActionBackgroundColor = overridePrimaryActionColor,
- secondaryActionBackgroundColor = overrideSecondaryActionColor
- )
+ colors =
+ SwipeToRevealDefaults.actionColors(
+ primaryActionBackgroundColor = overridePrimaryActionColor,
+ secondaryActionBackgroundColor = overrideSecondaryActionColor
+ )
)
}
- rule.onNodeWithTag(PRIMARY_ACTION_TAG)
+ rule
+ .onNodeWithTag(PRIMARY_ACTION_TAG)
.captureToImage()
.assertContainsColor(overridePrimaryActionColor, 50.0f)
- rule.onNodeWithTag(SECONDARY_ACTION_TAG)
+ rule
+ .onNodeWithTag(SECONDARY_ACTION_TAG)
.captureToImage()
.assertContainsColor(overrideSecondaryActionColor, 50.0f)
}
@@ -402,15 +386,14 @@
modifier: Modifier = Modifier,
revealState: RevealState = rememberRevealState(),
primaryAction: @Composable RevealScope.() -> Unit = { createPrimaryAction(revealState) },
- secondaryAction: @Composable RevealScope.() -> Unit =
- { createSecondaryAction(revealState) },
- undoPrimaryAction: (@Composable RevealScope.() -> Unit)? =
- { createUndoAction(revealState) },
+ secondaryAction: @Composable RevealScope.() -> Unit = {
+ createSecondaryAction(revealState)
+ },
+ undoPrimaryAction: (@Composable RevealScope.() -> Unit)? = {
+ createUndoAction(revealState)
+ },
undoSecondaryAction: (@Composable RevealScope.() -> Unit)? = {
- createUndoAction(
- revealState,
- modifier = Modifier.testTag(UNDO_SECONDARY_ACTION_TAG)
- )
+ createUndoAction(revealState, modifier = Modifier.testTag(UNDO_SECONDARY_ACTION_TAG))
},
onFullSwipe: () -> Unit = {},
colors: SwipeToRevealActionColors = SwipeToRevealDefaults.actionColors(),
@@ -434,15 +417,14 @@
modifier: Modifier = Modifier,
revealState: RevealState = rememberRevealState(),
primaryAction: @Composable RevealScope.() -> Unit = { createPrimaryAction(revealState) },
- secondaryAction: @Composable RevealScope.() -> Unit =
- { createSecondaryAction(revealState) },
- undoPrimaryAction: (@Composable RevealScope.() -> Unit)? =
- { createUndoAction(revealState) },
+ secondaryAction: @Composable RevealScope.() -> Unit = {
+ createSecondaryAction(revealState)
+ },
+ undoPrimaryAction: (@Composable RevealScope.() -> Unit)? = {
+ createUndoAction(revealState)
+ },
undoSecondaryAction: (@Composable RevealScope.() -> Unit)? = {
- createUndoAction(
- revealState,
- modifier = Modifier.testTag(UNDO_SECONDARY_ACTION_TAG)
- )
+ createUndoAction(revealState, modifier = Modifier.testTag(UNDO_SECONDARY_ACTION_TAG))
},
onFullSwipe: () -> Unit = {},
colors: SwipeToRevealActionColors = SwipeToRevealDefaults.actionColors(),
@@ -509,12 +491,8 @@
}
@Composable
- private fun createContent(
- modifier: Modifier = Modifier
- ) = Box(modifier = modifier
- .fillMaxWidth()
- .height(50.dp)
- .testTag(CONTENT_TAG))
+ private fun createContent(modifier: Modifier = Modifier) =
+ Box(modifier = modifier.fillMaxWidth().height(50.dp).testTag(CONTENT_TAG))
private val CONTENT_TAG = "Content"
private val PRIMARY_ACTION_TAG = "Action"
diff --git a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/SwipeableTest.kt b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/SwipeableTest.kt
index 21427f7..6c21dd8 100644
--- a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/SwipeableTest.kt
+++ b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/SwipeableTest.kt
@@ -48,8 +48,7 @@
// supports property nested scrolling, but the tests should all still be valid.
@OptIn(ExperimentalWearMaterialApi::class)
class SwipeableTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
@Test
fun hasHorizontalScrollSemantics_atMaxValue_whenUnswiped() {
@@ -63,7 +62,8 @@
}
}
- rule.onNodeWithTag(TEST_TAG)
+ rule
+ .onNodeWithTag(TEST_TAG)
.assert(hasScrollRangeCloseTo(Horizontal, value = 1f, maxValue = 1f))
.assert(keyNotDefined(VerticalScrollAxisRange))
}
@@ -80,7 +80,8 @@
}
}
- rule.onNodeWithTag(TEST_TAG)
+ rule
+ .onNodeWithTag(TEST_TAG)
.assert(hasScrollRangeCloseTo(Vertical, value = 1f, maxValue = 1f))
.assert(keyNotDefined(HorizontalScrollAxisRange))
}
@@ -97,19 +98,17 @@
}
}
- rule.onNodeWithTag(TEST_TAG)
- .performTouchInput {
- down(centerLeft)
- moveTo(centerLeft + percentOffset(.25f, 0f))
- }
- rule.onNodeWithTag(TEST_TAG)
+ rule.onNodeWithTag(TEST_TAG).performTouchInput {
+ down(centerLeft)
+ moveTo(centerLeft + percentOffset(.25f, 0f))
+ }
+ rule
+ .onNodeWithTag(TEST_TAG)
.assert(hasScrollRangeCloseTo(Horizontal, value = 0.75f, maxValue = 1f))
- rule.onNodeWithTag(TEST_TAG)
- .performTouchInput {
- moveTo(center)
- }
- rule.onNodeWithTag(TEST_TAG)
+ rule.onNodeWithTag(TEST_TAG).performTouchInput { moveTo(center) }
+ rule
+ .onNodeWithTag(TEST_TAG)
.assert(hasScrollRangeCloseTo(Horizontal, value = 0.5f, maxValue = 1f))
}
@@ -126,12 +125,12 @@
}
}
- rule.onNodeWithTag(TEST_TAG)
- .performTouchInput {
- down(centerRight)
- moveTo(centerRight - percentOffset(.25f, 0f))
- }
- rule.onNodeWithTag(TEST_TAG)
+ rule.onNodeWithTag(TEST_TAG).performTouchInput {
+ down(centerRight)
+ moveTo(centerRight - percentOffset(.25f, 0f))
+ }
+ rule
+ .onNodeWithTag(TEST_TAG)
.assert(
hasScrollRangeCloseTo(
orientation = Horizontal,
@@ -141,11 +140,9 @@
)
)
- rule.onNodeWithTag(TEST_TAG)
- .performTouchInput {
- moveTo(center)
- }
- rule.onNodeWithTag(TEST_TAG)
+ rule.onNodeWithTag(TEST_TAG).performTouchInput { moveTo(center) }
+ rule
+ .onNodeWithTag(TEST_TAG)
.assert(
hasScrollRangeCloseTo(
orientation = Horizontal,
@@ -169,7 +166,8 @@
}
}
- rule.onNodeWithTag(TEST_TAG)
+ rule
+ .onNodeWithTag(TEST_TAG)
.assert(keyNotDefined(HorizontalScrollAxisRange))
.assert(keyNotDefined(VerticalScrollAxisRange))
}
@@ -181,11 +179,12 @@
@Composable
private fun SimpleSwipeableBox(swipeableModifier: (Size) -> Modifier) {
val originalViewConfiguration = LocalViewConfiguration.current
- val viewConfiguration = remember(originalViewConfiguration) {
- object : ViewConfiguration by originalViewConfiguration {
- override val touchSlop: Float = 0f
+ val viewConfiguration =
+ remember(originalViewConfiguration) {
+ object : ViewConfiguration by originalViewConfiguration {
+ override val touchSlop: Float = 0f
+ }
}
- }
with(LocalDensity.current) {
val size = 100.dp
@@ -193,8 +192,7 @@
CompositionLocalProvider(LocalViewConfiguration provides viewConfiguration) {
Box(
- Modifier
- .testTag(TEST_TAG)
+ Modifier.testTag(TEST_TAG)
.requiredSize(size)
.then(remember { swipeableModifier(Size(sizePx, sizePx)) })
)
@@ -211,19 +209,22 @@
value: Float,
maxValue: Float,
reverseScrolling: Boolean = false
- ): SemanticsMatcher = SemanticsMatcher(
- "has $orientation scroll range [0,$maxValue] with " +
- "value=$value" + if (reverseScrolling) " (reversed)" else ""
- ) { node ->
- val threshold = .1f
- val property = when (orientation) {
- Horizontal -> HorizontalScrollAxisRange
- Vertical -> VerticalScrollAxisRange
+ ): SemanticsMatcher =
+ SemanticsMatcher(
+ "has $orientation scroll range [0,$maxValue] with " +
+ "value=$value" +
+ if (reverseScrolling) " (reversed)" else ""
+ ) { node ->
+ val threshold = .1f
+ val property =
+ when (orientation) {
+ Horizontal -> HorizontalScrollAxisRange
+ Vertical -> VerticalScrollAxisRange
+ }
+ node.config.getOrNull(property)?.let { range ->
+ (range.value() - value).absoluteValue <= threshold &&
+ range.maxValue() == maxValue &&
+ range.reverseScrolling == reverseScrolling
+ } ?: false
}
- node.config.getOrNull(property)?.let { range ->
- (range.value() - value).absoluteValue <= threshold &&
- range.maxValue() == maxValue &&
- range.reverseScrolling == reverseScrolling
- } ?: false
- }
}
diff --git a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/TextTest.kt b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/TextTest.kt
index 2422922..0865756 100644
--- a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/TextTest.kt
+++ b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/TextTest.kt
@@ -44,20 +44,20 @@
@RunWith(AndroidJUnit4::class)
class TextTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
- private val ExpectedTextStyle = TextStyle(
- color = Color.Red,
- fontSize = 32.sp,
- fontStyle = FontStyle.Italic,
- fontWeight = FontWeight.Normal,
- fontFamily = FontFamily.Default,
- letterSpacing = 1.sp,
- textDecoration = TextDecoration.Underline,
- textAlign = TextAlign.End,
- lineHeight = 10.sp,
- )
+ private val ExpectedTextStyle =
+ TextStyle(
+ color = Color.Red,
+ fontSize = 32.sp,
+ fontStyle = FontStyle.Italic,
+ fontWeight = FontWeight.Normal,
+ fontFamily = FontFamily.Default,
+ letterSpacing = 1.sp,
+ textDecoration = TextDecoration.Underline,
+ textAlign = TextAlign.End,
+ lineHeight = 10.sp,
+ )
private val TestText = "TestText"
@@ -72,13 +72,11 @@
}
}
- assertThat(
- localTextStyle?.platformStyle?.paragraphStyle?.includeFontPadding
- ).isEqualTo(false)
+ assertThat(localTextStyle?.platformStyle?.paragraphStyle?.includeFontPadding)
+ .isEqualTo(false)
- assertThat(
- display1TextStyle?.platformStyle?.paragraphStyle?.includeFontPadding
- ).isEqualTo(false)
+ assertThat(display1TextStyle?.platformStyle?.paragraphStyle?.includeFontPadding)
+ .isEqualTo(false)
}
@Test
@@ -93,47 +91,30 @@
"Lorem ipsum",
minLines = 1,
maxLines = 3,
- onTextLayout = {
- size1 = it.size.height
- }
+ onTextLayout = { size1 = it.size.height }
)
Text(
"Lorem ipsum",
minLines = 2,
maxLines = 3,
- onTextLayout = {
- size2 = it.size.height
- }
+ onTextLayout = { size2 = it.size.height }
)
}
}
}
- rule.runOnIdle {
- assertThat(size2).isGreaterThan(size1)
- }
+ rule.runOnIdle { assertThat(size2).isGreaterThan(size1) }
}
@Test(expected = IllegalArgumentException::class)
fun validateMinLinesGreaterThanZero() {
- rule.setContent {
- Text(
- TestText,
- minLines = 0
- )
- }
+ rule.setContent { Text(TestText, minLines = 0) }
}
@Test(expected = IllegalArgumentException::class)
fun validateMaxLinesGreaterThanMinLines() {
- rule.setContent {
- Text(
- TestText,
- minLines = 2,
- maxLines = 1
- )
- }
+ rule.setContent { Text(TestText, minLines = 2, maxLines = 1) }
}
@Test
@@ -148,18 +129,14 @@
Text(
TestText,
color = expectedColor,
- onTextLayout = {
- textColor = it.layoutInput.style.color
- }
+ onTextLayout = { textColor = it.layoutInput.style.color }
)
}
}
}
}
- rule.runOnIdle {
- assertThat(textColor).isEqualTo(expectedColor)
- }
+ rule.runOnIdle { assertThat(textColor).isEqualTo(expectedColor) }
}
@Test
@@ -170,20 +147,13 @@
CompositionLocalProvider(LocalContentColor provides Color.Blue) {
ProvideTextStyle(ExpectedTextStyle) {
Box(Modifier.background(Color.White)) {
- Text(
- TestText,
- onTextLayout = {
- textColor = it.layoutInput.style.color
- }
- )
+ Text(TestText, onTextLayout = { textColor = it.layoutInput.style.color })
}
}
}
}
- rule.runOnIdle {
- assertThat(textColor).isEqualTo(ExpectedTextStyle.color)
- }
+ rule.runOnIdle { assertThat(textColor).isEqualTo(ExpectedTextStyle.color) }
}
@Test
@@ -192,20 +162,13 @@
rule.setContent {
CompositionLocalProvider(LocalContentColor provides Color.Blue) {
- Box(Modifier.background(Color.White)) {
- Text(
- TestText,
- onTextLayout = {
- textColor = it.layoutInput.style.color
- }
- )
- }
+ Box(Modifier.background(Color.White)) {
+ Text(TestText, onTextLayout = { textColor = it.layoutInput.style.color })
+ }
}
}
- rule.runOnIdle {
- assertThat(textColor).isEqualTo(Color.Blue)
- }
+ rule.runOnIdle { assertThat(textColor).isEqualTo(Color.Blue) }
}
@Test
diff --git a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/TimeTextTest.kt b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/TimeTextTest.kt
index ed7b8a0..c85cf93 100644
--- a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/TimeTextTest.kt
+++ b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/TimeTextTest.kt
@@ -45,16 +45,11 @@
import org.junit.Test
class TimeTextTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
@Test
fun supports_testtag() {
- rule.setContentWithTheme {
- TimeText(
- modifier = Modifier.testTag(TEST_TAG)
- )
- }
+ rule.setContentWithTheme { TimeText(modifier = Modifier.testTag(TEST_TAG)) }
rule.onNodeWithTag(TEST_TAG).assertExists()
}
@@ -67,11 +62,11 @@
DeviceConfigurationOverride(DeviceConfigurationOverride.RoundScreen(false)) {
TimeText(
modifier = Modifier.testTag(TEST_TAG),
- timeSource = object : TimeSource {
- override val currentTime: String
- @Composable
- get() = timeState.value
- },
+ timeSource =
+ object : TimeSource {
+ override val currentTime: String
+ @Composable get() = timeState.value
+ },
)
}
}
@@ -88,11 +83,11 @@
DeviceConfigurationOverride(DeviceConfigurationOverride.RoundScreen(true)) {
TimeText(
modifier = Modifier.testTag(TEST_TAG),
- timeSource = object : TimeSource {
- override val currentTime: String
- @Composable
- get() = timeState.value
- },
+ timeSource =
+ object : TimeSource {
+ override val currentTime: String
+ @Composable get() = timeState.value
+ },
)
}
}
@@ -366,11 +361,7 @@
rule.setContentWithTheme {
DeviceConfigurationOverride(DeviceConfigurationOverride.RoundScreen(true)) {
TimeText(
- endCurvedContent = {
- curvedText(
- text = "End content"
- )
- },
+ endCurvedContent = { curvedText(text = "End content") },
textLinearSeparator = {
TimeTextDefaults.TextSeparator(
modifier = Modifier.testTag(LINEAR_SEPARATOR_ITEM_TAG)
@@ -434,16 +425,8 @@
rule.setContentWithTheme {
DeviceConfigurationOverride(DeviceConfigurationOverride.RoundScreen(true)) {
TimeText(
- startCurvedContent = {
- curvedText(
- text = "Start content"
- )
- },
- endCurvedContent = {
- curvedText(
- text = "End content"
- )
- },
+ startCurvedContent = { curvedText(text = "Start content") },
+ endCurvedContent = { curvedText(text = "End content") },
textLinearSeparator = {
TimeTextDefaults.TextSeparator(
modifier = Modifier.testTag(LINEAR_SEPARATOR_ITEM_TAG)
@@ -471,19 +454,16 @@
fun changes_timeTextStyle_on_square_device() {
val timeText = "testTime"
- val testTextStyle = TextStyle(
- color = Color.Green,
- background = Color.Black,
- fontSize = 20.sp
- )
+ val testTextStyle =
+ TextStyle(color = Color.Green, background = Color.Black, fontSize = 20.sp)
rule.setContentWithTheme {
DeviceConfigurationOverride(DeviceConfigurationOverride.RoundScreen(false)) {
TimeText(
- timeSource = object : TimeSource {
- override val currentTime: String
- @Composable
- get() = timeText
- },
+ timeSource =
+ object : TimeSource {
+ override val currentTime: String
+ @Composable get() = timeText
+ },
timeTextStyle = testTextStyle
)
}
@@ -498,26 +478,23 @@
fun changes_material_theme_on_square_device() {
val timeText = "testTime"
- val testTextStyle = TextStyle(
- color = Color.Green,
- background = Color.Black,
- fontStyle = FontStyle.Italic,
- fontSize = 25.sp,
- fontFamily = FontFamily.SansSerif
- )
+ val testTextStyle =
+ TextStyle(
+ color = Color.Green,
+ background = Color.Black,
+ fontStyle = FontStyle.Italic,
+ fontSize = 25.sp,
+ fontFamily = FontFamily.SansSerif
+ )
rule.setContent {
- MaterialTheme(
- typography = MaterialTheme.typography.copy(
- caption1 = testTextStyle
- )
- ) {
+ MaterialTheme(typography = MaterialTheme.typography.copy(caption1 = testTextStyle)) {
DeviceConfigurationOverride(DeviceConfigurationOverride.RoundScreen(false)) {
TimeText(
- timeSource = object : TimeSource {
- override val currentTime: String
- @Composable
- get() = timeText
- }
+ timeSource =
+ object : TimeSource {
+ override val currentTime: String
+ @Composable get() = timeText
+ }
)
}
}
@@ -532,8 +509,7 @@
}
class TimeSourceTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
@Test
fun formats_current_time() {
@@ -543,9 +519,7 @@
val convertedTime = DateFormat.format(format, currentCalendar).toString()
var actualTime: String? = null
- rule.setContentWithTheme {
- actualTime = currentTime({ currentTimeInMillis }, format).value
- }
+ rule.setContentWithTheme { actualTime = currentTime({ currentTimeInMillis }, format).value }
assertEquals(convertedTime, actualTime)
}
@@ -557,10 +531,8 @@
var actualTime: String? = null
rule.setContentWithTheme {
- actualTime = currentTime(
- { currentTimeInMillis },
- TimeTextDefaults.TimeFormat12Hours
- ).value
+ actualTime =
+ currentTime({ currentTimeInMillis }, TimeTextDefaults.TimeFormat12Hours).value
}
assertEquals(expectedTime, actualTime)
}
diff --git a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/ToggleButtonScreenshotTest.kt b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/ToggleButtonScreenshotTest.kt
index 59a6702..b6f502e 100644
--- a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/ToggleButtonScreenshotTest.kt
+++ b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/ToggleButtonScreenshotTest.kt
@@ -40,14 +40,11 @@
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
class ToggleButtonScreenshotTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
- @get:Rule
- val screenshotRule = AndroidXScreenshotTestRule(SCREENSHOT_GOLDEN_PATH)
+ @get:Rule val screenshotRule = AndroidXScreenshotTestRule(SCREENSHOT_GOLDEN_PATH)
- @get:Rule
- val testName = TestName()
+ @get:Rule val testName = TestName()
@Test
fun togglebutton_ltr() =
@@ -74,29 +71,27 @@
}
@Test
- fun togglebutton_disabled() =
- verifyScreenshot {
- ToggleButton(
- checked = false,
- onCheckedChange = {},
- enabled = false,
- modifier = Modifier.testTag(TEST_TAG)
- ) {
- Text("Off")
- }
+ fun togglebutton_disabled() = verifyScreenshot {
+ ToggleButton(
+ checked = false,
+ onCheckedChange = {},
+ enabled = false,
+ modifier = Modifier.testTag(TEST_TAG)
+ ) {
+ Text("Off")
}
+ }
private fun verifyScreenshot(
layoutDirection: LayoutDirection = LayoutDirection.Ltr,
content: @Composable () -> Unit
) {
rule.setContentWithTheme {
- CompositionLocalProvider(LocalLayoutDirection provides layoutDirection) {
- content()
- }
+ CompositionLocalProvider(LocalLayoutDirection provides layoutDirection) { content() }
}
- rule.onNodeWithTag(TEST_TAG)
+ rule
+ .onNodeWithTag(TEST_TAG)
.captureToImage()
.assertAgainstGolden(screenshotRule, testName.methodName)
}
diff --git a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/ToggleButtonTest.kt b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/ToggleButtonTest.kt
index ae4e264..5b5ef9c 100644
--- a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/ToggleButtonTest.kt
+++ b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/ToggleButtonTest.kt
@@ -63,8 +63,7 @@
import org.junit.Test
class ToggleButtonBehaviourTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
@Test
fun supports_testtag() {
@@ -195,11 +194,7 @@
)
}
- rule
- .onNodeWithTag(TEST_TAG)
- .assertIsOff()
- .performClick()
- .assertIsOn()
+ rule.onNodeWithTag(TEST_TAG).assertIsOff().performClick().assertIsOn()
}
@Test
@@ -215,11 +210,7 @@
)
}
- rule
- .onNodeWithTag(TEST_TAG)
- .assertIsOn()
- .performClick()
- .assertIsOff()
+ rule.onNodeWithTag(TEST_TAG).assertIsOn().performClick().assertIsOff()
}
@Test
@@ -235,11 +226,7 @@
)
}
- rule
- .onNodeWithTag(TEST_TAG)
- .assertIsOff()
- .performClick()
- .assertIsOff()
+ rule.onNodeWithTag(TEST_TAG).assertIsOff().performClick().assertIsOff()
}
@Test
@@ -253,13 +240,9 @@
)
}
- rule.onNodeWithTag(TEST_TAG)
- .assert(
- SemanticsMatcher.expectValue(
- SemanticsProperties.Role,
- Role.Checkbox
- )
- )
+ rule
+ .onNodeWithTag(TEST_TAG)
+ .assert(SemanticsMatcher.expectValue(SemanticsProperties.Role, Role.Checkbox))
}
@RequiresApi(Build.VERSION_CODES.O)
@@ -334,8 +317,7 @@
}
class ToggleButtonSizeTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
@Test
fun gives_default_correct_tapsize() {
@@ -362,8 +344,7 @@
}
class ToggleButtonColorTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
@RequiresApi(Build.VERSION_CODES.O)
@Test
@@ -417,19 +398,15 @@
checked = true,
onCheckedChange = {},
enabled = true,
- colors = ToggleButtonDefaults.toggleButtonColors(
- checkedBackgroundColor =
- override
- ),
+ colors =
+ ToggleButtonDefaults.toggleButtonColors(checkedBackgroundColor = override),
content = {},
modifier = Modifier.testTag(TEST_TAG)
)
}
}
- rule.onNodeWithTag(TEST_TAG)
- .captureToImage()
- .assertContainsColor(override, 50.0f)
+ rule.onNodeWithTag(TEST_TAG).captureToImage().assertContainsColor(override, 50.0f)
}
@Test
@@ -443,10 +420,8 @@
checked = true,
onCheckedChange = {},
enabled = true,
- colors = ToggleButtonDefaults.toggleButtonColors(
- checkedContentColor =
- override
- ),
+ colors =
+ ToggleButtonDefaults.toggleButtonColors(checkedContentColor = override),
content = { actualContentColor = LocalContentColor.current },
modifier = Modifier.testTag(TEST_TAG)
)
@@ -467,19 +442,17 @@
checked = false,
onCheckedChange = {},
enabled = true,
- colors = ToggleButtonDefaults.toggleButtonColors(
- uncheckedBackgroundColor =
- override
- ),
+ colors =
+ ToggleButtonDefaults.toggleButtonColors(
+ uncheckedBackgroundColor = override
+ ),
content = {},
modifier = Modifier.testTag(TEST_TAG)
)
}
}
- rule.onNodeWithTag(TEST_TAG)
- .captureToImage()
- .assertContainsColor(override, 50.0f)
+ rule.onNodeWithTag(TEST_TAG).captureToImage().assertContainsColor(override, 50.0f)
}
@Test
@@ -493,10 +466,8 @@
checked = false,
onCheckedChange = {},
enabled = true,
- colors = ToggleButtonDefaults.toggleButtonColors(
- uncheckedContentColor =
- override
- ),
+ colors =
+ ToggleButtonDefaults.toggleButtonColors(uncheckedContentColor = override),
content = { actualContentColor = LocalContentColor.current },
modifier = Modifier.testTag(TEST_TAG)
)
@@ -517,17 +488,17 @@
checked = true,
onCheckedChange = {},
enabled = false,
- colors = ToggleButtonDefaults.toggleButtonColors
- (disabledCheckedBackgroundColor = override),
+ colors =
+ ToggleButtonDefaults.toggleButtonColors(
+ disabledCheckedBackgroundColor = override
+ ),
content = {},
modifier = Modifier.testTag(TEST_TAG)
)
}
}
- rule.onNodeWithTag(TEST_TAG)
- .captureToImage()
- .assertContainsColor(override, 50.0f)
+ rule.onNodeWithTag(TEST_TAG).captureToImage().assertContainsColor(override, 50.0f)
}
@Test
@@ -541,13 +512,11 @@
checked = true,
onCheckedChange = {},
enabled = false,
- colors = ToggleButtonDefaults.toggleButtonColors(
- disabledCheckedContentColor =
- override
- ),
- content = {
- actualContentColor = LocalContentColor.current
- },
+ colors =
+ ToggleButtonDefaults.toggleButtonColors(
+ disabledCheckedContentColor = override
+ ),
+ content = { actualContentColor = LocalContentColor.current },
modifier = Modifier.testTag(TEST_TAG)
)
}
@@ -567,17 +536,17 @@
checked = false,
onCheckedChange = {},
enabled = false,
- colors = ToggleButtonDefaults.toggleButtonColors
- (disabledUncheckedBackgroundColor = override),
+ colors =
+ ToggleButtonDefaults.toggleButtonColors(
+ disabledUncheckedBackgroundColor = override
+ ),
content = {},
modifier = Modifier.testTag(TEST_TAG)
)
}
}
- rule.onNodeWithTag(TEST_TAG)
- .captureToImage()
- .assertContainsColor(override, 50.0f)
+ rule.onNodeWithTag(TEST_TAG).captureToImage().assertContainsColor(override, 50.0f)
}
@Test
@@ -591,8 +560,10 @@
checked = false,
onCheckedChange = {},
enabled = false,
- colors = ToggleButtonDefaults.toggleButtonColors
- (disabledUncheckedContentColor = override),
+ colors =
+ ToggleButtonDefaults.toggleButtonColors(
+ disabledUncheckedContentColor = override
+ ),
content = { actualContentColor = LocalContentColor.current },
modifier = Modifier.testTag(TEST_TAG)
)
@@ -619,11 +590,7 @@
rule.setContentWithTheme {
expectedBackground = backgroundColor()
expectedContent = contentColor()
- Box(
- modifier = Modifier
- .fillMaxSize()
- .background(testBackgroundColor)
- ) {
+ Box(modifier = Modifier.fillMaxSize().background(testBackgroundColor)) {
ToggleButton(
checked = checked,
onCheckedChange = {},
@@ -640,7 +607,8 @@
if (status.enabled()) {
assertEquals(expectedContent, actualContent)
if (expectedBackground != Color.Transparent) {
- rule.onNodeWithTag(TEST_TAG)
+ rule
+ .onNodeWithTag(TEST_TAG)
.captureToImage()
.assertContainsColor(expectedBackground, 50.0f)
}
@@ -650,11 +618,14 @@
}
assertEquals(expectedContent, actualContent)
if (expectedBackground != Color.Transparent) {
- rule.onNodeWithTag(TEST_TAG)
+ rule
+ .onNodeWithTag(TEST_TAG)
.captureToImage()
.assertContainsColor(
- expectedBackground.copy(alpha = actualDisabledAlpha)
- .compositeOver(testBackgroundColor), 50.0f
+ expectedBackground
+ .copy(alpha = actualDisabledAlpha)
+ .compositeOver(testBackgroundColor),
+ 50.0f
)
}
}
@@ -662,8 +633,7 @@
}
class ToggleButtonRoleTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
@Test
fun default_role_checkbox() {
@@ -714,9 +684,7 @@
expected: TapSize,
content: @Composable () -> Unit
) {
- setContentWithThemeForSizeAssertions {
- content()
- }
+ setContentWithThemeForSizeAssertions { content() }
.assertHeightIsEqualTo(expected.size)
.assertWidthIsEqualTo(expected.size)
}
@@ -733,13 +701,7 @@
background = MaterialTheme.colors.primary
surface = MaterialTheme.colors.surface
CompositionLocalProvider(LocalLayoutDirection provides layoutDirection) {
- Box(
- Modifier
- .padding(padding)
- .background(surface)
- ) {
- content()
- }
+ Box(Modifier.padding(padding).background(surface)) { content() }
}
}
@@ -768,12 +730,7 @@
background = MaterialTheme.colors.surface
buttonColor = MaterialTheme.colors.primary
Box(Modifier.background(background)) {
- content(
- Modifier
- .testTag(TEST_TAG)
- .padding(padding)
- .background(background)
- )
+ content(Modifier.testTag(TEST_TAG).padding(padding).background(background))
}
}
diff --git a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/ToggleChipScreenshotTest.kt b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/ToggleChipScreenshotTest.kt
index d01d31dc..61149ae 100644
--- a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/ToggleChipScreenshotTest.kt
+++ b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/ToggleChipScreenshotTest.kt
@@ -41,39 +41,27 @@
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
class ToggleChipScreenshotTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
- @get:Rule
- val screenshotRule = AndroidXScreenshotTestRule(SCREENSHOT_GOLDEN_PATH)
+ @get:Rule val screenshotRule = AndroidXScreenshotTestRule(SCREENSHOT_GOLDEN_PATH)
- @get:Rule
- val testName = TestName()
+ @get:Rule val testName = TestName()
+
+ @Test fun toggle_chip_checkbox() = verifyScreenshot { sampleToggleChip(checked = true) }
@Test
- fun toggle_chip_checkbox() = verifyScreenshot {
- sampleToggleChip(checked = true)
- }
+ fun toggle_chip_checkbox_unchecked() = verifyScreenshot { sampleToggleChip(checked = false) }
@Test
- fun toggle_chip_checkbox_unchecked() = verifyScreenshot {
- sampleToggleChip(checked = false)
- }
-
- @Test
- fun toggle_chip_checkbox_rtl() = verifyScreenshot(layoutDirection = LayoutDirection.Rtl) {
- sampleToggleChip()
- }
+ fun toggle_chip_checkbox_rtl() =
+ verifyScreenshot(layoutDirection = LayoutDirection.Rtl) { sampleToggleChip() }
@Test
fun toggle_chip_radio() = verifyScreenshot {
val checked = true
sampleToggleChip(
toggleControl = {
- Icon(
- imageVector = ToggleChipDefaults.radioIcon(checked),
- contentDescription = ""
- )
+ Icon(imageVector = ToggleChipDefaults.radioIcon(checked), contentDescription = "")
},
checked = checked
)
@@ -84,10 +72,7 @@
val checked = false
sampleToggleChip(
toggleControl = {
- Icon(
- imageVector = ToggleChipDefaults.radioIcon(checked),
- contentDescription = ""
- )
+ Icon(imageVector = ToggleChipDefaults.radioIcon(checked), contentDescription = "")
},
checked = checked,
)
@@ -98,10 +83,7 @@
val checked = true
sampleToggleChip(
toggleControl = {
- Icon(
- imageVector = ToggleChipDefaults.switchIcon(checked),
- contentDescription = ""
- )
+ Icon(imageVector = ToggleChipDefaults.switchIcon(checked), contentDescription = "")
},
checked = checked,
)
@@ -111,17 +93,15 @@
fun toggle_chip_switch_unchecked() = verifyScreenshot {
val checked = false
sampleToggleChip(
- colors = ToggleChipDefaults.toggleChipColors(
- uncheckedToggleControlColor = ToggleChipDefaults.SwitchUncheckedIconColor
- ),
+ colors =
+ ToggleChipDefaults.toggleChipColors(
+ uncheckedToggleControlColor = ToggleChipDefaults.SwitchUncheckedIconColor
+ ),
toggleControl = {
// For Switch toggle controls the Wear Material UX guidance is to set the
// unselected toggle control color to ToggleChipDefaults.switchUncheckedIconColor()
// rather than the default.
- Icon(
- imageVector = ToggleChipDefaults.switchIcon(checked),
- contentDescription = ""
- )
+ Icon(imageVector = ToggleChipDefaults.switchIcon(checked), contentDescription = "")
},
checked = checked,
)
@@ -134,20 +114,14 @@
)
}
- @Test
- fun split_toggle_chip() = verifyScreenshot {
- sampleSplitToggleChip()
- }
+ @Test fun split_toggle_chip() = verifyScreenshot { sampleSplitToggleChip() }
@Test
- fun split_toggle_chip_rtl() = verifyScreenshot(layoutDirection = LayoutDirection.Rtl) {
- sampleSplitToggleChip()
- }
+ fun split_toggle_chip_rtl() =
+ verifyScreenshot(layoutDirection = LayoutDirection.Rtl) { sampleSplitToggleChip() }
@Test
- fun split_toggle_chip_disabled() = verifyScreenshot {
- sampleSplitToggleChip(enabled = false)
- }
+ fun split_toggle_chip_disabled() = verifyScreenshot { sampleSplitToggleChip(enabled = false) }
@Composable
private fun sampleToggleChip(
@@ -183,12 +157,8 @@
enabled: Boolean = true,
) {
SplitToggleChip(
- label = {
- Text("Split chip", maxLines = 1, overflow = TextOverflow.Ellipsis)
- },
- secondaryLabel = {
- Text("Secondary", maxLines = 1, overflow = TextOverflow.Ellipsis)
- },
+ label = { Text("Split chip", maxLines = 1, overflow = TextOverflow.Ellipsis) },
+ secondaryLabel = { Text("Secondary", maxLines = 1, overflow = TextOverflow.Ellipsis) },
checked = true,
enabled = enabled,
toggleControl = {
@@ -208,12 +178,11 @@
content: @Composable () -> Unit
) {
rule.setContentWithTheme {
- CompositionLocalProvider(LocalLayoutDirection provides layoutDirection) {
- content()
- }
+ CompositionLocalProvider(LocalLayoutDirection provides layoutDirection) { content() }
}
- rule.onNodeWithTag(TEST_TAG)
+ rule
+ .onNodeWithTag(TEST_TAG)
.captureToImage()
.assertAgainstGolden(screenshotRule, testName.methodName)
}
diff --git a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/ToggleChipTest.kt b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/ToggleChipTest.kt
index aa5b545..e2de3bf 100644
--- a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/ToggleChipTest.kt
+++ b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/ToggleChipTest.kt
@@ -53,8 +53,7 @@
import org.junit.Test
class ToggleChipTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
@Test
fun supports_testtag() {
@@ -341,11 +340,7 @@
)
}
- rule
- .onNodeWithTag(TEST_TAG)
- .assertIsOff()
- .performClick()
- .assertIsOn()
+ rule.onNodeWithTag(TEST_TAG).assertIsOff().performClick().assertIsOn()
}
@Test
@@ -363,12 +358,7 @@
)
}
- rule
- .onNodeWithTag(TEST_TAG)
- .onChildAt(1)
- .assertIsOff()
- .performClick()
- .assertIsOn()
+ rule.onNodeWithTag(TEST_TAG).onChildAt(1).assertIsOff().performClick().assertIsOn()
}
@Test
@@ -385,11 +375,7 @@
)
}
- rule
- .onNodeWithTag(TEST_TAG)
- .assertIsOn()
- .performClick()
- .assertIsOff()
+ rule.onNodeWithTag(TEST_TAG).assertIsOn().performClick().assertIsOff()
}
@Test
@@ -407,12 +393,7 @@
)
}
- rule
- .onNodeWithTag(TEST_TAG)
- .onChildAt(1)
- .assertIsOn()
- .performClick()
- .assertIsOff()
+ rule.onNodeWithTag(TEST_TAG).onChildAt(1).assertIsOn().performClick().assertIsOff()
}
@Test
@@ -429,11 +410,7 @@
)
}
- rule
- .onNodeWithTag(TEST_TAG)
- .assertIsOff()
- .performClick()
- .assertIsOff()
+ rule.onNodeWithTag(TEST_TAG).assertIsOff().performClick().assertIsOff()
}
@Test
@@ -451,12 +428,7 @@
)
}
- rule
- .onNodeWithTag(TEST_TAG)
- .onChildAt(1)
- .assertIsOff()
- .performClick()
- .assertIsOff()
+ rule.onNodeWithTag(TEST_TAG).onChildAt(1).assertIsOff().performClick().assertIsOff()
}
@Test
@@ -472,13 +444,10 @@
)
}
- rule.onNodeWithTag(TEST_TAG).onChildAt(0)
- .assert(
- SemanticsMatcher.expectValue(
- SemanticsProperties.Role,
- Role.Button
- )
- )
+ rule
+ .onNodeWithTag(TEST_TAG)
+ .onChildAt(0)
+ .assert(SemanticsMatcher.expectValue(SemanticsProperties.Role, Role.Button))
}
@Test
@@ -514,29 +483,28 @@
rule.onNodeWithText(textContent).assertExists()
}
- @Test
- fun gives_base_chip_correct_height() =
- verifyChipHeight(ChipDefaults.Height)
+ @Test fun gives_base_chip_correct_height() = verifyChipHeight(ChipDefaults.Height)
@Test
fun gives_base_chip_has_adjustable_height() {
val expectedMinHeight = ToggleChipDefaults.Height + 1.dp
- rule.setContentWithThemeForSizeAssertions {
- ToggleChip(
- checked = true,
- onCheckedChange = {},
- label = {
- Text(
- text = "ToggleChip text spanning over multiple lines of text " +
- "to test height is adjustable. This should exceed the minimum height" +
- " for the ToggleChip."
- )
- },
- toggleControl = {
- Checkbox(checked = true)
- }
- )
- }.assertHeightIsAtLeast(expectedMinHeight)
+ rule
+ .setContentWithThemeForSizeAssertions {
+ ToggleChip(
+ checked = true,
+ onCheckedChange = {},
+ label = {
+ Text(
+ text =
+ "ToggleChip text spanning over multiple lines of text " +
+ "to test height is adjustable. This should exceed the minimum height" +
+ " for the ToggleChip."
+ )
+ },
+ toggleControl = { Checkbox(checked = true) }
+ )
+ }
+ .assertHeightIsAtLeast(expectedMinHeight)
}
private fun verifyChipHeight(expectedHeight: Dp) {
@@ -550,30 +518,29 @@
}
}
- @Test
- fun gives_split_chip_correct_height() =
- verifySplitChipHeight(ChipDefaults.Height)
+ @Test fun gives_split_chip_correct_height() = verifySplitChipHeight(ChipDefaults.Height)
@Test
fun gives_split_chip_has_adjustable_height() {
val expectedMinHeight = ToggleChipDefaults.Height + 1.dp
- rule.setContentWithThemeForSizeAssertions {
- SplitToggleChip(
- checked = true,
- onCheckedChange = {},
- onClick = {},
- label = {
- Text(
- text = "SplitToggleChip text spanning over multiple lines of text " +
- "to test height is adjustable. This should exceed the minimum height " +
- "for the SplitToggleChip."
- )
- },
- toggleControl = {
- Checkbox(checked = true)
- }
- )
- }.assertHeightIsAtLeast(expectedMinHeight)
+ rule
+ .setContentWithThemeForSizeAssertions {
+ SplitToggleChip(
+ checked = true,
+ onCheckedChange = {},
+ onClick = {},
+ label = {
+ Text(
+ text =
+ "SplitToggleChip text spanning over multiple lines of text " +
+ "to test height is adjustable. This should exceed the minimum height " +
+ "for the SplitToggleChip."
+ )
+ },
+ toggleControl = { Checkbox(checked = true) }
+ )
+ }
+ .assertHeightIsAtLeast(expectedMinHeight)
}
private fun verifySplitChipHeight(expectedHeight: Dp) {
@@ -730,7 +697,8 @@
actualBackgrondColor = MaterialTheme.colors.surface
}
- rule.onNodeWithTag(TEST_TAG)
+ rule
+ .onNodeWithTag(TEST_TAG)
.captureToImage()
.assertContainsColor(actualBackgrondColor, 50.0f)
}
@@ -755,9 +723,7 @@
}
}
- rule.onNodeWithTag(TEST_TAG)
- .captureToImage()
- .assertContainsColor(override, 50.0f)
+ rule.onNodeWithTag(TEST_TAG).captureToImage().assertContainsColor(override, 50.0f)
}
private fun verifyColors(
@@ -777,11 +743,7 @@
rule.setContentWithTheme {
expectedLabel = labelColor()
expectedIcon = toggleControlColor()
- Box(
- modifier = Modifier
- .fillMaxSize()
- .background(Color.Transparent)
- ) {
+ Box(modifier = Modifier.fillMaxSize().background(Color.Transparent)) {
if (splitToggleChip) {
SplitToggleChip(
checked = checked,
@@ -828,8 +790,5 @@
}
private fun ComposeContentTestRule.verifyHeight(expected: Dp, content: @Composable () -> Unit) {
- setContentWithThemeForSizeAssertions {
- content()
- }
- .assertHeightIsEqualTo(expected)
+ setContentWithThemeForSizeAssertions { content() }.assertHeightIsEqualTo(expected)
}
diff --git a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/ToggleControlScreenshotTest.kt b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/ToggleControlScreenshotTest.kt
index 98aacd3..b6177e22 100644
--- a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/ToggleControlScreenshotTest.kt
+++ b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/ToggleControlScreenshotTest.kt
@@ -45,132 +45,117 @@
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
class ToggleControlScreenshotTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
- @get:Rule
- val screenshotRule = AndroidXScreenshotTestRule(SCREENSHOT_GOLDEN_PATH)
+ @get:Rule val screenshotRule = AndroidXScreenshotTestRule(SCREENSHOT_GOLDEN_PATH)
- @get:Rule
- val testName = TestName()
+ @get:Rule val testName = TestName()
@Test
- fun checkbox_checked_enabled() =
- verifyScreenshot {
- Checkbox(checked = true, enabled = true, modifier = testBackgroundModifier())
- }
+ fun checkbox_checked_enabled() = verifyScreenshot {
+ Checkbox(checked = true, enabled = true, modifier = testBackgroundModifier())
+ }
@Test
- fun checkbox_unchecked_enabled() =
- verifyScreenshot {
- Checkbox(checked = false, enabled = true, modifier = testBackgroundModifier())
- }
+ fun checkbox_unchecked_enabled() = verifyScreenshot {
+ Checkbox(checked = false, enabled = true, modifier = testBackgroundModifier())
+ }
@Test
- fun checkbox_checked_disabled() =
- verifyScreenshot {
- Checkbox(checked = true, enabled = false, modifier = testBackgroundModifier())
- }
+ fun checkbox_checked_disabled() = verifyScreenshot {
+ Checkbox(checked = true, enabled = false, modifier = testBackgroundModifier())
+ }
@Test
- fun checkbox_unchecked_disabled() =
- verifyScreenshot {
- Checkbox(checked = false, enabled = false, modifier = testBackgroundModifier())
- }
+ fun checkbox_unchecked_disabled() = verifyScreenshot {
+ Checkbox(checked = false, enabled = false, modifier = testBackgroundModifier())
+ }
@Test
- fun switch_checked_enabled() =
- verifyScreenshot {
+ fun switch_checked_enabled() = verifyScreenshot {
+ Switch(checked = true, enabled = true, modifier = testBackgroundModifier())
+ }
+
+ @Test
+ fun switch_unchecked_enabled() = verifyScreenshot {
+ Switch(checked = false, enabled = true, modifier = testBackgroundModifier())
+ }
+
+ @Test
+ fun switch_checked_disabled() = verifyScreenshot {
+ Switch(checked = true, enabled = false, modifier = testBackgroundModifier())
+ }
+
+ @Test
+ fun switch_unchecked_disabled() = verifyScreenshot {
+ Switch(checked = false, enabled = false, modifier = testBackgroundModifier())
+ }
+
+ @Test
+ fun switch_rtl_checked_enabled() = verifyScreenshot {
+ CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl) {
Switch(checked = true, enabled = true, modifier = testBackgroundModifier())
}
+ }
@Test
- fun switch_unchecked_enabled() =
- verifyScreenshot {
+ fun switch_rtl_unchecked_enabled() = verifyScreenshot {
+ CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl) {
Switch(checked = false, enabled = true, modifier = testBackgroundModifier())
}
+ }
@Test
- fun switch_checked_disabled() =
- verifyScreenshot {
+ fun switch_rtl_checked_disabled() = verifyScreenshot {
+ CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl) {
Switch(checked = true, enabled = false, modifier = testBackgroundModifier())
}
+ }
@Test
- fun switch_unchecked_disabled() =
- verifyScreenshot {
+ fun switch_rtl_unchecked_disabled() = verifyScreenshot {
+ CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl) {
Switch(checked = false, enabled = false, modifier = testBackgroundModifier())
}
+ }
@Test
- fun switch_rtl_checked_enabled() =
- verifyScreenshot {
- CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl) {
- Switch(checked = true, enabled = true, modifier = testBackgroundModifier())
- }
- }
+ fun radiobutton_checked_enabled() = verifyScreenshot {
+ RadioButton(selected = true, enabled = true, modifier = testBackgroundModifier())
+ }
@Test
- fun switch_rtl_unchecked_enabled() =
- verifyScreenshot {
- CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl) {
- Switch(checked = false, enabled = true, modifier = testBackgroundModifier())
- }
- }
+ fun radiobutton_unchecked_enabled() = verifyScreenshot {
+ RadioButton(selected = false, enabled = true, modifier = testBackgroundModifier())
+ }
@Test
- fun switch_rtl_checked_disabled() =
- verifyScreenshot {
- CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl) {
- Switch(checked = true, enabled = false, modifier = testBackgroundModifier())
- }
- }
+ fun radiobutton_checked_disabled() = verifyScreenshot {
+ RadioButton(selected = true, enabled = false, modifier = testBackgroundModifier())
+ }
@Test
- fun switch_rtl_unchecked_disabled() =
- verifyScreenshot {
- CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl) {
- Switch(checked = false, enabled = false, modifier = testBackgroundModifier())
- }
- }
-
- @Test
- fun radiobutton_checked_enabled() =
- verifyScreenshot {
- RadioButton(selected = true, enabled = true, modifier = testBackgroundModifier())
- }
-
- @Test
- fun radiobutton_unchecked_enabled() =
- verifyScreenshot {
- RadioButton(selected = false, enabled = true, modifier = testBackgroundModifier())
- }
-
- @Test
- fun radiobutton_checked_disabled() =
- verifyScreenshot {
- RadioButton(selected = true, enabled = false, modifier = testBackgroundModifier())
- }
-
- @Test
- fun radiobutton_unchecked_disabled() =
- verifyScreenshot {
- RadioButton(selected = false, enabled = false, modifier = testBackgroundModifier())
- }
+ fun radiobutton_unchecked_disabled() = verifyScreenshot {
+ RadioButton(selected = false, enabled = false, modifier = testBackgroundModifier())
+ }
private fun verifyScreenshot(
threshold: Double = 0.98,
content: @Composable BoxScope.() -> Unit
) {
rule.setContentWithTheme(composable = content)
- rule.onNodeWithTag(TEST_TAG)
+ rule
+ .onNodeWithTag(TEST_TAG)
.captureToImage()
.assertAgainstGolden(screenshotRule, testName.methodName, MSSIMMatcher(threshold))
}
+
@Composable
private fun testBackgroundModifier(): Modifier =
- Modifier.testTag(TEST_TAG).background(
- MaterialTheme.colors.primary.copy(alpha = 0.5f)
- .compositeOver(MaterialTheme.colors.surface)
- )
+ Modifier.testTag(TEST_TAG)
+ .background(
+ MaterialTheme.colors.primary
+ .copy(alpha = 0.5f)
+ .compositeOver(MaterialTheme.colors.surface)
+ )
}
diff --git a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/ToggleControlTest.kt b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/ToggleControlTest.kt
index ba65438..b917d67 100644
--- a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/ToggleControlTest.kt
+++ b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/ToggleControlTest.kt
@@ -50,58 +50,40 @@
import org.junit.Test
class ToggleControlTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
@Test
fun checkbox_supports_testtag() {
- rule.setContentWithTheme {
- Checkbox(
- checked = true,
- modifier = Modifier.testTag(TEST_TAG)
- )
- }
+ rule.setContentWithTheme { Checkbox(checked = true, modifier = Modifier.testTag(TEST_TAG)) }
rule.onNodeWithTag(TEST_TAG).assertExists()
}
@Test
fun checkbox_is_expected_size() {
- rule.setContentWithThemeForSizeAssertions {
- Checkbox(
- checked = true,
- modifier = Modifier.testTag(TEST_TAG)
- )
- }.assertHeightIsEqualTo(24.dp).assertWidthIsEqualTo(24.dp)
+ rule
+ .setContentWithThemeForSizeAssertions {
+ Checkbox(checked = true, modifier = Modifier.testTag(TEST_TAG))
+ }
+ .assertHeightIsEqualTo(24.dp)
+ .assertWidthIsEqualTo(24.dp)
}
@Test
fun checkbox_has_role_checkbox_when_oncheckedchange_defined() {
rule.setContentWithTheme {
- Checkbox(
- checked = true,
- onCheckedChange = {},
- modifier = Modifier.testTag(TEST_TAG)
- )
+ Checkbox(checked = true, onCheckedChange = {}, modifier = Modifier.testTag(TEST_TAG))
}
- rule.onNodeWithTag(TEST_TAG)
- .assert(
- SemanticsMatcher.expectValue(
- SemanticsProperties.Role,
- Role.Checkbox
- )
- )
+ rule
+ .onNodeWithTag(TEST_TAG)
+ .assert(SemanticsMatcher.expectValue(SemanticsProperties.Role, Role.Checkbox))
}
@Test
fun checkbox_has_no_clickaction_by_default() {
rule.setContentWithTheme {
- Checkbox(
- checked = true,
- enabled = true,
- modifier = Modifier.testTag(TEST_TAG)
- )
+ Checkbox(checked = true, enabled = true, modifier = Modifier.testTag(TEST_TAG))
}
rule.onNodeWithTag(TEST_TAG).assertHasNoClickAction()
@@ -138,11 +120,7 @@
@Test
fun checkbox_is_correctly_enabled_when_enabled_equals_true() {
rule.setContentWithTheme {
- Checkbox(
- checked = true,
- enabled = true,
- modifier = Modifier.testTag(TEST_TAG)
- )
+ Checkbox(checked = true, enabled = true, modifier = Modifier.testTag(TEST_TAG))
}
rule.onNodeWithTag(TEST_TAG).assertIsEnabled()
@@ -167,11 +145,7 @@
fun checkbox_is_on_when_checked() {
// This test only applies when onCheckedChange is defined.
rule.setContentWithTheme {
- Checkbox(
- checked = true,
- onCheckedChange = {},
- modifier = Modifier.testTag(TEST_TAG)
- )
+ Checkbox(checked = true, onCheckedChange = {}, modifier = Modifier.testTag(TEST_TAG))
}
rule.onNodeWithTag(TEST_TAG).assertIsOn()
@@ -181,11 +155,7 @@
fun checkbox_is_off_when_checked() {
// This test only applies when onCheckedChange is defined.
rule.setContentWithTheme {
- Checkbox(
- checked = false,
- onCheckedChange = {},
- modifier = Modifier.testTag(TEST_TAG)
- )
+ Checkbox(checked = false, onCheckedChange = {}, modifier = Modifier.testTag(TEST_TAG))
}
rule.onNodeWithTag(TEST_TAG).assertIsOff()
@@ -203,11 +173,7 @@
)
}
- rule
- .onNodeWithTag(TEST_TAG)
- .assertIsOff()
- .performClick()
- .assertIsOn()
+ rule.onNodeWithTag(TEST_TAG).assertIsOff().performClick().assertIsOn()
}
@Test
@@ -222,11 +188,7 @@
)
}
- rule
- .onNodeWithTag(TEST_TAG)
- .assertIsOn()
- .performClick()
- .assertIsOff()
+ rule.onNodeWithTag(TEST_TAG).assertIsOn().performClick().assertIsOff()
}
@RequiresApi(Build.VERSION_CODES.O)
@@ -237,10 +199,11 @@
rule.setContentWithTheme {
Checkbox(
checked = true,
- colors = CheckboxDefaults.colors(
- checkedBoxColor = boxColor,
- checkedCheckmarkColor = checkmarkColor
- ),
+ colors =
+ CheckboxDefaults.colors(
+ checkedBoxColor = boxColor,
+ checkedCheckmarkColor = checkmarkColor
+ ),
modifier = Modifier.testTag(TEST_TAG)
)
}
@@ -259,9 +222,10 @@
rule.setContentWithTheme {
Checkbox(
checked = false,
- colors = CheckboxDefaults.colors(
- uncheckedBoxColor = boxColor,
- ),
+ colors =
+ CheckboxDefaults.colors(
+ uncheckedBoxColor = boxColor,
+ ),
modifier = Modifier.testTag(TEST_TAG)
)
}
@@ -272,53 +236,36 @@
@Test
fun switch_supports_testtag() {
- rule.setContentWithTheme {
- Switch(
- checked = true,
- modifier = Modifier.testTag(TEST_TAG)
- )
- }
+ rule.setContentWithTheme { Switch(checked = true, modifier = Modifier.testTag(TEST_TAG)) }
rule.onNodeWithTag(TEST_TAG).assertExists()
}
@Test
fun switch_is_expected_size() {
- rule.setContentWithThemeForSizeAssertions {
- Switch(
- checked = true,
- modifier = Modifier.testTag(TEST_TAG)
- )
- }.assertHeightIsEqualTo(24.dp).assertWidthIsEqualTo(24.dp)
+ rule
+ .setContentWithThemeForSizeAssertions {
+ Switch(checked = true, modifier = Modifier.testTag(TEST_TAG))
+ }
+ .assertHeightIsEqualTo(24.dp)
+ .assertWidthIsEqualTo(24.dp)
}
@Test
fun switch_has_role_switch_when_oncheckedchange_defined() {
rule.setContentWithTheme {
- Switch(
- checked = true,
- onCheckedChange = {},
- modifier = Modifier.testTag(TEST_TAG)
- )
+ Switch(checked = true, onCheckedChange = {}, modifier = Modifier.testTag(TEST_TAG))
}
- rule.onNodeWithTag(TEST_TAG)
- .assert(
- SemanticsMatcher.expectValue(
- SemanticsProperties.Role,
- Role.Switch
- )
- )
+ rule
+ .onNodeWithTag(TEST_TAG)
+ .assert(SemanticsMatcher.expectValue(SemanticsProperties.Role, Role.Switch))
}
@Test
fun switch_has_no_clickaction_by_default() {
rule.setContentWithTheme {
- Switch(
- checked = true,
- enabled = true,
- modifier = Modifier.testTag(TEST_TAG)
- )
+ Switch(checked = true, enabled = true, modifier = Modifier.testTag(TEST_TAG))
}
rule.onNodeWithTag(TEST_TAG).assertHasNoClickAction()
@@ -355,11 +302,7 @@
@Test
fun switch_is_correctly_enabled_when_enabled_equals_true() {
rule.setContentWithTheme {
- Switch(
- checked = true,
- enabled = true,
- modifier = Modifier.testTag(TEST_TAG)
- )
+ Switch(checked = true, enabled = true, modifier = Modifier.testTag(TEST_TAG))
}
rule.onNodeWithTag(TEST_TAG).assertIsEnabled()
@@ -383,11 +326,7 @@
fun switch_is_on_when_checked() {
// This test only applies when onCheckedChange is defined.
rule.setContentWithTheme {
- Switch(
- checked = true,
- onCheckedChange = {},
- modifier = Modifier.testTag(TEST_TAG)
- )
+ Switch(checked = true, onCheckedChange = {}, modifier = Modifier.testTag(TEST_TAG))
}
rule.onNodeWithTag(TEST_TAG).assertIsOn()
@@ -397,11 +336,7 @@
fun switch_is_off_when_checked() {
// This test only applies when onCheckedChange is defined.
rule.setContentWithTheme {
- Switch(
- checked = false,
- onCheckedChange = {},
- modifier = Modifier.testTag(TEST_TAG)
- )
+ Switch(checked = false, onCheckedChange = {}, modifier = Modifier.testTag(TEST_TAG))
}
rule.onNodeWithTag(TEST_TAG).assertIsOff()
@@ -419,11 +354,7 @@
)
}
- rule
- .onNodeWithTag(TEST_TAG)
- .assertIsOff()
- .performClick()
- .assertIsOn()
+ rule.onNodeWithTag(TEST_TAG).assertIsOff().performClick().assertIsOn()
}
@Test
@@ -438,11 +369,7 @@
)
}
- rule
- .onNodeWithTag(TEST_TAG)
- .assertIsOn()
- .performClick()
- .assertIsOff()
+ rule.onNodeWithTag(TEST_TAG).assertIsOn().performClick().assertIsOff()
}
@RequiresApi(Build.VERSION_CODES.O)
@@ -453,10 +380,11 @@
rule.setContentWithTheme {
Switch(
checked = true,
- colors = SwitchDefaults.colors(
- checkedThumbColor = thumbColor,
- checkedTrackColor = trackColor
- ),
+ colors =
+ SwitchDefaults.colors(
+ checkedThumbColor = thumbColor,
+ checkedTrackColor = trackColor
+ ),
modifier = Modifier.testTag(TEST_TAG)
)
}
@@ -474,10 +402,11 @@
rule.setContentWithTheme {
Switch(
checked = false,
- colors = SwitchDefaults.colors(
- uncheckedThumbColor = thumbColor,
- uncheckedTrackColor = trackColor
- ),
+ colors =
+ SwitchDefaults.colors(
+ uncheckedThumbColor = thumbColor,
+ uncheckedTrackColor = trackColor
+ ),
modifier = Modifier.testTag(TEST_TAG)
)
}
@@ -490,10 +419,7 @@
@Test
fun radiobutton_supports_testtag() {
rule.setContentWithTheme {
- RadioButton(
- selected = true,
- modifier = Modifier.testTag(TEST_TAG)
- )
+ RadioButton(selected = true, modifier = Modifier.testTag(TEST_TAG))
}
rule.onNodeWithTag(TEST_TAG).assertExists()
@@ -501,41 +427,29 @@
@Test
fun radiobutton_is_expected_size() {
- rule.setContentWithThemeForSizeAssertions {
- Switch(
- checked = true,
- modifier = Modifier.testTag(TEST_TAG)
- )
- }.assertHeightIsEqualTo(24.dp).assertWidthIsEqualTo(24.dp)
+ rule
+ .setContentWithThemeForSizeAssertions {
+ Switch(checked = true, modifier = Modifier.testTag(TEST_TAG))
+ }
+ .assertHeightIsEqualTo(24.dp)
+ .assertWidthIsEqualTo(24.dp)
}
@Test
fun radiobutton_has_role_radiobutton_when_onclick_defined() {
rule.setContentWithTheme {
- RadioButton(
- selected = true,
- onClick = {},
- modifier = Modifier.testTag(TEST_TAG)
- )
+ RadioButton(selected = true, onClick = {}, modifier = Modifier.testTag(TEST_TAG))
}
- rule.onNodeWithTag(TEST_TAG)
- .assert(
- SemanticsMatcher.expectValue(
- SemanticsProperties.Role,
- Role.RadioButton
- )
- )
+ rule
+ .onNodeWithTag(TEST_TAG)
+ .assert(SemanticsMatcher.expectValue(SemanticsProperties.Role, Role.RadioButton))
}
@Test
fun radiobutton_has_no_clickaction_by_default() {
rule.setContentWithTheme {
- RadioButton(
- selected = true,
- enabled = true,
- modifier = Modifier.testTag(TEST_TAG)
- )
+ RadioButton(selected = true, enabled = true, modifier = Modifier.testTag(TEST_TAG))
}
rule.onNodeWithTag(TEST_TAG).assertHasNoClickAction()
@@ -572,11 +486,7 @@
@Test
fun radiobutton_is_correctly_enabled_when_enabled_equals_true() {
rule.setContentWithTheme {
- RadioButton(
- selected = true,
- enabled = true,
- modifier = Modifier.testTag(TEST_TAG)
- )
+ RadioButton(selected = true, enabled = true, modifier = Modifier.testTag(TEST_TAG))
}
rule.onNodeWithTag(TEST_TAG).assertIsEnabled()
@@ -601,11 +511,7 @@
fun radiobutton_is_on_when_checked() {
// This test only applies when onClick is provided and the RadioButton itself is selectable.
rule.setContentWithTheme {
- RadioButton(
- selected = true,
- onClick = {},
- modifier = Modifier.testTag(TEST_TAG)
- )
+ RadioButton(selected = true, onClick = {}, modifier = Modifier.testTag(TEST_TAG))
}
rule.onNodeWithTag(TEST_TAG).assertIsSelected()
@@ -615,11 +521,7 @@
fun radiobutton_is_off_when_checked() {
// This test only applies when onClick is provided and the RadioButton itself is selectable.
rule.setContentWithTheme {
- RadioButton(
- selected = false,
- onClick = {},
- modifier = Modifier.testTag(TEST_TAG)
- )
+ RadioButton(selected = false, onClick = {}, modifier = Modifier.testTag(TEST_TAG))
}
rule.onNodeWithTag(TEST_TAG).assertIsNotSelected()
@@ -637,11 +539,7 @@
)
}
- rule
- .onNodeWithTag(TEST_TAG)
- .assertIsNotSelected()
- .performClick()
- .assertIsSelected()
+ rule.onNodeWithTag(TEST_TAG).assertIsNotSelected().performClick().assertIsSelected()
}
@Test
@@ -656,11 +554,7 @@
)
}
- rule
- .onNodeWithTag(TEST_TAG)
- .assertIsSelected()
- .performClick()
- .assertIsNotSelected()
+ rule.onNodeWithTag(TEST_TAG).assertIsSelected().performClick().assertIsNotSelected()
}
@RequiresApi(Build.VERSION_CODES.O)
@@ -671,10 +565,11 @@
rule.setContentWithTheme {
RadioButton(
selected = true,
- colors = RadioButtonDefaults.colors(
- selectedRingColor = ringColor,
- selectedDotColor = dotColor
- ),
+ colors =
+ RadioButtonDefaults.colors(
+ selectedRingColor = ringColor,
+ selectedDotColor = dotColor
+ ),
modifier = Modifier.testTag(TEST_TAG)
)
}
@@ -693,9 +588,10 @@
rule.setContentWithTheme {
RadioButton(
selected = false,
- colors = RadioButtonDefaults.colors(
- unselectedRingColor = ringColor,
- ),
+ colors =
+ RadioButtonDefaults.colors(
+ unselectedRingColor = ringColor,
+ ),
modifier = Modifier.testTag(TEST_TAG)
)
}
diff --git a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/TouchExplorationStateProviderTest.kt b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/TouchExplorationStateProviderTest.kt
index 5cc9727..5b75ab4 100644
--- a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/TouchExplorationStateProviderTest.kt
+++ b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/TouchExplorationStateProviderTest.kt
@@ -32,8 +32,7 @@
@RunWith(AndroidJUnit4::class)
class TouchExplorationStateProviderTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
@Test
fun returns_correct_values() {
diff --git a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/VignetteScreenshotTest.kt b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/VignetteScreenshotTest.kt
index cee74ee..4568381 100644
--- a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/VignetteScreenshotTest.kt
+++ b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/VignetteScreenshotTest.kt
@@ -45,14 +45,11 @@
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
class VignetteScreenshotTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
- @get:Rule
- val screenshotRule = AndroidXScreenshotTestRule(SCREENSHOT_GOLDEN_PATH)
+ @get:Rule val screenshotRule = AndroidXScreenshotTestRule(SCREENSHOT_GOLDEN_PATH)
- @get:Rule
- val testName = TestName()
+ @get:Rule val testName = TestName()
private val screenSize = 340.dp
@@ -86,15 +83,10 @@
}
}
- @Test
- fun vignette_square_top() = verifyScreenshot {
- sampleVignette(VignettePosition.Top)
- }
+ @Test fun vignette_square_top() = verifyScreenshot { sampleVignette(VignettePosition.Top) }
@Test
- fun vignette_square_bottom() = verifyScreenshot {
- sampleVignette(VignettePosition.Bottom)
- }
+ fun vignette_square_bottom() = verifyScreenshot { sampleVignette(VignettePosition.Bottom) }
@Test
fun vignette_square_top_and_bottom() = verifyScreenshot {
@@ -110,22 +102,15 @@
vignette = { Vignette(vignettePosition = vignettePosition) },
modifier = Modifier.testTag(TEST_TAG)
) {
- Box(
- modifier = modifier,
- contentAlignment = Alignment.Center
- ) {
- }
+ Box(modifier = modifier, contentAlignment = Alignment.Center) {}
}
}
- private fun verifyScreenshot(
- content: @Composable () -> Unit
- ) {
- rule.setContentWithTheme {
- content()
- }
+ private fun verifyScreenshot(content: @Composable () -> Unit) {
+ rule.setContentWithTheme { content() }
- rule.onNodeWithTag(TEST_TAG)
+ rule
+ .onNodeWithTag(TEST_TAG)
.captureToImage()
.assertAgainstGolden(screenshotRule, testName.methodName)
}
diff --git a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/dialog/DialogScreenshotTest.kt b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/dialog/DialogScreenshotTest.kt
index 3fe3e49..7823269 100644
--- a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/dialog/DialogScreenshotTest.kt
+++ b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/dialog/DialogScreenshotTest.kt
@@ -45,14 +45,11 @@
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
class DialogScreenshotTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
- @get:Rule
- val screenshotRule = AndroidXScreenshotTestRule(SCREENSHOT_GOLDEN_PATH)
+ @get:Rule val screenshotRule = AndroidXScreenshotTestRule(SCREENSHOT_GOLDEN_PATH)
- @get:Rule
- val testName = TestName()
+ @get:Rule val testName = TestName()
@Test
fun alert_title_body_and_buttons() = verifyScreenshot {
@@ -65,20 +62,10 @@
)
},
negativeButton = {
- Button(
- onClick = {},
- colors = ButtonDefaults.secondaryButtonColors()
- ) {
- Text("No")
- }
+ Button(onClick = {}, colors = ButtonDefaults.secondaryButtonColors()) { Text("No") }
},
positiveButton = {
- Button(
- onClick = {},
- colors = ButtonDefaults.primaryButtonColors()
- ) {
- Text("Yes")
- }
+ Button(onClick = {}, colors = ButtonDefaults.primaryButtonColors()) { Text("Yes") }
},
modifier = Modifier.testTag(TEST_TAG),
) {
@@ -103,20 +90,10 @@
)
},
negativeButton = {
- Button(
- onClick = {},
- colors = ButtonDefaults.secondaryButtonColors()
- ) {
- Text("No")
- }
+ Button(onClick = {}, colors = ButtonDefaults.secondaryButtonColors()) { Text("No") }
},
positiveButton = {
- Button(
- onClick = {},
- colors = ButtonDefaults.primaryButtonColors()
- ) {
- Text("Yes")
- }
+ Button(onClick = {}, colors = ButtonDefaults.primaryButtonColors()) { Text("Yes") }
},
modifier = Modifier.testTag(TEST_TAG),
)
@@ -126,10 +103,12 @@
fun alert_icon_title_and_chip() = verifyScreenshot {
Alert(
icon = { TestIcon() },
- title = { Text(
- text = "Grant location permission to use this app",
- textAlign = TextAlign.Center
- ) },
+ title = {
+ Text(
+ text = "Grant location permission to use this app",
+ textAlign = TextAlign.Center
+ )
+ },
modifier = Modifier.testTag(TEST_TAG),
) {
item {
@@ -148,8 +127,10 @@
Alert(
verticalArrangement = Arrangement.spacedBy(4.dp, Alignment.Top),
title = {
- Row(modifier = Modifier.fillMaxWidth(),
- horizontalArrangement = Arrangement.Center) {
+ Row(
+ modifier = Modifier.fillMaxWidth(),
+ horizontalArrangement = Arrangement.Center
+ ) {
Text(text = "Title that is quite long", textAlign = TextAlign.Center)
}
},
@@ -180,21 +161,15 @@
icon = { TestIcon() },
modifier = Modifier.testTag(TEST_TAG),
) {
- Text(
- text = "Success",
- textAlign = TextAlign.Center
- )
+ Text(text = "Success", textAlign = TextAlign.Center)
}
}
- private fun verifyScreenshot(
- content: @Composable () -> Unit
- ) {
- rule.setContentWithTheme {
- content()
- }
+ private fun verifyScreenshot(content: @Composable () -> Unit) {
+ rule.setContentWithTheme { content() }
- rule.onNodeWithTag(TEST_TAG)
+ rule
+ .onNodeWithTag(TEST_TAG)
.captureToImage()
.assertAgainstGolden(screenshotRule, testName.methodName)
}
diff --git a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/dialog/DialogTest.kt b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/dialog/DialogTest.kt
index 3a22a94..9be2bf8 100644
--- a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/dialog/DialogTest.kt
+++ b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/dialog/DialogTest.kt
@@ -66,8 +66,7 @@
internal const val CHIP_TAG = "Chip"
class DialogBehaviourTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
@Test
fun supports_testtag_on_alert_with_buttons() {
@@ -260,12 +259,8 @@
) {
Alert(
title = {},
- negativeButton = {
- Button(onClick = {}, content = {})
- },
- positiveButton = {
- Button(onClick = {}, content = {})
- },
+ negativeButton = { Button(onClick = {}, content = {}) },
+ positiveButton = { Button(onClick = {}, content = {}) },
content = { Text("Dialog", modifier = Modifier.testTag(TEST_TAG)) },
)
}
@@ -393,24 +388,22 @@
}
class DialogContentSizeAndPositionTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
@Test
fun spaces_icon_and_title_correctly_on_alert_with_buttons() {
- rule
- .setContentWithThemeForSizeAssertions(useUnmergedTree = true) {
- Alert(
- icon = { TestImage(ICON_TAG) },
- title = { Text("Title", modifier = Modifier.testTag(TITLE_TAG)) },
- negativeButton = {
- Button(onClick = {}, modifier = Modifier.testTag(BUTTON_TAG)) {}
- },
- positiveButton = { Button(onClick = {}) {} },
- verticalArrangement = Arrangement.spacedBy(0.dp, Alignment.CenterVertically),
- modifier = Modifier.testTag(TEST_TAG),
- )
- }
+ rule.setContentWithThemeForSizeAssertions(useUnmergedTree = true) {
+ Alert(
+ icon = { TestImage(ICON_TAG) },
+ title = { Text("Title", modifier = Modifier.testTag(TITLE_TAG)) },
+ negativeButton = {
+ Button(onClick = {}, modifier = Modifier.testTag(BUTTON_TAG)) {}
+ },
+ positiveButton = { Button(onClick = {}) {} },
+ verticalArrangement = Arrangement.spacedBy(0.dp, Alignment.CenterVertically),
+ modifier = Modifier.testTag(TEST_TAG),
+ )
+ }
val iconBottom = rule.onNodeWithTag(ICON_TAG).getUnclippedBoundsInRoot().bottom
val titleTop = rule.onNodeWithTag(TITLE_TAG).getUnclippedBoundsInRoot().top
@@ -421,20 +414,19 @@
fun spaces_title_and_buttons_correctly_on_alert_with_buttons() {
var titlePadding = 0.dp
- rule
- .setContentWithThemeForSizeAssertions(useUnmergedTree = true) {
- titlePadding = DialogDefaults.TitlePadding.calculateBottomPadding()
- Alert(
- icon = { TestImage(ICON_TAG) },
- title = { Text("Title", modifier = Modifier.testTag(TITLE_TAG)) },
- negativeButton = {
- Button(onClick = {}, modifier = Modifier.testTag(BUTTON_TAG)) {}
- },
- positiveButton = { Button(onClick = {}) {} },
- verticalArrangement = Arrangement.spacedBy(0.dp, Alignment.CenterVertically),
- modifier = Modifier.testTag(TEST_TAG),
- )
- }
+ rule.setContentWithThemeForSizeAssertions(useUnmergedTree = true) {
+ titlePadding = DialogDefaults.TitlePadding.calculateBottomPadding()
+ Alert(
+ icon = { TestImage(ICON_TAG) },
+ title = { Text("Title", modifier = Modifier.testTag(TITLE_TAG)) },
+ negativeButton = {
+ Button(onClick = {}, modifier = Modifier.testTag(BUTTON_TAG)) {}
+ },
+ positiveButton = { Button(onClick = {}) {} },
+ verticalArrangement = Arrangement.spacedBy(0.dp, Alignment.CenterVertically),
+ modifier = Modifier.testTag(TEST_TAG),
+ )
+ }
val titleBottom = rule.onNodeWithTag(TITLE_TAG).getUnclippedBoundsInRoot().bottom
val buttonTop = rule.onNodeWithTag(BUTTON_TAG).getUnclippedBoundsInRoot().top
@@ -443,24 +435,23 @@
@Test
fun spaces_icon_and_title_correctly_on_alert_with_chips() {
- rule
- .setContentWithThemeForSizeAssertions(useUnmergedTree = true) {
- Alert(
- icon = { TestImage(ICON_TAG) },
- title = { Text("Title", modifier = Modifier.testTag(TITLE_TAG)) },
- content = {
- item {
- Chip(
- label = { Text("Chip") },
- onClick = {},
- modifier = Modifier.testTag(CHIP_TAG)
- )
- }
- },
- verticalArrangement = Arrangement.spacedBy(0.dp, Alignment.CenterVertically),
- modifier = Modifier.testTag(TEST_TAG),
- )
- }
+ rule.setContentWithThemeForSizeAssertions(useUnmergedTree = true) {
+ Alert(
+ icon = { TestImage(ICON_TAG) },
+ title = { Text("Title", modifier = Modifier.testTag(TITLE_TAG)) },
+ content = {
+ item {
+ Chip(
+ label = { Text("Chip") },
+ onClick = {},
+ modifier = Modifier.testTag(CHIP_TAG)
+ )
+ }
+ },
+ verticalArrangement = Arrangement.spacedBy(0.dp, Alignment.CenterVertically),
+ modifier = Modifier.testTag(TEST_TAG),
+ )
+ }
val iconBottom = rule.onNodeWithTag(ICON_TAG).getUnclippedBoundsInRoot().bottom
val titleTop = rule.onNodeWithTag(TITLE_TAG).getUnclippedBoundsInRoot().top
@@ -471,25 +462,24 @@
fun spaces_title_and_chips_correctly_on_alert_with_chips() {
var titlePadding = 0.dp
- rule
- .setContentWithThemeForSizeAssertions(useUnmergedTree = true) {
- titlePadding = DialogDefaults.TitlePadding.calculateBottomPadding()
- Alert(
- icon = { TestImage(ICON_TAG) },
- title = { Text("Title", modifier = Modifier.testTag(TITLE_TAG)) },
- content = {
- item {
- Chip(
- label = { Text("Chip") },
- onClick = {},
- modifier = Modifier.testTag(CHIP_TAG)
- )
- }
- },
- verticalArrangement = Arrangement.spacedBy(0.dp, Alignment.CenterVertically),
- modifier = Modifier.testTag(TEST_TAG),
- )
- }
+ rule.setContentWithThemeForSizeAssertions(useUnmergedTree = true) {
+ titlePadding = DialogDefaults.TitlePadding.calculateBottomPadding()
+ Alert(
+ icon = { TestImage(ICON_TAG) },
+ title = { Text("Title", modifier = Modifier.testTag(TITLE_TAG)) },
+ content = {
+ item {
+ Chip(
+ label = { Text("Chip") },
+ onClick = {},
+ modifier = Modifier.testTag(CHIP_TAG)
+ )
+ }
+ },
+ verticalArrangement = Arrangement.spacedBy(0.dp, Alignment.CenterVertically),
+ modifier = Modifier.testTag(TEST_TAG),
+ )
+ }
val titleBottom = rule.onNodeWithTag(TITLE_TAG).getUnclippedBoundsInRoot().bottom
val chipTop = rule.onNodeWithTag(CHIP_TAG).getUnclippedBoundsInRoot().top
@@ -498,16 +488,15 @@
@Test
fun spaces_icon_and_title_correctly_on_confirmation() {
- rule
- .setContentWithThemeForSizeAssertions(useUnmergedTree = true) {
- Confirmation(
- onTimeout = {},
- icon = { TestImage(ICON_TAG) },
- content = { Text("Title", modifier = Modifier.testTag(TITLE_TAG)) },
- verticalArrangement = Arrangement.spacedBy(0.dp, Alignment.CenterVertically),
- modifier = Modifier.testTag(TEST_TAG),
- )
- }
+ rule.setContentWithThemeForSizeAssertions(useUnmergedTree = true) {
+ Confirmation(
+ onTimeout = {},
+ icon = { TestImage(ICON_TAG) },
+ content = { Text("Title", modifier = Modifier.testTag(TITLE_TAG)) },
+ verticalArrangement = Arrangement.spacedBy(0.dp, Alignment.CenterVertically),
+ modifier = Modifier.testTag(TEST_TAG),
+ )
+ }
val iconBottom = rule.onNodeWithTag(ICON_TAG).getUnclippedBoundsInRoot().bottom
val titleTop = rule.onNodeWithTag(TITLE_TAG).getUnclippedBoundsInRoot().top
@@ -518,20 +507,19 @@
fun spaces_title_and_body_correctly_on_alert_with_buttons() {
var titleSpacing = 0.dp
- rule
- .setContentWithThemeForSizeAssertions(useUnmergedTree = true) {
- titleSpacing = DialogDefaults.TitlePadding.calculateBottomPadding()
- Alert(
- title = { Text("Title", modifier = Modifier.testTag(TITLE_TAG)) },
- negativeButton = {
- Button(onClick = {}, modifier = Modifier.testTag(BUTTON_TAG)) {}
- },
- positiveButton = { Button(onClick = {}) {} },
- content = { Text("Body", modifier = Modifier.testTag(BODY_TAG)) },
- verticalArrangement = Arrangement.spacedBy(0.dp, Alignment.CenterVertically),
- modifier = Modifier.testTag(TEST_TAG),
- )
- }
+ rule.setContentWithThemeForSizeAssertions(useUnmergedTree = true) {
+ titleSpacing = DialogDefaults.TitlePadding.calculateBottomPadding()
+ Alert(
+ title = { Text("Title", modifier = Modifier.testTag(TITLE_TAG)) },
+ negativeButton = {
+ Button(onClick = {}, modifier = Modifier.testTag(BUTTON_TAG)) {}
+ },
+ positiveButton = { Button(onClick = {}) {} },
+ content = { Text("Body", modifier = Modifier.testTag(BODY_TAG)) },
+ verticalArrangement = Arrangement.spacedBy(0.dp, Alignment.CenterVertically),
+ modifier = Modifier.testTag(TEST_TAG),
+ )
+ }
val titleBottom = rule.onNodeWithTag(TITLE_TAG).getUnclippedBoundsInRoot().bottom
val bodyTop = rule.onNodeWithTag(BODY_TAG).getUnclippedBoundsInRoot().top
@@ -542,26 +530,25 @@
fun spaces_title_and_body_correctly_on_alert_with_chips() {
var titleSpacing = 0.dp
- rule
- .setContentWithThemeForSizeAssertions(useUnmergedTree = true) {
- titleSpacing = DialogDefaults.TitlePadding.calculateBottomPadding()
- Alert(
- icon = { TestImage(ICON_TAG) },
- title = { Text("Title", modifier = Modifier.testTag(TITLE_TAG)) },
- message = { Text("Message", modifier = Modifier.testTag(BODY_TAG)) },
- content = {
- item {
- Chip(
- label = { Text("Chip") },
- onClick = {},
- modifier = Modifier.testTag(CHIP_TAG)
- )
- }
- },
- verticalArrangement = Arrangement.spacedBy(0.dp, Alignment.CenterVertically),
- modifier = Modifier.testTag(TEST_TAG),
- )
- }
+ rule.setContentWithThemeForSizeAssertions(useUnmergedTree = true) {
+ titleSpacing = DialogDefaults.TitlePadding.calculateBottomPadding()
+ Alert(
+ icon = { TestImage(ICON_TAG) },
+ title = { Text("Title", modifier = Modifier.testTag(TITLE_TAG)) },
+ message = { Text("Message", modifier = Modifier.testTag(BODY_TAG)) },
+ content = {
+ item {
+ Chip(
+ label = { Text("Chip") },
+ onClick = {},
+ modifier = Modifier.testTag(CHIP_TAG)
+ )
+ }
+ },
+ verticalArrangement = Arrangement.spacedBy(0.dp, Alignment.CenterVertically),
+ modifier = Modifier.testTag(TEST_TAG),
+ )
+ }
val titleBottom = rule.onNodeWithTag(TITLE_TAG).getUnclippedBoundsInRoot().bottom
val bodyTop = rule.onNodeWithTag(BODY_TAG).getUnclippedBoundsInRoot().top
@@ -572,23 +559,20 @@
fun spaces_body_and_buttons_correctly_on_alert_with_buttons() {
var bodyPadding = 0.dp
- rule
- .setContentWithThemeForSizeAssertions(useUnmergedTree = true) {
- bodyPadding = DialogDefaults.BodyPadding.calculateBottomPadding()
- Alert(
- icon = {},
- title = {},
- negativeButton = {
- Button(onClick = {}, modifier = Modifier.testTag(BUTTON_TAG)) {}
- },
- positiveButton = {
- Button(onClick = {}) {}
- },
- content = { Text("Body", modifier = Modifier.testTag(BODY_TAG)) },
- verticalArrangement = Arrangement.spacedBy(0.dp, Alignment.CenterVertically),
- modifier = Modifier.testTag(TEST_TAG),
- )
- }
+ rule.setContentWithThemeForSizeAssertions(useUnmergedTree = true) {
+ bodyPadding = DialogDefaults.BodyPadding.calculateBottomPadding()
+ Alert(
+ icon = {},
+ title = {},
+ negativeButton = {
+ Button(onClick = {}, modifier = Modifier.testTag(BUTTON_TAG)) {}
+ },
+ positiveButton = { Button(onClick = {}) {} },
+ content = { Text("Body", modifier = Modifier.testTag(BODY_TAG)) },
+ verticalArrangement = Arrangement.spacedBy(0.dp, Alignment.CenterVertically),
+ modifier = Modifier.testTag(TEST_TAG),
+ )
+ }
val bodyBottom = rule.onNodeWithTag(BODY_TAG).getUnclippedBoundsInRoot().bottom
val buttonTop = rule.onNodeWithTag(BUTTON_TAG).getUnclippedBoundsInRoot().top
@@ -599,26 +583,25 @@
fun spaces_body_and_chips_correctly_on_alert_with_chips() {
var bodyPadding = 0.dp
- rule
- .setContentWithThemeForSizeAssertions(useUnmergedTree = true) {
- bodyPadding = DialogDefaults.BodyPadding.calculateBottomPadding()
- Alert(
- icon = { TestImage(ICON_TAG) },
- title = { Text("Title", modifier = Modifier.testTag(TITLE_TAG)) },
- message = { Text("Message", modifier = Modifier.testTag(BODY_TAG)) },
- content = {
- item {
- Chip(
- label = { Text("Chip") },
- onClick = {},
- modifier = Modifier.testTag(CHIP_TAG)
- )
- }
- },
- verticalArrangement = Arrangement.spacedBy(0.dp, Alignment.CenterVertically),
- modifier = Modifier.testTag(TEST_TAG),
- )
- }
+ rule.setContentWithThemeForSizeAssertions(useUnmergedTree = true) {
+ bodyPadding = DialogDefaults.BodyPadding.calculateBottomPadding()
+ Alert(
+ icon = { TestImage(ICON_TAG) },
+ title = { Text("Title", modifier = Modifier.testTag(TITLE_TAG)) },
+ message = { Text("Message", modifier = Modifier.testTag(BODY_TAG)) },
+ content = {
+ item {
+ Chip(
+ label = { Text("Chip") },
+ onClick = {},
+ modifier = Modifier.testTag(CHIP_TAG)
+ )
+ }
+ },
+ verticalArrangement = Arrangement.spacedBy(0.dp, Alignment.CenterVertically),
+ modifier = Modifier.testTag(TEST_TAG),
+ )
+ }
val bodyBottom = rule.onNodeWithTag(BODY_TAG).getUnclippedBoundsInRoot().bottom
val chipTop = rule.onNodeWithTag(CHIP_TAG).getUnclippedBoundsInRoot().top
@@ -627,8 +610,7 @@
}
class DialogContentColorTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
@Test
fun gives_icon_onbackground_on_alert_for_buttons() {
@@ -928,12 +910,7 @@
@Test
fun gives_correct_background_color_on_alert_for_chips() {
verifyBackgroundColor(expected = { MaterialTheme.colors.background }) {
- Alert(
- title = {},
- message = {},
- content = {},
- modifier = Modifier.testTag(TEST_TAG)
- )
+ Alert(title = {}, message = {}, content = {}, modifier = Modifier.testTag(TEST_TAG))
}
}
@@ -965,9 +942,7 @@
)
}
- rule.onNodeWithTag(TEST_TAG)
- .captureToImage()
- .assertContainsColor(overrideColor, 100.0f)
+ rule.onNodeWithTag(TEST_TAG).captureToImage().assertContainsColor(overrideColor, 100.0f)
}
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
@@ -985,9 +960,7 @@
)
}
- rule.onNodeWithTag(TEST_TAG)
- .captureToImage()
- .assertContainsColor(overrideColor, 100.0f)
+ rule.onNodeWithTag(TEST_TAG).captureToImage().assertContainsColor(overrideColor, 100.0f)
}
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
@@ -1004,9 +977,7 @@
)
}
- rule.onNodeWithTag(TEST_TAG)
- .captureToImage()
- .assertContainsColor(overrideColor, 100.0f)
+ rule.onNodeWithTag(TEST_TAG).captureToImage().assertContainsColor(overrideColor, 100.0f)
}
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
@@ -1024,15 +995,15 @@
}
}
- rule.onNodeWithTag(TEST_TAG)
+ rule
+ .onNodeWithTag(TEST_TAG)
.captureToImage()
.assertContainsColor(expectedBackground, 100.0f)
}
}
class DialogTextStyleTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
@Test
fun gives_title_correct_textstyle_on_alert_for_buttons() {
diff --git a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/dialog/DialogWithMaterialSlcTest.kt b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/dialog/DialogWithMaterialSlcTest.kt
index 1cc2342..bd00578 100644
--- a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/dialog/DialogWithMaterialSlcTest.kt
+++ b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/dialog/DialogWithMaterialSlcTest.kt
@@ -60,14 +60,10 @@
import org.junit.Rule
import org.junit.Test
-/**
- * These tests were copied from DialogTest.kt for support of deprecated Dialogs
- */
-
+/** These tests were copied from DialogTest.kt for support of deprecated Dialogs */
@Suppress("DEPRECATION")
class DialogWithMaterialSlcBehaviourTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
@Test
fun supports_testtag_on_alert_with_buttons() {
@@ -260,12 +256,8 @@
) {
AlertWithMaterialSlc(
title = {},
- negativeButton = {
- Button(onClick = {}, content = {})
- },
- positiveButton = {
- Button(onClick = {}, content = {})
- },
+ negativeButton = { Button(onClick = {}, content = {}) },
+ positiveButton = { Button(onClick = {}, content = {}) },
content = { Text("Dialog", modifier = Modifier.testTag(TEST_TAG)) },
)
}
@@ -394,24 +386,22 @@
@Suppress("DEPRECATION")
class DialogWithMaterialSlcContentSizeAndPositionTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
@Test
fun spaces_icon_and_title_correctly_on_alert_with_buttons() {
- rule
- .setContentWithThemeForSizeAssertions(useUnmergedTree = true) {
- AlertWithMaterialSlc(
- icon = { TestImage(ICON_TAG) },
- title = { Text("Title", modifier = Modifier.testTag(TITLE_TAG)) },
- negativeButton = {
- Button(onClick = {}, modifier = Modifier.testTag(BUTTON_TAG)) {}
- },
- positiveButton = { Button(onClick = {}) {} },
- verticalArrangement = Arrangement.spacedBy(0.dp, Alignment.CenterVertically),
- modifier = Modifier.testTag(TEST_TAG),
- )
- }
+ rule.setContentWithThemeForSizeAssertions(useUnmergedTree = true) {
+ AlertWithMaterialSlc(
+ icon = { TestImage(ICON_TAG) },
+ title = { Text("Title", modifier = Modifier.testTag(TITLE_TAG)) },
+ negativeButton = {
+ Button(onClick = {}, modifier = Modifier.testTag(BUTTON_TAG)) {}
+ },
+ positiveButton = { Button(onClick = {}) {} },
+ verticalArrangement = Arrangement.spacedBy(0.dp, Alignment.CenterVertically),
+ modifier = Modifier.testTag(TEST_TAG),
+ )
+ }
val iconBottom = rule.onNodeWithTag(ICON_TAG).getUnclippedBoundsInRoot().bottom
val titleTop = rule.onNodeWithTag(TITLE_TAG).getUnclippedBoundsInRoot().top
@@ -422,20 +412,19 @@
fun spaces_title_and_buttons_correctly_on_alert_with_buttons() {
var titlePadding = 0.dp
- rule
- .setContentWithThemeForSizeAssertions(useUnmergedTree = true) {
- titlePadding = DialogDefaults.TitlePadding.calculateBottomPadding()
- AlertWithMaterialSlc(
- icon = { TestImage(ICON_TAG) },
- title = { Text("Title", modifier = Modifier.testTag(TITLE_TAG)) },
- negativeButton = {
- Button(onClick = {}, modifier = Modifier.testTag(BUTTON_TAG)) {}
- },
- positiveButton = { Button(onClick = {}) {} },
- verticalArrangement = Arrangement.spacedBy(0.dp, Alignment.CenterVertically),
- modifier = Modifier.testTag(TEST_TAG),
- )
- }
+ rule.setContentWithThemeForSizeAssertions(useUnmergedTree = true) {
+ titlePadding = DialogDefaults.TitlePadding.calculateBottomPadding()
+ AlertWithMaterialSlc(
+ icon = { TestImage(ICON_TAG) },
+ title = { Text("Title", modifier = Modifier.testTag(TITLE_TAG)) },
+ negativeButton = {
+ Button(onClick = {}, modifier = Modifier.testTag(BUTTON_TAG)) {}
+ },
+ positiveButton = { Button(onClick = {}) {} },
+ verticalArrangement = Arrangement.spacedBy(0.dp, Alignment.CenterVertically),
+ modifier = Modifier.testTag(TEST_TAG),
+ )
+ }
val titleBottom = rule.onNodeWithTag(TITLE_TAG).getUnclippedBoundsInRoot().bottom
val buttonTop = rule.onNodeWithTag(BUTTON_TAG).getUnclippedBoundsInRoot().top
@@ -444,24 +433,23 @@
@Test
fun spaces_icon_and_title_correctly_on_alert_with_chips() {
- rule
- .setContentWithThemeForSizeAssertions(useUnmergedTree = true) {
- AlertWithMaterialSlc(
- icon = { TestImage(ICON_TAG) },
- title = { Text("Title", modifier = Modifier.testTag(TITLE_TAG)) },
- content = {
- item {
- Chip(
- label = { Text("Chip") },
- onClick = {},
- modifier = Modifier.testTag(CHIP_TAG)
- )
- }
- },
- verticalArrangement = Arrangement.spacedBy(0.dp, Alignment.CenterVertically),
- modifier = Modifier.testTag(TEST_TAG),
- )
- }
+ rule.setContentWithThemeForSizeAssertions(useUnmergedTree = true) {
+ AlertWithMaterialSlc(
+ icon = { TestImage(ICON_TAG) },
+ title = { Text("Title", modifier = Modifier.testTag(TITLE_TAG)) },
+ content = {
+ item {
+ Chip(
+ label = { Text("Chip") },
+ onClick = {},
+ modifier = Modifier.testTag(CHIP_TAG)
+ )
+ }
+ },
+ verticalArrangement = Arrangement.spacedBy(0.dp, Alignment.CenterVertically),
+ modifier = Modifier.testTag(TEST_TAG),
+ )
+ }
val iconBottom = rule.onNodeWithTag(ICON_TAG).getUnclippedBoundsInRoot().bottom
val titleTop = rule.onNodeWithTag(TITLE_TAG).getUnclippedBoundsInRoot().top
@@ -472,25 +460,24 @@
fun spaces_title_and_chips_correctly_on_alert_with_chips() {
var titlePadding = 0.dp
- rule
- .setContentWithThemeForSizeAssertions(useUnmergedTree = true) {
- titlePadding = DialogDefaults.TitlePadding.calculateBottomPadding()
- AlertWithMaterialSlc(
- icon = { TestImage(ICON_TAG) },
- title = { Text("Title", modifier = Modifier.testTag(TITLE_TAG)) },
- content = {
- item {
- Chip(
- label = { Text("Chip") },
- onClick = {},
- modifier = Modifier.testTag(CHIP_TAG)
- )
- }
- },
- verticalArrangement = Arrangement.spacedBy(0.dp, Alignment.CenterVertically),
- modifier = Modifier.testTag(TEST_TAG),
- )
- }
+ rule.setContentWithThemeForSizeAssertions(useUnmergedTree = true) {
+ titlePadding = DialogDefaults.TitlePadding.calculateBottomPadding()
+ AlertWithMaterialSlc(
+ icon = { TestImage(ICON_TAG) },
+ title = { Text("Title", modifier = Modifier.testTag(TITLE_TAG)) },
+ content = {
+ item {
+ Chip(
+ label = { Text("Chip") },
+ onClick = {},
+ modifier = Modifier.testTag(CHIP_TAG)
+ )
+ }
+ },
+ verticalArrangement = Arrangement.spacedBy(0.dp, Alignment.CenterVertically),
+ modifier = Modifier.testTag(TEST_TAG),
+ )
+ }
val titleBottom = rule.onNodeWithTag(TITLE_TAG).getUnclippedBoundsInRoot().bottom
val chipTop = rule.onNodeWithTag(CHIP_TAG).getUnclippedBoundsInRoot().top
@@ -499,16 +486,15 @@
@Test
fun spaces_icon_and_title_correctly_on_ConfirmationWithMaterialSlc() {
- rule
- .setContentWithThemeForSizeAssertions(useUnmergedTree = true) {
- ConfirmationWithMaterialSlc(
- onTimeout = {},
- icon = { TestImage(ICON_TAG) },
- content = { Text("Title", modifier = Modifier.testTag(TITLE_TAG)) },
- verticalArrangement = Arrangement.spacedBy(0.dp, Alignment.CenterVertically),
- modifier = Modifier.testTag(TEST_TAG),
- )
- }
+ rule.setContentWithThemeForSizeAssertions(useUnmergedTree = true) {
+ ConfirmationWithMaterialSlc(
+ onTimeout = {},
+ icon = { TestImage(ICON_TAG) },
+ content = { Text("Title", modifier = Modifier.testTag(TITLE_TAG)) },
+ verticalArrangement = Arrangement.spacedBy(0.dp, Alignment.CenterVertically),
+ modifier = Modifier.testTag(TEST_TAG),
+ )
+ }
val iconBottom = rule.onNodeWithTag(ICON_TAG).getUnclippedBoundsInRoot().bottom
val titleTop = rule.onNodeWithTag(TITLE_TAG).getUnclippedBoundsInRoot().top
@@ -519,20 +505,19 @@
fun spaces_title_and_body_correctly_on_alert_with_buttons() {
var titleSpacing = 0.dp
- rule
- .setContentWithThemeForSizeAssertions(useUnmergedTree = true) {
- titleSpacing = DialogDefaults.TitlePadding.calculateBottomPadding()
- AlertWithMaterialSlc(
- title = { Text("Title", modifier = Modifier.testTag(TITLE_TAG)) },
- negativeButton = {
- Button(onClick = {}, modifier = Modifier.testTag(BUTTON_TAG)) {}
- },
- positiveButton = { Button(onClick = {}) {} },
- content = { Text("Body", modifier = Modifier.testTag(BODY_TAG)) },
- verticalArrangement = Arrangement.spacedBy(0.dp, Alignment.CenterVertically),
- modifier = Modifier.testTag(TEST_TAG),
- )
- }
+ rule.setContentWithThemeForSizeAssertions(useUnmergedTree = true) {
+ titleSpacing = DialogDefaults.TitlePadding.calculateBottomPadding()
+ AlertWithMaterialSlc(
+ title = { Text("Title", modifier = Modifier.testTag(TITLE_TAG)) },
+ negativeButton = {
+ Button(onClick = {}, modifier = Modifier.testTag(BUTTON_TAG)) {}
+ },
+ positiveButton = { Button(onClick = {}) {} },
+ content = { Text("Body", modifier = Modifier.testTag(BODY_TAG)) },
+ verticalArrangement = Arrangement.spacedBy(0.dp, Alignment.CenterVertically),
+ modifier = Modifier.testTag(TEST_TAG),
+ )
+ }
val titleBottom = rule.onNodeWithTag(TITLE_TAG).getUnclippedBoundsInRoot().bottom
val bodyTop = rule.onNodeWithTag(BODY_TAG).getUnclippedBoundsInRoot().top
@@ -543,26 +528,25 @@
fun spaces_title_and_body_correctly_on_alert_with_chips() {
var titleSpacing = 0.dp
- rule
- .setContentWithThemeForSizeAssertions(useUnmergedTree = true) {
- titleSpacing = DialogDefaults.TitlePadding.calculateBottomPadding()
- AlertWithMaterialSlc(
- icon = { TestImage(ICON_TAG) },
- title = { Text("Title", modifier = Modifier.testTag(TITLE_TAG)) },
- message = { Text("Message", modifier = Modifier.testTag(BODY_TAG)) },
- content = {
- item {
- Chip(
- label = { Text("Chip") },
- onClick = {},
- modifier = Modifier.testTag(CHIP_TAG)
- )
- }
- },
- verticalArrangement = Arrangement.spacedBy(0.dp, Alignment.CenterVertically),
- modifier = Modifier.testTag(TEST_TAG),
- )
- }
+ rule.setContentWithThemeForSizeAssertions(useUnmergedTree = true) {
+ titleSpacing = DialogDefaults.TitlePadding.calculateBottomPadding()
+ AlertWithMaterialSlc(
+ icon = { TestImage(ICON_TAG) },
+ title = { Text("Title", modifier = Modifier.testTag(TITLE_TAG)) },
+ message = { Text("Message", modifier = Modifier.testTag(BODY_TAG)) },
+ content = {
+ item {
+ Chip(
+ label = { Text("Chip") },
+ onClick = {},
+ modifier = Modifier.testTag(CHIP_TAG)
+ )
+ }
+ },
+ verticalArrangement = Arrangement.spacedBy(0.dp, Alignment.CenterVertically),
+ modifier = Modifier.testTag(TEST_TAG),
+ )
+ }
val titleBottom = rule.onNodeWithTag(TITLE_TAG).getUnclippedBoundsInRoot().bottom
val bodyTop = rule.onNodeWithTag(BODY_TAG).getUnclippedBoundsInRoot().top
@@ -573,23 +557,20 @@
fun spaces_body_and_buttons_correctly_on_alert_with_buttons() {
var bodyPadding = 0.dp
- rule
- .setContentWithThemeForSizeAssertions(useUnmergedTree = true) {
- bodyPadding = DialogDefaults.BodyPadding.calculateBottomPadding()
- AlertWithMaterialSlc(
- icon = {},
- title = {},
- negativeButton = {
- Button(onClick = {}, modifier = Modifier.testTag(BUTTON_TAG)) {}
- },
- positiveButton = {
- Button(onClick = {}) {}
- },
- content = { Text("Body", modifier = Modifier.testTag(BODY_TAG)) },
- verticalArrangement = Arrangement.spacedBy(0.dp, Alignment.CenterVertically),
- modifier = Modifier.testTag(TEST_TAG),
- )
- }
+ rule.setContentWithThemeForSizeAssertions(useUnmergedTree = true) {
+ bodyPadding = DialogDefaults.BodyPadding.calculateBottomPadding()
+ AlertWithMaterialSlc(
+ icon = {},
+ title = {},
+ negativeButton = {
+ Button(onClick = {}, modifier = Modifier.testTag(BUTTON_TAG)) {}
+ },
+ positiveButton = { Button(onClick = {}) {} },
+ content = { Text("Body", modifier = Modifier.testTag(BODY_TAG)) },
+ verticalArrangement = Arrangement.spacedBy(0.dp, Alignment.CenterVertically),
+ modifier = Modifier.testTag(TEST_TAG),
+ )
+ }
val bodyBottom = rule.onNodeWithTag(BODY_TAG).getUnclippedBoundsInRoot().bottom
val buttonTop = rule.onNodeWithTag(BUTTON_TAG).getUnclippedBoundsInRoot().top
@@ -600,26 +581,25 @@
fun spaces_body_and_chips_correctly_on_alert_with_chips() {
var bodyPadding = 0.dp
- rule
- .setContentWithThemeForSizeAssertions(useUnmergedTree = true) {
- bodyPadding = DialogDefaults.BodyPadding.calculateBottomPadding()
- AlertWithMaterialSlc(
- icon = { TestImage(ICON_TAG) },
- title = { Text("Title", modifier = Modifier.testTag(TITLE_TAG)) },
- message = { Text("Message", modifier = Modifier.testTag(BODY_TAG)) },
- content = {
- item {
- Chip(
- label = { Text("Chip") },
- onClick = {},
- modifier = Modifier.testTag(CHIP_TAG)
- )
- }
- },
- verticalArrangement = Arrangement.spacedBy(0.dp, Alignment.CenterVertically),
- modifier = Modifier.testTag(TEST_TAG),
- )
- }
+ rule.setContentWithThemeForSizeAssertions(useUnmergedTree = true) {
+ bodyPadding = DialogDefaults.BodyPadding.calculateBottomPadding()
+ AlertWithMaterialSlc(
+ icon = { TestImage(ICON_TAG) },
+ title = { Text("Title", modifier = Modifier.testTag(TITLE_TAG)) },
+ message = { Text("Message", modifier = Modifier.testTag(BODY_TAG)) },
+ content = {
+ item {
+ Chip(
+ label = { Text("Chip") },
+ onClick = {},
+ modifier = Modifier.testTag(CHIP_TAG)
+ )
+ }
+ },
+ verticalArrangement = Arrangement.spacedBy(0.dp, Alignment.CenterVertically),
+ modifier = Modifier.testTag(TEST_TAG),
+ )
+ }
val bodyBottom = rule.onNodeWithTag(BODY_TAG).getUnclippedBoundsInRoot().bottom
val chipTop = rule.onNodeWithTag(CHIP_TAG).getUnclippedBoundsInRoot().top
@@ -629,8 +609,7 @@
@Suppress("DEPRECATION")
class DialogWithMaterialSlcContentColorTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
@Test
fun gives_icon_onbackground_on_alert_for_buttons() {
@@ -967,9 +946,7 @@
)
}
- rule.onNodeWithTag(TEST_TAG)
- .captureToImage()
- .assertContainsColor(overrideColor, 100.0f)
+ rule.onNodeWithTag(TEST_TAG).captureToImage().assertContainsColor(overrideColor, 100.0f)
}
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
@@ -987,9 +964,7 @@
)
}
- rule.onNodeWithTag(TEST_TAG)
- .captureToImage()
- .assertContainsColor(overrideColor, 100.0f)
+ rule.onNodeWithTag(TEST_TAG).captureToImage().assertContainsColor(overrideColor, 100.0f)
}
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
@@ -1006,9 +981,7 @@
)
}
- rule.onNodeWithTag(TEST_TAG)
- .captureToImage()
- .assertContainsColor(overrideColor, 100.0f)
+ rule.onNodeWithTag(TEST_TAG).captureToImage().assertContainsColor(overrideColor, 100.0f)
}
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
@@ -1020,15 +993,14 @@
var expectedBackground = Color.Transparent
rule.setContentWithTheme {
- Box(modifier = Modifier
- .fillMaxSize()
- .background(testBackground)) {
+ Box(modifier = Modifier.fillMaxSize().background(testBackground)) {
expectedBackground = expected()
content()
}
}
- rule.onNodeWithTag(TEST_TAG)
+ rule
+ .onNodeWithTag(TEST_TAG)
.captureToImage()
.assertContainsColor(expectedBackground, 100.0f)
}
@@ -1036,8 +1008,7 @@
@Suppress("DEPRECATION")
class DialogWithMaterialSlcTextStyleTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
@Test
fun gives_title_correct_textstyle_on_alert_for_buttons() {
diff --git a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/Button.kt b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/Button.kt
index 67e5b3c0..86ec2b5 100644
--- a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/Button.kt
+++ b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/Button.kt
@@ -37,47 +37,50 @@
/**
* Wear Material [Button] that offers a single slot to take any content (text, icon or image).
*
- * The [Button] is circular in shape. The recommended [Button] sizes can be obtained
- * from [ButtonDefaults] - see [ButtonDefaults.DefaultButtonSize], [ButtonDefaults.LargeButtonSize],
- * [ButtonDefaults.SmallButtonSize].
- * Icon content should be of size [ButtonDefaults.DefaultIconSize],
- * [ButtonDefaults.LargeIconSize] or [ButtonDefaults.SmallIconSize] respectively.
+ * The [Button] is circular in shape. The recommended [Button] sizes can be obtained from
+ * [ButtonDefaults] - see [ButtonDefaults.DefaultButtonSize], [ButtonDefaults.LargeButtonSize],
+ * [ButtonDefaults.SmallButtonSize]. Icon content should be of size
+ * [ButtonDefaults.DefaultIconSize], [ButtonDefaults.LargeIconSize] or
+ * [ButtonDefaults.SmallIconSize] respectively.
*
* The recommended set of [ButtonColors] styles can be obtained from [ButtonDefaults], e.g.
* [ButtonDefaults.primaryButtonColors] to get a color scheme for a primary [Button] which by
- * default will have a solid background of [Colors.primary] and content color of
- * [Colors.onPrimary].
+ * default will have a solid background of [Colors.primary] and content color of [Colors.onPrimary].
*
* [Button]s can be enabled or disabled. A disabled button will not respond to click events.
*
* Example of a [Button] displaying an icon:
+ *
* @sample androidx.wear.compose.material.samples.ButtonWithIcon
*
* Example of a large [Button] displaying an icon:
+ *
* @sample androidx.wear.compose.material.samples.LargeButtonWithIcon
*
* Example of a [Button] with text content and size modified to LargeButtonSize:
+ *
* @sample androidx.wear.compose.material.samples.ButtonWithText
*
* For more information, see the
- * [Buttons](https://developer.android.com/training/wearables/components/buttons)
- * guide.
+ * [Buttons](https://developer.android.com/training/wearables/components/buttons) guide.
*
* @param onClick Will be called when the user clicks the button.
* @param modifier Modifier to be applied to the button.
- * @param enabled Controls the enabled state of the button. When `false`, this button will not
- * be clickable.
+ * @param enabled Controls the enabled state of the button. When `false`, this button will not be
+ * clickable.
* @param colors [ButtonColors] that will be used to resolve the background and content color for
- * this button in different states. See [ButtonDefaults.buttonColors].
- * @param interactionSource The [MutableInteractionSource] representing the stream of
- * [Interaction]s for this Button. You can create and pass in your own remembered
- * [MutableInteractionSource] if you want to observe [Interaction]s and customize the
- * appearance / behavior of this Button in different [Interaction]s.
+ * this button in different states. See [ButtonDefaults.buttonColors].
+ * @param interactionSource The [MutableInteractionSource] representing the stream of [Interaction]s
+ * for this Button. You can create and pass in your own remembered [MutableInteractionSource] if
+ * you want to observe [Interaction]s and customize the appearance / behavior of this Button in
+ * different [Interaction]s.
* @param content The content displayed on the [Button] such as text, icon or image.
*/
-@Deprecated("This overload is provided for backwards compatibility with Compose for Wear OS 1.0." +
- "A newer overload is available with an additional shape parameter.",
- level = DeprecationLevel.HIDDEN)
+@Deprecated(
+ "This overload is provided for backwards compatibility with Compose for Wear OS 1.0." +
+ "A newer overload is available with an additional shape parameter.",
+ level = DeprecationLevel.HIDDEN
+)
@Composable
public fun Button(
onClick: () -> Unit,
@@ -101,46 +104,47 @@
/**
* Wear Material [Button] that offers a single slot to take any content (text, icon or image).
*
- * The recommended [Button] sizes can be obtained
- * from [ButtonDefaults] - see [ButtonDefaults.DefaultButtonSize], [ButtonDefaults.LargeButtonSize],
- * [ButtonDefaults.SmallButtonSize].
- * Icon content should be of size [ButtonDefaults.DefaultIconSize],
- * [ButtonDefaults.LargeIconSize] or [ButtonDefaults.SmallIconSize] respectively.
+ * The recommended [Button] sizes can be obtained from [ButtonDefaults] - see
+ * [ButtonDefaults.DefaultButtonSize], [ButtonDefaults.LargeButtonSize],
+ * [ButtonDefaults.SmallButtonSize]. Icon content should be of size
+ * [ButtonDefaults.DefaultIconSize], [ButtonDefaults.LargeIconSize] or
+ * [ButtonDefaults.SmallIconSize] respectively.
*
* The recommended set of [ButtonColors] styles can be obtained from [ButtonDefaults], e.g.
* [ButtonDefaults.primaryButtonColors] to get a color scheme for a primary [Button] which by
- * default will have a solid background of [Colors.primary] and content color of
- * [Colors.onPrimary].
+ * default will have a solid background of [Colors.primary] and content color of [Colors.onPrimary].
*
* [Button]s can be enabled or disabled. A disabled button will not respond to click events.
*
* Example of a [Button] displaying an icon:
+ *
* @sample androidx.wear.compose.material.samples.ButtonWithIcon
*
* Example of a large [Button] displaying an icon:
+ *
* @sample androidx.wear.compose.material.samples.LargeButtonWithIcon
*
* Example of a [Button] with text content and size modified to LargeButtonSize:
+ *
* @sample androidx.wear.compose.material.samples.ButtonWithText
*
* For more information, see the
- * [Buttons](https://developer.android.com/training/wearables/components/buttons)
- * guide.
+ * [Buttons](https://developer.android.com/training/wearables/components/buttons) guide.
*
* @param onClick Will be called when the user clicks the button.
* @param modifier Modifier to be applied to the button.
- * @param enabled Controls the enabled state of the button. When `false`, this button will not
- * be clickable.
+ * @param enabled Controls the enabled state of the button. When `false`, this button will not be
+ * clickable.
* @param colors [ButtonColors] that will be used to resolve the background and content color for
- * this button in different states. See [ButtonDefaults.buttonColors].
+ * this button in different states. See [ButtonDefaults.buttonColors].
* @param interactionSource an optional hoisted [MutableInteractionSource] for observing and
- * emitting [Interaction]s for this button. You can use this to change the button's appearance
- * or preview the button in different states. Note that if `null` is provided, interactions will
- * still happen internally.
+ * emitting [Interaction]s for this button. You can use this to change the button's appearance or
+ * preview the button in different states. Note that if `null` is provided, interactions will
+ * still happen internally.
* @param shape Defines the button's shape. It is strongly recommended to use the default as this
- * shape is a key characteristic of the Wear Material Theme.
+ * shape is a key characteristic of the Wear Material Theme.
* @param border [ButtonBorder] that will be used to resolve the button border in different states.
- * See [ButtonDefaults.buttonBorder].
+ * See [ButtonDefaults.buttonBorder].
* @param content The content displayed on the [Button] such as text, icon or image.
*/
@Composable
@@ -164,11 +168,12 @@
border = { border.borderStroke(enabled = it).value },
buttonSize = ButtonDefaults.DefaultButtonSize,
ripple = rippleOrFallbackImplementation(),
- content = provideScopeContent(
- colors.contentColor(enabled = enabled),
- MaterialTheme.typography.button,
- content
- )
+ content =
+ provideScopeContent(
+ colors.contentColor(enabled = enabled),
+ MaterialTheme.typography.button,
+ content
+ )
)
}
@@ -176,38 +181,38 @@
* Wear Material [OutlinedButton] that offers a single slot to take any content (text, icon or
* image).
*
- * The recommended [Button] sizes can be obtained
- * from [ButtonDefaults] - see [ButtonDefaults.DefaultButtonSize], [ButtonDefaults.LargeButtonSize],
- * [ButtonDefaults.SmallButtonSize].
- * Icon content should be of size [ButtonDefaults.DefaultIconSize],
- * [ButtonDefaults.LargeIconSize] or [ButtonDefaults.SmallIconSize] respectively.
+ * The recommended [Button] sizes can be obtained from [ButtonDefaults] - see
+ * [ButtonDefaults.DefaultButtonSize], [ButtonDefaults.LargeButtonSize],
+ * [ButtonDefaults.SmallButtonSize]. Icon content should be of size
+ * [ButtonDefaults.DefaultIconSize], [ButtonDefaults.LargeIconSize] or
+ * [ButtonDefaults.SmallIconSize] respectively.
*
* [Button]s can be enabled or disabled. A disabled button will not respond to click events.
*
- * An [OutlinedButton] has a transparent background and a thin border by default with
- * content taking the theme primary color.
+ * An [OutlinedButton] has a transparent background and a thin border by default with content taking
+ * the theme primary color.
*
* Example of a [OutlinedButton] displaying an icon:
+ *
* @sample androidx.wear.compose.material.samples.OutlinedButtonWithIcon
*
* For more information, see the
- * [Buttons](https://developer.android.com/training/wearables/components/buttons)
- * guide.
+ * [Buttons](https://developer.android.com/training/wearables/components/buttons) guide.
*
* @param onClick Will be called when the user clicks the button.
* @param modifier Modifier to be applied to the button.
- * @param enabled Controls the enabled state of the button. When `false`, this button will not
- * be clickable.
+ * @param enabled Controls the enabled state of the button. When `false`, this button will not be
+ * clickable.
* @param colors [ButtonColors] that will be used to resolve the background and content color for
- * this button in different states. See [ButtonDefaults.outlinedButtonColors].
+ * this button in different states. See [ButtonDefaults.outlinedButtonColors].
* @param interactionSource an optional hoisted [MutableInteractionSource] for observing and
- * emitting [Interaction]s for this button. You can use this to change the button's appearance
- * or preview the button in different states. Note that if `null` is provided, interactions will
- * still happen internally.
+ * emitting [Interaction]s for this button. You can use this to change the button's appearance or
+ * preview the button in different states. Note that if `null` is provided, interactions will
+ * still happen internally.
* @param shape Defines the button's shape. It is strongly recommended to use the default as this
- * shape is a key characteristic of the Wear Material Theme.
+ * shape is a key characteristic of the Wear Material Theme.
* @param border [ButtonBorder] that will be used to resolve the button border in different states.
- * See [ButtonDefaults.outlinedButtonBorder].
+ * See [ButtonDefaults.outlinedButtonBorder].
* @param content The content displayed on the [OutlinedButton] such as text, icon or image.
*/
@Composable
@@ -223,45 +228,46 @@
) = Button(onClick, modifier, enabled, colors, interactionSource, shape, border, content)
/**
- * Wear Material [CompactButton] that offers a single slot to take any content
- * (text, icon or image).
+ * Wear Material [CompactButton] that offers a single slot to take any content (text, icon or
+ * image).
*
* The [CompactButton] is circular in shape and has background size
- * [ButtonDefaults.ExtraSmallButtonSize]. There is an optional transparent padding around
- * the background, defaulted to [ButtonDefaults.CompactButtonBackgroundPadding],
- * which increases the clickable area. Icon content should have size [ButtonDefaults.SmallIconSize].
+ * [ButtonDefaults.ExtraSmallButtonSize]. There is an optional transparent padding around the
+ * background, defaulted to [ButtonDefaults.CompactButtonBackgroundPadding], which increases the
+ * clickable area. Icon content should have size [ButtonDefaults.SmallIconSize].
*
* The recommended set of [ButtonColors] styles can be obtained from [ButtonDefaults], e.g.
* [ButtonDefaults.primaryButtonColors] to get a color scheme for a primary [Button] which by
- * default will have a solid background of [Colors.primary] and content color of
- * [Colors.onPrimary].
+ * default will have a solid background of [Colors.primary] and content color of [Colors.onPrimary].
*
* [CompactButton]s can be enabled or disabled. A disabled button will not respond to click events.
*
* Example usage:
+ *
* @sample androidx.wear.compose.material.samples.CompactButtonWithIcon
*
* For more information, see the
- * [Buttons](https://developer.android.com/training/wearables/components/buttons)
- * guide.
+ * [Buttons](https://developer.android.com/training/wearables/components/buttons) guide.
*
* @param onClick Will be called when the user clicks the button.
* @param modifier Modifier to be applied to the button.
- * @param enabled Controls the enabled state of the button. When `false`, this button will not
- * be clickable.
+ * @param enabled Controls the enabled state of the button. When `false`, this button will not be
+ * clickable.
* @param colors [ButtonColors] that will be used to resolve the background and content color for
- * this button in different states. See [ButtonDefaults.buttonColors].
- * @param backgroundPadding Increases the transparent clickable area around the background,
- * defaults to [ButtonDefaults.CompactButtonBackgroundPadding]
- * @param interactionSource The [MutableInteractionSource] representing the stream of
- * [Interaction]s for this Button. You can create and pass in your own remembered
- * [MutableInteractionSource] if you want to observe [Interaction]s and customize the
- * appearance / behavior of this Button in different [Interaction]s.
+ * this button in different states. See [ButtonDefaults.buttonColors].
+ * @param backgroundPadding Increases the transparent clickable area around the background, defaults
+ * to [ButtonDefaults.CompactButtonBackgroundPadding]
+ * @param interactionSource The [MutableInteractionSource] representing the stream of [Interaction]s
+ * for this Button. You can create and pass in your own remembered [MutableInteractionSource] if
+ * you want to observe [Interaction]s and customize the appearance / behavior of this Button in
+ * different [Interaction]s.
* @param content The content displayed on the [CompactButton] such as text, icon or image.
*/
-@Deprecated("This overload is provided for backwards compatibility with Compose for Wear OS 1.0." +
- "A newer overload is available with an additional shape parameter.",
- level = DeprecationLevel.HIDDEN)
+@Deprecated(
+ "This overload is provided for backwards compatibility with Compose for Wear OS 1.0." +
+ "A newer overload is available with an additional shape parameter.",
+ level = DeprecationLevel.HIDDEN
+)
@Composable
public fun CompactButton(
onClick: () -> Unit,
@@ -271,56 +277,57 @@
backgroundPadding: Dp = ButtonDefaults.CompactButtonBackgroundPadding,
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
content: @Composable BoxScope.() -> Unit,
-) = CompactButton(
- onClick,
- modifier,
- enabled,
- colors,
- backgroundPadding,
- interactionSource,
- CircleShape,
- ButtonDefaults.buttonBorder(),
- content)
+) =
+ CompactButton(
+ onClick,
+ modifier,
+ enabled,
+ colors,
+ backgroundPadding,
+ interactionSource,
+ CircleShape,
+ ButtonDefaults.buttonBorder(),
+ content
+ )
/**
- * Wear Material [CompactButton] that offers a single slot to take any content
- * (text, icon or image).
+ * Wear Material [CompactButton] that offers a single slot to take any content (text, icon or
+ * image).
*
- * The [CompactButton] has background size [ButtonDefaults.ExtraSmallButtonSize].
- * There is an optional transparent padding around
- * the background, defaulted to [ButtonDefaults.CompactButtonBackgroundPadding],
- * which increases the clickable area. Icon content should have size [ButtonDefaults.SmallIconSize].
+ * The [CompactButton] has background size [ButtonDefaults.ExtraSmallButtonSize]. There is an
+ * optional transparent padding around the background, defaulted to
+ * [ButtonDefaults.CompactButtonBackgroundPadding], which increases the clickable area. Icon content
+ * should have size [ButtonDefaults.SmallIconSize].
*
* The recommended set of [ButtonColors] styles can be obtained from [ButtonDefaults], e.g.
* [ButtonDefaults.primaryButtonColors] to get a color scheme for a primary [Button] which by
- * default will have a solid background of [Colors.primary] and content color of
- * [Colors.onPrimary].
+ * default will have a solid background of [Colors.primary] and content color of [Colors.onPrimary].
*
* [CompactButton]s can be enabled or disabled. A disabled button will not respond to click events.
*
* Example usage:
+ *
* @sample androidx.wear.compose.material.samples.CompactButtonWithIcon
*
* For more information, see the
- * [Buttons](https://developer.android.com/training/wearables/components/buttons)
- * guide.
+ * [Buttons](https://developer.android.com/training/wearables/components/buttons) guide.
*
* @param onClick Will be called when the user clicks the button.
* @param modifier Modifier to be applied to the button.
- * @param enabled Controls the enabled state of the button. When `false`, this button will not
- * be clickable.
+ * @param enabled Controls the enabled state of the button. When `false`, this button will not be
+ * clickable.
* @param colors [ButtonColors] that will be used to resolve the background and content color for
- * this button in different states. See [ButtonDefaults.buttonColors].
- * @param backgroundPadding Increases the transparent clickable area around the background,
- * defaults to [ButtonDefaults.CompactButtonBackgroundPadding]
+ * this button in different states. See [ButtonDefaults.buttonColors].
+ * @param backgroundPadding Increases the transparent clickable area around the background, defaults
+ * to [ButtonDefaults.CompactButtonBackgroundPadding]
* @param interactionSource an optional hoisted [MutableInteractionSource] for observing and
- * emitting [Interaction]s for this button. You can use this to change the button's appearance
- * or preview the button in different states. Note that if `null` is provided, interactions will
- * still happen internally.
+ * emitting [Interaction]s for this button. You can use this to change the button's appearance or
+ * preview the button in different states. Note that if `null` is provided, interactions will
+ * still happen internally.
* @param shape Defines the button's shape. It is strongly recommended to use the default as this
- * shape is a key characteristic of the Wear Material Theme.
+ * shape is a key characteristic of the Wear Material Theme.
* @param border [ButtonBorder] that will be used to resolve the button border in different states.
- * See [ButtonDefaults.outlinedButtonBorder].
+ * See [ButtonDefaults.outlinedButtonBorder].
* @param content The content displayed on the [CompactButton] such as text, icon or image.
*/
@Composable
@@ -337,9 +344,8 @@
) {
androidx.wear.compose.materialcore.RoundButton(
onClick = onClick,
- modifier = modifier
- .padding(backgroundPadding)
- .requiredSize(ButtonDefaults.ExtraSmallButtonSize),
+ modifier =
+ modifier.padding(backgroundPadding).requiredSize(ButtonDefaults.ExtraSmallButtonSize),
enabled = enabled,
backgroundColor = { colors.backgroundColor(it).value },
interactionSource = interactionSource,
@@ -347,52 +353,53 @@
border = { border.borderStroke(it).value },
buttonSize = ButtonDefaults.ExtraSmallButtonSize,
ripple = rippleOrFallbackImplementation(),
- content = provideScopeContent(
- colors.contentColor(enabled = enabled),
- MaterialTheme.typography.button,
- content
- )
+ content =
+ provideScopeContent(
+ colors.contentColor(enabled = enabled),
+ MaterialTheme.typography.button,
+ content
+ )
)
}
/**
- * Wear Material [OutlinedCompactButton] that offers a single slot to take any content
- * (text, icon or image).
+ * Wear Material [OutlinedCompactButton] that offers a single slot to take any content (text, icon
+ * or image).
*
- * The [OutlinedCompactButton] has background size [ButtonDefaults.ExtraSmallButtonSize].
- * There is an transparent padding around the background, defaulted to
+ * The [OutlinedCompactButton] has background size [ButtonDefaults.ExtraSmallButtonSize]. There is
+ * an transparent padding around the background, defaulted to
* [ButtonDefaults.CompactButtonBackgroundPadding], which increases the clickable area. Icon content
* should have size [ButtonDefaults.SmallIconSize].
*
- * An [OutlinedCompactButton] has a transparent background and a thin border by default with
- * content taking the theme primary color.
+ * An [OutlinedCompactButton] has a transparent background and a thin border by default with content
+ * taking the theme primary color.
*
* [OutlinedCompactButton]s can be enabled or disabled. A disabled button will not respond to click
* events.
*
* Example usage:
+ *
* @sample androidx.wear.compose.material.samples.OutlinedCompactButtonWithIcon
*
* For more information, see the
- * [Buttons](https://developer.android.com/training/wearables/components/buttons)
- * guide.
+ * [Buttons](https://developer.android.com/training/wearables/components/buttons) guide.
*
* @param onClick Will be called when the user clicks the button.
* @param modifier Modifier to be applied to the button.
- * @param enabled Controls the enabled state of the button. When `false`, this button will not
- * be clickable.
+ * @param enabled Controls the enabled state of the button. When `false`, this button will not be
+ * clickable.
* @param colors [ButtonColors] that will be used to resolve the background and content color for
- * this button in different states. See [ButtonDefaults.outlinedButtonColors].
- * @param backgroundPadding Increases the transparent clickable area around the background,
- * defaults to [ButtonDefaults.CompactButtonBackgroundPadding]
+ * this button in different states. See [ButtonDefaults.outlinedButtonColors].
+ * @param backgroundPadding Increases the transparent clickable area around the background, defaults
+ * to [ButtonDefaults.CompactButtonBackgroundPadding]
* @param interactionSource an optional hoisted [MutableInteractionSource] for observing and
- * emitting [Interaction]s for this button. You can use this to change the button's appearance
- * or preview the button in different states. Note that if `null` is provided, interactions will
- * still happen internally.
+ * emitting [Interaction]s for this button. You can use this to change the button's appearance or
+ * preview the button in different states. Note that if `null` is provided, interactions will
+ * still happen internally.
* @param shape Defines the button's shape. It is strongly recommended to use the default as this
- * shape is a key characteristic of the Wear Material Theme.
+ * shape is a key characteristic of the Wear Material Theme.
* @param border [ButtonBorder] that will be used to resolve the button border in different states.
- * See [ButtonDefaults.outlinedButtonBorder].
+ * See [ButtonDefaults.outlinedButtonBorder].
* @param content The content displayed on the [OutlinedCompactButton] such as text, icon or image.
*/
@Composable
@@ -418,13 +425,13 @@
border = border,
content = content
)
+
/**
* Represents the background and content colors used in a button in different states.
*
- * See [ButtonDefaults.primaryButtonColors] for the default colors used in
- * a primary styled [Button].
- * See [ButtonDefaults.secondaryButtonColors] for the default colors used
- * in a secondary styled [Button].
+ * See [ButtonDefaults.primaryButtonColors] for the default colors used in a primary styled
+ * [Button]. See [ButtonDefaults.secondaryButtonColors] for the default colors used in a secondary
+ * styled [Button].
*/
@Stable
public interface ButtonColors {
@@ -433,21 +440,17 @@
*
* @param enabled whether the button is enabled
*/
- @Composable
- public fun backgroundColor(enabled: Boolean): State<Color>
+ @Composable public fun backgroundColor(enabled: Boolean): State<Color>
/**
* Represents the content color for this button, depending on [enabled].
*
* @param enabled whether the button is enabled
*/
- @Composable
- public fun contentColor(enabled: Boolean): State<Color>
+ @Composable public fun contentColor(enabled: Boolean): State<Color>
}
-/**
- * Represents the border stroke used in a [Button] in different states.
- */
+/** Represents the border stroke used in a [Button] in different states. */
@Stable
public interface ButtonBorder {
@Composable
@@ -459,9 +462,7 @@
public fun borderStroke(enabled: Boolean): State<BorderStroke?>
}
-/**
- * Contains the default values used by [Button].
- */
+/** Contains the default values used by [Button]. */
public object ButtonDefaults {
/**
* Creates a [ButtonColors] that represents the default background and content colors for a
@@ -501,16 +502,13 @@
backgroundColor: Color = MaterialTheme.colors.surface,
contentColor: Color = contentColorFor(backgroundColor)
): ButtonColors {
- return buttonColors(
- backgroundColor = backgroundColor,
- contentColor = contentColor
- )
+ return buttonColors(backgroundColor = backgroundColor, contentColor = contentColor)
}
/**
- * Creates a [ButtonColors] that represents the content colors for
- * an icon-only [Button]. If a button is disabled then the colors will have an alpha
- * ([ContentAlpha.disabled]) value applied.
+ * Creates a [ButtonColors] that represents the content colors for an icon-only [Button]. If a
+ * button is disabled then the colors will have an alpha ([ContentAlpha.disabled]) value
+ * applied.
*
* @param contentColor The content color of this [Button] when enabled
*/
@@ -525,9 +523,9 @@
}
/**
- * Creates a [ButtonColors] that represents the content colors for
- * an [OutlinedButton]. If a button is disabled then the colors will have an alpha
- * ([ContentAlpha.disabled]) value applied.
+ * Creates a [ButtonColors] that represents the content colors for an [OutlinedButton]. If a
+ * button is disabled then the colors will have an alpha ([ContentAlpha.disabled]) value
+ * applied.
*
* @param contentColor The content color of this [OutlinedButton] when enabled
*/
@@ -535,10 +533,7 @@
public fun outlinedButtonColors(
contentColor: Color = MaterialTheme.colors.primary,
): ButtonColors {
- return buttonColors(
- backgroundColor = Color.Transparent,
- contentColor = contentColor
- )
+ return buttonColors(backgroundColor = Color.Transparent, contentColor = contentColor)
}
/**
@@ -563,7 +558,7 @@
*
* @param borderColor The color to use for the border for this [OutlinedButton] when enabled
* @param disabledBorderColor The color to use for the border for this [OutlinedButton] when
- * disabled
+ * disabled
* @param borderWidth The width to use for the border for this [OutlinedButton]
*/
@Composable
@@ -578,53 +573,45 @@
)
}
- /**
- * The default background size of a [CompactButton].
- */
+ /** The default background size of a [CompactButton]. */
public val ExtraSmallButtonSize = 32.dp
/**
- * The recommended size for a small [Button].
- * You can apply this value for the size by overriding Modifier.size directly on [Button].
+ * The recommended size for a small [Button]. You can apply this value for the size by
+ * overriding Modifier.size directly on [Button].
*/
public val SmallButtonSize = 48.dp
/**
- * The default size applied for the [Button].
- * Note that you can override it by applying Modifier.size directly on [Button].
+ * The default size applied for the [Button]. Note that you can override it by applying
+ * Modifier.size directly on [Button].
*/
public val DefaultButtonSize = 52.dp
/**
- * The recommended size for a large [Button].
- * You can apply this value for the size by overriding Modifier.size directly on [Button].
+ * The recommended size for a large [Button]. You can apply this value for the size by
+ * overriding Modifier.size directly on [Button].
*/
public val LargeButtonSize = 60.dp
- /**
- * The size of an icon when used inside a small-sized [Button] or a [CompactButton].
- */
+ /** The size of an icon when used inside a small-sized [Button] or a [CompactButton]. */
public val SmallIconSize = 24.dp
- /**
- * The default size of an icon when used inside a default-sized [Button].
- */
+ /** The default size of an icon when used inside a default-sized [Button]. */
public val DefaultIconSize = 26.dp
- /**
- * The size of an icon when used inside a large-sized [Button].
- */
+ /** The size of an icon when used inside a large-sized [Button]. */
public val LargeIconSize = 30.dp
/**
- * The default padding for a [CompactButton]. This will result in a larger tap area
- * than visible area.
+ * The default padding for a [CompactButton]. This will result in a larger tap area than visible
+ * area.
*/
public val CompactButtonBackgroundPadding = 8.dp
/**
- * Creates a [ButtonColors] that represents the default background and content colors used in
- * a [Button].
+ * Creates a [ButtonColors] that represents the default background and content colors used in a
+ * [Button].
*
* @param backgroundColor the background color of this [Button] when enabled
* @param contentColor the content color of this [Button] when enabled
@@ -637,17 +624,16 @@
contentColor: Color = contentColorFor(backgroundColor),
disabledBackgroundColor: Color = backgroundColor.copy(alpha = ContentAlpha.disabled),
disabledContentColor: Color = contentColor.copy(alpha = ContentAlpha.disabled)
- ): ButtonColors = DefaultButtonColors(
- backgroundColor = backgroundColor,
- contentColor = contentColor,
- disabledBackgroundColor = disabledBackgroundColor,
- disabledContentColor = disabledContentColor
- )
+ ): ButtonColors =
+ DefaultButtonColors(
+ backgroundColor = backgroundColor,
+ contentColor = contentColor,
+ disabledBackgroundColor = disabledBackgroundColor,
+ disabledContentColor = disabledContentColor
+ )
}
-/**
- * Default [ButtonColors] implementation.
- */
+/** Default [ButtonColors] implementation. */
@Immutable
private class DefaultButtonColors(
private val backgroundColor: Color,
@@ -657,16 +643,12 @@
) : ButtonColors {
@Composable
override fun backgroundColor(enabled: Boolean): State<Color> {
- return rememberUpdatedState(
- if (enabled) backgroundColor else disabledBackgroundColor
- )
+ return rememberUpdatedState(if (enabled) backgroundColor else disabledBackgroundColor)
}
@Composable
override fun contentColor(enabled: Boolean): State<Color> {
- return rememberUpdatedState(
- if (enabled) contentColor else disabledContentColor
- )
+ return rememberUpdatedState(if (enabled) contentColor else disabledContentColor)
}
override fun equals(other: Any?): Boolean {
@@ -693,9 +675,7 @@
}
}
-/**
- * Default [ButtonBorder] implementation.
- */
+/** Default [ButtonBorder] implementation. */
@Immutable
private class DefaultButtonBorder(
private val borderStroke: BorderStroke? = null,
diff --git a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/Card.kt b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/Card.kt
index c9c736c..7ab5373 100644
--- a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/Card.kt
+++ b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/Card.kt
@@ -63,8 +63,8 @@
* Cards can be enabled or disabled. A disabled card will not respond to click events.
*
* For more information, see the
- * [Cards](https://developer.android.com/training/wearables/components/cards)
- * Wear OS Material design guide.
+ * [Cards](https://developer.android.com/training/wearables/components/cards) Wear OS Material
+ * design guide.
*
* Note that the Wear OS design guidance recommends a gradient or image background for Cards which
* is not the case for Mobile Cards. As a result you will see a backgroundPainter rather than a
@@ -73,23 +73,23 @@
*
* @param onClick Will be called when the user clicks the card
* @param modifier Modifier to be applied to the card
- * @param backgroundPainter A painter used to paint the background of the card. A card will
- * normally have a gradient background. Use [CardDefaults.cardBackgroundPainter()] to obtain an
- * appropriate painter
+ * @param backgroundPainter A painter used to paint the background of the card. A card will normally
+ * have a gradient background. Use [CardDefaults.cardBackgroundPainter()] to obtain an appropriate
+ * painter
* @param contentColor The default color to use for content() unless explicitly set.
- * @param enabled Controls the enabled state of the card. When false, this card will not
- * be clickable and there will be no ripple effect on click. Wear cards do not have any specific
- * elevation or alpha differences when not enabled - they are simply not clickable.
+ * @param enabled Controls the enabled state of the card. When false, this card will not be
+ * clickable and there will be no ripple effect on click. Wear cards do not have any specific
+ * elevation or alpha differences when not enabled - they are simply not clickable.
* @param contentPadding The spacing values to apply internally between the container and the
- * content
+ * content
* @param shape Defines the card's shape. It is strongly recommended to use the default as this
- * shape is a key characteristic of the Wear Material Theme
+ * shape is a key characteristic of the Wear Material Theme
* @param interactionSource an optional hoisted [MutableInteractionSource] for observing and
- * emitting [Interaction]s for this card. You can use this to change the card's appearance
- * or preview the card in different states. Note that if `null` is provided, interactions will
- * still happen internally.
- * @param role The type of user interface element. Accessibility services might use this
- * to describe the element or do customizations
+ * emitting [Interaction]s for this card. You can use this to change the card's appearance or
+ * preview the card in different states. Note that if `null` is provided, interactions will still
+ * happen internally.
+ * @param role The type of user interface element. Accessibility services might use this to describe
+ * the element or do customizations
* @param content Slot for composable body content displayed on the Card
*/
@Composable
@@ -136,48 +136,48 @@
* The first row of the layout has three slots, 1) a small optional application [Image] or [Icon] of
* size [CardDefaults.AppImageSize]x[CardDefaults.AppImageSize] dp, 2) an application name
* (emphasised with the [CardColors.appColor()] color), it is expected to be a short start aligned
- * [Text] composable, and 3) the time that the application activity has occurred which will be
- * shown on the top row of the card, this is expected to be an end aligned [Text] composable
- * showing a time relevant to the contents of the [Card].
+ * [Text] composable, and 3) the time that the application activity has occurred which will be shown
+ * on the top row of the card, this is expected to be an end aligned [Text] composable showing a
+ * time relevant to the contents of the [Card].
*
* The second row shows a title, this is expected to be a single row of start aligned [Text].
*
- * The rest of the [Card] contains the content which can be either [Text] or an [Image].
- * If the content is text it can be single or multiple line and is expected to be Top and Start
- * aligned.
+ * The rest of the [Card] contains the content which can be either [Text] or an [Image]. If the
+ * content is text it can be single or multiple line and is expected to be Top and Start aligned.
*
* If more than one composable is provided in the content slot it is the responsibility of the
* caller to determine how to layout the contents, e.g. provide either a row or a column.
*
* Example of an [AppCard] with icon, title, time and two lines of body text:
+ *
* @sample androidx.wear.compose.material.samples.AppCardWithIcon
*
* Example of an [AppCard] with image content:
+ *
* @sample androidx.wear.compose.material.samples.AppCardWithImage
*
* For more information, see the
- * [Cards](https://developer.android.com/training/wearables/components/cards)
- * guide.
+ * [Cards](https://developer.android.com/training/wearables/components/cards) guide.
*
* @param onClick Will be called when the user clicks the card
* @param appName A slot for displaying the application name, expected to be a single line of start
- * aligned text of [Typography.title3]
+ * aligned text of [Typography.title3]
* @param time A slot for displaying the time relevant to the contents of the card, expected to be a
- * short piece of end aligned text.
+ * short piece of end aligned text.
* @param title A slot for displaying the title of the card, expected to be one or two lines of
- * start aligned text of [Typography.button]
+ * start aligned text of [Typography.button]
* @param modifier Modifier to be applied to the card
- * @param enabled Controls the enabled state of the card. When false, this card will not
- * be clickable and there will be no ripple effect on click. Wear cards do not have any specific
- * elevation or alpha differences when not enabled - they are simply not clickable.
+ * @param enabled Controls the enabled state of the card. When false, this card will not be
+ * clickable and there will be no ripple effect on click. Wear cards do not have any specific
+ * elevation or alpha differences when not enabled - they are simply not clickable.
* @param appImage A slot for a small ([CardDefaults.AppImageSize]x[CardDefaults.AppImageSize] )
- * [Image] associated with the application.
- * @param backgroundPainter A painter used to paint the background of the card. A card will
- * normally have a gradient background. Use [CardDefaults.cardBackgroundPainter()] to obtain an
- * appropriate painter
+ * [Image] associated with the application.
+ * @param backgroundPainter A painter used to paint the background of the card. A card will normally
+ * have a gradient background. Use [CardDefaults.cardBackgroundPainter()] to obtain an appropriate
+ * painter
* @param contentColor The default color to use for content() slot unless explicitly set.
* @param appColor The default color to use for appName() and appImage() slots unless explicitly
- * set.
+ * set.
* @param timeColor The default color to use for time() slot unless explicitly set.
* @param titleColor The default color to use for title() slot unless explicitly set.
* @param content Slot for composable body content displayed on the Card
@@ -266,28 +266,29 @@
* caller to determine how to layout the contents, e.g. provide either a row or a column.
*
* Example of a [TitleCard] with two lines of body text:
+ *
* @sample androidx.wear.compose.material.samples.TitleCardStandard
*
* Example of a title card with a background image:
+ *
* @sample androidx.wear.compose.material.samples.TitleCardWithImageBackground
*
* For more information, see the
- * [Cards](https://developer.android.com/training/wearables/components/cards)
- * guide.
+ * [Cards](https://developer.android.com/training/wearables/components/cards) guide.
*
* @param onClick Will be called when the user clicks the card
* @param title A slot for displaying the title of the card, expected to be one or two lines of text
- * of [Typography.button]
+ * of [Typography.button]
* @param modifier Modifier to be applied to the card
- * @param enabled Controls the enabled state of the card. When false, this card will not
- * be clickable and there will be no ripple effect on click. Wear cards do not have any specific
- * elevation or alpha differences when not enabled - they are simply not clickable.
+ * @param enabled Controls the enabled state of the card. When false, this card will not be
+ * clickable and there will be no ripple effect on click. Wear cards do not have any specific
+ * elevation or alpha differences when not enabled - they are simply not clickable.
* @param time An optional slot for displaying the time relevant to the contents of the card,
- * expected to be a short piece of end aligned text.
+ * expected to be a short piece of end aligned text.
* @param backgroundPainter A painter used to paint the background of the card. A title card can
- * have either a gradient background or an image background, use
- * [CardDefaults.cardBackgroundPainter()] or [CardDefaults.imageBackgroundPainter()] to obtain an
- * appropriate painter
+ * have either a gradient background or an image background, use
+ * [CardDefaults.cardBackgroundPainter()] or [CardDefaults.imageBackgroundPainter()] to obtain an
+ * appropriate painter
* @param contentColor The default color to use for content() slot unless explicitly set.
* @param titleColor The default color to use for title() slot unless explicitly set.
* @param timeColor The default color to use for time() slot unless explicitly set.
@@ -350,40 +351,36 @@
}
}
-/**
- * Contains the default values used by [Card]
- */
+/** Contains the default values used by [Card] */
public object CardDefaults {
/**
* Creates a [Painter] for background colors for a [Card]. Cards typically have a linear
- * gradient for a background. The gradient will be between startBackgroundColor
- * and endBackgroundColor and at an angle of 45 degrees.
+ * gradient for a background. The gradient will be between startBackgroundColor and
+ * endBackgroundColor and at an angle of 45 degrees.
*
- * Cards should have a content color that contrasts with the background
- * gradient.
+ * Cards should have a content color that contrasts with the background gradient.
*
* @param startBackgroundColor The background color used at the start of the gradient of this
- * [Card]
+ * [Card]
* @param endBackgroundColor The background color used at the end of the gradient of this [Card]
* @param gradientDirection Whether the cards gradient should be start to end (indicated by
- * [LayoutDirection.Ltr]) or end to start (indicated by [LayoutDirection.Rtl]).
+ * [LayoutDirection.Ltr]) or end to start (indicated by [LayoutDirection.Rtl]).
*/
@Composable
public fun cardBackgroundPainter(
startBackgroundColor: Color =
- MaterialTheme.colors.primary.copy(alpha = 0.30f)
+ MaterialTheme.colors.primary
+ .copy(alpha = 0.30f)
.compositeOver(MaterialTheme.colors.background),
endBackgroundColor: Color =
- MaterialTheme.colors.onSurfaceVariant.copy(alpha = 0.20f)
+ MaterialTheme.colors.onSurfaceVariant
+ .copy(alpha = 0.20f)
.compositeOver(MaterialTheme.colors.background),
gradientDirection: LayoutDirection = LocalLayoutDirection.current
): Painter {
return BrushPainter(
FortyFiveDegreeLinearGradient(
- colors = listOf(
- startBackgroundColor,
- endBackgroundColor
- ),
+ colors = listOf(startBackgroundColor, endBackgroundColor),
ltr = gradientDirection == LayoutDirection.Ltr
)
)
@@ -400,17 +397,19 @@
*
* @param backgroundImagePainter The [Painter] to use to draw the background of the [Card]
* @param backgroundImageScrimBrush The [Brush] to use to paint a scrim over the background
- * image to ensure that any text drawn over the image is legible
+ * image to ensure that any text drawn over the image is legible
*/
@Composable
public fun imageWithScrimBackgroundPainter(
backgroundImagePainter: Painter,
- backgroundImageScrimBrush: Brush = Brush.linearGradient(
- colors = listOf(
- MaterialTheme.colors.surface.copy(alpha = 1.0f),
- MaterialTheme.colors.surface.copy(alpha = 0f)
+ backgroundImageScrimBrush: Brush =
+ Brush.linearGradient(
+ colors =
+ listOf(
+ MaterialTheme.colors.surface.copy(alpha = 1.0f),
+ MaterialTheme.colors.surface.copy(alpha = 0f)
+ )
)
- )
): Painter {
return ImageWithScrimPainter(
imagePainter = backgroundImagePainter,
@@ -421,27 +420,23 @@
private val CardHorizontalPadding = 12.dp
private val CardVerticalPadding = 12.dp
- /**
- * The default content padding used by [Card]
- */
- public val ContentPadding: PaddingValues = PaddingValues(
- start = CardHorizontalPadding,
- top = CardVerticalPadding,
- end = CardHorizontalPadding,
- bottom = CardVerticalPadding
- )
+ /** The default content padding used by [Card] */
+ public val ContentPadding: PaddingValues =
+ PaddingValues(
+ start = CardHorizontalPadding,
+ top = CardVerticalPadding,
+ end = CardHorizontalPadding,
+ bottom = CardVerticalPadding
+ )
- /**
- * The default size of the app icon/image when used inside a [AppCard].
- */
+ /** The default size of the app icon/image when used inside a [AppCard]. */
public val AppImageSize: Dp = 16.dp
}
-/**
- * A linear gradient that draws the gradient at 45 degrees from Top|Start.
- */
+/** A linear gradient that draws the gradient at 45 degrees from Top|Start. */
@Immutable
-internal class FortyFiveDegreeLinearGradient internal constructor(
+internal class FortyFiveDegreeLinearGradient
+internal constructor(
private val colors: List<Color>,
private val stops: List<Float>? = null,
private val tileMode: TileMode = TileMode.Clamp,
diff --git a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/Chip.kt b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/Chip.kt
index 5fed098..6fc4098 100644
--- a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/Chip.kt
+++ b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/Chip.kt
@@ -68,44 +68,44 @@
* as icons and labels.
*
* The [Chip] is Stadium shaped and has a max height designed to take no more than two lines of text
- * of [Typography.button] style. The [Chip] can have an icon or image horizontally
- * parallel to the two lines of text. With localisation and/or large font sizes, the [Chip] height
- * adjusts to accommodate the contents.
+ * of [Typography.button] style. The [Chip] can have an icon or image horizontally parallel to the
+ * two lines of text. With localisation and/or large font sizes, the [Chip] height adjusts to
+ * accommodate the contents.
*
* The [Chip] can have different styles with configurable content colors, background colors
* including gradients, these are provided by [ChipColors] implementations.
*
* The recommended set of [ChipColors] styles can be obtained from [ChipDefaults], e.g.
- * [ChipDefaults.primaryChipColors] to get a color scheme for a primary [Chip] which by default
- * will have a solid background of [Colors.primary] and content color of
- * [Colors.onPrimary].
+ * [ChipDefaults.primaryChipColors] to get a color scheme for a primary [Chip] which by default will
+ * have a solid background of [Colors.primary] and content color of [Colors.onPrimary].
*
* Chips can be enabled or disabled. A disabled chip will not respond to click events.
*
* For more information, see the
- * [Chips](https://developer.android.com/training/wearables/components/chips)
- * guide.
+ * [Chips](https://developer.android.com/training/wearables/components/chips) guide.
*
* @param onClick Will be called when the user clicks the chip
- * @param colors [ChipColors] that will be used to resolve the background and content color for
- * this chip in different states. See [ChipDefaults.chipColors].
+ * @param colors [ChipColors] that will be used to resolve the background and content color for this
+ * chip in different states. See [ChipDefaults.chipColors].
* @param modifier Modifier to be applied to the chip
- * @param enabled Controls the enabled state of the chip. When `false`, this chip will not
- * be clickable
+ * @param enabled Controls the enabled state of the chip. When `false`, this chip will not be
+ * clickable
* @param contentPadding The spacing values to apply internally between the container and the
- * content
+ * content
* @param shape Defines the chip's shape. It is strongly recommended to use the default as this
- * shape is a key characteristic of the Wear Material Theme
- * @param interactionSource The [MutableInteractionSource] representing the stream of
- * [Interaction]s for this Chip. You can create and pass in your own remembered
- * [MutableInteractionSource] if you want to observe [Interaction]s and customize the
- * appearance / behavior of this Chip in different [Interaction]s.
- * @param role The type of user interface element. Accessibility services might use this
- * to describe the element or do customizations
+ * shape is a key characteristic of the Wear Material Theme
+ * @param interactionSource The [MutableInteractionSource] representing the stream of [Interaction]s
+ * for this Chip. You can create and pass in your own remembered [MutableInteractionSource] if you
+ * want to observe [Interaction]s and customize the appearance / behavior of this Chip in
+ * different [Interaction]s.
+ * @param role The type of user interface element. Accessibility services might use this to describe
+ * the element or do customizations
*/
-@Deprecated("This overload is provided for backwards compatibility with Compose for Wear OS 1.0." +
- "A newer overload is available with an additional border parameter.",
- level = DeprecationLevel.HIDDEN)
+@Deprecated(
+ "This overload is provided for backwards compatibility with Compose for Wear OS 1.0." +
+ "A newer overload is available with an additional border parameter.",
+ level = DeprecationLevel.HIDDEN
+)
@Composable
public fun Chip(
onClick: () -> Unit,
@@ -117,17 +117,19 @@
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
role: Role? = Role.Button,
content: @Composable RowScope.() -> Unit,
-) = Chip(
- onClick = onClick,
- colors = colors,
- border = ChipDefaults.chipBorder(),
- modifier = modifier,
- enabled = enabled,
- contentPadding = contentPadding,
- shape = shape,
- interactionSource = interactionSource,
- role = role,
- content = content)
+) =
+ Chip(
+ onClick = onClick,
+ colors = colors,
+ border = ChipDefaults.chipBorder(),
+ modifier = modifier,
+ enabled = enabled,
+ contentPadding = contentPadding,
+ shape = shape,
+ interactionSource = interactionSource,
+ role = role,
+ content = content
+ )
/**
* Base level Wear Material [Chip] that offers a single slot to take any content.
@@ -136,42 +138,40 @@
* as icons and labels.
*
* The [Chip] is Stadium shaped and has a max height designed to take no more than two lines of text
- * of [Typography.button] style. The [Chip] can have an icon or image horizontally
- * parallel to the two lines of text. With localisation and/or large font sizes, the [Chip] height
- * adjusts to accommodate the contents.
+ * of [Typography.button] style. The [Chip] can have an icon or image horizontally parallel to the
+ * two lines of text. With localisation and/or large font sizes, the [Chip] height adjusts to
+ * accommodate the contents.
*
* The [Chip] can have different styles with configurable content colors, background colors
* including gradients, these are provided by [ChipColors] implementations.
*
* The recommended set of [ChipColors] styles can be obtained from [ChipDefaults], e.g.
- * [ChipDefaults.primaryChipColors] to get a color scheme for a primary [Chip] which by default
- * will have a solid background of [Colors.primary] and content color of
- * [Colors.onPrimary].
+ * [ChipDefaults.primaryChipColors] to get a color scheme for a primary [Chip] which by default will
+ * have a solid background of [Colors.primary] and content color of [Colors.onPrimary].
*
* Chips can be enabled or disabled. A disabled chip will not respond to click events.
*
* For more information, see the
- * [Chips](https://developer.android.com/training/wearables/components/chips)
- * guide.
+ * [Chips](https://developer.android.com/training/wearables/components/chips) guide.
*
* @param onClick Will be called when the user clicks the chip
- * @param colors [ChipColors] that will be used to resolve the background and content color for
- * this chip in different states. See [ChipDefaults.chipColors].
+ * @param colors [ChipColors] that will be used to resolve the background and content color for this
+ * chip in different states. See [ChipDefaults.chipColors].
* @param border [ChipBorder] that will be used to resolve the border for this chip in different
- * states. See [ChipDefaults.chipBorder].
+ * states. See [ChipDefaults.chipBorder].
* @param modifier Modifier to be applied to the chip
- * @param enabled Controls the enabled state of the chip. When `false`, this chip will not
- * be clickable
+ * @param enabled Controls the enabled state of the chip. When `false`, this chip will not be
+ * clickable
* @param contentPadding The spacing values to apply internally between the container and the
- * content
+ * content
* @param shape Defines the chip's shape. It is strongly recommended to use the default as this
- * shape is a key characteristic of the Wear Material Theme
+ * shape is a key characteristic of the Wear Material Theme
* @param interactionSource an optional hoisted [MutableInteractionSource] for observing and
- * emitting [Interaction]s for this chip. You can use this to change the chip's appearance
- * or preview the chip in different states. Note that if `null` is provided, interactions will
- * still happen internally.
- * @param role The type of user interface element. Accessibility services might use this
- * to describe the element or do customizations
+ * emitting [Interaction]s for this chip. You can use this to change the chip's appearance or
+ * preview the chip in different states. Note that if `null` is provided, interactions will still
+ * happen internally.
+ * @param role The type of user interface element. Accessibility services might use this to describe
+ * the element or do customizations
* @param content Slot for composable body content displayed on the Chip
*/
@Composable
@@ -207,10 +207,9 @@
* if provided, at the start of a row, with a column next containing the two label slots.
*
* The [Chip] is Stadium shaped and has a max height designed to take no more than two lines of text
- * of [Typography.button] style. If no secondary label is provided then the label
- * can be two lines of text. The label and secondary label should be consistently aligned.
- * With localisation and/or large font sizes, the [Chip] height adjusts to
- * accommodate the contents.
+ * of [Typography.button] style. If no secondary label is provided then the label can be two lines
+ * of text. The label and secondary label should be consistently aligned. With localisation and/or
+ * large font sizes, the [Chip] height adjusts to accommodate the contents.
*
* If a icon is provided then the labels should be "start" aligned, e.g. left aligned in ltr so that
* the text starts next to the icon.
@@ -219,49 +218,50 @@
* including gradients, these are provided by [ChipColors] implementations.
*
* The recommended set of [ChipColors] styles can be obtained from [ChipDefaults], e.g.
- * [ChipDefaults.primaryChipColors] to get a color scheme for a primary [Chip] which by default
- * will have a solid background of [Colors.primary] and content color of
- * [Colors.onPrimary].
+ * [ChipDefaults.primaryChipColors] to get a color scheme for a primary [Chip] which by default will
+ * have a solid background of [Colors.primary] and content color of [Colors.onPrimary].
*
* Chips can be enabled or disabled. A disabled chip will not respond to click events.
*
* Example of a [Chip] with icon and a label only with longer text:
+ *
* @sample androidx.wear.compose.material.samples.ChipWithIconAndLabel
*
* Example of a [Chip] with icon, label and secondary label:
+ *
* @sample androidx.wear.compose.material.samples.ChipWithIconAndLabels
*
* For more information, see the
- * [Chips](https://developer.android.com/training/wearables/components/chips)
- * guide.
+ * [Chips](https://developer.android.com/training/wearables/components/chips) guide.
*
* @param label A slot for providing the chip's main label. The contents are expected to be text
- * which is "start" aligned if there is an icon preset and "start" or "center" aligned if not.
+ * which is "start" aligned if there is an icon preset and "start" or "center" aligned if not.
* @param onClick Will be called when the user clicks the chip
* @param modifier Modifier to be applied to the chip
* @param secondaryLabel A slot for providing the chip's secondary label. The contents are expected
- * to be text which is "start" aligned if there is an icon preset and "start" or "center" aligned if
- * not. label and secondaryLabel contents should be consistently aligned.
+ * to be text which is "start" aligned if there is an icon preset and "start" or "center" aligned
+ * if not. label and secondaryLabel contents should be consistently aligned.
* @param icon A slot for providing the chip's icon. The contents are expected to be a horizontally
- * and vertically aligned icon of size [ChipDefaults.IconSize] or [ChipDefaults.LargeIconSize]. In
- * order to correctly render when the Chip is not enabled the icon must set its alpha value to
- * [LocalContentAlpha].
- * @param colors [ChipColors] that will be used to resolve the background and content color for
- * this chip in different states. See [ChipDefaults.chipColors]. Defaults to
- * [ChipDefaults.primaryChipColors]
- * @param enabled Controls the enabled state of the chip. When `false`, this chip will not
- * be clickable
- * @param interactionSource The [MutableInteractionSource] representing the stream of
- * [Interaction]s for this Chip. You can create and pass in your own remembered
- * [MutableInteractionSource] if you want to observe [Interaction]s and customize the
- * appearance / behavior of this Chip in different [Interaction]s.
-
+ * and vertically aligned icon of size [ChipDefaults.IconSize] or [ChipDefaults.LargeIconSize]. In
+ * order to correctly render when the Chip is not enabled the icon must set its alpha value to
+ * [LocalContentAlpha].
+ * @param colors [ChipColors] that will be used to resolve the background and content color for this
+ * chip in different states. See [ChipDefaults.chipColors]. Defaults to
+ * [ChipDefaults.primaryChipColors]
+ * @param enabled Controls the enabled state of the chip. When `false`, this chip will not be
+ * clickable
+ * @param interactionSource The [MutableInteractionSource] representing the stream of [Interaction]s
+ * for this Chip. You can create and pass in your own remembered [MutableInteractionSource] if you
+ * want to observe [Interaction]s and customize the appearance / behavior of this Chip in
+ * different [Interaction]s.
* @param contentPadding The spacing values to apply internally between the container and the
- * content
+ * content
*/
-@Deprecated("This overload is provided for backwards compatibility with Compose for Wear OS 1.0." +
- "A newer overload is available with an additional shape parameter.",
- level = DeprecationLevel.HIDDEN)
+@Deprecated(
+ "This overload is provided for backwards compatibility with Compose for Wear OS 1.0." +
+ "A newer overload is available with an additional shape parameter.",
+ level = DeprecationLevel.HIDDEN
+)
@Composable
public fun Chip(
label: @Composable RowScope.() -> Unit,
@@ -273,18 +273,19 @@
enabled: Boolean = true,
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
contentPadding: PaddingValues = ChipDefaults.ContentPadding,
-) = Chip(
- label,
- onClick,
- modifier,
- secondaryLabel,
- icon,
- colors,
- enabled,
- interactionSource,
- contentPadding,
- MaterialTheme.shapes.small
-)
+) =
+ Chip(
+ label,
+ onClick,
+ modifier,
+ secondaryLabel,
+ icon,
+ colors,
+ enabled,
+ interactionSource,
+ contentPadding,
+ MaterialTheme.shapes.small
+ )
/**
* Wear Material [Chip] that offers three slots and a specific layout for an icon, label and
@@ -292,10 +293,9 @@
* if provided, at the start of a row, with a column next containing the two label slots.
*
* The [Chip] is Stadium shaped and has a max height designed to take no more than two lines of text
- * of [Typography.button] style. If no secondary label is provided then the label
- * can be two lines of text. The label and secondary label should be consistently aligned.
- * With localisation and/or large font sizes, the [Chip] height adjusts to
- * accommodate the contents.
+ * of [Typography.button] style. If no secondary label is provided then the label can be two lines
+ * of text. The label and secondary label should be consistently aligned. With localisation and/or
+ * large font sizes, the [Chip] height adjusts to accommodate the contents.
*
* If a icon is provided then the labels should be "start" aligned, e.g. left aligned in ltr so that
* the text starts next to the icon.
@@ -304,48 +304,48 @@
* including gradients, these are provided by [ChipColors] implementations.
*
* The recommended set of [ChipColors] styles can be obtained from [ChipDefaults], e.g.
- * [ChipDefaults.primaryChipColors] to get a color scheme for a primary [Chip] which by default
- * will have a solid background of [Colors.primary] and content color of
- * [Colors.onPrimary].
+ * [ChipDefaults.primaryChipColors] to get a color scheme for a primary [Chip] which by default will
+ * have a solid background of [Colors.primary] and content color of [Colors.onPrimary].
*
* Chips can be enabled or disabled. A disabled chip will not respond to click events.
*
* Example of a [Chip] with icon and a label only with longer text:
+ *
* @sample androidx.wear.compose.material.samples.ChipWithIconAndLabel
*
* Example of a [Chip] with icon, label and secondary label:
+ *
* @sample androidx.wear.compose.material.samples.ChipWithIconAndLabels
*
* For more information, see the
- * [Chips](https://developer.android.com/training/wearables/components/chips)
- * guide.
+ * [Chips](https://developer.android.com/training/wearables/components/chips) guide.
*
* @param label A slot for providing the chip's main label. The contents are expected to be text
- * which is "start" aligned if there is an icon preset and "start" or "center" aligned if not.
+ * which is "start" aligned if there is an icon preset and "start" or "center" aligned if not.
* @param onClick Will be called when the user clicks the chip
* @param modifier Modifier to be applied to the chip
* @param secondaryLabel A slot for providing the chip's secondary label. The contents are expected
- * to be text which is "start" aligned if there is an icon preset and "start" or "center" aligned if
- * not. label and secondaryLabel contents should be consistently aligned.
+ * to be text which is "start" aligned if there is an icon preset and "start" or "center" aligned
+ * if not. label and secondaryLabel contents should be consistently aligned.
* @param icon A slot for providing the chip's icon. The contents are expected to be a horizontally
- * and vertically aligned icon of size [ChipDefaults.IconSize] or [ChipDefaults.LargeIconSize]. In
- * order to correctly render when the Chip is not enabled the icon must set its alpha value to
- * [LocalContentAlpha].
- * @param colors [ChipColors] that will be used to resolve the background and content color for
- * this chip in different states. See [ChipDefaults.chipColors]. Defaults to
- * [ChipDefaults.primaryChipColors]
- * @param enabled Controls the enabled state of the chip. When `false`, this chip will not
- * be clickable
+ * and vertically aligned icon of size [ChipDefaults.IconSize] or [ChipDefaults.LargeIconSize]. In
+ * order to correctly render when the Chip is not enabled the icon must set its alpha value to
+ * [LocalContentAlpha].
+ * @param colors [ChipColors] that will be used to resolve the background and content color for this
+ * chip in different states. See [ChipDefaults.chipColors]. Defaults to
+ * [ChipDefaults.primaryChipColors]
+ * @param enabled Controls the enabled state of the chip. When `false`, this chip will not be
+ * clickable
* @param interactionSource an optional hoisted [MutableInteractionSource] for observing and
- * emitting [Interaction]s for this chip. You can use this to change the chip's appearance
- * or preview the chip in different states. Note that if `null` is provided, interactions will
- * still happen internally.
+ * emitting [Interaction]s for this chip. You can use this to change the chip's appearance or
+ * preview the chip in different states. Note that if `null` is provided, interactions will still
+ * happen internally.
* @param contentPadding The spacing values to apply internally between the container and the
- * content
+ * content
* @param shape Defines the chip's shape. It is strongly recommended to use the default as this
- * shape is a key characteristic of the Wear Material Theme
- * @param border [ChipBorder] that will be used to resolve the chip border in different states.
- * See [ChipDefaults.chipBorder].
+ * shape is a key characteristic of the Wear Material Theme
+ * @param border [ChipBorder] that will be used to resolve the chip border in different states. See
+ * [ChipDefaults.chipBorder].
*/
@Composable
public fun Chip(
@@ -384,50 +384,49 @@
* if provided, at the start of a row, with a column next containing the two label slots.
*
* The [OutlinedChip] is Stadium shaped and has a max height designed to take no more than two lines
- * of text of [Typography.button] style. If no secondary label is provided then the label
- * can be two lines of text. The label and secondary label should be consistently aligned.
- * With localisation and/or large font sizes, the [OutlinedChip] height adjusts to
- * accommodate the contents.
+ * of text of [Typography.button] style. If no secondary label is provided then the label can be two
+ * lines of text. The label and secondary label should be consistently aligned. With localisation
+ * and/or large font sizes, the [OutlinedChip] height adjusts to accommodate the contents.
*
* If a icon is provided then the labels should be "start" aligned, e.g. left aligned in ltr so that
* the text starts next to the icon.
*
- * the [OutlinedChip] has a transparent background, a thin border and contents which are
- * colored with the theme primary color. Colors can be obtained and customized using
+ * the [OutlinedChip] has a transparent background, a thin border and contents which are colored
+ * with the theme primary color. Colors can be obtained and customized using
* [ChipDefaults.outlinedChipColors()].
*
* Chips can be enabled or disabled. A disabled chip will not respond to click events.
*
* Example of a [OutlinedChip] with icon and a label only with longer text:
+ *
* @sample androidx.wear.compose.material.samples.OutlinedChipWithIconAndLabel
*
* For more information, see the
- * [Chips](https://developer.android.com/training/wearables/components/chips)
- * guide.
+ * [Chips](https://developer.android.com/training/wearables/components/chips) guide.
*
* @param label A slot for providing the chip's main label. The contents are expected to be text
- * which is "start" aligned if there is an icon preset and "start" or "center" aligned if not.
+ * which is "start" aligned if there is an icon preset and "start" or "center" aligned if not.
* @param onClick Will be called when the user clicks the chip
* @param modifier Modifier to be applied to the chip
* @param secondaryLabel A slot for providing the chip's secondary label. The contents are expected
- * to be text which is "start" aligned if there is an icon preset and "start" or "center" aligned if
- * not. label and secondaryLabel contents should be consistently aligned.
+ * to be text which is "start" aligned if there is an icon preset and "start" or "center" aligned
+ * if not. label and secondaryLabel contents should be consistently aligned.
* @param icon A slot for providing the chip's icon. The contents are expected to be a horizontally
- * and vertically aligned icon of size [ChipDefaults.IconSize] or [ChipDefaults.LargeIconSize]. In
- * order to correctly render when the Chip is not enabled the icon must set its alpha value to
- * [LocalContentAlpha].
- * @param colors [ChipColors] that will be used to resolve the background and content color for
- * this chip in different states.
- * @param enabled Controls the enabled state of the chip. When `false`, this chip will not
- * be clickable
+ * and vertically aligned icon of size [ChipDefaults.IconSize] or [ChipDefaults.LargeIconSize]. In
+ * order to correctly render when the Chip is not enabled the icon must set its alpha value to
+ * [LocalContentAlpha].
+ * @param colors [ChipColors] that will be used to resolve the background and content color for this
+ * chip in different states.
+ * @param enabled Controls the enabled state of the chip. When `false`, this chip will not be
+ * clickable
* @param interactionSource an optional hoisted [MutableInteractionSource] for observing and
- * emitting [Interaction]s for this chip. You can use this to change the chip's appearance
- * or preview the chip in different states. Note that if `null` is provided, interactions will
- * still happen internally.
+ * emitting [Interaction]s for this chip. You can use this to change the chip's appearance or
+ * preview the chip in different states. Note that if `null` is provided, interactions will still
+ * happen internally.
* @param contentPadding The spacing values to apply internally between the container and the
- * content
+ * content
* @param shape Defines the chip's shape. It is strongly recommended to use the default as this
- * shape is a key characteristic of the Wear Material Theme
+ * shape is a key characteristic of the Wear Material Theme
* @param border [ChipBorder] that will be used to resolve the chip border in different states.
*/
@Composable
@@ -464,21 +463,19 @@
*
* The [CompactChip] is Stadium shaped and has a max height designed to take no more than one line
* of text of [Typography.caption1] style and/or one icon. The default max height is
- * [ChipDefaults.CompactChipHeight]. This includes a visible chip height of 32.dp and
- * 8.dp of padding above and below the chip in order to meet accessibility guidelines that
- * request a minimum of 48.dp height and width of tappable area.
+ * [ChipDefaults.CompactChipHeight]. This includes a visible chip height of 32.dp and 8.dp of
+ * padding above and below the chip in order to meet accessibility guidelines that request a minimum
+ * of 48.dp height and width of tappable area.
*
* If a icon is provided then the labels should be "start" aligned, e.g. left aligned in ltr so that
* the text starts next to the icon.
*
* The items are laid out as follows.
- *
* 1. If a label is provided then the chip will be laid out with the optional icon at the start of a
- * row followed by the label with a default max height of [ChipDefaults.CompactChipHeight].
- *
+ * row followed by the label with a default max height of [ChipDefaults.CompactChipHeight].
* 2. If only an icon is provided it will be laid out vertically and horizontally centered with a
- * default height of [ChipDefaults.CompactChipHeight] and the default width of
- * [ChipDefaults.IconOnlyCompactChipWidth]
+ * default height of [ChipDefaults.CompactChipHeight] and the default width of
+ * [ChipDefaults.IconOnlyCompactChipWidth]
*
* If neither icon nor label is provided then the chip will displayed like an icon only chip but
* with no contents and [ChipColors.background()] color.
@@ -487,49 +484,52 @@
* including gradients, these are provided by [ChipColors] implementations.
*
* The recommended set of [ChipColors] styles can be obtained from [ChipDefaults], e.g.
- * [ChipDefaults.primaryChipColors] to get a color scheme for a primary [Chip] which by default
- * will have a solid background of [Colors.primary] and content color of
- * [Colors.onPrimary].
+ * [ChipDefaults.primaryChipColors] to get a color scheme for a primary [Chip] which by default will
+ * have a solid background of [Colors.primary] and content color of [Colors.onPrimary].
*
* Chips can be enabled or disabled. A disabled chip will not respond to click events.
*
* Example of a [CompactChip] with icon and single line of label text:
+ *
* @sample androidx.wear.compose.material.samples.CompactChipWithIconAndLabel
*
* Example of a [CompactChip] with a label, note that the text is center aligned:
+ *
* @sample androidx.wear.compose.material.samples.CompactChipWithLabel
*
* Example of a [CompactChip] with an icon only, note that the recommended icon size is 24x24 when
* only an icon is displayed:
+ *
* @sample androidx.wear.compose.material.samples.CompactChipWithIcon
*
* For more information, see the
- * [Chips](https://developer.android.com/training/wearables/components/chips)
- * guide.
+ * [Chips](https://developer.android.com/training/wearables/components/chips) guide.
*
* @param onClick Will be called when the user clicks the chip
* @param modifier Modifier to be applied to the chip
* @param label A slot for providing the chip's main label. The contents are expected to be text
- * which is "start" aligned if there is an icon preset and "center" aligned if not.
+ * which is "start" aligned if there is an icon preset and "center" aligned if not.
* @param icon A slot for providing the chip's icon. The contents are expected to be a horizontally
- * and vertically aligned icon of size [ChipDefaults.SmallIconSize] when used with a label or
- * [ChipDefaults.IconSize] when used as the only content in the CompactChip. In order to correctly
- * render when the Chip is not enabled the icon must set its alpha value to [LocalContentAlpha].
- * @param colors [ChipColors] that will be used to resolve the background and content color for
- * this chip in different states. See [ChipDefaults.chipColors]. Defaults to
- * [ChipDefaults.primaryChipColors]
- * @param enabled Controls the enabled state of the chip. When `false`, this chip will not
- * be clickable
- * @param interactionSource The [MutableInteractionSource] representing the stream of
- * [Interaction]s for this Chip. You can create and pass in your own remembered
- * [MutableInteractionSource] if you want to observe [Interaction]s and customize the
- * appearance / behavior of this Chip in different [Interaction]s.
+ * and vertically aligned icon of size [ChipDefaults.SmallIconSize] when used with a label or
+ * [ChipDefaults.IconSize] when used as the only content in the CompactChip. In order to correctly
+ * render when the Chip is not enabled the icon must set its alpha value to [LocalContentAlpha].
+ * @param colors [ChipColors] that will be used to resolve the background and content color for this
+ * chip in different states. See [ChipDefaults.chipColors]. Defaults to
+ * [ChipDefaults.primaryChipColors]
+ * @param enabled Controls the enabled state of the chip. When `false`, this chip will not be
+ * clickable
+ * @param interactionSource The [MutableInteractionSource] representing the stream of [Interaction]s
+ * for this Chip. You can create and pass in your own remembered [MutableInteractionSource] if you
+ * want to observe [Interaction]s and customize the appearance / behavior of this Chip in
+ * different [Interaction]s.
* @param contentPadding The spacing values to apply internally between the container and the
- * content
+ * content
*/
-@Deprecated("This overload is provided for backwards compatibility with Compose for Wear OS 1.0." +
- "A newer overload is available with an additional shape parameter.",
- level = DeprecationLevel.HIDDEN)
+@Deprecated(
+ "This overload is provided for backwards compatibility with Compose for Wear OS 1.0." +
+ "A newer overload is available with an additional shape parameter.",
+ level = DeprecationLevel.HIDDEN
+)
@Composable
public fun CompactChip(
onClick: () -> Unit,
@@ -540,18 +540,19 @@
enabled: Boolean = true,
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
contentPadding: PaddingValues = ChipDefaults.CompactChipContentPadding,
-) = CompactChip(
- onClick,
- modifier,
- label,
- icon,
- colors,
- enabled,
- interactionSource,
- contentPadding,
- MaterialTheme.shapes.small,
- ChipDefaults.chipBorder()
-)
+) =
+ CompactChip(
+ onClick,
+ modifier,
+ label,
+ icon,
+ colors,
+ enabled,
+ interactionSource,
+ contentPadding,
+ MaterialTheme.shapes.small,
+ ChipDefaults.chipBorder()
+ )
/**
* A compact Wear Material Chip that offers two slots and a specific layout for an icon and label.
@@ -559,21 +560,19 @@
*
* The [CompactChip] is Stadium shaped and has a max height designed to take no more than one line
* of text of [Typography.caption1] style and/or one icon. The default max height is
- * [ChipDefaults.CompactChipHeight]. This includes a visible chip height of 32.dp and
- * 8.dp of padding above and below the chip in order to meet accessibility guidelines that
- * request a minimum of 48.dp height and width of tappable area.
+ * [ChipDefaults.CompactChipHeight]. This includes a visible chip height of 32.dp and 8.dp of
+ * padding above and below the chip in order to meet accessibility guidelines that request a minimum
+ * of 48.dp height and width of tappable area.
*
* If a icon is provided then the labels should be "start" aligned, e.g. left aligned in ltr so that
* the text starts next to the icon.
*
* The items are laid out as follows.
- *
* 1. If a label is provided then the chip will be laid out with the optional icon at the start of a
- * row followed by the label with a default max height of [ChipDefaults.CompactChipHeight].
- *
+ * row followed by the label with a default max height of [ChipDefaults.CompactChipHeight].
* 2. If only an icon is provided it will be laid out vertically and horizontally centered with a
- * default height of [ChipDefaults.CompactChipHeight] and the default width of
- * [ChipDefaults.IconOnlyCompactChipWidth]
+ * default height of [ChipDefaults.CompactChipHeight] and the default width of
+ * [ChipDefaults.IconOnlyCompactChipWidth]
*
* If neither icon nor label is provided then the chip will displayed like an icon only chip but
* with no contents and [ChipColors.background()] color.
@@ -582,49 +581,50 @@
* including gradients, these are provided by [ChipColors] implementations.
*
* The recommended set of [ChipColors] styles can be obtained from [ChipDefaults], e.g.
- * [ChipDefaults.primaryChipColors] to get a color scheme for a primary [Chip] which by default
- * will have a solid background of [Colors.primary] and content color of
- * [Colors.onPrimary].
+ * [ChipDefaults.primaryChipColors] to get a color scheme for a primary [Chip] which by default will
+ * have a solid background of [Colors.primary] and content color of [Colors.onPrimary].
*
* Chips can be enabled or disabled. A disabled chip will not respond to click events.
*
* Example of a [CompactChip] with icon and single line of label text:
+ *
* @sample androidx.wear.compose.material.samples.CompactChipWithIconAndLabel
*
* Example of a [CompactChip] with a label, note that the text is center aligned:
+ *
* @sample androidx.wear.compose.material.samples.CompactChipWithLabel
*
* Example of a [CompactChip] with an icon only, note that the recommended icon size is 24x24 when
* only an icon is displayed:
+ *
* @sample androidx.wear.compose.material.samples.CompactChipWithIcon
*
* For more information, see the
- * [Chips](https://developer.android.com/training/wearables/components/chips)
- * guide.
+ * [Chips](https://developer.android.com/training/wearables/components/chips) guide.
*
* @param onClick Will be called when the user clicks the chip
* @param modifier Modifier to be applied to the chip
* @param label A slot for providing the chip's main label. The contents are expected to be text
- * which is "start" aligned if there is an icon preset and "center" aligned if not.
+ * which is "start" aligned if there is an icon preset and "center" aligned if not.
* @param icon A slot for providing the chip's icon. The contents are expected to be a horizontally
- * and vertically aligned icon of size [ChipDefaults.SmallIconSize] when used with a label or
- * [ChipDefaults.IconSize] when used as the only content in the CompactChip. In order to correctly
- * render when the Chip is not enabled the icon must set its alpha value to [LocalContentAlpha].
- * @param colors [ChipColors] that will be used to resolve the background and content color for
- * this chip in different states. See [ChipDefaults.chipColors]. Defaults to
- * [ChipDefaults.primaryChipColors]
- * @param enabled Controls the enabled state of the chip. When `false`, this chip will not
- * be clickable
+ * and vertically aligned icon of size [ChipDefaults.SmallIconSize] when used with a label or
+ * [ChipDefaults.IconSize] when used as the only content in the CompactChip. In order to correctly
+ * render when the Chip is not enabled the icon must set its alpha value to [LocalContentAlpha].
+ * @param colors [ChipColors] that will be used to resolve the background and content color for this
+ * chip in different states. See [ChipDefaults.chipColors]. Defaults to
+ * [ChipDefaults.primaryChipColors]
+ * @param enabled Controls the enabled state of the chip. When `false`, this chip will not be
+ * clickable
* @param interactionSource an optional hoisted [MutableInteractionSource] for observing and
- * emitting [Interaction]s for this chip. You can use this to change the chip's appearance
- * or preview the chip in different states. Note that if `null` is provided, interactions will
- * still happen internally.
+ * emitting [Interaction]s for this chip. You can use this to change the chip's appearance or
+ * preview the chip in different states. Note that if `null` is provided, interactions will still
+ * happen internally.
* @param contentPadding The spacing values to apply internally between the container and the
- * content
+ * content
* @param shape Defines the chip's shape. It is strongly recommended to use the default as this
- * shape is a key characteristic of the Wear Material Theme
+ * shape is a key characteristic of the Wear Material Theme
* @param border [ChipBorder] that will be used to resolve the border for this chip in different
- * states. See [ChipDefaults.chipBorder].
+ * states. See [ChipDefaults.chipBorder].
*/
@Composable
public fun CompactChip(
@@ -641,9 +641,8 @@
) {
if (label != null) {
ChipImpl(
- modifier = modifier
- .compactChipModifier()
- .padding(ChipDefaults.CompactChipTapTargetPadding),
+ modifier =
+ modifier.compactChipModifier().padding(ChipDefaults.CompactChipTapTargetPadding),
label = label,
labelTypography = MaterialTheme.typography.caption1,
onClick = onClick,
@@ -661,10 +660,11 @@
// Icon only compact chips have their own layout with a specific width and center aligned
// content. We use the base simple single slot Chip under the covers.
ChipImpl(
- modifier = modifier
- .compactChipModifier()
- .width(ChipDefaults.IconOnlyCompactChipWidth)
- .padding(ChipDefaults.CompactChipTapTargetPadding),
+ modifier =
+ modifier
+ .compactChipModifier()
+ .width(ChipDefaults.IconOnlyCompactChipWidth)
+ .padding(ChipDefaults.CompactChipTapTargetPadding),
onClick = onClick,
colors = colors,
border = border,
@@ -674,11 +674,7 @@
interactionSource = interactionSource,
) {
// Use a box to fill and center align the icon into the single slot of the Chip
- Box(
- modifier = Modifier
- .fillMaxSize()
- .wrapContentSize(align = Alignment.Center)
- ) {
+ Box(modifier = Modifier.fillMaxSize().wrapContentSize(align = Alignment.Center)) {
if (icon != null) {
icon()
}
@@ -694,21 +690,19 @@
*
* The [CompactChip] is Stadium shaped and has a max height designed to take no more than one line
* of text of [Typography.caption1] style and/or one icon. The default max height is
- * [ChipDefaults.CompactChipHeight]. This includes a visible chip height of 32.dp and
- * 8.dp of padding above and below the chip in order to meet accessibility guidelines that
- * request a minimum of 48.dp height and width of tappable area.
+ * [ChipDefaults.CompactChipHeight]. This includes a visible chip height of 32.dp and 8.dp of
+ * padding above and below the chip in order to meet accessibility guidelines that request a minimum
+ * of 48.dp height and width of tappable area.
*
* If a icon is provided then the labels should be "start" aligned, e.g. left aligned in ltr so that
* the text starts next to the icon.
*
* The items are laid out as follows.
- *
* 1. If a label is provided then the chip will be laid out with the optional icon at the start of a
- * row followed by the label with a default max height of [ChipDefaults.CompactChipHeight].
- *
+ * row followed by the label with a default max height of [ChipDefaults.CompactChipHeight].
* 2. If only an icon is provided it will be laid out vertically and horizontally centered with a
- * default height of [ChipDefaults.CompactChipHeight] and the default width of
- * [ChipDefaults.IconOnlyCompactChipWidth]
+ * default height of [ChipDefaults.CompactChipHeight] and the default width of
+ * [ChipDefaults.IconOnlyCompactChipWidth]
*
* If neither icon nor label is provided then the chip will displayed like an icon only chip but
* with no contents and [ChipColors.background()] color.
@@ -720,35 +714,35 @@
* Chips can be enabled or disabled. A disabled chip will not respond to click events.
*
* Example of a [OutlinedCompactChip] with icon and single line of label text:
+ *
* @sample androidx.wear.compose.material.samples.OutlinedCompactChipWithIconAndLabel
*
* For more information, see the
- * [Chips](https://developer.android.com/training/wearables/components/chips)
- * guide.
+ * [Chips](https://developer.android.com/training/wearables/components/chips) guide.
*
* @param onClick Will be called when the user clicks the chip
* @param modifier Modifier to be applied to the chip
* @param label A slot for providing the chip's main label. The contents are expected to be text
- * which is "start" aligned if there is an icon preset and "center" aligned if not.
+ * which is "start" aligned if there is an icon preset and "center" aligned if not.
* @param icon A slot for providing the chip's icon. The contents are expected to be a horizontally
- * and vertically aligned icon of size [ChipDefaults.SmallIconSize] when used with a label or
- * [ChipDefaults.IconSize] when used as the only content in the CompactChip. In order to correctly
- * render when the Chip is not enabled the icon must set its alpha value to [LocalContentAlpha].
- * @param colors [ChipColors] that will be used to resolve the background and content color for
- * this chip in different states. See [ChipDefaults.outlinedChipColors]. Defaults to
- * [ChipDefaults.primaryChipColors]
- * @param enabled Controls the enabled state of the chip. When `false`, this chip will not
- * be clickable
+ * and vertically aligned icon of size [ChipDefaults.SmallIconSize] when used with a label or
+ * [ChipDefaults.IconSize] when used as the only content in the CompactChip. In order to correctly
+ * render when the Chip is not enabled the icon must set its alpha value to [LocalContentAlpha].
+ * @param colors [ChipColors] that will be used to resolve the background and content color for this
+ * chip in different states. See [ChipDefaults.outlinedChipColors]. Defaults to
+ * [ChipDefaults.primaryChipColors]
+ * @param enabled Controls the enabled state of the chip. When `false`, this chip will not be
+ * clickable
* @param interactionSource an optional hoisted [MutableInteractionSource] for observing and
- * emitting [Interaction]s for this chip. You can use this to change the chip's appearance
- * or preview the chip in different states. Note that if `null` is provided, interactions will
- * still happen internally.
+ * emitting [Interaction]s for this chip. You can use this to change the chip's appearance or
+ * preview the chip in different states. Note that if `null` is provided, interactions will still
+ * happen internally.
* @param contentPadding The spacing values to apply internally between the container and the
- * content
+ * content
* @param shape Defines the chip's shape. It is strongly recommended to use the default as this
- * shape is a key characteristic of the Wear Material Theme
+ * shape is a key characteristic of the Wear Material Theme
* @param border [ChipBorder] that will be used to resolve the border for this chip in different
- * states. See [ChipDefaults.outlinedChipBorder].
+ * states. See [ChipDefaults.outlinedChipBorder].
*/
@Composable
public fun OutlinedCompactChip(
@@ -779,48 +773,42 @@
/**
* Represents the background and content colors used in a chip in different states.
*
- * See [ChipDefaults.primaryChipColors] for the default colors used in a primary styled [Chip].
- * See [ChipDefaults.secondaryChipColors] for the default colors used in a secondary styled [Chip].
+ * See [ChipDefaults.primaryChipColors] for the default colors used in a primary styled [Chip]. See
+ * [ChipDefaults.secondaryChipColors] for the default colors used in a secondary styled [Chip].
*/
@Stable
public interface ChipColors {
/**
- * Represents the background treatment for this chip, depending on [enabled]. Backgrounds can
- * be solid, transparent or have a gradient applied.
+ * Represents the background treatment for this chip, depending on [enabled]. Backgrounds can be
+ * solid, transparent or have a gradient applied.
*
* @param enabled Whether the chip is enabled
*/
- @Composable
- public fun background(enabled: Boolean): State<Painter>
+ @Composable public fun background(enabled: Boolean): State<Painter>
/**
* Represents the content color for this chip, depending on [enabled].
*
* @param enabled Whether the chip is enabled
*/
- @Composable
- public fun contentColor(enabled: Boolean): State<Color>
+ @Composable public fun contentColor(enabled: Boolean): State<Color>
/**
* Represents the secondary content color for this chip, depending on [enabled].
*
* @param enabled Whether the chip is enabled
*/
- @Composable
- public fun secondaryContentColor(enabled: Boolean): State<Color>
+ @Composable public fun secondaryContentColor(enabled: Boolean): State<Color>
/**
* Represents the icon color for this chip, depending on [enabled].
*
* @param enabled Whether the chip is enabled
*/
- @Composable
- public fun iconColor(enabled: Boolean): State<Color>
+ @Composable public fun iconColor(enabled: Boolean): State<Color>
}
-/**
- * Represents the border stroke used in a [Chip] in different states.
- */
+/** Represents the border stroke used in a [Chip] in different states. */
@Stable
public interface ChipBorder {
@Composable
@@ -832,9 +820,7 @@
public fun borderStroke(enabled: Boolean): State<BorderStroke?>
}
-/**
- * Contains the default values used by [Chip]
- */
+/** Contains the default values used by [Chip] */
public object ChipDefaults {
/**
@@ -845,7 +831,7 @@
* @param backgroundColor The background color of this [Chip] when enabled
* @param contentColor The content color of this [Chip] when enabled
* @param secondaryContentColor The secondary content color of this [Chip] when enabled, used
- * for secondaryLabel content
+ * for secondaryLabel content
* @param iconColor The icon color of this [Chip] when enabled, used for icon content
*/
@Composable
@@ -880,22 +866,26 @@
* value applied.
*
* @param startBackgroundColor The background color used at the start of the gradient of this
- * [Chip] when enabled
+ * [Chip] when enabled
* @param endBackgroundColor The background color used at the end of the gradient of this [Chip]
- * when enabled
+ * when enabled
* @param contentColor The content color of this [Chip] when enabled
* @param secondaryContentColor The secondary content color of this [Chip] when enabled, used
- * for secondaryLabel content
+ * for secondaryLabel content
* @param iconColor The icon color of this [Chip] when enabled, used for icon content
* @param gradientDirection Whether the chips gradient should be start to end (indicated by
- * [LayoutDirection.Ltr]) or end to start (indicated by [LayoutDirection.Rtl]).
+ * [LayoutDirection.Ltr]) or end to start (indicated by [LayoutDirection.Rtl]).
*/
@Composable
public fun gradientBackgroundChipColors(
- startBackgroundColor: Color = MaterialTheme.colors.primary.copy(alpha = 0.5f)
- .compositeOver(MaterialTheme.colors.surface),
- endBackgroundColor: Color = MaterialTheme.colors.surface.copy(alpha = 0f)
- .compositeOver(MaterialTheme.colors.surface),
+ startBackgroundColor: Color =
+ MaterialTheme.colors.primary
+ .copy(alpha = 0.5f)
+ .compositeOver(MaterialTheme.colors.surface),
+ endBackgroundColor: Color =
+ MaterialTheme.colors.surface
+ .copy(alpha = 0f)
+ .compositeOver(MaterialTheme.colors.surface),
contentColor: Color = contentColorFor(endBackgroundColor),
secondaryContentColor: Color = contentColor,
iconColor: Color = contentColor,
@@ -904,36 +894,30 @@
val backgroundColors: List<Color>
val disabledBackgroundColors: List<Color>
if (gradientDirection == LayoutDirection.Ltr) {
- backgroundColors = listOf(
- startBackgroundColor,
- endBackgroundColor
- )
- disabledBackgroundColors = listOf(
- startBackgroundColor.copy(alpha = ContentAlpha.disabled),
- endBackgroundColor.copy(alpha = ContentAlpha.disabled)
- )
+ backgroundColors = listOf(startBackgroundColor, endBackgroundColor)
+ disabledBackgroundColors =
+ listOf(
+ startBackgroundColor.copy(alpha = ContentAlpha.disabled),
+ endBackgroundColor.copy(alpha = ContentAlpha.disabled)
+ )
} else {
- backgroundColors = listOf(
- endBackgroundColor,
- startBackgroundColor
- )
- disabledBackgroundColors = listOf(
- endBackgroundColor.copy(alpha = ContentAlpha.disabled),
- startBackgroundColor.copy(alpha = ContentAlpha.disabled),
- )
+ backgroundColors = listOf(endBackgroundColor, startBackgroundColor)
+ disabledBackgroundColors =
+ listOf(
+ endBackgroundColor.copy(alpha = ContentAlpha.disabled),
+ startBackgroundColor.copy(alpha = ContentAlpha.disabled),
+ )
}
return DefaultChipColors(
backgroundPainter = BrushPainter(Brush.linearGradient(backgroundColors)),
contentColor = contentColor,
secondaryContentColor = secondaryContentColor,
iconColor = iconColor,
- disabledBackgroundPainter = BrushPainter(
- Brush.linearGradient(disabledBackgroundColors)
- ),
+ disabledBackgroundPainter =
+ BrushPainter(Brush.linearGradient(disabledBackgroundColors)),
disabledContentColor = contentColor.copy(alpha = ContentAlpha.disabled),
- disabledSecondaryContentColor = secondaryContentColor.copy(
- alpha = ContentAlpha.disabled
- ),
+ disabledSecondaryContentColor =
+ secondaryContentColor.copy(alpha = ContentAlpha.disabled),
disabledIconColor = iconColor.copy(alpha = ContentAlpha.disabled),
)
}
@@ -947,7 +931,7 @@
* @param backgroundColor The background color of this [Chip] when enabled
* @param contentColor The content color of this [Chip] when enabled
* @param secondaryContentColor The secondary content color of this [Chip] when enabled, used
- * for secondaryLabel content
+ * for secondaryLabel content
* @param iconColor The icon color of this [Chip] when enabled, used for icon content
*/
@Composable
@@ -975,7 +959,7 @@
*
* @param contentColor The content color of this [Chip] when enabled
* @param secondaryContentColor The secondary content color of this [Chip] when enabled, used
- * for secondaryLabel content
+ * for secondaryLabel content
* @param iconColor The icon color of this [Chip] when enabled, used for icon content
*/
@Composable
@@ -1000,21 +984,23 @@
*
* @param backgroundImagePainter The [Painter] to use to draw the background of the [Chip]
* @param backgroundImageScrimBrush The [Brush] to use to paint a scrim over the background
- * image to ensure that any text drawn over the image is legible
+ * image to ensure that any text drawn over the image is legible
* @param contentColor The content color of this [Chip] when enabled
* @param secondaryContentColor The secondary content color of this [Chip] when enabled, used
- * for secondaryLabel content
+ * for secondaryLabel content
* @param iconColor The icon color of this [Chip] when enabled, used for icon content
*/
@Composable
public fun imageBackgroundChipColors(
backgroundImagePainter: Painter,
- backgroundImageScrimBrush: Brush = Brush.linearGradient(
- colors = listOf(
- MaterialTheme.colors.surface.copy(alpha = 1.0f),
- MaterialTheme.colors.surface.copy(alpha = 0f)
- )
- ),
+ backgroundImageScrimBrush: Brush =
+ Brush.linearGradient(
+ colors =
+ listOf(
+ MaterialTheme.colors.surface.copy(alpha = 1.0f),
+ MaterialTheme.colors.surface.copy(alpha = 0f)
+ )
+ ),
contentColor: Color = MaterialTheme.colors.onBackground,
secondaryContentColor: Color = contentColor,
iconColor: Color = contentColor,
@@ -1043,9 +1029,8 @@
iconColor = iconColor,
disabledBackgroundPainter = disabledBackgroundPainter,
disabledContentColor = contentColor.copy(alpha = ContentAlpha.disabled),
- disabledSecondaryContentColor = secondaryContentColor.copy(
- alpha = ContentAlpha.disabled
- ),
+ disabledSecondaryContentColor =
+ secondaryContentColor.copy(alpha = ContentAlpha.disabled),
disabledIconColor = iconColor.copy(alpha = ContentAlpha.disabled),
)
}
@@ -1059,7 +1044,7 @@
*
* @param contentColor The content color of this [Chip] when enabled
* @param secondaryContentColor The secondary content color of this [Chip] when enabled, used
- * for secondaryLabel content
+ * for secondaryLabel content
* @param iconColor The icon color of this [Chip] when enabled, used for icon content
*/
@Composable
@@ -1099,7 +1084,7 @@
*
* @param borderColor The color to use for the border for this [OutlinedChip] when enabled
* @param disabledBorderColor The color to use for the border for this [OutlinedChip] when
- * disabled
+ * disabled
* @param borderWidth The width to use for the border for this [OutlinedChip]
*/
@Composable
@@ -1117,32 +1102,30 @@
public val ChipHorizontalPadding = 14.dp
public val ChipVerticalPadding = 6.dp
- /**
- * The default content padding used by [Chip]
- */
- public val ContentPadding: PaddingValues = PaddingValues(
- start = ChipHorizontalPadding,
- top = ChipVerticalPadding,
- end = ChipHorizontalPadding,
- bottom = ChipVerticalPadding
- )
+ /** The default content padding used by [Chip] */
+ public val ContentPadding: PaddingValues =
+ PaddingValues(
+ start = ChipHorizontalPadding,
+ top = ChipVerticalPadding,
+ end = ChipHorizontalPadding,
+ bottom = ChipVerticalPadding
+ )
public val CompactChipHorizontalPadding = 12.dp
public val CompactChipVerticalPadding = 0.dp
- /**
- * The default content padding used by [CompactChip]
- */
- public val CompactChipContentPadding: PaddingValues = PaddingValues(
- start = CompactChipHorizontalPadding,
- top = CompactChipVerticalPadding,
- end = CompactChipHorizontalPadding,
- bottom = CompactChipVerticalPadding
- )
+ /** The default content padding used by [CompactChip] */
+ public val CompactChipContentPadding: PaddingValues =
+ PaddingValues(
+ start = CompactChipHorizontalPadding,
+ top = CompactChipVerticalPadding,
+ end = CompactChipHorizontalPadding,
+ bottom = CompactChipVerticalPadding
+ )
/**
- * The default height applied for the [Chip].
- * Note that you can override it by applying Modifier.heightIn directly on [Chip].
+ * The default height applied for the [Chip]. Note that you can override it by applying
+ * Modifier.heightIn directly on [Chip].
*/
public val Height = 52.dp
@@ -1160,30 +1143,21 @@
* The default padding to be provided around a [CompactChip] in order to ensure that its
* tappable area meets minimum UX guidance.
*/
- public val CompactChipTapTargetPadding: PaddingValues = PaddingValues(
- top = 8.dp,
- bottom = 8.dp
- )
+ public val CompactChipTapTargetPadding: PaddingValues = PaddingValues(top = 8.dp, bottom = 8.dp)
/**
- * The default width applied for the [CompactChip] when it has no label provided.
- * Note that you can override it by applying Modifier.width directly on [CompactChip].
+ * The default width applied for the [CompactChip] when it has no label provided. Note that you
+ * can override it by applying Modifier.width directly on [CompactChip].
*/
internal val IconOnlyCompactChipWidth = 52.dp
- /**
- * The default size of the icon when used inside a [Chip].
- */
+ /** The default size of the icon when used inside a [Chip]. */
public val IconSize: Dp = 24.dp
- /**
- * The size of the icon when used inside a Large "Avatar" [Chip].
- */
+ /** The size of the icon when used inside a Large "Avatar" [Chip]. */
public val LargeIconSize: Dp = 32.dp
- /**
- * The size of the icon when used inside a "Compact" [Chip].
- */
+ /** The size of the icon when used inside a "Compact" [Chip]. */
public val SmallIconSize: Dp = 20.dp
/**
@@ -1193,8 +1167,8 @@
internal val IconSpacing = 6.dp
/**
- * Creates a [ChipColors] that represents the default background and content colors used in
- * a [Chip].
+ * Creates a [ChipColors] that represents the default background and content colors used in a
+ * [Chip].
*
* @param backgroundColor The background color of this [Chip] when enabled
* @param contentColor The content color of this [Chip] when enabled
@@ -1216,16 +1190,17 @@
disabledSecondaryContentColor: Color =
secondaryContentColor.copy(alpha = ContentAlpha.disabled),
disabledIconColor: Color = iconColor.copy(alpha = ContentAlpha.disabled),
- ): ChipColors = DefaultChipColors(
- backgroundColor = backgroundColor,
- contentColor = contentColor,
- secondaryContentColor = secondaryContentColor,
- iconColor = iconColor,
- disabledBackgroundColor = disabledBackgroundColor,
- disabledContentColor = disabledContentColor,
- disabledSecondaryContentColor = disabledSecondaryContentColor,
- disabledIconColor = disabledIconColor
- )
+ ): ChipColors =
+ DefaultChipColors(
+ backgroundColor = backgroundColor,
+ contentColor = contentColor,
+ secondaryContentColor = secondaryContentColor,
+ iconColor = iconColor,
+ disabledBackgroundColor = disabledBackgroundColor,
+ disabledContentColor = disabledContentColor,
+ disabledSecondaryContentColor = disabledSecondaryContentColor,
+ disabledIconColor = disabledIconColor
+ )
/**
* Creates a [ChipColors] where all of the values are explicitly defined.
@@ -1249,21 +1224,20 @@
disabledContentColor: Color,
disabledSecondaryContentColor: Color,
disabledIconColor: Color,
- ): ChipColors = DefaultChipColors(
- backgroundPainter = backgroundPainter,
- contentColor = contentColor,
- secondaryContentColor = secondaryContentColor,
- iconColor = iconColor,
- disabledBackgroundPainter = disabledBackgroundPainter,
- disabledContentColor = disabledContentColor,
- disabledSecondaryContentColor = disabledSecondaryContentColor,
- disabledIconColor = disabledIconColor
- )
+ ): ChipColors =
+ DefaultChipColors(
+ backgroundPainter = backgroundPainter,
+ contentColor = contentColor,
+ secondaryContentColor = secondaryContentColor,
+ iconColor = iconColor,
+ disabledBackgroundPainter = disabledBackgroundPainter,
+ disabledContentColor = disabledContentColor,
+ disabledSecondaryContentColor = disabledSecondaryContentColor,
+ disabledIconColor = disabledIconColor
+ )
}
-/**
- * Default [ChipColors] implementation.
- */
+/** Default [ChipColors] implementation. */
@Immutable
internal class DefaultChipColors(
private val backgroundPainter: Painter,
@@ -1298,16 +1272,12 @@
@Composable
override fun background(enabled: Boolean): State<Painter> {
- return rememberUpdatedState(
- if (enabled) backgroundPainter else disabledBackgroundPainter
- )
+ return rememberUpdatedState(if (enabled) backgroundPainter else disabledBackgroundPainter)
}
@Composable
override fun contentColor(enabled: Boolean): State<Color> {
- return rememberUpdatedState(
- if (enabled) contentColor else disabledContentColor
- )
+ return rememberUpdatedState(if (enabled) contentColor else disabledContentColor)
}
@Composable
@@ -1354,9 +1324,7 @@
}
}
-/**
- * Default [ChipBorder] implementation.
- */
+/** Default [ChipBorder] implementation. */
@Immutable
private class DefaultChipBorder(
private val borderStroke: BorderStroke? = null,
@@ -1389,12 +1357,9 @@
@Composable
private fun Modifier.chipSizeModifier() =
- this.defaultMinSize(minHeight = ChipDefaults.Height)
- .height(IntrinsicSize.Min)
+ this.defaultMinSize(minHeight = ChipDefaults.Height).height(IntrinsicSize.Min)
-@Composable
-private fun Modifier.compactChipModifier() =
- this.height(ChipDefaults.CompactChipHeight)
+@Composable private fun Modifier.compactChipModifier() = this.height(ChipDefaults.CompactChipHeight)
@Composable
private fun ChipImpl(
@@ -1410,31 +1375,29 @@
content: @Composable RowScope.() -> Unit,
) {
val borderStroke = border?.borderStroke(enabled)?.value
- val borderModifier = if (borderStroke != null) modifier.border(
- border = borderStroke,
- shape = shape
- ) else modifier
+ val borderModifier =
+ if (borderStroke != null) modifier.border(border = borderStroke, shape = shape)
+ else modifier
Row(
- modifier = borderModifier
- .clip(shape = shape)
- .width(intrinsicSize = IntrinsicSize.Max)
- .paint(
- painter = colors.background(enabled).value,
- contentScale = ContentScale.Crop
+ modifier =
+ borderModifier
+ .clip(shape = shape)
+ .width(intrinsicSize = IntrinsicSize.Max)
+ .paint(painter = colors.background(enabled).value, contentScale = ContentScale.Crop)
+ .clickable(
+ enabled = enabled,
+ onClick = onClick,
+ role = role,
+ indication = rippleOrFallbackImplementation(),
+ interactionSource = interactionSource,
+ )
+ .padding(contentPadding),
+ content =
+ provideScopeContent(
+ colors.contentColor(enabled = enabled),
+ MaterialTheme.typography.button,
+ content
)
- .clickable(
- enabled = enabled,
- onClick = onClick,
- role = role,
- indication = rippleOrFallbackImplementation(),
- interactionSource = interactionSource,
- )
- .padding(contentPadding),
- content = provideScopeContent(
- colors.contentColor(enabled = enabled),
- MaterialTheme.typography.button,
- content
- )
)
}
@@ -1479,19 +1442,17 @@
}
Column {
Row(
- content = provideScopeContent(
- colors.contentColor(enabled),
- labelTypography,
- label
- )
+ content =
+ provideScopeContent(colors.contentColor(enabled), labelTypography, label)
)
secondaryLabel?.let {
Row(
- content = provideScopeContent(
- colors.secondaryContentColor(enabled),
- MaterialTheme.typography.caption2,
- secondaryLabel
- )
+ content =
+ provideScopeContent(
+ colors.secondaryContentColor(enabled),
+ MaterialTheme.typography.caption2,
+ secondaryLabel
+ )
)
}
}
diff --git a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/Colors.kt b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/Colors.kt
index 7db6c7c..2c3301c 100644
--- a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/Colors.kt
+++ b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/Colors.kt
@@ -41,9 +41,7 @@
val onError: Color = Color(0xFF000000)
) {
- /**
- * Returns a copy of this Colors, optionally overriding some of the values.
- */
+ /** Returns a copy of this Colors, optionally overriding some of the values. */
public fun copy(
primary: Color = this.primary,
primaryVariant: Color = this.primaryVariant,
@@ -58,21 +56,22 @@
onSurface: Color = this.onSurface,
onSurfaceVariant: Color = this.onSurfaceVariant,
onError: Color = this.onError
- ): Colors = Colors(
- primary = primary,
- primaryVariant = primaryVariant,
- secondary = secondary,
- secondaryVariant = secondaryVariant,
- background = background,
- surface = surface,
- error = error,
- onPrimary = onPrimary,
- onSecondary = onSecondary,
- onBackground = onBackground,
- onSurface = onSurface,
- onSurfaceVariant = onSurfaceVariant,
- onError = onError
- )
+ ): Colors =
+ Colors(
+ primary = primary,
+ primaryVariant = primaryVariant,
+ secondary = secondary,
+ secondaryVariant = secondaryVariant,
+ background = background,
+ surface = surface,
+ error = error,
+ onPrimary = onPrimary,
+ onSecondary = onSecondary,
+ onBackground = onBackground,
+ onSurface = onSurface,
+ onSurfaceVariant = onSurfaceVariant,
+ onError = onError
+ )
override fun toString(): String {
return "Colors(" +
@@ -94,8 +93,8 @@
}
/**
- * The Material color system contains pairs of colors that are typically used for the background
- * and content color inside a component. For example, a [Button] typically uses `primary` for its
+ * The Material color system contains pairs of colors that are typically used for the background and
+ * content color inside a component. For example, a [Button] typically uses `primary` for its
* background, and `onPrimary` for the color of its content (usually text or iconography).
*
* This function tries to match the provided [backgroundColor] to a 'background' color in this
@@ -106,8 +105,7 @@
* [Color.Unspecified].
*
* @return the matching content color for [backgroundColor]. If [backgroundColor] is not present in
- * the theme's [Colors], then returns [Color.Unspecified].
- *
+ * the theme's [Colors], then returns [Color.Unspecified].
* @see contentColorFor
*/
public fun Colors.contentColorFor(backgroundColor: Color): Color {
@@ -124,20 +122,19 @@
}
/**
- * The Material color system contains pairs of colors that are typically used for the background
- * and content color inside a component. For example, a [Button] typically uses `primary` for its
+ * The Material color system contains pairs of colors that are typically used for the background and
+ * content color inside a component. For example, a [Button] typically uses `primary` for its
* background, and `onPrimary` for the color of its content (usually text or iconography).
*
* This function tries to match the provided [backgroundColor] to a 'background' color in this
* [Colors], and then will return the corresponding color used for content. For example, when
* [backgroundColor] is [Colors.primary], this will return [Colors.onPrimary].
*
- * If [backgroundColor] does not match a background color in the theme, this will return
- * the current value of [LocalContentColor] as a best-effort color.
+ * If [backgroundColor] does not match a background color in the theme, this will return the current
+ * value of [LocalContentColor] as a best-effort color.
*
* @return the matching content color for [backgroundColor]. If [backgroundColor] is not present in
- * the theme's [Colors], then returns the current value of [LocalContentColor].
- *
+ * the theme's [Colors], then returns the current value of [LocalContentColor].
* @see Colors.contentColorFor
*/
@Composable
@@ -147,6 +144,7 @@
/**
* Convert given color to disabled color.
+ *
* @param disabledContentAlpha Alpha used to represent disabled content colors.
*/
@Composable
diff --git a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/ContentAlpha.kt b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/ContentAlpha.kt
index 2f6e8b5..205332f 100644
--- a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/ContentAlpha.kt
+++ b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/ContentAlpha.kt
@@ -33,21 +33,23 @@
*/
public val high: Float
@Composable
- get() = contentAlpha(
- highContrastAlpha = HighContrastContentAlpha.high,
- lowContrastAlpha = LowContrastContentAlpha.high
- )
+ get() =
+ contentAlpha(
+ highContrastAlpha = HighContrastContentAlpha.high,
+ lowContrastAlpha = LowContrastContentAlpha.high
+ )
/**
- * A medium level of content alpha, used to represent medium emphasis text such as
- * placeholder text in a [TextField].
+ * A medium level of content alpha, used to represent medium emphasis text such as placeholder
+ * text in a [TextField].
*/
public val medium: Float
@Composable
- get() = contentAlpha(
- highContrastAlpha = HighContrastContentAlpha.medium,
- lowContrastAlpha = LowContrastContentAlpha.medium
- )
+ get() =
+ contentAlpha(
+ highContrastAlpha = HighContrastContentAlpha.medium,
+ lowContrastAlpha = LowContrastContentAlpha.medium
+ )
/**
* A low level of content alpha used to represent disabled components, such as text in a
@@ -55,25 +57,24 @@
*/
public val disabled: Float
@Composable
- get() = contentAlpha(
- highContrastAlpha = HighContrastContentAlpha.disabled,
- lowContrastAlpha = LowContrastContentAlpha.disabled
- )
+ get() =
+ contentAlpha(
+ highContrastAlpha = HighContrastContentAlpha.disabled,
+ lowContrastAlpha = LowContrastContentAlpha.disabled
+ )
/**
* This default implementation uses separate alpha levels depending on the luminance of the
* incoming color, and whether the theme is light or dark. This is to ensure correct contrast
* and accessibility on all surfaces.
*
- * See [HighContrastContentAlpha] and [LowContrastContentAlpha] for what the levels are
- * used for, and under what circumstances.
+ * See [HighContrastContentAlpha] and [LowContrastContentAlpha] for what the levels are used
+ * for, and under what circumstances.
*/
@Composable
private fun contentAlpha(
- @FloatRange(from = 0.0, to = 1.0)
- highContrastAlpha: Float,
- @FloatRange(from = 0.0, to = 1.0)
- lowContrastAlpha: Float
+ @FloatRange(from = 0.0, to = 1.0) highContrastAlpha: Float,
+ @FloatRange(from = 0.0, to = 1.0) lowContrastAlpha: Float
): Float {
val contentColor = LocalContentColor.current
return if (contentColor.luminance() < 0.5) highContrastAlpha else lowContrastAlpha
@@ -91,18 +92,17 @@
*
* [MaterialTheme] sets this to [ContentAlpha.high] by default, as this is the default alpha for
* body text.
- *
*/
public val LocalContentAlpha: ProvidableCompositionLocal<Float> = compositionLocalOf { 1f }
/**
* Alpha levels for high luminance content in light theme, or low luminance content in dark theme.
*
- * This content will typically be placed on colored surfaces, so it is important that the
- * contrast here is higher to meet accessibility standards, and increase legibility.
+ * This content will typically be placed on colored surfaces, so it is important that the contrast
+ * here is higher to meet accessibility standards, and increase legibility.
*
- * These levels are typically used for text / iconography in primary colored tabs /
- * bottom navigation / etc.
+ * These levels are typically used for text / iconography in primary colored tabs / bottom
+ * navigation / etc.
*/
private object HighContrastContentAlpha {
const val high: Float = 1.00f
@@ -116,8 +116,8 @@
* This content will typically be placed on grayscale surfaces, so the contrast here can be lower
* without sacrificing accessibility and legibility.
*
- * These levels are typically used for body text on the main surface (white in light theme, grey
- * in dark theme) and text / iconography in surface colored tabs / bottom navigation / etc.
+ * These levels are typically used for body text on the main surface (white in light theme, grey in
+ * dark theme) and text / iconography in surface colored tabs / bottom navigation / etc.
*/
private object LowContrastContentAlpha {
const val high: Float = 0.87f
diff --git a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/CurvedText.kt b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/CurvedText.kt
index d39ed2c..c5738cb 100644
--- a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/CurvedText.kt
+++ b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/CurvedText.kt
@@ -34,10 +34,9 @@
import androidx.wear.compose.foundation.curvedRow
/**
- * CurvedText is a component allowing developers to easily write curved text following
- * the curvature a circle (usually at the edge of a circular screen).
- * CurvedText can be only created within the CurvedLayout to ensure the best experience, like being
- * able to specify to positioning.
+ * CurvedText is a component allowing developers to easily write curved text following the curvature
+ * a circle (usually at the edge of a circular screen). CurvedText can be only created within the
+ * CurvedLayout to ensure the best experience, like being able to specify to positioning.
*
* The default [style] uses the [LocalTextStyle] provided by the [MaterialTheme] / components,
* converting it to a [CurvedTextStyle]. Note that not all parameters are used by [curvedText].
@@ -46,12 +45,12 @@
* and using [TextStyle.copy] to keep any theme defined attributes, only modifying the specific
* attributes you want to override, then convert to [CurvedTextStyle]
*
- * For ease of use, commonly used parameters from [CurvedTextStyle] are also present here. The
- * order of precedence is as follows:
- * - If a parameter is explicitly set here (i.e, it is _not_ `null` or [TextUnit.Unspecified]),
- * then this parameter will always be used.
+ * For ease of use, commonly used parameters from [CurvedTextStyle] are also present here. The order
+ * of precedence is as follows:
+ * - If a parameter is explicitly set here (i.e, it is _not_ `null` or [TextUnit.Unspecified]), then
+ * this parameter will always be used.
* - If a parameter is _not_ set, (`null` or [TextUnit.Unspecified]), then the corresponding value
- * from [style] will be used instead.
+ * from [style] will be used instead.
*
* Additionally, for [color], if [color] is not set, and [style] does not have a color, then
* [LocalContentColor] will be used with an alpha of [LocalContentAlpha]- this allows this
@@ -59,31 +58,31 @@
* still maintain contrast and accessibility.
*
* For samples explicitly specifying style see:
+ *
* @sample androidx.wear.compose.material.samples.CurvedTextDemo
*
* For examples using CompositionLocal to specify the style, see:
+ *
* @sample androidx.wear.compose.material.samples.CurvedTextProviderDemo
*
* For more information, see the
- * [Curved Text](https://developer.android.com/training/wearables/compose/curved-text)
- * guide.
+ * [Curved Text](https://developer.android.com/training/wearables/compose/curved-text) guide.
*
* @param text The text to display
* @param modifier The [CurvedModifier] to apply to this curved text.
* @param background The background color for the text.
* @param color [Color] to apply to the text. If [Color.Unspecified], and [style] has no color set,
- * this will be [LocalContentColor].
+ * this will be [LocalContentColor].
* @param fontSize The size of glyphs to use when painting the text. See [TextStyle.fontSize].
* @param fontFamily The font family to be used when rendering the text.
* @param fontWeight The thickness of the glyphs, in a range of [1, 1000]. see [FontWeight]
* @param fontStyle The typeface variant to use when drawing the letters (e.g. italic).
- * @param fontSynthesis Whether to synthesize font weight and/or style when the requested weight
- * or style cannot be found in the provided font family.
+ * @param fontSynthesis Whether to synthesize font weight and/or style when the requested weight or
+ * style cannot be found in the provided font family.
* @param style Specifies the style to use.
- * @param angularDirection Specify if the text is laid out clockwise or anti-clockwise, and if
- * those needs to be reversed in a Rtl layout.
- * If not specified, it will be inherited from the enclosing [curvedRow] or [CurvedLayout]
- * See [CurvedDirection.Angular].
+ * @param angularDirection Specify if the text is laid out clockwise or anti-clockwise, and if those
+ * needs to be reversed in a Rtl layout. If not specified, it will be inherited from the enclosing
+ * [curvedRow] or [CurvedLayout] See [CurvedDirection.Angular].
* @param overflow How visual overflow should be handled.
*/
public fun CurvedScope.curvedText(
@@ -99,31 +98,32 @@
style: CurvedTextStyle? = null,
angularDirection: CurvedDirection.Angular? = null,
overflow: TextOverflow = TextOverflow.Clip,
-) = basicCurvedText(text, modifier, angularDirection, overflow) {
- val baseStyle = style ?: CurvedTextStyle(LocalTextStyle.current)
- val textColor = color.takeOrElse {
- baseStyle.color.takeOrElse {
- LocalContentColor.current.copy(alpha = LocalContentAlpha.current)
- }
- }
- baseStyle.merge(
- CurvedTextStyle(
- color = textColor,
- fontSize = fontSize,
- fontFamily = fontFamily,
- fontWeight = fontWeight,
- fontStyle = fontStyle,
- fontSynthesis = fontSynthesis,
- background = background
+) =
+ basicCurvedText(text, modifier, angularDirection, overflow) {
+ val baseStyle = style ?: CurvedTextStyle(LocalTextStyle.current)
+ val textColor =
+ color.takeOrElse {
+ baseStyle.color.takeOrElse {
+ LocalContentColor.current.copy(alpha = LocalContentAlpha.current)
+ }
+ }
+ baseStyle.merge(
+ CurvedTextStyle(
+ color = textColor,
+ fontSize = fontSize,
+ fontFamily = fontFamily,
+ fontWeight = fontWeight,
+ fontStyle = fontStyle,
+ fontSynthesis = fontSynthesis,
+ background = background
+ )
)
- )
-}
+ }
/**
- * CurvedText is a component allowing developers to easily write curved text following
- * the curvature a circle (usually at the edge of a circular screen).
- * CurvedText can be only created within the CurvedLayout to ensure the best experience, like being
- * able to specify to positioning.
+ * CurvedText is a component allowing developers to easily write curved text following the curvature
+ * a circle (usually at the edge of a circular screen). CurvedText can be only created within the
+ * CurvedLayout to ensure the best experience, like being able to specify to positioning.
*
* The default [style] uses the [LocalTextStyle] provided by the [MaterialTheme] / components,
* converting it to a [CurvedTextStyle]. Note that not all parameters are used by [curvedText].
@@ -132,12 +132,12 @@
* and using [TextStyle.copy] to keep any theme defined attributes, only modifying the specific
* attributes you want to override, then convert to [CurvedTextStyle]
*
- * For ease of use, commonly used parameters from [CurvedTextStyle] are also present here. The
- * order of precedence is as follows:
- * - If a parameter is explicitly set here (i.e, it is _not_ `null` or [TextUnit.Unspecified]),
- * then this parameter will always be used.
+ * For ease of use, commonly used parameters from [CurvedTextStyle] are also present here. The order
+ * of precedence is as follows:
+ * - If a parameter is explicitly set here (i.e, it is _not_ `null` or [TextUnit.Unspecified]), then
+ * this parameter will always be used.
* - If a parameter is _not_ set, (`null` or [TextUnit.Unspecified]), then the corresponding value
- * from [style] will be used instead.
+ * from [style] will be used instead.
*
* Additionally, for [color], if [color] is not set, and [style] does not have a color, then
* [LocalContentColor] will be used with an alpha of [LocalContentAlpha]- this allows this
@@ -147,25 +147,25 @@
* @sample androidx.wear.compose.material.samples.CurvedTextDemo
*
* For more information, see the
- * [Curved Text](https://developer.android.com/training/wearables/compose/curved-text)
- * guide.
+ * [Curved Text](https://developer.android.com/training/wearables/compose/curved-text) guide.
*
* @param text The text to display
* @param modifier The [CurvedModifier] to apply to this curved text.
* @param background The background color for the text.
* @param color [Color] to apply to the text. If [Color.Unspecified], and [style] has no color set,
- * this will be [LocalContentColor].
+ * this will be [LocalContentColor].
* @param fontSize The size of glyphs to use when painting the text. See [TextStyle.fontSize].
* @param style Specifies the style to use.
- * @param angularDirection Specify if the text is laid out clockwise or anti-clockwise, and if
- * those needs to be reversed in a Rtl layout.
- * If not specified, it will be inherited from the enclosing [curvedRow] or [CurvedLayout]
- * See [CurvedDirection.Angular].
+ * @param angularDirection Specify if the text is laid out clockwise or anti-clockwise, and if those
+ * needs to be reversed in a Rtl layout. If not specified, it will be inherited from the enclosing
+ * [curvedRow] or [CurvedLayout] See [CurvedDirection.Angular].
* @param overflow How visual overflow should be handled.
*/
-@Deprecated("This overload is provided for backwards compatibility with Compose for " +
- "Wear OS 1.0. A newer overload is available with additional font parameters.",
- level = DeprecationLevel.HIDDEN)
+@Deprecated(
+ "This overload is provided for backwards compatibility with Compose for " +
+ "Wear OS 1.0. A newer overload is available with additional font parameters.",
+ level = DeprecationLevel.HIDDEN
+)
public fun CurvedScope.curvedText(
text: String,
modifier: CurvedModifier = CurvedModifier,
@@ -175,18 +175,16 @@
style: CurvedTextStyle? = null,
angularDirection: CurvedDirection.Angular? = null,
overflow: TextOverflow = TextOverflow.Clip,
-) = basicCurvedText(text, modifier, angularDirection, overflow) {
- val baseStyle = style ?: CurvedTextStyle(LocalTextStyle.current)
- val textColor = color.takeOrElse {
- baseStyle.color.takeOrElse {
- LocalContentColor.current.copy(alpha = LocalContentAlpha.current)
- }
- }
- baseStyle.merge(
- CurvedTextStyle(
- color = textColor,
- fontSize = fontSize,
- background = background
+) =
+ basicCurvedText(text, modifier, angularDirection, overflow) {
+ val baseStyle = style ?: CurvedTextStyle(LocalTextStyle.current)
+ val textColor =
+ color.takeOrElse {
+ baseStyle.color.takeOrElse {
+ LocalContentColor.current.copy(alpha = LocalContentAlpha.current)
+ }
+ }
+ baseStyle.merge(
+ CurvedTextStyle(color = textColor, fontSize = fontSize, background = background)
)
- )
-}
+ }
diff --git a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/HorizontalPageIndicator.kt b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/HorizontalPageIndicator.kt
index 53e808f..ed0dfcb 100644
--- a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/HorizontalPageIndicator.kt
+++ b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/HorizontalPageIndicator.kt
@@ -56,41 +56,38 @@
import kotlin.math.roundToInt
/**
- * A horizontal indicator for a Pager, representing
- * the currently active page and total pages drawn using a [Shape]. It shows up to 6 pages
- * on the screen and doesn't represent the exact page index if there are more than 6 pages.
- * Instead of showing the exact position, [HorizontalPageIndicator] shows a half-size indicator
- * on the left or on the right if there are more pages.
+ * A horizontal indicator for a Pager, representing the currently active page and total pages drawn
+ * using a [Shape]. It shows up to 6 pages on the screen and doesn't represent the exact page index
+ * if there are more than 6 pages. Instead of showing the exact position, [HorizontalPageIndicator]
+ * shows a half-size indicator on the left or on the right if there are more pages.
*
- * Here's how different positions 0..10 might be visually represented:
- * "X" is selected item, "O" and "o" full and half size items respectively.
+ * Here's how different positions 0..10 might be visually represented: "X" is selected item, "O" and
+ * "o" full and half size items respectively.
*
- * O X O O O o - 2nd position out of 10. There are no more items on the left but more on the right
- * o O O O X o - might be 6, 7 or 8 out of 10, as there are more possible items
- * on the left and on the right
- * o O O O X O - is 9 out of 10, as there're no more items on the right
+ * O X O O O o - 2nd position out of 10. There are no more items on the left but more on the right o
+ * O O O X o - might be 6, 7 or 8 out of 10, as there are more possible items on the left and on the
+ * right o O O O X O - is 9 out of 10, as there're no more items on the right
*
- * [HorizontalPageIndicator] may be linear or curved, depending on [indicatorStyle]. By default
- * it depends on the screen shape of the device - for circular screens it will be curved,
- * whilst for square screens it will be linear.
+ * [HorizontalPageIndicator] may be linear or curved, depending on [indicatorStyle]. By default it
+ * depends on the screen shape of the device - for circular screens it will be curved, whilst for
+ * square screens it will be linear.
*
- * This component also allows customising the [indicatorShape], which defines how the
- * indicator is visually represented.
+ * This component also allows customising the [indicatorShape], which defines how the indicator is
+ * visually represented.
*
* @sample androidx.wear.compose.material.samples.HorizontalPageIndicatorSample
*
- * @param pageIndicatorState The state object of a [HorizontalPageIndicator] to be used to
- * observe the Pager's state.
+ * @param pageIndicatorState The state object of a [HorizontalPageIndicator] to be used to observe
+ * the Pager's state.
* @param modifier Modifier to be applied to the [HorizontalPageIndicator]
- * @param indicatorStyle The style of [HorizontalPageIndicator] - may be linear or curved.
- * By default determined by the screen shape.
+ * @param indicatorStyle The style of [HorizontalPageIndicator] - may be linear or curved. By
+ * default determined by the screen shape.
* @param selectedColor The color of the selected [HorizontalPageIndicator] item
- * @param unselectedColor The color of unselected [HorizontalPageIndicator] items.
- * Defaults to [selectedColor] with 30% alpha
+ * @param unselectedColor The color of unselected [HorizontalPageIndicator] items. Defaults to
+ * [selectedColor] with 30% alpha
* @param indicatorSize The size of each [HorizontalPageIndicator] item in [Dp]
* @param spacing The spacing between indicator items in [Dp]
- * @param indicatorShape The shape of each [HorizontalPageIndicator] item.
- * Defaults to [CircleShape]
+ * @param indicatorShape The shape of each [HorizontalPageIndicator] item. Defaults to [CircleShape]
*/
@Composable
public fun HorizontalPageIndicator(
@@ -118,56 +115,50 @@
val spacerDefaultSize = (indicatorSize + spacing).value
val pagesOnScreen = min(MaxNumberOfIndicators, pageIndicatorState.pageCount)
- val pagesState = remember(pageIndicatorState.pageCount) {
- PagesState(
- totalPages = pageIndicatorState.pageCount,
- pagesOnScreen = pagesOnScreen
- )
- }
+ val pagesState =
+ remember(pageIndicatorState.pageCount) {
+ PagesState(totalPages = pageIndicatorState.pageCount, pagesOnScreen = pagesOnScreen)
+ }
pagesState.recalculateState(normalizedSelectedPage, normalizedOffset)
val indicatorFactory: @Composable (Int) -> Unit = { page ->
// An external box with a fixed indicatorSize - let us remain the same size for
// an indicator even if it's shrinked for smooth animations
- Box(
- modifier = Modifier
- .padding(horizontal = horizontalPadding)
- .size(indicatorSize)
- ) {
+ Box(modifier = Modifier.padding(horizontal = horizontalPadding).size(indicatorSize)) {
Box(
- modifier = Modifier
- .fillMaxSize()
- .align(Alignment.Center)
- .scale(pagesState.sizeRatio(page))
- .clip(indicatorShape)
- .alpha(pagesState.alpha(page))
- // Interpolation between unselected and selected colors depending
- // on selectedPageRatio
- .background(
- lerp(
- unselectedColor, selectedColor,
- pagesState.calculateSelectedRatio(page, normalizedOffset)
+ modifier =
+ Modifier.fillMaxSize()
+ .align(Alignment.Center)
+ .scale(pagesState.sizeRatio(page))
+ .clip(indicatorShape)
+ .alpha(pagesState.alpha(page))
+ // Interpolation between unselected and selected colors depending
+ // on selectedPageRatio
+ .background(
+ lerp(
+ unselectedColor,
+ selectedColor,
+ pagesState.calculateSelectedRatio(page, normalizedOffset)
+ )
)
- )
)
}
}
- val spacerLeft = @Composable {
- Spacer(
- Modifier
- .width((pagesState.leftSpacerSizeRatio * spacerDefaultSize).dp)
- .height(indicatorSize)
- )
- }
- val spacerRight = @Composable {
- Spacer(
- Modifier
- .width((pagesState.rightSpacerSizeRatio * spacerDefaultSize).dp)
- .height(indicatorSize)
-
- )
- }
+ val spacerLeft =
+ @Composable {
+ Spacer(
+ Modifier.width((pagesState.leftSpacerSizeRatio * spacerDefaultSize).dp)
+ .height(indicatorSize)
+ )
+ }
+ val spacerRight =
+ @Composable {
+ Spacer(
+ Modifier.width((pagesState.rightSpacerSizeRatio * spacerDefaultSize).dp)
+ .height(indicatorSize)
+ )
+ }
when (indicatorStyle) {
PageIndicatorStyle.Linear -> {
@@ -183,11 +174,11 @@
var containerSize by remember { mutableStateOf(IntSize.Zero) }
val boundsSize: Density.() -> IntSize = {
-
- val size = IntSize(
- width = ((indicatorSize + spacing).toPx() * pagesOnScreen).roundToInt(),
- height = (indicatorSize * 2).toPx().roundToInt().coerceAtLeast(0)
- )
+ val size =
+ IntSize(
+ width = ((indicatorSize + spacing).toPx() * pagesOnScreen).roundToInt(),
+ height = (indicatorSize * 2).toPx().roundToInt().coerceAtLeast(0)
+ )
size
}
@@ -206,8 +197,8 @@
offset = boundsOffset,
size = boundsSize,
modifier = modifier,
- onSizeChanged = { containerSize = it }) {
-
+ onSizeChanged = { containerSize = it }
+ ) {
CurvedPageIndicator(
pagesOnScreen = pagesOnScreen,
indicatorFactory = indicatorFactory,
@@ -219,44 +210,33 @@
}
}
-/**
- * The style of [HorizontalPageIndicator]. May be Curved or Linear
- */
+/** The style of [HorizontalPageIndicator]. May be Curved or Linear */
@kotlin.jvm.JvmInline
public value class PageIndicatorStyle internal constructor(internal val value: Int) {
companion object {
- /**
- * Curved style of [HorizontalPageIndicator]
- */
+ /** Curved style of [HorizontalPageIndicator] */
public val Curved = PageIndicatorStyle(0)
- /**
- * Linear style of [HorizontalPageIndicator]
- */
+ /** Linear style of [HorizontalPageIndicator] */
public val Linear = PageIndicatorStyle(1)
}
}
-/**
- * Contains the default values used by [HorizontalPageIndicator]
- */
+/** Contains the default values used by [HorizontalPageIndicator] */
public object PageIndicatorDefaults {
/**
- * Default style of [HorizontalPageIndicator]. Depending on shape of device, it returns either Curved
- * or Linear style.
+ * Default style of [HorizontalPageIndicator]. Depending on shape of device, it returns either
+ * Curved or Linear style.
*/
@Composable
public fun style(): PageIndicatorStyle =
- if (isRoundDevice()) PageIndicatorStyle.Curved
- else PageIndicatorStyle.Linear
+ if (isRoundDevice()) PageIndicatorStyle.Curved else PageIndicatorStyle.Linear
internal val MaxNumberOfIndicators = 6
}
-/**
- * An interface for connection between Pager and [HorizontalPageIndicator].
- */
+/** An interface for connection between Pager and [HorizontalPageIndicator]. */
public interface PageIndicatorState {
/**
* The current offset from the start of [selectedPage], as a ratio of the page width.
@@ -265,14 +245,10 @@
*/
public val pageOffset: Float
- /**
- * The currently selected page index
- */
+ /** The currently selected page index */
public val selectedPage: Int
- /**
- * Total number of pages
- */
+ /** Total number of pages */
public val pageCount: Int
}
@@ -283,7 +259,6 @@
indicatorFactory: @Composable (Int) -> Unit,
spacerLeft: @Composable () -> Unit,
spacerRight: @Composable () -> Unit
-
) {
Box(modifier = Modifier.fillMaxSize()) {
Row(
@@ -315,16 +290,10 @@
angularDirection = CurvedDirection.Angular.Reversed
) {
// drawing 1 extra spacer for transition
- curvedComposable {
- spacerLeft()
- }
+ curvedComposable { spacerLeft() }
for (page in 0..pagesOnScreen) {
- curvedComposable {
- indicatorFactory(page)
- }
+ curvedComposable { indicatorFactory(page) }
}
- curvedComposable {
- spacerRight()
- }
+ curvedComposable { spacerRight() }
}
}
diff --git a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/Icon.kt b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/Icon.kt
index 181a2cd1..fc441a6 100644
--- a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/Icon.kt
+++ b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/Icon.kt
@@ -32,12 +32,12 @@
*
* @param imageVector [ImageVector] to draw inside this Icon
* @param contentDescription Text used by accessibility services to describe what this icon
- * represents. This should always be provided unless this icon is used for decorative purposes,
- * and does not represent a meaningful action that a user can take. This text should be
- * localized, such as by using [androidx.compose.ui.res.stringResource] or similar
+ * represents. This should always be provided unless this icon is used for decorative purposes,
+ * and does not represent a meaningful action that a user can take. This text should be localized,
+ * such as by using [androidx.compose.ui.res.stringResource] or similar
* @param modifier Optional [Modifier] for this Icon
- * @param tint Tint to be applied to [imageVector]. If [Color.Unspecified] is provided, then no
- * tint is applied
+ * @param tint Tint to be applied to [imageVector]. If [Color.Unspecified] is provided, then no tint
+ * is applied
*/
@Composable
fun Icon(
@@ -60,12 +60,12 @@
*
* @param bitmap [ImageBitmap] to draw inside this Icon
* @param contentDescription Text used by accessibility services to describe what this icon
- * represents. This should always be provided unless this icon is used for decorative purposes,
- * and does not represent a meaningful action that a user can take. This text should be
- * localized, such as by using [androidx.compose.ui.res.stringResource] or similar
+ * represents. This should always be provided unless this icon is used for decorative purposes,
+ * and does not represent a meaningful action that a user can take. This text should be localized,
+ * such as by using [androidx.compose.ui.res.stringResource] or similar
* @param modifier Optional [Modifier] for this Icon
- * @param tint Tint to be applied to [bitmap]. If [Color.Unspecified] is provided, then no
- * tint is applied
+ * @param tint Tint to be applied to [bitmap]. If [Color.Unspecified] is provided, then no tint is
+ * applied
*/
@Composable
fun Icon(
@@ -89,12 +89,12 @@
*
* @param painter [Painter] to draw inside this Icon
* @param contentDescription Text used by accessibility services to describe what this icon
- * represents. This should always be provided unless this icon is used for decorative purposes,
- * and does not represent a meaningful action that a user can take. This text should be
- * localized, such as by using [androidx.compose.ui.res.stringResource] or similar
+ * represents. This should always be provided unless this icon is used for decorative purposes,
+ * and does not represent a meaningful action that a user can take. This text should be localized,
+ * such as by using [androidx.compose.ui.res.stringResource] or similar
* @param modifier Optional [Modifier] for this Icon
- * @param tint Tint to be applied to [painter]. If [Color.Unspecified] is provided, then no
- * tint is applied
+ * @param tint Tint to be applied to [painter]. If [Color.Unspecified] is provided, then no tint is
+ * applied
*/
@Composable
fun Icon(
diff --git a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/ImageWithScrimPainter.kt b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/ImageWithScrimPainter.kt
index e585061..4b626b8 100644
--- a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/ImageWithScrimPainter.kt
+++ b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/ImageWithScrimPainter.kt
@@ -77,8 +77,6 @@
"scrimAlpha=$scrimAlpha)"
}
- /**
- * Size of the combined painter, return Unspecified to allow us to fill the available space
- */
+ /** Size of the combined painter, return Unspecified to allow us to fill the available space */
override val intrinsicSize: Size = imagePainter.intrinsicSize
}
diff --git a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/ListHeader.kt b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/ListHeader.kt
index 0566bf5..2bf6f5e 100644
--- a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/ListHeader.kt
+++ b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/ListHeader.kt
@@ -38,8 +38,9 @@
* MaterialTheme. The contents will be start and end padded and should cover up to 3 lines of text.
*
* Example usage:
+ *
* @sample androidx.wear.compose.material.samples.ScalingLazyColumnWithHeaders
-
+ *
* @param modifier The modifier for the list header
* @param backgroundColor The background color to apply - typically Color.Transparent
* @param contentColor The color to apply to content
@@ -53,13 +54,14 @@
content: @Composable RowScope.() -> Unit
) {
Row(
- modifier = modifier
- .defaultMinSize(minHeight = 48.dp)
- .height(IntrinsicSize.Min)
- .wrapContentSize()
- .background(backgroundColor)
- .padding(horizontal = 14.dp)
- .semantics(mergeDescendants = true) { heading() }
+ modifier =
+ modifier
+ .defaultMinSize(minHeight = 48.dp)
+ .height(IntrinsicSize.Min)
+ .wrapContentSize()
+ .background(backgroundColor)
+ .padding(horizontal = 14.dp)
+ .semantics(mergeDescendants = true) { heading() }
) {
CompositionLocalProvider(
LocalContentColor provides contentColor,
diff --git a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/MaterialTextSelectionColors.kt b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/MaterialTextSelectionColors.kt
index fe1151e..3a912d7 100644
--- a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/MaterialTextSelectionColors.kt
+++ b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/MaterialTextSelectionColors.kt
@@ -38,40 +38,39 @@
// Test with ContentAlpha.medium to ensure that the selection background is accessible in the
// 'worst case' scenario. We explicitly don't test with ContentAlpha.disabled, as disabled
// text shouldn't be selectable / is noted as disabled for accessibility purposes.
- val textColorWithLowestAlpha = colors.contentColorFor(backgroundColor)
- .takeOrElse {
- LocalContentColor.current
- }.copy(
- alpha = ContentAlpha.medium
- )
+ val textColorWithLowestAlpha =
+ colors
+ .contentColorFor(backgroundColor)
+ .takeOrElse { LocalContentColor.current }
+ .copy(alpha = ContentAlpha.medium)
return remember(primaryColor, backgroundColor, textColorWithLowestAlpha) {
TextSelectionColors(
handleColor = colors.primary,
- backgroundColor = calculateSelectionBackgroundColor(
- selectionColor = primaryColor,
- textColor = textColorWithLowestAlpha,
- backgroundColor = backgroundColor
- )
+ backgroundColor =
+ calculateSelectionBackgroundColor(
+ selectionColor = primaryColor,
+ textColor = textColorWithLowestAlpha,
+ backgroundColor = backgroundColor
+ )
)
}
}
/**
- * Best-effort calculates a color (with alpha) for the selection background that (if possible)
- * will have at least [DesiredContrastRatio] with [textColor], when the selection background
- * is on top of [backgroundColor].
+ * Best-effort calculates a color (with alpha) for the selection background that (if possible) will
+ * have at least [DesiredContrastRatio] with [textColor], when the selection background is on top of
+ * [backgroundColor].
*
- * Since this is a minimum contrast ratio, [textColor] should have the lowest alpha that
- * may be applied to content so we can ensure that the selection background color is accessible
- * in that worst-case scenario for contrast.
+ * Since this is a minimum contrast ratio, [textColor] should have the lowest alpha that may be
+ * applied to content so we can ensure that the selection background color is accessible in that
+ * worst-case scenario for contrast.
*
* @param selectionColor the 'raw' (without alpha) selection color that we should search alpha for
* @param textColor the color of text with minimal alpha applied to test for contrast with
* @param backgroundColor the color of the background that the selection color will typically be
- * placed against
- *
- * @return a resulting [selectionColor] with alpha applied that results in acceptable contrast
- * (if possible with the values for [selectionColor], [textColor] and [backgroundColor]).
+ * placed against
+ * @return a resulting [selectionColor] with alpha applied that results in acceptable contrast (if
+ * possible with the values for [selectionColor], [textColor] and [backgroundColor]).
*/
/*@VisibleForTesting*/
internal fun calculateSelectionBackgroundColor(
@@ -79,31 +78,36 @@
textColor: Color,
backgroundColor: Color
): Color {
- val maximumContrastRatio = calculateContrastRatio(
- selectionColor = selectionColor,
- selectionColorAlpha = DefaultSelectionBackgroundAlpha,
- textColor = textColor,
- backgroundColor = backgroundColor
- )
-
- val minimumContrastRatio = calculateContrastRatio(
- selectionColor = selectionColor,
- selectionColorAlpha = MinimumSelectionBackgroundAlpha,
- textColor = textColor,
- backgroundColor = backgroundColor
- )
-
- val alpha = when {
- // If the default alpha has enough contrast, use that
- maximumContrastRatio >= DesiredContrastRatio -> DefaultSelectionBackgroundAlpha
- // If the minimum alpha still does not have enough contrast, just use the minimum and return
- minimumContrastRatio < DesiredContrastRatio -> MinimumSelectionBackgroundAlpha
- else -> binarySearchForAccessibleSelectionColorAlpha(
+ val maximumContrastRatio =
+ calculateContrastRatio(
selectionColor = selectionColor,
+ selectionColorAlpha = DefaultSelectionBackgroundAlpha,
textColor = textColor,
backgroundColor = backgroundColor
)
- }
+
+ val minimumContrastRatio =
+ calculateContrastRatio(
+ selectionColor = selectionColor,
+ selectionColorAlpha = MinimumSelectionBackgroundAlpha,
+ textColor = textColor,
+ backgroundColor = backgroundColor
+ )
+
+ val alpha =
+ when {
+ // If the default alpha has enough contrast, use that
+ maximumContrastRatio >= DesiredContrastRatio -> DefaultSelectionBackgroundAlpha
+ // If the minimum alpha still does not have enough contrast, just use the minimum and
+ // return
+ minimumContrastRatio < DesiredContrastRatio -> MinimumSelectionBackgroundAlpha
+ else ->
+ binarySearchForAccessibleSelectionColorAlpha(
+ selectionColor = selectionColor,
+ textColor = textColor,
+ backgroundColor = backgroundColor
+ )
+ }
return selectionColor.copy(alpha = alpha)
}
@@ -115,25 +119,24 @@
* The resulting alpha will be within the range of [MinimumSelectionBackgroundAlpha] and
* [DefaultSelectionBackgroundAlpha] - since not all values for [selectionColor], [textColor] and
* [backgroundColor] can be guaranteed to produce an accessible contrast ratio, this is a
- * best-effort attempt and [MinimumSelectionBackgroundAlpha] might still not produce an
- * accessible contrast ratio. In this case developers are encouraged to manually choose a
- * different color for selection that _is_ accessible with their chosen content and background
- * colors.
+ * best-effort attempt and [MinimumSelectionBackgroundAlpha] might still not produce an accessible
+ * contrast ratio. In this case developers are encouraged to manually choose a different color for
+ * selection that _is_ accessible with their chosen content and background colors.
*
- * Caps the number of attempts at 7 for performance and to avoid infinite searching when there is
- * no value that results in an accessible contrast ratio. Because alpha is limited to [0,1], 7
- * steps results in a precision of ~0.01, since log2(1/0.01) ≈ 7.
+ * Caps the number of attempts at 7 for performance and to avoid infinite searching when there is no
+ * value that results in an accessible contrast ratio. Because alpha is limited to [0,1], 7 steps
+ * results in a precision of ~0.01, since log2(1/0.01) ≈ 7.
*
* Note: binary searching here is chosen since it is not possible to 'solve' for alpha, since the
- * transformation from color -> contrast ratio is not linear (the gamma exponent for sRGB colors
- * is 2.4). We can approximate this to 2, but this results in not that accurate solutions, and we
- * need to guarantee that they are at least above [DesiredContrastRatio] - falling just below is
- * not an acceptable result.
+ * transformation from color -> contrast ratio is not linear (the gamma exponent for sRGB colors is
+ * 2.4). We can approximate this to 2, but this results in not that accurate solutions, and we need
+ * to guarantee that they are at least above [DesiredContrastRatio] - falling just below is not an
+ * acceptable result.
*
* @param selectionColor the 'raw' (without alpha) selection color that we should search alpha for
* @param textColor the color of text with minimal alpha applied to test for contrast with
* @param backgroundColor the color of the background that the selection color will typically be
- * placed against
+ * placed against
*/
private fun binarySearchForAccessibleSelectionColorAlpha(
selectionColor: Color,
@@ -148,12 +151,13 @@
var highAlpha = DefaultSelectionBackgroundAlpha
while (attempts < maxAttempts) {
- val contrastRatio = calculateContrastRatio(
- selectionColor = selectionColor,
- selectionColorAlpha = alpha,
- textColor = textColor,
- backgroundColor = backgroundColor
- )
+ val contrastRatio =
+ calculateContrastRatio(
+ selectionColor = selectionColor,
+ selectionColorAlpha = alpha,
+ textColor = textColor,
+ backgroundColor = backgroundColor
+ )
// Percentage error of the calculated contrast compared to the actual contrast. Positive
// numbers here mean we have higher contrast than needed.
@@ -174,8 +178,8 @@
}
/**
- * Calculates the contrast ratio of [textColor] against [selectionColor] with
- * [selectionColorAlpha], all on top of [backgroundColor].
+ * Calculates the contrast ratio of [textColor] against [selectionColor] with [selectionColorAlpha],
+ * all on top of [backgroundColor].
*
* Both the [selectionColor] and [textColor] will be composited to handle transparency.
*
@@ -183,8 +187,7 @@
* @param selectionColorAlpha the alpha for [selectionColor] to test contrast with
* @param textColor the color of text with minimal alpha applied to test for contrast with
* @param backgroundColor the color of the background that the selection color will typically be
- * placed against
- *
+ * placed against
* @return the contrast ratio as a value between 1 and 21. See [calculateContrastRatio]
*/
private fun calculateContrastRatio(
@@ -193,17 +196,18 @@
textColor: Color,
backgroundColor: Color
): Float {
- val compositeBackground = selectionColor.copy(alpha = selectionColorAlpha)
- .compositeOver(backgroundColor)
+ val compositeBackground =
+ selectionColor.copy(alpha = selectionColorAlpha).compositeOver(backgroundColor)
val compositeTextColor = textColor.compositeOver(compositeBackground)
return calculateContrastRatio(compositeTextColor, compositeBackground)
}
/**
- * Calculates the contrast ratio of [foreground] against [background], returning a value between
- * 1 and 21. (1:1 and 21:1 ratios).
+ * Calculates the contrast ratio of [foreground] against [background], returning a value between 1
+ * and 21. (1:1 and 21:1 ratios).
*
- * Formula taken from [WCAG 2.0](https://www.w3.org/TR/UNDERSTANDING-WCAG20/visual-audio-contrast-contrast.html#contrast-ratiodef)
+ * Formula taken from
+ * [WCAG 2.0](https://www.w3.org/TR/UNDERSTANDING-WCAG20/visual-audio-contrast-contrast.html#contrast-ratiodef)
*
* Note: [foreground] and [background] *must* be opaque. See [Color.compositeOver] to pre-composite
* a translucent foreground over the background.
@@ -226,14 +230,12 @@
private const val DefaultSelectionBackgroundAlpha = 0.4f
/**
- * Not all combinations of text color and selection color will have a reasonable alpha that
- * produces a contrast ratio of at least [DesiredContrastRatio] - in this case just pick a low
- * but still visible alpha so at least the contrast ratio is as good as it can be - this is
- * preferable to crashing at runtime.
+ * Not all combinations of text color and selection color will have a reasonable alpha that produces
+ * a contrast ratio of at least [DesiredContrastRatio] - in this case just pick a low but still
+ * visible alpha so at least the contrast ratio is as good as it can be - this is preferable to
+ * crashing at runtime.
*/
private const val MinimumSelectionBackgroundAlpha = DefaultSelectionBackgroundAlpha / 2f
-/**
- * Material and WCAG 2.0 sc 1.4.3 minimum contrast for AA text
- */
+/** Material and WCAG 2.0 sc 1.4.3 minimum contrast for AA text */
private const val DesiredContrastRatio = 4.5f
diff --git a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/MaterialTheme.kt b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/MaterialTheme.kt
index 8f7bdbf..2969fe7 100644
--- a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/MaterialTheme.kt
+++ b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/MaterialTheme.kt
@@ -25,8 +25,8 @@
// TODO: Provide references to the Wear material design specs.
/**
- * MaterialTheme defines the styling principles from the WearOS Material design specification
- * which extends the Material design specification.
+ * MaterialTheme defines the styling principles from the WearOS Material design specification which
+ * extends the Material design specification.
*
* Wear Material components from package/sub-packages in [androidx.wear.compose.material] use values
* provided here when retrieving default values.
@@ -38,17 +38,16 @@
* and shapes defined in the [Wear Shape scheme](https://).
*
* All values may be set by providing this component with the [colors][Colors],
- * [typography][Typography], and [shapes][Shapes] attributes. Use this to configure the
- * overall theme of elements within this MaterialTheme.
+ * [typography][Typography], and [shapes][Shapes] attributes. Use this to configure the overall
+ * theme of elements within this MaterialTheme.
*
* Any values that are not set will inherit the current value from the theme, falling back to the
- * defaults if there is no parent MaterialTheme. This allows using a MaterialTheme at the
- * top of your application, and then separate MaterialTheme(s) for different screens / parts of
- * your UI, overriding only the parts of the theme definition that need to change.
+ * defaults if there is no parent MaterialTheme. This allows using a MaterialTheme at the top of
+ * your application, and then separate MaterialTheme(s) for different screens / parts of your UI,
+ * overriding only the parts of the theme definition that need to change.
*
* For more information, see the
- * [Theming](https://developer.android.com/training/wearables/components/theme)
- * guide.
+ * [Theming](https://developer.android.com/training/wearables/components/theme) guide.
*
* @param colors A complete definition of the Wear Material Color theme for this hierarchy
* @param typography A set of text styles to be used as this hierarchy's typography system
@@ -83,17 +82,11 @@
public object MaterialTheme {
public val colors: Colors
- @ReadOnlyComposable
- @Composable
- get() = LocalColors.current
+ @ReadOnlyComposable @Composable get() = LocalColors.current
public val typography: Typography
- @ReadOnlyComposable
- @Composable
- get() = LocalTypography.current
+ @ReadOnlyComposable @Composable get() = LocalTypography.current
public val shapes: Shapes
- @ReadOnlyComposable
- @Composable
- get() = LocalShapes.current
+ @ReadOnlyComposable @Composable get() = LocalShapes.current
}
diff --git a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/Picker.kt b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/Picker.kt
index a0c562a..adcf8e2 100644
--- a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/Picker.kt
+++ b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/Picker.kt
@@ -73,55 +73,56 @@
import kotlinx.coroutines.launch
/**
- * A scrollable list of items to pick from. By default, items will be repeated
- * "infinitely" in both directions, unless [PickerState#repeatItems] is specified as false.
+ * A scrollable list of items to pick from. By default, items will be repeated "infinitely" in both
+ * directions, unless [PickerState#repeatItems] is specified as false.
*
- * This overload has default support for rotary side button (crown) and bezel input devices.
- * The content will be scrolled when the rotary device is rotated
- * with a snap motion which will snap each item to the centre of the list
- * while it is rotated. It uses [RotaryScrollableDefaults.snapBehavior].
- * This behavior can be modified using the alternative Picker overload
- * that takes a custom `rotaryBehavior` parameter.
+ * This overload has default support for rotary side button (crown) and bezel input devices. The
+ * content will be scrolled when the rotary device is rotated with a snap motion which will snap
+ * each item to the centre of the list while it is rotated. It uses
+ * [RotaryScrollableDefaults.snapBehavior]. This behavior can be modified using the alternative
+ * Picker overload that takes a custom `rotaryBehavior` parameter.
*
* Example of a simple picker to select one of five options:
+ *
* @sample androidx.wear.compose.material.samples.SimplePicker
*
* Example of dual pickers, where clicking switches which one is editable and which is read-only:
+ *
* @sample androidx.wear.compose.material.samples.DualPicker
*
* @param state The state of the component
- * @param contentDescription Text used by accessibility services to describe what the
- * selected option represents. This text should be localized, such as by using
- * [androidx.compose.ui.res.stringResource] or similar. Typically, the content description is
- * inferred via derivedStateOf to avoid unnecessary recompositions, like this:
- * val description by remember { derivedStateOf { /* expression using state.selectedOption */ } }
+ * @param contentDescription Text used by accessibility services to describe what the selected
+ * option represents. This text should be localized, such as by using
+ * [androidx.compose.ui.res.stringResource] or similar. Typically, the content description is
+ * inferred via derivedStateOf to avoid unnecessary recompositions, like this: val description by
+ * remember { derivedStateOf { /* expression using state.selectedOption */ } }
* @param modifier Modifier to be applied to the Picker
* @param readOnly Determines whether the Picker should display other available options for this
- * field, inviting the user to scroll to change the value. When readOnly = true,
- * only displays the currently selected option (and optionally a label). This is intended to be
- * used for screens that display multiple Pickers, only one of which has the focus at a time.
- * @param readOnlyLabel A slot for providing a label, displayed above the selected option
- * when the [Picker] is read-only. The label is overlaid with the currently selected
- * option within a Box, so it is recommended that the label is given [Alignment.TopCenter].
- * @param onSelected Action triggered when the Picker is selected by clicking. Used by
- * accessibility semantics, which facilitates implementation of multi-picker screens.
+ * field, inviting the user to scroll to change the value. When readOnly = true, only displays the
+ * currently selected option (and optionally a label). This is intended to be used for screens
+ * that display multiple Pickers, only one of which has the focus at a time.
+ * @param readOnlyLabel A slot for providing a label, displayed above the selected option when the
+ * [Picker] is read-only. The label is overlaid with the currently selected option within a Box,
+ * so it is recommended that the label is given [Alignment.TopCenter].
+ * @param onSelected Action triggered when the Picker is selected by clicking. Used by accessibility
+ * semantics, which facilitates implementation of multi-picker screens.
* @param scalingParams The parameters to configure the scaling and transparency effects for the
- * component. See [ScalingParams]
+ * component. See [ScalingParams]
* @param separation The amount of separation in [Dp] between items. Can be negative, which can be
- * useful for Text if it has plenty of whitespace.
+ * useful for Text if it has plenty of whitespace.
* @param gradientRatio The size relative to the Picker height that the top and bottom gradients
- * take. These gradients blur the picker content on the top and bottom. The default is 0.33,
- * so the top 1/3 and the bottom 1/3 of the picker are taken by gradients. Should be between 0.0 and
- * 0.5. Use 0.0 to disable the gradient.
+ * take. These gradients blur the picker content on the top and bottom. The default is 0.33, so
+ * the top 1/3 and the bottom 1/3 of the picker are taken by gradients. Should be between 0.0 and
+ * 0.5. Use 0.0 to disable the gradient.
* @param gradientColor Should be the color outside of the Picker, so there is continuity.
* @param flingBehavior logic describing fling behavior.
* @param userScrollEnabled Determines whether the picker should be scrollable or not. When
- * userScrollEnabled = true, picker is scrollable. This is different from [readOnly] as it changes
- * the scrolling behaviour.
+ * userScrollEnabled = true, picker is scrollable. This is different from [readOnly] as it changes
+ * the scrolling behaviour.
* @param option A block which describes the content. Inside this block you can reference
- * [PickerScope.selectedOption] and other properties in [PickerScope]. When read-only mode is in
- * use on a screen, it is recommended that this content is given [Alignment.Center] in order to
- * align with the centrally selected Picker value.
+ * [PickerScope.selectedOption] and other properties in [PickerScope]. When read-only mode is in
+ * use on a screen, it is recommended that this content is given [Alignment.Center] in order to
+ * align with the centrally selected Picker value.
*/
@Deprecated(
"Please use the new overload with additional rotaryBehavior parameter",
@@ -137,8 +138,7 @@
onSelected: () -> Unit = {},
scalingParams: ScalingParams = PickerDefaults.defaultScalingParams(),
separation: Dp = 0.dp,
- @FloatRange(from = 0.0, to = 0.5)
- gradientRatio: Float = PickerDefaults.DefaultGradientRatio,
+ @FloatRange(from = 0.0, to = 0.5) gradientRatio: Float = PickerDefaults.DefaultGradientRatio,
gradientColor: Color = MaterialTheme.colors.background,
flingBehavior: FlingBehavior = PickerDefaults.flingBehavior(state),
userScrollEnabled: Boolean = true,
@@ -157,72 +157,71 @@
gradientColor = gradientColor,
flingBehavior = flingBehavior,
userScrollEnabled = userScrollEnabled,
- rotaryScrollableBehavior = RotaryScrollableDefaults.snapBehavior(
- state,
- state.toRotarySnapLayoutInfoProvider()
- ),
+ rotaryScrollableBehavior =
+ RotaryScrollableDefaults.snapBehavior(state, state.toRotarySnapLayoutInfoProvider()),
option = option
)
}
/**
- * A scrollable list of items to pick from. By default, items will be repeated
- * "infinitely" in both directions, unless [PickerState#repeatItems] is specified as false.
+ * A scrollable list of items to pick from. By default, items will be repeated "infinitely" in both
+ * directions, unless [PickerState#repeatItems] is specified as false.
*
- * This overload supports rotary input. Rotary input allows users to scroll the content
- * of the [Picker] - by using a crown or a rotating bezel on their Wear OS device.
- * It can be modified with [rotaryScrollableBehavior] param.
- * Note that rotary scroll and touch scroll should be aligned.
- * If [rotaryScrollableBehavior] is set for snap (using [RotaryScrollableDefaults.snapBehavior]),
+ * This overload supports rotary input. Rotary input allows users to scroll the content of the
+ * [Picker] - by using a crown or a rotating bezel on their Wear OS device. It can be modified with
+ * [rotaryScrollableBehavior] param. Note that rotary scroll and touch scroll should be aligned. If
+ * [rotaryScrollableBehavior] is set for snap (using [RotaryScrollableDefaults.snapBehavior]),
* [flingBehavior] should be set for snap as well (using [PickerDefaults.flingBehavior]).
*
* Example of a simple picker to select one of five options:
+ *
* @sample androidx.wear.compose.material.samples.SimplePicker
*
* Example of dual pickers, where clicking switches which one is editable and which is read-only:
+ *
* @sample androidx.wear.compose.material.samples.DualPicker
*
* @param state The state of the component
- * @param contentDescription Text used by accessibility services to describe what the
- * selected option represents. This text should be localized, such as by using
- * [androidx.compose.ui.res.stringResource] or similar. Typically, the content description is
- * inferred via derivedStateOf to avoid unnecessary recompositions, like this:
- * val description by remember { derivedStateOf { /* expression using state.selectedOption */ } }
+ * @param contentDescription Text used by accessibility services to describe what the selected
+ * option represents. This text should be localized, such as by using
+ * [androidx.compose.ui.res.stringResource] or similar. Typically, the content description is
+ * inferred via derivedStateOf to avoid unnecessary recompositions, like this: val description by
+ * remember { derivedStateOf { /* expression using state.selectedOption */ } }
* @param modifier Modifier to be applied to the Picker
* @param readOnly Determines whether the Picker should display other available options for this
- * field, inviting the user to scroll to change the value. When readOnly = true,
- * only displays the currently selected option (and optionally a label). This is intended to be
- * used for screens that display multiple Pickers, only one of which has the focus at a time.
- * @param readOnlyLabel A slot for providing a label, displayed above the selected option
- * when the [Picker] is read-only. The label is overlaid with the currently selected
- * option within a Box, so it is recommended that the label is given [Alignment.TopCenter].
- * @param onSelected Action triggered when the Picker is selected by clicking. Used by
- * accessibility semantics, which facilitates implementation of multi-picker screens.
+ * field, inviting the user to scroll to change the value. When readOnly = true, only displays the
+ * currently selected option (and optionally a label). This is intended to be used for screens
+ * that display multiple Pickers, only one of which has the focus at a time.
+ * @param readOnlyLabel A slot for providing a label, displayed above the selected option when the
+ * [Picker] is read-only. The label is overlaid with the currently selected option within a Box,
+ * so it is recommended that the label is given [Alignment.TopCenter].
+ * @param onSelected Action triggered when the Picker is selected by clicking. Used by accessibility
+ * semantics, which facilitates implementation of multi-picker screens.
* @param scalingParams The parameters to configure the scaling and transparency effects for the
- * component. See [ScalingParams]
+ * component. See [ScalingParams]
* @param separation The amount of separation in [Dp] between items. Can be negative, which can be
- * useful for Text if it has plenty of whitespace.
+ * useful for Text if it has plenty of whitespace.
* @param gradientRatio The size relative to the Picker height that the top and bottom gradients
- * take. These gradients blur the picker content on the top and bottom. The default is 0.33,
- * so the top 1/3 and the bottom 1/3 of the picker are taken by gradients. Should be between 0.0 and
- * 0.5. Use 0.0 to disable the gradient.
+ * take. These gradients blur the picker content on the top and bottom. The default is 0.33, so
+ * the top 1/3 and the bottom 1/3 of the picker are taken by gradients. Should be between 0.0 and
+ * 0.5. Use 0.0 to disable the gradient.
* @param gradientColor Should be the color outside of the Picker, so there is continuity.
* @param flingBehavior logic describing fling behavior. Note that when configuring fling or snap
- * behavior, this flingBehavior parameter and the [rotaryScrollableBehavior] parameter that controls
- * rotary scroll are expected to be consistent.
+ * behavior, this flingBehavior parameter and the [rotaryScrollableBehavior] parameter that
+ * controls rotary scroll are expected to be consistent.
* @param userScrollEnabled Determines whether the picker should be scrollable or not. When
- * userScrollEnabled = true, picker is scrollable. This is different from [readOnly] as it changes
- * the scrolling behaviour.
+ * userScrollEnabled = true, picker is scrollable. This is different from [readOnly] as it changes
+ * the scrolling behaviour.
* @param rotaryScrollableBehavior Parameter for changing rotary behavior. Supports scroll
- * [RotaryScrollableDefaults.behavior] and snap [RotaryScrollableDefaults.snapBehavior].
- * We do recommend to use [RotaryScrollableDefaults.snapBehavior] as this is a recommended
- * behavior for Pickers. Note that when configuring fling or snap behavior, this rotaryBehavior
- * parameter and the [flingBehavior] parameter that controls touch scroll are expected to be
- * consistent. Can be null if rotary support is not required.
+ * [RotaryScrollableDefaults.behavior] and snap [RotaryScrollableDefaults.snapBehavior]. We do
+ * recommend to use [RotaryScrollableDefaults.snapBehavior] as this is a recommended behavior for
+ * Pickers. Note that when configuring fling or snap behavior, this rotaryBehavior parameter and
+ * the [flingBehavior] parameter that controls touch scroll are expected to be consistent. Can be
+ * null if rotary support is not required.
* @param option A block which describes the content. Inside this block you can reference
- * [PickerScope.selectedOption] and other properties in [PickerScope]. When read-only mode is in
- * use on a screen, it is recommended that this content is given [Alignment.Center] in order to
- * align with the centrally selected Picker value.
+ * [PickerScope.selectedOption] and other properties in [PickerScope]. When read-only mode is in
+ * use on a screen, it is recommended that this content is given [Alignment.Center] in order to
+ * align with the centrally selected Picker value.
*/
@OptIn(ExperimentalWearFoundationApi::class)
@Composable
@@ -235,15 +234,12 @@
onSelected: () -> Unit = {},
scalingParams: ScalingParams = PickerDefaults.defaultScalingParams(),
separation: Dp = 0.dp,
- @FloatRange(from = 0.0, to = 0.5)
- gradientRatio: Float = PickerDefaults.DefaultGradientRatio,
+ @FloatRange(from = 0.0, to = 0.5) gradientRatio: Float = PickerDefaults.DefaultGradientRatio,
gradientColor: Color = MaterialTheme.colors.background,
flingBehavior: FlingBehavior = PickerDefaults.flingBehavior(state),
userScrollEnabled: Boolean = true,
- rotaryScrollableBehavior: RotaryScrollableBehavior? = RotaryScrollableDefaults.snapBehavior(
- state,
- state.toRotarySnapLayoutInfoProvider()
- ),
+ rotaryScrollableBehavior: RotaryScrollableBehavior? =
+ RotaryScrollableDefaults.snapBehavior(state, state.toRotarySnapLayoutInfoProvider()),
option: @Composable PickerScope.(optionIndex: Int) -> Unit
) {
require(gradientRatio in 0f..0.5f) { "gradientRatio should be between 0.0 and 0.5" }
@@ -252,67 +248,69 @@
val coroutineScope = rememberCoroutineScope()
Box(modifier = modifier) {
ScalingLazyColumn(
- modifier = Modifier.clearAndSetSemantics {
- onClick {
- coroutineScope.launch {
- onSelected()
- }
- true
- }
- scrollToIndex {
- coroutineScope.launch {
- state.scrollToOption(it)
- onSelected()
- }
- true
- }
- if (!state.isScrollInProgress && contentDescription != null) {
- this.contentDescription = contentDescription
- }
- focused = !readOnly
- }.then(
- if (!readOnly && gradientRatio > 0.0f) {
- Modifier
- .drawWithContent {
- drawContent()
- drawGradient(gradientColor, gradientRatio)
- }
- // b/223386180 - add padding when drawing rectangles to
- // prevent jitter on screen.
- .padding(vertical = 1.dp)
- .align(Alignment.Center)
- } else if (readOnly) {
- Modifier
- .drawWithContent {
- drawContent()
- val visibleItems =
- state.scalingLazyListState.layoutInfo.visibleItemsInfo
- if (visibleItems.isNotEmpty()) {
- val centerItem =
- visibleItems.fastFirstOrNull { info ->
- info.index == state.scalingLazyListState.centerItemIndex
- } ?: visibleItems[visibleItems.size / 2]
- val shimHeight =
- (size.height - centerItem.unadjustedSize.toFloat() -
- separation.toPx()) / 2.0f
- drawShim(gradientColor, shimHeight)
- }
+ modifier =
+ Modifier.clearAndSetSemantics {
+ onClick {
+ coroutineScope.launch { onSelected() }
+ true
}
- // b/223386180 - add padding when drawing rectangles to
- // prevent jitter on screen.
- .padding(vertical = 1.dp)
- .align(Alignment.Center)
- } else {
- Modifier.align(Alignment.Center)
- }
- ),
+ scrollToIndex {
+ coroutineScope.launch {
+ state.scrollToOption(it)
+ onSelected()
+ }
+ true
+ }
+ if (!state.isScrollInProgress && contentDescription != null) {
+ this.contentDescription = contentDescription
+ }
+ focused = !readOnly
+ }
+ .then(
+ if (!readOnly && gradientRatio > 0.0f) {
+ Modifier.drawWithContent {
+ drawContent()
+ drawGradient(gradientColor, gradientRatio)
+ }
+ // b/223386180 - add padding when drawing rectangles to
+ // prevent jitter on screen.
+ .padding(vertical = 1.dp)
+ .align(Alignment.Center)
+ } else if (readOnly) {
+ Modifier.drawWithContent {
+ drawContent()
+ val visibleItems =
+ state.scalingLazyListState.layoutInfo.visibleItemsInfo
+ if (visibleItems.isNotEmpty()) {
+ val centerItem =
+ visibleItems.fastFirstOrNull { info ->
+ info.index ==
+ state.scalingLazyListState.centerItemIndex
+ } ?: visibleItems[visibleItems.size / 2]
+ val shimHeight =
+ (size.height -
+ centerItem.unadjustedSize.toFloat() -
+ separation.toPx()) / 2.0f
+ drawShim(gradientColor, shimHeight)
+ }
+ }
+ // b/223386180 - add padding when drawing rectangles to
+ // prevent jitter on screen.
+ .padding(vertical = 1.dp)
+ .align(Alignment.Center)
+ } else {
+ Modifier.align(Alignment.Center)
+ }
+ ),
state = state.scalingLazyListState,
content = {
items(state.numberOfItems()) { ix ->
with(pickerScope) {
- Box(Modifier.graphicsLayer {
- compositingStrategy = CompositingStrategy.Offscreen
- }) {
+ Box(
+ Modifier.graphicsLayer {
+ compositingStrategy = CompositingStrategy.Offscreen
+ }
+ ) {
option((ix + state.optionsOffset) % state.numberOfOptions)
}
}
@@ -322,9 +320,7 @@
contentPadding = PaddingValues(0.dp),
scalingParams = scalingParams,
horizontalAlignment = Alignment.CenterHorizontally,
- verticalArrangement = Arrangement.spacedBy(
- space = separation
- ),
+ verticalArrangement = Arrangement.spacedBy(space = separation),
flingBehavior = flingBehavior,
autoCentering = AutoCenteringParams(itemIndex = 0),
userScrollEnabled = userScrollEnabled
@@ -353,7 +349,8 @@
@Deprecated(
"This overload is provided for backwards compatibility with Compose for Wear OS 1.1." +
"A newer overload is available which uses ScalingParams from " +
- "androidx.wear.compose.foundation.lazy package", level = DeprecationLevel.HIDDEN
+ "androidx.wear.compose.foundation.lazy package",
+ level = DeprecationLevel.HIDDEN
)
@Composable
public fun Picker(
@@ -365,73 +362,78 @@
onSelected: () -> Unit = {},
scalingParams: androidx.wear.compose.material.ScalingParams = PickerDefaults.scalingParams(),
separation: Dp = 0.dp,
- @FloatRange(from = 0.0, to = 0.5)
- gradientRatio: Float = PickerDefaults.DefaultGradientRatio,
+ @FloatRange(from = 0.0, to = 0.5) gradientRatio: Float = PickerDefaults.DefaultGradientRatio,
gradientColor: Color = MaterialTheme.colors.background,
flingBehavior: FlingBehavior = PickerDefaults.flingBehavior(state),
userScrollEnabled: Boolean = true,
option: @Composable PickerScope.(optionIndex: Int) -> Unit
-) = Picker(
- state = state,
- contentDescription = contentDescription,
- modifier = modifier,
- readOnly = readOnly,
- readOnlyLabel = readOnlyLabel,
- onSelected = onSelected,
- scalingParams = convertToDefaultFoundationScalingParams(scalingParams),
- separation = separation,
- gradientRatio = gradientRatio,
- gradientColor = gradientColor,
- flingBehavior = flingBehavior,
- userScrollEnabled = userScrollEnabled,
- option = option
-)
+) =
+ Picker(
+ state = state,
+ contentDescription = contentDescription,
+ modifier = modifier,
+ readOnly = readOnly,
+ readOnlyLabel = readOnlyLabel,
+ onSelected = onSelected,
+ scalingParams = convertToDefaultFoundationScalingParams(scalingParams),
+ separation = separation,
+ gradientRatio = gradientRatio,
+ gradientColor = gradientColor,
+ flingBehavior = flingBehavior,
+ userScrollEnabled = userScrollEnabled,
+ option = option
+ )
/**
- * A scrollable list of items to pick from. By default, items will be repeated
- * "infinitely" in both directions, unless [PickerState#repeatItems] is specified as false.
+ * A scrollable list of items to pick from. By default, items will be repeated "infinitely" in both
+ * directions, unless [PickerState#repeatItems] is specified as false.
*
* Example of a simple picker to select one of five options:
+ *
* @sample androidx.wear.compose.material.samples.SimplePicker
*
* Example of dual pickers, where clicking switches which one is editable and which is read-only:
+ *
* @sample androidx.wear.compose.material.samples.DualPicker
*
* @param state The state of the component
- * @param contentDescription Text used by accessibility services to describe what the
- * selected option represents. This text should be localized, such as by using
- * [androidx.compose.ui.res.stringResource] or similar. Typically, the content description is
- * inferred via derivedStateOf to avoid unnecessary recompositions, like this:
- * val description by remember { derivedStateOf { /* expression using state.selectedOption */ } }
+ * @param contentDescription Text used by accessibility services to describe what the selected
+ * option represents. This text should be localized, such as by using
+ * [androidx.compose.ui.res.stringResource] or similar. Typically, the content description is
+ * inferred via derivedStateOf to avoid unnecessary recompositions, like this: val description by
+ * remember { derivedStateOf { /* expression using state.selectedOption */ } }
* @param modifier Modifier to be applied to the Picker
* @param readOnly Determines whether the Picker should display other available options for this
- * field, inviting the user to scroll to change the value. When readOnly = true,
- * only displays the currently selected option (and optionally a label). This is intended to be
- * used for screens that display multiple Pickers, only one of which has the focus at a time.
- * @param readOnlyLabel A slot for providing a label, displayed above the selected option
- * when the [Picker] is read-only. The label is overlaid with the currently selected
- * option within a Box, so it is recommended that the label is given [Alignment.TopCenter].
- * @param onSelected Action triggered when the Picker is selected by clicking. Used by
- * accessibility semantics, which facilitates implementation of multi-picker screens.
+ * field, inviting the user to scroll to change the value. When readOnly = true, only displays the
+ * currently selected option (and optionally a label). This is intended to be used for screens
+ * that display multiple Pickers, only one of which has the focus at a time.
+ * @param readOnlyLabel A slot for providing a label, displayed above the selected option when the
+ * [Picker] is read-only. The label is overlaid with the currently selected option within a Box,
+ * so it is recommended that the label is given [Alignment.TopCenter].
+ * @param onSelected Action triggered when the Picker is selected by clicking. Used by accessibility
+ * semantics, which facilitates implementation of multi-picker screens.
* @param scalingParams The parameters to configure the scaling and transparency effects for the
- * component. See [ScalingParams]
+ * component. See [ScalingParams]
* @param separation The amount of separation in [Dp] between items. Can be negative, which can be
- * useful for Text if it has plenty of whitespace.
+ * useful for Text if it has plenty of whitespace.
* @param gradientRatio The size relative to the Picker height that the top and bottom gradients
- * take. These gradients blur the picker content on the top and bottom. The default is 0.33,
- * so the top 1/3 and the bottom 1/3 of the picker are taken by gradients. Should be between 0.0 and
- * 0.5. Use 0.0 to disable the gradient.
+ * take. These gradients blur the picker content on the top and bottom. The default is 0.33, so
+ * the top 1/3 and the bottom 1/3 of the picker are taken by gradients. Should be between 0.0 and
+ * 0.5. Use 0.0 to disable the gradient.
* @param gradientColor Should be the color outside of the Picker, so there is continuity.
* @param flingBehavior logic describing fling behavior.
* @param option A block which describes the content. Inside this block you can reference
- * [PickerScope.selectedOption] and other properties in [PickerScope]. When read-only mode is in
- * use on a screen, it is recommended that this content is given [Alignment.Center] in order to
- * align with the centrally selected Picker value.
+ * [PickerScope.selectedOption] and other properties in [PickerScope]. When read-only mode is in
+ * use on a screen, it is recommended that this content is given [Alignment.Center] in order to
+ * align with the centrally selected Picker value.
*/
@Suppress("DEPRECATION")
-@Deprecated("This overload is provided for backwards compatibility with Compose for Wear OS 1.1." +
- "A newer overload is available with additional userScrollEnabled parameter which improves " +
- "accessibility of [Picker].", level = DeprecationLevel.HIDDEN)
+@Deprecated(
+ "This overload is provided for backwards compatibility with Compose for Wear OS 1.1." +
+ "A newer overload is available with additional userScrollEnabled parameter which improves " +
+ "accessibility of [Picker].",
+ level = DeprecationLevel.HIDDEN
+)
@Composable
public fun Picker(
state: PickerState,
@@ -442,65 +444,69 @@
onSelected: () -> Unit = {},
scalingParams: androidx.wear.compose.material.ScalingParams = PickerDefaults.scalingParams(),
separation: Dp = 0.dp,
- @FloatRange(from = 0.0, to = 0.5)
- gradientRatio: Float = PickerDefaults.DefaultGradientRatio,
+ @FloatRange(from = 0.0, to = 0.5) gradientRatio: Float = PickerDefaults.DefaultGradientRatio,
gradientColor: Color = MaterialTheme.colors.background,
flingBehavior: FlingBehavior = PickerDefaults.flingBehavior(state),
option: @Composable PickerScope.(optionIndex: Int) -> Unit
-) = Picker(
- state = state,
- contentDescription = contentDescription,
- modifier = modifier,
- readOnly = readOnly,
- readOnlyLabel = readOnlyLabel,
- onSelected = onSelected,
- scalingParams = convertToDefaultFoundationScalingParams(scalingParams),
- separation = separation,
- gradientRatio = gradientRatio,
- gradientColor = gradientColor,
- flingBehavior = flingBehavior,
- userScrollEnabled = true,
- option = option
-)
+) =
+ Picker(
+ state = state,
+ contentDescription = contentDescription,
+ modifier = modifier,
+ readOnly = readOnly,
+ readOnlyLabel = readOnlyLabel,
+ onSelected = onSelected,
+ scalingParams = convertToDefaultFoundationScalingParams(scalingParams),
+ separation = separation,
+ gradientRatio = gradientRatio,
+ gradientColor = gradientColor,
+ flingBehavior = flingBehavior,
+ userScrollEnabled = true,
+ option = option
+ )
/**
- * A scrollable list of items to pick from. By default, items will be repeated
- * "infinitely" in both directions, unless [PickerState#repeatItems] is specified as false.
+ * A scrollable list of items to pick from. By default, items will be repeated "infinitely" in both
+ * directions, unless [PickerState#repeatItems] is specified as false.
*
* Example of a simple picker to select one of five options:
+ *
* @sample androidx.wear.compose.material.samples.SimplePicker
*
* Example of dual pickers, where clicking switches which one is editable and which is read-only:
+ *
* @sample androidx.wear.compose.material.samples.DualPicker
*
* @param state The state of the component
* @param modifier Modifier to be applied to the Picker
* @param readOnly Determines whether the Picker should display other available options for this
- * field, inviting the user to scroll to change the value. When readOnly = true,
- * only displays the currently selected option (and optionally a label). This is intended to be
- * used for screens that display multiple Pickers, only one of which has the focus at a time.
- * @param readOnlyLabel A slot for providing a label, displayed above the selected option
- * when the [Picker] is read-only. The label is overlaid with the currently selected
- * option within a Box, so it is recommended that the label is given [Alignment.TopCenter].
+ * field, inviting the user to scroll to change the value. When readOnly = true, only displays the
+ * currently selected option (and optionally a label). This is intended to be used for screens
+ * that display multiple Pickers, only one of which has the focus at a time.
+ * @param readOnlyLabel A slot for providing a label, displayed above the selected option when the
+ * [Picker] is read-only. The label is overlaid with the currently selected option within a Box,
+ * so it is recommended that the label is given [Alignment.TopCenter].
* @param scalingParams The parameters to configure the scaling and transparency effects for the
- * component. See [ScalingParams]
+ * component. See [ScalingParams]
* @param separation The amount of separation in [Dp] between items. Can be negative, which can be
- * useful for Text if it has plenty of whitespace.
+ * useful for Text if it has plenty of whitespace.
* @param gradientRatio The size relative to the Picker height that the top and bottom gradients
- * take. These gradients blur the picker content on the top and bottom. The default is 0.33,
- * so the top 1/3 and the bottom 1/3 of the picker are taken by gradients. Should be between 0.0 and
- * 0.5. Use 0.0 to disable the gradient.
+ * take. These gradients blur the picker content on the top and bottom. The default is 0.33, so
+ * the top 1/3 and the bottom 1/3 of the picker are taken by gradients. Should be between 0.0 and
+ * 0.5. Use 0.0 to disable the gradient.
* @param gradientColor Should be the color outside of the Picker, so there is continuity.
* @param flingBehavior logic describing fling behavior.
* @param option A block which describes the content. Inside this block you can reference
- * [PickerScope.selectedOption] and other properties in [PickerScope]. When read-only mode is in
- * use on a screen, it is recommended that this content is given [Alignment.Center] in order to
- * align with the centrally selected Picker value.
+ * [PickerScope.selectedOption] and other properties in [PickerScope]. When read-only mode is in
+ * use on a screen, it is recommended that this content is given [Alignment.Center] in order to
+ * align with the centrally selected Picker value.
*/
@Suppress("DEPRECATION")
-@Deprecated("This overload is provided for backwards compatibility with Compose for Wear OS 1.0." +
- "A newer overload is available with additional contentDescription, onSelected and " +
- "userScrollEnabled parameters, which improves accessibility of [Picker].")
+@Deprecated(
+ "This overload is provided for backwards compatibility with Compose for Wear OS 1.0." +
+ "A newer overload is available with additional contentDescription, onSelected and " +
+ "userScrollEnabled parameters, which improves accessibility of [Picker]."
+)
@Composable
public fun Picker(
state: PickerState,
@@ -509,35 +515,29 @@
readOnlyLabel: @Composable (BoxScope.() -> Unit)? = null,
scalingParams: androidx.wear.compose.material.ScalingParams = PickerDefaults.scalingParams(),
separation: Dp = 0.dp,
- @FloatRange(from = 0.0, to = 0.5)
- gradientRatio: Float = PickerDefaults.DefaultGradientRatio,
+ @FloatRange(from = 0.0, to = 0.5) gradientRatio: Float = PickerDefaults.DefaultGradientRatio,
gradientColor: Color = MaterialTheme.colors.background,
flingBehavior: FlingBehavior = PickerDefaults.flingBehavior(state),
option: @Composable PickerScope.(optionIndex: Int) -> Unit
-) = Picker(
- state = state,
- contentDescription = null,
- modifier = modifier,
- readOnly = readOnly,
- readOnlyLabel = readOnlyLabel,
- scalingParams = convertToDefaultFoundationScalingParams(scalingParams),
- separation = separation,
- gradientRatio = gradientRatio,
- gradientColor = gradientColor,
- flingBehavior = flingBehavior,
- userScrollEnabled = true,
- option = option
-)
+) =
+ Picker(
+ state = state,
+ contentDescription = null,
+ modifier = modifier,
+ readOnly = readOnly,
+ readOnlyLabel = readOnlyLabel,
+ scalingParams = convertToDefaultFoundationScalingParams(scalingParams),
+ separation = separation,
+ gradientRatio = gradientRatio,
+ gradientColor = gradientColor,
+ flingBehavior = flingBehavior,
+ userScrollEnabled = true,
+ option = option
+ )
// Apply a shim on the top and bottom of the Picker to hide all but the selected option.
-private fun ContentDrawScope.drawShim(
- gradientColor: Color,
- height: Float
-) {
- drawRect(
- color = gradientColor,
- size = Size(size.width, height)
- )
+private fun ContentDrawScope.drawShim(gradientColor: Color, height: Float) {
+ drawRect(color = gradientColor, size = Size(size.width, height))
drawRect(
color = gradientColor,
topLeft = Offset(0f, size.height - height),
@@ -546,10 +546,7 @@
}
// Apply a fade-out gradient on the top and bottom of the Picker.
-private fun ContentDrawScope.drawGradient(
- gradientColor: Color,
- gradientRatio: Float
-) {
+private fun ContentDrawScope.drawGradient(gradientColor: Color, gradientRatio: Float) {
drawRect(
Brush.linearGradient(
colors = listOf(gradientColor, Color.Transparent),
@@ -578,7 +575,8 @@
initialNumberOfOptions: Int,
initiallySelectedOption: Int = 0,
repeatItems: Boolean = true
-): PickerState = rememberSaveable(
+): PickerState =
+ rememberSaveable(
initialNumberOfOptions,
initiallySelectedOption,
repeatItems,
@@ -597,7 +595,8 @@
* @param repeatItems if true (the default), the contents of the component will be repeated
*/
@Stable
-public class PickerState constructor(
+public class PickerState
+constructor(
/*@IntRange(from = 1)*/
initialNumberOfOptions: Int,
initiallySelectedOption: Int = 0,
@@ -615,11 +614,12 @@
verifyNumberOfOptions(newNumberOfOptions)
// We need to maintain the mapping between the currently selected item and the
// currently selected option.
- optionsOffset = positiveModulo(
- selectedOption.coerceAtMost(newNumberOfOptions - 1) -
- scalingLazyListState.centerItemIndex,
- newNumberOfOptions
- )
+ optionsOffset =
+ positiveModulo(
+ selectedOption.coerceAtMost(newNumberOfOptions - 1) -
+ scalingLazyListState.centerItemIndex,
+ newNumberOfOptions
+ )
_numberOfOptions = newNumberOfOptions
}
@@ -638,15 +638,10 @@
internal val scalingLazyListState = run {
val repeats = if (repeatItems) LARGE_NUMBER_OF_ITEMS / numberOfOptions else 1
val centerOffset = numberOfOptions * (repeats / 2)
- ScalingLazyListState(
- centerOffset + initiallySelectedOption,
- 0
- )
+ ScalingLazyListState(centerOffset + initiallySelectedOption, 0)
}
- /**
- * Index of the option selected (i.e., at the center)
- */
+ /** Index of the option selected (i.e., at the center) */
public val selectedOption: Int
get() = (scalingLazyListState.centerItemIndex + optionsOffset) % numberOfOptions
@@ -664,14 +659,11 @@
/**
* Animate (smooth scroll) to the given item at [index]
*
- * A smooth scroll always happens to the closest item if PickerState has repeatItems=true.
- * For example, picker values are :
- * 0 1 2 3 0 1 2 [3] 0 1 2 3
- * Target value is [0].
- * 0 1 2 3 >0< 1 2 [3] >0< 1 2 3
- * Picker can be scrolled forwards or backwards. To get to the target 0 it requires 1 step to
- * scroll forwards and 3 steps to scroll backwards. Picker will be scrolled forwards
- * as this is the closest destination.
+ * A smooth scroll always happens to the closest item if PickerState has repeatItems=true. For
+ * example, picker values are : 0 1 2 3 0 1 2 [3] 0 1 2 3 Target value is [0]. 0 1 2 3 >0< 1 2
+ * [3] >0< 1 2 3 Picker can be scrolled forwards or backwards. To get to the target 0 it
+ * requires 1 step to scroll forwards and 3 steps to scroll backwards. Picker will be scrolled
+ * forwards as this is the closest destination.
*
* If the distance between possible targets is the same, picker will be scrolled backwards.
*
@@ -684,25 +676,18 @@
}
public companion object {
- /**
- * The default [Saver] implementation for [PickerState].
- */
- val Saver = listSaver<PickerState, Any?>(
- save = {
- listOf(
- it.numberOfOptions,
- it.selectedOption,
- it.repeatItems
- )
- },
- restore = { saved ->
- PickerState(
- initialNumberOfOptions = saved[0] as Int,
- initiallySelectedOption = saved[1] as Int,
- repeatItems = saved[2] as Boolean
- )
- }
- )
+ /** The default [Saver] implementation for [PickerState]. */
+ val Saver =
+ listSaver<PickerState, Any?>(
+ save = { listOf(it.numberOfOptions, it.selectedOption, it.repeatItems) },
+ restore = { saved ->
+ PickerState(
+ initialNumberOfOptions = saved[0] as Int,
+ initiallySelectedOption = saved[1] as Int,
+ repeatItems = saved[2] as Boolean
+ )
+ }
+ )
}
public override suspend fun scroll(
@@ -725,9 +710,7 @@
override val canScrollBackward: Boolean
get() = scalingLazyListState.canScrollBackward
- /**
- * Function which calculates the real position of an option
- */
+ /** Function which calculates the real position of an option */
private fun getClosestTargetItemIndex(option: Int): Int =
if (!repeatItems) {
option
@@ -749,9 +732,7 @@
}
}
-/**
- * Contains the default values used by [Picker]
- */
+/** Contains the default values used by [Picker] */
public object PickerDefaults {
/**
@@ -762,11 +743,12 @@
@Deprecated(
"This overload is provided for backwards compatibility with Compose for" +
" Wear OS 1.1 and was deprecated. Use [defaultScalingParams] instead",
- replaceWith = ReplaceWith(
- "PickerDefaults.defaultScalingParams(edgeScale," +
- " edgeAlpha, minElementHeight, maxElementHeight, minTransitionArea, " +
- "maxTransitionArea, scaleInterpolator, viewportVerticalOffsetResolver)"
- ),
+ replaceWith =
+ ReplaceWith(
+ "PickerDefaults.defaultScalingParams(edgeScale," +
+ " edgeAlpha, minElementHeight, maxElementHeight, minTransitionArea, " +
+ "maxTransitionArea, scaleInterpolator, viewportVerticalOffsetResolver)"
+ ),
level = DeprecationLevel.WARNING
)
public fun scalingParams(
@@ -841,67 +823,54 @@
public val DefaultGradientRatio = 0.33f
}
-/**
- * Receiver scope which is used by [Picker].
- */
+/** Receiver scope which is used by [Picker]. */
public interface PickerScope {
- /**
- * Index of the item selected (i.e., at the center)
- */
+ /** Index of the item selected (i.e., at the center) */
public val selectedOption: Int
}
private fun positiveModulo(n: Int, mod: Int) = ((n % mod) + mod) % mod
private fun convertToDefaultFoundationScalingParams(
- @Suppress("DEPRECATION")
- scalingParams: androidx.wear.compose.material.ScalingParams
-): ScalingParams = PickerDefaults.defaultScalingParams(
- edgeScale = scalingParams.edgeScale,
- edgeAlpha = scalingParams.edgeAlpha,
- minElementHeight = scalingParams.minElementHeight,
- maxElementHeight = scalingParams.maxElementHeight,
- minTransitionArea = scalingParams.minTransitionArea,
- maxTransitionArea = scalingParams.maxTransitionArea,
- scaleInterpolator = scalingParams.scaleInterpolator,
- viewportVerticalOffsetResolver = { viewportConstraints ->
- scalingParams.resolveViewportVerticalOffset(viewportConstraints)
- }
-)
+ @Suppress("DEPRECATION") scalingParams: androidx.wear.compose.material.ScalingParams
+): ScalingParams =
+ PickerDefaults.defaultScalingParams(
+ edgeScale = scalingParams.edgeScale,
+ edgeAlpha = scalingParams.edgeAlpha,
+ minElementHeight = scalingParams.minElementHeight,
+ maxElementHeight = scalingParams.maxElementHeight,
+ minTransitionArea = scalingParams.minTransitionArea,
+ maxTransitionArea = scalingParams.maxTransitionArea,
+ scaleInterpolator = scalingParams.scaleInterpolator,
+ viewportVerticalOffsetResolver = { viewportConstraints ->
+ scalingParams.resolveViewportVerticalOffset(viewportConstraints)
+ }
+ )
-/**
- * An extension function for creating [RotarySnapLayoutInfoProvider] from [Picker]
- */
+/** An extension function for creating [RotarySnapLayoutInfoProvider] from [Picker] */
@OptIn(ExperimentalWearFoundationApi::class)
@Composable
-internal fun PickerState.toRotarySnapLayoutInfoProvider():
- RotarySnapLayoutInfoProvider =
+internal fun PickerState.toRotarySnapLayoutInfoProvider(): RotarySnapLayoutInfoProvider =
remember(this) { PickerRotarySnapLayoutInfoProvider(this) }
-/**
- * An implementation of RotaryScrollableAdapter for [Picker]
- */
+/** An implementation of RotaryScrollableAdapter for [Picker] */
@ExperimentalWearFoundationApi
-internal class PickerRotarySnapLayoutInfoProvider(
- private val scrollableState: PickerState
-) : RotarySnapLayoutInfoProvider {
+internal class PickerRotarySnapLayoutInfoProvider(private val scrollableState: PickerState) :
+ RotarySnapLayoutInfoProvider {
- /**
- * Returns a height of a first item, as all items in picker have the same height.
- */
+ /** Returns a height of a first item, as all items in picker have the same height. */
override val averageItemSize: Float
- get() = scrollableState.scalingLazyListState
- .layoutInfo.visibleItemsInfo.firstOrNull()?.unadjustedSize?.toFloat() ?: 0f
+ get() =
+ scrollableState.scalingLazyListState.layoutInfo.visibleItemsInfo
+ .firstOrNull()
+ ?.unadjustedSize
+ ?.toFloat() ?: 0f
- /**
- * Current (centred) item index
- */
+ /** Current (centred) item index */
override val currentItemIndex: Int
get() = scrollableState.scalingLazyListState.centerItemIndex
- /**
- * An offset from the item centre
- */
+ /** An offset from the item centre */
override val currentItemOffset: Float
get() = scrollableState.scalingLazyListState.centerItemScrollOffset.toFloat()
@@ -910,9 +879,7 @@
}
@Stable
-private class PickerScopeImpl(
- private val pickerState: PickerState
-) : PickerScope {
+private class PickerScopeImpl(private val pickerState: PickerState) : PickerScope {
override val selectedOption: Int
get() = pickerState.selectedOption
}
diff --git a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/PickerGroup.kt b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/PickerGroup.kt
index 1b56621..ae19370 100644
--- a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/PickerGroup.kt
+++ b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/PickerGroup.kt
@@ -50,38 +50,39 @@
/**
* A group of [Picker]s to build components where multiple pickers are required to be combined
- * together.
- * The component maintains the focus between different [Picker]s by using [PickerGroupState]. It can
- * be handled from outside the component using the same instance and its properties.
- * When touch exploration services are enabled, the focus moves to the picker which is clicked. To
- * handle clicks in a different manner, use the [onSelected] lambda to control the focus of talkback
- * and actual focus.
+ * together. The component maintains the focus between different [Picker]s by using
+ * [PickerGroupState]. It can be handled from outside the component using the same instance and its
+ * properties. When touch exploration services are enabled, the focus moves to the picker which is
+ * clicked. To handle clicks in a different manner, use the [onSelected] lambda to control the focus
+ * of talkback and actual focus.
*
* It is recommended to ensure that a [Picker] in non read only mode should have user scroll enabled
* when touch exploration services are running.
*
* Example of a sample picker group with an hour and minute picker (24 hour format)
+ *
* @sample androidx.wear.compose.material.samples.PickerGroup24Hours
*
* Example of an auto centering picker group where the total width exceeds screen's width
+ *
* @sample androidx.wear.compose.material.samples.AutoCenteringPickerGroup
*
- * @param pickers List of [Picker]s represented using [PickerGroupItem] in the same order of
- * display from left to right.
+ * @param pickers List of [Picker]s represented using [PickerGroupItem] in the same order of display
+ * from left to right.
* @param modifier Modifier to be applied to the PickerGroup
* @param pickerGroupState The state of the component
* @param onSelected Action triggered when one of the [Picker] is selected inside the group
* @param autoCenter Indicates whether the selected [Picker] should be centered on the screen. It is
- * recommended to set this as true when all the pickers cannot be fit into the screen. Or provide a
- * mechanism to navigate to pickers which are not visible on screen. If false, the whole row
- * containing pickers would be centered.
+ * recommended to set this as true when all the pickers cannot be fit into the screen. Or provide
+ * a mechanism to navigate to pickers which are not visible on screen. If false, the whole row
+ * containing pickers would be centered.
* @param propagateMinConstraints Whether the incoming min constraints should be passed to content.
* @param touchExplorationStateProvider A [TouchExplorationStateProvider] to provide the current
- * state of touch exploration service. This will be used to determine how the PickerGroup and
- * talkback focus behaves/reacts to click and scroll events.
+ * state of touch exploration service. This will be used to determine how the PickerGroup and
+ * talkback focus behaves/reacts to click and scroll events.
* @param separator A composable block which describes the separator between different [Picker]s.
- * The integer parameter to the composable depicts the index where it will be kept. For example, 0
- * would represent the separator between the first and second picker.
+ * The integer parameter to the composable depicts the index where it will be kept. For example, 0
+ * would represent the separator between the first and second picker.
*/
@OptIn(ExperimentalWearFoundationApi::class)
@Composable
@@ -99,16 +100,15 @@
val touchExplorationServicesEnabled by touchExplorationStateProvider.touchExplorationState()
AutoCenteringRow(
- modifier = modifier
- .then(
+ modifier =
+ modifier.then(
// When touch exploration services are enabled, send the scroll events on the parent
// composable to selected picker
- if (touchExplorationServicesEnabled &&
- pickerGroupState.selectedIndex in pickers.indices
+ if (
+ touchExplorationServicesEnabled &&
+ pickerGroupState.selectedIndex in pickers.indices
) {
- Modifier.scrollablePicker(
- pickers[pickerGroupState.selectedIndex].pickerState
- )
+ Modifier.scrollablePicker(pickers[pickerGroupState.selectedIndex].pickerState)
} else {
Modifier
}
@@ -117,9 +117,9 @@
) {
// When no Picker is selected, provide an empty composable as a placeholder
// and tell the HierarchicalFocusCoordinator to clear the focus.
- HierarchicalFocusCoordinator(requiresFocus = {
- !pickers.indices.contains(pickerGroupState.selectedIndex)
- }) {}
+ HierarchicalFocusCoordinator(
+ requiresFocus = { !pickers.indices.contains(pickerGroupState.selectedIndex) }
+ ) {}
pickers.forEachIndexed { index, pickerData ->
val pickerSelected = index == pickerGroupState.selectedIndex
val flingBehavior = PickerDefaults.flingBehavior(state = pickerData.pickerState)
@@ -129,15 +129,17 @@
state = pickerData.pickerState,
contentDescription = pickerData.contentDescription,
readOnly = !pickerSelected,
- modifier = pickerData.modifier
- .then(
- // If auto center is enabled, apply auto centering modifier on selected
- // picker to center it
- if (pickerSelected && autoCenter) Modifier.autoCenteringTarget()
- else Modifier
- )
- // Do not need focusable as it's already set in ScalingLazyColumn
- .focusRequester(focusRequester),
+ modifier =
+ pickerData.modifier
+ .then(
+ // If auto center is enabled, apply auto centering modifier on
+ // selected
+ // picker to center it
+ if (pickerSelected && autoCenter) Modifier.autoCenteringTarget()
+ else Modifier
+ )
+ // Do not need focusable as it's already set in ScalingLazyColumn
+ .focusRequester(focusRequester),
readOnlyLabel = pickerData.readOnlyLabel,
flingBehavior = flingBehavior,
onSelected = pickerData.onSelected,
@@ -147,19 +149,21 @@
Box(
if (touchExplorationServicesEnabled || pickerSelected) {
Modifier
- } else Modifier.pointerInput(Unit) {
- coroutineScope {
- // Keep looking for touch events on the picker if it is not
- // selected
- while (true) {
- awaitEachGesture {
- awaitFirstDown(requireUnconsumed = false)
- pickerGroupState.selectedIndex = index
- onSelected(index)
+ } else
+ Modifier.pointerInput(Unit) {
+ coroutineScope {
+ // Keep looking for touch events on the picker if it is
+ // not
+ // selected
+ while (true) {
+ awaitEachGesture {
+ awaitFirstDown(requireUnconsumed = false)
+ pickerGroupState.selectedIndex = index
+ onSelected(index)
+ }
}
}
}
- }
) {
option(optionIndex, pickerSelected)
}
@@ -180,42 +184,30 @@
* @param initiallySelectedIndex the picker index that will be initially focused
*/
@Composable
-public fun rememberPickerGroupState(
- initiallySelectedIndex: Int = 0
-): PickerGroupState = rememberSaveable(
- initiallySelectedIndex,
- saver = PickerGroupState.Saver
-) {
- PickerGroupState(initiallySelectedIndex)
-}
+public fun rememberPickerGroupState(initiallySelectedIndex: Int = 0): PickerGroupState =
+ rememberSaveable(initiallySelectedIndex, saver = PickerGroupState.Saver) {
+ PickerGroupState(initiallySelectedIndex)
+ }
/**
* A state object that can be used to observe the selected [Picker].
*
* @param initiallySelectedIndex the picker index that will be initially selected
*/
-public class PickerGroupState constructor(
+public class PickerGroupState
+constructor(
initiallySelectedIndex: Int = 0,
) {
- /**
- * The current selected [Picker] index.
- */
+ /** The current selected [Picker] index. */
var selectedIndex by mutableIntStateOf(initiallySelectedIndex)
public companion object {
- val Saver = listSaver<PickerGroupState, Any?>(
- save = {
- listOf(
- it.selectedIndex
- )
- },
- restore = { saved ->
- PickerGroupState(
- initiallySelectedIndex = saved[0] as Int
- )
- }
- )
+ val Saver =
+ listSaver<PickerGroupState, Any?>(
+ save = { listOf(it.selectedIndex) },
+ restore = { saved -> PickerGroupState(initiallySelectedIndex = saved[0] as Int) }
+ )
}
}
@@ -224,19 +216,19 @@
*
* @param pickerState The state of the picker
* @param modifier Modifier to be applied to the Picker
- * @param contentDescription Text used by accessibility services to describe what the
- * selected option represents. This text should be localized, such as by using
- * [androidx.compose.ui.res.stringResource] or similar. Typically, the content description is
- * inferred via derivedStateOf to avoid unnecessary recompositions, like this:
- * val description by remember { derivedStateOf { /* expression using state.selectedOption */ } }
+ * @param contentDescription Text used by accessibility services to describe what the selected
+ * option represents. This text should be localized, such as by using
+ * [androidx.compose.ui.res.stringResource] or similar. Typically, the content description is
+ * inferred via derivedStateOf to avoid unnecessary recompositions, like this: val description by
+ * remember { derivedStateOf { /* expression using state.selectedOption */ } }
* @param focusRequester Optional [FocusRequester] for the [Picker]. If not provided, a local
- * instance of [FocusRequester] will be created to handle the focus between different pickers
+ * instance of [FocusRequester] will be created to handle the focus between different pickers
* @param onSelected Action triggered when the Picker is selected by clicking
- * @param readOnlyLabel A slot for providing a label, displayed above the selected option
- * when the [Picker] is read-only. The label is overlaid with the currently selected
- * option within a Box, so it is recommended that the label is given [Alignment.TopCenter].
+ * @param readOnlyLabel A slot for providing a label, displayed above the selected option when the
+ * [Picker] is read-only. The label is overlaid with the currently selected option within a Box,
+ * so it is recommended that the label is given [Alignment.TopCenter].
* @param option A block which describes the content. The integer parameter to the composable
- * denotes the index of the option and boolean denotes whether the picker is selected or not.
+ * denotes the index of the option and boolean denotes whether the picker is selected or not.
*/
public class PickerGroupItem(
val pickerState: PickerState,
@@ -263,16 +255,16 @@
Layout(modifier = modifier, content = content) { measurables, parentConstraints ->
// Reset the min width and height of the constraints used to measure child composables
// if min constraints are not supposed to propagated.
- val constraints = if (propagateMinConstraints) {
- parentConstraints
- } else {
- parentConstraints.copy(minWidth = 0, minHeight = 0)
- }
+ val constraints =
+ if (propagateMinConstraints) {
+ parentConstraints
+ } else {
+ parentConstraints.copy(minWidth = 0, minHeight = 0)
+ }
val placeables = measurables.fastMap { it.measure(constraints) }
val centeringOffset = computeCenteringOffset(placeables)
val rowWidth =
- if (constraints.hasBoundedWidth) constraints.maxWidth
- else constraints.minWidth
+ if (constraints.hasBoundedWidth) constraints.maxWidth else constraints.minWidth
val rowHeight = calculateHeight(constraints, placeables)
layout(width = rowWidth, height = rowHeight) {
var x = rowWidth / 2f - centeringOffset
@@ -288,9 +280,7 @@
* A scrollable modifier which can be applied on a composable to propagate the scrollable events to
* the specified [Picker] defined by the [PickerState].
*/
-private fun Modifier.scrollablePicker(
- pickerState: PickerState
-) = composed {
+private fun Modifier.scrollablePicker(pickerState: PickerState) = composed {
this.scrollable(
state = pickerState,
orientation = Orientation.Vertical,
@@ -328,11 +318,12 @@
return maxChildrenHeight.coerceIn(constraints.minHeight, constraints.maxHeight)
}
-internal fun Modifier.autoCenteringTarget() = this.then(
- object : ParentDataModifier {
- override fun Density.modifyParentData(parentData: Any?) = AutoCenteringRowParentData()
- }
-)
+internal fun Modifier.autoCenteringTarget() =
+ this.then(
+ object : ParentDataModifier {
+ override fun Density.modifyParentData(parentData: Any?) = AutoCenteringRowParentData()
+ }
+ )
internal class AutoCenteringRowParentData
diff --git a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/Placeholder.kt b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/Placeholder.kt
index 3f8d608..67c66bb 100644
--- a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/Placeholder.kt
+++ b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/Placeholder.kt
@@ -71,19 +71,20 @@
* that needs to be displayed in a component is not yet available, e.g. it is loading
* asynchronously.
*
- * A [PlaceholderState] should be created for each component that has placeholder data. The
- * state is used to coordinate all of the different placeholder effects and animations.
+ * A [PlaceholderState] should be created for each component that has placeholder data. The state is
+ * used to coordinate all of the different placeholder effects and animations.
*
- * Placeholder has a number of different effects designed to work together.
- * [Modifier.placeholder] draws a placeholder shape on top of content that is waiting to load. There
- * can be multiple placeholders in a component.
- * [Modifier.placeholderShimmer] does a shimmer animation over the whole component that includes the
- * placeholders. There should only be one placeholderShimmer for each component.
+ * Placeholder has a number of different effects designed to work together. [Modifier.placeholder]
+ * draws a placeholder shape on top of content that is waiting to load. There can be multiple
+ * placeholders in a component. [Modifier.placeholderShimmer] does a shimmer animation over the
+ * whole component that includes the placeholders. There should only be one placeholderShimmer for
+ * each component.
*
* NOTE: The order of modifiers is important. If you are adding both [Modifier.placeholder] and
* [Modifier.placeholderShimmer] to the same composable then the shimmer must be before in the
* modifier chain. Example of [Text] composable with both placeholderShimmer and placeholder
* modifiers.
+ *
* @sample androidx.wear.compose.material.samples.TextPlaceholder
*
* Background placeholder effects are used to mask the background of components like chips and cards
@@ -97,7 +98,8 @@
*/
@ExperimentalWearMaterialApi
@Stable
-public class PlaceholderState internal constructor(
+public class PlaceholderState
+internal constructor(
private val isContentReady: State<() -> Boolean>,
private val maxScreenDimension: Float,
private val isReduceMotionEnabled: Boolean
@@ -117,16 +119,12 @@
*/
internal var backgroundOffset: Offset = Offset.Zero
- /**
- * Start the animation of the placeholder state.
- */
+ /** Start the animation of the placeholder state. */
public suspend fun startPlaceholderAnimation() {
if (!isReduceMotionEnabled) {
coroutineScope {
while (isActive) {
- withInfiniteAnimationFrameMillis {
- frameMillis.longValue = it
- }
+ withInfiniteAnimationFrameMillis { frameMillis.longValue = it }
}
}
}
@@ -146,10 +144,11 @@
* [PLACEHOLDER_WIPE_OFF_PROGRESSION_DURATION_MS]
*/
internal val placeholderWipeOffProgression: Float by derivedStateOf {
- val absoluteProgression = ((frameMillis.longValue - startOfWipeOffAnimation).coerceAtMost(
- PLACEHOLDER_WIPE_OFF_PROGRESSION_DURATION_MS
- ).toFloat() /
- PLACEHOLDER_WIPE_OFF_PROGRESSION_DURATION_MS).coerceAtMost(1f)
+ val absoluteProgression =
+ ((frameMillis.longValue - startOfWipeOffAnimation)
+ .coerceAtMost(PLACEHOLDER_WIPE_OFF_PROGRESSION_DURATION_MS)
+ .toFloat() / PLACEHOLDER_WIPE_OFF_PROGRESSION_DURATION_MS)
+ .coerceAtMost(1f)
val easedProgression = wipeOffInterpolator.transform(absoluteProgression)
lerp(-maxScreenDimension * 1.75f, maxScreenDimension * 0.75f, easedProgression)
}
@@ -161,20 +160,19 @@
*
* The progression represents the x and y coordinates in pixels of the Top|Left part of the
* gradient that flows across the screen. The progression will start at -maxScreenDimension (max
- * of height/width to create a 45 degree angle) and progress to the
- * maximumScreenDimension.
+ * of height/width to create a 45 degree angle) and progress to the maximumScreenDimension.
*
* The time taken for this progression is [PLACEHOLDER_WIPE_OFF_PROGRESSION_ALPHA_DURATION_MS]
*/
@ExperimentalWearMaterialApi
internal val placeholderWipeOffAlpha: Float by derivedStateOf {
- val absoluteProgression = ((frameMillis.longValue - startOfWipeOffAnimation).coerceAtMost(
- PLACEHOLDER_WIPE_OFF_PROGRESSION_ALPHA_DURATION_MS
- ).toFloat() /
- PLACEHOLDER_WIPE_OFF_PROGRESSION_ALPHA_DURATION_MS).coerceAtMost(1f)
+ val absoluteProgression =
+ ((frameMillis.longValue - startOfWipeOffAnimation)
+ .coerceAtMost(PLACEHOLDER_WIPE_OFF_PROGRESSION_ALPHA_DURATION_MS)
+ .toFloat() / PLACEHOLDER_WIPE_OFF_PROGRESSION_ALPHA_DURATION_MS)
+ .coerceAtMost(1f)
- val alpha =
- lerp(0f, 1f, absoluteProgression)
+ val alpha = lerp(0f, 1f, absoluteProgression)
wipeOffInterpolator.transform(alpha)
}
@@ -187,9 +185,10 @@
@ExperimentalWearMaterialApi
public val placeholderProgression: Float by derivedStateOf {
val absoluteProgression =
- (frameMillis.longValue.mod(PLACEHOLDER_SHIMMER_GAP_BETWEEN_ANIMATION_LOOPS_MS)
- .coerceAtMost(PLACEHOLDER_SHIMMER_DURATION_MS).toFloat() /
- PLACEHOLDER_SHIMMER_DURATION_MS)
+ (frameMillis.longValue
+ .mod(PLACEHOLDER_SHIMMER_GAP_BETWEEN_ANIMATION_LOOPS_MS)
+ .coerceAtMost(PLACEHOLDER_SHIMMER_DURATION_MS)
+ .toFloat() / PLACEHOLDER_SHIMMER_DURATION_MS)
val easedProgression = progressionInterpolator.transform(absoluteProgression)
lerp(-maxScreenDimension * 0.5f, maxScreenDimension * 1.5f, easedProgression)
}
@@ -202,29 +201,29 @@
@ExperimentalWearMaterialApi
internal val placeholderShimmerAlpha: Float by derivedStateOf {
val absoluteProgression =
- (frameMillis.longValue.mod(PLACEHOLDER_SHIMMER_GAP_BETWEEN_ANIMATION_LOOPS_MS)
- .coerceAtMost(PLACEHOLDER_SHIMMER_DURATION_MS).toFloat() /
- PLACEHOLDER_SHIMMER_DURATION_MS)
+ (frameMillis.longValue
+ .mod(PLACEHOLDER_SHIMMER_GAP_BETWEEN_ANIMATION_LOOPS_MS)
+ .coerceAtMost(PLACEHOLDER_SHIMMER_DURATION_MS)
+ .toFloat() / PLACEHOLDER_SHIMMER_DURATION_MS)
if (absoluteProgression <= 0.5f) {
- val alpha =
- lerp(0f, 0.15f, absoluteProgression * 2f)
+ val alpha = lerp(0f, 0.15f, absoluteProgression * 2f)
progressionInterpolator.transform(alpha)
} else {
- val alpha =
- lerp(0.15f, 0f, (absoluteProgression - 0.5f) * 2f)
+ val alpha = lerp(0.15f, 0f, (absoluteProgression - 0.5f) * 2f)
progressionInterpolator.transform(alpha)
}
}
/**
* The current value of the placeholder visual effect gradient progression alpha/opacity during
- * the fade-in part of reset placeholder animation. This allows the effect to be faded in
- * during the [PLACEHOLDER_RESET_ANIMATION_DURATION].
+ * the fade-in part of reset placeholder animation. This allows the effect to be faded in during
+ * the [PLACEHOLDER_RESET_ANIMATION_DURATION].
*/
internal val resetPlaceholderFadeInAlpha: Float by derivedStateOf {
val absoluteProgression =
- (frameMillis.longValue - startOfResetAnimation - RAPID).coerceAtMost(QUICK.toLong())
+ (frameMillis.longValue - startOfResetAnimation - RAPID)
+ .coerceAtMost(QUICK.toLong())
.toFloat() / QUICK.toFloat()
if (absoluteProgression < 0f) {
0f
@@ -241,8 +240,8 @@
*/
internal val resetPlaceholderFadeOutAlpha: Float by derivedStateOf {
val absoluteProgression =
- (frameMillis.longValue - startOfResetAnimation).coerceAtMost(RAPID.toLong())
- .toFloat() / RAPID.toFloat()
+ (frameMillis.longValue - startOfResetAnimation).coerceAtMost(RAPID.toLong()).toFloat() /
+ RAPID.toFloat()
val alpha = lerp(1f, 0f, absoluteProgression)
resetFadeOutInterpolator.transform(alpha)
}
@@ -259,64 +258,67 @@
* Should only be called when [isShowContent] is false. Returns true if the wipe-off effect that
* reveals content should be shown and false if the placeholder effect should be shown.
*/
- public val isWipeOff: Boolean by derivedStateOf {
- placeholderStage == PlaceholderStage.WipeOff
- }
+ public val isWipeOff: Boolean by derivedStateOf { placeholderStage == PlaceholderStage.WipeOff }
/**
* The width of the gradient to use for the placeholder shimmer and wipe-off effects. This is
- * the value in pixels that should be used in either horizontal or vertical direction to
- * be equivalent to a gradient width of 2 x maxScreenDimension rotated through 45 degrees.
+ * the value in pixels that should be used in either horizontal or vertical direction to be
+ * equivalent to a gradient width of 2 x maxScreenDimension rotated through 45 degrees.
*/
- internal val gradientXYWidth: Float by derivedStateOf {
- maxScreenDimension * 2f.pow(1.5f)
- }
+ internal val gradientXYWidth: Float by derivedStateOf { maxScreenDimension * 2f.pow(1.5f) }
internal var placeholderStage: PlaceholderStage =
if (isContentReady.value.invoke()) PlaceholderStage.ShowContent
else PlaceholderStage.ShowPlaceholder
- get() = derivedStateOf {
- if (field == PlaceholderStage.WipeOff || field == PlaceholderStage.ShowPlaceholder) {
- // WipeOff
- if (startOfWipeOffAnimation != 0L) {
- if ((frameMillis.longValue - startOfWipeOffAnimation) >=
- PLACEHOLDER_WIPE_OFF_PROGRESSION_DURATION_MS
+ get() =
+ derivedStateOf {
+ if (
+ field == PlaceholderStage.WipeOff ||
+ field == PlaceholderStage.ShowPlaceholder
) {
- field = PlaceholderStage.ShowContent
- }
- // Placeholder
- } else if (isContentReady.value()) {
- if (isReduceMotionEnabled) {
- field = PlaceholderStage.ShowContent
- } else {
- startOfWipeOffAnimation = frameMillis.longValue
- field = PlaceholderStage.WipeOff
- }
- }
- } else {
- if (!isContentReady.value()) {
- // Reset
- if (startOfResetAnimation != 0L) {
- if (frameMillis.longValue - startOfResetAnimation >=
- PLACEHOLDER_RESET_ANIMATION_DURATION
- ) {
- startOfResetAnimation = 0L
- field = PlaceholderStage.ShowPlaceholder
+ // WipeOff
+ if (startOfWipeOffAnimation != 0L) {
+ if (
+ (frameMillis.longValue - startOfWipeOffAnimation) >=
+ PLACEHOLDER_WIPE_OFF_PROGRESSION_DURATION_MS
+ ) {
+ field = PlaceholderStage.ShowContent
+ }
+ // Placeholder
+ } else if (isContentReady.value()) {
+ if (isReduceMotionEnabled) {
+ field = PlaceholderStage.ShowContent
+ } else {
+ startOfWipeOffAnimation = frameMillis.longValue
+ field = PlaceholderStage.WipeOff
+ }
}
} else {
- // ShowContent
- startOfWipeOffAnimation = 0L
- if (isReduceMotionEnabled) {
- field = PlaceholderStage.ShowPlaceholder
- } else {
- startOfResetAnimation = frameMillis.longValue
- field = PlaceholderStage.ResetContent
+ if (!isContentReady.value()) {
+ // Reset
+ if (startOfResetAnimation != 0L) {
+ if (
+ frameMillis.longValue - startOfResetAnimation >=
+ PLACEHOLDER_RESET_ANIMATION_DURATION
+ ) {
+ startOfResetAnimation = 0L
+ field = PlaceholderStage.ShowPlaceholder
+ }
+ } else {
+ // ShowContent
+ startOfWipeOffAnimation = 0L
+ if (isReduceMotionEnabled) {
+ field = PlaceholderStage.ShowPlaceholder
+ } else {
+ startOfResetAnimation = frameMillis.longValue
+ field = PlaceholderStage.ResetContent
+ }
+ }
}
}
+ field
}
- }
- field
- }.value
+ .value
/**
* The frame time in milliseconds in the calling context of frame dispatch. Used to coordinate
@@ -337,14 +339,14 @@
* Creates a [PlaceholderState] that is remembered across compositions. To start placeholder
* animations run [PlaceholderState.startPlaceholderAnimation].
*
- * A [PlaceholderState] should be created for each component that has placeholder data. The
- * state is used to coordinate all of the different placeholder effects and animations.
+ * A [PlaceholderState] should be created for each component that has placeholder data. The state is
+ * used to coordinate all of the different placeholder effects and animations.
*
- * Placeholder has a number of different effects designed to work together.
- * [Modifier.placeholder] draws a placeholder shape on top of content that is waiting to load. There
- * can be multiple placeholders in a component.
- * [Modifier.placeholderShimmer] does a shimmer animation over the whole component that includes the
- * placeholders. There should only be one placeholderShimmer for each component.
+ * Placeholder has a number of different effects designed to work together. [Modifier.placeholder]
+ * draws a placeholder shape on top of content that is waiting to load. There can be multiple
+ * placeholders in a component. [Modifier.placeholderShimmer] does a shimmer animation over the
+ * whole component that includes the placeholders. There should only be one placeholderShimmer for
+ * each component.
*
* Background placeholder effects are used to mask the background of components like chips and cards
* until all of the data has loaded. Use [PlaceholderDefaults.placeholderChipColors]
@@ -356,26 +358,17 @@
* and a wipe off animation will remove the placeholders to reveal the content.
*
* @param isContentReady a lambda to determine whether all of the data/content has been loaded for a
- * given component and is ready to be displayed.
+ * given component and is ready to be displayed.
*/
@OptIn(ExperimentalWearFoundationApi::class)
@ExperimentalWearMaterialApi
@Composable
-public fun rememberPlaceholderState(
- isContentReady: () -> Boolean
-): PlaceholderState {
- val maxScreenDimension = with(LocalDensity.current) {
- Dp(max(screenHeightDp(), screenWidthDp()).toFloat()).toPx()
- }
+public fun rememberPlaceholderState(isContentReady: () -> Boolean): PlaceholderState {
+ val maxScreenDimension =
+ with(LocalDensity.current) { Dp(max(screenHeightDp(), screenWidthDp()).toFloat()).toPx() }
val isReduceMotionEnabled = LocalReduceMotion.current.enabled()
val myLambdaState = rememberUpdatedState(isContentReady)
- return remember {
- PlaceholderState(
- myLambdaState,
- maxScreenDimension,
- isReduceMotionEnabled
- )
- }
+ return remember { PlaceholderState(myLambdaState, maxScreenDimension, isReduceMotionEnabled) }
}
/**
@@ -383,10 +376,12 @@
* the placeholder. Typically used whilst content is 'loading' and then 'revealed'.
*
* Example of a [Chip] with icon and a label that put placeholders over individual content slots:
+ *
* @sample androidx.wear.compose.material.samples.ChipWithIconAndLabelAndPlaceholders
*
* Example of a [Chip] with icon and a primary and secondary labels that draws another [Chip] over
* the top of it when waiting for placeholder data to load:
+ *
* @sample androidx.wear.compose.material.samples.ChipWithIconAndLabelsAndOverlaidPlaceholder
*
* The [placeholderState] determines when to 'show' and 'wipe off' the placeholder.
@@ -395,10 +390,11 @@
* [Modifier.placeholderShimmer] to the same composable then the shimmer must be first in the
* modifier chain. Example of [Text] composable with both placeholderShimmer and placeholder
* modifiers.
+ *
* @sample androidx.wear.compose.material.samples.TextPlaceholder
*
* @param placeholderState determines whether the placeholder is visible and controls animation
- * effects for the placeholder.
+ * effects for the placeholder.
* @param shape the shape to apply to the placeholder
* @param color the color of the placeholder.
*/
@@ -408,19 +404,23 @@
placeholderState: PlaceholderState,
shape: Shape = MaterialTheme.shapes.small,
color: Color =
- MaterialTheme.colors.onSurface.copy(alpha = 0.1f)
+ MaterialTheme.colors.onSurface
+ .copy(alpha = 0.1f)
.compositeOver(MaterialTheme.colors.surface)
-): Modifier = this then PlaceholderElement(
- placeholderState = placeholderState,
- color = color,
- shape = shape,
- inspectorInfo = debugInspectorInfo {
- name = "placeholder"
- properties["placeholderState"] = placeholderState
- properties["shape"] = shape
- properties["color"] = color
- }
-)
+): Modifier =
+ this then
+ PlaceholderElement(
+ placeholderState = placeholderState,
+ color = color,
+ shape = shape,
+ inspectorInfo =
+ debugInspectorInfo {
+ name = "placeholder"
+ properties["placeholderState"] = placeholderState
+ properties["shape"] = shape
+ properties["color"] = color
+ }
+ )
/**
* Modifier to draw a placeholder shimmer over a component. The placeholder shimmer is a 45 degree
@@ -428,23 +428,26 @@
* animation frame clock which orchestrates the shimmer so that every component will shimmer as the
* gradient progresses across the screen.
*
- * Example of a [Chip] with icon and a label that put placeholders over individual content slots
- * and then draws a placeholder shimmer over the result:
+ * Example of a [Chip] with icon and a label that put placeholders over individual content slots and
+ * then draws a placeholder shimmer over the result:
+ *
* @sample androidx.wear.compose.material.samples.ChipWithIconAndLabelAndPlaceholders
*
* Example of a [Chip] with icon and a primary and secondary labels that draws another [Chip] over
* the top of it when waiting for placeholder data to load and then draws a placeholder shimmer over
* the top:
+ *
* @sample androidx.wear.compose.material.samples.ChipWithIconAndLabelsAndOverlaidPlaceholder
*
* NOTE: The order of modifiers is important. If you are adding both [Modifier.placeholder] and
* [Modifier.placeholderShimmer] to the same composable then the shimmer must be before in the
* modifier chain. Example of [Text] composable with both placeholderShimmer and placeholder
* modifiers.
+ *
* @sample androidx.wear.compose.material.samples.TextPlaceholder
*
* @param placeholderState the current placeholder state that determine whether the placeholder
- * shimmer should be shown.
+ * shimmer should be shown.
* @param shape the shape of the component.
* @param color the color to use in the shimmer.
*/
@@ -455,33 +458,35 @@
placeholderState: PlaceholderState,
shape: Shape = MaterialTheme.shapes.small,
color: Color = MaterialTheme.colors.onSurface,
-): Modifier = this.then(
- if (LocalReduceMotion.current.enabled()) {
- Modifier
- } else {
- PlaceholderShimmerElement(
- placeholderState = placeholderState,
- color = color,
- shape = shape,
- inspectorInfo = debugInspectorInfo {
- name = "placeholderShimmer"
- properties["placeholderState"] = placeholderState
- properties["shape"] = shape
- properties["color"] = color
- }
- )
- }
-)
+): Modifier =
+ this.then(
+ if (LocalReduceMotion.current.enabled()) {
+ Modifier
+ } else {
+ PlaceholderShimmerElement(
+ placeholderState = placeholderState,
+ color = color,
+ shape = shape,
+ inspectorInfo =
+ debugInspectorInfo {
+ name = "placeholderShimmer"
+ properties["placeholderState"] = placeholderState
+ properties["shape"] = shape
+ properties["color"] = color
+ }
+ )
+ }
+ )
/**
* Contains the default values used for providing placeholders.
*
- * There are three distinct but coordinated aspects to placeholders in Compose for Wear OS.
- * Firstly placeholder [Modifier.placeholder] which is drawn over content that is not yet loaded.
- * Secondly a placeholder background which provides a background brush to cover the usual background
- * of containers such as [Chip] or [Card] until all of the content has loaded.
- * Thirdly a placeholder shimmer effect [Modifier.placeholderShimmer] effect which runs in an
- * animation loop while waiting for the data to load.
+ * There are three distinct but coordinated aspects to placeholders in Compose for Wear OS. Firstly
+ * placeholder [Modifier.placeholder] which is drawn over content that is not yet loaded. Secondly a
+ * placeholder background which provides a background brush to cover the usual background of
+ * containers such as [Chip] or [Card] until all of the content has loaded. Thirdly a placeholder
+ * shimmer effect [Modifier.placeholderShimmer] effect which runs in an animation loop while waiting
+ * for the data to load.
*/
@ExperimentalWearMaterialApi
public object PlaceholderDefaults {
@@ -489,15 +494,15 @@
/**
* Create a [ChipColors] that can be used in placeholder mode. This will provide the placeholder
* background effect that covers the normal chip background with a solid background of [color]
- * when the [placeholderState] is set to show the placeholder and a wipe off gradient
- * brush when the state is in wipe-off mode. If the state is
- * [PlaceholderState.isShowContent] then the normal background will be used. All other colors
- * will be delegated to [originalChipColors].
+ * when the [placeholderState] is set to show the placeholder and a wipe off gradient brush when
+ * the state is in wipe-off mode. If the state is [PlaceholderState.isShowContent] then the
+ * normal background will be used. All other colors will be delegated to [originalChipColors].
*
* Example of a [Chip] with icon and a label that put placeholders over individual content slots
- * and then draws a placeholder shimmer over the result and draws over the [Chip]s
- * normal background color with [color] as the placeholder background color which will be wiped
- * away once all of the placeholder data is loaded:
+ * and then draws a placeholder shimmer over the result and draws over the [Chip]s normal
+ * background color with [color] as the placeholder background color which will be wiped away
+ * once all of the placeholder data is loaded:
+ *
* @sample androidx.wear.compose.material.samples.ChipWithIconAndLabelAndPlaceholders
*
* @param originalChipColors the chip colors to use when not in placeholder mode.
@@ -512,23 +517,25 @@
): ChipColors {
return if (!placeholderState.isShowContent) {
ChipDefaults.chipColors(
- backgroundPainter = PlaceholderBackgroundPainter(
- painter = originalChipColors.background(enabled = true).value,
- placeholderState = placeholderState,
- color = color
- ),
+ backgroundPainter =
+ PlaceholderBackgroundPainter(
+ painter = originalChipColors.background(enabled = true).value,
+ placeholderState = placeholderState,
+ color = color
+ ),
contentColor = originalChipColors.contentColor(enabled = true).value,
- secondaryContentColor = originalChipColors
- .secondaryContentColor(enabled = true).value,
+ secondaryContentColor =
+ originalChipColors.secondaryContentColor(enabled = true).value,
iconColor = originalChipColors.iconColor(enabled = true).value,
- disabledBackgroundPainter = PlaceholderBackgroundPainter(
- painter = originalChipColors.background(enabled = false).value,
- placeholderState = placeholderState,
- color = color
- ),
+ disabledBackgroundPainter =
+ PlaceholderBackgroundPainter(
+ painter = originalChipColors.background(enabled = false).value,
+ placeholderState = placeholderState,
+ color = color
+ ),
disabledContentColor = originalChipColors.contentColor(enabled = false).value,
- disabledSecondaryContentColor = originalChipColors
- .secondaryContentColor(enabled = false).value,
+ disabledSecondaryContentColor =
+ originalChipColors.secondaryContentColor(enabled = false).value,
disabledIconColor = originalChipColors.iconColor(enabled = false).value,
)
} else {
@@ -537,14 +544,15 @@
}
/**
- * Create a [ChipColors] that can be used for a [Chip] that is used as a placeholder drawn
- * on top of another [Chip]. When not drawing a placeholder background brush the chip
- * will be transparent allowing the contents of the chip below to be displayed.
+ * Create a [ChipColors] that can be used for a [Chip] that is used as a placeholder drawn on
+ * top of another [Chip]. When not drawing a placeholder background brush the chip will be
+ * transparent allowing the contents of the chip below to be displayed.
*
* Example of a [Chip] with icon and a primary and secondary labels that draws another [Chip]
* over the top of it when waiting for placeholder data to load and draws over the [Chip]s
* normal background color with [color] as the placeholder background color which will be wiped
* away once all of the placeholder data is loaded:
+ *
* @sample androidx.wear.compose.material.samples.ChipWithIconAndLabelsAndOverlaidPlaceholder
*
* @param color the color to use for the placeholder background brush.
@@ -556,19 +564,21 @@
color: Color = MaterialTheme.colors.surface,
): ChipColors {
return ChipDefaults.chipColors(
- backgroundPainter = PlaceholderBackgroundPainter(
- painter = null,
- placeholderState = placeholderState,
- color = color
- ),
+ backgroundPainter =
+ PlaceholderBackgroundPainter(
+ painter = null,
+ placeholderState = placeholderState,
+ color = color
+ ),
contentColor = Color.Transparent,
secondaryContentColor = Color.Transparent,
iconColor = Color.Transparent,
- disabledBackgroundPainter = PlaceholderBackgroundPainter(
- painter = null,
- placeholderState = placeholderState,
- color = color
- ),
+ disabledBackgroundPainter =
+ PlaceholderBackgroundPainter(
+ painter = null,
+ placeholderState = placeholderState,
+ color = color
+ ),
disabledContentColor = Color.Transparent,
disabledSecondaryContentColor = Color.Transparent,
disabledIconColor = Color.Transparent,
@@ -576,11 +586,11 @@
}
/**
- * Create a [Painter] that wraps another painter and overlays a placeholder background brush
- * on top. If the [placeholderState] is [PlaceholderState.isShowContent] the original painter
- * will be used. Otherwise the [painter] will be drawn and then a placeholder background will be
- * drawn over it or a wipe-off brush will be used to reveal the background
- * when the state is [PlaceholderState.isWipeOff].
+ * Create a [Painter] that wraps another painter and overlays a placeholder background brush on
+ * top. If the [placeholderState] is [PlaceholderState.isShowContent] the original painter will
+ * be used. Otherwise the [painter] will be drawn and then a placeholder background will be
+ * drawn over it or a wipe-off brush will be used to reveal the background when the state is
+ * [PlaceholderState.isWipeOff].
*
* @param placeholderState the state of the placeholder
* @param painter the original painter that will be drawn over when in placeholder mode.
@@ -604,10 +614,10 @@
}
/**
- * Create a [Painter] that paints with a placeholder background brush.
- * If the [placeholderState] is [PlaceholderState.isShowContent] then a transparent background
- * will be shown. Otherwise a placeholder background will be drawn or a wipe-off brush
- * will be used to reveal the content underneath when [PlaceholderState.isWipeOff] is true.
+ * Create a [Painter] that paints with a placeholder background brush. If the [placeholderState]
+ * is [PlaceholderState.isShowContent] then a transparent background will be shown. Otherwise a
+ * placeholder background will be drawn or a wipe-off brush will be used to reveal the content
+ * underneath when [PlaceholderState.isWipeOff] is true.
*
* @param placeholderState the state of the placeholder
* @param color the color to use for the placeholder background brush
@@ -628,27 +638,23 @@
@ExperimentalWearMaterialApi
@Immutable
@JvmInline
-/**
- * Enumerate the possible stages (states) that a placeholder can be in.
- */
+/** Enumerate the possible stages (states) that a placeholder can be in. */
internal value class PlaceholderStage internal constructor(internal val type: Int) {
companion object {
- /**
- * Show placeholders and placeholder effects. Use when waiting for content to load.
- */
+ /** Show placeholders and placeholder effects. Use when waiting for content to load. */
val ShowPlaceholder = PlaceholderStage(0)
/**
* Wipe off placeholder effects. Used to animate the wiping away of placeholders and
- * revealing the content underneath. Enter this stage from [ShowPlaceholder] when the
- * next animation loop is started and the content is ready.
+ * revealing the content underneath. Enter this stage from [ShowPlaceholder] when the next
+ * animation loop is started and the content is ready.
*/
val WipeOff = PlaceholderStage(1)
/**
- * Indicates that placeholders no longer to be shown. Enter this stage from
- * [WipeOff] in the loop after the wire-off animation.
+ * Indicates that placeholders no longer to be shown. Enter this stage from [WipeOff] in the
+ * loop after the wire-off animation.
*/
val ShowContent = PlaceholderStage(2)
@@ -670,25 +676,25 @@
}
@OptIn(ExperimentalWearMaterialApi::class)
-private fun wipeOffBrush(
- color: Color,
- offset: Offset,
- placeholderState: PlaceholderState
-): Brush {
+private fun wipeOffBrush(color: Color, offset: Offset, placeholderState: PlaceholderState): Brush {
val halfGradientWidth = placeholderState.gradientXYWidth / 2f
return Brush.linearGradient(
- colorStops = listOf(
- 0f to Color.Transparent,
- 0.75f to color,
- ).toTypedArray(),
- start = Offset(
- x = placeholderState.placeholderWipeOffProgression - halfGradientWidth - offset.x,
- y = placeholderState.placeholderWipeOffProgression - halfGradientWidth - offset.y
- ),
- end = Offset(
- x = placeholderState.placeholderWipeOffProgression + halfGradientWidth - offset.x,
- y = placeholderState.placeholderWipeOffProgression + halfGradientWidth - offset.y
- ),
+ colorStops =
+ listOf(
+ 0f to Color.Transparent,
+ 0.75f to color,
+ )
+ .toTypedArray(),
+ start =
+ Offset(
+ x = placeholderState.placeholderWipeOffProgression - halfGradientWidth - offset.x,
+ y = placeholderState.placeholderWipeOffProgression - halfGradientWidth - offset.y
+ ),
+ end =
+ Offset(
+ x = placeholderState.placeholderWipeOffProgression + halfGradientWidth - offset.x,
+ y = placeholderState.placeholderWipeOffProgression + halfGradientWidth - offset.y
+ ),
)
}
@@ -707,33 +713,31 @@
// Due to anti aliasing we can not use a SolidColor brush over the top of the background
// painter without seeing some background color bleeding through. As a result we use
// the colorFilter to tint the normal background painter instead - b/253667329
- val (brush, colorFilter) = when (placeholderState.placeholderStage) {
- PlaceholderStage.WipeOff -> {
- wipeOffBrush(
- color,
- placeholderState.backgroundOffset,
- placeholderState
- ) to null
- }
-
- PlaceholderStage.ShowPlaceholder, PlaceholderStage.ResetContent -> {
- if (painter == null) {
- SolidColor(color) to null
- } else {
- null to ColorFilter.tint(color = color)
+ val (brush, colorFilter) =
+ when (placeholderState.placeholderStage) {
+ PlaceholderStage.WipeOff -> {
+ wipeOffBrush(color, placeholderState.backgroundOffset, placeholderState) to null
+ }
+ PlaceholderStage.ShowPlaceholder,
+ PlaceholderStage.ResetContent -> {
+ if (painter == null) {
+ SolidColor(color) to null
+ } else {
+ null to ColorFilter.tint(color = color)
+ }
+ }
+ // For the ShowContent case
+ else -> {
+ null to null
}
}
- // For the ShowContent case
- else -> {
- null to null
- }
- }
- alpha = if (placeholderState.placeholderStage == PlaceholderStage.ResetContent) {
- 1f - placeholderState.resetPlaceholderFadeOutAlpha
- } else {
- 1f
- }
+ alpha =
+ if (placeholderState.placeholderStage == PlaceholderStage.ResetContent) {
+ 1f - placeholderState.resetPlaceholderFadeOutAlpha
+ } else {
+ 1f
+ }
val size = this.size
if (painter != null) {
@@ -783,9 +787,7 @@
"intrinsicSize=$intrinsicSize)"
}
- /**
- * Size of the combined painter, return Unspecified to allow us to fill the available space
- */
+ /** Size of the combined painter, return Unspecified to allow us to fill the available space */
override val intrinsicSize: Size = painter?.intrinsicSize ?: Size.Unspecified
}
@@ -840,9 +842,7 @@
outline = lastOutline!!
} else {
// Manually observe reads so we can directly invalidate the outline when it changes
- observeReads {
- outline = shape.createOutline(size, layoutDirection, this)
- }
+ observeReads { outline = shape.createOutline(size, layoutDirection, this) }
}
drawOutline(outline!!, brush = brush, alpha = alpha)
lastOutline = outline
@@ -909,21 +909,22 @@
) : AbstractPlaceholderModifierNode(alpha, shape) {
override fun generateBrush(offset: Offset): Brush? {
return when (placeholderState.placeholderStage) {
- PlaceholderStage.ShowPlaceholder, PlaceholderStage.ResetContent -> {
+ PlaceholderStage.ShowPlaceholder,
+ PlaceholderStage.ResetContent -> {
SolidColor(
color.copy(
alpha =
- if (placeholderState.placeholderStage == PlaceholderStage.ResetContent) {
- placeholderState.resetPlaceholderFadeInAlpha * color.alpha
- } else color.alpha
+ if (
+ placeholderState.placeholderStage == PlaceholderStage.ResetContent
+ ) {
+ placeholderState.resetPlaceholderFadeInAlpha * color.alpha
+ } else color.alpha
)
)
}
-
PlaceholderStage.WipeOff -> {
wipeOffBrush(color, offset, placeholderState)
}
-
else -> {
null
}
@@ -996,19 +997,23 @@
return if (placeholderState.placeholderStage == PlaceholderStage.ShowPlaceholder) {
val halfGradientWidth = placeholderState.gradientXYWidth / 2f
Brush.linearGradient(
- start = Offset(
- x = placeholderState.placeholderProgression - halfGradientWidth - offset.x,
- y = placeholderState.placeholderProgression - halfGradientWidth - offset.y
- ),
- end = Offset(
- x = placeholderState.placeholderProgression + halfGradientWidth - offset.x,
- y = placeholderState.placeholderProgression + halfGradientWidth - offset.y
- ),
- colorStops = listOf(
- 0.1f to color.copy(alpha = 0f),
- 0.65f to color.copy(alpha = placeholderState.placeholderShimmerAlpha),
- 0.9f to color.copy(alpha = 0f),
- ).toTypedArray()
+ start =
+ Offset(
+ x = placeholderState.placeholderProgression - halfGradientWidth - offset.x,
+ y = placeholderState.placeholderProgression - halfGradientWidth - offset.y
+ ),
+ end =
+ Offset(
+ x = placeholderState.placeholderProgression + halfGradientWidth - offset.x,
+ y = placeholderState.placeholderProgression + halfGradientWidth - offset.y
+ ),
+ colorStops =
+ listOf(
+ 0.1f to color.copy(alpha = 0f),
+ 0.65f to color.copy(alpha = placeholderState.placeholderShimmerAlpha),
+ 0.9f to color.copy(alpha = 0f),
+ )
+ .toTypedArray()
)
} else {
null
diff --git a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/PositionIndicator.kt b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/PositionIndicator.kt
index 6667755..6b7e047 100644
--- a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/PositionIndicator.kt
+++ b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/PositionIndicator.kt
@@ -82,25 +82,19 @@
import kotlinx.coroutines.launch
/**
- * Enum used by adapters to specify if the Position Indicator needs to be shown, hidden,
- * or hidden after a small delay.
+ * Enum used by adapters to specify if the Position Indicator needs to be shown, hidden, or hidden
+ * after a small delay.
*/
@kotlin.jvm.JvmInline
public value class PositionIndicatorVisibility internal constructor(internal val value: Int) {
companion object {
- /**
- * Show the Position Indicator.
- */
+ /** Show the Position Indicator. */
val Show = PositionIndicatorVisibility(1)
- /**
- * Hide the Position Indicator.
- */
+ /** Hide the Position Indicator. */
val Hide = PositionIndicatorVisibility(2)
- /**
- * Hide the Position Indicator after a short delay.
- */
+ /** Hide the Position Indicator after a short delay. */
val AutoHide = PositionIndicatorVisibility(3)
}
}
@@ -108,76 +102,66 @@
/**
* An object representing the relative position of a scrollbar or rolling side button or rotating
* bezel position. This interface is implemented by classes that adapt other state information such
- * as [ScalingLazyListState] or [ScrollState] of scrollable containers or to represent the
- * position of say a volume control that can be 'ticked' using a rolling side button or rotating
- * bezel.
+ * as [ScalingLazyListState] or [ScrollState] of scrollable containers or to represent the position
+ * of say a volume control that can be 'ticked' using a rolling side button or rotating bezel.
*
* Implementing classes provide [positionFraction] to determine where in the range [0..1] that the
* indicator should be displayed and [sizeFraction] to determine the size of the indicator in the
- * range [0..1]. E.g. If a [ScalingLazyListState] had 50 items and the last 5 were visible it
- * would have a position of 1.0f to show that the scroll is positioned at the end of the list and a
- * size of 5 / 50 = 0.1f to indicate that 10% of the visible items are currently visible.
+ * range [0..1]. E.g. If a [ScalingLazyListState] had 50 items and the last 5 were visible it would
+ * have a position of 1.0f to show that the scroll is positioned at the end of the list and a size
+ * of 5 / 50 = 0.1f to indicate that 10% of the visible items are currently visible.
*/
@Stable
interface PositionIndicatorState {
/**
- * Position of the indicator in the range [0f,1f]. 0f means it is at the top|start, 1f means
- * it is positioned at the bottom|end.
+ * Position of the indicator in the range [0f,1f]. 0f means it is at the top|start, 1f means it
+ * is positioned at the bottom|end.
*/
- @get:FloatRange(from = 0.0, to = 1.0)
- val positionFraction: Float
+ @get:FloatRange(from = 0.0, to = 1.0) val positionFraction: Float
/**
* Size of the indicator in the range [0f,1f]. 1f means it takes the whole space.
*
- * @param scrollableContainerSizePx the height or width of the container
- * in pixels depending on orientation of the indicator, (height for vertical, width for
- * horizontal)
+ * @param scrollableContainerSizePx the height or width of the container in pixels depending on
+ * orientation of the indicator, (height for vertical, width for horizontal)
*/
@FloatRange(from = 0.0, to = 1.0)
- fun sizeFraction(
- @FloatRange(from = 0.0)
- scrollableContainerSizePx: Float
- ): Float
+ fun sizeFraction(@FloatRange(from = 0.0) scrollableContainerSizePx: Float): Float
/**
* Should we show the Position Indicator
*
- * @param scrollableContainerSizePx the height or width of the container
- * in pixels depending on orientation of the indicator, (height for vertical, width for
- * horizontal)
+ * @param scrollableContainerSizePx the height or width of the container in pixels depending on
+ * orientation of the indicator, (height for vertical, width for horizontal)
*/
fun visibility(
- @FloatRange(from = 0.0)
- scrollableContainerSizePx: Float
+ @FloatRange(from = 0.0) scrollableContainerSizePx: Float
): PositionIndicatorVisibility
}
/**
- * Creates an [PositionIndicator] based on the values in a [ScrollState] object.
- * e.g. a [Column] implementing [Modifier.verticalScroll] provides a [ScrollState].
+ * Creates an [PositionIndicator] based on the values in a [ScrollState] object. e.g. a [Column]
+ * implementing [Modifier.verticalScroll] provides a [ScrollState].
*
* For more information, see the
- * [Scroll indicators](https://developer.android.com/training/wearables/components/scroll)
- * guide.
+ * [Scroll indicators](https://developer.android.com/training/wearables/components/scroll) guide.
*
* @param scrollState The scrollState to use as the basis for the PositionIndicatorState.
* @param modifier The modifier to be applied to the component
* @param reverseDirection Reverses direction of PositionIndicator if true
- * @param fadeInAnimationSpec [AnimationSpec] for fade-in animation.
- * Fade-in animation is triggered when the [PositionIndicator] becomes
- * visible - either when state.visibility changes to Show, or state.visibility
- * is AutoHide and state.positionFraction/state.sizeFraction are changed.
- * To disable this animation [snap] AnimationSpec should be passed instead.
- * @param fadeOutAnimationSpec [AnimationSpec] for fade-out animation.
- * The Fade-out animation is used for hiding the [PositionIndicator] and making it invisible.
- * [PositionIndicator] will be hidden after a specified delay if no changes
- * in state.positionFraction or state.sizeFraction were detected.
- * If [fadeOutAnimationSpec] is [snap], then after a delay it will be instantly hidden.
- * @param positionAnimationSpec [AnimationSpec] for position animation.
- * The Position animation is used for animating changes between state.positionFraction
- * and state.sizeFraction of [PositionIndicatorState].
- * To disable this animation [snap] AnimationSpec should be passed instead.
+ * @param fadeInAnimationSpec [AnimationSpec] for fade-in animation. Fade-in animation is triggered
+ * when the [PositionIndicator] becomes visible - either when state.visibility changes to Show, or
+ * state.visibility is AutoHide and state.positionFraction/state.sizeFraction are changed. To
+ * disable this animation [snap] AnimationSpec should be passed instead.
+ * @param fadeOutAnimationSpec [AnimationSpec] for fade-out animation. The Fade-out animation is
+ * used for hiding the [PositionIndicator] and making it invisible. [PositionIndicator] will be
+ * hidden after a specified delay if no changes in state.positionFraction or state.sizeFraction
+ * were detected. If [fadeOutAnimationSpec] is [snap], then after a delay it will be instantly
+ * hidden.
+ * @param positionAnimationSpec [AnimationSpec] for position animation. The Position animation is
+ * used for animating changes between state.positionFraction and state.sizeFraction of
+ * [PositionIndicatorState]. To disable this animation [snap] AnimationSpec should be passed
+ * instead.
*/
@Composable
public fun PositionIndicator(
@@ -186,27 +170,26 @@
reverseDirection: Boolean = false,
fadeInAnimationSpec: AnimationSpec<Float> = PositionIndicatorDefaults.visibilityAnimationSpec,
fadeOutAnimationSpec: AnimationSpec<Float> = PositionIndicatorDefaults.visibilityAnimationSpec,
- positionAnimationSpec: AnimationSpec<Float> =
- PositionIndicatorDefaults.positionAnimationSpec
-) = PositionIndicator(
- ScrollStateAdapter(scrollState),
- indicatorHeight = 50.dp,
- indicatorWidth = 4.dp,
- paddingHorizontal = PositionIndicatorDefaults.horizontalPadding,
- modifier = modifier,
- reverseDirection = reverseDirection,
- fadeInAnimationSpec = fadeInAnimationSpec,
- fadeOutAnimationSpec = fadeOutAnimationSpec,
- positionAnimationSpec = positionAnimationSpec
-)
+ positionAnimationSpec: AnimationSpec<Float> = PositionIndicatorDefaults.positionAnimationSpec
+) =
+ PositionIndicator(
+ ScrollStateAdapter(scrollState),
+ indicatorHeight = 50.dp,
+ indicatorWidth = 4.dp,
+ paddingHorizontal = PositionIndicatorDefaults.horizontalPadding,
+ modifier = modifier,
+ reverseDirection = reverseDirection,
+ fadeInAnimationSpec = fadeInAnimationSpec,
+ fadeOutAnimationSpec = fadeOutAnimationSpec,
+ positionAnimationSpec = positionAnimationSpec
+ )
/**
- * Creates an [PositionIndicator] based on the values in a [ScrollState] object.
- * e.g. a [Column] implementing [Modifier.verticalScroll] provides a [ScrollState].
+ * Creates an [PositionIndicator] based on the values in a [ScrollState] object. e.g. a [Column]
+ * implementing [Modifier.verticalScroll] provides a [ScrollState].
*
* For more information, see the
- * [Scroll indicators](https://developer.android.com/training/wearables/components/scroll)
- * guide.
+ * [Scroll indicators](https://developer.android.com/training/wearables/components/scroll) guide.
*
* @param scrollState The scrollState to use as the basis for the PositionIndicatorState.
* @param modifier The modifier to be applied to the component
@@ -224,38 +207,37 @@
scrollState: ScrollState,
modifier: Modifier = Modifier,
reverseDirection: Boolean = false
-) = PositionIndicator(
- scrollState = scrollState,
- modifier = modifier,
- reverseDirection = reverseDirection
-)
+) =
+ PositionIndicator(
+ scrollState = scrollState,
+ modifier = modifier,
+ reverseDirection = reverseDirection
+ )
/**
- * Creates an [PositionIndicator] based on the values in a [ScalingLazyListState] object that
- * a [ScalingLazyColumn] uses.
+ * Creates an [PositionIndicator] based on the values in a [ScalingLazyListState] object that a
+ * [ScalingLazyColumn] uses.
*
* For more information, see the
- * [Scroll indicators](https://developer.android.com/training/wearables/components/scroll)
- * guide.
+ * [Scroll indicators](https://developer.android.com/training/wearables/components/scroll) guide.
*
* @param scalingLazyListState the [ScalingLazyListState] to use as the basis for the
- * PositionIndicatorState.
+ * PositionIndicatorState.
* @param modifier The modifier to be applied to the component
* @param reverseDirection Reverses direction of PositionIndicator if true
- * @param fadeInAnimationSpec [AnimationSpec] for fade-in animation.
- * Fade-in animation is triggered when the [PositionIndicator] becomes
- * visible - either when state.visibility changes to Show, or state.visibility
- * is AutoHide and state.positionFraction/state.sizeFraction are changed.
- * To disable this animation [snap] AnimationSpec should be passed instead.
- * @param fadeOutAnimationSpec [AnimationSpec] for fade-out animation.
- * The Fade-out animation is used for hiding the [PositionIndicator] and making it invisible.
- * [PositionIndicator] will be hidden after a specified delay if no changes
- * in state.positionFraction or state.sizeFraction were detected.
- * If [fadeOutAnimationSpec] is [snap], then after a delay it will be instantly hidden.
- * @param positionAnimationSpec [AnimationSpec] for position animation.
- * The Position animation is used for animating changes between state.positionFraction
- * and state.sizeFraction of [PositionIndicatorState].
- * To disable this animation [snap] AnimationSpec should be passed instead.
+ * @param fadeInAnimationSpec [AnimationSpec] for fade-in animation. Fade-in animation is triggered
+ * when the [PositionIndicator] becomes visible - either when state.visibility changes to Show, or
+ * state.visibility is AutoHide and state.positionFraction/state.sizeFraction are changed. To
+ * disable this animation [snap] AnimationSpec should be passed instead.
+ * @param fadeOutAnimationSpec [AnimationSpec] for fade-out animation. The Fade-out animation is
+ * used for hiding the [PositionIndicator] and making it invisible. [PositionIndicator] will be
+ * hidden after a specified delay if no changes in state.positionFraction or state.sizeFraction
+ * were detected. If [fadeOutAnimationSpec] is [snap], then after a delay it will be instantly
+ * hidden.
+ * @param positionAnimationSpec [AnimationSpec] for position animation. The Position animation is
+ * used for animating changes between state.positionFraction and state.sizeFraction of
+ * [PositionIndicatorState]. To disable this animation [snap] AnimationSpec should be passed
+ * instead.
*/
@Composable
public fun PositionIndicator(
@@ -264,32 +246,29 @@
reverseDirection: Boolean = false,
fadeInAnimationSpec: AnimationSpec<Float> = PositionIndicatorDefaults.visibilityAnimationSpec,
fadeOutAnimationSpec: AnimationSpec<Float> = PositionIndicatorDefaults.visibilityAnimationSpec,
- positionAnimationSpec: AnimationSpec<Float> =
- PositionIndicatorDefaults.positionAnimationSpec
-) = PositionIndicator(
- state = ScalingLazyColumnStateAdapter(
- state = scalingLazyListState
- ),
- indicatorHeight = 50.dp,
- indicatorWidth = 4.dp,
- paddingHorizontal = PositionIndicatorDefaults.horizontalPadding,
- modifier = modifier,
- reverseDirection = reverseDirection,
- fadeInAnimationSpec = fadeInAnimationSpec,
- fadeOutAnimationSpec = fadeOutAnimationSpec,
- positionAnimationSpec = positionAnimationSpec
-)
+ positionAnimationSpec: AnimationSpec<Float> = PositionIndicatorDefaults.positionAnimationSpec
+) =
+ PositionIndicator(
+ state = ScalingLazyColumnStateAdapter(state = scalingLazyListState),
+ indicatorHeight = 50.dp,
+ indicatorWidth = 4.dp,
+ paddingHorizontal = PositionIndicatorDefaults.horizontalPadding,
+ modifier = modifier,
+ reverseDirection = reverseDirection,
+ fadeInAnimationSpec = fadeInAnimationSpec,
+ fadeOutAnimationSpec = fadeOutAnimationSpec,
+ positionAnimationSpec = positionAnimationSpec
+ )
/**
- * Creates an [PositionIndicator] based on the values in a [ScalingLazyListState] object that
- * a [ScalingLazyColumn] uses.
+ * Creates an [PositionIndicator] based on the values in a [ScalingLazyListState] object that a
+ * [ScalingLazyColumn] uses.
*
* For more information, see the
- * [Scroll indicators](https://developer.android.com/training/wearables/components/scroll)
- * guide.
+ * [Scroll indicators](https://developer.android.com/training/wearables/components/scroll) guide.
*
* @param scalingLazyListState the [ScalingLazyListState] to use as the basis for the
- * PositionIndicatorState.
+ * PositionIndicatorState.
* @param modifier The modifier to be applied to the component
* @param reverseDirection Reverses direction of PositionIndicator if true
*/
@@ -305,22 +284,22 @@
scalingLazyListState: ScalingLazyListState,
modifier: Modifier = Modifier,
reverseDirection: Boolean = false
-) = PositionIndicator(
- scalingLazyListState = scalingLazyListState,
- modifier = modifier,
- reverseDirection = reverseDirection
-)
+) =
+ PositionIndicator(
+ scalingLazyListState = scalingLazyListState,
+ modifier = modifier,
+ reverseDirection = reverseDirection
+ )
/**
- * Creates an [PositionIndicator] based on the values in a [ScalingLazyListState] object that
- * a [ScalingLazyColumn] uses.
+ * Creates an [PositionIndicator] based on the values in a [ScalingLazyListState] object that a
+ * [ScalingLazyColumn] uses.
*
* For more information, see the
- * [Scroll indicators](https://developer.android.com/training/wearables/components/scroll)
- * guide.
+ * [Scroll indicators](https://developer.android.com/training/wearables/components/scroll) guide.
*
* @param scalingLazyListState the [ScalingLazyListState] to use as the basis for the
- * PositionIndicatorState.
+ * PositionIndicatorState.
* @param modifier The modifier to be applied to the component
* @param reverseDirection Reverses direction of PositionIndicator if true
*/
@@ -328,50 +307,47 @@
@Deprecated(
"This overload is provided for backwards compatibility with Compose for Wear OS 1.1." +
"A newer overload is available which uses ScalingLazyListState from " +
- "androidx.wear.compose.foundation.lazy package", level = DeprecationLevel.WARNING
+ "androidx.wear.compose.foundation.lazy package",
+ level = DeprecationLevel.WARNING
)
@Composable
public fun PositionIndicator(
scalingLazyListState: androidx.wear.compose.material.ScalingLazyListState,
modifier: Modifier = Modifier,
reverseDirection: Boolean = false
-) = PositionIndicator(
- state = MaterialScalingLazyColumnStateAdapter(
- state = scalingLazyListState
- ),
- indicatorHeight = 50.dp,
- indicatorWidth = 4.dp,
- paddingHorizontal = PositionIndicatorDefaults.horizontalPadding,
- modifier = modifier,
- reverseDirection = reverseDirection
-)
+) =
+ PositionIndicator(
+ state = MaterialScalingLazyColumnStateAdapter(state = scalingLazyListState),
+ indicatorHeight = 50.dp,
+ indicatorWidth = 4.dp,
+ paddingHorizontal = PositionIndicatorDefaults.horizontalPadding,
+ modifier = modifier,
+ reverseDirection = reverseDirection
+ )
/**
- * Creates an [PositionIndicator] based on the values in a [LazyListState] object that
- * a [LazyColumn] uses.
+ * Creates an [PositionIndicator] based on the values in a [LazyListState] object that a
+ * [LazyColumn] uses.
*
* For more information, see the
- * [Scroll indicators](https://developer.android.com/training/wearables/components/scroll)
- * guide.
+ * [Scroll indicators](https://developer.android.com/training/wearables/components/scroll) guide.
*
- * @param lazyListState the [LazyListState] to use as the basis for the
- * PositionIndicatorState.
+ * @param lazyListState the [LazyListState] to use as the basis for the PositionIndicatorState.
* @param modifier The modifier to be applied to the component
* @param reverseDirection Reverses direction of PositionIndicator if true
- * @param fadeInAnimationSpec [AnimationSpec] for fade-in animation.
- * Fade-in animation is triggered when the [PositionIndicator] becomes
- * visible - either when state.visibility changes to Show, or state.visibility
- * is AutoHide and state.positionFraction/state.sizeFraction are changed.
- * To disable this animation [snap] AnimationSpec should be passed instead.
- * @param fadeOutAnimationSpec [AnimationSpec] for fade-out animation.
- * The Fade-out animation is used for hiding the [PositionIndicator] and making it invisible.
- * [PositionIndicator] will be hidden after a specified delay if no changes
- * in state.positionFraction or state.sizeFraction were detected.
- * If [fadeOutAnimationSpec] is [snap], then after a delay it will be instantly hidden.
- * @param positionAnimationSpec [AnimationSpec] for position animation.
- * The Position animation is used for animating changes between state.positionFraction
- * and state.sizeFraction of [PositionIndicatorState].
- * To disable this animation [snap] AnimationSpec should be passed instead.
+ * @param fadeInAnimationSpec [AnimationSpec] for fade-in animation. Fade-in animation is triggered
+ * when the [PositionIndicator] becomes visible - either when state.visibility changes to Show, or
+ * state.visibility is AutoHide and state.positionFraction/state.sizeFraction are changed. To
+ * disable this animation [snap] AnimationSpec should be passed instead.
+ * @param fadeOutAnimationSpec [AnimationSpec] for fade-out animation. The Fade-out animation is
+ * used for hiding the [PositionIndicator] and making it invisible. [PositionIndicator] will be
+ * hidden after a specified delay if no changes in state.positionFraction or state.sizeFraction
+ * were detected. If [fadeOutAnimationSpec] is [snap], then after a delay it will be instantly
+ * hidden.
+ * @param positionAnimationSpec [AnimationSpec] for position animation. The Position animation is
+ * used for animating changes between state.positionFraction and state.sizeFraction of
+ * [PositionIndicatorState]. To disable this animation [snap] AnimationSpec should be passed
+ * instead.
*/
@Composable
public fun PositionIndicator(
@@ -380,32 +356,28 @@
reverseDirection: Boolean = false,
fadeInAnimationSpec: AnimationSpec<Float> = PositionIndicatorDefaults.visibilityAnimationSpec,
fadeOutAnimationSpec: AnimationSpec<Float> = PositionIndicatorDefaults.visibilityAnimationSpec,
- positionAnimationSpec: AnimationSpec<Float> =
- PositionIndicatorDefaults.positionAnimationSpec
-) = PositionIndicator(
- state = LazyColumnStateAdapter(
- state = lazyListState
- ),
- indicatorHeight = 50.dp,
- indicatorWidth = 4.dp,
- paddingHorizontal = PositionIndicatorDefaults.horizontalPadding,
- modifier = modifier,
- reverseDirection = reverseDirection,
- fadeInAnimationSpec = fadeInAnimationSpec,
- fadeOutAnimationSpec = fadeOutAnimationSpec,
- positionAnimationSpec = positionAnimationSpec
-)
+ positionAnimationSpec: AnimationSpec<Float> = PositionIndicatorDefaults.positionAnimationSpec
+) =
+ PositionIndicator(
+ state = LazyColumnStateAdapter(state = lazyListState),
+ indicatorHeight = 50.dp,
+ indicatorWidth = 4.dp,
+ paddingHorizontal = PositionIndicatorDefaults.horizontalPadding,
+ modifier = modifier,
+ reverseDirection = reverseDirection,
+ fadeInAnimationSpec = fadeInAnimationSpec,
+ fadeOutAnimationSpec = fadeOutAnimationSpec,
+ positionAnimationSpec = positionAnimationSpec
+ )
/**
- * Creates an [PositionIndicator] based on the values in a [LazyListState] object that
- * a [LazyColumn] uses.
+ * Creates an [PositionIndicator] based on the values in a [LazyListState] object that a
+ * [LazyColumn] uses.
*
* For more information, see the
- * [Scroll indicators](https://developer.android.com/training/wearables/components/scroll)
- * guide.
+ * [Scroll indicators](https://developer.android.com/training/wearables/components/scroll) guide.
*
- * @param lazyListState the [LazyListState] to use as the basis for the
- * PositionIndicatorState.
+ * @param lazyListState the [LazyListState] to use as the basis for the PositionIndicatorState.
* @param modifier The modifier to be applied to the component
* @param reverseDirection Reverses direction of PositionIndicator if true
*/
@@ -421,15 +393,14 @@
lazyListState: LazyListState,
modifier: Modifier = Modifier,
reverseDirection: Boolean = false
-) = PositionIndicator(
- lazyListState = lazyListState,
- modifier = modifier,
- reverseDirection = reverseDirection
-)
+) =
+ PositionIndicator(
+ lazyListState = lazyListState,
+ modifier = modifier,
+ reverseDirection = reverseDirection
+ )
-/**
- * Specifies where in the screen the Position indicator will be.
- */
+/** Specifies where in the screen the Position indicator will be. */
@kotlin.jvm.JvmInline
value class PositionIndicatorAlignment internal constructor(internal val pos: Int) {
companion object {
@@ -442,25 +413,23 @@
// TODO(b/224770222): Add tests.
/**
* Position the indicator opposite to the physical rotating side button (RSB). (at the left
- * by default and at the right if the device is rotated 180 degrees)
- * This is the default for RSB indicators as we want to avoid it being obscured when the
- * user is interacting with the RSB.
+ * by default and at the right if the device is rotated 180 degrees) This is the default for
+ * RSB indicators as we want to avoid it being obscured when the user is interacting with
+ * the RSB.
*/
val OppositeRsb = PositionIndicatorAlignment(1)
/**
- * Position the indicator at the left of the screen.
- * This is useful to implement custom positioning, but usually
- * [PositionIndicatorAlignment#End] or [PositionIndicatorAlignment#OppositeRsb] should be
- * used.
+ * Position the indicator at the left of the screen. This is useful to implement custom
+ * positioning, but usually [PositionIndicatorAlignment#End] or
+ * [PositionIndicatorAlignment#OppositeRsb] should be used.
*/
val Left = PositionIndicatorAlignment(2)
/**
- * Position the indicator at the right of the screen
- * This is useful to implement custom positioning, but usually
- * [PositionIndicatorAlignment#End] or [PositionIndicatorAlignment#OppositeRsb] should be
- * used.
+ * Position the indicator at the right of the screen This is useful to implement custom
+ * positioning, but usually [PositionIndicatorAlignment#End] or
+ * [PositionIndicatorAlignment#OppositeRsb] should be used.
*/
val Right = PositionIndicatorAlignment(3)
}
@@ -480,32 +449,29 @@
* Creates a [PositionIndicator] for controls like rotating side button, rotating bezel or slider.
*
* For more information, see the
- * [Scroll indicators](https://developer.android.com/training/wearables/components/scroll)
- * guide.
+ * [Scroll indicators](https://developer.android.com/training/wearables/components/scroll) guide.
*
- * @param value Value of the indicator in the [range] where 1 represents the
- * maximum value. E.g. If displaying a volume value from 0..11 then the [value] will be
- * volume/11.
+ * @param value Value of the indicator in the [range] where 1 represents the maximum value. E.g. If
+ * displaying a volume value from 0..11 then the [value] will be volume/11.
* @param range range of values that [value] can take
* @param modifier Modifier to be applied to the component
* @param color Color to draw the indicator on.
* @param reverseDirection Reverses direction of PositionIndicator if true
* @param position indicates where to put the PositionIndicator in the screen, default is
- * [PositionIndicatorPosition#OppositeRsb]
- * @param fadeInAnimationSpec [AnimationSpec] for fade-in animation.
- * Fade-in animation is triggered when the [PositionIndicator] becomes
- * visible - either when state.visibility changes to Show, or state.visibility
- * is AutoHide and state.positionFraction/state.sizeFraction are changed.
- * To disable this animation [snap] AnimationSpec should be passed instead.
- * @param fadeOutAnimationSpec [AnimationSpec] for fade-out animation.
- * The Fade-out animation is used for hiding the [PositionIndicator] and making it invisible.
- * [PositionIndicator] will be hidden after a specified delay if no changes
- * in state.positionFraction or state.sizeFraction were detected.
- * If [fadeOutAnimationSpec] is [snap], then after a delay it will be instantly hidden.
- * @param positionAnimationSpec [AnimationSpec] for position animation.
- * The Position animation is used for animating changes between state.positionFraction
- * and state.sizeFraction of [PositionIndicatorState].
- * To disable this animation [snap] AnimationSpec should be passed instead.
+ * [PositionIndicatorPosition#OppositeRsb]
+ * @param fadeInAnimationSpec [AnimationSpec] for fade-in animation. Fade-in animation is triggered
+ * when the [PositionIndicator] becomes visible - either when state.visibility changes to Show, or
+ * state.visibility is AutoHide and state.positionFraction/state.sizeFraction are changed. To
+ * disable this animation [snap] AnimationSpec should be passed instead.
+ * @param fadeOutAnimationSpec [AnimationSpec] for fade-out animation. The Fade-out animation is
+ * used for hiding the [PositionIndicator] and making it invisible. [PositionIndicator] will be
+ * hidden after a specified delay if no changes in state.positionFraction or state.sizeFraction
+ * were detected. If [fadeOutAnimationSpec] is [snap], then after a delay it will be instantly
+ * hidden.
+ * @param positionAnimationSpec [AnimationSpec] for position animation. The Position animation is
+ * used for animating changes between state.positionFraction and state.sizeFraction of
+ * [PositionIndicatorState]. To disable this animation [snap] AnimationSpec should be passed
+ * instead.
*/
@Composable
public fun PositionIndicator(
@@ -517,40 +483,39 @@
position: PositionIndicatorAlignment = PositionIndicatorAlignment.OppositeRsb,
fadeInAnimationSpec: AnimationSpec<Float> = PositionIndicatorDefaults.visibilityAnimationSpec,
fadeOutAnimationSpec: AnimationSpec<Float> = PositionIndicatorDefaults.visibilityAnimationSpec,
- positionAnimationSpec: AnimationSpec<Float> =
- PositionIndicatorDefaults.positionAnimationSpec
-) = PositionIndicator(
- state = FractionPositionIndicatorState {
- (value() - range.start) / (range.endInclusive - range.start)
- },
- indicatorHeight = 76.dp,
- indicatorWidth = 6.dp,
- paddingHorizontal = 5.dp,
- color = color,
- modifier = modifier,
- reverseDirection = reverseDirection,
- position = position,
- fadeInAnimationSpec = fadeInAnimationSpec,
- fadeOutAnimationSpec = fadeOutAnimationSpec,
- positionAnimationSpec = positionAnimationSpec
-)
+ positionAnimationSpec: AnimationSpec<Float> = PositionIndicatorDefaults.positionAnimationSpec
+) =
+ PositionIndicator(
+ state =
+ FractionPositionIndicatorState {
+ (value() - range.start) / (range.endInclusive - range.start)
+ },
+ indicatorHeight = 76.dp,
+ indicatorWidth = 6.dp,
+ paddingHorizontal = 5.dp,
+ color = color,
+ modifier = modifier,
+ reverseDirection = reverseDirection,
+ position = position,
+ fadeInAnimationSpec = fadeInAnimationSpec,
+ fadeOutAnimationSpec = fadeOutAnimationSpec,
+ positionAnimationSpec = positionAnimationSpec
+ )
/**
* Creates a [PositionIndicator] for controls like rotating side button, rotating bezel or slider.
*
* For more information, see the
- * [Scroll indicators](https://developer.android.com/training/wearables/components/scroll)
- * guide.
+ * [Scroll indicators](https://developer.android.com/training/wearables/components/scroll) guide.
*
- * @param value Value of the indicator in the [range] where 1 represents the
- * maximum value. E.g. If displaying a volume value from 0..11 then the [value] will be
- * volume/11.
+ * @param value Value of the indicator in the [range] where 1 represents the maximum value. E.g. If
+ * displaying a volume value from 0..11 then the [value] will be volume/11.
* @param range range of values that [value] can take
* @param modifier Modifier to be applied to the component
* @param color Color to draw the indicator on.
* @param reverseDirection Reverses direction of PositionIndicator if true
* @param position indicates where to put the PositionIndicator in the screen, default is
- * [PositionIndicatorPosition#OppositeRsb]
+ * [PositionIndicatorPosition#OppositeRsb]
*/
@Deprecated(
"This overload is provided for backwards compatibility with " +
@@ -567,14 +532,15 @@
color: Color = MaterialTheme.colors.onBackground,
reverseDirection: Boolean = false,
position: PositionIndicatorAlignment = PositionIndicatorAlignment.OppositeRsb
-) = PositionIndicator(
- value = value,
- modifier = modifier,
- range = range,
- color = color,
- reverseDirection = reverseDirection,
- position = position
-)
+) =
+ PositionIndicator(
+ value = value,
+ modifier = modifier,
+ range = range,
+ color = color,
+ reverseDirection = reverseDirection,
+ position = position
+ )
/**
* An indicator on one side of the screen to show the current [PositionIndicatorState].
@@ -598,17 +564,16 @@
*
* For performance reasons and for UX consistency, when [PositionIndicator] is used with scrollable
* list, we recommend to switch off fade-in and position animations by passing [snap] spec into
- * [fadeInAnimationSpec] and [positionAnimationSpec] parameters.
- * If [PositionIndicator] is used as a standalone indicator, for example as volume control,
- * then we recommend to have all 3 animations turned on.
+ * [fadeInAnimationSpec] and [positionAnimationSpec] parameters. If [PositionIndicator] is used as a
+ * standalone indicator, for example as volume control, then we recommend to have all 3 animations
+ * turned on.
*
* If color of [PositionIndicator] is not white and position animation is enabled - a short
- * highlight animation will be triggered on any position change.
- * This is a short animation accenting [PositionIndicator] with white color with 33% opacity.
+ * highlight animation will be triggered on any position change. This is a short animation accenting
+ * [PositionIndicator] with white color with 33% opacity.
*
* For more information, see the
- * [Scroll indicators](https://developer.android.com/training/wearables/components/scroll)
- * guide.
+ * [Scroll indicators](https://developer.android.com/training/wearables/components/scroll) guide.
*
* @param state the [PositionIndicatorState] of the state we are displaying.
* @param indicatorHeight the height of the position indicator in Dp.
@@ -619,21 +584,19 @@
* @param color the color to draw the active part of the indicator in.
* @param reverseDirection Reverses direction of PositionIndicator if true.
* @param position indicates where to put the PositionIndicator on the screen, default is
- * [PositionIndicatorPosition#End]
- * @param fadeInAnimationSpec [AnimationSpec] for fade-in animation.
- * Fade-in animation is triggered when the [PositionIndicator] becomes
- * visible - either when state.visibility changes to Show, or state.visibility
- * is AutoHide and state.positionFraction/state.sizeFraction are changed.
- * To disable this animation [snap] AnimationSpec should be passed instead.
- * @param fadeOutAnimationSpec [AnimationSpec] for fade-out animation.
- * The Fade-out animation is used for hiding the [PositionIndicator] and making it invisible.
- * [PositionIndicator] will be hidden after a specified delay if no changes
- * in state.positionFraction or state.sizeFraction were detected.
- * If [fadeOutAnimationSpec] is [snap], then after a delay it will be instantly hidden.
- * @param positionAnimationSpec [AnimationSpec] for position animation.
- * The Position animation is used for animating changes between state.positionFraction
- * and state.sizeFraction of [PositionIndicatorState].
- * To disable animation [snap] should be passed.
+ * [PositionIndicatorPosition#End]
+ * @param fadeInAnimationSpec [AnimationSpec] for fade-in animation. Fade-in animation is triggered
+ * when the [PositionIndicator] becomes visible - either when state.visibility changes to Show, or
+ * state.visibility is AutoHide and state.positionFraction/state.sizeFraction are changed. To
+ * disable this animation [snap] AnimationSpec should be passed instead.
+ * @param fadeOutAnimationSpec [AnimationSpec] for fade-out animation. The Fade-out animation is
+ * used for hiding the [PositionIndicator] and making it invisible. [PositionIndicator] will be
+ * hidden after a specified delay if no changes in state.positionFraction or state.sizeFraction
+ * were detected. If [fadeOutAnimationSpec] is [snap], then after a delay it will be instantly
+ * hidden.
+ * @param positionAnimationSpec [AnimationSpec] for position animation. The Position animation is
+ * used for animating changes between state.positionFraction and state.sizeFraction of
+ * [PositionIndicatorState]. To disable animation [snap] should be passed.
*/
@Composable
public fun PositionIndicator(
@@ -648,8 +611,7 @@
position: PositionIndicatorAlignment = PositionIndicatorAlignment.End,
fadeInAnimationSpec: AnimationSpec<Float> = PositionIndicatorDefaults.visibilityAnimationSpec,
fadeOutAnimationSpec: AnimationSpec<Float> = PositionIndicatorDefaults.visibilityAnimationSpec,
- positionAnimationSpec: AnimationSpec<Float> =
- PositionIndicatorDefaults.positionAnimationSpec
+ positionAnimationSpec: AnimationSpec<Float> = PositionIndicatorDefaults.positionAnimationSpec
) {
val isScreenRound = isRoundDevice()
val layoutDirection = LocalLayoutDirection.current
@@ -667,28 +629,31 @@
val positionFractionAnimatable = remember { Animatable(0f) }
val sizeFractionAnimatable = remember { Animatable(0f) }
- val indicatorOnTheRight = when (position) {
- PositionIndicatorAlignment.End -> layoutDirection == LayoutDirection.Ltr
- PositionIndicatorAlignment.Left -> false
- PositionIndicatorAlignment.Right -> true
- PositionIndicatorAlignment.OppositeRsb -> leftyMode
- else -> true
- }
+ val indicatorOnTheRight =
+ when (position) {
+ PositionIndicatorAlignment.End -> layoutDirection == LayoutDirection.Ltr
+ PositionIndicatorAlignment.Left -> false
+ PositionIndicatorAlignment.Right -> true
+ PositionIndicatorAlignment.OppositeRsb -> leftyMode
+ else -> true
+ }
val boundsSize: Density.() -> IntSize = {
IntSize(
((if (isScreenRound) {
- // r is the distance from the center of the container to the arc we draw the
- // position indicator on (the center of the arc, which is indicatorWidth wide).
- val r = containerSize.width.toFloat() / 2 - paddingHorizontal.toPx() -
- indicatorWidth.toPx() / 2
- // The sqrt is the size of the projection on the x axis of line between center of
- // the container and the point where we start the arc.
- // The coerceAtLeast is needed while initializing since containerSize.width is 0
- r - sqrt((sqr(r) - sqr(indicatorHeight.toPx() / 2)).coerceAtLeast(0f))
- } else 0f) +
- paddingHorizontal.toPx() + indicatorWidth.toPx()
- ).roundToInt(),
+ // r is the distance from the center of the container to the arc we draw the
+ // position indicator on (the center of the arc, which is indicatorWidth wide).
+ val r =
+ containerSize.width.toFloat() / 2 -
+ paddingHorizontal.toPx() -
+ indicatorWidth.toPx() / 2
+ // The sqrt is the size of the projection on the x axis of line between center
+ // of
+ // the container and the point where we start the arc.
+ // The coerceAtLeast is needed while initializing since containerSize.width is 0
+ r - sqrt((sqr(r) - sqr(indicatorHeight.toPx() / 2)).coerceAtLeast(0f))
+ } else 0f) + paddingHorizontal.toPx() + indicatorWidth.toPx())
+ .roundToInt(),
(indicatorHeight.toPx() + indicatorWidth.toPx()).roundToInt()
)
}
@@ -712,90 +677,95 @@
var skipFirstPositionAnimation = true
// Skip first alpha animation only when initial visibility is not Hide
- var skipFirstAlphaAnimation = state.visibility(containerSize.height.toFloat()) !=
- PositionIndicatorVisibility.Hide
+ var skipFirstAlphaAnimation =
+ state.visibility(containerSize.height.toFloat()) != PositionIndicatorVisibility.Hide
launch {
// This snapshotFlow listens to changes in position, size and visibility
// of PositionIndicatorState and starts necessary animations if needed
snapshotFlow {
- DisplayState(
- state.positionFraction,
- state.sizeFraction(containerSize.height.toFloat()),
- state.visibility(containerSize.height.toFloat())
- )
- }.collectLatest {
- // Workaround for b/315149417. When visibility is Hide and other values equal to 0,
- // we consider that as non-initialized state.
- // It means that we skip first alpha animation, and also ignore these values.
- if (skipFirstPositionAnimation &&
- it.visibility == PositionIndicatorVisibility.Hide &&
- it.position == 0f &&
- it.size == 0f
- ) {
- skipFirstAlphaAnimation = true
- return@collectLatest
+ DisplayState(
+ state.positionFraction,
+ state.sizeFraction(containerSize.height.toFloat()),
+ state.visibility(containerSize.height.toFloat())
+ )
}
+ .collectLatest {
+ // Workaround for b/315149417. When visibility is Hide and other values equal to
+ // 0,
+ // we consider that as non-initialized state.
+ // It means that we skip first alpha animation, and also ignore these values.
+ if (
+ skipFirstPositionAnimation &&
+ it.visibility == PositionIndicatorVisibility.Hide &&
+ it.position == 0f &&
+ it.size == 0f
+ ) {
+ skipFirstAlphaAnimation = true
+ return@collectLatest
+ }
- if (skipFirstPositionAnimation || updatedPositionAnimationSpec is SnapSpec) {
- sizeFractionAnimatable.snapTo(it.size)
- positionFractionAnimatable.snapTo(it.position)
- skipFirstPositionAnimation = false
- } else {
- launch {
- sizeFractionAnimatable
- .animateTo(
+ if (skipFirstPositionAnimation || updatedPositionAnimationSpec is SnapSpec) {
+ sizeFractionAnimatable.snapTo(it.size)
+ positionFractionAnimatable.snapTo(it.position)
+ skipFirstPositionAnimation = false
+ } else {
+ launch {
+ sizeFractionAnimatable.animateTo(
it.size,
animationSpec = updatedPositionAnimationSpec
)
- }
- launch {
- positionFractionAnimatable
- .animateTo(
+ }
+ launch {
+ positionFractionAnimatable.animateTo(
it.position,
animationSpec = updatedPositionAnimationSpec
)
- }
-
- if (shouldShowHighlight) {
- launch {
- highlightChannel.trySend(true)
- delay(150)
- highlightChannel.trySend(false)
- }
- }
- }
-
- when (it.visibility) {
- PositionIndicatorVisibility.Hide -> {
- handleFadeOut(updatedFadeOutAnimationSpec, animateAlphaChannel, alphaValue)
- }
-
- // PositionIndicatorVisibility.Show and
- // PositionIndicatorVisibility.AutoHide cases
- else -> {
- // If fadeInAnimationSpec is SnapSpec or we skip the first animation,
- // then we change alphaValue directly here
- if (updatedFadeInAnimationSpec is SnapSpec || skipFirstAlphaAnimation) {
- alphaValue.floatValue = 1f
- skipFirstAlphaAnimation = false
- } else {
- // Otherwise we send an event to animation channel
- animateAlphaChannel.trySend(1f)
}
- if (it.visibility == PositionIndicatorVisibility.AutoHide) {
- // Waiting for 2000ms and changing alpha value to 0f
- delay(2000)
+ if (shouldShowHighlight) {
+ launch {
+ highlightChannel.trySend(true)
+ delay(150)
+ highlightChannel.trySend(false)
+ }
+ }
+ }
+
+ when (it.visibility) {
+ PositionIndicatorVisibility.Hide -> {
handleFadeOut(
- updatedFadeInAnimationSpec,
+ updatedFadeOutAnimationSpec,
animateAlphaChannel,
alphaValue
)
}
+
+ // PositionIndicatorVisibility.Show and
+ // PositionIndicatorVisibility.AutoHide cases
+ else -> {
+ // If fadeInAnimationSpec is SnapSpec or we skip the first animation,
+ // then we change alphaValue directly here
+ if (updatedFadeInAnimationSpec is SnapSpec || skipFirstAlphaAnimation) {
+ alphaValue.floatValue = 1f
+ skipFirstAlphaAnimation = false
+ } else {
+ // Otherwise we send an event to animation channel
+ animateAlphaChannel.trySend(1f)
+ }
+
+ if (it.visibility == PositionIndicatorVisibility.AutoHide) {
+ // Waiting for 2000ms and changing alpha value to 0f
+ delay(2000)
+ handleFadeOut(
+ updatedFadeInAnimationSpec,
+ animateAlphaChannel,
+ alphaValue
+ )
+ }
+ }
}
}
- }
}
}
@@ -804,121 +774,117 @@
// highlight animations to specified value.
if (shouldShowHighlight && positionAnimationSpec !is SnapSpec) {
launch {
- highlightChannel
- .receiveAsFlow()
- .distinctUntilChanged()
- .collectLatest { showHighlight ->
- if (showHighlight) {
- animate(
- highlightAlpha,
- 0.33f,
- animationSpec = tween(
+ highlightChannel.receiveAsFlow().distinctUntilChanged().collectLatest {
+ showHighlight ->
+ if (showHighlight) {
+ animate(
+ highlightAlpha,
+ 0.33f,
+ animationSpec =
+ tween(
durationMillis = 150,
easing = CubicBezierEasing(0f, 0f, 0.2f, 1f)
)
- ) { value, _ ->
- highlightAlpha = value
- }
- } else {
- animate(
- highlightAlpha,
- 0f,
- animationSpec = tween(
+ ) { value, _ ->
+ highlightAlpha = value
+ }
+ } else {
+ animate(
+ highlightAlpha,
+ 0f,
+ animationSpec =
+ tween(
durationMillis = 500,
easing = CubicBezierEasing(0.25f, 0f, 0.75f, 1f)
)
- ) { value, _ ->
- highlightAlpha = value
- }
+ ) { value, _ ->
+ highlightAlpha = value
}
}
+ }
}
}
// Listens to events in [animateAlphaChannel] and triggers
// alpha animations to specified value.
- animateAlphaChannel
- .receiveAsFlow()
- .distinctUntilChanged()
- .collectLatest { targetValue ->
- animate(
- alphaValue.floatValue,
- targetValue,
- animationSpec = if (targetValue >= 1f)
- updatedFadeInAnimationSpec else updatedFadeOutAnimationSpec
- ) { value, _ ->
- alphaValue.floatValue = value
- }
+ animateAlphaChannel.receiveAsFlow().distinctUntilChanged().collectLatest { targetValue ->
+ animate(
+ alphaValue.floatValue,
+ targetValue,
+ animationSpec =
+ if (targetValue >= 1f) updatedFadeInAnimationSpec
+ else updatedFadeOutAnimationSpec
+ ) { value, _ ->
+ alphaValue.floatValue = value
}
+ }
}
- BoundsLimiter(boundsOffset, boundsSize, modifier, onSizeChanged = {
- containerSize = it
- }) {
+ BoundsLimiter(boundsOffset, boundsSize, modifier, onSizeChanged = { containerSize = it }) {
Box(
- modifier = Modifier
- .fillMaxSize()
- .graphicsLayer {
- alpha = alphaValue.floatValue
- }
- .drawWithCache {
- // We need to invert reverseDirection when the screen is round and we are on
- // the left.
- val actualReverseDirection =
- if (isScreenRound && !indicatorOnTheRight) {
- !reverseDirection
- } else {
- reverseDirection
- }
+ modifier =
+ Modifier.fillMaxSize()
+ .graphicsLayer { alpha = alphaValue.floatValue }
+ .drawWithCache {
+ // We need to invert reverseDirection when the screen is round and we are on
+ // the left.
+ val actualReverseDirection =
+ if (isScreenRound && !indicatorOnTheRight) {
+ !reverseDirection
+ } else {
+ reverseDirection
+ }
- val indicatorPosition = if (actualReverseDirection) {
- 1 - positionFractionAnimatable.value
- } else {
- positionFractionAnimatable.value
- }
+ val indicatorPosition =
+ if (actualReverseDirection) {
+ 1 - positionFractionAnimatable.value
+ } else {
+ positionFractionAnimatable.value
+ }
- val indicatorWidthPx = indicatorWidth.toPx()
+ val indicatorWidthPx = indicatorWidth.toPx()
- // We want position = 0 be the indicator aligned at the top of its area and
- // position = 1 be aligned at the bottom of the area.
- val indicatorStart = indicatorPosition * (1 - sizeFractionAnimatable.value)
+ // We want position = 0 be the indicator aligned at the top of its area and
+ // position = 1 be aligned at the bottom of the area.
+ val indicatorStart = indicatorPosition * (1 - sizeFractionAnimatable.value)
- val diameter =
- max(containerSize.width.toFloat(), containerSize.height.toFloat())
+ val diameter =
+ max(containerSize.width.toFloat(), containerSize.height.toFloat())
- val paddingHorizontalPx = paddingHorizontal.toPx()
- onDrawWithContent {
- if (isScreenRound) {
- val usableHalf = diameter / 2f - paddingHorizontalPx
- val sweepDegrees =
- (2 * asin((indicatorHeight.toPx() / 2) / usableHalf)).toDegrees()
+ val paddingHorizontalPx = paddingHorizontal.toPx()
+ onDrawWithContent {
+ if (isScreenRound) {
+ val usableHalf = diameter / 2f - paddingHorizontalPx
+ val sweepDegrees =
+ (2 * asin((indicatorHeight.toPx() / 2) / usableHalf))
+ .toDegrees()
- drawCurvedIndicator(
- color,
- background,
- paddingHorizontalPx,
- indicatorOnTheRight,
- sweepDegrees,
- indicatorWidthPx,
- indicatorStart,
- sizeFractionAnimatable.value,
- highlightAlpha
- )
- } else {
- drawStraightIndicator(
- color,
- background,
- paddingHorizontalPx,
- indicatorOnTheRight,
- indicatorWidthPx,
- indicatorHeight.toPx(),
- indicatorStart,
- sizeFractionAnimatable.value,
- highlightAlpha
- )
+ drawCurvedIndicator(
+ color,
+ background,
+ paddingHorizontalPx,
+ indicatorOnTheRight,
+ sweepDegrees,
+ indicatorWidthPx,
+ indicatorStart,
+ sizeFractionAnimatable.value,
+ highlightAlpha
+ )
+ } else {
+ drawStraightIndicator(
+ color,
+ background,
+ paddingHorizontalPx,
+ indicatorOnTheRight,
+ indicatorWidthPx,
+ indicatorHeight.toPx(),
+ indicatorStart,
+ sizeFractionAnimatable.value,
+ highlightAlpha
+ )
+ }
}
}
- }
)
}
}
@@ -939,8 +905,7 @@
* screen according to [paddingHorizontal]
*
* For more information, see the
- * [Scroll indicators](https://developer.android.com/training/wearables/components/scroll)
- * guide.
+ * [Scroll indicators](https://developer.android.com/training/wearables/components/scroll) guide.
*
* @param state the [PositionIndicatorState] of the state we are displaying.
* @param indicatorHeight the height of the position indicator in Dp.
@@ -951,7 +916,7 @@
* @param color the color to draw the active part of the indicator in.
* @param reverseDirection Reverses direction of PositionIndicator if true.
* @param position indicates where to put the PositionIndicator on the screen, default is
- * [PositionIndicatorPosition#End]
+ * [PositionIndicatorPosition#End]
*/
@Deprecated(
"This overload is provided for backwards compatibility with " +
@@ -985,30 +950,23 @@
)
}
-/**
- * Contains the default values used for [PositionIndicator].
- */
+/** Contains the default values used for [PositionIndicator]. */
public object PositionIndicatorDefaults {
/**
- * [AnimationSpec] used for position animation.
- * To disable this animation, pass [snap] AnimationSpec instead
+ * [AnimationSpec] used for position animation. To disable this animation, pass [snap]
+ * AnimationSpec instead
*/
val positionAnimationSpec: AnimationSpec<Float> =
- tween(
- durationMillis = 500,
- easing = CubicBezierEasing(0f, 0f, 0f, 1f)
- )
+ tween(durationMillis = 500, easing = CubicBezierEasing(0f, 0f, 0f, 1f))
/**
- * [AnimationSpec] used for visibility (fade-in and fade-out) animations.
- * To disable this animation, pass [snap] AnimationSpec instead
+ * [AnimationSpec] used for visibility (fade-in and fade-out) animations. To disable this
+ * animation, pass [snap] AnimationSpec instead
*/
val visibilityAnimationSpec: AnimationSpec<Float> =
spring(stiffness = Spring.StiffnessMediumLow)
- /**
- * Horizontal padding from the PositionIndicator to the screen edge.
- */
+ /** Horizontal padding from the PositionIndicator to the screen edge. */
internal val horizontalPadding = 2.dp
}
@@ -1057,15 +1015,12 @@
* An implementation of [PositionIndicatorState] to display a value that is being incremented or
* decremented with a rolling side button, rotating bezel or a slider e.g. a volume control.
*
- * @param fraction Value of the indicator in the range 0..1 where 1 represents the
- * maximum value. E.g. If displaying a volume value from 0..11 then the [fraction] will be
- * volume/11.
- *
+ * @param fraction Value of the indicator in the range 0..1 where 1 represents the maximum value.
+ * E.g. If displaying a volume value from 0..11 then the [fraction] will be volume/11.
* @VisibleForTesting
*/
-internal class FractionPositionIndicatorState(
- private val fraction: () -> Float
-) : PositionIndicatorState {
+internal class FractionPositionIndicatorState(private val fraction: () -> Float) :
+ PositionIndicatorState {
override val positionFraction = 1f // Position indicator always starts at the bottom|end
override fun sizeFraction(scrollableContainerSizePx: Float) = fraction()
@@ -1083,7 +1038,6 @@
* implementing the [ScrollState] class such as a [Column] implementing [Modifier.verticalScroll].
*
* @param scrollState the [ScrollState] to adapt
- *
* @VisibleForTesting
*/
internal class ScrollStateAdapter(private val scrollState: ScrollState) : PositionIndicatorState {
@@ -1103,12 +1057,11 @@
scrollableContainerSizePx / (scrollableContainerSizePx + scrollState.maxValue)
}
- override fun visibility(scrollableContainerSizePx: Float) = if (scrollState.maxValue == 0) {
- PositionIndicatorVisibility.Hide
- } else if (scrollState.isScrollInProgress)
- PositionIndicatorVisibility.Show
- else
- PositionIndicatorVisibility.AutoHide
+ override fun visibility(scrollableContainerSizePx: Float) =
+ if (scrollState.maxValue == 0) {
+ PositionIndicatorVisibility.Hide
+ } else if (scrollState.isScrollInProgress) PositionIndicatorVisibility.Show
+ else PositionIndicatorVisibility.AutoHide
override fun equals(other: Any?): Boolean {
return (other as? ScrollStateAdapter)?.scrollState == scrollState
@@ -1125,14 +1078,12 @@
*
* Note that size and position calculations ignore spacing between list items both for determining
* the number and the number of visible items.
-
- * @param state the [ScalingLazyListState] to adapt.
*
+ * @param state the [ScalingLazyListState] to adapt.
* @VisibleForTesting
*/
-internal class ScalingLazyColumnStateAdapter(
- private val state: ScalingLazyListState
-) : PositionIndicatorState {
+internal class ScalingLazyColumnStateAdapter(private val state: ScalingLazyListState) :
+ PositionIndicatorState {
override val positionFraction: Float
get() {
@@ -1142,8 +1093,8 @@
} else {
val decimalFirstItemIndex = decimalFirstItemIndex(layoutInfo)
val decimalLastItemIndex = decimalLastItemIndex(layoutInfo)
- val decimalLastItemIndexDistanceFromEnd = layoutInfo.totalItemsCount -
- decimalLastItemIndex
+ val decimalLastItemIndexDistanceFromEnd =
+ layoutInfo.totalItemsCount - decimalLastItemIndex
if (decimalFirstItemIndex + decimalLastItemIndexDistanceFromEnd == 0.0f) {
0.0f
@@ -1162,8 +1113,7 @@
val decimalFirstItemIndex = decimalFirstItemIndex(layoutInfo)
val decimalLastItemIndex = decimalLastItemIndex(layoutInfo)
- (decimalLastItemIndex - decimalFirstItemIndex) /
- layoutInfo.totalItemsCount.toFloat()
+ (decimalLastItemIndex - decimalFirstItemIndex) / layoutInfo.totalItemsCount.toFloat()
}
}
@@ -1171,10 +1121,8 @@
val layoutInfo: ScalingLazyListLayoutInfo = state.layoutInfo
val canScroll = layoutInfo.visibleItemsInfo.isNotEmpty() && canScrollBackwardsOrForwards()
return if (canScroll) {
- if (state.isScrollInProgress)
- PositionIndicatorVisibility.Show
- else
- PositionIndicatorVisibility.AutoHide
+ if (state.isScrollInProgress) PositionIndicatorVisibility.Show
+ else PositionIndicatorVisibility.AutoHide
} else {
PositionIndicatorVisibility.Hide
}
@@ -1212,8 +1160,8 @@
val viewportEndOffset = layoutInfo.viewportSize.height / 2f
// Coerce item size to at least 1 to avoid divide by zero for zero height items
val lastItemVisibleFraction =
- (1f - ((lastItemEndOffset - viewportEndOffset) /
- lastItem.size.coerceAtLeast(1))).coerceAtMost(1f)
+ (1f - ((lastItemEndOffset - viewportEndOffset) / lastItem.size.coerceAtLeast(1)))
+ .coerceAtMost(1f)
return lastItem.index.toFloat() + lastItemVisibleFraction
}
@@ -1235,8 +1183,8 @@
val viewportStartOffset = -(layoutInfo.viewportSize.height / 2f)
// Coerce item size to at least 1 to avoid divide by zero for zero height items
val firstItemInvisibleFraction =
- ((viewportStartOffset - firstItemStartOffset) /
- firstItem.size.coerceAtLeast(1)).coerceAtLeast(0f)
+ ((viewportStartOffset - firstItemStartOffset) / firstItem.size.coerceAtLeast(1))
+ .coerceAtLeast(0f)
return firstItem.index.toFloat() + firstItemInvisibleFraction
}
@@ -1251,13 +1199,12 @@
*
* Note that size and position calculations ignore spacing between list items both for determining
* the number and the number of visible items.
-
+ *
* @param state the [ScalingLazyListState] to adapt.
*/
@Deprecated("Use [ScalingLazyColumnStateAdapter] instead")
internal class MaterialScalingLazyColumnStateAdapter(
- @Suppress("DEPRECATION")
- private val state: androidx.wear.compose.material.ScalingLazyListState
+ @Suppress("DEPRECATION") private val state: androidx.wear.compose.material.ScalingLazyListState
) : PositionIndicatorState {
override val positionFraction: Float
@@ -1269,8 +1216,8 @@
} else {
val decimalFirstItemIndex = decimalFirstItemIndex(layoutInfo)
val decimalLastItemIndex = decimalLastItemIndex(layoutInfo)
- val decimalLastItemIndexDistanceFromEnd = layoutInfo.totalItemsCount -
- decimalLastItemIndex
+ val decimalLastItemIndexDistanceFromEnd =
+ layoutInfo.totalItemsCount - decimalLastItemIndex
if (decimalFirstItemIndex + decimalLastItemIndexDistanceFromEnd == 0.0f) {
0.0f
@@ -1289,8 +1236,7 @@
val decimalFirstItemIndex = decimalFirstItemIndex(layoutInfo)
val decimalLastItemIndex = decimalLastItemIndex(layoutInfo)
- (decimalLastItemIndex - decimalFirstItemIndex) /
- layoutInfo.totalItemsCount.toFloat()
+ (decimalLastItemIndex - decimalFirstItemIndex) / layoutInfo.totalItemsCount.toFloat()
}
}
@@ -1298,10 +1244,8 @@
val layoutInfo = state.layoutInfo
val canScroll = layoutInfo.visibleItemsInfo.isNotEmpty() && canScrollBackwardsOrForwards()
return if (canScroll) {
- if (state.isScrollInProgress)
- PositionIndicatorVisibility.Show
- else
- PositionIndicatorVisibility.AutoHide
+ if (state.isScrollInProgress) PositionIndicatorVisibility.Show
+ else PositionIndicatorVisibility.AutoHide
} else {
PositionIndicatorVisibility.Hide
}
@@ -1346,8 +1290,8 @@
val viewportEndOffset = state.viewportHeightPx.value!! / 2f
// Coerce item size to at least 1 to avoid divide by zero for zero height items
val lastItemVisibleFraction =
- (1f - ((lastItemEndOffset - viewportEndOffset) /
- lastItem.size.coerceAtLeast(1))).coerceAtMost(1f)
+ (1f - ((lastItemEndOffset - viewportEndOffset) / lastItem.size.coerceAtLeast(1)))
+ .coerceAtMost(1f)
return lastItem.index.toFloat() + lastItemVisibleFraction
}
@@ -1372,8 +1316,8 @@
val viewportStartOffset = -(state.viewportHeightPx.value!! / 2f)
// Coerce item size to at least 1 to avoid divide by zero for zero height items
val firstItemInvisibleFraction =
- ((viewportStartOffset - firstItemStartOffset) /
- firstItem.size.coerceAtLeast(1)).coerceAtLeast(0f)
+ ((viewportStartOffset - firstItemStartOffset) / firstItem.size.coerceAtLeast(1))
+ .coerceAtLeast(0f)
return firstItem.index.toFloat() + firstItemInvisibleFraction
}
@@ -1384,12 +1328,9 @@
* [LazyColumn] component via its [LazyListState].
*
* @param state the [LazyListState] to adapt.
- *
* @VisibleForTesting
*/
-internal class LazyColumnStateAdapter(
- private val state: LazyListState
-) : PositionIndicatorState {
+internal class LazyColumnStateAdapter(private val state: LazyListState) : PositionIndicatorState {
override val positionFraction: Float
get() {
return if (state.layoutInfo.visibleItemsInfo.isEmpty()) {
@@ -1398,8 +1339,8 @@
val decimalFirstItemIndex = decimalFirstItemIndex()
val decimalLastItemIndex = decimalLastItemIndex()
- val decimalLastItemIndexDistanceFromEnd = state.layoutInfo.totalItemsCount -
- decimalLastItemIndex
+ val decimalLastItemIndexDistanceFromEnd =
+ state.layoutInfo.totalItemsCount - decimalLastItemIndex
if (decimalFirstItemIndex + decimalLastItemIndexDistanceFromEnd == 0.0f) {
0.0f
@@ -1423,10 +1364,8 @@
override fun visibility(scrollableContainerSizePx: Float): PositionIndicatorVisibility {
return if (sizeFraction(scrollableContainerSizePx) < 0.999f) {
- if (state.isScrollInProgress)
- PositionIndicatorVisibility.Show
- else
- PositionIndicatorVisibility.AutoHide
+ if (state.isScrollInProgress) PositionIndicatorVisibility.Show
+ else PositionIndicatorVisibility.AutoHide
} else {
PositionIndicatorVisibility.Hide
}
@@ -1446,7 +1385,8 @@
// Coerce item sizes to at least 1 to avoid divide by zero for zero height items
val lastItemVisibleSize =
(state.layoutInfo.viewportEndOffset - lastItem.offset)
- .coerceAtMost(lastItem.size).coerceAtLeast(1)
+ .coerceAtMost(lastItem.size)
+ .coerceAtLeast(1)
return lastItem.index.toFloat() +
lastItemVisibleSize.toFloat() / lastItem.size.coerceAtLeast(1).toFloat()
}
@@ -1457,8 +1397,7 @@
val firstItemOffset = firstItem.offset - state.layoutInfo.viewportStartOffset
// Coerce item size to at least 1 to avoid divide by zero for zero height items
return firstItem.index.toFloat() -
- firstItemOffset.coerceAtMost(0).toFloat() /
- firstItem.size.coerceAtLeast(1).toFloat()
+ firstItemOffset.coerceAtMost(0).toFloat() / firstItem.size.coerceAtLeast(1).toFloat()
}
}
@@ -1475,14 +1414,16 @@
highlightAlpha: Float
) {
val diameter = max(size.width, size.height)
- val arcSize = Size(
- diameter - 2 * paddingHorizontalPx - indicatorWidthPx,
- diameter - 2 * paddingHorizontalPx - indicatorWidthPx
- )
- val arcTopLeft = Offset(
- size.width - diameter + paddingHorizontalPx + indicatorWidthPx / 2f,
- (size.height - diameter) / 2f + paddingHorizontalPx + indicatorWidthPx / 2f,
- )
+ val arcSize =
+ Size(
+ diameter - 2 * paddingHorizontalPx - indicatorWidthPx,
+ diameter - 2 * paddingHorizontalPx - indicatorWidthPx
+ )
+ val arcTopLeft =
+ Offset(
+ size.width - diameter + paddingHorizontalPx + indicatorWidthPx / 2f,
+ (size.height - diameter) / 2f + paddingHorizontalPx + indicatorWidthPx / 2f,
+ )
val startAngleOffset = if (indicatorOnTheRight) 0f else 180f
drawArc(
background,
@@ -1515,11 +1456,12 @@
indicatorSize: Float,
highlightAlpha: Float
) {
- val x = if (indicatorOnTheRight) {
- size.width - paddingHorizontalPx - indicatorWidthPx / 2
- } else {
- paddingHorizontalPx + indicatorWidthPx / 2
- }
+ val x =
+ if (indicatorOnTheRight) {
+ size.width - paddingHorizontalPx - indicatorWidthPx / 2
+ } else {
+ paddingHorizontalPx + indicatorWidthPx / 2
+ }
val lineTop = Offset(x, (size.height - indicatorHeightPx) / 2f)
val lineBottom = lineTop + Offset(0f, indicatorHeightPx)
drawLine(
@@ -1542,12 +1484,11 @@
private fun sqr(x: Float) = x * x
-/**
- * Find the start offset of the list item w.r.t. the
- */
+/** Find the start offset of the list item w.r.t. the */
internal fun ScalingLazyListItemInfo.startOffset(anchorType: ScalingLazyListAnchorType) =
- offset - if (anchorType == ScalingLazyListAnchorType.ItemCenter) {
- (size / 2f)
- } else {
- 0f
- }
+ offset -
+ if (anchorType == ScalingLazyListAnchorType.ItemCenter) {
+ (size / 2f)
+ } else {
+ 0f
+ }
diff --git a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/ProgressIndicator.kt b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/ProgressIndicator.kt
index 940cacc..a798053 100644
--- a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/ProgressIndicator.kt
+++ b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/ProgressIndicator.kt
@@ -45,42 +45,44 @@
import kotlin.math.min
/**
- * Determinate <a href="https://material.io/components/progress-indicators#circular-progress-indicators" class="external" target="_blank">Material Design circular progress indicator</a>.
+ * Determinate <a
+ * href="https://material.io/components/progress-indicators#circular-progress-indicators"
+ * class="external" target="_blank">Material Design circular progress indicator</a>.
*
* Progress indicators express the proportion of completion of an ongoing task.
*
- * [Progress Indicator doc](https://developer.android.com/training/wearables/components/progress-indicator)
- * 
+ * [Progress Indicator
+ * doc](https://developer.android.com/training/wearables/components/progress-indicator) 
*
- * There is no animation between [progress] values by default, but progress can be animated
- * with the recommended [ProgressIndicatorDefaults.ProgressAnimationSpec],
- * as in the following example:
+ * There is no animation between [progress] values by default, but progress can be animated with the
+ * recommended [ProgressIndicatorDefaults.ProgressAnimationSpec], as in the following example:
+ *
* @sample androidx.wear.compose.material.samples.CircularProgressIndicatorWithAnimation
*
- * [CircularProgressIndicator] supports a gap in the circular track between
- * [endAngle] and [startAngle], which leaves room for other content,
- * such as [TimeText] at the top of the screen. Example:
+ * [CircularProgressIndicator] supports a gap in the circular track between [endAngle] and
+ * [startAngle], which leaves room for other content, such as [TimeText] at the top of the screen.
+ * Example:
+ *
* @sample androidx.wear.compose.material.samples.CircularProgressIndicatorFullscreenWithGap
*
* @param modifier Modifier to be applied to the CircularProgressIndicator
* @param progress The progress of this progress indicator where 0.0 represents no progress and 1.0
- * represents completion. Values outside of this range are coerced into the range 0..1.
- * @param startAngle The starting position of the progress arc,
- * measured clockwise in degrees (0 to 360) from the 3 o'clock position. For example, 0 and 360
- * represent 3 o'clock, 90 and 180 represent 6 o'clock and 9 o'clock respectively.
- * Default is 270 degrees (top of the screen)
- * @param endAngle The ending position of the progress arc,
- * measured clockwise in degrees (0 to 360) from the 3 o'clock position. For example, 0 and 360
- * represent 3 o'clock, 90 and 180 represent 6 o'clock and 9 o'clock respectively.
- * By default equal to [startAngle]
+ * represents completion. Values outside of this range are coerced into the range 0..1.
+ * @param startAngle The starting position of the progress arc, measured clockwise in degrees (0
+ * to 360) from the 3 o'clock position. For example, 0 and 360 represent 3 o'clock, 90 and 180
+ * represent 6 o'clock and 9 o'clock respectively. Default is 270 degrees (top of the screen)
+ * @param endAngle The ending position of the progress arc, measured clockwise in degrees (0 to 360)
+ * from the 3 o'clock position. For example, 0 and 360 represent 3 o'clock, 90 and 180 represent 6
+ * o'clock and 9 o'clock respectively. By default equal to [startAngle]
* @param indicatorColor The color of the progress indicator bar.
* @param trackColor The color of the background progress track.
* @param strokeWidth The stroke width for the progress indicator.
*/
@Composable
public fun CircularProgressIndicator(
- @FloatRange(from = 0.0, to = 1.0)
- progress: Float,
+ @FloatRange(from = 0.0, to = 1.0) progress: Float,
modifier: Modifier = Modifier,
startAngle: Float = 270f,
endAngle: Float = startAngle,
@@ -103,41 +105,35 @@
onDrawWithContent {
// Draw a background
- drawCircularIndicator(
- startAngle,
- backgroundSweep,
- trackColor,
- stroke
- )
+ drawCircularIndicator(startAngle, backgroundSweep, trackColor, stroke)
// Draw a progress
- drawCircularIndicator(
- startAngle,
- progressSweep,
- indicatorColor,
- stroke
- )
+ drawCircularIndicator(startAngle, progressSweep, indicatorColor, stroke)
}
}
)
}
/**
- * Indeterminate <a href="https://material.io/components/progress-indicators#circular-progress-indicators" class="external" target="_blank">Material Design circular progress indicator</a>.
+ * Indeterminate <a
+ * href="https://material.io/components/progress-indicators#circular-progress-indicators"
+ * class="external" target="_blank">Material Design circular progress indicator</a>.
*
* Indeterminate progress indicator expresses an unspecified wait time and spins indefinitely.
*
- * [Progress Indicator doc](https://developer.android.com/training/wearables/components/progress-indicator)
- * 
+ * [Progress Indicator
+ * doc](https://developer.android.com/training/wearables/components/progress-indicator) 
*
* Example of indeterminate progress indicator:
+ *
* @sample androidx.wear.compose.material.samples.IndeterminateCircularProgressIndicator
*
* @param modifier Modifier to be applied to the CircularProgressIndicator
- * @param startAngle The starting position of the progress arc,
- * measured clockwise in degrees (0 to 360) from the 3 o'clock position. For example, 0 and 360
- * represent 3 o'clock, 90 and 180 represent 6 o'clock and 9 o'clock respectively.
- * Default is 270 degrees (top of the screen)
+ * @param startAngle The starting position of the progress arc, measured clockwise in degrees (0
+ * to 360) from the 3 o'clock position. For example, 0 and 360 represent 3 o'clock, 90 and 180
+ * represent 6 o'clock and 9 o'clock respectively. Default is 270 degrees (top of the screen)
* @param indicatorColor The color of the progress indicator bar.
* @param trackColor The color of the background progress track
* @param strokeWidth The stroke width for the progress indicator.
@@ -147,58 +143,61 @@
modifier: Modifier = Modifier,
startAngle: Float = 270f,
indicatorColor: Color = MaterialTheme.colors.onBackground,
- trackColor: Color = MaterialTheme.colors.onBackground
- .copy(alpha = 0.3f),
+ trackColor: Color = MaterialTheme.colors.onBackground.copy(alpha = 0.3f),
strokeWidth: Dp = IndeterminateStrokeWidth,
) {
val transition = rememberInfiniteTransition()
// The current rotation around the circle, so we know where to start the rotation from
- val currentRotation by transition.animateValue(
- 0,
- RotationsPerCycle,
- Int.VectorConverter,
- infiniteRepeatable(
- animation = tween(
- durationMillis = RotationDuration * RotationsPerCycle,
- easing = LinearEasing
+ val currentRotation by
+ transition.animateValue(
+ 0,
+ RotationsPerCycle,
+ Int.VectorConverter,
+ infiniteRepeatable(
+ animation =
+ tween(
+ durationMillis = RotationDuration * RotationsPerCycle,
+ easing = LinearEasing
+ )
)
)
- )
// How far forward (degrees) the base point should be from the start point
- val baseRotation by transition.animateFloat(
- 0f,
- BaseRotationAngle,
- infiniteRepeatable(
- animation = tween(
- durationMillis = RotationDuration,
- easing = LinearEasing
+ val baseRotation by
+ transition.animateFloat(
+ 0f,
+ BaseRotationAngle,
+ infiniteRepeatable(
+ animation = tween(durationMillis = RotationDuration, easing = LinearEasing)
)
)
- )
// How far forward (degrees) both the head and tail should be from the base point
- val endAngle by transition.animateFloat(
- 0f,
- JumpRotationAngle,
- infiniteRepeatable(
- animation = keyframes {
- durationMillis = HeadAndTailAnimationDuration + HeadAndTailDelayDuration
- 0f at 0 using CircularEasing
- JumpRotationAngle at HeadAndTailAnimationDuration
- }
+ val endAngle by
+ transition.animateFloat(
+ 0f,
+ JumpRotationAngle,
+ infiniteRepeatable(
+ animation =
+ keyframes {
+ durationMillis = HeadAndTailAnimationDuration + HeadAndTailDelayDuration
+ 0f at 0 using CircularEasing
+ JumpRotationAngle at HeadAndTailAnimationDuration
+ }
+ )
)
- )
- val startProgressAngle by transition.animateFloat(
- 0f,
- JumpRotationAngle,
- infiniteRepeatable(
- animation = keyframes {
- durationMillis = HeadAndTailAnimationDuration + HeadAndTailDelayDuration
- 0f at HeadAndTailDelayDuration using CircularEasing
- JumpRotationAngle at durationMillis
- }
+ val startProgressAngle by
+ transition.animateFloat(
+ 0f,
+ JumpRotationAngle,
+ infiniteRepeatable(
+ animation =
+ keyframes {
+ durationMillis = HeadAndTailAnimationDuration + HeadAndTailDelayDuration
+ 0f at HeadAndTailDelayDuration using CircularEasing
+ JumpRotationAngle at durationMillis
+ }
+ )
)
- )
// Canvas internally uses Spacer.drawBehind.
// Using Spacer.drawWithCache to optimize the stroke allocations.
@@ -207,8 +206,7 @@
.progressSemantics()
.size(IndeterminateCircularIndicatorDiameter)
.focusable()
- .drawWithCache
- {
+ .drawWithCache {
val stroke = Stroke(width = strokeWidth.toPx(), cap = StrokeCap.Round)
val currentRotationAngleOffset = (currentRotation * RotationAngleOffset) % 360f
@@ -227,12 +225,11 @@
stroke
)
}
- })
+ }
+ )
}
-/**
- * Contains the default values used for [CircularProgressIndicator].
- */
+/** Contains the default values used for [CircularProgressIndicator]. */
public object ProgressIndicatorDefaults {
/**
* Default stroke width for [CircularProgressIndicator]
@@ -259,13 +256,14 @@
* The default [AnimationSpec] that should be used when animating between progress in a
* determinate progress indicator.
*/
- public val ProgressAnimationSpec = SpringSpec(
- dampingRatio = Spring.DampingRatioNoBouncy,
- stiffness = Spring.StiffnessVeryLow,
- // The default threshold is 0.01, or 1% of the overall progress range, which is quite
- // large and noticeable.
- visibilityThreshold = 1 / 1000f
- )
+ public val ProgressAnimationSpec =
+ SpringSpec(
+ dampingRatio = Spring.DampingRatioNoBouncy,
+ stiffness = Spring.StiffnessVeryLow,
+ // The default threshold is 0.01, or 1% of the overall progress range, which is quite
+ // large and noticeable.
+ visibilityThreshold = 1 / 1000f
+ )
// CircularProgressIndicator Material specs
// Diameter of the indicator circle
@@ -318,10 +316,11 @@
startAngle = startAngle,
sweepAngle = sweep,
useCenter = false,
- topLeft = Offset(
- diameterOffset + (size.width - diameter) / 2,
- diameterOffset + (size.height - diameter) / 2
- ),
+ topLeft =
+ Offset(
+ diameterOffset + (size.width - diameter) / 2,
+ diameterOffset + (size.height - diameter) / 2
+ ),
size = Size(arcDimen, arcDimen),
style = stroke
)
diff --git a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/Providers.kt b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/Providers.kt
index 634663a..15991ab 100644
--- a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/Providers.kt
+++ b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/Providers.kt
@@ -79,31 +79,33 @@
internal fun <T> provideNullableScopeContent(
contentColor: State<Color>,
content: (@Composable T.() -> Unit)?
-): (@Composable T.() -> Unit)? = content?.let {
- {
- val color = contentColor.value
- CompositionLocalProvider(
- LocalContentColor provides color,
- LocalContentAlpha provides color.alpha
- ) {
- content()
+): (@Composable T.() -> Unit)? =
+ content?.let {
+ {
+ val color = contentColor.value
+ CompositionLocalProvider(
+ LocalContentColor provides color,
+ LocalContentAlpha provides color.alpha
+ ) {
+ content()
+ }
}
}
-}
internal fun <T> provideNullableScopeContent(
contentColor: State<Color>,
textStyle: TextStyle,
content: (@Composable T.() -> Unit)?
-): (@Composable T.() -> Unit)? = content?.let {
- {
- val color = contentColor.value
- CompositionLocalProvider(
- LocalContentColor provides color,
- LocalContentAlpha provides color.alpha,
- LocalTextStyle provides textStyle
- ) {
- content()
+): (@Composable T.() -> Unit)? =
+ content?.let {
+ {
+ val color = contentColor.value
+ CompositionLocalProvider(
+ LocalContentColor provides color,
+ LocalContentAlpha provides color.alpha,
+ LocalTextStyle provides textStyle
+ ) {
+ content()
+ }
}
}
-}
diff --git a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/RangeDefaults.kt b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/RangeDefaults.kt
index a4943d6..4d901dd 100644
--- a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/RangeDefaults.kt
+++ b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/RangeDefaults.kt
@@ -32,21 +32,24 @@
): Modifier {
val step = RangeDefaults.snapValueToStep(value, valueRange, steps)
return semantics(mergeDescendants = true) {
- if (!enabled) disabled()
- setProgress(
- action = { targetValue ->
- val newStepIndex = RangeDefaults.snapValueToStep(targetValue, valueRange, steps)
- if (step == newStepIndex) {
- false
- } else {
- onValueChange(targetValue)
- true
+ if (!enabled) disabled()
+ setProgress(
+ action = { targetValue ->
+ val newStepIndex = RangeDefaults.snapValueToStep(targetValue, valueRange, steps)
+ if (step == newStepIndex) {
+ false
+ } else {
+ onValueChange(targetValue)
+ true
+ }
}
- }
+ )
+ }
+ .progressSemantics(
+ RangeDefaults.calculateCurrentStepValue(step, steps, valueRange),
+ valueRange,
+ steps
)
- }.progressSemantics(
- RangeDefaults.calculateCurrentStepValue(step, steps, valueRange), valueRange, steps
- )
}
internal fun IntProgression.stepsNumber(): Int = (last - first) / step - 1
diff --git a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/Ripple.kt b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/Ripple.kt
index 2c3da14..9b652b6 100644
--- a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/Ripple.kt
+++ b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/Ripple.kt
@@ -41,17 +41,17 @@
/**
* Creates a Ripple using the provided values and values inferred from the theme.
*
- * A Ripple is a Material implementation of [Indication] that expresses different [Interaction]s
- * by drawing ripple animations and state layers.
+ * A Ripple is a Material implementation of [Indication] that expresses different [Interaction]s by
+ * drawing ripple animations and state layers.
*
- * A Ripple responds to [PressInteraction.Press] by starting a new animation, and
- * responds to other [Interaction]s by showing a fixed state layer with varying alpha values
- * depending on the [Interaction].
+ * A Ripple responds to [PressInteraction.Press] by starting a new animation, and responds to other
+ * [Interaction]s by showing a fixed state layer with varying alpha values depending on the
+ * [Interaction].
*
* [MaterialTheme] provides Ripples using [androidx.compose.foundation.LocalIndication], so a Ripple
* will be used as the default [Indication] inside components such as
- * [androidx.compose.foundation.clickable] and [androidx.compose.foundation.indication], in
- * addition to Material provided components that use a Ripple as well.
+ * [androidx.compose.foundation.clickable] and [androidx.compose.foundation.indication], in addition
+ * to Material provided components that use a Ripple as well.
*
* You can also explicitly create a Ripple and provide it to custom components in order to change
* the parameters from the default, such as to create an unbounded ripple with a fixed size.
@@ -60,15 +60,14 @@
* [ripple] overload with a [ColorProducer] parameter. This will avoid unnecessary recompositions
* when changing the color, and preserve existing ripple state when the color changes.
*
- * @param bounded If true, ripples are clipped by the bounds of the target layout. Unbounded
- * ripples always animate from the target layout center, bounded ripples animate from the touch
- * position.
+ * @param bounded If true, ripples are clipped by the bounds of the target layout. Unbounded ripples
+ * always animate from the target layout center, bounded ripples animate from the touch position.
* @param radius the radius for the ripple. If [Dp.Unspecified] is provided then the size will be
- * calculated based on the target layout size.
+ * calculated based on the target layout size.
* @param color the color of the ripple. This color is usually the same color used by the text or
- * iconography in the component. This color will then have alpha applied to calculate the final
- * color used to draw the ripple. If [Color.Unspecified] is provided the color used will be
- * the default ripple color instead.
+ * iconography in the component. This color will then have alpha applied to calculate the final
+ * color used to draw the ripple. If [Color.Unspecified] is provided the color used will be the
+ * default ripple color instead.
*/
@Stable
fun ripple(
@@ -86,17 +85,17 @@
/**
* Creates a Ripple using the provided values and values inferred from the theme.
*
- * A Ripple is a Material implementation of [Indication] that expresses different [Interaction]s
- * by drawing ripple animations and state layers.
+ * A Ripple is a Material implementation of [Indication] that expresses different [Interaction]s by
+ * drawing ripple animations and state layers.
*
- * A Ripple responds to [PressInteraction.Press] by starting a new ripple animation, and
- * responds to other [Interaction]s by showing a fixed state layer with varying alpha values
- * depending on the [Interaction].
+ * A Ripple responds to [PressInteraction.Press] by starting a new ripple animation, and responds to
+ * other [Interaction]s by showing a fixed state layer with varying alpha values depending on the
+ * [Interaction].
*
* [MaterialTheme] provides Ripples using [androidx.compose.foundation.LocalIndication], so a Ripple
* will be used as the default [Indication] inside components such as
- * [androidx.compose.foundation.clickable] and [androidx.compose.foundation.indication], in
- * addition to Material provided components that use a Ripple as well.
+ * [androidx.compose.foundation.clickable] and [androidx.compose.foundation.indication], in addition
+ * to Material provided components that use a Ripple as well.
*
* You can also explicitly create a Ripple and provide it to custom components in order to change
* the parameters from the default, such as to create an unbounded ripple with a fixed size.
@@ -106,16 +105,16 @@
* unnecessary recompositions.
*
* @param color the color of the ripple. This color is usually the same color used by the text or
- * iconography in the component. This color will then have alpha applied to calculate the final
- * * color used to draw the ripple. If you are creating this [ColorProducer] outside of composition
- * (where it will be automatically remembered), make sure that its instance is stable
- * (such as by remembering the object that holds it), or remember the returned [ripple] object to
- * make sure that ripple nodes are not being created each recomposition.
- * @param bounded If true, ripples are clipped by the bounds of the target layout. Unbounded
- * ripples always animate from the target layout center, bounded ripples animate from the touch
- * position.
+ * iconography in the component. This color will then have alpha applied to calculate the final
+ * * color used to draw the ripple. If you are creating this [ColorProducer] outside of
+ * composition (where it will be automatically remembered), make sure that its instance is
+ * stable (such as by remembering the object that holds it), or remember the returned [ripple]
+ * object to make sure that ripple nodes are not being created each recomposition.
+ *
+ * @param bounded If true, ripples are clipped by the bounds of the target layout. Unbounded ripples
+ * always animate from the target layout center, bounded ripples animate from the touch position.
* @param radius the radius for the ripple. If [Dp.Unspecified] is provided then the size will be
- * calculated based on the target layout size.
+ * calculated based on the target layout size.
*/
@Stable
fun ripple(
@@ -126,16 +125,14 @@
return RippleNodeFactory(bounded, radius, color)
}
-/**
- * Default values used by [ripple].
- */
+/** Default values used by [ripple]. */
private object RippleDefaults {
/**
* Represents the default color that will be used for a ripple if a color has not been
* explicitly set on the ripple instance.
*
- * @param contentColor the color of content (text or iconography) in the component that
- * contains the ripple.
+ * @param contentColor the color of content (text or iconography) in the component that contains
+ * the ripple.
*/
fun rippleColor(
contentColor: Color,
@@ -155,8 +152,8 @@
/**
* Temporary CompositionLocal to allow configuring whether the old ripple implementation that uses
* the deprecated [androidx.compose.material.ripple.RippleTheme] API should be used in Material
- * components and LocalIndication, instead of the new [ripple] API. This flag defaults to false,
- * and will be removed after one stable release: it should only be used to temporarily unblock
+ * components and LocalIndication, instead of the new [ripple] API. This flag defaults to false, and
+ * will be removed after one stable release: it should only be used to temporarily unblock
* upgrading.
*
* Provide this CompositionLocal before you provide [MaterialTheme] to make sure it is correctly
@@ -167,7 +164,9 @@
@get:ExperimentalWearMaterialApi
@ExperimentalWearMaterialApi
val LocalUseFallbackRippleImplementation: ProvidableCompositionLocal<Boolean> =
- staticCompositionLocalOf { false }
+ staticCompositionLocalOf {
+ false
+ }
// TODO: b/304985887 - remove after one stable release
@Suppress("DEPRECATION_ERROR")
@@ -194,13 +193,12 @@
@Composable
override fun defaultColor() = RippleDefaults.rippleColor(LocalContentColor.current)
- @Deprecated("Super method is deprecated")
- @Composable
- override fun rippleAlpha() = RippleAlpha
+ @Deprecated("Super method is deprecated") @Composable override fun rippleAlpha() = RippleAlpha
}
@Stable
-private class RippleNodeFactory private constructor(
+private class RippleNodeFactory
+private constructor(
private val bounded: Boolean,
private val radius: Dp,
private val colorProducer: ColorProducer?,
@@ -212,11 +210,7 @@
colorProducer: ColorProducer
) : this(bounded, radius, colorProducer, Color.Unspecified)
- constructor(
- bounded: Boolean,
- radius: Dp,
- color: Color
- ) : this(bounded, radius, null, color)
+ constructor(bounded: Boolean, radius: Dp, color: Color) : this(bounded, radius, null, color)
override fun create(interactionSource: InteractionSource): DelegatableNode {
val colorProducer = colorProducer ?: ColorProducer { color }
@@ -269,23 +263,18 @@
}
}
-private val DefaultBoundedRipple = RippleNodeFactory(
- bounded = true,
- radius = Dp.Unspecified,
- color = Color.Unspecified
-)
+private val DefaultBoundedRipple =
+ RippleNodeFactory(bounded = true, radius = Dp.Unspecified, color = Color.Unspecified)
-private val DefaultUnboundedRipple = RippleNodeFactory(
- bounded = false,
- radius = Dp.Unspecified,
- color = Color.Unspecified
-)
+private val DefaultUnboundedRipple =
+ RippleNodeFactory(bounded = false, radius = Dp.Unspecified, color = Color.Unspecified)
private val CalculateRippleAlpha = { RippleAlpha }
-private val RippleAlpha = RippleAlpha(
- pressedAlpha = 0.10f,
- focusedAlpha = 0.12f,
- draggedAlpha = 0.08f,
- hoveredAlpha = 0.04f
-)
+private val RippleAlpha =
+ RippleAlpha(
+ pressedAlpha = 0.10f,
+ focusedAlpha = 0.12f,
+ draggedAlpha = 0.08f,
+ hoveredAlpha = 0.04f
+ )
diff --git a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/Scaffold.kt b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/Scaffold.kt
index fb7965a..425bf72b 100644
--- a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/Scaffold.kt
+++ b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/Scaffold.kt
@@ -23,16 +23,16 @@
/**
* Scaffold implements the basic Wear Material Design visual layout structure.
*
- * This component provides API to put together several material components to construct your
- * screen, by ensuring proper layout strategy for them and collecting necessary data so these
- * components will work together correctly.
+ * This component provides API to put together several material components to construct your screen,
+ * by ensuring proper layout strategy for them and collecting necessary data so these components
+ * will work together correctly.
*
* The Scaffold provides the main application structure in a Wear Material application. It provides
* slots for the different parts of the application and sensible defaults were appropriate.
*
* The layout of the Wear Scaffold is typically z-layered with decorations such as
- * [PositionIndicator], [HorizontalPageIndicator] and [Vignette]
- * applied in the order laid out in the Wear Material Design guidance.
+ * [PositionIndicator], [HorizontalPageIndicator] and [Vignette] applied in the order laid out in
+ * the Wear Material Design guidance.
*
* Simple example of a Scaffold with a [ScalingLazyColumn] as the main application content and a
* scroll indicator to show the position of the items in the ScalingLazyColumn as.
@@ -41,16 +41,16 @@
*
* @param modifier optional Modifier for the root of the [Scaffold]
* @param vignette a full screen slot for applying a vignette over the contents of the scaffold. The
- * vignette is used to blur the screen edges when the main content is scrollable content that
- * extends beyond the screen edge.
+ * vignette is used to blur the screen edges when the main content is scrollable content that
+ * extends beyond the screen edge.
* @param positionIndicator slot for optional position indicator used to display information about
- * the position of the Scaffold's contents. Usually a [PositionIndicator]. Common use cases for the
- * position indicator are scroll indication for a list or rsb/bezel indication such as volume.
- * @param pageIndicator slot for optional page indicator used to display information about
- * the selected page of the Scaffold's contents. Usually a [HorizontalPageIndicator]. Common use case for the
- * page indicator is a pager with horizontally swipeable pages.
+ * the position of the Scaffold's contents. Usually a [PositionIndicator]. Common use cases for
+ * the position indicator are scroll indication for a list or rsb/bezel indication such as volume.
+ * @param pageIndicator slot for optional page indicator used to display information about the
+ * selected page of the Scaffold's contents. Usually a [HorizontalPageIndicator]. Common use case
+ * for the page indicator is a pager with horizontally swipeable pages.
* @param timeText time and potential application status message to display at the top middle of the
- * screen. Expected to be a TimeText component.
+ * screen. Expected to be a TimeText component.
* @param content Slot for composable screen content
*/
@Composable
diff --git a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/ScalingLazyColumn.kt b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/ScalingLazyColumn.kt
index 5ca39eb..d7e9d65 100644
--- a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/ScalingLazyColumn.kt
+++ b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/ScalingLazyColumn.kt
@@ -59,22 +59,21 @@
import androidx.wear.compose.foundation.lazy.CombinedPaddingValues
import androidx.wear.compose.foundation.lazy.verticalNegativePadding
-/**
- * Receiver scope which is used by [ScalingLazyColumn].
- */
-@Deprecated("Was moved to androidx.wear.compose.foundation.lazy package. " +
- "Please use it instead")
+/** Receiver scope which is used by [ScalingLazyColumn]. */
+@Deprecated(
+ "Was moved to androidx.wear.compose.foundation.lazy package. " + "Please use it instead"
+)
@ScalingLazyScopeMarker
public sealed interface ScalingLazyListScope {
/**
* Adds a single item.
*
- * @param key a stable and unique key representing the item. Using the same key
- * for multiple items in the list is not allowed. Type of the key should be saveable
- * via Bundle on Android. If null is passed the position in the list will represent the key.
- * When you specify the key the scroll position will be maintained based on the key, which
- * means if you add/remove items before the current visible item the item with the given key
- * will be kept as the first visible one.
+ * @param key a stable and unique key representing the item. Using the same key for multiple
+ * items in the list is not allowed. Type of the key should be saveable via Bundle on Android.
+ * If null is passed the position in the list will represent the key. When you specify the key
+ * the scroll position will be maintained based on the key, which means if you add/remove
+ * items before the current visible item the item with the given key will be kept as the first
+ * visible one.
* @param content the content of the item
*/
fun item(key: Any? = null, content: @Composable ScalingLazyListItemScope.() -> Unit)
@@ -83,12 +82,12 @@
* Adds a [count] of items.
*
* @param count the items count
- * @param key a factory of stable and unique keys representing the item. Using the same key
- * for multiple items in the list is not allowed. Type of the key should be saveable
- * via Bundle on Android. If null is passed the position in the list will represent the key.
- * When you specify the key the scroll position will be maintained based on the key, which
- * means if you add/remove items before the current visible item the item with the given key
- * will be kept as the first visible one.
+ * @param key a factory of stable and unique keys representing the item. Using the same key for
+ * multiple items in the list is not allowed. Type of the key should be saveable via Bundle on
+ * Android. If null is passed the position in the list will represent the key. When you
+ * specify the key the scroll position will be maintained based on the key, which means if you
+ * add/remove items before the current visible item the item with the given key will be kept
+ * as the first visible one.
* @param itemContent the content displayed by a single item
*/
fun items(
@@ -102,100 +101,107 @@
* Adds a list of items.
*
* @param items the data list
- * @param key a factory of stable and unique keys representing the item. Using the same key
- * for multiple items in the list is not allowed. Type of the key should be saveable
- * via Bundle on Android. If null is passed the position in the list will represent the key.
- * When you specify the key the scroll position will be maintained based on the key, which
- * means if you add/remove items before the current visible item the item with the given key
- * will be kept as the first visible one.
+ * @param key a factory of stable and unique keys representing the item. Using the same key for
+ * multiple items in the list is not allowed. Type of the key should be saveable via Bundle on
+ * Android. If null is passed the position in the list will represent the key. When you specify
+ * the key the scroll position will be maintained based on the key, which means if you add/remove
+ * items before the current visible item the item with the given key will be kept as the first
+ * visible one.
* @param itemContent the content displayed by a single item
*/
-@Deprecated("Was moved to androidx.wear.compose.foundation.lazy package. " +
- "Please use it instead")
+@Deprecated(
+ "Was moved to androidx.wear.compose.foundation.lazy package. " + "Please use it instead"
+)
public inline fun <T> ScalingLazyListScope.items(
items: List<T>,
noinline key: ((item: T) -> Any)? = null,
crossinline itemContent: @Composable ScalingLazyListItemScope.(item: T) -> Unit
-) = items(items.size, if (key != null) { index: Int -> key(items[index]) } else null) {
- itemContent(items[it])
-}
+) =
+ items(items.size, if (key != null) { index: Int -> key(items[index]) } else null) {
+ itemContent(items[it])
+ }
/**
* Adds a list of items where the content of an item is aware of its index.
*
* @param items the data list
- * @param key a factory of stable and unique keys representing the item. Using the same key
- * for multiple items in the list is not allowed. Type of the key should be saveable
- * via Bundle on Android. If null is passed the position in the list will represent the key.
- * When you specify the key the scroll position will be maintained based on the key, which
- * means if you add/remove items before the current visible item the item with the given key
- * will be kept as the first visible one.
+ * @param key a factory of stable and unique keys representing the item. Using the same key for
+ * multiple items in the list is not allowed. Type of the key should be saveable via Bundle on
+ * Android. If null is passed the position in the list will represent the key. When you specify
+ * the key the scroll position will be maintained based on the key, which means if you add/remove
+ * items before the current visible item the item with the given key will be kept as the first
+ * visible one.
* @param itemContent the content displayed by a single item
*/
-@Deprecated("Was moved to androidx.wear.compose.foundation.lazy package. " +
- "Please use it instead")
+@Deprecated(
+ "Was moved to androidx.wear.compose.foundation.lazy package. " + "Please use it instead"
+)
inline fun <T> ScalingLazyListScope.itemsIndexed(
items: List<T>,
noinline key: ((index: Int, item: T) -> Any)? = null,
crossinline itemContent: @Composable ScalingLazyListItemScope.(index: Int, item: T) -> Unit
-) = items(items.size, if (key != null) { index: Int -> key(index, items[index]) } else null) {
- itemContent(it, items[it])
-}
+) =
+ items(items.size, if (key != null) { index: Int -> key(index, items[index]) } else null) {
+ itemContent(it, items[it])
+ }
/**
* Adds an array of items.
*
* @param items the data array
- * @param key a factory of stable and unique keys representing the item. Using the same key
- * for multiple items in the list is not allowed. Type of the key should be saveable
- * via Bundle on Android. If null is passed the position in the list will represent the key.
- * When you specify the key the scroll position will be maintained based on the key, which
- * means if you add/remove items before the current visible item the item with the given key
- * will be kept as the first visible one.
+ * @param key a factory of stable and unique keys representing the item. Using the same key for
+ * multiple items in the list is not allowed. Type of the key should be saveable via Bundle on
+ * Android. If null is passed the position in the list will represent the key. When you specify
+ * the key the scroll position will be maintained based on the key, which means if you add/remove
+ * items before the current visible item the item with the given key will be kept as the first
+ * visible one.
* @param itemContent the content displayed by a single item
*/
-@Deprecated("Was moved to androidx.wear.compose.foundation.lazy package. " +
- "Please use it instead")
+@Deprecated(
+ "Was moved to androidx.wear.compose.foundation.lazy package. " + "Please use it instead"
+)
inline fun <T> ScalingLazyListScope.items(
items: Array<T>,
noinline key: ((item: T) -> Any)? = null,
crossinline itemContent: @Composable ScalingLazyListItemScope.(item: T) -> Unit
-) = items(items.size, if (key != null) { index: Int -> key(items[index]) } else null) {
- itemContent(items[it])
-}
+) =
+ items(items.size, if (key != null) { index: Int -> key(items[index]) } else null) {
+ itemContent(items[it])
+ }
/**
* Adds an array of items where the content of an item is aware of its index.
*
* @param items the data array
- * @param key a factory of stable and unique keys representing the item. Using the same key
- * for multiple items in the list is not allowed. Type of the key should be saveable
- * via Bundle on Android. If null is passed the position in the list will represent the key.
- * When you specify the key the scroll position will be maintained based on the key, which
- * means if you add/remove items before the current visible item the item with the given key
- * will be kept as the first visible one.
+ * @param key a factory of stable and unique keys representing the item. Using the same key for
+ * multiple items in the list is not allowed. Type of the key should be saveable via Bundle on
+ * Android. If null is passed the position in the list will represent the key. When you specify
+ * the key the scroll position will be maintained based on the key, which means if you add/remove
+ * items before the current visible item the item with the given key will be kept as the first
+ * visible one.
* @param itemContent the content displayed by a single item
*/
-@Deprecated("Was moved to androidx.wear.compose.foundation.lazy package. " +
- "Please use it instead")
+@Deprecated(
+ "Was moved to androidx.wear.compose.foundation.lazy package. " + "Please use it instead"
+)
public inline fun <T> ScalingLazyListScope.itemsIndexed(
items: Array<T>,
noinline key: ((index: Int, item: T) -> Any)? = null,
crossinline itemContent: @Composable ScalingLazyListItemScope.(index: Int, item: T) -> Unit
-) = items(items.size, if (key != null) { index: Int -> key(index, items[index]) } else null) {
- itemContent(it, items[it])
-}
+) =
+ items(items.size, if (key != null) { index: Int -> key(index, items[index]) } else null) {
+ itemContent(it, items[it])
+ }
@Immutable
-@Deprecated("Was moved to androidx.wear.compose.foundation.lazy package. " +
- "Please use it instead")
+@Deprecated(
+ "Was moved to androidx.wear.compose.foundation.lazy package. " + "Please use it instead"
+)
@kotlin.jvm.JvmInline
public value class ScalingLazyListAnchorType internal constructor(internal val type: Int) {
companion object {
- /**
- * Place the center of the item on (or as close to) the center line of the viewport
- */
+ /** Place the center of the item on (or as close to) the center line of the viewport */
val ItemCenter = ScalingLazyListAnchorType(0)
/**
@@ -217,20 +223,19 @@
/**
* Parameters to determine which list item and offset to calculate auto-centering spacing for. The
* default values are [itemIndex] = 1 and [itemOffset] = 0. This will provide sufficient padding for
- * the second item (index = 1) in the list being centerable. This is to match the Wear UX
- * guidelines that a typical list will have a ListHeader item as the first item in the list
- * (index = 0) and that this should not be scrollable into the middle of the viewport, instead the
- * first list item that a user can interact with (index = 1) would be the first that would be in the
- * center.
+ * the second item (index = 1) in the list being centerable. This is to match the Wear UX guidelines
+ * that a typical list will have a ListHeader item as the first item in the list (index = 0) and
+ * that this should not be scrollable into the middle of the viewport, instead the first list item
+ * that a user can interact with (index = 1) would be the first that would be in the center.
*
* If your use case is different and you want all list items to be able to be scrolled to the
* viewport middle, including the first item in the list then set [itemIndex] = 0.
*
- * The higher the value for [itemIndex] you provide the less auto centering padding will be
- * provided as the amount of padding needed to allow that item to be centered will reduce.
- * Even for a list of short items (such as [CompactChip]) setting [itemIndex] above 3 or 4 is likely
- * to result in no auto-centering padding being provided as items with index 3 or 4 will probably
- * already be naturally scrollable to the center of the viewport.
+ * The higher the value for [itemIndex] you provide the less auto centering padding will be provided
+ * as the amount of padding needed to allow that item to be centered will reduce. Even for a list of
+ * short items (such as [CompactChip]) setting [itemIndex] above 3 or 4 is likely to result in no
+ * auto-centering padding being provided as items with index 3 or 4 will probably already be
+ * naturally scrollable to the center of the viewport.
*
* [itemOffset] allows adjustment of the items position relative the [ScalingLazyColumn]s
* [ScalingLazyListAnchorType]. This can be useful if you need fine grained control over item
@@ -244,21 +249,22 @@
* center.
*
* @param itemIndex Which list item index to enable auto-centering from. Space (padding) will be
- * added such that items with index [itemIndex] or greater will be able to be scrolled to the center
- * of the viewport. If the developer wants to add additional space to allow other list items to also
- * be scrollable to the center they can use contentPadding on the ScalingLazyColumn. If the
- * developer wants custom control over position and spacing they can switch off autoCentering
- * and provide contentPadding.
- *
- * @param itemOffset What offset, if any, to apply when calculating space for auto-centering
- * the [itemIndex] item. E.g. itemOffset can be used if the developer wants to align the viewport
- * center in the gap between two list items.
+ * added such that items with index [itemIndex] or greater will be able to be scrolled to the
+ * center of the viewport. If the developer wants to add additional space to allow other list
+ * items to also be scrollable to the center they can use contentPadding on the ScalingLazyColumn.
+ * If the developer wants custom control over position and spacing they can switch off
+ * autoCentering and provide contentPadding.
+ * @param itemOffset What offset, if any, to apply when calculating space for auto-centering the
+ * [itemIndex] item. E.g. itemOffset can be used if the developer wants to align the viewport
+ * center in the gap between two list items.
*
* For an example of a [ScalingLazyColumn] with an explicit itemOffset see:
+ *
* @sample androidx.wear.compose.material.samples.ScalingLazyColumnEdgeAnchoredAndAnimatedScrollTo
*/
-@Deprecated("Was moved to androidx.wear.compose.foundation.lazy package. " +
- "Please use it instead")
+@Deprecated(
+ "Was moved to androidx.wear.compose.foundation.lazy package. " + "Please use it instead"
+)
@Immutable
public class AutoCenteringParams(
// @IntRange(from = 0)
@@ -283,60 +289,64 @@
* A scrolling scaling/fisheye list component that forms a key part of the Wear Material Design
* language. Provides scaling and transparency effects to the content items.
*
- * [ScalingLazyColumn] is designed to be able to handle potentially large numbers of content
- * items. Content items are only materialized and composed when needed.
+ * [ScalingLazyColumn] is designed to be able to handle potentially large numbers of content items.
+ * Content items are only materialized and composed when needed.
*
- * If scaling/fisheye functionality is not required then a [LazyColumn] should be considered
- * instead to avoid any overhead of measuring and calculating scaling and transparency effects for
- * the content items.
+ * If scaling/fisheye functionality is not required then a [LazyColumn] should be considered instead
+ * to avoid any overhead of measuring and calculating scaling and transparency effects for the
+ * content items.
*
* Example of a [ScalingLazyColumn] with default parameters:
+ *
* @sample androidx.wear.compose.material.samples.SimpleScalingLazyColumn
*
* Example of a [ScalingLazyColumn] using [ScalingLazyListAnchorType.ItemStart] anchoring, in this
* configuration the edge of list items is aligned to the center of the screen. Also this example
* shows scrolling to a clicked list item with [ScalingLazyListState.animateScrollToItem]:
+ *
* @sample androidx.wear.compose.material.samples.ScalingLazyColumnEdgeAnchoredAndAnimatedScrollTo
*
* Example of a [ScalingLazyColumn] with snap of items to the viewport center:
+ *
* @sample androidx.wear.compose.material.samples.SimpleScalingLazyColumnWithSnap
*
* Example of a [ScalingLazyColumn] where [autoCentering] has been disabled and explicit
* [contentPadding] provided to ensure there is space above the first and below the last list item
* to allow them to be scrolled into view on circular screens:
+ *
* @sample androidx.wear.compose.material.samples.SimpleScalingLazyColumnWithContentPadding
*
* For more information, see the
- * [Lists](https://developer.android.com/training/wearables/components/lists)
- * guide.
+ * [Lists](https://developer.android.com/training/wearables/components/lists) guide.
*
* @param modifier The modifier to be applied to the component
* @param state The state of the component
* @param contentPadding The padding to apply around the contents
* @param reverseLayout reverse the direction of scrolling and layout, when `true` items will be
- * composed from the bottom to the top
- * @param verticalArrangement The vertical arrangement of the layout's children. This allows us
- * to add spacing between items and specify the arrangement of the items when we have not enough
- * of them to fill the whole minimum size
+ * composed from the bottom to the top
+ * @param verticalArrangement The vertical arrangement of the layout's children. This allows us to
+ * add spacing between items and specify the arrangement of the items when we have not enough of
+ * them to fill the whole minimum size
* @param horizontalAlignment the horizontal alignment applied to the items
* @param flingBehavior Logic describing fling behavior. If snapping is required use
- * [ScalingLazyColumnDefaults.snapFlingBehavior].
- * @param userScrollEnabled whether the scrolling via the user gestures or accessibility actions
- * is allowed. You can still scroll programmatically using the state even when it is disabled.
+ * [ScalingLazyColumnDefaults.snapFlingBehavior].
+ * @param userScrollEnabled whether the scrolling via the user gestures or accessibility actions is
+ * allowed. You can still scroll programmatically using the state even when it is disabled.
* @param scalingParams The parameters to configure the scaling and transparency effects for the
- * component
+ * component
* @param anchorType How to anchor list items to the center-line of the viewport
* @param autoCentering AutoCenteringParams parameter to control whether space/padding should be
- * automatically added to make sure that list items can be scrolled into the center of the viewport
- * (based on their [anchorType]). If non-null then space will be added before the first list item,
- * if needed, to ensure that items with indexes greater than or equal to the itemIndex (offset by
- * itemOffset pixels) will be able to be scrolled to the center of the viewport. Similarly space
- * will be added at the end of the list to ensure that items can be scrolled up to the center. If
- * null no automatic space will be added and instead the developer can use [contentPadding] to
- * manually arrange the items.
+ * automatically added to make sure that list items can be scrolled into the center of the
+ * viewport (based on their [anchorType]). If non-null then space will be added before the first
+ * list item, if needed, to ensure that items with indexes greater than or equal to the itemIndex
+ * (offset by itemOffset pixels) will be able to be scrolled to the center of the viewport.
+ * Similarly space will be added at the end of the list to ensure that items can be scrolled up to
+ * the center. If null no automatic space will be added and instead the developer can use
+ * [contentPadding] to manually arrange the items.
*/
-@Deprecated("Was moved to androidx.wear.compose.foundation.lazy package. " +
- "Please use it instead")
+@Deprecated(
+ "Was moved to androidx.wear.compose.foundation.lazy package. " + "Please use it instead"
+)
@Composable
public fun ScalingLazyColumn(
modifier: Modifier = Modifier,
@@ -364,10 +374,8 @@
with(density) {
val extraPadding = extraPaddingInPixels.toDp()
- val combinedPaddingValues = CombinedPaddingValues(
- contentPadding = contentPadding,
- extraPadding = extraPadding
- )
+ val combinedPaddingValues =
+ CombinedPaddingValues(contentPadding = contentPadding, extraPadding = extraPadding)
val beforeContentPaddingInPx =
if (reverseLayout) contentPadding.calculateBottomPadding().roundToPx()
@@ -380,16 +388,18 @@
val itemScope =
ScalingLazyListItemScopeImpl(
density = density,
- constraints = constraints.offset(
- horizontal = -(
- contentPadding.calculateStartPadding(layoutDirection) +
- contentPadding.calculateEndPadding(layoutDirection)
- ).toPx().toInt(),
- vertical = -(
- contentPadding.calculateTopPadding() +
- contentPadding.calculateBottomPadding()
- ).roundToPx()
- )
+ constraints =
+ constraints.offset(
+ horizontal =
+ -(contentPadding.calculateStartPadding(layoutDirection) +
+ contentPadding.calculateEndPadding(layoutDirection))
+ .toPx()
+ .toInt(),
+ vertical =
+ -(contentPadding.calculateTopPadding() +
+ contentPadding.calculateBottomPadding())
+ .roundToPx()
+ )
)
// Set up transient state
@@ -398,26 +408,26 @@
state.beforeContentPaddingPx.value = beforeContentPaddingInPx
state.afterContentPaddingPx.value = afterContentPaddingInPx
state.viewportHeightPx.value = constraints.maxHeight
- state.gapBetweenItemsPx.value =
- verticalArrangement.spacing.roundToPx()
+ state.gapBetweenItemsPx.value = verticalArrangement.spacing.roundToPx()
state.anchorType.value = anchorType
state.autoCentering.value = autoCentering
state.reverseLayout.value = reverseLayout
state.localInspectionMode.value = LocalInspectionMode.current
LazyColumn(
- modifier = Modifier
- .clipToBounds()
- .verticalNegativePadding(extraPadding)
- .onGloballyPositioned {
- val layoutInfo = state.layoutInfo
- if (!initialized &&
- layoutInfo is DefaultScalingLazyListLayoutInfo &&
- layoutInfo.readyForInitialScroll
- ) {
- initialized = true
- }
- },
+ modifier =
+ Modifier.clipToBounds()
+ .verticalNegativePadding(extraPadding)
+ .onGloballyPositioned {
+ val layoutInfo = state.layoutInfo
+ if (
+ !initialized &&
+ layoutInfo is DefaultScalingLazyListLayoutInfo &&
+ layoutInfo.readyForInitialScroll
+ ) {
+ initialized = true
+ }
+ },
horizontalAlignment = horizontalAlignment,
contentPadding = combinedPaddingValues,
reverseLayout = reverseLayout,
@@ -426,21 +436,19 @@
flingBehavior = flingBehavior,
userScrollEnabled = userScrollEnabled,
) {
- val scope = ScalingLazyListScopeImpl(
- state = state,
- scope = this,
- itemScope = itemScope
- )
+ val scope =
+ ScalingLazyListScopeImpl(state = state, scope = this, itemScope = itemScope)
// Only add spacers if autoCentering == true as we have to consider the impact of
// vertical spacing between items.
if (autoCentering != null) {
item {
Spacer(
- modifier = remember(state) {
- Modifier.autoCenteringHeight {
- state.topAutoCenteringItemSizePx
+ modifier =
+ remember(state) {
+ Modifier.autoCenteringHeight {
+ state.topAutoCenteringItemSizePx
+ }
}
- }
)
}
}
@@ -448,29 +456,27 @@
if (autoCentering != null) {
item {
Spacer(
- modifier = remember(state) {
- Modifier.autoCenteringHeight {
- state.bottomAutoCenteringItemSizePx
+ modifier =
+ remember(state) {
+ Modifier.autoCenteringHeight {
+ state.bottomAutoCenteringItemSizePx
+ }
}
- }
)
}
}
}
if (initialized) {
- LaunchedEffect(state) {
- state.scrollToInitialItem()
- }
+ LaunchedEffect(state) { state.scrollToInitialItem() }
}
}
}
}
-/**
- * Contains the default values used by [ScalingLazyColumn]
- */
-@Deprecated("Was moved to androidx.wear.compose.foundation.lazy package. " +
- "Please use it instead")
+/** Contains the default values used by [ScalingLazyColumn] */
+@Deprecated(
+ "Was moved to androidx.wear.compose.foundation.lazy package. " + "Please use it instead"
+)
public object ScalingLazyColumnDefaults {
/**
* Creates a [ScalingParams] that represents the scaling and alpha properties for a
@@ -490,11 +496,11 @@
* the potential for larger list items to start their transition earlier (closer to the center)
* than smaller items.
*
- * [minTransitionArea] and [maxTransitionArea] are both in the range [0f..1f] and are
- * the fraction of the distance between the edge of the viewport and the center of
- * the viewport. E.g. a value of 0.2f for minTransitionArea and 0.75f for maxTransitionArea
- * determines that all transition lines will fall between 1/5th (20%) and 3/4s (75%) of the
- * distance between the viewport edge and center.
+ * [minTransitionArea] and [maxTransitionArea] are both in the range [0f..1f] and are the
+ * fraction of the distance between the edge of the viewport and the center of the viewport.
+ * E.g. a value of 0.2f for minTransitionArea and 0.75f for maxTransitionArea determines that
+ * all transition lines will fall between 1/5th (20%) and 3/4s (75%) of the distance between the
+ * viewport edge and center.
*
* The size of the each item is used to determine where within the transition area range
* minTransitionArea..maxTransitionArea the actual transition line will be. [minElementHeight]
@@ -510,71 +516,59 @@
*
* If an item is smaller than or equal to minElementSize its transition line with be at
* minTransitionArea and if it is larger than or equal to maxElementSize its transition line
- * will be at maxTransitionArea.
+ * will be at maxTransitionArea.
*
- * For example, if we take the default values for minTransitionArea = 0.2f and
- * maxTransitionArea = 0.6f and minElementSize = 0.2f and maxElementSize= 0.8f then an item
- * with a height of 0.4f (40%) of the viewport height is one third of way between
- * minElementSize and maxElementSize, (0.4f - 0.2f) / (0.8f - 0.2f) = 0.33f. So its transition
- * line would be one third of way between 0.2f and 0.6f, transition line = 0.2f + (0.6f -
- * 0.2f) * 0.33f = 0.33f.
+ * For example, if we take the default values for minTransitionArea = 0.2f and maxTransitionArea
+ * = 0.6f and minElementSize = 0.2f and maxElementSize= 0.8f then an item with a height of 0.4f
+ * (40%) of the viewport height is one third of way between minElementSize and maxElementSize,
+ * (0.4f - 0.2f) / (0.8f - 0.2f) = 0.33f. So its transition line would be one third of way
+ * between 0.2f and 0.6f, transition line = 0.2f + (0.6f - 0.2f) * 0.33f = 0.33f.
*
- * Once the position of the transition line is established we now have a transition area
- * for the item, e.g. in the example above the item will start/finish its transitions when it
- * is 0.33f (33%) of the distance from the edge of the viewport and will start/finish its
- * transitions at the viewport edge.
+ * Once the position of the transition line is established we now have a transition area for the
+ * item, e.g. in the example above the item will start/finish its transitions when it is 0.33f
+ * (33%) of the distance from the edge of the viewport and will start/finish its transitions at
+ * the viewport edge.
*
- * The scaleInterpolator is used to determine how much of the scaling and alpha to apply
- * as the item transits through the transition area.
+ * The scaleInterpolator is used to determine how much of the scaling and alpha to apply as the
+ * item transits through the transition area.
*
- * The edge of the item furthest from the edge of the screen is used as a scaling trigger
- * point for each item.
+ * The edge of the item furthest from the edge of the screen is used as a scaling trigger point
+ * for each item.
*
- * @param edgeScale What fraction of the full size of the item to scale it by when most
- * scaled, e.g. at the edge of the viewport. A value between [0f,1f], so a value of 0.2f
- * means to scale an item to 20% of its normal size.
- *
- * @param edgeAlpha What fraction of the full transparency of the item to draw it with
- * when closest to the edge of the screen. A value between [0f,1f], so a value of
- * 0.2f means to set the alpha of an item to 20% of its normal value.
- *
- * @param minElementHeight The minimum element height as a ratio of the viewport size to use
- * for determining the transition point within ([minTransitionArea], [maxTransitionArea])
- * that a given content item will start to be transitioned. Items smaller than
- * [minElementHeight] will be treated as if [minElementHeight]. Must be less than or equal to
- * [maxElementHeight].
- *
- * @param maxElementHeight The maximum element height as a ratio of the viewport size to use
- * for determining the transition point within ([minTransitionArea], [maxTransitionArea])
- * that a given content item will start to be transitioned. Items larger than [maxElementHeight]
- * will be treated as if [maxElementHeight]. Must be greater than or equal to
- * [minElementHeight].
- *
- * @param minTransitionArea The lower bound of the transition line area, closest to the
- * edge of the viewport. Defined as a fraction (value between 0f..1f) of the distance between
- * the viewport edge and viewport center line. Must be less than or equal to
- * [maxTransitionArea].
- *
- * @param maxTransitionArea The upper bound of the transition line area, closest to the
- * center of the viewport. The fraction (value between 0f..1f) of the distance
- * between the viewport edge and viewport center line. Must be greater
- * than or equal to [minTransitionArea].
- *
- * @param scaleInterpolator An interpolator to use to determine how to apply scaling as a
- * item transitions across the scaling transition area.
- *
+ * @param edgeScale What fraction of the full size of the item to scale it by when most scaled,
+ * e.g. at the edge of the viewport. A value between [0f,1f], so a value of 0.2f means to
+ * scale an item to 20% of its normal size.
+ * @param edgeAlpha What fraction of the full transparency of the item to draw it with when
+ * closest to the edge of the screen. A value between [0f,1f], so a value of 0.2f means to set
+ * the alpha of an item to 20% of its normal value.
+ * @param minElementHeight The minimum element height as a ratio of the viewport size to use for
+ * determining the transition point within ([minTransitionArea], [maxTransitionArea]) that a
+ * given content item will start to be transitioned. Items smaller than [minElementHeight]
+ * will be treated as if [minElementHeight]. Must be less than or equal to [maxElementHeight].
+ * @param maxElementHeight The maximum element height as a ratio of the viewport size to use for
+ * determining the transition point within ([minTransitionArea], [maxTransitionArea]) that a
+ * given content item will start to be transitioned. Items larger than [maxElementHeight] will
+ * be treated as if [maxElementHeight]. Must be greater than or equal to [minElementHeight].
+ * @param minTransitionArea The lower bound of the transition line area, closest to the edge of
+ * the viewport. Defined as a fraction (value between 0f..1f) of the distance between the
+ * viewport edge and viewport center line. Must be less than or equal to [maxTransitionArea].
+ * @param maxTransitionArea The upper bound of the transition line area, closest to the center
+ * of the viewport. The fraction (value between 0f..1f) of the distance between the viewport
+ * edge and viewport center line. Must be greater than or equal to [minTransitionArea].
+ * @param scaleInterpolator An interpolator to use to determine how to apply scaling as a item
+ * transitions across the scaling transition area.
* @param viewportVerticalOffsetResolver The additional padding to consider above and below the
- * viewport of a [ScalingLazyColumn] when considering which items to draw in the viewport. If
- * set to 0 then no additional padding will be provided and only the items which would appear
- * in the viewport before any scaling is applied will be considered for drawing, this may
- * leave blank space at the top and bottom of the viewport where the next available item
- * could have been drawn once other items have been scaled down in size. The larger this
- * value is set to will allow for more content items to be considered for drawing in the
- * viewport, however there is a performance cost associated with materializing items that are
- * subsequently not drawn. The higher/more extreme the scaling parameters that are applied to
- * the [ScalingLazyColumn] the more padding may be needed to ensure there are always enough
- * content items available to be rendered. By default will be 5% of the maxHeight of the
- * viewport above and below the content.
+ * viewport of a [ScalingLazyColumn] when considering which items to draw in the viewport. If
+ * set to 0 then no additional padding will be provided and only the items which would appear
+ * in the viewport before any scaling is applied will be considered for drawing, this may
+ * leave blank space at the top and bottom of the viewport where the next available item could
+ * have been drawn once other items have been scaled down in size. The larger this value is
+ * set to will allow for more content items to be considered for drawing in the viewport,
+ * however there is a performance cost associated with materializing items that are
+ * subsequently not drawn. The higher/more extreme the scaling parameters that are applied to
+ * the [ScalingLazyColumn] the more padding may be needed to ensure there are always enough
+ * content items available to be rendered. By default will be 5% of the maxHeight of the
+ * viewport above and below the content.
*/
fun scalingParams(
edgeScale: Float = 0.7f,
@@ -585,16 +579,17 @@
maxTransitionArea: Float = 0.55f,
scaleInterpolator: Easing = CubicBezierEasing(0.3f, 0f, 0.7f, 1f),
viewportVerticalOffsetResolver: (Constraints) -> Int = { (it.maxHeight / 20f).toInt() }
- ): ScalingParams = DefaultScalingParams(
- edgeScale = edgeScale,
- edgeAlpha = edgeAlpha,
- minElementHeight = minElementHeight,
- maxElementHeight = maxElementHeight,
- minTransitionArea = minTransitionArea,
- maxTransitionArea = maxTransitionArea,
- scaleInterpolator = scaleInterpolator,
- viewportVerticalOffsetResolver = viewportVerticalOffsetResolver
- )
+ ): ScalingParams =
+ DefaultScalingParams(
+ edgeScale = edgeScale,
+ edgeAlpha = edgeAlpha,
+ minElementHeight = minElementHeight,
+ maxElementHeight = maxElementHeight,
+ minTransitionArea = minTransitionArea,
+ maxTransitionArea = maxTransitionArea,
+ scaleInterpolator = scaleInterpolator,
+ viewportVerticalOffsetResolver = viewportVerticalOffsetResolver
+ )
/**
* Create and remember a [FlingBehavior] that will represent natural fling curve with snap to
@@ -602,7 +597,7 @@
*
* @param state the state of the [ScalingLazyColumn]
* @param snapOffset an optional offset to be applied when snapping the item. After the snap the
- * snapped items offset will be [snapOffset].
+ * snapped items offset will be [snapOffset].
* @param decay the decay to use
*/
@Composable
@@ -633,12 +628,7 @@
override fun item(key: Any?, content: @Composable (ScalingLazyListItemScope.() -> Unit)) {
val startIndex = currentStartIndex
scope.item(key = key) {
- ScalingLazyColumnItemWrapper(
- startIndex,
- state,
- itemScope,
- content
- )
+ ScalingLazyColumnItemWrapper(startIndex, state, itemScope, content)
}
currentStartIndex++
}
@@ -650,11 +640,7 @@
) {
val startIndex = currentStartIndex
scope.items(count = count, key = key) {
- ScalingLazyColumnItemWrapper(
- startIndex + it,
- state = state,
- itemScope = itemScope
- ) {
+ ScalingLazyColumnItemWrapper(startIndex + it, state = state, itemScope = itemScope) {
itemContent(it)
}
}
@@ -670,44 +656,44 @@
content: @Composable (ScalingLazyListItemScope.() -> Unit)
) {
Box(
- modifier = Modifier.graphicsLayer {
- val reverseLayout = state.reverseLayout.value!!
- val anchorType = state.anchorType.value!!
- val items = state.layoutInfo.internalVisibleItemInfo()
- val currentItem = items.fastFirstOrNull { it.index == index }
- if (currentItem != null) {
- alpha = currentItem.alpha
- scaleX = currentItem.scale
- scaleY = currentItem.scale
- // Calculate how much to adjust/translate the position of the list item by
- // determining the different between the unadjusted start position based on the
- // underlying LazyList layout and the start position adjusted to take into account
- // scaling of the list items. Items further from the middle of the visible viewport
- // will be subject to more adjustment.
- if (currentItem.scale > 0f) {
- val offsetAdjust = currentItem.startOffset(anchorType) -
- currentItem.unadjustedStartOffset(anchorType)
- translationY = if (reverseLayout) -offsetAdjust else offsetAdjust
- transformOrigin = TransformOrigin(
- pivotFractionX = 0.5f,
- pivotFractionY = if (reverseLayout) 1.0f else 0.0f
- )
+ modifier =
+ Modifier.graphicsLayer {
+ val reverseLayout = state.reverseLayout.value!!
+ val anchorType = state.anchorType.value!!
+ val items = state.layoutInfo.internalVisibleItemInfo()
+ val currentItem = items.fastFirstOrNull { it.index == index }
+ if (currentItem != null) {
+ alpha = currentItem.alpha
+ scaleX = currentItem.scale
+ scaleY = currentItem.scale
+ // Calculate how much to adjust/translate the position of the list item by
+ // determining the different between the unadjusted start position based on the
+ // underlying LazyList layout and the start position adjusted to take into
+ // account
+ // scaling of the list items. Items further from the middle of the visible
+ // viewport
+ // will be subject to more adjustment.
+ if (currentItem.scale > 0f) {
+ val offsetAdjust =
+ currentItem.startOffset(anchorType) -
+ currentItem.unadjustedStartOffset(anchorType)
+ translationY = if (reverseLayout) -offsetAdjust else offsetAdjust
+ transformOrigin =
+ TransformOrigin(
+ pivotFractionX = 0.5f,
+ pivotFractionY = if (reverseLayout) 1.0f else 0.0f
+ )
+ }
}
}
- }
) {
itemScope.content()
}
}
-private fun Modifier.autoCenteringHeight(getHeight: () -> Int) =
- layout { measurable, constraints ->
- val height = getHeight()
- val placeable = measurable.measure(
- constraints.copy(minHeight = height, maxHeight = height)
- )
+private fun Modifier.autoCenteringHeight(getHeight: () -> Int) = layout { measurable, constraints ->
+ val height = getHeight()
+ val placeable = measurable.measure(constraints.copy(minHeight = height, maxHeight = height))
- layout(placeable.width, placeable.height) {
- placeable.place(IntOffset.Zero)
- }
- }
+ layout(placeable.width, placeable.height) { placeable.place(IntOffset.Zero) }
+}
diff --git a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/ScalingLazyColumnMeasure.kt b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/ScalingLazyColumnMeasure.kt
index bf11025..7ae61dc 100644
--- a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/ScalingLazyColumnMeasure.kt
+++ b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/ScalingLazyColumnMeasure.kt
@@ -34,14 +34,14 @@
/**
* Parameters to control the scaling of the contents of a [ScalingLazyColumn].
*
- * Items in the ScalingLazyColumn have scaling and alpha effects applied to them depending on
- * their position in the viewport. The closer to the edge (top or bottom) of the viewport that
- * they are the greater the down scaling and transparency that is applied. Note that scaling and
- * transparency effects are applied from the center of the viewport (nearest to full size and normal
+ * Items in the ScalingLazyColumn have scaling and alpha effects applied to them depending on their
+ * position in the viewport. The closer to the edge (top or bottom) of the viewport that they are
+ * the greater the down scaling and transparency that is applied. Note that scaling and transparency
+ * effects are applied from the center of the viewport (nearest to full size and normal
* transparency) towards the edge (items can be smaller and more transparent).
*
- * Deciding how much scaling and alpha to apply is based on the position and size of the item
- * and on a series of properties that are used to determine the transition area for each item.
+ * Deciding how much scaling and alpha to apply is based on the position and size of the item and on
+ * a series of properties that are used to determine the transition area for each item.
*
* The transition area is defined by the edge of the screen and a transition line which is
* calculated for each item in the list. There are two symmetrical transition lines/areas one at the
@@ -57,84 +57,78 @@
* lines interact with the opposite edges of the list item top with bottom, bottom with top it is
* often desirable to have inverted transition lines for large list items.
*
- * [minTransitionArea] and [maxTransitionArea] are both in the range [0f..1f] and are
- * the fraction of the distance between the edges of the viewport. E.g. a value of 0.2f for
- * minTransitionArea and 0.75f for maxTransitionArea determines that all transition lines will fall
- * between 1/5th (20%) and 3/4s (75%) of the height of the viewport.
+ * [minTransitionArea] and [maxTransitionArea] are both in the range [0f..1f] and are the fraction
+ * of the distance between the edges of the viewport. E.g. a value of 0.2f for minTransitionArea and
+ * 0.75f for maxTransitionArea determines that all transition lines will fall between 1/5th (20%)
+ * and 3/4s (75%) of the height of the viewport.
*
* The size of the each item is used to determine where within the transition area range
- * minTransitionArea..maxTransitionArea the actual transition line will be. [minElementHeight]
- * and [maxElementHeight] are used along with the item height (as a fraction of the viewport
- * height in the range [0f..1f]) to find the transition line. So if the items size is 0.25f
- * (25%) of way between minElementSize..maxElementSize then the transition line will be 0.25f
- * (25%) of the way between minTransitionArea..maxTransitionArea.
+ * minTransitionArea..maxTransitionArea the actual transition line will be. [minElementHeight] and
+ * [maxElementHeight] are used along with the item height (as a fraction of the viewport height in
+ * the range [0f..1f]) to find the transition line. So if the items size is 0.25f (25%) of way
+ * between minElementSize..maxElementSize then the transition line will be 0.25f (25%) of the way
+ * between minTransitionArea..maxTransitionArea.
*
* A list item smaller than minElementHeight is rounded up to minElementHeight and larger than
- * maxElementHeight is rounded down to maxElementHeight. Whereabouts the items height sits
- * between minElementHeight..maxElementHeight is then used to determine where the transition
- * line sits between minTransitionArea..maxTransition area.
+ * maxElementHeight is rounded down to maxElementHeight. Whereabouts the items height sits between
+ * minElementHeight..maxElementHeight is then used to determine where the transition line sits
+ * between minTransitionArea..maxTransition area.
*
* If an item is smaller than or equal to minElementSize its transition line with be at
- * minTransitionArea and if it is larger than or equal to maxElementSize its transition line
- * will be at maxTransitionArea.
+ * minTransitionArea and if it is larger than or equal to maxElementSize its transition line will be
+ * at maxTransitionArea.
*
- * For example, if we take the default values for minTransitionArea = 0.2f and
- * maxTransitionArea = 0.6f and minElementSize = 0.2f and maxElementSize= 0.8f then an item
- * with a height of 0.4f (40%) of the viewport height is one third of way between
- * minElementSize and maxElementSize, (0.4f - 0.2f) / (0.8f - 0.2f) = 0.33f. So its transition
- * line would be one third of way between 0.2f and 0.6f, transition line = 0.2f + (0.6f -
- * 0.2f) * 0.33f = 0.33f.
+ * For example, if we take the default values for minTransitionArea = 0.2f and maxTransitionArea =
+ * 0.6f and minElementSize = 0.2f and maxElementSize= 0.8f then an item with a height of 0.4f (40%)
+ * of the viewport height is one third of way between minElementSize and maxElementSize, (0.4f -
+ * 0.2f) / (0.8f - 0.2f) = 0.33f. So its transition line would be one third of way between 0.2f and
+ * 0.6f, transition line = 0.2f + (0.6f - 0.2f) * 0.33f = 0.33f.
*
- * Once the position of the transition line is established we now have a transition area
- * for the item, e.g. in the example above the item will start/finish its transitions when it
- * is 0.33f (33%) of the distance from the edge of the viewport and will start/finish its
- * transitions at the viewport edge.
+ * Once the position of the transition line is established we now have a transition area for the
+ * item, e.g. in the example above the item will start/finish its transitions when it is 0.33f (33%)
+ * of the distance from the edge of the viewport and will start/finish its transitions at the
+ * viewport edge.
*
- * The scaleInterpolator is used to determine how much of the scaling and alpha to apply
- * as the item transits through the transition area.
+ * The scaleInterpolator is used to determine how much of the scaling and alpha to apply as the item
+ * transits through the transition area.
*
- * The edge of the item furthest from the edge of the screen is used as a scaling trigger
- * point for each item.
+ * The edge of the item furthest from the edge of the screen is used as a scaling trigger point for
+ * each item.
*/
@Stable
-@Deprecated("Was moved to androidx.wear.compose.foundation.lazy package. " +
- "Please use it instead")
+@Deprecated(
+ "Was moved to androidx.wear.compose.foundation.lazy package. " + "Please use it instead"
+)
public interface ScalingParams {
/**
- * What fraction of the full size of the item to scale it by when most
- * scaled, e.g. at the edge of the viewport. A value between [0f,1f], so a value of 0.2f
- * means to scale an item to 20% of its normal size.
+ * What fraction of the full size of the item to scale it by when most scaled, e.g. at the edge
+ * of the viewport. A value between [0f,1f], so a value of 0.2f means to scale an item to 20% of
+ * its normal size.
*/
- @get:FloatRange(from = 0.0, to = 1.0)
- val edgeScale: Float
+ @get:FloatRange(from = 0.0, to = 1.0) val edgeScale: Float
/**
- * What fraction of the full transparency of the item to draw it with
- * when closest to the edge of the screen. A value between [0f,1f], so a value of
- * 0.2f means to set the alpha of an item to 20% of its normal value.
+ * What fraction of the full transparency of the item to draw it with when closest to the edge
+ * of the screen. A value between [0f,1f], so a value of 0.2f means to set the alpha of an item
+ * to 20% of its normal value.
*/
- @get:FloatRange(from = 0.0, to = 1.0)
- val edgeAlpha: Float
+ @get:FloatRange(from = 0.0, to = 1.0) val edgeAlpha: Float
/**
- * The maximum element height as a ratio of the viewport size to use
- * for determining the transition point within ([minTransitionArea], [maxTransitionArea])
- * that a given content item will start to be transitioned. Items larger than [maxElementHeight]
- * will be treated as if [maxElementHeight]. Must be greater than or equal to
- * [minElementHeight].
+ * The maximum element height as a ratio of the viewport size to use for determining the
+ * transition point within ([minTransitionArea], [maxTransitionArea]) that a given content item
+ * will start to be transitioned. Items larger than [maxElementHeight] will be treated as if
+ * [maxElementHeight]. Must be greater than or equal to [minElementHeight].
*/
- @get:FloatRange(from = 0.0, to = 1.0)
- val minElementHeight: Float
+ @get:FloatRange(from = 0.0, to = 1.0) val minElementHeight: Float
/**
- * The maximum element height as a ratio of the viewport size to use
- * for determining the transition point within ([minTransitionArea], [maxTransitionArea])
- * that a given content item will start to be transitioned. Items larger than [maxElementHeight]
- * will be treated as if [maxElementHeight]. Must be greater than or equal to
- * [minElementHeight].
+ * The maximum element height as a ratio of the viewport size to use for determining the
+ * transition point within ([minTransitionArea], [maxTransitionArea]) that a given content item
+ * will start to be transitioned. Items larger than [maxElementHeight] will be treated as if
+ * [maxElementHeight]. Must be greater than or equal to [minElementHeight].
*/
- @get:FloatRange(from = 0.0, to = 1.0)
- val maxElementHeight: Float
+ @get:FloatRange(from = 0.0, to = 1.0) val maxElementHeight: Float
/**
* The lower bound of the transition line area, closest to the edge of the viewport. Defined as
@@ -150,13 +144,12 @@
* list items exist. Depending on the size of the list item the specific point in the area is
* calculated.
*/
- @get:FloatRange(from = 0.0, to = 1.0)
- val minTransitionArea: Float
+ @get:FloatRange(from = 0.0, to = 1.0) val minTransitionArea: Float
/**
- * The upper bound of the transition line area, closest to the
- * center of the viewport. The fraction (value between 0f..1f) of the distance
- * between the viewport edges. Must be greater than or equal to [minTransitionArea].
+ * The upper bound of the transition line area, closest to the center of the viewport. The
+ * fraction (value between 0f..1f) of the distance between the viewport edges. Must be greater
+ * than or equal to [minTransitionArea].
*
* For transition lines a value of 0f means that the transition line is at the viewport edge,
* e.g. no transition, a value of 0.25f means that the transition line is 25% of the screen size
@@ -167,8 +160,7 @@
* list items exist. Depending on the size of the list item the specific point in the area is
* calculated.
*/
- @get:FloatRange(from = 0.0, to = 1.0)
- val maxTransitionArea: Float
+ @get:FloatRange(from = 0.0, to = 1.0) val maxTransitionArea: Float
/**
* An interpolator to use to determine how to apply scaling as a item transitions across the
@@ -177,18 +169,17 @@
val scaleInterpolator: Easing
/**
- * The additional padding to consider above and below the
- * viewport of a [ScalingLazyColumn] when considering which items to draw in the viewport. If
- * set to 0 then no additional padding will be provided and only the items which would appear
- * in the viewport before any scaling is applied will be considered for drawing, this may
- * leave blank space at the top and bottom of the viewport where the next available item
- * could have been drawn once other items have been scaled down in size. The larger this
- * value is set to will allow for more content items to be considered for drawing in the
- * viewport, however there is a performance cost associated with materializing items that are
- * subsequently not drawn. The higher/more extreme the scaling parameters that are applied to
- * the [ScalingLazyColumn] the more padding may be needed to ensure there are always enough
- * content items available to be rendered. By default will be 20% of the maxHeight of the
- * viewport above and below the content.
+ * The additional padding to consider above and below the viewport of a [ScalingLazyColumn] when
+ * considering which items to draw in the viewport. If set to 0 then no additional padding will
+ * be provided and only the items which would appear in the viewport before any scaling is
+ * applied will be considered for drawing, this may leave blank space at the top and bottom of
+ * the viewport where the next available item could have been drawn once other items have been
+ * scaled down in size. The larger this value is set to will allow for more content items to be
+ * considered for drawing in the viewport, however there is a performance cost associated with
+ * materializing items that are subsequently not drawn. The higher/more extreme the scaling
+ * parameters that are applied to the [ScalingLazyColumn] the more padding may be needed to
+ * ensure there are always enough content items available to be rendered. By default will be 20%
+ * of the maxHeight of the viewport above and below the content.
*
* @param viewportConstraints the viewports constraints
*/
@@ -208,12 +199,12 @@
) : ScalingParams {
init {
- check(
- minElementHeight <= maxElementHeight
- ) { "minElementHeight must be less than or equal to maxElementHeight" }
- check(
- minTransitionArea <= maxTransitionArea
- ) { "minTransitionArea must be less than or equal to maxTransitionArea" }
+ check(minElementHeight <= maxElementHeight) {
+ "minElementHeight must be less than or equal to maxElementHeight"
+ }
+ check(minTransitionArea <= maxTransitionArea) {
+ "minTransitionArea must be less than or equal to maxTransitionArea"
+ }
}
override fun resolveViewportVerticalOffset(viewportConstraints: Constraints): Int {
@@ -274,8 +265,8 @@
* @param viewPortEndPx The end position of the component's viewport in pixels
* @param itemTopPx The top of the content item in pixels.
* @param itemBottomPx The bottom of the content item in pixels.
- * @param scalingParams The parameters that determine where the item's scaling transition line
- * is, how scaling and transparency to apply.
+ * @param scalingParams The parameters that determine where the item's scaling transition line is,
+ * how scaling and transparency to apply.
*/
internal fun calculateScaleAndAlpha(
viewPortStartPx: Int,
@@ -298,16 +289,19 @@
// Work out the scaling line based on size, this is a value between 0.0..1.0
val sizeRatio =
- inverseLerp(scalingParams.minElementHeight, scalingParams.maxElementHeight,
- heightAsFractionOfViewPort)
+ inverseLerp(
+ scalingParams.minElementHeight,
+ scalingParams.maxElementHeight,
+ heightAsFractionOfViewPort
+ )
val scalingLineAsFractionOfViewPort =
lerp(scalingParams.minTransitionArea, scalingParams.maxTransitionArea, sizeRatio)
if (itemEdgeAsFractionOfViewPort < scalingLineAsFractionOfViewPort) {
// We are scaling
- val scalingProgressRaw = 1f - itemEdgeAsFractionOfViewPort /
- scalingLineAsFractionOfViewPort
+ val scalingProgressRaw =
+ 1f - itemEdgeAsFractionOfViewPort / scalingLineAsFractionOfViewPort
val scalingInterpolated = scalingParams.scaleInterpolator.transform(scalingProgressRaw)
scaleToApply = lerp(1.0f, scalingParams.edgeScale, scalingInterpolated)
@@ -320,22 +314,22 @@
/**
* Create a [ScalingLazyListItemInfo] given an unscaled start and end position for an item.
*
- * @param itemStart the x-axis position of a list item. The x-axis position takes into account
- * any adjustment to the original position based on the scaling of other list items.
- * @param item the original item info used to provide the pre-scaling position and size
- * information for the item.
- * @param verticalAdjustment the amount of vertical adjustment to apply to item positions to
- * allow for content padding in order to determine the adjusted position of the item within the
- * viewport in order to correctly calculate the scaling to apply.
+ * @param itemStart the x-axis position of a list item. The x-axis position takes into account any
+ * adjustment to the original position based on the scaling of other list items.
+ * @param item the original item info used to provide the pre-scaling position and size information
+ * for the item.
+ * @param verticalAdjustment the amount of vertical adjustment to apply to item positions to allow
+ * for content padding in order to determine the adjusted position of the item within the viewport
+ * in order to correctly calculate the scaling to apply.
* @param viewportHeightPx the height of the viewport in pixels
* @param viewportCenterLinePx the center line of the viewport in pixels
* @param scalingParams the scaling params to use for determining the scaled size of the item
* @param beforeContentPaddingPx the number of pixels of padding before the first item
* @param anchorType the type of pivot to use for the center item when calculating position and
- * offset
- * @param visible a flag to determine whether the list items should be visible or transparent.
- * Items are normally visible, but can be drawn transparently when the list is not yet initialized,
- * unless we are in preview (LocalInspectionModel) mode.
+ * offset
+ * @param visible a flag to determine whether the list items should be visible or transparent. Items
+ * are normally visible, but can be drawn transparently when the list is not yet initialized,
+ * unless we are in preview (LocalInspectionModel) mode.
*/
internal fun calculateItemInfo(
itemStart: Int,
@@ -352,33 +346,40 @@
val adjustedItemStart = itemStart - verticalAdjustment
val adjustedItemEnd = itemStart + item.size - verticalAdjustment
- val scaleAndAlpha = calculateScaleAndAlpha(
- viewPortStartPx = 0, viewPortEndPx = viewportHeightPx, itemTopPx = adjustedItemStart,
- itemBottomPx = adjustedItemEnd, scalingParams = scalingParams
- )
+ val scaleAndAlpha =
+ calculateScaleAndAlpha(
+ viewPortStartPx = 0,
+ viewPortEndPx = viewportHeightPx,
+ itemTopPx = adjustedItemStart,
+ itemBottomPx = adjustedItemEnd,
+ scalingParams = scalingParams
+ )
val isAboveLine = (adjustedItemEnd + adjustedItemStart) < viewportHeightPx
val scaledHeight = (item.size * scaleAndAlpha.scale).roundToInt()
- val scaledItemTop = if (!isAboveLine) {
- itemStart
- } else {
- itemStart + item.size - scaledHeight
- }
+ val scaledItemTop =
+ if (!isAboveLine) {
+ itemStart
+ } else {
+ itemStart + item.size - scaledHeight
+ }
- val offset = convertToCenterOffset(
- anchorType = anchorType,
- itemScrollOffset = scaledItemTop,
- viewportCenterLinePx = viewportCenterLinePx,
- beforeContentPaddingInPx = beforeContentPaddingPx,
- itemSizeInPx = scaledHeight
- )
- val unadjustedOffset = convertToCenterOffset(
- anchorType = anchorType,
- itemScrollOffset = item.offset,
- viewportCenterLinePx = viewportCenterLinePx,
- beforeContentPaddingInPx = beforeContentPaddingPx,
- itemSizeInPx = item.size
- )
+ val offset =
+ convertToCenterOffset(
+ anchorType = anchorType,
+ itemScrollOffset = scaledItemTop,
+ viewportCenterLinePx = viewportCenterLinePx,
+ beforeContentPaddingInPx = beforeContentPaddingPx,
+ itemSizeInPx = scaledHeight
+ )
+ val unadjustedOffset =
+ convertToCenterOffset(
+ anchorType = anchorType,
+ itemScrollOffset = item.offset,
+ viewportCenterLinePx = viewportCenterLinePx,
+ beforeContentPaddingInPx = beforeContentPaddingPx,
+ itemSizeInPx = item.size
+ )
return DefaultScalingLazyListItemInfo(
// Adjust index to take into account the Spacer before the first list item
index = if (autoCentering != null) item.index - 1 else item.index,
@@ -438,8 +439,8 @@
}
/**
- * Calculate the offset from the viewport center line of the Start|Center of an items unadjusted
- * or scaled size. The for items with an height that is an odd number and that have
+ * Calculate the offset from the viewport center line of the Start|Center of an items unadjusted or
+ * scaled size. The for items with an height that is an odd number and that have
* ScalingLazyListAnchorType.Center the offset will be rounded down. E.g. An item which is 19 pixels
* in height will have a center offset of 9 pixes.
*
@@ -456,7 +457,8 @@
beforeContentPaddingInPx: Int,
itemSizeInPx: Int
): Int {
- return itemScrollOffset - viewportCenterLinePx + beforeContentPaddingInPx +
+ return itemScrollOffset - viewportCenterLinePx +
+ beforeContentPaddingInPx +
if (anchorType == ScalingLazyListAnchorType.ItemStart) {
0
} else {
@@ -464,23 +466,23 @@
}
}
-/**
- * Find the start offset of the list item w.r.t. the
- */
+/** Find the start offset of the list item w.r.t. the */
internal fun ScalingLazyListItemInfo.startOffset(anchorType: ScalingLazyListAnchorType) =
- offset - if (anchorType == ScalingLazyListAnchorType.ItemCenter) {
- (size / 2f)
- } else {
- 0f
- }
+ offset -
+ if (anchorType == ScalingLazyListAnchorType.ItemCenter) {
+ (size / 2f)
+ } else {
+ 0f
+ }
/**
* Find the start position of the list item from its unadjusted offset w.r.t. the ScalingLazyColumn
* center of viewport offset = 0 coordinate model.
*/
internal fun ScalingLazyListItemInfo.unadjustedStartOffset(anchorType: ScalingLazyListAnchorType) =
- unadjustedOffset - if (anchorType == ScalingLazyListAnchorType.ItemCenter) {
- (unadjustedSize / 2f)
- } else {
- 0f
- }
+ unadjustedOffset -
+ if (anchorType == ScalingLazyListAnchorType.ItemCenter) {
+ (unadjustedSize / 2f)
+ } else {
+ 0f
+ }
diff --git a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/ScalingLazyColumnSnapFlingBehavior.kt b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/ScalingLazyColumnSnapFlingBehavior.kt
index fb71229..2237c8c 100644
--- a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/ScalingLazyColumnSnapFlingBehavior.kt
+++ b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/ScalingLazyColumnSnapFlingBehavior.kt
@@ -41,51 +41,56 @@
) : FlingBehavior {
override suspend fun ScrollScope.performFling(initialVelocity: Float): Float {
- val animationState = AnimationState(
- initialValue = 0f,
- initialVelocity = initialVelocity,
- )
+ val animationState =
+ AnimationState(
+ initialValue = 0f,
+ initialVelocity = initialVelocity,
+ )
var lastValue = 0f
val visibleItemsInfo = state.layoutInfo.visibleItemsInfo
val isAFling = abs(initialVelocity) > 1f && visibleItemsInfo.size > 1
- val finalTarget = if (isAFling) {
- // Target we will land on given initialVelocity & decay
- val decayTarget = decay.calculateTargetValue(0f, initialVelocity)
- var endOfListReached = false
+ val finalTarget =
+ if (isAFling) {
+ // Target we will land on given initialVelocity & decay
+ val decayTarget = decay.calculateTargetValue(0f, initialVelocity)
+ var endOfListReached = false
- animationState.animateDecay(decay) {
- val delta = value - lastValue
- val consumed = scrollBy(delta)
- lastValue = value
+ animationState.animateDecay(decay) {
+ val delta = value - lastValue
+ val consumed = scrollBy(delta)
+ lastValue = value
- // When we are "slow" enough, switch from decay to the final snap.
- if (abs(velocity) < SNAP_SPEED_THRESHOLD) cancelAnimation()
+ // When we are "slow" enough, switch from decay to the final snap.
+ if (abs(velocity) < SNAP_SPEED_THRESHOLD) cancelAnimation()
- // If we can't consume the scroll, also stop.
- if (abs(delta - consumed) > 0.1f) {
- endOfListReached = true
- cancelAnimation()
+ // If we can't consume the scroll, also stop.
+ if (abs(delta - consumed) > 0.1f) {
+ endOfListReached = true
+ cancelAnimation()
+ }
}
- }
- if (endOfListReached) {
- // We couldn't scroll as much as we wanted, likely we reached the end of the list,
- // Snap to the current item and finish.
- scrollBy((snapOffset - state.centerItemScrollOffset).toFloat())
- return animationState.velocity
+ if (endOfListReached) {
+ // We couldn't scroll as much as we wanted, likely we reached the end of the
+ // list,
+ // Snap to the current item and finish.
+ scrollBy((snapOffset - state.centerItemScrollOffset).toFloat())
+ return animationState.velocity
+ } else {
+ // Now that scrolling slowed down, adjust the animation to land in the item
+ // closest
+ // to the original target. Note that the target may be off-screen, in that case
+ // we
+ // will land on the last visible item in that direction.
+ (state.layoutInfo.visibleItemsInfo
+ .fastMap { animationState.value + it.unadjustedOffset + snapOffset }
+ .fastMinByOrNull { abs(it - decayTarget) } ?: decayTarget)
+ }
} else {
- // Now that scrolling slowed down, adjust the animation to land in the item closest
- // to the original target. Note that the target may be off-screen, in that case we
- // will land on the last visible item in that direction.
- (state.layoutInfo.visibleItemsInfo
- .fastMap { animationState.value + it.unadjustedOffset + snapOffset }
- .fastMinByOrNull { abs(it - decayTarget) } ?: decayTarget)
+ // Not a fling, just snap to the current item.
+ (snapOffset - state.centerItemScrollOffset).toFloat()
}
- } else {
- // Not a fling, just snap to the current item.
- (snapOffset - state.centerItemScrollOffset).toFloat()
- }
// We have a velocity (animationState.velocity), and a target (finalTarget),
// Construct a cubic bezier with the given initial velocity, and ending at 0 speed,
@@ -102,10 +107,12 @@
val initialInertia = 0.5f
// Compute how much time we want to spend on the final snap, depending on the speed
- val finalSnapDuration = lerp(
- FINAL_SNAP_DURATION_MIN, FINAL_SNAP_DURATION_MAX,
- abs(initialSpeed) / SNAP_SPEED_THRESHOLD
- )
+ val finalSnapDuration =
+ lerp(
+ FINAL_SNAP_DURATION_MIN,
+ FINAL_SNAP_DURATION_MAX,
+ abs(initialSpeed) / SNAP_SPEED_THRESHOLD
+ )
// Initial control point. Has slope (velocity) adjustedSpeed and magnitude (inertia)
// initialInertia
@@ -113,13 +120,15 @@
val easingX0 = initialInertia / sqrt(1f + adjustedSpeed * adjustedSpeed)
val easingY0 = easingX0 * adjustedSpeed
- // Final control point. Has slope 0, unless that will make us accelerate then decelerate,
+ // Final control point. Has slope 0, unless that will make us accelerate then
+ // decelerate,
// in that case we set the slope to 1.
val easingX1 = 0.8f
val easingY1 = if (easingX0 > easingY0) 0.8f else 1f
animationState.animateTo(
- finalTarget, tween(
+ finalTarget,
+ tween(
(finalSnapDuration * 1000).roundToInt(),
easing = CubicBezierEasing(easingX0, easingY0, easingX1, easingY1)
)
diff --git a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/ScalingLazyListItemInfo.kt b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/ScalingLazyListItemInfo.kt
index def6417..82a9639 100644
--- a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/ScalingLazyListItemInfo.kt
+++ b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/ScalingLazyListItemInfo.kt
@@ -20,17 +20,14 @@
*
* @see ScalingLazyListLayoutInfo
*/
-@Deprecated("Was moved to androidx.wear.compose.foundation.lazy package. " +
- "Please use it instead")
+@Deprecated(
+ "Was moved to androidx.wear.compose.foundation.lazy package. " + "Please use it instead"
+)
public sealed interface ScalingLazyListItemInfo {
- /**
- * The index of the item in the list.
- */
+ /** The index of the item in the list. */
val index: Int
- /**
- * The key of the item which was passed to the item() or items() function.
- */
+ /** The key of the item which was passed to the item() or items() function. */
val key: Any
/**
@@ -42,9 +39,9 @@
* For [ScalingLazyListAnchorType.ItemCenter] the offset is from the center of the list item to
* the center-line of the viewport.
*
- * For [ScalingLazyListAnchorType.ItemStart] if is the offset
- * between the start (edge) of the item and the center-line of the viewport, for normal layout
- * this will be the top edge of the item, for reverseLayout it will be the bottom edge.
+ * For [ScalingLazyListAnchorType.ItemStart] if is the offset between the start (edge) of the
+ * item and the center-line of the viewport, for normal layout this will be the top edge of the
+ * item, for reverseLayout it will be the bottom edge.
*/
val unadjustedOffset: Int
@@ -57,9 +54,9 @@
* For [ScalingLazyListAnchorType.ItemCenter] the offset is from the center of the list item to
* the center-line of the viewport.
*
- * For [ScalingLazyListAnchorType.ItemStart] if is the offset
- * between the start (edge) of the item and the center-line of the viewport, for normal layout
- * this will be the top edge of the item, for reverseLayout it will be the bottom edge.
+ * For [ScalingLazyListAnchorType.ItemStart] if is the offset between the start (edge) of the
+ * item and the center-line of the viewport, for normal layout this will be the top edge of the
+ * item, for reverseLayout it will be the bottom edge.
*
* A positive value indicates that the item's anchor point is below the viewport center-line, a
* negative value indicates that the item anchor point is above the viewport center-line.
@@ -72,18 +69,12 @@
*/
val size: Int
- /**
- * How much scaling has been applied to the item, between 0 and 1
- */
+ /** How much scaling has been applied to the item, between 0 and 1 */
val scale: Float
- /**
- * How much alpha has been applied to the item, between 0 and 1
- */
+ /** How much alpha has been applied to the item, between 0 and 1 */
val alpha: Float
- /**
- * The original (before scaling) size of the list item
- */
+ /** The original (before scaling) size of the list item */
val unadjustedSize: Int
}
diff --git a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/ScalingLazyListItemScope.kt b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/ScalingLazyListItemScope.kt
index 2f2c6fad..55aa26b 100644
--- a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/ScalingLazyListItemScope.kt
+++ b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/ScalingLazyListItemScope.kt
@@ -27,33 +27,30 @@
import androidx.compose.ui.unit.Density
import androidx.compose.ui.unit.Dp
-/**
- * Receiver scope being used by the item content parameter of ScalingLazyColumn.
- */
+/** Receiver scope being used by the item content parameter of ScalingLazyColumn. */
@Stable
-@Deprecated("Was moved to androidx.wear.compose.foundation.lazy package. " +
- "Please use it instead")
+@Deprecated(
+ "Was moved to androidx.wear.compose.foundation.lazy package. " + "Please use it instead"
+)
@ScalingLazyScopeMarker
public sealed interface ScalingLazyListItemScope {
/**
* Have the content fill the [Constraints.maxWidth] and [Constraints.maxHeight] of the parent
* measurement constraints by setting the [minimum width][Constraints.minWidth] to be equal to
- * the [maximum width][Constraints.maxWidth] multiplied by [fraction] and the [minimum
- * height][Constraints.minHeight] to be equal to the [maximum height][Constraints.maxHeight]
- * multiplied by [fraction]. Note that, by default, the [fraction] is 1, so the modifier will
- * make the content fill the whole available space. [fraction] must be between `0` and `1`.
+ * the [maximum width][Constraints.maxWidth] multiplied by [fraction] and the
+ * [minimum height][Constraints.minHeight] to be equal to the
+ * [maximum height][Constraints.maxHeight] multiplied by [fraction]. Note that, by default, the
+ * [fraction] is 1, so the modifier will make the content fill the whole available space.
+ * [fraction] must be between `0` and `1`.
*
* Regular [Modifier.fillMaxSize] can't work inside the scrolling layouts as the items are
* measured with [Constraints.Infinity] as the constraints for the main axis.
*/
- fun Modifier.fillParentMaxSize(
- @FloatRange(from = 0.0, to = 1.0)
- fraction: Float = 1f
- ): Modifier
+ fun Modifier.fillParentMaxSize(@FloatRange(from = 0.0, to = 1.0) fraction: Float = 1f): Modifier
/**
- * Have the content fill the [Constraints.maxWidth] of the parent measurement constraints
- * by setting the [minimum width][Constraints.minWidth] to be equal to the
+ * Have the content fill the [Constraints.maxWidth] of the parent measurement constraints by
+ * setting the [minimum width][Constraints.minWidth] to be equal to the
* [maximum width][Constraints.maxWidth] multiplied by [fraction]. Note that, by default, the
* [fraction] is 1, so the modifier will make the content fill the whole parent width.
* [fraction] must be between `0` and `1`.
@@ -62,13 +59,12 @@
* items are measured with [Constraints.Infinity] as the constraints for the main axis.
*/
fun Modifier.fillParentMaxWidth(
- @FloatRange(from = 0.0, to = 1.0)
- fraction: Float = 1f
+ @FloatRange(from = 0.0, to = 1.0) fraction: Float = 1f
): Modifier
/**
- * Have the content fill the [Constraints.maxHeight] of the incoming measurement constraints
- * by setting the [minimum height][Constraints.minHeight] to be equal to the
+ * Have the content fill the [Constraints.maxHeight] of the incoming measurement constraints by
+ * setting the [minimum height][Constraints.minHeight] to be equal to the
* [maximum height][Constraints.maxHeight] multiplied by [fraction]. Note that, by default, the
* [fraction] is 1, so the modifier will make the content fill the whole parent height.
* [fraction] must be between `0` and `1`.
@@ -77,8 +73,7 @@
* items are measured with [Constraints.Infinity] as the constraints for the main axis.
*/
fun Modifier.fillParentMaxHeight(
- @FloatRange(from = 0.0, to = 1.0)
- fraction: Float = 1f
+ @FloatRange(from = 0.0, to = 1.0) fraction: Float = 1f
): Modifier
}
@@ -89,14 +84,10 @@
private val maxWidth: Dp = with(density) { constraints.maxWidth.toDp() }
private val maxHeight: Dp = with(density) { constraints.maxHeight.toDp() }
- override fun Modifier.fillParentMaxSize(fraction: Float) = size(
- maxWidth * fraction,
- maxHeight * fraction
- )
+ override fun Modifier.fillParentMaxSize(fraction: Float) =
+ size(maxWidth * fraction, maxHeight * fraction)
- override fun Modifier.fillParentMaxWidth(fraction: Float) =
- width(maxWidth * fraction)
+ override fun Modifier.fillParentMaxWidth(fraction: Float) = width(maxWidth * fraction)
- override fun Modifier.fillParentMaxHeight(fraction: Float) =
- height(maxHeight * fraction)
+ override fun Modifier.fillParentMaxHeight(fraction: Float) = height(maxHeight * fraction)
}
diff --git a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/ScalingLazyListLayoutInfo.kt b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/ScalingLazyListLayoutInfo.kt
index 7db894a..7f9f731 100644
--- a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/ScalingLazyListLayoutInfo.kt
+++ b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/ScalingLazyListLayoutInfo.kt
@@ -24,14 +24,12 @@
*
* Use [ScalingLazyListState.layoutInfo] to retrieve this
*/
-@Deprecated("Was moved to androidx.wear.compose.foundation.lazy package. " +
- "Please use it instead")
+@Deprecated(
+ "Was moved to androidx.wear.compose.foundation.lazy package. " + "Please use it instead"
+)
public sealed interface ScalingLazyListLayoutInfo {
- /**
- * The list of [ScalingLazyListItemInfo] representing all the currently visible items.
- */
- @Suppress("DEPRECATION")
- val visibleItemsInfo: List<ScalingLazyListItemInfo>
+ /** The list of [ScalingLazyListItemInfo] representing all the currently visible items. */
+ @Suppress("DEPRECATION") val visibleItemsInfo: List<ScalingLazyListItemInfo>
/**
* The start offset of the layout's viewport in pixels. You can think of it as a minimum offset
@@ -52,9 +50,7 @@
*/
val viewportEndOffset: Int
- /**
- * The total count of items passed to [ScalingLazyColumn].
- */
+ /** The total count of items passed to [ScalingLazyColumn]. */
val totalItemsCount: Int
/**
@@ -63,14 +59,10 @@
*/
val viewportSize: IntSize
- /**
- * The orientation of the scaling lazy list.
- */
+ /** The orientation of the scaling lazy list. */
val orientation: Orientation
- /**
- * True if the direction of scrolling and layout is reversed.
- */
+ /** True if the direction of scrolling and layout is reversed. */
val reverseLayout: Boolean
/**
@@ -81,9 +73,8 @@
val beforeContentPadding: Int
/**
- * The content padding in pixels applied after the last item in the direction of scrolling.
- * For example it is a bottom content padding for ScalingLazyColumn with reverseLayout set to
- * false.
+ * The content padding in pixels applied after the last item in the direction of scrolling. For
+ * example it is a bottom content padding for ScalingLazyColumn with reverseLayout set to false.
*/
val afterContentPadding: Int
diff --git a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/ScalingLazyListState.kt b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/ScalingLazyListState.kt
index 2109674..a2d3047 100644
--- a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/ScalingLazyListState.kt
+++ b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/ScalingLazyListState.kt
@@ -43,24 +43,21 @@
* Creates a [ScalingLazyListState] that is remembered across compositions.
*
* @param initialCenterItemIndex the initial value for [ScalingLazyListState.centerItemIndex],
- * defaults to 1. This will place the 2nd list item (index == 1) in the center of the viewport and
- * the first item (index == 0) before it.
- *
+ * defaults to 1. This will place the 2nd list item (index == 1) in the center of the viewport and
+ * the first item (index == 0) before it.
* @param initialCenterItemScrollOffset the initial value for
- * [ScalingLazyListState.centerItemScrollOffset] in pixels
+ * [ScalingLazyListState.centerItemScrollOffset] in pixels
*/
-@Deprecated("Was moved to androidx.wear.compose.foundation.lazy package. " +
- "Please use it instead")
+@Deprecated(
+ "Was moved to androidx.wear.compose.foundation.lazy package. " + "Please use it instead"
+)
@Composable
public fun rememberScalingLazyListState(
initialCenterItemIndex: Int = 1,
initialCenterItemScrollOffset: Int = 0
): ScalingLazyListState {
return rememberSaveable(saver = ScalingLazyListState.Saver) {
- ScalingLazyListState(
- initialCenterItemIndex,
- initialCenterItemScrollOffset
- )
+ ScalingLazyListState(initialCenterItemIndex, initialCenterItemScrollOffset)
}
}
@@ -70,14 +67,14 @@
* In most cases, this will be created via [rememberScalingLazyListState].
*
* @param initialCenterItemIndex the initial value for [ScalingLazyListState.centerItemIndex],
- * defaults to 1. This will place the 2nd list item (index == 1) in the center of the viewport and
- * the first item (index == 0) before it.
+ * defaults to 1. This will place the 2nd list item (index == 1) in the center of the viewport and
+ * the first item (index == 0) before it.
*
* If the developer wants custom control over position and spacing they can switch off autoCentering
* and provide contentPadding.
*
* @param initialCenterItemScrollOffset the initial value for
- * [ScalingLazyListState.centerItemScrollOffset]
+ * [ScalingLazyListState.centerItemScrollOffset]
*
* Note that it is not always possible for the values provided by [initialCenterItemIndex] and
* [initialCenterItemScrollOffset] to be honored, e.g. If [initialCenterItemIndex] is set to a value
@@ -86,10 +83,12 @@
* [ScalingLazyColumn]. After the [ScalingLazyColumn] is initially drawn the actual values for the
* [centerItemIndex] and [centerItemScrollOffset] can be read from the state.
*/
-@Deprecated("Was moved to androidx.wear.compose.foundation.lazy package. " +
- "Please use it instead")
+@Deprecated(
+ "Was moved to androidx.wear.compose.foundation.lazy package. " + "Please use it instead"
+)
@Stable
-class ScalingLazyListState constructor(
+class ScalingLazyListState
+constructor(
private var initialCenterItemIndex: Int = 1,
private var initialCenterItemScrollOffset: Int = 0
) : ScrollableState {
@@ -119,18 +118,21 @@
} ?: initialCenterItemIndex
}
- /**
- * The index of the item positioned closest to the viewport center
- */
+ /** The index of the item positioned closest to the viewport center */
public val centerItemIndex: Int
get() = _centerItemIndex.value
internal val topAutoCenteringItemSizePx: Int by derivedStateOf {
- if (extraPaddingPx.value == null || scalingParams.value == null ||
- gapBetweenItemsPx.value == null || viewportHeightPx.value == null ||
- anchorType.value == null || reverseLayout.value == null ||
- beforeContentPaddingPx.value == null || autoCentering.value == null ||
- autoCentering.value == null
+ if (
+ extraPaddingPx.value == null ||
+ scalingParams.value == null ||
+ gapBetweenItemsPx.value == null ||
+ viewportHeightPx.value == null ||
+ anchorType.value == null ||
+ reverseLayout.value == null ||
+ beforeContentPaddingPx.value == null ||
+ autoCentering.value == null ||
+ autoCentering.value == null
) {
0
} else {
@@ -139,11 +141,16 @@
}
internal val bottomAutoCenteringItemSizePx: Int by derivedStateOf {
- if (extraPaddingPx.value == null || scalingParams.value == null ||
- gapBetweenItemsPx.value == null || viewportHeightPx.value == null ||
- anchorType.value == null || reverseLayout.value == null ||
- beforeContentPaddingPx.value == null || autoCentering.value == null ||
- layoutInfo.internalVisibleItemInfo().isEmpty()
+ if (
+ extraPaddingPx.value == null ||
+ scalingParams.value == null ||
+ gapBetweenItemsPx.value == null ||
+ viewportHeightPx.value == null ||
+ anchorType.value == null ||
+ reverseLayout.value == null ||
+ beforeContentPaddingPx.value == null ||
+ autoCentering.value == null ||
+ layoutInfo.internalVisibleItemInfo().isEmpty()
) {
0
} else {
@@ -171,10 +178,14 @@
* example, you can use it to calculate what items are currently visible.
*/
public val layoutInfo: ScalingLazyListLayoutInfo by derivedStateOf {
- if (extraPaddingPx.value == null || scalingParams.value == null ||
- gapBetweenItemsPx.value == null || viewportHeightPx.value == null ||
- anchorType.value == null || reverseLayout.value == null ||
- beforeContentPaddingPx.value == null
+ if (
+ extraPaddingPx.value == null ||
+ scalingParams.value == null ||
+ gapBetweenItemsPx.value == null ||
+ viewportHeightPx.value == null ||
+ anchorType.value == null ||
+ reverseLayout.value == null ||
+ beforeContentPaddingPx.value == null
) {
EmptyScalingLazyListLayoutInfo
} else {
@@ -194,28 +205,26 @@
lazyListState.layoutInfo.viewportStartOffset + extraPaddingPx.value!!
// Find the item in the middle of the viewport
- val centralItemArrayIndex =
- findItemNearestCenter(verticalAdjustment)
+ val centralItemArrayIndex = findItemNearestCenter(verticalAdjustment)
if (centralItemArrayIndex != null) {
val originalVisibleItemsInfo = lazyListState.layoutInfo.visibleItemsInfo
val centralItem = originalVisibleItemsInfo[centralItemArrayIndex]
// Place the center item
- val centerItemInfo: ScalingLazyListItemInfo = calculateItemInfo(
- centralItem.offset,
- centralItem,
- verticalAdjustment,
- viewportHeightPx,
- viewportCenterLinePx(),
- scalingParams.value!!,
- beforeContentPaddingPx.value!!,
- anchorType.value!!,
- autoCentering.value,
- visible
- )
- visibleItemsInfo.add(
- centerItemInfo
- )
+ val centerItemInfo: ScalingLazyListItemInfo =
+ calculateItemInfo(
+ centralItem.offset,
+ centralItem,
+ verticalAdjustment,
+ viewportHeightPx,
+ viewportCenterLinePx(),
+ scalingParams.value!!,
+ beforeContentPaddingPx.value!!,
+ anchorType.value!!,
+ autoCentering.value,
+ visible
+ )
+ visibleItemsInfo.add(centerItemInfo)
newCenterItemIndex = centerItemInfo.index
newCenterItemScrollOffset = -centerItemInfo.offset
@@ -223,8 +232,10 @@
// Find the adjusted position of the central item in the coordinate system of the
// underlying LazyColumn by adjusting for any scaling
val centralItemAdjustedUnderlyingOffset =
- centralItem.offset + ((centerItemInfo.startOffset(anchorType.value!!) -
- centerItemInfo.unadjustedStartOffset(anchorType.value!!))).roundToInt()
+ centralItem.offset +
+ ((centerItemInfo.startOffset(anchorType.value!!) -
+ centerItemInfo.unadjustedStartOffset(anchorType.value!!)))
+ .roundToInt()
// Go Up
// nextItemBottomNoPadding uses the coordinate system of the underlying LazyList. It
@@ -242,21 +253,21 @@
(centralItemArrayIndex - 1 downTo 0).forEach { ix ->
if (nextItemBottomNoPadding >= verticalAdjustment) {
- val currentItem =
- lazyListState.layoutInfo.visibleItemsInfo[ix]
+ val currentItem = lazyListState.layoutInfo.visibleItemsInfo[ix]
if (!discardAutoCenteringListItem(currentItem)) {
- val itemInfo = calculateItemInfo(
- nextItemBottomNoPadding - currentItem.size,
- currentItem,
- verticalAdjustment,
- viewportHeightPx,
- viewportCenterLinePx(),
- scalingParams.value!!,
- beforeContentPaddingPx.value!!,
- anchorType.value!!,
- autoCentering.value,
- visible
- )
+ val itemInfo =
+ calculateItemInfo(
+ nextItemBottomNoPadding - currentItem.size,
+ currentItem,
+ verticalAdjustment,
+ viewportHeightPx,
+ viewportCenterLinePx(),
+ scalingParams.value!!,
+ beforeContentPaddingPx.value!!,
+ anchorType.value!!,
+ autoCentering.value,
+ visible
+ )
visibleItemsInfo.add(0, itemInfo)
nextItemBottomNoPadding =
nextItemBottomNoPadding - itemInfo.size - gapBetweenItemsPx.value!!
@@ -271,27 +282,27 @@
// keeps track of the top of the next potential list item that is a candidate to be
// drawn in the viewport as we walk down the list items from the center.
var nextItemTopNoPadding =
- centralItemAdjustedUnderlyingOffset + centerItemInfo.size +
+ centralItemAdjustedUnderlyingOffset +
+ centerItemInfo.size +
gapBetweenItemsPx.value!!
- (((centralItemArrayIndex + 1) until
- originalVisibleItemsInfo.size)).forEach { ix ->
+ (((centralItemArrayIndex + 1) until originalVisibleItemsInfo.size)).forEach { ix ->
if ((nextItemTopNoPadding - viewportHeightPx) <= verticalAdjustment) {
- val currentItem =
- lazyListState.layoutInfo.visibleItemsInfo[ix]
+ val currentItem = lazyListState.layoutInfo.visibleItemsInfo[ix]
if (!discardAutoCenteringListItem(currentItem)) {
- val itemInfo = calculateItemInfo(
- nextItemTopNoPadding,
- currentItem,
- verticalAdjustment,
- viewportHeightPx,
- viewportCenterLinePx(),
- scalingParams.value!!,
- beforeContentPaddingPx.value!!,
- anchorType.value!!,
- autoCentering.value,
- visible
- )
+ val itemInfo =
+ calculateItemInfo(
+ nextItemTopNoPadding,
+ currentItem,
+ verticalAdjustment,
+ viewportHeightPx,
+ viewportCenterLinePx(),
+ scalingParams.value!!,
+ beforeContentPaddingPx.value!!,
+ anchorType.value!!,
+ autoCentering.value,
+ visible
+ )
visibleItemsInfo.add(itemInfo)
nextItemTopNoPadding += itemInfo.size + gapBetweenItemsPx.value!!
@@ -312,23 +323,23 @@
// 1. We are not yet initialized and
val readyForInitialScroll =
- if (! initialized.value) {
+ if (!initialized.value) {
// 1. autoCentering is off or
// 2. The list has no items or
// 3. the before content autoCentering Spacer has been sized.
- // NOTE: It is possible, if the first real item in the list is large, that the size
+ // NOTE: It is possible, if the first real item in the list is large, that the
+ // size
// of the Spacer is 0.
- autoCentering.value == null || (
- lazyListState.layoutInfo.visibleItemsInfo.size >= 2 && (
+ autoCentering.value == null ||
+ (lazyListState.layoutInfo.visibleItemsInfo.size >= 2 &&
+ (
// or Empty list (other than the 2 spacers)
lazyListState.layoutInfo.visibleItemsInfo.size == 2 ||
// or first item is correctly size
topSpacerIsCorrectlySized(
lazyListState.layoutInfo.visibleItemsInfo,
lazyListState.layoutInfo.totalItemsCount
- )
- )
- )
+ )))
} else {
// We are already initialized and have an incomplete scroll to finish
incompleteScrollItem.value != null
@@ -337,39 +348,39 @@
DefaultScalingLazyListLayoutInfo(
internalVisibleItemsInfo = visibleItemsInfo,
totalItemsCount = totalItemsCount,
- viewportStartOffset = lazyListState.layoutInfo.viewportStartOffset +
- extraPaddingPx.value!!,
- viewportEndOffset = lazyListState.layoutInfo.viewportEndOffset -
- extraPaddingPx.value!!,
+ viewportStartOffset =
+ lazyListState.layoutInfo.viewportStartOffset + extraPaddingPx.value!!,
+ viewportEndOffset =
+ lazyListState.layoutInfo.viewportEndOffset - extraPaddingPx.value!!,
centerItemIndex = if (initialized.value) newCenterItemIndex else 0,
centerItemScrollOffset = if (initialized.value) newCenterItemScrollOffset else 0,
reverseLayout = reverseLayout.value!!,
orientation = lazyListState.layoutInfo.orientation,
- viewportSize = IntSize(
- width = lazyListState.layoutInfo.viewportSize.width,
- height = lazyListState.layoutInfo.viewportSize.height -
- extraPaddingPx.value!! * 2
- ),
+ viewportSize =
+ IntSize(
+ width = lazyListState.layoutInfo.viewportSize.width,
+ height =
+ lazyListState.layoutInfo.viewportSize.height -
+ extraPaddingPx.value!! * 2
+ ),
beforeContentPadding = beforeContentPaddingPx.value!!,
afterContentPadding = afterContentPaddingPx.value!!,
- beforeAutoCenteringPadding = calculateTopAutoCenteringPaddingPx(visibleItemsInfo,
- totalItemsCount),
- afterAutoCenteringPadding = calculateBottomAutoCenteringPaddingPx(visibleItemsInfo,
- totalItemsCount),
+ beforeAutoCenteringPadding =
+ calculateTopAutoCenteringPaddingPx(visibleItemsInfo, totalItemsCount),
+ afterAutoCenteringPadding =
+ calculateBottomAutoCenteringPaddingPx(visibleItemsInfo, totalItemsCount),
readyForInitialScroll = readyForInitialScroll,
initialized = initialized.value,
)
}
}
- private fun findItemNearestCenter(
- verticalAdjustment: Int
- ): Int? {
+ private fun findItemNearestCenter(verticalAdjustment: Int): Int? {
var result: Int? = null
// Find the item in the middle of the viewport
for (i in lazyListState.layoutInfo.visibleItemsInfo.indices) {
val item = lazyListState.layoutInfo.visibleItemsInfo[i]
- if (! discardAutoCenteringListItem(item)) {
+ if (!discardAutoCenteringListItem(item)) {
val rawItemStart = item.offset - verticalAdjustment
val rawItemEnd = rawItemStart + item.size + gapBetweenItemsPx.value!! / 2f
result = i
@@ -382,21 +393,20 @@
}
companion object {
- /**
- * The default [Saver] implementation for [ScalingLazyListState].
- */
- val Saver = listSaver<ScalingLazyListState, Int>(
- save = {
- listOf(
- it.centerItemIndex,
- it.centerItemScrollOffset,
- )
- },
- restore = {
- val scalingLazyColumnState = ScalingLazyListState(it[0], it[1])
- scalingLazyColumnState
- }
- )
+ /** The default [Saver] implementation for [ScalingLazyListState]. */
+ val Saver =
+ listSaver<ScalingLazyListState, Int>(
+ save = {
+ listOf(
+ it.centerItemIndex,
+ it.centerItemScrollOffset,
+ )
+ },
+ restore = {
+ val scalingLazyColumnState = ScalingLazyListState(it[0], it[1])
+ scalingLazyColumnState
+ }
+ )
}
override val isScrollInProgress: Boolean
@@ -420,14 +430,15 @@
override val canScrollBackward: Boolean
get() = lazyListState.canScrollBackward
+
/**
* Instantly brings the item at [index] to the center of the viewport and positions it based on
* the [anchorType] and applies the [scrollOffset] pixels.
*
* @param index the index to which to scroll. Must be non-negative.
* @param scrollOffset the offset that the item should end up after the scroll. Note that
- * positive offset refers to forward scroll, so in a top-to-bottom list, positive offset will
- * scroll the item further upward (taking it partly offscreen).
+ * positive offset refers to forward scroll, so in a top-to-bottom list, positive offset will
+ * scroll the item further upward (taking it partly offscreen).
*/
public suspend fun scrollToItem(
/*@IntRange(from = 0)*/
@@ -439,14 +450,14 @@
}
/**
- * Brings the item at [index] to the center of the viewport and positions it based on
- * the [anchorType] and applies the [scrollOffset] pixels.
+ * Brings the item at [index] to the center of the viewport and positions it based on the
+ * [anchorType] and applies the [scrollOffset] pixels.
*
* @param animated whether to animate the scroll
* @param index the index to which to scroll. Must be non-negative.
* @param scrollOffset the offset that the item should end up after the scroll. Note that
- * positive offset refers to forward scroll, so in a top-to-bottom list, positive offset will
- * scroll the item further upward (taking it partly offscreen).
+ * positive offset refers to forward scroll, so in a top-to-bottom list, positive offset will
+ * scroll the item further upward (taking it partly offscreen).
*/
internal suspend fun scrollToItem(
animated: Boolean,
@@ -467,8 +478,7 @@
val targetIndex = index.coerceAtMost(layoutInfo.totalItemsCount)
val lazyListStateIndex = targetIndex + if (autoCentering.value != null) 1 else 0
- val offsetToCenterOfViewport =
- beforeContentPaddingPx.value!! - viewportCenterLinePx()
+ val offsetToCenterOfViewport = beforeContentPaddingPx.value!! - viewportCenterLinePx()
if (anchorType.value == ScalingLazyListAnchorType.ItemStart) {
val offset = offsetToCenterOfViewport + scrollOffset
return lazyListState.scrollToItem(animated, lazyListStateIndex, offset)
@@ -525,9 +535,8 @@
*
* @param index the index to which to scroll. Must be non-negative.
* @param scrollOffset the offset that the item should end up after the scroll (same as
- * [scrollToItem]) - note that positive offset refers to forward scroll, so in a
- * top-to-bottom list, positive offset will scroll the item further upward (taking it partly
- * offscreen)
+ * [scrollToItem]) - note that positive offset refers to forward scroll, so in a top-to-bottom
+ * list, positive offset will scroll the item further upward (taking it partly offscreen)
*/
public suspend fun animateScrollToItem(
/*@IntRange(from = 0)*/
@@ -551,8 +560,11 @@
visibleItems: List<ScalingLazyListItemInfo>,
totalItemCount: Int
): Int {
- if (autoCentering.value == null ||
- (visibleItems.isNotEmpty() && visibleItems.first().index != 0)) return 0
+ if (
+ autoCentering.value == null ||
+ (visibleItems.isNotEmpty() && visibleItems.first().index != 0)
+ )
+ return 0
// Work out the index we want to find - if there are less items in the list than would be
// needed to make initialItemIndex be visible then use the last visible item
@@ -561,8 +573,7 @@
// Find the initialCenterItem, if it is null that means it is not in view - therefore
// we have more than enough content before it to make sure it can be scrolled to the center
// of the viewport
- val initialCenterItem =
- visibleItems.fastFirstOrNull { it.index == itemIndexToFind }
+ val initialCenterItem = visibleItems.fastFirstOrNull { it.index == itemIndexToFind }
// Determine how much space we actually need
var spaceNeeded = spaceNeeded(initialCenterItem)
@@ -600,8 +611,7 @@
// Find the initialCenterItem, if it is null that means it is not in view - therefore
// we have more than enough content before it to make sure it can be scrolled to the center
// of the viewport
- val initialCenterItem =
- visibleItems.fastFirstOrNull { it.index == itemIndexToFind }
+ val initialCenterItem = visibleItems.fastFirstOrNull { it.index == itemIndexToFind }
// Determine how much space we actually need
var spaceNeeded = spaceNeeded(initialCenterItem)
@@ -622,34 +632,42 @@
}
private fun spaceNeeded(item: ScalingLazyListItemInfo?) =
- viewportCenterLinePx() - gapBetweenItemsPx.value!! - autoCentering.value!!.itemOffset -
+ viewportCenterLinePx() -
+ gapBetweenItemsPx.value!! -
+ autoCentering.value!!.itemOffset -
(item?.unadjustedItemSizeAboveOffsetPoint() ?: 0)
private fun spaceNeeded(item: LazyListItemInfo?) =
- viewportCenterLinePx() - gapBetweenItemsPx.value!! - autoCentering.value!!.itemOffset -
+ viewportCenterLinePx() -
+ gapBetweenItemsPx.value!! -
+ autoCentering.value!!.itemOffset -
(item?.itemSizeAboveOffsetPoint() ?: 0)
private fun calculateBottomAutoCenteringPaddingPx(
visibleItemsInfo: List<ScalingLazyListItemInfo>,
totalItemsCount: Int
- ) = if (autoCentering.value != null && visibleItemsInfo.isNotEmpty() &&
- visibleItemsInfo.last().index == totalItemsCount - 1
- ) {
- // Round any fractional part up for the bottom spacer as we round down toward zero
- // for the viewport center line and item heights working from the top of the
- // viewport and then add 1 pixel if needed (for an odd height viewport) at the end
- // spacer
- viewportHeightPx.value!! - viewportCenterLinePx() -
- visibleItemsInfo.last().unadjustedItemSizeBelowOffsetPoint()
- } else {
- 0
- }
+ ) =
+ if (
+ autoCentering.value != null &&
+ visibleItemsInfo.isNotEmpty() &&
+ visibleItemsInfo.last().index == totalItemsCount - 1
+ ) {
+ // Round any fractional part up for the bottom spacer as we round down toward zero
+ // for the viewport center line and item heights working from the top of the
+ // viewport and then add 1 pixel if needed (for an odd height viewport) at the end
+ // spacer
+ viewportHeightPx.value!! -
+ viewportCenterLinePx() -
+ visibleItemsInfo.last().unadjustedItemSizeBelowOffsetPoint()
+ } else {
+ 0
+ }
/**
* Calculate the center line of the viewport. This is half of the viewport height rounded down
* to the nearest int. This means that for a viewport with an odd number of pixels in height we
- * will have the area above the viewport being one pixel smaller, e.g. a 199 pixel high
- * viewport will be treated as having 99 pixels above and 100 pixels below the center line.
+ * will have the area above the viewport being one pixel smaller, e.g. a 199 pixel high viewport
+ * will be treated as having 99 pixels above and 100 pixels below the center line.
*/
private fun viewportCenterLinePx(): Int = viewportHeightPx.value!! / 2
@@ -666,8 +684,8 @@
}
/**
- * How much of the items size would be above the point on the item that represents the
- * offset point. For an edge anchored item the offset point is the top of the item. For a center
+ * How much of the items size would be above the point on the item that represents the offset
+ * point. For an edge anchored item the offset point is the top of the item. For a center
* anchored item the offset point is floor(height/2).
*/
private fun LazyListItemInfo.itemSizeAboveOffsetPoint() =
@@ -678,8 +696,8 @@
}
/**
- * How much of the items size would be below the point on the item that represents the
- * offset point. For an edge anchored item the offset point is the top of the item. For a center
+ * How much of the items size would be below the point on the item that represents the offset
+ * point. For an edge anchored item the offset point is the top of the item. For a center
* anchored item the offset point is floor(height/2).
*/
private fun ScalingLazyListItemInfo.unadjustedItemSizeBelowOffsetPoint() =
diff --git a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/ScalingLazyScopeMarker.kt b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/ScalingLazyScopeMarker.kt
index aaa2487..0cb79b9 100644
--- a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/ScalingLazyScopeMarker.kt
+++ b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/ScalingLazyScopeMarker.kt
@@ -16,10 +16,9 @@
package androidx.wear.compose.material
-/**
- * DSL marker used to distinguish between lazy layout scope and the item scope.
- */
-@Deprecated("Was moved to androidx.wear.compose.foundation.lazy package. " +
- "Please use it instead")
+/** DSL marker used to distinguish between lazy layout scope and the item scope. */
+@Deprecated(
+ "Was moved to androidx.wear.compose.foundation.lazy package. " + "Please use it instead"
+)
@DslMarker
annotation class ScalingLazyScopeMarker
diff --git a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/ScrollAway.kt b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/ScrollAway.kt
index 5a6fd04d..e938cce 100644
--- a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/ScrollAway.kt
+++ b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/ScrollAway.kt
@@ -36,104 +36,96 @@
import androidx.wear.compose.foundation.lazy.ScalingLazyListState
/**
- * Scroll an item vertically in/out of view based on a [ScrollState].
- * Typically used to scroll a [TimeText] item out of view as the user starts to scroll a
- * vertically scrollable [Column] of items upwards and bring additional items into view.
+ * Scroll an item vertically in/out of view based on a [ScrollState]. Typically used to scroll a
+ * [TimeText] item out of view as the user starts to scroll a vertically scrollable [Column] of
+ * items upwards and bring additional items into view.
*
* @param scrollState The [ScrollState] to used as the basis for the scroll-away.
- * @param offset Adjustment to the starting point for scrolling away. Positive values result in
- * the scroll away starting later.
+ * @param offset Adjustment to the starting point for scrolling away. Positive values result in the
+ * scroll away starting later.
*/
public fun Modifier.scrollAway(
scrollState: ScrollState,
offset: Dp = 0.dp,
-): Modifier = scrollAway {
- ScrollParams(
- valid = true,
- yPx = scrollState.value - offset.toPx()
- )
-}
+): Modifier = scrollAway { ScrollParams(valid = true, yPx = scrollState.value - offset.toPx()) }
/**
- * Scroll an item vertically in/out of view based on a [LazyListState].
- * Typically used to scroll a [TimeText] item out of view as the user starts to scroll
- * a [LazyColumn] of items upwards and bring additional items into view.
+ * Scroll an item vertically in/out of view based on a [LazyListState]. Typically used to scroll a
+ * [TimeText] item out of view as the user starts to scroll a [LazyColumn] of items upwards and
+ * bring additional items into view.
*
* @param scrollState The [LazyListState] to used as the basis for the scroll-away.
* @param itemIndex The item for which the scroll offset will trigger scrolling away.
- * @param offset Adjustment to the starting point for scrolling away. Positive values result in
- * the scroll away starting later.
+ * @param offset Adjustment to the starting point for scrolling away. Positive values result in the
+ * scroll away starting later.
*/
public fun Modifier.scrollAway(
scrollState: LazyListState,
itemIndex: Int = 0,
offset: Dp = 0.dp,
-): Modifier =
- scrollAway {
- ScrollParams(
- valid = itemIndex < scrollState.layoutInfo.totalItemsCount,
- yPx = scrollState.layoutInfo.visibleItemsInfo.fastFirstOrNull { it.index == itemIndex }
- ?.let {
- -it.offset - offset.toPx()
- }
- )
- }
+): Modifier = scrollAway {
+ ScrollParams(
+ valid = itemIndex < scrollState.layoutInfo.totalItemsCount,
+ yPx =
+ scrollState.layoutInfo.visibleItemsInfo
+ .fastFirstOrNull { it.index == itemIndex }
+ ?.let { -it.offset - offset.toPx() }
+ )
+}
/**
- * Scroll an item vertically in/out of view based on a [ScalingLazyListState].
- * Typically used to scroll a [TimeText] item out of view as the user starts to scroll
- * a [ScalingLazyColumn] of items upwards and bring additional items into view.
+ * Scroll an item vertically in/out of view based on a [ScalingLazyListState]. Typically used to
+ * scroll a [TimeText] item out of view as the user starts to scroll a [ScalingLazyColumn] of items
+ * upwards and bring additional items into view.
*
* @param scrollState The [ScalingLazyListState] to used as the basis for the scroll-away.
* @param itemIndex The item for which the scroll offset will trigger scrolling away.
- * @param offset Adjustment to the starting point for scrolling away. Positive values result in
- * the scroll away starting later, negative values start scrolling away earlier.
+ * @param offset Adjustment to the starting point for scrolling away. Positive values result in the
+ * scroll away starting later, negative values start scrolling away earlier.
*/
public fun Modifier.scrollAway(
scrollState: ScalingLazyListState,
itemIndex: Int = 1,
offset: Dp = 0.dp,
-): Modifier =
- scrollAway {
- ScrollParams(
- valid = itemIndex < scrollState.layoutInfo.totalItemsCount,
- yPx = scrollState.layoutInfo.visibleItemsInfo.fastFirstOrNull { it.index == itemIndex }
- ?.let {
- -it.offset - offset.toPx()
- }
- )
- }
+): Modifier = scrollAway {
+ ScrollParams(
+ valid = itemIndex < scrollState.layoutInfo.totalItemsCount,
+ yPx =
+ scrollState.layoutInfo.visibleItemsInfo
+ .fastFirstOrNull { it.index == itemIndex }
+ ?.let { -it.offset - offset.toPx() }
+ )
+}
/**
- * Scroll an item vertically in/out of view based on a [ScalingLazyListState].
- * Typically used to scroll a [TimeText] item out of view as the user starts to scroll
- * a [ScalingLazyColumn] of items upwards and bring additional items into view.
+ * Scroll an item vertically in/out of view based on a [ScalingLazyListState]. Typically used to
+ * scroll a [TimeText] item out of view as the user starts to scroll a [ScalingLazyColumn] of items
+ * upwards and bring additional items into view.
*
* @param scrollState The [ScalingLazyListState] to used as the basis for the scroll-away.
* @param itemIndex The item for which the scroll offset will trigger scrolling away.
- * @param offset Adjustment to the starting point for scrolling away. Positive values result in
- * the scroll away starting later, negative values start scrolling away earlier.
+ * @param offset Adjustment to the starting point for scrolling away. Positive values result in the
+ * scroll away starting later, negative values start scrolling away earlier.
*/
@Deprecated(
"This overload is provided for backwards compatibility with Compose for Wear OS 1.1." +
"A newer overload is available which uses ScalingLazyListState " +
- "from wear.compose.foundation.lazy package", level = DeprecationLevel.WARNING
+ "from wear.compose.foundation.lazy package",
+ level = DeprecationLevel.WARNING
)
public fun Modifier.scrollAway(
- @Suppress("DEPRECATION")
- scrollState: androidx.wear.compose.material.ScalingLazyListState,
+ @Suppress("DEPRECATION") scrollState: androidx.wear.compose.material.ScalingLazyListState,
itemIndex: Int = 1,
offset: Dp = 0.dp,
-): Modifier =
- scrollAway {
- ScrollParams(
- valid = itemIndex < scrollState.layoutInfo.totalItemsCount,
- yPx = scrollState.layoutInfo.visibleItemsInfo.fastFirstOrNull { it.index == itemIndex }
- ?.let {
- -it.offset - offset.toPx()
- }
- )
- }
+): Modifier = scrollAway {
+ ScrollParams(
+ valid = itemIndex < scrollState.layoutInfo.totalItemsCount,
+ yPx =
+ scrollState.layoutInfo.visibleItemsInfo
+ .fastFirstOrNull { it.index == itemIndex }
+ ?.let { -it.offset - offset.toPx() }
+ )
+}
private fun Modifier.scrollAway(scrollFn: Density.() -> ScrollParams): Modifier =
this.then(
diff --git a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/SelectableChip.kt b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/SelectableChip.kt
index 4d6815b..fd49597 100644
--- a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/SelectableChip.kt
+++ b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/SelectableChip.kt
@@ -43,62 +43,60 @@
import androidx.compose.ui.unit.dp
/**
- * A [SelectableChip] is a specialized type of [Chip] that includes a slot for a bi-state
- * selection control such as a radio button. This overload provides suitable accessibility semantics
- * for a selectable control like [RadioButton]. For toggleable controls like [Checkbox]
- * and [Switch], use [ToggleChip] instead.
+ * A [SelectableChip] is a specialized type of [Chip] that includes a slot for a bi-state selection
+ * control such as a radio button. This overload provides suitable accessibility semantics for a
+ * selectable control like [RadioButton]. For toggleable controls like [Checkbox] and [Switch], use
+ * [ToggleChip] instead.
*
- * The Wear Material [SelectableChip] offers four slots and a specific layout for an
- * application icon, a label, a secondaryLabel and selection control.
- * The application icon and secondaryLabel are optional. The items are laid out in a row with the
- * optional icon at the start, a column containing the two label slots in the middle
- * and a slot for the selection control at the end.
+ * The Wear Material [SelectableChip] offers four slots and a specific layout for an application
+ * icon, a label, a secondaryLabel and selection control. The application icon and secondaryLabel
+ * are optional. The items are laid out in a row with the optional icon at the start, a column
+ * containing the two label slots in the middle and a slot for the selection control at the end.
*
- * The [SelectableChip] is Stadium shaped and has a max height designed to take no more than
- * two lines of text of [Typography.button] style.
- * With localisation and/or large font sizes, the [SelectableChip] height adjusts to
- * accommodate the contents. The label and secondary label should be consistently aligned.
+ * The [SelectableChip] is Stadium shaped and has a max height designed to take no more than two
+ * lines of text of [Typography.button] style. With localisation and/or large font sizes, the
+ * [SelectableChip] height adjusts to accommodate the contents. The label and secondary label should
+ * be consistently aligned.
*
- * The recommended set of [SelectableChipColors] can be obtained from
- * [SelectableChipDefaults], e.g. [SelectableChipDefaults.selectableChipColors].
+ * The recommended set of [SelectableChipColors] can be obtained from [SelectableChipDefaults], e.g.
+ * [SelectableChipDefaults.selectableChipColors].
*
* Chips can be enabled or disabled. A disabled chip will not respond to click events.
*
* Example of a [SelectableChip] with an icon, label and secondary label (defaults to radio button):
+ *
* @sample androidx.wear.compose.material.samples.SelectableChipWithRadioButton
*
* For more information, see the
- * [Toggle Chips](https://developer.android.com/training/wearables/components/toggle-chips)
- * guide.
+ * [Toggle Chips](https://developer.android.com/training/wearables/components/toggle-chips) guide.
*
* @param selected Boolean flag indicating whether this button is currently selected.
* @param onClick Callback to be invoked when this button is selected.
* @param label A slot for providing the chip's main label. The contents are expected to be text
- * which is "start" aligned.
+ * which is "start" aligned.
* @param modifier Modifier to be applied to the chip
* @param appIcon An optional slot for providing an icon to indicate the purpose of the chip. The
- * contents are expected to be a horizontally and vertically centre aligned icon of size
- * [SelectableChipDefaults.IconSize]. In order to correctly render when the Chip is not enabled the
- * icon must set its alpha value to [LocalContentAlpha].
+ * contents are expected to be a horizontally and vertically centre aligned icon of size
+ * [SelectableChipDefaults.IconSize]. In order to correctly render when the Chip is not enabled
+ * the icon must set its alpha value to [LocalContentAlpha].
* @param secondaryLabel A slot for providing the chip's secondary label. The contents are expected
- * to be text which is "start" aligned if there is an icon preset and "start" or "center" aligned if
- * not. label and secondaryLabel contents should be consistently aligned.
- * @param colors [SelectableChipColors] that will be used to resolve the background and
- * content color for this chip in different states, see
- * [SelectableChipDefaults.selectableChipColors].
- * @param enabled Controls the enabled state of the chip. When `false`, this chip will not
- * be clickable
+ * to be text which is "start" aligned if there is an icon preset and "start" or "center" aligned
+ * if not. label and secondaryLabel contents should be consistently aligned.
+ * @param colors [SelectableChipColors] that will be used to resolve the background and content
+ * color for this chip in different states, see [SelectableChipDefaults.selectableChipColors].
+ * @param enabled Controls the enabled state of the chip. When `false`, this chip will not be
+ * clickable
* @param interactionSource an optional hoisted [MutableInteractionSource] for observing and
- * emitting [Interaction]s for this chip's "selectable" tap area. You can use this to change the
- * chip's appearance or preview the chip in different states. Note that if `null` is provided,
- * interactions will still happen internally.
+ * emitting [Interaction]s for this chip's "selectable" tap area. You can use this to change the
+ * chip's appearance or preview the chip in different states. Note that if `null` is provided,
+ * interactions will still happen internally.
* @param contentPadding The spacing values to apply internally between the container and the
- * content
+ * content
* @param shape Defines the chip's shape. It is strongly recommended to use the default as this
- * shape is a key characteristic of the Wear Material Theme
- * @param selectionControl A slot for providing the chip's selection control. One built-in
- * type of selection control is supported, see [RadioButton]. For [Checkbox] and [Switch],
- * use [ToggleChip] in order to provide the correct semantics for accessibility.
+ * shape is a key characteristic of the Wear Material Theme
+ * @param selectionControl A slot for providing the chip's selection control. One built-in type of
+ * selection control is supported, see [RadioButton]. For [Checkbox] and [Switch], use
+ * [ToggleChip] in order to provide the correct semantics for accessibility.
*/
@Composable
public fun SelectableChip(
@@ -116,120 +114,121 @@
selectionControl: @Composable () -> Unit = {
RadioButton(selected = selected, enabled = enabled)
}
-) = androidx.wear.compose.materialcore.ToggleButton(
- checked = selected,
- onCheckedChange = onClick,
- label = provideScopeContent(
- contentColor = colors.contentColor(enabled = enabled, selected),
- textStyle = MaterialTheme.typography.button,
- content = label
- ),
- toggleControl = null,
- selectionControl = provideContent(
- contentColor = colors.selectionControlColor(enabled, selected),
- content = selectionControl
- ),
- modifier = modifier
- .defaultMinSize(minHeight = SelectableChipDefaults.Height)
- .height(IntrinsicSize.Min),
- icon = provideNullableScopeContent(
- contentColor = colors.contentColor(enabled = enabled, selected = selected),
- content = appIcon
- ),
- secondaryLabel = provideNullableScopeContent(
- contentColor = colors.secondaryContentColor(enabled = enabled, selected),
- textStyle = MaterialTheme.typography.caption2,
- content = secondaryLabel
- ),
- background = { isEnabled, isSelected ->
- val painter = colors.background(
- enabled = isEnabled,
- selected = isSelected
- ).value
+) =
+ androidx.wear.compose.materialcore.ToggleButton(
+ checked = selected,
+ onCheckedChange = onClick,
+ label =
+ provideScopeContent(
+ contentColor = colors.contentColor(enabled = enabled, selected),
+ textStyle = MaterialTheme.typography.button,
+ content = label
+ ),
+ toggleControl = null,
+ selectionControl =
+ provideContent(
+ contentColor = colors.selectionControlColor(enabled, selected),
+ content = selectionControl
+ ),
+ modifier =
+ modifier
+ .defaultMinSize(minHeight = SelectableChipDefaults.Height)
+ .height(IntrinsicSize.Min),
+ icon =
+ provideNullableScopeContent(
+ contentColor = colors.contentColor(enabled = enabled, selected = selected),
+ content = appIcon
+ ),
+ secondaryLabel =
+ provideNullableScopeContent(
+ contentColor = colors.secondaryContentColor(enabled = enabled, selected),
+ textStyle = MaterialTheme.typography.caption2,
+ content = secondaryLabel
+ ),
+ background = { isEnabled, isSelected ->
+ val painter = colors.background(enabled = isEnabled, selected = isSelected).value
- Modifier.paint(painter = painter, contentScale = ContentScale.Crop)
- },
- enabled = enabled,
- interactionSource = interactionSource,
- contentPadding = contentPadding,
- shape = shape,
- toggleControlHeight = SELECTABLE_CONTROL_HEIGHT,
- toggleControlWidth = SELECTABLE_CONTROL_WIDTH,
- labelSpacerSize = 0.dp,
- toggleControlSpacing = TOGGLE_CONTROL_SPACING,
- iconSpacing = ICON_SPACING,
- ripple = rippleOrFallbackImplementation()
-)
+ Modifier.paint(painter = painter, contentScale = ContentScale.Crop)
+ },
+ enabled = enabled,
+ interactionSource = interactionSource,
+ contentPadding = contentPadding,
+ shape = shape,
+ toggleControlHeight = SELECTABLE_CONTROL_HEIGHT,
+ toggleControlWidth = SELECTABLE_CONTROL_WIDTH,
+ labelSpacerSize = 0.dp,
+ toggleControlSpacing = TOGGLE_CONTROL_SPACING,
+ iconSpacing = ICON_SPACING,
+ ripple = rippleOrFallbackImplementation()
+ )
/**
- * A [SplitSelectableChip] is a specialized type of [Chip] that includes a slot for a
- * selection control, such as a radio button. The [SplitSelectableChip] differs from the
- * [SelectableChip] by having two "tappable" areas, one clickable and one selectable.
+ * A [SplitSelectableChip] is a specialized type of [Chip] that includes a slot for a selection
+ * control, such as a radio button. The [SplitSelectableChip] differs from the [SelectableChip] by
+ * having two "tappable" areas, one clickable and one selectable.
*
* The [SplitSelectableChip] provides suitable accessibility semantics for a selectable control like
* [RadioButton]. For toggleable controls like [Checkbox] and [Switch], use [SplitToggleChip].
*
* The Wear Material [SplitSelectableChip] offers three slots and a specific layout for a label,
- * secondaryLabel and selection control. The secondaryLabel is optional. The items are laid out
- * with a column containing the two label slots and a slot for the selection control at the
- * end.
+ * secondaryLabel and selection control. The secondaryLabel is optional. The items are laid out with
+ * a column containing the two label slots and a slot for the selection control at the end.
*
* A [SplitSelectableChip] has two tappable areas, one tap area for the labels and another for the
* selection control. The [onContainerClick] callback will be associated with the main body of the
- * [SplitSelectableChip] with the [onSelectionClick] callback associated with the
- * selection control area only.
+ * [SplitSelectableChip] with the [onSelectionClick] callback associated with the selection control
+ * area only.
*
- * For a [SplitSelectableChip] the background of the tappable background area behind the
- * selection control will have a visual effect applied to provide a "divider" between the two
- * tappable areas.
+ * For a [SplitSelectableChip] the background of the tappable background area behind the selection
+ * control will have a visual effect applied to provide a "divider" between the two tappable areas.
*
* The [SplitSelectableChip] is Stadium shaped and has a max height designed to take no more than
- * two lines of text of [Typography.button] style.
- * With localisation and/or large font sizes, the [SplitSelectableChip] height adjusts
- * to accommodate the contents. The label and secondary label should be consistently aligned.
+ * two lines of text of [Typography.button] style. With localisation and/or large font sizes, the
+ * [SplitSelectableChip] height adjusts to accommodate the contents. The label and secondary label
+ * should be consistently aligned.
*
- * The recommended set of [SplitSelectableChipColors] can be obtained from
- * [SelectableChipDefaults], e.g. [SelectableChipDefaults.splitSelectableChipColors].
+ * The recommended set of [SplitSelectableChipColors] can be obtained from [SelectableChipDefaults],
+ * e.g. [SelectableChipDefaults.splitSelectableChipColors].
*
* Chips can be enabled or disabled. A disabled chip will not respond to click events.
*
* Example of a [SplitSelectableChip] with a label and the radio button selection control:
+ *
* @sample androidx.wear.compose.material.samples.SplitSelectableChipWithRadioButton
*
* For more information, see the
- * [Toggle Chips](https://developer.android.com/training/wearables/components/toggle-chips)
- * guide.
+ * [Toggle Chips](https://developer.android.com/training/wearables/components/toggle-chips) guide.
*
* @param selected Boolean flag indicating whether this button is currently selected.
* @param onSelectionClick Callback to be invoked when this button is selected.
* @param label A slot for providing the chip's main label. The contents are expected to be text
- * which is "start" aligned.
+ * which is "start" aligned.
* @param onContainerClick Callback to be invoked when the user clicks the main body of the chip,
- * the area containing the labels.
+ * the area containing the labels.
* @param modifier Modifier to be applied to the chip
* @param secondaryLabel A slot for providing the chip's secondary label. The contents are expected
- * to be "start" or "center" aligned. label and secondaryLabel contents should be consistently
- * aligned.
- * @param colors [SplitSelectableChipColors] that will be used to resolve the background and
- * content color for this chip in different states, see
- * [SelectableChipDefaults.splitSelectableChipColors].
- * @param enabled Controls the enabled state of the chip. When `false`, this chip will not
- * be clickable
- * @param selectionInteractionSource an optional hoisted [MutableInteractionSource] for observing and
- * emitting [Interaction]s for this chip's "selectable" tap area. You can use this to change the
- * chip's appearance or preview the chip in different states. Note that if `null` is provided,
- * interactions will still happen internally.
+ * to be "start" or "center" aligned. label and secondaryLabel contents should be consistently
+ * aligned.
+ * @param colors [SplitSelectableChipColors] that will be used to resolve the background and content
+ * color for this chip in different states, see
+ * [SelectableChipDefaults.splitSelectableChipColors].
+ * @param enabled Controls the enabled state of the chip. When `false`, this chip will not be
+ * clickable
+ * @param selectionInteractionSource an optional hoisted [MutableInteractionSource] for observing
+ * and emitting [Interaction]s for this chip's "selectable" tap area. You can use this to change
+ * the chip's appearance or preview the chip in different states. Note that if `null` is provided,
+ * interactions will still happen internally.
* @param containerInteractionSource an optional hoisted [MutableInteractionSource] for observing
- * and emitting [Interaction]s for this chip's "clickable" tap area. You can use this to change the
- * chip's appearance or preview the chip in different states. Note that if `null` is provided,
- * interactions will still happen internally.
+ * and emitting [Interaction]s for this chip's "clickable" tap area. You can use this to change
+ * the chip's appearance or preview the chip in different states. Note that if `null` is provided,
+ * interactions will still happen internally.
* @param contentPadding The spacing values to apply internally between the container and the
- * content
+ * content
* @param shape Defines the chip's shape. It is strongly recommended to use the default as this
- * shape is a key characteristic of the Wear Material Theme
- * @param selectionControl A slot for providing the chip's selection control. One built-in
- * selection control is provided, see [RadioButton]. For [Checkbox] and [Switch], use
- * [SplitToggleChip] instead.
+ * shape is a key characteristic of the Wear Material Theme
+ * @param selectionControl A slot for providing the chip's selection control. One built-in selection
+ * control is provided, see [RadioButton]. For [Checkbox] and [Switch], use [SplitToggleChip]
+ * instead.
*/
@Composable
public fun SplitSelectableChip(
@@ -248,60 +247,58 @@
selectionControl: @Composable BoxScope.() -> Unit = {
RadioButton(selected = selected, enabled = enabled)
},
-) = androidx.wear.compose.materialcore.SplitToggleButton(
- checked = selected,
- onCheckedChange = onSelectionClick,
- label = provideScopeContent(
- contentColor = colors.contentColor(enabled = enabled),
- textStyle = MaterialTheme.typography.button,
- content = label
- ),
- onClick = onContainerClick,
- toggleControl = null,
- selectionControl = provideScopeContent(
- contentColor = colors.selectionControlColor(enabled = enabled, selected = selected),
- content = selectionControl
- ),
- modifier = modifier
- .defaultMinSize(minHeight = SelectableChipDefaults.Height)
- .height(IntrinsicSize.Min),
- secondaryLabel = provideNullableScopeContent(
- contentColor = colors.secondaryContentColor(enabled = enabled),
- textStyle = MaterialTheme.typography.caption2,
- content = secondaryLabel
- ),
- backgroundColor = { isEnabled, _ -> colors.backgroundColor(enabled = isEnabled) },
- splitBackgroundColor = { isEnabled, isSelected ->
- colors.splitBackgroundOverlay(
- enabled = isEnabled,
- selected = isSelected
- )
- },
- enabled = enabled,
- checkedInteractionSource = selectionInteractionSource,
- clickInteractionSource = containerInteractionSource,
- contentPadding = contentPadding,
- shape = shape,
- labelSpacerSize = 0.dp,
- ripple = rippleOrFallbackImplementation()
-)
+) =
+ androidx.wear.compose.materialcore.SplitToggleButton(
+ checked = selected,
+ onCheckedChange = onSelectionClick,
+ label =
+ provideScopeContent(
+ contentColor = colors.contentColor(enabled = enabled),
+ textStyle = MaterialTheme.typography.button,
+ content = label
+ ),
+ onClick = onContainerClick,
+ toggleControl = null,
+ selectionControl =
+ provideScopeContent(
+ contentColor = colors.selectionControlColor(enabled = enabled, selected = selected),
+ content = selectionControl
+ ),
+ modifier =
+ modifier
+ .defaultMinSize(minHeight = SelectableChipDefaults.Height)
+ .height(IntrinsicSize.Min),
+ secondaryLabel =
+ provideNullableScopeContent(
+ contentColor = colors.secondaryContentColor(enabled = enabled),
+ textStyle = MaterialTheme.typography.caption2,
+ content = secondaryLabel
+ ),
+ backgroundColor = { isEnabled, _ -> colors.backgroundColor(enabled = isEnabled) },
+ splitBackgroundColor = { isEnabled, isSelected ->
+ colors.splitBackgroundOverlay(enabled = isEnabled, selected = isSelected)
+ },
+ enabled = enabled,
+ checkedInteractionSource = selectionInteractionSource,
+ clickInteractionSource = containerInteractionSource,
+ contentPadding = contentPadding,
+ shape = shape,
+ labelSpacerSize = 0.dp,
+ ripple = rippleOrFallbackImplementation()
+ )
-/**
- * Represents the background and content colors used in [SelectableChip]s
- * in different states.
- */
+/** Represents the background and content colors used in [SelectableChip]s in different states. */
@Stable
public interface SelectableChipColors {
/**
* Represents the background treatment for this chip, depending on the [enabled] and [selected]
- * properties. Backgrounds are typically a linear gradient when the chip is selected
- * and solid when it is not.
+ * properties. Backgrounds are typically a linear gradient when the chip is selected and solid
+ * when it is not.
*
* @param enabled Whether the chip is enabled
* @param selected Whether the chip is currently selected or unselected
*/
- @Composable
- public fun background(enabled: Boolean, selected: Boolean): State<Painter>
+ @Composable public fun background(enabled: Boolean, selected: Boolean): State<Painter>
/**
* Represents the content color for this chip, depending on the [enabled] and [selected]
@@ -310,8 +307,7 @@
* @param enabled Whether the chip is enabled
* @param selected Whether the chip is currently selected or unselected
*/
- @Composable
- public fun contentColor(enabled: Boolean, selected: Boolean): State<Color>
+ @Composable public fun contentColor(enabled: Boolean, selected: Boolean): State<Color>
/**
* Represents the secondary content color for this chip, depending on the [enabled] and
@@ -320,8 +316,7 @@
* @param enabled Whether the chip is enabled
* @param selected Whether the chip is currently selected or unselected
*/
- @Composable
- public fun secondaryContentColor(enabled: Boolean, selected: Boolean): State<Color>
+ @Composable public fun secondaryContentColor(enabled: Boolean, selected: Boolean): State<Color>
/**
* Represents the color for the selection control content for this chip, depending on the
@@ -330,8 +325,7 @@
* @param enabled Whether the chip is enabled
* @param selected Whether the chip is currently selected or unselected
*/
- @Composable
- public fun selectionControlColor(enabled: Boolean, selected: Boolean): State<Color>
+ @Composable public fun selectionControlColor(enabled: Boolean, selected: Boolean): State<Color>
}
/**
@@ -344,24 +338,21 @@
*
* @param enabled Whether the chip is enabled
*/
- @Composable
- public fun backgroundColor(enabled: Boolean): State<Color>
+ @Composable public fun backgroundColor(enabled: Boolean): State<Color>
/**
* Represents the content color for this chip, depending on whether it is [enabled]
*
* @param enabled Whether the chip is enabled
*/
- @Composable
- public fun contentColor(enabled: Boolean): State<Color>
+ @Composable public fun contentColor(enabled: Boolean): State<Color>
/**
* Represents the secondary content color for this chip, depending on whether it is [enabled]
*
* @param enabled Whether the chip is enabled
*/
- @Composable
- public fun secondaryContentColor(enabled: Boolean): State<Color>
+ @Composable public fun secondaryContentColor(enabled: Boolean): State<Color>
/**
* Represents the color for the selection control content for this chip, depending on the
@@ -370,8 +361,7 @@
* @param enabled Whether the chip is enabled
* @param selected Whether the chip is currently selected or unselected
*/
- @Composable
- public fun selectionControlColor(enabled: Boolean, selected: Boolean): State<Color>
+ @Composable public fun selectionControlColor(enabled: Boolean, selected: Boolean): State<Color>
/**
* Represents the overlay to apply to a split background SplitSelectableChip to distinguish
@@ -381,52 +371,51 @@
* @param enabled Whether the chip is enabled
* @param selected Whether the chip is currently selected or unselected
*/
- @Composable
- public fun splitBackgroundOverlay(enabled: Boolean, selected: Boolean): State<Color>
+ @Composable public fun splitBackgroundOverlay(enabled: Boolean, selected: Boolean): State<Color>
}
-/**
- * Contains the default values used by [SelectableChip]s and [SplitSelectableChip]s
- */
+/** Contains the default values used by [SelectableChip]s and [SplitSelectableChip]s */
public object SelectableChipDefaults {
/**
- * Creates a [SelectableChipColors] for use in a [SelectableChip].
- * [SelectableChip]s are expected to have a linear gradient background when
- * selected, similar to a [ChipDefaults.gradientBackgroundChipColors] and a solid
- * neutral background when not selected (similar to a [ChipDefaults.secondaryChipColors])
+ * Creates a [SelectableChipColors] for use in a [SelectableChip]. [SelectableChip]s are
+ * expected to have a linear gradient background when selected, similar to a
+ * [ChipDefaults.gradientBackgroundChipColors] and a solid neutral background when not selected
+ * (similar to a [ChipDefaults.secondaryChipColors])
*
* @param selectedStartBackgroundColor The background color used at the start of the gradient of
- * a [SelectableChip] when enabled and selected.
+ * a [SelectableChip] when enabled and selected.
* @param selectedEndBackgroundColor The background color used at the end of the gradient of a
- * [SelectableChip] when enabled and selected.
+ * [SelectableChip] when enabled and selected.
* @param selectedContentColor The content color of a [SelectableChip] when enabled and
- * selected.
+ * selected.
* @param selectedSecondaryContentColor The secondary content color of this [SelectableChip]
- * when enabled and selected, used for secondaryLabel content
+ * when enabled and selected, used for secondaryLabel content
* @param selectedSelectionControlColor The selection control color of this [SelectableChip]
- * when enabled and selected, used for selectionControl content
+ * when enabled and selected, used for selectionControl content
* @param unselectedStartBackgroundColor The background color used at the start of the gradient
- * of a [SelectableChip] when enabled and unselected.
+ * of a [SelectableChip] when enabled and unselected.
* @param unselectedEndBackgroundColor The background color used at the end of the gradient of a
- * [SelectableChip] when enabled and unselected.
+ * [SelectableChip] when enabled and unselected.
* @param unselectedContentColor The content color of a [SelectableChip] when enabled and
- * unselected.
+ * unselected.
* @param unselectedSecondaryContentColor The secondary content color of this [SelectableChip]
- * when enabled and unselected, used for secondaryLabel content
+ * when enabled and unselected, used for secondaryLabel content
* @param unselectedSelectionControlColor The selection control color of this [SelectableChip]
- * when enabled and unselected.
+ * when enabled and unselected.
* @param gradientDirection Whether the chips gradient should be start to end (indicated by
- * [LayoutDirection.Ltr]) or end to start (indicated by [LayoutDirection.Rtl]).
+ * [LayoutDirection.Ltr]) or end to start (indicated by [LayoutDirection.Rtl]).
*/
@Suppress("PrimitiveInCollection")
@Composable
public fun selectableChipColors(
selectedStartBackgroundColor: Color =
- MaterialTheme.colors.surface.copy(alpha = 0f)
+ MaterialTheme.colors.surface
+ .copy(alpha = 0f)
.compositeOver(MaterialTheme.colors.surface),
selectedEndBackgroundColor: Color =
- MaterialTheme.colors.primary.copy(alpha = 0.5f)
+ MaterialTheme.colors.primary
+ .copy(alpha = 0.5f)
.compositeOver(MaterialTheme.colors.surface),
selectedContentColor: Color = MaterialTheme.colors.onSurface,
selectedSecondaryContentColor: Color = MaterialTheme.colors.onSurfaceVariant,
@@ -441,81 +430,68 @@
val selectedBackgroundColors: List<Color>
val disabledSelectedBackgroundColors: List<Color>
if (gradientDirection == LayoutDirection.Ltr) {
- selectedBackgroundColors = listOf(
- selectedStartBackgroundColor,
- selectedEndBackgroundColor
- )
- disabledSelectedBackgroundColors = listOf(
- selectedStartBackgroundColor.copy(alpha = ContentAlpha.disabled),
- selectedEndBackgroundColor.copy(alpha = ContentAlpha.disabled)
- )
+ selectedBackgroundColors =
+ listOf(selectedStartBackgroundColor, selectedEndBackgroundColor)
+ disabledSelectedBackgroundColors =
+ listOf(
+ selectedStartBackgroundColor.copy(alpha = ContentAlpha.disabled),
+ selectedEndBackgroundColor.copy(alpha = ContentAlpha.disabled)
+ )
} else {
- selectedBackgroundColors = listOf(
- selectedEndBackgroundColor,
- selectedStartBackgroundColor
- )
- disabledSelectedBackgroundColors = listOf(
- selectedEndBackgroundColor.copy(alpha = ContentAlpha.disabled),
- selectedStartBackgroundColor.copy(alpha = ContentAlpha.disabled),
- )
+ selectedBackgroundColors =
+ listOf(selectedEndBackgroundColor, selectedStartBackgroundColor)
+ disabledSelectedBackgroundColors =
+ listOf(
+ selectedEndBackgroundColor.copy(alpha = ContentAlpha.disabled),
+ selectedStartBackgroundColor.copy(alpha = ContentAlpha.disabled),
+ )
}
val unselectedBackgroundColors: List<Color>
val disabledUnselectedBackgroundColors: List<Color>
if (gradientDirection == LayoutDirection.Ltr) {
- unselectedBackgroundColors = listOf(
- unselectedStartBackgroundColor,
- unselectedEndBackgroundColor
- )
- disabledUnselectedBackgroundColors = listOf(
- unselectedStartBackgroundColor.copy(alpha = ContentAlpha.disabled),
- unselectedEndBackgroundColor.copy(alpha = ContentAlpha.disabled)
- )
+ unselectedBackgroundColors =
+ listOf(unselectedStartBackgroundColor, unselectedEndBackgroundColor)
+ disabledUnselectedBackgroundColors =
+ listOf(
+ unselectedStartBackgroundColor.copy(alpha = ContentAlpha.disabled),
+ unselectedEndBackgroundColor.copy(alpha = ContentAlpha.disabled)
+ )
} else {
- unselectedBackgroundColors = listOf(
- unselectedEndBackgroundColor,
- unselectedStartBackgroundColor
- )
- disabledUnselectedBackgroundColors = listOf(
- unselectedEndBackgroundColor.copy(alpha = ContentAlpha.disabled),
- unselectedStartBackgroundColor.copy(alpha = ContentAlpha.disabled),
- )
+ unselectedBackgroundColors =
+ listOf(unselectedEndBackgroundColor, unselectedStartBackgroundColor)
+ disabledUnselectedBackgroundColors =
+ listOf(
+ unselectedEndBackgroundColor.copy(alpha = ContentAlpha.disabled),
+ unselectedStartBackgroundColor.copy(alpha = ContentAlpha.disabled),
+ )
}
return DefaultSelectableChipColors(
- selectedBackgroundPainter = BrushPainter(
- Brush.linearGradient(selectedBackgroundColors)
- ),
+ selectedBackgroundPainter =
+ BrushPainter(Brush.linearGradient(selectedBackgroundColors)),
selectedContentColor = selectedContentColor,
selectedSecondaryContentColor = selectedSecondaryContentColor,
selectedIconColor = selectedSelectionControlColor,
- unselectedBackgroundPainter = BrushPainter(
- Brush.linearGradient(unselectedBackgroundColors)
- ),
+ unselectedBackgroundPainter =
+ BrushPainter(Brush.linearGradient(unselectedBackgroundColors)),
unselectedContentColor = unselectedContentColor,
unselectedSecondaryContentColor = unselectedSecondaryContentColor,
unselectedIconColor = unselectedSelectionControlColor,
- disabledSelectedBackgroundPainter = BrushPainter(
- Brush.linearGradient(disabledSelectedBackgroundColors)
- ),
+ disabledSelectedBackgroundPainter =
+ BrushPainter(Brush.linearGradient(disabledSelectedBackgroundColors)),
disabledSelectedContentColor = selectedContentColor.copy(alpha = ContentAlpha.disabled),
- disabledSelectedSecondaryContentColor = selectedSecondaryContentColor.copy(
- alpha = ContentAlpha.disabled
- ),
- disabledSelectedIconColor = selectedSelectionControlColor.copy(
- alpha = ContentAlpha.disabled
- ),
- disabledUnselectedBackgroundPainter = BrushPainter(
- Brush.linearGradient(disabledUnselectedBackgroundColors)
- ),
- disabledUnselectedContentColor = unselectedContentColor.copy(
- alpha = ContentAlpha.disabled
- ),
- disabledUnselectedSecondaryContentColor = unselectedSecondaryContentColor.copy(
- alpha = ContentAlpha.disabled
- ),
- disabledUnselectedIconColor = unselectedSelectionControlColor.copy(
- alpha = ContentAlpha.disabled
- ),
+ disabledSelectedSecondaryContentColor =
+ selectedSecondaryContentColor.copy(alpha = ContentAlpha.disabled),
+ disabledSelectedIconColor =
+ selectedSelectionControlColor.copy(alpha = ContentAlpha.disabled),
+ disabledUnselectedBackgroundPainter =
+ BrushPainter(Brush.linearGradient(disabledUnselectedBackgroundColors)),
+ disabledUnselectedContentColor =
+ unselectedContentColor.copy(alpha = ContentAlpha.disabled),
+ disabledUnselectedSecondaryContentColor =
+ unselectedSecondaryContentColor.copy(alpha = ContentAlpha.disabled),
+ disabledUnselectedIconColor =
+ unselectedSelectionControlColor.copy(alpha = ContentAlpha.disabled),
)
}
@@ -525,15 +501,15 @@
* @param backgroundColor The background color of this [SplitSelectableChip] when enabled
* @param contentColor The content color of this [SplitSelectableChip] when enabled.
* @param secondaryContentColor The secondary content color of this[SplitSelectableChip] when
- * enabled
- * @param selectedSelectionControlColor The selection control content color of
- * this [SplitSelectableChip] when enabled.
+ * enabled
+ * @param selectedSelectionControlColor The selection control content color of this
+ * [SplitSelectableChip] when enabled.
* @param unselectedSelectionControlColor The selection control content color of this
- * [SplitSelectableChip] when enabled.
+ * [SplitSelectableChip] when enabled.
* @param splitBackgroundOverlayColor The color to use to lighten/distinguish the background
- * behind the selection control for a split background chip. A split background chip has two
- * tappable areas, one for the main body of the chip and one for area around the selection
- * control icon.
+ * behind the selection control for a split background chip. A split background chip has two
+ * tappable areas, one for the main body of the chip and one for area around the selection
+ * control icon.
*/
@Composable
public fun splitSelectableChipColors(
@@ -554,16 +530,13 @@
unselectedSplitBackgroundOverlay = splitBackgroundOverlayColor,
disabledBackgroundColor = backgroundColor.copy(alpha = ContentAlpha.disabled),
disabledContentColor = contentColor.copy(alpha = ContentAlpha.disabled),
- disabledSecondaryContentColor = secondaryContentColor.copy(
- alpha = ContentAlpha.disabled
- ),
- disabledSelectedIconColor = selectedSelectionControlColor.copy(
- alpha = ContentAlpha.disabled
- ),
+ disabledSecondaryContentColor =
+ secondaryContentColor.copy(alpha = ContentAlpha.disabled),
+ disabledSelectedIconColor =
+ selectedSelectionControlColor.copy(alpha = ContentAlpha.disabled),
disabledSelectedSplitBackgroundOverlay = splitBackgroundOverlayColor,
- disabledUnselectedIconColor = unselectedSelectionControlColor.copy(
- alpha = ContentAlpha.disabled
- ),
+ disabledUnselectedIconColor =
+ unselectedSelectionControlColor.copy(alpha = ContentAlpha.disabled),
disabledUnselectedSplitBackgroundOverlay = splitBackgroundOverlayColor,
)
}
@@ -571,20 +544,19 @@
private val ChipHorizontalPadding = 14.dp
private val ChipVerticalPadding = 6.dp
- /**
- * The default content padding used by [SelectableChip] and [SplitSelectableChip]
- */
- public val ContentPadding: PaddingValues = PaddingValues(
- start = ChipHorizontalPadding,
- top = ChipVerticalPadding,
- end = ChipHorizontalPadding,
- bottom = ChipVerticalPadding
- )
+ /** The default content padding used by [SelectableChip] and [SplitSelectableChip] */
+ public val ContentPadding: PaddingValues =
+ PaddingValues(
+ start = ChipHorizontalPadding,
+ top = ChipVerticalPadding,
+ end = ChipHorizontalPadding,
+ bottom = ChipVerticalPadding
+ )
/**
- * The default height applied for the [SelectableChip] or [SplitSelectableChip].
- * Note that you can override it by applying Modifier.heightIn directly
- * on [SelectableChip] or [SplitSelectableChip].
+ * The default height applied for the [SelectableChip] or [SplitSelectableChip]. Note that you
+ * can override it by applying Modifier.heightIn directly on [SelectableChip] or
+ * [SplitSelectableChip].
*/
public val Height = 52.dp
@@ -595,9 +567,7 @@
public val IconSize: Dp = 24.dp
}
-/**
- * Default [SelectableChipColors] implementation.
- */
+/** Default [SelectableChipColors] implementation. */
@Immutable
private class DefaultSelectableChipColors(
private val selectedBackgroundPainter: Painter,
@@ -624,8 +594,8 @@
if (enabled) {
if (selected) selectedBackgroundPainter else unselectedBackgroundPainter
} else {
- if (selected) disabledSelectedBackgroundPainter else
- disabledUnselectedBackgroundPainter
+ if (selected) disabledSelectedBackgroundPainter
+ else disabledUnselectedBackgroundPainter
}
)
}
@@ -647,8 +617,8 @@
if (enabled) {
if (selected) selectedSecondaryContentColor else unselectedSecondaryContentColor
} else {
- if (selected) disabledSelectedSecondaryContentColor else
- disabledUnselectedSecondaryContentColor
+ if (selected) disabledSelectedSecondaryContentColor
+ else disabledUnselectedSecondaryContentColor
}
)
}
@@ -683,17 +653,16 @@
return false
if (disabledSelectedContentColor != other.disabledSelectedContentColor) return false
if (disabledSelectedIconColor != other.disabledSelectedIconColor) return false
- if (disabledSelectedSecondaryContentColor !=
- other.disabledSelectedSecondaryContentColor
- ) return false
- if (disabledUnselectedBackgroundPainter !=
- other.disabledUnselectedBackgroundPainter
- ) return false
+ if (disabledSelectedSecondaryContentColor != other.disabledSelectedSecondaryContentColor)
+ return false
+ if (disabledUnselectedBackgroundPainter != other.disabledUnselectedBackgroundPainter)
+ return false
if (disabledUnselectedContentColor != other.disabledUnselectedContentColor) return false
if (disabledUnselectedIconColor != other.disabledUnselectedIconColor) return false
- if (disabledUnselectedSecondaryContentColor !=
- other.disabledUnselectedSecondaryContentColor
- ) return false
+ if (
+ disabledUnselectedSecondaryContentColor != other.disabledUnselectedSecondaryContentColor
+ )
+ return false
return true
}
@@ -719,9 +688,7 @@
}
}
-/**
- * Default [SplitSelectableChipColors] implementation.
- */
+/** Default [SplitSelectableChipColors] implementation. */
@Immutable
private class DefaultSplitSelectableChipColors(
private val backgroundColor: Color,
@@ -742,16 +709,12 @@
@Composable
override fun backgroundColor(enabled: Boolean): State<Color> {
- return rememberUpdatedState(
- if (enabled) backgroundColor else disabledBackgroundColor
- )
+ return rememberUpdatedState(if (enabled) backgroundColor else disabledBackgroundColor)
}
@Composable
override fun contentColor(enabled: Boolean): State<Color> {
- return rememberUpdatedState(
- if (enabled) contentColor else disabledContentColor
- )
+ return rememberUpdatedState(if (enabled) contentColor else disabledContentColor)
}
@Composable
@@ -778,8 +741,8 @@
if (enabled) {
if (selected) selectedSplitBackgroundOverlay else unselectedSplitBackgroundOverlay
} else {
- if (selected) disabledSelectedSplitBackgroundOverlay else
- disabledUnselectedSplitBackgroundOverlay
+ if (selected) disabledSelectedSplitBackgroundOverlay
+ else disabledUnselectedSplitBackgroundOverlay
}
)
}
@@ -801,13 +764,14 @@
if (disabledContentColor != other.disabledContentColor) return false
if (disabledSelectedIconColor != other.disabledSelectedIconColor) return false
if (disabledSecondaryContentColor != other.disabledSecondaryContentColor) return false
- if (disabledSelectedSplitBackgroundOverlay !=
- other.disabledSelectedSplitBackgroundOverlay
- ) return false
+ if (disabledSelectedSplitBackgroundOverlay != other.disabledSelectedSplitBackgroundOverlay)
+ return false
if (disabledUnselectedIconColor != other.disabledUnselectedIconColor) return false
- if (disabledUnselectedSplitBackgroundOverlay !=
- other.disabledUnselectedSplitBackgroundOverlay
- ) return false
+ if (
+ disabledUnselectedSplitBackgroundOverlay !=
+ other.disabledUnselectedSplitBackgroundOverlay
+ )
+ return false
return true
}
diff --git a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/Shapes.kt b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/Shapes.kt
index 65ba135..cfd70fa 100644
--- a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/Shapes.kt
+++ b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/Shapes.kt
@@ -25,34 +25,27 @@
/**
* Components are grouped into shape categories based on common features. These categories provide a
* way to change multiple component values at once, by changing the category’s values.
- *
*/
@Immutable
public class Shapes(
- /**
- * Buttons and Chips use this shape
- */
+ /** Buttons and Chips use this shape */
public val small: CornerBasedShape = RoundedCornerShape(corner = CornerSize(50)),
-
public val medium: CornerBasedShape = RoundedCornerShape(4.dp),
- /**
- * Cards use this shape
- */
+ /** Cards use this shape */
public val large: CornerBasedShape = RoundedCornerShape(26.dp),
) {
- /**
- * Returns a copy of this Shapes, optionally overriding some of the values.
- */
+ /** Returns a copy of this Shapes, optionally overriding some of the values. */
public fun copy(
small: CornerBasedShape = this.small,
medium: CornerBasedShape = this.medium,
large: CornerBasedShape = this.large,
- ): Shapes = Shapes(
- small = small,
- medium = medium,
- large = large,
- )
+ ): Shapes =
+ Shapes(
+ small = small,
+ medium = medium,
+ large = large,
+ )
override fun equals(other: Any?): Boolean {
if (this === other) return true
@@ -77,7 +70,5 @@
}
}
-/**
- * CompositionLocal used to specify the default shapes for the surfaces.
- */
+/** CompositionLocal used to specify the default shapes for the surfaces. */
internal val LocalShapes = staticCompositionLocalOf { Shapes() }
diff --git a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/Slider.kt b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/Slider.kt
index ec0a2a2..68a333f 100644
--- a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/Slider.kt
+++ b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/Slider.kt
@@ -54,42 +54,43 @@
/**
* [InlineSlider] allows users to make a selection from a range of values. The range of selections
- * is shown as a bar between the minimum and maximum values of the range,
- * from which users may select a single value.
- * InlineSlider is ideal for adjusting settings such as volume or brightness.
+ * is shown as a bar between the minimum and maximum values of the range, from which users may
+ * select a single value. InlineSlider is ideal for adjusting settings such as volume or brightness.
*
* Value can be increased and decreased by clicking on the increase and decrease buttons, located
- * accordingly to the start and end of the control. Buttons can have custom icons -
- * [decreaseIcon] and [increaseIcon].
+ * accordingly to the start and end of the control. Buttons can have custom icons - [decreaseIcon]
+ * and [increaseIcon].
*
- * The bar in the middle of control can have separators if [segmented] flag is set to true.
- * A single step value is calculated as the difference between min and max values of [valueRange]
- * divided by [steps] + 1 value.
+ * The bar in the middle of control can have separators if [segmented] flag is set to true. A single
+ * step value is calculated as the difference between min and max values of [valueRange] divided by
+ * [steps] + 1 value.
*
* A continuous non-segmented slider sample:
+ *
* @sample androidx.wear.compose.material.samples.InlineSliderSample
*
* A segmented slider sample:
+ *
* @sample androidx.wear.compose.material.samples.InlineSliderSegmentedSample
*
* @param value Current value of the Slider. If outside of [valueRange] provided, value will be
- * coerced to this range.
+ * coerced to this range.
* @param onValueChange Lambda in which value should be updated
* @param steps Specifies the number of discrete values, excluding min and max values, evenly
- * distributed across the whole value range. Must not be negative. If 0, slider will have only
- * min and max values and no steps in between
+ * distributed across the whole value range. Must not be negative. If 0, slider will have only min
+ * and max values and no steps in between
* @param decreaseIcon A slot for an icon which is placed on the decrease (start) button
* @param increaseIcon A slot for an icon which is placed on the increase (end) button
* @param modifier Modifiers for the Slider layout
- * @param enabled Controls the enabled state of the slider.
- * When `false`, this slider will not be clickable
+ * @param enabled Controls the enabled state of the slider. When `false`, this slider will not be
+ * clickable
* @param valueRange Range of values that Slider value can take. Passed [value] will be coerced to
- * this range
- * @param segmented A boolean value which specifies whether a bar will be split into
- * segments or not. Recommendation is while using this flag do not have more than 8 [steps]
- * as it might affect user experience. By default true if number of [steps] is <=8.
- * @param colors [InlineSliderColors] that will be used to resolve the background and content
- * color for this slider in different states
+ * this range
+ * @param segmented A boolean value which specifies whether a bar will be split into segments or
+ * not. Recommendation is while using this flag do not have more than 8 [steps] as it might affect
+ * user experience. By default true if number of [steps] is <=8.
+ * @param colors [InlineSliderColors] that will be used to resolve the background and content color
+ * for this slider in different states
*/
@Composable
public fun InlineSlider(
@@ -107,26 +108,16 @@
require(steps >= 0) { "steps should be >= 0" }
val currentStep =
remember(value, valueRange, steps) {
- RangeDefaults.snapValueToStep(
- value,
- valueRange,
- steps
- )
+ RangeDefaults.snapValueToStep(value, valueRange, steps)
}
Box(
- modifier = modifier
- .fillMaxWidth()
- .rangeSemantics(
- value,
- enabled,
- onValueChange,
- valueRange,
- steps
- )
- .height(InlineSliderDefaults.SliderHeight)
- .clip(MaterialTheme.shapes.small),
+ modifier =
+ modifier
+ .fillMaxWidth()
+ .rangeSemantics(value, enabled, onValueChange, valueRange, steps)
+ .height(InlineSliderDefaults.SliderHeight)
+ .clip(MaterialTheme.shapes.small),
) {
-
val visibleSegments = if (segmented) steps + 1 else 1
val updateValue: (Int) -> Unit = { stepDiff ->
@@ -141,9 +132,7 @@
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Start,
- modifier = Modifier
- .fillMaxWidth()
- .background(backgroundColor.value)
+ modifier = Modifier.fillMaxWidth().background(backgroundColor.value)
) {
val increaseButtonEnabled = enabled && currentStep < steps + 1
val decreaseButtonEnabled = enabled && currentStep > 0
@@ -158,8 +147,7 @@
)
Box(
- Modifier
- .width(InlineSliderDefaults.SpacersWidth)
+ Modifier.width(InlineSliderDefaults.SpacersWidth)
.fillMaxHeight()
.background(colors.spacerColor(enabled).value)
)
@@ -167,33 +155,32 @@
val valueRatio by animateFloatAsState(currentStep.toFloat() / (steps + 1).toFloat())
Box(
- modifier = Modifier
- .padding(horizontal = InlineSliderDefaults.BarMargin)
- .height(InlineSliderDefaults.BarHeight)
- .weight(1f)
- .clip(MaterialTheme.shapes.small)
- .drawProgressBar(
- selectedBarColor = selectedBarColor,
- unselectedBarColor = unselectedBarColor,
- barSeparatorColor = backgroundColor,
- visibleSegments = visibleSegments,
- valueRatio = valueRatio,
- direction = LocalLayoutDirection.current,
- drawSelectedProgressBar = { color, ratio, direction, drawScope ->
- drawScope.drawSelectedProgressBar(color, ratio, direction)
- },
- drawUnselectedProgressBar = { color, ratio, direction, drawScope ->
- drawScope.drawUnselectedProgressBar(color, ratio, direction)
- },
- drawProgressBarSeparator = { color, position, drawScope ->
- drawScope.drawProgressBarSeparator(color, position)
- }
- )
+ modifier =
+ Modifier.padding(horizontal = InlineSliderDefaults.BarMargin)
+ .height(InlineSliderDefaults.BarHeight)
+ .weight(1f)
+ .clip(MaterialTheme.shapes.small)
+ .drawProgressBar(
+ selectedBarColor = selectedBarColor,
+ unselectedBarColor = unselectedBarColor,
+ barSeparatorColor = backgroundColor,
+ visibleSegments = visibleSegments,
+ valueRatio = valueRatio,
+ direction = LocalLayoutDirection.current,
+ drawSelectedProgressBar = { color, ratio, direction, drawScope ->
+ drawScope.drawSelectedProgressBar(color, ratio, direction)
+ },
+ drawUnselectedProgressBar = { color, ratio, direction, drawScope ->
+ drawScope.drawUnselectedProgressBar(color, ratio, direction)
+ },
+ drawProgressBarSeparator = { color, position, drawScope ->
+ drawScope.drawProgressBarSeparator(color, position)
+ }
+ )
)
Box(
- Modifier
- .width(InlineSliderDefaults.SpacersWidth)
+ Modifier.width(InlineSliderDefaults.SpacersWidth)
.fillMaxHeight()
.background(colors.spacerColor(enabled).value)
)
@@ -212,45 +199,45 @@
/**
* [InlineSlider] allows users to make a selection from a range of values. The range of selections
- * is shown as a bar between the minimum and maximum values of the range,
- * from which users may select a single value.
- * InlineSlider is ideal for adjusting settings such as volume or brightness.
+ * is shown as a bar between the minimum and maximum values of the range, from which users may
+ * select a single value. InlineSlider is ideal for adjusting settings such as volume or brightness.
*
* Value can be increased and decreased by clicking on the increase and decrease buttons, located
- * accordingly to the start and end of the control. Buttons can have custom icons -
- * [decreaseIcon] and [increaseIcon].
+ * accordingly to the start and end of the control. Buttons can have custom icons - [decreaseIcon]
+ * and [increaseIcon].
*
- * The bar in the middle of control can have separators if [segmented] flag is set to true.
- * A number of steps is calculated as the difference between max and min values of
- * [valueProgression] divided by [valueProgression].step - 1.
- * For example, with a range of 100..120 and a step 5,
- * number of steps will be (120-100)/ 5 - 1 = 3. Steps are 100(first), 105, 110, 115, 120(last)
+ * The bar in the middle of control can have separators if [segmented] flag is set to true. A number
+ * of steps is calculated as the difference between max and min values of [valueProgression] divided
+ * by [valueProgression].step - 1. For example, with a range of 100..120 and a step 5, number of
+ * steps will be (120-100)/ 5 - 1 = 3. Steps are 100(first), 105, 110, 115, 120(last)
*
- * If [valueProgression] range is not equally divisible by [valueProgression].step,
- * then [valueProgression].last will be adjusted to the closest divisible value in the range.
- * For example, 1..13 range and a step = 5, steps will be 1(first) , 6 , 11(last)
+ * If [valueProgression] range is not equally divisible by [valueProgression].step, then
+ * [valueProgression].last will be adjusted to the closest divisible value in the range. For
+ * example, 1..13 range and a step = 5, steps will be 1(first) , 6 , 11(last)
*
* A continuous non-segmented slider sample:
+ *
* @sample androidx.wear.compose.material.samples.InlineSliderWithIntegerSample
*
* A segmented slider sample:
+ *
* @sample androidx.wear.compose.material.samples.InlineSliderSegmentedSample
*
- * @param value Current value of the Slider. If outside of [valueProgression] provided, value will be
- * coerced to this range.
+ * @param value Current value of the Slider. If outside of [valueProgression] provided, value will
+ * be coerced to this range.
* @param onValueChange Lambda in which value should be updated
- * @param valueProgression Progression of values that Slider value can take. Consists of
- * rangeStart, rangeEnd and step. Range will be equally divided by step size
+ * @param valueProgression Progression of values that Slider value can take. Consists of rangeStart,
+ * rangeEnd and step. Range will be equally divided by step size
* @param decreaseIcon A slot for an icon which is placed on the decrease (start) button
* @param increaseIcon A slot for an icon which is placed on the increase (end) button
* @param modifier Modifiers for the Slider layout
- * @param enabled Controls the enabled state of the slider.
- * When `false`, this slider will not be clickable
- * @param segmented A boolean value which specifies whether a bar will be split into
- * segments or not. Recommendation is while using this flag do not have more than 8 steps
- * as it might affect user experience. By default true if number of steps is <=8.
- * @param colors [InlineSliderColors] that will be used to resolve the background and content
- * color for this slider in different states
+ * @param enabled Controls the enabled state of the slider. When `false`, this slider will not be
+ * clickable
+ * @param segmented A boolean value which specifies whether a bar will be split into segments or
+ * not. Recommendation is while using this flag do not have more than 8 steps as it might affect
+ * user experience. By default true if number of steps is <=8.
+ * @param colors [InlineSliderColors] that will be used to resolve the background and content color
+ * for this slider in different states
*/
@Composable
public fun InlineSlider(
@@ -278,46 +265,40 @@
)
}
-/**
- * Represents the background and content colors used in [InlineSlider] in different states.
- */
+/** Represents the background and content colors used in [InlineSlider] in different states. */
@Stable
public interface InlineSliderColors {
/**
* Represents the background color for this slider, depending on [enabled].
+ *
* @param enabled Whether the slider is enabled
*/
- @Composable
- public fun backgroundColor(enabled: Boolean): State<Color>
+ @Composable public fun backgroundColor(enabled: Boolean): State<Color>
/**
- * Represents the color of the progress bar in the middle of the slider,
- * depending on the [enabled] and [selected].
+ * Represents the color of the progress bar in the middle of the slider, depending on the
+ * [enabled] and [selected].
*
* @param enabled Whether the slider is enabled
* @param selected Whether color is for selected part of the slider
*/
- @Composable
- public fun barColor(enabled: Boolean, selected: Boolean): State<Color>
+ @Composable public fun barColor(enabled: Boolean, selected: Boolean): State<Color>
/**
- * Represents the color of the spacer between buttons and a progress bar,
- * depending on the [enabled]
+ * Represents the color of the spacer between buttons and a progress bar, depending on the
+ * [enabled]
*
* @param enabled Whether the slider is enabled
*/
- @Composable
- public fun spacerColor(enabled: Boolean): State<Color>
+ @Composable public fun spacerColor(enabled: Boolean): State<Color>
}
-/**
- * Defaults used by slider
- */
+/** Defaults used by slider */
public object InlineSliderDefaults {
/**
- * The default height applied for the [InlineSlider].
- * Note that you can override it by applying Modifier.size directly on [InlineSlider].
+ * The default height applied for the [InlineSlider]. Note that you can override it by applying
+ * Modifier.size directly on [InlineSlider].
*/
internal val SliderHeight = 52.dp
@@ -334,16 +315,16 @@
internal val BarSeparatorWidth = 1.dp
/**
- * Creates a [InlineSliderColors] that represents the default background
- * and content colors used in an [InlineSlider].
+ * Creates a [InlineSliderColors] that represents the default background and content colors used
+ * in an [InlineSlider].
*
* @param backgroundColor The background color of this [InlineSlider] when enabled
* @param spacerColor The color of the spacer between buttons and a progress bar when enabled
* @param selectedBarColor The color of the progress bar when enabled
* @param unselectedBarColor The background color of the progress bar when enabled
* @param disabledBackgroundColor The background color of this [InlineSlider] when disabled
- * @param disabledSpacerColor The color of the spacer between buttons and a progress bar
- * when disabled
+ * @param disabledSpacerColor The color of the spacer between buttons and a progress bar when
+ * disabled
* @param disabledSelectedBarColor The color of the progress bar when disabled
* @param disabledUnselectedBarColor The background color of the progress bar when disabled
*/
@@ -357,25 +338,22 @@
disabledSpacerColor: Color = spacerColor.copy(alpha = ContentAlpha.disabled),
disabledSelectedBarColor: Color = selectedBarColor.copy(alpha = ContentAlpha.disabled),
disabledUnselectedBarColor: Color = unselectedBarColor.copy(alpha = 0.05f),
- ): InlineSliderColors = DefaultInlineSliderColors(
- backgroundColor = backgroundColor,
- spacerColor = spacerColor,
- selectedBarColor = selectedBarColor,
- unselectedBarColor = unselectedBarColor,
- disabledBackgroundColor = disabledBackgroundColor,
- disabledSpacerColor = disabledSpacerColor,
- disabledSelectedBarColor = disabledSelectedBarColor,
- disabledUnselectedBarColor = disabledUnselectedBarColor
- )
+ ): InlineSliderColors =
+ DefaultInlineSliderColors(
+ backgroundColor = backgroundColor,
+ spacerColor = spacerColor,
+ selectedBarColor = selectedBarColor,
+ unselectedBarColor = unselectedBarColor,
+ disabledBackgroundColor = disabledBackgroundColor,
+ disabledSpacerColor = disabledSpacerColor,
+ disabledSelectedBarColor = disabledSelectedBarColor,
+ disabledUnselectedBarColor = disabledUnselectedBarColor
+ )
- /**
- * Decrease [ImageVector]
- */
+ /** Decrease [ImageVector] */
public val Decrease = androidx.wear.compose.materialcore.RangeIcons.Minus
- /**
- * Increase [ImageVector]
- */
+ /** Increase [ImageVector] */
public val Increase = Icons.Filled.Add
}
@@ -396,9 +374,7 @@
@Composable
override fun spacerColor(enabled: Boolean): State<Color> =
- animateColorAsState(
- if (enabled) spacerColor else disabledSpacerColor
- )
+ animateColorAsState(if (enabled) spacerColor else disabledSpacerColor)
@Composable
override fun barColor(enabled: Boolean, selected: Boolean): State<Color> =
@@ -448,12 +424,8 @@
) {
drawLine(
color,
- Offset(
- directedValue(direction, 0f, size.width * (1 - valueRatio)), size.height / 2
- ),
- Offset(
- directedValue(direction, size.width * valueRatio, size.width), size.height / 2
- ),
+ Offset(directedValue(direction, 0f, size.width * (1 - valueRatio)), size.height / 2),
+ Offset(directedValue(direction, size.width * valueRatio, size.width), size.height / 2),
strokeWidth = InlineSliderDefaults.BarHeight.toPx()
)
}
@@ -465,11 +437,10 @@
) {
drawLine(
color,
+ Offset(directedValue(direction, size.width * valueRatio, 0f), size.height / 2),
Offset(
- directedValue(direction, size.width * valueRatio, 0f), size.height / 2
- ),
- Offset(
- directedValue(direction, size.width, size.width * (1 - valueRatio)), size.height / 2
+ directedValue(direction, size.width, size.width * (1 - valueRatio)),
+ size.height / 2
),
strokeWidth = InlineSliderDefaults.BarHeight.toPx()
)
@@ -485,11 +456,9 @@
}
@Composable
-private fun InlineSliderButtonContent(
- enabled: Boolean,
- content: @Composable () -> Unit
-) = CompositionLocalProvider(
- LocalContentAlpha provides
- if (enabled) LocalContentAlpha.current else ContentAlpha.disabled,
- content = content
-)
+private fun InlineSliderButtonContent(enabled: Boolean, content: @Composable () -> Unit) =
+ CompositionLocalProvider(
+ LocalContentAlpha provides
+ if (enabled) LocalContentAlpha.current else ContentAlpha.disabled,
+ content = content
+ )
diff --git a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/Stepper.kt b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/Stepper.kt
index 33da0fc..9b2378b 100644
--- a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/Stepper.kt
+++ b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/Stepper.kt
@@ -27,40 +27,40 @@
import kotlin.math.roundToInt
/**
- * [Stepper] allows users to make a selection from a range of values.
- * It's a full-screen control with increase button on the top, decrease button on the bottom and
- * a slot (expected to have either [Text] or [Chip]) in the middle.
- * Value can be increased and decreased by clicking on the increase and decrease buttons.
- * Buttons can have custom icons - [decreaseIcon] and [increaseIcon].
+ * [Stepper] allows users to make a selection from a range of values. It's a full-screen control
+ * with increase button on the top, decrease button on the bottom and a slot (expected to have
+ * either [Text] or [Chip]) in the middle. Value can be increased and decreased by clicking on the
+ * increase and decrease buttons. Buttons can have custom icons - [decreaseIcon] and [increaseIcon].
* Step value is calculated as the difference between min and max values divided by [steps]+1.
* Stepper itself doesn't show the current value but can be displayed via the content slot or
- * [PositionIndicator] if required.
- * If [value] is not equal to any step value, then it will be coerced to the closest step value.
- * However, the [value] itself will not be changed and [onValueChange] in this case will
- * not be triggered.
+ * [PositionIndicator] if required. If [value] is not equal to any step value, then it will be
+ * coerced to the closest step value. However, the [value] itself will not be changed and
+ * [onValueChange] in this case will not be triggered.
*
* @sample androidx.wear.compose.material.samples.StepperSample
+ *
* @sample androidx.wear.compose.material.samples.StepperWithoutRangeSemanticsSample
+ *
* @sample androidx.wear.compose.material.samples.StepperWithCustomSemanticsSample
*
* @param value Current value of the Stepper. If outside of [valueRange] provided, value will be
- * coerced to this range.
+ * coerced to this range.
* @param onValueChange Lambda in which value should be updated
* @param steps Specifies the number of discrete values, excluding min and max values, evenly
- * distributed across the whole value range. Must not be negative. If 0, stepper will have only
- * min and max values and no steps in between
+ * distributed across the whole value range. Must not be negative. If 0, stepper will have only
+ * min and max values and no steps in between
* @param decreaseIcon A slot for an icon which is placed on the decrease (bottom) button
* @param increaseIcon A slot for an icon which is placed on the increase (top) button
* @param modifier Modifiers for the Stepper layout
* @param valueRange Range of values that Stepper value can take. Passed [value] will be coerced to
- * this range
+ * this range
* @param backgroundColor [Color] representing the background color for the stepper.
* @param contentColor [Color] representing the color for [content] in the middle.
- * @param iconColor Icon tint [Color] which used by [increaseIcon] and [decreaseIcon]
- * that defaults to [contentColor], unless specifically overridden.
- * @param enableRangeSemantics Boolean to decide if range semantics should be enabled.
- * Set to false to disable default stepper range semantics. Alternatively to customize semantics
- * set this value as false and chain new semantics to the modifier.
+ * @param iconColor Icon tint [Color] which used by [increaseIcon] and [decreaseIcon] that defaults
+ * to [contentColor], unless specifically overridden.
+ * @param enableRangeSemantics Boolean to decide if range semantics should be enabled. Set to false
+ * to disable default stepper range semantics. Alternatively to customize semantics set this value
+ * as false and chain new semantics to the modifier.
* @param content Content body for the Stepper.
*/
@Composable
@@ -85,71 +85,67 @@
decreaseIcon = decreaseIcon,
increaseIcon = increaseIcon,
valueRange = valueRange,
- modifier = if (enableRangeSemantics) {
- modifier.rangeSemantics(
- value, true, onValueChange, valueRange, steps
- )
- } else {
- modifier
- },
+ modifier =
+ if (enableRangeSemantics) {
+ modifier.rangeSemantics(value, true, onValueChange, valueRange, steps)
+ } else {
+ modifier
+ },
backgroundColor = backgroundColor,
- enabledButtonProviderValues = arrayOf(
- LocalContentColor provides iconColor,
- LocalContentAlpha provides iconColor.alpha
- ),
- disabledButtonProviderValues = arrayOf(
- LocalContentColor provides iconColor.copy(alpha = ContentAlpha.disabled),
- LocalContentAlpha provides iconColor.copy(alpha = ContentAlpha.disabled).alpha
- ),
+ enabledButtonProviderValues =
+ arrayOf(
+ LocalContentColor provides iconColor,
+ LocalContentAlpha provides iconColor.alpha
+ ),
+ disabledButtonProviderValues =
+ arrayOf(
+ LocalContentColor provides iconColor.copy(alpha = ContentAlpha.disabled),
+ LocalContentAlpha provides iconColor.copy(alpha = ContentAlpha.disabled).alpha
+ ),
buttonRipple = rippleOrFallbackImplementation(bounded = false)
) {
- CompositionLocalProvider(
- LocalContentColor provides contentColor
- ) {
- content()
- }
+ CompositionLocalProvider(LocalContentColor provides contentColor) { content() }
}
}
/**
- * [Stepper] allows users to make a selection from a range of values.
- * It's a full-screen control with increase button on the top, decrease button on the bottom and
- * a slot (expected to have either [Text] or [Chip]) in the middle.
- * Value can be increased and decreased by clicking on the increase and decrease buttons.
- * Buttons can have custom icons - [decreaseIcon] and [increaseIcon].
+ * [Stepper] allows users to make a selection from a range of values. It's a full-screen control
+ * with increase button on the top, decrease button on the bottom and a slot (expected to have
+ * either [Text] or [Chip]) in the middle. Value can be increased and decreased by clicking on the
+ * increase and decrease buttons. Buttons can have custom icons - [decreaseIcon] and [increaseIcon].
* Stepper itself doesn't show the current value but can be displayed via the content slot or
* [PositionIndicator] if required.
*
* @sample androidx.wear.compose.material.samples.StepperWithIntegerSample
*
* A number of steps is calculated as the difference between max and min values of
- * [valueProgression] divided by [valueProgression].step - 1.
- * For example, with a range of 100..120 and a step 5,
- * number of steps will be (120-100)/ 5 - 1 = 3. Steps are 100(first), 105, 110, 115, 120(last)
+ * [valueProgression] divided by [valueProgression].step - 1. For example, with a range of 100..120
+ * and a step 5, number of steps will be (120-100)/ 5 - 1 = 3. Steps are 100(first), 105, 110, 115,
+ * 120(last)
*
- * If [valueProgression] range is not equally divisible by [valueProgression].step,
- * then [valueProgression].last will be adjusted to the closest divisible value in the range.
- * For example, 1..13 range and a step = 5, steps will be 1(first) , 6 , 11(last)
+ * If [valueProgression] range is not equally divisible by [valueProgression].step, then
+ * [valueProgression].last will be adjusted to the closest divisible value in the range. For
+ * example, 1..13 range and a step = 5, steps will be 1(first) , 6 , 11(last)
*
* If [value] is not equal to any step value, then it will be coerced to the closest step value.
- * However, the [value] itself will not be changed and [onValueChange] in this case will
- * not be triggered.
+ * However, the [value] itself will not be changed and [onValueChange] in this case will not be
+ * triggered.
*
- * @param value Current value of the Stepper. If outside of [valueProgression] provided, value will be
- * coerced to this range.
+ * @param value Current value of the Stepper. If outside of [valueProgression] provided, value will
+ * be coerced to this range.
* @param onValueChange Lambda in which value should be updated
* @param valueProgression Progression of values that Stepper value can take. Consists of
- * rangeStart, rangeEnd and step. Range will be equally divided by step size
+ * rangeStart, rangeEnd and step. Range will be equally divided by step size
* @param decreaseIcon A slot for an icon which is placed on the decrease (bottom) button
* @param increaseIcon A slot for an icon which is placed on the increase (top) button
* @param modifier Modifiers for the Stepper layout
* @param backgroundColor [Color] representing the background color for the stepper.
* @param contentColor [Color] representing the color for [content] in the middle.
- * @param iconColor Icon tint [Color] which used by [increaseIcon] and [decreaseIcon]
- * that defaults to [contentColor], unless specifically overridden.
- * @param enableRangeSemantics Boolean to decide if default stepper semantics should be enabled.
- * Set to false to disable default stepper range semantics. Alternatively to customize semantics
- * set this value as false and chain new semantics to the modifier.
+ * @param iconColor Icon tint [Color] which used by [increaseIcon] and [decreaseIcon] that defaults
+ * to [contentColor], unless specifically overridden.
+ * @param enableRangeSemantics Boolean to decide if default stepper semantics should be enabled. Set
+ * to false to disable default stepper range semantics. Alternatively to customize semantics set
+ * this value as false and chain new semantics to the modifier.
* @param content Content body for the Stepper.
*/
@Composable
@@ -183,11 +179,10 @@
}
/**
- * [Stepper] allows users to make a selection from a range of values.
- * It's a full-screen control with increase button on the top, decrease button on the bottom and
- * a slot (expected to have either [Text] or [Chip]) in the middle.
- * Value can be increased and decreased by clicking on the increase and decrease buttons.
- * Buttons can have custom icons - [decreaseIcon] and [increaseIcon].
+ * [Stepper] allows users to make a selection from a range of values. It's a full-screen control
+ * with increase button on the top, decrease button on the bottom and a slot (expected to have
+ * either [Text] or [Chip]) in the middle. Value can be increased and decreased by clicking on the
+ * increase and decrease buttons. Buttons can have custom icons - [decreaseIcon] and [increaseIcon].
* Step value is calculated as the difference between min and max values divided by [steps]+1.
* Stepper itself doesn't show the current value but can be displayed via the content slot or
* [PositionIndicator] if required.
@@ -195,20 +190,20 @@
* @sample androidx.wear.compose.material.samples.StepperSample
*
* @param value Current value of the Stepper. If outside of [valueRange] provided, value will be
- * coerced to this range.
+ * coerced to this range.
* @param onValueChange Lambda in which value should be updated
* @param steps Specifies the number of discrete values, excluding min and max values, evenly
- * distributed across the whole value range. Must not be negative. If 0, stepper will have only
- * min and max values and no steps in between
+ * distributed across the whole value range. Must not be negative. If 0, stepper will have only
+ * min and max values and no steps in between
* @param decreaseIcon A slot for an icon which is placed on the decrease (bottom) button
* @param increaseIcon A slot for an icon which is placed on the increase (top) button
* @param modifier Modifiers for the Stepper layout
* @param valueRange Range of values that Stepper value can take. Passed [value] will be coerced to
- * this range
+ * this range
* @param backgroundColor [Color] representing the background color for the stepper.
* @param contentColor [Color] representing the color for [content] in the middle.
- * @param iconColor Icon tint [Color] which used by [increaseIcon] and [decreaseIcon]
- * that defaults to [contentColor], unless specifically overridden.
+ * @param iconColor Icon tint [Color] which used by [increaseIcon] and [decreaseIcon] that defaults
+ * to [contentColor], unless specifically overridden.
*/
@Deprecated(
"This overload is provided for backwards compatibility with Compose for Wear OS 1.1. " +
@@ -228,53 +223,53 @@
contentColor: Color = contentColorFor(backgroundColor),
iconColor: Color = contentColor,
content: @Composable BoxScope.() -> Unit
-) = Stepper(
- value = value,
- onValueChange = onValueChange,
- steps = steps,
- decreaseIcon = decreaseIcon,
- increaseIcon = increaseIcon,
- modifier = modifier,
- valueRange = valueRange,
- backgroundColor = backgroundColor,
- contentColor = contentColor,
- iconColor = iconColor,
- enableRangeSemantics = true,
- content = content
-)
+) =
+ Stepper(
+ value = value,
+ onValueChange = onValueChange,
+ steps = steps,
+ decreaseIcon = decreaseIcon,
+ increaseIcon = increaseIcon,
+ modifier = modifier,
+ valueRange = valueRange,
+ backgroundColor = backgroundColor,
+ contentColor = contentColor,
+ iconColor = iconColor,
+ enableRangeSemantics = true,
+ content = content
+ )
/**
- * [Stepper] allows users to make a selection from a range of values.
- * It's a full-screen control with increase button on the top, decrease button on the bottom and
- * a slot (expected to have either [Text] or [Chip]) in the middle.
- * Value can be increased and decreased by clicking on the increase and decrease buttons.
- * Buttons can have custom icons - [decreaseIcon] and [increaseIcon].
+ * [Stepper] allows users to make a selection from a range of values. It's a full-screen control
+ * with increase button on the top, decrease button on the bottom and a slot (expected to have
+ * either [Text] or [Chip]) in the middle. Value can be increased and decreased by clicking on the
+ * increase and decrease buttons. Buttons can have custom icons - [decreaseIcon] and [increaseIcon].
* Stepper itself doesn't show the current value but can be displayed via the content slot or
* [PositionIndicator] if required.
*
* @sample androidx.wear.compose.material.samples.StepperWithIntegerSample
*
* A number of steps is calculated as the difference between max and min values of
- * [valueProgression] divided by [valueProgression].step - 1.
- * For example, with a range of 100..120 and a step 5,
- * number of steps will be (120-100)/ 5 - 1 = 3. Steps are 100(first), 105, 110, 115, 120(last)
+ * [valueProgression] divided by [valueProgression].step - 1. For example, with a range of 100..120
+ * and a step 5, number of steps will be (120-100)/ 5 - 1 = 3. Steps are 100(first), 105, 110, 115,
+ * 120(last)
*
- * If [valueProgression] range is not equally divisible by [valueProgression].step,
- * then [valueProgression].last will be adjusted to the closest divisible value in the range.
- * For example, 1..13 range and a step = 5, steps will be 1(first) , 6 , 11(last)
+ * If [valueProgression] range is not equally divisible by [valueProgression].step, then
+ * [valueProgression].last will be adjusted to the closest divisible value in the range. For
+ * example, 1..13 range and a step = 5, steps will be 1(first) , 6 , 11(last)
*
- * @param value Current value of the Stepper. If outside of [valueProgression] provided, value will be
- * coerced to this range.
+ * @param value Current value of the Stepper. If outside of [valueProgression] provided, value will
+ * be coerced to this range.
* @param onValueChange Lambda in which value should be updated
* @param valueProgression Progression of values that Stepper value can take. Consists of
- * rangeStart, rangeEnd and step. Range will be equally divided by step size
+ * rangeStart, rangeEnd and step. Range will be equally divided by step size
* @param decreaseIcon A slot for an icon which is placed on the decrease (bottom) button
* @param increaseIcon A slot for an icon which is placed on the increase (top) button
* @param modifier Modifiers for the Stepper layout
* @param backgroundColor [Color] representing the background color for the stepper.
* @param contentColor [Color] representing the color for [content] in the middle.
- * @param iconColor Icon tint [Color] which used by [increaseIcon] and [decreaseIcon]
- * that defaults to [contentColor], unless specifically overridden.
+ * @param iconColor Icon tint [Color] which used by [increaseIcon] and [decreaseIcon] that defaults
+ * to [contentColor], unless specifically overridden.
*/
@Deprecated(
"This overload is provided for backwards compatibility with Compose for Wear OS 1.1. " +
@@ -309,17 +304,11 @@
)
}
-/**
- * Defaults used by stepper
- */
+/** Defaults used by stepper */
public object StepperDefaults {
- /**
- * Decrease [ImageVector]
- */
+ /** Decrease [ImageVector] */
public val Decrease = androidx.wear.compose.materialcore.RangeIcons.Minus
- /**
- * Increase [ImageVector]
- */
+ /** Increase [ImageVector] */
public val Increase = Icons.Filled.Add
}
diff --git a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/SwipeToDismissBox.kt b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/SwipeToDismissBox.kt
index 84c8f65..d448f0f 100644
--- a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/SwipeToDismissBox.kt
+++ b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/SwipeToDismissBox.kt
@@ -35,13 +35,15 @@
import androidx.wear.compose.foundation.edgeSwipeToDismiss as foundationEdgeSwipeToDismiss
/**
- * Wear Material [SwipeToDismissBox] that handles the swipe-to-dismiss gesture. Takes a single
- * slot for the background (only displayed during the swipe gesture) and the foreground content.
+ * Wear Material [SwipeToDismissBox] that handles the swipe-to-dismiss gesture. Takes a single slot
+ * for the background (only displayed during the swipe gesture) and the foreground content.
*
* Example of a [SwipeToDismissBox] with stateful composables:
+ *
* @sample androidx.wear.compose.material.samples.StatefulSwipeToDismissBox
*
* Example of using [Modifier.edgeSwipeToDismiss] with [SwipeToDismissBox]
+ *
* @sample androidx.wear.compose.material.samples.EdgeSwipeForSwipeToDismiss
*
* For more information, see the
@@ -51,21 +53,21 @@
* @param state State containing information about ongoing swipe or animation.
* @param modifier Optional [Modifier] for this component.
* @param backgroundScrimColor Color for background scrim
- * @param contentScrimColor Optional [Color] used for the scrim over the
- * content composable during the swipe gesture.
- * @param backgroundKey Optional [key] which identifies the content currently composed in
- * the [content] block when isBackground == true. Provide the backgroundKey if your background
- * content will be displayed as a foreground after the swipe animation ends
- * (as is common when [SwipeToDismissBox] is used for the navigation). This allows
- * remembered state to be correctly moved between background and foreground.
- * @Param contentKey Optional [key] which identifies the content currently composed in the
- * [content] block when isBackground == false. See [backgroundKey].
- * @Param hasBackground Optional [Boolean] used to indicate if the content has no background,
- * in which case the swipe gesture is disabled (since there is no parent destination).
- * @param content Slot for content, with the isBackground parameter enabling content to be
- * displayed behind the foreground content - the background is normally hidden,
- * is shown behind a scrim during the swipe gesture,
- * and is shown without scrim once the finger passes the swipe-to-dismiss threshold.
+ * @param contentScrimColor Optional [Color] used for the scrim over the content composable during
+ * the swipe gesture.
+ * @param backgroundKey Optional [key] which identifies the content currently composed in the
+ * [content] block when isBackground == true. Provide the backgroundKey if your background content
+ * will be displayed as a foreground after the swipe animation ends (as is common when
+ * [SwipeToDismissBox] is used for the navigation). This allows remembered state to be correctly
+ * moved between background and foreground.
+ * @param content Slot for content, with the isBackground parameter enabling content to be displayed
+ * behind the foreground content - the background is normally hidden, is shown behind a scrim
+ * during the swipe gesture, and is shown without scrim once the finger passes the
+ * swipe-to-dismiss threshold.
+ * @Param contentKey Optional [key] which identifies the content currently composed in the [content]
+ * block when isBackground == false. See [backgroundKey].
+ * @Param hasBackground Optional [Boolean] used to indicate if the content has no background, in
+ * which case the swipe gesture is disabled (since there is no parent destination).
*/
@Composable
public fun SwipeToDismissBox(
@@ -94,13 +96,15 @@
}
/**
- * Wear Material [SwipeToDismissBox] that handles the swipe-to-dismiss gesture. Takes a single
- * slot for the background (only displayed during the swipe gesture) and the foreground content.
+ * Wear Material [SwipeToDismissBox] that handles the swipe-to-dismiss gesture. Takes a single slot
+ * for the background (only displayed during the swipe gesture) and the foreground content.
*
* Example of a [SwipeToDismissBox] with stateful composables:
+ *
* @sample androidx.wear.compose.material.samples.StatefulSwipeToDismissBox
*
* Example of using [Modifier.edgeSwipeToDismiss] with [SwipeToDismissBox]
+ *
* @sample androidx.wear.compose.material.samples.EdgeSwipeForSwipeToDismiss
*
* For more information, see the
@@ -110,31 +114,33 @@
* @param state State containing information about ongoing swipe or animation.
* @param modifier Optional [Modifier] for this component.
* @param backgroundScrimColor Color for background scrim
- * @param contentScrimColor Optional [Color] used for the scrim over the
- * content composable during the swipe gesture.
- * @param backgroundKey Optional [key] which identifies the content currently composed in
- * the [content] block when isBackground == true. Provide the backgroundKey if your background
- * content will be displayed as a foreground after the swipe animation ends
- * (as is common when [SwipeToDismissBox] is used for the navigation). This allows
- * remembered state to be correctly moved between background and foreground.
- * @Param contentKey Optional [key] which identifies the content currently composed in the
- * [content] block when isBackground == false. See [backgroundKey].
- * @Param hasBackground Optional [Boolean] used to indicate if the content has no background,
- * in which case the swipe gesture is disabled (since there is no parent destination).
- * @param content Slot for content, with the isBackground parameter enabling content to be
- * displayed behind the foreground content - the background is normally hidden,
- * is shown behind a scrim during the swipe gesture,
- * and is shown without scrim once the finger passes the swipe-to-dismiss threshold.
+ * @param contentScrimColor Optional [Color] used for the scrim over the content composable during
+ * the swipe gesture.
+ * @param backgroundKey Optional [key] which identifies the content currently composed in the
+ * [content] block when isBackground == true. Provide the backgroundKey if your background content
+ * will be displayed as a foreground after the swipe animation ends (as is common when
+ * [SwipeToDismissBox] is used for the navigation). This allows remembered state to be correctly
+ * moved between background and foreground.
+ * @param content Slot for content, with the isBackground parameter enabling content to be displayed
+ * behind the foreground content - the background is normally hidden, is shown behind a scrim
+ * during the swipe gesture, and is shown without scrim once the finger passes the
+ * swipe-to-dismiss threshold.
+ * @Param contentKey Optional [key] which identifies the content currently composed in the [content]
+ * block when isBackground == false. See [backgroundKey].
+ * @Param hasBackground Optional [Boolean] used to indicate if the content has no background, in
+ * which case the swipe gesture is disabled (since there is no parent destination).
*/
@Suppress("DEPRECATION")
@Deprecated(
"This overload is provided for backwards compatibility. " +
"A newer overload is available that uses " +
"androidx.wear.compose.foundation.SwipeToDismissBoxState.",
- replaceWith = ReplaceWith("SwipeToDismissBox(" +
- "state, modifier, backgroundScrimColor, contentScrimColor, backgroundKey, contentKey," +
- "hasBackground, content)"
- )
+ replaceWith =
+ ReplaceWith(
+ "SwipeToDismissBox(" +
+ "state, modifier, backgroundScrimColor, contentScrimColor, backgroundKey, contentKey," +
+ "hasBackground, content)"
+ )
)
@Composable
public fun SwipeToDismissBox(
@@ -163,14 +169,16 @@
}
/**
- * Wear Material [SwipeToDismissBox] that handles the swipe-to-dismiss gesture.
- * This overload takes an [onDismissed] parameter which is used to execute a command when the
- * swipe to dismiss has completed, such as navigating to another screen.
+ * Wear Material [SwipeToDismissBox] that handles the swipe-to-dismiss gesture. This overload takes
+ * an [onDismissed] parameter which is used to execute a command when the swipe to dismiss has
+ * completed, such as navigating to another screen.
*
* Example of a simple SwipeToDismissBox:
+ *
* @sample androidx.wear.compose.material.samples.SimpleSwipeToDismissBox
*
* Example of using [Modifier.edgeSwipeToDismiss] with [SwipeToDismissBox]
+ *
* @sample androidx.wear.compose.material.samples.EdgeSwipeForSwipeToDismiss
*
* For more information, see the
@@ -181,21 +189,21 @@
* @param modifier Optional [Modifier] for this component.
* @param state State containing information about ongoing swipe or animation.
* @param backgroundScrimColor Color for background scrim
- * @param contentScrimColor Optional [Color] used for the scrim over the
- * content composable during the swipe gesture.
- * @param backgroundKey Optional [key] which identifies the content currently composed in
- * the [content] block when isBackground == true. Provide the backgroundKey if your background
- * content will be displayed as a foreground after the swipe animation ends
- * (as is common when [SwipeToDismissBox] is used for the navigation). This allows
- * remembered state to be correctly moved between background and foreground.
- * @Param contentKey Optional [key] which identifies the content currently composed in the
- * [content] block when isBackground == false. See [backgroundKey].
- * @Param hasBackground Optional [Boolean] used to indicate if the content has no background,
- * in which case the swipe gesture is disabled (since there is no parent destination).
- * @param content Slot for content, with the isBackground parameter enabling content to be
- * displayed behind the foreground content - the background is normally hidden,
- * is shown behind a scrim during the swipe gesture,
- * and is shown without scrim once the finger passes the swipe-to-dismiss threshold.
+ * @param contentScrimColor Optional [Color] used for the scrim over the content composable during
+ * the swipe gesture.
+ * @param backgroundKey Optional [key] which identifies the content currently composed in the
+ * [content] block when isBackground == true. Provide the backgroundKey if your background content
+ * will be displayed as a foreground after the swipe animation ends (as is common when
+ * [SwipeToDismissBox] is used for the navigation). This allows remembered state to be correctly
+ * moved between background and foreground.
+ * @param content Slot for content, with the isBackground parameter enabling content to be displayed
+ * behind the foreground content - the background is normally hidden, is shown behind a scrim
+ * during the swipe gesture, and is shown without scrim once the finger passes the
+ * swipe-to-dismiss threshold.
+ * @Param contentKey Optional [key] which identifies the content currently composed in the [content]
+ * block when isBackground == false. See [backgroundKey].
+ * @Param hasBackground Optional [Boolean] used to indicate if the content has no background, in
+ * which case the swipe gesture is disabled (since there is no parent destination).
*/
@Composable
public fun SwipeToDismissBox(
@@ -227,14 +235,16 @@
}
/**
- * Wear Material [SwipeToDismissBox] that handles the swipe-to-dismiss gesture.
- * This overload takes an [onDismissed] parameter which is used to execute a command when the
- * swipe to dismiss has completed, such as navigating to another screen.
+ * Wear Material [SwipeToDismissBox] that handles the swipe-to-dismiss gesture. This overload takes
+ * an [onDismissed] parameter which is used to execute a command when the swipe to dismiss has
+ * completed, such as navigating to another screen.
*
* Example of a simple SwipeToDismissBox:
+ *
* @sample androidx.wear.compose.material.samples.SimpleSwipeToDismissBox
*
* Example of using [Modifier.edgeSwipeToDismiss] with [SwipeToDismissBox]
+ *
* @sample androidx.wear.compose.material.samples.EdgeSwipeForSwipeToDismiss
*
* For more information, see the
@@ -245,31 +255,33 @@
* @param modifier Optional [Modifier] for this component.
* @param state State containing information about ongoing swipe or animation.
* @param backgroundScrimColor Color for background scrim
- * @param contentScrimColor Optional [Color] used for the scrim over the
- * content composable during the swipe gesture.
- * @param backgroundKey Optional [key] which identifies the content currently composed in
- * the [content] block when isBackground == true. Provide the backgroundKey if your background
- * content will be displayed as a foreground after the swipe animation ends
- * (as is common when [SwipeToDismissBox] is used for the navigation). This allows
- * remembered state to be correctly moved between background and foreground.
- * @Param contentKey Optional [key] which identifies the content currently composed in the
- * [content] block when isBackground == false. See [backgroundKey].
- * @Param hasBackground Optional [Boolean] used to indicate if the content has no background,
- * in which case the swipe gesture is disabled (since there is no parent destination).
- * @param content Slot for content, with the isBackground parameter enabling content to be
- * displayed behind the foreground content - the background is normally hidden,
- * is shown behind a scrim during the swipe gesture,
- * and is shown without scrim once the finger passes the swipe-to-dismiss threshold.
+ * @param contentScrimColor Optional [Color] used for the scrim over the content composable during
+ * the swipe gesture.
+ * @param backgroundKey Optional [key] which identifies the content currently composed in the
+ * [content] block when isBackground == true. Provide the backgroundKey if your background content
+ * will be displayed as a foreground after the swipe animation ends (as is common when
+ * [SwipeToDismissBox] is used for the navigation). This allows remembered state to be correctly
+ * moved between background and foreground.
+ * @param content Slot for content, with the isBackground parameter enabling content to be displayed
+ * behind the foreground content - the background is normally hidden, is shown behind a scrim
+ * during the swipe gesture, and is shown without scrim once the finger passes the
+ * swipe-to-dismiss threshold.
+ * @Param contentKey Optional [key] which identifies the content currently composed in the [content]
+ * block when isBackground == false. See [backgroundKey].
+ * @Param hasBackground Optional [Boolean] used to indicate if the content has no background, in
+ * which case the swipe gesture is disabled (since there is no parent destination).
*/
@Suppress("DEPRECATION")
@Deprecated(
"This overload is provided for backwards compatibility. " +
"A newer overload is available that uses " +
"androidx.wear.compose.foundation.SwipeToDismissBoxState.",
- replaceWith = ReplaceWith("SwipeToDismissBox(" +
- "onDismiss, modifier, state, backgroundScrimColor, contentScrimColor, backgroundKey," +
- "contentKey, hasBackground, content)"
- ),
+ replaceWith =
+ ReplaceWith(
+ "SwipeToDismissBox(" +
+ "onDismiss, modifier, state, backgroundScrimColor, contentScrimColor, backgroundKey," +
+ "contentKey, hasBackground, content)"
+ ),
level = DeprecationLevel.HIDDEN
)
@Composable
@@ -328,16 +340,14 @@
/**
* The target value of the state.
*
- * If a swipe is in progress, this is the value that the state would animate to if the
- * swipe finished. If an animation is running, this is the target value of that animation.
- * Finally, if no swipe or animation is in progress, this is the same as the [currentValue].
+ * If a swipe is in progress, this is the value that the state would animate to if the swipe
+ * finished. If an animation is running, this is the target value of that animation. Finally, if
+ * no swipe or animation is in progress, this is the same as the [currentValue].
*/
public val targetValue: SwipeToDismissValue
get() = convertFromFoundationSwipeToDismissValue(foundationState.targetValue)
- /**
- * Whether the state is currently animating.
- */
+ /** Whether the state is currently animating. */
public val isAnimationRunning: Boolean
get() = foundationState.isAnimationRunning
@@ -349,18 +359,16 @@
public suspend fun snapTo(targetValue: SwipeToDismissValue) =
foundationState.snapTo(convertToFoundationSwipeToDismissValue(targetValue))
- /**
- * Foundation version of the [SwipeToDismissBoxState].
- */
+ /** Foundation version of the [SwipeToDismissBoxState]. */
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
- val foundationState = androidx.wear.compose.foundation.SwipeToDismissBoxState(
- animationSpec = animationSpec,
- confirmStateChange = { value: androidx.wear.compose.foundation.SwipeToDismissValue ->
- confirmStateChange(convertFromFoundationSwipeToDismissValue(value))
- }
- )
- @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
- get() = field
+ val foundationState =
+ androidx.wear.compose.foundation.SwipeToDismissBoxState(
+ animationSpec = animationSpec,
+ confirmStateChange = { value: androidx.wear.compose.foundation.SwipeToDismissValue ->
+ confirmStateChange(convertFromFoundationSwipeToDismissValue(value))
+ }
+ )
+ @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) get() = field
}
/**
@@ -387,9 +395,7 @@
}
}
-/**
- * Contains defaults for [SwipeToDismissBox].
- */
+/** Contains defaults for [SwipeToDismissBox]. */
@Deprecated(
"Please import SwipeToDismissBoxDefaults from androidx.wear.compose.foundation.",
)
@@ -402,78 +408,71 @@
public val AnimationSpec = SwipeableDefaults.AnimationSpec
/**
- * The default width of the area which might trigger a swipe
- * with [edgeSwipeToDismiss] modifier
+ * The default width of the area which might trigger a swipe with [edgeSwipeToDismiss] modifier
*/
public val EdgeWidth = 30.dp
}
-/**
- * Keys used to persistent state in [SwipeToDismissBox].
- */
+/** Keys used to persistent state in [SwipeToDismissBox]. */
public enum class SwipeToDismissKeys {
/**
- * The default background key to identify the content displayed by the content block
- * when isBackground == true. Specifying a background key instead of using the default
- * allows remembered state to be correctly moved between background and foreground.
+ * The default background key to identify the content displayed by the content block when
+ * isBackground == true. Specifying a background key instead of using the default allows
+ * remembered state to be correctly moved between background and foreground.
*/
Background,
/**
- * The default content key to identify the content displayed by the content block
- * when isBackground == false. Specifying a background key instead of using the default
- * allows remembered state to be correctly moved between background and foreground.
+ * The default content key to identify the content displayed by the content block when
+ * isBackground == false. Specifying a background key instead of using the default allows
+ * remembered state to be correctly moved between background and foreground.
*/
Content
}
-/**
- * States used as targets for the anchor points for swipe-to-dismiss.
- */
+/** States used as targets for the anchor points for swipe-to-dismiss. */
@Deprecated(
"SwipeToDismiss has been migrated to androidx.wear.compose.foundation. " +
"Please import SwipeToDismissValue from androidx.wear.compose.foundation instead.",
)
public enum class SwipeToDismissValue {
- /**
- * The state of the SwipeToDismissBox before the swipe started.
- */
+ /** The state of the SwipeToDismissBox before the swipe started. */
Default,
- /**
- * The state of the SwipeToDismissBox after the swipe passes the swipe-to-dismiss threshold.
- */
+ /** The state of the SwipeToDismissBox after the swipe passes the swipe-to-dismiss threshold. */
Dismissed
}
/**
- * Limits swipe to dismiss to be active from the edge of the viewport only. Used when the center
- * of the screen needs to be able to handle horizontal paging, such as 2-d scrolling a Map
- * or swiping horizontally between pages. Swipe to the right is intercepted on the left
- * part of the viewport with width specified by [edgeWidth], with other touch events
- * ignored - vertical scroll, click, long click, etc.
+ * Limits swipe to dismiss to be active from the edge of the viewport only. Used when the center of
+ * the screen needs to be able to handle horizontal paging, such as 2-d scrolling a Map or swiping
+ * horizontally between pages. Swipe to the right is intercepted on the left part of the viewport
+ * with width specified by [edgeWidth], with other touch events ignored - vertical scroll, click,
+ * long click, etc.
*
* Currently Edge swipe, like swipe to dismiss, is only supported on the left part of the viewport
* regardless of layout direction as content is swiped away from left to right.
*
- * Requires that the element to which this modifier is applied exists within a
- * SwipeToDismissBox which is using the same [SwipeToDismissBoxState] instance.
+ * Requires that the element to which this modifier is applied exists within a SwipeToDismissBox
+ * which is using the same [SwipeToDismissBoxState] instance.
*
* Example of a modifier usage with SwipeToDismiss
+ *
* @sample androidx.wear.compose.material.samples.EdgeSwipeForSwipeToDismiss
*
- * @param swipeToDismissBoxState A state of SwipeToDismissBox. Used to trigger swipe gestures
- * on SwipeToDismissBox
+ * @param swipeToDismissBoxState A state of SwipeToDismissBox. Used to trigger swipe gestures on
+ * SwipeToDismissBox
* @param edgeWidth A width of edge, where swipe should be recognised
*/
@Suppress("DEPRECATION")
@Deprecated(
"SwipeToDismiss has been migrated to androidx.wear.compose.foundation. " +
"Please import Modifier.edgeSwipeToDismiss from androidx.wear.compose.foundation instead.",
- replaceWith = ReplaceWith(
- "androidx.wear.compose.foundation.edgeSwipeToDismiss(",
- "swipeToDismissBoxState, edgeWidth)"
- )
+ replaceWith =
+ ReplaceWith(
+ "androidx.wear.compose.foundation.edgeSwipeToDismiss(",
+ "swipeToDismissBoxState, edgeWidth)"
+ )
)
public fun Modifier.edgeSwipeToDismiss(
swipeToDismissBoxState: SwipeToDismissBoxState,
@@ -485,26 +484,21 @@
)
@Suppress("DEPRECATION")
-private fun convertToFoundationSwipeToDismissValue(
- value: SwipeToDismissValue
-) = when (value) {
- SwipeToDismissValue.Default ->
- androidx.wear.compose.foundation.SwipeToDismissValue.Default
-
- SwipeToDismissValue.Dismissed ->
- androidx.wear.compose.foundation.SwipeToDismissValue.Dismissed
-}
+private fun convertToFoundationSwipeToDismissValue(value: SwipeToDismissValue) =
+ when (value) {
+ SwipeToDismissValue.Default -> androidx.wear.compose.foundation.SwipeToDismissValue.Default
+ SwipeToDismissValue.Dismissed ->
+ androidx.wear.compose.foundation.SwipeToDismissValue.Dismissed
+ }
@Suppress("DEPRECATION")
private fun convertFromFoundationSwipeToDismissValue(
value: androidx.wear.compose.foundation.SwipeToDismissValue
-) = when (value) {
- androidx.wear.compose.foundation.SwipeToDismissValue.Default ->
- SwipeToDismissValue.Default
+) =
+ when (value) {
+ androidx.wear.compose.foundation.SwipeToDismissValue.Default -> SwipeToDismissValue.Default
+ androidx.wear.compose.foundation.SwipeToDismissValue.Dismissed ->
+ SwipeToDismissValue.Dismissed
+ }
- androidx.wear.compose.foundation.SwipeToDismissValue.Dismissed ->
- SwipeToDismissValue.Dismissed
-}
-
-private val SWIPE_TO_DISMISS_BOX_ANIMATION_SPEC =
- TweenSpec<Float>(200, 0, LinearOutSlowInEasing)
+private val SWIPE_TO_DISMISS_BOX_ANIMATION_SPEC = TweenSpec<Float>(200, 0, LinearOutSlowInEasing)
diff --git a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/SwipeToReveal.kt b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/SwipeToReveal.kt
index d1fc9b3..dbc65a9 100644
--- a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/SwipeToReveal.kt
+++ b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/SwipeToReveal.kt
@@ -58,37 +58,37 @@
/**
* [SwipeToReveal] Material composable for [Chip]s. This adds the option to configure up to two
- * additional actions on the [Chip]: a mandatory [primaryAction] and an optional
- * [secondaryAction]. These actions are initially hidden and revealed only when the [content] is
- * swiped. These additional actions can be triggered by clicking on them after they are revealed.
- * It is recommended to trigger [primaryAction] on full swipe of the [content].
+ * additional actions on the [Chip]: a mandatory [primaryAction] and an optional [secondaryAction].
+ * These actions are initially hidden and revealed only when the [content] is swiped. These
+ * additional actions can be triggered by clicking on them after they are revealed. It is
+ * recommended to trigger [primaryAction] on full swipe of the [content].
*
* For actions like "Delete", consider adding [undoPrimaryAction] (displayed when the
* [primaryAction] is activated) and/or [undoSecondaryAction] (displayed when the [secondaryAction]
* is activated). Adding undo composables allow users to undo the action that they just performed.
*
* Example of [SwipeToRevealChip] with primary and secondary actions
+ *
* @sample androidx.wear.compose.material.samples.SwipeToRevealChipSample
*
- * @param primaryAction A composable to describe the primary action when swiping. The action will
- * be triggered on clicking the action. See [SwipeToRevealPrimaryAction].
+ * @param primaryAction A composable to describe the primary action when swiping. The action will be
+ * triggered on clicking the action. See [SwipeToRevealPrimaryAction].
* @param revealState [RevealState] of the [SwipeToReveal]
* @param onFullSwipe A lambda which will be triggered on full swipe from either of the anchors. We
- * recommend to keep this similar to primary action click action. This sets the
- * [RevealState.lastActionType] to [RevealActionType.PrimaryAction].
+ * recommend to keep this similar to primary action click action. This sets the
+ * [RevealState.lastActionType] to [RevealActionType.PrimaryAction].
* @param modifier [Modifier] to be applied on the composable
- * @param secondaryAction A composable to describe the contents of secondary action. The action
- * will be triggered on clicking the action. See [SwipeToRevealSecondaryAction]
+ * @param secondaryAction A composable to describe the contents of secondary action. The action will
+ * be triggered on clicking the action. See [SwipeToRevealSecondaryAction]
* @param undoPrimaryAction A composable to describe the contents of undo action when the primary
- * action was triggered. See [SwipeToRevealUndoAction]
+ * action was triggered. See [SwipeToRevealUndoAction]
* @param undoSecondaryAction composable to describe the contents of undo action when secondary
- * action was triggered. See [SwipeToRevealUndoAction]
+ * action was triggered. See [SwipeToRevealUndoAction]
* @param colors An instance of [SwipeToRevealActionColors] to describe the colors of actions. See
- * [SwipeToRevealDefaults.actionColors].
+ * [SwipeToRevealDefaults.actionColors].
* @param shape The shape of primary and secondary action composables. Recommended shape for chips
- * is [Shapes.small].
+ * is [Shapes.small].
* @param content The initial content shown prior to the swipe-to-reveal gesture.
- *
* @see [SwipeToReveal]
*/
@ExperimentalWearMaterialApi
@@ -122,37 +122,37 @@
/**
* [SwipeToReveal] Material composable for [Card]s. This adds the option to configure up to two
- * additional actions on the [Card]: a mandatory [primaryAction] and an optional
- * [secondaryAction]. These actions are initially hidden and revealed only when the [content] is
- * swiped. These additional actions can be triggered by clicking on them after they are revealed.
- * It is recommended to trigger [primaryAction] on full swipe of the [content].
+ * additional actions on the [Card]: a mandatory [primaryAction] and an optional [secondaryAction].
+ * These actions are initially hidden and revealed only when the [content] is swiped. These
+ * additional actions can be triggered by clicking on them after they are revealed. It is
+ * recommended to trigger [primaryAction] on full swipe of the [content].
*
* For actions like "Delete", consider adding [undoPrimaryAction] (displayed when the
* [primaryAction] is activated) and/or [undoSecondaryAction] (displayed when the [secondaryAction]
* is activated). Adding undo composables allow users to undo the action that they just performed.
*
* Example of [SwipeToRevealCard] with primary and secondary actions
+ *
* @sample androidx.wear.compose.material.samples.SwipeToRevealCardSample
*
- * @param primaryAction A composable to describe the primary action when swiping. The action will
- * be triggered on clicking the action. See [SwipeToRevealPrimaryAction].
+ * @param primaryAction A composable to describe the primary action when swiping. The action will be
+ * triggered on clicking the action. See [SwipeToRevealPrimaryAction].
* @param revealState [RevealState] of the [SwipeToReveal]
* @param onFullSwipe A lambda which will be triggered on full swipe from either of the anchors. We
- * recommend to keep this similar to primary action click action. This sets the
- * [RevealState.lastActionType] to [RevealActionType.PrimaryAction].
+ * recommend to keep this similar to primary action click action. This sets the
+ * [RevealState.lastActionType] to [RevealActionType.PrimaryAction].
* @param modifier [Modifier] to be applied on the composable
* @param secondaryAction A composable to describe the contents of secondary action.The action will
- * be triggered on clicking the action. See [SwipeToRevealSecondaryAction]
+ * be triggered on clicking the action. See [SwipeToRevealSecondaryAction]
* @param undoPrimaryAction A composable to describe the contents of undo action when the primary
- * action was triggered. See [SwipeToRevealUndoAction]
+ * action was triggered. See [SwipeToRevealUndoAction]
* @param undoSecondaryAction A composable to describe the contents of undo action when secondary
- * action was triggered. See [SwipeToRevealUndoAction]
+ * action was triggered. See [SwipeToRevealUndoAction]
* @param colors An instance of [SwipeToRevealActionColors] to describe the colors of actions. See
- * [SwipeToRevealDefaults.actionColors].
+ * [SwipeToRevealDefaults.actionColors].
* @param shape The shape of primary and secondary action composables. Recommended shape for cards
- * is [SwipeToRevealDefaults.CardActionShape].
+ * is [SwipeToRevealDefaults.CardActionShape].
* @param content The initial content shown prior to the swipe-to-reveal gesture.
- *
* @see [SwipeToReveal]
*/
@ExperimentalWearMaterialApi
@@ -185,16 +185,16 @@
}
/**
- * A composable which can be used for setting the primary action of material [SwipeToRevealCard]
- * and [SwipeToRevealChip].
+ * A composable which can be used for setting the primary action of material [SwipeToRevealCard] and
+ * [SwipeToRevealChip].
*
* @param revealState The [RevealState] of the [SwipeToReveal] where this action is used.
* @param onClick A lambda which gets triggered when the action is clicked.
* @param icon The icon which will be displayed initially on the action
* @param label The label which will be displayed on the expanded action
* @param modifier [Modifier] to be applied on the action
- * @param interactionSource The [MutableInteractionSource] representing the stream of
- * interactions with this action.
+ * @param interactionSource The [MutableInteractionSource] representing the stream of interactions
+ * with this action.
*/
@OptIn(ExperimentalWearFoundationApi::class)
@ExperimentalWearMaterialApi
@@ -206,15 +206,16 @@
label: @Composable () -> Unit,
modifier: Modifier = Modifier,
interactionSource: MutableInteractionSource? = null,
-) = ActionCommon(
- revealState = revealState,
- actionType = RevealActionType.PrimaryAction,
- onClick = onClick,
- modifier = modifier,
- interactionSource = interactionSource,
- icon = icon,
- label = label
-)
+) =
+ ActionCommon(
+ revealState = revealState,
+ actionType = RevealActionType.PrimaryAction,
+ onClick = onClick,
+ modifier = modifier,
+ interactionSource = interactionSource,
+ icon = icon,
+ label = label
+ )
/**
* A composable which can be used for setting the secondary action of material [SwipeToRevealCard]
@@ -223,10 +224,10 @@
* @param revealState The [RevealState] of the [SwipeToReveal] where this action is used.
* @param onClick A lambda which gets triggered when the action is clicked.
* @param modifier [Modifier] to be applied on the action
- * @param interactionSource The [MutableInteractionSource] representing the stream of
- * interactions with this action.
+ * @param interactionSource The [MutableInteractionSource] representing the stream of interactions
+ * with this action.
* @param content The composable which will be displayed on the action. It is recommended to keep
- * this content as an [Icon] composable.
+ * this content as an [Icon] composable.
*/
@OptIn(ExperimentalWearFoundationApi::class)
@ExperimentalWearMaterialApi
@@ -237,28 +238,29 @@
modifier: Modifier = Modifier,
interactionSource: MutableInteractionSource? = null,
content: @Composable () -> Unit,
-) = ActionCommon(
- revealState = revealState,
- actionType = RevealActionType.SecondaryAction,
- onClick = onClick,
- modifier = modifier,
- interactionSource = interactionSource,
- icon = content,
- label = null
-)
+) =
+ ActionCommon(
+ revealState = revealState,
+ actionType = RevealActionType.SecondaryAction,
+ onClick = onClick,
+ modifier = modifier,
+ interactionSource = interactionSource,
+ icon = content,
+ label = null
+ )
/**
- * A composable which can be used for setting the undo action of material [SwipeToRevealCard]
- * and [SwipeToRevealChip].
+ * A composable which can be used for setting the undo action of material [SwipeToRevealCard] and
+ * [SwipeToRevealChip].
*
* @param revealState The [RevealState] of the [SwipeToReveal] where this action is used.
* @param onClick A lambda which gets triggered when the action is clicked.
* @param modifier [Modifier] to be applied on the action
- * @param interactionSource The [MutableInteractionSource] representing the stream of
- * interactions with this action.
+ * @param interactionSource The [MutableInteractionSource] representing the stream of interactions
+ * with this action.
* @param icon An optional icon which will be displayed on the action
* @param label An optional label which will be displayed on the action. We strongly recommend to
- * set [icon] and/or [label] for the action.
+ * set [icon] and/or [label] for the action.
*/
@OptIn(ExperimentalWearFoundationApi::class)
@ExperimentalWearMaterialApi
@@ -272,8 +274,8 @@
label: (@Composable () -> Unit)? = null,
) {
Row(
- modifier = modifier
- .clickable(
+ modifier =
+ modifier.clickable(
interactionSource = interactionSource,
indication = rippleOrFallbackImplementation(),
role = Role.Button,
@@ -290,30 +292,24 @@
}
}
-/**
- * Defaults for Material [SwipeToReveal].
- */
+/** Defaults for Material [SwipeToReveal]. */
@ExperimentalWearMaterialApi
@OptIn(ExperimentalWearFoundationApi::class)
public object SwipeToRevealDefaults {
- /**
- * Recommended shape for [SwipeToReveal] actions when used with [Card].
- */
+ /** Recommended shape for [SwipeToReveal] actions when used with [Card]. */
public val CardActionShape = RoundedCornerShape(40.dp)
/**
- * The recommended colors used to display the contents of the
- * primary, secondary and undo actions in [SwipeToReveal].
+ * The recommended colors used to display the contents of the primary, secondary and undo
+ * actions in [SwipeToReveal].
*
- * @param primaryActionBackgroundColor The background color (color of the shape) of the
- * primary action
+ * @param primaryActionBackgroundColor The background color (color of the shape) of the primary
+ * action
* @param primaryActionContentColor The content color (text and icon) of the primary action
* @param secondaryActionBackgroundColor The background color (color of the shape) of the
- * secondary action
- * @param secondaryActionContentColor The content color (text and icon) of the
- * secondary action
- * @param undoActionBackgroundColor The background color (color of the shape) of the
- * undo action
+ * secondary action
+ * @param secondaryActionContentColor The content color (text and icon) of the secondary action
+ * @param undoActionBackgroundColor The background color (color of the shape) of the undo action
* @param undoActionContentColor The content color (text) of the undo action
*/
@Composable
@@ -335,14 +331,10 @@
)
}
- /**
- * [ImageVector] for delete icon, often used for the primary action.
- */
+ /** [ImageVector] for delete icon, often used for the primary action. */
public val Delete = Icons.Outlined.Delete
- /**
- * [ImageVector] for more options icon, often used for the secondary action.
- */
+ /** [ImageVector] for more options icon, often used for the secondary action. */
public val MoreOptions = Icons.Outlined.MoreVert
internal val UndoButtonHorizontalPadding = 14.dp
@@ -351,8 +343,8 @@
}
/**
- * A class representing the colors applied in [SwipeToReveal] actions.
- * See [SwipeToRevealDefaults.actionColors].
+ * A class representing the colors applied in [SwipeToReveal] actions. See
+ * [SwipeToRevealDefaults.actionColors].
*
* @param primaryActionBackgroundColor Color of the shape (background) of primary action
* @param primaryActionContentColor Color of icon or text used in the primary action
@@ -362,7 +354,8 @@
* @param undoActionContentColor Color of the icon or text used in the undo action
*/
@ExperimentalWearMaterialApi
-public class SwipeToRevealActionColors constructor(
+public class SwipeToRevealActionColors
+constructor(
val primaryActionBackgroundColor: Color,
val primaryActionContentColor: Color,
val secondaryActionBackgroundColor: Color,
@@ -430,45 +423,37 @@
content = primaryAction
)
},
- secondaryAction = secondaryAction?.let {
- {
- ActionWrapper(
- revealState = revealState,
- backgroundColor = colors.secondaryActionBackgroundColor,
- contentColor = colors.secondaryActionContentColor,
- shape = shape,
- content = secondaryAction
- )
- }
- },
+ secondaryAction =
+ secondaryAction?.let {
+ {
+ ActionWrapper(
+ revealState = revealState,
+ backgroundColor = colors.secondaryActionBackgroundColor,
+ contentColor = colors.secondaryActionContentColor,
+ shape = shape,
+ content = secondaryAction
+ )
+ }
+ },
undoAction =
- when (revealState.lastActionType) {
- RevealActionType.SecondaryAction -> undoSecondaryAction?.let {
- {
- UndoActionWrapper(
- colors = colors,
- content = undoSecondaryAction
- )
- }
- }
- // With manual swiping the last click action type will be none, show undo action
- RevealActionType.PrimaryAction, RevealActionType.None -> undoPrimaryAction?.let {
- {
- UndoActionWrapper(
- colors = colors,
- content = undoPrimaryAction
- )
- }
- }
- else -> null
- },
+ when (revealState.lastActionType) {
+ RevealActionType.SecondaryAction ->
+ undoSecondaryAction?.let {
+ { UndoActionWrapper(colors = colors, content = undoSecondaryAction) }
+ }
+ // With manual swiping the last click action type will be none, show undo action
+ RevealActionType.PrimaryAction,
+ RevealActionType.None ->
+ undoPrimaryAction?.let {
+ { UndoActionWrapper(colors = colors, content = undoPrimaryAction) }
+ }
+ else -> null
+ },
content = content
)
}
-/**
- * Action composables for [SwipeToReveal].
- */
+/** Action composables for [SwipeToReveal]. */
@OptIn(ExperimentalWearFoundationApi::class, ExperimentalWearMaterialApi::class)
@Composable
private fun RevealScope.ActionWrapper(
@@ -481,25 +466,23 @@
// Change opacity of shape from 0% to 100% between 10% and 20% of the progress
val shapeAlpha =
if (revealOffset > 0)
- ((-revealState.offset - revealOffset * 0.1f) / (0.1f * revealOffset))
- .coerceIn(0.0f, 1.0f)
+ ((-revealState.offset - revealOffset * 0.1f) / (0.1f * revealOffset)).coerceIn(
+ 0.0f,
+ 1.0f
+ )
else 1f
Box(
- modifier = Modifier
- .graphicsLayer { alpha = shapeAlpha }
- .background(backgroundColor, shape)
- // Limit the incoming constraints to max height
- .heightIn(min = 0.dp, max = SwipeToRevealDefaults.ActionMaxHeight)
- // Then, fill the max height based on incoming constraints
- .fillMaxSize()
- .clip(shape),
+ modifier =
+ Modifier.graphicsLayer { alpha = shapeAlpha }
+ .background(backgroundColor, shape)
+ // Limit the incoming constraints to max height
+ .heightIn(min = 0.dp, max = SwipeToRevealDefaults.ActionMaxHeight)
+ // Then, fill the max height based on incoming constraints
+ .fillMaxSize()
+ .clip(shape),
contentAlignment = Alignment.Center
) {
- CompositionLocalProvider(
- LocalContentColor provides contentColor
- ) {
- content()
- }
+ CompositionLocalProvider(LocalContentColor provides contentColor) { content() }
}
}
@@ -510,19 +493,17 @@
content: @Composable RevealScope.() -> Unit
) {
Box(
- modifier = Modifier
- .clip(MaterialTheme.shapes.small)
- .defaultMinSize(minHeight = 52.dp)
- .background(color = colors.undoActionBackgroundColor)
- .padding(
- horizontal = SwipeToRevealDefaults.UndoButtonHorizontalPadding,
- vertical = SwipeToRevealDefaults.UndoButtonVerticalPadding
- ),
+ modifier =
+ Modifier.clip(MaterialTheme.shapes.small)
+ .defaultMinSize(minHeight = 52.dp)
+ .background(color = colors.undoActionBackgroundColor)
+ .padding(
+ horizontal = SwipeToRevealDefaults.UndoButtonHorizontalPadding,
+ vertical = SwipeToRevealDefaults.UndoButtonVerticalPadding
+ ),
contentAlignment = Alignment.Center
) {
- CompositionLocalProvider(
- LocalContentColor provides colors.undoActionContentColor
- ) {
+ CompositionLocalProvider(LocalContentColor provides colors.undoActionContentColor) {
content()
}
}
@@ -540,46 +521,40 @@
label: (@Composable () -> Unit)? = null,
) {
Row(
- modifier = modifier
- .fillMaxSize()
- .clickable(
- interactionSource = interactionSource,
- indication = rippleOrFallbackImplementation(),
- role = Role.Button,
- onClick = {
- revealState.lastActionType = actionType
- onClick()
- }
- ),
+ modifier =
+ modifier
+ .fillMaxSize()
+ .clickable(
+ interactionSource = interactionSource,
+ indication = rippleOrFallbackImplementation(),
+ role = Role.Button,
+ onClick = {
+ revealState.lastActionType = actionType
+ onClick()
+ }
+ ),
horizontalArrangement = Arrangement.Center,
verticalAlignment = Alignment.CenterVertically
) {
if (icon != null) {
- ActionIcon(
- revealState = revealState,
- content = icon
- )
+ ActionIcon(revealState = revealState, content = icon)
}
if (label != null) {
- ActionLabel(
- revealState = revealState,
- content = label
- )
+ ActionLabel(revealState = revealState, content = label)
}
}
}
@OptIn(ExperimentalWearFoundationApi::class)
@Composable
-private fun RevealScope.ActionIcon(
- revealState: RevealState,
- content: @Composable () -> Unit
-) {
+private fun RevealScope.ActionIcon(revealState: RevealState, content: @Composable () -> Unit) {
// Change opacity of icons from 0% to 100% between 50% to 75% of the progress
val iconAlpha =
if (revealOffset > 0)
- ((-revealState.offset - revealOffset * 0.5f) / (revealOffset * 0.25f))
- .coerceIn(0.0f, 1.0f)
+ ((-revealState.offset - revealOffset * 0.5f) / (revealOffset * 0.25f)).coerceIn(
+ 0.0f,
+ 1.0f
+ )
else 1f
// Scale icons from 70% to 100% between 50% and 100% of the progress
val iconScale =
@@ -591,11 +566,12 @@
)
else 1f
Box(
- modifier = Modifier.graphicsLayer {
- alpha = iconAlpha
- scaleX = iconScale
- scaleY = iconScale
- }
+ modifier =
+ Modifier.graphicsLayer {
+ alpha = iconAlpha
+ scaleX = iconScale
+ scaleY = iconScale
+ }
) {
content()
}
@@ -603,18 +579,13 @@
@OptIn(ExperimentalWearFoundationApi::class)
@Composable
-private fun RevealScope.ActionLabel(
- revealState: RevealState,
- content: @Composable () -> Unit
-) {
- val labelAlpha = animateFloatAsState(
- targetValue = if (abs(revealState.offset) > revealOffset) 1f else 0f,
- animationSpec = tween(
- durationMillis = RAPID,
- delayMillis = RAPID
- ),
- label = "ActionLabelAlpha"
- )
+private fun RevealScope.ActionLabel(revealState: RevealState, content: @Composable () -> Unit) {
+ val labelAlpha =
+ animateFloatAsState(
+ targetValue = if (abs(revealState.offset) > revealOffset) 1f else 0f,
+ animationSpec = tween(durationMillis = RAPID, delayMillis = RAPID),
+ label = "ActionLabelAlpha"
+ )
AnimatedVisibility(
visible = abs(revealState.offset) > revealOffset,
enter = expandHorizontally(animationSpec = tween(durationMillis = RAPID)),
diff --git a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/Swipeable.kt b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/Swipeable.kt
index b689e6d..b6f1704 100644
--- a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/Swipeable.kt
+++ b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/Swipeable.kt
@@ -70,15 +70,15 @@
/**
* State of the [swipeable] modifier.
*
- * This contains necessary information about any ongoing swipe or animation and provides methods
- * to change the state either immediately or by starting an animation. To create and remember a
+ * This contains necessary information about any ongoing swipe or animation and provides methods to
+ * change the state either immediately or by starting an animation. To create and remember a
* [SwipeableState] with the default animation clock, use [rememberSwipeableState].
*
* @param initialValue The initial value of the state.
* @param animationSpec The default animation that will be used to animate to a new state.
- * @param confirmStateChange Optional callback invoked to confirm or veto a pending state change.
- * If the state change is accepted, the offset is optionally be reset to the initial value.
- * and offset is reset.
+ * @param confirmStateChange Optional callback invoked to confirm or veto a pending state change. If
+ * the state change is accepted, the offset is optionally be reset to the initial value. and
+ * offset is reset.
*/
@Stable
@ExperimentalWearMaterialApi
@@ -98,9 +98,7 @@
var currentValue: T by mutableStateOf(initialValue)
private set
- /**
- * Whether the state is currently animating.
- */
+ /** Whether the state is currently animating. */
@ExperimentalWearMaterialApi
var isAnimationRunning: Boolean by mutableStateOf(false)
private set
@@ -108,17 +106,17 @@
/**
* The current position (in pixels) of the [swipeable].
*
- * You should use this state to offset your content accordingly. The recommended way is to
- * use `Modifier.offsetPx`. This includes the resistance by default, if resistance is enabled.
+ * You should use this state to offset your content accordingly. The recommended way is to use
+ * `Modifier.offsetPx`. This includes the resistance by default, if resistance is enabled.
*/
@ExperimentalWearMaterialApi
- val offset: State<Float> get() = offsetState
+ val offset: State<Float>
+ get() = offsetState
- /**
- * The amount by which the [swipeable] has been swiped past its bounds.
- */
+ /** The amount by which the [swipeable] has been swiped past its bounds. */
@ExperimentalWearMaterialApi
- val overflow: State<Float> get() = overflowState
+ val overflow: State<Float>
+ get() = overflowState
private val offsetState = mutableFloatStateOf(0f)
private val overflowState = mutableFloatStateOf(0f)
@@ -135,9 +133,7 @@
internal var anchors by mutableStateOf(emptyMap<Float, T>())
private val latestNonEmptyAnchorsFlow: Flow<Map<Float, T>> =
- snapshotFlow { anchors }
- .filter { it.isNotEmpty() }
- .take(1)
+ snapshotFlow { anchors }.filter { it.isNotEmpty() }.take(1)
internal var minBound = Float.NEGATIVE_INFINITY
internal var maxBound = Float.POSITIVE_INFINITY
@@ -146,28 +142,21 @@
if (anchors.isEmpty()) {
// need to do initial synchronization synchronously :(
val offset = newAnchors.getOffset(currentValue)
- requireNotNull(offset) {
- "The initial value must have an associated anchor."
- }
+ requireNotNull(offset) { "The initial value must have an associated anchor." }
offsetState.floatValue = offset
absoluteOffset.floatValue = offset
initialOffset = offset
}
}
- internal suspend fun processNewAnchors(
- oldAnchors: Map<Float, T>,
- newAnchors: Map<Float, T>
- ) {
+ internal suspend fun processNewAnchors(oldAnchors: Map<Float, T>, newAnchors: Map<Float, T>) {
if (oldAnchors.isEmpty()) {
// If this is the first time that we receive anchors, then we need to initialise
// the state so we snap to the offset associated to the initial value.
minBound = newAnchors.keys.minOrNull()!!
maxBound = newAnchors.keys.maxOrNull()!!
val initialOffset = newAnchors.getOffset(currentValue)
- requireNotNull(initialOffset) {
- "The initial value must have an associated anchor."
- }
+ requireNotNull(initialOffset) { "The initial value must have an associated anchor." }
snapInternalToOffset(initialOffset)
} else if (newAnchors != oldAnchors) {
// If we have received new anchors, then the offset of the current value might
@@ -178,19 +167,20 @@
maxBound = Float.POSITIVE_INFINITY
val animationTargetValue = animationTarget.value
// if we're in the animation already, let's find it a new home
- val targetOffset = if (animationTargetValue != null) {
- // first, try to map old state to the new state
- val oldState = oldAnchors[animationTargetValue]
- val newState = newAnchors.getOffset(oldState)
- // return new state if exists, or find the closes one among new anchors
- newState ?: newAnchors.keys.minByOrNull { abs(it - animationTargetValue) }!!
- } else {
- // we're not animating, proceed by finding the new anchors for an old value
- val actualOldValue = oldAnchors[offset.value]
- val value = if (actualOldValue == currentValue) currentValue else actualOldValue
- newAnchors.getOffset(value) ?: newAnchors
- .keys.minByOrNull { abs(it - offset.value) }!!
- }
+ val targetOffset =
+ if (animationTargetValue != null) {
+ // first, try to map old state to the new state
+ val oldState = oldAnchors[animationTargetValue]
+ val newState = newAnchors.getOffset(oldState)
+ // return new state if exists, or find the closes one among new anchors
+ newState ?: newAnchors.keys.minByOrNull { abs(it - animationTargetValue) }!!
+ } else {
+ // we're not animating, proceed by finding the new anchors for an old value
+ val actualOldValue = oldAnchors[offset.value]
+ val value = if (actualOldValue == currentValue) currentValue else actualOldValue
+ newAnchors.getOffset(value)
+ ?: newAnchors.keys.minByOrNull { abs(it - offset.value) }!!
+ }
try {
animateInternalToOffset(targetOffset, animationSpec)
} catch (c: CancellationException) {
@@ -221,9 +211,7 @@
}
private suspend fun snapInternalToOffset(target: Float) {
- draggableState.drag {
- dragBy(target - absoluteOffset.floatValue)
- }
+ draggableState.drag { dragBy(target - absoluteOffset.floatValue) }
}
private suspend fun animateInternalToOffset(target: Float, spec: AnimationSpec<Float>) {
@@ -254,14 +242,16 @@
val targetValue: T
get() {
// TODO(calintat): Track current velocity (b/149549482) and use that here.
- val target = animationTarget.value ?: computeTarget(
- offset = offset.value,
- lastValue = anchors.getOffset(currentValue) ?: offset.value,
- anchors = anchors.keys,
- thresholds = thresholds,
- velocity = 0f,
- velocityThreshold = Float.POSITIVE_INFINITY
- )
+ val target =
+ animationTarget.value
+ ?: computeTarget(
+ offset = offset.value,
+ lastValue = anchors.getOffset(currentValue) ?: offset.value,
+ anchors = anchors.keys,
+ thresholds = thresholds,
+ velocity = 0f,
+ velocityThreshold = Float.POSITIVE_INFINITY
+ )
return anchors[target] ?: currentValue
}
@@ -322,9 +312,7 @@
suspend fun snapTo(targetValue: T) {
latestNonEmptyAnchorsFlow.collect { anchors ->
val targetOffset = anchors.getOffset(targetValue)
- requireNotNull(targetOffset) {
- "The target value must have an associated anchor."
- }
+ requireNotNull(targetOffset) { "The target value must have an associated anchor." }
snapInternalToOffset(targetOffset)
currentValue = targetValue
}
@@ -341,16 +329,17 @@
latestNonEmptyAnchorsFlow.collect { anchors ->
try {
val targetOffset = anchors.getOffset(targetValue)
- requireNotNull(targetOffset) {
- "The target value must have an associated anchor."
- }
+ requireNotNull(targetOffset) { "The target value must have an associated anchor." }
animateInternalToOffset(targetOffset, anim)
} finally {
val endOffset = absoluteOffset.floatValue
- val endValue = anchors
- // fighting rounding error once again, anchor should be as close as 0.5 pixels
- .filterKeys { anchorOffset -> abs(anchorOffset - endOffset) < 0.5f }
- .values.firstOrNull() ?: currentValue
+ val endValue =
+ anchors
+ // fighting rounding error once again, anchor should be as close as 0.5
+ // pixels
+ .filterKeys { anchorOffset -> abs(anchorOffset - endOffset) < 0.5f }
+ .values
+ .firstOrNull() ?: currentValue
currentValue = endValue
}
}
@@ -361,26 +350,26 @@
* [velocity]. Fling with settling [swipeable] will always consume all the velocity provided
* since it will settle at the anchor.
*
- * In general cases, [swipeable] flings by itself when being swiped. This method is to be
- * used for nested scroll logic that wraps the [swipeable]. In nested scroll developer may
- * want to trigger settling fling when the child scroll container reaches the bound.
+ * In general cases, [swipeable] flings by itself when being swiped. This method is to be used
+ * for nested scroll logic that wraps the [swipeable]. In nested scroll developer may want to
+ * trigger settling fling when the child scroll container reaches the bound.
*
* @param velocity velocity to fling and settle with
- *
* @return the reason fling ended
*/
@ExperimentalWearMaterialApi
suspend fun performFling(velocity: Float) {
latestNonEmptyAnchorsFlow.collect { anchors ->
val lastAnchor = anchors.getOffset(currentValue)!!
- val targetValue = computeTarget(
- offset = offset.value,
- lastValue = lastAnchor,
- anchors = anchors.keys,
- thresholds = thresholds,
- velocity = velocity,
- velocityThreshold = velocityThreshold
- )
+ val targetValue =
+ computeTarget(
+ offset = offset.value,
+ lastValue = lastAnchor,
+ anchors = anchors.keys,
+ thresholds = thresholds,
+ velocity = velocity,
+ velocityThreshold = velocityThreshold
+ )
val targetState = anchors[targetValue]
if (targetState != null && confirmStateChange(targetState)) animateTo(targetState)
// If the user vetoed the state change, rollback to the previous state.
@@ -392,16 +381,15 @@
* Force [swipeable] to consume drag delta provided from outside of the regular [swipeable]
* gesture flow.
*
- * Note: This method performs generic drag and it won't settle to any particular anchor,
- * leaving swipeable in between anchors. When done dragging, [performFling] must be
- * called as well to ensure swipeable will settle at the anchor.
+ * Note: This method performs generic drag and it won't settle to any particular anchor, leaving
+ * swipeable in between anchors. When done dragging, [performFling] must be called as well to
+ * ensure swipeable will settle at the anchor.
*
- * In general cases, [swipeable] drags by itself when being swiped. This method is to be
- * used for nested scroll logic that wraps the [swipeable]. In nested scroll developer may
- * want to force drag when the child scroll container reaches the bound.
+ * In general cases, [swipeable] drags by itself when being swiped. This method is to be used
+ * for nested scroll logic that wraps the [swipeable]. In nested scroll developer may want to
+ * force drag when the child scroll container reaches the bound.
*
* @param delta delta in pixels to drag by
- *
* @return the amount of [delta] consumed
*/
internal fun performDrag(delta: Float): Float {
@@ -415,18 +403,15 @@
}
companion object {
- /**
- * The default [Saver] implementation for [SwipeableState].
- */
+ /** The default [Saver] implementation for [SwipeableState]. */
fun <T : Any> Saver(
animationSpec: AnimationSpec<Float>,
confirmStateChange: (T) -> Boolean,
- ) = Saver<SwipeableState<T>, T>(
- save = { it.currentValue },
- restore = {
- SwipeableState(it, animationSpec, confirmStateChange)
- }
- )
+ ) =
+ Saver<SwipeableState<T>, T>(
+ save = { it.currentValue },
+ restore = { SwipeableState(it, animationSpec, confirmStateChange) }
+ )
}
}
@@ -437,16 +422,15 @@
*
* @param from The state corresponding to the anchor we are moving away from.
* @param to The state corresponding to the anchor we are moving towards.
- * @param fraction The fraction that the current position represents between [from] and [to].
- * Must be between `0` and `1`.
+ * @param fraction The fraction that the current position represents between [from] and [to]. Must
+ * be between `0` and `1`.
*/
@Immutable
@ExperimentalWearMaterialApi
class SwipeProgress<T>(
val from: T,
val to: T,
- @FloatRange(from = 0.0, to = 1.0)
- val fraction: Float
+ @FloatRange(from = 0.0, to = 1.0) val fraction: Float
) {
override fun equals(other: Any?): Boolean {
if (this === other) return true
@@ -486,10 +470,11 @@
confirmStateChange: (newValue: T) -> Boolean = { true },
): SwipeableState<T> {
return rememberSaveable(
- saver = SwipeableState.Saver(
- animationSpec = animationSpec,
- confirmStateChange = confirmStateChange,
- )
+ saver =
+ SwipeableState.Saver(
+ animationSpec = animationSpec,
+ confirmStateChange = confirmStateChange,
+ )
) {
SwipeableState(
initialValue = initialValue,
@@ -504,14 +489,14 @@
/**
* Enable swipe gestures between a set of predefined states.
*
- * To use this, you must provide a map of anchors (in pixels) to states (of type [T]).
- * Note that this map cannot be empty and cannot have two anchors mapped to the same state.
+ * To use this, you must provide a map of anchors (in pixels) to states (of type [T]). Note that
+ * this map cannot be empty and cannot have two anchors mapped to the same state.
*
* When a swipe is detected, the offset of the [SwipeableState] will be updated with the swipe
* delta. You should use this offset to move your content accordingly (see `Modifier.offsetPx`).
* When the swipe ends, the offset will be animated to one of the anchors and when that anchor is
- * reached, the value of the [SwipeableState] will also be updated to the state corresponding to
- * the new anchor. The target anchor is calculated based on the provided positional [thresholds].
+ * reached, the value of the [SwipeableState] will also be updated to the state corresponding to the
+ * new anchor. The target anchor is calculated based on the provided positional [thresholds].
*
* Swiping is constrained between the minimum and maximum anchors. If the user attempts to swipe
* past these bounds, a resistance effect will be applied by default. The amount of resistance at
@@ -523,18 +508,18 @@
* @param state The state of the [swipeable].
* @param anchors Pairs of anchors and states, used to map anchors to states and vice versa.
* @param thresholds Specifies where the thresholds between the states are. The thresholds will be
- * used to determine which state to animate to when swiping stops. This is represented as a lambda
- * that takes two states and returns the threshold between them in the form of a [ThresholdConfig].
- * Note that the order of the states corresponds to the swipe direction.
+ * used to determine which state to animate to when swiping stops. This is represented as a lambda
+ * that takes two states and returns the threshold between them in the form of a
+ * [ThresholdConfig]. Note that the order of the states corresponds to the swipe direction.
* @param orientation The orientation in which the [swipeable] can be swiped.
* @param enabled Whether this [swipeable] is enabled and should react to the user's input.
- * @param reverseDirection Whether to reverse the direction of the swipe, so a top to bottom
- * swipe will behave like bottom to top, and a left to right swipe will behave like right to left.
- * @param interactionSource Optional [MutableInteractionSource] that will passed on to
- * the internal [Modifier.draggable].
+ * @param reverseDirection Whether to reverse the direction of the swipe, so a top to bottom swipe
+ * will behave like bottom to top, and a left to right swipe will behave like right to left.
+ * @param interactionSource Optional [MutableInteractionSource] that will passed on to the internal
+ * [Modifier.draggable].
* @param resistance Controls how much resistance will be applied when swiping past the bounds.
- * @param velocityThreshold The threshold (in dp per second) that the end velocity has to exceed
- * in order to animate to the next state, even if the positional [thresholds] have not been reached.
+ * @param velocityThreshold The threshold (in dp per second) that the end velocity has to exceed in
+ * order to animate to the next state, even if the positional [thresholds] have not been reached.
*/
@ExperimentalWearMaterialApi
fun <T> Modifier.swipeable(
@@ -547,86 +532,96 @@
thresholds: (from: T, to: T) -> ThresholdConfig = { _, _ -> FractionalThreshold(0.5f) },
resistance: ResistanceConfig? = resistanceConfig(anchors.keys),
velocityThreshold: Dp = VelocityThreshold
-) = composed(
- inspectorInfo = debugInspectorInfo {
- name = "swipeable"
- properties["state"] = state
- properties["anchors"] = anchors
- properties["orientation"] = orientation
- properties["enabled"] = enabled
- properties["reverseDirection"] = reverseDirection
- properties["interactionSource"] = interactionSource
- properties["thresholds"] = thresholds
- properties["resistance"] = resistance
- properties["velocityThreshold"] = velocityThreshold
- }
-) {
- require(anchors.isNotEmpty()) {
- "You must have at least one anchor."
- }
- require(anchors.values.distinct().count() == anchors.size) {
- "You cannot have two anchors mapped to the same state."
- }
- val density = LocalDensity.current
- state.ensureInit(anchors)
- LaunchedEffect(anchors, state) {
- val oldAnchors = state.anchors
- state.anchors = anchors
- state.resistance = resistance
- state.thresholds = { a, b ->
- val from = anchors.getValue(a)
- val to = anchors.getValue(b)
- with(thresholds(from, to)) { density.computeThreshold(a, b) }
+) =
+ composed(
+ inspectorInfo =
+ debugInspectorInfo {
+ name = "swipeable"
+ properties["state"] = state
+ properties["anchors"] = anchors
+ properties["orientation"] = orientation
+ properties["enabled"] = enabled
+ properties["reverseDirection"] = reverseDirection
+ properties["interactionSource"] = interactionSource
+ properties["thresholds"] = thresholds
+ properties["resistance"] = resistance
+ properties["velocityThreshold"] = velocityThreshold
+ }
+ ) {
+ require(anchors.isNotEmpty()) { "You must have at least one anchor." }
+ require(anchors.values.distinct().count() == anchors.size) {
+ "You cannot have two anchors mapped to the same state."
}
- with(density) {
- state.velocityThreshold = velocityThreshold.toPx()
+ val density = LocalDensity.current
+ state.ensureInit(anchors)
+ LaunchedEffect(anchors, state) {
+ val oldAnchors = state.anchors
+ state.anchors = anchors
+ state.resistance = resistance
+ state.thresholds = { a, b ->
+ val from = anchors.getValue(a)
+ val to = anchors.getValue(b)
+ with(thresholds(from, to)) { density.computeThreshold(a, b) }
+ }
+ with(density) { state.velocityThreshold = velocityThreshold.toPx() }
+ state.processNewAnchors(oldAnchors, anchors)
}
- state.processNewAnchors(oldAnchors, anchors)
- }
- // Swipeables publish scroll range semantics so they look like they can scroll between values
- // of 0 and 1, inclusive, so that AndroidComposeView can report a value from its canScroll
- // methods that correctly tells the system's ScrollDismissLayout whether it should intercept
- // touch values (see b/199908428). This logic is *not* duplicated in the non-Wear swipeable
- // because it's a bit of a hack to fix navigation in WearOS. Once swipeable implements proper
- // nested scrolling, and the two swipeable implementations are merged, this fake scrolling stuff
- // should be gone anyway. Also note that the regular Android swipe-to-go-back gesture works very
- // differently than the wear gesture so we don't need this workaround to support it.
- // TODO(b/201009199): Modifier.swipeable should coordinate with the nested scrolling system.
- val semantics = if (!enabled) Modifier else Modifier.semantics {
- // Set a fake scroll range axis so that the AndroidComposeView can correctly report whether
- // scrolling is supported via canScroll{Horizontally,Vertically}.
- val range = ScrollAxisRange(
- value = {
- // Avoid dividing by 0.
- if (state.minBound == state.maxBound) {
- 0f
- } else {
- val clampedOffset = state.offset.value.coerceIn(state.minBound, state.maxBound)
- // [0f, 1f] representing the fraction between the swipe bounds.
- // Return the remaining fraction available to swipe.
- (state.maxBound - clampedOffset) / (state.maxBound - state.minBound)
+ // Swipeables publish scroll range semantics so they look like they can scroll between
+ // values
+ // of 0 and 1, inclusive, so that AndroidComposeView can report a value from its canScroll
+ // methods that correctly tells the system's ScrollDismissLayout whether it should intercept
+ // touch values (see b/199908428). This logic is *not* duplicated in the non-Wear swipeable
+ // because it's a bit of a hack to fix navigation in WearOS. Once swipeable implements
+ // proper
+ // nested scrolling, and the two swipeable implementations are merged, this fake scrolling
+ // stuff
+ // should be gone anyway. Also note that the regular Android swipe-to-go-back gesture works
+ // very
+ // differently than the wear gesture so we don't need this workaround to support it.
+ // TODO(b/201009199): Modifier.swipeable should coordinate with the nested scrolling system.
+ val semantics =
+ if (!enabled) Modifier
+ else
+ Modifier.semantics {
+ // Set a fake scroll range axis so that the AndroidComposeView can correctly
+ // report whether
+ // scrolling is supported via canScroll{Horizontally,Vertically}.
+ val range =
+ ScrollAxisRange(
+ value = {
+ // Avoid dividing by 0.
+ if (state.minBound == state.maxBound) {
+ 0f
+ } else {
+ val clampedOffset =
+ state.offset.value.coerceIn(state.minBound, state.maxBound)
+ // [0f, 1f] representing the fraction between the swipe bounds.
+ // Return the remaining fraction available to swipe.
+ (state.maxBound - clampedOffset) /
+ (state.maxBound - state.minBound)
+ }
+ },
+ maxValue = { 1f },
+ reverseScrolling = reverseDirection
+ )
+ when (orientation) {
+ Orientation.Horizontal -> horizontalScrollAxisRange = range
+ Orientation.Vertical -> verticalScrollAxisRange = range
+ }
}
- },
- maxValue = { 1f },
- reverseScrolling = reverseDirection
- )
- when (orientation) {
- Orientation.Horizontal -> horizontalScrollAxisRange = range
- Orientation.Vertical -> verticalScrollAxisRange = range
- }
- }
- Modifier.then(semantics).draggable(
- orientation = orientation,
- enabled = enabled,
- reverseDirection = reverseDirection,
- interactionSource = interactionSource,
- startDragImmediately = state.isAnimationRunning,
- onDragStopped = { velocity -> launch { state.performFling(velocity) } },
- state = state.draggableState
- )
-}
+ Modifier.then(semantics)
+ .draggable(
+ orientation = orientation,
+ enabled = enabled,
+ reverseDirection = reverseDirection,
+ interactionSource = interactionSource,
+ startDragImmediately = state.isAnimationRunning,
+ onDragStopped = { velocity -> launch { state.performFling(velocity) } },
+ state = state.draggableState
+ )
+ }
/**
* Interface to compute a threshold between two anchors/states in a [swipeable].
@@ -636,9 +631,7 @@
@Stable
@ExperimentalWearMaterialApi
interface ThresholdConfig {
- /**
- * Compute the value of the threshold (in pixels), once the values of the anchors are known.
- */
+ /** Compute the value of the threshold (in pixels), once the values of the anchors are known. */
fun Density.computeThreshold(fromValue: Float, toValue: Float): Float
}
@@ -662,10 +655,8 @@
*/
@Immutable
@ExperimentalWearMaterialApi
-data class FractionalThreshold(
- @FloatRange(from = 0.0, to = 1.0)
- private val fraction: Float
-) : ThresholdConfig {
+data class FractionalThreshold(@FloatRange(from = 0.0, to = 1.0) private val fraction: Float) :
+ ThresholdConfig {
override fun Density.computeThreshold(fromValue: Float, toValue: Float): Float {
return lerp(fromValue, toValue, fraction)
}
@@ -675,33 +666,30 @@
* Specifies how resistance is calculated in [swipeable].
*
* There are two things needed to calculate resistance: the resistance basis determines how much
- * overflow will be consumed to achieve maximum resistance, and the resistance factor determines
- * the amount of resistance (the larger the resistance factor, the stronger the resistance).
+ * overflow will be consumed to achieve maximum resistance, and the resistance factor determines the
+ * amount of resistance (the larger the resistance factor, the stronger the resistance).
*
- * The resistance basis is usually either the size of the component which [swipeable] is applied
- * to, or the distance between the minimum and maximum anchors. For a constructor in which the
+ * The resistance basis is usually either the size of the component which [swipeable] is applied to,
+ * or the distance between the minimum and maximum anchors. For a constructor in which the
* resistance basis defaults to the latter, consider using [resistanceConfig].
*
* You may specify different resistance factors for each bound. Consider using one of the default
- * resistance factors in [SwipeableDefaults]: `StandardResistanceFactor` to convey that the user
- * has run out of things to see, and `StiffResistanceFactor` to convey that the user cannot swipe
- * this right now. Also, you can set either factor to 0 to disable resistance at that bound.
+ * resistance factors in [SwipeableDefaults]: `StandardResistanceFactor` to convey that the user has
+ * run out of things to see, and `StiffResistanceFactor` to convey that the user cannot swipe this
+ * right now. Also, you can set either factor to 0 to disable resistance at that bound.
*
* @param basis Specifies the maximum amount of overflow that will be consumed. Must be positive.
- * @param factorAtMin The factor by which to scale the resistance at the minimum bound.
- * Must not be negative.
- * @param factorAtMax The factor by which to scale the resistance at the maximum bound.
- * Must not be negative.
+ * @param factorAtMin The factor by which to scale the resistance at the minimum bound. Must not be
+ * negative.
+ * @param factorAtMax The factor by which to scale the resistance at the maximum bound. Must not be
+ * negative.
*/
@Immutable
@ExperimentalWearMaterialApi
class ResistanceConfig(
- @FloatRange(from = 0.0, fromInclusive = false)
- val basis: Float,
- @FloatRange(from = 0.0)
- val factorAtMin: Float = StandardResistanceFactor,
- @FloatRange(from = 0.0)
- val factorAtMax: Float = StandardResistanceFactor
+ @FloatRange(from = 0.0, fromInclusive = false) val basis: Float,
+ @FloatRange(from = 0.0) val factorAtMin: Float = StandardResistanceFactor,
+ @FloatRange(from = 0.0) val factorAtMax: Float = StandardResistanceFactor
) {
fun computeResistance(overflow: Float): Float {
val factor = if (overflow < 0) factorAtMin else factorAtMax
@@ -734,17 +722,14 @@
}
/**
- * Given an offset x and a set of anchors, return a list of anchors:
- * 1. [ ] if the set of anchors is empty,
- * 2. [ x ] if x is equal to one of the anchors,
- * 3. [ min ] if min is the minimum anchor and x < min,
- * 4. [ max ] if max is the maximum anchor and x > max, or
- * 5. [ a , b ] if a and b are anchors such that a < x < b and b - a is minimal.
+ * Given an offset x and a set of anchors, return a list of anchors:
+ * 1. [ ] if the set of anchors is empty,
+ * 2. [ x ] if x is equal to one of the anchors,
+ * 3. [ min ] if min is the minimum anchor and x < min,
+ * 4. [ max ] if max is the maximum anchor and x > max, or
+ * 5. [ a , b ] if a and b are anchors such that a < x < b and b - a is minimal.
*/
-private fun findBounds(
- offset: Float,
- anchors: Set<Float>
-): List<Float> {
+private fun findBounds(offset: Float, anchors: Set<Float>): List<Float> {
// Find the anchors the target lies between with a little bit of rounding error.
val a = anchors.filter { it <= offset + 0.001 }.fastMaxBy { it }
val b = anchors.filter { it >= offset - 0.001 }.fastMinByOrNull { it }
@@ -805,36 +790,26 @@
return entries.firstOrNull { it.value == state }?.key
}
-/**
- * Contains useful defaults for [swipeable] and [SwipeableState].
- */
+/** Contains useful defaults for [swipeable] and [SwipeableState]. */
@ExperimentalWearMaterialApi
object SwipeableDefaults {
- /**
- * The default animation used by [SwipeableState].
- */
+ /** The default animation used by [SwipeableState]. */
val AnimationSpec = SpringSpec<Float>()
- /**
- * The default velocity threshold (1.8 dp per millisecond) used by [swipeable].
- */
+ /** The default velocity threshold (1.8 dp per millisecond) used by [swipeable]. */
val VelocityThreshold = 125.dp
- /**
- * A stiff resistance factor which indicates that swiping isn't available right now.
- */
+ /** A stiff resistance factor which indicates that swiping isn't available right now. */
const val StiffResistanceFactor = 20f
- /**
- * A standard resistance factor which indicates that the user has run out of things to see.
- */
+ /** A standard resistance factor which indicates that the user has run out of things to see. */
const val StandardResistanceFactor = 10f
/**
* The default resistance config used by [swipeable].
*
- * This returns `null` if there is one anchor. If there are at least two anchors, it returns
- * a [ResistanceConfig] with the resistance basis equal to the distance between the two bounds.
+ * This returns `null` if there is one anchor. If there are at least two anchors, it returns a
+ * [ResistanceConfig] with the resistance basis equal to the distance between the two bounds.
*/
fun resistanceConfig(
anchors: Set<Float>,
diff --git a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/Text.kt b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/Text.kt
index 7991332..5a541b8 100644
--- a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/Text.kt
+++ b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/Text.kt
@@ -41,52 +41,52 @@
* High level element that displays text and provides semantics / accessibility information.
*
* The default [style] uses the [LocalTextStyle] provided by the [MaterialTheme] / components. If
- * you are setting your own style, you may want to consider first retrieving [LocalTextStyle],
- * and using [TextStyle.copy] to keep any theme defined attributes, only modifying the specific
+ * you are setting your own style, you may want to consider first retrieving [LocalTextStyle], and
+ * using [TextStyle.copy] to keep any theme defined attributes, only modifying the specific
* attributes you want to override.
*
* For ease of use, commonly used parameters from [TextStyle] are also present here. The order of
* precedence is as follows:
- * - If a parameter is explicitly set here (i.e, it is _not_ `null` or [TextUnit.Unspecified]),
- * then this parameter will always be used.
+ * - If a parameter is explicitly set here (i.e, it is _not_ `null` or [TextUnit.Unspecified]), then
+ * this parameter will always be used.
* - If a parameter is _not_ set, (`null` or [TextUnit.Unspecified]), then the corresponding value
- * from [style] will be used instead.
+ * from [style] will be used instead.
*
* Additionally, for [color], if [color] is not set, and [style] does not have a color, then
- * [LocalContentColor] will be used with an alpha of [LocalContentAlpha]- this allows this
- * [Text] or element containing this [Text] to adapt to different background colors and still
- * maintain contrast and accessibility.
+ * [LocalContentColor] will be used with an alpha of [LocalContentAlpha]- this allows this [Text] or
+ * element containing this [Text] to adapt to different background colors and still maintain
+ * contrast and accessibility.
*
* @param text The text to be displayed.
* @param modifier [Modifier] to apply to this layout node.
* @param color [Color] to apply to the text. If [Color.Unspecified], and [style] has no color set,
- * this will be [LocalContentColor].
+ * this will be [LocalContentColor].
* @param fontSize The size of glyphs to use when painting the text. See [TextStyle.fontSize].
- * @param fontStyle The typeface variant to use when drawing the letters (e.g., italic).
- * See [TextStyle.fontStyle].
+ * @param fontStyle The typeface variant to use when drawing the letters (e.g., italic). See
+ * [TextStyle.fontStyle].
* @param fontWeight The typeface thickness to use when painting the text (e.g., [FontWeight.Bold]).
* @param fontFamily The font family to be used when rendering the text. See [TextStyle.fontFamily].
- * @param letterSpacing The amount of space to add between each letter.
- * See [TextStyle.letterSpacing].
- * @param textDecoration The decorations to paint on the text (e.g., an underline).
- * See [TextStyle.textDecoration].
- * @param textAlign The alignment of the text within the lines of the paragraph.
- * See [TextStyle.textAlign].
- * @param lineHeight Line height for the [Paragraph] in [TextUnit] unit, e.g. SP or EM.
- * See [TextStyle.lineHeight].
+ * @param letterSpacing The amount of space to add between each letter. See
+ * [TextStyle.letterSpacing].
+ * @param textDecoration The decorations to paint on the text (e.g., an underline). See
+ * [TextStyle.textDecoration].
+ * @param textAlign The alignment of the text within the lines of the paragraph. See
+ * [TextStyle.textAlign].
+ * @param lineHeight Line height for the [Paragraph] in [TextUnit] unit, e.g. SP or EM. See
+ * [TextStyle.lineHeight].
* @param overflow How visual overflow should be handled.
* @param softWrap Whether the text should break at soft line breaks. If false, the glyphs in the
- * text will be positioned as if there was unlimited horizontal space. If [softWrap] is false,
- * [overflow] and TextAlign may have unexpected effects.
- * @param maxLines An optional maximum number of lines for the text to span, wrapping if
- * necessary. If the text exceeds the given number of lines, it will be truncated according to
- * [overflow] and [softWrap]. If it is not null, then it must be greater than zero.
+ * text will be positioned as if there was unlimited horizontal space. If [softWrap] is false,
+ * [overflow] and TextAlign may have unexpected effects.
+ * @param maxLines An optional maximum number of lines for the text to span, wrapping if necessary.
+ * If the text exceeds the given number of lines, it will be truncated according to [overflow] and
+ * [softWrap]. If it is not null, then it must be greater than zero.
* @param minLines The minimum height in terms of minimum number of visible lines. It is required
- * that 1 <= [minLines] <= [maxLines].
+ * that 1 <= [minLines] <= [maxLines].
* @param onTextLayout Callback that is executed when a new text layout is calculated. A
- * [TextLayoutResult] object that callback provides contains paragraph information, size of the
- * text, baselines and other details. The callback can be used to add additional decoration or
- * functionality to the text. For example, to draw selection around the text.
+ * [TextLayoutResult] object that callback provides contains paragraph information, size of the
+ * text, baselines and other details. The callback can be used to add additional decoration or
+ * functionality to the text. For example, to draw selection around the text.
* @param style Style configuration for the text such as color, font, line height etc.
*/
@Composable
@@ -135,54 +135,56 @@
* High level element that displays text and provides semantics / accessibility information.
*
* The default [style] uses the [LocalTextStyle] provided by the [MaterialTheme] / components. If
- * you are setting your own style, you may want to consider first retrieving [LocalTextStyle],
- * and using [TextStyle.copy] to keep any theme defined attributes, only modifying the specific
+ * you are setting your own style, you may want to consider first retrieving [LocalTextStyle], and
+ * using [TextStyle.copy] to keep any theme defined attributes, only modifying the specific
* attributes you want to override.
*
* For ease of use, commonly used parameters from [TextStyle] are also present here. The order of
* precedence is as follows:
- * - If a parameter is explicitly set here (i.e, it is _not_ `null` or [TextUnit.Unspecified]),
- * then this parameter will always be used.
+ * - If a parameter is explicitly set here (i.e, it is _not_ `null` or [TextUnit.Unspecified]), then
+ * this parameter will always be used.
* - If a parameter is _not_ set, (`null` or [TextUnit.Unspecified]), then the corresponding value
- * from [style] will be used instead.
+ * from [style] will be used instead.
*
* Additionally, for [color], if [color] is not set, and [style] does not have a color, then
- * [LocalContentColor] will be used with an alpha of [LocalContentAlpha]- this allows this
- * [Text] or element containing this [Text] to adapt to different background colors and still
- * maintain contrast and accessibility.
+ * [LocalContentColor] will be used with an alpha of [LocalContentAlpha]- this allows this [Text] or
+ * element containing this [Text] to adapt to different background colors and still maintain
+ * contrast and accessibility.
*
* @param text The text to be displayed.
* @param modifier [Modifier] to apply to this layout node.
* @param color [Color] to apply to the text. If [Color.Unspecified], and [style] has no color set,
- * this will be [LocalContentColor].
+ * this will be [LocalContentColor].
* @param fontSize The size of glyphs to use when painting the text. See [TextStyle.fontSize].
- * @param fontStyle The typeface variant to use when drawing the letters (e.g., italic).
- * See [TextStyle.fontStyle].
+ * @param fontStyle The typeface variant to use when drawing the letters (e.g., italic). See
+ * [TextStyle.fontStyle].
* @param fontWeight The typeface thickness to use when painting the text (e.g., [FontWeight.Bold]).
* @param fontFamily The font family to be used when rendering the text. See [TextStyle.fontFamily].
- * @param letterSpacing The amount of space to add between each letter.
- * See [TextStyle.letterSpacing].
- * @param textDecoration The decorations to paint on the text (e.g., an underline).
- * See [TextStyle.textDecoration].
- * @param textAlign The alignment of the text within the lines of the paragraph.
- * See [TextStyle.textAlign].
- * @param lineHeight Line height for the [Paragraph] in [TextUnit] unit, e.g. SP or EM.
- * See [TextStyle.lineHeight].
+ * @param letterSpacing The amount of space to add between each letter. See
+ * [TextStyle.letterSpacing].
+ * @param textDecoration The decorations to paint on the text (e.g., an underline). See
+ * [TextStyle.textDecoration].
+ * @param textAlign The alignment of the text within the lines of the paragraph. See
+ * [TextStyle.textAlign].
+ * @param lineHeight Line height for the [Paragraph] in [TextUnit] unit, e.g. SP or EM. See
+ * [TextStyle.lineHeight].
* @param overflow How visual overflow should be handled.
* @param softWrap Whether the text should break at soft line breaks. If false, the glyphs in the
- * text will be positioned as if there was unlimited horizontal space. If [softWrap] is false,
- * [overflow] and TextAlign may have unexpected effects.
- * @param maxLines An optional maximum number of lines for the text to span, wrapping if
- * necessary. If the text exceeds the given number of lines, it will be truncated according to
- * [overflow] and [softWrap]. If it is not null, then it must be greater than zero.
+ * text will be positioned as if there was unlimited horizontal space. If [softWrap] is false,
+ * [overflow] and TextAlign may have unexpected effects.
+ * @param maxLines An optional maximum number of lines for the text to span, wrapping if necessary.
+ * If the text exceeds the given number of lines, it will be truncated according to [overflow] and
+ * [softWrap]. If it is not null, then it must be greater than zero.
* @param onTextLayout Callback that is executed when a new text layout is calculated. A
- * [TextLayoutResult] object that callback provides contains paragraph information, size of the
- * text, baselines and other details. The callback can be used to add additional decoration or
- * functionality to the text. For example, to draw selection around the text.
+ * [TextLayoutResult] object that callback provides contains paragraph information, size of the
+ * text, baselines and other details. The callback can be used to add additional decoration or
+ * functionality to the text. For example, to draw selection around the text.
* @param style Style configuration for the text such as color, font, line height etc.
*/
-@Deprecated("Maintained for binary compatibility with Compose for Wear OS 1.1",
- level = DeprecationLevel.HIDDEN)
+@Deprecated(
+ "Maintained for binary compatibility with Compose for Wear OS 1.1",
+ level = DeprecationLevel.HIDDEN
+)
@Composable
fun Text(
text: String,
@@ -227,54 +229,54 @@
* High level element that displays text and provides semantics / accessibility information.
*
* The default [style] uses the [LocalTextStyle] provided by the [MaterialTheme] / components. If
- * you are setting your own style, you may want to consider first retrieving [LocalTextStyle],
- * and using [TextStyle.copy] to keep any theme defined attributes, only modifying the specific
+ * you are setting your own style, you may want to consider first retrieving [LocalTextStyle], and
+ * using [TextStyle.copy] to keep any theme defined attributes, only modifying the specific
* attributes you want to override.
*
* For ease of use, commonly used parameters from [TextStyle] are also present here. The order of
* precedence is as follows:
- * - If a parameter is explicitly set here (i.e, it is _not_ `null` or [TextUnit.Unspecified]),
- * then this parameter will always be used.
+ * - If a parameter is explicitly set here (i.e, it is _not_ `null` or [TextUnit.Unspecified]), then
+ * this parameter will always be used.
* - If a parameter is _not_ set, (`null` or [TextUnit.Unspecified]), then the corresponding value
- * from [style] will be used instead.
+ * from [style] will be used instead.
*
* Additionally, for [color], if [color] is not set, and [style] does not have a color, then
- * [LocalContentColor] will be used with an alpha of [LocalContentAlpha]- this allows this
- * [Text] or element containing this [Text] to adapt to different background colors and still
- * maintain contrast and accessibility.
+ * [LocalContentColor] will be used with an alpha of [LocalContentAlpha]- this allows this [Text] or
+ * element containing this [Text] to adapt to different background colors and still maintain
+ * contrast and accessibility.
*
* @param text The text to be displayed, where [AnnotatedString] allows multiple styles to be used.
* @param modifier [Modifier] to apply to this layout node.
* @param color [Color] to apply to the text. If [Color.Unspecified], and [style] has no color set,
- * this will be [LocalContentColor].
+ * this will be [LocalContentColor].
* @param fontSize The size of glyphs to use when painting the text. See [TextStyle.fontSize].
- * @param fontStyle The typeface variant to use when drawing the letters (e.g., italic).
- * See [TextStyle.fontStyle].
+ * @param fontStyle The typeface variant to use when drawing the letters (e.g., italic). See
+ * [TextStyle.fontStyle].
* @param fontWeight The typeface thickness to use when painting the text (e.g., [FontWeight.Bold]).
* @param fontFamily The font family to be used when rendering the text. See [TextStyle.fontFamily].
- * @param letterSpacing The amount of space to add between each letter.
- * See [TextStyle.letterSpacing].
- * @param textDecoration The decorations to paint on the text (e.g., an underline).
- * See [TextStyle.textDecoration].
- * @param textAlign The alignment of the text within the lines of the paragraph.
- * See [TextStyle.textAlign].
- * @param lineHeight Line height for the [Paragraph] in [TextUnit] unit, e.g. SP or EM.
- * See [TextStyle.lineHeight].
+ * @param letterSpacing The amount of space to add between each letter. See
+ * [TextStyle.letterSpacing].
+ * @param textDecoration The decorations to paint on the text (e.g., an underline). See
+ * [TextStyle.textDecoration].
+ * @param textAlign The alignment of the text within the lines of the paragraph. See
+ * [TextStyle.textAlign].
+ * @param lineHeight Line height for the [Paragraph] in [TextUnit] unit, e.g. SP or EM. See
+ * [TextStyle.lineHeight].
* @param overflow How visual overflow should be handled.
* @param softWrap Whether the text should break at soft line breaks. If false, the glyphs in the
- * text will be positioned as if there was unlimited horizontal space. If [softWrap] is false,
- * [overflow] and TextAlign may have unexpected effects.
- * @param maxLines An optional maximum number of lines for the text to span, wrapping if
- * necessary. If the text exceeds the given number of lines, it will be truncated according to
- * [overflow] and [softWrap]. If it is not null, then it must be greater than zero.
+ * text will be positioned as if there was unlimited horizontal space. If [softWrap] is false,
+ * [overflow] and TextAlign may have unexpected effects.
+ * @param maxLines An optional maximum number of lines for the text to span, wrapping if necessary.
+ * If the text exceeds the given number of lines, it will be truncated according to [overflow] and
+ * [softWrap]. If it is not null, then it must be greater than zero.
* @param minLines The minimum height in terms of minimum number of visible lines. It is required
- * that 1 <= [minLines] <= [maxLines].
- * @param inlineContent A map store composables that replaces certain ranges of the text. It's
- * used to insert composables into text layout. Check [InlineTextContent] for more information.
+ * that 1 <= [minLines] <= [maxLines].
+ * @param inlineContent A map store composables that replaces certain ranges of the text. It's used
+ * to insert composables into text layout. Check [InlineTextContent] for more information.
* @param onTextLayout Callback that is executed when a new text layout is calculated. A
- * [TextLayoutResult] object that callback provides contains paragraph information, size of the
- * text, baselines and other details. The callback can be used to add additional decoration or
- * functionality to the text. For example, to draw selection around the text.
+ * [TextLayoutResult] object that callback provides contains paragraph information, size of the
+ * text, baselines and other details. The callback can be used to add additional decoration or
+ * functionality to the text. For example, to draw selection around the text.
* @param style Style configuration for the text such as color, font, line height etc.
*/
@Composable
@@ -298,11 +300,12 @@
onTextLayout: (TextLayoutResult) -> Unit = {},
style: TextStyle = LocalTextStyle.current
) {
- val textColor = color.takeOrElse {
- style.color.takeOrElse {
- LocalContentColor.current.copy(alpha = LocalContentAlpha.current)
+ val textColor =
+ color.takeOrElse {
+ style.color.takeOrElse {
+ LocalContentColor.current.copy(alpha = LocalContentAlpha.current)
+ }
}
- }
androidx.wear.compose.materialcore.Text(
text = text,
modifier = modifier,
@@ -329,56 +332,58 @@
* High level element that displays text and provides semantics / accessibility information.
*
* The default [style] uses the [LocalTextStyle] provided by the [MaterialTheme] / components. If
- * you are setting your own style, you may want to consider first retrieving [LocalTextStyle],
- * and using [TextStyle.copy] to keep any theme defined attributes, only modifying the specific
+ * you are setting your own style, you may want to consider first retrieving [LocalTextStyle], and
+ * using [TextStyle.copy] to keep any theme defined attributes, only modifying the specific
* attributes you want to override.
*
* For ease of use, commonly used parameters from [TextStyle] are also present here. The order of
* precedence is as follows:
- * - If a parameter is explicitly set here (i.e, it is _not_ `null` or [TextUnit.Unspecified]),
- * then this parameter will always be used.
+ * - If a parameter is explicitly set here (i.e, it is _not_ `null` or [TextUnit.Unspecified]), then
+ * this parameter will always be used.
* - If a parameter is _not_ set, (`null` or [TextUnit.Unspecified]), then the corresponding value
- * from [style] will be used instead.
+ * from [style] will be used instead.
*
* Additionally, for [color], if [color] is not set, and [style] does not have a color, then
- * [LocalContentColor] will be used with an alpha of [LocalContentAlpha]- this allows this
- * [Text] or element containing this [Text] to adapt to different background colors and still
- * maintain contrast and accessibility.
+ * [LocalContentColor] will be used with an alpha of [LocalContentAlpha]- this allows this [Text] or
+ * element containing this [Text] to adapt to different background colors and still maintain
+ * contrast and accessibility.
*
* @param text The text to be displayed, where [AnnotatedString] allows multiple styles to be used.
* @param modifier [Modifier] to apply to this layout node.
* @param color [Color] to apply to the text. If [Color.Unspecified], and [style] has no color set,
- * this will be [LocalContentColor].
+ * this will be [LocalContentColor].
* @param fontSize The size of glyphs to use when painting the text. See [TextStyle.fontSize].
- * @param fontStyle The typeface variant to use when drawing the letters (e.g., italic).
- * See [TextStyle.fontStyle].
+ * @param fontStyle The typeface variant to use when drawing the letters (e.g., italic). See
+ * [TextStyle.fontStyle].
* @param fontWeight The typeface thickness to use when painting the text (e.g., [FontWeight.Bold]).
* @param fontFamily The font family to be used when rendering the text. See [TextStyle.fontFamily].
- * @param letterSpacing The amount of space to add between each letter.
- * See [TextStyle.letterSpacing].
- * @param textDecoration The decorations to paint on the text (e.g., an underline).
- * See [TextStyle.textDecoration].
- * @param textAlign The alignment of the text within the lines of the paragraph.
- * See [TextStyle.textAlign].
- * @param lineHeight Line height for the [Paragraph] in [TextUnit] unit, e.g. SP or EM.
- * See [TextStyle.lineHeight].
+ * @param letterSpacing The amount of space to add between each letter. See
+ * [TextStyle.letterSpacing].
+ * @param textDecoration The decorations to paint on the text (e.g., an underline). See
+ * [TextStyle.textDecoration].
+ * @param textAlign The alignment of the text within the lines of the paragraph. See
+ * [TextStyle.textAlign].
+ * @param lineHeight Line height for the [Paragraph] in [TextUnit] unit, e.g. SP or EM. See
+ * [TextStyle.lineHeight].
* @param overflow How visual overflow should be handled.
* @param softWrap Whether the text should break at soft line breaks. If false, the glyphs in the
- * text will be positioned as if there was unlimited horizontal space. If [softWrap] is false,
- * [overflow] and TextAlign may have unexpected effects.
- * @param maxLines An optional maximum number of lines for the text to span, wrapping if
- * necessary. If the text exceeds the given number of lines, it will be truncated according to
- * [overflow] and [softWrap]. If it is not null, then it must be greater than zero.
- * @param inlineContent A map store composables that replaces certain ranges of the text. It's
- * used to insert composables into text layout. Check [InlineTextContent] for more information.
+ * text will be positioned as if there was unlimited horizontal space. If [softWrap] is false,
+ * [overflow] and TextAlign may have unexpected effects.
+ * @param maxLines An optional maximum number of lines for the text to span, wrapping if necessary.
+ * If the text exceeds the given number of lines, it will be truncated according to [overflow] and
+ * [softWrap]. If it is not null, then it must be greater than zero.
+ * @param inlineContent A map store composables that replaces certain ranges of the text. It's used
+ * to insert composables into text layout. Check [InlineTextContent] for more information.
* @param onTextLayout Callback that is executed when a new text layout is calculated. A
- * [TextLayoutResult] object that callback provides contains paragraph information, size of the
- * text, baselines and other details. The callback can be used to add additional decoration or
- * functionality to the text. For example, to draw selection around the text.
+ * [TextLayoutResult] object that callback provides contains paragraph information, size of the
+ * text, baselines and other details. The callback can be used to add additional decoration or
+ * functionality to the text. For example, to draw selection around the text.
* @param style Style configuration for the text such as color, font, line height etc.
*/
-@Deprecated("Maintained for binary compatibility with Compose for Wear OS 1.1",
- level = DeprecationLevel.HIDDEN)
+@Deprecated(
+ "Maintained for binary compatibility with Compose for Wear OS 1.1",
+ level = DeprecationLevel.HIDDEN
+)
@Composable
fun Text(
text: AnnotatedString,
@@ -433,9 +438,9 @@
// TODO: b/156598010 remove this and replace with fold definition on the backing CompositionLocal
/**
- * This function is used to set the current value of [LocalTextStyle], merging the given style
- * with the current style values for any missing attributes. Any [Text] components included in
- * this component's [content] will be styled with this style unless styled explicitly.
+ * This function is used to set the current value of [LocalTextStyle], merging the given style with
+ * the current style values for any missing attributes. Any [Text] components included in this
+ * component's [content] will be styled with this style unless styled explicitly.
*
* @see LocalTextStyle
*/
diff --git a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/TimeText.kt b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/TimeText.kt
index a37d956..457b197 100644
--- a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/TimeText.kt
+++ b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/TimeText.kt
@@ -63,34 +63,33 @@
import java.util.Locale
/**
- * Layout to show the current time and a label at the top of the screen.
- * If device has a round screen, then the time will be curved along the top edge of the screen,
- * if rectangular - then the text and the time will be straight
+ * Layout to show the current time and a label at the top of the screen. If device has a round
+ * screen, then the time will be curved along the top edge of the screen, if rectangular - then the
+ * text and the time will be straight
*
- * This composable supports additional composable views to the left and to the right
- * of the clock: Start Content and End Content.
- * [startCurvedContent], [endCurvedContent] and [textCurvedSeparator] are used
- * for Round screens.
- * [startLinearContent], [endLinearContent] and [textLinearSeparator] are used
- * for Square screens.
- * For proper support of Square and Round screens both Linear and Curved methods should
- * be implemented.
+ * This composable supports additional composable views to the left and to the right of the clock:
+ * Start Content and End Content. [startCurvedContent], [endCurvedContent] and [textCurvedSeparator]
+ * are used for Round screens. [startLinearContent], [endLinearContent] and [textLinearSeparator]
+ * are used for Square screens. For proper support of Square and Round screens both Linear and
+ * Curved methods should be implemented.
*
* Note that Wear Material UX guidance recommends that time text should not be larger than 90
* degrees of the screen edge on round devices and prefers short status messages be shown in start
* content only using the MaterialTheme.colors.primary color for the status message.
*
* For more information, see the
- * [Curved Text](https://developer.android.com/training/wearables/components/curved-text)
- * guide.
+ * [Curved Text](https://developer.android.com/training/wearables/components/curved-text) guide.
*
* A [TimeText] with a short app status message shown in the start content:
+ *
* @sample androidx.wear.compose.material.samples.TimeTextWithStatus
*
* An example of a [TimeText] with a different date and time format:
+ *
* @sample androidx.wear.compose.material.samples.TimeTextWithFullDateAndTimeFormat
*
* An example of a [TimeText] animating a message that is added or removed
+ *
* @sample androidx.wear.compose.material.samples.TimeTextAnimation
*
* @param modifier Current modifier.
@@ -128,10 +127,7 @@
it.invoke(this)
textCurvedSeparator()
}
- curvedText(
- text = timeText,
- style = CurvedTextStyle(timeTextStyle)
- )
+ curvedText(text = timeText, style = CurvedTextStyle(timeTextStyle))
endCurvedContent?.let {
textCurvedSeparator()
it.invoke(this)
@@ -140,9 +136,7 @@
}
} else {
Row(
- modifier = modifier
- .fillMaxSize()
- .padding(contentPadding),
+ modifier = modifier.fillMaxSize().padding(contentPadding),
verticalAlignment = Alignment.Top,
horizontalArrangement = Arrangement.Center
) {
@@ -163,42 +157,35 @@
}
}
-/**
- * Contains the default values used by [TimeText]
- */
+/** Contains the default values used by [TimeText] */
public object TimeTextDefaults {
private val Padding = 2.dp
- /**
- * Default format for 24h clock.
- */
+ /** Default format for 24h clock. */
const val TimeFormat24Hours = "HH:mm"
- /**
- * Default format for 12h clock.
- */
+ /** Default format for 12h clock. */
const val TimeFormat12Hours = "h:mm"
- /**
- * The default content padding used by [TimeText]
- */
+ /** The default content padding used by [TimeText] */
public val ContentPadding: PaddingValues = PaddingValues(Padding)
/**
- * Retrieves default timeFormat for the device. Depending on settings, it can be either
- * 12h or 24h format
+ * Retrieves default timeFormat for the device. Depending on settings, it can be either 12h or
+ * 24h format
*/
@Composable
public fun timeFormat(): String {
val format = if (is24HourFormat()) TimeFormat24Hours else TimeFormat12Hours
return DateFormat.getBestDateTimePattern(Locale.getDefault(), format)
- .replace("a", "").trim()
+ .replace("a", "")
+ .trim()
}
/**
- * Creates a [TextStyle] with default parameters used for showing time
- * on square screens. By default a copy of MaterialTheme.typography.caption1 style is created
+ * Creates a [TextStyle] with default parameters used for showing time on square screens. By
+ * default a copy of MaterialTheme.typography.caption1 style is created
*
* @param background The background color
* @param color The main color
@@ -209,12 +196,14 @@
background: Color = Color.Unspecified,
color: Color = Color.Unspecified,
fontSize: TextUnit = TextUnit.Unspecified,
- ) = MaterialTheme.typography.caption1 +
- TextStyle(color = color, background = background, fontSize = fontSize)
+ ) =
+ MaterialTheme.typography.caption1 +
+ TextStyle(color = color, background = background, fontSize = fontSize)
/**
- * A default implementation of Separator shown between start/end content and the time
- * on square screens
+ * A default implementation of Separator shown between start/end content and the time on square
+ * screens
+ *
* @param modifier A default modifier for the separator
* @param textStyle A [TextStyle] for the separator
* @param contentPadding The spacing values between the container and the separator
@@ -225,16 +214,13 @@
textStyle: TextStyle = timeTextStyle(),
contentPadding: PaddingValues = PaddingValues(horizontal = 4.dp)
) {
- Text(
- text = "·",
- style = textStyle,
- modifier = modifier.padding(contentPadding)
- )
+ Text(text = "·", style = textStyle, modifier = modifier.padding(contentPadding))
}
/**
- * A default implementation of Separator shown between start/end content and the time
- * on round screens
+ * A default implementation of Separator shown between start/end content and the time on round
+ * screens
+ *
* @param curvedTextStyle A [CurvedTextStyle] for the separator
* @param contentArcPadding A [ArcPaddingValues] for the separator text
*/
@@ -250,18 +236,14 @@
}
/**
- * A default implementation of [TimeSource].
- * Once the system time changes, it triggers an update of the [TimeSource.currentTime]
- * which is formatted before that using [timeFormat] param.
+ * A default implementation of [TimeSource]. Once the system time changes, it triggers an update
+ * of the [TimeSource.currentTime] which is formatted before that using [timeFormat] param.
*
- * Android implementation:
- * [DefaultTimeSource] for Android uses [android.text.format.DateFormat]
+ * Android implementation: [DefaultTimeSource] for Android uses [android.text.format.DateFormat]
* [timeFormat] should follow the standard
* [Date and Time patterns](https://developer.android.com/reference/java/text/SimpleDateFormat#date-and-time-patterns)
- * Examples:
- * "h:mm a" - 12:08 PM
- * "yyyy.MM.dd HH:mm:ss" - 2021.11.01 14:08:56
- * More examples can be found [here](https://developer.android.com/reference/java/text/SimpleDateFormat#examples)
+ * Examples: "h:mm a" - 12:08 PM "yyyy.MM.dd HH:mm:ss" - 2021.11.01 14:08:56 More examples can
+ * be found [here](https://developer.android.com/reference/java/text/SimpleDateFormat#examples)
*
* Desktop implementation: TBD
*
@@ -270,81 +252,70 @@
public fun timeSource(timeFormat: String): TimeSource = DefaultTimeSource(timeFormat)
}
-/**
- * An interface which is responsible for retrieving a formatted time.
- */
+/** An interface which is responsible for retrieving a formatted time. */
public interface TimeSource {
/**
* A method responsible for returning updated time string.
+ *
* @return Formatted time string.
*/
val currentTime: String
@Composable get
}
-/**
- * An extension function, which converts PaddingValues into ArcPaddingValues
- */
-private fun PaddingValues.toArcPadding() = object : ArcPaddingValues {
- override fun calculateOuterPadding(radialDirection: CurvedDirection.Radial) =
- calculateTopPadding()
+/** An extension function, which converts PaddingValues into ArcPaddingValues */
+private fun PaddingValues.toArcPadding() =
+ object : ArcPaddingValues {
+ override fun calculateOuterPadding(radialDirection: CurvedDirection.Radial) =
+ calculateTopPadding()
- override fun calculateInnerPadding(radialDirection: CurvedDirection.Radial) =
- calculateBottomPadding()
+ override fun calculateInnerPadding(radialDirection: CurvedDirection.Radial) =
+ calculateBottomPadding()
- override fun calculateAfterPadding(
- layoutDirection: LayoutDirection,
- angularDirection: CurvedDirection.Angular
- ) = calculateRightPadding(layoutDirection)
+ override fun calculateAfterPadding(
+ layoutDirection: LayoutDirection,
+ angularDirection: CurvedDirection.Angular
+ ) = calculateRightPadding(layoutDirection)
- override fun calculateBeforePadding(
- layoutDirection: LayoutDirection,
- angularDirection: CurvedDirection.Angular
- ) = calculateLeftPadding(layoutDirection)
-}
+ override fun calculateBeforePadding(
+ layoutDirection: LayoutDirection,
+ angularDirection: CurvedDirection.Angular
+ ) = calculateLeftPadding(layoutDirection)
+ }
internal class DefaultTimeSource constructor(timeFormat: String) : TimeSource {
private val _timeFormat = timeFormat
override val currentTime: String
- @Composable
- get() = currentTime({ currentTimeMillis() }, _timeFormat).value
+ @Composable get() = currentTime({ currentTimeMillis() }, _timeFormat).value
}
@Composable
@VisibleForTesting
-internal fun currentTime(
- time: () -> Long,
- timeFormat: String
-): State<String> {
+internal fun currentTime(time: () -> Long, timeFormat: String): State<String> {
var calendar by remember { mutableStateOf(Calendar.getInstance()) }
var currentTime by remember { mutableLongStateOf(time()) }
- val timeText = remember {
- derivedStateOf { formatTime(calendar, currentTime, timeFormat) }
- }
+ val timeText = remember { derivedStateOf { formatTime(calendar, currentTime, timeFormat) } }
val context = LocalContext.current
val updatedTimeLambda by rememberUpdatedState(time)
DisposableEffect(context, updatedTimeLambda) {
- val receiver = TimeBroadcastReceiver(
- onTimeChanged = { currentTime = updatedTimeLambda() },
- onTimeZoneChanged = { calendar = Calendar.getInstance() }
- )
+ val receiver =
+ TimeBroadcastReceiver(
+ onTimeChanged = { currentTime = updatedTimeLambda() },
+ onTimeZoneChanged = { calendar = Calendar.getInstance() }
+ )
receiver.register(context)
- onDispose {
- receiver.unregister(context)
- }
+ onDispose { receiver.unregister(context) }
}
return timeText
}
-/**
- * A [BroadcastReceiver] to receive time tick, time change, and time zone change events.
- */
+/** A [BroadcastReceiver] to receive time tick, time change, and time zone change events. */
private class TimeBroadcastReceiver(
val onTimeChanged: () -> Unit,
val onTimeZoneChanged: () -> Unit
@@ -378,11 +349,7 @@
}
}
-private fun formatTime(
- calendar: Calendar,
- currentTime: Long,
- timeFormat: String
-): String {
+private fun formatTime(calendar: Calendar, currentTime: Long, timeFormat: String): String {
calendar.timeInMillis = currentTime
return DateFormat.format(timeFormat, calendar).toString()
}
diff --git a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/ToggleButton.kt b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/ToggleButton.kt
index a7c289a..1f979c3 100644
--- a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/ToggleButton.kt
+++ b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/ToggleButton.kt
@@ -34,25 +34,23 @@
import androidx.compose.ui.unit.dp
/**
- * Wear Material [ToggleButton] that offers a single slot to take any content
- * (text, icon or image).
+ * Wear Material [ToggleButton] that offers a single slot to take any content (text, icon or image).
*
* The [ToggleButton] is circular in shape and defaults to size
* [ToggleButtonDefaults.DefaultToggleButtonSize] or [ToggleButtonDefaults.SmallToggleButtonSize].
* Icon content should be of size [ToggleButtonDefaults.DefaultIconSize] or
* [ToggleButtonDefaults.SmallIconSize] respectively.
*
- * The recommended set of checked and unchecked [ToggleButtonColors] can be obtained
- * from [ToggleButtonDefaults.toggleButtonColors], which defaults to
- * checked colors being
- * a solid background of [Colors.primary] with content color of [Colors.onPrimary]
- * and unchecked colors being
- * a solid background of [Colors.surface] with content color of [Colors.onSurface].
+ * The recommended set of checked and unchecked [ToggleButtonColors] can be obtained from
+ * [ToggleButtonDefaults.toggleButtonColors], which defaults to checked colors being a solid
+ * background of [Colors.primary] with content color of [Colors.onPrimary] and unchecked colors
+ * being a solid background of [Colors.surface] with content color of [Colors.onSurface].
*
* [ToggleButton]s can be enabled or disabled. A disabled toggle button will not respond to click
* events.
*
* Example of a [ToggleButton] with an icon:
+ *
* @sample androidx.wear.compose.material.samples.ToggleButtonWithIcon
*
* For more information, see the
@@ -62,19 +60,21 @@
* @param checked Boolean flag indicating whether this toggle button is currently checked.
* @param onCheckedChange Callback to be invoked when this toggle button is clicked.
* @param modifier Modifier to be applied to the toggle button.
- * @param enabled Controls the enabled state of the toggle button. When `false`,
- * this toggle button will not be clickable.
- * @param colors [ToggleButtonColors] that will be used to resolve the background and
- * content color for this toggle button. See [ToggleButtonDefaults.toggleButtonColors].
- * @param interactionSource The [MutableInteractionSource] representing the stream of
- * [Interaction]s for this toggle button. You can create and pass in your own remembered
- * [MutableInteractionSource] if you want to observe [Interaction]s and customize the
- * appearance / behavior of this ToggleButton in different [Interaction]s.
+ * @param enabled Controls the enabled state of the toggle button. When `false`, this toggle button
+ * will not be clickable.
+ * @param colors [ToggleButtonColors] that will be used to resolve the background and content color
+ * for this toggle button. See [ToggleButtonDefaults.toggleButtonColors].
+ * @param interactionSource The [MutableInteractionSource] representing the stream of [Interaction]s
+ * for this toggle button. You can create and pass in your own remembered
+ * [MutableInteractionSource] if you want to observe [Interaction]s and customize the appearance /
+ * behavior of this ToggleButton in different [Interaction]s.
* @param content The icon, image or text to be drawn inside the toggle button.
*/
-@Deprecated("This overload is provided for backwards compatibility with Compose for Wear OS 1.0." +
- "A newer overload is available with an additional shape parameter.",
- level = DeprecationLevel.HIDDEN)
+@Deprecated(
+ "This overload is provided for backwards compatibility with Compose for Wear OS 1.0." +
+ "A newer overload is available with an additional shape parameter.",
+ level = DeprecationLevel.HIDDEN
+)
@Composable
public fun ToggleButton(
checked: Boolean,
@@ -84,36 +84,36 @@
colors: ToggleButtonColors = ToggleButtonDefaults.toggleButtonColors(),
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
content: @Composable BoxScope.() -> Unit,
-) = ToggleButton(
- checked,
- onCheckedChange,
- modifier,
- enabled,
- colors,
- interactionSource,
- CircleShape,
- ToggleButtonDefaults.DefaultRole,
- content)
+) =
+ ToggleButton(
+ checked,
+ onCheckedChange,
+ modifier,
+ enabled,
+ colors,
+ interactionSource,
+ CircleShape,
+ ToggleButtonDefaults.DefaultRole,
+ content
+ )
/**
- * Wear Material [ToggleButton] that offers a single slot to take any content
- * (text, icon or image).
+ * Wear Material [ToggleButton] that offers a single slot to take any content (text, icon or image).
*
- * The [ToggleButton] defaults to size [ToggleButtonDefaults.DefaultToggleButtonSize] or [ToggleButtonDefaults.SmallToggleButtonSize].
- * Icon content should be of size [ToggleButtonDefaults.DefaultIconSize] or
- * [ToggleButtonDefaults.SmallIconSize] respectively.
+ * The [ToggleButton] defaults to size [ToggleButtonDefaults.DefaultToggleButtonSize] or
+ * [ToggleButtonDefaults.SmallToggleButtonSize]. Icon content should be of size
+ * [ToggleButtonDefaults.DefaultIconSize] or [ToggleButtonDefaults.SmallIconSize] respectively.
*
- * The recommended set of checked and unchecked [ToggleButtonColors] can be obtained
- * from [ToggleButtonDefaults.toggleButtonColors], which defaults to
- * checked colors being
- * a solid background of [Colors.primary] with content color of [Colors.onPrimary]
- * and unchecked colors being
- * a solid background of [Colors.surface] with content color of [Colors.onSurface].
+ * The recommended set of checked and unchecked [ToggleButtonColors] can be obtained from
+ * [ToggleButtonDefaults.toggleButtonColors], which defaults to checked colors being a solid
+ * background of [Colors.primary] with content color of [Colors.onPrimary] and unchecked colors
+ * being a solid background of [Colors.surface] with content color of [Colors.onSurface].
*
* [ToggleButton]s can be enabled or disabled. A disabled toggle button will not respond to click
* events.
*
* Example of a [ToggleButton] with an icon:
+ *
* @sample androidx.wear.compose.material.samples.ToggleButtonWithIcon
*
* For more information, see the
@@ -123,21 +123,23 @@
* @param checked Boolean flag indicating whether this toggle button is currently checked.
* @param onCheckedChange Callback to be invoked when this toggle button is clicked.
* @param modifier Modifier to be applied to the toggle button.
- * @param enabled Controls the enabled state of the toggle button. When `false`,
- * this toggle button will not be clickable.
- * @param colors [ToggleButtonColors] that will be used to resolve the background and
- * content color for this toggle button. See [ToggleButtonDefaults.toggleButtonColors].
- * @param interactionSource The [MutableInteractionSource] representing the stream of
- * [Interaction]s for this toggle button. You can create and pass in your own remembered
- * [MutableInteractionSource] if you want to observe [Interaction]s and customize the
- * appearance / behavior of this ToggleButton in different [Interaction]s.
+ * @param enabled Controls the enabled state of the toggle button. When `false`, this toggle button
+ * will not be clickable.
+ * @param colors [ToggleButtonColors] that will be used to resolve the background and content color
+ * for this toggle button. See [ToggleButtonDefaults.toggleButtonColors].
+ * @param interactionSource The [MutableInteractionSource] representing the stream of [Interaction]s
+ * for this toggle button. You can create and pass in your own remembered
+ * [MutableInteractionSource] if you want to observe [Interaction]s and customize the appearance /
+ * behavior of this ToggleButton in different [Interaction]s.
* @param shape Defines the shape for this toggle button. It is strongly recommended to use the
- * default as this shape is a key characteristic of the Wear Material Theme.
+ * default as this shape is a key characteristic of the Wear Material Theme.
* @param content The icon, image or text to be drawn inside the toggle button.
*/
-@Deprecated("This overload is provided for backwards compatibility with Compose for Wear OS 1.1." +
- "A newer overload is available with an additional semantic role parameter.",
- level = DeprecationLevel.HIDDEN)
+@Deprecated(
+ "This overload is provided for backwards compatibility with Compose for Wear OS 1.1." +
+ "A newer overload is available with an additional semantic role parameter.",
+ level = DeprecationLevel.HIDDEN
+)
@Composable
public fun ToggleButton(
checked: Boolean,
@@ -148,36 +150,36 @@
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
shape: Shape = CircleShape,
content: @Composable BoxScope.() -> Unit,
-) = ToggleButton(
- checked,
- onCheckedChange,
- modifier,
- enabled,
- colors,
- interactionSource,
- shape,
- ToggleButtonDefaults.DefaultRole,
- content)
+) =
+ ToggleButton(
+ checked,
+ onCheckedChange,
+ modifier,
+ enabled,
+ colors,
+ interactionSource,
+ shape,
+ ToggleButtonDefaults.DefaultRole,
+ content
+ )
/**
- * Wear Material [ToggleButton] that offers a single slot to take any content
- * (text, icon or image).
+ * Wear Material [ToggleButton] that offers a single slot to take any content (text, icon or image).
*
- * The [ToggleButton] defaults to size [ToggleButtonDefaults.DefaultToggleButtonSize] or [ToggleButtonDefaults.SmallToggleButtonSize].
- * Icon content should be of size [ToggleButtonDefaults.DefaultIconSize] or
- * [ToggleButtonDefaults.SmallIconSize] respectively.
+ * The [ToggleButton] defaults to size [ToggleButtonDefaults.DefaultToggleButtonSize] or
+ * [ToggleButtonDefaults.SmallToggleButtonSize]. Icon content should be of size
+ * [ToggleButtonDefaults.DefaultIconSize] or [ToggleButtonDefaults.SmallIconSize] respectively.
*
- * The recommended set of checked and unchecked [ToggleButtonColors] can be obtained
- * from [ToggleButtonDefaults.toggleButtonColors], which defaults to
- * checked colors being
- * a solid background of [Colors.primary] with content color of [Colors.onPrimary]
- * and unchecked colors being
- * a solid background of [Colors.surface] with content color of [Colors.onSurface].
+ * The recommended set of checked and unchecked [ToggleButtonColors] can be obtained from
+ * [ToggleButtonDefaults.toggleButtonColors], which defaults to checked colors being a solid
+ * background of [Colors.primary] with content color of [Colors.onPrimary] and unchecked colors
+ * being a solid background of [Colors.surface] with content color of [Colors.onSurface].
*
* [ToggleButton]s can be enabled or disabled. A disabled toggle button will not respond to click
* events.
*
* Example of a [ToggleButton] with an icon:
+ *
* @sample androidx.wear.compose.material.samples.ToggleButtonWithIcon
*
* For more information, see the
@@ -187,18 +189,17 @@
* @param checked Boolean flag indicating whether this toggle button is currently checked.
* @param onCheckedChange Callback to be invoked when this toggle button is clicked.
* @param modifier Modifier to be applied to the toggle button.
- * @param enabled Controls the enabled state of the toggle button. When `false`,
- * this toggle button will not be clickable.
- * @param colors [ToggleButtonColors] that will be used to resolve the background and
- * content color for this toggle button. See [ToggleButtonDefaults.toggleButtonColors].
+ * @param enabled Controls the enabled state of the toggle button. When `false`, this toggle button
+ * will not be clickable.
+ * @param colors [ToggleButtonColors] that will be used to resolve the background and content color
+ * for this toggle button. See [ToggleButtonDefaults.toggleButtonColors].
* @param interactionSource an optional hoisted [MutableInteractionSource] for observing and
- * emitting [Interaction]s for this toggle button. You can use this to change the toggle button's
- * appearance or preview the toggle button in different states. Note that if `null` is provided,
- * interactions will still happen internally.
+ * emitting [Interaction]s for this toggle button. You can use this to change the toggle button's
+ * appearance or preview the toggle button in different states. Note that if `null` is provided,
+ * interactions will still happen internally.
* @param shape Defines the shape for this toggle button. It is strongly recommended to use the
- * default as this shape is a key characteristic of the Wear Material Theme.
- * @param role Role semantics that accessibility services can use to provide more
- * context to users.
+ * default as this shape is a key characteristic of the Wear Material Theme.
+ * @param role Role semantics that accessibility services can use to provide more context to users.
* @param content The icon, image or text to be drawn inside the toggle button.
*/
@Composable
@@ -226,13 +227,15 @@
interactionSource = interactionSource,
shape = shape,
ripple = rippleOrFallbackImplementation(),
- content = provideScopeContent(
- colors.contentColor(enabled = enabled, checked = checked),
- MaterialTheme.typography.button,
- content
- )
+ content =
+ provideScopeContent(
+ colors.contentColor(enabled = enabled, checked = checked),
+ MaterialTheme.typography.button,
+ content
+ )
)
}
+
/**
* Represents the background and content colors used in a toggle button in different states.
*
@@ -247,8 +250,7 @@
* @param enabled whether the toggle button is enabled
* @param checked whether the toggle button is checked
*/
- @Composable
- public fun backgroundColor(enabled: Boolean, checked: Boolean): State<Color>
+ @Composable public fun backgroundColor(enabled: Boolean, checked: Boolean): State<Color>
/**
* Represents the content color for this toggle button, depending on [enabled] and [checked].
@@ -256,61 +258,52 @@
* @param enabled whether the toggle button is enabled
* @param checked whether the toggle button is checked
*/
- @Composable
- public fun contentColor(enabled: Boolean, checked: Boolean): State<Color>
+ @Composable public fun contentColor(enabled: Boolean, checked: Boolean): State<Color>
}
-/**
- * Contains the default values used by [ToggleButton].
- */
+/** Contains the default values used by [ToggleButton]. */
public object ToggleButtonDefaults {
/**
- * The recommended size for a small [ToggleButton].
- * You can apply this value for the size by overriding Modifier.size directly on [ToggleButton].
+ * The recommended size for a small [ToggleButton]. You can apply this value for the size by
+ * overriding Modifier.size directly on [ToggleButton].
*/
public val SmallToggleButtonSize = 48.dp
/**
- * The default size applied for the [ToggleButton].
- * Note that you can override it by applying Modifier.size directly on [ToggleButton].
+ * The default size applied for the [ToggleButton]. Note that you can override it by applying
+ * Modifier.size directly on [ToggleButton].
*/
public val DefaultToggleButtonSize = 52.dp
- /**
- * The size of an icon when used inside a small-sized [ToggleButton].
- */
+ /** The size of an icon when used inside a small-sized [ToggleButton]. */
public val SmallIconSize = 24.dp
- /**
- * The default size of an icon when used inside a default-sized [ToggleButton].
- */
+ /** The default size of an icon when used inside a default-sized [ToggleButton]. */
public val DefaultIconSize = 26.dp
- /**
- * Role semantics that accessibility services can use to provide more context to users.
- */
+ /** Role semantics that accessibility services can use to provide more context to users. */
public val DefaultRole = Role.Checkbox
/**
- * Creates a [ToggleButtonColors] that represents the background and content colors
- * used in a [ToggleButton]. Defaults to primary-styled checked colors
- * and surface-styled unchecked colors.
+ * Creates a [ToggleButtonColors] that represents the background and content colors used in a
+ * [ToggleButton]. Defaults to primary-styled checked colors and surface-styled unchecked
+ * colors.
*
* @param checkedBackgroundColor the background color of this [ToggleButton] when enabled and
- * checked
+ * checked
* @param checkedContentColor the content color of this [ToggleButton] when enabled and checked
* @param disabledCheckedBackgroundColor the background color of this [ToggleButton] when
- * checked and not enabled
- * @param disabledCheckedContentColor the content color of this [ToggleButton] when checked
- * and not enabled
+ * checked and not enabled
+ * @param disabledCheckedContentColor the content color of this [ToggleButton] when checked and
+ * not enabled
* @param uncheckedBackgroundColor the background color of this [ToggleButton] when enabled and
- * unchecked
+ * unchecked
* @param uncheckedContentColor the content color of this [ToggleButton] when enabled and
- * unchecked
+ * unchecked
* @param disabledUncheckedBackgroundColor the background color of this [ToggleButton] when
- * unchecked and not enabled
+ * unchecked and not enabled
* @param disabledUncheckedContentColor the content color of this [ToggleButton] when unchecked
- * and not enabled
+ * and not enabled
*/
@Composable
public fun toggleButtonColors(
@@ -325,21 +318,20 @@
uncheckedBackgroundColor.copy(alpha = ContentAlpha.disabled),
disabledUncheckedContentColor: Color =
uncheckedContentColor.copy(alpha = ContentAlpha.disabled),
- ): ToggleButtonColors = DefaultToggleButtonColors(
- checkedBackgroundColor = checkedBackgroundColor,
- checkedContentColor = checkedContentColor,
- disabledCheckedBackgroundColor = disabledCheckedBackgroundColor,
- disabledCheckedContentColor = disabledCheckedContentColor,
- uncheckedBackgroundColor = uncheckedBackgroundColor,
- uncheckedContentColor = uncheckedContentColor,
- disabledUncheckedBackgroundColor = disabledUncheckedBackgroundColor,
- disabledUncheckedContentColor = disabledUncheckedContentColor,
- )
+ ): ToggleButtonColors =
+ DefaultToggleButtonColors(
+ checkedBackgroundColor = checkedBackgroundColor,
+ checkedContentColor = checkedContentColor,
+ disabledCheckedBackgroundColor = disabledCheckedBackgroundColor,
+ disabledCheckedContentColor = disabledCheckedContentColor,
+ uncheckedBackgroundColor = uncheckedBackgroundColor,
+ uncheckedContentColor = uncheckedContentColor,
+ disabledUncheckedBackgroundColor = disabledUncheckedBackgroundColor,
+ disabledUncheckedContentColor = disabledUncheckedContentColor,
+ )
}
-/**
- * Default [ToggleButtonColors] implementation.
- */
+/** Default [ToggleButtonColors] implementation. */
@Immutable
private class DefaultToggleButtonColors(
private val checkedBackgroundColor: Color,
diff --git a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/ToggleChip.kt b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/ToggleChip.kt
index 12c36dc..dba3f9f 100644
--- a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/ToggleChip.kt
+++ b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/ToggleChip.kt
@@ -48,61 +48,59 @@
/**
* A [ToggleChip] is a specialized type of [Chip] that includes a slot for a bi-state toggle control
- * such as a toggle or checkbox. This overload provides suitable accessibility semantics
- * for a toggleable control like [Checkbox] and [Switch]. For selectable controls
- * like [RadioButton], use [SelectableChip] in order to provide the correct semantics for
- * accessibility.
+ * such as a toggle or checkbox. This overload provides suitable accessibility semantics for a
+ * toggleable control like [Checkbox] and [Switch]. For selectable controls like [RadioButton], use
+ * [SelectableChip] in order to provide the correct semantics for accessibility.
*
* The Wear Material [ToggleChip] offers four slots and a specific layout for an application icon, a
* label, a secondaryLabel and toggle control. The application icon and secondaryLabel are optional.
* The items are laid out in a row with the optional icon at the start, a column containing the two
* label slots in the middle and a slot for the toggle control at the end.
*
- * The [ToggleChip] is Stadium shaped and has a max height designed to take no more than
- * two lines of text of [Typography.button] style.
- * With localisation and/or large font sizes, the [ToggleChip] height adjusts to
- * accommodate the contents. The label and secondary label should be consistently aligned.
+ * The [ToggleChip] is Stadium shaped and has a max height designed to take no more than two lines
+ * of text of [Typography.button] style. With localisation and/or large font sizes, the [ToggleChip]
+ * height adjusts to accommodate the contents. The label and secondary label should be consistently
+ * aligned.
*
- * The recommended set of [ToggleChipColors] can be obtained from
- * [ToggleChipDefaults], e.g. [ToggleChipDefaults.toggleChipColors].
+ * The recommended set of [ToggleChipColors] can be obtained from [ToggleChipDefaults], e.g.
+ * [ToggleChipDefaults.toggleChipColors].
*
* Chips can be enabled or disabled. A disabled chip will not respond to click events.
*
* Example of a [ToggleChip] with an icon, label and secondary label (defaults to switch toggle):
+ *
* @sample androidx.wear.compose.material.samples.ToggleChipWithSwitch
*
* For more information, see the
- * [Toggle Chips](https://developer.android.com/training/wearables/components/toggle-chips)
- * guide.
+ * [Toggle Chips](https://developer.android.com/training/wearables/components/toggle-chips) guide.
*
* @param checked Boolean flag indicating whether this button is currently checked.
* @param onCheckedChange Callback to be invoked when this button's checked status changes
* @param label A slot for providing the chip's main label. The contents are expected to be text
- * which is "start" aligned.
- * @param toggleControl A slot for providing the chip's toggle control. Two built-in types
- * of toggle control are supported - [Checkbox] and [Switch]. For [RadioButton],
- * use [SelectableChip], in order to provide the correct semantics for accessibility.
+ * which is "start" aligned.
+ * @param toggleControl A slot for providing the chip's toggle control. Two built-in types of toggle
+ * control are supported - [Checkbox] and [Switch]. For [RadioButton], use [SelectableChip], in
+ * order to provide the correct semantics for accessibility.
* @param modifier Modifier to be applied to the chip
* @param appIcon An optional slot for providing an icon to indicate the purpose of the chip. The
- * contents are expected to be a horizontally and vertically centre aligned icon of size
- * [ToggleChipDefaults.IconSize]. In order to correctly render when the Chip is not enabled the
- * icon must set its alpha value to [LocalContentAlpha].
+ * contents are expected to be a horizontally and vertically centre aligned icon of size
+ * [ToggleChipDefaults.IconSize]. In order to correctly render when the Chip is not enabled the
+ * icon must set its alpha value to [LocalContentAlpha].
* @param secondaryLabel A slot for providing the chip's secondary label. The contents are expected
- * to be text which is "start" aligned if there is an icon preset and "start" or "center" aligned if
- * not. label and secondaryLabel contents should be consistently aligned.
- * @param colors [ToggleChipColors] that will be used to resolve the background and
- * content color for this chip in different states, see
- * [ToggleChipDefaults.toggleChipColors].
- * @param enabled Controls the enabled state of the chip. When `false`, this chip will not
- * be clickable
+ * to be text which is "start" aligned if there is an icon preset and "start" or "center" aligned
+ * if not. label and secondaryLabel contents should be consistently aligned.
+ * @param colors [ToggleChipColors] that will be used to resolve the background and content color
+ * for this chip in different states, see [ToggleChipDefaults.toggleChipColors].
+ * @param enabled Controls the enabled state of the chip. When `false`, this chip will not be
+ * clickable
* @param interactionSource an optional hoisted [MutableInteractionSource] for observing and
- * emitting [Interaction]s for this chip's "toggleable" tap area. You can use this to change the
- * chip's appearance or preview the chip in different states. Note that if `null` is provided,
- * interactions will still happen internally.
+ * emitting [Interaction]s for this chip's "toggleable" tap area. You can use this to change the
+ * chip's appearance or preview the chip in different states. Note that if `null` is provided,
+ * interactions will still happen internally.
* @param contentPadding The spacing values to apply internally between the container and the
- * content
+ * content
* @param shape Defines the chip's shape. It is strongly recommended to use the default as this
- * shape is a key characteristic of the Wear Material Theme
+ * shape is a key characteristic of the Wear Material Theme
*/
@Composable
public fun ToggleChip(
@@ -118,64 +116,65 @@
interactionSource: MutableInteractionSource? = null,
contentPadding: PaddingValues = ToggleChipDefaults.ContentPadding,
shape: Shape = MaterialTheme.shapes.large,
-) = androidx.wear.compose.materialcore.ToggleButton(
- checked = checked,
- onCheckedChange = onCheckedChange,
- label = provideScopeContent(
- contentColor = colors.contentColor(enabled = enabled, checked),
- textStyle = MaterialTheme.typography.button,
- content = label
- ),
- toggleControl = provideContent(
- contentColor = colors.toggleControlColor(enabled, checked),
- content = toggleControl
- ),
- selectionControl = null,
- modifier = modifier
- .defaultMinSize(minHeight = ToggleChipDefaults.Height)
- .height(IntrinsicSize.Min),
- icon = provideNullableScopeContent(
- contentColor = colors.contentColor(enabled = enabled, checked = checked),
- content = appIcon
- ),
- secondaryLabel = provideNullableScopeContent(
- contentColor = colors.secondaryContentColor(enabled = enabled, checked),
- textStyle = MaterialTheme.typography.caption2,
- content = secondaryLabel
- ),
- background = { isEnabled, isChecked ->
- val painter = colors.background(
- enabled = isEnabled,
- checked = isChecked
- ).value
+) =
+ androidx.wear.compose.materialcore.ToggleButton(
+ checked = checked,
+ onCheckedChange = onCheckedChange,
+ label =
+ provideScopeContent(
+ contentColor = colors.contentColor(enabled = enabled, checked),
+ textStyle = MaterialTheme.typography.button,
+ content = label
+ ),
+ toggleControl =
+ provideContent(
+ contentColor = colors.toggleControlColor(enabled, checked),
+ content = toggleControl
+ ),
+ selectionControl = null,
+ modifier =
+ modifier
+ .defaultMinSize(minHeight = ToggleChipDefaults.Height)
+ .height(IntrinsicSize.Min),
+ icon =
+ provideNullableScopeContent(
+ contentColor = colors.contentColor(enabled = enabled, checked = checked),
+ content = appIcon
+ ),
+ secondaryLabel =
+ provideNullableScopeContent(
+ contentColor = colors.secondaryContentColor(enabled = enabled, checked),
+ textStyle = MaterialTheme.typography.caption2,
+ content = secondaryLabel
+ ),
+ background = { isEnabled, isChecked ->
+ val painter = colors.background(enabled = isEnabled, checked = isChecked).value
- Modifier.paint(painter = painter, contentScale = ContentScale.Crop)
- },
- enabled = enabled,
- interactionSource = interactionSource,
- contentPadding = contentPadding,
- shape = shape,
- toggleControlHeight = TOGGLE_CONTROL_HEIGHT,
- toggleControlWidth = TOGGLE_CONTROL_WIDTH,
- labelSpacerSize = 0.dp,
- toggleControlSpacing = TOGGLE_CONTROL_SPACING,
- iconSpacing = ICON_SPACING,
- ripple = rippleOrFallbackImplementation()
-)
+ Modifier.paint(painter = painter, contentScale = ContentScale.Crop)
+ },
+ enabled = enabled,
+ interactionSource = interactionSource,
+ contentPadding = contentPadding,
+ shape = shape,
+ toggleControlHeight = TOGGLE_CONTROL_HEIGHT,
+ toggleControlWidth = TOGGLE_CONTROL_WIDTH,
+ labelSpacerSize = 0.dp,
+ toggleControlSpacing = TOGGLE_CONTROL_SPACING,
+ iconSpacing = ICON_SPACING,
+ ripple = rippleOrFallbackImplementation()
+ )
/**
* A [SplitToggleChip] is a specialized type of [Chip] that includes a slot for a toggle control,
- * such as a toggle or checkbox. The [SplitToggleChip] differs from the
- * [ToggleChip] by having two "tappable" areas, one clickable and one toggleable.
+ * such as a toggle or checkbox. The [SplitToggleChip] differs from the [ToggleChip] by having two
+ * "tappable" areas, one clickable and one toggleable.
*
- * This overload provides suitable accessibility semantics for a toggleable control like
- * [Checkbox] and [Switch]. For selectable controls like [RadioButton],
- * use [SelectableChip] instead.
+ * This overload provides suitable accessibility semantics for a toggleable control like [Checkbox]
+ * and [Switch]. For selectable controls like [RadioButton], use [SelectableChip] instead.
*
* The Wear Material [SplitToggleChip] offers three slots and a specific layout for a label,
- * secondaryLabel and toggle control. The secondaryLabel is optional. The items are laid out
- * with a column containing the two label slots and a slot for the toggle control at the
- * end.
+ * secondaryLabel and toggle control. The secondaryLabel is optional. The items are laid out with a
+ * column containing the two label slots and a slot for the toggle control at the end.
*
* A [SplitToggleChip] has two tappable areas, one tap area for the labels and another for the
* toggle control. The [onClick] listener will be associated with the main body of the split toggle
@@ -184,57 +183,54 @@
* For a split toggle chip the background of the tappable background area behind the toggle control
* will have a visual effect applied to provide a "divider" between the two tappable areas.
*
- * The [SplitToggleChip] is Stadium shaped and has a max height designed to take no more than
- * two lines of text of [Typography.button] style.
- * With localisation and/or large font sizes, the [SplitToggleChip] height adjusts
- * to accommodate the contents. The label and secondary label should be consistently aligned.
+ * The [SplitToggleChip] is Stadium shaped and has a max height designed to take no more than two
+ * lines of text of [Typography.button] style. With localisation and/or large font sizes, the
+ * [SplitToggleChip] height adjusts to accommodate the contents. The label and secondary label
+ * should be consistently aligned.
*
- * The recommended set of [SplitToggleChipColors] can be obtained from
- * [ToggleChipDefaults], e.g. [ToggleChipDefaults.splitToggleChipColors].
+ * The recommended set of [SplitToggleChipColors] can be obtained from [ToggleChipDefaults], e.g.
+ * [ToggleChipDefaults.splitToggleChipColors].
*
* Chips can be enabled or disabled. A disabled chip will not respond to click events.
*
* Example of a [SplitToggleChip] with a label and the toggle control changed to checkbox:
+ *
* @sample androidx.wear.compose.material.samples.SplitToggleChipWithCheckbox
*
* For more information, see the
- * [Toggle Chips](https://developer.android.com/training/wearables/components/toggle-chips)
- * guide.
+ * [Toggle Chips](https://developer.android.com/training/wearables/components/toggle-chips) guide.
*
* @param checked Boolean flag indicating whether this button is currently checked.
- * @param onCheckedChange Callback to be invoked when this buttons checked status is
- * changed.
+ * @param onCheckedChange Callback to be invoked when this buttons checked status is changed.
* @param label A slot for providing the chip's main label. The contents are expected to be text
- * which is "start" aligned.
+ * which is "start" aligned.
* @param onClick Click listener called when the user clicks the main body of the chip, the area
- * behind the labels.
- * @param toggleControl A slot for providing the chip's toggle controls(s). Two built-in types
- * of toggle control are supported, see [Checkbox] and [Switch]. For [RadioButton],
- * use [SelectableChip] instead.
- * [ImageVector]s can be obtained from [ToggleChipDefaults.switchIcon], [ToggleChipDefaults.radioIcon]
- * and [ToggleChipDefaults.checkboxIcon]. In order to correctly render when the Chip is not enabled the
- * icon must set its alpha value to [LocalContentAlpha].
+ * behind the labels.
+ * @param toggleControl A slot for providing the chip's toggle controls(s). Two built-in types of
+ * toggle control are supported, see [Checkbox] and [Switch]. For [RadioButton], use
+ * [SelectableChip] instead. [ImageVector]s can be obtained from [ToggleChipDefaults.switchIcon],
+ * [ToggleChipDefaults.radioIcon] and [ToggleChipDefaults.checkboxIcon]. In order to correctly
+ * render when the Chip is not enabled the icon must set its alpha value to [LocalContentAlpha].
* @param modifier Modifier to be applied to the chip
* @param secondaryLabel A slot for providing the chip's secondary label. The contents are expected
- * to be "start" or "center" aligned. label and secondaryLabel contents should be consistently
- * aligned.
- * @param colors [SplitToggleChipColors] that will be used to resolve the background and
- * content color for this chip in different states, see
- * [ToggleChipDefaults.splitToggleChipColors].
- * @param enabled Controls the enabled state of the chip. When `false`, this chip will not
- * be clickable
+ * to be "start" or "center" aligned. label and secondaryLabel contents should be consistently
+ * aligned.
+ * @param colors [SplitToggleChipColors] that will be used to resolve the background and content
+ * color for this chip in different states, see [ToggleChipDefaults.splitToggleChipColors].
+ * @param enabled Controls the enabled state of the chip. When `false`, this chip will not be
+ * clickable
* @param checkedInteractionSource an optional hoisted [MutableInteractionSource] for observing and
- * emitting [Interaction]s for this chip's "toggleable" tap area. You can use this to change the
- * chip's appearance or preview the chip in different states. Note that if `null` is provided,
- * interactions will still happen internally.
+ * emitting [Interaction]s for this chip's "toggleable" tap area. You can use this to change the
+ * chip's appearance or preview the chip in different states. Note that if `null` is provided,
+ * interactions will still happen internally.
* @param clickInteractionSource an optional hoisted [MutableInteractionSource] for observing and
- * emitting [Interaction]s for this chip's "clickable" tap area. You can use this to change the
- * chip's appearance or preview the chip in different states. Note that if `null` is provided,
- * interactions will still happen internally.
+ * emitting [Interaction]s for this chip's "clickable" tap area. You can use this to change the
+ * chip's appearance or preview the chip in different states. Note that if `null` is provided,
+ * interactions will still happen internally.
* @param contentPadding The spacing values to apply internally between the container and the
- * content
+ * content
* @param shape Defines the chip's shape. It is strongly recommended to use the default as this
- * shape is a key characteristic of the Wear Material Theme
+ * shape is a key characteristic of the Wear Material Theme
*/
@Composable
public fun SplitToggleChip(
@@ -251,60 +247,58 @@
clickInteractionSource: MutableInteractionSource? = null,
contentPadding: PaddingValues = ToggleChipDefaults.ContentPadding,
shape: Shape = MaterialTheme.shapes.large,
-) = androidx.wear.compose.materialcore.SplitToggleButton(
- checked = checked,
- onCheckedChange = onCheckedChange,
- label = provideScopeContent(
- contentColor = colors.contentColor(enabled = enabled),
- textStyle = MaterialTheme.typography.button,
- content = label
- ),
- onClick = onClick,
- toggleControl = provideScopeContent(
- contentColor = colors.toggleControlColor(enabled = enabled, checked = checked),
- content = toggleControl
- ),
- selectionControl = null,
- modifier = modifier
- .defaultMinSize(minHeight = ToggleChipDefaults.Height)
- .height(IntrinsicSize.Min),
- secondaryLabel = provideNullableScopeContent(
- contentColor = colors.secondaryContentColor(enabled = enabled),
- textStyle = MaterialTheme.typography.caption2,
- content = secondaryLabel
- ),
- backgroundColor = { isEnabled, _ -> colors.backgroundColor(enabled = isEnabled) },
- splitBackgroundColor = { isEnabled, isChecked ->
- colors.splitBackgroundOverlay(
- enabled = isEnabled,
- checked = isChecked
- )
- },
- enabled = enabled,
- checkedInteractionSource = checkedInteractionSource,
- clickInteractionSource = clickInteractionSource,
- contentPadding = contentPadding,
- shape = shape,
- labelSpacerSize = 0.dp,
- ripple = rippleOrFallbackImplementation()
-)
+) =
+ androidx.wear.compose.materialcore.SplitToggleButton(
+ checked = checked,
+ onCheckedChange = onCheckedChange,
+ label =
+ provideScopeContent(
+ contentColor = colors.contentColor(enabled = enabled),
+ textStyle = MaterialTheme.typography.button,
+ content = label
+ ),
+ onClick = onClick,
+ toggleControl =
+ provideScopeContent(
+ contentColor = colors.toggleControlColor(enabled = enabled, checked = checked),
+ content = toggleControl
+ ),
+ selectionControl = null,
+ modifier =
+ modifier
+ .defaultMinSize(minHeight = ToggleChipDefaults.Height)
+ .height(IntrinsicSize.Min),
+ secondaryLabel =
+ provideNullableScopeContent(
+ contentColor = colors.secondaryContentColor(enabled = enabled),
+ textStyle = MaterialTheme.typography.caption2,
+ content = secondaryLabel
+ ),
+ backgroundColor = { isEnabled, _ -> colors.backgroundColor(enabled = isEnabled) },
+ splitBackgroundColor = { isEnabled, isChecked ->
+ colors.splitBackgroundOverlay(enabled = isEnabled, checked = isChecked)
+ },
+ enabled = enabled,
+ checkedInteractionSource = checkedInteractionSource,
+ clickInteractionSource = clickInteractionSource,
+ contentPadding = contentPadding,
+ shape = shape,
+ labelSpacerSize = 0.dp,
+ ripple = rippleOrFallbackImplementation()
+ )
-/**
- * Represents the background and content colors used in [ToggleChip]s
- * in different states.
- */
+/** Represents the background and content colors used in [ToggleChip]s in different states. */
@Stable
public interface ToggleChipColors {
/**
* Represents the background treatment for this chip, depending on the [enabled] and [checked]
- * properties. Backgrounds are typically a linear gradient when the chip is checked
- * and solid when it is not.
+ * properties. Backgrounds are typically a linear gradient when the chip is checked and solid
+ * when it is not.
*
* @param enabled Whether the chip is enabled
* @param checked Whether the chip is currently checked or unchecked
*/
- @Composable
- public fun background(enabled: Boolean, checked: Boolean): State<Painter>
+ @Composable public fun background(enabled: Boolean, checked: Boolean): State<Painter>
/**
* Represents the content color for this chip, depending on the [enabled] and [checked]
@@ -313,8 +307,7 @@
* @param enabled Whether the chip is enabled
* @param checked Whether the chip is currently checked or unchecked
*/
- @Composable
- public fun contentColor(enabled: Boolean, checked: Boolean): State<Color>
+ @Composable public fun contentColor(enabled: Boolean, checked: Boolean): State<Color>
/**
* Represents the secondary content color for this chip, depending on the [enabled] and
@@ -323,23 +316,19 @@
* @param enabled Whether the chip is enabled
* @param checked Whether the chip is currently checked or unchecked
*/
- @Composable
- public fun secondaryContentColor(enabled: Boolean, checked: Boolean): State<Color>
+ @Composable public fun secondaryContentColor(enabled: Boolean, checked: Boolean): State<Color>
/**
- * Represents the color for the toggle control content for this chip, depending on the
- * [enabled] and [checked] properties.
+ * Represents the color for the toggle control content for this chip, depending on the [enabled]
+ * and [checked] properties.
*
* @param enabled Whether the chip is enabled
* @param checked Whether the chip is currently checked or unchecked
*/
- @Composable
- public fun toggleControlColor(enabled: Boolean, checked: Boolean): State<Color>
+ @Composable public fun toggleControlColor(enabled: Boolean, checked: Boolean): State<Color>
}
-/**
- * Represents the background and content colors used in [SplitToggleChip]s in different states.
- */
+/** Represents the background and content colors used in [SplitToggleChip]s in different states. */
@Stable
public interface SplitToggleChipColors {
/**
@@ -347,89 +336,81 @@
*
* @param enabled Whether the chip is enabled
*/
- @Composable
- public fun backgroundColor(enabled: Boolean): State<Color>
+ @Composable public fun backgroundColor(enabled: Boolean): State<Color>
/**
* Represents the content color for this chip, depending on whether it is [enabled]
*
* @param enabled Whether the chip is enabled
*/
- @Composable
- public fun contentColor(enabled: Boolean): State<Color>
+ @Composable public fun contentColor(enabled: Boolean): State<Color>
/**
* Represents the secondary content color for this chip, depending on whether it is [enabled]
*
* @param enabled Whether the chip is enabled
*/
- @Composable
- public fun secondaryContentColor(enabled: Boolean): State<Color>
+ @Composable public fun secondaryContentColor(enabled: Boolean): State<Color>
/**
- * Represents the color for the toggle control content for this chip, depending on the
- * [enabled] and [checked] properties.
+ * Represents the color for the toggle control content for this chip, depending on the [enabled]
+ * and [checked] properties.
*
* @param enabled Whether the chip is enabled
* @param checked Whether the chip is currently checked or unchecked
*/
- @Composable
- public fun toggleControlColor(enabled: Boolean, checked: Boolean): State<Color>
+ @Composable public fun toggleControlColor(enabled: Boolean, checked: Boolean): State<Color>
/**
- * Represents the overlay to apply to a split background SplitToggleChip to distinguish
- * between the two tappable areas. The overlay will be applied to "lighten" the background of
- * area under the toggle control, depending on the [enabled] and [checked] properties.
+ * Represents the overlay to apply to a split background SplitToggleChip to distinguish between
+ * the two tappable areas. The overlay will be applied to "lighten" the background of area under
+ * the toggle control, depending on the [enabled] and [checked] properties.
*
* @param enabled Whether the chip is enabled
* @param checked Whether the chip is currently checked or unchecked
*/
- @Composable
- public fun splitBackgroundOverlay(enabled: Boolean, checked: Boolean): State<Color>
+ @Composable public fun splitBackgroundOverlay(enabled: Boolean, checked: Boolean): State<Color>
}
-/**
- * Contains the default values used by [ToggleChip]s and [SplitToggleChip]s
- */
+/** Contains the default values used by [ToggleChip]s and [SplitToggleChip]s */
public object ToggleChipDefaults {
/**
- * Creates a [ToggleChipColors] for use in a [ToggleChip].
- * [ToggleChip]s are expected to have a linear gradient background when
- * checked, similar to a [ChipDefaults.gradientBackgroundChipColors] and a solid
- * neutral background when not checked (similar to a
- * [ChipDefaults.secondaryChipColors])
+ * Creates a [ToggleChipColors] for use in a [ToggleChip]. [ToggleChip]s are expected to have a
+ * linear gradient background when checked, similar to a
+ * [ChipDefaults.gradientBackgroundChipColors] and a solid neutral background when not checked
+ * (similar to a [ChipDefaults.secondaryChipColors])
*
* @param checkedStartBackgroundColor The background color used at the start of the gradient of
- * a [ToggleChip] when enabled and checked.
+ * a [ToggleChip] when enabled and checked.
* @param checkedEndBackgroundColor The background color used at the end of the gradient of a
- * [ToggleChip] when enabled and checked.
- * @param checkedContentColor The content color of a [ToggleChip] when enabled and
- * checked.
+ * [ToggleChip] when enabled and checked.
+ * @param checkedContentColor The content color of a [ToggleChip] when enabled and checked.
* @param checkedSecondaryContentColor The secondary content color of this [ToggleChip] when
- * enabled and checked, used for secondaryLabel content
+ * enabled and checked, used for secondaryLabel content
* @param checkedToggleControlColor The toggle control color of this [ToggleChip] when enabled
- * and checked, used for toggleControl content
+ * and checked, used for toggleControl content
* @param uncheckedStartBackgroundColor The background color used at the start of the gradient
- * of a [ToggleChip] when enabled and unchecked.
+ * of a [ToggleChip] when enabled and unchecked.
* @param uncheckedEndBackgroundColor The background color used at the end of the gradient of a
- * [ToggleChip] when enabled and unchecked.
- * @param uncheckedContentColor The content color of a [ToggleChip] when enabled and
- * checked.
+ * [ToggleChip] when enabled and unchecked.
+ * @param uncheckedContentColor The content color of a [ToggleChip] when enabled and checked.
* @param uncheckedSecondaryContentColor The secondary content color of this [ToggleChip] when
- * enabled and unchecked, used for secondaryLabel content
+ * enabled and unchecked, used for secondaryLabel content
* @param uncheckedToggleControlColor The toggle control color of this [ToggleChip] when enabled
- * and unchecked.
+ * and unchecked.
* @param gradientDirection Whether the chips gradient should be start to end (indicated by
- * [LayoutDirection.Ltr]) or end to start (indicated by [LayoutDirection.Rtl]).
+ * [LayoutDirection.Ltr]) or end to start (indicated by [LayoutDirection.Rtl]).
*/
@Composable
public fun toggleChipColors(
checkedStartBackgroundColor: Color =
- MaterialTheme.colors.surface.copy(alpha = 0f)
+ MaterialTheme.colors.surface
+ .copy(alpha = 0f)
.compositeOver(MaterialTheme.colors.surface),
checkedEndBackgroundColor: Color =
- MaterialTheme.colors.primary.copy(alpha = 0.5f)
+ MaterialTheme.colors.primary
+ .copy(alpha = 0.5f)
.compositeOver(MaterialTheme.colors.surface),
checkedContentColor: Color = MaterialTheme.colors.onSurface,
checkedSecondaryContentColor: Color = MaterialTheme.colors.onSurfaceVariant,
@@ -444,44 +425,38 @@
val checkedBackgroundColors: List<Color>
val disabledCheckedBackgroundColors: List<Color>
if (gradientDirection == LayoutDirection.Ltr) {
- checkedBackgroundColors = listOf(
- checkedStartBackgroundColor,
- checkedEndBackgroundColor
- )
- disabledCheckedBackgroundColors = listOf(
- checkedStartBackgroundColor.copy(alpha = ContentAlpha.disabled),
- checkedEndBackgroundColor.copy(alpha = ContentAlpha.disabled)
- )
+ checkedBackgroundColors = listOf(checkedStartBackgroundColor, checkedEndBackgroundColor)
+ disabledCheckedBackgroundColors =
+ listOf(
+ checkedStartBackgroundColor.copy(alpha = ContentAlpha.disabled),
+ checkedEndBackgroundColor.copy(alpha = ContentAlpha.disabled)
+ )
} else {
- checkedBackgroundColors = listOf(
- checkedEndBackgroundColor,
- checkedStartBackgroundColor
- )
- disabledCheckedBackgroundColors = listOf(
- checkedEndBackgroundColor.copy(alpha = ContentAlpha.disabled),
- checkedStartBackgroundColor.copy(alpha = ContentAlpha.disabled),
- )
+ checkedBackgroundColors = listOf(checkedEndBackgroundColor, checkedStartBackgroundColor)
+ disabledCheckedBackgroundColors =
+ listOf(
+ checkedEndBackgroundColor.copy(alpha = ContentAlpha.disabled),
+ checkedStartBackgroundColor.copy(alpha = ContentAlpha.disabled),
+ )
}
val uncheckedBackgroundColors: List<Color>
val disabledUncheckedBackgroundColors: List<Color>
if (gradientDirection == LayoutDirection.Ltr) {
- uncheckedBackgroundColors = listOf(
- uncheckedStartBackgroundColor,
- uncheckedEndBackgroundColor
- )
- disabledUncheckedBackgroundColors = listOf(
- uncheckedStartBackgroundColor.copy(alpha = ContentAlpha.disabled),
- uncheckedEndBackgroundColor.copy(alpha = ContentAlpha.disabled)
- )
+ uncheckedBackgroundColors =
+ listOf(uncheckedStartBackgroundColor, uncheckedEndBackgroundColor)
+ disabledUncheckedBackgroundColors =
+ listOf(
+ uncheckedStartBackgroundColor.copy(alpha = ContentAlpha.disabled),
+ uncheckedEndBackgroundColor.copy(alpha = ContentAlpha.disabled)
+ )
} else {
- uncheckedBackgroundColors = listOf(
- uncheckedEndBackgroundColor,
- uncheckedStartBackgroundColor
- )
- disabledUncheckedBackgroundColors = listOf(
- uncheckedEndBackgroundColor.copy(alpha = ContentAlpha.disabled),
- uncheckedStartBackgroundColor.copy(alpha = ContentAlpha.disabled),
- )
+ uncheckedBackgroundColors =
+ listOf(uncheckedEndBackgroundColor, uncheckedStartBackgroundColor)
+ disabledUncheckedBackgroundColors =
+ listOf(
+ uncheckedEndBackgroundColor.copy(alpha = ContentAlpha.disabled),
+ uncheckedStartBackgroundColor.copy(alpha = ContentAlpha.disabled),
+ )
}
return DefaultToggleChipColors(
@@ -489,34 +464,26 @@
checkedContentColor = checkedContentColor,
checkedSecondaryContentColor = checkedSecondaryContentColor,
checkedIconColor = checkedToggleControlColor,
- uncheckedBackgroundPainter = BrushPainter(
- Brush.linearGradient(uncheckedBackgroundColors)
- ),
+ uncheckedBackgroundPainter =
+ BrushPainter(Brush.linearGradient(uncheckedBackgroundColors)),
uncheckedContentColor = uncheckedContentColor,
uncheckedSecondaryContentColor = uncheckedSecondaryContentColor,
uncheckedIconColor = uncheckedToggleControlColor,
- disabledCheckedBackgroundPainter = BrushPainter(
- Brush.linearGradient(disabledCheckedBackgroundColors)
- ),
+ disabledCheckedBackgroundPainter =
+ BrushPainter(Brush.linearGradient(disabledCheckedBackgroundColors)),
disabledCheckedContentColor = checkedContentColor.copy(alpha = ContentAlpha.disabled),
- disabledCheckedSecondaryContentColor = checkedSecondaryContentColor.copy(
- alpha = ContentAlpha.disabled
- ),
- disabledCheckedIconColor = checkedToggleControlColor.copy(
- alpha = ContentAlpha.disabled
- ),
- disabledUncheckedBackgroundPainter = BrushPainter(
- Brush.linearGradient(disabledUncheckedBackgroundColors)
- ),
- disabledUncheckedContentColor = uncheckedContentColor.copy(
- alpha = ContentAlpha.disabled
- ),
- disabledUncheckedSecondaryContentColor = uncheckedSecondaryContentColor.copy(
- alpha = ContentAlpha.disabled
- ),
- disabledUncheckedIconColor = uncheckedToggleControlColor.copy(
- alpha = ContentAlpha.disabled
- ),
+ disabledCheckedSecondaryContentColor =
+ checkedSecondaryContentColor.copy(alpha = ContentAlpha.disabled),
+ disabledCheckedIconColor =
+ checkedToggleControlColor.copy(alpha = ContentAlpha.disabled),
+ disabledUncheckedBackgroundPainter =
+ BrushPainter(Brush.linearGradient(disabledUncheckedBackgroundColors)),
+ disabledUncheckedContentColor =
+ uncheckedContentColor.copy(alpha = ContentAlpha.disabled),
+ disabledUncheckedSecondaryContentColor =
+ uncheckedSecondaryContentColor.copy(alpha = ContentAlpha.disabled),
+ disabledUncheckedIconColor =
+ uncheckedToggleControlColor.copy(alpha = ContentAlpha.disabled),
)
}
@@ -526,15 +493,15 @@
* @param backgroundColor The background color of this [SplitToggleChip] when enabled
* @param contentColor The content color of this [SplitToggleChip] when enabled.
* @param secondaryContentColor The secondary content color of this[SplitToggleChip] when
- * enabled
+ * enabled
* @param checkedToggleControlColor The toggle control content color of this [SplitToggleChip]
- * when enabled.
+ * when enabled.
* @param uncheckedToggleControlColor The toggle control content color of this [SplitToggleChip]
- * when enabled.
+ * when enabled.
* @param splitBackgroundOverlayColor The color to use to lighten/distinguish the background
- * behind the ToggleControl for a split background chip. A split background chip has two
- * tappable areas, one for the main body of the chip and one for area around the toggle
- * control icon.
+ * behind the ToggleControl for a split background chip. A split background chip has two
+ * tappable areas, one for the main body of the chip and one for area around the toggle
+ * control icon.
*/
@Composable
public fun splitToggleChipColors(
@@ -555,46 +522,40 @@
uncheckedSplitBackgroundOverlay = splitBackgroundOverlayColor,
disabledBackgroundColor = backgroundColor.copy(alpha = ContentAlpha.disabled),
disabledContentColor = contentColor.copy(alpha = ContentAlpha.disabled),
- disabledSecondaryContentColor = secondaryContentColor.copy(
- alpha = ContentAlpha.disabled
- ),
- disabledCheckedIconColor = checkedToggleControlColor.copy(
- alpha = ContentAlpha.disabled
- ),
+ disabledSecondaryContentColor =
+ secondaryContentColor.copy(alpha = ContentAlpha.disabled),
+ disabledCheckedIconColor =
+ checkedToggleControlColor.copy(alpha = ContentAlpha.disabled),
disabledCheckedSplitBackgroundOverlay = splitBackgroundOverlayColor,
- disabledUncheckedIconColor = uncheckedToggleControlColor.copy(
- alpha = ContentAlpha.disabled
- ),
+ disabledUncheckedIconColor =
+ uncheckedToggleControlColor.copy(alpha = ContentAlpha.disabled),
disabledUncheckedSplitBackgroundOverlay = splitBackgroundOverlayColor,
)
}
- /**
- * The Wear Material UX recommended color to use for an unchecked switch icon.
- */
+ /** The Wear Material UX recommended color to use for an unchecked switch icon. */
public val SwitchUncheckedIconColor: Color
@Composable get() = MaterialTheme.colors.onSurface.copy(0.6f)
private val ChipHorizontalPadding = 14.dp
private val ChipVerticalPadding = 6.dp
- /**
- * The default content padding used by [ToggleChip] and [SplitToggleChip]
- */
- public val ContentPadding: PaddingValues = PaddingValues(
- start = ChipHorizontalPadding,
- top = ChipVerticalPadding,
- end = ChipHorizontalPadding,
- bottom = ChipVerticalPadding
- )
+ /** The default content padding used by [ToggleChip] and [SplitToggleChip] */
+ public val ContentPadding: PaddingValues =
+ PaddingValues(
+ start = ChipHorizontalPadding,
+ top = ChipVerticalPadding,
+ end = ChipHorizontalPadding,
+ bottom = ChipVerticalPadding
+ )
/**
* Creates switch style toggle [ImageVector]s for use in the toggleControl slot of a
- * [ToggleChip] or [SplitToggleChip].
- * Depending on [checked] will return either an 'on' (checked) or 'off' (unchecked) switch icon.
+ * [ToggleChip] or [SplitToggleChip]. Depending on [checked] will return either an 'on'
+ * (checked) or 'off' (unchecked) switch icon.
*
* @param checked whether the [ToggleChip] or [SplitToggleChip] is currently 'on' (checked/true)
- * or 'off' (unchecked/false)
+ * or 'off' (unchecked/false)
*/
public fun switchIcon(
checked: Boolean,
@@ -602,12 +563,11 @@
/**
* Creates a radio button style toggle [ImageVector]s for use in the toggleControl slot of a
- * [ToggleChip] or [SplitToggleChip].
- * Depending on [checked] will return either an 'on' (checked) or 'off' (unchecked) radio button
- * icon.
+ * [ToggleChip] or [SplitToggleChip]. Depending on [checked] will return either an 'on'
+ * (checked) or 'off' (unchecked) radio button icon.
*
* @param checked whether the [ToggleChip] or [SplitToggleChip] is currently 'on' (checked/true)
- * or 'off' (unchecked/false)
+ * or 'off' (unchecked/false)
*/
public fun radioIcon(
checked: Boolean,
@@ -615,21 +575,19 @@
/**
* Creates checkbox style toggle [ImageVector]s for use in the toggleControl slot of a
- * [ToggleChip] or [SplitToggleChip].
- * Depending on [checked] will return either an 'on' (ticked/checked) or 'off'
- * (unticked/unchecked) checkbox image.
+ * [ToggleChip] or [SplitToggleChip]. Depending on [checked] will return either an 'on'
+ * (ticked/checked) or 'off' (unticked/unchecked) checkbox image.
*
* @param checked whether the [ToggleChip] or [SplitToggleChip] is currently 'on' (checked/true)
- * or 'off' (unchecked/false)
+ * or 'off' (unchecked/false)
*/
public fun checkboxIcon(
checked: Boolean,
): ImageVector = if (checked) CheckboxOn else CheckboxOff
/**
- * The default height applied for the [ToggleChip] or [SplitToggleChip].
- * Note that you can override it by applying Modifier.heightIn directly on [ToggleChip] or
- * [SplitToggleChip].
+ * The default height applied for the [ToggleChip] or [SplitToggleChip]. Note that you can
+ * override it by applying Modifier.heightIn directly on [ToggleChip] or [SplitToggleChip].
*/
public val Height = 52.dp
@@ -644,28 +602,29 @@
if (_switchOn != null) {
return _switchOn!!
}
- _switchOn = materialIcon(name = "SwitchOn") {
- materialPath(fillAlpha = 0.38f, strokeAlpha = 0.38f) {
- moveTo(5.0f, 7.0f)
- lineTo(19.0f, 7.0f)
- arcTo(5.0f, 5.0f, 0.0f, false, true, 24.0f, 12.0f)
- lineTo(24.0f, 12.0f)
- arcTo(5.0f, 5.0f, 0.0f, false, true, 19.0f, 17.0f)
- lineTo(5.0f, 17.0f)
- arcTo(5.0f, 5.0f, 0.0f, false, true, 0.0f, 12.0f)
- lineTo(0.0f, 12.0f)
- arcTo(5.0f, 5.0f, 0.0f, false, true, 5.0f, 7.0f)
- close()
+ _switchOn =
+ materialIcon(name = "SwitchOn") {
+ materialPath(fillAlpha = 0.38f, strokeAlpha = 0.38f) {
+ moveTo(5.0f, 7.0f)
+ lineTo(19.0f, 7.0f)
+ arcTo(5.0f, 5.0f, 0.0f, false, true, 24.0f, 12.0f)
+ lineTo(24.0f, 12.0f)
+ arcTo(5.0f, 5.0f, 0.0f, false, true, 19.0f, 17.0f)
+ lineTo(5.0f, 17.0f)
+ arcTo(5.0f, 5.0f, 0.0f, false, true, 0.0f, 12.0f)
+ lineTo(0.0f, 12.0f)
+ arcTo(5.0f, 5.0f, 0.0f, false, true, 5.0f, 7.0f)
+ close()
+ }
+ materialPath(pathFillType = PathFillType.EvenOdd) {
+ moveTo(17.0f, 19.0f)
+ curveTo(20.866f, 19.0f, 24.0f, 15.866f, 24.0f, 12.0f)
+ curveTo(24.0f, 8.134f, 20.866f, 5.0f, 17.0f, 5.0f)
+ curveTo(13.134f, 5.0f, 10.0f, 8.134f, 10.0f, 12.0f)
+ curveTo(10.0f, 15.866f, 13.134f, 19.0f, 17.0f, 19.0f)
+ close()
+ }
}
- materialPath(pathFillType = PathFillType.EvenOdd) {
- moveTo(17.0f, 19.0f)
- curveTo(20.866f, 19.0f, 24.0f, 15.866f, 24.0f, 12.0f)
- curveTo(24.0f, 8.134f, 20.866f, 5.0f, 17.0f, 5.0f)
- curveTo(13.134f, 5.0f, 10.0f, 8.134f, 10.0f, 12.0f)
- curveTo(10.0f, 15.866f, 13.134f, 19.0f, 17.0f, 19.0f)
- close()
- }
- }
return _switchOn!!
}
@@ -676,28 +635,29 @@
if (_switchOff != null) {
return _switchOff!!
}
- _switchOff = materialIcon(name = "SwitchOff") {
- materialPath(fillAlpha = 0.38f, strokeAlpha = 0.38f) {
- moveTo(5.0f, 7.0f)
- lineTo(19.0f, 7.0f)
- arcTo(5.0f, 5.0f, 0.0f, false, true, 24.0f, 12.0f)
- lineTo(24.0f, 12.0f)
- arcTo(5.0f, 5.0f, 0.0f, false, true, 19.0f, 17.0f)
- lineTo(5.0f, 17.0f)
- arcTo(5.0f, 5.0f, 0.0f, false, true, 0.0f, 12.0f)
- lineTo(0.0f, 12.0f)
- arcTo(5.0f, 5.0f, 0.0f, false, true, 5.0f, 7.0f)
- close()
+ _switchOff =
+ materialIcon(name = "SwitchOff") {
+ materialPath(fillAlpha = 0.38f, strokeAlpha = 0.38f) {
+ moveTo(5.0f, 7.0f)
+ lineTo(19.0f, 7.0f)
+ arcTo(5.0f, 5.0f, 0.0f, false, true, 24.0f, 12.0f)
+ lineTo(24.0f, 12.0f)
+ arcTo(5.0f, 5.0f, 0.0f, false, true, 19.0f, 17.0f)
+ lineTo(5.0f, 17.0f)
+ arcTo(5.0f, 5.0f, 0.0f, false, true, 0.0f, 12.0f)
+ lineTo(0.0f, 12.0f)
+ arcTo(5.0f, 5.0f, 0.0f, false, true, 5.0f, 7.0f)
+ close()
+ }
+ materialPath(pathFillType = PathFillType.EvenOdd) {
+ moveTo(7.0f, 19.0f)
+ curveTo(10.866f, 19.0f, 14.0f, 15.866f, 14.0f, 12.0f)
+ curveTo(14.0f, 8.134f, 10.866f, 5.0f, 7.0f, 5.0f)
+ curveTo(3.134f, 5.0f, 0.0f, 8.134f, 0.0f, 12.0f)
+ curveTo(0.0f, 15.866f, 3.134f, 19.0f, 7.0f, 19.0f)
+ close()
+ }
}
- materialPath(pathFillType = PathFillType.EvenOdd) {
- moveTo(7.0f, 19.0f)
- curveTo(10.866f, 19.0f, 14.0f, 15.866f, 14.0f, 12.0f)
- curveTo(14.0f, 8.134f, 10.866f, 5.0f, 7.0f, 5.0f)
- curveTo(3.134f, 5.0f, 0.0f, 8.134f, 0.0f, 12.0f)
- curveTo(0.0f, 15.866f, 3.134f, 19.0f, 7.0f, 19.0f)
- close()
- }
- }
return _switchOff!!
}
@@ -708,28 +668,29 @@
if (_radioOn != null) {
return _radioOn!!
}
- _radioOn = materialIcon(name = "RadioOn") {
- materialPath {
- moveTo(12.0f, 2.0f)
- curveTo(6.48f, 2.0f, 2.0f, 6.48f, 2.0f, 12.0f)
- curveTo(2.0f, 17.52f, 6.48f, 22.0f, 12.0f, 22.0f)
- curveTo(17.52f, 22.0f, 22.0f, 17.52f, 22.0f, 12.0f)
- curveTo(22.0f, 6.48f, 17.52f, 2.0f, 12.0f, 2.0f)
- close()
- moveTo(12.0f, 20.0f)
- curveTo(7.58f, 20.0f, 4.0f, 16.42f, 4.0f, 12.0f)
- curveTo(4.0f, 7.58f, 7.58f, 4.0f, 12.0f, 4.0f)
- curveTo(16.42f, 4.0f, 20.0f, 7.58f, 20.0f, 12.0f)
- curveTo(20.0f, 16.42f, 16.42f, 20.0f, 12.0f, 20.0f)
- close()
+ _radioOn =
+ materialIcon(name = "RadioOn") {
+ materialPath {
+ moveTo(12.0f, 2.0f)
+ curveTo(6.48f, 2.0f, 2.0f, 6.48f, 2.0f, 12.0f)
+ curveTo(2.0f, 17.52f, 6.48f, 22.0f, 12.0f, 22.0f)
+ curveTo(17.52f, 22.0f, 22.0f, 17.52f, 22.0f, 12.0f)
+ curveTo(22.0f, 6.48f, 17.52f, 2.0f, 12.0f, 2.0f)
+ close()
+ moveTo(12.0f, 20.0f)
+ curveTo(7.58f, 20.0f, 4.0f, 16.42f, 4.0f, 12.0f)
+ curveTo(4.0f, 7.58f, 7.58f, 4.0f, 12.0f, 4.0f)
+ curveTo(16.42f, 4.0f, 20.0f, 7.58f, 20.0f, 12.0f)
+ curveTo(20.0f, 16.42f, 16.42f, 20.0f, 12.0f, 20.0f)
+ close()
+ }
+ materialPath {
+ moveTo(12.0f, 12.0f)
+ moveToRelative(-5.0f, 0.0f)
+ arcToRelative(5.0f, 5.0f, 0.0f, true, true, 10.0f, 0.0f)
+ arcToRelative(5.0f, 5.0f, 0.0f, true, true, -10.0f, 0.0f)
+ }
}
- materialPath {
- moveTo(12.0f, 12.0f)
- moveToRelative(-5.0f, 0.0f)
- arcToRelative(5.0f, 5.0f, 0.0f, true, true, 10.0f, 0.0f)
- arcToRelative(5.0f, 5.0f, 0.0f, true, true, -10.0f, 0.0f)
- }
- }
return _radioOn!!
}
@@ -740,22 +701,23 @@
if (_radioOff != null) {
return _radioOff!!
}
- _radioOff = materialIcon(name = "RadioOff") {
- materialPath {
- moveTo(12.0f, 2.0f)
- curveTo(6.48f, 2.0f, 2.0f, 6.48f, 2.0f, 12.0f)
- curveTo(2.0f, 17.52f, 6.48f, 22.0f, 12.0f, 22.0f)
- curveTo(17.52f, 22.0f, 22.0f, 17.52f, 22.0f, 12.0f)
- curveTo(22.0f, 6.48f, 17.52f, 2.0f, 12.0f, 2.0f)
- close()
- moveTo(12.0f, 20.0f)
- curveTo(7.58f, 20.0f, 4.0f, 16.42f, 4.0f, 12.0f)
- curveTo(4.0f, 7.58f, 7.58f, 4.0f, 12.0f, 4.0f)
- curveTo(16.42f, 4.0f, 20.0f, 7.58f, 20.0f, 12.0f)
- curveTo(20.0f, 16.42f, 16.42f, 20.0f, 12.0f, 20.0f)
- close()
+ _radioOff =
+ materialIcon(name = "RadioOff") {
+ materialPath {
+ moveTo(12.0f, 2.0f)
+ curveTo(6.48f, 2.0f, 2.0f, 6.48f, 2.0f, 12.0f)
+ curveTo(2.0f, 17.52f, 6.48f, 22.0f, 12.0f, 22.0f)
+ curveTo(17.52f, 22.0f, 22.0f, 17.52f, 22.0f, 12.0f)
+ curveTo(22.0f, 6.48f, 17.52f, 2.0f, 12.0f, 2.0f)
+ close()
+ moveTo(12.0f, 20.0f)
+ curveTo(7.58f, 20.0f, 4.0f, 16.42f, 4.0f, 12.0f)
+ curveTo(4.0f, 7.58f, 7.58f, 4.0f, 12.0f, 4.0f)
+ curveTo(16.42f, 4.0f, 20.0f, 7.58f, 20.0f, 12.0f)
+ curveTo(20.0f, 16.42f, 16.42f, 20.0f, 12.0f, 20.0f)
+ close()
+ }
}
- }
return _radioOff!!
}
@@ -766,35 +728,36 @@
if (_checkboxOn != null) {
return _checkboxOn!!
}
- _checkboxOn = materialIcon(name = "CheckboxOn") {
- materialPath {
- moveTo(19.0f, 3.0f)
- horizontalLineTo(5.0f)
- curveTo(3.9f, 3.0f, 3.0f, 3.9f, 3.0f, 5.0f)
- verticalLineTo(19.0f)
- curveTo(3.0f, 20.1f, 3.9f, 21.0f, 5.0f, 21.0f)
- horizontalLineTo(19.0f)
- curveTo(20.1f, 21.0f, 21.0f, 20.1f, 21.0f, 19.0f)
- verticalLineTo(5.0f)
- curveTo(21.0f, 3.9f, 20.1f, 3.0f, 19.0f, 3.0f)
- close()
- moveTo(19.0f, 19.0f)
- horizontalLineTo(5.0f)
- verticalLineTo(5.0f)
- horizontalLineTo(19.0f)
- verticalLineTo(19.0f)
- close()
- moveTo(18.0f, 9.0f)
- lineTo(16.6f, 7.6f)
- lineTo(13.3f, 10.9f)
- lineTo(10.0f, 14.2f)
- lineTo(7.4f, 11.6f)
- lineTo(6.0f, 13.0f)
- lineTo(10.0f, 17.0f)
- lineTo(18.0f, 9.0f)
- close()
+ _checkboxOn =
+ materialIcon(name = "CheckboxOn") {
+ materialPath {
+ moveTo(19.0f, 3.0f)
+ horizontalLineTo(5.0f)
+ curveTo(3.9f, 3.0f, 3.0f, 3.9f, 3.0f, 5.0f)
+ verticalLineTo(19.0f)
+ curveTo(3.0f, 20.1f, 3.9f, 21.0f, 5.0f, 21.0f)
+ horizontalLineTo(19.0f)
+ curveTo(20.1f, 21.0f, 21.0f, 20.1f, 21.0f, 19.0f)
+ verticalLineTo(5.0f)
+ curveTo(21.0f, 3.9f, 20.1f, 3.0f, 19.0f, 3.0f)
+ close()
+ moveTo(19.0f, 19.0f)
+ horizontalLineTo(5.0f)
+ verticalLineTo(5.0f)
+ horizontalLineTo(19.0f)
+ verticalLineTo(19.0f)
+ close()
+ moveTo(18.0f, 9.0f)
+ lineTo(16.6f, 7.6f)
+ lineTo(13.3f, 10.9f)
+ lineTo(10.0f, 14.2f)
+ lineTo(7.4f, 11.6f)
+ lineTo(6.0f, 13.0f)
+ lineTo(10.0f, 17.0f)
+ lineTo(18.0f, 9.0f)
+ close()
+ }
}
- }
return _checkboxOn!!
}
@@ -805,35 +768,34 @@
if (_checkboxOff != null) {
return _checkboxOff!!
}
- _checkboxOff = materialIcon(name = "CheckboxOff") {
- materialPath {
- moveTo(19.0f, 5.0f)
- verticalLineTo(19.0f)
- horizontalLineTo(5.0f)
- verticalLineTo(5.0f)
- horizontalLineTo(19.0f)
- close()
- moveTo(19.0f, 3.0f)
- horizontalLineTo(5.0f)
- curveTo(3.9f, 3.0f, 3.0f, 3.9f, 3.0f, 5.0f)
- verticalLineTo(19.0f)
- curveTo(3.0f, 20.1f, 3.9f, 21.0f, 5.0f, 21.0f)
- horizontalLineTo(19.0f)
- curveTo(20.1f, 21.0f, 21.0f, 20.1f, 21.0f, 19.0f)
- verticalLineTo(5.0f)
- curveTo(21.0f, 3.9f, 20.1f, 3.0f, 19.0f, 3.0f)
- close()
+ _checkboxOff =
+ materialIcon(name = "CheckboxOff") {
+ materialPath {
+ moveTo(19.0f, 5.0f)
+ verticalLineTo(19.0f)
+ horizontalLineTo(5.0f)
+ verticalLineTo(5.0f)
+ horizontalLineTo(19.0f)
+ close()
+ moveTo(19.0f, 3.0f)
+ horizontalLineTo(5.0f)
+ curveTo(3.9f, 3.0f, 3.0f, 3.9f, 3.0f, 5.0f)
+ verticalLineTo(19.0f)
+ curveTo(3.0f, 20.1f, 3.9f, 21.0f, 5.0f, 21.0f)
+ horizontalLineTo(19.0f)
+ curveTo(20.1f, 21.0f, 21.0f, 20.1f, 21.0f, 19.0f)
+ verticalLineTo(5.0f)
+ curveTo(21.0f, 3.9f, 20.1f, 3.0f, 19.0f, 3.0f)
+ close()
+ }
}
- }
return _checkboxOff!!
}
private var _checkboxOff: ImageVector? = null
}
-/**
- * Default [ToggleChipColors] implementation.
- */
+/** Default [ToggleChipColors] implementation. */
@Immutable
private class DefaultToggleChipColors(
private val checkedBackgroundPainter: Painter,
@@ -860,8 +822,8 @@
if (enabled) {
if (checked) checkedBackgroundPainter else uncheckedBackgroundPainter
} else {
- if (checked) disabledCheckedBackgroundPainter else
- disabledUncheckedBackgroundPainter
+ if (checked) disabledCheckedBackgroundPainter
+ else disabledUncheckedBackgroundPainter
}
)
}
@@ -883,8 +845,8 @@
if (enabled) {
if (checked) checkedSecondaryContentColor else uncheckedSecondaryContentColor
} else {
- if (checked) disabledCheckedSecondaryContentColor else
- disabledUncheckedSecondaryContentColor
+ if (checked) disabledCheckedSecondaryContentColor
+ else disabledUncheckedSecondaryContentColor
}
)
}
@@ -918,17 +880,14 @@
if (disabledCheckedBackgroundPainter != other.disabledCheckedBackgroundPainter) return false
if (disabledCheckedContentColor != other.disabledCheckedContentColor) return false
if (disabledCheckedIconColor != other.disabledCheckedIconColor) return false
- if (disabledCheckedSecondaryContentColor !=
- other.disabledCheckedSecondaryContentColor
- ) return false
- if (disabledUncheckedBackgroundPainter !=
- other.disabledUncheckedBackgroundPainter
- ) return false
+ if (disabledCheckedSecondaryContentColor != other.disabledCheckedSecondaryContentColor)
+ return false
+ if (disabledUncheckedBackgroundPainter != other.disabledUncheckedBackgroundPainter)
+ return false
if (disabledUncheckedContentColor != other.disabledUncheckedContentColor) return false
if (disabledUncheckedIconColor != other.disabledUncheckedIconColor) return false
- if (disabledUncheckedSecondaryContentColor !=
- other.disabledUncheckedSecondaryContentColor
- ) return false
+ if (disabledUncheckedSecondaryContentColor != other.disabledUncheckedSecondaryContentColor)
+ return false
return true
}
@@ -954,9 +913,7 @@
}
}
-/**
- * Default [SplitToggleChipColors] implementation.
- */
+/** Default [SplitToggleChipColors] implementation. */
@Immutable
private class DefaultSplitToggleChipColors(
private val backgroundColor: Color,
@@ -977,16 +934,12 @@
@Composable
override fun backgroundColor(enabled: Boolean): State<Color> {
- return rememberUpdatedState(
- if (enabled) backgroundColor else disabledBackgroundColor
- )
+ return rememberUpdatedState(if (enabled) backgroundColor else disabledBackgroundColor)
}
@Composable
override fun contentColor(enabled: Boolean): State<Color> {
- return rememberUpdatedState(
- if (enabled) contentColor else disabledContentColor
- )
+ return rememberUpdatedState(if (enabled) contentColor else disabledContentColor)
}
@Composable
@@ -1013,8 +966,8 @@
if (enabled) {
if (checked) checkedSplitBackgroundOverlay else uncheckedSplitBackgroundOverlay
} else {
- if (checked) disabledCheckedSplitBackgroundOverlay else
- disabledUncheckedSplitBackgroundOverlay
+ if (checked) disabledCheckedSplitBackgroundOverlay
+ else disabledUncheckedSplitBackgroundOverlay
}
)
}
@@ -1036,13 +989,13 @@
if (disabledContentColor != other.disabledContentColor) return false
if (disabledCheckedIconColor != other.disabledCheckedIconColor) return false
if (disabledSecondaryContentColor != other.disabledSecondaryContentColor) return false
- if (disabledCheckedSplitBackgroundOverlay !=
- other.disabledCheckedSplitBackgroundOverlay
- ) return false
+ if (disabledCheckedSplitBackgroundOverlay != other.disabledCheckedSplitBackgroundOverlay)
+ return false
if (disabledUncheckedIconColor != other.disabledUncheckedIconColor) return false
- if (disabledUncheckedSplitBackgroundOverlay !=
- other.disabledUncheckedSplitBackgroundOverlay
- ) return false
+ if (
+ disabledUncheckedSplitBackgroundOverlay != other.disabledUncheckedSplitBackgroundOverlay
+ )
+ return false
return true
}
diff --git a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/ToggleControl.kt b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/ToggleControl.kt
index 07d80b9..6b12942 100644
--- a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/ToggleControl.kt
+++ b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/ToggleControl.kt
@@ -38,25 +38,25 @@
import androidx.wear.compose.materialcore.animateSelectionColor
/**
- * [Checkbox] provides an animated checkbox for use as a toggle control in
- * [ToggleChip] or [SplitToggleChip].
+ * [Checkbox] provides an animated checkbox for use as a toggle control in [ToggleChip] or
+ * [SplitToggleChip].
*
* Example of a [SplitToggleChip] with [Checkbox] toggle control:
+ *
* @sample androidx.wear.compose.material.samples.SplitToggleChipWithCheckbox
*
* @param checked Boolean flag indicating whether this checkbox is currently checked.
- * @param modifier Modifier to be applied to the checkbox. This can be used to provide a
- * content description for accessibility.
+ * @param modifier Modifier to be applied to the checkbox. This can be used to provide a content
+ * description for accessibility.
* @param colors [CheckboxColors] from which the box and checkmark colors will be obtained.
- * @param enabled Boolean flag indicating the enabled state of the [Checkbox] (affects
- * the color).
+ * @param enabled Boolean flag indicating the enabled state of the [Checkbox] (affects the color).
* @param onCheckedChange Callback to be invoked when Checkbox is clicked. If null, then this is
- * passive and relies entirely on a higher-level component to control the state
- * (such as [ToggleChip] or [SplitToggleChip]).
+ * passive and relies entirely on a higher-level component to control the state (such as
+ * [ToggleChip] or [SplitToggleChip]).
* @param interactionSource When also providing [onCheckedChange], an optional hoisted
- * [MutableInteractionSource] for observing and emitting [Interaction]s for this checkbox.
- * You can use this to change the checkbox's appearance or preview the checkbox in different states.
- * Note that if `null` is provided, interactions will still happen internally.
+ * [MutableInteractionSource] for observing and emitting [Interaction]s for this checkbox. You can
+ * use this to change the checkbox's appearance or preview the checkbox in different states. Note
+ * that if `null` is provided, interactions will still happen internally.
*/
@Composable
public fun Checkbox(
@@ -66,51 +66,46 @@
enabled: Boolean = true,
onCheckedChange: ((Boolean) -> Unit)? = null,
interactionSource: MutableInteractionSource? = null,
-) = androidx.wear.compose.materialcore.Checkbox(
- checked = checked,
- modifier = modifier,
- boxColor = { isEnabled, isChecked ->
- colors.boxColor(
- enabled = isEnabled,
- checked = isChecked
- )
- },
- checkmarkColor = { isEnabled, isChecked ->
- colors.checkmarkColor(
- enabled = isEnabled,
- checked = isChecked
- )
- },
- enabled = enabled,
- onCheckedChange = onCheckedChange,
- interactionSource = interactionSource,
- drawBox = { drawScope, color, _, _ -> drawScope.drawBox(color) },
- progressAnimationSpec = PROGRESS_ANIMATION_SPEC,
- width = WIDTH,
- height = HEIGHT,
- ripple = rippleOrFallbackImplementation()
-)
+) =
+ androidx.wear.compose.materialcore.Checkbox(
+ checked = checked,
+ modifier = modifier,
+ boxColor = { isEnabled, isChecked ->
+ colors.boxColor(enabled = isEnabled, checked = isChecked)
+ },
+ checkmarkColor = { isEnabled, isChecked ->
+ colors.checkmarkColor(enabled = isEnabled, checked = isChecked)
+ },
+ enabled = enabled,
+ onCheckedChange = onCheckedChange,
+ interactionSource = interactionSource,
+ drawBox = { drawScope, color, _, _ -> drawScope.drawBox(color) },
+ progressAnimationSpec = PROGRESS_ANIMATION_SPEC,
+ width = WIDTH,
+ height = HEIGHT,
+ ripple = rippleOrFallbackImplementation()
+ )
/**
- * [Switch] provides an animated switch for use as a toggle control in
- * [ToggleChip] or [SplitToggleChip].
+ * [Switch] provides an animated switch for use as a toggle control in [ToggleChip] or
+ * [SplitToggleChip].
*
* Example of a [ToggleChip] with [Switch] toggle control:
+ *
* @sample androidx.wear.compose.material.samples.ToggleChipWithSwitch
*
* @param checked Boolean flag indicating whether this switch is currently toggled on.
- * @param modifier Modifier to be applied to the switch. This can be used to provide a
- * content description for accessibility.
+ * @param modifier Modifier to be applied to the switch. This can be used to provide a content
+ * description for accessibility.
* @param colors [SwitchColors] from which the colors of the thumb and track will be obtained.
- * @param enabled Boolean flag indicating the enabled state of the [Switch] (affects
- * the color).
+ * @param enabled Boolean flag indicating the enabled state of the [Switch] (affects the color).
* @param onCheckedChange Callback to be invoked when Switch is clicked. If null, then this is
- * passive and relies entirely on a higher-level component to control the state
- * (such as [ToggleChip] or [SplitToggleChip]).
+ * passive and relies entirely on a higher-level component to control the state (such as
+ * [ToggleChip] or [SplitToggleChip]).
* @param interactionSource When also providing [onCheckedChange], an optional hoisted
- * [MutableInteractionSource] for observing and emitting [Interaction]s for this switch.
- * You can use this to change the switch's appearance or preview the switch in different states.
- * Note that if `null` is provided, interactions will still happen internally.
+ * [MutableInteractionSource] for observing and emitting [Interaction]s for this switch. You can
+ * use this to change the switch's appearance or preview the switch in different states. Note that
+ * if `null` is provided, interactions will still happen internally.
*/
@Composable
public fun Switch(
@@ -120,67 +115,57 @@
enabled: Boolean = true,
onCheckedChange: ((Boolean) -> Unit)? = null,
interactionSource: MutableInteractionSource? = null,
-) = androidx.wear.compose.materialcore.Switch(
- modifier = modifier,
- checked = checked,
- enabled = enabled,
- onCheckedChange = onCheckedChange,
- interactionSource = interactionSource,
- trackFillColor = { isEnabled, isChecked ->
- colors.trackColor(
- enabled = isEnabled,
- checked = isChecked
- )
- },
- trackStrokeColor = { isEnabled, isChecked ->
- colors.trackColor(
- enabled = isEnabled,
- checked = isChecked
- )
- },
- thumbColor = { isEnabled, isChecked ->
- colors.thumbColor(
- enabled = isEnabled,
- checked = isChecked
- )
- },
- thumbIconColor = { isEnabled, isChecked ->
- colors.thumbColor(
- enabled = isEnabled,
- checked = isChecked
- )
- },
- trackWidth = SWITCH_TRACK_LENGTH,
- trackHeight = SWITCH_TRACK_HEIGHT,
- drawThumb = { drawScope, color, progress, _, isRtl ->
- drawScope.drawThumb(color = color, progress = progress, isRtl = isRtl)
- },
- progressAnimationSpec = PROGRESS_ANIMATION_SPEC,
- width = WIDTH,
- height = HEIGHT,
- ripple = rippleOrFallbackImplementation()
-)
+) =
+ androidx.wear.compose.materialcore.Switch(
+ modifier = modifier,
+ checked = checked,
+ enabled = enabled,
+ onCheckedChange = onCheckedChange,
+ interactionSource = interactionSource,
+ trackFillColor = { isEnabled, isChecked ->
+ colors.trackColor(enabled = isEnabled, checked = isChecked)
+ },
+ trackStrokeColor = { isEnabled, isChecked ->
+ colors.trackColor(enabled = isEnabled, checked = isChecked)
+ },
+ thumbColor = { isEnabled, isChecked ->
+ colors.thumbColor(enabled = isEnabled, checked = isChecked)
+ },
+ thumbIconColor = { isEnabled, isChecked ->
+ colors.thumbColor(enabled = isEnabled, checked = isChecked)
+ },
+ trackWidth = SWITCH_TRACK_LENGTH,
+ trackHeight = SWITCH_TRACK_HEIGHT,
+ drawThumb = { drawScope, color, progress, _, isRtl ->
+ drawScope.drawThumb(color = color, progress = progress, isRtl = isRtl)
+ },
+ progressAnimationSpec = PROGRESS_ANIMATION_SPEC,
+ width = WIDTH,
+ height = HEIGHT,
+ ripple = rippleOrFallbackImplementation()
+ )
/**
- * [RadioButton] provides an animated radio button for use as a toggle control in
- * [ToggleChip] or [SplitToggleChip].
+ * [RadioButton] provides an animated radio button for use as a toggle control in [ToggleChip] or
+ * [SplitToggleChip].
*
* Example of a [ToggleChip] with [RadioButton] toggle control:
+ *
* @sample androidx.wear.compose.material.samples.SelectableChipWithRadioButton
*
* @param selected Boolean flag indicating whether this radio button is currently toggled on.
- * @param modifier Modifier to be applied to the radio button. This can be used to provide a
- * content description for accessibility.
+ * @param modifier Modifier to be applied to the radio button. This can be used to provide a content
+ * description for accessibility.
* @param colors [ToggleChipColors] from which the toggleControlColors will be obtained.
- * @param enabled Boolean flag indicating the enabled state of the [RadioButton] (affects
- * the color).
- * @param onClick Callback to be invoked when RadioButton is clicked. If null, then this is
- * passive and relies entirely on a higher-level component to control the state
- * (such as [ToggleChip] or [SplitToggleChip]).
+ * @param enabled Boolean flag indicating the enabled state of the [RadioButton] (affects the
+ * color).
+ * @param onClick Callback to be invoked when RadioButton is clicked. If null, then this is passive
+ * and relies entirely on a higher-level component to control the state (such as [ToggleChip] or
+ * [SplitToggleChip]).
* @param interactionSource When also providing [onClick], an optional hoisted
- * [MutableInteractionSource] for observing and emitting [Interaction]s for this radio button.
- * You can use this to change the radio button's appearance or preview the radio button in
- * different states. Note that if `null` is provided, interactions will still happen internally.
+ * [MutableInteractionSource] for observing and emitting [Interaction]s for this radio button. You
+ * can use this to change the radio button's appearance or preview the radio button in different
+ * states. Note that if `null` is provided, interactions will still happen internally.
*/
@Composable
public fun RadioButton(
@@ -190,36 +175,29 @@
enabled: Boolean = true,
onClick: (() -> Unit)? = null,
interactionSource: MutableInteractionSource? = null,
-) = androidx.wear.compose.materialcore.RadioButton(
- modifier = modifier,
- selected = selected,
- enabled = enabled,
- ringColor = { isEnabled, isSelected ->
- colors.ringColor(
- enabled = isEnabled,
- selected = isSelected
- )
- },
- dotColor = { isEnabled, isSelected ->
- colors.dotColor(
- enabled = isEnabled,
- selected = isSelected
- )
- },
- onClick = onClick,
- interactionSource = interactionSource,
- dotRadiusProgressDuration = { isSelected -> if (isSelected) QUICK else RAPID },
- dotAlphaProgressDuration = RAPID,
- dotAlphaProgressDelay = FLASH,
- easing = STANDARD_IN,
- width = WIDTH,
- height = HEIGHT,
- ripple = rippleOrFallbackImplementation()
-)
+) =
+ androidx.wear.compose.materialcore.RadioButton(
+ modifier = modifier,
+ selected = selected,
+ enabled = enabled,
+ ringColor = { isEnabled, isSelected ->
+ colors.ringColor(enabled = isEnabled, selected = isSelected)
+ },
+ dotColor = { isEnabled, isSelected ->
+ colors.dotColor(enabled = isEnabled, selected = isSelected)
+ },
+ onClick = onClick,
+ interactionSource = interactionSource,
+ dotRadiusProgressDuration = { isSelected -> if (isSelected) QUICK else RAPID },
+ dotAlphaProgressDuration = RAPID,
+ dotAlphaProgressDelay = FLASH,
+ easing = STANDARD_IN,
+ width = WIDTH,
+ height = HEIGHT,
+ ripple = rippleOrFallbackImplementation()
+ )
-/**
- * Represents the content colors used in [Checkbox] in different states.
- */
+/** Represents the content colors used in [Checkbox] in different states. */
@Stable
public interface CheckboxColors {
/**
@@ -229,8 +207,7 @@
* @param enabled Whether the [Checkbox] is enabled
* @param checked Whether the [Checkbox] is currently checked or unchecked
*/
- @Composable
- public fun boxColor(enabled: Boolean, checked: Boolean): State<Color>
+ @Composable public fun boxColor(enabled: Boolean, checked: Boolean): State<Color>
/**
* Represents the checkmark color for this [Checkbox], depending on the [enabled] and [checked]
@@ -239,13 +216,10 @@
* @param enabled Whether the [Checkbox] is enabled
* @param checked Whether the [Checkbox] is currently checked or unchecked
*/
- @Composable
- public fun checkmarkColor(enabled: Boolean, checked: Boolean): State<Color>
+ @Composable public fun checkmarkColor(enabled: Boolean, checked: Boolean): State<Color>
}
-/**
- * Represents the content colors used in [Switch] in different states.
- */
+/** Represents the content colors used in [Switch] in different states. */
@Stable
public interface SwitchColors {
/**
@@ -255,8 +229,7 @@
* @param enabled Whether the [Switch] is enabled
* @param checked Whether the [Switch] is currently checked or unchecked
*/
- @Composable
- public fun thumbColor(enabled: Boolean, checked: Boolean): State<Color>
+ @Composable public fun thumbColor(enabled: Boolean, checked: Boolean): State<Color>
/**
* Represents the track color for this [Switch], depending on the [enabled] and [checked]
@@ -265,58 +238,53 @@
* @param enabled Whether the [Switch] is enabled
* @param checked Whether the [Switch] is currently checked or unchecked
*/
- @Composable
- public fun trackColor(enabled: Boolean, checked: Boolean): State<Color>
+ @Composable public fun trackColor(enabled: Boolean, checked: Boolean): State<Color>
}
-/**
- * Represents the content colors used in [RadioButton] in different states.
- */
+/** Represents the content colors used in [RadioButton] in different states. */
@Stable
public interface RadioButtonColors {
/**
- * Represents the outer ring color for this [RadioButton], depending on
- * the [enabled] and [selected] properties.
+ * Represents the outer ring color for this [RadioButton], depending on the [enabled] and
+ * [selected] properties.
*
* @param enabled Whether the [RadioButton] is enabled
* @param selected Whether the [RadioButton] is currently selected or unselected
*/
- @Composable
- public fun ringColor(enabled: Boolean, selected: Boolean): State<Color>
+ @Composable public fun ringColor(enabled: Boolean, selected: Boolean): State<Color>
/**
- * Represents the inner dot color for this [RadioButton], depending on
- * the [enabled] and [selected] properties.
+ * Represents the inner dot color for this [RadioButton], depending on the [enabled] and
+ * [selected] properties.
*
* @param enabled Whether the [RadioButton] is enabled
* @param selected Whether the [RadioButton] is currently selected or unselected
*/
- @Composable
- public fun dotColor(enabled: Boolean, selected: Boolean): State<Color>
+ @Composable public fun dotColor(enabled: Boolean, selected: Boolean): State<Color>
}
-/**
- * Contains the default values used by [Checkbox].
- */
+/** Contains the default values used by [Checkbox]. */
public object CheckboxDefaults {
/**
* Creates a [CheckboxColors] for use in a [Checkbox].
*
* @param checkedBoxColor The box color of this [Checkbox] when enabled and checked.
* @param uncheckedBoxColor The box color of this [Checkbox] when enabled and unchecked.
- * @param checkedCheckmarkColor The check mark color of this [Checkbox] when enabled
- * and checked.
- * @param uncheckedCheckmarkColor The check mark color of this [Checkbox] when enabled
- * and unchecked.
+ * @param checkedCheckmarkColor The check mark color of this [Checkbox] when enabled and
+ * checked.
+ * @param uncheckedCheckmarkColor The check mark color of this [Checkbox] when enabled and
+ * unchecked.
*/
@Composable
public fun colors(
checkedBoxColor: Color = MaterialTheme.colors.secondary,
checkedCheckmarkColor: Color = checkedBoxColor,
- uncheckedBoxColor: Color = contentColorFor(
- MaterialTheme.colors.primary.copy(alpha = 0.5f)
- .compositeOver(MaterialTheme.colors.surface)
- ),
+ uncheckedBoxColor: Color =
+ contentColorFor(
+ MaterialTheme.colors.primary
+ .copy(alpha = 0.5f)
+ .compositeOver(MaterialTheme.colors.surface)
+ ),
uncheckedCheckmarkColor: Color = uncheckedBoxColor,
): CheckboxColors {
return DefaultCheckboxColors(
@@ -324,21 +292,15 @@
checkedCheckmarkColor = checkedCheckmarkColor,
uncheckedBoxColor = uncheckedBoxColor,
uncheckedCheckmarkColor = uncheckedCheckmarkColor,
- disabledCheckedBoxColor =
- checkedBoxColor.toDisabledColor(),
- disabledCheckedCheckmarkColor =
- checkedCheckmarkColor.toDisabledColor(),
- disabledUncheckedBoxColor =
- uncheckedBoxColor.toDisabledColor(),
- disabledUncheckedCheckmarkColor =
- uncheckedCheckmarkColor.toDisabledColor(),
+ disabledCheckedBoxColor = checkedBoxColor.toDisabledColor(),
+ disabledCheckedCheckmarkColor = checkedCheckmarkColor.toDisabledColor(),
+ disabledUncheckedBoxColor = uncheckedBoxColor.toDisabledColor(),
+ disabledUncheckedCheckmarkColor = uncheckedCheckmarkColor.toDisabledColor(),
)
}
}
-/**
- * Contains the default values used by [Switch].
- */
+/** Contains the default values used by [Switch]. */
public object SwitchDefaults {
/**
* Creates a [SwitchColors] for use in a [Switch].
@@ -362,46 +324,51 @@
uncheckedThumbColor = uncheckedThumbColor,
uncheckedTrackColor = uncheckedTrackColor,
disabledCheckedThumbColor = checkedThumbColor.toDisabledColor(),
- disabledCheckedTrackColor = checkedTrackColor.toDisabledColor(
- disabledContentAlpha = checkedTrackColor.alpha * ContentAlpha.disabled),
+ disabledCheckedTrackColor =
+ checkedTrackColor.toDisabledColor(
+ disabledContentAlpha = checkedTrackColor.alpha * ContentAlpha.disabled
+ ),
disabledUncheckedThumbColor =
- uncheckedThumbColor.toDisabledColor(
- disabledContentAlpha = uncheckedThumbColor.alpha * ContentAlpha.disabled),
+ uncheckedThumbColor.toDisabledColor(
+ disabledContentAlpha = uncheckedThumbColor.alpha * ContentAlpha.disabled
+ ),
disabledUncheckedTrackColor =
- uncheckedTrackColor.toDisabledColor(
- disabledContentAlpha = uncheckedTrackColor.alpha * ContentAlpha.disabled),
+ uncheckedTrackColor.toDisabledColor(
+ disabledContentAlpha = uncheckedTrackColor.alpha * ContentAlpha.disabled
+ ),
)
}
}
-/**
- * Contains the default values used by [RadioButton].
- */
+/** Contains the default values used by [RadioButton]. */
public object RadioButtonDefaults {
/**
* Creates a [RadioButtonColors] for use in a [RadioButton].
*
- * @param selectedRingColor The outer ring color of this [RadioButton] when enabled
- * and selected.
- * @param selectedDotColor The inner dot color of this [RadioButton] when enabled
- * and selected.
- * @param unselectedRingColor The outer ring color of this [RadioButton] when enabled
- * and unselected.
- * @param unselectedDotColor The inner dot color of this [RadioButton] when enabled
- * and unselected.
+ * @param selectedRingColor The outer ring color of this [RadioButton] when enabled and
+ * selected.
+ * @param selectedDotColor The inner dot color of this [RadioButton] when enabled and selected.
+ * @param unselectedRingColor The outer ring color of this [RadioButton] when enabled and
+ * unselected.
+ * @param unselectedDotColor The inner dot color of this [RadioButton] when enabled and
+ * unselected.
*/
@Composable
public fun colors(
selectedRingColor: Color = MaterialTheme.colors.secondary,
selectedDotColor: Color = MaterialTheme.colors.secondary,
- unselectedRingColor: Color = contentColorFor(
- MaterialTheme.colors.primary.copy(alpha = 0.5f)
- .compositeOver(MaterialTheme.colors.surface)
- ),
- unselectedDotColor: Color = contentColorFor(
- MaterialTheme.colors.primary.copy(alpha = 0.5f)
- .compositeOver(MaterialTheme.colors.surface)
- ),
+ unselectedRingColor: Color =
+ contentColorFor(
+ MaterialTheme.colors.primary
+ .copy(alpha = 0.5f)
+ .compositeOver(MaterialTheme.colors.surface)
+ ),
+ unselectedDotColor: Color =
+ contentColorFor(
+ MaterialTheme.colors.primary
+ .copy(alpha = 0.5f)
+ .compositeOver(MaterialTheme.colors.surface)
+ ),
): RadioButtonColors {
return DefaultRadioButtonColors(
selectedRingColor = selectedRingColor,
@@ -431,11 +398,7 @@
)
}
-private fun DrawScope.drawThumb(
- color: Color,
- progress: Float,
- isRtl: Boolean
-) {
+private fun DrawScope.drawThumb(color: Color, progress: Float, isRtl: Boolean) {
val switchThumbRadiusPx = SWITCH_THUMB_RADIUS.toPx()
val switchTrackLengthPx = SWITCH_TRACK_LENGTH.toPx()
@@ -455,9 +418,7 @@
)
}
-/**
- * Default [CheckboxColors] implementation.
- */
+/** Default [CheckboxColors] implementation. */
@Immutable
private class DefaultCheckboxColors(
private val checkedBoxColor: Color,
@@ -525,9 +486,7 @@
}
}
-/**
- * Default [SwitchColors] implementation.
- */
+/** Default [SwitchColors] implementation. */
@Immutable
private class DefaultSwitchColors(
private val checkedThumbColor: Color,
@@ -595,9 +554,7 @@
}
}
-/**
- * Default [SwitchColors] implementation.
- */
+/** Default [SwitchColors] implementation. */
@Immutable
private class DefaultRadioButtonColors(
private val selectedRingColor: Color,
diff --git a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/TouchExplorationStateProvider.kt b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/TouchExplorationStateProvider.kt
index 665daf1..82fa12e 100644
--- a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/TouchExplorationStateProvider.kt
+++ b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/TouchExplorationStateProvider.kt
@@ -44,8 +44,7 @@
* attach the state to itself. This will allow composables to react to change in service state,
* if required.
*/
- @Composable
- fun touchExplorationState(): State<Boolean>
+ @Composable fun touchExplorationState(): State<Boolean>
}
/**
@@ -87,9 +86,7 @@
onDispose: () -> Unit = {}
) {
DisposableEffect(this) {
- val observer = LifecycleEventObserver { _, event ->
- handleEvent(event)
- }
+ val observer = LifecycleEventObserver { _, event -> handleEvent(event) }
[email protected](observer)
onDispose {
onDispose()
@@ -98,14 +95,14 @@
}
}
- private class Listener constructor(
+ private class Listener
+ constructor(
private val accessibilityManager: AccessibilityManager,
) : AccessibilityStateChangeListener, TouchExplorationStateChangeListener, State<Boolean> {
private var accessibilityEnabled by mutableStateOf(accessibilityManager.isEnabled)
- private var touchExplorationEnabled by mutableStateOf(
- accessibilityManager.isTouchExplorationEnabled
- )
+ private var touchExplorationEnabled by
+ mutableStateOf(accessibilityManager.isTouchExplorationEnabled)
override val value: Boolean
get() = accessibilityEnabled && touchExplorationEnabled
diff --git a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/Typography.kt b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/Typography.kt
index 5bbfa4c..85d7144 100644
--- a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/Typography.kt
+++ b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/Typography.kt
@@ -26,53 +26,44 @@
/**
* Class holding typography definitions as defined by the Wear Material typography specification.
*
- * The text styles in this typography are scaled according to the user's preferred font size in
- * the system settings. Larger font sizes can be fixed if necessary in order to avoid pressure on
- * screen space, because they are already sufficiently accessible.
- * Here is an example of fixing the font size for Display1:
+ * The text styles in this typography are scaled according to the user's preferred font size in the
+ * system settings. Larger font sizes can be fixed if necessary in order to avoid pressure on screen
+ * space, because they are already sufficiently accessible. Here is an example of fixing the font
+ * size for Display1:
+ *
* @sample androidx.wear.compose.material.samples.FixedFontSize
*
* @property display1 Display1 is the largest headline. Displays are the largest text on the screen,
- * reserved for short, important text or numerals.
- *
+ * reserved for short, important text or numerals.
* @property display2 Display2 is the second largest headline. Displays are the largest text on the
- * screen, reserved for short, important text or numerals.
- *
+ * screen, reserved for short, important text or numerals.
* @property display3 Display3 is the third largest headline. Displays are the largest text on the
- * screen, reserved for short, important text or numerals.
- *
+ * screen, reserved for short, important text or numerals.
* @property title1 Title1 is the largest title. Titles are smaller than Displays. They are
- * typically reserved for medium-emphasis text that is shorter in length.
- *
- * @property title2 Title2 is the medium title. Titles are smaller than Displays. They are
- * typically reserved for medium-emphasis text that is shorter in length.
- *
+ * typically reserved for medium-emphasis text that is shorter in length.
+ * @property title2 Title2 is the medium title. Titles are smaller than Displays. They are typically
+ * reserved for medium-emphasis text that is shorter in length.
* @property title3 Title3 is the smallest title. Titles are smaller than Displays. They are
- * typically reserved for medium-emphasis text that is shorter in length.
- *
+ * typically reserved for medium-emphasis text that is shorter in length.
* @property body1 Body1 is the largest body. Body texts are typically used for long-form writing as
- * it works well for small text sizes. For longer sections of text, a serif or sans serif typeface
- * is recommended.
- *
+ * it works well for small text sizes. For longer sections of text, a serif or sans serif typeface
+ * is recommended.
* @property body2 Body2 is the smallest body. Body texts are typically used for long-form writing
- * as it works well for small text sizes. For longer sections of text, a serif or sans serif
- * typeface is recommended.
- *
+ * as it works well for small text sizes. For longer sections of text, a serif or sans serif
+ * typeface is recommended.
* @property button Button text is a call to action used in different types of buttons (such as
- * text, outlined and contained buttons) and in tabs, dialogs, and cards. Button text is typically
- * sans serif, using all caps text.
- *
+ * text, outlined and contained buttons) and in tabs, dialogs, and cards. Button text is typically
+ * sans serif, using all caps text.
* @property caption1 Caption1 is the largest caption. Caption texts are the smallest font sizes.
- * They are used on secondary content.
- *
+ * They are used on secondary content.
* @property caption2 Caption2 is the second largest caption. Caption texts are the smallest font
- * sizes. They are used on secondary content.
- *
+ * sizes. They are used on secondary content.
* @property caption3 Caption3 is an exceptional small font size which is used for the extra
- * long-form writing like legal texts.
+ * long-form writing like legal texts.
*/
@Immutable
-public class Typography internal constructor(
+public class Typography
+internal constructor(
public val display1: TextStyle,
public val display2: TextStyle,
public val display3: TextStyle,
@@ -86,80 +77,92 @@
public val caption2: TextStyle,
public val caption3: TextStyle,
) {
- public constructor (
+ public constructor(
defaultFontFamily: FontFamily = FontFamily.Default,
- display1: TextStyle = DefaultTextStyle.copy(
- fontWeight = FontWeight.Medium,
- fontSize = 40.sp,
- lineHeight = 46.sp,
- letterSpacing = 0.5.sp
- ),
- display2: TextStyle = DefaultTextStyle.copy(
- fontWeight = FontWeight.Medium,
- fontSize = 34.sp,
- lineHeight = 40.sp,
- letterSpacing = 1.sp
- ),
- display3: TextStyle = DefaultTextStyle.copy(
- fontWeight = FontWeight.Medium,
- fontSize = 30.sp,
- lineHeight = 36.sp,
- letterSpacing = 0.8.sp,
- ),
- title1: TextStyle = DefaultTextStyle.copy(
- fontWeight = FontWeight.Medium,
- fontSize = 24.sp,
- lineHeight = 28.sp,
- letterSpacing = 0.2.sp
- ),
- title2: TextStyle = DefaultTextStyle.copy(
- fontWeight = FontWeight.Medium,
- fontSize = 20.sp,
- lineHeight = 24.sp,
- letterSpacing = 0.2.sp
- ),
- title3: TextStyle = DefaultTextStyle.copy(
- fontWeight = FontWeight.Medium,
- fontSize = 16.sp,
- lineHeight = 20.sp,
- letterSpacing = 0.2.sp
- ),
- body1: TextStyle = DefaultTextStyle.copy(
- fontWeight = FontWeight.Normal,
- fontSize = 16.sp,
- lineHeight = 20.sp,
- letterSpacing = 0.18.sp
- ),
- body2: TextStyle = DefaultTextStyle.copy(
- fontWeight = FontWeight.Normal,
- fontSize = 14.sp,
- lineHeight = 18.sp,
- letterSpacing = 0.2.sp
- ),
- button: TextStyle = DefaultTextStyle.copy(
- fontWeight = FontWeight.Bold,
- fontSize = 15.sp,
- lineHeight = 19.sp,
- letterSpacing = 0.38.sp
- ),
- caption1: TextStyle = DefaultTextStyle.copy(
- fontWeight = FontWeight.Medium,
- fontSize = 14.sp,
- lineHeight = 18.sp,
- letterSpacing = 0.1.sp
- ),
- caption2: TextStyle = DefaultTextStyle.copy(
- fontWeight = FontWeight.Medium,
- fontSize = 12.sp,
- lineHeight = 16.sp,
- letterSpacing = 0.1.sp
- ),
- caption3: TextStyle = DefaultTextStyle.copy(
- fontWeight = FontWeight.Medium,
- fontSize = 10.sp,
- lineHeight = 14.sp,
- letterSpacing = 0.1.sp
- )
+ display1: TextStyle =
+ DefaultTextStyle.copy(
+ fontWeight = FontWeight.Medium,
+ fontSize = 40.sp,
+ lineHeight = 46.sp,
+ letterSpacing = 0.5.sp
+ ),
+ display2: TextStyle =
+ DefaultTextStyle.copy(
+ fontWeight = FontWeight.Medium,
+ fontSize = 34.sp,
+ lineHeight = 40.sp,
+ letterSpacing = 1.sp
+ ),
+ display3: TextStyle =
+ DefaultTextStyle.copy(
+ fontWeight = FontWeight.Medium,
+ fontSize = 30.sp,
+ lineHeight = 36.sp,
+ letterSpacing = 0.8.sp,
+ ),
+ title1: TextStyle =
+ DefaultTextStyle.copy(
+ fontWeight = FontWeight.Medium,
+ fontSize = 24.sp,
+ lineHeight = 28.sp,
+ letterSpacing = 0.2.sp
+ ),
+ title2: TextStyle =
+ DefaultTextStyle.copy(
+ fontWeight = FontWeight.Medium,
+ fontSize = 20.sp,
+ lineHeight = 24.sp,
+ letterSpacing = 0.2.sp
+ ),
+ title3: TextStyle =
+ DefaultTextStyle.copy(
+ fontWeight = FontWeight.Medium,
+ fontSize = 16.sp,
+ lineHeight = 20.sp,
+ letterSpacing = 0.2.sp
+ ),
+ body1: TextStyle =
+ DefaultTextStyle.copy(
+ fontWeight = FontWeight.Normal,
+ fontSize = 16.sp,
+ lineHeight = 20.sp,
+ letterSpacing = 0.18.sp
+ ),
+ body2: TextStyle =
+ DefaultTextStyle.copy(
+ fontWeight = FontWeight.Normal,
+ fontSize = 14.sp,
+ lineHeight = 18.sp,
+ letterSpacing = 0.2.sp
+ ),
+ button: TextStyle =
+ DefaultTextStyle.copy(
+ fontWeight = FontWeight.Bold,
+ fontSize = 15.sp,
+ lineHeight = 19.sp,
+ letterSpacing = 0.38.sp
+ ),
+ caption1: TextStyle =
+ DefaultTextStyle.copy(
+ fontWeight = FontWeight.Medium,
+ fontSize = 14.sp,
+ lineHeight = 18.sp,
+ letterSpacing = 0.1.sp
+ ),
+ caption2: TextStyle =
+ DefaultTextStyle.copy(
+ fontWeight = FontWeight.Medium,
+ fontSize = 12.sp,
+ lineHeight = 16.sp,
+ letterSpacing = 0.1.sp
+ ),
+ caption3: TextStyle =
+ DefaultTextStyle.copy(
+ fontWeight = FontWeight.Medium,
+ fontSize = 10.sp,
+ lineHeight = 14.sp,
+ letterSpacing = 0.1.sp
+ )
) : this(
display1 = display1.withDefaultFontFamily(defaultFontFamily),
display2 = display2.withDefaultFontFamily(defaultFontFamily),
@@ -175,9 +178,7 @@
caption3 = caption3.withDefaultFontFamily(defaultFontFamily),
)
- /**
- * Returns a copy of this Typography, optionally overriding some of the values.
- */
+ /** Returns a copy of this Typography, optionally overriding some of the values. */
public fun copy(
display1: TextStyle = this.display1,
display2: TextStyle = this.display2,
@@ -191,20 +192,21 @@
caption1: TextStyle = this.caption1,
caption2: TextStyle = this.caption2,
caption3: TextStyle = this.caption3,
- ): Typography = Typography(
- display1,
- display2,
- display3,
- title1,
- title2,
- title3,
- body1,
- body2,
- button,
- caption1,
- caption2,
- caption3,
- )
+ ): Typography =
+ Typography(
+ display1,
+ display2,
+ display3,
+ title1,
+ title2,
+ title3,
+ body1,
+ body2,
+ button,
+ caption1,
+ caption2,
+ caption3,
+ )
override fun equals(other: Any?): Boolean {
if (this === other) return true
@@ -250,8 +252,8 @@
}
/**
- * @return [this] if there is a [FontFamily] defined, otherwise copies [this] with [default] as
- * the [FontFamily].
+ * @return [this] if there is a [FontFamily] defined, otherwise copies [this] with [default] as the
+ * [FontFamily].
*/
private fun TextStyle.withDefaultFontFamily(default: FontFamily): TextStyle {
return if (fontFamily != null) this else copy(fontFamily = default)
@@ -259,18 +261,17 @@
private const val DefaultIncludeFontPadding = false
-internal val DefaultTextStyle = TextStyle.Default.copy(
- platformStyle = PlatformTextStyle(
- includeFontPadding = DefaultIncludeFontPadding
+internal val DefaultTextStyle =
+ TextStyle.Default.copy(
+ platformStyle = PlatformTextStyle(includeFontPadding = DefaultIncludeFontPadding)
)
-)
/**
* This Ambient holds on to the current definition of typography for this application as described
* by the Wear Material spec. You can read the values in it when creating custom components that
* want to use Wear Material types, as well as override the values when you want to re-style a part
- * of your hierarchy. Material components related to text such as [Button] will use this Ambient
- * to set values with which to style children text components.
+ * of your hierarchy. Material components related to text such as [Button] will use this Ambient to
+ * set values with which to style children text components.
*
* To access values within this ambient, use [MaterialTheme.typography].
*/
diff --git a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/Vignette.kt b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/Vignette.kt
index 8350b98..7efeb12 100644
--- a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/Vignette.kt
+++ b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/Vignette.kt
@@ -26,9 +26,7 @@
import androidx.wear.compose.foundation.lazy.ScalingLazyColumn
import androidx.wear.compose.materialcore.isRoundDevice
-/**
- * Possible combinations for vignette state.
- */
+/** Possible combinations for vignette state. */
@kotlin.jvm.JvmInline
public value class VignettePosition constructor(private val key: Int) {
internal fun drawTop(): Boolean {
@@ -50,19 +48,13 @@
}
companion object {
- /**
- * Only the top part of the vignette is displayed.
- */
+ /** Only the top part of the vignette is displayed. */
val Top = VignettePosition(0)
- /**
- * Only the bottom part of the vignette is displayed.
- */
+ /** Only the bottom part of the vignette is displayed. */
val Bottom = VignettePosition(1)
- /**
- * Both the top and bottom of the vignette is displayed.
- */
+ /** Both the top and bottom of the vignette is displayed. */
val TopAndBottom = VignettePosition(2)
}
@@ -82,8 +74,8 @@
*
* The vignette is designed to be used as an overlay, typically in the [Scaffold].
*
- * Simple example of a Vignette with a [ScalingLazyColumn] as the main application content where
- * the top/bottom vignette images can be turned on/off can be found at
+ * Simple example of a Vignette with a [ScalingLazyColumn] as the main application content where the
+ * top/bottom vignette images can be turned on/off can be found at
*
* @sample androidx.wear.compose.material.samples.SimpleScaffoldWithScrollIndicator
*
@@ -99,28 +91,26 @@
Box(modifier = modifier.fillMaxSize()) {
if (vignettePosition.drawTop()) {
Image(
- painter = imageResource(
- if (isRoundDevice()) ImageResources.CircularVignetteTop
- else ImageResources.RectangularVignetteTop
- ),
+ painter =
+ imageResource(
+ if (isRoundDevice()) ImageResources.CircularVignetteTop
+ else ImageResources.RectangularVignetteTop
+ ),
contentScale = ContentScale.FillWidth,
contentDescription = null,
- modifier = Modifier
- .align(Alignment.TopCenter)
- .fillMaxWidth(),
+ modifier = Modifier.align(Alignment.TopCenter).fillMaxWidth(),
)
}
if (vignettePosition.drawBottom()) {
Image(
- painter = imageResource(
- if (isRoundDevice()) ImageResources.CircularVignetteBottom
- else ImageResources.RectangularVignetteBottom
- ),
+ painter =
+ imageResource(
+ if (isRoundDevice()) ImageResources.CircularVignetteBottom
+ else ImageResources.RectangularVignetteBottom
+ ),
contentScale = ContentScale.FillWidth,
contentDescription = null,
- modifier = Modifier
- .align(Alignment.BottomCenter)
- .fillMaxWidth(),
+ modifier = Modifier.align(Alignment.BottomCenter).fillMaxWidth(),
)
}
}
diff --git a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/dialog/Dialog.android.kt b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/dialog/Dialog.android.kt
index e66a1ed..e591bf5 100644
--- a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/dialog/Dialog.android.kt
+++ b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/dialog/Dialog.android.kt
@@ -55,24 +55,24 @@
/**
* [Dialog] displays a full-screen dialog, layered over any other content. It takes a single slot,
- * which is expected to be an opinionated Wear dialog content, such as [Alert]
- * or [Confirmation].
+ * which is expected to be an opinionated Wear dialog content, such as [Alert] or [Confirmation].
*
- * The dialog supports swipe-to-dismiss and reveals the parent content in the background
- * during the swipe gesture.
+ * The dialog supports swipe-to-dismiss and reveals the parent content in the background during the
+ * swipe gesture.
*
* Example of content using [Dialog] to trigger an alert dialog using [Alert]:
+ *
* @sample androidx.wear.compose.material.samples.AlertDialogSample
*
- * Example of content using [Dialog] to trigger a confirmation dialog using
- * [Confirmation]:
+ * Example of content using [Dialog] to trigger a confirmation dialog using [Confirmation]:
+ *
* @sample androidx.wear.compose.material.samples.ConfirmationDialogSample
-
- * @param showDialog Controls whether to display the [Dialog]. Set to true initially to trigger
- * an 'intro' animation and display the [Dialog]. Subsequently, setting to false triggers
- * an 'outro' animation, then [Dialog] calls [onDismissRequest] and hides itself.
- * @param onDismissRequest Executes when the user dismisses the dialog.
- * Must remove the dialog from the composition.
+ *
+ * @param showDialog Controls whether to display the [Dialog]. Set to true initially to trigger an
+ * 'intro' animation and display the [Dialog]. Subsequently, setting to false triggers an 'outro'
+ * animation, then [Dialog] calls [onDismissRequest] and hides itself.
+ * @param onDismissRequest Executes when the user dismisses the dialog. Must remove the dialog from
+ * the composition.
* @param modifier Modifier to be applied to the dialog.
* @param scrollState The scroll state for the dialog so that the scroll position can be displayed.
* @param properties Typically platform specific properties to further configure the dialog.
@@ -99,24 +99,24 @@
/**
* [Dialog] displays a full-screen dialog, layered over any other content. It takes a single slot,
- * which is expected to be an opinionated Wear dialog content, such as [Alert]
- * or [Confirmation].
+ * which is expected to be an opinionated Wear dialog content, such as [Alert] or [Confirmation].
*
- * The dialog supports swipe-to-dismiss and reveals the parent content in the background
- * during the swipe gesture.
+ * The dialog supports swipe-to-dismiss and reveals the parent content in the background during the
+ * swipe gesture.
*
* Example of content using [Dialog] to trigger an alert dialog using [Alert]:
+ *
* @sample androidx.wear.compose.material.samples.AlertDialogSample
*
- * Example of content using [Dialog] to trigger a confirmation dialog using
- * [Confirmation]:
+ * Example of content using [Dialog] to trigger a confirmation dialog using [Confirmation]:
+ *
* @sample androidx.wear.compose.material.samples.ConfirmationDialogSample
-
- * @param showDialog Controls whether to display the [Dialog]. Set to true initially to trigger
- * an 'intro' animation and display the [Dialog]. Subsequently, setting to false triggers
- * an 'outro' animation, then [Dialog] calls [onDismissRequest] and hides itself.
- * @param onDismissRequest Executes when the user dismisses the dialog.
- * Must remove the dialog from the composition.
+ *
+ * @param showDialog Controls whether to display the [Dialog]. Set to true initially to trigger an
+ * 'intro' animation and display the [Dialog]. Subsequently, setting to false triggers an 'outro'
+ * animation, then [Dialog] calls [onDismissRequest] and hides itself.
+ * @param onDismissRequest Executes when the user dismisses the dialog. Must remove the dialog from
+ * the composition.
* @param modifier Modifier to be applied to the dialog.
* @param scrollState The scroll state for the dialog so that the scroll position can be displayed.
* @param properties Typically platform specific properties to further configure the dialog.
@@ -126,7 +126,8 @@
@Deprecated(
"This overload is provided for backwards compatibility with Compose for Wear OS 1.1." +
"A newer overload is available which uses ScalingLazyListState from " +
- "wear.compose.foundation.lazy package", level = DeprecationLevel.HIDDEN
+ "wear.compose.foundation.lazy package",
+ level = DeprecationLevel.HIDDEN
)
@Composable
public fun Dialog(
@@ -149,8 +150,8 @@
}
/**
- * A Dialog composable which was created for sharing code between 2 versions
- * of public [Dialog]s - with ScalingLazyListState from material and another from foundation.lazy
+ * A Dialog composable which was created for sharing code between 2 versions of public [Dialog]s -
+ * with ScalingLazyListState from material and another from foundation.lazy
*/
@Composable
private fun Dialog(
@@ -167,16 +168,13 @@
}
val transition = rememberTransition(transitionState)
- var pendingOnDismissCall by remember {
- mutableStateOf(false)
- }
+ var pendingOnDismissCall by remember { mutableStateOf(false) }
if (showDialog || transition.currentState == DialogVisibility.Display) {
Dialog(
onDismissRequest = onDismissRequest,
properties = properties,
) {
-
val backgroundScrimAlpha by animateBackgroundScrimAlpha(transition)
val contentAlpha by animateContentAlpha(transition)
val scale by animateDialogScale(transition)
@@ -184,14 +182,16 @@
vignette = {
AnimatedVisibility(
visible = transition.targetState == DialogVisibility.Display,
- enter = fadeIn(
- animationSpec =
- TweenSpec(durationMillis = CASUAL, easing = STANDARD_IN)
- ),
- exit = fadeOut(
- animationSpec =
- TweenSpec(durationMillis = CASUAL, easing = STANDARD_OUT)
- ),
+ enter =
+ fadeIn(
+ animationSpec =
+ TweenSpec(durationMillis = CASUAL, easing = STANDARD_IN)
+ ),
+ exit =
+ fadeOut(
+ animationSpec =
+ TweenSpec(durationMillis = CASUAL, easing = STANDARD_OUT)
+ ),
) {
Vignette(vignettePosition = VignettePosition.TopAndBottom)
}
@@ -200,11 +200,12 @@
) {
SwipeToDismissBox(
state = rememberSwipeToDismissBoxState(),
- modifier = Modifier.graphicsLayer(
- alpha = backgroundScrimAlpha,
- scaleX = scale,
- scaleY = scale,
- ),
+ modifier =
+ Modifier.graphicsLayer(
+ alpha = backgroundScrimAlpha,
+ scaleX = scale,
+ scaleY = scale,
+ ),
onDismissed = {
onDismissRequest()
// Reset state for the next time this dialog is shown.
@@ -213,10 +214,10 @@
) { isBackground ->
if (!isBackground) {
Box(
- modifier = Modifier
- .matchParentSize()
- .graphicsLayer(alpha = contentAlpha)
- .background(MaterialTheme.colors.background)
+ modifier =
+ Modifier.matchParentSize()
+ .graphicsLayer(alpha = contentAlpha)
+ .background(MaterialTheme.colors.background)
) {
content()
positionIndicator()
@@ -236,9 +237,10 @@
}
LaunchedEffect(transitionState.currentState) {
- if (pendingOnDismissCall &&
- transitionState.currentState == DialogVisibility.Hide &&
- transitionState.isIdle
+ if (
+ pendingOnDismissCall &&
+ transitionState.currentState == DialogVisibility.Hide &&
+ transitionState.isIdle
) {
// After the outro animation, leave the dialog & reset alpha/scale transitions.
onDismissRequest()
@@ -250,79 +252,73 @@
}
@Composable
-private fun animateBackgroundScrimAlpha(
- transition: Transition<DialogVisibility>
-) = transition.animateFloat(
- transitionSpec = {
- when (transition.targetState) {
- DialogVisibility.Display -> tween(
- durationMillis = (RAPID / 0.9f).toInt(),
- easing = STANDARD_OUT
- )
-
- DialogVisibility.Hide -> keyframes {
- // Outro
- durationMillis = QUICK + RAPID
- 1f at 0
- 0.9f at RAPID using STANDARD_IN
- 0.0f at RAPID + QUICK
+private fun animateBackgroundScrimAlpha(transition: Transition<DialogVisibility>) =
+ transition.animateFloat(
+ transitionSpec = {
+ when (transition.targetState) {
+ DialogVisibility.Display ->
+ tween(durationMillis = (RAPID / 0.9f).toInt(), easing = STANDARD_OUT)
+ DialogVisibility.Hide ->
+ keyframes {
+ // Outro
+ durationMillis = QUICK + RAPID
+ 1f at 0
+ 0.9f at RAPID using STANDARD_IN
+ 0.0f at RAPID + QUICK
+ }
}
+ },
+ label = "background-scrim-alpha"
+ ) { stage ->
+ when (stage) {
+ DialogVisibility.Hide -> 0f
+ DialogVisibility.Display -> 1f
}
- },
- label = "background-scrim-alpha"
-) { stage ->
- when (stage) {
- DialogVisibility.Hide -> 0f
- DialogVisibility.Display -> 1f
}
-}
@Composable
-private fun animateContentAlpha(
- transition: Transition<DialogVisibility>
-) = transition.animateFloat(
- transitionSpec = {
- when (transition.targetState) {
- DialogVisibility.Display -> keyframes {
- // Intro
- durationMillis = QUICK + RAPID
- 0.0f at 0
- 0.1f at RAPID using STANDARD_IN
- 1f at RAPID + QUICK
+private fun animateContentAlpha(transition: Transition<DialogVisibility>) =
+ transition.animateFloat(
+ transitionSpec = {
+ when (transition.targetState) {
+ DialogVisibility.Display ->
+ keyframes {
+ // Intro
+ durationMillis = QUICK + RAPID
+ 0.0f at 0
+ 0.1f at RAPID using STANDARD_IN
+ 1f at RAPID + QUICK
+ }
+ DialogVisibility.Hide ->
+ tween(durationMillis = (RAPID / 0.9f).toInt(), easing = STANDARD_OUT)
}
-
- DialogVisibility.Hide -> tween(
- durationMillis = (RAPID / 0.9f).toInt(),
- easing = STANDARD_OUT
- )
+ },
+ label = "content-alpha"
+ ) { stage ->
+ when (stage) {
+ DialogVisibility.Hide -> 0f
+ DialogVisibility.Display -> 1f
}
- },
- label = "content-alpha"
-) { stage ->
- when (stage) {
- DialogVisibility.Hide -> 0f
- DialogVisibility.Display -> 1f
}
-}
@Composable
-private fun animateDialogScale(
- transition: Transition<DialogVisibility>
-) = transition.animateFloat(
- transitionSpec = {
- when (transition.targetState) {
- DialogVisibility.Display -> tween(durationMillis = CASUAL, easing = STANDARD_IN)
- DialogVisibility.Hide -> tween(durationMillis = CASUAL, easing = STANDARD_OUT)
+private fun animateDialogScale(transition: Transition<DialogVisibility>) =
+ transition.animateFloat(
+ transitionSpec = {
+ when (transition.targetState) {
+ DialogVisibility.Display -> tween(durationMillis = CASUAL, easing = STANDARD_IN)
+ DialogVisibility.Hide -> tween(durationMillis = CASUAL, easing = STANDARD_OUT)
+ }
+ },
+ label = "scale"
+ ) { stage ->
+ when (stage) {
+ DialogVisibility.Hide -> 1.25f
+ DialogVisibility.Display -> 1.0f
}
- },
- label = "scale"
-) { stage ->
- when (stage) {
- DialogVisibility.Hide -> 1.25f
- DialogVisibility.Display -> 1.0f
}
-}
private enum class DialogVisibility {
- Hide, Display;
+ Hide,
+ Display
}
diff --git a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/dialog/Dialog.kt b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/dialog/Dialog.kt
index 64e3eda..05fda60 100644
--- a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/dialog/Dialog.kt
+++ b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/dialog/Dialog.kt
@@ -55,36 +55,35 @@
import kotlinx.coroutines.delay
/**
- * [Alert] lays out the content for an opinionated, alert screen.
- * This overload offers 5 slots for title, negative button, positive button, optional icon and
- * optional content. The buttons are shown side-by-side below the icon, text and content.
- * [Alert] is scrollable by default if the content is taller than the viewport.
+ * [Alert] lays out the content for an opinionated, alert screen. This overload offers 5 slots for
+ * title, negative button, positive button, optional icon and optional content. The buttons are
+ * shown side-by-side below the icon, text and content. [Alert] is scrollable by default if the
+ * content is taller than the viewport.
*
- * [Alert] can be used as a destination in a navigation graph
- * e.g. using SwipeDismissableNavHost. However, for a conventional fullscreen dialog,
- * displayed on top of other content, use [Dialog].
+ * [Alert] can be used as a destination in a navigation graph e.g. using SwipeDismissableNavHost.
+ * However, for a conventional fullscreen dialog, displayed on top of other content, use [Dialog].
*
* Example of an [Alert] with an icon, title, body text and buttons:
+ *
* @sample androidx.wear.compose.material.samples.AlertWithButtons
*
- * @param title A slot for displaying the title of the dialog,
- * expected to be one or two lines of text.
- * @param negativeButton A slot for a [Button] indicating negative sentiment (e.g. No).
- * Clicking the button must remove the dialog from the composition hierarchy.
- * @param positiveButton A slot for a [Button] indicating positive sentiment (e.g. Yes).
- * Clicking the button must remove the dialog from the composition hierarchy.
+ * @param title A slot for displaying the title of the dialog, expected to be one or two lines of
+ * text.
+ * @param negativeButton A slot for a [Button] indicating negative sentiment (e.g. No). Clicking the
+ * button must remove the dialog from the composition hierarchy.
+ * @param positiveButton A slot for a [Button] indicating positive sentiment (e.g. Yes). Clicking
+ * the button must remove the dialog from the composition hierarchy.
* @param modifier Modifier to be applied to the dialog content.
* @param icon Optional slot for an icon to be shown at the top of the dialog.
* @param scrollState The scroll state for the dialog so that the scroll position can be displayed
- * e.g. by the [PositionIndicator] passed to [Scaffold].
+ * e.g. by the [PositionIndicator] passed to [Scaffold].
* @param backgroundColor [Color] representing the background color for the dialog.
* @param contentColor [Color] representing the color for [content].
* @param titleColor [Color] representing the color for [title].
- * @param iconColor Icon [Color] that defaults to [contentColor],
- * unless specifically overridden.
- * @param verticalArrangement The vertical arrangement of the dialog's children. This allows us
- * to add spacing between items and specify the arrangement of the items when we have not enough
- * of them to fill the whole minimum size.
+ * @param iconColor Icon [Color] that defaults to [contentColor], unless specifically overridden.
+ * @param verticalArrangement The vertical arrangement of the dialog's children. This allows us to
+ * add spacing between items and specify the arrangement of the items when we have not enough of
+ * them to fill the whole minimum size.
* @param contentPadding The padding to apply around the whole of the dialog's contents.
* @param content A slot for additional content, expected to be 2-3 lines of text.
*/
@@ -112,19 +111,13 @@
backgroundColor = backgroundColor,
) {
if (icon != null) {
- item {
- DialogIconHeader(iconColor, content = icon)
- }
+ item { DialogIconHeader(iconColor, content = icon) }
}
- item {
- DialogTitle(titleColor, padding = DialogDefaults.TitlePadding, title)
- }
+ item { DialogTitle(titleColor, padding = DialogDefaults.TitlePadding, title) }
if (content != null) {
- item {
- DialogBody(contentColor, content)
- }
+ item { DialogBody(contentColor, content) }
}
// Buttons
@@ -141,36 +134,35 @@
}
/**
- * [Alert] lays out the content for an opinionated, alert screen.
- * This overload offers 5 slots for title, negative button, positive button, optional icon and
- * optional content. The buttons are shown side-by-side below the icon, text and content.
- * [Alert] is scrollable by default if the content is taller than the viewport.
+ * [Alert] lays out the content for an opinionated, alert screen. This overload offers 5 slots for
+ * title, negative button, positive button, optional icon and optional content. The buttons are
+ * shown side-by-side below the icon, text and content. [Alert] is scrollable by default if the
+ * content is taller than the viewport.
*
- * [Alert] can be used as a destination in a navigation graph
- * e.g. using SwipeDismissableNavHost. However, for a conventional fullscreen dialog,
- * displayed on top of other content, use [Dialog].
+ * [Alert] can be used as a destination in a navigation graph e.g. using SwipeDismissableNavHost.
+ * However, for a conventional fullscreen dialog, displayed on top of other content, use [Dialog].
*
* Example of an [Alert] with an icon, title, body text and buttons:
+ *
* @sample androidx.wear.compose.material.samples.AlertWithButtons
*
- * @param title A slot for displaying the title of the dialog,
- * expected to be one or two lines of text.
- * @param negativeButton A slot for a [Button] indicating negative sentiment (e.g. No).
- * Clicking the button must remove the dialog from the composition hierarchy.
- * @param positiveButton A slot for a [Button] indicating positive sentiment (e.g. Yes).
- * Clicking the button must remove the dialog from the composition hierarchy.
+ * @param title A slot for displaying the title of the dialog, expected to be one or two lines of
+ * text.
+ * @param negativeButton A slot for a [Button] indicating negative sentiment (e.g. No). Clicking the
+ * button must remove the dialog from the composition hierarchy.
+ * @param positiveButton A slot for a [Button] indicating positive sentiment (e.g. Yes). Clicking
+ * the button must remove the dialog from the composition hierarchy.
* @param modifier Modifier to be applied to the dialog content.
* @param icon Optional slot for an icon to be shown at the top of the dialog.
* @param scrollState The scroll state for the dialog so that the scroll position can be displayed
- * e.g. by the [PositionIndicator] passed to [Scaffold].
+ * e.g. by the [PositionIndicator] passed to [Scaffold].
* @param backgroundColor [Color] representing the background color for the dialog.
* @param contentColor [Color] representing the color for [content].
* @param titleColor [Color] representing the color for [title].
- * @param iconColor Icon [Color] that defaults to [contentColor],
- * unless specifically overridden.
- * @param verticalArrangement The vertical arrangement of the dialog's children. This allows us
- * to add spacing between items and specify the arrangement of the items when we have not enough
- * of them to fill the whole minimum size.
+ * @param iconColor Icon [Color] that defaults to [contentColor], unless specifically overridden.
+ * @param verticalArrangement The vertical arrangement of the dialog's children. This allows us to
+ * add spacing between items and specify the arrangement of the items when we have not enough of
+ * them to fill the whole minimum size.
* @param contentPadding The padding to apply around the whole of the dialog's contents.
* @param content A slot for additional content, expected to be 2-3 lines of text.
*/
@@ -178,7 +170,8 @@
@Deprecated(
"This overload is provided for backwards compatibility with Compose for Wear OS 1.1." +
"A newer overload is available which uses ScalingLazyListState from " +
- "wear.compose.foundation.lazy package", level = DeprecationLevel.HIDDEN
+ "wear.compose.foundation.lazy package",
+ level = DeprecationLevel.HIDDEN
)
@Composable
public fun Alert(
@@ -214,9 +207,7 @@
)
}
-/**
- * @VisibleForTesting
- */
+/** @VisibleForTesting */
@Suppress("DEPRECATION")
@Deprecated("Used only for testing")
@Composable
@@ -244,19 +235,13 @@
backgroundColor = backgroundColor,
) {
if (icon != null) {
- item {
- DialogIconHeader(iconColor, content = icon)
- }
+ item { DialogIconHeader(iconColor, content = icon) }
}
- item {
- DialogTitle(titleColor, padding = DialogDefaults.TitlePadding, title)
- }
+ item { DialogTitle(titleColor, padding = DialogDefaults.TitlePadding, title) }
if (content != null) {
- item {
- DialogBody(contentColor, content)
- }
+ item { DialogBody(contentColor, content) }
}
// Buttons
@@ -273,32 +258,32 @@
}
/**
- * [Alert] lays out the content for an opinionated, alert screen.
- * This overload offers 4 slots for title, optional icon, optional message text and
- * a content slot expected to be one or more vertically stacked [Chip]s or [ToggleChip]s.
- * [Alert] is scrollable by default if the content is taller than the viewport.
+ * [Alert] lays out the content for an opinionated, alert screen. This overload offers 4 slots for
+ * title, optional icon, optional message text and a content slot expected to be one or more
+ * vertically stacked [Chip]s or [ToggleChip]s. [Alert] is scrollable by default if the content is
+ * taller than the viewport.
*
- * [Alert] can be used as a destination in a navigation graph
- * e.g. using SwipeDismissableNavHost. However, for a conventional fullscreen dialog,
- * displayed on top of other content, use [Dialog].
+ * [Alert] can be used as a destination in a navigation graph e.g. using SwipeDismissableNavHost.
+ * However, for a conventional fullscreen dialog, displayed on top of other content, use [Dialog].
*
* Example of an [Alert] with an icon, title, message text and chips:
+ *
* @sample androidx.wear.compose.material.samples.AlertWithChips
*
- * @param title A slot for displaying the title of the dialog,
- * expected to be one or two lines of text.
+ * @param title A slot for displaying the title of the dialog, expected to be one or two lines of
+ * text.
* @param modifier Modifier to be applied to the dialog.
* @param icon Optional slot for an icon to be shown at the top of the dialog.
* @param message Optional slot for additional message content, expected to be 2-3 lines of text.
* @param scrollState The scroll state for the dialog so that the scroll position can be displayed
- * e.g. by the [PositionIndicator] passed to [Scaffold].
+ * e.g. by the [PositionIndicator] passed to [Scaffold].
* @param backgroundColor [Color] representing the background color for the dialog.
* @param titleColor [Color] representing the color for [title].
* @param messageColor [Color] representing the color for [message].
* @param iconColor [Color] representing the color for [icon].
- * @param verticalArrangement The vertical arrangement of the dialog's children. This allows us
- * to add spacing between items and specify the arrangement of the items when we have not enough
- * of them to fill the whole minimum size.
+ * @param verticalArrangement The vertical arrangement of the dialog's children. This allows us to
+ * add spacing between items and specify the arrangement of the items when we have not enough of
+ * them to fill the whole minimum size.
* @param contentPadding The padding to apply around the whole of the dialog's contents.
* @param content A slot for one or more spaced [Chip]s, stacked vertically.
*/
@@ -325,19 +310,13 @@
backgroundColor = backgroundColor,
) {
if (icon != null) {
- item {
- DialogIconHeader(iconColor, content = icon)
- }
+ item { DialogIconHeader(iconColor, content = icon) }
}
- item {
- DialogTitle(titleColor, padding = DialogDefaults.TitlePadding, content = title)
- }
+ item { DialogTitle(titleColor, padding = DialogDefaults.TitlePadding, content = title) }
if (message != null) {
- item {
- DialogBody(messageColor, message)
- }
+ item { DialogBody(messageColor, message) }
}
content()
@@ -345,32 +324,32 @@
}
/**
- * [Alert] lays out the content for an opinionated, alert screen.
- * This overload offers 4 slots for title, optional icon, optional message text and
- * a content slot expected to be one or more vertically stacked [Chip]s or [ToggleChip]s.
- * [Alert] is scrollable by default if the content is taller than the viewport.
+ * [Alert] lays out the content for an opinionated, alert screen. This overload offers 4 slots for
+ * title, optional icon, optional message text and a content slot expected to be one or more
+ * vertically stacked [Chip]s or [ToggleChip]s. [Alert] is scrollable by default if the content is
+ * taller than the viewport.
*
- * [Alert] can be used as a destination in a navigation graph
- * e.g. using SwipeDismissableNavHost. However, for a conventional fullscreen dialog,
- * displayed on top of other content, use [Dialog].
+ * [Alert] can be used as a destination in a navigation graph e.g. using SwipeDismissableNavHost.
+ * However, for a conventional fullscreen dialog, displayed on top of other content, use [Dialog].
*
* Example of an [Alert] with an icon, title, message text and chips:
+ *
* @sample androidx.wear.compose.material.samples.AlertWithChips
*
- * @param title A slot for displaying the title of the dialog,
- * expected to be one or two lines of text.
+ * @param title A slot for displaying the title of the dialog, expected to be one or two lines of
+ * text.
* @param modifier Modifier to be applied to the dialog.
* @param icon Optional slot for an icon to be shown at the top of the dialog.
* @param message Optional slot for additional message content, expected to be 2-3 lines of text.
* @param scrollState The scroll state for the dialog so that the scroll position can be displayed
- * e.g. by the [PositionIndicator] passed to [Scaffold].
+ * e.g. by the [PositionIndicator] passed to [Scaffold].
* @param backgroundColor [Color] representing the background color for the dialog.
* @param titleColor [Color] representing the color for [title].
* @param messageColor [Color] representing the color for [message].
* @param iconColor [Color] representing the color for [icon].
- * @param verticalArrangement The vertical arrangement of the dialog's children. This allows us
- * to add spacing between items and specify the arrangement of the items when we have not enough
- * of them to fill the whole minimum size.
+ * @param verticalArrangement The vertical arrangement of the dialog's children. This allows us to
+ * add spacing between items and specify the arrangement of the items when we have not enough of
+ * them to fill the whole minimum size.
* @param contentPadding The padding to apply around the whole of the dialog's contents.
* @param content A slot for one or more spaced [Chip]s, stacked vertically.
*/
@@ -378,7 +357,8 @@
@Deprecated(
"This overload is provided for backwards compatibility with Compose for Wear OS 1.1." +
"A newer overload is available which uses ScalingLazyListState and ScalingLazyListScope " +
- "from wear.compose.foundation.lazy package", level = DeprecationLevel.HIDDEN
+ "from wear.compose.foundation.lazy package",
+ level = DeprecationLevel.HIDDEN
)
@Composable
public fun Alert(
@@ -412,9 +392,7 @@
)
}
-/**
- * @VisibleForTesting
- */
+/** @VisibleForTesting */
@Suppress("DEPRECATION")
@Deprecated("Used only for testing")
@Composable
@@ -441,19 +419,13 @@
backgroundColor = backgroundColor,
) {
if (icon != null) {
- item {
- DialogIconHeader(iconColor, content = icon)
- }
+ item { DialogIconHeader(iconColor, content = icon) }
}
- item {
- DialogTitle(titleColor, padding = DialogDefaults.TitlePadding, content = title)
- }
+ item { DialogTitle(titleColor, padding = DialogDefaults.TitlePadding, content = title) }
if (message != null) {
- item {
- DialogBody(messageColor, message)
- }
+ item { DialogBody(messageColor, message) }
}
content()
@@ -461,32 +433,33 @@
}
/**
- * [Confirmation] lays out the content for an opinionated confirmation screen that
- * displays a message to the user for [durationMillis]. It has a slot for an icon or image
- * (which could be animated).
+ * [Confirmation] lays out the content for an opinionated confirmation screen that displays a
+ * message to the user for [durationMillis]. It has a slot for an icon or image (which could be
+ * animated).
*
- * [Confirmation] can be used as a destination in a navigation graph
- * e.g. using SwipeDismissableNavHost. However, for a conventional fullscreen dialog,
- * displayed on top of other content, use [Dialog].
+ * [Confirmation] can be used as a destination in a navigation graph e.g. using
+ * SwipeDismissableNavHost. However, for a conventional fullscreen dialog, displayed on top of other
+ * content, use [Dialog].
*
* Example of a [Confirmation] with animation:
+ *
* @sample androidx.wear.compose.material.samples.ConfirmationWithAnimation
*
* @param onTimeout Event invoked when the dialog has been shown for [durationMillis].
* @param modifier Modifier to be applied to the dialog.
* @param icon An optional slot for displaying an icon or image.
* @param scrollState The scroll state for the dialog so that the scroll position can be displayed
- * e.g. by the [PositionIndicator] passed to [Scaffold].
- * @param durationMillis The number of milliseconds for which the dialog is displayed,
- * must be positive. Suggested values are [DialogDefaults.ShortDurationMillis],
- * [DialogDefaults.LongDurationMillis] or [DialogDefaults.IndefiniteDurationMillis].
+ * e.g. by the [PositionIndicator] passed to [Scaffold].
+ * @param durationMillis The number of milliseconds for which the dialog is displayed, must be
+ * positive. Suggested values are [DialogDefaults.ShortDurationMillis],
+ * [DialogDefaults.LongDurationMillis] or [DialogDefaults.IndefiniteDurationMillis].
* @param backgroundColor [Color] representing the background color for this dialog.
* @param contentColor [Color] representing the color for [content].
- * @param iconColor Icon [Color] that defaults to the [contentColor],
- * unless specifically overridden.
- * @param verticalArrangement The vertical arrangement of the dialog's children. This allows us
- * to add spacing between items and specify the arrangement of the items when we have not enough
- * of them to fill the whole minimum size.
+ * @param iconColor Icon [Color] that defaults to the [contentColor], unless specifically
+ * overridden.
+ * @param verticalArrangement The vertical arrangement of the dialog's children. This allows us to
+ * add spacing between items and specify the arrangement of the items when we have not enough of
+ * them to fill the whole minimum size.
* @param contentPadding The padding to apply around the whole of the dialog's contents.
* @param content A slot for the dialog title, expected to be one line of text.
*/
@@ -521,9 +494,7 @@
backgroundColor = backgroundColor,
) {
if (icon != null) {
- item {
- DialogIconHeader(iconColor, content = icon)
- }
+ item { DialogIconHeader(iconColor, content = icon) }
}
item {
@@ -537,40 +508,42 @@
}
/**
- * [Confirmation] lays out the content for an opinionated confirmation screen that
- * displays a message to the user for [durationMillis]. It has a slot for an icon or image
- * (which could be animated).
+ * [Confirmation] lays out the content for an opinionated confirmation screen that displays a
+ * message to the user for [durationMillis]. It has a slot for an icon or image (which could be
+ * animated).
*
- * [Confirmation] can be used as a destination in a navigation graph
- * e.g. using SwipeDismissableNavHost. However, for a conventional fullscreen dialog,
- * displayed on top of other content, use [Dialog].
+ * [Confirmation] can be used as a destination in a navigation graph e.g. using
+ * SwipeDismissableNavHost. However, for a conventional fullscreen dialog, displayed on top of other
+ * content, use [Dialog].
*
* Example of a [Confirmation] with animation:
+ *
* @sample androidx.wear.compose.material.samples.ConfirmationWithAnimation
*
* @param onTimeout Event invoked when the dialog has been shown for [durationMillis].
* @param modifier Modifier to be applied to the dialog.
* @param icon An optional slot for displaying an icon or image.
* @param scrollState The scroll state for the dialog so that the scroll position can be displayed
- * e.g. by the [PositionIndicator] passed to [Scaffold].
- * @param durationMillis The number of milliseconds for which the dialog is displayed,
- * must be positive. Suggested values are [DialogDefaults.ShortDurationMillis],
- * [DialogDefaults.LongDurationMillis] or [DialogDefaults.IndefiniteDurationMillis].
+ * e.g. by the [PositionIndicator] passed to [Scaffold].
+ * @param durationMillis The number of milliseconds for which the dialog is displayed, must be
+ * positive. Suggested values are [DialogDefaults.ShortDurationMillis],
+ * [DialogDefaults.LongDurationMillis] or [DialogDefaults.IndefiniteDurationMillis].
* @param backgroundColor [Color] representing the background color for this dialog.
* @param contentColor [Color] representing the color for [content].
- * @param iconColor Icon [Color] that defaults to the [contentColor],
- * unless specifically overridden.
- * @param verticalArrangement The vertical arrangement of the dialog's children. This allows us
- * to add spacing between items and specify the arrangement of the items when we have not enough
- * of them to fill the whole minimum size.
+ * @param iconColor Icon [Color] that defaults to the [contentColor], unless specifically
+ * overridden.
+ * @param verticalArrangement The vertical arrangement of the dialog's children. This allows us to
+ * add spacing between items and specify the arrangement of the items when we have not enough of
+ * them to fill the whole minimum size.
* @param contentPadding The padding to apply around the whole of the dialog's contents.
* @param content A slot for the dialog title, expected to be one line of text.
*/
@Suppress("DEPRECATION")
@Deprecated(
- "This overload is provided for backwards compatibility with Compose for Wear OS 1.1." +
+ "This overload is provided for backwards compatibility with Compose for Wear OS 1.1." +
"A newer overload is available which uses ScalingLazyListState from " +
- "wear.compose.foundation.lazy package", level = DeprecationLevel.HIDDEN
+ "wear.compose.foundation.lazy package",
+ level = DeprecationLevel.HIDDEN
)
@Composable
public fun Confirmation(
@@ -602,9 +575,7 @@
)
}
-/**
- * @VisibleForTesting
- */
+/** @VisibleForTesting */
@Suppress("DEPRECATION")
@Deprecated("Used only for testing")
@Composable
@@ -639,9 +610,7 @@
backgroundColor = backgroundColor,
) {
if (icon != null) {
- item {
- DialogIconHeader(iconColor, content = icon)
- }
+ item { DialogIconHeader(iconColor, content = icon) }
}
item {
@@ -654,88 +623,56 @@
}
}
-/**
- * Contains the default values used by [Alert] and [Confirmation].
- */
+/** Contains the default values used by [Alert] and [Confirmation]. */
public object DialogDefaults {
- /**
- * Creates the recommended vertical arrangement for [Alert] dialog content.
- */
- public val AlertVerticalArrangement =
- Arrangement.spacedBy(4.dp, Alignment.CenterVertically)
+ /** Creates the recommended vertical arrangement for [Alert] dialog content. */
+ public val AlertVerticalArrangement = Arrangement.spacedBy(4.dp, Alignment.CenterVertically)
- /**
- * Creates the recommended vertical arrangement for [Confirmation] dialog content.
- */
+ /** Creates the recommended vertical arrangement for [Confirmation] dialog content. */
public val ConfirmationVerticalArrangement =
Arrangement.spacedBy(space = 8.dp, alignment = Alignment.CenterVertically)
- /**
- * The padding to apply around the contents.
- */
+ /** The padding to apply around the contents. */
public val ContentPadding = PaddingValues(horizontal = 10.dp)
- /**
- * Short duration for showing [Confirmation].
- */
+ /** Short duration for showing [Confirmation]. */
public val ShortDurationMillis = 4000L
- /**
- * Long duration for showing [Confirmation].
- */
+ /** Long duration for showing [Confirmation]. */
public val LongDurationMillis = 10000L
- /**
- * Show [Confirmation] indefinitely (supports swipe-to-dismiss).
- */
+ /** Show [Confirmation] indefinitely (supports swipe-to-dismiss). */
public val IndefiniteDurationMillis = Long.MAX_VALUE
- /**
- * Spacing between [Button]s.
- */
+ /** Spacing between [Button]s. */
internal val ButtonSpacing = 12.dp
- /**
- * Spacing below [Icon].
- */
+ /** Spacing below [Icon]. */
internal val IconSpacing = 4.dp
- /**
- * Padding around body content.
- */
+ /** Padding around body content. */
internal val BodyPadding
- @Composable get() =
- if (isRoundDevice())
- PaddingValues(start = 8.dp, end = 8.dp, top = 0.dp, bottom = 12.dp)
- else
- PaddingValues(start = 5.dp, end = 5.dp, top = 0.dp, bottom = 12.dp)
+ @Composable
+ get() =
+ if (isRoundDevice()) PaddingValues(start = 8.dp, end = 8.dp, top = 0.dp, bottom = 12.dp)
+ else PaddingValues(start = 5.dp, end = 5.dp, top = 0.dp, bottom = 12.dp)
- /**
- * Padding around title text.
- */
+ /** Padding around title text. */
internal val TitlePadding
- @Composable get() =
+ @Composable
+ get() =
if (isRoundDevice())
- PaddingValues(
- start = 14.dp,
- end = 14.dp,
- top = 0.dp,
- bottom = 8.dp
- )
- else
- PaddingValues(start = 5.dp, end = 5.dp, top = 0.dp, bottom = 8.dp)
+ PaddingValues(start = 14.dp, end = 14.dp, top = 0.dp, bottom = 8.dp)
+ else PaddingValues(start = 5.dp, end = 5.dp, top = 0.dp, bottom = 8.dp)
- /**
- * Bottom padding for title text.
- */
+ /** Bottom padding for title text. */
internal val TitleBottomPadding
- @Composable get() =
- PaddingValues(start = 0.dp, end = 0.dp, top = 0.dp, bottom = 16.dp)
+ @Composable get() = PaddingValues(start = 0.dp, end = 0.dp, top = 0.dp, bottom = 16.dp)
}
/**
- * Common Wear Material dialog implementation that offers a single content slot,
- * fills the screen and is scrollable by default if the content is taller than the viewport.
+ * Common Wear Material dialog implementation that offers a single content slot, fills the screen
+ * and is scrollable by default if the content is taller than the viewport.
*/
@Composable
private fun DialogImpl(
@@ -752,16 +689,14 @@
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = verticalArrangement,
contentPadding = contentPadding,
- modifier = modifier
- .fillMaxSize()
- .background(backgroundColor),
+ modifier = modifier.fillMaxSize().background(backgroundColor),
content = content
)
}
/**
- * Common Wear Material dialog implementation that offers a single content slot,
- * fills the screen and is scrollable by default if the content is taller than the viewport.
+ * Common Wear Material dialog implementation that offers a single content slot, fills the screen
+ * and is scrollable by default if the content is taller than the viewport.
*/
@Suppress("DEPRECATION")
@Deprecated(
@@ -783,36 +718,26 @@
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = verticalArrangement,
contentPadding = contentPadding,
- modifier = modifier
- .fillMaxSize()
- .background(backgroundColor),
+ modifier = modifier.fillMaxSize().background(backgroundColor),
content = content
)
}
/**
- * [DialogIconHeader] displays an icon at the top of the dialog
- * followed by the recommended spacing.
+ * [DialogIconHeader] displays an icon at the top of the dialog followed by the recommended spacing.
*
* @param iconColor [Color] in which to tint the icon.
* @param content Slot for an icon.
*/
@Composable
-private fun DialogIconHeader(
- iconColor: Color,
- content: @Composable ColumnScope.() -> Unit
-) {
+private fun DialogIconHeader(iconColor: Color, content: @Composable ColumnScope.() -> Unit) {
CompositionLocalProvider(LocalContentColor provides iconColor) {
Column(
modifier = Modifier.fillMaxWidth(),
horizontalAlignment = Alignment.CenterHorizontally
) {
content()
- Spacer(
- Modifier
- .fillMaxWidth()
- .height(DialogDefaults.IconSpacing)
- )
+ Spacer(Modifier.fillMaxWidth().height(DialogDefaults.IconSpacing))
}
}
}
@@ -840,21 +765,13 @@
}
}
-/**
- * [DialogBody] displays the body content in a dialog with recommended padding.
- */
+/** [DialogBody] displays the body content in a dialog with recommended padding. */
@Composable
-private fun DialogBody(
- bodyColor: Color,
- content: @Composable ColumnScope.() -> Unit
-) {
+private fun DialogBody(bodyColor: Color, content: @Composable ColumnScope.() -> Unit) {
CompositionLocalProvider(
LocalContentColor provides bodyColor,
LocalTextStyle provides MaterialTheme.typography.body2
) {
- Column(
- modifier = Modifier.padding(DialogDefaults.BodyPadding),
- content = content
- )
+ Column(modifier = Modifier.padding(DialogDefaults.BodyPadding), content = content)
}
}
diff --git a/wear/compose/compose-material3/benchmark/src/androidTest/java/androidx/wear/compose/material3/benchmark/ButtonBenchmark.kt b/wear/compose/compose-material3/benchmark/src/androidTest/java/androidx/wear/compose/material3/benchmark/ButtonBenchmark.kt
index 564847a..7a5e969 100644
--- a/wear/compose/compose-material3/benchmark/src/androidTest/java/androidx/wear/compose/material3/benchmark/ButtonBenchmark.kt
+++ b/wear/compose/compose-material3/benchmark/src/androidTest/java/androidx/wear/compose/material3/benchmark/ButtonBenchmark.kt
@@ -38,13 +38,10 @@
class ButtonBenchmark(private val buttonType: ButtonType) {
companion object {
- @Parameterized.Parameters(name = "{0}")
- @JvmStatic
- fun parameters() = ButtonType.values()
+ @Parameterized.Parameters(name = "{0}") @JvmStatic fun parameters() = ButtonType.values()
}
- @get:Rule
- val benchmarkRule = ComposeBenchmarkRule()
+ @get:Rule val benchmarkRule = ComposeBenchmarkRule()
private val buttonTestCaseFactory = { ButtonTestCase(buttonType) }
@@ -54,14 +51,11 @@
}
}
-internal class ButtonTestCase(
- private val buttonType: ButtonType
-) : LayeredComposeTestCase() {
+internal class ButtonTestCase(private val buttonType: ButtonType) : LayeredComposeTestCase() {
@Composable
override fun MeasuredContent() {
when (buttonType) {
- ButtonType.FilledButton ->
- Button(onClick = { /* do something */ }) { Text("Button") }
+ ButtonType.FilledButton -> Button(onClick = { /* do something */ }) { Text("Button") }
ButtonType.FilledTonalButton ->
FilledTonalButton(onClick = { /* do something */ }) { Text("Filled Tonal Button") }
ButtonType.OutlinedButton ->
@@ -75,12 +69,14 @@
@Composable
override fun ContentWrappers(content: @Composable () -> Unit) {
- MaterialTheme {
- content()
- }
+ MaterialTheme { content() }
}
}
enum class ButtonType {
- FilledButton, FilledTonalButton, OutlinedButton, ChildButton, CompactButton
+ FilledButton,
+ FilledTonalButton,
+ OutlinedButton,
+ ChildButton,
+ CompactButton
}
diff --git a/wear/compose/compose-material3/benchmark/src/androidTest/java/androidx/wear/compose/material3/benchmark/CardBenchmark.kt b/wear/compose/compose-material3/benchmark/src/androidTest/java/androidx/wear/compose/material3/benchmark/CardBenchmark.kt
index 1e24a83..c534575 100644
--- a/wear/compose/compose-material3/benchmark/src/androidTest/java/androidx/wear/compose/material3/benchmark/CardBenchmark.kt
+++ b/wear/compose/compose-material3/benchmark/src/androidTest/java/androidx/wear/compose/material3/benchmark/CardBenchmark.kt
@@ -37,13 +37,10 @@
class CardBenchmark(private val type: CardType) {
companion object {
- @Parameterized.Parameters(name = "{0}")
- @JvmStatic
- fun parameters() = CardType.values()
+ @Parameterized.Parameters(name = "{0}") @JvmStatic fun parameters() = CardType.values()
}
- @get:Rule
- val benchmarkRule = ComposeBenchmarkRule()
+ @get:Rule val benchmarkRule = ComposeBenchmarkRule()
private val cardTestCaseFactory = { CardTestCase(type) }
@@ -58,16 +55,15 @@
@Composable
override fun MeasuredContent() {
when (type) {
- CardType.Card ->
- Card(onClick = { /* do something */ }) { Text("Card") }
-
+ CardType.Card -> Card(onClick = { /* do something */ }) { Text("Card") }
CardType.AppCard ->
AppCard(
onClick = { /* do something */ },
appName = { Text("App name") },
title = { Text("Card title") },
- ) { Text("App Card") }
-
+ ) {
+ Text("App Card")
+ }
CardType.TitleCard ->
TitleCard(
onClick = { /* do something */ },
@@ -75,7 +71,6 @@
) {
Text("Title Card")
}
-
CardType.OutlinedCard ->
OutlinedCard(onClick = { /* do something */ }) { Text("Outlined Card") }
}
@@ -83,12 +78,13 @@
@Composable
override fun ContentWrappers(content: @Composable () -> Unit) {
- MaterialTheme {
- content()
- }
+ MaterialTheme { content() }
}
}
enum class CardType {
- Card, AppCard, TitleCard, OutlinedCard
+ Card,
+ AppCard,
+ TitleCard,
+ OutlinedCard
}
diff --git a/wear/compose/compose-material3/benchmark/src/androidTest/java/androidx/wear/compose/material3/benchmark/ColorSchemeBenchmark.kt b/wear/compose/compose-material3/benchmark/src/androidTest/java/androidx/wear/compose/material3/benchmark/ColorSchemeBenchmark.kt
index 2e6efe4..e4bd58a 100644
--- a/wear/compose/compose-material3/benchmark/src/androidTest/java/androidx/wear/compose/material3/benchmark/ColorSchemeBenchmark.kt
+++ b/wear/compose/compose-material3/benchmark/src/androidTest/java/androidx/wear/compose/material3/benchmark/ColorSchemeBenchmark.kt
@@ -37,8 +37,7 @@
@MediumTest
@RunWith(AndroidJUnit4::class)
class ColorSchemeBenchmark {
- @get:Rule
- val benchmarkRule = ComposeBenchmarkRule()
+ @get:Rule val benchmarkRule = ComposeBenchmarkRule()
private val colorSchemeTestCaseFactory = { ColorSchemeTestCase() }
@@ -57,113 +56,121 @@
// Primary
Box(modifier = Modifier.size(1.dp).background(MaterialTheme.colorScheme.primary))
Box(
- modifier = Modifier.size(1.dp).background(
- MaterialTheme.colorScheme.contentColorFor(MaterialTheme.colorScheme.primary)
- )
+ modifier =
+ Modifier.size(1.dp)
+ .background(
+ MaterialTheme.colorScheme.contentColorFor(
+ MaterialTheme.colorScheme.primary
+ )
+ )
)
// Primary Container
Box(
- modifier = Modifier
- .size(1.dp)
- .background(MaterialTheme.colorScheme.primaryContainer)
+ modifier =
+ Modifier.size(1.dp).background(MaterialTheme.colorScheme.primaryContainer)
)
Box(
- modifier = Modifier
- .size(1.dp)
- .background(
- MaterialTheme.colorScheme.contentColorFor(
- MaterialTheme.colorScheme.primaryContainer
+ modifier =
+ Modifier.size(1.dp)
+ .background(
+ MaterialTheme.colorScheme.contentColorFor(
+ MaterialTheme.colorScheme.primaryContainer
+ )
)
- )
)
// Secondary
Box(modifier = Modifier.size(1.dp).background(MaterialTheme.colorScheme.secondary))
Box(
- modifier = Modifier
- .size(1.dp)
- .background(
- MaterialTheme.colorScheme.contentColorFor(
- MaterialTheme.colorScheme.secondary
+ modifier =
+ Modifier.size(1.dp)
+ .background(
+ MaterialTheme.colorScheme.contentColorFor(
+ MaterialTheme.colorScheme.secondary
+ )
)
- )
)
// Secondary Container
Box(
- modifier = Modifier
- .size(1.dp)
- .background(MaterialTheme.colorScheme.secondaryContainer)
+ modifier =
+ Modifier.size(1.dp).background(MaterialTheme.colorScheme.secondaryContainer)
)
Box(
- modifier = Modifier
- .size(1.dp)
- .background(
- MaterialTheme.colorScheme.contentColorFor(
- MaterialTheme.colorScheme.secondaryContainer
+ modifier =
+ Modifier.size(1.dp)
+ .background(
+ MaterialTheme.colorScheme.contentColorFor(
+ MaterialTheme.colorScheme.secondaryContainer
+ )
)
- )
)
// Tertiary
Box(modifier = Modifier.size(1.dp).background(MaterialTheme.colorScheme.tertiary))
Box(
- modifier = Modifier
- .size(1.dp)
- .background(
- MaterialTheme.colorScheme.contentColorFor(
- MaterialTheme.colorScheme.tertiary
+ modifier =
+ Modifier.size(1.dp)
+ .background(
+ MaterialTheme.colorScheme.contentColorFor(
+ MaterialTheme.colorScheme.tertiary
+ )
)
- )
)
// Tertiary Container
Box(
- modifier = Modifier
- .size(1.dp)
- .background(MaterialTheme.colorScheme.tertiaryContainer)
+ modifier =
+ Modifier.size(1.dp).background(MaterialTheme.colorScheme.tertiaryContainer)
)
Box(
- modifier = Modifier
- .size(1.dp)
- .background(
- MaterialTheme.colorScheme.contentColorFor(
- MaterialTheme.colorScheme.tertiaryContainer
+ modifier =
+ Modifier.size(1.dp)
+ .background(
+ MaterialTheme.colorScheme.contentColorFor(
+ MaterialTheme.colorScheme.tertiaryContainer
+ )
)
- )
)
// Surface
- Box(modifier = Modifier
- .size(1.dp)
- .background(MaterialTheme.colorScheme.surfaceContainer))
- Box(modifier = Modifier
- .size(1.dp)
- .background(
- MaterialTheme.colorScheme
- .contentColorFor(MaterialTheme.colorScheme.surfaceContainer)
- )
+ Box(
+ modifier =
+ Modifier.size(1.dp).background(MaterialTheme.colorScheme.surfaceContainer)
+ )
+ Box(
+ modifier =
+ Modifier.size(1.dp)
+ .background(
+ MaterialTheme.colorScheme.contentColorFor(
+ MaterialTheme.colorScheme.surfaceContainer
+ )
+ )
)
// Background
Box(modifier = Modifier.size(1.dp).background(MaterialTheme.colorScheme.background))
Box(
- modifier = Modifier
- .size(1.dp)
- .background(
- MaterialTheme.colorScheme.contentColorFor(
- MaterialTheme.colorScheme.background
+ modifier =
+ Modifier.size(1.dp)
+ .background(
+ MaterialTheme.colorScheme.contentColorFor(
+ MaterialTheme.colorScheme.background
+ )
)
- )
)
// Error
Box(modifier = Modifier.size(1.dp).background(MaterialTheme.colorScheme.error))
Box(
- modifier = Modifier.size(1.dp).background(
- MaterialTheme.colorScheme.contentColorFor(MaterialTheme.colorScheme.error)
- )
+ modifier =
+ Modifier.size(1.dp)
+ .background(
+ MaterialTheme.colorScheme.contentColorFor(
+ MaterialTheme.colorScheme.error
+ )
+ )
)
}
}
diff --git a/wear/compose/compose-material3/benchmark/src/androidTest/java/androidx/wear/compose/material3/benchmark/IconBenchmark.kt b/wear/compose/compose-material3/benchmark/src/androidTest/java/androidx/wear/compose/material3/benchmark/IconBenchmark.kt
index 12f524f..e8d85cc 100644
--- a/wear/compose/compose-material3/benchmark/src/androidTest/java/androidx/wear/compose/material3/benchmark/IconBenchmark.kt
+++ b/wear/compose/compose-material3/benchmark/src/androidTest/java/androidx/wear/compose/material3/benchmark/IconBenchmark.kt
@@ -41,21 +41,16 @@
import org.junit.runner.RunWith
import org.junit.runners.Parameterized
-/**
- * Benchmark for Wear Compose Material 3 [Icon].
- */
+/** Benchmark for Wear Compose Material 3 [Icon]. */
@LargeTest
@RunWith(Parameterized::class)
class IconBenchmark(private val iconType: IconType) {
companion object {
- @Parameterized.Parameters(name = "{0}")
- @JvmStatic
- fun parameters() = IconType.values()
+ @Parameterized.Parameters(name = "{0}") @JvmStatic fun parameters() = IconType.values()
}
- @get:Rule
- val benchmarkRule = ComposeBenchmarkRule()
+ @get:Rule val benchmarkRule = ComposeBenchmarkRule()
private val iconCaseFactory = { IconTestCase(iconType) }
@@ -95,56 +90,46 @@
}
}
-internal class IconTestCase(
- private val iconType: IconType
-) : LayeredComposeTestCase() {
+internal class IconTestCase(private val iconType: IconType) : LayeredComposeTestCase() {
private val width = 24.dp
private val height = 24.dp
- private val imageVector = ImageVector.Builder(
- defaultWidth = width, defaultHeight = height,
- viewportWidth = width.value, viewportHeight = height.value
- ).build()
- private val imageBitmap = ImageBitmap(
- width = width.value.toInt(),
- height = height.value.toInt()
- )
- private val painter = object : Painter() {
- override fun DrawScope.onDraw() {
- drawRect(color = Color.Black)
- }
+ private val imageVector =
+ ImageVector.Builder(
+ defaultWidth = width,
+ defaultHeight = height,
+ viewportWidth = width.value,
+ viewportHeight = height.value
+ )
+ .build()
+ private val imageBitmap =
+ ImageBitmap(width = width.value.toInt(), height = height.value.toInt())
+ private val painter =
+ object : Painter() {
+ override fun DrawScope.onDraw() {
+ drawRect(color = Color.Black)
+ }
- override val intrinsicSize: Size
- get() = Size(width.value, height.value)
- }
+ override val intrinsicSize: Size
+ get() = Size(width.value, height.value)
+ }
@Composable
override fun MeasuredContent() {
when (iconType) {
- IconType.ImageVector -> Icon(
- imageVector = imageVector,
- contentDescription = "vector"
- )
-
- IconType.Bitmap -> Icon(
- bitmap = imageBitmap,
- contentDescription = "bitmap"
- )
-
- IconType.Painter -> Icon(
- painter = painter,
- contentDescription = "painter"
- )
+ IconType.ImageVector -> Icon(imageVector = imageVector, contentDescription = "vector")
+ IconType.Bitmap -> Icon(bitmap = imageBitmap, contentDescription = "bitmap")
+ IconType.Painter -> Icon(painter = painter, contentDescription = "painter")
}
}
@Composable
override fun ContentWrappers(content: @Composable () -> Unit) {
- MaterialTheme {
- content()
- }
+ MaterialTheme { content() }
}
}
enum class IconType {
- ImageVector, Bitmap, Painter
+ ImageVector,
+ Bitmap,
+ Painter
}
diff --git a/wear/compose/compose-material3/benchmark/src/androidTest/java/androidx/wear/compose/material3/benchmark/SelectableButtonBenchmark.kt b/wear/compose/compose-material3/benchmark/src/androidTest/java/androidx/wear/compose/material3/benchmark/SelectableButtonBenchmark.kt
index 09dcc03..93f4022 100644
--- a/wear/compose/compose-material3/benchmark/src/androidTest/java/androidx/wear/compose/material3/benchmark/SelectableButtonBenchmark.kt
+++ b/wear/compose/compose-material3/benchmark/src/androidTest/java/androidx/wear/compose/material3/benchmark/SelectableButtonBenchmark.kt
@@ -34,8 +34,7 @@
@RunWith(AndroidJUnit4::class)
class SelectableButtonBenchmark {
- @get:Rule
- val benchmarkRule = ComposeBenchmarkRule()
+ @get:Rule val benchmarkRule = ComposeBenchmarkRule()
private val selectableButtonTestCaseFactory = {
SelectableButtonTestCase(SelectableButtonType.SelectableButton)
@@ -56,9 +55,8 @@
}
}
-internal class SelectableButtonTestCase(
- private val type: SelectableButtonType
-) : LayeredComposeTestCase() {
+internal class SelectableButtonTestCase(private val type: SelectableButtonType) :
+ LayeredComposeTestCase() {
@Composable
override fun MeasuredContent() {
if (type == SelectableButtonType.SelectableButton) {
@@ -69,7 +67,8 @@
SplitSelectableButton(
selected = true,
onSelectionClick = { /* do something */ },
- onContainerClick = { /* do something */ }) {
+ onContainerClick = { /* do something */ }
+ ) {
Text(text = "SplitSelectableButton")
}
}
@@ -77,12 +76,11 @@
@Composable
override fun ContentWrappers(content: @Composable () -> Unit) {
- MaterialTheme {
- content()
- }
+ MaterialTheme { content() }
}
}
enum class SelectableButtonType {
- SelectableButton, SplitSelectableButton
+ SelectableButton,
+ SplitSelectableButton
}
diff --git a/wear/compose/compose-material3/benchmark/src/androidTest/java/androidx/wear/compose/material3/benchmark/TextBenchmark.kt b/wear/compose/compose-material3/benchmark/src/androidTest/java/androidx/wear/compose/material3/benchmark/TextBenchmark.kt
index 2532b47..d5640f4 100644
--- a/wear/compose/compose-material3/benchmark/src/androidTest/java/androidx/wear/compose/material3/benchmark/TextBenchmark.kt
+++ b/wear/compose/compose-material3/benchmark/src/androidTest/java/androidx/wear/compose/material3/benchmark/TextBenchmark.kt
@@ -34,15 +34,12 @@
import org.junit.Test
import org.junit.runner.RunWith
-/**
- * Benchmark for Wear Compose Material 3 [Text].
- */
+/** Benchmark for Wear Compose Material 3 [Text]. */
@LargeTest
@RunWith(AndroidJUnit4::class)
class TextBenchmark {
- @get:Rule
- val benchmarkRule = ComposeBenchmarkRule()
+ @get:Rule val benchmarkRule = ComposeBenchmarkRule()
private val textCaseFactory = { TextTestCase() }
@@ -90,8 +87,6 @@
@Composable
override fun ContentWrappers(content: @Composable () -> Unit) {
- MaterialTheme {
- content()
- }
+ MaterialTheme { content() }
}
}
diff --git a/wear/compose/compose-material3/benchmark/src/androidTest/java/androidx/wear/compose/material3/benchmark/TextButtonBenchmark.kt b/wear/compose/compose-material3/benchmark/src/androidTest/java/androidx/wear/compose/material3/benchmark/TextButtonBenchmark.kt
index aa17033..311f798 100644
--- a/wear/compose/compose-material3/benchmark/src/androidTest/java/androidx/wear/compose/material3/benchmark/TextButtonBenchmark.kt
+++ b/wear/compose/compose-material3/benchmark/src/androidTest/java/androidx/wear/compose/material3/benchmark/TextButtonBenchmark.kt
@@ -40,8 +40,7 @@
fun parameters() = TextButtonType.values()
}
- @get:Rule
- val benchmarkRule = ComposeBenchmarkRule()
+ @get:Rule val benchmarkRule = ComposeBenchmarkRule()
private val testCaseFactory = { TextButtonTestCase(textButtonType) }
@@ -51,46 +50,42 @@
}
}
-internal class TextButtonTestCase(
- private val textButtonType: TextButtonType
-) : LayeredComposeTestCase() {
+internal class TextButtonTestCase(private val textButtonType: TextButtonType) :
+ LayeredComposeTestCase() {
@Composable
override fun MeasuredContent() {
when (textButtonType) {
TextButtonType.FilledTextButton ->
- TextButton(
- onClick = {},
- colors = TextButtonDefaults.filledTextButtonColors()
- ) { Text("ABC") }
-
+ TextButton(onClick = {}, colors = TextButtonDefaults.filledTextButtonColors()) {
+ Text("ABC")
+ }
TextButtonType.FilledTonalTextButton ->
TextButton(
onClick = {},
colors = TextButtonDefaults.filledTonalTextButtonColors()
- ) { Text("ABC") }
-
+ ) {
+ Text("ABC")
+ }
TextButtonType.OutlinedTextButton ->
- TextButton(
- onClick = {},
- colors = TextButtonDefaults.outlinedTextButtonColors()
- ) { Text("ABC") }
-
+ TextButton(onClick = {}, colors = TextButtonDefaults.outlinedTextButtonColors()) {
+ Text("ABC")
+ }
TextButtonType.TextButton ->
- TextButton(
- onClick = {},
- colors = TextButtonDefaults.textButtonColors()
- ) { Text("ABC") }
+ TextButton(onClick = {}, colors = TextButtonDefaults.textButtonColors()) {
+ Text("ABC")
+ }
}
}
@Composable
override fun ContentWrappers(content: @Composable () -> Unit) {
- MaterialTheme {
- content()
- }
+ MaterialTheme { content() }
}
}
enum class TextButtonType {
- FilledTextButton, FilledTonalTextButton, OutlinedTextButton, TextButton
+ FilledTextButton,
+ FilledTonalTextButton,
+ OutlinedTextButton,
+ TextButton
}
diff --git a/wear/compose/compose-material3/benchmark/src/androidTest/java/androidx/wear/compose/material3/benchmark/TextToggleButtonBenchmark.kt b/wear/compose/compose-material3/benchmark/src/androidTest/java/androidx/wear/compose/material3/benchmark/TextToggleButtonBenchmark.kt
index 3c5b87e..6bfc465 100644
--- a/wear/compose/compose-material3/benchmark/src/androidTest/java/androidx/wear/compose/material3/benchmark/TextToggleButtonBenchmark.kt
+++ b/wear/compose/compose-material3/benchmark/src/androidTest/java/androidx/wear/compose/material3/benchmark/TextToggleButtonBenchmark.kt
@@ -39,8 +39,7 @@
fun parameters() = TextToggleButtonType.values()
}
- @get:Rule
- val benchmarkRule = ComposeBenchmarkRule()
+ @get:Rule val benchmarkRule = ComposeBenchmarkRule()
private val testCaseFactory = { TextToggleButtonTestCase(type) }
@@ -50,34 +49,25 @@
}
}
-internal class TextToggleButtonTestCase(
- private val type: TextToggleButtonType
-) : LayeredComposeTestCase() {
+internal class TextToggleButtonTestCase(private val type: TextToggleButtonType) :
+ LayeredComposeTestCase() {
@Composable
override fun MeasuredContent() {
when (type) {
TextToggleButtonType.TextToggleButtonOn ->
- TextToggleButton(
- checked = true,
- onCheckedChange = {}
- ) { Text("On") }
-
+ TextToggleButton(checked = true, onCheckedChange = {}) { Text("On") }
TextToggleButtonType.TextToggleButtonOff ->
- TextToggleButton(
- checked = false,
- onCheckedChange = {}
- ) { Text("Off") }
+ TextToggleButton(checked = false, onCheckedChange = {}) { Text("Off") }
}
}
@Composable
override fun ContentWrappers(content: @Composable () -> Unit) {
- MaterialTheme {
- content()
- }
+ MaterialTheme { content() }
}
}
enum class TextToggleButtonType {
- TextToggleButtonOn, TextToggleButtonOff
+ TextToggleButtonOn,
+ TextToggleButtonOff
}
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 7cf93a0..ae67b73 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
@@ -64,34 +64,16 @@
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
) {
+ item { ListHeader { Text("1 slot button") } }
+ item { SimpleButtonSample() }
item {
- ListHeader {
- Text("1 slot button")
- }
+ ButtonWithOnLongClick({ showOnClickToast(context) }) { showOnLongClickToast(context) }
}
item {
- SimpleButtonSample()
+ Button(onClick = { /* Do something */ }, label = { Text("Button") }, enabled = false)
}
- item {
- ButtonWithOnLongClick({ showOnClickToast(context) }) {
- showOnLongClickToast(context)
- }
- }
- item {
- Button(
- onClick = { /* Do something */ },
- label = { Text("Button") },
- enabled = false
- )
- }
- item {
- ListHeader {
- Text("3 slot button")
- }
- }
- item {
- ButtonSample()
- }
+ item { ListHeader { Text("3 slot button") } }
+ item { ButtonSample() }
item {
Button(
onClick = { /* Do something */ },
@@ -117,14 +99,8 @@
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
) {
- item {
- ListHeader {
- Text("1 slot button")
- }
- }
- item {
- SimpleFilledTonalButtonSample()
- }
+ item { ListHeader { Text("1 slot button") } }
+ item { SimpleFilledTonalButtonSample() }
item {
FilledTonalButtonWithOnLongClick({ showOnClickToast(context) }) {
showOnLongClickToast(context)
@@ -137,14 +113,8 @@
enabled = false
)
}
- item {
- ListHeader {
- Text("3 slot button")
- }
- }
- item {
- FilledTonalButtonSample()
- }
+ item { ListHeader { Text("3 slot button") } }
+ item { FilledTonalButtonSample() }
item {
FilledTonalButton(
onClick = { /* Do something */ },
@@ -170,14 +140,8 @@
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
) {
- item {
- ListHeader {
- Text("1 slot button")
- }
- }
- item {
- SimpleOutlinedButtonSample()
- }
+ item { ListHeader { Text("1 slot button") } }
+ item { SimpleOutlinedButtonSample() }
item {
OutlinedButtonWithOnLongClick({ showOnClickToast(context) }) {
showOnLongClickToast(context)
@@ -190,14 +154,8 @@
enabled = false
)
}
- item {
- ListHeader {
- Text("3 slot button")
- }
- }
- item {
- OutlinedButtonSample()
- }
+ item { ListHeader { Text("3 slot button") } }
+ item { OutlinedButtonSample() }
item {
OutlinedButton(
onClick = { /* Do something */ },
@@ -223,14 +181,8 @@
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
) {
- item {
- ListHeader {
- Text("1 slot button")
- }
- }
- item {
- SimpleChildButtonSample()
- }
+ item { ListHeader { Text("1 slot button") } }
+ item { SimpleChildButtonSample() }
item {
ChildButtonWithOnLongClick({ showOnClickToast(context) }) {
showOnLongClickToast(context)
@@ -243,14 +195,8 @@
enabled = false
)
}
- item {
- ListHeader {
- Text("3 slot button")
- }
- }
- item {
- ChildButtonSample()
- }
+ item { ListHeader { Text("3 slot button") } }
+ item { ChildButtonSample() }
item {
ChildButton(
onClick = { /* Do something */ },
@@ -276,25 +222,15 @@
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
) {
- item {
- ListHeader {
- Text("2 slot compact button")
- }
- }
- item {
- CompactButtonSample()
- }
+ item { ListHeader { Text("2 slot compact button") } }
+ item { CompactButtonSample() }
item {
CompactButtonWithOnLongClick({ showOnClickToast(context) }) {
showOnLongClickToast(context)
}
}
- item {
- FilledTonalCompactButtonSample()
- }
- item {
- OutlinedCompactButtonSample()
- }
+ item { FilledTonalCompactButtonSample() }
+ item { OutlinedCompactButtonSample() }
item {
CompactButton(
onClick = { /* Do something */ },
@@ -304,11 +240,7 @@
Text("Child Compact Button", maxLines = 1, overflow = TextOverflow.Ellipsis)
}
}
- item {
- ListHeader {
- Text("Icon only compact button")
- }
- }
+ item { ListHeader { Text("Icon only compact button") } }
item {
CompactButton(
onClick = { /* Do something */ },
@@ -337,11 +269,7 @@
colors = ButtonDefaults.childButtonColors()
)
}
- item {
- ListHeader {
- Text("Text only compact button")
- }
- }
+ item { ListHeader { Text("Text only compact button") } }
item {
CompactButton(
onClick = { /* Do something */ },
@@ -383,34 +311,14 @@
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
) {
- item {
- ListHeader {
- Text("3 line label")
- }
- }
- item {
- MultilineButton(enabled = true)
- }
- item {
- MultilineButton(enabled = false)
- }
- item {
- MultilineButton(enabled = true, icon = { StandardIcon(ButtonDefaults.IconSize) })
- }
- item {
- MultilineButton(enabled = false, icon = { StandardIcon(ButtonDefaults.IconSize) })
- }
- item {
- ListHeader {
- Text("5 line button")
- }
- }
- item {
- Multiline3SlotButton(enabled = true)
- }
- item {
- Multiline3SlotButton(enabled = false)
- }
+ item { ListHeader { Text("3 line label") } }
+ item { MultilineButton(enabled = true) }
+ item { MultilineButton(enabled = false) }
+ item { MultilineButton(enabled = true, icon = { StandardIcon(ButtonDefaults.IconSize) }) }
+ item { MultilineButton(enabled = false, icon = { StandardIcon(ButtonDefaults.IconSize) }) }
+ item { ListHeader { Text("5 line button") } }
+ item { Multiline3SlotButton(enabled = true) }
+ item { Multiline3SlotButton(enabled = false) }
item {
Multiline3SlotButton(enabled = true, icon = { StandardIcon(ButtonDefaults.IconSize) })
}
@@ -426,28 +334,12 @@
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
) {
- item {
- ListHeader {
- Text("Label + Avatar")
- }
- }
- item {
- AvatarButton(enabled = true)
- }
- item {
- AvatarButton(enabled = false)
- }
- item {
- ListHeader {
- Text("Primary/Secondary + Avatar")
- }
- }
- item {
- Avatar3SlotButton(enabled = true)
- }
- item {
- Avatar3SlotButton(enabled = false)
- }
+ item { ListHeader { Text("Label + Avatar") } }
+ item { AvatarButton(enabled = true) }
+ item { AvatarButton(enabled = false) }
+ item { ListHeader { Text("Primary/Secondary + Avatar") } }
+ item { Avatar3SlotButton(enabled = true) }
+ item { Avatar3SlotButton(enabled = false) }
}
}
diff --git a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/CardDemo.kt b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/CardDemo.kt
index 9180758..e0cb4f0 100644
--- a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/CardDemo.kt
+++ b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/CardDemo.kt
@@ -87,10 +87,8 @@
) {
Spacer(Modifier.height(6.dp))
Image(
- modifier = Modifier
- .padding(end = 28.dp)
- .aspectRatio(16f / 9f)
- .clip(RoundedCornerShape(16.dp)),
+ modifier =
+ Modifier.padding(end = 28.dp).aspectRatio(16f / 9f).clip(RoundedCornerShape(16.dp)),
painter = painterResource(id = R.drawable.card_background),
contentScale = ContentScale.Crop,
contentDescription = null
diff --git a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/IconButtonDemo.kt b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/IconButtonDemo.kt
index 8ecebb0..e994317 100644
--- a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/IconButtonDemo.kt
+++ b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/IconButtonDemo.kt
@@ -46,79 +46,45 @@
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
) {
- item {
- ListHeader {
- Text("Icon button")
- }
- }
+ item { ListHeader { Text("Icon button") } }
item {
Row {
IconButtonSample()
Spacer(modifier = Modifier.width(5.dp))
- IconButton(
- onClick = { },
- enabled = false
- ) {
- StandardIcon(ButtonDefaults.IconSize)
- }
+ IconButton(onClick = {}, enabled = false) { StandardIcon(ButtonDefaults.IconSize) }
}
}
- item {
- ListHeader {
- Text("Filled Tonal")
- }
- }
+ item { ListHeader { Text("Filled Tonal") } }
item {
Row {
FilledTonalIconButtonSample()
Spacer(modifier = Modifier.width(5.dp))
- FilledTonalIconButton(
- onClick = { },
- enabled = false
- ) {
+ FilledTonalIconButton(onClick = {}, enabled = false) {
StandardIcon(ButtonDefaults.IconSize)
}
}
}
- item {
- ListHeader {
- Text("Filled")
- }
- }
+ item { ListHeader { Text("Filled") } }
item {
Row {
FilledIconButtonSample()
Spacer(modifier = Modifier.width(5.dp))
- FilledIconButton(
- onClick = { },
- enabled = false
- ) {
+ FilledIconButton(onClick = {}, enabled = false) {
StandardIcon(ButtonDefaults.IconSize)
}
}
}
- item {
- ListHeader {
- Text("Outlined")
- }
- }
+ item { ListHeader { Text("Outlined") } }
item {
Row {
OutlinedIconButtonSample()
Spacer(modifier = Modifier.width(5.dp))
- OutlinedIconButton(
- onClick = { },
- enabled = false
- ) {
+ OutlinedIconButton(onClick = {}, enabled = false) {
StandardIcon(ButtonDefaults.IconSize)
}
}
}
- item {
- ListHeader {
- Text("Sizes")
- }
- }
+ item { ListHeader { Text("Sizes") } }
item {
Row(verticalAlignment = Alignment.CenterVertically) {
Text("${IconButtonDefaults.LargeButtonSize.value.toInt()}dp")
@@ -154,7 +120,8 @@
private fun IconButtonWithSize(size: Dp) {
FilledTonalIconButton(
modifier = Modifier.touchTargetAwareSize(size),
- onClick = { /* Do something */ }) {
+ onClick = { /* Do something */ }
+ ) {
StandardIcon(IconButtonDefaults.iconSizeFor(size))
}
}
diff --git a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/IconToggleButtonDemo.kt b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/IconToggleButtonDemo.kt
index 86ac15d..6a9babb 100644
--- a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/IconToggleButtonDemo.kt
+++ b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/IconToggleButtonDemo.kt
@@ -48,11 +48,7 @@
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
) {
- item {
- ListHeader {
- Text("Icon Toggle Button", textAlign = TextAlign.Center)
- }
- }
+ item { ListHeader { Text("Icon Toggle Button", textAlign = TextAlign.Center) } }
item {
Row {
IconToggleButtonSample() // Enabled & checked
@@ -67,11 +63,7 @@
IconToggleButtonsDemo(enabled = false, initialChecked = false)
}
}
- item {
- ListHeader {
- Text("Sizes")
- }
- }
+ item { ListHeader { Text("Sizes") } }
item {
Row(verticalAlignment = Alignment.CenterVertically) {
Text("${IconButtonDefaults.LargeButtonSize.value.toInt()}dp")
diff --git a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/ListHeaderDemo.kt b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/ListHeaderDemo.kt
index f5094c4..e8ceee4 100644
--- a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/ListHeaderDemo.kt
+++ b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/ListHeaderDemo.kt
@@ -26,17 +26,9 @@
@Composable
fun ListHeaderDemo() {
- ScalingLazyColumn(
- modifier = Modifier.fillMaxWidth()
- ) {
- item {
- ListHeaderSample()
- }
- item {
- ListSubheaderSample()
- }
- item {
- ListSubheaderWithIconSample()
- }
+ ScalingLazyColumn(modifier = Modifier.fillMaxWidth()) {
+ item { ListHeaderSample() }
+ item { ListSubheaderSample() }
+ item { ListSubheaderWithIconSample() }
}
}
diff --git a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/ProgressIndicatorDemo.kt b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/ProgressIndicatorDemo.kt
index 25a62eb..f3bd26d 100644
--- a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/ProgressIndicatorDemo.kt
+++ b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/ProgressIndicatorDemo.kt
@@ -39,47 +39,43 @@
import androidx.wear.compose.material3.samples.MediaButtonProgressIndicatorSample
import androidx.wear.compose.material3.samples.OverflowProgressIndicatorSample
-val ProgressIndicatorDemos = listOf(
- DemoCategory(
- "Samples",
- listOf(
- ComposableDemo("Full screen") {
- Centralize {
- FullScreenProgressIndicatorSample()
- }
- },
- ComposableDemo("Media button wrapping") {
- Centralize {
- MediaButtonProgressIndicatorSample()
- }
- },
- ComposableDemo("Overflow progress (>100%)") {
- Centralize {
- OverflowProgressIndicatorSample()
- }
- },
- ComposableDemo("Small sized indicator") {
- Box(
- modifier = Modifier
- .fillMaxSize()
- .background(MaterialTheme.colorScheme.background)
- ) {
- Button({ /* No op */ }, modifier = Modifier.align(Alignment.Center)) {
- Text(
- "Loading...",
- modifier = Modifier.align(Alignment.CenterVertically))
- Spacer(modifier = Modifier.size(10.dp))
- CircularProgressIndicator(
- progress = { 0.75f },
- modifier = Modifier.size(IconButtonDefaults.DefaultButtonSize),
- startAngle = 120f,
- endAngle = 60f,
- strokeWidth = ButtonCircularIndicatorStrokeWidth,
- colors = ProgressIndicatorDefaults.colors(indicatorColor = Color.Red)
- )
+val ProgressIndicatorDemos =
+ listOf(
+ DemoCategory(
+ "Samples",
+ listOf(
+ ComposableDemo("Full screen") {
+ Centralize { FullScreenProgressIndicatorSample() }
+ },
+ ComposableDemo("Media button wrapping") {
+ Centralize { MediaButtonProgressIndicatorSample() }
+ },
+ ComposableDemo("Overflow progress (>100%)") {
+ Centralize { OverflowProgressIndicatorSample() }
+ },
+ ComposableDemo("Small sized indicator") {
+ Box(
+ modifier =
+ Modifier.fillMaxSize().background(MaterialTheme.colorScheme.background)
+ ) {
+ Button({ /* No op */ }, modifier = Modifier.align(Alignment.Center)) {
+ Text(
+ "Loading...",
+ modifier = Modifier.align(Alignment.CenterVertically)
+ )
+ Spacer(modifier = Modifier.size(10.dp))
+ CircularProgressIndicator(
+ progress = { 0.75f },
+ modifier = Modifier.size(IconButtonDefaults.DefaultButtonSize),
+ startAngle = 120f,
+ endAngle = 60f,
+ strokeWidth = ButtonCircularIndicatorStrokeWidth,
+ colors =
+ ProgressIndicatorDefaults.colors(indicatorColor = Color.Red)
+ )
+ }
}
}
- }
+ )
)
)
-)
diff --git a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/SelectableButtonDemo.kt b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/SelectableButtonDemo.kt
index 52981be..bb4cfcc 100644
--- a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/SelectableButtonDemo.kt
+++ b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/SelectableButtonDemo.kt
@@ -44,9 +44,7 @@
modifier = Modifier.fillMaxSize().selectableGroup(),
horizontalAlignment = Alignment.CenterHorizontally,
) {
- item {
- ListHeader { Text("Selectable Button") }
- }
+ item { ListHeader { Text("Selectable Button") } }
item {
DemoSelectableButton(
enabled = true,
@@ -61,18 +59,10 @@
onSelected = { selectedRadioIndex = 1 }
)
}
- item {
- ListHeader { Text("Disabled Selectable Button") }
- }
- item {
- DemoSelectableButton(enabled = false, selected = true)
- }
- item {
- DemoSelectableButton(enabled = false, selected = false)
- }
- item {
- ListHeader { Text("Icon") }
- }
+ item { ListHeader { Text("Disabled Selectable Button") } }
+ item { DemoSelectableButton(enabled = false, selected = true) }
+ item { DemoSelectableButton(enabled = false, selected = false) }
+ item { ListHeader { Text("Icon") } }
item {
DemoSelectableButton(
enabled = true,
@@ -82,17 +72,11 @@
}
}
item {
- DemoSelectableButton(
- enabled = true,
- selected = true,
- secondary = "Secondary label"
- ) {
+ DemoSelectableButton(enabled = true, selected = true, secondary = "Secondary label") {
Icon(imageVector = Icons.Filled.Favorite, contentDescription = "Favorite icon")
}
}
- item {
- ListHeader { Text("Multi-line") }
- }
+ item { ListHeader { Text("Multi-line") } }
item {
DemoSelectableButton(
enabled = true,
@@ -140,17 +124,18 @@
overflow = TextOverflow.Ellipsis
)
},
- secondaryLabel = secondary?.let {
- {
- Text(
- secondary,
- Modifier.fillMaxWidth(),
- maxLines = 2,
- textAlign = TextAlign.Start,
- overflow = TextOverflow.Ellipsis
- )
- }
- },
+ secondaryLabel =
+ secondary?.let {
+ {
+ Text(
+ secondary,
+ Modifier.fillMaxWidth(),
+ maxLines = 2,
+ textAlign = TextAlign.Start,
+ overflow = TextOverflow.Ellipsis
+ )
+ }
+ },
selected = selected,
onSelect = onSelected,
enabled = enabled,
diff --git a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/SelectionControlsDemo.kt b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/SelectionControlsDemo.kt
index 3f4c64e..07eef5a 100644
--- a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/SelectionControlsDemo.kt
+++ b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/SelectionControlsDemo.kt
@@ -35,11 +35,10 @@
fun RadioButtonDemo() {
var selectedIndex by remember { mutableIntStateOf(0) }
ScalingLazyColumn(
- modifier = Modifier.fillMaxSize(), horizontalAlignment = Alignment.CenterHorizontally,
+ modifier = Modifier.fillMaxSize(),
+ horizontalAlignment = Alignment.CenterHorizontally,
) {
- item {
- ListHeader { Text(text = "Radio Button") }
- }
+ item { ListHeader { Text(text = "Radio Button") } }
item {
RadioButtonDemo(
selected = selectedIndex == 0,
@@ -54,28 +53,16 @@
enabled = true
)
}
- item {
- ListHeader { Text(text = "Disabled Radio Button", textAlign = TextAlign.Center) }
- }
- item {
- RadioButtonDemo(selected = false, enabled = false)
- }
- item {
- RadioButtonDemo(selected = true, enabled = false)
- }
+ item { ListHeader { Text(text = "Disabled Radio Button", textAlign = TextAlign.Center) } }
+ item { RadioButtonDemo(selected = false, enabled = false) }
+ item { RadioButtonDemo(selected = true, enabled = false) }
}
}
@Composable
-private fun RadioButtonDemo(
- selected: Boolean,
- enabled: Boolean,
- onSelected: () -> Unit = {}
-) {
+private fun RadioButtonDemo(selected: Boolean, enabled: Boolean, onSelected: () -> Unit = {}) {
SelectableButton(
- label = {
- Text("Primary label", maxLines = 1, overflow = TextOverflow.Ellipsis)
- },
+ label = { Text("Primary label", maxLines = 1, overflow = TextOverflow.Ellipsis) },
selected = selected,
onSelect = onSelected,
enabled = enabled,
diff --git a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/SettingsDemo.kt b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/SettingsDemo.kt
index f0415ce..bef1e8b 100644
--- a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/SettingsDemo.kt
+++ b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/SettingsDemo.kt
@@ -39,14 +39,8 @@
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally
) {
- item {
- ListHeader(
- modifier = Modifier.fillMaxWidth()
- ) {
- Text("Settings")
- }
- }
- // Connectivity
+ item { ListHeader(modifier = Modifier.fillMaxWidth()) { Text("Settings") } }
+ // Connectivity
item {
SettingsChip(
painterResourceId = R.drawable.ic_settings_connectivity,
@@ -55,17 +49,11 @@
}
// Display
item {
- SettingsChip(
- painterResourceId = R.drawable.ic_settings_brightness,
- text = "Display"
- )
+ SettingsChip(painterResourceId = R.drawable.ic_settings_brightness, text = "Display")
}
// Gestures
item {
- SettingsChip(
- painterResourceId = R.drawable.ic_settings_gestures,
- text = "Gestures"
- )
+ SettingsChip(painterResourceId = R.drawable.ic_settings_gestures, text = "Gestures")
}
// Apps & Notifications
item {
@@ -75,39 +63,18 @@
)
}
// Google
- item {
- SettingsChip(
- painterResourceId = R.drawable.ic_settings_googleg,
- text = "Google"
- )
- }
+ item { SettingsChip(painterResourceId = R.drawable.ic_settings_googleg, text = "Google") }
// Sound
- item {
- SettingsChip(
- painterResourceId = R.drawable.ic_settings_sound,
- text = "Sound"
- )
- }
+ item { SettingsChip(painterResourceId = R.drawable.ic_settings_sound, text = "Sound") }
// Vibration
item {
- SettingsChip(
- painterResourceId = R.drawable.ic_settings_vibration,
- text = "Vibration"
- )
+ SettingsChip(painterResourceId = R.drawable.ic_settings_vibration, text = "Vibration")
}
// Battery
- item {
- SettingsChip(
- painterResourceId = R.drawable.ic_settings_battery,
- text = "Battery"
- )
- }
+ item { SettingsChip(painterResourceId = R.drawable.ic_settings_battery, text = "Battery") }
// General
item {
- SettingsChip(
- painterResourceId = R.drawable.ic_settings_watch_device,
- text = "General"
- )
+ SettingsChip(painterResourceId = R.drawable.ic_settings_watch_device, text = "General")
}
// Health Profile
item {
@@ -118,10 +85,7 @@
}
// Location
item {
- SettingsChip(
- painterResourceId = R.drawable.ic_settings_location,
- text = "Location"
- )
+ SettingsChip(painterResourceId = R.drawable.ic_settings_location, text = "Location")
}
// Safety and Emergency
item {
@@ -139,36 +103,20 @@
}
// Security
item {
- SettingsChip(
- painterResourceId = R.drawable.ic_settings_security,
- text = "Security"
- )
+ SettingsChip(painterResourceId = R.drawable.ic_settings_security, text = "Security")
}
// System
- item {
- SettingsChip(
- painterResourceId = R.drawable.ic_settings_system,
- text = "System"
- )
- }
+ item { SettingsChip(painterResourceId = R.drawable.ic_settings_system, text = "System") }
}
}
@Composable
-private fun SettingsChip(
- painterResourceId: Int,
- text: String
-) {
+private fun SettingsChip(painterResourceId: Int, text: String) {
Button(
onClick = { /* */ },
modifier = Modifier.fillMaxSize(),
colors = ButtonDefaults.filledTonalButtonColors(),
- icon = {
- Icon(
- painter = painterResource(painterResourceId),
- contentDescription = text
- )
- },
+ icon = { Icon(painter = painterResource(painterResourceId), contentDescription = text) },
label = { Text(text) }
)
}
diff --git a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/SliderDemo.kt b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/SliderDemo.kt
index feab507..a3061c5 100644
--- a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/SliderDemo.kt
+++ b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/SliderDemo.kt
@@ -54,9 +54,7 @@
"Samples",
listOf(
ComposableDemo("Inline slider") {
- Centralize(Modifier.padding(horizontal = 10.dp)) {
- InlineSliderSample()
- }
+ Centralize(Modifier.padding(horizontal = 10.dp)) { InlineSliderSample() }
},
ComposableDemo("Segmented inline slider") {
Centralize(Modifier.padding(horizontal = 10.dp)) {
@@ -77,9 +75,7 @@
ComposableDemo("RTL Inline slider") { InlineSliderRTLDemo() },
ComposableDemo("Inline slider segmented") { InlineSliderDemo(segmented = true) },
ComposableDemo("With custom color") { InlineSliderCustomColorsDemo() },
- ComposableDemo("Inline slider with integers") {
- InlineSliderWithIntegersDemo()
- },
+ ComposableDemo("Inline slider with integers") { InlineSliderWithIntegersDemo() },
)
)
)
@@ -92,16 +88,12 @@
ScalingLazyColumn(
horizontalAlignment = Alignment.CenterHorizontally,
- verticalArrangement = Arrangement.spacedBy(
- space = 4.dp,
- alignment = Alignment.CenterVertically
- ),
+ verticalArrangement =
+ Arrangement.spacedBy(space = 4.dp, alignment = Alignment.CenterVertically),
modifier = Modifier.fillMaxSize(),
autoCentering = AutoCenteringParams(itemIndex = 0)
) {
- item {
- Text("Enabled Slider, value = $enabledValue")
- }
+ item { Text("Enabled Slider, value = $enabledValue") }
item {
DefaultInlineSlider(
value = enabledValue,
@@ -112,9 +104,7 @@
onValueChange = { enabledValue = it }
)
}
- item {
- Text("Disabled Slider, value = $disabledValue")
- }
+ item { Text("Disabled Slider, value = $disabledValue") }
item {
DefaultInlineSlider(
value = disabledValue,
@@ -136,26 +126,21 @@
ScalingLazyColumn(
horizontalAlignment = Alignment.CenterHorizontally,
- verticalArrangement = Arrangement.spacedBy(
- space = 4.dp,
- alignment = Alignment.CenterVertically
- ),
+ verticalArrangement =
+ Arrangement.spacedBy(space = 4.dp, alignment = Alignment.CenterVertically),
modifier = Modifier.fillMaxSize(),
autoCentering = AutoCenteringParams(itemIndex = 0)
) {
- item {
- Text("No segments, value = $valueWithoutSegments")
- }
+ item { Text("No segments, value = $valueWithoutSegments") }
item {
DefaultInlineSlider(
value = valueWithoutSegments,
valueProgression = IntProgression.fromClosedRange(0, 15, 3),
segmented = false,
- onValueChange = { valueWithoutSegments = it })
+ onValueChange = { valueWithoutSegments = it }
+ )
}
- item {
- Text("With segments, value = $valueWithSegments")
- }
+ item { Text("With segments, value = $valueWithSegments") }
item {
DefaultInlineSlider(
value = valueWithSegments,
@@ -178,30 +163,26 @@
@Composable
fun InlineSliderCustomColorsDemo() {
var value by remember { mutableFloatStateOf(4.5f) }
- Box(
- contentAlignment = Alignment.Center,
- modifier = Modifier
- .fillMaxSize()
- .padding(10.dp)
- ) {
+ Box(contentAlignment = Alignment.Center, modifier = Modifier.fillMaxSize().padding(10.dp)) {
DefaultInlineSlider(
value = value,
onValueChange = { value = it },
valueRange = 3f..6f,
steps = 5,
segmented = true,
- colors = InlineSliderDefaults.colors(
- containerColor = Color.Green,
- buttonIconColor = Color.Yellow,
- selectedBarColor = Color.Magenta,
- unselectedBarColor = Color.White,
- barSeparatorColor = Color.Cyan,
- disabledContainerColor = Color.DarkGray,
- disabledButtonIconColor = Color.LightGray,
- disabledSelectedBarColor = Color.Red,
- disabledUnselectedBarColor = Color.Blue,
- disabledBarSeparatorColor = Color.Gray
- ),
+ colors =
+ InlineSliderDefaults.colors(
+ containerColor = Color.Green,
+ buttonIconColor = Color.Yellow,
+ selectedBarColor = Color.Magenta,
+ unselectedBarColor = Color.White,
+ barSeparatorColor = Color.Cyan,
+ disabledContainerColor = Color.DarkGray,
+ disabledButtonIconColor = Color.LightGray,
+ disabledSelectedBarColor = Color.Red,
+ disabledUnselectedBarColor = Color.Blue,
+ disabledBarSeparatorColor = Color.Gray
+ ),
)
}
}
diff --git a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/SplitSelectableButtonDemo.kt b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/SplitSelectableButtonDemo.kt
index 368138b..8801b26 100644
--- a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/SplitSelectableButtonDemo.kt
+++ b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/SplitSelectableButtonDemo.kt
@@ -44,33 +44,21 @@
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
) {
+ item { ListHeader { Text("Split Selectable Button") } }
item {
- ListHeader { Text("Split Selectable Button") }
+ DemoSplitSelectableButton(enabled = true, (selectedRadioIndex == 0)) {
+ selectedRadioIndex = 0
+ }
}
item {
- DemoSplitSelectableButton(
- enabled = true,
- (selectedRadioIndex == 0)
- ) { selectedRadioIndex = 0 }
+ DemoSplitSelectableButton(enabled = true, (selectedRadioIndex == 1)) {
+ selectedRadioIndex = 1
+ }
}
- item {
- DemoSplitSelectableButton(
- enabled = true,
- (selectedRadioIndex == 1)
- ) { selectedRadioIndex = 1 }
- }
- item {
- ListHeader { Text("Disabled Radio Button") }
- }
- item {
- DemoSplitSelectableButton(enabled = false, selected = true)
- }
- item {
- DemoSplitSelectableButton(enabled = false, selected = false)
- }
- item {
- ListHeader { Text("Multi-line") }
- }
+ item { ListHeader { Text("Disabled Radio Button") } }
+ item { DemoSplitSelectableButton(enabled = false, selected = true) }
+ item { DemoSplitSelectableButton(enabled = false, selected = false) }
+ item { ListHeader { Text("Multi-line") } }
item {
DemoSplitSelectableButton(
enabled = true,
@@ -117,17 +105,18 @@
overflow = TextOverflow.Ellipsis
)
},
- secondaryLabel = secondary?.let {
- {
- Text(
- secondary,
- modifier = Modifier.fillMaxWidth(),
- maxLines = 2,
- textAlign = TextAlign.Start,
- overflow = TextOverflow.Ellipsis
- )
- }
- },
+ secondaryLabel =
+ secondary?.let {
+ {
+ Text(
+ secondary,
+ modifier = Modifier.fillMaxWidth(),
+ maxLines = 2,
+ textAlign = TextAlign.Start,
+ overflow = TextOverflow.Ellipsis
+ )
+ }
+ },
selected = selected,
onSelectionClick = onSelected,
onContainerClick = {
@@ -136,9 +125,7 @@
},
enabled = enabled,
selectionControl = {
- RadioButton(modifier = Modifier.semantics {
- contentDescription = primary
- })
+ RadioButton(modifier = Modifier.semantics { contentDescription = primary })
}
)
}
diff --git a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/SplitToggleButtonDemo.kt b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/SplitToggleButtonDemo.kt
index f5c0740..cdf58cc 100644
--- a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/SplitToggleButtonDemo.kt
+++ b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/SplitToggleButtonDemo.kt
@@ -44,45 +44,19 @@
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
) {
- item {
- ListHeader { Text("Checkbox") }
- }
- item {
- DemoSplitToggleCheckbox(enabled = true, initiallyChecked = true)
- }
- item {
- DemoSplitToggleCheckbox(enabled = true, initiallyChecked = false)
- }
- item {
- ListHeader { Text("Disabled Checkbox") }
- }
- item {
- DemoSplitToggleCheckbox(enabled = false, initiallyChecked = true)
- }
- item {
- DemoSplitToggleCheckbox(enabled = false, initiallyChecked = false)
- }
- item {
- ListHeader { Text("Switch") }
- }
- item {
- DemoSplitToggleSwitch(enabled = true, initiallyChecked = true)
- }
- item {
- DemoSplitToggleSwitch(enabled = true, initiallyChecked = false)
- }
- item {
- ListHeader { Text("Disabled Switch") }
- }
- item {
- DemoSplitToggleSwitch(enabled = false, initiallyChecked = true)
- }
- item {
- DemoSplitToggleSwitch(enabled = false, initiallyChecked = false)
- }
- item {
- ListHeader { Text("Multi-line") }
- }
+ item { ListHeader { Text("Checkbox") } }
+ item { DemoSplitToggleCheckbox(enabled = true, initiallyChecked = true) }
+ item { DemoSplitToggleCheckbox(enabled = true, initiallyChecked = false) }
+ item { ListHeader { Text("Disabled Checkbox") } }
+ item { DemoSplitToggleCheckbox(enabled = false, initiallyChecked = true) }
+ item { DemoSplitToggleCheckbox(enabled = false, initiallyChecked = false) }
+ item { ListHeader { Text("Switch") } }
+ item { DemoSplitToggleSwitch(enabled = true, initiallyChecked = true) }
+ item { DemoSplitToggleSwitch(enabled = true, initiallyChecked = false) }
+ item { ListHeader { Text("Disabled Switch") } }
+ item { DemoSplitToggleSwitch(enabled = false, initiallyChecked = true) }
+ item { DemoSplitToggleSwitch(enabled = false, initiallyChecked = false) }
+ item { ListHeader { Text("Multi-line") } }
item {
DemoSplitToggleCheckbox(
enabled = true,
@@ -131,9 +105,7 @@
},
checked = checked,
toggleControl = {
- Checkbox(modifier = Modifier.semantics {
- contentDescription = primary
- })
+ Checkbox(modifier = Modifier.semantics { contentDescription = primary })
},
onCheckedChange = { checked = it },
onClick = {
@@ -172,11 +144,7 @@
)
},
checked = checked,
- toggleControl = {
- Switch(modifier = Modifier.semantics {
- contentDescription = text
- })
- },
+ toggleControl = { Switch(modifier = Modifier.semantics { contentDescription = text }) },
onCheckedChange = { checked = it },
onClick = {
val toastText = text + " " + if (checked) "Checked" else "Not Checked"
diff --git a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/TextButtonDemo.kt b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/TextButtonDemo.kt
index d4f5d3a..137a469 100644
--- a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/TextButtonDemo.kt
+++ b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/TextButtonDemo.kt
@@ -45,31 +45,21 @@
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
) {
- item {
- ListHeader {
- Text("Text Button")
- }
- }
+ item { ListHeader { Text("Text Button") } }
item {
Row {
TextButtonSample()
Spacer(modifier = Modifier.width(5.dp))
- TextButton(onClick = { }, enabled = false) {
- Text(text = "ABC")
- }
+ TextButton(onClick = {}, enabled = false) { Text(text = "ABC") }
}
}
- item {
- ListHeader {
- Text("Filled Tonal")
- }
- }
+ item { ListHeader { Text("Filled Tonal") } }
item {
Row {
FilledTonalTextButtonSample()
Spacer(modifier = Modifier.width(5.dp))
TextButton(
- onClick = { },
+ onClick = {},
enabled = false,
colors = TextButtonDefaults.filledTonalTextButtonColors()
) {
@@ -77,17 +67,13 @@
}
}
}
- item {
- ListHeader {
- Text("Filled")
- }
- }
+ item { ListHeader { Text("Filled") } }
item {
Row {
FilledTextButtonSample()
Spacer(modifier = Modifier.width(5.dp))
TextButton(
- onClick = { },
+ onClick = {},
enabled = false,
colors = TextButtonDefaults.filledTextButtonColors()
) {
@@ -95,17 +81,13 @@
}
}
}
- item {
- ListHeader {
- Text("Outlined")
- }
- }
+ item { ListHeader { Text("Outlined") } }
item {
Row {
OutlinedTextButtonSample()
Spacer(modifier = Modifier.width(5.dp))
TextButton(
- onClick = { },
+ onClick = {},
enabled = false,
colors = TextButtonDefaults.outlinedTextButtonColors(),
border = ButtonDefaults.outlinedButtonBorder(enabled = false)
@@ -114,11 +96,7 @@
}
}
}
- item {
- ListHeader {
- Text("Sizes")
- }
- }
+ item { ListHeader { Text("Sizes") } }
item {
Row(verticalAlignment = Alignment.CenterVertically) {
Text("${TextButtonDefaults.LargeButtonSize.value.toInt()}dp")
@@ -147,7 +125,7 @@
private fun TextButtonWithSize(size: Dp) {
TextButton(
modifier = Modifier.touchTargetAwareSize(size),
- onClick = { },
+ onClick = {},
enabled = true,
colors = TextButtonDefaults.filledTonalTextButtonColors()
) {
diff --git a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/TextToggleButtonDemo.kt b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/TextToggleButtonDemo.kt
index 955f9a8..0b3c923 100644
--- a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/TextToggleButtonDemo.kt
+++ b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/TextToggleButtonDemo.kt
@@ -45,11 +45,7 @@
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
) {
- item {
- ListHeader {
- Text("Text Toggle Button", textAlign = TextAlign.Center)
- }
- }
+ item { ListHeader { Text("Text Toggle Button", textAlign = TextAlign.Center) } }
item {
Row {
TextToggleButtonSample() // Enabled and checked
@@ -64,11 +60,7 @@
TextToggleButtonsDemo(enabled = false, initialChecked = false)
}
}
- item {
- ListHeader {
- Text("Sizes")
- }
- }
+ item { ListHeader { Text("Sizes") } }
item {
Row(verticalAlignment = Alignment.CenterVertically) {
Text("${TextButtonDefaults.LargeButtonSize.value.toInt()}dp")
@@ -114,8 +106,6 @@
modifier = Modifier.touchTargetAwareSize(size),
onCheckedChange = { checked = !checked },
) {
- Text(
- text = if (checked) "On" else "Off"
- )
+ Text(text = if (checked) "On" else "Off")
}
}
diff --git a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/ToggleButtonDemo.kt b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/ToggleButtonDemo.kt
index fc3460f..99846fa 100644
--- a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/ToggleButtonDemo.kt
+++ b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/ToggleButtonDemo.kt
@@ -44,45 +44,19 @@
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
) {
- item {
- ListHeader { Text("Checkbox") }
- }
- item {
- DemoToggleCheckbox(enabled = true, initiallyChecked = true)
- }
- item {
- DemoToggleCheckbox(enabled = true, initiallyChecked = false)
- }
- item {
- ListHeader { Text("Disabled Checkbox") }
- }
- item {
- DemoToggleCheckbox(enabled = false, initiallyChecked = true)
- }
- item {
- DemoToggleCheckbox(enabled = false, initiallyChecked = false)
- }
- item {
- ListHeader { Text("Switch") }
- }
- item {
- DemoToggleSwitch(enabled = true, initiallyChecked = true)
- }
- item {
- DemoToggleSwitch(enabled = true, initiallyChecked = false)
- }
- item {
- ListHeader { Text("Disabled Switch") }
- }
- item {
- DemoToggleSwitch(enabled = false, initiallyChecked = true)
- }
- item {
- DemoToggleSwitch(enabled = false, initiallyChecked = false)
- }
- item {
- ListHeader { Text("Icon") }
- }
+ item { ListHeader { Text("Checkbox") } }
+ item { DemoToggleCheckbox(enabled = true, initiallyChecked = true) }
+ item { DemoToggleCheckbox(enabled = true, initiallyChecked = false) }
+ item { ListHeader { Text("Disabled Checkbox") } }
+ item { DemoToggleCheckbox(enabled = false, initiallyChecked = true) }
+ item { DemoToggleCheckbox(enabled = false, initiallyChecked = false) }
+ item { ListHeader { Text("Switch") } }
+ item { DemoToggleSwitch(enabled = true, initiallyChecked = true) }
+ item { DemoToggleSwitch(enabled = true, initiallyChecked = false) }
+ item { ListHeader { Text("Disabled Switch") } }
+ item { DemoToggleSwitch(enabled = false, initiallyChecked = true) }
+ item { DemoToggleSwitch(enabled = false, initiallyChecked = false) }
+ item { ListHeader { Text("Icon") } }
item {
DemoToggleCheckbox(
enabled = true,
@@ -102,9 +76,7 @@
Icon(imageVector = Icons.Filled.Favorite, contentDescription = "Favorite icon")
}
}
- item {
- ListHeader { Text("Multi-line") }
- }
+ item { ListHeader { Text("Multi-line") } }
item {
DemoToggleCheckbox(
enabled = true,
diff --git a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/ToggleControlsDemo.kt b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/ToggleControlsDemo.kt
index f075f0f..3883eb5 100644
--- a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/ToggleControlsDemo.kt
+++ b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/ToggleControlsDemo.kt
@@ -38,55 +38,31 @@
@Composable
fun CheckboxDemos() {
ScalingLazyColumn(
- modifier = Modifier.fillMaxSize(), horizontalAlignment = Alignment.CenterHorizontally,
+ modifier = Modifier.fillMaxSize(),
+ horizontalAlignment = Alignment.CenterHorizontally,
) {
- item {
- ListHeader { Text(text = "Checkbox") }
- }
- item {
- CheckboxDemo(initialChecked = false, enabled = true)
- }
- item {
- CheckboxDemo(initialChecked = true, enabled = true)
- }
- item {
- ListHeader { Text(text = "Disabled Checkbox") }
- }
- item {
- CheckboxDemo(initialChecked = false, enabled = false)
- }
- item {
- CheckboxDemo(initialChecked = true, enabled = false)
- }
+ item { ListHeader { Text(text = "Checkbox") } }
+ item { CheckboxDemo(initialChecked = false, enabled = true) }
+ item { CheckboxDemo(initialChecked = true, enabled = true) }
+ item { ListHeader { Text(text = "Disabled Checkbox") } }
+ item { CheckboxDemo(initialChecked = false, enabled = false) }
+ item { CheckboxDemo(initialChecked = true, enabled = false) }
}
}
@Composable
fun SwitchDemos() {
ScalingLazyColumn(
- modifier = Modifier.fillMaxSize(), horizontalAlignment = Alignment.CenterHorizontally,
+ modifier = Modifier.fillMaxSize(),
+ horizontalAlignment = Alignment.CenterHorizontally,
) {
- item {
- ListHeader { Text(text = "Switch") }
- }
- item {
- SwitchDemo(initialChecked = false, enabled = true)
- }
- item {
- SwitchDemo(initialChecked = true, enabled = true)
- }
- item {
- ListHeader { Text(text = "Disabled Switch") }
- }
- item {
- SwitchDemo(initialChecked = false, enabled = false)
- }
- item {
- SwitchDemo(initialChecked = true, enabled = false)
- }
- item {
- ListHeader { Text(text = "RTL Switch") }
- }
+ item { ListHeader { Text(text = "Switch") } }
+ item { SwitchDemo(initialChecked = false, enabled = true) }
+ item { SwitchDemo(initialChecked = true, enabled = true) }
+ item { ListHeader { Text(text = "Disabled Switch") } }
+ item { SwitchDemo(initialChecked = false, enabled = false) }
+ item { SwitchDemo(initialChecked = true, enabled = false) }
+ item { ListHeader { Text(text = "RTL Switch") } }
item {
CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl) {
SwitchDemo(initialChecked = false, enabled = true)
@@ -104,9 +80,7 @@
private fun CheckboxDemo(initialChecked: Boolean, enabled: Boolean) {
var checked by remember { mutableStateOf(initialChecked) }
ToggleButton(
- label = {
- Text("Primary label", maxLines = 1, overflow = TextOverflow.Ellipsis)
- },
+ label = { Text("Primary label", maxLines = 1, overflow = TextOverflow.Ellipsis) },
checked = checked,
toggleControl = { Checkbox() },
onCheckedChange = { checked = it },
@@ -118,9 +92,7 @@
private fun SwitchDemo(initialChecked: Boolean, enabled: Boolean) {
var checked by remember { mutableStateOf(initialChecked) }
ToggleButton(
- label = {
- Text("Primary label", maxLines = 1, overflow = TextOverflow.Ellipsis)
- },
+ label = { Text("Primary label", maxLines = 1, overflow = TextOverflow.Ellipsis) },
checked = checked,
toggleControl = { Switch() },
onCheckedChange = { checked = it },
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 33855ad..e7aea2b 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
@@ -29,131 +29,75 @@
import androidx.wear.compose.material3.samples.StepperWithIntegerSample
import androidx.wear.compose.material3.samples.StepperWithRangeSemanticsSample
-val WearMaterial3Demos = DemoCategory(
- "Material 3",
- listOf(
- DemoCategory(
- "Button",
- listOf(
- ComposableDemo("Button") {
- ButtonDemo()
- },
- ComposableDemo("Filled Tonal Button") {
- FilledTonalButtonDemo()
- },
- ComposableDemo("Outlined Button") {
- OutlinedButtonDemo()
- },
- ComposableDemo("Child Button") {
- ChildButtonDemo()
- },
- ComposableDemo("Compact Button") {
- CompactButtonDemo()
- },
- ComposableDemo("Multiline Button") {
- MultilineButtonDemo()
- },
- ComposableDemo("Avatar Button") {
- AvatarButtonDemo()
- },
- )
- ),
- ComposableDemo("List Header") {
- Centralize {
- ListHeaderDemo()
- }
- },
- DemoCategory(
- "Time Text",
- TimeTextDemos
- ),
- ComposableDemo("Card") {
- CardDemo()
- },
- ComposableDemo("Text Button") {
- TextButtonDemo()
- },
- ComposableDemo("Icon Button") {
- IconButtonDemo()
- },
- ComposableDemo("Text Toggle Button") {
- TextToggleButtonDemo()
- },
- ComposableDemo("Icon Toggle Button") {
- IconToggleButtonDemo()
- },
- ComposableDemo("Checkbox") {
- CheckboxDemos()
- },
- ComposableDemo("Switch") {
- SwitchDemos()
- },
- ComposableDemo("Radio Button") {
- RadioButtonDemo()
- },
- ComposableDemo("Selectable Button") {
- SelectableButtonDemo()
- },
- ComposableDemo("Split Selectable Button") {
- SplitSelectableButtonDemo()
- },
- ComposableDemo("Toggle Button") {
- ToggleButtonDemo()
- },
- ComposableDemo("Split Toggle Button") {
- SplitToggleButtonDemo()
- },
- DemoCategory(
- "Stepper",
- listOf(
- DemoCategory(
- "Samples",
- listOf(
- ComposableDemo("Stepper") {
- Centralize { StepperSample() }
- },
- ComposableDemo("Integer Stepper") {
- Centralize { StepperWithIntegerSample() }
- },
- ComposableDemo("Stepper with rangeSemantics") {
- Centralize { StepperWithRangeSemanticsSample() }
- }
+val WearMaterial3Demos =
+ DemoCategory(
+ "Material 3",
+ listOf(
+ DemoCategory(
+ "Button",
+ listOf(
+ ComposableDemo("Button") { ButtonDemo() },
+ ComposableDemo("Filled Tonal Button") { FilledTonalButtonDemo() },
+ ComposableDemo("Outlined Button") { OutlinedButtonDemo() },
+ ComposableDemo("Child Button") { ChildButtonDemo() },
+ ComposableDemo("Compact Button") { CompactButtonDemo() },
+ ComposableDemo("Multiline Button") { MultilineButtonDemo() },
+ ComposableDemo("Avatar Button") { AvatarButtonDemo() },
+ )
+ ),
+ ComposableDemo("List Header") { Centralize { ListHeaderDemo() } },
+ DemoCategory("Time Text", TimeTextDemos),
+ ComposableDemo("Card") { CardDemo() },
+ ComposableDemo("Text Button") { TextButtonDemo() },
+ ComposableDemo("Icon Button") { IconButtonDemo() },
+ ComposableDemo("Text Toggle Button") { TextToggleButtonDemo() },
+ ComposableDemo("Icon Toggle Button") { IconToggleButtonDemo() },
+ ComposableDemo("Checkbox") { CheckboxDemos() },
+ ComposableDemo("Switch") { SwitchDemos() },
+ ComposableDemo("Radio Button") { RadioButtonDemo() },
+ ComposableDemo("Selectable Button") { SelectableButtonDemo() },
+ ComposableDemo("Split Selectable Button") { SplitSelectableButtonDemo() },
+ ComposableDemo("Toggle Button") { ToggleButtonDemo() },
+ ComposableDemo("Split Toggle Button") { SplitToggleButtonDemo() },
+ DemoCategory(
+ "Stepper",
+ listOf(
+ DemoCategory(
+ "Samples",
+ listOf(
+ ComposableDemo("Stepper") { Centralize { StepperSample() } },
+ ComposableDemo("Integer Stepper") {
+ Centralize { StepperWithIntegerSample() }
+ },
+ ComposableDemo("Stepper with rangeSemantics") {
+ Centralize { StepperWithRangeSemanticsSample() }
+ }
+ )
)
)
- )
- ),
- DemoCategory(
- "Slider",
- SliderDemos
- ),
- DemoCategory(
- "Progress Indicator",
- ProgressIndicatorDemos
- ),
- ComposableDemo(
- title = "Fixed Font Size"
- ) {
- Centralize { FixedFontSize() }
- },
- DemoCategory(
- title = "Swipe To Dismiss",
- listOf(
- ComposableDemo("Simple") { SimpleSwipeToDismissBox(it.navigateBack) },
- ComposableDemo("Stateful") { StatefulSwipeToDismissBox() },
- ComposableDemo("Edge swipe") { EdgeSwipeForSwipeToDismiss(it.navigateBack) },
- )
- ),
- DemoCategory(
- title = "Horizontal Page Indicator",
- listOf(
- ComposableDemo("Simple HorizontalPageIndicator") {
- HorizontalPageIndicatorSample()
- },
- ComposableDemo("HorizontalPageIndicator with Pager") {
- HorizontalPageIndicatorWithPagerSample(it.swipeToDismissBoxState)
- },
- )
- ),
- ComposableDemo("Settings Demo") { SettingsDemo() }
+ ),
+ DemoCategory("Slider", SliderDemos),
+ DemoCategory("Progress Indicator", ProgressIndicatorDemos),
+ ComposableDemo(title = "Fixed Font Size") { Centralize { FixedFontSize() } },
+ DemoCategory(
+ title = "Swipe To Dismiss",
+ listOf(
+ ComposableDemo("Simple") { SimpleSwipeToDismissBox(it.navigateBack) },
+ ComposableDemo("Stateful") { StatefulSwipeToDismissBox() },
+ ComposableDemo("Edge swipe") { EdgeSwipeForSwipeToDismiss(it.navigateBack) },
+ )
+ ),
+ DemoCategory(
+ title = "Horizontal Page Indicator",
+ listOf(
+ ComposableDemo("Simple HorizontalPageIndicator") {
+ HorizontalPageIndicatorSample()
+ },
+ ComposableDemo("HorizontalPageIndicator with Pager") {
+ HorizontalPageIndicatorWithPagerSample(it.swipeToDismissBoxState)
+ },
+ )
+ ),
+ ComposableDemo("Settings Demo") { SettingsDemo() }
+ )
)
-)
diff --git a/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/ButtonSample.kt b/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/ButtonSample.kt
index 9d8c610..132193b 100644
--- a/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/ButtonSample.kt
+++ b/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/ButtonSample.kt
@@ -36,18 +36,12 @@
@Sampled
@Composable
fun SimpleButtonSample() {
- Button(
- onClick = { /* Do something */ },
- label = { Text("Button") }
- )
+ Button(onClick = { /* Do something */ }, label = { Text("Button") })
}
@Sampled
@Composable
-fun ButtonWithOnLongClick(
- onClickHandler: () -> Unit,
- onLongClickHandler: () -> Unit
-) {
+fun ButtonWithOnLongClick(onClickHandler: () -> Unit, onLongClickHandler: () -> Unit) {
Button(
onClick = onClickHandler,
onLongClick = onLongClickHandler,
@@ -76,18 +70,12 @@
@Sampled
@Composable
fun SimpleFilledTonalButtonSample() {
- FilledTonalButton(
- onClick = { /* Do something */ },
- label = { Text("Filled Tonal Button") }
- )
+ FilledTonalButton(onClick = { /* Do something */ }, label = { Text("Filled Tonal Button") })
}
@Sampled
@Composable
-fun FilledTonalButtonWithOnLongClick(
- onClickHandler: () -> Unit,
- onLongClickHandler: () -> Unit
-) {
+fun FilledTonalButtonWithOnLongClick(onClickHandler: () -> Unit, onLongClickHandler: () -> Unit) {
FilledTonalButton(
onClick = onClickHandler,
onLongClick = onLongClickHandler,
@@ -116,18 +104,12 @@
@Sampled
@Composable
fun SimpleOutlinedButtonSample() {
- OutlinedButton(
- onClick = { /* Do something */ },
- label = { Text("Outlined Button") }
- )
+ OutlinedButton(onClick = { /* Do something */ }, label = { Text("Outlined Button") })
}
@Sampled
@Composable
-fun OutlinedButtonWithOnLongClick(
- onClickHandler: () -> Unit,
- onLongClickHandler: () -> Unit
-) {
+fun OutlinedButtonWithOnLongClick(onClickHandler: () -> Unit, onLongClickHandler: () -> Unit) {
OutlinedButton(
onClick = onClickHandler,
onLongClick = onLongClickHandler,
@@ -156,18 +138,12 @@
@Sampled
@Composable
fun SimpleChildButtonSample() {
- ChildButton(
- onClick = { /* Do something */ },
- label = { Text("Child Button") }
- )
+ ChildButton(onClick = { /* Do something */ }, label = { Text("Child Button") })
}
@Sampled
@Composable
-fun ChildButtonWithOnLongClick(
- onClickHandler: () -> Unit,
- onLongClickHandler: () -> Unit
-) {
+fun ChildButtonWithOnLongClick(onClickHandler: () -> Unit, onLongClickHandler: () -> Unit) {
ChildButton(
onClick = onClickHandler,
onLongClick = onLongClickHandler,
@@ -212,10 +188,7 @@
@Sampled
@Composable
-fun CompactButtonWithOnLongClick(
- onClickHandler: () -> Unit,
- onLongClickHandler: () -> Unit
-) {
+fun CompactButtonWithOnLongClick(onClickHandler: () -> Unit, onLongClickHandler: () -> Unit) {
CompactButton(
onClick = onClickHandler,
onLongClick = onLongClickHandler,
diff --git a/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/CardSample.kt b/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/CardSample.kt
index 3b4c458..884adb5 100644
--- a/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/CardSample.kt
+++ b/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/CardSample.kt
@@ -69,9 +69,9 @@
Icon(
painter = painterResource(id = android.R.drawable.star_big_off),
contentDescription = "Star icon",
- modifier = Modifier
- .size(CardDefaults.AppImageSize)
- .wrapContentSize(align = Alignment.Center),
+ modifier =
+ Modifier.size(CardDefaults.AppImageSize)
+ .wrapContentSize(align = Alignment.Center),
)
},
title = { Text("Card title") },
@@ -111,13 +111,15 @@
onClick = { /* Do something */ },
title = { Text("Card title") },
time = { Text("now") },
- colors = CardDefaults.imageCardColors(
- containerPainter = CardDefaults.imageWithScrimBackgroundPainter(
- backgroundImagePainter = painterResource(id = R.drawable.backgroundimage)
+ colors =
+ CardDefaults.imageCardColors(
+ containerPainter =
+ CardDefaults.imageWithScrimBackgroundPainter(
+ backgroundImagePainter = painterResource(id = R.drawable.backgroundimage)
+ ),
+ contentColor = MaterialTheme.colorScheme.onSurface,
+ titleColor = MaterialTheme.colorScheme.onSurface
),
- contentColor = MaterialTheme.colorScheme.onSurface,
- titleColor = MaterialTheme.colorScheme.onSurface
- ),
modifier = Modifier.semantics { contentDescription = "Background image" }
) {
Text("Card content")
diff --git a/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/HorizontalPageIndicatorSample.kt b/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/HorizontalPageIndicatorSample.kt
index 233d8f3..c8f1a82 100644
--- a/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/HorizontalPageIndicatorSample.kt
+++ b/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/HorizontalPageIndicatorSample.kt
@@ -47,15 +47,13 @@
val pageCount = 9
var selectedPage by remember { mutableStateOf(0) }
- val animatedSelectedPage by animateFloatAsState(
- targetValue = selectedPage.toFloat(), label = "animateSelectedPage",
- )
+ val animatedSelectedPage by
+ animateFloatAsState(
+ targetValue = selectedPage.toFloat(),
+ label = "animateSelectedPage",
+ )
- Box(
- modifier = Modifier
- .fillMaxSize()
- .padding(6.dp)
- ) {
+ Box(modifier = Modifier.fillMaxSize().padding(6.dp)) {
InlineSlider(
modifier = Modifier.align(Alignment.Center),
value = selectedPage,
@@ -80,19 +78,11 @@
Box {
HorizontalPager(
- modifier = Modifier
- .fillMaxSize()
- .edgeSwipeToDismiss(swipeState),
+ modifier = Modifier.fillMaxSize().edgeSwipeToDismiss(swipeState),
state = pagerState,
) { page ->
- Box(
- modifier = Modifier
- .fillMaxSize()
- ) {
- Text(
- modifier = Modifier.align(Alignment.Center),
- text = "Page #$page"
- )
+ Box(modifier = Modifier.fillMaxSize()) {
+ Text(modifier = Modifier.align(Alignment.Center), text = "Page #$page")
}
}
HorizontalPageIndicator(
diff --git a/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/IconButtonSample.kt b/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/IconButtonSample.kt
index 14255f1..5560388 100644
--- a/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/IconButtonSample.kt
+++ b/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/IconButtonSample.kt
@@ -30,10 +30,7 @@
@Sampled
fun IconButtonSample() {
IconButton(onClick = { /* Do something */ }) {
- Icon(
- imageVector = Icons.Filled.Favorite,
- contentDescription = "Favorite icon"
- )
+ Icon(imageVector = Icons.Filled.Favorite, contentDescription = "Favorite icon")
}
}
@@ -41,10 +38,7 @@
@Sampled
fun FilledIconButtonSample() {
FilledIconButton(onClick = { /* Do something */ }) {
- Icon(
- imageVector = Icons.Filled.Favorite,
- contentDescription = "Favorite icon"
- )
+ Icon(imageVector = Icons.Filled.Favorite, contentDescription = "Favorite icon")
}
}
@@ -52,10 +46,7 @@
@Sampled
fun FilledTonalIconButtonSample() {
FilledTonalIconButton(onClick = { /* Do something */ }) {
- Icon(
- imageVector = Icons.Filled.Favorite,
- contentDescription = "Favorite icon"
- )
+ Icon(imageVector = Icons.Filled.Favorite, contentDescription = "Favorite icon")
}
}
@@ -63,9 +54,6 @@
@Sampled
fun OutlinedIconButtonSample() {
OutlinedIconButton(onClick = { /* Do something */ }) {
- Icon(
- imageVector = Icons.Filled.Favorite,
- contentDescription = "Favorite icon"
- )
+ Icon(imageVector = Icons.Filled.Favorite, contentDescription = "Favorite icon")
}
}
diff --git a/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/IconToggleButtonSample.kt b/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/IconToggleButtonSample.kt
index 1ece752..84892fb 100644
--- a/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/IconToggleButtonSample.kt
+++ b/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/IconToggleButtonSample.kt
@@ -31,13 +31,7 @@
@Composable
fun IconToggleButtonSample() {
var checked by remember { mutableStateOf(true) }
- IconToggleButton(
- checked = checked,
- onCheckedChange = { checked = !checked }
- ) {
- Icon(
- imageVector = Icons.Filled.Favorite,
- contentDescription = "Favorite icon"
- )
+ IconToggleButton(checked = checked, onCheckedChange = { checked = !checked }) {
+ Icon(imageVector = Icons.Filled.Favorite, contentDescription = "Favorite icon")
}
}
diff --git a/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/ListHeaderSample.kt b/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/ListHeaderSample.kt
index 3b32885..abb6f9f 100644
--- a/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/ListHeaderSample.kt
+++ b/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/ListHeaderSample.kt
@@ -28,17 +28,13 @@
@Sampled
@Composable
fun ListHeaderSample() {
- ListHeader {
- Text("Header")
- }
+ ListHeader { Text("Header") }
}
@Sampled
@Composable
fun ListSubheaderSample() {
- ListSubheader {
- Text("Subheader")
- }
+ ListSubheader { Text("Subheader") }
}
@Sampled
diff --git a/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/MaterialThemeSample.kt b/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/MaterialThemeSample.kt
index 9d05440..94ebed6 100644
--- a/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/MaterialThemeSample.kt
+++ b/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/MaterialThemeSample.kt
@@ -26,11 +26,13 @@
@Sampled
@Composable
fun FixedFontSize() {
- val typography = MaterialTheme.typography.copy(
- displayLarge = MaterialTheme.typography.displayLarge.copy(
- fontSize = with(LocalDensity.current) { 40.dp.toSp() }
+ val typography =
+ MaterialTheme.typography.copy(
+ displayLarge =
+ MaterialTheme.typography.displayLarge.copy(
+ fontSize = with(LocalDensity.current) { 40.dp.toSp() }
+ )
)
- )
MaterialTheme(typography = typography) {
Text(
text = "Fixed Font",
diff --git a/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/ProgressIndicatorSample.kt b/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/ProgressIndicatorSample.kt
index 74e3487..bd5d2e7 100644
--- a/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/ProgressIndicatorSample.kt
+++ b/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/ProgressIndicatorSample.kt
@@ -50,19 +50,19 @@
fun FullScreenProgressIndicatorSample() {
Box(
modifier =
- Modifier
- .background(MaterialTheme.colorScheme.background)
- .padding(FullScreenPadding)
- .fillMaxSize()
+ Modifier.background(MaterialTheme.colorScheme.background)
+ .padding(FullScreenPadding)
+ .fillMaxSize()
) {
CircularProgressIndicator(
progress = { 0.25f },
startAngle = 120f,
endAngle = 60f,
- colors = ProgressIndicatorDefaults.colors(
- indicatorColor = Color.Green,
- trackColor = Color.Green.copy(alpha = 0.5f)
- ),
+ colors =
+ ProgressIndicatorDefaults.colors(
+ indicatorColor = Color.Green,
+ trackColor = Color.Green.copy(alpha = 0.5f)
+ ),
)
}
}
@@ -70,29 +70,22 @@
@Sampled
@Composable
fun MediaButtonProgressIndicatorSample() {
- var isPlaying by remember {
- mutableStateOf(false)
- }
+ var isPlaying by remember { mutableStateOf(false) }
val progressPadding = 4.dp
- Box(
- modifier = Modifier
- .fillMaxSize()
- .background(MaterialTheme.colorScheme.background)
- ) {
-
+ Box(modifier = Modifier.fillMaxSize().background(MaterialTheme.colorScheme.background)) {
Box(
- modifier = Modifier
- .align(Alignment.Center)
- .size(IconButtonDefaults.DefaultButtonSize + progressPadding)
+ modifier =
+ Modifier.align(Alignment.Center)
+ .size(IconButtonDefaults.DefaultButtonSize + progressPadding)
) {
CircularProgressIndicator(progress = { 0.75f }, strokeWidth = progressPadding)
IconButton(
- modifier = Modifier
- .align(Alignment.Center)
- .padding(progressPadding)
- .clip(CircleShape)
- .background(MaterialTheme.colorScheme.surfaceContainerLow),
+ modifier =
+ Modifier.align(Alignment.Center)
+ .padding(progressPadding)
+ .clip(CircleShape)
+ .background(MaterialTheme.colorScheme.surfaceContainerLow),
onClick = { isPlaying = !isPlaying }
) {
Icon(
@@ -109,10 +102,9 @@
fun OverflowProgressIndicatorSample() {
Box(
modifier =
- Modifier
- .background(MaterialTheme.colorScheme.background)
- .padding(FullScreenPadding)
- .fillMaxSize()
+ Modifier.background(MaterialTheme.colorScheme.background)
+ .padding(FullScreenPadding)
+ .fillMaxSize()
) {
CircularProgressIndicator(
// The progress is limited by 100%, 120% ends up being 20% with the track brush
@@ -120,14 +112,16 @@
progress = { 0.2f },
startAngle = 120f,
endAngle = 60f,
- colors = ProgressIndicatorDefaults.colors(
- trackBrush = Brush.linearGradient(
- listOf(
- MaterialTheme.colorScheme.primary,
- MaterialTheme.colorScheme.surfaceContainer
- )
+ colors =
+ ProgressIndicatorDefaults.colors(
+ trackBrush =
+ Brush.linearGradient(
+ listOf(
+ MaterialTheme.colorScheme.primary,
+ MaterialTheme.colorScheme.surfaceContainer
+ )
+ )
)
- )
)
}
}
diff --git a/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/SelectableButtonSample.kt b/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/SelectableButtonSample.kt
index b97d750..6a6c526 100644
--- a/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/SelectableButtonSample.kt
+++ b/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/SelectableButtonSample.kt
@@ -43,38 +43,24 @@
var selectedButton by remember { mutableStateOf(0) }
// RadioButton uses the Radio selection control by default.
SelectableButton(
- label = {
- Text("Selectable button", maxLines = 3, overflow = TextOverflow.Ellipsis)
- },
+ label = { Text("Selectable button", maxLines = 3, overflow = TextOverflow.Ellipsis) },
secondaryLabel = {
Text("With secondary label", maxLines = 2, overflow = TextOverflow.Ellipsis)
},
selected = selectedButton == 0,
onSelect = { selectedButton = 0 },
- icon = {
- Icon(
- Icons.Filled.Favorite,
- contentDescription = "Favorite icon"
- )
- },
+ icon = { Icon(Icons.Filled.Favorite, contentDescription = "Favorite icon") },
enabled = true,
)
Spacer(modifier = Modifier.height(4.dp))
SelectableButton(
- label = {
- Text("Selectable button", maxLines = 3, overflow = TextOverflow.Ellipsis)
- },
+ label = { Text("Selectable button", maxLines = 3, overflow = TextOverflow.Ellipsis) },
secondaryLabel = {
Text("With secondary label", maxLines = 3, overflow = TextOverflow.Ellipsis)
},
selected = selectedButton == 1,
onSelect = { selectedButton = 1 },
- icon = {
- Icon(
- Icons.Filled.Favorite,
- contentDescription = "Favorite icon"
- )
- },
+ icon = { Icon(Icons.Filled.Favorite, contentDescription = "Favorite icon") },
enabled = true,
)
}
@@ -87,9 +73,7 @@
var selectedButton by remember { mutableStateOf(0) }
// SplitRadioButton uses the Radio selection control by default.
SplitSelectableButton(
- label = {
- Text("First Button", maxLines = 3, overflow = TextOverflow.Ellipsis)
- },
+ label = { Text("First Button", maxLines = 3, overflow = TextOverflow.Ellipsis) },
selected = selectedButton == 0,
onSelectionClick = { selectedButton = 0 },
onContainerClick = {
@@ -99,9 +83,7 @@
)
Spacer(modifier = Modifier.height(4.dp))
SplitSelectableButton(
- label = {
- Text("Second Button", maxLines = 3, overflow = TextOverflow.Ellipsis)
- },
+ label = { Text("Second Button", maxLines = 3, overflow = TextOverflow.Ellipsis) },
selected = selectedButton == 1,
onSelectionClick = { selectedButton = 1 },
onContainerClick = {
diff --git a/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/StepperSample.kt b/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/StepperSample.kt
index a0f0f9c..f4f33f7 100644
--- a/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/StepperSample.kt
+++ b/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/StepperSample.kt
@@ -42,7 +42,9 @@
increaseIcon = { Icon(StepperDefaults.Increase, "Increase") },
decreaseIcon = { Icon(StepperDefaults.Decrease, "Decrease") },
steps = 7
- ) { Text("Value: $value") }
+ ) {
+ Text("Value: $value")
+ }
}
@Sampled
@@ -56,7 +58,9 @@
increaseIcon = { Icon(StepperDefaults.Increase, "Increase") },
decreaseIcon = { Icon(StepperDefaults.Decrease, "Decrease") },
valueProgression = 1..10
- ) { Text("Value: $value") }
+ ) {
+ Text("Value: $value")
+ }
}
@Sampled
@@ -76,5 +80,7 @@
increaseIcon = { Icon(StepperDefaults.Increase, "Increase") },
decreaseIcon = { Icon(StepperDefaults.Decrease, "Decrease") },
steps = steps,
- ) { Text("Value: $value") }
+ ) {
+ Text("Value: $value")
+ }
}
diff --git a/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/SwipeToDismissBoxSample.kt b/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/SwipeToDismissBoxSample.kt
index 9a49f2e..6e477af 100644
--- a/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/SwipeToDismissBoxSample.kt
+++ b/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/SwipeToDismissBoxSample.kt
@@ -51,23 +51,16 @@
@Sampled
@Composable
-fun SimpleSwipeToDismissBox(
- navigateBack: () -> Unit
-) {
- SwipeToDismissBox(
- onDismissed = navigateBack
- ) { isBackground ->
+fun SimpleSwipeToDismissBox(navigateBack: () -> Unit) {
+ SwipeToDismissBox(onDismissed = navigateBack) { isBackground ->
if (isBackground) {
Box(
- modifier = Modifier
- .fillMaxSize()
- .background(MaterialTheme.colorScheme.secondaryContainer)
+ modifier =
+ Modifier.fillMaxSize().background(MaterialTheme.colorScheme.secondaryContainer)
)
} else {
Column(
- modifier = Modifier
- .fillMaxSize()
- .background(MaterialTheme.colorScheme.primary),
+ modifier = Modifier.fillMaxSize().background(MaterialTheme.colorScheme.primary),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center,
) {
@@ -103,7 +96,6 @@
backgroundKey = if (!showMainScreen) "MainKey" else "Background",
contentKey = if (showMainScreen) "MainKey" else "ItemKey",
) { isBackground ->
-
if (isBackground || showMainScreen) {
// Best practice would be to use State Hoisting and leave this composable stateless.
// Here, we want to support MainScreen being shown from different destinations
@@ -116,26 +108,22 @@
// and can be shown in foreground or background.
val checked = rememberSaveable { mutableStateOf(true) }
Column(
- modifier = Modifier
- .fillMaxSize()
- .padding(horizontal = 8.dp, vertical = 8.dp),
- verticalArrangement = Arrangement.spacedBy(
- 4.dp, Alignment.CenterVertically
- ),
+ modifier =
+ Modifier.fillMaxSize().padding(horizontal = 8.dp, vertical = 8.dp),
+ verticalArrangement =
+ Arrangement.spacedBy(4.dp, Alignment.CenterVertically),
) {
Row(
- modifier = Modifier
- .height(40.dp)
- .background(
- color = MaterialTheme.colorScheme.surfaceContainer,
- shape = CircleShape
- )
- .padding(horizontal = 12.dp),
+ modifier =
+ Modifier.height(40.dp)
+ .background(
+ color = MaterialTheme.colorScheme.surfaceContainer,
+ shape = CircleShape
+ )
+ .padding(horizontal = 12.dp),
verticalAlignment = Alignment.CenterVertically,
) {
- Box(
- modifier = Modifier.clickable { showMainScreen = false }
- ) {
+ Box(modifier = Modifier.clickable { showMainScreen = false }) {
Text("Item details")
}
ToggleButton(
@@ -150,9 +138,7 @@
)
} else {
Column(
- modifier = Modifier
- .fillMaxSize()
- .background(MaterialTheme.colorScheme.primary),
+ modifier = Modifier.fillMaxSize().background(MaterialTheme.colorScheme.primary),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center,
) {
@@ -165,33 +151,28 @@
@Sampled
@Composable
-fun EdgeSwipeForSwipeToDismiss(
- navigateBack: () -> Unit
-) {
+fun EdgeSwipeForSwipeToDismiss(navigateBack: () -> Unit) {
val state = rememberSwipeToDismissBoxState()
// When using Modifier.edgeSwipeToDismiss, it is required that the element on which the
// modifier applies exists within a SwipeToDismissBox which shares the same state.
- SwipeToDismissBox(
- state = state,
- onDismissed = navigateBack
- ) { isBackground ->
+ SwipeToDismissBox(state = state, onDismissed = navigateBack) { isBackground ->
val horizontalScrollState = rememberScrollState(0)
if (isBackground) {
Box(
- modifier = Modifier
- .fillMaxSize()
- .background(MaterialTheme.colorScheme.secondaryContainer)
+ modifier =
+ Modifier.fillMaxSize().background(MaterialTheme.colorScheme.secondaryContainer)
)
} else {
Box(modifier = Modifier.fillMaxSize()) {
Text(
- modifier = Modifier
- .align(Alignment.Center)
- .edgeSwipeToDismiss(state)
- .horizontalScroll(horizontalScrollState),
- text = "This text can be scrolled horizontally - to dismiss, swipe " +
- "right from the left edge of the screen (called Edge Swiping)",
+ modifier =
+ Modifier.align(Alignment.Center)
+ .edgeSwipeToDismiss(state)
+ .horizontalScroll(horizontalScrollState),
+ text =
+ "This text can be scrolled horizontally - to dismiss, swipe " +
+ "right from the left edge of the screen (called Edge Swiping)",
)
}
}
diff --git a/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/TextButtonSample.kt b/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/TextButtonSample.kt
index c47e108..f340a68 100644
--- a/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/TextButtonSample.kt
+++ b/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/TextButtonSample.kt
@@ -28,9 +28,7 @@
@Composable
@Sampled
fun TextButtonSample() {
- TextButton(onClick = { /* Do something */ }) {
- Text(text = "ABC")
- }
+ TextButton(onClick = { /* Do something */ }) { Text(text = "ABC") }
}
@Composable
diff --git a/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/TextToggleButtonSample.kt b/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/TextToggleButtonSample.kt
index 7cabde1..4da883e 100644
--- a/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/TextToggleButtonSample.kt
+++ b/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/TextToggleButtonSample.kt
@@ -33,13 +33,8 @@
@Composable
fun TextToggleButtonSample() {
var checked by remember { mutableStateOf(true) }
- TextToggleButton(
- checked = checked,
- onCheckedChange = { checked = !checked }
- ) {
- Text(
- text = if (checked) "On" else "Off"
- )
+ TextToggleButton(checked = checked, onCheckedChange = { checked = !checked }) {
+ Text(text = if (checked) "On" else "Off")
}
}
diff --git a/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/TimeTextSample.kt b/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/TimeTextSample.kt
index 45588cd..b4bf119 100644
--- a/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/TimeTextSample.kt
+++ b/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/TimeTextSample.kt
@@ -29,9 +29,7 @@
@Sampled
@Composable
fun TimeTextClockOnly() {
- TimeText {
- time()
- }
+ TimeText { time() }
}
@Sampled
diff --git a/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/ToggleButtonSample.kt b/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/ToggleButtonSample.kt
index 247aacd..953f5fa 100644
--- a/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/ToggleButtonSample.kt
+++ b/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/ToggleButtonSample.kt
@@ -37,21 +37,14 @@
fun ToggleButtonWithCheckbox() {
var checked by remember { mutableStateOf(true) }
ToggleButton(
- label = {
- Text("Checkbox", maxLines = 3, overflow = TextOverflow.Ellipsis)
- },
+ label = { Text("Checkbox", maxLines = 3, overflow = TextOverflow.Ellipsis) },
secondaryLabel = {
Text("With secondary label", maxLines = 2, overflow = TextOverflow.Ellipsis)
},
checked = checked,
toggleControl = { Checkbox() },
onCheckedChange = { checked = it },
- icon = {
- Icon(
- Icons.Filled.Favorite,
- contentDescription = "Favorite icon"
- )
- },
+ icon = { Icon(Icons.Filled.Favorite, contentDescription = "Favorite icon") },
enabled = true,
)
}
@@ -61,21 +54,14 @@
fun ToggleButtonWithSwitch() {
var checked by remember { mutableStateOf(true) }
ToggleButton(
- label = {
- Text("Switch", maxLines = 3, overflow = TextOverflow.Ellipsis)
- },
+ label = { Text("Switch", maxLines = 3, overflow = TextOverflow.Ellipsis) },
secondaryLabel = {
Text("With secondary label", maxLines = 2, overflow = TextOverflow.Ellipsis)
},
checked = checked,
toggleControl = { Switch() },
onCheckedChange = { checked = it },
- icon = {
- Icon(
- Icons.Filled.Favorite,
- contentDescription = "Favorite icon"
- )
- },
+ icon = { Icon(Icons.Filled.Favorite, contentDescription = "Favorite icon") },
enabled = true,
)
}
@@ -85,9 +71,7 @@
fun SplitToggleButtonWithCheckbox() {
var checked by remember { mutableStateOf(true) }
SplitToggleButton(
- label = {
- Text("Split with CheckboxIcon", maxLines = 3, overflow = TextOverflow.Ellipsis)
- },
+ label = { Text("Split with CheckboxIcon", maxLines = 3, overflow = TextOverflow.Ellipsis) },
checked = checked,
toggleControl = { Checkbox() },
onCheckedChange = { checked = it },
@@ -103,9 +87,7 @@
fun SplitToggleButtonWithSwitch() {
var checked by remember { mutableStateOf(true) }
SplitToggleButton(
- label = {
- Text("Split with CheckboxIcon", maxLines = 3, overflow = TextOverflow.Ellipsis)
- },
+ label = { Text("Split with CheckboxIcon", maxLines = 3, overflow = TextOverflow.Ellipsis) },
checked = checked,
toggleControl = { Switch() },
onCheckedChange = { checked = it },
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 ab36b79..7393cb2 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
@@ -55,72 +55,42 @@
@RunWith(AndroidJUnit4::class)
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
class ButtonScreenshotTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
- @get:Rule
- val screenshotRule = AndroidXScreenshotTestRule(SCREENSHOT_GOLDEN_PATH)
+ @get:Rule val screenshotRule = AndroidXScreenshotTestRule(SCREENSHOT_GOLDEN_PATH)
- @get:Rule
- val testName = TestName()
+ @get:Rule val testName = TestName()
+
+ @Test fun button_enabled() = verifyScreenshot() { BaseButton() }
+
+ @Test fun button_disabled() = verifyScreenshot() { BaseButton(enabled = false) }
@Test
- fun button_enabled() = verifyScreenshot() {
- BaseButton()
- }
+ fun three_slot_button_ltr() =
+ verifyScreenshot(layoutDirection = LayoutDirection.Ltr) { ThreeSlotButton() }
@Test
- fun button_disabled() = verifyScreenshot() {
- BaseButton(enabled = false)
- }
+ fun three_slot_button_rtl() =
+ verifyScreenshot(layoutDirection = LayoutDirection.Rtl) { ThreeSlotButton() }
- @Test
- fun three_slot_button_ltr() = verifyScreenshot(layoutDirection = LayoutDirection.Ltr) {
- ThreeSlotButton()
- }
+ @Test fun button_outlined_enabled() = verifyScreenshot() { OutlinedButton() }
- @Test
- fun three_slot_button_rtl() = verifyScreenshot(layoutDirection = LayoutDirection.Rtl) {
- ThreeSlotButton()
- }
+ @Test fun button_outlined_disabled() = verifyScreenshot() { OutlinedButton(enabled = false) }
- @Test
- fun button_outlined_enabled() = verifyScreenshot() {
- OutlinedButton()
- }
-
- @Test
- fun button_outlined_disabled() = verifyScreenshot() {
- OutlinedButton(enabled = false)
- }
-
- @Test
- fun button_image_background_enabled() = verifyScreenshot {
- ImageBackgroundButton()
- }
+ @Test fun button_image_background_enabled() = verifyScreenshot { ImageBackgroundButton() }
@Test
fun button_image_background_disabled() = verifyScreenshot {
ImageBackgroundButton(enabled = false)
}
- @Test
- fun compact_button_enabled() = verifyScreenshot {
- CompactButton()
- }
+ @Test fun compact_button_enabled() = verifyScreenshot { CompactButton() }
- @Test
- fun compact_button_disabled() = verifyScreenshot {
- CompactButton(enabled = false)
- }
+ @Test fun compact_button_disabled() = verifyScreenshot { CompactButton(enabled = false) }
@Composable
private fun BaseButton(enabled: Boolean = true) {
- Button(
- enabled = enabled,
- onClick = {},
- modifier = Modifier.testTag(TEST_TAG)
- ) {
+ Button(enabled = enabled, onClick = {}, modifier = Modifier.testTag(TEST_TAG)) {
CenteredText("Base Button")
}
}
@@ -139,11 +109,7 @@
@Composable
private fun OutlinedButton(enabled: Boolean = true) {
- OutlinedButton(
- enabled = enabled,
- onClick = {},
- modifier = Modifier.testTag(TEST_TAG)
- ) {
+ OutlinedButton(enabled = enabled, onClick = {}, modifier = Modifier.testTag(TEST_TAG)) {
CenteredText("Outlined Button")
}
}
@@ -155,9 +121,10 @@
onClick = {},
label = { Text("Image Button") },
secondaryLabel = { Text("Secondary Label") },
- colors = ButtonDefaults.imageBackgroundButtonColors(
- backgroundImagePainter = painterResource(R.drawable.backgroundimage1)
- ),
+ colors =
+ ButtonDefaults.imageBackgroundButtonColors(
+ backgroundImagePainter = painterResource(R.drawable.backgroundimage1)
+ ),
icon = { TestIcon() },
modifier = Modifier.testTag(TEST_TAG)
)
@@ -181,16 +148,16 @@
rule.setContentWithTheme {
CompositionLocalProvider(LocalLayoutDirection provides layoutDirection) {
Box(
- modifier = Modifier
- .fillMaxSize()
- .background(MaterialTheme.colorScheme.background)
+ modifier =
+ Modifier.fillMaxSize().background(MaterialTheme.colorScheme.background)
) {
content()
}
}
}
- rule.onNodeWithTag(TEST_TAG)
+ rule
+ .onNodeWithTag(TEST_TAG)
.captureToImage()
.assertAgainstGolden(screenshotRule, testName.methodName)
}
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ButtonTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ButtonTest.kt
index 5b43b7e..1261a1f 100644
--- a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ButtonTest.kt
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ButtonTest.kt
@@ -64,8 +64,7 @@
import org.junit.Test
class ButtonTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
@Test
fun supports_testtag() {
@@ -84,11 +83,7 @@
@Test
fun has_click_action_when_enabled() {
rule.setContentWithTheme {
- Button(
- onClick = {},
- enabled = true,
- modifier = Modifier.testTag(TEST_TAG)
- ) {
+ Button(onClick = {}, enabled = true, modifier = Modifier.testTag(TEST_TAG)) {
Text("Test")
}
}
@@ -99,11 +94,7 @@
@Test
fun has_click_action_when_disabled() {
rule.setContentWithTheme {
- Button(
- onClick = {},
- enabled = false,
- modifier = Modifier.testTag(TEST_TAG)
- ) {
+ Button(onClick = {}, enabled = false, modifier = Modifier.testTag(TEST_TAG)) {
Text("Test")
}
}
@@ -114,11 +105,7 @@
@Test
fun is_correctly_enabled() {
rule.setContentWithTheme {
- Button(
- onClick = {},
- enabled = true,
- modifier = Modifier.testTag(TEST_TAG)
- ) {
+ Button(onClick = {}, enabled = true, modifier = Modifier.testTag(TEST_TAG)) {
Text("Test")
}
}
@@ -129,11 +116,7 @@
@Test
fun is_correctly_disabled() {
rule.setContentWithTheme {
- Button(
- onClick = {},
- enabled = false,
- modifier = Modifier.testTag(TEST_TAG)
- ) {
+ Button(onClick = {}, enabled = false, modifier = Modifier.testTag(TEST_TAG)) {
Text("Test")
}
}
@@ -157,9 +140,7 @@
rule.onNodeWithTag(TEST_TAG).performClick()
- rule.runOnIdle {
- assertEquals(true, clicked)
- }
+ rule.runOnIdle { assertEquals(true, clicked) }
}
@Test
@@ -177,13 +158,9 @@
}
}
- rule.onNodeWithTag(TEST_TAG).performTouchInput {
- longClick()
- }
+ rule.onNodeWithTag(TEST_TAG).performTouchInput { longClick() }
- rule.runOnIdle {
- assertEquals(true, longClicked)
- }
+ rule.runOnIdle { assertEquals(true, longClicked) }
}
@Test
@@ -195,7 +172,8 @@
modifier = Modifier.testTag(TEST_TAG),
onClick = {},
onLongClick = {},
- onLongClickLabel = testLabel) {
+ onLongClickLabel = testLabel
+ ) {
Text("Button")
}
}
@@ -219,9 +197,7 @@
rule.onNodeWithTag(TEST_TAG).performClick()
- rule.runOnIdle {
- assertEquals(false, clicked)
- }
+ rule.runOnIdle { assertEquals(false, clicked) }
}
@Test
@@ -239,33 +215,20 @@
}
}
- rule.onNodeWithTag(TEST_TAG).performTouchInput {
- longClick()
- }
+ rule.onNodeWithTag(TEST_TAG).performTouchInput { longClick() }
- rule.runOnIdle {
- assertEquals(false, longClicked)
- }
+ rule.runOnIdle { assertEquals(false, longClicked) }
}
@Test
fun has_role_button() {
rule.setContentWithTheme {
- Button(
- onClick = {},
- modifier = Modifier.testTag(TEST_TAG)
- ) {
- Text("Test")
- }
+ Button(onClick = {}, modifier = Modifier.testTag(TEST_TAG)) { Text("Test") }
}
- rule.onNodeWithTag(TEST_TAG)
- .assert(
- SemanticsMatcher.expectValue(
- SemanticsProperties.Role,
- Role.Button
- )
- )
+ rule
+ .onNodeWithTag(TEST_TAG)
+ .assert(SemanticsMatcher.expectValue(SemanticsProperties.Role, Role.Button))
}
@Test
@@ -281,13 +244,9 @@
)
}
- rule.onNodeWithTag(TEST_TAG)
- .assert(
- SemanticsMatcher.expectValue(
- SemanticsProperties.Role,
- Role.Button
- )
- )
+ rule
+ .onNodeWithTag(TEST_TAG)
+ .assert(SemanticsMatcher.expectValue(SemanticsProperties.Role, Role.Button))
}
@Test
@@ -319,12 +278,8 @@
expectedSecondaryTextStyle = MaterialTheme.typography.labelSmall
Button(
onClick = {},
- label = {
- actualLabelTextStyle = LocalTextStyle.current
- },
- secondaryLabel = {
- actualSecondaryLabelTextStyle = LocalTextStyle.current
- }
+ label = { actualLabelTextStyle = LocalTextStyle.current },
+ secondaryLabel = { actualSecondaryLabelTextStyle = LocalTextStyle.current }
)
}
assertEquals(expectedTextStyle, actualLabelTextStyle)
@@ -338,10 +293,7 @@
expectedShape = RoundedCornerShape(CornerSize(50)),
colors = { ButtonDefaults.buttonColors() }
) { modifier ->
- Button(
- onClick = {},
- modifier = modifier
- ) {
+ Button(onClick = {}, modifier = modifier) {
// omit content to allow us to validate the shape by pixel checking.
}
}
@@ -352,15 +304,9 @@
fun allows_custom_shape_override() {
val shape = CutCornerShape(4.dp)
- rule.isShape(
- expectedShape = shape,
- colors = { ButtonDefaults.buttonColors() }
- ) { modifier ->
- Button(
- onClick = {},
- modifier = modifier,
- shape = shape
- ) {
+ rule.isShape(expectedShape = shape, colors = { ButtonDefaults.buttonColors() }) { modifier
+ ->
+ Button(onClick = {}, modifier = modifier, shape = shape) {
// omit content to allow us to validate the shape by pixel checking.
}
}
@@ -368,11 +314,8 @@
@Test
fun gives_base_button_correct_height() {
- rule.setContentWithThemeForSizeAssertions {
- Button(
- onClick = {}
- ) {}
- }
+ rule
+ .setContentWithThemeForSizeAssertions { Button(onClick = {}) {} }
.assertHeightIsEqualTo(ButtonDefaults.Height)
}
@@ -380,25 +323,27 @@
fun gives_base_button_has_adjustable_height() {
val minHeight = ButtonDefaults.Height + 1.dp
- rule.setContentWithThemeForSizeAssertions {
- Button(
- onClick = {},
- ) {
- Text(text = "Button with multiple lines of text to exceed default" +
- " minimum height. This should exceed the minimum height for the button.")
+ rule
+ .setContentWithThemeForSizeAssertions {
+ Button(
+ onClick = {},
+ ) {
+ Text(
+ text =
+ "Button with multiple lines of text to exceed default" +
+ " minimum height. This should exceed the minimum height for the button."
+ )
+ }
}
- }
.assertHeightIsAtLeast(minHeight)
}
@Test
fun gives_three_slot_button_correct_height() {
- rule.setContentWithThemeForSizeAssertions {
- Button(
- onClick = {},
- label = { Text("Label") }
- )
- }
+ rule
+ .setContentWithThemeForSizeAssertions {
+ Button(onClick = {}, label = { Text("Label") })
+ }
.assertHeightIsEqualTo(ButtonDefaults.Height)
}
@@ -406,35 +351,39 @@
fun gives_three_slot_button_has_adjustable_height() {
val minHeight = ButtonDefaults.Height + 1.dp
- rule.setContentWithThemeForSizeAssertions {
- Button(
- onClick = {},
- label = {
- Text(text = "Button with multiple lines of text to exceed default" +
- " minimum height. This should exceed the minimum height for the button.")
- }
- )
- }
+ rule
+ .setContentWithThemeForSizeAssertions {
+ Button(
+ onClick = {},
+ label = {
+ Text(
+ text =
+ "Button with multiple lines of text to exceed default" +
+ " minimum height. This should exceed the minimum height for the button."
+ )
+ }
+ )
+ }
.assertHeightIsAtLeast(minHeight)
}
@Test
fun has_icon_in_correct_location_for_three_slot_button_and_label_only() {
val iconTag = "TestIcon"
- rule
- .setContentWithThemeForSizeAssertions(useUnmergedTree = true) {
- Button(
- onClick = {},
- label = { Text("Blue green orange") },
- icon = { TestImage(iconTag) },
- modifier = Modifier.testTag(TEST_TAG)
- )
- }
+ rule.setContentWithThemeForSizeAssertions(useUnmergedTree = true) {
+ Button(
+ onClick = {},
+ label = { Text("Blue green orange") },
+ icon = { TestImage(iconTag) },
+ modifier = Modifier.testTag(TEST_TAG)
+ )
+ }
val itemBounds = rule.onNodeWithTag(TEST_TAG).getUnclippedBoundsInRoot()
- val iconBounds = rule.onNodeWithTag(iconTag, useUnmergedTree = true)
- .getUnclippedBoundsInRoot()
+ val iconBounds =
+ rule.onNodeWithTag(iconTag, useUnmergedTree = true).getUnclippedBoundsInRoot()
- rule.onNodeWithContentDescription(iconTag, useUnmergedTree = true)
+ rule
+ .onNodeWithContentDescription(iconTag, useUnmergedTree = true)
.assertTopPositionInRootIsEqualTo((itemBounds.height - iconBounds.height) / 2)
}
@@ -453,12 +402,12 @@
fun gives_disabled_base_button_correct_colors() {
rule.verifyButtonColors(
status = Status.Disabled,
- expectedContainerColor = { MaterialTheme.colorScheme.onSurface.copy(
- alpha = DisabledContainerAlpha
- ) },
- expectedContentColor = { MaterialTheme.colorScheme.onSurface.copy(
- alpha = DisabledContentAlpha
- ) },
+ expectedContainerColor = {
+ MaterialTheme.colorScheme.onSurface.copy(alpha = DisabledContainerAlpha)
+ },
+ expectedContentColor = {
+ MaterialTheme.colorScheme.onSurface.copy(alpha = DisabledContentAlpha)
+ },
)
}
@@ -478,12 +427,12 @@
fun gives_disabled_filled_tonal_base_button_correct_colors() {
rule.verifyButtonColors(
status = Status.Disabled,
- expectedContainerColor = { MaterialTheme.colorScheme.onSurface.copy(
- alpha = DisabledContainerAlpha
- ) },
- expectedContentColor = { MaterialTheme.colorScheme.onSurface.copy(
- alpha = DisabledContentAlpha
- ) },
+ expectedContainerColor = {
+ MaterialTheme.colorScheme.onSurface.copy(alpha = DisabledContainerAlpha)
+ },
+ expectedContentColor = {
+ MaterialTheme.colorScheme.onSurface.copy(alpha = DisabledContentAlpha)
+ },
content = { FilledTonalButton(Status.Disabled) }
)
}
@@ -505,9 +454,9 @@
rule.verifyButtonColors(
status = Status.Disabled,
expectedContainerColor = { Color.Transparent },
- expectedContentColor = { MaterialTheme.colorScheme.onSurface.copy(
- alpha = DisabledContentAlpha
- ) },
+ expectedContentColor = {
+ MaterialTheme.colorScheme.onSurface.copy(alpha = DisabledContentAlpha)
+ },
content = { OutlinedButton(Status.Disabled) }
)
}
@@ -529,9 +478,9 @@
rule.verifyButtonColors(
status = Status.Disabled,
expectedContainerColor = { Color.Transparent },
- expectedContentColor = { MaterialTheme.colorScheme.onSurface.copy(
- alpha = DisabledContentAlpha
- ) },
+ expectedContentColor = {
+ MaterialTheme.colorScheme.onSurface.copy(alpha = DisabledContentAlpha)
+ },
content = { ChildButton(Status.Disabled) }
)
}
@@ -623,11 +572,7 @@
rule.verifyButtonBorderColor(
expectedBorderColor = { MaterialTheme.colorScheme.outline },
content = { modifier: Modifier ->
- OutlinedButton(
- onClick = {},
- modifier = modifier,
- enabled = status.enabled()
- ) {}
+ OutlinedButton(onClick = {}, modifier = modifier, enabled = status.enabled()) {}
}
)
}
@@ -645,9 +590,10 @@
onClick = {},
modifier = modifier,
enabled = status.enabled(),
- border = ButtonDefaults.outlinedButtonBorder(
- enabled = status.enabled(),
- )
+ border =
+ ButtonDefaults.outlinedButtonBorder(
+ enabled = status.enabled(),
+ )
) {}
}
)
@@ -664,11 +610,12 @@
onClick = {},
modifier = modifier,
enabled = status.enabled(),
- border = ButtonDefaults.outlinedButtonBorder(
- enabled = status.enabled(),
- borderColor = Color.Green,
- disabledBorderColor = Color.Red
- )
+ border =
+ ButtonDefaults.outlinedButtonBorder(
+ enabled = status.enabled(),
+ borderColor = Color.Green,
+ disabledBorderColor = Color.Red
+ )
) {}
}
)
@@ -685,11 +632,12 @@
onClick = {},
modifier = modifier,
enabled = status.enabled(),
- border = ButtonDefaults.outlinedButtonBorder(
- enabled = status.enabled(),
- borderColor = Color.Green,
- disabledBorderColor = Color.Red
- )
+ border =
+ ButtonDefaults.outlinedButtonBorder(
+ enabled = status.enabled(),
+ borderColor = Color.Green,
+ disabledBorderColor = Color.Red
+ )
) {}
}
)
@@ -702,12 +650,7 @@
rule.setContentWithTheme {
expectedTextStyle = MaterialTheme.typography.labelSmall
- CompactButton(
- onClick = {},
- label = {
- actualLabelTextStyle = LocalTextStyle.current
- }
- )
+ CompactButton(onClick = {}, label = { actualLabelTextStyle = LocalTextStyle.current })
}
assertEquals(expectedTextStyle, actualLabelTextStyle)
}
@@ -715,60 +658,58 @@
@Test
fun icon_only_compact_button_has_correct_default_width_and_height() {
val iconTag = "TestIcon"
- rule
- .setContentWithThemeForSizeAssertions(useUnmergedTree = true) {
- CompactButton(
- onClick = {},
- modifier = Modifier.testTag(TEST_TAG),
- icon = { TestImage(iconTag) }
- )
- }
+ rule.setContentWithThemeForSizeAssertions(useUnmergedTree = true) {
+ CompactButton(
+ onClick = {},
+ modifier = Modifier.testTag(TEST_TAG),
+ icon = { TestImage(iconTag) }
+ )
+ }
- rule.onRoot().assertWidthIsEqualTo(ButtonDefaults.IconOnlyCompactButtonWidth)
+ rule
+ .onRoot()
+ .assertWidthIsEqualTo(ButtonDefaults.IconOnlyCompactButtonWidth)
.assertHeightIsEqualTo(ButtonDefaults.CompactButtonHeight)
}
@Test
fun label_only_compact_button_has_correct_default_height() {
- rule
- .setContentWithThemeForSizeAssertions(useUnmergedTree = true) {
- CompactButton(
- onClick = {},
- modifier = Modifier.testTag(TEST_TAG),
- label = { Text("Test") }
- )
- }
+ rule.setContentWithThemeForSizeAssertions(useUnmergedTree = true) {
+ CompactButton(
+ onClick = {},
+ modifier = Modifier.testTag(TEST_TAG),
+ label = { Text("Test") }
+ )
+ }
rule.onRoot().assertHeightIsEqualTo(ButtonDefaults.CompactButtonHeight)
}
@Test
fun no_content_compact_button_has_correct_default_width_and_height() {
- rule
- .setContentWithThemeForSizeAssertions(useUnmergedTree = true) {
- CompactButton(
- onClick = {},
- modifier = Modifier.testTag(TEST_TAG),
- )
- }
+ rule.setContentWithThemeForSizeAssertions(useUnmergedTree = true) {
+ CompactButton(
+ onClick = {},
+ modifier = Modifier.testTag(TEST_TAG),
+ )
+ }
- rule.onRoot().assertWidthIsEqualTo(ButtonDefaults.IconOnlyCompactButtonWidth)
+ rule
+ .onRoot()
+ .assertWidthIsEqualTo(ButtonDefaults.IconOnlyCompactButtonWidth)
.assertHeightIsEqualTo(ButtonDefaults.CompactButtonHeight)
}
@Test
fun icon_only_compact_button_can_have_width_overridden() {
val iconTag = "TestIcon"
- rule
- .setContentWithThemeForSizeAssertions(useUnmergedTree = true) {
- CompactButton(
- onClick = {},
- modifier = Modifier
- .testTag(TEST_TAG)
- .width(100.dp),
- icon = { TestImage(iconTag) }
- )
- }
+ rule.setContentWithThemeForSizeAssertions(useUnmergedTree = true) {
+ CompactButton(
+ onClick = {},
+ modifier = Modifier.testTag(TEST_TAG).width(100.dp),
+ icon = { TestImage(iconTag) }
+ )
+ }
rule.onRoot().assertWidthIsEqualTo(100.dp)
}
@@ -776,20 +717,20 @@
@Test
fun has_icon_in_correct_location_in_compact_button() {
val iconTag = "TestIcon"
- rule
- .setContentWithThemeForSizeAssertions(useUnmergedTree = true) {
- CompactButton(
- onClick = {},
- label = { Text("Blue green orange") },
- icon = { TestImage(iconTag) },
- modifier = Modifier.testTag(TEST_TAG)
- )
- }
+ rule.setContentWithThemeForSizeAssertions(useUnmergedTree = true) {
+ CompactButton(
+ onClick = {},
+ label = { Text("Blue green orange") },
+ icon = { TestImage(iconTag) },
+ modifier = Modifier.testTag(TEST_TAG)
+ )
+ }
val itemBounds = rule.onNodeWithTag(TEST_TAG).getUnclippedBoundsInRoot()
- val iconBounds = rule.onNodeWithTag(iconTag, useUnmergedTree = true)
- .getUnclippedBoundsInRoot()
+ val iconBounds =
+ rule.onNodeWithTag(iconTag, useUnmergedTree = true).getUnclippedBoundsInRoot()
- rule.onNodeWithContentDescription(iconTag, useUnmergedTree = true)
+ rule
+ .onNodeWithContentDescription(iconTag, useUnmergedTree = true)
.assertTopPositionInRootIsEqualTo(
(itemBounds.height - iconBounds.height) / 2 +
ButtonDefaults.CompactButtonTapTargetPadding.calculateTopPadding()
@@ -799,19 +740,19 @@
@Test
fun has_icon_in_correct_location_when_icon_only_compact_button() {
val iconTag = "TestIcon"
- rule
- .setContentWithThemeForSizeAssertions(useUnmergedTree = true) {
- CompactButton(
- onClick = {},
- icon = { TestImage(iconTag) },
- modifier = Modifier.testTag(TEST_TAG)
- )
- }
+ rule.setContentWithThemeForSizeAssertions(useUnmergedTree = true) {
+ CompactButton(
+ onClick = {},
+ icon = { TestImage(iconTag) },
+ modifier = Modifier.testTag(TEST_TAG)
+ )
+ }
val itemBounds = rule.onNodeWithTag(TEST_TAG).getUnclippedBoundsInRoot()
- val iconBounds = rule.onNodeWithTag(iconTag, useUnmergedTree = true)
- .getUnclippedBoundsInRoot()
+ val iconBounds =
+ rule.onNodeWithTag(iconTag, useUnmergedTree = true).getUnclippedBoundsInRoot()
- rule.onNodeWithContentDescription(iconTag, useUnmergedTree = true)
+ rule
+ .onNodeWithContentDescription(iconTag, useUnmergedTree = true)
.assertTopPositionInRootIsEqualTo(
(itemBounds.height - iconBounds.height) / 2 +
ButtonDefaults.CompactButtonTapTargetPadding.calculateTopPadding()
@@ -903,7 +844,9 @@
expectedContainerColor = expectedContainerColor,
expectedContentColor = expectedContentColor,
applyAlphaForDisabled = false,
- content = { return@verifyColors content() }
+ content = {
+ return@verifyColors content()
+ }
)
}
@@ -938,9 +881,7 @@
}
@Composable
-private fun OutlinedButton(
- status: Status
-): Color {
+private fun OutlinedButton(status: Status): Color {
var actualContentColor = Color.Transparent
OutlinedButton(
onClick = {},
@@ -953,9 +894,7 @@
}
@Composable
-private fun ChildButton(
- status: Status
-): Color {
+private fun ChildButton(status: Status): Color {
var actualContentColor = Color.Transparent
ChildButton(
onClick = {},
@@ -982,18 +921,15 @@
setContentWithTheme {
val buttonColors = expectedColor()
- containerColor = (
- (buttonColors.containerPainter(status.enabled()) as ColorPainter).color)
- .compositeOver(testBackgroundColor)
+ containerColor =
+ ((buttonColors.containerPainter(status.enabled()) as ColorPainter).color).compositeOver(
+ testBackgroundColor
+ )
labelColor = buttonColors.contentColor(status.enabled())
secondaryLabelColor = buttonColors.secondaryContentColor(status.enabled())
iconColor = buttonColors.iconColor(status.enabled())
- Box(
- Modifier
- .fillMaxSize()
- .background(testBackgroundColor)
- ) {
+ Box(Modifier.fillMaxSize().background(testBackgroundColor)) {
threeSlotButtonColors = content()
}
}
@@ -1010,9 +946,7 @@
}
@Composable
-private fun ThreeSlotFilledButton(
- status: Status
-): ThreeSlotButtonColors {
+private fun ThreeSlotFilledButton(status: Status): ThreeSlotButtonColors {
var actualLabelColor: Color = Color.Transparent
var actualSecondaryLabelColor: Color = Color.Transparent
var actualIconColor: Color = Color.Transparent
@@ -1028,9 +962,7 @@
}
@Composable
-private fun ThreeSlotFilledTonalButton(
- status: Status
-): ThreeSlotButtonColors {
+private fun ThreeSlotFilledTonalButton(status: Status): ThreeSlotButtonColors {
var actualLabelColor: Color = Color.Transparent
var actualSecondaryLabelColor: Color = Color.Transparent
var actualIconColor: Color = Color.Transparent
@@ -1046,9 +978,7 @@
}
@Composable
-private fun ThreeSlotOutlinedButton(
- status: Status
-): ThreeSlotButtonColors {
+private fun ThreeSlotOutlinedButton(status: Status): ThreeSlotButtonColors {
var actualLabelColor: Color = Color.Transparent
var actualSecondaryLabelColor: Color = Color.Transparent
var actualIconColor: Color = Color.Transparent
@@ -1064,9 +994,7 @@
}
@Composable
-private fun ThreeSlotChildButton(
- status: Status
-): ThreeSlotButtonColors {
+private fun ThreeSlotChildButton(status: Status): ThreeSlotButtonColors {
var actualLabelColor: Color = Color.Transparent
var actualSecondaryLabelColor: Color = Color.Transparent
var actualIconColor: Color = Color.Transparent
@@ -1091,18 +1019,12 @@
setContentWithTheme {
finalExpectedBorderColor = expectedBorderColor().compositeOver(testBackground)
- Box(
- Modifier
- .fillMaxSize()
- .background(testBackground)
- ) {
+ Box(Modifier.fillMaxSize().background(testBackground)) {
content(Modifier.testTag(TEST_TAG))
}
}
- onNodeWithTag(TEST_TAG)
- .captureToImage()
- .assertContainsColor(finalExpectedBorderColor)
+ onNodeWithTag(TEST_TAG).captureToImage().assertContainsColor(finalExpectedBorderColor)
}
@RequiresApi(Build.VERSION_CODES.O)
@@ -1122,11 +1044,7 @@
if (buttonColor == Color.Transparent) {
buttonColor = background
}
- content(
- Modifier
- .testTag(TEST_TAG)
- .padding(padding)
- )
+ content(Modifier.testTag(TEST_TAG).padding(padding))
}
}
@@ -1156,16 +1074,14 @@
var actualIconColor = Color.Transparent
setContentWithTheme {
- containerColor = ((colors().containerPainter(status.enabled()) as ColorPainter).color)
- .compositeOver(testBackgroundColor)
+ containerColor =
+ ((colors().containerPainter(status.enabled()) as ColorPainter).color).compositeOver(
+ testBackgroundColor
+ )
labelColor = colors().contentColor(status.enabled())
iconColor = colors().iconColor(status.enabled())
- Box(
- Modifier
- .fillMaxSize()
- .background(testBackgroundColor)
- ) {
+ Box(Modifier.fillMaxSize().background(testBackgroundColor)) {
CompactButton(
onClick = {},
colors = colors(),
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/CardScreenshotTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/CardScreenshotTest.kt
index 01cec23..a53c3f9 100644
--- a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/CardScreenshotTest.kt
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/CardScreenshotTest.kt
@@ -44,100 +44,91 @@
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
class CardScreenshotTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
- @get:Rule
- val screenshotRule = AndroidXScreenshotTestRule(SCREENSHOT_GOLDEN_PATH)
+ @get:Rule val screenshotRule = AndroidXScreenshotTestRule(SCREENSHOT_GOLDEN_PATH)
- @get:Rule
- val testName = TestName()
+ @get:Rule val testName = TestName()
+
+ @Test fun card_ltr() = verifyScreenshot(layoutDirection = LayoutDirection.Ltr) { sampleCard() }
@Test
- fun card_ltr() = verifyScreenshot(layoutDirection = LayoutDirection.Ltr) {
- sampleCard()
- }
+ fun card_disabled() =
+ verifyScreenshot(layoutDirection = LayoutDirection.Ltr) { sampleCard(enabled = false) }
- @Test
- fun card_disabled() = verifyScreenshot(layoutDirection = LayoutDirection.Ltr) {
- sampleCard(enabled = false)
- }
-
- @Test
- fun card_rtl() = verifyScreenshot(layoutDirection = LayoutDirection.Rtl) {
- sampleCard()
- }
+ @Test fun card_rtl() = verifyScreenshot(layoutDirection = LayoutDirection.Rtl) { sampleCard() }
@Test
fun card_image_background() = verifyScreenshot {
sampleCard(
- colors = CardDefaults.imageCardColors(
- containerPainter = CardDefaults.imageWithScrimBackgroundPainter(
- backgroundImagePainter = painterResource(
- id = androidx.wear.compose.material3.test.R.drawable.backgroundimage1
- )
+ colors =
+ CardDefaults.imageCardColors(
+ containerPainter =
+ CardDefaults.imageWithScrimBackgroundPainter(
+ backgroundImagePainter =
+ painterResource(
+ id =
+ androidx.wear.compose.material3.test.R.drawable
+ .backgroundimage1
+ )
+ )
)
- )
)
}
@Test
- fun outlined_card_ltr() = verifyScreenshot(layoutDirection = LayoutDirection.Ltr) {
- sampleOutlinedCard()
- }
+ fun outlined_card_ltr() =
+ verifyScreenshot(layoutDirection = LayoutDirection.Ltr) { sampleOutlinedCard() }
@Test
- fun outlined_card_disabled() = verifyScreenshot(layoutDirection = LayoutDirection.Ltr) {
- sampleOutlinedCard(enabled = false)
- }
+ fun outlined_card_disabled() =
+ verifyScreenshot(layoutDirection = LayoutDirection.Ltr) {
+ sampleOutlinedCard(enabled = false)
+ }
@Test
- fun outlined_card_rtl() = verifyScreenshot(layoutDirection = LayoutDirection.Rtl) {
- sampleOutlinedCard()
- }
+ fun outlined_card_rtl() =
+ verifyScreenshot(layoutDirection = LayoutDirection.Rtl) { sampleOutlinedCard() }
@Test
- fun app_card_ltr() = verifyScreenshot(layoutDirection = LayoutDirection.Ltr) {
- sampleAppCard()
- }
+ fun app_card_ltr() = verifyScreenshot(layoutDirection = LayoutDirection.Ltr) { sampleAppCard() }
@Test
- fun app_card_disabled() = verifyScreenshot(layoutDirection = LayoutDirection.Ltr) {
- sampleAppCard(enabled = false)
- }
+ fun app_card_disabled() =
+ verifyScreenshot(layoutDirection = LayoutDirection.Ltr) { sampleAppCard(enabled = false) }
@Test
- fun app_card_rtl() = verifyScreenshot(layoutDirection = LayoutDirection.Rtl) {
- sampleAppCard()
- }
+ fun app_card_rtl() = verifyScreenshot(layoutDirection = LayoutDirection.Rtl) { sampleAppCard() }
@Test
fun app_card_image_background() = verifyScreenshot {
sampleAppCard(
- colors = CardDefaults.imageCardColors(
- containerPainter = CardDefaults.imageWithScrimBackgroundPainter(
- backgroundImagePainter = painterResource(
- id = androidx.wear.compose.material3.test.R.drawable.backgroundimage1
- )
+ colors =
+ CardDefaults.imageCardColors(
+ containerPainter =
+ CardDefaults.imageWithScrimBackgroundPainter(
+ backgroundImagePainter =
+ painterResource(
+ id =
+ androidx.wear.compose.material3.test.R.drawable
+ .backgroundimage1
+ )
+ )
)
- )
)
}
@Test
- fun title_card_ltr() = verifyScreenshot(layoutDirection = LayoutDirection.Ltr) {
- sampleTitleCard()
- }
+ fun title_card_ltr() =
+ verifyScreenshot(layoutDirection = LayoutDirection.Ltr) { sampleTitleCard() }
@Test
- fun title_card_disabled() = verifyScreenshot(layoutDirection = LayoutDirection.Ltr) {
- sampleTitleCard(enabled = false)
- }
+ fun title_card_disabled() =
+ verifyScreenshot(layoutDirection = LayoutDirection.Ltr) { sampleTitleCard(enabled = false) }
@Test
- fun title_card_rtl() = verifyScreenshot(layoutDirection = LayoutDirection.Rtl) {
- sampleTitleCard()
- }
+ fun title_card_rtl() =
+ verifyScreenshot(layoutDirection = LayoutDirection.Rtl) { sampleTitleCard() }
@Test
fun title_card_with_time_and_subtitle_ltr() =
@@ -178,13 +169,18 @@
@Test
fun title_card_image_background() = verifyScreenshot {
sampleTitleCard(
- colors = CardDefaults.imageCardColors(
- containerPainter = CardDefaults.imageWithScrimBackgroundPainter(
- backgroundImagePainter = painterResource(
- id = androidx.wear.compose.material3.test.R.drawable.backgroundimage1
- )
+ colors =
+ CardDefaults.imageCardColors(
+ containerPainter =
+ CardDefaults.imageWithScrimBackgroundPainter(
+ backgroundImagePainter =
+ painterResource(
+ id =
+ androidx.wear.compose.material3.test.R.drawable
+ .backgroundimage1
+ )
+ )
)
- )
)
}
@@ -197,9 +193,7 @@
enabled = enabled,
onClick = {},
colors = colors,
- modifier = Modifier
- .testTag(TEST_TAG)
- .width(cardWidth),
+ modifier = Modifier.testTag(TEST_TAG).width(cardWidth),
) {
Text("Card: Some body content")
}
@@ -212,9 +206,7 @@
OutlinedCard(
enabled = enabled,
onClick = {},
- modifier = Modifier
- .testTag(TEST_TAG)
- .width(cardWidth),
+ modifier = Modifier.testTag(TEST_TAG).width(cardWidth),
) {
Text("Outlined Card: Some body content")
}
@@ -233,9 +225,7 @@
title = { Text("AppCard") },
colors = colors,
time = { Text("now") },
- modifier = Modifier
- .testTag(TEST_TAG)
- .width(cardWidth),
+ modifier = Modifier.testTag(TEST_TAG).width(cardWidth),
) {
Text("Some body content")
Text("and some more body content")
@@ -253,9 +243,7 @@
title = { Text("TitleCard") },
time = { Text("now") },
colors = colors,
- modifier = Modifier
- .testTag(TEST_TAG)
- .width(cardWidth),
+ modifier = Modifier.testTag(TEST_TAG).width(cardWidth),
) {
Text("Some body content")
Text("and some more body content")
@@ -263,9 +251,7 @@
}
@Composable
- private fun sampleTitleCardWithTimeAndSubtitle(
- enabled: Boolean = true
- ) {
+ private fun sampleTitleCardWithTimeAndSubtitle(enabled: Boolean = true) {
TitleCard(
enabled = enabled,
onClick = {},
@@ -277,9 +263,7 @@
}
@Composable
- private fun sampleTitleCardWithContentTimeAndSubtitle(
- enabled: Boolean = true
- ) {
+ private fun sampleTitleCardWithContentTimeAndSubtitle(enabled: Boolean = true) {
TitleCard(
enabled = enabled,
onClick = {},
@@ -297,12 +281,11 @@
content: @Composable () -> Unit
) {
rule.setContentWithTheme {
- CompositionLocalProvider(LocalLayoutDirection provides layoutDirection) {
- content()
- }
+ CompositionLocalProvider(LocalLayoutDirection provides layoutDirection) { content() }
}
- rule.onNodeWithTag(TEST_TAG)
+ rule
+ .onNodeWithTag(TEST_TAG)
.captureToImage()
.assertAgainstGolden(screenshotRule, testName.methodName)
}
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/CardTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/CardTest.kt
index 55db445..1aad635 100644
--- a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/CardTest.kt
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/CardTest.kt
@@ -51,18 +51,12 @@
import org.junit.Test
class CardTest {
- @get:Rule
- val rule: ComposeContentTestRule = createComposeRule()
+ @get:Rule val rule: ComposeContentTestRule = createComposeRule()
@Test
fun supports_test_tag() {
rule.setContentWithTheme {
- Card(
- onClick = {},
- modifier = Modifier.testTag(TEST_TAG)
- ) {
- TestImage()
- }
+ Card(onClick = {}, modifier = Modifier.testTag(TEST_TAG)) { TestImage() }
}
rule.onNodeWithTag(TEST_TAG).assertExists()
@@ -71,11 +65,7 @@
@Test
fun has_clickaction_when_enabled() {
rule.setContentWithTheme {
- Card(
- onClick = {},
- enabled = true,
- modifier = Modifier.testTag(TEST_TAG)
- ) {
+ Card(onClick = {}, enabled = true, modifier = Modifier.testTag(TEST_TAG)) {
TestImage()
}
}
@@ -86,11 +76,7 @@
@Test
fun has_clickaction_when_disabled() {
rule.setContentWithTheme {
- Card(
- onClick = {},
- enabled = false,
- modifier = Modifier.testTag(TEST_TAG)
- ) {
+ Card(onClick = {}, enabled = false, modifier = Modifier.testTag(TEST_TAG)) {
TestImage()
}
}
@@ -101,11 +87,7 @@
@Test
fun is_correctly_enabled_when_enabled_equals_true() {
rule.setContentWithTheme {
- Card(
- onClick = {},
- enabled = true,
- modifier = Modifier.testTag(TEST_TAG)
- ) {
+ Card(onClick = {}, enabled = true, modifier = Modifier.testTag(TEST_TAG)) {
TestImage()
}
}
@@ -116,11 +98,7 @@
@Test
fun is_correctly_disabled_when_enabled_equals_false() {
rule.setContentWithTheme {
- Card(
- onClick = {},
- enabled = false,
- modifier = Modifier.testTag(TEST_TAG)
- ) {
+ Card(onClick = {}, enabled = false, modifier = Modifier.testTag(TEST_TAG)) {
TestImage()
}
}
@@ -144,9 +122,7 @@
rule.onNodeWithTag(TEST_TAG).performClick()
- rule.runOnIdle {
- assertEquals(true, clicked)
- }
+ rule.runOnIdle { assertEquals(true, clicked) }
}
@Test
@@ -165,9 +141,7 @@
rule.onNodeWithTag(TEST_TAG).performClick()
- rule.runOnIdle {
- assertEquals(false, clicked)
- }
+ rule.runOnIdle { assertEquals(false, clicked) }
}
@Test
@@ -176,20 +150,15 @@
Card(
onClick = {},
enabled = false,
- modifier = Modifier.testTag(TEST_TAG)
- .semantics { role = Role.Button },
+ modifier = Modifier.testTag(TEST_TAG).semantics { role = Role.Button },
) {
TestImage()
}
}
- rule.onNodeWithTag(TEST_TAG)
- .assert(
- SemanticsMatcher.expectValue(
- SemanticsProperties.Role,
- Role.Button
- )
- )
+ rule
+ .onNodeWithTag(TEST_TAG)
+ .assert(SemanticsMatcher.expectValue(SemanticsProperties.Role, Role.Button))
}
@Test
@@ -205,9 +174,10 @@
@Test
fun gives_base_card_correct_default_max_height(): Unit =
verifyHeight(
- expectedHeight = 100.dp +
- CardDefaults.ContentPadding.calculateBottomPadding() +
- CardDefaults.ContentPadding.calculateTopPadding(),
+ expectedHeight =
+ 100.dp +
+ CardDefaults.ContentPadding.calculateBottomPadding() +
+ CardDefaults.ContentPadding.calculateTopPadding(),
imageModifier = Modifier.requiredHeight(100.dp)
)
@@ -215,13 +185,17 @@
fun gives_enabled_default_colors(): Unit =
verifyColors(
CardStatus.Enabled,
- ) { MaterialTheme.colorScheme.onSurfaceVariant }
+ ) {
+ MaterialTheme.colorScheme.onSurfaceVariant
+ }
@Test
fun gives_disabled_default_colors(): Unit =
verifyColors(
CardStatus.Disabled,
- ) { MaterialTheme.colorScheme.onSurfaceVariant }
+ ) {
+ MaterialTheme.colorScheme.onSurfaceVariant
+ }
@Test
fun app_card_gives_default_colors() {
@@ -240,11 +214,7 @@
expectedTimeColor = MaterialTheme.colorScheme.onSurfaceVariant
expectedTitleColor = MaterialTheme.colorScheme.onSurface
expectedContentColor = MaterialTheme.colorScheme.onSurfaceVariant
- Box(
- modifier = Modifier
- .fillMaxSize()
- .background(testBackground)
- ) {
+ Box(modifier = Modifier.fillMaxSize().background(testBackground)) {
AppCard(
onClick = {},
appName = { actualAppColor = LocalContentColor.current },
@@ -277,11 +247,7 @@
expectedTimeColor = MaterialTheme.colorScheme.onSurfaceVariant
expectedTitleColor = MaterialTheme.colorScheme.onSurface
expectedContentColor = MaterialTheme.colorScheme.onSurfaceVariant
- Box(
- modifier = Modifier
- .fillMaxSize()
- .background(testBackground)
- ) {
+ Box(modifier = Modifier.fillMaxSize().background(testBackground)) {
TitleCard(
onClick = {},
time = { actualTimeColor = LocalContentColor.current },
@@ -312,11 +278,7 @@
expectedTimeColor = MaterialTheme.colorScheme.onSurfaceVariant
expectedSubtitleColor = MaterialTheme.colorScheme.tertiary
expectedTitleColor = MaterialTheme.colorScheme.onSurface
- Box(
- modifier = Modifier
- .fillMaxSize()
- .background(testBackground)
- ) {
+ Box(modifier = Modifier.fillMaxSize().background(testBackground)) {
TitleCard(
onClick = {},
time = { actualTimeColor = LocalContentColor.current },
@@ -339,26 +301,20 @@
val testBackground = Color.Green
rule.setContentWithTheme {
- Box(
- modifier = Modifier
- .fillMaxSize()
- .background(testBackground)
- ) {
+ Box(modifier = Modifier.fillMaxSize().background(testBackground)) {
OutlinedCard(
onClick = {},
border = CardDefaults.outlinedCardBorder(outlineColor),
- modifier = Modifier
- .testTag(TEST_TAG)
- .size(100.dp)
- .align(Alignment.Center)
- ) {
- }
+ modifier = Modifier.testTag(TEST_TAG).size(100.dp).align(Alignment.Center)
+ ) {}
}
}
rule.onNodeWithTag(TEST_TAG).captureToImage().assertContainsColor(outlineColor)
// As the color of the OutlinedCard is transparent, we expect to see a
// testBackground color covering everything except border.
- rule.onNodeWithTag(TEST_TAG).captureToImage()
+ rule
+ .onNodeWithTag(TEST_TAG)
+ .captureToImage()
.assertColorInPercentageRange(testBackground, 93f..97f)
}
@@ -369,28 +325,22 @@
val testBackground = Color.Green
rule.setContentWithTheme {
- Box(
- modifier = Modifier
- .fillMaxSize()
- .background(testBackground)
- ) {
+ Box(modifier = Modifier.fillMaxSize().background(testBackground)) {
TitleCard(
onClick = {},
title = {},
border = CardDefaults.outlinedCardBorder(outlineColor),
colors = CardDefaults.outlinedCardColors(),
- modifier = Modifier
- .testTag(TEST_TAG)
- .size(100.dp)
- .align(Alignment.Center)
- ) {
- }
+ modifier = Modifier.testTag(TEST_TAG).size(100.dp).align(Alignment.Center)
+ ) {}
}
}
rule.onNodeWithTag(TEST_TAG).captureToImage().assertContainsColor(outlineColor)
// As the color of the OutlinedCard is transparent, we expect to see a
// testBackground color covering everything except border.
- rule.onNodeWithTag(TEST_TAG).captureToImage()
+ rule
+ .onNodeWithTag(TEST_TAG)
+ .captureToImage()
.assertColorInPercentageRange(testBackground, 93f..97f)
}
@@ -401,29 +351,23 @@
val testBackground = Color.Green
rule.setContentWithTheme {
- Box(
- modifier = Modifier
- .fillMaxSize()
- .background(testBackground)
- ) {
+ Box(modifier = Modifier.fillMaxSize().background(testBackground)) {
AppCard(
onClick = {},
appName = {},
title = {},
border = CardDefaults.outlinedCardBorder(outlineColor),
colors = CardDefaults.outlinedCardColors(),
- modifier = Modifier
- .testTag(TEST_TAG)
- .size(100.dp)
- .align(Alignment.Center)
- ) {
- }
+ modifier = Modifier.testTag(TEST_TAG).size(100.dp).align(Alignment.Center)
+ ) {}
}
}
rule.onNodeWithTag(TEST_TAG).captureToImage().assertContainsColor(outlineColor)
// As the color of the OutlinedCard is transparent, we expect to see a
// testBackground color covering everything except border.
- rule.onNodeWithTag(TEST_TAG).captureToImage()
+ rule
+ .onNodeWithTag(TEST_TAG)
+ .captureToImage()
.assertColorInPercentageRange(testBackground, 93f..97f)
}
@@ -435,9 +379,7 @@
expectedTextStyle = MaterialTheme.typography.bodyLarge
Card(
onClick = {},
- content = {
- actualTextStyle = LocalTextStyle.current
- },
+ content = { actualTextStyle = LocalTextStyle.current },
enabled = true,
modifier = Modifier.testTag(TEST_TAG)
)
@@ -464,15 +406,9 @@
AppCard(
onClick = {},
- appName = {
- actualAppTextStyle = LocalTextStyle.current
- },
- time = {
- actualTimeTextStyle = LocalTextStyle.current
- },
- title = {
- actualTitleTextStyle = LocalTextStyle.current
- },
+ appName = { actualAppTextStyle = LocalTextStyle.current },
+ time = { actualTimeTextStyle = LocalTextStyle.current },
+ title = { actualTitleTextStyle = LocalTextStyle.current },
modifier = Modifier.testTag(TEST_TAG)
) {
actuaContentTextStyle = LocalTextStyle.current
@@ -500,12 +436,8 @@
TitleCard(
onClick = {},
- time = {
- actualTimeTextStyle = LocalTextStyle.current
- },
- title = {
- actualTitleTextStyle = LocalTextStyle.current
- },
+ time = { actualTimeTextStyle = LocalTextStyle.current },
+ title = { actualTitleTextStyle = LocalTextStyle.current },
modifier = Modifier.testTag(TEST_TAG)
) {
actuaContentTextStyle = LocalTextStyle.current
@@ -536,15 +468,9 @@
AppCard(
onClick = {},
- appName = {
- actualAppTextStyle = LocalTextStyle.current
- },
- time = {
- actualTimeTextStyle = LocalTextStyle.current
- },
- title = {
- actualTitleTextStyle = LocalTextStyle.current
- },
+ appName = { actualAppTextStyle = LocalTextStyle.current },
+ time = { actualTimeTextStyle = LocalTextStyle.current },
+ title = { actualTitleTextStyle = LocalTextStyle.current },
modifier = Modifier.testTag(TEST_TAG)
) {
actuaContentTextStyle = LocalTextStyle.current
@@ -567,21 +493,14 @@
}
}
- private fun verifyColors(
- status: CardStatus,
- contentColor: @Composable () -> Color
- ) {
+ private fun verifyColors(status: CardStatus, contentColor: @Composable () -> Color) {
var expectedContent = Color.Transparent
var actualContent = Color.Transparent
val testBackground = Color.White
rule.setContentWithTheme {
expectedContent = contentColor()
- Box(
- modifier = Modifier
- .fillMaxSize()
- .background(testBackground)
- ) {
+ Box(modifier = Modifier.fillMaxSize().background(testBackground)) {
Card(
onClick = {},
content = { actualContent = LocalContentColor.current },
@@ -596,9 +515,7 @@
}
private fun ComposeContentTestRule.verifyHeight(expected: Dp, content: @Composable () -> Unit) {
- setContentWithThemeForSizeAssertions {
- content()
- }.assertHeightIsEqualTo(expected, Dp(1.0f))
+ setContentWithThemeForSizeAssertions { content() }.assertHeightIsEqualTo(expected, Dp(1.0f))
}
private enum class CardStatus {
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/CurvedTextTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/CurvedTextTest.kt
index ccb12db..036c740 100644
--- a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/CurvedTextTest.kt
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/CurvedTextTest.kt
@@ -38,8 +38,7 @@
@RunWith(AndroidJUnit4::class)
@RequiresApi(Build.VERSION_CODES.O)
class CurvedTextTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
private val testText = "TestText"
@@ -51,9 +50,7 @@
curvedText(
text = testText,
color = Color.Red,
- style = CurvedTextStyle(
- color = Color.Blue
- )
+ style = CurvedTextStyle(color = Color.Blue)
)
}
}
@@ -70,12 +67,7 @@
CompositionLocalProvider(LocalContentColor provides Color.Yellow) {
CurvedLayout {
curvedRow {
- curvedText(
- text = testText,
- style = CurvedTextStyle(
- color = Color.Blue
- )
- )
+ curvedText(text = testText, style = CurvedTextStyle(color = Color.Blue))
}
}
}
@@ -100,7 +92,9 @@
}
}
- rule.onNodeWithContentDescription(testText).captureToImage()
+ rule
+ .onNodeWithContentDescription(testText)
+ .captureToImage()
.assertContainsColor(Color.Yellow)
}
}
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/HorizontalPageIndicatorScreenshotTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/HorizontalPageIndicatorScreenshotTest.kt
index fc3e2b7..92820fd 100644
--- a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/HorizontalPageIndicatorScreenshotTest.kt
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/HorizontalPageIndicatorScreenshotTest.kt
@@ -48,14 +48,11 @@
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
class HorizontalPageIndicatorScreenshotTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
- @get:Rule
- val screenshotRule = AndroidXScreenshotTestRule(SCREENSHOT_GOLDEN_PATH)
+ @get:Rule val screenshotRule = AndroidXScreenshotTestRule(SCREENSHOT_GOLDEN_PATH)
- @get:Rule
- val testName = TestName()
+ @get:Rule val testName = TestName()
@Test
fun horizontalPageIndicator_circular_selected_page() {
@@ -87,10 +84,7 @@
between_pages(false)
}
- private fun selected_page(
- isRound: Boolean,
- layoutDirection: LayoutDirection
- ) {
+ private fun selected_page(isRound: Boolean, layoutDirection: LayoutDirection) {
rule.setContentWithTheme {
DeviceConfigurationOverride(
DeviceConfigurationOverride.LayoutDirection(layoutDirection)
@@ -100,7 +94,8 @@
}
rule.waitForIdle()
- rule.onNodeWithTag(TEST_TAG)
+ rule
+ .onNodeWithTag(TEST_TAG)
.captureToImage()
.assertAgainstGolden(screenshotRule, testName.methodName)
}
@@ -108,11 +103,7 @@
private fun between_pages(isRound: Boolean) {
rule.setContentWithTheme {
DeviceConfigurationOverride(DeviceConfigurationOverride.RoundScreen(isRound)) {
- Box(
- modifier = Modifier
- .testTag(TEST_TAG)
- .size(200.dp)
- ) {
+ Box(modifier = Modifier.testTag(TEST_TAG).size(200.dp)) {
HorizontalPageIndicator(
pageCount = PAGE_COUNT,
currentPage = SELECTED_PAGE_INDEX,
@@ -126,7 +117,8 @@
}
rule.waitForIdle()
- rule.onNodeWithTag(TEST_TAG)
+ rule
+ .onNodeWithTag(TEST_TAG)
.captureToImage()
.assertAgainstGolden(screenshotRule, testName.methodName)
}
@@ -134,11 +126,7 @@
@Composable
private fun defaultHorizontalPageIndicator(isRound: Boolean) {
DeviceConfigurationOverride(DeviceConfigurationOverride.RoundScreen(isRound)) {
- Box(
- modifier = Modifier
- .testTag(TEST_TAG)
- .size(200.dp)
- ) {
+ Box(modifier = Modifier.testTag(TEST_TAG).size(200.dp)) {
HorizontalPageIndicator(
pageCount = PAGE_COUNT,
currentPage = SELECTED_PAGE_INDEX,
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/HorizontalPageIndicatorTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/HorizontalPageIndicatorTest.kt
index 654e4ca..3431b39 100644
--- a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/HorizontalPageIndicatorTest.kt
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/HorizontalPageIndicatorTest.kt
@@ -36,8 +36,7 @@
@RequiresApi(Build.VERSION_CODES.O)
class HorizontalPageIndicatorTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
@Test
public fun supports_testtag_circular() {
@@ -145,11 +144,7 @@
private fun position_is_selected(isRound: Boolean) {
rule.setContentWithTheme {
DeviceConfigurationOverride(DeviceConfigurationOverride.RoundScreen(isRound)) {
- Box(
- modifier = Modifier
- .testTag(TEST_TAG)
- .size(150.dp)
- ) {
+ Box(modifier = Modifier.testTag(TEST_TAG).size(150.dp)) {
HorizontalPageIndicator(
pageCount = PAGE_COUNT,
currentPage = SELECTED_PAGE_INDEX,
@@ -165,22 +160,22 @@
// A selected dot with specified color should be visible on the screen, which is apprx 1.3%
// (1.3% per dot, 1 dot in total)
- rule.onNodeWithTag(TEST_TAG).captureToImage()
+ rule
+ .onNodeWithTag(TEST_TAG)
+ .captureToImage()
.assertColorInPercentageRange(selectedColor, 1.2f..1.5f)
// Unselected dots should also be visible on the screen, and should take around 4%
// (1.3% per dot, 3 dots total)
- rule.onNodeWithTag(TEST_TAG).captureToImage()
+ rule
+ .onNodeWithTag(TEST_TAG)
+ .captureToImage()
.assertColorInPercentageRange(unselectedColor, 3.8f..4.5f)
}
private fun in_between_positions(isRound: Boolean) {
rule.setContentWithTheme {
DeviceConfigurationOverride(DeviceConfigurationOverride.RoundScreen(isRound)) {
- Box(
- modifier = Modifier
- .testTag(TEST_TAG)
- .size(150.dp)
- ) {
+ Box(modifier = Modifier.testTag(TEST_TAG).size(150.dp)) {
HorizontalPageIndicator(
pageCount = PAGE_COUNT,
currentPage = SELECTED_PAGE_INDEX,
@@ -196,12 +191,16 @@
// Selected color should occupy 2 dots with space in between, which
// approximately equals to 3.5%
- rule.onNodeWithTag(TEST_TAG).captureToImage()
+ rule
+ .onNodeWithTag(TEST_TAG)
+ .captureToImage()
.assertColorInPercentageRange(selectedColor, 3f..4f)
// Unselected dots ( which doesn't participate in color merge)
// should also be visible on the screen, and should take around 2.7%
// (1.3% per dot, 2 dots in total)
- rule.onNodeWithTag(TEST_TAG).captureToImage()
+ rule
+ .onNodeWithTag(TEST_TAG)
+ .captureToImage()
.assertColorInPercentageRange(unselectedColor, 2.5f..3f)
}
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/IconButtonScreenshotTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/IconButtonScreenshotTest.kt
index 5a05221..fb2582c 100644
--- a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/IconButtonScreenshotTest.kt
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/IconButtonScreenshotTest.kt
@@ -57,14 +57,11 @@
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
class IconButtonScreenshotTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
- @get:Rule
- val screenshotRule = AndroidXScreenshotTestRule(SCREENSHOT_GOLDEN_PATH)
+ @get:Rule val screenshotRule = AndroidXScreenshotTestRule(SCREENSHOT_GOLDEN_PATH)
- @get:Rule
- val testName = TestName()
+ @get:Rule val testName = TestName()
@Test
fun filled_icon_button_enabled() = verifyScreenshot {
@@ -122,10 +119,9 @@
}
@Test
- fun filled_tonal_compact_icon_button_disabled() =
- verifyScreenshot {
- sampleFilledTonalIconButton(enabled = false, isCompact = true)
- }
+ fun filled_tonal_compact_icon_button_disabled() = verifyScreenshot {
+ sampleFilledTonalIconButton(enabled = false, isCompact = true)
+ }
@Test
fun outlined_compact_icon_button_enabled() = verifyScreenshot {
@@ -155,21 +151,25 @@
@Composable
private fun sampleFilledIconButton(enabled: Boolean, isCompact: Boolean) {
FilledIconButton(
- onClick = {}, enabled = enabled, modifier = Modifier
- .testTag(TEST_TAG)
- .then(
- if (isCompact)
- Modifier.touchTargetAwareSize(IconButtonDefaults.ExtraSmallButtonSize)
- else Modifier
- )
+ onClick = {},
+ enabled = enabled,
+ modifier =
+ Modifier.testTag(TEST_TAG)
+ .then(
+ if (isCompact)
+ Modifier.touchTargetAwareSize(IconButtonDefaults.ExtraSmallButtonSize)
+ else Modifier
+ )
) {
Icon(
imageVector = Icons.Outlined.Home,
contentDescription = "Home",
- modifier = if (isCompact) Modifier.size(
- IconButtonDefaults.iconSizeFor(IconButtonDefaults.SmallIconSize)
- )
- else Modifier
+ modifier =
+ if (isCompact)
+ Modifier.size(
+ IconButtonDefaults.iconSizeFor(IconButtonDefaults.SmallIconSize)
+ )
+ else Modifier
)
}
}
@@ -177,21 +177,25 @@
@Composable
private fun sampleFilledTonalIconButton(enabled: Boolean, isCompact: Boolean) {
FilledTonalIconButton(
- onClick = {}, enabled = enabled, modifier = Modifier
- .testTag(TEST_TAG)
- .then(
- if (isCompact)
- Modifier.touchTargetAwareSize(IconButtonDefaults.ExtraSmallButtonSize)
- else Modifier
- )
+ onClick = {},
+ enabled = enabled,
+ modifier =
+ Modifier.testTag(TEST_TAG)
+ .then(
+ if (isCompact)
+ Modifier.touchTargetAwareSize(IconButtonDefaults.ExtraSmallButtonSize)
+ else Modifier
+ )
) {
Icon(
imageVector = Icons.Outlined.Home,
contentDescription = "Home",
- modifier = if (isCompact) Modifier.size(
- IconButtonDefaults.iconSizeFor(IconButtonDefaults.SmallIconSize)
- )
- else Modifier
+ modifier =
+ if (isCompact)
+ Modifier.size(
+ IconButtonDefaults.iconSizeFor(IconButtonDefaults.SmallIconSize)
+ )
+ else Modifier
)
}
}
@@ -199,21 +203,25 @@
@Composable
private fun sampleOutlinedIconButton(enabled: Boolean, isCompact: Boolean) {
OutlinedIconButton(
- onClick = {}, enabled = enabled, modifier = Modifier
- .testTag(TEST_TAG)
- .then(
- if (isCompact)
- Modifier.touchTargetAwareSize(IconButtonDefaults.ExtraSmallButtonSize)
- else Modifier
- )
+ onClick = {},
+ enabled = enabled,
+ modifier =
+ Modifier.testTag(TEST_TAG)
+ .then(
+ if (isCompact)
+ Modifier.touchTargetAwareSize(IconButtonDefaults.ExtraSmallButtonSize)
+ else Modifier
+ )
) {
Icon(
imageVector = Icons.Outlined.Home,
contentDescription = "Home",
- modifier = if (isCompact) Modifier.size(
- IconButtonDefaults.iconSizeFor(IconButtonDefaults.SmallIconSize)
- )
- else Modifier
+ modifier =
+ if (isCompact)
+ Modifier.size(
+ IconButtonDefaults.iconSizeFor(IconButtonDefaults.SmallIconSize)
+ )
+ else Modifier
)
}
}
@@ -225,21 +233,26 @@
modifier: Modifier = Modifier
) {
IconButton(
- onClick = {}, enabled = enabled, modifier = modifier
- .testTag(TEST_TAG)
- .then(
- if (isCompact)
- Modifier.touchTargetAwareSize(IconButtonDefaults.ExtraSmallButtonSize)
- else Modifier
- )
+ onClick = {},
+ enabled = enabled,
+ modifier =
+ modifier
+ .testTag(TEST_TAG)
+ .then(
+ if (isCompact)
+ Modifier.touchTargetAwareSize(IconButtonDefaults.ExtraSmallButtonSize)
+ else Modifier
+ )
) {
Icon(
imageVector = Icons.Outlined.Home,
contentDescription = "Home",
- modifier = if (isCompact) Modifier.size(
- IconButtonDefaults.iconSizeFor(IconButtonDefaults.SmallIconSize)
- )
- else Modifier
+ modifier =
+ if (isCompact)
+ Modifier.size(
+ IconButtonDefaults.iconSizeFor(IconButtonDefaults.SmallIconSize)
+ )
+ else Modifier
)
}
}
@@ -250,15 +263,15 @@
) {
rule.setContentWithTheme {
Box(
- modifier = Modifier
- .fillMaxSize()
- .background(MaterialTheme.colorScheme.background)
+ modifier = Modifier.fillMaxSize().background(MaterialTheme.colorScheme.background)
) {
content()
}
}
- rule.onNodeWithTag(TEST_TAG).captureToImage()
+ rule
+ .onNodeWithTag(TEST_TAG)
+ .captureToImage()
.assertAgainstGolden(screenshotRule, methodName)
}
}
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/IconButtonTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/IconButtonTest.kt
index ff27305..85fbbb4 100644
--- a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/IconButtonTest.kt
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/IconButtonTest.kt
@@ -53,18 +53,12 @@
import org.junit.Test
class IconButtonTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
@Test
fun supports_testtag() {
rule.setContentWithTheme {
- IconButton(
- modifier = Modifier.testTag(TEST_TAG),
- onClick = {}
- ) {
- TestImage()
- }
+ IconButton(modifier = Modifier.testTag(TEST_TAG), onClick = {}) { TestImage() }
}
rule.onNodeWithTag(TEST_TAG).assertExists()
@@ -73,11 +67,7 @@
@Test
fun has_click_action_when_enabled() {
rule.setContentWithTheme {
- IconButton(
- onClick = {},
- enabled = true,
- modifier = Modifier.testTag(TEST_TAG)
- ) {
+ IconButton(onClick = {}, enabled = true, modifier = Modifier.testTag(TEST_TAG)) {
TestImage()
}
}
@@ -88,11 +78,7 @@
@Test
fun has_click_action_when_disabled() {
rule.setContentWithTheme {
- IconButton(
- onClick = {},
- enabled = false,
- modifier = Modifier.testTag(TEST_TAG)
- ) {
+ IconButton(onClick = {}, enabled = false, modifier = Modifier.testTag(TEST_TAG)) {
TestImage()
}
}
@@ -103,11 +89,7 @@
@Test
fun is_correctly_enabled() {
rule.setContentWithTheme {
- IconButton(
- onClick = {},
- enabled = true,
- modifier = Modifier.testTag(TEST_TAG)
- ) {
+ IconButton(onClick = {}, enabled = true, modifier = Modifier.testTag(TEST_TAG)) {
TestImage()
}
}
@@ -118,11 +100,7 @@
@Test
fun is_correctly_disabled() {
rule.setContentWithTheme {
- IconButton(
- onClick = {},
- enabled = false,
- modifier = Modifier.testTag(TEST_TAG)
- ) {
+ IconButton(onClick = {}, enabled = false, modifier = Modifier.testTag(TEST_TAG)) {
TestImage()
}
}
@@ -146,9 +124,7 @@
rule.onNodeWithTag(TEST_TAG).performClick()
- rule.runOnIdle {
- assertEquals(true, clicked)
- }
+ rule.runOnIdle { assertEquals(true, clicked) }
}
@Test
@@ -167,29 +143,18 @@
rule.onNodeWithTag(TEST_TAG).performClick()
- rule.runOnIdle {
- assertEquals(false, clicked)
- }
+ rule.runOnIdle { assertEquals(false, clicked) }
}
@Test
fun has_role_button() {
rule.setContentWithTheme {
- IconButton(
- onClick = {},
- modifier = Modifier.testTag(TEST_TAG)
- ) {
- TestImage()
- }
+ IconButton(onClick = {}, modifier = Modifier.testTag(TEST_TAG)) { TestImage() }
}
- rule.onNodeWithTag(TEST_TAG)
- .assert(
- SemanticsMatcher.expectValue(
- SemanticsProperties.Role,
- Role.Button
- )
- )
+ rule
+ .onNodeWithTag(TEST_TAG)
+ .assert(SemanticsMatcher.expectValue(SemanticsProperties.Role, Role.Button))
}
@Test
@@ -199,29 +164,21 @@
rule.setContentWithTheme {
IconButton(
onClick = {},
- modifier = Modifier
- .testTag(TEST_TAG)
- .semantics { role = overrideRole }
+ modifier = Modifier.testTag(TEST_TAG).semantics { role = overrideRole }
) {
TestImage()
}
}
- rule.onNodeWithTag(TEST_TAG).assert(
- SemanticsMatcher.expectValue(
- SemanticsProperties.Role,
- overrideRole
- )
- )
+ rule
+ .onNodeWithTag(TEST_TAG)
+ .assert(SemanticsMatcher.expectValue(SemanticsProperties.Role, overrideRole))
}
@Test
fun gives_default_button_correct_tap_size() {
rule.verifyTapSize(DefaultButtonSize) { modifier ->
- IconButton(
- onClick = {},
- modifier = modifier.touchTargetAwareSize(DefaultButtonSize)
- ) {
+ IconButton(onClick = {}, modifier = modifier.touchTargetAwareSize(DefaultButtonSize)) {
TestImage()
}
}
@@ -230,10 +187,7 @@
@Test
fun gives_large_button_correct_tap_size() {
rule.verifyTapSize(LargeButtonSize) { modifier ->
- IconButton(
- onClick = {},
- modifier = modifier.touchTargetAwareSize(LargeButtonSize)
- ) {
+ IconButton(onClick = {}, modifier = modifier.touchTargetAwareSize(LargeButtonSize)) {
TestImage()
}
}
@@ -242,10 +196,7 @@
@Test
fun gives_small_button_correct_tap_size() {
rule.verifyTapSize(SmallButtonSize) { modifier ->
- IconButton(
- onClick = {},
- modifier = modifier.touchTargetAwareSize(SmallButtonSize)
- ) {
+ IconButton(onClick = {}, modifier = modifier.touchTargetAwareSize(SmallButtonSize)) {
TestImage()
}
}
@@ -253,9 +204,7 @@
@Test
fun gives_extra_small_button_correct_tap_size() {
- rule.verifyTapSize(
- expectedSize = MinimumButtonTapSize
- ) { modifier ->
+ rule.verifyTapSize(expectedSize = MinimumButtonTapSize) { modifier ->
IconButton(
onClick = {},
modifier = modifier.touchTargetAwareSize(ExtraSmallButtonSize)
@@ -268,10 +217,7 @@
@Test
fun gives_default_correct_size() =
rule.verifyActualSize(DefaultButtonSize) {
- IconButton(
- onClick = {},
- modifier = it.touchTargetAwareSize(DefaultButtonSize)
- ) {
+ IconButton(onClick = {}, modifier = it.touchTargetAwareSize(DefaultButtonSize)) {
TestImage()
}
}
@@ -279,10 +225,7 @@
@Test
fun gives_small_correct_size() =
rule.verifyActualSize(SmallButtonSize) {
- IconButton(
- onClick = {},
- modifier = it.touchTargetAwareSize(SmallButtonSize)
- ) {
+ IconButton(onClick = {}, modifier = it.touchTargetAwareSize(SmallButtonSize)) {
TestImage()
}
}
@@ -290,10 +233,7 @@
@Test
fun gives_extraSmall_correct_size() =
rule.verifyActualSize(ExtraSmallButtonSize) {
- IconButton(
- onClick = {},
- modifier = it.touchTargetAwareSize(ExtraSmallButtonSize)
- ) {
+ IconButton(onClick = {}, modifier = it.touchTargetAwareSize(ExtraSmallButtonSize)) {
TestImage()
}
}
@@ -301,10 +241,7 @@
@Test
fun gives_large_correct_size() =
rule.verifyActualSize(LargeButtonSize) {
- IconButton(
- onClick = {},
- modifier = it.touchTargetAwareSize(LargeButtonSize)
- ) {
+ IconButton(onClick = {}, modifier = it.touchTargetAwareSize(LargeButtonSize)) {
TestImage()
}
}
@@ -316,10 +253,7 @@
expectedShape = CircleShape,
colors = { IconButtonDefaults.iconButtonColors() }
) { modifier ->
- IconButton(
- onClick = {},
- modifier = modifier
- ) {
+ IconButton(onClick = {}, modifier = modifier) {
// omit content to allow us to validate the shape by pixel checking.
}
}
@@ -330,15 +264,9 @@
fun allows_custom_shape_override() {
val shape = CutCornerShape(4.dp)
- rule.isShape(
- expectedShape = shape,
- colors = { IconButtonDefaults.iconButtonColors() }
- ) { modifier ->
- IconButton(
- onClick = {},
- modifier = modifier,
- shape = shape
- ) {
+ rule.isShape(expectedShape = shape, colors = { IconButtonDefaults.iconButtonColors() }) {
+ modifier ->
+ IconButton(onClick = {}, modifier = modifier, shape = shape) {
// omit content to allow us to validate the shape by pixel checking.
}
}
@@ -362,9 +290,9 @@
status = Status.Disabled,
colors = { IconButtonDefaults.iconButtonColors() },
expectedContainerColor = { Color.Transparent },
- expectedContentColor = { MaterialTheme.colorScheme.onSurface.copy(
- alpha = DisabledContentAlpha
- ) }
+ expectedContentColor = {
+ MaterialTheme.colorScheme.onSurface.copy(alpha = DisabledContentAlpha)
+ }
)
}
@@ -385,12 +313,12 @@
rule.verifyIconButtonColors(
status = Status.Disabled,
colors = { IconButtonDefaults.filledIconButtonColors() },
- expectedContainerColor = { MaterialTheme.colorScheme.onSurface.copy(
- alpha = DisabledContainerAlpha
- ) },
- expectedContentColor = { MaterialTheme.colorScheme.onSurface.copy(
- alpha = DisabledContentAlpha
- ) }
+ expectedContainerColor = {
+ MaterialTheme.colorScheme.onSurface.copy(alpha = DisabledContainerAlpha)
+ },
+ expectedContentColor = {
+ MaterialTheme.colorScheme.onSurface.copy(alpha = DisabledContentAlpha)
+ }
)
}
@@ -411,12 +339,12 @@
rule.verifyIconButtonColors(
status = Status.Disabled,
colors = { IconButtonDefaults.filledTonalIconButtonColors() },
- expectedContainerColor = { MaterialTheme.colorScheme.onSurface.copy(
- alpha = DisabledContainerAlpha
- ) },
- expectedContentColor = { MaterialTheme.colorScheme.onSurface.copy(
- alpha = DisabledContentAlpha
- ) }
+ expectedContainerColor = {
+ MaterialTheme.colorScheme.onSurface.copy(alpha = DisabledContainerAlpha)
+ },
+ expectedContentColor = {
+ MaterialTheme.colorScheme.onSurface.copy(alpha = DisabledContentAlpha)
+ }
)
}
@@ -438,9 +366,9 @@
status = Status.Disabled,
colors = { IconButtonDefaults.outlinedIconButtonColors() },
expectedContainerColor = { Color.Transparent },
- expectedContentColor = { MaterialTheme.colorScheme.onSurface.copy(
- alpha = DisabledContentAlpha
- ) }
+ expectedContentColor = {
+ MaterialTheme.colorScheme.onSurface.copy(alpha = DisabledContentAlpha)
+ }
)
}
@@ -451,11 +379,7 @@
rule.verifyButtonBorderColor(
expectedBorderColor = { MaterialTheme.colorScheme.outline },
content = { modifier: Modifier ->
- OutlinedIconButton(
- onClick = {},
- modifier = modifier,
- enabled = status.enabled()
- ) {}
+ OutlinedIconButton(onClick = {}, modifier = modifier, enabled = status.enabled()) {}
}
)
}
@@ -469,11 +393,7 @@
MaterialTheme.colorScheme.outline.copy(alpha = DisabledBorderAlpha)
},
content = { modifier: Modifier ->
- OutlinedIconButton(
- onClick = {},
- modifier = modifier,
- enabled = status.enabled()
- ) {}
+ OutlinedIconButton(onClick = {}, modifier = modifier, enabled = status.enabled()) {}
}
)
}
@@ -489,11 +409,12 @@
onClick = {},
modifier = modifier,
enabled = status.enabled(),
- border = ButtonDefaults.outlinedButtonBorder(
- enabled = status.enabled(),
- borderColor = Color.Green,
- disabledBorderColor = Color.Red
- )
+ border =
+ ButtonDefaults.outlinedButtonBorder(
+ enabled = status.enabled(),
+ borderColor = Color.Green,
+ disabledBorderColor = Color.Red
+ )
) {}
}
)
@@ -544,11 +465,7 @@
if (buttonColor == Color.Transparent) {
buttonColor = background
}
- content(
- Modifier
- .testTag(TEST_TAG)
- .padding(padding)
- )
+ content(Modifier.testTag(TEST_TAG).padding(padding))
}
}
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/IconTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/IconTest.kt
index 9088b8e..ee1a9e9 100644
--- a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/IconTest.kt
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/IconTest.kt
@@ -51,8 +51,7 @@
import org.junit.Test
class IconTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
private val testTag = "TestText"
@@ -62,9 +61,7 @@
val height = 24.dp
val vector = Icons.Filled.Menu
rule
- .setContentWithThemeForSizeAssertions {
- Icon(vector, null)
- }
+ .setContentWithThemeForSizeAssertions { Icon(vector, null) }
.assertWidthIsEqualTo(width)
.assertHeightIsEqualTo(height)
}
@@ -73,14 +70,16 @@
fun vector_customIconSize_dimensions() {
val width = 35.dp
val height = 83.dp
- val vector = ImageVector.Builder(
- defaultWidth = width, defaultHeight = height,
- viewportWidth = width.value, viewportHeight = height.value
- ).build()
+ val vector =
+ ImageVector.Builder(
+ defaultWidth = width,
+ defaultHeight = height,
+ viewportWidth = width.value,
+ viewportHeight = height.value
+ )
+ .build()
rule
- .setContentWithThemeForSizeAssertions {
- Icon(vector, null)
- }
+ .setContentWithThemeForSizeAssertions { Icon(vector, null) }
.assertWidthIsEqualTo(width)
.assertHeightIsEqualTo(height)
}
@@ -91,9 +90,10 @@
val height = 24.dp
rule
.setContentWithThemeForSizeAssertions {
- val image = with(LocalDensity.current) {
- ImageBitmap(width.roundToPx(), height.roundToPx())
- }
+ val image =
+ with(LocalDensity.current) {
+ ImageBitmap(width.roundToPx(), height.roundToPx())
+ }
Icon(image, null)
}
@@ -108,9 +108,10 @@
rule
.setContentWithThemeForSizeAssertions {
- val image = with(LocalDensity.current) {
- ImageBitmap(width.roundToPx(), height.roundToPx())
- }
+ val image =
+ with(LocalDensity.current) {
+ ImageBitmap(width.roundToPx(), height.roundToPx())
+ }
Icon(image, null)
}
@@ -125,9 +126,7 @@
val painter = ColorPainter(Color.Red)
rule
- .setContentWithThemeForSizeAssertions {
- Icon(painter, null)
- }
+ .setContentWithThemeForSizeAssertions { Icon(painter, null) }
.assertWidthIsEqualTo(width)
.assertHeightIsEqualTo(height)
}
@@ -139,9 +138,10 @@
rule
.setContentWithThemeForSizeAssertions {
- val image = with(LocalDensity.current) {
- ImageBitmap(width.roundToPx(), height.roundToPx())
- }
+ val image =
+ with(LocalDensity.current) {
+ ImageBitmap(width.roundToPx(), height.roundToPx())
+ }
val bitmapPainter = BitmapPainter(image)
Icon(bitmapPainter, null)
@@ -158,36 +158,30 @@
val height = 24.dp
var expectedIntSize: IntSize? = null
- rule
- .setContentWithTheme {
- val image: ImageBitmap
- with(LocalDensity.current) {
- image = createBitmapWithColor(
- this,
- width.roundToPx(),
- height.roundToPx(),
- Color.Red
- )
- }
- Icon(
- image,
- null,
- // Force Icon to be 50dp
- modifier = Modifier.requiredSize(50.dp).testTag(testTag),
- tint = Color.Unspecified
- )
- with(LocalDensity.current) {
- val dimension = 50.dp.roundToPx()
- expectedIntSize = IntSize(dimension, dimension)
- }
+ rule.setContentWithTheme {
+ val image: ImageBitmap
+ with(LocalDensity.current) {
+ image =
+ createBitmapWithColor(this, width.roundToPx(), height.roundToPx(), Color.Red)
}
+ Icon(
+ image,
+ null,
+ // Force Icon to be 50dp
+ modifier = Modifier.requiredSize(50.dp).testTag(testTag),
+ tint = Color.Unspecified
+ )
+ with(LocalDensity.current) {
+ val dimension = 50.dp.roundToPx()
+ expectedIntSize = IntSize(dimension, dimension)
+ }
+ }
- rule.onNodeWithTag(testTag)
+ rule
+ .onNodeWithTag(testTag)
.captureToImage()
// The icon should be 50x50 and fill the whole size with red pixels
- .assertPixels(expectedSize = expectedIntSize!!) {
- Color.Red
- }
+ .assertPixels(expectedSize = expectedIntSize!!) { Color.Red }
}
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
@@ -196,24 +190,14 @@
val width = 35.dp
val height = 83.dp
- rule
- .setContentWithTheme {
- val image: ImageBitmap
- with(LocalDensity.current) {
- image = createBitmapWithColor(
- this,
- width.roundToPx(),
- height.roundToPx(),
- Color.Red
- )
- }
- Icon(
- image,
- null,
- modifier = Modifier.testTag(testTag),
- tint = Color.Unspecified
- )
+ rule.setContentWithTheme {
+ val image: ImageBitmap
+ with(LocalDensity.current) {
+ image =
+ createBitmapWithColor(this, width.roundToPx(), height.roundToPx(), Color.Red)
}
+ Icon(image, null, modifier = Modifier.testTag(testTag), tint = Color.Unspecified)
+ }
// With no color provided for a tint, the icon should render the original pixels
rule.onNodeWithTag(testTag).captureToImage().assertPixels { Color.Red }
@@ -225,24 +209,14 @@
val width = 35.dp
val height = 83.dp
- rule
- .setContentWithTheme {
- val image: ImageBitmap
- with(LocalDensity.current) {
- image = createBitmapWithColor(
- this,
- width.roundToPx(),
- height.roundToPx(),
- Color.Red
- )
- }
- Icon(
- image,
- null,
- modifier = Modifier.testTag(testTag),
- tint = Color.Blue
- )
+ rule.setContentWithTheme {
+ val image: ImageBitmap
+ with(LocalDensity.current) {
+ image =
+ createBitmapWithColor(this, width.roundToPx(), height.roundToPx(), Color.Red)
}
+ Icon(image, null, modifier = Modifier.testTag(testTag), tint = Color.Blue)
+ }
// With a tint color provided, all pixels should be blue
rule.onNodeWithTag(testTag).captureToImage().assertPixels { Color.Blue }
@@ -250,16 +224,16 @@
@Test
fun defaultSemanticsWhenContentDescriptionProvided() {
- rule
- .setContent {
- Icon(
- bitmap = ImageBitmap(100, 100),
- contentDescription = "qwerty",
- modifier = Modifier.testTag(testTag)
- )
- }
+ rule.setContent {
+ Icon(
+ bitmap = ImageBitmap(100, 100),
+ contentDescription = "qwerty",
+ modifier = Modifier.testTag(testTag)
+ )
+ }
- rule.onNodeWithTag(testTag)
+ rule
+ .onNodeWithTag(testTag)
.assertContentDescriptionEquals("qwerty")
.assert(SemanticsMatcher.expectValue(SemanticsProperties.Role, Role.Image))
}
@@ -272,12 +246,7 @@
): ImageBitmap {
val size = Size(width.toFloat(), height.toFloat())
val image = ImageBitmap(width, height)
- CanvasDrawScope().draw(
- density,
- LayoutDirection.Ltr,
- Canvas(image),
- size
- ) {
+ CanvasDrawScope().draw(density, LayoutDirection.Ltr, Canvas(image), size) {
drawRect(color)
}
return image
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/IconToggleButtonScreenshotTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/IconToggleButtonScreenshotTest.kt
index 9e449ed..04eb12e 100644
--- a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/IconToggleButtonScreenshotTest.kt
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/IconToggleButtonScreenshotTest.kt
@@ -38,49 +38,51 @@
@RunWith(AndroidJUnit4::class)
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
class IconToggleButtonScreenshotTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
- @get:Rule
- val screenshotRule = AndroidXScreenshotTestRule(SCREENSHOT_GOLDEN_PATH)
+ @get:Rule val screenshotRule = AndroidXScreenshotTestRule(SCREENSHOT_GOLDEN_PATH)
- @get:Rule
- val testName = TestName()
+ @get:Rule val testName = TestName()
@Test
- fun iconToggleButtonEnabledAndChecked() = rule.verifyScreenshot(
- methodName = testName.methodName,
- screenshotRule = screenshotRule,
- content = { sampleIconToggleButton() }
- )
+ fun iconToggleButtonEnabledAndChecked() =
+ rule.verifyScreenshot(
+ methodName = testName.methodName,
+ screenshotRule = screenshotRule,
+ content = { sampleIconToggleButton() }
+ )
@Test
- fun iconToggleButtonEnabledAndUnchecked() = rule.verifyScreenshot(
- methodName = testName.methodName,
- screenshotRule = screenshotRule,
- content = { sampleIconToggleButton(checked = false) }
- )
+ fun iconToggleButtonEnabledAndUnchecked() =
+ rule.verifyScreenshot(
+ methodName = testName.methodName,
+ screenshotRule = screenshotRule,
+ content = { sampleIconToggleButton(checked = false) }
+ )
@Test
- fun iconToggleButtonDisabledAndChecked() = rule.verifyScreenshot(
- methodName = testName.methodName,
- screenshotRule = screenshotRule,
- content = { sampleIconToggleButton(enabled = false) }
- )
+ fun iconToggleButtonDisabledAndChecked() =
+ rule.verifyScreenshot(
+ methodName = testName.methodName,
+ screenshotRule = screenshotRule,
+ content = { sampleIconToggleButton(enabled = false) }
+ )
@Test
- fun iconToggleButtonDisabledAndUnchecked() = rule.verifyScreenshot(
- methodName = testName.methodName,
- screenshotRule = screenshotRule,
- content = { sampleIconToggleButton(enabled = false, checked = false) }
- )
+ fun iconToggleButtonDisabledAndUnchecked() =
+ rule.verifyScreenshot(
+ methodName = testName.methodName,
+ screenshotRule = screenshotRule,
+ content = { sampleIconToggleButton(enabled = false, checked = false) }
+ )
@Test
- fun iconToggleButtonWithOffset() = rule.verifyScreenshot(
- methodName = testName.methodName,
- screenshotRule = screenshotRule,
- content = { sampleIconToggleButton(modifier = Modifier.offset(10.dp)) }
- )
+ fun iconToggleButtonWithOffset() =
+ rule.verifyScreenshot(
+ methodName = testName.methodName,
+ screenshotRule = screenshotRule,
+ content = { sampleIconToggleButton(modifier = Modifier.offset(10.dp)) }
+ )
@Composable
private fun sampleIconToggleButton(
@@ -94,10 +96,7 @@
enabled = enabled,
modifier = modifier.testTag(TEST_TAG)
) {
- Icon(
- imageVector = Icons.Outlined.Star,
- contentDescription = "Favourite"
- )
+ Icon(imageVector = Icons.Outlined.Star, contentDescription = "Favourite")
}
}
}
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/IconToggleButtonTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/IconToggleButtonTest.kt
index ae204b1..188a8f8 100644
--- a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/IconToggleButtonTest.kt
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/IconToggleButtonTest.kt
@@ -62,8 +62,7 @@
class IconToggleButtonTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
@Test
fun supports_testTag() {
@@ -203,10 +202,7 @@
}
rule.waitForIdle()
- rule.onNodeWithTag(TEST_TAG)
- .assertIsOff()
- .performClick()
- .assertIsOn()
+ rule.onNodeWithTag(TEST_TAG).assertIsOff().performClick().assertIsOn()
}
@Test
@@ -222,10 +218,7 @@
}
rule.waitForIdle()
- rule.onNodeWithTag(TEST_TAG)
- .assertIsOn()
- .performClick()
- .assertIsOff()
+ rule.onNodeWithTag(TEST_TAG).assertIsOn().performClick().assertIsOff()
}
@Test
@@ -242,10 +235,7 @@
}
rule.waitForIdle()
- rule.onNodeWithTag(TEST_TAG)
- .assertIsOff()
- .performClick()
- .assertIsOff()
+ rule.onNodeWithTag(TEST_TAG).assertIsOff().performClick().assertIsOff()
}
@RequiresApi(Build.VERSION_CODES.O)
@@ -259,8 +249,8 @@
IconToggleButton(
enabled = true,
checked = true,
- onCheckedChange = { },
- content = { },
+ onCheckedChange = {},
+ content = {},
modifier = Modifier.testTag(TEST_TAG)
)
}
@@ -276,8 +266,8 @@
IconToggleButton(
enabled = true,
checked = true,
- onCheckedChange = { },
- content = { },
+ onCheckedChange = {},
+ content = {},
modifier = Modifier.testTag(TEST_TAG)
)
}
@@ -294,8 +284,8 @@
enabled = true,
checked = true,
shape = RectangleShape,
- onCheckedChange = { },
- content = { },
+ onCheckedChange = {},
+ content = {},
modifier = Modifier.testTag(TEST_TAG)
)
}
@@ -306,8 +296,8 @@
IconToggleButton(
enabled = true,
checked = true,
- onCheckedChange = { },
- content = { },
+ onCheckedChange = {},
+ content = {},
modifier = it.touchTargetAwareSize(IconButtonDefaults.DefaultButtonSize)
)
}
@@ -318,8 +308,8 @@
IconToggleButton(
enabled = true,
checked = true,
- onCheckedChange = { },
- content = { },
+ onCheckedChange = {},
+ content = {},
modifier = it.touchTargetAwareSize(IconButtonDefaults.SmallButtonSize)
)
}
@@ -330,8 +320,8 @@
IconToggleButton(
enabled = true,
checked = true,
- onCheckedChange = { },
- content = { },
+ onCheckedChange = {},
+ content = {},
modifier = it.touchTargetAwareSize(IconButtonDefaults.ExtraSmallButtonSize)
)
}
@@ -342,8 +332,8 @@
IconToggleButton(
enabled = true,
checked = true,
- onCheckedChange = { },
- content = { },
+ onCheckedChange = {},
+ content = {},
modifier = it.touchTargetAwareSize(IconButtonDefaults.LargeButtonSize)
)
}
@@ -354,8 +344,8 @@
IconToggleButton(
enabled = true,
checked = true,
- onCheckedChange = { },
- content = { },
+ onCheckedChange = {},
+ content = {},
modifier = it.touchTargetAwareSize(IconButtonDefaults.DefaultButtonSize)
)
}
@@ -366,8 +356,8 @@
IconToggleButton(
enabled = true,
checked = true,
- onCheckedChange = { },
- content = { },
+ onCheckedChange = {},
+ content = {},
modifier = it.touchTargetAwareSize(IconButtonDefaults.SmallButtonSize)
)
}
@@ -378,8 +368,8 @@
IconToggleButton(
enabled = true,
checked = true,
- onCheckedChange = { },
- content = { },
+ onCheckedChange = {},
+ content = {},
modifier = it.touchTargetAwareSize(IconButtonDefaults.ExtraSmallButtonSize)
)
}
@@ -390,8 +380,8 @@
IconToggleButton(
enabled = true,
checked = true,
- onCheckedChange = { },
- content = { },
+ onCheckedChange = {},
+ content = {},
modifier = it.touchTargetAwareSize(IconButtonDefaults.LargeButtonSize)
)
}
@@ -426,9 +416,7 @@
checked = false,
colors = { IconButtonDefaults.iconToggleButtonColors() },
containerColor = {
- MaterialTheme.colorScheme.onSurface.toDisabledColor(
- DisabledContainerAlpha
- )
+ MaterialTheme.colorScheme.onSurface.toDisabledColor(DisabledContainerAlpha)
},
contentColor = { MaterialTheme.colorScheme.onSurface.toDisabledColor() }
)
@@ -441,9 +429,7 @@
checked = true,
colors = { IconButtonDefaults.iconToggleButtonColors() },
containerColor = {
- MaterialTheme.colorScheme.onSurface.toDisabledColor(
- DisabledContainerAlpha
- )
+ MaterialTheme.colorScheme.onSurface.toDisabledColor(DisabledContainerAlpha)
},
contentColor = { MaterialTheme.colorScheme.onSurface.toDisabledColor() },
)
@@ -457,9 +443,7 @@
status = Status.Enabled,
checked = true,
colors = {
- IconButtonDefaults.iconToggleButtonColors(
- checkedContainerColor = overrideColor
- )
+ IconButtonDefaults.iconToggleButtonColors(checkedContainerColor = overrideColor)
},
containerColor = { overrideColor },
contentColor = { MaterialTheme.colorScheme.onPrimary }
@@ -475,9 +459,7 @@
status = Status.Enabled,
checked = true,
colors = {
- IconButtonDefaults.iconToggleButtonColors(
- checkedContentColor = overrideColor
- )
+ IconButtonDefaults.iconToggleButtonColors(checkedContentColor = overrideColor)
},
containerColor = { MaterialTheme.colorScheme.primary },
contentColor = { overrideColor }
@@ -493,9 +475,7 @@
status = Status.Enabled,
checked = false,
colors = {
- IconButtonDefaults.iconToggleButtonColors(
- uncheckedContainerColor = overrideColor
- )
+ IconButtonDefaults.iconToggleButtonColors(uncheckedContainerColor = overrideColor)
},
containerColor = { overrideColor },
contentColor = { MaterialTheme.colorScheme.onSurfaceVariant }
@@ -511,9 +491,7 @@
status = Status.Enabled,
checked = false,
colors = {
- IconButtonDefaults.iconToggleButtonColors(
- uncheckedContentColor = overrideColor
- )
+ IconButtonDefaults.iconToggleButtonColors(uncheckedContentColor = overrideColor)
},
containerColor = { MaterialTheme.colorScheme.surfaceContainer },
contentColor = { overrideColor }
@@ -554,9 +532,7 @@
)
},
containerColor = {
- MaterialTheme.colorScheme.onSurface.toDisabledColor(
- DisabledContainerAlpha
- )
+ MaterialTheme.colorScheme.onSurface.toDisabledColor(DisabledContainerAlpha)
},
contentColor = { overrideColor }
)
@@ -597,9 +573,7 @@
},
contentColor = { overrideColor },
containerColor = {
- MaterialTheme.colorScheme.onSurface.toDisabledColor(
- DisabledContainerAlpha
- )
+ MaterialTheme.colorScheme.onSurface.toDisabledColor(DisabledContainerAlpha)
}
)
}
@@ -616,12 +590,9 @@
)
}
- rule.onNodeWithTag(TEST_TAG).assert(
- SemanticsMatcher.expectValue(
- SemanticsProperties.Role,
- Role.Checkbox
- )
- )
+ rule
+ .onNodeWithTag(TEST_TAG)
+ .assert(SemanticsMatcher.expectValue(SemanticsProperties.Role, Role.Checkbox))
}
@Test
@@ -634,18 +605,13 @@
onCheckedChange = {},
enabled = false,
content = { TestImage() },
- modifier = Modifier
- .testTag(TEST_TAG)
- .semantics { role = overrideRole }
+ modifier = Modifier.testTag(TEST_TAG).semantics { role = overrideRole }
)
}
- rule.onNodeWithTag(TEST_TAG).assert(
- SemanticsMatcher.expectValue(
- SemanticsProperties.Role,
- overrideRole
- )
- )
+ rule
+ .onNodeWithTag(TEST_TAG)
+ .assert(SemanticsMatcher.expectValue(SemanticsProperties.Role, overrideRole))
}
@RequiresApi(Build.VERSION_CODES.O)
@@ -662,7 +628,7 @@
content = {
var actualContentColor = Color.Transparent
IconToggleButton(
- onCheckedChange = { },
+ onCheckedChange = {},
enabled = status.enabled(),
checked = checked,
colors = colors(),
@@ -677,10 +643,9 @@
@Composable
private fun shapeColor(): Color {
- return IconButtonDefaults.iconToggleButtonColors().containerColor(
- enabled = true,
- checked = true
- ).value
+ return IconButtonDefaults.iconToggleButtonColors()
+ .containerColor(enabled = true, checked = true)
+ .value
}
@RequiresApi(Build.VERSION_CODES.O)
@@ -696,13 +661,7 @@
setContentWithTheme {
shapeColor = shapeColorComposable.invoke()
CompositionLocalProvider(LocalLayoutDirection provides layoutDirection) {
- Box(
- Modifier
- .padding(padding)
- .background(backgroundColor)
- ) {
- content()
- }
+ Box(Modifier.padding(padding).background(backgroundColor)) { content() }
}
}
@@ -734,17 +693,11 @@
finalExpectedContainerColor =
expectedContainerColor().compositeOver(testBackgroundColor)
finalExpectedContent = expectedContentColor()
- Box(
- Modifier
- .fillMaxSize()
- .background(testBackgroundColor)
- ) {
+ Box(Modifier.fillMaxSize().background(testBackgroundColor)) {
actualContentColor = content()
}
}
Assert.assertEquals(finalExpectedContent, actualContentColor)
- onNodeWithTag(TEST_TAG)
- .captureToImage()
- .assertContainsColor(finalExpectedContainerColor)
+ onNodeWithTag(TEST_TAG).captureToImage().assertContainsColor(finalExpectedContainerColor)
}
}
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ListHeaderScreenshotTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ListHeaderScreenshotTest.kt
index 6ae78d2..1f3ba09 100644
--- a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ListHeaderScreenshotTest.kt
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ListHeaderScreenshotTest.kt
@@ -36,69 +36,62 @@
@RunWith(AndroidJUnit4::class)
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
class ListHeaderScreenshotTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
- @get:Rule
- val screenshotRule = AndroidXScreenshotTestRule(SCREENSHOT_GOLDEN_PATH)
+ @get:Rule val screenshotRule = AndroidXScreenshotTestRule(SCREENSHOT_GOLDEN_PATH)
- @get:Rule
- val testName = TestName()
+ @get:Rule val testName = TestName()
@Test
- fun listheader() = rule.verifyScreenshot(
- methodName = testName.methodName,
- screenshotRule = screenshotRule
- ) {
- ListHeader(modifier = Modifier.testTag(TEST_TAG)) {
- Text("Header")
+ fun listheader() =
+ rule.verifyScreenshot(methodName = testName.methodName, screenshotRule = screenshotRule) {
+ ListHeader(modifier = Modifier.testTag(TEST_TAG)) { Text("Header") }
}
- }
@Test
- fun listsubheader_textonly() = rule.verifyScreenshot(
- methodName = testName.methodName,
- screenshotRule = screenshotRule,
- ) {
- ListSubheader(modifier = Modifier.testTag(TEST_TAG)) {
- Text("Subheader")
+ fun listsubheader_textonly() =
+ rule.verifyScreenshot(
+ methodName = testName.methodName,
+ screenshotRule = screenshotRule,
+ ) {
+ ListSubheader(modifier = Modifier.testTag(TEST_TAG)) { Text("Subheader") }
}
- }
@Test
- fun listsubheader_textonly_rtl() = rule.verifyScreenshot(
- methodName = testName.methodName,
- screenshotRule = screenshotRule,
- layoutDirection = LayoutDirection.Rtl,
- ) {
- ListSubheader(modifier = Modifier.testTag(TEST_TAG)) {
- Text("Subheader")
+ fun listsubheader_textonly_rtl() =
+ rule.verifyScreenshot(
+ methodName = testName.methodName,
+ screenshotRule = screenshotRule,
+ layoutDirection = LayoutDirection.Rtl,
+ ) {
+ ListSubheader(modifier = Modifier.testTag(TEST_TAG)) { Text("Subheader") }
}
- }
@Test
- fun listsubheader_text_and_icon() = rule.verifyScreenshot(
- methodName = testName.methodName,
- screenshotRule = screenshotRule,
- layoutDirection = LayoutDirection.Ltr,
- ) {
- ListSubheader(
- modifier = Modifier.testTag(TEST_TAG),
- label = { Text(text = "Subheader") },
- icon = { Icon(imageVector = Icons.Outlined.Home, "home") }
- )
- }
+ fun listsubheader_text_and_icon() =
+ rule.verifyScreenshot(
+ methodName = testName.methodName,
+ screenshotRule = screenshotRule,
+ layoutDirection = LayoutDirection.Ltr,
+ ) {
+ ListSubheader(
+ modifier = Modifier.testTag(TEST_TAG),
+ label = { Text(text = "Subheader") },
+ icon = { Icon(imageVector = Icons.Outlined.Home, "home") }
+ )
+ }
@Test
- fun listsubheader_text_and_icon_rtl() = rule.verifyScreenshot(
- methodName = testName.methodName,
- screenshotRule = screenshotRule,
- layoutDirection = LayoutDirection.Rtl
- ) {
- ListSubheader(
- modifier = Modifier.testTag(TEST_TAG),
- label = { Text(text = "Subheader") },
- icon = { Icon(imageVector = Icons.Outlined.Home, "home") }
- )
- }
+ fun listsubheader_text_and_icon_rtl() =
+ rule.verifyScreenshot(
+ methodName = testName.methodName,
+ screenshotRule = screenshotRule,
+ layoutDirection = LayoutDirection.Rtl
+ ) {
+ ListSubheader(
+ modifier = Modifier.testTag(TEST_TAG),
+ label = { Text(text = "Subheader") },
+ icon = { Icon(imageVector = Icons.Outlined.Home, "home") }
+ )
+ }
}
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ListHeaderTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ListHeaderTest.kt
index 033c0d5..167473c 100644
--- a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ListHeaderTest.kt
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ListHeaderTest.kt
@@ -39,17 +39,12 @@
@LargeTest
@RunWith(AndroidJUnit4::class)
class ListHeaderTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
@Test
fun supports_testtag() {
rule.setContentWithTheme {
- ListHeader(
- modifier = Modifier.testTag(TEST_TAG)
- ) {
- Text("Header")
- }
+ ListHeader(modifier = Modifier.testTag(TEST_TAG)) { Text("Header") }
}
rule.onNodeWithTag(TEST_TAG).assertExists()
@@ -58,11 +53,7 @@
@Test
fun listHeader_has_semantic_heading_property() {
rule.setContentWithTheme {
- ListHeader(
- modifier = Modifier.testTag(TEST_TAG)
- ) {
- Text("Header")
- }
+ ListHeader(modifier = Modifier.testTag(TEST_TAG)) { Text("Header") }
}
rule.assertNodeIsHeading(TEST_TAG)
@@ -71,11 +62,7 @@
@Test
fun listSubheader_has_semantic_heading_property() {
rule.setContentWithTheme {
- ListSubheader(
- modifier = Modifier.testTag(TEST_TAG)
- ) {
- Text("Subheader")
- }
+ ListSubheader(modifier = Modifier.testTag(TEST_TAG)) { Text("Subheader") }
}
rule.assertNodeIsHeading(TEST_TAG)
@@ -88,9 +75,7 @@
rule.setContentWithTheme {
expectedTextStyle = MaterialTheme.typography.titleMedium
- ListHeader {
- actualTextStyle = LocalTextStyle.current
- }
+ ListHeader { actualTextStyle = LocalTextStyle.current }
}
Assert.assertEquals(expectedTextStyle, actualTextStyle)
@@ -100,32 +85,32 @@
fun listHeader_has_adjustable_height() {
val minHeight = ListHeaderTokens.Height + 1.dp
- rule.setContentWithThemeForSizeAssertions {
- ListHeader(
- modifier = Modifier.testTag(TEST_TAG)
- ) {
- Text("Header with multiple lines of text to exceed" +
- " the minimum height, should adjust"
- )
+ rule
+ .setContentWithThemeForSizeAssertions {
+ ListHeader(modifier = Modifier.testTag(TEST_TAG)) {
+ Text(
+ "Header with multiple lines of text to exceed" +
+ " the minimum height, should adjust"
+ )
+ }
}
- }
- .assertHeightIsAtLeast(minHeight)
+ .assertHeightIsAtLeast(minHeight)
}
@Test
fun listsubHeader_has_adjustable_height() {
val minHeight = ListSubHeaderTokens.Height + 1.dp
- rule.setContentWithThemeForSizeAssertions {
- ListSubheader(
- modifier = Modifier.testTag(TEST_TAG)
- ) {
- Text("Header with multiple lines of text to exceed" +
- " the minimum height, should adjust"
- )
+ rule
+ .setContentWithThemeForSizeAssertions {
+ ListSubheader(modifier = Modifier.testTag(TEST_TAG)) {
+ Text(
+ "Header with multiple lines of text to exceed" +
+ " the minimum height, should adjust"
+ )
+ }
}
- }
- .assertHeightIsAtLeast(minHeight)
+ .assertHeightIsAtLeast(minHeight)
}
@Test
@@ -135,20 +120,13 @@
rule.setContentWithTheme {
expectedTextStyle = MaterialTheme.typography.titleMedium
- ListSubheader {
- actualTextStyle = LocalTextStyle.current
- }
+ ListSubheader { actualTextStyle = LocalTextStyle.current }
}
Assert.assertEquals(expectedTextStyle, actualTextStyle)
}
private fun ComposeContentTestRule.assertNodeIsHeading(tag: String) {
- onNodeWithTag(tag)
- .assert(
- SemanticsMatcher.keyIsDefined(
- SemanticsProperties.Heading
- )
- )
+ onNodeWithTag(tag).assert(SemanticsMatcher.keyIsDefined(SemanticsProperties.Heading))
}
}
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/Material3Test.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/Material3Test.kt
index f8b5ba8..394a936 100644
--- a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/Material3Test.kt
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/Material3Test.kt
@@ -70,9 +70,7 @@
import kotlin.math.abs
import org.junit.Assert
-/**
- * Constant to emulate very big but finite constraints
- */
+/** Constant to emulate very big but finite constraints */
val BigTestMaxWidth = 5000.dp
val BigTestMaxHeight = 5000.dp
@@ -82,10 +80,9 @@
fun TestImage(iconLabel: String = "TestIcon") {
val testImage = Icons.Outlined.Add
Image(
- testImage, iconLabel,
- modifier = Modifier
- .fillMaxSize()
- .testTag(iconLabel),
+ testImage,
+ iconLabel,
+ modifier = Modifier.fillMaxSize().testTag(iconLabel),
contentScale = ContentScale.Fit,
alignment = Alignment.Center
)
@@ -102,13 +99,8 @@
}
@Composable
-fun CenteredText(
- text: String
-) {
- Column(
- modifier = Modifier.fillMaxHeight(),
- verticalArrangement = Arrangement.Center
- ) {
+fun CenteredText(text: String) {
+ Column(modifier = Modifier.fillMaxHeight(), verticalArrangement = Arrangement.Center) {
Text(text)
}
}
@@ -122,10 +114,8 @@
setContent {
MaterialTheme {
Box(
- Modifier.sizeIn(
- maxWidth = parentMaxWidth,
- maxHeight = parentMaxHeight
- ).testTag("containerForSizeAssertion")
+ Modifier.sizeIn(maxWidth = parentMaxWidth, maxHeight = parentMaxHeight)
+ .testTag("containerForSizeAssertion")
) {
content()
}
@@ -137,10 +127,11 @@
fun ComposeContentTestRule.textStyleOf(text: String): TextStyle {
val textLayoutResults = mutableListOf<TextLayoutResult>()
- onNodeWithText(text, useUnmergedTree = true)
- .performSemanticsAction(SemanticsActions.GetTextLayoutResult) {
- it(textLayoutResults)
- }
+ onNodeWithText(text, useUnmergedTree = true).performSemanticsAction(
+ SemanticsActions.GetTextLayoutResult
+ ) {
+ it(textLayoutResults)
+ }
return textLayoutResults[0].layoutInput.style
}
@@ -148,20 +139,14 @@
modifier: Modifier = Modifier,
composable: @Composable BoxScope.() -> Unit
) {
- setContent {
- MaterialTheme {
- Box(modifier = modifier, content = composable)
- }
- }
+ setContent { MaterialTheme { Box(modifier = modifier, content = composable) } }
}
internal fun ComposeContentTestRule.verifyTapSize(
expectedSize: Dp,
content: @Composable (modifier: Modifier) -> Unit
) {
- setContentWithTheme {
- content(Modifier.testTag(TEST_TAG))
- }
+ setContentWithTheme { content(Modifier.testTag(TEST_TAG)) }
waitForIdle()
onNodeWithTag(TEST_TAG)
@@ -173,14 +158,10 @@
expectedSize: Dp,
content: @Composable (modifier: Modifier) -> Unit
) {
- setContentWithTheme {
- content(Modifier.testTag(TEST_TAG))
- }
+ setContentWithTheme { content(Modifier.testTag(TEST_TAG)) }
waitForIdle()
- onNodeWithTag(TEST_TAG)
- .assertHeightIsEqualTo(expectedSize)
- .assertWidthIsEqualTo(expectedSize)
+ onNodeWithTag(TEST_TAG).assertHeightIsEqualTo(expectedSize).assertWidthIsEqualTo(expectedSize)
}
@RequiresApi(Build.VERSION_CODES.O)
@@ -198,33 +179,26 @@
setContentWithTheme {
finalExpectedContainerColor =
if (status.enabled() || !applyAlphaForDisabled) {
- expectedContainerColor()
- } else {
- expectedContainerColor().copy(DisabledContentAlpha)
- }.compositeOver(testBackgroundColor)
+ expectedContainerColor()
+ } else {
+ expectedContainerColor().copy(DisabledContentAlpha)
+ }
+ .compositeOver(testBackgroundColor)
finalExpectedContent =
if (status.enabled() || !applyAlphaForDisabled) {
expectedContentColor()
} else {
expectedContentColor().copy(DisabledContentAlpha)
}
- Box(
- Modifier
- .fillMaxSize()
- .background(testBackgroundColor)
- ) {
+ Box(Modifier.fillMaxSize().background(testBackgroundColor)) {
actualContentColor = content()
}
}
Assert.assertEquals(finalExpectedContent, actualContentColor)
- onNodeWithTag(TEST_TAG)
- .captureToImage()
- .assertContainsColor(finalExpectedContainerColor)
+ onNodeWithTag(TEST_TAG).captureToImage().assertContainsColor(finalExpectedContainerColor)
}
-/**
- * Checks that [expectedColor] is in the percentage [range] of an [ImageBitmap] color histogram
- */
+/** Checks that [expectedColor] is in the percentage [range] of an [ImageBitmap] color histogram */
fun ImageBitmap.assertColorInPercentageRange(
expectedColor: Color,
range: ClosedFloatingPointRange<Float> = 50.0f..100.0f
@@ -262,20 +236,25 @@
assertion: (DpRect) -> Unit
): SemanticsNodeInteraction {
val node = fetchSemanticsNode("Failed to retrieve bounds of the node.")
- val bounds = with(node.root!!.density) {
- node.unclippedBoundsInRoot.let {
- DpRect(it.left.toDp(), it.top.toDp(), it.right.toDp(), it.bottom.toDp())
+ val bounds =
+ with(node.root!!.density) {
+ node.unclippedBoundsInRoot.let {
+ DpRect(it.left.toDp(), it.top.toDp(), it.right.toDp(), it.bottom.toDp())
+ }
}
- }
assertion.invoke(bounds)
return this
}
-internal fun SemanticsNodeInteraction.assertOnLongClickLabelMatches(expectedValue: String):
- SemanticsNodeInteraction {
- return assert(SemanticsMatcher("onLongClickLabel = '$expectedValue'") {
- it.config.getOrElseNullable(SemanticsActions.OnLongClick) { null }?.label == expectedValue
- })
+internal fun SemanticsNodeInteraction.assertOnLongClickLabelMatches(
+ expectedValue: String
+): SemanticsNodeInteraction {
+ return assert(
+ SemanticsMatcher("onLongClickLabel = '$expectedValue'") {
+ it.config.getOrElseNullable(SemanticsActions.OnLongClick) { null }?.label ==
+ expectedValue
+ }
+ )
}
private val SemanticsNode.unclippedBoundsInRoot: Rect
@@ -288,9 +267,9 @@
}
/**
- * Returns if this value is equal to the [reference], within a given [tolerance]. If the
- * reference value is [Float.NaN], [Float.POSITIVE_INFINITY] or [Float.NEGATIVE_INFINITY], this
- * only returns true if this value is exactly the same (tolerance is disregarded).
+ * Returns if this value is equal to the [reference], within a given [tolerance]. If the reference
+ * value is [Float.NaN], [Float.POSITIVE_INFINITY] or [Float.NEGATIVE_INFINITY], this only returns
+ * true if this value is exactly the same (tolerance is disregarded).
*/
private fun Dp.isWithinTolerance(reference: Dp, tolerance: Dp): Boolean {
return when {
@@ -311,15 +290,12 @@
* @param expected The expected value to which this one should be equal to.
* @param subject Used in the error message to identify which item this assertion failed on.
* @param tolerance The tolerance within which the values should be treated as equal.
- *
* @throws AssertionError if comparison fails.
*/
internal fun Dp.assertIsEqualTo(expected: Dp, subject: String, tolerance: Dp = Dp(.5f)) {
if (!isWithinTolerance(expected, tolerance)) {
// Comparison failed, report the error in DPs
- throw AssertionError(
- "Actual $subject is $this, expected $expected (tolerance: $tolerance)"
- )
+ throw AssertionError("Actual $subject is $this, expected $expected (tolerance: $tolerance)")
}
}
@@ -334,17 +310,14 @@
setContentWithTheme {
CompositionLocalProvider(LocalLayoutDirection provides layoutDirection) {
Box(
- modifier = Modifier
- .fillMaxSize()
- .background(MaterialTheme.colorScheme.background)
+ modifier = Modifier.fillMaxSize().background(MaterialTheme.colorScheme.background)
) {
content()
}
}
}
- onNodeWithTag(testTag).captureToImage()
- .assertAgainstGolden(screenshotRule, methodName)
+ onNodeWithTag(testTag).captureToImage().assertAgainstGolden(screenshotRule, methodName)
}
private fun ImageBitmap.histogram(): MutableMap<Color, Long> {
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ProgressIndicatorScreenshotTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ProgressIndicatorScreenshotTest.kt
index 5f45b38..e6ad406 100644
--- a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ProgressIndicatorScreenshotTest.kt
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ProgressIndicatorScreenshotTest.kt
@@ -53,22 +53,17 @@
@RunWith(AndroidJUnit4::class)
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
class ProgressIndicatorScreenshotTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
- @get:Rule
- val screenshotRule = AndroidXScreenshotTestRule(SCREENSHOT_GOLDEN_PATH)
+ @get:Rule val screenshotRule = AndroidXScreenshotTestRule(SCREENSHOT_GOLDEN_PATH)
- @get:Rule
- val testName = TestName()
+ @get:Rule val testName = TestName()
@Test
fun progress_indicator_fullscreen() = verifyScreenshot {
CircularProgressIndicator(
progress = { 0.25f },
- modifier = Modifier
- .aspectRatio(1f)
- .testTag(TEST_TAG),
+ modifier = Modifier.aspectRatio(1f).testTag(TEST_TAG),
startAngle = 120f,
endAngle = 60f,
)
@@ -78,15 +73,14 @@
fun progress_indicator_custom_color() = verifyScreenshot {
CircularProgressIndicator(
progress = { 0.75f },
- modifier = Modifier
- .size(200.dp)
- .testTag(TEST_TAG),
+ modifier = Modifier.size(200.dp).testTag(TEST_TAG),
startAngle = 120f,
endAngle = 60f,
- colors = ProgressIndicatorDefaults.colors(
- indicatorColor = Color.Green,
- trackColor = Color.Red.copy(alpha = 0.5f)
- )
+ colors =
+ ProgressIndicatorDefaults.colors(
+ indicatorColor = Color.Green,
+ trackColor = Color.Red.copy(alpha = 0.5f)
+ )
)
}
@@ -94,18 +88,18 @@
fun progress_indicator_wrapping_media_button() = verifyScreenshot {
val progressPadding = 4.dp
Box(
- modifier = Modifier
- .size(IconButtonDefaults.DefaultButtonSize + progressPadding)
- .testTag(TEST_TAG)
+ modifier =
+ Modifier.size(IconButtonDefaults.DefaultButtonSize + progressPadding)
+ .testTag(TEST_TAG)
) {
CircularProgressIndicator(progress = { 0.75f }, strokeWidth = progressPadding)
IconButton(
- modifier = Modifier
- .align(Alignment.Center)
- .padding(progressPadding)
- .clip(CircleShape)
- .background(MaterialTheme.colorScheme.surfaceContainer),
- onClick = { }
+ modifier =
+ Modifier.align(Alignment.Center)
+ .padding(progressPadding)
+ .clip(CircleShape)
+ .background(MaterialTheme.colorScheme.surfaceContainer),
+ onClick = {}
) {
Icon(
imageVector = Icons.Filled.PlayArrow,
@@ -119,19 +113,19 @@
fun progress_indicator_overflow() = verifyScreenshot {
CircularProgressIndicator(
progress = { 0.2f },
- modifier = Modifier
- .aspectRatio(1f)
- .testTag(TEST_TAG),
+ modifier = Modifier.aspectRatio(1f).testTag(TEST_TAG),
startAngle = 120f,
endAngle = 60f,
- colors = ProgressIndicatorDefaults.colors(
- trackBrush = Brush.linearGradient(
- listOf(
- MaterialTheme.colorScheme.surfaceContainer,
- MaterialTheme.colorScheme.primary
- )
+ colors =
+ ProgressIndicatorDefaults.colors(
+ trackBrush =
+ Brush.linearGradient(
+ listOf(
+ MaterialTheme.colorScheme.surfaceContainer,
+ MaterialTheme.colorScheme.primary
+ )
+ )
)
- )
)
}
@@ -143,7 +137,8 @@
)
}
- rule.onNodeWithTag(TEST_TAG)
+ rule
+ .onNodeWithTag(TEST_TAG)
.captureToImage()
.assertAgainstGolden(screenshotRule, testName.methodName)
}
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ProgressIndicatorTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ProgressIndicatorTest.kt
index 15ac226..f0f5b16 100644
--- a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ProgressIndicatorTest.kt
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ProgressIndicatorTest.kt
@@ -37,8 +37,7 @@
class CircularProgressIndicatorTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
@Test
fun supports_testtag() {
@@ -60,13 +59,11 @@
)
}
- rule.onNodeWithTag(TEST_TAG)
- .assertRangeInfoEquals(ProgressBarRangeInfo(0f, 0f..1f))
+ rule.onNodeWithTag(TEST_TAG).assertRangeInfoEquals(ProgressBarRangeInfo(0f, 0f..1f))
rule.runOnIdle { progress.value = 0.5f }
- rule.onNodeWithTag(TEST_TAG)
- .assertRangeInfoEquals(ProgressBarRangeInfo(0.5f, 0f..1f))
+ rule.onNodeWithTag(TEST_TAG).assertRangeInfoEquals(ProgressBarRangeInfo(0.5f, 0f..1f))
}
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
@@ -76,10 +73,11 @@
CircularProgressIndicator(
modifier = Modifier.testTag(TEST_TAG),
progress = { 1f },
- colors = ProgressIndicatorDefaults.colors(
- indicatorColor = Color.Yellow,
- trackColor = Color.Red
- ),
+ colors =
+ ProgressIndicatorDefaults.colors(
+ indicatorColor = Color.Yellow,
+ trackColor = Color.Red
+ ),
)
}
rule.waitForIdle()
@@ -98,17 +96,15 @@
CircularProgressIndicator(
modifier = Modifier.testTag(TEST_TAG),
progress = { 0f },
- colors = ProgressIndicatorDefaults.colors(
- indicatorColor = Color.Yellow,
- trackColor = Color.Red
- ),
+ colors =
+ ProgressIndicatorDefaults.colors(
+ indicatorColor = Color.Yellow,
+ trackColor = Color.Red
+ ),
)
}
rule.waitForIdle()
- rule
- .onNodeWithTag(TEST_TAG)
- .captureToImage()
- .assertDoesNotContainColor(Color.Yellow)
+ rule.onNodeWithTag(TEST_TAG).captureToImage().assertDoesNotContainColor(Color.Yellow)
// by default progress track approximately takes 25% of the control.
rule
.onNodeWithTag(TEST_TAG)
@@ -125,10 +121,11 @@
progress = { 0.5f },
startAngle = 0f,
endAngle = 180f,
- colors = ProgressIndicatorDefaults.colors(
- indicatorColor = Color.Yellow,
- trackColor = Color.Red
- ),
+ colors =
+ ProgressIndicatorDefaults.colors(
+ indicatorColor = Color.Yellow,
+ trackColor = Color.Red
+ ),
)
}
rule.waitForIdle()
@@ -157,8 +154,7 @@
rule.runOnIdle { progress.value = 1.5f }
- rule.onNodeWithTag(TEST_TAG)
- .assertRangeInfoEquals(ProgressBarRangeInfo(1f, 0f..1f))
+ rule.onNodeWithTag(TEST_TAG).assertRangeInfoEquals(ProgressBarRangeInfo(1f, 0f..1f))
}
@Test
@@ -174,8 +170,7 @@
rule.runOnIdle { progress.value = -1.5f }
- rule.onNodeWithTag(TEST_TAG)
- .assertRangeInfoEquals(ProgressBarRangeInfo(0f, 0f..1f))
+ rule.onNodeWithTag(TEST_TAG).assertRangeInfoEquals(ProgressBarRangeInfo(0f, 0f..1f))
}
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
@@ -185,10 +180,11 @@
CircularProgressIndicator(
modifier = Modifier.testTag(TEST_TAG),
progress = { 0.05f },
- colors = ProgressIndicatorDefaults.colors(
- indicatorColor = Color.Yellow,
- trackColor = Color.Red
- ),
+ colors =
+ ProgressIndicatorDefaults.colors(
+ indicatorColor = Color.Yellow,
+ trackColor = Color.Red
+ ),
)
}
rule.waitForIdle()
@@ -210,10 +206,11 @@
modifier = Modifier.testTag(TEST_TAG),
progress = { 0.5f },
strokeWidth = 4.dp,
- colors = ProgressIndicatorDefaults.colors(
- indicatorColor = Color.Yellow,
- trackColor = Color.Red
- ),
+ colors =
+ ProgressIndicatorDefaults.colors(
+ indicatorColor = Color.Yellow,
+ trackColor = Color.Red
+ ),
)
}
rule.waitForIdle()
@@ -235,10 +232,11 @@
modifier = Modifier.testTag(TEST_TAG),
progress = { 0.5f },
strokeWidth = 36.dp,
- colors = ProgressIndicatorDefaults.colors(
- indicatorColor = Color.Yellow,
- trackColor = Color.Red
- ),
+ colors =
+ ProgressIndicatorDefaults.colors(
+ indicatorColor = Color.Yellow,
+ trackColor = Color.Red
+ ),
)
}
rule.waitForIdle()
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/SelectableButtonScreenshotTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/SelectableButtonScreenshotTest.kt
index 36f49be..7eb1119 100644
--- a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/SelectableButtonScreenshotTest.kt
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/SelectableButtonScreenshotTest.kt
@@ -43,14 +43,11 @@
@RunWith(AndroidJUnit4::class)
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
class SelectableButtonScreenshotTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
- @get:Rule
- val screenshotRule = AndroidXScreenshotTestRule(SCREENSHOT_GOLDEN_PATH)
+ @get:Rule val screenshotRule = AndroidXScreenshotTestRule(SCREENSHOT_GOLDEN_PATH)
- @get:Rule
- val testName = TestName()
+ @get:Rule val testName = TestName()
@Test
fun radio_button_selected() = verifyScreenshot {
@@ -188,12 +185,8 @@
) {
SelectableButton(
icon = { TestIcon() },
- label = {
- Text("RadioButton")
- },
- secondaryLabel = {
- Text("Secondary label")
- },
+ label = { Text("RadioButton") },
+ secondaryLabel = { Text("Secondary label") },
selected = selected,
enabled = enabled,
selectionControl = selectionControl,
@@ -209,17 +202,11 @@
selectionControl: @Composable SelectionControlScope.() -> Unit = { RadioButton() }
) {
SplitSelectableButton(
- label = {
- Text("SplitRadioButton")
- },
- secondaryLabel = {
- Text("Secondary label")
- },
+ label = { Text("SplitRadioButton") },
+ secondaryLabel = { Text("Secondary label") },
selected = selected,
enabled = enabled,
- selectionControl = {
- selectionControl()
- },
+ selectionControl = { selectionControl() },
onSelectionClick = {},
onContainerClick = {},
modifier = Modifier.testTag(TEST_TAG),
@@ -232,15 +219,12 @@
) {
rule.setContentWithTheme {
CompositionLocalProvider(LocalLayoutDirection provides layoutDirection) {
- Box(
- modifier = Modifier.background(Color.Black)
- ) {
- content()
- }
+ Box(modifier = Modifier.background(Color.Black)) { content() }
}
}
- rule.onNodeWithTag(TEST_TAG)
+ rule
+ .onNodeWithTag(TEST_TAG)
.captureToImage()
.assertAgainstGolden(screenshotRule, testName.methodName)
}
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/SelectableButtonTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/SelectableButtonTest.kt
index 9dfff16..8658dec 100644
--- a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/SelectableButtonTest.kt
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/SelectableButtonTest.kt
@@ -56,15 +56,12 @@
import org.junit.Test
class SelectableButtonTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
@Test
fun selectable_button_supports_testtag() {
rule.setContentWithTheme {
- SelectableButtonWithDefaults(
- modifier = Modifier.testTag(TEST_TAG)
- )
+ SelectableButtonWithDefaults(modifier = Modifier.testTag(TEST_TAG))
}
rule.onNodeWithTag(TEST_TAG).assertExists()
@@ -73,9 +70,7 @@
@Test
fun split_selectable_button_supports_testtag() {
rule.setContentWithTheme {
- SplitSelectableButtonWithDefaults(
- modifier = Modifier.testTag(TEST_TAG)
- )
+ SplitSelectableButtonWithDefaults(modifier = Modifier.testTag(TEST_TAG))
}
rule.onNodeWithTag(TEST_TAG).assertExists()
@@ -84,41 +79,28 @@
@Test
fun selectable_button_has_role_radiobutton() {
rule.setContentWithTheme {
- SelectableButtonWithDefaults(
- modifier = Modifier.testTag(TEST_TAG)
- )
+ SelectableButtonWithDefaults(modifier = Modifier.testTag(TEST_TAG))
}
- rule.onNodeWithTag(TEST_TAG)
- .assert(
- SemanticsMatcher.expectValue(
- SemanticsProperties.Role,
- Role.RadioButton
- )
- )
+ rule
+ .onNodeWithTag(TEST_TAG)
+ .assert(SemanticsMatcher.expectValue(SemanticsProperties.Role, Role.RadioButton))
}
@Test
fun selectable_button_samples_build() {
- rule.setContentWithTheme {
- SelectableButtonSample()
- }
+ rule.setContentWithTheme { SelectableButtonSample() }
}
@Test
fun split_selectable_button_samples_build() {
- rule.setContentWithTheme {
- SplitSelectableButtonSample()
- }
+ rule.setContentWithTheme { SplitSelectableButtonSample() }
}
@Test
fun selectable_button_has_clickaction_when_enabled() {
rule.setContentWithTheme {
- SelectableButtonWithDefaults(
- enabled = true,
- modifier = Modifier.testTag(TEST_TAG)
- )
+ SelectableButtonWithDefaults(enabled = true, modifier = Modifier.testTag(TEST_TAG))
}
rule.onNodeWithTag(TEST_TAG).assertHasClickAction()
@@ -127,10 +109,7 @@
@Test
fun split_selectable_button_has_clickaction_when_enabled() {
rule.setContentWithTheme {
- SplitSelectableButtonWithDefaults(
- enabled = true,
- modifier = Modifier.testTag(TEST_TAG)
- )
+ SplitSelectableButtonWithDefaults(enabled = true, modifier = Modifier.testTag(TEST_TAG))
}
rule.onNodeWithTag(TEST_TAG).onChildAt(0).assertHasClickAction()
@@ -139,10 +118,7 @@
@Test
fun selectable_button_has_clickaction_when_disabled() {
rule.setContentWithTheme {
- SelectableButtonWithDefaults(
- enabled = false,
- modifier = Modifier.testTag(TEST_TAG)
- )
+ SelectableButtonWithDefaults(enabled = false, modifier = Modifier.testTag(TEST_TAG))
}
rule.onNodeWithTag(TEST_TAG).assertHasClickAction()
@@ -163,9 +139,7 @@
@Test
fun selectable_button_is_selectable() {
rule.setContentWithTheme {
- SelectableButtonWithDefaults(
- modifier = Modifier.testTag(TEST_TAG)
- )
+ SelectableButtonWithDefaults(modifier = Modifier.testTag(TEST_TAG))
}
rule.onNode(isSelectable()).assertExists()
@@ -174,9 +148,7 @@
@Test
fun split_selectable_button_is_selectable() {
rule.setContentWithTheme {
- SplitSelectableButtonWithDefaults(
- modifier = Modifier.testTag(TEST_TAG)
- )
+ SplitSelectableButtonWithDefaults(modifier = Modifier.testTag(TEST_TAG))
}
rule.onNode(isSelectable()).assertExists()
@@ -185,9 +157,7 @@
@Test
fun split_selectable_button_is_clickable() {
rule.setContentWithTheme {
- SplitSelectableButtonWithDefaults(
- modifier = Modifier.testTag(TEST_TAG)
- )
+ SplitSelectableButtonWithDefaults(modifier = Modifier.testTag(TEST_TAG))
}
rule.onNodeWithTag(TEST_TAG).onChildAt(0).assertHasClickAction()
}
@@ -195,10 +165,7 @@
@Test
fun selectable_button_is_correctly_enabled() {
rule.setContentWithTheme {
- SelectableButtonWithDefaults(
- enabled = true,
- modifier = Modifier.testTag(TEST_TAG)
- )
+ SelectableButtonWithDefaults(enabled = true, modifier = Modifier.testTag(TEST_TAG))
}
rule.onNodeWithTag(TEST_TAG).assertIsEnabled()
@@ -207,10 +174,7 @@
@Test
fun split_selectable_button_is_correctly_enabled() {
rule.setContentWithTheme {
- SplitSelectableButtonWithDefaults(
- enabled = true,
- modifier = Modifier.testTag(TEST_TAG)
- )
+ SplitSelectableButtonWithDefaults(enabled = true, modifier = Modifier.testTag(TEST_TAG))
}
rule.onNodeWithTag(TEST_TAG).assertIsEnabled()
@@ -219,10 +183,7 @@
@Test
fun selectable_button_is_correctly_disabled() {
rule.setContentWithTheme {
- SelectableButtonWithDefaults(
- enabled = false,
- modifier = Modifier.testTag(TEST_TAG)
- )
+ SelectableButtonWithDefaults(enabled = false, modifier = Modifier.testTag(TEST_TAG))
}
rule.onNodeWithTag(TEST_TAG).assertIsNotEnabled()
@@ -243,10 +204,7 @@
@Test
fun selectable_button_is_correctly_selected() {
rule.setContentWithTheme {
- SelectableButtonWithDefaults(
- selected = true,
- modifier = Modifier.testTag(TEST_TAG)
- )
+ SelectableButtonWithDefaults(selected = true, modifier = Modifier.testTag(TEST_TAG))
}
rule.onNodeWithTag(TEST_TAG).assertIsSelected()
@@ -267,10 +225,7 @@
@Test
fun selectable_button_is_correctly_unselected() {
rule.setContentWithTheme {
- SelectableButtonWithDefaults(
- selected = false,
- modifier = Modifier.testTag(TEST_TAG)
- )
+ SelectableButtonWithDefaults(selected = false, modifier = Modifier.testTag(TEST_TAG))
}
rule.onNodeWithTag(TEST_TAG).assertIsNotSelected()
@@ -300,11 +255,7 @@
)
}
- rule
- .onNodeWithTag(TEST_TAG)
- .assertIsNotSelected()
- .performClick()
- .assertIsSelected()
+ rule.onNodeWithTag(TEST_TAG).assertIsNotSelected().performClick().assertIsSelected()
}
@Test
@@ -397,11 +348,7 @@
)
}
- rule
- .onNodeWithTag(TEST_TAG)
- .assertIsNotSelected()
- .performClick()
- .assertIsNotSelected()
+ rule.onNodeWithTag(TEST_TAG).assertIsNotSelected().performClick().assertIsNotSelected()
}
@Test
@@ -428,40 +375,27 @@
fun can_override_role() {
rule.setContentWithTheme {
SelectableButtonWithDefaults(
- modifier = Modifier
- .testTag(TEST_TAG)
- .semantics {
- role = Role.Button
- }
+ modifier = Modifier.testTag(TEST_TAG).semantics { role = Role.Button }
)
}
- rule.onNodeWithTag(TEST_TAG)
- .assert(
- SemanticsMatcher.expectValue(
- SemanticsProperties.Role,
- Role.Button
- )
- )
+ rule
+ .onNodeWithTag(TEST_TAG)
+ .assert(SemanticsMatcher.expectValue(SemanticsProperties.Role, Role.Button))
}
@Test
fun split_button_clickable_has_role_button() {
rule.setContentWithTheme {
- SplitSelectableButtonWithDefaults(
- modifier = Modifier.testTag(TEST_TAG)
- )
+ SplitSelectableButtonWithDefaults(modifier = Modifier.testTag(TEST_TAG))
}
// NB The toggle control (Checkbox or Switch) provides its own role,
// but the main clickable section is a Button.
- rule.onNodeWithTag(TEST_TAG).onChildAt(0)
- .assert(
- SemanticsMatcher.expectValue(
- SemanticsProperties.Role,
- Role.Button
- )
- )
+ rule
+ .onNodeWithTag(TEST_TAG)
+ .onChildAt(0)
+ .assert(SemanticsMatcher.expectValue(SemanticsProperties.Role, Role.Button))
}
@Test
@@ -472,9 +406,7 @@
SelectableButtonWithDefaults(
selected = true,
onSelected = {},
- label = {
- Text(text = textContent)
- }
+ label = { Text(text = textContent) }
)
}
@@ -489,9 +421,7 @@
SplitSelectableButtonWithDefaults(
selected = true,
onSelected = {},
- label = {
- Text(text = textContent)
- }
+ label = { Text(text = textContent) }
)
}
@@ -502,60 +432,58 @@
fun selectable_button_hasAdjustableHeight() {
val minHeight: Dp = 53.dp
- rule.setContentWithThemeForSizeAssertions {
- SelectableButtonWithDefaults(
- label = {
- Text(
- text = "RadioButton text spanning over multiple lines of text " +
- "to test height is adjustable. This should exceed the minimum height" +
- " for the RadioButton."
- )
- },
- secondaryLabel = {
- Text(
- text = "Secondary label with text."
- )
- }
- )
- }.assertHeightIsAtLeast(minHeight)
+ rule
+ .setContentWithThemeForSizeAssertions {
+ SelectableButtonWithDefaults(
+ label = {
+ Text(
+ text =
+ "RadioButton text spanning over multiple lines of text " +
+ "to test height is adjustable. This should exceed the minimum height" +
+ " for the RadioButton."
+ )
+ },
+ secondaryLabel = { Text(text = "Secondary label with text.") }
+ )
+ }
+ .assertHeightIsAtLeast(minHeight)
}
@Test
fun split_selectable_button_hasAdjustableHeight() {
val minHeight: Dp = 53.dp
- rule.setContentWithThemeForSizeAssertions {
- SplitSelectableButtonWithDefaults(
- label = {
- Text(
- text = "Primary label with 3 lines of text."
- )
- },
- secondaryLabel = {
- Text(
- text = "SplitRadioButton text spanning over multiple lines of text " +
- "to test height is adjustable. This should exceed the minimum height" +
- " for the SplitRadioButton."
- )
- }
- )
- }.assertHeightIsAtLeast(minHeight)
+ rule
+ .setContentWithThemeForSizeAssertions {
+ SplitSelectableButtonWithDefaults(
+ label = { Text(text = "Primary label with 3 lines of text.") },
+ secondaryLabel = {
+ Text(
+ text =
+ "SplitRadioButton text spanning over multiple lines of text " +
+ "to test height is adjustable. This should exceed the minimum height" +
+ " for the SplitRadioButton."
+ )
+ }
+ )
+ }
+ .assertHeightIsAtLeast(minHeight)
}
@Test
fun selectable_button_height_defaults_52dp() {
- rule.setContentWithThemeForSizeAssertions {
- SelectableButtonWithDefaults(
- secondaryLabel = { Text("Secondary label") }
- )
- }.assertHeightIsEqualTo(52.dp)
+ rule
+ .setContentWithThemeForSizeAssertions {
+ SelectableButtonWithDefaults(secondaryLabel = { Text("Secondary label") })
+ }
+ .assertHeightIsEqualTo(52.dp)
}
@Test
fun split_selectable_button_height_defaults_52dp() {
- rule.setContentWithThemeForSizeAssertions {
- SplitSelectableButtonWithDefaults()
- }.assertHeightIsEqualTo(52.dp)
+ rule
+ .setContentWithThemeForSizeAssertions { SplitSelectableButtonWithDefaults() }
+ .assertHeightIsEqualTo(52.dp)
}
@RequiresApi(Build.VERSION_CODES.O)
@@ -603,19 +531,18 @@
rule.setContentWithTheme {
SelectableButtonWithDefaults(
selected = selected,
- colors = SelectableButtonDefaults.selectableButtonColors(
- selectedContainerColor = SELECTED_COLOR,
- unselectedContainerColor = UNSELECTED_COLOR
- ),
+ colors =
+ SelectableButtonDefaults.selectableButtonColors(
+ selectedContainerColor = SELECTED_COLOR,
+ unselectedContainerColor = UNSELECTED_COLOR
+ ),
onSelected = {},
enabled = enabled,
modifier = Modifier.testTag(TEST_TAG),
)
}
- rule.onNodeWithTag(TEST_TAG)
- .captureToImage()
- .assertContainsColor(expectedColor)
+ rule.onNodeWithTag(TEST_TAG).captureToImage().assertContainsColor(expectedColor)
}
@RequiresApi(Build.VERSION_CODES.O)
@@ -627,19 +554,18 @@
rule.setContentWithTheme {
SplitSelectableButtonWithDefaults(
selected = selected,
- colors = SelectableButtonDefaults.splitSelectableButtonColors(
- selectedContainerColor = SELECTED_COLOR,
- unselectedContainerColor = UNSELECTED_COLOR
- ),
+ colors =
+ SelectableButtonDefaults.splitSelectableButtonColors(
+ selectedContainerColor = SELECTED_COLOR,
+ unselectedContainerColor = UNSELECTED_COLOR
+ ),
onSelected = {},
enabled = enabled,
modifier = Modifier.testTag(TEST_TAG),
)
}
- rule.onNodeWithTag(TEST_TAG)
- .captureToImage()
- .assertContainsColor(expectedColor)
+ rule.onNodeWithTag(TEST_TAG).captureToImage().assertContainsColor(expectedColor)
}
}
@@ -650,9 +576,7 @@
enabled: Boolean = true,
colors: SelectableButtonColors = SelectableButtonDefaults.selectableButtonColors(),
onSelected: () -> Unit = {},
- label: @Composable RowScope.() -> Unit = {
- Text("Primary")
- },
+ label: @Composable RowScope.() -> Unit = { Text("Primary") },
secondaryLabel: @Composable (RowScope.() -> Unit)? = null,
icon: @Composable (BoxScope.() -> Unit)? = null,
selectionControl: @Composable SelectionControlScope.() -> Unit = { RadioButton() }
@@ -677,22 +601,21 @@
colors: SplitSelectableButtonColors = SelectableButtonDefaults.splitSelectableButtonColors(),
onSelected: () -> Unit = {},
onClick: () -> Unit = {},
- label: @Composable RowScope.() -> Unit = {
- Text("Primary")
- },
+ label: @Composable RowScope.() -> Unit = { Text("Primary") },
secondaryLabel: @Composable (RowScope.() -> Unit)? = null,
selectionControl: @Composable SelectionControlScope.() -> Unit = { RadioButton() }
-) = SplitSelectableButton(
- modifier = modifier,
- colors = colors,
- selected = selected,
- enabled = enabled,
- onSelectionClick = onSelected,
- label = label,
- secondaryLabel = secondaryLabel,
- onContainerClick = onClick,
- selectionControl = selectionControl,
-)
+) =
+ SplitSelectableButton(
+ modifier = modifier,
+ colors = colors,
+ selected = selected,
+ enabled = enabled,
+ onSelectionClick = onSelected,
+ label = label,
+ secondaryLabel = secondaryLabel,
+ onContainerClick = onClick,
+ selectionControl = selectionControl,
+ )
private val SELECTED_COLOR = Color(0xFFA020F0)
private val UNSELECTED_COLOR = Color(0xFFFFA500)
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/SelectionControlsScreenshotTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/SelectionControlsScreenshotTest.kt
index 8b1c3c8..e21deef 100644
--- a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/SelectionControlsScreenshotTest.kt
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/SelectionControlsScreenshotTest.kt
@@ -41,61 +41,54 @@
@RunWith(AndroidJUnit4::class)
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
class SelectionControlsScreenshotTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
- @get:Rule
- val screenshotRule = AndroidXScreenshotTestRule(SCREENSHOT_GOLDEN_PATH)
+ @get:Rule val screenshotRule = AndroidXScreenshotTestRule(SCREENSHOT_GOLDEN_PATH)
- @get:Rule
- val testName = TestName()
+ @get:Rule val testName = TestName()
@Test
- fun radiobutton_checked_enabled() =
- verifyScreenshot {
- with(SelectionControlScope(isEnabled = true, isSelected = true)) {
- RadioButton(modifier = testBackgroundModifier())
- }
+ fun radiobutton_checked_enabled() = verifyScreenshot {
+ with(SelectionControlScope(isEnabled = true, isSelected = true)) {
+ RadioButton(modifier = testBackgroundModifier())
}
+ }
@Test
- fun radiobutton_unchecked_enabled() =
- verifyScreenshot {
- with(SelectionControlScope(isEnabled = true, isSelected = false)) {
- RadioButton(modifier = testBackgroundModifier())
- }
+ fun radiobutton_unchecked_enabled() = verifyScreenshot {
+ with(SelectionControlScope(isEnabled = true, isSelected = false)) {
+ RadioButton(modifier = testBackgroundModifier())
}
+ }
@Test
- fun radiobutton_checked_disabled() =
- verifyScreenshot {
- with(SelectionControlScope(isEnabled = false, isSelected = true)) {
- RadioButton(modifier = testBackgroundModifier())
- }
+ fun radiobutton_checked_disabled() = verifyScreenshot {
+ with(SelectionControlScope(isEnabled = false, isSelected = true)) {
+ RadioButton(modifier = testBackgroundModifier())
}
+ }
@Test
- fun radiobutton_unchecked_disabled() =
- verifyScreenshot {
- with(SelectionControlScope(isEnabled = false, isSelected = false)) {
- RadioButton(modifier = testBackgroundModifier())
- }
+ fun radiobutton_unchecked_disabled() = verifyScreenshot {
+ with(SelectionControlScope(isEnabled = false, isSelected = false)) {
+ RadioButton(modifier = testBackgroundModifier())
}
+ }
private fun verifyScreenshot(
threshold: Double = 0.98,
content: @Composable BoxScope.() -> Unit
) {
rule.setContentWithTheme(composable = content)
- rule.onNodeWithTag(TEST_TAG)
+ rule
+ .onNodeWithTag(TEST_TAG)
.captureToImage()
.assertAgainstGolden(screenshotRule, testName.methodName, MSSIMMatcher(threshold))
}
@Composable
private fun testBackgroundModifier(): Modifier =
- Modifier
- .testTag(TEST_TAG)
+ Modifier.testTag(TEST_TAG)
.background(
MaterialTheme.colorScheme.primary
.copy(alpha = 0.5f)
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/SelectionControlsTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/SelectionControlsTest.kt
index 825057e..5abd471 100644
--- a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/SelectionControlsTest.kt
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/SelectionControlsTest.kt
@@ -32,16 +32,13 @@
import org.junit.Test
class SelectionControlsTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
@Test
fun radio_control_supports_testtag() {
rule.setContentWithTheme {
with(SelectionControlScope(isEnabled = true, isSelected = true)) {
- RadioButton(
- Modifier.testTag(TEST_TAG)
- )
+ RadioButton(Modifier.testTag(TEST_TAG))
}
}
@@ -53,9 +50,7 @@
rule
.setContentWithThemeForSizeAssertions {
with(SelectionControlScope(isEnabled = true, isSelected = true)) {
- RadioButton(
- modifier = Modifier.testTag(TEST_TAG)
- )
+ RadioButton(modifier = Modifier.testTag(TEST_TAG))
}
}
.assertHeightIsEqualTo(SELECTION_CONTROL_HEIGHT)
@@ -66,9 +61,7 @@
fun radio_control_is_correctly_enabled() {
rule.setContentWithTheme {
with(SelectionControlScope(isEnabled = true, isSelected = true)) {
- RadioButton(
- modifier = Modifier.testTag(TEST_TAG)
- )
+ RadioButton(modifier = Modifier.testTag(TEST_TAG))
}
}
@@ -82,9 +75,7 @@
rule.setContentWithTheme {
with(SelectionControlScope(isEnabled = true, isSelected = true)) {
RadioButton(
- colors = RadioButtonDefaults.colors(
- selectedColor = color
- ),
+ colors = RadioButtonDefaults.colors(selectedColor = color),
modifier = Modifier.testTag(TEST_TAG)
)
}
@@ -103,9 +94,10 @@
rule.setContentWithTheme {
with(SelectionControlScope(isEnabled = true, isSelected = false)) {
RadioButton(
- colors = RadioButtonDefaults.colors(
- unselectedColor = color,
- ),
+ colors =
+ RadioButtonDefaults.colors(
+ unselectedColor = color,
+ ),
modifier = Modifier.testTag(TEST_TAG)
)
}
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/SliderScreenshotTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/SliderScreenshotTest.kt
index bff1c22..f7bc074 100644
--- a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/SliderScreenshotTest.kt
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/SliderScreenshotTest.kt
@@ -57,14 +57,11 @@
@OptIn(ExperimentalWearMaterial3Api::class)
class SliderScreenshotTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
- @get:Rule
- val screenshotRule = AndroidXScreenshotTestRule(SCREENSHOT_GOLDEN_PATH)
+ @get:Rule val screenshotRule = AndroidXScreenshotTestRule(SCREENSHOT_GOLDEN_PATH)
- @get:Rule
- val testName = TestName()
+ @get:Rule val testName = TestName()
@Test
fun inlineslider_not_segmented() {
@@ -75,7 +72,7 @@
segmented = false,
increaseIcon = { Icon(InlineSliderDefaults.Increase, "Increase") },
decreaseIcon = { Icon(InlineSliderDefaults.Decrease, "Decrease") },
- onValueChange = { },
+ onValueChange = {},
valueRange = 1f..4f,
steps = 2
)
@@ -92,7 +89,7 @@
enabled = false,
increaseIcon = { Icon(InlineSliderDefaults.Increase, "Increase") },
decreaseIcon = { Icon(InlineSliderDefaults.Decrease, "Decrease") },
- onValueChange = { },
+ onValueChange = {},
valueRange = 1f..4f,
steps = 2
)
@@ -108,7 +105,7 @@
segmented = true,
increaseIcon = { Icon(InlineSliderDefaults.Increase, "Increase") },
decreaseIcon = { Icon(InlineSliderDefaults.Decrease, "Decrease") },
- onValueChange = { },
+ onValueChange = {},
valueRange = 1f..4f,
steps = 2
)
@@ -125,7 +122,7 @@
enabled = false,
increaseIcon = { Icon(InlineSliderDefaults.Increase, "Increase") },
decreaseIcon = { Icon(InlineSliderDefaults.Decrease, "Decrease") },
- onValueChange = { },
+ onValueChange = {},
valueRange = 1f..4f,
steps = 2
)
@@ -135,15 +132,13 @@
@Test
public fun inlineslider_rtl() {
verifyScreenshot {
- CompositionLocalProvider(
- LocalLayoutDirection provides LayoutDirection.Rtl
- ) {
+ CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl) {
InlineSlider(
modifier = Modifier.testTag(TEST_TAG),
value = 2f,
increaseIcon = { Icon(InlineSliderDefaults.Increase, "Increase") },
decreaseIcon = { Icon(InlineSliderDefaults.Decrease, "Decrease") },
- onValueChange = { },
+ onValueChange = {},
valueRange = 1f..4f,
steps = 2
)
@@ -190,19 +185,20 @@
segmented = true,
increaseIcon = { Icon(InlineSliderDefaults.Increase, "Increase") },
decreaseIcon = { Icon(InlineSliderDefaults.Decrease, "Decrease") },
- colors = InlineSliderDefaults.colors(
- containerColor = Color.Green,
- buttonIconColor = Color.Yellow,
- selectedBarColor = Color.Magenta,
- unselectedBarColor = Color.White,
- barSeparatorColor = Color.Cyan,
- disabledContainerColor = Color.DarkGray,
- disabledButtonIconColor = Color.LightGray,
- disabledSelectedBarColor = Color.Red,
- disabledUnselectedBarColor = Color.Blue,
- disabledBarSeparatorColor = Color.Gray
- ),
- onValueChange = { },
+ colors =
+ InlineSliderDefaults.colors(
+ containerColor = Color.Green,
+ buttonIconColor = Color.Yellow,
+ selectedBarColor = Color.Magenta,
+ unselectedBarColor = Color.White,
+ barSeparatorColor = Color.Cyan,
+ disabledContainerColor = Color.DarkGray,
+ disabledButtonIconColor = Color.LightGray,
+ disabledSelectedBarColor = Color.Red,
+ disabledUnselectedBarColor = Color.Blue,
+ disabledBarSeparatorColor = Color.Gray
+ ),
+ onValueChange = {},
valueRange = 1f..4f,
steps = 2
)
@@ -215,19 +211,11 @@
InlineSlider(
modifier = Modifier.testTag(TEST_TAG),
value = 2f,
- onValueChange = { },
+ onValueChange = {},
valueRange = 1f..4f,
- decreaseIcon = {
- Icon(
- imageVector = Icons.Default.Star,
- contentDescription = ""
- )
- },
+ decreaseIcon = { Icon(imageVector = Icons.Default.Star, contentDescription = "") },
increaseIcon = {
- Icon(
- imageVector = Icons.Filled.ThumbUp,
- contentDescription = ""
- )
+ Icon(imageVector = Icons.Filled.ThumbUp, contentDescription = "")
},
steps = 2
)
@@ -244,19 +232,20 @@
segmented = true,
increaseIcon = { Icon(InlineSliderDefaults.Increase, "Increase") },
decreaseIcon = { Icon(InlineSliderDefaults.Decrease, "Decrease") },
- colors = InlineSliderDefaults.colors(
- containerColor = Color.Green,
- buttonIconColor = Color.Yellow,
- selectedBarColor = Color.Magenta,
- unselectedBarColor = Color.White,
- barSeparatorColor = Color.Cyan,
- disabledContainerColor = Color.DarkGray,
- disabledButtonIconColor = Color.LightGray,
- disabledSelectedBarColor = Color.Red,
- disabledUnselectedBarColor = Color.Blue,
- disabledBarSeparatorColor = Color.Gray
- ),
- onValueChange = { },
+ colors =
+ InlineSliderDefaults.colors(
+ containerColor = Color.Green,
+ buttonIconColor = Color.Yellow,
+ selectedBarColor = Color.Magenta,
+ unselectedBarColor = Color.White,
+ barSeparatorColor = Color.Cyan,
+ disabledContainerColor = Color.DarkGray,
+ disabledButtonIconColor = Color.LightGray,
+ disabledSelectedBarColor = Color.Red,
+ disabledUnselectedBarColor = Color.Blue,
+ disabledBarSeparatorColor = Color.Gray
+ ),
+ onValueChange = {},
valueRange = 1f..4f,
steps = 2
)
@@ -270,39 +259,28 @@
modifier = Modifier.testTag(TEST_TAG),
value = 2f,
enabled = false,
- onValueChange = { },
+ onValueChange = {},
valueRange = 1f..4f,
- decreaseIcon = {
- Icon(
- imageVector = Icons.Default.Star,
- contentDescription = ""
- )
- },
+ decreaseIcon = { Icon(imageVector = Icons.Default.Star, contentDescription = "") },
increaseIcon = {
- Icon(
- imageVector = Icons.Filled.ThumbUp,
- contentDescription = ""
- )
+ Icon(imageVector = Icons.Filled.ThumbUp, contentDescription = "")
},
steps = 2
)
}
}
- private fun verifyScreenshot(
- content: @Composable () -> Unit
- ) {
+ private fun verifyScreenshot(content: @Composable () -> Unit) {
rule.setContentWithTheme {
Box(
- modifier = Modifier
- .fillMaxSize()
- .background(MaterialTheme.colorScheme.background)
+ modifier = Modifier.fillMaxSize().background(MaterialTheme.colorScheme.background)
) {
content()
}
}
- rule.onNodeWithTag(TEST_TAG)
+ rule
+ .onNodeWithTag(TEST_TAG)
.captureToImage()
.assertAgainstGolden(screenshotRule, testName.methodName)
}
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/SliderTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/SliderTest.kt
index d14aee4..d4d8716 100644
--- a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/SliderTest.kt
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/SliderTest.kt
@@ -44,8 +44,7 @@
@OptIn(ExperimentalWearMaterial3Api::class)
public class SliderTest {
- @get:Rule
- public val rule = createComposeRule()
+ @get:Rule public val rule = createComposeRule()
@Test
public fun supports_testtag() {
@@ -75,11 +74,8 @@
modifier = Modifier.testTag(TEST_TAG)
)
}
- rule.runOnIdle {
- state.value = 20f
- }
- rule.onNodeWithTag(TEST_TAG)
- .assertRangeInfoEquals(ProgressBarRangeInfo(10f, 0f..10f, 4))
+ rule.runOnIdle { state.value = 20f }
+ rule.onNodeWithTag(TEST_TAG).assertRangeInfoEquals(ProgressBarRangeInfo(10f, 0f..10f, 4))
}
@Test
@@ -95,22 +91,14 @@
modifier = Modifier.testTag(TEST_TAG)
)
}
- rule.runOnIdle {
- state.value = -20f
- }
- rule.onNodeWithTag(TEST_TAG)
- .assertRangeInfoEquals(ProgressBarRangeInfo(0f, 0f..10f, 4))
+ rule.runOnIdle { state.value = -20f }
+ rule.onNodeWithTag(TEST_TAG).assertRangeInfoEquals(ProgressBarRangeInfo(0f, 0f..10f, 4))
}
@Test(expected = IllegalArgumentException::class)
public fun throws_when_steps_negative() {
rule.setContent {
- DefaultInlineSlider(
- value = 0f,
- valueRange = 0f..10f,
- onValueChange = {},
- steps = -1
- )
+ DefaultInlineSlider(value = 0f, valueRange = 0f..10f, onValueChange = {}, steps = -1)
}
}
@@ -129,12 +117,9 @@
)
}
- rule.runOnUiThread {
- state.value = 0.6f
- }
+ rule.runOnUiThread { state.value = 0.6f }
- rule.onNodeWithTag(TEST_TAG)
- .assertRangeInfoEquals(ProgressBarRangeInfo(0.6f, range, 4))
+ rule.onNodeWithTag(TEST_TAG).assertRangeInfoEquals(ProgressBarRangeInfo(0.6f, range, 4))
}
@Test
@@ -152,12 +137,9 @@
)
}
- rule.runOnUiThread {
- state.value = 0.65f
- }
+ rule.runOnUiThread { state.value = 0.65f }
- rule.onNodeWithTag(TEST_TAG)
- .assertRangeInfoEquals(ProgressBarRangeInfo(0.6f, range, 4))
+ rule.onNodeWithTag(TEST_TAG).assertRangeInfoEquals(ProgressBarRangeInfo(0.6f, range, 4))
}
@Test
@@ -175,12 +157,9 @@
)
}
- rule.runOnUiThread {
- state.value = 0.55f
- }
+ rule.runOnUiThread { state.value = 0.55f }
- rule.onNodeWithTag(TEST_TAG)
- .assertRangeInfoEquals(ProgressBarRangeInfo(0.6f, range, 4))
+ rule.onNodeWithTag(TEST_TAG).assertRangeInfoEquals(ProgressBarRangeInfo(0.6f, range, 4))
}
@Test
@@ -197,9 +176,7 @@
}
rule.onNodeWithTag(TEST_TAG).performTouchInput { click(Offset(15f, height / 2f)) }
- rule.runOnIdle {
- Truth.assertThat(state.value).isWithin(0.001f).of(1f)
- }
+ rule.runOnIdle { Truth.assertThat(state.value).isWithin(0.001f).of(1f) }
}
@Test
@@ -216,9 +193,7 @@
}
rule.onNodeWithTag(TEST_TAG).performTouchInput { click(Offset(width - 15f, height / 2f)) }
- rule.runOnIdle {
- Truth.assertThat(state.value).isWithin(0.001f).of(3f)
- }
+ rule.runOnIdle { Truth.assertThat(state.value).isWithin(0.001f).of(3f) }
}
@Test
@@ -231,13 +206,15 @@
enabled = false,
increaseIcon = {
Icon(
- InlineSliderDefaults.Increase, "Increase",
+ InlineSliderDefaults.Increase,
+ "Increase",
Modifier.size(InlineSliderDefaults.IconSize)
)
},
decreaseIcon = {
Icon(
- InlineSliderDefaults.Decrease, "Decrease",
+ InlineSliderDefaults.Decrease,
+ "Decrease",
Modifier.size(InlineSliderDefaults.IconSize)
)
},
@@ -248,9 +225,7 @@
}
rule.onNodeWithTag(TEST_TAG).performTouchInput { click(Offset(15f, height / 2f)) }
- rule.runOnIdle {
- Truth.assertThat(state.value).isWithin(0.001f).of(2f)
- }
+ rule.runOnIdle { Truth.assertThat(state.value).isWithin(0.001f).of(2f) }
}
@Test
@@ -264,13 +239,15 @@
onValueChange = { state.value = it },
increaseIcon = {
Icon(
- InlineSliderDefaults.Increase, "Increase",
+ InlineSliderDefaults.Increase,
+ "Increase",
Modifier.size(InlineSliderDefaults.IconSize)
)
},
decreaseIcon = {
Icon(
- InlineSliderDefaults.Decrease, "Decrease",
+ InlineSliderDefaults.Decrease,
+ "Decrease",
Modifier.size(InlineSliderDefaults.IconSize)
)
},
@@ -280,9 +257,7 @@
}
rule.onNodeWithTag(TEST_TAG).performTouchInput { click(Offset(width - 15f, height / 2f)) }
- rule.runOnIdle {
- Truth.assertThat(state.value).isWithin(0.001f).of(2f)
- }
+ rule.runOnIdle { Truth.assertThat(state.value).isWithin(0.001f).of(2f) }
}
@Test
@@ -299,9 +274,7 @@
}
rule.onNodeWithTag(TEST_TAG).performTouchInput { click(Offset(15f, height / 2f)) }
- rule.runOnIdle {
- Truth.assertThat(state.value).isWithin(0.001f).of(1f)
- }
+ rule.runOnIdle { Truth.assertThat(state.value).isWithin(0.001f).of(1f) }
}
@Test
@@ -318,9 +291,7 @@
}
rule.onNodeWithTag(TEST_TAG).performTouchInput { click(Offset(width - 15f, height / 2f)) }
- rule.runOnIdle {
- Truth.assertThat(state.value).isWithin(0.001f).of(4f)
- }
+ rule.runOnIdle { Truth.assertThat(state.value).isWithin(0.001f).of(4f) }
}
@Test
@@ -335,15 +306,14 @@
onValueChange = {},
increaseIcon = {
Icon(
- InlineSliderDefaults.Increase, "Increase",
+ InlineSliderDefaults.Increase,
+ "Increase",
Modifier.size(InlineSliderDefaults.IconSize)
)
},
decreaseIcon = {
Icon(
- modifier = Modifier
- .testTag(iconTag)
- .size(InlineSliderDefaults.IconSize),
+ modifier = Modifier.testTag(iconTag).size(InlineSliderDefaults.IconSize),
imageVector = Icons.Default.Star,
contentDescription = ""
)
@@ -352,7 +322,8 @@
}
rule.waitForIdle()
- rule.onNodeWithTag(iconTag, true)
+ rule
+ .onNodeWithTag(iconTag, true)
.assertExists()
.assertLeftPositionInRootIsEqualTo(IconsOuterHorizontalMargin)
}
@@ -369,16 +340,15 @@
onValueChange = {},
increaseIcon = {
Icon(
- modifier = Modifier
- .testTag(iconTag)
- .size(InlineSliderDefaults.IconSize),
+ modifier = Modifier.testTag(iconTag).size(InlineSliderDefaults.IconSize),
imageVector = Icons.Default.Star,
contentDescription = ""
)
},
decreaseIcon = {
Icon(
- InlineSliderDefaults.Decrease, "Decrease",
+ InlineSliderDefaults.Decrease,
+ "Decrease",
Modifier.size(InlineSliderDefaults.IconSize)
)
},
@@ -387,11 +357,11 @@
val unclippedBoundsInRoot = rule.onRoot().getUnclippedBoundsInRoot()
rule.waitForIdle()
- rule.onNodeWithTag(iconTag, true)
+ rule
+ .onNodeWithTag(iconTag, true)
.assertExists()
.assertLeftPositionInRootIsEqualTo(
- unclippedBoundsInRoot.width -
- IconsOuterHorizontalMargin - DefaultIconWidth
+ unclippedBoundsInRoot.width - IconsOuterHorizontalMargin - DefaultIconWidth
)
}
@@ -406,13 +376,15 @@
steps = 5,
increaseIcon = {
Icon(
- InlineSliderDefaults.Increase, "Increase",
+ InlineSliderDefaults.Increase,
+ "Increase",
Modifier.size(InlineSliderDefaults.IconSize)
)
},
decreaseIcon = {
Icon(
- InlineSliderDefaults.Decrease, testContentDescription,
+ InlineSliderDefaults.Decrease,
+ testContentDescription,
Modifier.size(InlineSliderDefaults.IconSize)
)
},
@@ -421,7 +393,8 @@
}
rule.waitForIdle()
- rule.onNodeWithTag(TEST_TAG, true)
+ rule
+ .onNodeWithTag(TEST_TAG, true)
// 0 is the index of decrease button, 1 - increase button
.onChildAt(0)
.onChild()
@@ -439,13 +412,15 @@
steps = 5,
increaseIcon = {
Icon(
- InlineSliderDefaults.Increase, testContentDescription,
+ InlineSliderDefaults.Increase,
+ testContentDescription,
Modifier.size(InlineSliderDefaults.IconSize)
)
},
decreaseIcon = {
Icon(
- InlineSliderDefaults.Decrease, "Decrease",
+ InlineSliderDefaults.Decrease,
+ "Decrease",
Modifier.size(InlineSliderDefaults.IconSize)
)
},
@@ -454,7 +429,8 @@
}
rule.waitForIdle()
- rule.onNodeWithTag(TEST_TAG, true)
+ rule
+ .onNodeWithTag(TEST_TAG, true)
// 0 is the index of decrease button, 1 - increase button
.onChildAt(1)
.onChild()
@@ -486,8 +462,7 @@
)
}
- rule.onNodeWithTag(TEST_TAG)
- .assertRangeInfoEquals(ProgressBarRangeInfo(2f, 0f..10f, 9))
+ rule.onNodeWithTag(TEST_TAG).assertRangeInfoEquals(ProgressBarRangeInfo(2f, 0f..10f, 9))
}
@Test
@@ -501,8 +476,7 @@
)
}
- rule.onNodeWithTag(TEST_TAG)
- .assertRangeInfoEquals(ProgressBarRangeInfo(2f, 0f..10f, 4))
+ rule.onNodeWithTag(TEST_TAG).assertRangeInfoEquals(ProgressBarRangeInfo(2f, 0f..10f, 4))
}
@Test
@@ -516,8 +490,7 @@
)
}
- rule.onNodeWithTag(TEST_TAG)
- .assertRangeInfoEquals(ProgressBarRangeInfo(6f, 0f..12f, 1))
+ rule.onNodeWithTag(TEST_TAG).assertRangeInfoEquals(ProgressBarRangeInfo(6f, 0f..12f, 1))
}
@Test
@@ -532,11 +505,8 @@
modifier = Modifier.testTag(TEST_TAG)
)
}
- rule.runOnIdle {
- state.value = 20
- }
- rule.onNodeWithTag(TEST_TAG)
- .assertRangeInfoEquals(ProgressBarRangeInfo(10f, 0f..10f, 9))
+ rule.runOnIdle { state.value = 20 }
+ rule.onNodeWithTag(TEST_TAG).assertRangeInfoEquals(ProgressBarRangeInfo(10f, 0f..10f, 9))
}
@Test
@@ -551,11 +521,8 @@
modifier = Modifier.testTag(TEST_TAG)
)
}
- rule.runOnIdle {
- state.value = -20
- }
- rule.onNodeWithTag(TEST_TAG)
- .assertRangeInfoEquals(ProgressBarRangeInfo(0f, 0f..10f, 9))
+ rule.runOnIdle { state.value = -20 }
+ rule.onNodeWithTag(TEST_TAG).assertRangeInfoEquals(ProgressBarRangeInfo(0f, 0f..10f, 9))
}
@Test
@@ -571,12 +538,9 @@
)
}
- rule.runOnUiThread {
- state.value = 6
- }
+ rule.runOnUiThread { state.value = 6 }
- rule.onNodeWithTag(TEST_TAG)
- .assertRangeInfoEquals(ProgressBarRangeInfo(6f, 0f..12f, 3))
+ rule.onNodeWithTag(TEST_TAG).assertRangeInfoEquals(ProgressBarRangeInfo(6f, 0f..12f, 3))
}
@Test
@@ -592,12 +556,9 @@
)
}
- rule.runOnUiThread {
- state.value = 7
- }
+ rule.runOnUiThread { state.value = 7 }
- rule.onNodeWithTag(TEST_TAG)
- .assertRangeInfoEquals(ProgressBarRangeInfo(6f, 0f..12f, 3))
+ rule.onNodeWithTag(TEST_TAG).assertRangeInfoEquals(ProgressBarRangeInfo(6f, 0f..12f, 3))
}
@Test
@@ -613,12 +574,9 @@
)
}
- rule.runOnUiThread {
- state.value = 8
- }
+ rule.runOnUiThread { state.value = 8 }
- rule.onNodeWithTag(TEST_TAG)
- .assertRangeInfoEquals(ProgressBarRangeInfo(9f, 0f..12f, 3))
+ rule.onNodeWithTag(TEST_TAG).assertRangeInfoEquals(ProgressBarRangeInfo(9f, 0f..12f, 3))
}
@Test
@@ -634,9 +592,7 @@
}
rule.onNodeWithTag(TEST_TAG).performTouchInput { click(Offset(15f, height / 2f)) }
- rule.runOnIdle {
- Truth.assertThat(state.value).isEqualTo(1)
- }
+ rule.runOnIdle { Truth.assertThat(state.value).isEqualTo(1) }
}
@Test
@@ -652,9 +608,7 @@
}
rule.onNodeWithTag(TEST_TAG).performTouchInput { click(Offset(width - 15f, height / 2f)) }
- rule.runOnIdle {
- Truth.assertThat(state.value).isEqualTo(3)
- }
+ rule.runOnIdle { Truth.assertThat(state.value).isEqualTo(3) }
}
@Test
@@ -667,13 +621,15 @@
enabled = false,
increaseIcon = {
Icon(
- InlineSliderDefaults.Increase, "Increase",
+ InlineSliderDefaults.Increase,
+ "Increase",
Modifier.size(InlineSliderDefaults.IconSize)
)
},
decreaseIcon = {
Icon(
- InlineSliderDefaults.Decrease, "Decrease",
+ InlineSliderDefaults.Decrease,
+ "Decrease",
Modifier.size(InlineSliderDefaults.IconSize)
)
},
@@ -683,9 +639,7 @@
}
rule.onNodeWithTag(TEST_TAG).performTouchInput { click(Offset(15f, height / 2f)) }
- rule.runOnIdle {
- Truth.assertThat(state.value).isEqualTo(2)
- }
+ rule.runOnIdle { Truth.assertThat(state.value).isEqualTo(2) }
}
@Test
@@ -701,9 +655,7 @@
}
rule.onNodeWithTag(TEST_TAG).performTouchInput { click(Offset(15f, height / 2f)) }
- rule.runOnIdle {
- Truth.assertThat(state.value).isEqualTo(1)
- }
+ rule.runOnIdle { Truth.assertThat(state.value).isEqualTo(1) }
}
@Test
@@ -719,9 +671,7 @@
}
rule.onNodeWithTag(TEST_TAG).performTouchInput { click(Offset(width - 15f, height / 2f)) }
- rule.runOnIdle {
- Truth.assertThat(state.value).isEqualTo(4)
- }
+ rule.runOnIdle { Truth.assertThat(state.value).isEqualTo(4) }
}
@Composable
@@ -737,13 +687,15 @@
value = value,
increaseIcon = {
Icon(
- InlineSliderDefaults.Increase, "Increase",
+ InlineSliderDefaults.Increase,
+ "Increase",
Modifier.size(InlineSliderDefaults.IconSize)
)
},
decreaseIcon = {
Icon(
- InlineSliderDefaults.Decrease, "Decrease",
+ InlineSliderDefaults.Decrease,
+ "Decrease",
Modifier.size(InlineSliderDefaults.IconSize)
)
},
@@ -765,13 +717,15 @@
value = value,
increaseIcon = {
Icon(
- InlineSliderDefaults.Increase, "Increase",
+ InlineSliderDefaults.Increase,
+ "Increase",
Modifier.size(InlineSliderDefaults.IconSize)
)
},
decreaseIcon = {
Icon(
- InlineSliderDefaults.Decrease, "Decrease",
+ InlineSliderDefaults.Decrease,
+ "Decrease",
Modifier.size(InlineSliderDefaults.IconSize)
)
},
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/StepperScreenshotTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/StepperScreenshotTest.kt
index 292f290..882fff6 100644
--- a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/StepperScreenshotTest.kt
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/StepperScreenshotTest.kt
@@ -58,14 +58,11 @@
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
@OptIn(ExperimentalWearMaterial3Api::class)
public class StepperScreenshotTest {
- @get:Rule
- public val rule = createComposeRule()
+ @get:Rule public val rule = createComposeRule()
- @get:Rule
- public val screenshotRule = AndroidXScreenshotTestRule(SCREENSHOT_GOLDEN_PATH)
+ @get:Rule public val screenshotRule = AndroidXScreenshotTestRule(SCREENSHOT_GOLDEN_PATH)
- @get:Rule
- public val testName = TestName()
+ @get:Rule public val testName = TestName()
@Test
public fun stepper_no_content() {
@@ -89,17 +86,9 @@
value = 2f,
steps = 3,
onValueChange = {},
- decreaseIcon = {
- Icon(
- imageVector = Icons.Default.Star,
- contentDescription = ""
- )
- },
+ decreaseIcon = { Icon(imageVector = Icons.Default.Star, contentDescription = "") },
increaseIcon = {
- Icon(
- imageVector = Icons.Filled.ThumbUp,
- contentDescription = ""
- )
+ Icon(imageVector = Icons.Filled.ThumbUp, contentDescription = "")
},
) {}
}
@@ -119,12 +108,7 @@
FilledTonalButton(
onClick = {},
modifier = Modifier.width(146.dp),
- label = {
- Text(
- text = "Demo",
- modifier = Modifier.fillMaxWidth()
- )
- }
+ label = { Text(text = "Demo", modifier = Modifier.fillMaxWidth()) }
)
}
}
@@ -179,20 +163,17 @@
}
}
- private fun verifyScreenshot(
- content: @Composable () -> Unit
- ) {
+ private fun verifyScreenshot(content: @Composable () -> Unit) {
rule.setContentWithTheme {
Box(
- modifier = Modifier
- .fillMaxSize()
- .background(MaterialTheme.colorScheme.background)
+ modifier = Modifier.fillMaxSize().background(MaterialTheme.colorScheme.background)
) {
content()
}
}
- rule.onNodeWithTag(TEST_TAG)
+ rule
+ .onNodeWithTag(TEST_TAG)
.captureToImage()
.assertAgainstGolden(screenshotRule, testName.methodName)
}
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/StepperTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/StepperTest.kt
index 030a9a0..fe7e04c 100644
--- a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/StepperTest.kt
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/StepperTest.kt
@@ -51,8 +51,7 @@
@OptIn(ExperimentalWearMaterial3Api::class)
class StepperTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
@Test
fun supports_testtag() {
@@ -71,22 +70,24 @@
}
@Test
- fun coerces_value_top_limit() = rule.setNewValueAndCheck(
- range = 0f..10f,
- steps = 4,
- initialValue = 4f,
- newValue = 20f,
- expectedFinalValue = 10f
- )
+ fun coerces_value_top_limit() =
+ rule.setNewValueAndCheck(
+ range = 0f..10f,
+ steps = 4,
+ initialValue = 4f,
+ newValue = 20f,
+ expectedFinalValue = 10f
+ )
@Test
- fun coerces_value_lower_limit() = rule.setNewValueAndCheck(
- range = 0f..10f,
- steps = 4,
- initialValue = 4f,
- newValue = -20f,
- expectedFinalValue = 0f
- )
+ fun coerces_value_lower_limit() =
+ rule.setNewValueAndCheck(
+ range = 0f..10f,
+ steps = 4,
+ initialValue = 4f,
+ newValue = -20f,
+ expectedFinalValue = 0f
+ )
@Test(expected = IllegalArgumentException::class)
fun throws_when_steps_negative() {
@@ -102,34 +103,37 @@
}
@Test
- fun coerce_value_exactly() = rule.setNewValueAndCheck(
- range = 0f..1f,
- steps = 4,
- initialValue = 0f,
- // Allowed values are only 0, 0.2, 0.4, 0.6, 0.8, 1
- newValue = 0.6f,
- expectedFinalValue = 0.6f
- )
+ fun coerce_value_exactly() =
+ rule.setNewValueAndCheck(
+ range = 0f..1f,
+ steps = 4,
+ initialValue = 0f,
+ // Allowed values are only 0, 0.2, 0.4, 0.6, 0.8, 1
+ newValue = 0.6f,
+ expectedFinalValue = 0.6f
+ )
@Test
- fun coerce_value_to_previous() = rule.setNewValueAndCheck(
- range = 0f..1f,
- steps = 4,
- initialValue = 0f,
- // Allowed values are only 0, 0.2, 0.4, 0.6, 0.8, 1
- newValue = 0.65f,
- expectedFinalValue = 0.6f
- )
+ fun coerce_value_to_previous() =
+ rule.setNewValueAndCheck(
+ range = 0f..1f,
+ steps = 4,
+ initialValue = 0f,
+ // Allowed values are only 0, 0.2, 0.4, 0.6, 0.8, 1
+ newValue = 0.65f,
+ expectedFinalValue = 0.6f
+ )
@Test
- fun coerce_value_to_next() = rule.setNewValueAndCheck(
- range = 0f..1f,
- steps = 4,
- initialValue = 0f,
- // Allowed values are only 0, 0.2, 0.4, 0.6, 0.8, 1
- newValue = 0.55f,
- expectedFinalValue = 0.6f
- )
+ fun coerce_value_to_next() =
+ rule.setNewValueAndCheck(
+ range = 0f..1f,
+ steps = 4,
+ initialValue = 0f,
+ // Allowed values are only 0, 0.2, 0.4, 0.6, 0.8, 1
+ newValue = 0.55f,
+ expectedFinalValue = 0.6f
+ )
@Test
fun decreases_value_by_clicking_bottom() {
@@ -139,13 +143,9 @@
rule.initDefaultStepper(state, range, 2)
// The clickable area for a decrease button takes bottom 35% of the screen
- rule.onNodeWithTag(TEST_TAG).performTouchInput {
- click(Offset(width / 2f, height - 15f))
- }
+ rule.onNodeWithTag(TEST_TAG).performTouchInput { click(Offset(width / 2f, height - 15f)) }
- rule.runOnIdle {
- Truth.assertThat(state.value).isWithin(0.001f).of(1f)
- }
+ rule.runOnIdle { Truth.assertThat(state.value).isWithin(0.001f).of(1f) }
}
@Test
@@ -158,9 +158,7 @@
// The clickable area for an increase button takes top 35% of the screen
rule.onNodeWithTag(TEST_TAG).performTouchInput { click(Offset(width / 2f, 15f)) }
- rule.runOnIdle {
- Truth.assertThat(state.value).isWithin(0.001f).of(3f)
- }
+ rule.runOnIdle { Truth.assertThat(state.value).isWithin(0.001f).of(3f) }
}
@Test
@@ -174,9 +172,7 @@
// The clickable area for a decrease button takes bottom 35% of the screen
rule.onNodeWithTag(TEST_TAG).performTouchInput { click(Offset(width / 2f, height - 15f)) }
- rule.runOnIdle {
- Truth.assertThat(state.value).isWithin(0.001f).of(1f)
- }
+ rule.runOnIdle { Truth.assertThat(state.value).isWithin(0.001f).of(1f) }
}
@Test
@@ -190,9 +186,7 @@
// The clickable area for an increase button takes top 35% of the screen
rule.onNodeWithTag(TEST_TAG).performTouchInput { click(Offset(width / 2f, 15f)) }
- rule.runOnIdle {
- Truth.assertThat(state.value).isWithin(0.001f).of(4f)
- }
+ rule.runOnIdle { Truth.assertThat(state.value).isWithin(0.001f).of(4f) }
}
@Test
@@ -232,7 +226,7 @@
modifier = Modifier.testTag(TEST_TAG),
value = 0f,
steps = 5,
- onValueChange = { },
+ onValueChange = {},
increaseIcon = { Icon(StepperDefaults.Increase, "Increase") },
decreaseIcon = {
Icon(
@@ -246,11 +240,11 @@
val unclippedBoundsInRoot = rule.onRoot().getUnclippedBoundsInRoot()
rule.waitForIdle()
- rule.onNodeWithTag(iconTag, true)
+ rule
+ .onNodeWithTag(iconTag, true)
.assertExists()
.assertTopPositionInRootIsEqualTo(
- unclippedBoundsInRoot.height -
- BorderVerticalMargin - DefaultIconHeight
+ unclippedBoundsInRoot.height - BorderVerticalMargin - DefaultIconHeight
)
}
@@ -263,7 +257,7 @@
modifier = Modifier.testTag(TEST_TAG),
value = 0f,
steps = 5,
- onValueChange = { },
+ onValueChange = {},
increaseIcon = {
Icon(
modifier = Modifier.testTag(iconTag),
@@ -275,7 +269,8 @@
) {}
}
rule.waitForIdle()
- rule.onNodeWithTag(iconTag, true)
+ rule
+ .onNodeWithTag(iconTag, true)
.assertExists()
.assertTopPositionInRootIsEqualTo(BorderVerticalMargin)
}
@@ -291,18 +286,17 @@
steps = 5,
increaseIcon = { Icon(StepperDefaults.Increase, "Increase") },
decreaseIcon = { Icon(StepperDefaults.Decrease, "Decrease") },
- onValueChange = { },
+ onValueChange = {},
) {
- Text("Testing", modifier = Modifier
- .testTag(contentTag)
- .fillMaxHeight())
+ Text("Testing", modifier = Modifier.testTag(contentTag).fillMaxHeight())
}
}
val rootHeight = rule.onRoot().getUnclippedBoundsInRoot().height
rule.waitForIdle()
- rule.onNodeWithTag(contentTag, true)
+ rule
+ .onNodeWithTag(contentTag, true)
.assertExists()
.assertTopPositionInRootIsEqualTo(
// Position of the content is a weight(35%) of (top button minus 2 spacers 8dp each)
@@ -322,12 +316,13 @@
steps = 5,
increaseIcon = { Icon(StepperDefaults.Increase, testContentDescription) },
decreaseIcon = { Icon(StepperDefaults.Decrease, "Decrease") },
- onValueChange = { },
+ onValueChange = {},
) {}
}
rule.waitForIdle()
- rule.onNodeWithTag(TEST_TAG, true)
+ rule
+ .onNodeWithTag(TEST_TAG, true)
// 0 is the index of increase button, 1 - decrease button, content is empty
.onChildAt(0)
.onChild()
@@ -345,12 +340,13 @@
steps = 5,
increaseIcon = { Icon(StepperDefaults.Increase, "Increase") },
decreaseIcon = { Icon(StepperDefaults.Decrease, testContentDescription) },
- onValueChange = { },
+ onValueChange = {},
) {}
}
rule.waitForIdle()
- rule.onNodeWithTag(TEST_TAG, true)
+ rule
+ .onNodeWithTag(TEST_TAG, true)
// 0 is the index of increase button, 1 - decrease button, content is empty
.onChildAt(1)
.onChild()
@@ -371,14 +367,15 @@
value = value,
steps = steps,
valueRange = valueRange,
- onValueChange = { },
+ onValueChange = {},
increaseIcon = { Icon(StepperDefaults.Increase, "Increase") },
decreaseIcon = { Icon(StepperDefaults.Decrease, "Decrease") },
) {}
}
rule.waitForIdle()
// Should throw assertion error for assertRangeInfoEquals
- rule.onNodeWithTag(TEST_TAG, true)
+ rule
+ .onNodeWithTag(TEST_TAG, true)
.assertExists()
.assertRangeInfoEquals(ProgressBarRangeInfo(value, valueRange, steps))
}
@@ -394,16 +391,16 @@
value = value,
steps = steps,
valueRange = valueRange,
- onValueChange = { },
+ onValueChange = {},
increaseIcon = { Icon(StepperDefaults.Increase, "Increase") },
decreaseIcon = { Icon(StepperDefaults.Decrease, "Decrease") },
- modifier = Modifier
- .testTag(TEST_TAG)
- .rangeSemantics(value, true, {}, valueRange, steps)
+ modifier =
+ Modifier.testTag(TEST_TAG).rangeSemantics(value, true, {}, valueRange, steps)
) {}
}
rule.waitForIdle()
- rule.onNodeWithTag(TEST_TAG, true)
+ rule
+ .onNodeWithTag(TEST_TAG, true)
.assertExists()
.assertRangeInfoEquals(ProgressBarRangeInfo(value, valueRange, steps))
}
@@ -414,9 +411,7 @@
var actualIconColor = Color.Transparent
rule.setContentWithTheme {
- expectedIconColor = MaterialTheme.colorScheme.primary.copy(
- alpha = DisabledContentAlpha
- )
+ expectedIconColor = MaterialTheme.colorScheme.primary.copy(alpha = DisabledContentAlpha)
Stepper(
value = state.value,
onValueChange = { state.value = it },
@@ -448,8 +443,7 @@
@OptIn(ExperimentalWearMaterial3Api::class)
class IntegerStepperTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
@Test
fun supports_testtag() {
@@ -468,44 +462,49 @@
}
@Test
- fun coerces_value_top_limit() = rule.setNewValueAndCheck(
- progression = 0..10,
- initialValue = 4,
- newValue = 20,
- expectedFinalValue = 10
- )
+ fun coerces_value_top_limit() =
+ rule.setNewValueAndCheck(
+ progression = 0..10,
+ initialValue = 4,
+ newValue = 20,
+ expectedFinalValue = 10
+ )
@Test
- fun coerces_value_lower_limit() = rule.setNewValueAndCheck(
- progression = 0..10,
- initialValue = 4,
- newValue = -20,
- expectedFinalValue = 0
- )
+ fun coerces_value_lower_limit() =
+ rule.setNewValueAndCheck(
+ progression = 0..10,
+ initialValue = 4,
+ newValue = -20,
+ expectedFinalValue = 0
+ )
@Test
- fun coerce_value_exactly() = rule.setNewValueAndCheck(
- progression = IntProgression.fromClosedRange(0, 12, 3),
- initialValue = 0,
- newValue = 3,
- expectedFinalValue = 3
- )
+ fun coerce_value_exactly() =
+ rule.setNewValueAndCheck(
+ progression = IntProgression.fromClosedRange(0, 12, 3),
+ initialValue = 0,
+ newValue = 3,
+ expectedFinalValue = 3
+ )
@Test
- fun coerce_value_to_previous() = rule.setNewValueAndCheck(
- progression = IntProgression.fromClosedRange(0, 12, 3),
- initialValue = 0,
- newValue = 4,
- expectedFinalValue = 3
- )
+ fun coerce_value_to_previous() =
+ rule.setNewValueAndCheck(
+ progression = IntProgression.fromClosedRange(0, 12, 3),
+ initialValue = 0,
+ newValue = 4,
+ expectedFinalValue = 3
+ )
@Test
- fun coerce_value_to_next() = rule.setNewValueAndCheck(
- progression = IntProgression.fromClosedRange(0, 12, 3),
- initialValue = 0,
- newValue = 5,
- expectedFinalValue = 6
- )
+ fun coerce_value_to_next() =
+ rule.setNewValueAndCheck(
+ progression = IntProgression.fromClosedRange(0, 12, 3),
+ initialValue = 0,
+ newValue = 5,
+ expectedFinalValue = 6
+ )
@Test(expected = java.lang.AssertionError::class)
fun does_not_support_stepper_range_semantics_by_default() {
@@ -524,7 +523,8 @@
}
rule.waitForIdle()
// Should throw assertion error for assertRangeInfoEquals
- rule.onNodeWithTag(TEST_TAG, true)
+ rule
+ .onNodeWithTag(TEST_TAG, true)
.assertExists()
.assertRangeInfoEquals(
ProgressBarRangeInfo(
@@ -547,19 +547,21 @@
valueProgression = valueProgression,
increaseIcon = { Icon(StepperDefaults.Increase, "Increase") },
decreaseIcon = { Icon(StepperDefaults.Decrease, "Decrease") },
- modifier = Modifier
- .testTag(TEST_TAG)
- .rangeSemantics(
- value.toFloat(),
- true, {},
- valueProgression.first.toFloat()..valueProgression.last.toFloat(),
- valueProgression.stepsNumber()
- )
+ modifier =
+ Modifier.testTag(TEST_TAG)
+ .rangeSemantics(
+ value.toFloat(),
+ true,
+ {},
+ valueProgression.first.toFloat()..valueProgression.last.toFloat(),
+ valueProgression.stepsNumber()
+ )
) {}
}
rule.waitForIdle()
- rule.onNodeWithTag(TEST_TAG, true)
+ rule
+ .onNodeWithTag(TEST_TAG, true)
.assertExists()
.assertRangeInfoEquals(
ProgressBarRangeInfo(
@@ -608,9 +610,9 @@
steps = steps,
increaseIcon = { Icon(StepperDefaults.Increase, INCREASE) },
decreaseIcon = { Icon(StepperDefaults.Decrease, DECREASE) },
- modifier = Modifier
- .testTag(TEST_TAG)
- .rangeSemantics(state.value, true, onValueChange, valueRange, steps)
+ modifier =
+ Modifier.testTag(TEST_TAG)
+ .rangeSemantics(state.value, true, onValueChange, valueRange, steps)
) {}
}
}
@@ -657,15 +659,15 @@
valueProgression = valueProgression,
increaseIcon = { Icon(StepperDefaults.Increase, "Increase") },
decreaseIcon = { Icon(StepperDefaults.Decrease, "Decrease") },
- modifier = Modifier
- .testTag(TEST_TAG)
- .rangeSemantics(
- state.value.toFloat(),
- true,
- { onValueChange(it.roundToInt()) },
- valueRange,
- steps
- )
+ modifier =
+ Modifier.testTag(TEST_TAG)
+ .rangeSemantics(
+ state.value.toFloat(),
+ true,
+ { onValueChange(it.roundToInt()) },
+ valueRange,
+ steps
+ )
) {}
}
}
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/TextButtonScreenshotTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/TextButtonScreenshotTest.kt
index 6c3a665..9faa545 100644
--- a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/TextButtonScreenshotTest.kt
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/TextButtonScreenshotTest.kt
@@ -51,25 +51,17 @@
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
class TextButtonScreenshotTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
- @get:Rule
- val screenshotRule = AndroidXScreenshotTestRule(SCREENSHOT_GOLDEN_PATH)
+ @get:Rule val screenshotRule = AndroidXScreenshotTestRule(SCREENSHOT_GOLDEN_PATH)
- @get:Rule
- val testName = TestName()
+ @get:Rule val testName = TestName()
@Test
- fun filled_text_button_enabled() = verifyScreenshot {
- sampleFilledTextButton(enabled = true)
- }
+ fun filled_text_button_enabled() = verifyScreenshot { sampleFilledTextButton(enabled = true) }
@Test
- fun filled_text_button_disabled() =
- verifyScreenshot {
- sampleFilledTextButton(enabled = false)
- }
+ fun filled_text_button_disabled() = verifyScreenshot { sampleFilledTextButton(enabled = false) }
@Test
fun filled_tonal_text_button_enabled() = verifyScreenshot {
@@ -77,10 +69,9 @@
}
@Test
- fun filled_tonal_text_button_disabled() =
- verifyScreenshot {
- sampleFilledTonalTextButton(enabled = false)
- }
+ fun filled_tonal_text_button_disabled() = verifyScreenshot {
+ sampleFilledTonalTextButton(enabled = false)
+ }
@Test
fun outlined_text_button_enabled() = verifyScreenshot {
@@ -92,15 +83,9 @@
sampleOutlinedTextButton(enabled = false)
}
- @Test
- fun text_button_enabled() = verifyScreenshot {
- sampleTextButton(enabled = true)
- }
+ @Test fun text_button_enabled() = verifyScreenshot { sampleTextButton(enabled = true) }
- @Test
- fun text_button_disabled() = verifyScreenshot {
- sampleTextButton(enabled = false)
- }
+ @Test fun text_button_disabled() = verifyScreenshot { sampleTextButton(enabled = false) }
@Test
fun text_button_with_offset() = verifyScreenshot {
@@ -146,11 +131,7 @@
@Composable
private fun sampleTextButton(enabled: Boolean, modifier: Modifier = Modifier) {
- TextButton(
- onClick = {},
- enabled = enabled,
- modifier = modifier.testTag(TEST_TAG)
- ) {
+ TextButton(onClick = {}, enabled = enabled, modifier = modifier.testTag(TEST_TAG)) {
Text(text = "ABC")
}
}
@@ -161,15 +142,15 @@
) {
rule.setContentWithTheme {
Box(
- modifier = Modifier
- .fillMaxSize()
- .background(MaterialTheme.colorScheme.background)
+ modifier = Modifier.fillMaxSize().background(MaterialTheme.colorScheme.background)
) {
content()
}
}
- rule.onNodeWithTag(TEST_TAG).captureToImage()
+ rule
+ .onNodeWithTag(TEST_TAG)
+ .captureToImage()
.assertAgainstGolden(screenshotRule, methodName)
}
}
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/TextButtonTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/TextButtonTest.kt
index ff11878..be045e9 100644
--- a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/TextButtonTest.kt
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/TextButtonTest.kt
@@ -55,18 +55,12 @@
import org.junit.Test
class TextButtonTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
@Test
fun supports_testtag() {
rule.setContentWithTheme {
- TextButton(
- modifier = Modifier.testTag(TEST_TAG),
- onClick = {}
- ) {
- Text("Test")
- }
+ TextButton(modifier = Modifier.testTag(TEST_TAG), onClick = {}) { Text("Test") }
}
rule.onNodeWithTag(TEST_TAG).assertExists()
@@ -103,11 +97,7 @@
@Test
fun has_click_action_when_enabled() {
rule.setContentWithTheme {
- TextButton(
- onClick = {},
- enabled = true,
- modifier = Modifier.testTag(TEST_TAG)
- ) {
+ TextButton(onClick = {}, enabled = true, modifier = Modifier.testTag(TEST_TAG)) {
Text("Test")
}
}
@@ -118,11 +108,7 @@
@Test
fun has_click_action_when_disabled() {
rule.setContentWithTheme {
- TextButton(
- onClick = {},
- enabled = false,
- modifier = Modifier.testTag(TEST_TAG)
- ) {
+ TextButton(onClick = {}, enabled = false, modifier = Modifier.testTag(TEST_TAG)) {
Text("Test")
}
}
@@ -133,11 +119,7 @@
@Test
fun is_correctly_enabled() {
rule.setContentWithTheme {
- TextButton(
- onClick = {},
- enabled = true,
- modifier = Modifier.testTag(TEST_TAG)
- ) {
+ TextButton(onClick = {}, enabled = true, modifier = Modifier.testTag(TEST_TAG)) {
Text("Test")
}
}
@@ -148,11 +130,7 @@
@Test
fun is_correctly_disabled() {
rule.setContentWithTheme {
- TextButton(
- onClick = {},
- enabled = false,
- modifier = Modifier.testTag(TEST_TAG)
- ) {
+ TextButton(onClick = {}, enabled = false, modifier = Modifier.testTag(TEST_TAG)) {
Text("Test")
}
}
@@ -176,9 +154,7 @@
rule.onNodeWithTag(TEST_TAG).performClick()
- rule.runOnIdle {
- assertEquals(true, clicked)
- }
+ rule.runOnIdle { assertEquals(true, clicked) }
}
@Test
@@ -197,29 +173,18 @@
rule.onNodeWithTag(TEST_TAG).performClick()
- rule.runOnIdle {
- assertEquals(false, clicked)
- }
+ rule.runOnIdle { assertEquals(false, clicked) }
}
@Test
fun has_role_button() {
rule.setContentWithTheme {
- TextButton(
- onClick = {},
- modifier = Modifier.testTag(TEST_TAG)
- ) {
- Text("Test")
- }
+ TextButton(onClick = {}, modifier = Modifier.testTag(TEST_TAG)) { Text("Test") }
}
- rule.onNodeWithTag(TEST_TAG)
- .assert(
- SemanticsMatcher.expectValue(
- SemanticsProperties.Role,
- Role.Button
- )
- )
+ rule
+ .onNodeWithTag(TEST_TAG)
+ .assert(SemanticsMatcher.expectValue(SemanticsProperties.Role, Role.Button))
}
@Test
@@ -229,20 +194,15 @@
rule.setContentWithTheme {
TextButton(
onClick = {},
- modifier = Modifier
- .testTag(TEST_TAG)
- .semantics { role = overrideRole }
+ modifier = Modifier.testTag(TEST_TAG).semantics { role = overrideRole }
) {
Text("Test")
}
}
- rule.onNodeWithTag(TEST_TAG).assert(
- SemanticsMatcher.expectValue(
- SemanticsProperties.Role,
- overrideRole
- )
- )
+ rule
+ .onNodeWithTag(TEST_TAG)
+ .assert(SemanticsMatcher.expectValue(SemanticsProperties.Role, overrideRole))
}
@Test
@@ -265,10 +225,7 @@
@Test
fun gives_default_button_correct_tap_size() {
rule.verifyTapSize(DefaultButtonSize) { modifier ->
- TextButton(
- onClick = {},
- modifier = modifier.touchTargetAwareSize(DefaultButtonSize)
- ) {
+ TextButton(onClick = {}, modifier = modifier.touchTargetAwareSize(DefaultButtonSize)) {
Text("ABC")
}
}
@@ -277,10 +234,7 @@
@Test
fun gives_large_button_correct_tap_size() {
rule.verifyTapSize(LargeButtonSize) { modifier ->
- TextButton(
- onClick = {},
- modifier = modifier.touchTargetAwareSize(LargeButtonSize)
- ) {
+ TextButton(onClick = {}, modifier = modifier.touchTargetAwareSize(LargeButtonSize)) {
Text("Large")
}
}
@@ -289,10 +243,7 @@
@Test
fun gives_small_button_correct_tap_size() {
rule.verifyTapSize(SmallButtonSize) { modifier ->
- TextButton(
- onClick = {},
- modifier = modifier.touchTargetAwareSize(SmallButtonSize)
- ) {
+ TextButton(onClick = {}, modifier = modifier.touchTargetAwareSize(SmallButtonSize)) {
Text("abc")
}
}
@@ -305,10 +256,7 @@
expectedShape = CircleShape,
colors = { TextButtonDefaults.textButtonColors() }
) { modifier ->
- TextButton(
- onClick = {},
- modifier = modifier
- ) {
+ TextButton(onClick = {}, modifier = modifier) {
// omit content to allow us to validate the shape by pixel checking.
}
}
@@ -319,15 +267,9 @@
fun allows_custom_shape_override() {
val shape = CutCornerShape(4.dp)
- rule.isShape(
- expectedShape = shape,
- colors = { TextButtonDefaults.textButtonColors() }
- ) { modifier ->
- TextButton(
- onClick = {},
- modifier = modifier,
- shape = shape
- ) {
+ rule.isShape(expectedShape = shape, colors = { TextButtonDefaults.textButtonColors() }) {
+ modifier ->
+ TextButton(onClick = {}, modifier = modifier, shape = shape) {
// omit content to allow us to validate the shape by pixel checking.
}
}
@@ -351,9 +293,9 @@
status = Status.Disabled,
colors = { TextButtonDefaults.textButtonColors() },
expectedContainerColor = { Color.Transparent },
- expectedContentColor = { MaterialTheme.colorScheme.onSurface.copy(
- alpha = DisabledContentAlpha
- ) }
+ expectedContentColor = {
+ MaterialTheme.colorScheme.onSurface.copy(alpha = DisabledContentAlpha)
+ }
)
}
@@ -374,12 +316,12 @@
rule.verifyTextButtonColors(
status = Status.Disabled,
colors = { TextButtonDefaults.filledTextButtonColors() },
- expectedContainerColor = { MaterialTheme.colorScheme.onSurface.copy(
- alpha = DisabledContainerAlpha
- ) },
- expectedContentColor = { MaterialTheme.colorScheme.onSurface.copy(
- alpha = DisabledContentAlpha
- ) }
+ expectedContainerColor = {
+ MaterialTheme.colorScheme.onSurface.copy(alpha = DisabledContainerAlpha)
+ },
+ expectedContentColor = {
+ MaterialTheme.colorScheme.onSurface.copy(alpha = DisabledContentAlpha)
+ }
)
}
@@ -400,12 +342,12 @@
rule.verifyTextButtonColors(
status = Status.Disabled,
colors = { TextButtonDefaults.filledTonalTextButtonColors() },
- expectedContainerColor = { MaterialTheme.colorScheme.onSurface.copy(
- alpha = DisabledContainerAlpha
- ) },
- expectedContentColor = { MaterialTheme.colorScheme.onSurface.copy(
- alpha = DisabledContentAlpha
- ) }
+ expectedContainerColor = {
+ MaterialTheme.colorScheme.onSurface.copy(alpha = DisabledContainerAlpha)
+ },
+ expectedContentColor = {
+ MaterialTheme.colorScheme.onSurface.copy(alpha = DisabledContentAlpha)
+ }
)
}
@@ -427,9 +369,9 @@
status = Status.Disabled,
colors = { TextButtonDefaults.outlinedTextButtonColors() },
expectedContainerColor = { Color.Transparent },
- expectedContentColor = { MaterialTheme.colorScheme.onSurface.copy(
- alpha = DisabledContentAlpha
- ) }
+ expectedContentColor = {
+ MaterialTheme.colorScheme.onSurface.copy(alpha = DisabledContentAlpha)
+ }
)
}
@@ -466,7 +408,6 @@
enabled = status.enabled(),
colors = TextButtonDefaults.outlinedTextButtonColors(),
border = ButtonDefaults.outlinedButtonBorder(enabled = status.enabled())
-
) {}
}
)
@@ -483,11 +424,12 @@
onClick = {},
modifier = modifier,
enabled = status.enabled(),
- border = ButtonDefaults.outlinedButtonBorder(
- enabled = status.enabled(),
- borderColor = Color.Green,
- disabledBorderColor = Color.Red
- )
+ border =
+ ButtonDefaults.outlinedButtonBorder(
+ enabled = status.enabled(),
+ borderColor = Color.Green,
+ disabledBorderColor = Color.Red
+ )
) {}
}
)
@@ -538,11 +480,7 @@
if (buttonColor == Color.Transparent) {
buttonColor = background
}
- content(
- Modifier
- .testTag(TEST_TAG)
- .padding(padding)
- )
+ content(Modifier.testTag(TEST_TAG).padding(padding))
}
}
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/TextTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/TextTest.kt
index 1323d67..8c9e808 100644
--- a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/TextTest.kt
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/TextTest.kt
@@ -43,20 +43,20 @@
@SmallTest
@RunWith(AndroidJUnit4::class)
class TextTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
- private val ExpectedTextStyle = TextStyle(
- color = Color.Red,
- fontSize = 32.sp,
- fontStyle = FontStyle.Italic,
- fontWeight = FontWeight.Normal,
- fontFamily = FontFamily.Default,
- letterSpacing = 1.sp,
- textDecoration = TextDecoration.Underline,
- textAlign = TextAlign.End,
- lineHeight = 10.sp,
- )
+ private val ExpectedTextStyle =
+ TextStyle(
+ color = Color.Red,
+ fontSize = 32.sp,
+ fontStyle = FontStyle.Italic,
+ fontWeight = FontWeight.Normal,
+ fontFamily = FontFamily.Default,
+ letterSpacing = 1.sp,
+ textDecoration = TextDecoration.Underline,
+ textAlign = TextAlign.End,
+ lineHeight = 10.sp,
+ )
private val TestText = "TestText"
@@ -71,13 +71,11 @@
}
}
- assertThat(
- localTextStyle?.platformStyle?.paragraphStyle?.includeFontPadding
- ).isEqualTo(false)
+ assertThat(localTextStyle?.platformStyle?.paragraphStyle?.includeFontPadding)
+ .isEqualTo(false)
- assertThat(
- displayMediumTextStyle?.platformStyle?.paragraphStyle?.includeFontPadding
- ).isEqualTo(false)
+ assertThat(displayMediumTextStyle?.platformStyle?.paragraphStyle?.includeFontPadding)
+ .isEqualTo(false)
}
@Test
@@ -92,47 +90,30 @@
"Lorem ipsum",
minLines = 1,
maxLines = 3,
- onTextLayout = {
- size1 = it.size.height
- }
+ onTextLayout = { size1 = it.size.height }
)
Text(
"Lorem ipsum",
minLines = 2,
maxLines = 3,
- onTextLayout = {
- size2 = it.size.height
- }
+ onTextLayout = { size2 = it.size.height }
)
}
}
}
- rule.runOnIdle {
- assertThat(size2).isGreaterThan(size1)
- }
+ rule.runOnIdle { assertThat(size2).isGreaterThan(size1) }
}
@Test(expected = IllegalArgumentException::class)
fun validateMinLinesGreaterThanZero() {
- rule.setContent {
- Text(
- TestText,
- minLines = 0
- )
- }
+ rule.setContent { Text(TestText, minLines = 0) }
}
@Test(expected = IllegalArgumentException::class)
fun validateMaxLinesGreaterThanMinLines() {
- rule.setContent {
- Text(
- TestText,
- minLines = 2,
- maxLines = 1
- )
- }
+ rule.setContent { Text(TestText, minLines = 2, maxLines = 1) }
}
@Test
@@ -147,18 +128,14 @@
Text(
TestText,
color = expectedColor,
- onTextLayout = {
- textColor = it.layoutInput.style.color
- }
+ onTextLayout = { textColor = it.layoutInput.style.color }
)
}
}
}
}
- rule.runOnIdle {
- assertThat(textColor).isEqualTo(expectedColor)
- }
+ rule.runOnIdle { assertThat(textColor).isEqualTo(expectedColor) }
}
@Test
@@ -169,20 +146,13 @@
CompositionLocalProvider(LocalContentColor provides Color.Blue) {
ProvideTextStyle(ExpectedTextStyle) {
Box(Modifier.background(Color.White)) {
- Text(
- TestText,
- onTextLayout = {
- textColor = it.layoutInput.style.color
- }
- )
+ Text(TestText, onTextLayout = { textColor = it.layoutInput.style.color })
}
}
}
}
- rule.runOnIdle {
- assertThat(textColor).isEqualTo(ExpectedTextStyle.color)
- }
+ rule.runOnIdle { assertThat(textColor).isEqualTo(ExpectedTextStyle.color) }
}
@Test
@@ -192,19 +162,12 @@
rule.setContent {
CompositionLocalProvider(LocalContentColor provides Color.Blue) {
Box(Modifier.background(Color.White)) {
- Text(
- TestText,
- onTextLayout = {
- textColor = it.layoutInput.style.color
- }
- )
+ Text(TestText, onTextLayout = { textColor = it.layoutInput.style.color })
}
}
}
- rule.runOnIdle {
- assertThat(textColor).isEqualTo(Color.Blue)
- }
+ rule.runOnIdle { assertThat(textColor).isEqualTo(Color.Blue) }
}
@Test
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/TextToggleButtonScreenshotTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/TextToggleButtonScreenshotTest.kt
index 0748512..fb4421f 100644
--- a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/TextToggleButtonScreenshotTest.kt
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/TextToggleButtonScreenshotTest.kt
@@ -36,49 +36,51 @@
@RunWith(AndroidJUnit4::class)
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
class TextToggleButtonScreenshotTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
- @get:Rule
- val screenshotRule = AndroidXScreenshotTestRule(SCREENSHOT_GOLDEN_PATH)
+ @get:Rule val screenshotRule = AndroidXScreenshotTestRule(SCREENSHOT_GOLDEN_PATH)
- @get:Rule
- val testName = TestName()
+ @get:Rule val testName = TestName()
@Test
- fun textToggleButtonEnabledAndChecked() = rule.verifyScreenshot(
- methodName = testName.methodName,
- screenshotRule = screenshotRule,
- content = { sampleTextToggleButton() }
- )
+ fun textToggleButtonEnabledAndChecked() =
+ rule.verifyScreenshot(
+ methodName = testName.methodName,
+ screenshotRule = screenshotRule,
+ content = { sampleTextToggleButton() }
+ )
@Test
- fun textToggleButtonEnabledAndUnchecked() = rule.verifyScreenshot(
- methodName = testName.methodName,
- screenshotRule = screenshotRule,
- content = { sampleTextToggleButton(checked = false) }
- )
+ fun textToggleButtonEnabledAndUnchecked() =
+ rule.verifyScreenshot(
+ methodName = testName.methodName,
+ screenshotRule = screenshotRule,
+ content = { sampleTextToggleButton(checked = false) }
+ )
@Test
- fun textToggleButtonDisabledAndChecked() = rule.verifyScreenshot(
- methodName = testName.methodName,
- screenshotRule = screenshotRule,
- content = { sampleTextToggleButton(enabled = false) }
- )
+ fun textToggleButtonDisabledAndChecked() =
+ rule.verifyScreenshot(
+ methodName = testName.methodName,
+ screenshotRule = screenshotRule,
+ content = { sampleTextToggleButton(enabled = false) }
+ )
@Test
- fun textToggleButtonDisabledAndUnchecked() = rule.verifyScreenshot(
- methodName = testName.methodName,
- screenshotRule = screenshotRule,
- content = { sampleTextToggleButton(enabled = false, checked = false) }
- )
+ fun textToggleButtonDisabledAndUnchecked() =
+ rule.verifyScreenshot(
+ methodName = testName.methodName,
+ screenshotRule = screenshotRule,
+ content = { sampleTextToggleButton(enabled = false, checked = false) }
+ )
@Test
- fun textToggleButtonWithOffset() = rule.verifyScreenshot(
- methodName = testName.methodName,
- screenshotRule = screenshotRule,
- content = { sampleTextToggleButton(modifier = Modifier.offset(10.dp)) }
- )
+ fun textToggleButtonWithOffset() =
+ rule.verifyScreenshot(
+ methodName = testName.methodName,
+ screenshotRule = screenshotRule,
+ content = { sampleTextToggleButton(modifier = Modifier.offset(10.dp)) }
+ )
@Composable
private fun sampleTextToggleButton(
@@ -90,7 +92,8 @@
checked = checked,
onCheckedChange = {},
enabled = enabled,
- modifier = modifier.testTag(TEST_TAG)) {
+ modifier = modifier.testTag(TEST_TAG)
+ ) {
Text(text = if (checked) "ON" else "OFF")
}
}
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/TextToggleButtonTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/TextToggleButtonTest.kt
index 60c1dc7..3b9584c 100644
--- a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/TextToggleButtonTest.kt
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/TextToggleButtonTest.kt
@@ -64,8 +64,7 @@
class TextToggleButtonTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
@Test
fun supports_testTag() {
@@ -205,10 +204,7 @@
}
rule.waitForIdle()
- rule.onNodeWithTag(TEST_TAG)
- .assertIsOff()
- .performClick()
- .assertIsOn()
+ rule.onNodeWithTag(TEST_TAG).assertIsOff().performClick().assertIsOn()
}
@Test
@@ -224,10 +220,7 @@
}
rule.waitForIdle()
- rule.onNodeWithTag(TEST_TAG)
- .assertIsOn()
- .performClick()
- .assertIsOff()
+ rule.onNodeWithTag(TEST_TAG).assertIsOn().performClick().assertIsOff()
}
@Test
@@ -244,10 +237,7 @@
}
rule.waitForIdle()
- rule.onNodeWithTag(TEST_TAG)
- .assertIsOff()
- .performClick()
- .assertIsOff()
+ rule.onNodeWithTag(TEST_TAG).assertIsOff().performClick().assertIsOff()
}
@RequiresApi(Build.VERSION_CODES.O)
@@ -261,8 +251,8 @@
TextToggleButton(
enabled = true,
checked = true,
- onCheckedChange = { },
- content = { },
+ onCheckedChange = {},
+ content = {},
modifier = Modifier.testTag(TEST_TAG)
)
}
@@ -278,8 +268,8 @@
TextToggleButton(
enabled = true,
checked = true,
- onCheckedChange = { },
- content = { },
+ onCheckedChange = {},
+ content = {},
modifier = Modifier.testTag(TEST_TAG)
)
}
@@ -296,8 +286,8 @@
enabled = true,
checked = true,
shape = RectangleShape,
- onCheckedChange = { },
- content = { },
+ onCheckedChange = {},
+ content = {},
modifier = Modifier.testTag(TEST_TAG)
)
}
@@ -308,11 +298,11 @@
TextToggleButton(
enabled = true,
checked = true,
- onCheckedChange = { },
- content = { },
- modifier = Modifier
- .testTag(TEST_TAG)
- .touchTargetAwareSize(TextButtonDefaults.DefaultButtonSize)
+ onCheckedChange = {},
+ content = {},
+ modifier =
+ Modifier.testTag(TEST_TAG)
+ .touchTargetAwareSize(TextButtonDefaults.DefaultButtonSize)
)
}
@@ -322,11 +312,11 @@
TextToggleButton(
enabled = true,
checked = true,
- onCheckedChange = { },
- content = { },
- modifier = Modifier
- .testTag(TEST_TAG)
- .touchTargetAwareSize(TextButtonDefaults.SmallButtonSize)
+ onCheckedChange = {},
+ content = {},
+ modifier =
+ Modifier.testTag(TEST_TAG)
+ .touchTargetAwareSize(TextButtonDefaults.SmallButtonSize)
)
}
@@ -336,11 +326,11 @@
TextToggleButton(
enabled = true,
checked = true,
- onCheckedChange = { },
- content = { },
- modifier = Modifier
- .testTag(TEST_TAG)
- .touchTargetAwareSize(TextButtonDefaults.LargeButtonSize)
+ onCheckedChange = {},
+ content = {},
+ modifier =
+ Modifier.testTag(TEST_TAG)
+ .touchTargetAwareSize(TextButtonDefaults.LargeButtonSize)
)
}
@@ -350,11 +340,11 @@
TextToggleButton(
enabled = true,
checked = true,
- onCheckedChange = { },
- content = { },
- modifier = Modifier
- .testTag(TEST_TAG)
- .touchTargetAwareSize(TextButtonDefaults.DefaultButtonSize)
+ onCheckedChange = {},
+ content = {},
+ modifier =
+ Modifier.testTag(TEST_TAG)
+ .touchTargetAwareSize(TextButtonDefaults.DefaultButtonSize)
)
}
@@ -364,11 +354,11 @@
TextToggleButton(
enabled = true,
checked = true,
- onCheckedChange = { },
- content = { },
- modifier = Modifier
- .testTag(TEST_TAG)
- .touchTargetAwareSize(TextButtonDefaults.SmallButtonSize)
+ onCheckedChange = {},
+ content = {},
+ modifier =
+ Modifier.testTag(TEST_TAG)
+ .touchTargetAwareSize(TextButtonDefaults.SmallButtonSize)
)
}
@@ -378,11 +368,11 @@
TextToggleButton(
enabled = true,
checked = true,
- onCheckedChange = { },
- content = { },
- modifier = Modifier
- .testTag(TEST_TAG)
- .touchTargetAwareSize(TextButtonDefaults.LargeButtonSize)
+ onCheckedChange = {},
+ content = {},
+ modifier =
+ Modifier.testTag(TEST_TAG)
+ .touchTargetAwareSize(TextButtonDefaults.LargeButtonSize)
)
}
@@ -416,9 +406,7 @@
checked = false,
colors = { TextButtonDefaults.textToggleButtonColors() },
containerColor = {
- MaterialTheme.colorScheme.onSurface.toDisabledColor(
- DisabledContainerAlpha
- )
+ MaterialTheme.colorScheme.onSurface.toDisabledColor(DisabledContainerAlpha)
},
contentColor = { MaterialTheme.colorScheme.onSurface.toDisabledColor() }
)
@@ -431,9 +419,7 @@
checked = true,
colors = { TextButtonDefaults.textToggleButtonColors() },
containerColor = {
- MaterialTheme.colorScheme.onSurface.toDisabledColor(
- DisabledContainerAlpha
- )
+ MaterialTheme.colorScheme.onSurface.toDisabledColor(DisabledContainerAlpha)
},
contentColor = { MaterialTheme.colorScheme.onSurface.toDisabledColor() },
)
@@ -447,9 +433,7 @@
status = Status.Enabled,
checked = true,
colors = {
- TextButtonDefaults.textToggleButtonColors(
- checkedContainerColor = override
- )
+ TextButtonDefaults.textToggleButtonColors(checkedContainerColor = override)
},
containerColor = { override },
contentColor = { MaterialTheme.colorScheme.onPrimary }
@@ -464,11 +448,7 @@
rule.verifyTextToggleButtonColors(
status = Status.Enabled,
checked = true,
- colors = {
- TextButtonDefaults.textToggleButtonColors(
- checkedContentColor = override
- )
- },
+ colors = { TextButtonDefaults.textToggleButtonColors(checkedContentColor = override) },
containerColor = { MaterialTheme.colorScheme.primary },
contentColor = { override }
)
@@ -483,9 +463,7 @@
status = Status.Enabled,
checked = false,
colors = {
- TextButtonDefaults.textToggleButtonColors(
- uncheckedContainerColor = override
- )
+ TextButtonDefaults.textToggleButtonColors(uncheckedContainerColor = override)
},
containerColor = { override },
contentColor = { MaterialTheme.colorScheme.onSurfaceVariant }
@@ -501,9 +479,7 @@
status = Status.Enabled,
checked = false,
colors = {
- TextButtonDefaults.textToggleButtonColors(
- uncheckedContentColor = override
- )
+ TextButtonDefaults.textToggleButtonColors(uncheckedContentColor = override)
},
containerColor = { MaterialTheme.colorScheme.surfaceContainer },
contentColor = { override }
@@ -519,9 +495,7 @@
status = Status.Disabled,
checked = true,
colors = {
- TextButtonDefaults.textToggleButtonColors(
- disabledCheckedContainerColor = override
- )
+ TextButtonDefaults.textToggleButtonColors(disabledCheckedContainerColor = override)
},
containerColor = { override },
contentColor = { MaterialTheme.colorScheme.onSurface.toDisabledColor() }
@@ -602,12 +576,9 @@
)
}
- rule.onNodeWithTag(TEST_TAG).assert(
- SemanticsMatcher.expectValue(
- SemanticsProperties.Role,
- Role.Checkbox
- )
- )
+ rule
+ .onNodeWithTag(TEST_TAG)
+ .assert(SemanticsMatcher.expectValue(SemanticsProperties.Role, Role.Checkbox))
}
@Test
@@ -620,26 +591,20 @@
onCheckedChange = {},
enabled = true,
content = { Text("ABC") },
- modifier = Modifier
- .testTag(TEST_TAG)
- .semantics { role = overrideRole }
+ modifier = Modifier.testTag(TEST_TAG).semantics { role = overrideRole }
)
}
- rule.onNodeWithTag(TEST_TAG).assert(
- SemanticsMatcher.expectValue(
- SemanticsProperties.Role,
- overrideRole
- )
- )
+ rule
+ .onNodeWithTag(TEST_TAG)
+ .assert(SemanticsMatcher.expectValue(SemanticsProperties.Role, overrideRole))
}
@Composable
private fun shapeColor(): Color {
- return TextButtonDefaults.textToggleButtonColors().containerColor(
- enabled = true,
- checked = true
- ).value
+ return TextButtonDefaults.textToggleButtonColors()
+ .containerColor(enabled = true, checked = true)
+ .value
}
@RequiresApi(Build.VERSION_CODES.O)
@@ -656,7 +621,7 @@
content = {
var actualContentColor = Color.Transparent
TextToggleButton(
- onCheckedChange = { },
+ onCheckedChange = {},
enabled = status.enabled(),
checked = checked,
colors = colors(),
@@ -682,13 +647,7 @@
setContentWithTheme {
shapeColor = shapeColorComposable.invoke()
CompositionLocalProvider(LocalLayoutDirection provides layoutDirection) {
- Box(
- Modifier
- .padding(padding)
- .background(backgroundColor)
- ) {
- content()
- }
+ Box(Modifier.padding(padding).background(backgroundColor)) { content() }
}
}
@@ -720,27 +679,19 @@
finalExpectedContainerColor =
expectedContainerColor().compositeOver(testBackgroundColor)
finalExpectedContent = expectedContentColor()
- Box(
- Modifier
- .fillMaxSize()
- .background(testBackgroundColor)
- ) {
+ Box(Modifier.fillMaxSize().background(testBackgroundColor)) {
actualContentColor = content()
}
}
Assert.assertEquals(finalExpectedContent, actualContentColor)
- onNodeWithTag(TEST_TAG)
- .captureToImage()
- .assertContainsColor(finalExpectedContainerColor)
+ onNodeWithTag(TEST_TAG).captureToImage().assertContainsColor(finalExpectedContainerColor)
}
private fun ComposeContentTestRule.verifyActualSize(
expectedSize: Dp,
content: @Composable (modifier: Modifier) -> Unit
) {
- setContentWithTheme {
- content(Modifier.testTag(TEST_TAG))
- }
+ setContentWithTheme { content(Modifier.testTag(TEST_TAG)) }
waitForIdle()
onNodeWithTag(TEST_TAG)
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/TimeTextScreenshotTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/TimeTextScreenshotTest.kt
index 8b2b3f1..16065ea 100644
--- a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/TimeTextScreenshotTest.kt
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/TimeTextScreenshotTest.kt
@@ -46,14 +46,11 @@
@RunWith(AndroidJUnit4::class)
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
class TimeTextScreenshotTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
- @get:Rule
- val screenshotRule = AndroidXScreenshotTestRule(SCREENSHOT_GOLDEN_PATH)
+ @get:Rule val screenshotRule = AndroidXScreenshotTestRule(SCREENSHOT_GOLDEN_PATH)
- @get:Rule
- val testName = TestName()
+ @get:Rule val testName = TestName()
@Test
fun time_text_with_clock_only_on_round_device() = verifyScreenshot {
@@ -65,13 +62,14 @@
}
@Test
- fun time_text_with_clock_only_on_non_round_device() = verifyScreenshot(false) {
- TimeText(
- modifier = Modifier.testTag(TEST_TAG),
- ) {
- time()
+ fun time_text_with_clock_only_on_non_round_device() =
+ verifyScreenshot(false) {
+ TimeText(
+ modifier = Modifier.testTag(TEST_TAG),
+ ) {
+ time()
+ }
}
- }
@Test
fun time_text_with_status_on_round_device() = verifyScreenshot {
@@ -85,15 +83,16 @@
}
@Test
- fun time_text_with_status_on_non_round_device() = verifyScreenshot(false) {
- TimeText(
- modifier = Modifier.testTag(TEST_TAG),
- ) {
- text("ETA 12:48")
- separator()
- time()
+ fun time_text_with_status_on_non_round_device() =
+ verifyScreenshot(false) {
+ TimeText(
+ modifier = Modifier.testTag(TEST_TAG),
+ ) {
+ text("ETA 12:48")
+ separator()
+ time()
+ }
}
- }
@Test
fun time_text_with_icon_on_round_device() = verifyScreenshot {
@@ -113,21 +112,22 @@
}
@Test
- fun time_text_with_icon_on_non_round_device() = verifyScreenshot(false) {
- TimeText(
- modifier = Modifier.testTag(TEST_TAG),
- ) {
- time()
- separator()
- composable {
- Icon(
- imageVector = Icons.Filled.Favorite,
- contentDescription = "Favorite",
- modifier = Modifier.size(13.dp)
- )
+ fun time_text_with_icon_on_non_round_device() =
+ verifyScreenshot(false) {
+ TimeText(
+ modifier = Modifier.testTag(TEST_TAG),
+ ) {
+ time()
+ separator()
+ composable {
+ Icon(
+ imageVector = Icons.Filled.Favorite,
+ contentDescription = "Favorite",
+ modifier = Modifier.size(13.dp)
+ )
+ }
}
}
- }
@Test
fun time_text_with_custom_colors_on_round_device() = verifyScreenshot {
@@ -148,27 +148,25 @@
}
@Test
- fun time_text_with_custom_colors_on_non_round_device() = verifyScreenshot(false) {
- val customStyle = TimeTextDefaults.timeTextStyle(color = Color.Red)
- val timeTextStyle = TimeTextDefaults.timeTextStyle(color = Color.Cyan)
- val separatorStyle = TimeTextDefaults.timeTextStyle(color = Color.Yellow)
- TimeText(
- contentColor = Color.Green,
- timeTextStyle = timeTextStyle,
- modifier = Modifier.testTag(TEST_TAG),
- ) {
- text("ETA", customStyle)
- composable { Spacer(modifier = Modifier.size(4.dp)) }
- text("12:48")
- separator(separatorStyle)
- time()
+ fun time_text_with_custom_colors_on_non_round_device() =
+ verifyScreenshot(false) {
+ val customStyle = TimeTextDefaults.timeTextStyle(color = Color.Red)
+ val timeTextStyle = TimeTextDefaults.timeTextStyle(color = Color.Cyan)
+ val separatorStyle = TimeTextDefaults.timeTextStyle(color = Color.Yellow)
+ TimeText(
+ contentColor = Color.Green,
+ timeTextStyle = timeTextStyle,
+ modifier = Modifier.testTag(TEST_TAG),
+ ) {
+ text("ETA", customStyle)
+ composable { Spacer(modifier = Modifier.size(4.dp)) }
+ text("12:48")
+ separator(separatorStyle)
+ time()
+ }
}
- }
- private fun verifyScreenshot(
- isDeviceRound: Boolean = true,
- content: @Composable () -> Unit
- ) {
+ private fun verifyScreenshot(isDeviceRound: Boolean = true, content: @Composable () -> Unit) {
rule.verifyScreenshot(
methodName = testName.methodName,
screenshotRule = screenshotRule,
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/TimeTextTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/TimeTextTest.kt
index 8a71524..4594542 100644
--- a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/TimeTextTest.kt
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/TimeTextTest.kt
@@ -43,18 +43,11 @@
import org.junit.Test
class TimeTextTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
@Test
fun supports_testtag() {
- rule.setContentWithTheme {
- TimeText(
- modifier = Modifier.testTag(TEST_TAG)
- ) {
- time()
- }
- }
+ rule.setContentWithTheme { TimeText(modifier = Modifier.testTag(TEST_TAG)) { time() } }
rule.onNodeWithTag(TEST_TAG).assertExists()
}
@@ -64,15 +57,13 @@
val timeState = mutableStateOf("Unchanged")
rule.setContentWithTheme {
- DeviceConfigurationOverride(
- DeviceConfigurationOverride.RoundScreen(false)
- ) {
+ DeviceConfigurationOverride(DeviceConfigurationOverride.RoundScreen(false)) {
TimeText(
modifier = Modifier.testTag(TEST_TAG),
- timeSource = object : TimeSource {
- @Composable
- override fun currentTime(): String = timeState.value
- },
+ timeSource =
+ object : TimeSource {
+ @Composable override fun currentTime(): String = timeState.value
+ },
) {
time()
}
@@ -87,15 +78,13 @@
val timeState = mutableStateOf("Unchanged")
rule.setContentWithTheme {
- DeviceConfigurationOverride(
- DeviceConfigurationOverride.RoundScreen(true)
- ) {
+ DeviceConfigurationOverride(DeviceConfigurationOverride.RoundScreen(true)) {
TimeText(
modifier = Modifier.testTag(TEST_TAG),
- timeSource = object : TimeSource {
- @Composable
- override fun currentTime(): String = timeState.value
- },
+ timeSource =
+ object : TimeSource {
+ @Composable override fun currentTime(): String = timeState.value
+ },
) {
time()
}
@@ -111,9 +100,7 @@
val statusText = "Status"
rule.setContentWithTheme {
- DeviceConfigurationOverride(
- DeviceConfigurationOverride.RoundScreen(false)
- ) {
+ DeviceConfigurationOverride(DeviceConfigurationOverride.RoundScreen(false)) {
TimeText {
text(statusText)
separator()
@@ -130,9 +117,7 @@
val statusText = "Status"
rule.setContentWithTheme {
- DeviceConfigurationOverride(
- DeviceConfigurationOverride.RoundScreen(true)
- ) {
+ DeviceConfigurationOverride(DeviceConfigurationOverride.RoundScreen(true)) {
TimeText {
text(statusText)
separator()
@@ -150,9 +135,7 @@
val separatorText = "·"
rule.setContentWithTheme {
- DeviceConfigurationOverride(
- DeviceConfigurationOverride.RoundScreen(false)
- ) {
+ DeviceConfigurationOverride(DeviceConfigurationOverride.RoundScreen(false)) {
TimeText {
text(statusText)
separator()
@@ -170,9 +153,7 @@
val separatorText = "·"
rule.setContentWithTheme {
- DeviceConfigurationOverride(
- DeviceConfigurationOverride.RoundScreen(true)
- ) {
+ DeviceConfigurationOverride(DeviceConfigurationOverride.RoundScreen(true)) {
TimeText {
text(statusText)
separator()
@@ -187,9 +168,7 @@
@Test
fun checks_composable_displayed_on_non_round_device() {
rule.setContentWithTheme {
- DeviceConfigurationOverride(
- DeviceConfigurationOverride.RoundScreen(false)
- ) {
+ DeviceConfigurationOverride(DeviceConfigurationOverride.RoundScreen(false)) {
TimeText {
time()
separator()
@@ -209,9 +188,7 @@
@Test
fun checks_composable_displayed_on_round_device() {
rule.setContentWithTheme {
- DeviceConfigurationOverride(
- DeviceConfigurationOverride.RoundScreen(true)
- ) {
+ DeviceConfigurationOverride(DeviceConfigurationOverride.RoundScreen(true)) {
TimeText {
time()
separator()
@@ -232,20 +209,15 @@
fun changes_timeTextStyle_on_non_round_device() {
val timeText = "testTime"
- val testTextStyle = TextStyle(
- color = Color.Green,
- background = Color.Black,
- fontSize = 20.sp
- )
+ val testTextStyle =
+ TextStyle(color = Color.Green, background = Color.Black, fontSize = 20.sp)
rule.setContentWithTheme {
- DeviceConfigurationOverride(
- DeviceConfigurationOverride.RoundScreen(false)
- ) {
+ DeviceConfigurationOverride(DeviceConfigurationOverride.RoundScreen(false)) {
TimeText(
- timeSource = object : TimeSource {
- @Composable
- override fun currentTime(): String = timeText
- },
+ timeSource =
+ object : TimeSource {
+ @Composable override fun currentTime(): String = timeText
+ },
timeTextStyle = testTextStyle
) {
time()
@@ -262,27 +234,22 @@
fun changes_material_theme_on_non_round_device_except_color() {
val timeText = "testTime"
- val testTextStyle = TextStyle(
- color = Color.Green,
- background = Color.Black,
- fontStyle = FontStyle.Italic,
- fontSize = 25.sp,
- fontFamily = FontFamily.SansSerif
- )
+ val testTextStyle =
+ TextStyle(
+ color = Color.Green,
+ background = Color.Black,
+ fontStyle = FontStyle.Italic,
+ fontSize = 25.sp,
+ fontFamily = FontFamily.SansSerif
+ )
rule.setContent {
- MaterialTheme(
- typography = MaterialTheme.typography.copy(
- labelSmall = testTextStyle
- )
- ) {
- DeviceConfigurationOverride(
- DeviceConfigurationOverride.RoundScreen(false)
- ) {
+ MaterialTheme(typography = MaterialTheme.typography.copy(labelSmall = testTextStyle)) {
+ DeviceConfigurationOverride(DeviceConfigurationOverride.RoundScreen(false)) {
TimeText(
- timeSource = object : TimeSource {
- @Composable
- override fun currentTime(): String = timeText
- },
+ timeSource =
+ object : TimeSource {
+ @Composable override fun currentTime(): String = timeText
+ },
) {
time()
}
@@ -302,28 +269,23 @@
val timeText = "testTime"
var onBackgroundColor = Color.Unspecified
- val testTextStyle = TextStyle(
- color = Color.Green,
- background = Color.Black,
- fontStyle = FontStyle.Italic,
- fontSize = 25.sp,
- fontFamily = FontFamily.SansSerif
- )
+ val testTextStyle =
+ TextStyle(
+ color = Color.Green,
+ background = Color.Black,
+ fontStyle = FontStyle.Italic,
+ fontSize = 25.sp,
+ fontFamily = FontFamily.SansSerif
+ )
rule.setContent {
- MaterialTheme(
- typography = MaterialTheme.typography.copy(
- labelSmall = testTextStyle
- )
- ) {
+ MaterialTheme(typography = MaterialTheme.typography.copy(labelSmall = testTextStyle)) {
onBackgroundColor = MaterialTheme.colorScheme.onBackground
- DeviceConfigurationOverride(
- DeviceConfigurationOverride.RoundScreen(false)
- ) {
+ DeviceConfigurationOverride(DeviceConfigurationOverride.RoundScreen(false)) {
TimeText(
- timeSource = object : TimeSource {
- @Composable
- override fun currentTime(): String = timeText
- },
+ timeSource =
+ object : TimeSource {
+ @Composable override fun currentTime(): String = timeText
+ },
) {
time()
}
@@ -341,9 +303,7 @@
rule.setContentWithTheme {
primaryColor = MaterialTheme.colorScheme.primary
- DeviceConfigurationOverride(
- DeviceConfigurationOverride.RoundScreen(false)
- ) {
+ DeviceConfigurationOverride(DeviceConfigurationOverride.RoundScreen(false)) {
TimeText {
text(leadingText)
separator()
@@ -361,9 +321,7 @@
val customColor = Color.Green
rule.setContentWithTheme {
- DeviceConfigurationOverride(
- DeviceConfigurationOverride.RoundScreen(false)
- ) {
+ DeviceConfigurationOverride(DeviceConfigurationOverride.RoundScreen(false)) {
TimeText(
contentColor = customColor,
) {
@@ -381,23 +339,12 @@
fun supports_custom_text_style_on_non_round_device() {
val leadingText = "leadingText"
- val timeTextStyle = TextStyle(
- background = Color.Blue,
- fontSize = 14.sp
- )
- val contentTextStyle = TextStyle(
- color = Color.Green,
- background = Color.Black,
- fontSize = 20.sp
- )
+ val timeTextStyle = TextStyle(background = Color.Blue, fontSize = 14.sp)
+ val contentTextStyle =
+ TextStyle(color = Color.Green, background = Color.Black, fontSize = 20.sp)
rule.setContentWithTheme {
- DeviceConfigurationOverride(
- DeviceConfigurationOverride.RoundScreen(false)
- ) {
- TimeText(
- contentColor = Color.Red,
- timeTextStyle = timeTextStyle
- ) {
+ DeviceConfigurationOverride(DeviceConfigurationOverride.RoundScreen(false)) {
+ TimeText(contentColor = Color.Red, timeTextStyle = timeTextStyle) {
text(leadingText, contentTextStyle)
separator()
time()
@@ -418,9 +365,7 @@
val convertedTime = DateFormat.format(format, currentCalendar).toString()
var actualTime: String? = null
- rule.setContentWithTheme {
- actualTime = currentTime({ currentTimeInMillis }, format).value
- }
+ rule.setContentWithTheme { actualTime = currentTime({ currentTimeInMillis }, format).value }
Assert.assertEquals(convertedTime, actualTime)
}
@@ -432,10 +377,8 @@
var actualTime: String? = null
rule.setContentWithTheme {
- actualTime = currentTime(
- { currentTimeInMillis },
- TimeTextDefaults.TimeFormat12Hours
- ).value
+ actualTime =
+ currentTime({ currentTimeInMillis }, TimeTextDefaults.TimeFormat12Hours).value
}
Assert.assertEquals(expectedTime, actualTime)
}
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ToggleButtonScreenshotTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ToggleButtonScreenshotTest.kt
index c54a6ab..323b6b1 100644
--- a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ToggleButtonScreenshotTest.kt
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ToggleButtonScreenshotTest.kt
@@ -43,21 +43,15 @@
@RunWith(AndroidJUnit4::class)
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
class ToggleButtonScreenshotTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
- @get:Rule
- val screenshotRule = AndroidXScreenshotTestRule(SCREENSHOT_GOLDEN_PATH)
+ @get:Rule val screenshotRule = AndroidXScreenshotTestRule(SCREENSHOT_GOLDEN_PATH)
- @get:Rule
- val testName = TestName()
+ @get:Rule val testName = TestName()
@Test
fun toggle_button_checked_checkbox() = verifyScreenshot {
- sampleToggleButton(
- checked = true,
- toggleControl = { Checkbox() }
- )
+ sampleToggleButton(checked = true, toggleControl = { Checkbox() })
}
@Test
@@ -70,270 +64,150 @@
@Test
fun toggle_button_checked_switch() = verifyScreenshot {
- sampleToggleButton(
- checked = true,
- toggleControl = { Switch() }
- )
+ sampleToggleButton(checked = true, toggleControl = { Switch() })
}
@Test
fun toggle_button_unchecked_switch() = verifyScreenshot {
- sampleToggleButton(
- checked = false,
- toggleControl = { Switch() }
- )
+ sampleToggleButton(checked = false, toggleControl = { Switch() })
}
@Test
fun toggle_button_checked_checkbox_rtl() =
verifyScreenshot(layoutDirection = LayoutDirection.Rtl) {
- sampleToggleButton(
- checked = true,
- toggleControl = { Checkbox() }
- )
+ sampleToggleButton(checked = true, toggleControl = { Checkbox() })
}
@Test
fun toggle_button_unchecked_checkbox_rtl() =
verifyScreenshot(layoutDirection = LayoutDirection.Rtl) {
- sampleToggleButton(
- checked = false,
- toggleControl = { Checkbox() }
- )
+ sampleToggleButton(checked = false, toggleControl = { Checkbox() })
}
@Test
fun toggle_button_checked_switch_rtl() =
verifyScreenshot(layoutDirection = LayoutDirection.Rtl) {
- sampleToggleButton(
- checked = true,
- toggleControl = { Switch() }
- )
+ sampleToggleButton(checked = true, toggleControl = { Switch() })
}
@Test
fun toggle_button_unchecked_switch_rtl() =
verifyScreenshot(layoutDirection = LayoutDirection.Rtl) {
- sampleToggleButton(
- checked = false,
- toggleControl = { Switch() }
- )
+ sampleToggleButton(checked = false, toggleControl = { Switch() })
}
@Test
fun disabled_toggle_button_checked_checkbox() = verifyScreenshot {
- sampleToggleButton(
- checked = true,
- enabled = false,
- toggleControl = { Checkbox() }
- )
+ sampleToggleButton(checked = true, enabled = false, toggleControl = { Checkbox() })
}
@Test
fun disabled_toggle_button_unchecked_checkbox() = verifyScreenshot {
- sampleToggleButton(
- checked = false,
- enabled = false,
- toggleControl = { Checkbox() }
- )
+ sampleToggleButton(checked = false, enabled = false, toggleControl = { Checkbox() })
}
@Test
fun disabled_toggle_button_checked_switch() = verifyScreenshot {
- sampleToggleButton(
- checked = true,
- enabled = false,
- toggleControl = { Switch() }
- )
+ sampleToggleButton(checked = true, enabled = false, toggleControl = { Switch() })
}
@Test
fun disabled_toggle_button_unchecked_switch() = verifyScreenshot {
- sampleToggleButton(
- checked = false,
- enabled = false,
- toggleControl = { Switch() }
- )
+ sampleToggleButton(checked = false, enabled = false, toggleControl = { Switch() })
}
@Test
fun disabled_toggle_button_checked_checkbox_rtl() =
verifyScreenshot(layoutDirection = LayoutDirection.Rtl) {
- sampleToggleButton(
- checked = true,
- enabled = false,
- toggleControl = { Checkbox() }
- )
+ sampleToggleButton(checked = true, enabled = false, toggleControl = { Checkbox() })
}
@Test
fun disabled_toggle_button_unchecked_checkbox_rtl() =
verifyScreenshot(layoutDirection = LayoutDirection.Rtl) {
- sampleToggleButton(
- checked = false,
- enabled = false,
- toggleControl = { Checkbox() }
- )
+ sampleToggleButton(checked = false, enabled = false, toggleControl = { Checkbox() })
}
@Test
fun disabled_toggle_button_checked_switch_rtl() =
verifyScreenshot(layoutDirection = LayoutDirection.Rtl) {
- sampleToggleButton(
- checked = true,
- enabled = false,
- toggleControl = { Switch() }
- )
+ sampleToggleButton(checked = true, enabled = false, toggleControl = { Switch() })
}
@Test
fun disabled_toggle_button_unchecked_switch_rtl() =
verifyScreenshot(layoutDirection = LayoutDirection.Rtl) {
- sampleToggleButton(
- checked = false,
- enabled = false,
- toggleControl = { Switch() }
- )
+ sampleToggleButton(checked = false, enabled = false, toggleControl = { Switch() })
}
@Test
fun split_toggle_button_checked_checkbox() = verifyScreenshot {
- sampleSplitToggleButton(
- checked = true,
- toggleControl = {
- Checkbox()
- }
- )
+ sampleSplitToggleButton(checked = true, toggleControl = { Checkbox() })
}
@Test
fun split_toggle_button_unchecked_checkbox() = verifyScreenshot {
- sampleSplitToggleButton(
- checked = false,
- toggleControl = {
- Checkbox()
- }
- )
+ sampleSplitToggleButton(checked = false, toggleControl = { Checkbox() })
}
@Test
fun split_toggle_button_checked_switch() = verifyScreenshot {
- sampleSplitToggleButton(
- checked = true,
- toggleControl = {
- Switch()
- }
- )
+ sampleSplitToggleButton(checked = true, toggleControl = { Switch() })
}
@Test
fun split_toggle_button_unchecked_switch() = verifyScreenshot {
- sampleSplitToggleButton(
- checked = false,
- toggleControl = {
- Switch()
- }
- )
+ sampleSplitToggleButton(checked = false, toggleControl = { Switch() })
}
@Test
fun split_toggle_button_checked_checkbox_rtl() =
verifyScreenshot(layoutDirection = LayoutDirection.Rtl) {
- sampleSplitToggleButton(
- checked = true,
- toggleControl = {
- Checkbox()
- }
- )
+ sampleSplitToggleButton(checked = true, toggleControl = { Checkbox() })
}
@Test
fun split_toggle_button_unchecked_checkbox_rtl() =
verifyScreenshot(layoutDirection = LayoutDirection.Rtl) {
- sampleSplitToggleButton(
- checked = false,
- toggleControl = {
- Checkbox()
- }
- )
+ sampleSplitToggleButton(checked = false, toggleControl = { Checkbox() })
}
@Test
fun split_toggle_button_checked_switch_rtl() =
verifyScreenshot(layoutDirection = LayoutDirection.Rtl) {
- sampleSplitToggleButton(
- checked = true,
- toggleControl = {
- Switch()
- }
- )
+ sampleSplitToggleButton(checked = true, toggleControl = { Switch() })
}
@Test
fun split_toggle_button_unchecked_switch_rtl() =
verifyScreenshot(layoutDirection = LayoutDirection.Rtl) {
- sampleSplitToggleButton(
- checked = false,
- toggleControl = {
- Switch()
- }
- )
+ sampleSplitToggleButton(checked = false, toggleControl = { Switch() })
}
@Test
fun disabled_split_toggle_button_checked_checkbox() = verifyScreenshot {
- sampleSplitToggleButton(
- checked = true,
- enabled = false,
- toggleControl = {
- Checkbox()
- }
- )
+ sampleSplitToggleButton(checked = true, enabled = false, toggleControl = { Checkbox() })
}
@Test
fun disabled_split_toggle_button_unchecked_checkbox() = verifyScreenshot {
- sampleSplitToggleButton(
- checked = false,
- enabled = false,
- toggleControl = {
- Checkbox()
- }
- )
+ sampleSplitToggleButton(checked = false, enabled = false, toggleControl = { Checkbox() })
}
@Test
fun disabled_split_toggle_button_checked_switch() = verifyScreenshot {
- sampleSplitToggleButton(
- checked = true,
- enabled = false,
- toggleControl = {
- Switch()
- }
- )
+ sampleSplitToggleButton(checked = true, enabled = false, toggleControl = { Switch() })
}
@Test
fun disabled_split_toggle_button_unchecked_switch() = verifyScreenshot {
- sampleSplitToggleButton(
- checked = false,
- enabled = false,
- toggleControl = {
- Switch()
- }
- )
+ sampleSplitToggleButton(checked = false, enabled = false, toggleControl = { Switch() })
}
@Test
fun disabled_split_toggle_button_checked_checkbox_rtl() =
verifyScreenshot(layoutDirection = LayoutDirection.Rtl) {
- sampleSplitToggleButton(
- checked = true,
- enabled = false,
- toggleControl = {
- Checkbox()
- }
- )
+ sampleSplitToggleButton(checked = true, enabled = false, toggleControl = { Checkbox() })
}
@Test
@@ -342,52 +216,32 @@
sampleSplitToggleButton(
checked = false,
enabled = false,
- toggleControl = {
- Checkbox()
- }
+ toggleControl = { Checkbox() }
)
}
@Test
fun disabled_split_toggle_button_checked_switch_rtl() =
verifyScreenshot(layoutDirection = LayoutDirection.Rtl) {
- sampleSplitToggleButton(
- checked = true,
- enabled = false,
- toggleControl = {
- Switch()
- }
- )
+ sampleSplitToggleButton(checked = true, enabled = false, toggleControl = { Switch() })
}
@Test
fun disabled_split_toggle_button_unchecked_switch_rtl() =
verifyScreenshot(layoutDirection = LayoutDirection.Rtl) {
- sampleSplitToggleButton(
- checked = false,
- enabled = false,
- toggleControl = {
- Switch()
- }
- )
+ sampleSplitToggleButton(checked = false, enabled = false, toggleControl = { Switch() })
}
@Composable
private fun sampleToggleButton(
enabled: Boolean = true,
checked: Boolean = true,
- toggleControl: @Composable ToggleControlScope.() -> Unit = {
- Checkbox()
- },
+ toggleControl: @Composable ToggleControlScope.() -> Unit = { Checkbox() },
) {
ToggleButton(
icon = { TestIcon() },
- label = {
- Text("ToggleButton")
- },
- secondaryLabel = {
- Text("Secondary label")
- },
+ label = { Text("ToggleButton") },
+ secondaryLabel = { Text("Secondary label") },
checked = checked,
enabled = enabled,
toggleControl = toggleControl,
@@ -400,16 +254,11 @@
private fun sampleSplitToggleButton(
checked: Boolean = true,
enabled: Boolean = true,
- toggleControl: @Composable ToggleControlScope.() -> Unit = {
- }
+ toggleControl: @Composable ToggleControlScope.() -> Unit = {}
) {
SplitToggleButton(
- label = {
- Text("SplitToggleButton")
- },
- secondaryLabel = {
- Text("Secondary label")
- },
+ label = { Text("SplitToggleButton") },
+ secondaryLabel = { Text("Secondary label") },
checked = checked,
enabled = enabled,
toggleControl = toggleControl,
@@ -425,15 +274,12 @@
) {
rule.setContentWithTheme {
CompositionLocalProvider(LocalLayoutDirection provides layoutDirection) {
- Box(
- modifier = Modifier.background(Color.Black)
- ) {
- content()
- }
+ Box(modifier = Modifier.background(Color.Black)) { content() }
}
}
- rule.onNodeWithTag(TEST_TAG)
+ rule
+ .onNodeWithTag(TEST_TAG)
.captureToImage()
.assertAgainstGolden(screenshotRule, testName.methodName)
}
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ToggleButtonTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ToggleButtonTest.kt
index f670028..08ae745 100644
--- a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ToggleButtonTest.kt
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ToggleButtonTest.kt
@@ -62,16 +62,11 @@
import org.junit.Test
class ToggleButtonTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
@Test
fun supports_testtag() {
- rule.setContentWithTheme {
- ToggleButtonWithDefaults(
- modifier = Modifier.testTag(TEST_TAG)
- )
- }
+ rule.setContentWithTheme { ToggleButtonWithDefaults(modifier = Modifier.testTag(TEST_TAG)) }
rule.onNodeWithTag(TEST_TAG).assertExists()
}
@@ -79,9 +74,7 @@
@Test
fun split_button_supports_testtag() {
rule.setContentWithTheme {
- SplitToggleButtonWithDefaults(
- modifier = Modifier.testTag(TEST_TAG)
- )
+ SplitToggleButtonWithDefaults(modifier = Modifier.testTag(TEST_TAG))
}
rule.onNodeWithTag(TEST_TAG).assertExists()
@@ -106,10 +99,7 @@
@Test
fun has_clickaction_when_enabled() {
rule.setContentWithTheme {
- ToggleButtonWithDefaults(
- enabled = true,
- modifier = Modifier.testTag(TEST_TAG)
- )
+ ToggleButtonWithDefaults(enabled = true, modifier = Modifier.testTag(TEST_TAG))
}
rule.onNodeWithTag(TEST_TAG).assertHasClickAction()
@@ -118,10 +108,7 @@
@Test
fun split_button_has_clickaction_when_enabled() {
rule.setContentWithTheme {
- SplitToggleButtonWithDefaults(
- enabled = true,
- modifier = Modifier.testTag(TEST_TAG)
- )
+ SplitToggleButtonWithDefaults(enabled = true, modifier = Modifier.testTag(TEST_TAG))
}
rule.onNodeWithTag(TEST_TAG).onChildAt(0).assertHasClickAction()
@@ -130,10 +117,7 @@
@Test
fun has_clickaction_when_disabled() {
rule.setContentWithTheme {
- ToggleButtonWithDefaults(
- enabled = false,
- modifier = Modifier.testTag(TEST_TAG)
- )
+ ToggleButtonWithDefaults(enabled = false, modifier = Modifier.testTag(TEST_TAG))
}
rule.onNodeWithTag(TEST_TAG).assertHasClickAction()
@@ -142,10 +126,7 @@
@Test
fun split_button_has_clickaction_when_disabled() {
rule.setContentWithTheme {
- SplitToggleButtonWithDefaults(
- enabled = false,
- modifier = Modifier.testTag(TEST_TAG)
- )
+ SplitToggleButtonWithDefaults(enabled = false, modifier = Modifier.testTag(TEST_TAG))
}
rule.onNodeWithTag(TEST_TAG).onChildAt(0).assertHasClickAction()
@@ -153,11 +134,7 @@
@Test
fun is_toggleable() {
- rule.setContentWithTheme {
- ToggleButtonWithDefaults(
- modifier = Modifier.testTag(TEST_TAG)
- )
- }
+ rule.setContentWithTheme { ToggleButtonWithDefaults(modifier = Modifier.testTag(TEST_TAG)) }
rule.onNode(isToggleable()).assertExists()
}
@@ -165,9 +142,7 @@
@Test
fun split_button_is_toggleable() {
rule.setContentWithTheme {
- SplitToggleButtonWithDefaults(
- modifier = Modifier.testTag(TEST_TAG)
- )
+ SplitToggleButtonWithDefaults(modifier = Modifier.testTag(TEST_TAG))
}
rule.onNode(isToggleable()).assertExists()
@@ -176,9 +151,7 @@
@Test
fun split_button_is_clickable() {
rule.setContentWithTheme {
- SplitToggleButtonWithDefaults(
- modifier = Modifier.testTag(TEST_TAG)
- )
+ SplitToggleButtonWithDefaults(modifier = Modifier.testTag(TEST_TAG))
}
rule.onNodeWithTag(TEST_TAG).onChildAt(0).assertHasClickAction()
}
@@ -186,10 +159,7 @@
@Test
fun is_correctly_enabled() {
rule.setContentWithTheme {
- ToggleButtonWithDefaults(
- enabled = true,
- modifier = Modifier.testTag(TEST_TAG)
- )
+ ToggleButtonWithDefaults(enabled = true, modifier = Modifier.testTag(TEST_TAG))
}
rule.onNodeWithTag(TEST_TAG).assertIsEnabled()
@@ -198,10 +168,7 @@
@Test
fun split_button_is_correctly_enabled() {
rule.setContentWithTheme {
- SplitToggleButtonWithDefaults(
- enabled = true,
- modifier = Modifier.testTag(TEST_TAG)
- )
+ SplitToggleButtonWithDefaults(enabled = true, modifier = Modifier.testTag(TEST_TAG))
}
rule.onNodeWithTag(TEST_TAG).assertIsEnabled()
@@ -210,10 +177,7 @@
@Test
fun is_correctly_disabled() {
rule.setContentWithTheme {
- ToggleButtonWithDefaults(
- enabled = false,
- modifier = Modifier.testTag(TEST_TAG)
- )
+ ToggleButtonWithDefaults(enabled = false, modifier = Modifier.testTag(TEST_TAG))
}
rule.onNodeWithTag(TEST_TAG).assertIsNotEnabled()
@@ -222,10 +186,7 @@
@Test
fun split_button_is_correctly_disabled() {
rule.setContentWithTheme {
- SplitToggleButtonWithDefaults(
- enabled = false,
- modifier = Modifier.testTag(TEST_TAG)
- )
+ SplitToggleButtonWithDefaults(enabled = false, modifier = Modifier.testTag(TEST_TAG))
}
rule.onNodeWithTag(TEST_TAG).onChildAt(0).assertIsNotEnabled()
@@ -234,10 +195,7 @@
@Test
fun is_on_when_checked() {
rule.setContentWithTheme {
- ToggleButtonWithDefaults(
- checked = true,
- modifier = Modifier.testTag(TEST_TAG)
- )
+ ToggleButtonWithDefaults(checked = true, modifier = Modifier.testTag(TEST_TAG))
}
rule.onNodeWithTag(TEST_TAG).assertIsOn()
@@ -246,10 +204,7 @@
@Test
fun split_button_is_on_when_checked() {
rule.setContentWithTheme {
- SplitToggleButtonWithDefaults(
- checked = true,
- modifier = Modifier.testTag(TEST_TAG)
- )
+ SplitToggleButtonWithDefaults(checked = true, modifier = Modifier.testTag(TEST_TAG))
}
rule.onNodeWithTag(TEST_TAG).onChildAt(1).assertIsOn()
@@ -258,10 +213,7 @@
@Test
fun is_off_when_unchecked() {
rule.setContentWithTheme {
- ToggleButtonWithDefaults(
- checked = false,
- modifier = Modifier.testTag(TEST_TAG)
- )
+ ToggleButtonWithDefaults(checked = false, modifier = Modifier.testTag(TEST_TAG))
}
rule.onNodeWithTag(TEST_TAG).assertIsOff()
@@ -270,10 +222,7 @@
@Test
fun split_button_is_off_when_unchecked() {
rule.setContentWithTheme {
- SplitToggleButtonWithDefaults(
- checked = false,
- modifier = Modifier.testTag(TEST_TAG)
- )
+ SplitToggleButtonWithDefaults(checked = false, modifier = Modifier.testTag(TEST_TAG))
}
rule.onNodeWithTag(TEST_TAG).onChildAt(1).assertIsOff()
@@ -291,11 +240,7 @@
)
}
- rule
- .onNodeWithTag(TEST_TAG)
- .assertIsOff()
- .performClick()
- .assertIsOn()
+ rule.onNodeWithTag(TEST_TAG).assertIsOff().performClick().assertIsOn()
}
@Test
@@ -310,12 +255,7 @@
)
}
- rule
- .onNodeWithTag(TEST_TAG)
- .onChildAt(1)
- .assertIsOff()
- .performClick()
- .assertIsOn()
+ rule.onNodeWithTag(TEST_TAG).onChildAt(1).assertIsOff().performClick().assertIsOn()
}
@Test
@@ -330,11 +270,7 @@
)
}
- rule
- .onNodeWithTag(TEST_TAG)
- .assertIsOn()
- .performClick()
- .assertIsOff()
+ rule.onNodeWithTag(TEST_TAG).assertIsOn().performClick().assertIsOff()
}
@Test
@@ -349,12 +285,7 @@
)
}
- rule
- .onNodeWithTag(TEST_TAG)
- .onChildAt(1)
- .assertIsOn()
- .performClick()
- .assertIsOff()
+ rule.onNodeWithTag(TEST_TAG).onChildAt(1).assertIsOn().performClick().assertIsOff()
}
@Test
@@ -369,11 +300,7 @@
)
}
- rule
- .onNodeWithTag(TEST_TAG)
- .assertIsOff()
- .performClick()
- .assertIsOff()
+ rule.onNodeWithTag(TEST_TAG).assertIsOff().performClick().assertIsOff()
}
@Test
@@ -388,52 +315,34 @@
)
}
- rule
- .onNodeWithTag(TEST_TAG)
- .onChildAt(1)
- .assertIsOff()
- .performClick()
- .assertIsOff()
+ rule.onNodeWithTag(TEST_TAG).onChildAt(1).assertIsOff().performClick().assertIsOff()
}
@Test
fun can_override_role() {
rule.setContentWithTheme {
ToggleButtonWithDefaults(
- modifier = Modifier
- .testTag(TEST_TAG)
- .semantics {
- role = Role.Button
- }
+ modifier = Modifier.testTag(TEST_TAG).semantics { role = Role.Button }
)
}
- rule.onNodeWithTag(TEST_TAG)
- .assert(
- SemanticsMatcher.expectValue(
- SemanticsProperties.Role,
- Role.Button
- )
- )
+ rule
+ .onNodeWithTag(TEST_TAG)
+ .assert(SemanticsMatcher.expectValue(SemanticsProperties.Role, Role.Button))
}
@Test
fun split_button_clickable_has_role_button() {
rule.setContentWithTheme {
- SplitToggleButtonWithDefaults(
- modifier = Modifier.testTag(TEST_TAG)
- )
+ SplitToggleButtonWithDefaults(modifier = Modifier.testTag(TEST_TAG))
}
// NB The toggle control (Checkbox or Switch) provides its own role,
// but the main clickable section is a Button.
- rule.onNodeWithTag(TEST_TAG).onChildAt(0)
- .assert(
- SemanticsMatcher.expectValue(
- SemanticsProperties.Role,
- Role.Button
- )
- )
+ rule
+ .onNodeWithTag(TEST_TAG)
+ .onChildAt(0)
+ .assert(SemanticsMatcher.expectValue(SemanticsProperties.Role, Role.Button))
}
@Test
@@ -444,9 +353,7 @@
ToggleButtonWithDefaults(
checked = true,
onCheckedChange = {},
- label = {
- Text(text = textContent)
- }
+ label = { Text(text = textContent) }
)
}
@@ -461,9 +368,7 @@
SplitToggleButtonWithDefaults(
checked = true,
onCheckedChange = {},
- label = {
- Text(text = textContent)
- }
+ label = { Text(text = textContent) }
)
}
@@ -474,60 +379,58 @@
fun toggle_button_hasAdjustableHeight() {
val minHeight: Dp = 53.dp
- rule.setContentWithThemeForSizeAssertions {
- ToggleButtonWithDefaults(
- label = {
- Text(
- text = "ToggleButton text spanning over multiple lines of text " +
- "to test height is adjustable. This should exceed the minimum height" +
- " for the ToggleButton."
- )
- },
- secondaryLabel = {
- Text(
- text = "Secondary label with text."
- )
- }
- )
- }.assertHeightIsAtLeast(minHeight)
+ rule
+ .setContentWithThemeForSizeAssertions {
+ ToggleButtonWithDefaults(
+ label = {
+ Text(
+ text =
+ "ToggleButton text spanning over multiple lines of text " +
+ "to test height is adjustable. This should exceed the minimum height" +
+ " for the ToggleButton."
+ )
+ },
+ secondaryLabel = { Text(text = "Secondary label with text.") }
+ )
+ }
+ .assertHeightIsAtLeast(minHeight)
}
@Test
fun split_toggle_button_hasAdjustableHeight() {
val minHeight: Dp = 53.dp
- rule.setContentWithThemeForSizeAssertions {
- SplitToggleButtonWithDefaults(
- label = {
- Text(
- text = "Primary label with 3 lines of text."
- )
- },
- secondaryLabel = {
- Text(
- text = "SplitToggleButton text spanning over multiple lines of text " +
- "to test height is adjustable. This should exceed the minimum height" +
- " for the SplitToggleButton."
- )
- }
- )
- }.assertHeightIsAtLeast(minHeight)
+ rule
+ .setContentWithThemeForSizeAssertions {
+ SplitToggleButtonWithDefaults(
+ label = { Text(text = "Primary label with 3 lines of text.") },
+ secondaryLabel = {
+ Text(
+ text =
+ "SplitToggleButton text spanning over multiple lines of text " +
+ "to test height is adjustable. This should exceed the minimum height" +
+ " for the SplitToggleButton."
+ )
+ }
+ )
+ }
+ .assertHeightIsAtLeast(minHeight)
}
@Test
fun toggle_button_height_defaults_52dp() {
- rule.setContentWithThemeForSizeAssertions {
- ToggleButtonWithDefaults(
- secondaryLabel = { Text("Secondary label") }
- )
- }.assertHeightIsEqualTo(52.dp)
+ rule
+ .setContentWithThemeForSizeAssertions {
+ ToggleButtonWithDefaults(secondaryLabel = { Text("Secondary label") })
+ }
+ .assertHeightIsEqualTo(52.dp)
}
@Test
fun split_toggle_button_height_defaults_52dp() {
- rule.setContentWithThemeForSizeAssertions {
- SplitToggleButtonWithDefaults()
- }.assertHeightIsEqualTo(52.dp)
+ rule
+ .setContentWithThemeForSizeAssertions { SplitToggleButtonWithDefaults() }
+ .assertHeightIsEqualTo(52.dp)
}
@RequiresApi(Build.VERSION_CODES.O)
@@ -623,19 +526,18 @@
rule.setContentWithTheme {
ToggleButtonWithDefaults(
checked = checked,
- colors = ToggleButtonDefaults.toggleButtonColors(
- checkedContainerColor = CHECKED_COLOR,
- uncheckedContainerColor = UNCHECKED_COLOR
- ),
+ colors =
+ ToggleButtonDefaults.toggleButtonColors(
+ checkedContainerColor = CHECKED_COLOR,
+ uncheckedContainerColor = UNCHECKED_COLOR
+ ),
onCheckedChange = {},
enabled = enabled,
modifier = Modifier.testTag(TEST_TAG),
)
}
- rule.onNodeWithTag(TEST_TAG)
- .captureToImage()
- .assertContainsColor(expectedColor)
+ rule.onNodeWithTag(TEST_TAG).captureToImage().assertContainsColor(expectedColor)
}
@RequiresApi(Build.VERSION_CODES.O)
@@ -647,19 +549,18 @@
rule.setContentWithTheme {
SplitToggleButtonWithDefaults(
checked = checked,
- colors = ToggleButtonDefaults.splitToggleButtonColors(
- checkedContainerColor = CHECKED_COLOR,
- uncheckedContainerColor = UNCHECKED_COLOR
- ),
+ colors =
+ ToggleButtonDefaults.splitToggleButtonColors(
+ checkedContainerColor = CHECKED_COLOR,
+ uncheckedContainerColor = UNCHECKED_COLOR
+ ),
onCheckedChange = {},
enabled = enabled,
modifier = Modifier.testTag(TEST_TAG),
)
}
- rule.onNodeWithTag(TEST_TAG)
- .captureToImage()
- .assertContainsColor(expectedColor)
+ rule.onNodeWithTag(TEST_TAG).captureToImage().assertContainsColor(expectedColor)
}
}
@@ -670,9 +571,7 @@
enabled: Boolean = true,
colors: ToggleButtonColors = ToggleButtonDefaults.toggleButtonColors(),
onCheckedChange: (Boolean) -> Unit = {},
- label: @Composable RowScope.() -> Unit = {
- Text("Primary")
- },
+ label: @Composable RowScope.() -> Unit = { Text("Primary") },
secondaryLabel: @Composable (RowScope.() -> Unit)? = null,
icon: @Composable (BoxScope.() -> Unit)? = null,
toggleControl: @Composable ToggleControlScope.() -> Unit = { Checkbox() }
@@ -697,28 +596,24 @@
colors: SplitToggleButtonColors = ToggleButtonDefaults.splitToggleButtonColors(),
onCheckedChange: (Boolean) -> Unit = {},
onClick: () -> Unit = {},
- label: @Composable RowScope.() -> Unit = {
- Text("Primary")
- },
+ label: @Composable RowScope.() -> Unit = { Text("Primary") },
secondaryLabel: @Composable (RowScope.() -> Unit)? = null,
toggleControl: @Composable ToggleControlScope.() -> Unit = { Checkbox() }
-) = SplitToggleButton(
- modifier = modifier,
- colors = colors,
- checked = checked,
- enabled = enabled,
- onCheckedChange = onCheckedChange,
- label = label,
- secondaryLabel = secondaryLabel,
- onClick = onClick,
- toggleControl = toggleControl,
-)
+) =
+ SplitToggleButton(
+ modifier = modifier,
+ colors = colors,
+ checked = checked,
+ enabled = enabled,
+ onCheckedChange = onCheckedChange,
+ label = label,
+ secondaryLabel = secondaryLabel,
+ onClick = onClick,
+ toggleControl = toggleControl,
+ )
@RequiresApi(Build.VERSION_CODES.O)
-private fun ComposeContentTestRule.verifyToggleButtonColors(
- enabled: Boolean,
- checked: Boolean
-) {
+private fun ComposeContentTestRule.verifyToggleButtonColors(enabled: Boolean, checked: Boolean) {
val testBackgroundColor = Color.White
var expectedContainerColor = Color.Transparent
var expectedLabelColor = Color.Transparent
@@ -728,16 +623,12 @@
var actualIconColor = Color.Transparent
var actualSecondaryLabelColor = Color.Transparent
setContentWithTheme {
- expectedContainerColor = toggle_button_container_color(checked, enabled)
- .compositeOver(testBackgroundColor)
+ expectedContainerColor =
+ toggle_button_container_color(checked, enabled).compositeOver(testBackgroundColor)
expectedLabelColor = toggle_button_content_color(checked, enabled)
expectedSecondaryLabelColor = toggle_button_secondary_label_color(checked, enabled)
expectedIconColor = toggle_button_icon_color(enabled)
- Box(
- Modifier
- .fillMaxSize()
- .background(testBackgroundColor)
- ) {
+ Box(Modifier.fillMaxSize().background(testBackgroundColor)) {
ToggleButton(
modifier = Modifier.testTag(TEST_TAG),
checked = checked,
@@ -774,18 +665,16 @@
var actualLabelColor = Color.Transparent
var actualSecondaryLabelColor = Color.Transparent
setContentWithTheme {
- expectedContainerColor = split_toggle_button_container_color(checked)
- .withDisabledAlphaApplied(enabled = enabled)
- .compositeOver(testBackgroundColor)
- expectedLabelColor = split_toggle_button_content_color(checked)
- .withDisabledAlphaApplied(enabled = enabled)
- expectedSecondaryLabelColor = split_toggle_button_secondary_label_color(checked)
- .withDisabledAlphaApplied(enabled = enabled)
- Box(
- Modifier
- .fillMaxSize()
- .background(testBackgroundColor)
- ) {
+ expectedContainerColor =
+ split_toggle_button_container_color(checked)
+ .withDisabledAlphaApplied(enabled = enabled)
+ .compositeOver(testBackgroundColor)
+ expectedLabelColor =
+ split_toggle_button_content_color(checked).withDisabledAlphaApplied(enabled = enabled)
+ expectedSecondaryLabelColor =
+ split_toggle_button_secondary_label_color(checked)
+ .withDisabledAlphaApplied(enabled = enabled)
+ Box(Modifier.fillMaxSize().background(testBackgroundColor)) {
SplitToggleButton(
modifier = Modifier.testTag(TEST_TAG),
checked = checked,
@@ -820,61 +709,45 @@
}
@Composable
-private fun toggle_button_content_color(
- checked: Boolean,
- enabled: Boolean
-): Color {
+private fun toggle_button_content_color(checked: Boolean, enabled: Boolean): Color {
return if (checked && enabled) MaterialTheme.colorScheme.onPrimaryContainer
else if (!checked && enabled) MaterialTheme.colorScheme.onSurface
else MaterialTheme.colorScheme.onSurface.toDisabledColor(disabledAlpha = 0.38f)
}
@Composable
-private fun toggle_button_secondary_label_color(
- checked: Boolean,
- enabled: Boolean
-): Color {
+private fun toggle_button_secondary_label_color(checked: Boolean, enabled: Boolean): Color {
return if (checked && enabled) MaterialTheme.colorScheme.onPrimaryContainer.copy(alpha = 0.8f)
else if (!checked && enabled) MaterialTheme.colorScheme.onSurfaceVariant
else MaterialTheme.colorScheme.onSurface.toDisabledColor(disabledAlpha = 0.38f)
}
@Composable
-private fun toggle_button_icon_color(
- enabled: Boolean
-): Color {
+private fun toggle_button_icon_color(enabled: Boolean): Color {
return if (enabled) MaterialTheme.colorScheme.primary
else MaterialTheme.colorScheme.onSurface.toDisabledColor(disabledAlpha = 0.38f)
}
@Composable
-private fun split_toggle_button_container_color(
- checked: Boolean
-): Color {
+private fun split_toggle_button_container_color(checked: Boolean): Color {
return if (checked) MaterialTheme.colorScheme.primaryContainer
else MaterialTheme.colorScheme.surfaceContainer
}
@Composable
-private fun split_toggle_button_content_color(
- checked: Boolean
-): Color {
+private fun split_toggle_button_content_color(checked: Boolean): Color {
return if (checked) MaterialTheme.colorScheme.onPrimaryContainer
else MaterialTheme.colorScheme.onSurface
}
@Composable
-private fun split_toggle_button_secondary_label_color(
- checked: Boolean
-): Color {
+private fun split_toggle_button_secondary_label_color(checked: Boolean): Color {
return if (checked) MaterialTheme.colorScheme.onPrimaryContainer.copy(alpha = 0.8f)
else MaterialTheme.colorScheme.onSurfaceVariant
}
@Composable
-private fun Color.withDisabledAlphaApplied(
- enabled: Boolean
-): Color {
+private fun Color.withDisabledAlphaApplied(enabled: Boolean): Color {
return if (!enabled) toDisabledColor(disabledAlpha = 0.38f) else this
}
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ToggleControlsScreenshotTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ToggleControlsScreenshotTest.kt
index 85d3f0e..f6568b5 100644
--- a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ToggleControlsScreenshotTest.kt
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ToggleControlsScreenshotTest.kt
@@ -44,133 +44,118 @@
@RunWith(AndroidJUnit4::class)
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
class ToggleControlsScreenshotTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
- @get:Rule
- val screenshotRule = AndroidXScreenshotTestRule(SCREENSHOT_GOLDEN_PATH)
+ @get:Rule val screenshotRule = AndroidXScreenshotTestRule(SCREENSHOT_GOLDEN_PATH)
- @get:Rule
- val testName = TestName()
+ @get:Rule val testName = TestName()
@Test
- fun checkbox_checked_enabled() =
- verifyScreenshot {
- with(ToggleControlScope(isChecked = true, isEnabled = true)) {
- Checkbox(modifier = testBackgroundModifier())
- }
+ fun checkbox_checked_enabled() = verifyScreenshot {
+ with(ToggleControlScope(isChecked = true, isEnabled = true)) {
+ Checkbox(modifier = testBackgroundModifier())
}
+ }
@Test
- fun checkbox_unchecked_enabled() =
- verifyScreenshot {
- with(ToggleControlScope(isChecked = false, isEnabled = true)) {
- Checkbox(modifier = testBackgroundModifier())
- }
+ fun checkbox_unchecked_enabled() = verifyScreenshot {
+ with(ToggleControlScope(isChecked = false, isEnabled = true)) {
+ Checkbox(modifier = testBackgroundModifier())
}
+ }
@Test
- fun checkbox_checked_disabled() =
- verifyScreenshot {
- with(ToggleControlScope(isChecked = true, isEnabled = false)) {
- Checkbox(modifier = testBackgroundModifier())
- }
+ fun checkbox_checked_disabled() = verifyScreenshot {
+ with(ToggleControlScope(isChecked = true, isEnabled = false)) {
+ Checkbox(modifier = testBackgroundModifier())
}
+ }
@Test
- fun checkbox_unchecked_disabled() =
- verifyScreenshot {
- with(ToggleControlScope(isChecked = false, isEnabled = false)) {
- Checkbox(modifier = testBackgroundModifier())
- }
+ fun checkbox_unchecked_disabled() = verifyScreenshot {
+ with(ToggleControlScope(isChecked = false, isEnabled = false)) {
+ Checkbox(modifier = testBackgroundModifier())
}
+ }
@Test
- fun switch_checked_enabled() =
- verifyScreenshot {
+ fun switch_checked_enabled() = verifyScreenshot {
+ with(ToggleControlScope(isChecked = true, isEnabled = true)) {
+ Switch(modifier = testBackgroundModifier())
+ }
+ }
+
+ @Test
+ fun switch_unchecked_enabled() = verifyScreenshot {
+ with(ToggleControlScope(isChecked = false, isEnabled = true)) {
+ Switch(modifier = testBackgroundModifier())
+ }
+ }
+
+ @Test
+ fun switch_checked_disabled() = verifyScreenshot {
+ with(ToggleControlScope(isChecked = true, isEnabled = false)) {
+ Switch(modifier = testBackgroundModifier())
+ }
+ }
+
+ @Test
+ fun switch_unchecked_disabled() = verifyScreenshot {
+ with(ToggleControlScope(isChecked = false, isEnabled = false)) {
+ Switch(modifier = testBackgroundModifier())
+ }
+ }
+
+ @Test
+ fun switch_rtl_checked_enabled() = verifyScreenshot {
+ CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl) {
with(ToggleControlScope(isChecked = true, isEnabled = true)) {
Switch(modifier = testBackgroundModifier())
}
}
+ }
@Test
- fun switch_unchecked_enabled() =
- verifyScreenshot {
+ fun switch_rtl_unchecked_enabled() = verifyScreenshot {
+ CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl) {
with(ToggleControlScope(isChecked = false, isEnabled = true)) {
Switch(modifier = testBackgroundModifier())
}
}
+ }
@Test
- fun switch_checked_disabled() =
- verifyScreenshot {
+ fun switch_rtl_checked_disabled() = verifyScreenshot {
+ CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl) {
with(ToggleControlScope(isChecked = true, isEnabled = false)) {
Switch(modifier = testBackgroundModifier())
}
}
+ }
@Test
- fun switch_unchecked_disabled() =
- verifyScreenshot {
+ fun switch_rtl_unchecked_disabled() = verifyScreenshot {
+ CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl) {
with(ToggleControlScope(isChecked = false, isEnabled = false)) {
Switch(modifier = testBackgroundModifier())
}
}
-
- @Test
- fun switch_rtl_checked_enabled() =
- verifyScreenshot {
- CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl) {
- with(ToggleControlScope(isChecked = true, isEnabled = true)) {
- Switch(modifier = testBackgroundModifier())
- }
- }
- }
-
- @Test
- fun switch_rtl_unchecked_enabled() =
- verifyScreenshot {
- CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl) {
- with(ToggleControlScope(isChecked = false, isEnabled = true)) {
- Switch(modifier = testBackgroundModifier())
- }
- }
- }
-
- @Test
- fun switch_rtl_checked_disabled() =
- verifyScreenshot {
- CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl) {
- with(ToggleControlScope(isChecked = true, isEnabled = false)) {
- Switch(modifier = testBackgroundModifier())
- }
- }
- }
-
- @Test
- fun switch_rtl_unchecked_disabled() =
- verifyScreenshot {
- CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl) {
- with(ToggleControlScope(isChecked = false, isEnabled = false)) {
- Switch(modifier = testBackgroundModifier())
- }
- }
- }
+ }
private fun verifyScreenshot(
threshold: Double = 0.98,
content: @Composable BoxScope.() -> Unit
) {
rule.setContentWithTheme(composable = content)
- rule.onNodeWithTag(TEST_TAG)
+ rule
+ .onNodeWithTag(TEST_TAG)
.captureToImage()
.assertAgainstGolden(screenshotRule, testName.methodName, MSSIMMatcher(threshold))
}
@Composable
private fun testBackgroundModifier(): Modifier =
- Modifier
- .testTag(TEST_TAG)
+ Modifier.testTag(TEST_TAG)
.background(
MaterialTheme.colorScheme.primary
.copy(alpha = 0.5f)
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ToggleControlsTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ToggleControlsTest.kt
index 4755838..c9d272e 100644
--- a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ToggleControlsTest.kt
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ToggleControlsTest.kt
@@ -37,8 +37,7 @@
import org.junit.Test
class ToggleControlsTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
@Test
fun checkbox_supports_testtag() {
@@ -71,13 +70,9 @@
}
}
- rule.onNodeWithTag(TEST_TAG)
- .assert(
- SemanticsMatcher.expectValue(
- SemanticsProperties.Role,
- Role.Checkbox
- )
- )
+ rule
+ .onNodeWithTag(TEST_TAG)
+ .assert(SemanticsMatcher.expectValue(SemanticsProperties.Role, Role.Checkbox))
}
@RequiresApi(Build.VERSION_CODES.O)
@@ -88,10 +83,11 @@
rule.setContentWithTheme {
with(ToggleControlScope(isEnabled = true, isChecked = true)) {
Checkbox(
- colors = CheckboxDefaults.colors(
- checkedBoxColor = boxColor,
- checkedCheckmarkColor = checkmarkColor
- ),
+ colors =
+ CheckboxDefaults.colors(
+ checkedBoxColor = boxColor,
+ checkedCheckmarkColor = checkmarkColor
+ ),
modifier = Modifier.testTag(TEST_TAG)
)
}
@@ -111,9 +107,10 @@
rule.setContentWithTheme {
with(ToggleControlScope(isEnabled = true, isChecked = false)) {
Checkbox(
- colors = CheckboxDefaults.colors(
- uncheckedBoxColor = boxColor,
- ),
+ colors =
+ CheckboxDefaults.colors(
+ uncheckedBoxColor = boxColor,
+ ),
modifier = Modifier.testTag(TEST_TAG)
)
}
@@ -154,13 +151,9 @@
}
}
- rule.onNodeWithTag(TEST_TAG)
- .assert(
- SemanticsMatcher.expectValue(
- SemanticsProperties.Role,
- Role.Switch
- )
- )
+ rule
+ .onNodeWithTag(TEST_TAG)
+ .assert(SemanticsMatcher.expectValue(SemanticsProperties.Role, Role.Switch))
}
@Test
@@ -184,12 +177,13 @@
rule.setContentWithTheme {
with(ToggleControlScope(isEnabled = true, isChecked = true)) {
Switch(
- colors = SwitchDefaults.colors(
- checkedThumbColor = thumbColor,
- checkedThumbIconColor = thumbIconColor,
- checkedTrackColor = trackColor,
- checkedTrackBorderColor = trackStrokeColor
- ),
+ colors =
+ SwitchDefaults.colors(
+ checkedThumbColor = thumbColor,
+ checkedThumbIconColor = thumbIconColor,
+ checkedTrackColor = trackColor,
+ checkedTrackBorderColor = trackStrokeColor
+ ),
modifier = Modifier.testTag(TEST_TAG)
)
}
@@ -212,12 +206,13 @@
rule.setContentWithTheme {
with(ToggleControlScope(isEnabled = true, isChecked = false)) {
Switch(
- colors = SwitchDefaults.colors(
- uncheckedThumbColor = thumbColor,
- uncheckedThumbIconColor = thumbIconColor,
- uncheckedTrackColor = trackColor,
- uncheckedTrackBorderColor = trackStrokeColor
- ),
+ colors =
+ SwitchDefaults.colors(
+ uncheckedThumbColor = thumbColor,
+ uncheckedThumbIconColor = thumbIconColor,
+ uncheckedTrackColor = trackColor,
+ uncheckedTrackBorderColor = trackStrokeColor
+ ),
modifier = Modifier.testTag(TEST_TAG)
)
}
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Angular.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Angular.kt
index 722b694..d31a259 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Angular.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Angular.kt
@@ -18,12 +18,8 @@
import kotlin.math.PI
-/**
- * Converts the angle measured in degrees to an equivalent angle measured in radians.
- */
+/** Converts the angle measured in degrees to an equivalent angle measured in radians. */
internal fun Float.toRadians() = this * PI.toFloat() / 180f
-/**
- * Converts the angle measured in radians to an equivalent angle measured in degrees.
- */
+/** Converts the angle measured in radians to an equivalent angle measured in degrees. */
internal fun Float.toDegrees() = this * 180f / PI.toFloat()
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 53a96b4..13b612f 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
@@ -65,55 +65,57 @@
import androidx.wear.compose.material3.tokens.OutlinedButtonTokens
/**
- * Base level Wear Material3 [Button] that offers a single slot to take any content.
- * Used as the container for more opinionated [Button] components that take specific
- * content such as icons and labels.
+ * Base level Wear Material3 [Button] that offers a single slot to take any content. Used as the
+ * container for more opinionated [Button] components that take specific content such as icons and
+ * labels.
*
* The [Button] is stadium-shaped by default and its standard height is designed to take 2 lines of
* text of [Typography.labelMedium] style. With localisation and/or large font sizes, the text can
* extend to a maximum of 3 lines in which case, the [Button] height adjusts to accommodate the
* contents.
*
- * [Button] takes the [ButtonDefaults.buttonColors] color scheme by default,
- * with colored background, contrasting content color and no border. This is a high-emphasis button
- * for the primary, most important or most common action on a screen.
+ * [Button] takes the [ButtonDefaults.buttonColors] color scheme by default, with colored
+ * background, contrasting content color and no border. This is a high-emphasis button for the
+ * primary, most important or most common action on a screen.
*
* Other recommended buttons with [ButtonColors] for different levels of emphasis are:
- * [FilledTonalButton] which defaults to [ButtonDefaults.filledTonalButtonColors],
- * [OutlinedButton] which defaults to [ButtonDefaults.outlinedButtonColors] and
- * [ChildButton] which defaults to [ButtonDefaults.childButtonColors].
- * Buttons can also take an image background using [ButtonDefaults.imageBackgroundButtonColors].
+ * [FilledTonalButton] which defaults to [ButtonDefaults.filledTonalButtonColors], [OutlinedButton]
+ * which defaults to [ButtonDefaults.outlinedButtonColors] and [ChildButton] which defaults to
+ * [ButtonDefaults.childButtonColors]. Buttons can also take an image background using
+ * [ButtonDefaults.imageBackgroundButtonColors].
*
* Button can be enabled or disabled. A disabled button will not respond to click events.
*
- * TODO(b/261838497) Add Material3 UX guidance links
- *
* Example of a [Button]:
+ *
* @sample androidx.wear.compose.material3.samples.SimpleButtonSample
*
* Example of a [Button] with onLongClick:
+ *
* @sample androidx.wear.compose.material3.samples.ButtonWithOnLongClick
*
* @param onClick Will be called when the user clicks the button
* @param modifier Modifier to be applied to the button
- * @param onLongClick Called when this button is long clicked (long-pressed). When this callback
- * is set, [onLongClickLabel] should be set as well.
+ * @param onLongClick Called when this button is long clicked (long-pressed). When this callback is
+ * set, [onLongClickLabel] should be set as well.
* @param onLongClickLabel Semantic / accessibility label for the [onLongClick] action.
- * @param enabled Controls the enabled state of the button. When `false`, this button will not
- * be clickable
+ * @param enabled Controls the enabled state of the button. When `false`, this button will not be
+ * clickable
* @param shape Defines the button's shape. It is strongly recommended to use the default as this
- * shape is a key characteristic of the Wear Material3 Theme
+ * shape is a key characteristic of the Wear Material3 Theme
* @param colors [ButtonColors] that will be used to resolve the background and content color for
- * this button in different states. See [ButtonDefaults.buttonColors].
- * @param border Optional [BorderStroke] that will be used to resolve the border for this
- * button in different states.
+ * this button in different states. See [ButtonDefaults.buttonColors].
+ * @param border Optional [BorderStroke] that will be used to resolve the border for this button in
+ * different states.
* @param contentPadding The spacing values to apply internally between the container and the
- * content
+ * content
* @param interactionSource an optional hoisted [MutableInteractionSource] for observing and
- * emitting [Interaction]s for this button. You can use this to change the button's appearance
- * or preview the button in different states. Note that if `null` is provided, interactions will
- * still happen internally.
+ * emitting [Interaction]s for this button. You can use this to change the button's appearance or
+ * preview the button in different states. Note that if `null` is provided, interactions will
+ * still happen internally.
* @param content Slot for composable body content displayed on the Button
+ *
+ * TODO(b/261838497) Add Material3 UX guidance links
*/
@Composable
fun Button(
@@ -128,73 +130,76 @@
contentPadding: PaddingValues = ButtonDefaults.ContentPadding,
interactionSource: MutableInteractionSource? = null,
content: @Composable RowScope.() -> Unit,
-) = ButtonImpl(
- onClick = onClick,
- modifier = modifier.buttonSizeModifier(),
- onLongClick = onLongClick,
- onLongClickLabel = onLongClickLabel,
- enabled = enabled,
- shape = shape,
- labelFont = FilledButtonTokens.LabelFont.value,
- colors = colors,
- border = border,
- contentPadding = contentPadding,
- interactionSource = interactionSource,
- content = content
-)
+) =
+ ButtonImpl(
+ onClick = onClick,
+ modifier = modifier.buttonSizeModifier(),
+ onLongClick = onLongClick,
+ onLongClickLabel = onLongClickLabel,
+ enabled = enabled,
+ shape = shape,
+ labelFont = FilledButtonTokens.LabelFont.value,
+ colors = colors,
+ border = border,
+ contentPadding = contentPadding,
+ interactionSource = interactionSource,
+ content = content
+ )
/**
- * Base level Wear Material3 [FilledTonalButton] that offers a single slot to take any content.
- * Used as the container for more opinionated [FilledTonalButton] components that take specific
- * content such as icons and labels.
+ * Base level Wear Material3 [FilledTonalButton] that offers a single slot to take any content. Used
+ * as the container for more opinionated [FilledTonalButton] components that take specific content
+ * such as icons and labels.
*
* The [FilledTonalButton] is Stadium-shaped by default and has a max height designed to take no
- * more than two lines of text of [Typography.labelMedium] style.
- * With localisation and/or large font sizes, the text can extend to a maximum of 3 lines in which
- * case, the [FilledTonalButton] height adjusts to accommodate the contents.
- * The [FilledTonalButton] can have an icon or image horizontally parallel to the two lines of text.
+ * more than two lines of text of [Typography.labelMedium] style. With localisation and/or large
+ * font sizes, the text can extend to a maximum of 3 lines in which case, the [FilledTonalButton]
+ * height adjusts to accommodate the contents. The [FilledTonalButton] can have an icon or image
+ * horizontally parallel to the two lines of text.
*
* [FilledTonalButton] takes the [ButtonDefaults.filledTonalButtonColors] color scheme by default,
* with muted background, contrasting content color and no border. This is a medium-emphasis button
* for important actions that don't distract from other onscreen elements, such as final or
* unblocking actions in a flow with less emphasis than [Button].
*
- * Other recommended buttons with [ButtonColors] for different levels of emphasis are:
- * [Button] which defaults to [ButtonDefaults.buttonColors],
- * [OutlinedButton] which defaults to [ButtonDefaults.outlinedButtonColors] and
- * [ChildButton] which defaults to [ButtonDefaults.childButtonColors].
- * Buttons can also take an image background using [ButtonDefaults.imageBackgroundButtonColors].
+ * Other recommended buttons with [ButtonColors] for different levels of emphasis are: [Button]
+ * which defaults to [ButtonDefaults.buttonColors], [OutlinedButton] which defaults to
+ * [ButtonDefaults.outlinedButtonColors] and [ChildButton] which defaults to
+ * [ButtonDefaults.childButtonColors]. Buttons can also take an image background using
+ * [ButtonDefaults.imageBackgroundButtonColors].
*
* Button can be enabled or disabled. A disabled button will not respond to click events.
*
- * TODO(b/261838497) Add Material3 UX guidance links
- *
* Example of a [FilledTonalButton]:
+ *
* @sample androidx.wear.compose.material3.samples.SimpleFilledTonalButtonSample
*
* Example of a [FilledTonalButton] with onLongClick:
+ *
* @sample androidx.wear.compose.material3.samples.FilledTonalButtonWithOnLongClick
*
* @param onClick Will be called when the user clicks the button
* @param modifier Modifier to be applied to the button
- * @param onLongClick Called when this button is long clicked (long-pressed). When this callback
- * is set, [onLongClickLabel] should be set as well.
+ * @param onLongClick Called when this button is long clicked (long-pressed). When this callback is
+ * set, [onLongClickLabel] should be set as well.
* @param onLongClickLabel Semantic / accessibility label for the [onLongClick] action.
- * @param enabled Controls the enabled state of the button. When `false`, this button will not
- * be clickable
+ * @param enabled Controls the enabled state of the button. When `false`, this button will not be
+ * clickable
* @param shape Defines the button's shape. It is strongly recommended to use the default as this
- * shape is a key characteristic of the Wear Material3 Theme
+ * shape is a key characteristic of the Wear Material3 Theme
* @param colors [ButtonColors] that will be used to resolve the background and content color for
- * this button in different states. See [ButtonDefaults.filledTonalButtonColors].
- * @param border Optional [BorderStroke] that will be used to resolve the border for this
- * button in different states.
+ * this button in different states. See [ButtonDefaults.filledTonalButtonColors].
+ * @param border Optional [BorderStroke] that will be used to resolve the border for this button in
+ * different states.
* @param contentPadding The spacing values to apply internally between the container and the
- * content
+ * content
* @param interactionSource an optional hoisted [MutableInteractionSource] for observing and
- * emitting [Interaction]s for this button. You can use this to change the button's appearance
- * or preview the button in different states. Note that if `null` is provided, interactions will
- * still happen internally.
+ * emitting [Interaction]s for this button. You can use this to change the button's appearance or
+ * preview the button in different states. Note that if `null` is provided, interactions will
+ * still happen internally.
* @param content Slot for composable body content displayed on the Button
+ *
+ * TODO(b/261838497) Add Material3 UX guidance links
*/
@Composable
fun FilledTonalButton(
@@ -209,72 +214,75 @@
contentPadding: PaddingValues = ButtonDefaults.ContentPadding,
interactionSource: MutableInteractionSource? = null,
content: @Composable RowScope.() -> Unit,
-) = ButtonImpl(
- onClick = onClick,
- modifier = modifier.buttonSizeModifier(),
- onLongClick = onLongClick,
- onLongClickLabel = onLongClickLabel,
- enabled = enabled,
- shape = shape,
- labelFont = FilledTonalButtonTokens.LabelFont.value,
- colors = colors,
- border = border,
- contentPadding = contentPadding,
- interactionSource = interactionSource,
- content = content
-)
+) =
+ ButtonImpl(
+ onClick = onClick,
+ modifier = modifier.buttonSizeModifier(),
+ onLongClick = onLongClick,
+ onLongClickLabel = onLongClickLabel,
+ enabled = enabled,
+ shape = shape,
+ labelFont = FilledTonalButtonTokens.LabelFont.value,
+ colors = colors,
+ border = border,
+ contentPadding = contentPadding,
+ interactionSource = interactionSource,
+ content = content
+ )
/**
* Base level Wear Material3 [OutlinedButton] that offers a single slot to take any content. Used as
- * the container for more opinionated [OutlinedButton] components that take specific content such
- * as icons and labels.
+ * the container for more opinionated [OutlinedButton] components that take specific content such as
+ * icons and labels.
*
* The [OutlinedButton] is Stadium-shaped by default and has a max height designed to take no more
- * than two lines of text of [Typography.labelMedium] style.
- * With localisation and/or large font sizes, the text can extend to a maximum of 3 lines in which
- * case, the [OutlinedButton] height adjusts to accommodate the contents.
- * The [OutlinedButton] can have an icon or image horizontally parallel to the two lines of text.
+ * than two lines of text of [Typography.labelMedium] style. With localisation and/or large font
+ * sizes, the text can extend to a maximum of 3 lines in which case, the [OutlinedButton] height
+ * adjusts to accommodate the contents. The [OutlinedButton] can have an icon or image horizontally
+ * parallel to the two lines of text.
*
- * [OutlinedButton] takes the [ButtonDefaults.outlinedButtonColors] color scheme by default,
- * with a transparent background and a thin border. This is a medium-emphasis button
- * for important, non-primary actions that need attention.
+ * [OutlinedButton] takes the [ButtonDefaults.outlinedButtonColors] color scheme by default, with a
+ * transparent background and a thin border. This is a medium-emphasis button for important,
+ * non-primary actions that need attention.
*
- * Other recommended buttons with [ButtonColors] for different levels of emphasis are:
- * [Button] which defaults to [ButtonDefaults.buttonColors],
- * [FilledTonalButton] which defaults to [ButtonDefaults.filledTonalButtonColors],
- * [ChildButton] which defaults to [ButtonDefaults.childButtonColors].
- * Buttons can also take an image background using [ButtonDefaults.imageBackgroundButtonColors].
+ * Other recommended buttons with [ButtonColors] for different levels of emphasis are: [Button]
+ * which defaults to [ButtonDefaults.buttonColors], [FilledTonalButton] which defaults to
+ * [ButtonDefaults.filledTonalButtonColors], [ChildButton] which defaults to
+ * [ButtonDefaults.childButtonColors]. Buttons can also take an image background using
+ * [ButtonDefaults.imageBackgroundButtonColors].
*
* Button can be enabled or disabled. A disabled button will not respond to click events.
*
- * TODO(b/261838497) Add Material3 UX guidance links
- *
* Example of an [OutlinedButton]:
+ *
* @sample androidx.wear.compose.material3.samples.SimpleOutlinedButtonSample
*
* Example of a [OutlinedButton] with onLongClick:
+ *
* @sample androidx.wear.compose.material3.samples.OutlinedButtonWithOnLongClick
*
* @param onClick Will be called when the user clicks the button
* @param modifier Modifier to be applied to the button
- * @param onLongClick Called when this button is long clicked (long-pressed). When this callback
- * is set, [onLongClickLabel] should be set as well.
+ * @param onLongClick Called when this button is long clicked (long-pressed). When this callback is
+ * set, [onLongClickLabel] should be set as well.
* @param onLongClickLabel Semantic / accessibility label for the [onLongClick] action.
- * @param enabled Controls the enabled state of the button. When `false`, this button will not
- * be clickable
+ * @param enabled Controls the enabled state of the button. When `false`, this button will not be
+ * clickable
* @param shape Defines the button's shape. It is strongly recommended to use the default as this
- * shape is a key characteristic of the Wear Material3 Theme
+ * shape is a key characteristic of the Wear Material3 Theme
* @param colors [ButtonColors] that will be used to resolve the background and content color for
- * this button in different states. See [ButtonDefaults.outlinedButtonColors].
- * @param border Optional [BorderStroke] that will be used to resolve the border for this
- * button in different states. See [ButtonDefaults.outlinedButtonBorder].
+ * this button in different states. See [ButtonDefaults.outlinedButtonColors].
+ * @param border Optional [BorderStroke] that will be used to resolve the border for this button in
+ * different states. See [ButtonDefaults.outlinedButtonBorder].
* @param contentPadding The spacing values to apply internally between the container and the
- * content
+ * content
* @param interactionSource an optional hoisted [MutableInteractionSource] for observing and
- * emitting [Interaction]s for this button. You can use this to change the button's appearance
- * or preview the button in different states. Note that if `null` is provided, interactions will
- * still happen internally.
+ * emitting [Interaction]s for this button. You can use this to change the button's appearance or
+ * preview the button in different states. Note that if `null` is provided, interactions will
+ * still happen internally.
* @param content Slot for composable body content displayed on the OutlinedButton
+ *
+ * TODO(b/261838497) Add Material3 UX guidance links
*/
@Composable
fun OutlinedButton(
@@ -289,72 +297,75 @@
contentPadding: PaddingValues = ButtonDefaults.ContentPadding,
interactionSource: MutableInteractionSource? = null,
content: @Composable RowScope.() -> Unit,
-) = ButtonImpl(
- onClick = onClick,
- modifier = modifier.buttonSizeModifier(),
- onLongClick = onLongClick,
- onLongClickLabel = onLongClickLabel,
- enabled = enabled,
- shape = shape,
- labelFont = OutlinedButtonTokens.LabelFont.value,
- colors = colors,
- border = border,
- contentPadding = contentPadding,
- interactionSource = interactionSource,
- content = content
-)
+) =
+ ButtonImpl(
+ onClick = onClick,
+ modifier = modifier.buttonSizeModifier(),
+ onLongClick = onLongClick,
+ onLongClickLabel = onLongClickLabel,
+ enabled = enabled,
+ shape = shape,
+ labelFont = OutlinedButtonTokens.LabelFont.value,
+ colors = colors,
+ border = border,
+ contentPadding = contentPadding,
+ interactionSource = interactionSource,
+ content = content
+ )
/**
* Base level Wear Material3 [ChildButton] that offers a single slot to take any content. Used as
- * the container for more opinionated [ChildButton] components that take specific content such
- * as icons and labels.
+ * the container for more opinionated [ChildButton] components that take specific content such as
+ * icons and labels.
*
- * The [ChildButton] is stadium-shaped by default and its standard height is designed to
- * take 2 lines of text of [Typography.labelMedium] style.
- * With localisation and/or large font sizes, the text can extend to a maximum of 3 lines in which
- * case, the [ChildButton] height adjusts to accommodate the contents.
- * The [ChildButton] can have an icon or image horizontally parallel to the two lines of text.
+ * The [ChildButton] is stadium-shaped by default and its standard height is designed to take 2
+ * lines of text of [Typography.labelMedium] style. With localisation and/or large font sizes, the
+ * text can extend to a maximum of 3 lines in which case, the [ChildButton] height adjusts to
+ * accommodate the contents. The [ChildButton] can have an icon or image horizontally parallel to
+ * the two lines of text.
*
- * [ChildButton] takes the [ButtonDefaults.childButtonColors] color scheme by default,
- * with a transparent background and no border. This is a low-emphasis button for optional
- * or supplementary actions with the least amount of prominence.
+ * [ChildButton] takes the [ButtonDefaults.childButtonColors] color scheme by default, with a
+ * transparent background and no border. This is a low-emphasis button for optional or supplementary
+ * actions with the least amount of prominence.
*
- * Other recommended buttons with [ButtonColors] for different levels of emphasis are:
- * [Button] which defaults to [ButtonDefaults.buttonColors],
- * [FilledTonalButton] which defaults to [ButtonDefaults.filledTonalButtonColors],
- * [OutlinedButton] which defaults to [ButtonDefaults.outlinedButtonColors] and
- * Buttons can also take an image background using [ButtonDefaults.imageBackgroundButtonColors].
+ * Other recommended buttons with [ButtonColors] for different levels of emphasis are: [Button]
+ * which defaults to [ButtonDefaults.buttonColors], [FilledTonalButton] which defaults to
+ * [ButtonDefaults.filledTonalButtonColors], [OutlinedButton] which defaults to
+ * [ButtonDefaults.outlinedButtonColors] and Buttons can also take an image background using
+ * [ButtonDefaults.imageBackgroundButtonColors].
*
* Button can be enabled or disabled. A disabled button will not respond to click events.
*
- * TODO(b/261838497) Add Material3 UX guidance links
- *
* Example of a [ChildButton]:
+ *
* @sample androidx.wear.compose.material3.samples.SimpleChildButtonSample
*
* Example of a [ChildButton] with onLongClick:
+ *
* @sample androidx.wear.compose.material3.samples.ChildButtonWithOnLongClick
*
* @param onClick Will be called when the user clicks the button
* @param modifier Modifier to be applied to the button
- * @param onLongClick Called when this button is long clicked (long-pressed). When this callback
- * is set, [onLongClickLabel] should be set as well.
+ * @param onLongClick Called when this button is long clicked (long-pressed). When this callback is
+ * set, [onLongClickLabel] should be set as well.
* @param onLongClickLabel Semantic / accessibility label for the [onLongClick] action.
- * @param enabled Controls the enabled state of the button. When `false`, this button will not
- * be clickable
+ * @param enabled Controls the enabled state of the button. When `false`, this button will not be
+ * clickable
* @param shape Defines the button's shape. It is strongly recommended to use the default as this
- * shape is a key characteristic of the Wear Material3 Theme
+ * shape is a key characteristic of the Wear Material3 Theme
* @param colors [ButtonColors] that will be used to resolve the background and content color for
- * this button in different states. See [ButtonDefaults.childButtonColors].
- * @param border Optional [BorderStroke] that will be used to resolve the border for this
- * button in different states.
+ * this button in different states. See [ButtonDefaults.childButtonColors].
+ * @param border Optional [BorderStroke] that will be used to resolve the border for this button in
+ * different states.
* @param contentPadding The spacing values to apply internally between the container and the
- * content
+ * content
* @param interactionSource an optional hoisted [MutableInteractionSource] for observing and
- * emitting [Interaction]s for this button. You can use this to change the button's appearance
- * or preview the button in different states. Note that if `null` is provided, interactions will
- * still happen internally.
+ * emitting [Interaction]s for this button. You can use this to change the button's appearance or
+ * preview the button in different states. Note that if `null` is provided, interactions will
+ * still happen internally.
* @param content Slot for composable body content displayed on the ChildButton
+ *
+ * TODO(b/261838497) Add Material3 UX guidance links
*/
@Composable
fun ChildButton(
@@ -369,82 +380,81 @@
contentPadding: PaddingValues = ButtonDefaults.ContentPadding,
interactionSource: MutableInteractionSource? = null,
content: @Composable RowScope.() -> Unit,
-) = ButtonImpl(
- onClick = onClick,
- modifier = modifier.buttonSizeModifier(),
- onLongClick = onLongClick,
- onLongClickLabel = onLongClickLabel,
- enabled = enabled,
- shape = shape,
- labelFont = OutlinedButtonTokens.LabelFont.value,
- colors = colors,
- border = border,
- contentPadding = contentPadding,
- interactionSource = interactionSource,
- content = content
-)
+) =
+ ButtonImpl(
+ onClick = onClick,
+ modifier = modifier.buttonSizeModifier(),
+ onLongClick = onLongClick,
+ onLongClickLabel = onLongClickLabel,
+ enabled = enabled,
+ shape = shape,
+ labelFont = OutlinedButtonTokens.LabelFont.value,
+ colors = colors,
+ border = border,
+ contentPadding = contentPadding,
+ interactionSource = interactionSource,
+ content = content
+ )
/**
- * Wear Material3 [Button] that offers three slots and a specific layout for an
- * icon, label and secondaryLabel. The icon and secondaryLabel are optional.
- * The items are laid out with the icon, if provided, at the start of a row, with a column next
- * containing the two label slots.
+ * Wear Material3 [Button] that offers three slots and a specific layout for an icon, label and
+ * secondaryLabel. The icon and secondaryLabel are optional. The items are laid out with the icon,
+ * if provided, at the start of a row, with a column next containing the two label slots.
*
* The [Button] is stadium-shaped by default and its standard height is designed to take 2 lines of
- * text of [Typography.labelMedium] style - either a two-line label or both a single line label
- * and a secondary label.
- * With localisation and/or large font sizes, the [Button] height adjusts to
+ * text of [Typography.labelMedium] style - either a two-line label or both a single line label and
+ * a secondary label. With localisation and/or large font sizes, the [Button] height adjusts to
* accommodate the contents. The label and secondary label should be consistently aligned.
*
* If a icon is provided then the labels should be "start" aligned, e.g. left aligned in ltr so that
* the text starts next to the icon.
*
- * [Button] takes the [ButtonDefaults.buttonColors] color scheme by default,
- * with colored background, contrasting content color and no border. This is a high-emphasis button
- * for the primary, most important or most common action on a screen.
+ * [Button] takes the [ButtonDefaults.buttonColors] color scheme by default, with colored
+ * background, contrasting content color and no border. This is a high-emphasis button for the
+ * primary, most important or most common action on a screen.
*
* Other recommended buttons with [ButtonColors] for different levels of emphasis are:
- * [FilledTonalButton] which defaults to [ButtonDefaults.filledTonalButtonColors],
- * [OutlinedButton] which defaults to [ButtonDefaults.outlinedButtonColors] and
- * [ChildButton] which defaults to [ButtonDefaults.childButtonColors].
- * Buttons can also take an image background using [ButtonDefaults.imageBackgroundButtonColors].
+ * [FilledTonalButton] which defaults to [ButtonDefaults.filledTonalButtonColors], [OutlinedButton]
+ * which defaults to [ButtonDefaults.outlinedButtonColors] and [ChildButton] which defaults to
+ * [ButtonDefaults.childButtonColors]. Buttons can also take an image background using
+ * [ButtonDefaults.imageBackgroundButtonColors].
*
* [Button] can be enabled or disabled. A disabled button will not respond to click events.
*
- * TODO(b/261838497) Add Material3 UX guidance links
- *
* Example of a [Button] with an icon and secondary label:
+ *
* @sample androidx.wear.compose.material3.samples.ButtonSample
*
* @param onClick Will be called when the user clicks the button
* @param modifier Modifier to be applied to the button
- * @param onLongClick Called when this button is long clicked (long-pressed). When this callback
- * is set, [onLongClickLabel] should be set as well.
+ * @param onLongClick Called when this button is long clicked (long-pressed). When this callback is
+ * set, [onLongClickLabel] should be set as well.
* @param onLongClickLabel Semantic / accessibility label for the [onLongClick] action.
* @param secondaryLabel A slot for providing the button's secondary label. The contents are
- * expected to be text which is "start" aligned if there is an icon preset and
- * "start" or "center" aligned if not.
- * label and secondaryLabel contents should be consistently aligned.
+ * expected to be text which is "start" aligned if there is an icon preset and "start" or "center"
+ * aligned if not. label and secondaryLabel contents should be consistently aligned.
* @param icon A slot for providing the button's icon. The contents are expected to be a
- * horizontally and vertically aligned icon of size [ButtonDefaults.IconSize] or
- * [ButtonDefaults.LargeIconSize].
- * @param enabled Controls the enabled state of the button. When `false`, this button will not
- * be clickable
+ * horizontally and vertically aligned icon of size [ButtonDefaults.IconSize] or
+ * [ButtonDefaults.LargeIconSize].
+ * @param enabled Controls the enabled state of the button. When `false`, this button will not be
+ * clickable
* @param shape Defines the button's shape. It is strongly recommended to use the default as this
- * shape is a key characteristic of the Wear Material3 Theme
+ * shape is a key characteristic of the Wear Material3 Theme
* @param colors [ButtonColors] that will be used to resolve the background and content color for
- * this button in different states. See [ButtonDefaults.buttonColors]. Defaults to
- * [ButtonDefaults.buttonColors]
- * @param border Optional [BorderStroke] that will be used to resolve the button border in
- * different states.
+ * this button in different states. See [ButtonDefaults.buttonColors]. Defaults to
+ * [ButtonDefaults.buttonColors]
+ * @param border Optional [BorderStroke] that will be used to resolve the button border in different
+ * states.
* @param contentPadding The spacing values to apply internally between the container and the
- * content
+ * content
* @param interactionSource an optional hoisted [MutableInteractionSource] for observing and
- * emitting [Interaction]s for this button. You can use this to change the button's appearance
- * or preview the button in different states. Note that if `null` is provided, interactions will
- * still happen internally.
+ * emitting [Interaction]s for this button. You can use this to change the button's appearance or
+ * preview the button in different states. Note that if `null` is provided, interactions will
+ * still happen internally.
* @param label A slot for providing the button's main label. The contents are expected to be text
- * which is "start" aligned if there is an icon preset and "start" or "center" aligned if not.
+ * which is "start" aligned if there is an icon preset and "start" or "center" aligned if not.
+ *
+ * TODO(b/261838497) Add Material3 UX guidance links
*/
@Composable
fun Button(
@@ -461,35 +471,35 @@
contentPadding: PaddingValues = ButtonDefaults.ContentPadding,
interactionSource: MutableInteractionSource? = null,
label: @Composable RowScope.() -> Unit,
-) = ButtonImpl(
- onClick = onClick,
- modifier = modifier.buttonSizeModifier(),
- onLongClick = onLongClick,
- onLongClickLabel = onLongClickLabel,
- secondaryLabel = secondaryLabel,
- icon = icon,
- enabled = enabled,
- shape = shape,
- labelFont = FilledButtonTokens.LabelFont.value,
- secondaryLabelFont = FilledButtonTokens.SecondaryLabelFont.value,
- colors = colors,
- border = border,
- contentPadding = contentPadding,
- interactionSource = interactionSource,
- label = label
-)
+) =
+ ButtonImpl(
+ onClick = onClick,
+ modifier = modifier.buttonSizeModifier(),
+ onLongClick = onLongClick,
+ onLongClickLabel = onLongClickLabel,
+ secondaryLabel = secondaryLabel,
+ icon = icon,
+ enabled = enabled,
+ shape = shape,
+ labelFont = FilledButtonTokens.LabelFont.value,
+ secondaryLabelFont = FilledButtonTokens.SecondaryLabelFont.value,
+ colors = colors,
+ border = border,
+ contentPadding = contentPadding,
+ interactionSource = interactionSource,
+ label = label
+ )
/**
- * Wear Material3 [FilledTonalButton] that offers three slots and a specific layout for an
- * icon, label and secondaryLabel. The icon and secondaryLabel are optional.
- * The items are laid out with the icon, if provided, at the start of a row, with a column next
- * containing the two label slots.
+ * Wear Material3 [FilledTonalButton] that offers three slots and a specific layout for an icon,
+ * label and secondaryLabel. The icon and secondaryLabel are optional. The items are laid out with
+ * the icon, if provided, at the start of a row, with a column next containing the two label slots.
*
* The [FilledTonalButton] is stadium-shaped by default and its standard height is designed to take
- * 2 lines of text of [Typography.labelMedium] style - either a two-line label or both a single
- * line label and a secondary label.
- * With localisation and/or large font sizes, the [FilledTonalButton] height adjusts
- * to accommodate the contents. The label and secondary label should be consistently aligned.
+ * 2 lines of text of [Typography.labelMedium] style - either a two-line label or both a single line
+ * label and a secondary label. With localisation and/or large font sizes, the [FilledTonalButton]
+ * height adjusts to accommodate the contents. The label and secondary label should be consistently
+ * aligned.
*
* If a icon is provided then the labels should be "start" aligned, e.g. left aligned in ltr so that
* the text starts next to the icon.
@@ -502,48 +512,48 @@
* for important actions that don't distract from other onscreen elements, such as final or
* unblocking actions in a flow with less emphasis than [Button].
*
- * Other recommended buttons with [ButtonColors] for different levels of emphasis are:
- * [Button] which defaults to [ButtonDefaults.buttonColors],
- * [OutlinedButton] which defaults to [ButtonDefaults.outlinedButtonColors] and
- * [ChildButton] which defaults to [ButtonDefaults.childButtonColors].
- * Buttons can also take an image background using [ButtonDefaults.imageBackgroundButtonColors].
+ * Other recommended buttons with [ButtonColors] for different levels of emphasis are: [Button]
+ * which defaults to [ButtonDefaults.buttonColors], [OutlinedButton] which defaults to
+ * [ButtonDefaults.outlinedButtonColors] and [ChildButton] which defaults to
+ * [ButtonDefaults.childButtonColors]. Buttons can also take an image background using
+ * [ButtonDefaults.imageBackgroundButtonColors].
*
- * [FilledTonalButton] can be enabled or disabled. A disabled button will not respond to
- * click events.
- *
- * TODO(b/261838497) Add Material3 UX guidance links
+ * [FilledTonalButton] can be enabled or disabled. A disabled button will not respond to click
+ * events.
*
* Example of a [FilledTonalButton] with an icon and secondary label:
+ *
* @sample androidx.wear.compose.material3.samples.FilledTonalButtonSample
*
* @param onClick Will be called when the user clicks the button
* @param modifier Modifier to be applied to the button
- * @param onLongClick Called when this button is long clicked (long-pressed). When this callback
- * is set, [onLongClickLabel] should be set as well.
+ * @param onLongClick Called when this button is long clicked (long-pressed). When this callback is
+ * set, [onLongClickLabel] should be set as well.
* @param onLongClickLabel Semantic / accessibility label for the [onLongClick] action.
* @param secondaryLabel A slot for providing the button's secondary label. The contents are
- * expected to be text which is "start" aligned if there is an icon preset and
- * "start" or "center" aligned if not.
- * label and secondaryLabel contents should be consistently aligned.
+ * expected to be text which is "start" aligned if there is an icon preset and "start" or "center"
+ * aligned if not. label and secondaryLabel contents should be consistently aligned.
* @param icon A slot for providing the button's icon. The contents are expected to be a
- * horizontally and vertically aligned icon of size [ButtonDefaults.IconSize] or
- * [ButtonDefaults.LargeIconSize].
- * @param enabled Controls the enabled state of the button. When `false`, this button will not
- * be clickable
+ * horizontally and vertically aligned icon of size [ButtonDefaults.IconSize] or
+ * [ButtonDefaults.LargeIconSize].
+ * @param enabled Controls the enabled state of the button. When `false`, this button will not be
+ * clickable
* @param shape Defines the button's shape. It is strongly recommended to use the default as this
- * shape is a key characteristic of the Wear Material3 Theme
+ * shape is a key characteristic of the Wear Material3 Theme
* @param colors [ButtonColors] that will be used to resolve the background and content color for
- * this button in different states. See [ButtonDefaults.filledTonalButtonColors].
- * @param border Optional [BorderStroke] that will be used to resolve the button border in
- * different states.
+ * this button in different states. See [ButtonDefaults.filledTonalButtonColors].
+ * @param border Optional [BorderStroke] that will be used to resolve the button border in different
+ * states.
* @param contentPadding The spacing values to apply internally between the container and the
- * content
+ * content
* @param interactionSource an optional hoisted [MutableInteractionSource] for observing and
- * emitting [Interaction]s for this button. You can use this to change the button's appearance
- * or preview the button in different states. Note that if `null` is provided, interactions will
- * still happen internally.
+ * emitting [Interaction]s for this button. You can use this to change the button's appearance or
+ * preview the button in different states. Note that if `null` is provided, interactions will
+ * still happen internally.
* @param label A slot for providing the button's main label. The contents are expected to be text
- * which is "start" aligned if there is an icon preset and "start" or "center" aligned if not.
+ * which is "start" aligned if there is an icon preset and "start" or "center" aligned if not.
+ *
+ * TODO(b/261838497) Add Material3 UX guidance links
*/
@Composable
fun FilledTonalButton(
@@ -560,84 +570,84 @@
contentPadding: PaddingValues = ButtonDefaults.ContentPadding,
interactionSource: MutableInteractionSource? = null,
label: @Composable RowScope.() -> Unit,
-) = ButtonImpl(
- onClick = onClick,
- modifier = modifier.buttonSizeModifier(),
- onLongClick = onLongClick,
- onLongClickLabel = onLongClickLabel,
- secondaryLabel = secondaryLabel,
- icon = icon,
- enabled = enabled,
- shape = shape,
- labelFont = FilledTonalButtonTokens.LabelFont.value,
- secondaryLabelFont = FilledTonalButtonTokens.SecondaryLabelFont.value,
- colors = colors,
- border = border,
- contentPadding = contentPadding,
- interactionSource = interactionSource,
- label = label
-)
+) =
+ ButtonImpl(
+ onClick = onClick,
+ modifier = modifier.buttonSizeModifier(),
+ onLongClick = onLongClick,
+ onLongClickLabel = onLongClickLabel,
+ secondaryLabel = secondaryLabel,
+ icon = icon,
+ enabled = enabled,
+ shape = shape,
+ labelFont = FilledTonalButtonTokens.LabelFont.value,
+ secondaryLabelFont = FilledTonalButtonTokens.SecondaryLabelFont.value,
+ colors = colors,
+ border = border,
+ contentPadding = contentPadding,
+ interactionSource = interactionSource,
+ label = label
+ )
/**
- * Wear Material3 [OutlinedButton] that offers three slots and a specific layout for an
- * icon, label and secondaryLabel. The icon and secondaryLabel are optional.
- * The items are laid out with the icon, if provided, at the start of a row, with a column next
- * containing the two label slots.
+ * Wear Material3 [OutlinedButton] that offers three slots and a specific layout for an icon, label
+ * and secondaryLabel. The icon and secondaryLabel are optional. The items are laid out with the
+ * icon, if provided, at the start of a row, with a column next containing the two label slots.
*
- * The [OutlinedButton] is stadium-shaped by default and its standard height is designed to take
- * 2 lines of text of [Typography.labelMedium] style - either a two-line label or both a single
- * line label and a secondary label.
- * With localisation and/or large font sizes, the [OutlinedButton] height adjusts to
- * accommodate the contents. The label and secondary label should be consistently aligned.
+ * The [OutlinedButton] is stadium-shaped by default and its standard height is designed to take 2
+ * lines of text of [Typography.labelMedium] style - either a two-line label or both a single line
+ * label and a secondary label. With localisation and/or large font sizes, the [OutlinedButton]
+ * height adjusts to accommodate the contents. The label and secondary label should be consistently
+ * aligned.
*
* If a icon is provided then the labels should be "start" aligned, e.g. left aligned in ltr so that
* the text starts next to the icon.
*
- * [OutlinedButton] takes the [ButtonDefaults.outlinedButtonColors] color scheme by default,
- * with a transparent background and a thin border. This is a medium-emphasis button
- * for important, non-primary actions that need attention.
+ * [OutlinedButton] takes the [ButtonDefaults.outlinedButtonColors] color scheme by default, with a
+ * transparent background and a thin border. This is a medium-emphasis button for important,
+ * non-primary actions that need attention.
*
- * Other recommended buttons with [ButtonColors] for different levels of emphasis are:
- * [Button] which defaults to [ButtonDefaults.buttonColors],
- * [FilledTonalButton] which defaults to [ButtonDefaults.filledTonalButtonColors],
- * [ChildButton] which defaults to [ButtonDefaults.childButtonColors].
- * Buttons can also take an image background using [ButtonDefaults.imageBackgroundButtonColors].
+ * Other recommended buttons with [ButtonColors] for different levels of emphasis are: [Button]
+ * which defaults to [ButtonDefaults.buttonColors], [FilledTonalButton] which defaults to
+ * [ButtonDefaults.filledTonalButtonColors], [ChildButton] which defaults to
+ * [ButtonDefaults.childButtonColors]. Buttons can also take an image background using
+ * [ButtonDefaults.imageBackgroundButtonColors].
*
* [OutlinedButton] can be enabled or disabled. A disabled button will not respond to click events.
*
- * TODO(b/261838497) Add Material3 UX guidance links
- *
* Example of an [OutlinedButton] with an icon and secondary label:
+ *
* @sample androidx.wear.compose.material3.samples.OutlinedButtonSample
*
* @param onClick Will be called when the user clicks the button
* @param modifier Modifier to be applied to the button
- * @param onLongClick Called when this button is long clicked (long-pressed). When this callback
- * is set, [onLongClickLabel] should be set as well.
+ * @param onLongClick Called when this button is long clicked (long-pressed). When this callback is
+ * set, [onLongClickLabel] should be set as well.
* @param onLongClickLabel Semantic / accessibility label for the [onLongClick] action.
* @param secondaryLabel A slot for providing the button's secondary label. The contents are
- * expected to be text which is "start" aligned if there is an icon preset and
- * "start" or "center" aligned if not.
- * label and secondaryLabel contents should be consistently aligned.
+ * expected to be text which is "start" aligned if there is an icon preset and "start" or "center"
+ * aligned if not. label and secondaryLabel contents should be consistently aligned.
* @param icon A slot for providing the button's icon. The contents are expected to be a
- * horizontally and vertically aligned icon of size [ButtonDefaults.IconSize] or
- * [ButtonDefaults.LargeIconSize].
- * @param enabled Controls the enabled state of the button. When `false`, this button will not
- * be clickable
+ * horizontally and vertically aligned icon of size [ButtonDefaults.IconSize] or
+ * [ButtonDefaults.LargeIconSize].
+ * @param enabled Controls the enabled state of the button. When `false`, this button will not be
+ * clickable
* @param shape Defines the button's shape. It is strongly recommended to use the default as this
- * shape is a key characteristic of the Wear Material3 Theme
+ * shape is a key characteristic of the Wear Material3 Theme
* @param colors [ButtonColors] that will be used to resolve the background and content color for
- * this button in different states. See [ButtonDefaults.outlinedButtonColors].
- * @param border Optional [BorderStroke] that will be used to resolve the button border in
- * different states. See [ButtonDefaults.outlinedButtonBorder].
+ * this button in different states. See [ButtonDefaults.outlinedButtonColors].
+ * @param border Optional [BorderStroke] that will be used to resolve the button border in different
+ * states. See [ButtonDefaults.outlinedButtonBorder].
* @param contentPadding The spacing values to apply internally between the container and the
- * content
+ * content
* @param interactionSource an optional hoisted [MutableInteractionSource] for observing and
- * emitting [Interaction]s for this button. You can use this to change the button's appearance
- * or preview the button in different states. Note that if `null` is provided, interactions will
- * still happen internally.
+ * emitting [Interaction]s for this button. You can use this to change the button's appearance or
+ * preview the button in different states. Note that if `null` is provided, interactions will
+ * still happen internally.
* @param label A slot for providing the button's main label. The contents are expected to be text
- * which is "start" aligned if there is an icon preset and "start" or "center" aligned if not.
+ * which is "start" aligned if there is an icon preset and "start" or "center" aligned if not.
+ *
+ * TODO(b/261838497) Add Material3 UX guidance links
*/
@Composable
fun OutlinedButton(
@@ -654,83 +664,84 @@
contentPadding: PaddingValues = ButtonDefaults.ContentPadding,
interactionSource: MutableInteractionSource? = null,
label: @Composable RowScope.() -> Unit,
-) = ButtonImpl(
- onClick = onClick,
- modifier = modifier.buttonSizeModifier(),
- onLongClick = onLongClick,
- onLongClickLabel = onLongClickLabel,
- secondaryLabel = secondaryLabel,
- icon = icon,
- enabled = enabled,
- shape = shape,
- labelFont = OutlinedButtonTokens.LabelFont.value,
- secondaryLabelFont = OutlinedButtonTokens.SecondaryLabelFont.value,
- colors = colors,
- border = border,
- contentPadding = contentPadding,
- interactionSource = interactionSource,
- label = label
-)
+) =
+ ButtonImpl(
+ onClick = onClick,
+ modifier = modifier.buttonSizeModifier(),
+ onLongClick = onLongClick,
+ onLongClickLabel = onLongClickLabel,
+ secondaryLabel = secondaryLabel,
+ icon = icon,
+ enabled = enabled,
+ shape = shape,
+ labelFont = OutlinedButtonTokens.LabelFont.value,
+ secondaryLabelFont = OutlinedButtonTokens.SecondaryLabelFont.value,
+ colors = colors,
+ border = border,
+ contentPadding = contentPadding,
+ interactionSource = interactionSource,
+ label = label
+ )
/**
* Wear Material3 [ChildButton] that offers three slots and a specific layout for an icon, label and
* secondaryLabel. The icon and secondaryLabel are optional. The items are laid out with the icon,
* if provided, at the start of a row, with a column next containing the two label slots.
*
- * The [ChildButton] is stadium-shaped by default and its standard height is designed to take
- * 2 lines of text of [Typography.labelMedium] style - either a two-line label or both a single
- * line label and a secondary label.
- * With localisation and/or large font sizes, the [ChildButton] height adjusts to
- * accommodate the contents. The label and secondary label should be consistently aligned.
+ * The [ChildButton] is stadium-shaped by default and its standard height is designed to take 2
+ * lines of text of [Typography.labelMedium] style - either a two-line label or both a single line
+ * label and a secondary label. With localisation and/or large font sizes, the [ChildButton] height
+ * adjusts to accommodate the contents. The label and secondary label should be consistently
+ * aligned.
*
* If a icon is provided then the labels should be "start" aligned, e.g. left aligned in ltr so that
* the text starts next to the icon.
*
- * [ChildButton] takes the [ButtonDefaults.childButtonColors] color scheme by default,
- * with a transparent background and no border. This is a low-emphasis button for optional
- * or supplementary actions with the least amount of prominence.
+ * [ChildButton] takes the [ButtonDefaults.childButtonColors] color scheme by default, with a
+ * transparent background and no border. This is a low-emphasis button for optional or supplementary
+ * actions with the least amount of prominence.
*
- * Other recommended buttons with [ButtonColors] for different levels of emphasis are:
- * [Button] which defaults to [ButtonDefaults.buttonColors],
- * [FilledTonalButton] which defaults to [ButtonDefaults.filledTonalButtonColors],
- * [OutlinedButton] which defaults to [ButtonDefaults.outlinedButtonColors].
- * Buttons can also take an image background using [ButtonDefaults.imageBackgroundButtonColors].
+ * Other recommended buttons with [ButtonColors] for different levels of emphasis are: [Button]
+ * which defaults to [ButtonDefaults.buttonColors], [FilledTonalButton] which defaults to
+ * [ButtonDefaults.filledTonalButtonColors], [OutlinedButton] which defaults to
+ * [ButtonDefaults.outlinedButtonColors]. Buttons can also take an image background using
+ * [ButtonDefaults.imageBackgroundButtonColors].
*
* [Button] can be enabled or disabled. A disabled button will not respond to click events.
*
- * TODO(b/261838497) Add Material3 UX guidance links
- *
* Example of a [ChildButton] with an icon and secondary label:
+ *
* @sample androidx.wear.compose.material3.samples.ChildButtonSample
*
* @param onClick Will be called when the user clicks the button
* @param modifier Modifier to be applied to the button
- * @param onLongClick Called when this button is long clicked (long-pressed). When this callback
- * is set, [onLongClickLabel] should be set as well.
+ * @param onLongClick Called when this button is long clicked (long-pressed). When this callback is
+ * set, [onLongClickLabel] should be set as well.
* @param onLongClickLabel Semantic / accessibility label for the [onLongClick] action.
* @param secondaryLabel A slot for providing the button's secondary label. The contents are
- * expected to be text which is "start" aligned if there is an icon preset and
- * "start" or "center" aligned if not.
- * label and secondaryLabel contents should be consistently aligned.
+ * expected to be text which is "start" aligned if there is an icon preset and "start" or "center"
+ * aligned if not. label and secondaryLabel contents should be consistently aligned.
* @param icon A slot for providing the button's icon. The contents are expected to be a
- * horizontally and vertically aligned icon of size [ButtonDefaults.IconSize] or
- * [ButtonDefaults.LargeIconSize].
- * @param enabled Controls the enabled state of the button. When `false`, this button will not
- * be clickable
+ * horizontally and vertically aligned icon of size [ButtonDefaults.IconSize] or
+ * [ButtonDefaults.LargeIconSize].
+ * @param enabled Controls the enabled state of the button. When `false`, this button will not be
+ * clickable
* @param shape Defines the button's shape. It is strongly recommended to use the default as this
- * shape is a key characteristic of the Wear Material3 Theme
+ * shape is a key characteristic of the Wear Material3 Theme
* @param colors [ButtonColors] that will be used to resolve the background and content color for
- * this button in different states. See [ButtonDefaults.childButtonColors].
- * @param border Optional [BorderStroke] that will be used to resolve the button border in
- * different states.
+ * this button in different states. See [ButtonDefaults.childButtonColors].
+ * @param border Optional [BorderStroke] that will be used to resolve the button border in different
+ * states.
* @param contentPadding The spacing values to apply internally between the container and the
- * content
+ * content
* @param interactionSource an optional hoisted [MutableInteractionSource] for observing and
- * emitting [Interaction]s for this button. You can use this to change the button's appearance
- * or preview the button in different states. Note that if `null` is provided, interactions will
- * still happen internally.
+ * emitting [Interaction]s for this button. You can use this to change the button's appearance or
+ * preview the button in different states. Note that if `null` is provided, interactions will
+ * still happen internally.
* @param label A slot for providing the button's main label. The contents are expected to be text
- * which is "start" aligned if there is an icon preset and "start" or "center" aligned if not.
+ * which is "start" aligned if there is an icon preset and "start" or "center" aligned if not.
+ *
+ * TODO(b/261838497) Add Material3 UX guidance links
*/
@Composable
fun ChildButton(
@@ -747,103 +758,104 @@
contentPadding: PaddingValues = ButtonDefaults.ContentPadding,
interactionSource: MutableInteractionSource? = null,
label: @Composable RowScope.() -> Unit,
-) = ButtonImpl(
- onClick = onClick,
- modifier = modifier.buttonSizeModifier(),
- onLongClick = onLongClick,
- onLongClickLabel = onLongClickLabel,
- secondaryLabel = secondaryLabel,
- icon = icon,
- enabled = enabled,
- shape = shape,
- labelFont = ChildButtonTokens.LabelFont.value,
- secondaryLabelFont = ChildButtonTokens.SecondaryLabelFont.value,
- colors = colors,
- border = border,
- contentPadding = contentPadding,
- interactionSource = interactionSource,
- label = label
-)
+) =
+ ButtonImpl(
+ onClick = onClick,
+ modifier = modifier.buttonSizeModifier(),
+ onLongClick = onLongClick,
+ onLongClickLabel = onLongClickLabel,
+ secondaryLabel = secondaryLabel,
+ icon = icon,
+ enabled = enabled,
+ shape = shape,
+ labelFont = ChildButtonTokens.LabelFont.value,
+ secondaryLabelFont = ChildButtonTokens.SecondaryLabelFont.value,
+ colors = colors,
+ border = border,
+ contentPadding = contentPadding,
+ interactionSource = interactionSource,
+ label = label
+ )
/**
- * A Wear Material3 [CompactButton] that offers two slots and a specific layout for an
- * icon and label. Both the icon and label are optional however it is expected that at least one
- * will be provided.
+ * A Wear Material3 [CompactButton] that offers two slots and a specific layout for an icon and
+ * label. Both the icon and label are optional however it is expected that at least one will be
+ * provided.
*
- * The [CompactButton] is Stadium shaped and has a max height designed to take no more
- * than one line of text and/or one icon. The default max height
- * is [ButtonDefaults.CompactButtonHeight]. This includes a visible button height of 32.dp
- * and 8.dp of padding above and below the button in order to meet accessibility guidelines that
- * request a minimum of 48.dp height and width of tappable area.
+ * The [CompactButton] is Stadium shaped and has a max height designed to take no more than one line
+ * of text and/or one icon. The default max height is [ButtonDefaults.CompactButtonHeight]. This
+ * includes a visible button height of 32.dp and 8.dp of padding above and below the button in order
+ * to meet accessibility guidelines that request a minimum of 48.dp height and width of tappable
+ * area.
*
* If an icon is provided then the labels should be "start" aligned, e.g. left aligned in
* left-to-right mode so that the text starts next to the icon.
*
* The items are laid out as follows.
- *
- * 1. If a label is provided then the button will be laid out with the optional icon at the
- * start of a row followed by the label with a default max height of
- * [ButtonDefaults.CompactButtonHeight].
- *
+ * 1. If a label is provided then the button will be laid out with the optional icon at the start of
+ * a row followed by the label with a default max height of [ButtonDefaults.CompactButtonHeight].
* 2. If only an icon is provided it will be laid out vertically and horizontally centered with a
- * default height of [ButtonDefaults.CompactButtonHeight] and the default width of
- * [ButtonDefaults.IconOnlyCompactButtonWidth]
+ * default height of [ButtonDefaults.CompactButtonHeight] and the default width of
+ * [ButtonDefaults.IconOnlyCompactButtonWidth]
*
* If neither icon nor label is provided then the button will displayed like an icon only button but
* with no contents or background color.
*
- * [CompactButton] takes the [ButtonDefaults.buttonColors] color scheme by default,
- * with colored background, contrasting content color and no border. This is a high-emphasis button
- * for the primary, most important or most common action on a screen.
+ * [CompactButton] takes the [ButtonDefaults.buttonColors] color scheme by default, with colored
+ * background, contrasting content color and no border. This is a high-emphasis button for the
+ * primary, most important or most common action on a screen.
*
* Other recommended [ButtonColors] for different levels of emphasis are:
* [ButtonDefaults.filledTonalButtonColors], [ButtonDefaults.outlinedButtonColors] and
- * [ButtonDefaults.childButtonColors].
- * Buttons can also take an image background using [ButtonDefaults.imageBackgroundButtonColors].
+ * [ButtonDefaults.childButtonColors]. Buttons can also take an image background using
+ * [ButtonDefaults.imageBackgroundButtonColors].
*
- * [CompactButton] can be enabled or disabled. A disabled button will not respond
- * to click events.
- *
- * TODO(b/261838497) Add Material3 samples and UX guidance links
+ * [CompactButton] can be enabled or disabled. A disabled button will not respond to click events.
*
* Example of a [CompactButton] with an icon and a label
+ *
* @sample androidx.wear.compose.material3.samples.CompactButtonSample
*
* Example of a [CompactButton] with an icon and label and with
* [ButtonDefaults.filledTonalButtonColors]
+ *
* @sample androidx.wear.compose.material3.samples.FilledTonalCompactButtonSample
*
* Example of a [CompactButton] with an icon and label and with
* [ButtonDefaults.outlinedButtonBorder] and [ButtonDefaults.outlinedButtonColors]
+ *
* @sample androidx.wear.compose.material3.samples.OutlinedCompactButtonSample
*
* Example of a [CompactButton] with onLongClick:
+ *
* @sample androidx.wear.compose.material3.samples.CompactButtonWithOnLongClick
*
* @param onClick Will be called when the user clicks the button
* @param modifier Modifier to be applied to the button
- * @param onLongClick Called when this button is long clicked (long-pressed). When this callback
- * is set, [onLongClickLabel] should be set as well.
+ * @param onLongClick Called when this button is long clicked (long-pressed). When this callback is
+ * set, [onLongClickLabel] should be set as well.
* @param onLongClickLabel Semantic / accessibility label for the [onLongClick] action.
* @param label A slot for providing the button's main label. The contents are expected to be text
- * which is "start" aligned if there is an icon preset and "center" aligned if not.
+ * which is "start" aligned if there is an icon preset and "center" aligned if not.
* @param icon A slot for providing the button's icon. The contents are expected to be a
- * horizontally and vertically aligned icon of size [ButtonDefaults.SmallIconSize] when used
- * with a label or [ButtonDefaults.IconSize] when used as the only content in the button.
+ * horizontally and vertically aligned icon of size [ButtonDefaults.SmallIconSize] when used with
+ * a label or [ButtonDefaults.IconSize] when used as the only content in the button.
* @param colors [ButtonColors] that will be used to resolve the background and content color for
- * this button in different states. See [ButtonDefaults.buttonColors].
- * @param enabled Controls the enabled state of the button. When `false`, this button will not
- * be clickable
+ * this button in different states. See [ButtonDefaults.buttonColors].
+ * @param enabled Controls the enabled state of the button. When `false`, this button will not be
+ * clickable
* @param interactionSource an optional hoisted [MutableInteractionSource] for observing and
- * emitting [Interaction]s for this button. You can use this to change the button's appearance
- * or preview the button in different states. Note that if `null` is provided, interactions will
- * still happen internally.
+ * emitting [Interaction]s for this button. You can use this to change the button's appearance or
+ * preview the button in different states. Note that if `null` is provided, interactions will
+ * still happen internally.
* @param contentPadding The spacing values to apply internally between the container and the
- * content
+ * content
* @param shape Defines the button's shape. It is strongly recommended to use the default as this
- * shape is a key characteristic of the Wear Material3 Theme
- * @param border Optional [BorderStroke] that will be used to resolve the border for this
- * button in different states.
+ * shape is a key characteristic of the Wear Material3 Theme
+ * @param border Optional [BorderStroke] that will be used to resolve the border for this button in
+ * different states.
+ *
+ * TODO(b/261838497) Add Material3 samples and UX guidance links
*/
@Composable
fun CompactButton(
@@ -863,9 +875,10 @@
if (label != null) {
ButtonImpl(
onClick = onClick,
- modifier = modifier
- .compactButtonModifier()
- .padding(ButtonDefaults.CompactButtonTapTargetPadding),
+ modifier =
+ modifier
+ .compactButtonModifier()
+ .padding(ButtonDefaults.CompactButtonTapTargetPadding),
onLongClick = onLongClick,
onLongClickLabel = onLongClickLabel,
secondaryLabel = null,
@@ -885,10 +898,11 @@
// content. We use the base simple single slot Button under the covers.
ButtonImpl(
onClick = onClick,
- modifier = modifier
- .compactButtonModifier()
- .width(ButtonDefaults.IconOnlyCompactButtonWidth)
- .padding(ButtonDefaults.CompactButtonTapTargetPadding),
+ modifier =
+ modifier
+ .compactButtonModifier()
+ .width(ButtonDefaults.IconOnlyCompactButtonWidth)
+ .padding(ButtonDefaults.CompactButtonTapTargetPadding),
onLongClick = onLongClick,
onLongClickLabel = onLongClickLabel,
enabled = enabled,
@@ -901,11 +915,7 @@
) {
// Use a box to fill and center align the icon into the single slot of the
// Button
- Box(
- modifier = Modifier
- .fillMaxSize()
- .wrapContentSize(align = Alignment.Center)
- ) {
+ Box(modifier = Modifier.fillMaxSize().wrapContentSize(align = Alignment.Center)) {
if (icon != null) {
icon()
}
@@ -914,54 +924,46 @@
}
}
-/**
- * Contains the default values used by [Button]
- */
+/** Contains the default values used by [Button] */
object ButtonDefaults {
- /**
- * Recommended [Shape] for [Button].
- */
+ /** Recommended [Shape] for [Button]. */
val shape: Shape
@Composable get() = FilledButtonTokens.ContainerShape.value
- /**
- * Recommended [Shape] for [CompactButton].
- */
+ /** Recommended [Shape] for [CompactButton]. */
val compactButtonShape: Shape
@Composable get() = CompactButtonTokens.ContainerShape.value
/**
- * Creates a [ButtonColors] with a muted background and contrasting content color,
- * the defaults for medium emphasis buttons like [FilledTonalButton].
- * Use [filledTonalButtonColors] for important actions that don't distract from
- * other onscreen elements, such as final or unblocking actions in a flow with less emphasis
- * than [buttonColors].
+ * Creates a [ButtonColors] with a muted background and contrasting content color, the defaults
+ * for medium emphasis buttons like [FilledTonalButton]. Use [filledTonalButtonColors] for
+ * important actions that don't distract from other onscreen elements, such as final or
+ * unblocking actions in a flow with less emphasis than [buttonColors].
*
- * If a button is disabled then the content will have an alpha([DisabledContentAlpha])
- * value applied and container will have alpha ([DisabledContainerAlpha]) value applied.
+ * If a button is disabled then the content will have an alpha([DisabledContentAlpha]) value
+ * applied and container will have alpha ([DisabledContainerAlpha]) value applied.
*/
@Composable
fun filledTonalButtonColors() = MaterialTheme.colorScheme.defaultFilledTonalButtonColors
/**
- * Creates a [ButtonColors] with a muted background and contrasting content color,
- * the defaults for medium emphasis buttons like [FilledTonalButton].
- * Use [filledTonalButtonColors] for important actions that don't distract from
- * other onscreen elements, such as final or unblocking actions in a flow with less emphasis
- * than [buttonColors].
+ * Creates a [ButtonColors] with a muted background and contrasting content color, the defaults
+ * for medium emphasis buttons like [FilledTonalButton]. Use [filledTonalButtonColors] for
+ * important actions that don't distract from other onscreen elements, such as final or
+ * unblocking actions in a flow with less emphasis than [buttonColors].
*
- * If a button is disabled then the content will have an alpha([DisabledContentAlpha])
- * value applied and container will have alpha ([DisabledContainerAlpha]) value applied.
+ * If a button is disabled then the content will have an alpha([DisabledContentAlpha]) value
+ * applied and container will have alpha ([DisabledContainerAlpha]) value applied.
*
* @param containerColor The background color of this [Button] when enabled
* @param contentColor The content color of this [Button] when enabled
* @param secondaryContentColor The secondary content color of this [Button] when enabled, used
- * for secondaryLabel content
+ * for secondaryLabel content
* @param iconColor The icon color of this [Button] when enabled, used for icon content
* @param disabledContainerColor The background color of this [Button] when not enabled
* @param disabledContentColor The content color of this [Button] when not enabled
* @param disabledSecondaryContentColor The secondary content color of this [Button] when not
- * enabled
+ * enabled
* @param disabledIconColor The content color of this [Button] when not enabled
*/
@Composable
@@ -974,43 +976,43 @@
disabledContentColor: Color = Color.Unspecified,
disabledSecondaryContentColor: Color = Color.Unspecified,
disabledIconColor: Color = Color.Unspecified
- ): ButtonColors = MaterialTheme.colorScheme.defaultFilledTonalButtonColors.copy(
- containerColor = containerColor,
- contentColor = contentColor,
- secondaryContentColor = secondaryContentColor,
- iconColor = iconColor,
- disabledContainerColor = disabledContainerColor,
- disabledContentColor = disabledContentColor,
- disabledSecondaryContentColor = disabledSecondaryContentColor,
- disabledIconColor = disabledIconColor
- )
+ ): ButtonColors =
+ MaterialTheme.colorScheme.defaultFilledTonalButtonColors.copy(
+ containerColor = containerColor,
+ contentColor = contentColor,
+ secondaryContentColor = secondaryContentColor,
+ iconColor = iconColor,
+ disabledContainerColor = disabledContainerColor,
+ disabledContentColor = disabledContentColor,
+ disabledSecondaryContentColor = disabledSecondaryContentColor,
+ disabledIconColor = disabledIconColor
+ )
/**
* Creates a [ButtonColors] with a transparent background (typically paired with
- * [ButtonDefaults.outlinedButtonBorder]), the defaults for medium emphasis buttons
- * like [OutlinedButton], for important, non-primary actions that need attention.
+ * [ButtonDefaults.outlinedButtonBorder]), the defaults for medium emphasis buttons like
+ * [OutlinedButton], for important, non-primary actions that need attention.
*
- * If a button is disabled then the content will have an alpha([DisabledContentAlpha])
- * value applied and container will have an alpha([DisabledContainerAlpha]) applied.
+ * If a button is disabled then the content will have an alpha([DisabledContentAlpha]) value
+ * applied and container will have an alpha([DisabledContainerAlpha]) applied.
*/
- @Composable
- fun outlinedButtonColors() = MaterialTheme.colorScheme.defaultOutlinedButtonColors
+ @Composable fun outlinedButtonColors() = MaterialTheme.colorScheme.defaultOutlinedButtonColors
/**
* Creates a [ButtonColors] with a transparent background (typically paired with
- * [ButtonDefaults.outlinedButtonBorder]), the defaults for medium emphasis buttons
- * like [OutlinedButton], for important, non-primary actions that need attention.
+ * [ButtonDefaults.outlinedButtonBorder]), the defaults for medium emphasis buttons like
+ * [OutlinedButton], for important, non-primary actions that need attention.
*
- * If a button is disabled then the content will have an alpha([DisabledContentAlpha])
- * value applied and container will have an alpha([DisabledContainerAlpha]) applied.
+ * If a button is disabled then the content will have an alpha([DisabledContentAlpha]) value
+ * applied and container will have an alpha([DisabledContainerAlpha]) applied.
*
* @param contentColor The content color of this [Button] when enabled
* @param secondaryContentColor The secondary content color of this [Button] when enabled, used
- * for secondaryLabel content
+ * for secondaryLabel content
* @param iconColor The icon color of this [Button] when enabled, used for icon content
* @param disabledContentColor The content color of this [Button] when not enabled
* @param disabledSecondaryContentColor The secondary content color of this [Button] when not
- * enabled
+ * enabled
* @param disabledIconColor The content color of this [Button] when not enabled
*/
@Composable
@@ -1021,46 +1023,45 @@
disabledContentColor: Color = Color.Unspecified,
disabledSecondaryContentColor: Color = Color.Unspecified,
disabledIconColor: Color = Color.Unspecified
- ): ButtonColors = MaterialTheme.colorScheme.defaultOutlinedButtonColors.copy(
- containerColor = Color.Transparent,
- contentColor = contentColor,
- secondaryContentColor = secondaryContentColor,
- iconColor = iconColor,
- disabledContainerColor = Color.Transparent,
- disabledContentColor = disabledContentColor,
- disabledSecondaryContentColor = disabledSecondaryContentColor,
- disabledIconColor = disabledIconColor
- )
+ ): ButtonColors =
+ MaterialTheme.colorScheme.defaultOutlinedButtonColors.copy(
+ containerColor = Color.Transparent,
+ contentColor = contentColor,
+ secondaryContentColor = secondaryContentColor,
+ iconColor = iconColor,
+ disabledContainerColor = Color.Transparent,
+ disabledContentColor = disabledContentColor,
+ disabledSecondaryContentColor = disabledSecondaryContentColor,
+ disabledIconColor = disabledIconColor
+ )
/**
- * Creates a [ButtonColors] with transparent background, the defaults for low emphasis
- * buttons like [ChildButton]. Use [childButtonColors] for optional or supplementary
- * actions with the least amount of prominence.
+ * Creates a [ButtonColors] with transparent background, the defaults for low emphasis buttons
+ * like [ChildButton]. Use [childButtonColors] for optional or supplementary actions with the
+ * least amount of prominence.
*
- * If a button is disabled then the content will have an alpha([DisabledContentAlpha])
- * value applied and container will have an alpha([DisabledContainerAlpha]) value applied.
+ * If a button is disabled then the content will have an alpha([DisabledContentAlpha]) value
+ * applied and container will have an alpha([DisabledContainerAlpha]) value applied.
*/
- @Composable
- fun childButtonColors() = MaterialTheme.colorScheme.defaultChildButtonColors
+ @Composable fun childButtonColors() = MaterialTheme.colorScheme.defaultChildButtonColors
/**
- * Creates a [ButtonColors] with transparent background, the defaults for low emphasis
- * buttons like [ChildButton]. Use [childButtonColors] for optional or supplementary
- * actions with the least amount of prominence.
+ * Creates a [ButtonColors] with transparent background, the defaults for low emphasis buttons
+ * like [ChildButton]. Use [childButtonColors] for optional or supplementary actions with the
+ * least amount of prominence.
*
- * If a button is disabled then the content will have an alpha([DisabledContentAlpha])
- * value applied and container will have an alpha([DisabledContainerAlpha]) value applied.
+ * If a button is disabled then the content will have an alpha([DisabledContentAlpha]) value
+ * applied and container will have an alpha([DisabledContainerAlpha]) value applied.
*
* @param contentColor The content color of this [Button] when enabled
* @param secondaryContentColor The secondary content color of this [Button] when enabled, used
- * for secondaryLabel content
+ * for secondaryLabel content
* @param iconColor The icon color of this [Button] when enabled, used for icon content
* @param disabledContentColor The content color of this [Button] when not enabled
* @param disabledSecondaryContentColor The secondary content color of this [Button] when not
- * enabled
+ * enabled
* @param disabledIconColor The content color of this [Button] when not enabled
*/
-
@Composable
fun childButtonColors(
contentColor: Color = Color.Unspecified,
@@ -1069,60 +1070,65 @@
disabledContentColor: Color = Color.Unspecified,
disabledSecondaryContentColor: Color = Color.Unspecified,
disabledIconColor: Color = Color.Unspecified,
- ): ButtonColors = MaterialTheme.colorScheme.defaultChildButtonColors.copy(
- containerColor = Color.Transparent,
- contentColor = contentColor,
- secondaryContentColor = secondaryContentColor,
- iconColor = iconColor,
- disabledContainerColor = Color.Transparent,
- disabledContentColor = disabledContentColor,
- disabledSecondaryContentColor = disabledSecondaryContentColor,
- disabledIconColor = disabledIconColor
- )
+ ): ButtonColors =
+ MaterialTheme.colorScheme.defaultChildButtonColors.copy(
+ containerColor = Color.Transparent,
+ contentColor = contentColor,
+ secondaryContentColor = secondaryContentColor,
+ iconColor = iconColor,
+ disabledContainerColor = Color.Transparent,
+ disabledContentColor = disabledContentColor,
+ disabledSecondaryContentColor = disabledSecondaryContentColor,
+ disabledIconColor = disabledIconColor
+ )
/**
- * Creates a [ButtonColors] for a [Button] with an image background, typically with a scrim
- * over the image to ensure that the content is visible. Uses a default content color
- * of [ColorScheme.onSurface].
+ * Creates a [ButtonColors] for a [Button] with an image background, typically with a scrim over
+ * the image to ensure that the content is visible. Uses a default content color of
+ * [ColorScheme.onSurface].
*
* @param backgroundImagePainter The [Painter] to use to draw the background of the [Button]
* @param backgroundImageScrimBrush The [Brush] to use to paint a scrim over the background
- * image to ensure that any text drawn over the image is legible
+ * image to ensure that any text drawn over the image is legible
* @param contentColor The content color of this [Button] when enabled
* @param secondaryContentColor The secondary content color of this [Button] when enabled, used
- * for secondaryLabel content
+ * for secondaryLabel content
* @param iconColor The icon color of this [Button] when enabled, used for icon content
* @param disabledContentColor The content color of this [Button] when disabled
* @param disabledSecondaryContentColor The secondary content color of this [Button] when
- * disabled, used for secondary label content
+ * disabled, used for secondary label content
* @param disabledIconColor The icon color of this [Button] when disabled, used for icon content
*/
@Composable
fun imageBackgroundButtonColors(
backgroundImagePainter: Painter,
- backgroundImageScrimBrush: Brush = Brush.linearGradient(
- colors = listOf(
- ImageButtonTokens.BackgroundImageGradientColor.value.copy(
- alpha = ImageButtonTokens.GradientStartOpacity
- ),
- ImageButtonTokens.BackgroundImageGradientColor.value.copy(
- alpha = ImageButtonTokens.GradientEndOpacity
- )
- )
- ),
+ backgroundImageScrimBrush: Brush =
+ Brush.linearGradient(
+ colors =
+ listOf(
+ ImageButtonTokens.BackgroundImageGradientColor.value.copy(
+ alpha = ImageButtonTokens.GradientStartOpacity
+ ),
+ ImageButtonTokens.BackgroundImageGradientColor.value.copy(
+ alpha = ImageButtonTokens.GradientEndOpacity
+ )
+ )
+ ),
contentColor: Color = ImageButtonTokens.ContentColor.value,
secondaryContentColor: Color = ImageButtonTokens.SecondaryContentColor.value,
iconColor: Color = ImageButtonTokens.IconColor.value,
- disabledContentColor: Color = ImageButtonTokens.DisabledContentColor.value.toDisabledColor(
- disabledAlpha = ImageButtonTokens.DisabledContentOpacity
- ),
- disabledSecondaryContentColor: Color = ImageButtonTokens.DisabledContentColor.value
- .toDisabledColor(
+ disabledContentColor: Color =
+ ImageButtonTokens.DisabledContentColor.value.toDisabledColor(
disabledAlpha = ImageButtonTokens.DisabledContentOpacity
),
- disabledIconColor: Color = ImageButtonTokens.DisabledContentColor.value.toDisabledColor(
- disabledAlpha = ImageButtonTokens.DisabledContentOpacity
- )
+ disabledSecondaryContentColor: Color =
+ ImageButtonTokens.DisabledContentColor.value.toDisabledColor(
+ disabledAlpha = ImageButtonTokens.DisabledContentOpacity
+ ),
+ disabledIconColor: Color =
+ ImageButtonTokens.DisabledContentColor.value.toDisabledColor(
+ disabledAlpha = ImageButtonTokens.DisabledContentOpacity
+ )
): ButtonColors {
val backgroundPainter =
remember(backgroundImagePainter, backgroundImageScrimBrush) {
@@ -1157,13 +1163,12 @@
* Creates a [BorderStroke], such as for an [OutlinedButton]
*
* @param enabled Controls the color of the border based on the enabled/disabled state of the
- * button
+ * button
* @param borderColor The color to use for the border for this outline when enabled
- * @param disabledBorderColor The color to use for the border for this outline when
- * disabled
+ * @param disabledBorderColor The color to use for the border for this outline when disabled
* @param borderWidth The width to use for the border for this outline. It is strongly
- * recommended to use the default width as this outline is a key characteristic
- * of Wear Material3.
+ * recommended to use the default width as this outline is a key characteristic of Wear
+ * Material3.
*/
@Composable
fun outlinedButtonBorder(
@@ -1181,15 +1186,14 @@
}
/**
- * Creates a [ButtonColors] that represents the default background and content colors used in
- * a [Button].
+ * Creates a [ButtonColors] that represents the default background and content colors used in a
+ * [Button].
*/
- @Composable
- fun buttonColors(): ButtonColors = MaterialTheme.colorScheme.defaultButtonColors
+ @Composable fun buttonColors(): ButtonColors = MaterialTheme.colorScheme.defaultButtonColors
/**
- * Creates a [ButtonColors] that represents the default background and content colors used in
- * a [Button].
+ * Creates a [ButtonColors] that represents the default background and content colors used in a
+ * [Button].
*
* @param containerColor The background color of this [Button] when enabled
* @param contentColor The content color of this [Button] when enabled
@@ -1210,61 +1214,55 @@
disabledContentColor: Color = Color.Unspecified,
disabledSecondaryContentColor: Color = Color.Unspecified,
disabledIconColor: Color = Color.Unspecified
- ): ButtonColors = MaterialTheme.colorScheme.defaultButtonColors.copy(
- containerColor = containerColor,
- contentColor = contentColor,
- secondaryContentColor = secondaryContentColor,
- iconColor = iconColor,
- disabledContainerColor = disabledContainerColor,
- disabledContentColor = disabledContentColor,
- disabledSecondaryContentColor = disabledSecondaryContentColor,
- disabledIconColor = disabledIconColor
- )
+ ): ButtonColors =
+ MaterialTheme.colorScheme.defaultButtonColors.copy(
+ containerColor = containerColor,
+ contentColor = contentColor,
+ secondaryContentColor = secondaryContentColor,
+ iconColor = iconColor,
+ disabledContainerColor = disabledContainerColor,
+ disabledContentColor = disabledContentColor,
+ disabledSecondaryContentColor = disabledSecondaryContentColor,
+ disabledIconColor = disabledIconColor
+ )
val ButtonHorizontalPadding = 14.dp
val ButtonVerticalPadding = 6.dp
- /**
- * The default content padding used by [Button]
- */
- val ContentPadding: PaddingValues = PaddingValues(
- horizontal = ButtonHorizontalPadding,
- vertical = ButtonVerticalPadding,
- )
+ /** The default content padding used by [Button] */
+ val ContentPadding: PaddingValues =
+ PaddingValues(
+ horizontal = ButtonHorizontalPadding,
+ vertical = ButtonVerticalPadding,
+ )
- /**
- * The default size of the icon when used inside a [Button].
- */
+ /** The default size of the icon when used inside a [Button]. */
val IconSize: Dp = FilledButtonTokens.IconSize
- /**
- * The size of the icon when used inside a Large "Avatar" [Button].
- */
+ /** The size of the icon when used inside a Large "Avatar" [Button]. */
val LargeIconSize: Dp = FilledButtonTokens.IconLargeSize
/**
- * The default height applied for the [Button].
- * Note that you can override it by applying Modifier.heightIn directly on [Button].
+ * The default height applied for the [Button]. Note that you can override it by applying
+ * Modifier.heightIn directly on [Button].
*/
val Height = FilledButtonTokens.ContainerHeight
val CompactButtonHorizontalPadding = 12.dp
val CompactButtonVerticalPadding = 0.dp
- /**
- * The default content padding used by [CompactButton]
- */
- val CompactButtonContentPadding: PaddingValues = PaddingValues(
- start = CompactButtonHorizontalPadding,
- top = CompactButtonVerticalPadding,
- end = CompactButtonHorizontalPadding,
- bottom = CompactButtonVerticalPadding
- )
+ /** The default content padding used by [CompactButton] */
+ val CompactButtonContentPadding: PaddingValues =
+ PaddingValues(
+ start = CompactButtonHorizontalPadding,
+ top = CompactButtonVerticalPadding,
+ end = CompactButtonHorizontalPadding,
+ bottom = CompactButtonVerticalPadding
+ )
/**
- * The height applied for the [CompactButton]. This includes a
- * visible button height of 32.dp and 8.dp of padding above and below the button
- * in order to meet accessibility guidelines that
+ * The height applied for the [CompactButton]. This includes a visible button height of 32.dp
+ * and 8.dp of padding above and below the button in order to meet accessibility guidelines that
* request a minimum of 48.dp height and width of tappable area.
*
* Note that you can override it by adjusting Modifier.height and Modifier.padding directly on
@@ -1272,129 +1270,173 @@
*/
val CompactButtonHeight = CompactButtonTokens.ContainerHeight
- /**
- * The size of the icon when used inside a "[CompactButton].
- */
+ /** The size of the icon when used inside a "[CompactButton]. */
val SmallIconSize: Dp = CompactButtonTokens.IconSize
/**
* The default padding to be provided around a [CompactButton] in order to ensure that its
* tappable area meets minimum UX guidance.
*/
- val CompactButtonTapTargetPadding: PaddingValues = PaddingValues(
- top = 8.dp,
- bottom = 8.dp
- )
+ val CompactButtonTapTargetPadding: PaddingValues = PaddingValues(top = 8.dp, bottom = 8.dp)
private val ColorScheme.defaultFilledButtonColors: ButtonColors
get() {
- return defaultFilledButtonColorsCached ?: ButtonColors(
- containerColor = fromToken(FilledButtonTokens.ContainerColor),
- contentColor = fromToken(FilledButtonTokens.LabelColor),
- secondaryContentColor = fromToken(FilledButtonTokens.SecondaryLabelColor),
- iconColor = fromToken(FilledButtonTokens.IconColor),
- disabledContainerColor = fromToken(FilledButtonTokens.DisabledContainerColor)
- .toDisabledColor(disabledAlpha = FilledButtonTokens.DisabledContainerOpacity),
- disabledContentColor = fromToken(FilledButtonTokens.DisabledContentColor)
- .toDisabledColor(disabledAlpha = FilledButtonTokens.DisabledContentOpacity),
- disabledSecondaryContentColor = fromToken(FilledButtonTokens.DisabledContentColor)
- .toDisabledColor(disabledAlpha = FilledButtonTokens.DisabledContentOpacity),
- disabledIconColor = fromToken(FilledButtonTokens.DisabledContentColor)
- .toDisabledColor(disabledAlpha = FilledButtonTokens.DisabledContentOpacity)
- ).also {
- defaultFilledButtonColorsCached = it
- }
+ return defaultFilledButtonColorsCached
+ ?: ButtonColors(
+ containerColor = fromToken(FilledButtonTokens.ContainerColor),
+ contentColor = fromToken(FilledButtonTokens.LabelColor),
+ secondaryContentColor = fromToken(FilledButtonTokens.SecondaryLabelColor),
+ iconColor = fromToken(FilledButtonTokens.IconColor),
+ disabledContainerColor =
+ fromToken(FilledButtonTokens.DisabledContainerColor)
+ .toDisabledColor(
+ disabledAlpha = FilledButtonTokens.DisabledContainerOpacity
+ ),
+ disabledContentColor =
+ fromToken(FilledButtonTokens.DisabledContentColor)
+ .toDisabledColor(
+ disabledAlpha = FilledButtonTokens.DisabledContentOpacity
+ ),
+ disabledSecondaryContentColor =
+ fromToken(FilledButtonTokens.DisabledContentColor)
+ .toDisabledColor(
+ disabledAlpha = FilledButtonTokens.DisabledContentOpacity
+ ),
+ disabledIconColor =
+ fromToken(FilledButtonTokens.DisabledContentColor)
+ .toDisabledColor(
+ disabledAlpha = FilledButtonTokens.DisabledContentOpacity
+ )
+ )
+ .also { defaultFilledButtonColorsCached = it }
}
private val ColorScheme.defaultFilledTonalButtonColors: ButtonColors
get() {
- return defaultFilledTonalButtonColorsCached ?: ButtonColors(
- containerColor = fromToken(FilledTonalButtonTokens.ContainerColor),
- contentColor = fromToken(FilledTonalButtonTokens.LabelColor),
- secondaryContentColor = fromToken(FilledTonalButtonTokens.SecondaryLabelColor),
- iconColor = fromToken(FilledTonalButtonTokens.IconColor),
- disabledContainerColor = fromToken(FilledTonalButtonTokens.DisabledContainerColor)
- .toDisabledColor(
- disabledAlpha = FilledTonalButtonTokens.DisabledContainerOpacity
- ),
- disabledContentColor = fromToken(FilledTonalButtonTokens.DisabledContentColor)
- .toDisabledColor(
- disabledAlpha = FilledTonalButtonTokens.DisabledContentOpacity
- ),
- disabledSecondaryContentColor =
- fromToken(FilledTonalButtonTokens.DisabledContentColor)
- .toDisabledColor(
- disabledAlpha = FilledTonalButtonTokens.DisabledContentOpacity
- ),
- disabledIconColor = fromToken(FilledTonalButtonTokens.DisabledContentColor)
- .toDisabledColor(disabledAlpha = FilledTonalButtonTokens.DisabledContentOpacity)
- ).also {
- defaultFilledTonalButtonColorsCached = it
- }
+ return defaultFilledTonalButtonColorsCached
+ ?: ButtonColors(
+ containerColor = fromToken(FilledTonalButtonTokens.ContainerColor),
+ contentColor = fromToken(FilledTonalButtonTokens.LabelColor),
+ secondaryContentColor =
+ fromToken(FilledTonalButtonTokens.SecondaryLabelColor),
+ iconColor = fromToken(FilledTonalButtonTokens.IconColor),
+ disabledContainerColor =
+ fromToken(FilledTonalButtonTokens.DisabledContainerColor)
+ .toDisabledColor(
+ disabledAlpha = FilledTonalButtonTokens.DisabledContainerOpacity
+ ),
+ disabledContentColor =
+ fromToken(FilledTonalButtonTokens.DisabledContentColor)
+ .toDisabledColor(
+ disabledAlpha = FilledTonalButtonTokens.DisabledContentOpacity
+ ),
+ disabledSecondaryContentColor =
+ fromToken(FilledTonalButtonTokens.DisabledContentColor)
+ .toDisabledColor(
+ disabledAlpha = FilledTonalButtonTokens.DisabledContentOpacity
+ ),
+ disabledIconColor =
+ fromToken(FilledTonalButtonTokens.DisabledContentColor)
+ .toDisabledColor(
+ disabledAlpha = FilledTonalButtonTokens.DisabledContentOpacity
+ )
+ )
+ .also { defaultFilledTonalButtonColorsCached = it }
}
private val ColorScheme.defaultOutlinedButtonColors: ButtonColors
get() {
- return defaultOutlinedButtonColorsCached ?: ButtonColors(
- containerColor = Color.Transparent,
- contentColor = fromToken(OutlinedButtonTokens.LabelColor),
- secondaryContentColor = fromToken(OutlinedButtonTokens.SecondaryLabelColor),
- iconColor = fromToken(OutlinedButtonTokens.IconColor),
- disabledContainerColor = Color.Transparent,
- disabledContentColor = fromToken(OutlinedButtonTokens.DisabledContentColor)
- .toDisabledColor(disabledAlpha = OutlinedButtonTokens.DisabledContentOpacity),
- disabledSecondaryContentColor = fromToken(OutlinedButtonTokens.DisabledContentColor)
- .toDisabledColor(disabledAlpha = OutlinedButtonTokens.DisabledContentOpacity),
- disabledIconColor = fromToken(OutlinedButtonTokens.DisabledContentColor)
- .toDisabledColor(disabledAlpha = OutlinedButtonTokens.DisabledContentOpacity)
- ).also {
- defaultOutlinedButtonColorsCached = it
- }
+ return defaultOutlinedButtonColorsCached
+ ?: ButtonColors(
+ containerColor = Color.Transparent,
+ contentColor = fromToken(OutlinedButtonTokens.LabelColor),
+ secondaryContentColor = fromToken(OutlinedButtonTokens.SecondaryLabelColor),
+ iconColor = fromToken(OutlinedButtonTokens.IconColor),
+ disabledContainerColor = Color.Transparent,
+ disabledContentColor =
+ fromToken(OutlinedButtonTokens.DisabledContentColor)
+ .toDisabledColor(
+ disabledAlpha = OutlinedButtonTokens.DisabledContentOpacity
+ ),
+ disabledSecondaryContentColor =
+ fromToken(OutlinedButtonTokens.DisabledContentColor)
+ .toDisabledColor(
+ disabledAlpha = OutlinedButtonTokens.DisabledContentOpacity
+ ),
+ disabledIconColor =
+ fromToken(OutlinedButtonTokens.DisabledContentColor)
+ .toDisabledColor(
+ disabledAlpha = OutlinedButtonTokens.DisabledContentOpacity
+ )
+ )
+ .also { defaultOutlinedButtonColorsCached = it }
}
private val ColorScheme.defaultChildButtonColors: ButtonColors
get() {
- return defaultChildButtonColorsCached ?: ButtonColors(
- containerColor = Color.Transparent,
- contentColor = fromToken(ChildButtonTokens.LabelColor),
- secondaryContentColor = fromToken(ChildButtonTokens.SecondaryLabelColor),
- iconColor = fromToken(ChildButtonTokens.IconColor),
- disabledContainerColor = Color.Transparent,
- disabledContentColor = fromToken(ChildButtonTokens.DisabledContentColor)
- .toDisabledColor(disabledAlpha = ChildButtonTokens.DisabledContentOpacity),
- disabledSecondaryContentColor = fromToken(ChildButtonTokens.DisabledContentColor)
- .toDisabledColor(disabledAlpha = ChildButtonTokens.DisabledContentOpacity),
- disabledIconColor = fromToken(ChildButtonTokens.DisabledContentColor)
- .toDisabledColor(disabledAlpha = ChildButtonTokens.DisabledContentOpacity),
- ).also {
- defaultChildButtonColorsCached = it
- }
+ return defaultChildButtonColorsCached
+ ?: ButtonColors(
+ containerColor = Color.Transparent,
+ contentColor = fromToken(ChildButtonTokens.LabelColor),
+ secondaryContentColor = fromToken(ChildButtonTokens.SecondaryLabelColor),
+ iconColor = fromToken(ChildButtonTokens.IconColor),
+ disabledContainerColor = Color.Transparent,
+ disabledContentColor =
+ fromToken(ChildButtonTokens.DisabledContentColor)
+ .toDisabledColor(
+ disabledAlpha = ChildButtonTokens.DisabledContentOpacity
+ ),
+ disabledSecondaryContentColor =
+ fromToken(ChildButtonTokens.DisabledContentColor)
+ .toDisabledColor(
+ disabledAlpha = ChildButtonTokens.DisabledContentOpacity
+ ),
+ disabledIconColor =
+ fromToken(ChildButtonTokens.DisabledContentColor)
+ .toDisabledColor(
+ disabledAlpha = ChildButtonTokens.DisabledContentOpacity
+ ),
+ )
+ .also { defaultChildButtonColorsCached = it }
}
private val ColorScheme.defaultButtonColors: ButtonColors
get() {
- return defaultButtonColorsCached ?: ButtonColors(
- containerColor = fromToken(FilledButtonTokens.ContainerColor),
- contentColor = fromToken(FilledButtonTokens.LabelColor),
- secondaryContentColor = fromToken(FilledButtonTokens.SecondaryLabelColor)
- .copy(alpha = FilledButtonTokens.SecondaryLabelOpacity),
- iconColor = fromToken(FilledButtonTokens.IconColor),
- disabledContainerColor = fromToken(FilledButtonTokens.DisabledContainerColor)
- .toDisabledColor(disabledAlpha = FilledButtonTokens.DisabledContainerOpacity),
- disabledContentColor = fromToken(FilledButtonTokens.DisabledContentColor)
- .toDisabledColor(disabledAlpha = FilledButtonTokens.DisabledContentOpacity),
- disabledSecondaryContentColor = fromToken(FilledButtonTokens.DisabledContentColor)
- .toDisabledColor(disabledAlpha = FilledButtonTokens.DisabledContentOpacity),
- disabledIconColor = fromToken(FilledButtonTokens.DisabledContentColor)
- .toDisabledColor(disabledAlpha = FilledButtonTokens.DisabledContentOpacity)
- ).also {
- defaultButtonColorsCached = it
- }
+ return defaultButtonColorsCached
+ ?: ButtonColors(
+ containerColor = fromToken(FilledButtonTokens.ContainerColor),
+ contentColor = fromToken(FilledButtonTokens.LabelColor),
+ secondaryContentColor =
+ fromToken(FilledButtonTokens.SecondaryLabelColor)
+ .copy(alpha = FilledButtonTokens.SecondaryLabelOpacity),
+ iconColor = fromToken(FilledButtonTokens.IconColor),
+ disabledContainerColor =
+ fromToken(FilledButtonTokens.DisabledContainerColor)
+ .toDisabledColor(
+ disabledAlpha = FilledButtonTokens.DisabledContainerOpacity
+ ),
+ disabledContentColor =
+ fromToken(FilledButtonTokens.DisabledContentColor)
+ .toDisabledColor(
+ disabledAlpha = FilledButtonTokens.DisabledContentOpacity
+ ),
+ disabledSecondaryContentColor =
+ fromToken(FilledButtonTokens.DisabledContentColor)
+ .toDisabledColor(
+ disabledAlpha = FilledButtonTokens.DisabledContentOpacity
+ ),
+ disabledIconColor =
+ fromToken(FilledButtonTokens.DisabledContentColor)
+ .toDisabledColor(
+ disabledAlpha = FilledButtonTokens.DisabledContentOpacity
+ )
+ )
+ .also { defaultButtonColorsCached = it }
}
/**
- * The default width applied for the [CompactButton] when it has no label provided.
- * Note that you can override it by applying Modifier.width directly on [CompactButton].
+ * The default width applied for the [CompactButton] when it has no label provided. Note that
+ * you can override it by applying Modifier.width directly on [CompactButton].
*/
internal val IconOnlyCompactButtonWidth = CompactButtonTokens.IconOnlyWidth
@@ -1406,20 +1448,21 @@
}
/**
- * Represents the container and content colors used in buttons
- * in different states.
+ * Represents the container and content colors used in buttons in different states.
*
* @param containerPainter [Painter] to use to draw the background of the [Button] when enabled.
* @param contentColor The content color of this [Button] when enabled.
* @param secondaryContentColor The content color of this [Button] when enabled.
* @param iconColor The content color of this [Button] when enabled.
- * @param disabledContainerPainter [Painter] to use to draw the background of the [Button] when not enabled.
+ * @param disabledContainerPainter [Painter] to use to draw the background of the [Button] when not
+ * enabled.
* @param disabledContentColor The content color of this [Button] when not enabled.
* @param disabledSecondaryContentColor The content color of this [Button] when not enabled.
* @param disabledIconColor The content color of this [Button] when not enabled.
*/
@Immutable
-class ButtonColors constructor(
+class ButtonColors
+constructor(
val containerPainter: Painter,
val contentColor: Color,
val secondaryContentColor: Color,
@@ -1470,18 +1513,19 @@
disabledContentColor: Color,
disabledSecondaryContentColor: Color,
disabledIconColor: Color,
- ) = ButtonColors(
- if (containerColor != Color.Unspecified) ColorPainter(containerColor)
- else this.containerPainter,
- contentColor.takeOrElse { this.contentColor },
- secondaryContentColor.takeOrElse { this.secondaryContentColor },
- iconColor.takeOrElse { this.iconColor },
- if (disabledContainerColor != Color.Unspecified) ColorPainter(disabledContainerColor)
- else this.disabledContainerPainter,
- disabledContentColor.takeOrElse { this.disabledContentColor },
- disabledSecondaryContentColor.takeOrElse { this.disabledSecondaryContentColor },
- disabledIconColor.takeOrElse { this.disabledIconColor }
- )
+ ) =
+ ButtonColors(
+ if (containerColor != Color.Unspecified) ColorPainter(containerColor)
+ else this.containerPainter,
+ contentColor.takeOrElse { this.contentColor },
+ secondaryContentColor.takeOrElse { this.secondaryContentColor },
+ iconColor.takeOrElse { this.iconColor },
+ if (disabledContainerColor != Color.Unspecified) ColorPainter(disabledContainerColor)
+ else this.disabledContainerPainter,
+ disabledContentColor.takeOrElse { this.disabledContentColor },
+ disabledSecondaryContentColor.takeOrElse { this.disabledSecondaryContentColor },
+ disabledIconColor.takeOrElse { this.disabledIconColor }
+ )
/**
* Represents the container color for this button, depending on [enabled].
@@ -1554,17 +1598,15 @@
@Composable
private fun Modifier.buttonSizeModifier(): Modifier =
- this
- .defaultMinSize(minHeight = ButtonDefaults.Height)
- .height(IntrinsicSize.Min)
+ this.defaultMinSize(minHeight = ButtonDefaults.Height).height(IntrinsicSize.Min)
@Composable
private fun Modifier.compactButtonModifier(): Modifier =
this.height(ButtonDefaults.CompactButtonHeight)
/**
- * Button with label. This allows to use the token values for
- * individual buttons instead of relying on common values.
+ * Button with label. This allows to use the token values for individual buttons instead of relying
+ * on common values.
*/
@OptIn(ExperimentalFoundationApi::class)
@Composable
@@ -1582,40 +1624,34 @@
interactionSource: MutableInteractionSource?,
content: @Composable RowScope.() -> Unit
) {
- val borderModifier = if (border != null)
- modifier.border(
- border = border,
- shape = shape
- ) else modifier
+ val borderModifier =
+ if (border != null) modifier.border(border = border, shape = shape) else modifier
Row(
- modifier = borderModifier
- .clip(shape = shape)
- .width(intrinsicSize = IntrinsicSize.Max)
- .paint(
- painter = colors.containerPainter(enabled = enabled),
- contentScale = ContentScale.Crop
- )
- .combinedClickable(
- enabled = enabled,
- onClick = onClick,
- onLongClick = onLongClick,
- onLongClickLabel = onLongClickLabel,
- role = Role.Button,
- indication = rippleOrFallbackImplementation(),
- interactionSource = interactionSource,
- )
- .padding(contentPadding),
- content = provideScopeContent(
- colors.contentColor(enabled = enabled),
- labelFont,
- content
- )
+ modifier =
+ borderModifier
+ .clip(shape = shape)
+ .width(intrinsicSize = IntrinsicSize.Max)
+ .paint(
+ painter = colors.containerPainter(enabled = enabled),
+ contentScale = ContentScale.Crop
+ )
+ .combinedClickable(
+ enabled = enabled,
+ onClick = onClick,
+ onLongClick = onLongClick,
+ onLongClickLabel = onLongClickLabel,
+ role = Role.Button,
+ indication = rippleOrFallbackImplementation(),
+ interactionSource = interactionSource,
+ )
+ .padding(contentPadding),
+ content = provideScopeContent(colors.contentColor(enabled = enabled), labelFont, content)
)
}
/**
- * Button with icon, label and secondary label. This allows to use the token values for
- * individual buttons instead of relying on common values.
+ * Button with icon, label and secondary label. This allows to use the token values for individual
+ * buttons instead of relying on common values.
*/
@Composable
private fun ButtonImpl(
@@ -1662,21 +1698,16 @@
Spacer(modifier = Modifier.size(ButtonDefaults.IconSpacing))
}
Column {
- Row(
- content = provideScopeContent(
- colors.contentColor(enabled),
- labelFont,
- label
- )
- )
+ Row(content = provideScopeContent(colors.contentColor(enabled), labelFont, label))
if (secondaryLabel != null && secondaryLabelFont != null) {
Spacer(modifier = Modifier.size(2.dp))
Row(
- content = provideScopeContent(
- colors.secondaryContentColor(enabled),
- secondaryLabelFont,
- secondaryLabel
- )
+ content =
+ provideScopeContent(
+ colors.secondaryContentColor(enabled),
+ secondaryLabelFont,
+ secondaryLabel
+ )
)
}
}
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Card.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Card.kt
index c7c556b..064d4fe 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Card.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Card.kt
@@ -60,28 +60,29 @@
* Cards can be enabled or disabled. A disabled card will not respond to click events.
*
* Example of a [Card]:
+ *
* @sample androidx.wear.compose.material3.samples.CardSample
*
* For more information, see the
- * [Cards](https://developer.android.com/training/wearables/components/cards)
- * Wear OS Material design guide.
+ * [Cards](https://developer.android.com/training/wearables/components/cards) Wear OS Material
+ * design guide.
*
* @param onClick Will be called when the user clicks the card
* @param modifier Modifier to be applied to the card
- * @param enabled Controls the enabled state of the card. When false, this card will not
- * be clickable and there will be no ripple effect on click. Wear cards do not have any specific
- * elevation or alpha differences when not enabled - they are simply not clickable.
+ * @param enabled Controls the enabled state of the card. When false, this card will not be
+ * clickable and there will be no ripple effect on click. Wear cards do not have any specific
+ * elevation or alpha differences when not enabled - they are simply not clickable.
* @param shape Defines the card's shape. It is strongly recommended to use the default as this
- * shape is a key characteristic of the Wear Material Theme
+ * shape is a key characteristic of the Wear Material Theme
* @param colors [CardColors] that will be used to resolve the colors used for this card in
- * different states. See [CardDefaults.cardColors].
+ * different states. See [CardDefaults.cardColors].
* @param border A BorderStroke object which is used for drawing outlines.
* @param contentPadding The spacing values to apply internally between the container and the
- * content
+ * content
* @param interactionSource an optional hoisted [MutableInteractionSource] for observing and
- * emitting [Interaction]s for this card. You can use this to change the card's appearance
- * or preview the card in different states. Note that if `null` is provided, interactions will
- * still happen internally.
+ * emitting [Interaction]s for this card. You can use this to change the card's appearance or
+ * preview the card in different states. Note that if `null` is provided, interactions will still
+ * happen internally.
* @param content The main slot for a content of this card
*/
@Composable
@@ -120,56 +121,57 @@
* The first row of the layout has three slots, 1) a small optional application [Image] or [Icon] of
* size [CardDefaults.AppImageSize]x[CardDefaults.AppImageSize] dp, 2) an application name
* (emphasised with the [CardColors.appColor()] color), it is expected to be a short start aligned
- * [Text] composable, and 3) the time that the application activity has occurred which will be
- * shown on the top row of the card, this is expected to be an end aligned [Text] composable
- * showing a time relevant to the contents of the [Card].
+ * [Text] composable, and 3) the time that the application activity has occurred which will be shown
+ * on the top row of the card, this is expected to be an end aligned [Text] composable showing a
+ * time relevant to the contents of the [Card].
*
* The second row shows a title, this is expected to be a single row of start aligned [Text].
*
- * The rest of the [Card] contains the content which can be either [Text] or an [Image].
- * If the content is text it can be single or multiple line and is expected to be Top and Start
- * aligned.
+ * The rest of the [Card] contains the content which can be either [Text] or an [Image]. If the
+ * content is text it can be single or multiple line and is expected to be Top and Start aligned.
*
* If more than one composable is provided in the content slot it is the responsibility of the
* caller to determine how to layout the contents, e.g. provide either a row or a column.
*
* Example of an [AppCard]:
+ *
* @sample androidx.wear.compose.material3.samples.AppCardSample
*
* Example of an [AppCard] with icon:
+ *
* @sample androidx.wear.compose.material3.samples.AppCardWithIconSample
*
* Example of an outlined [AppCard]:
+ *
* @sample androidx.wear.compose.material3.samples.OutlinedAppCardSample
*
* For more information, see the
- * [Cards](https://developer.android.com/training/wearables/components/cards)
- * guide.
+ * [Cards](https://developer.android.com/training/wearables/components/cards) guide.
*
* @param onClick Will be called when the user clicks the card
* @param appName A slot for displaying the application name, expected to be a single line of start
- * aligned text of [Typography.labelSmall]
+ * aligned text of [Typography.labelSmall]
* @param title A slot for displaying the title of the card, expected to be one or two lines of
- * start aligned text of [Typography.titleMedium]
+ * start aligned text of [Typography.titleMedium]
* @param modifier Modifier to be applied to the card
- * @param enabled Controls the enabled state of the card. When false, this card will not
- * be clickable and there will be no ripple effect on click. Wear cards do not have any specific
- * elevation or alpha differences when not enabled - they are simply not clickable.
+ * @param enabled Controls the enabled state of the card. When false, this card will not be
+ * clickable and there will be no ripple effect on click. Wear cards do not have any specific
+ * elevation or alpha differences when not enabled - they are simply not clickable.
* @param shape Defines the card's shape. It is strongly recommended to use the default as this
- * shape is a key characteristic of the Wear Material Theme
+ * shape is a key characteristic of the Wear Material Theme
* @param colors [CardColors] that will be used to resolve the colors used for this card in
- * different states. See [CardDefaults.cardColors].
+ * different states. See [CardDefaults.cardColors].
* @param border A BorderStroke object which is used for drawing outlines.
* @param contentPadding The spacing values to apply internally between the container and the
- * content
+ * content
* @param interactionSource an optional hoisted [MutableInteractionSource] for observing and
- * emitting [Interaction]s for this card. You can use this to change the card's appearance
- * or preview the card in different states. Note that if `null` is provided, interactions will
- * still happen internally.
+ * emitting [Interaction]s for this card. You can use this to change the card's appearance or
+ * preview the card in different states. Note that if `null` is provided, interactions will still
+ * happen internally.
* @param appImage A slot for a small ([CardDefaults.AppImageSize]x[CardDefaults.AppImageSize] )
- * [Image] associated with the application.
+ * [Image] associated with the application.
* @param time A slot for displaying the time relevant to the contents of the card, expected to be a
- * short piece of end aligned text of [Typography.labelSmall].
+ * short piece of end aligned text of [Typography.labelSmall].
* @param content The main slot for a content of this card
*/
@Composable
@@ -207,16 +209,17 @@
appName()
}
},
- time = time?.let {
- {
- CompositionLocalProvider(
- LocalContentColor provides colors.timeColor,
- LocalTextStyle provides CardTokens.TimeTypography.value,
- ) {
- time()
+ time =
+ time?.let {
+ {
+ CompositionLocalProvider(
+ LocalContentColor provides colors.timeColor,
+ LocalTextStyle provides CardTokens.TimeTypography.value,
+ ) {
+ time()
+ }
}
- }
- },
+ },
title = {
CompositionLocalProvider(
LocalContentColor provides colors.titleColor,
@@ -237,63 +240,63 @@
}
/**
- * Opinionated Wear Material 3 [Card] that offers a specific layout to show interactive
- * information about an application, e.g. a message. TitleCards are designed for use within an
- * application.
+ * Opinionated Wear Material 3 [Card] that offers a specific layout to show interactive information
+ * about an application, e.g. a message. TitleCards are designed for use within an application.
*
- * The [time], [subtitle] and [content] fields are optional,
- * but it is expected that at least one of these is provided.
- * The layout will vary according to which fields are supplied - see samples.
+ * The [time], [subtitle] and [content] fields are optional, but it is expected that at least one of
+ * these is provided. The layout will vary according to which fields are supplied - see samples.
*
* If the [content] is text it can be single or multiple line and is expected to be Top and Start
- * aligned. When [subtitle] is used [content] shouldn't
- * exceed 2 lines height. Overall the [title], [content] and [subtitle] text should be no more than
- * 5 rows of text combined.
+ * aligned. When [subtitle] is used [content] shouldn't exceed 2 lines height. Overall the [title],
+ * [content] and [subtitle] text should be no more than 5 rows of text combined.
*
* If more than one composable is provided in the [content] slot it is the responsibility of the
* caller to determine how to layout the contents, e.g. provide either a row or a column.
*
* Example of a [TitleCard] with [time], [title] and [content]:
+ *
* @sample androidx.wear.compose.material3.samples.TitleCardSample
*
* Example of a [TitleCard] with a background image:
+ *
* @sample androidx.wear.compose.material3.samples.TitleCardWithImageSample
*
* Example of a [TitleCard] with [time], [title] and [subtitle]:
+ *
* @sample androidx.wear.compose.material3.samples.TitleCardWithSubtitleAndTimeSample
*
* Example of an outlined [TitleCard]:
+ *
* @sample androidx.wear.compose.material3.samples.OutlinedTitleCardSample
*
* For more information, see the
- * [Cards](https://developer.android.com/training/wearables/components/cards)
- * guide.
+ * [Cards](https://developer.android.com/training/wearables/components/cards) guide.
*
* @param onClick Will be called when the user clicks the card
- * @param title A slot for displaying the title of the card, expected to be one or
- * two lines of text.
+ * @param title A slot for displaying the title of the card, expected to be one or two lines of
+ * text.
* @param modifier Modifier to be applied to the card
* @param time An optional slot for displaying the time relevant to the contents of the card,
- * expected to be a short piece of text. Depending on whether we have a [content]
- * or not, can be placed at the end of the [title] line or above it.
- * @param subtitle An optional slot for displaying the subtitle of the card, expected to be
- * one line of text.
- * @param enabled Controls the enabled state of the card. When false, this card will not
- * be clickable and there will be no ripple effect on click. Wear cards do not have any specific
- * elevation or alpha differences when not enabled - they are simply not clickable.
+ * expected to be a short piece of text. Depending on whether we have a [content] or not, can be
+ * placed at the end of the [title] line or above it.
+ * @param subtitle An optional slot for displaying the subtitle of the card, expected to be one line
+ * of text.
+ * @param enabled Controls the enabled state of the card. When false, this card will not be
+ * clickable and there will be no ripple effect on click. Wear cards do not have any specific
+ * elevation or alpha differences when not enabled - they are simply not clickable.
* @param shape Defines the card's shape. It is strongly recommended to use the default as this
- * shape is a key characteristic of the Wear Material Theme
+ * shape is a key characteristic of the Wear Material Theme
* @param colors [CardColors] that will be used to resolve the colors used for this card in
- * different states. See [CardDefaults.cardColors].
+ * different states. See [CardDefaults.cardColors].
* @param border A BorderStroke object which is used for drawing outlines.
* @param contentPadding The spacing values to apply internally between the container and the
- * content
+ * content
* @param interactionSource an optional hoisted [MutableInteractionSource] for observing and
- * emitting [Interaction]s for this card. You can use this to change the card's appearance
- * or preview the card in different states. Note that if `null` is provided, interactions will
- * still happen internally.
- * @param content The optional body content of the card. If not provided then title
- * and subtitle are expected to be provided
+ * emitting [Interaction]s for this card. You can use this to change the card's appearance or
+ * preview the card in different states. Note that if `null` is provided, interactions will still
+ * happen internally.
+ * @param content The optional body content of the card. If not provided then title and subtitle are
+ * expected to be provided
*/
@Composable
fun TitleCard(
@@ -313,10 +316,11 @@
val timeWithTextStyle: @Composable () -> Unit = {
time?.let {
CompositionLocalProvider(
- values = arrayOf(
- LocalContentColor provides colors.timeColor,
- LocalTextStyle provides CardTokens.TimeTypography.value
- ),
+ values =
+ arrayOf(
+ LocalContentColor provides colors.timeColor,
+ LocalTextStyle provides CardTokens.TimeTypography.value
+ ),
content = time
)
}
@@ -356,10 +360,11 @@
}
content?.let {
CompositionLocalProvider(
- values = arrayOf(
- LocalContentColor provides colors.contentColor,
- LocalTextStyle provides CardTokens.ContentTypography.value
- ),
+ values =
+ arrayOf(
+ LocalContentColor provides colors.contentColor,
+ LocalTextStyle provides CardTokens.ContentTypography.value
+ ),
content = content
)
}
@@ -379,37 +384,38 @@
/**
* Outlined Wear Material 3 [Card] that offers a single slot to take any content.
*
- * Outlined [Card] components that take specific content such
- * as icons, images, titles, subtitles and labels. Outlined Cards have a
- * visual boundary around the container. This can emphasise the content of this card.
+ * Outlined [Card] components that take specific content such as icons, images, titles, subtitles
+ * and labels. Outlined Cards have a visual boundary around the container. This can emphasise the
+ * content of this card.
*
* The [Card] is Rectangle shaped with rounded corners by default.
*
* Cards can be enabled or disabled. A disabled card will not respond to click events.
*
* Example of an [OutlinedCard]:
+ *
* @sample androidx.wear.compose.material3.samples.OutlinedCardSample
*
* For more information, see the
- * [Cards](https://developer.android.com/training/wearables/components/cards)
- * Wear OS Material design guide.
+ * [Cards](https://developer.android.com/training/wearables/components/cards) Wear OS Material
+ * design guide.
*
* @param onClick Will be called when the user clicks the card
* @param modifier Modifier to be applied to the card
- * @param enabled Controls the enabled state of the card. When false, this card will not
- * be clickable and there will be no ripple effect on click. Wear cards do not have any specific
- * elevation or alpha differences when not enabled - they are simply not clickable.
+ * @param enabled Controls the enabled state of the card. When false, this card will not be
+ * clickable and there will be no ripple effect on click. Wear cards do not have any specific
+ * elevation or alpha differences when not enabled - they are simply not clickable.
* @param shape Defines the card's shape. It is strongly recommended to use the default as this
- * shape is a key characteristic of the Wear Material Theme
+ * shape is a key characteristic of the Wear Material Theme
* @param colors [CardColors] that will be used to resolve the colors used for this card in
- * different states. See [CardDefaults.cardColors].
+ * different states. See [CardDefaults.cardColors].
* @param border A BorderStroke object which is used for the outline drawing.
* @param contentPadding The spacing values to apply internally between the container and the
- * content
+ * content
* @param interactionSource an optional hoisted [MutableInteractionSource] for observing and
- * emitting [Interaction]s for this card. You can use this to change the card's appearance
- * or preview the card in different states. Note that if `null` is provided, interactions will
- * still happen internally.
+ * emitting [Interaction]s for this card. You can use this to change the card's appearance or
+ * preview the card in different states. Note that if `null` is provided, interactions will still
+ * happen internally.
* @param content The main slot for a content of this card
*/
@Composable
@@ -438,17 +444,14 @@
)
}
-/**
- * Contains the default values used by [Card]
- */
+/** Contains the default values used by [Card] */
object CardDefaults {
/**
* Creates a [CardColors] that represents the default container and content colors used in a
* [Card], [AppCard] or [TitleCard].
*/
- @Composable
- fun cardColors() = MaterialTheme.colorScheme.defaultCardColors
+ @Composable fun cardColors() = MaterialTheme.colorScheme.defaultCardColors
/**
* Creates a [CardColors] that represents the default container and content colors used in a
@@ -469,21 +472,21 @@
timeColor: Color = Color.Unspecified,
titleColor: Color = Color.Unspecified,
subtitleColor: Color = Color.Unspecified,
- ): CardColors = MaterialTheme.colorScheme.defaultCardColors.copy(
- containerColor = containerColor,
- contentColor = contentColor,
- appNameColor = appNameColor,
- timeColor = timeColor,
- titleColor = titleColor,
- subtitleColor = subtitleColor
- )
+ ): CardColors =
+ MaterialTheme.colorScheme.defaultCardColors.copy(
+ containerColor = containerColor,
+ contentColor = contentColor,
+ appNameColor = appNameColor,
+ timeColor = timeColor,
+ titleColor = titleColor,
+ subtitleColor = subtitleColor
+ )
/**
* Creates a [CardColors] that represents the default container and content colors used in an
* [OutlinedCard], outlined [AppCard] or [TitleCard].
*/
- @Composable
- fun outlinedCardColors() = MaterialTheme.colorScheme.defaultOutlinedCardColors
+ @Composable fun outlinedCardColors() = MaterialTheme.colorScheme.defaultOutlinedCardColors
/**
* Creates a [CardColors] that represents the default container and content colors used in an
@@ -502,18 +505,19 @@
timeColor: Color = Color.Unspecified,
titleColor: Color = Color.Unspecified,
subtitleColor: Color = Color.Unspecified
- ): CardColors = MaterialTheme.colorScheme.defaultOutlinedCardColors.copy(
- containerColor = Color.Transparent,
- contentColor = contentColor,
- appNameColor = appNameColor,
- timeColor = timeColor,
- titleColor = titleColor,
- subtitleColor = subtitleColor
- )
+ ): CardColors =
+ MaterialTheme.colorScheme.defaultOutlinedCardColors.copy(
+ containerColor = Color.Transparent,
+ contentColor = contentColor,
+ appNameColor = appNameColor,
+ timeColor = timeColor,
+ titleColor = titleColor,
+ subtitleColor = subtitleColor
+ )
/**
- * Creates a [CardColors] that represents the default container and content colors
- * used in a [Card], [AppCard] or [TitleCard] with Image set as a background.
+ * Creates a [CardColors] that represents the default container and content colors used in a
+ * [Card], [AppCard] or [TitleCard] with Image set as a background.
*
* @param containerPainter a Painter which is used for background drawing.
* @param contentColor the content color of this [Card].
@@ -534,19 +538,15 @@
val colorScheme = MaterialTheme.colorScheme
return CardColors(
containerPainter = containerPainter,
- contentColor = contentColor.takeOrElse {
- colorScheme.fromToken(ImageCardTokens.ContentColor)
- },
- appNameColor = appNameColor.takeOrElse {
- colorScheme.fromToken(ImageCardTokens.AppNameColor)
- },
+ contentColor =
+ contentColor.takeOrElse { colorScheme.fromToken(ImageCardTokens.ContentColor) },
+ appNameColor =
+ appNameColor.takeOrElse { colorScheme.fromToken(ImageCardTokens.AppNameColor) },
timeColor = timeColor.takeOrElse { colorScheme.fromToken(ImageCardTokens.TimeColor) },
- titleColor = titleColor.takeOrElse {
- colorScheme.fromToken(ImageCardTokens.TitleColor)
- },
- subtitleColor = subtitleColor.takeOrElse {
- colorScheme.fromToken(ImageCardTokens.SubtitleColor)
- }
+ titleColor =
+ titleColor.takeOrElse { colorScheme.fromToken(ImageCardTokens.TitleColor) },
+ subtitleColor =
+ subtitleColor.takeOrElse { colorScheme.fromToken(ImageCardTokens.SubtitleColor) }
)
}
@@ -561,7 +561,7 @@
*
* @param backgroundImagePainter The [Painter] to use to draw the background of the [Card]
* @param backgroundImageScrimBrush The [Brush] to use to paint a scrim over the background
- * image to ensure that any text drawn over the image is legible
+ * image to ensure that any text drawn over the image is legible
*/
@Composable
fun imageWithScrimBackgroundPainter(
@@ -576,6 +576,7 @@
/**
* Creates a [BorderStroke] that represents the default border used in Outlined Cards.
+ *
* @param outlineColor The color to be used for drawing an outline.
* @param borderWidth width of the border in [Dp].
*/
@@ -583,58 +584,58 @@
fun outlinedCardBorder(
outlineColor: Color = OutlinedCardTokens.ContainerBorderColor.value,
borderWidth: Dp = OutlinedCardTokens.BorderWidth
- ): BorderStroke =
- BorderStroke(borderWidth, outlineColor)
+ ): BorderStroke = BorderStroke(borderWidth, outlineColor)
private val CardHorizontalPadding = 10.dp
private val CardVerticalPadding = 10.dp
private val OverlayScrimColor: Color = Color(0x99202124)
- /**
- * The default content padding used by [Card]
- */
- val ContentPadding: PaddingValues = PaddingValues(
- start = CardHorizontalPadding,
- top = CardVerticalPadding,
- end = CardHorizontalPadding,
- bottom = CardVerticalPadding
- )
+ /** The default content padding used by [Card] */
+ val ContentPadding: PaddingValues =
+ PaddingValues(
+ start = CardHorizontalPadding,
+ top = CardVerticalPadding,
+ end = CardHorizontalPadding,
+ bottom = CardVerticalPadding
+ )
- /**
- * The default size of the app icon/image when used inside a [AppCard].
- */
+ /** The default size of the app icon/image when used inside a [AppCard]. */
val AppImageSize: Dp = CardTokens.AppImageSize
private val ColorScheme.defaultCardColors: CardColors
get() {
- return defaultCardColorsCached ?: CardColors(
- containerPainter = ColorPainter(fromToken(CardTokens.ContainerColor)),
- contentColor = fromToken(CardTokens.ContentColor),
- appNameColor = fromToken(CardTokens.AppNameColor),
- timeColor = fromToken(CardTokens.TimeColor),
- titleColor = fromToken(CardTokens.TitleColor),
- subtitleColor = fromToken(CardTokens.SubtitleColor)
- ).also { defaultCardColorsCached = it }
+ return defaultCardColorsCached
+ ?: CardColors(
+ containerPainter = ColorPainter(fromToken(CardTokens.ContainerColor)),
+ contentColor = fromToken(CardTokens.ContentColor),
+ appNameColor = fromToken(CardTokens.AppNameColor),
+ timeColor = fromToken(CardTokens.TimeColor),
+ titleColor = fromToken(CardTokens.TitleColor),
+ subtitleColor = fromToken(CardTokens.SubtitleColor)
+ )
+ .also { defaultCardColorsCached = it }
}
private val ColorScheme.defaultOutlinedCardColors: CardColors
get() {
- return defaultOutlinedCardColorsCached ?: CardColors(
- containerPainter = ColorPainter(Color.Transparent),
- contentColor = fromToken(OutlinedCardTokens.ContentColor),
- appNameColor = fromToken(OutlinedCardTokens.AppNameColor),
- timeColor = fromToken(OutlinedCardTokens.TimeColor),
- titleColor = fromToken(OutlinedCardTokens.TitleColor),
- subtitleColor = fromToken(OutlinedCardTokens.SubtitleColor)
- ).also { defaultOutlinedCardColorsCached = it }
+ return defaultOutlinedCardColorsCached
+ ?: CardColors(
+ containerPainter = ColorPainter(Color.Transparent),
+ contentColor = fromToken(OutlinedCardTokens.ContentColor),
+ appNameColor = fromToken(OutlinedCardTokens.AppNameColor),
+ timeColor = fromToken(OutlinedCardTokens.TimeColor),
+ titleColor = fromToken(OutlinedCardTokens.TitleColor),
+ subtitleColor = fromToken(OutlinedCardTokens.SubtitleColor)
+ )
+ .also { defaultOutlinedCardColorsCached = it }
}
}
/**
- * Represents Colors used in [Card].
- * Unlike other Material 3 components, Cards do not change their color appearance when
- * they are disabled. All colors remain the same in enabled and disabled states.
+ * Represents Colors used in [Card]. Unlike other Material 3 components, Cards do not change their
+ * color appearance when they are disabled. All colors remain the same in enabled and disabled
+ * states.
*
* @param containerPainter [Painter] which is used to draw the background of this [Card].
* @param contentColor the content color of this [Card].
@@ -660,15 +661,17 @@
timeColor: Color,
titleColor: Color,
subtitleColor: Color
- ) = CardColors(
- containerPainter = if (containerColor != Color.Unspecified) ColorPainter(containerColor)
- else this.containerPainter,
- contentColor = contentColor.takeOrElse { this.contentColor },
- appNameColor = appNameColor.takeOrElse { this.appNameColor },
- timeColor = timeColor.takeOrElse { this.timeColor },
- titleColor = titleColor.takeOrElse { this.titleColor },
- subtitleColor = subtitleColor.takeOrElse { this.subtitleColor }
- )
+ ) =
+ CardColors(
+ containerPainter =
+ if (containerColor != Color.Unspecified) ColorPainter(containerColor)
+ else this.containerPainter,
+ contentColor = contentColor.takeOrElse { this.contentColor },
+ appNameColor = appNameColor.takeOrElse { this.appNameColor },
+ timeColor = timeColor.takeOrElse { this.timeColor },
+ titleColor = titleColor.takeOrElse { this.titleColor },
+ subtitleColor = subtitleColor.takeOrElse { this.subtitleColor }
+ )
override fun equals(other: Any?): Boolean {
if (this === other) return true
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/CurvedText.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/CurvedText.kt
index 708c5a9..f8c386b 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/CurvedText.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/CurvedText.kt
@@ -35,16 +35,14 @@
import androidx.wear.compose.foundation.sizeIn
/**
- * CurvedText is a component allowing developers to easily write curved text following
- * the curvature a circle (usually at the edge of a circular screen).
- * CurvedText can be only created within the CurvedLayout to ensure the best experience, like being
- * able to specify to positioning.
+ * CurvedText is a component allowing developers to easily write curved text following the curvature
+ * a circle (usually at the edge of a circular screen). CurvedText can be only created within the
+ * CurvedLayout to ensure the best experience, like being able to specify to positioning.
*
- * Note that Wear Material UX guidance recommends that [curvedText] should not exceed
- * the sweep angle [CurvedTextDefaults.ScrollableContentMaxSweepAngle] on screens with
- * scrollable content such as lists. This limit is enforced by default.
- * For screens without scrollable content, [CurvedTextDefaults.StaticContentMaxSweepAngle]
- * may be used instead.
+ * Note that Wear Material UX guidance recommends that [curvedText] should not exceed the sweep
+ * angle [CurvedTextDefaults.ScrollableContentMaxSweepAngle] on screens with scrollable content such
+ * as lists. This limit is enforced by default. For screens without scrollable content,
+ * [CurvedTextDefaults.StaticContentMaxSweepAngle] may be used instead.
*
* The default [style] uses the [LocalTextStyle] provided by the [MaterialTheme] / components,
* converting it to a [CurvedTextStyle]. Note that not all parameters are used by [curvedText].
@@ -53,45 +51,44 @@
* and using [TextStyle.copy] to keep any theme defined attributes, only modifying the specific
* attributes you want to override, then convert to [CurvedTextStyle]
*
- * For ease of use, commonly used parameters from [CurvedTextStyle] are also present here. The
- * order of precedence is as follows:
- * - If a parameter is explicitly set here (i.e, it is _not_ `null` or [TextUnit.Unspecified]),
- * then this parameter will always be used.
+ * For ease of use, commonly used parameters from [CurvedTextStyle] are also present here. The order
+ * of precedence is as follows:
+ * - If a parameter is explicitly set here (i.e, it is _not_ `null` or [TextUnit.Unspecified]), then
+ * this parameter will always be used.
* - If a parameter is _not_ set, (`null` or [TextUnit.Unspecified]), then the corresponding value
- * from [style] will be used instead.
+ * from [style] will be used instead.
*
* Additionally, for [color], if [color] is not set, and [style] does not have a color, then
* [LocalContentColor] will be used.
*
* For samples explicitly specifying style see:
- * TODO(b/283777480): Add CurvedText samples
*
* For examples using CompositionLocal to specify the style, see:
- * TODO(b/283777480): Add CurvedText samples
*
* For more information, see the
- * [Curved Text](https://developer.android.com/training/wearables/compose/curved-text)
- * guide.
+ * [Curved Text](https://developer.android.com/training/wearables/compose/curved-text) guide.
*
* @param text The text to display
* @param modifier The [CurvedModifier] to apply to this curved text.
- * @param maxSweepAngle The default maximum sweep angle in degrees. For screens without
- * scrollable content, [CurvedTextDefaults.StaticContentMaxSweepAngle] may be used instead.
+ * @param maxSweepAngle The default maximum sweep angle in degrees. For screens without scrollable
+ * content, [CurvedTextDefaults.StaticContentMaxSweepAngle] may be used instead.
* @param background The background color for the text.
* @param color [Color] to apply to the text. If [Color.Unspecified], and [style] has no color set,
- * this will be [LocalContentColor].
+ * this will be [LocalContentColor].
* @param fontSize The size of glyphs to use when painting the text. See [TextStyle.fontSize].
* @param fontFamily The font family to be used when rendering the text.
* @param fontWeight The thickness of the glyphs, in a range of [1, 1000]. see [FontWeight]
* @param fontStyle The typeface variant to use when drawing the letters (e.g. italic).
- * @param fontSynthesis Whether to synthesize font weight and/or style when the requested weight
- * or style cannot be found in the provided font family.
+ * @param fontSynthesis Whether to synthesize font weight and/or style when the requested weight or
+ * style cannot be found in the provided font family.
* @param style Specifies the style to use.
- * @param angularDirection Specify if the text is laid out clockwise or anti-clockwise, and if
- * those needs to be reversed in a Rtl layout.
- * If not specified, it will be inherited from the enclosing [curvedRow] or [CurvedLayout]
- * See [CurvedDirection.Angular].
+ * @param angularDirection Specify if the text is laid out clockwise or anti-clockwise, and if those
+ * needs to be reversed in a Rtl layout. If not specified, it will be inherited from the enclosing
+ * [curvedRow] or [CurvedLayout] See [CurvedDirection.Angular].
* @param overflow How visual overflow should be handled.
+ *
+ * TODO(b/283777480): Add CurvedText samples
+ * TODO(b/283777480): Add CurvedText samples
*/
fun CurvedScope.curvedText(
text: String,
@@ -107,45 +104,43 @@
style: CurvedTextStyle? = null,
angularDirection: CurvedDirection.Angular? = null,
overflow: TextOverflow = TextOverflow.Clip,
-) = basicCurvedText(
- text = text,
- modifier = modifier.sizeIn(maxSweepDegrees = maxSweepAngle),
- angularDirection = angularDirection,
- overflow = overflow
-) {
- val baseStyle = style ?: CurvedTextStyle(LocalTextStyle.current)
- val textColor = color.takeOrElse {
- baseStyle.color.takeOrElse {
- LocalContentColor.current
- }
- }
- baseStyle.merge(
- CurvedTextStyle(
- color = textColor,
- fontSize = fontSize,
- fontFamily = fontFamily,
- fontWeight = fontWeight,
- fontStyle = fontStyle,
- fontSynthesis = fontSynthesis,
- background = background
+) =
+ basicCurvedText(
+ text = text,
+ modifier = modifier.sizeIn(maxSweepDegrees = maxSweepAngle),
+ angularDirection = angularDirection,
+ overflow = overflow
+ ) {
+ val baseStyle = style ?: CurvedTextStyle(LocalTextStyle.current)
+ val textColor =
+ color.takeOrElse { baseStyle.color.takeOrElse { LocalContentColor.current } }
+ baseStyle.merge(
+ CurvedTextStyle(
+ color = textColor,
+ fontSize = fontSize,
+ fontFamily = fontFamily,
+ fontWeight = fontWeight,
+ fontStyle = fontStyle,
+ fontSynthesis = fontSynthesis,
+ background = background
+ )
)
- )
-}
+ }
object CurvedTextDefaults {
/**
- * The default maximum sweep angle in degrees used by [curvedText]. This threshold
- * is for the [curvedText] displayed on screens with scrollable content, such as lists..
+ * The default maximum sweep angle in degrees used by [curvedText]. This threshold is for the
+ * [curvedText] displayed on screens with scrollable content, such as lists..
*
- * This is calculated by keeping the length of the corresponding chord
- * on the circle to be approximately 57% of the screen width.
+ * This is calculated by keeping the length of the corresponding chord on the circle to be
+ * approximately 57% of the screen width.
*/
const val ScrollableContentMaxSweepAngle: Float = 70f
/**
- * The recommended maximum sweep angle in degrees used by [curvedText]
- * for screens without scrollable content.
+ * The recommended maximum sweep angle in degrees used by [curvedText] for screens without
+ * scrollable content.
*/
const val StaticContentMaxSweepAngle: Float = 120f
}
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/HorizontalPageIndicator.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/HorizontalPageIndicator.kt
index c8e49ea..f711c09 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/HorizontalPageIndicator.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/HorizontalPageIndicator.kt
@@ -60,42 +60,40 @@
import kotlin.math.roundToInt
/**
- * Horizontal page indicator for use with [HorizontalPager], representing
- * the currently active page and the total number of pages.
- * Pages are indicated as a Circle shape.
- * The indicator shows up to six pages individually -
- * if there are more than six pages, [HorizontalPageIndicator] shows a
+ * Horizontal page indicator for use with [HorizontalPager], representing the currently active page
+ * and the total number of pages. Pages are indicated as a Circle shape. The indicator shows up to
+ * six pages individually - if there are more than six pages, [HorizontalPageIndicator] shows a
* half-size indicator to the left or right to indicate that more are available.
*
- * Here's how different positions 0..10 might be visually represented:
- * "X" is selected item, "O" and "o" full and half size items respectively.
+ * Here's how different positions 0..10 might be visually represented: "X" is selected item, "O" and
+ * "o" full and half size items respectively.
*
- * O X O O O o - 2nd position out of 10. There are no more items on the left but more on the right
- * o O O O X o - current page could be 6, 7 or 8 out of 10, as there are more possible items
- * on the left and on the right
- * o O O O X O - current page is 9 out of 10, as there're no more items on the right
+ * O X O O O o - 2nd position out of 10. There are no more items on the left but more on the right o
+ * O O O X o - current page could be 6, 7 or 8 out of 10, as there are more possible items on the
+ * left and on the right o O O O X O - current page is 9 out of 10, as there're no more items on the
+ * right
*
- * [HorizontalPageIndicator] can be linear or curved, depending on the screen shape
- * of the device - for circular screens it will be curved,
- * whilst for square screens it will be linear.
+ * [HorizontalPageIndicator] can be linear or curved, depending on the screen shape of the device -
+ * for circular screens it will be curved, whilst for square screens it will be linear.
*
* @sample androidx.wear.compose.material3.samples.HorizontalPageIndicatorSample
*
* Example usage with HorizontalPager:
+ *
* @sample androidx.wear.compose.material3.samples.HorizontalPageIndicatorWithPagerSample
*
* @param pageCount Total number of pages
* @param currentPage The currently selected page index
- * @param currentPageOffsetFraction The offset fraction of the currently selected page.
- * Represents the offset as a fraction of the transition from the selected page to the next or
- * previous page. Can be positive or negative.
+ * @param currentPageOffsetFraction The offset fraction of the currently selected page. Represents
+ * the offset as a fraction of the transition from the selected page to the next or previous page.
+ * Can be positive or negative.
* @param modifier Modifier to be applied to the [HorizontalPageIndicator]
* @param selectedColor The color of the selected [HorizontalPageIndicator] item
- * @param unselectedColor The color of unselected [HorizontalPageIndicator] items.
- * Defaults to [selectedColor] with 30% alpha
+ * @param unselectedColor The color of unselected [HorizontalPageIndicator] items. Defaults to
+ * [selectedColor] with 30% alpha
* @param indicatorSize The size of each [HorizontalPageIndicator] item in [Dp]
* @param spacing The spacing between indicator items in [Dp]
- **/
+ */
@Composable
public fun HorizontalPageIndicator(
pageCount: Int,
@@ -115,12 +113,8 @@
val offset = currentPageOffsetWithFraction - selectedPage
val pagesOnScreen = Integer.min(MaxNumberOfIndicators, pageCount)
- val pagesState = remember(pageCount) {
- PagesState(
- totalPages = pageCount,
- pagesOnScreen = pagesOnScreen
- )
- }
+ val pagesState =
+ remember(pageCount) { PagesState(totalPages = pageCount, pagesOnScreen = pagesOnScreen) }
pagesState.recalculateState(selectedPage, offset)
val leftSpacerSize = (indicatorSize + spacing) * pagesState.leftSpacerSizeRatio
@@ -130,11 +124,11 @@
var containerSize by remember { mutableStateOf(IntSize.Zero) }
val boundsSize: Density.() -> IntSize = {
-
- val size = IntSize(
- width = ((indicatorSize + spacing).toPx() * pagesOnScreen).roundToInt(),
- height = (indicatorSize * 2).toPx().roundToInt().coerceAtLeast(0)
- )
+ val size =
+ IntSize(
+ width = ((indicatorSize + spacing).toPx() * pagesOnScreen).roundToInt(),
+ height = (indicatorSize * 2).toPx().roundToInt().coerceAtLeast(0)
+ )
size
}
@@ -153,8 +147,8 @@
offset = boundsOffset,
size = boundsSize,
modifier = modifier,
- onSizeChanged = { containerSize = it }) {
-
+ onSizeChanged = { containerSize = it }
+ ) {
CurvedPageIndicator(
visibleDotIndex = pagesState.visibleDotIndex,
pagesOnScreen = pagesOnScreen,
@@ -207,9 +201,7 @@
}
}
-/**
- * Contains the default values used by [HorizontalPageIndicator]
- */
+/** Contains the default values used by [HorizontalPageIndicator] */
internal object PageIndicatorDefaults {
val MaxNumberOfIndicators = 6
@@ -226,8 +218,7 @@
spacerRight: @Composable () -> Unit
) {
Box(
- modifier = Modifier
- .fillMaxSize(),
+ modifier = Modifier.fillMaxSize(),
) {
Row(
modifier = modifier.align(Alignment.BottomCenter),
@@ -244,9 +235,7 @@
indicator(visibleDotIndex)
indicator(visibleDotIndex + 1)
}
- Box {
- selectedIndicator()
- }
+ Box { selectedIndicator() }
}
for (page in visibleDotIndex + 2..pagesOnScreen) {
indicator(page)
@@ -266,8 +255,8 @@
val horizontalPadding = spacing / 2
val isRtl = isLayoutDirectionRtl()
Spacer(
- modifier = Modifier
- .drawWithCache {
+ modifier =
+ Modifier.drawWithCache {
// Adding 2px to fully cover edges of non-selected indicators
val strokeWidth = indicatorSize.toPx() + 2
val startX = horizontalPadding.toPx() + strokeWidth / 2
@@ -281,15 +270,18 @@
// otherwise on APIs <= 26 line will not be drawn
val additionalPixel = if (isRtl) -1 else 1
- val start = Offset(
- startX + drawWidth * (if (isRtl) startSpacerWeight else endSpacerWeight) +
- additionalPixel,
- this.size.height / 2
- )
- val end = Offset(
- endX - drawWidth * (if (isRtl) endSpacerWeight else startSpacerWeight),
- this.size.height / 2
- )
+ val start =
+ Offset(
+ startX +
+ drawWidth * (if (isRtl) startSpacerWeight else endSpacerWeight) +
+ additionalPixel,
+ this.size.height / 2
+ )
+ val end =
+ Offset(
+ endX - drawWidth * (if (isRtl) endSpacerWeight else startSpacerWeight),
+ this.size.height / 2
+ )
onDrawBehind {
drawLine(
color = selectedColor,
@@ -312,10 +304,8 @@
spacing: Dp,
) {
Spacer(
- modifier = Modifier
- .padding(horizontal = spacing / 2)
- .size(indicatorSize)
- .drawWithCache {
+ modifier =
+ Modifier.padding(horizontal = spacing / 2).size(indicatorSize).drawWithCache {
val strokeWidth = indicatorSize.toPx() * pagesState.sizeRatio(page)
val start = Offset(strokeWidth / 2 + 1, this.size.height / 2)
val end = Offset(strokeWidth / 2, this.size.height / 2)
@@ -393,17 +383,16 @@
// Add 0.5dp to cover the sweepDegrees of unselected indicators
curvedRow(CurvedModifier.angularSizeDp(spacing + indicatorSize + 0.5.dp)) {
if (endSpacerWeight > 0f) {
- curvedRow(CurvedModifier.weight(endSpacerWeight)) { }
+ curvedRow(CurvedModifier.weight(endSpacerWeight)) {}
}
curvedRow(
- CurvedModifier
- .background(selectedColor, cap = StrokeCap.Round)
+ CurvedModifier.background(selectedColor, cap = StrokeCap.Round)
.weight(blurbWeight)
// Adding 0.3dp to fully cover edges of non-selected indicators
.radialSize(indicatorSize + 0.3.dp)
- ) { }
+ ) {}
if (startSpacerWeight > 0f) {
- curvedRow(CurvedModifier.weight(startSpacerWeight)) { }
+ curvedRow(CurvedModifier.weight(startSpacerWeight)) {}
}
}
}
@@ -422,14 +411,13 @@
// Values below 0.2f also give some artifacts b/291753164
.size(0.2f, size * pagesState.sizeRatio(page))
.background(
- color = unselectedColor.copy(
- alpha = unselectedColor.alpha * pagesState.alpha(page)
- ),
+ color =
+ unselectedColor.copy(alpha = unselectedColor.alpha * pagesState.alpha(page)),
cap = StrokeCap.Round
)
- ) { }
+ ) {}
}
private fun CurvedScope.curvedSpacer(size: Dp) {
- curvedBox(CurvedModifier.angularSizeDp(size).radialSize(0.dp)) { }
+ curvedBox(CurvedModifier.angularSizeDp(size).radialSize(0.dp)) {}
}
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Icon.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Icon.kt
index 70d0acf..1abf5e6 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Icon.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Icon.kt
@@ -32,12 +32,12 @@
*
* @param imageVector [ImageVector] to draw inside this Icon
* @param contentDescription Text used by accessibility services to describe what this icon
- * represents. This should always be provided unless this icon is used for decorative purposes,
- * and does not represent a meaningful action that a user can take. This text should be
- * localized, such as by using [androidx.compose.ui.res.stringResource] or similar
+ * represents. This should always be provided unless this icon is used for decorative purposes,
+ * and does not represent a meaningful action that a user can take. This text should be localized,
+ * such as by using [androidx.compose.ui.res.stringResource] or similar
* @param modifier Optional [Modifier] for this Icon
- * @param tint Tint to be applied to [imageVector]. If [Color.Unspecified] is provided, then no
- * tint is applied
+ * @param tint Tint to be applied to [imageVector]. If [Color.Unspecified] is provided, then no tint
+ * is applied
*/
@Composable
fun Icon(
@@ -60,12 +60,12 @@
*
* @param bitmap [ImageBitmap] to draw inside this Icon
* @param contentDescription Text used by accessibility services to describe what this icon
- * represents. This should always be provided unless this icon is used for decorative purposes,
- * and does not represent a meaningful action that a user can take. This text should be
- * localized, such as by using [androidx.compose.ui.res.stringResource] or similar
+ * represents. This should always be provided unless this icon is used for decorative purposes,
+ * and does not represent a meaningful action that a user can take. This text should be localized,
+ * such as by using [androidx.compose.ui.res.stringResource] or similar
* @param modifier Optional [Modifier] for this Icon
- * @param tint Tint to be applied to [bitmap]. If [Color.Unspecified] is provided, then no
- * tint is applied
+ * @param tint Tint to be applied to [bitmap]. If [Color.Unspecified] is provided, then no tint is
+ * applied
*/
@Composable
fun Icon(
@@ -89,12 +89,12 @@
*
* @param painter [Painter] to draw inside this Icon
* @param contentDescription Text used by accessibility services to describe what this icon
- * represents. This should always be provided unless this icon is used for decorative purposes,
- * and does not represent a meaningful action that a user can take. This text should be
- * localized, such as by using [androidx.compose.ui.res.stringResource] or similar
+ * represents. This should always be provided unless this icon is used for decorative purposes,
+ * and does not represent a meaningful action that a user can take. This text should be localized,
+ * such as by using [androidx.compose.ui.res.stringResource] or similar
* @param modifier Optional [Modifier] for this Icon
- * @param tint Tint to be applied to [painter]. If [Color.Unspecified] is provided, then no
- * tint is applied
+ * @param tint Tint to be applied to [painter]. If [Color.Unspecified] is provided, then no tint is
+ * applied
*/
@Composable
fun Icon(
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/IconButton.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/IconButton.kt
index 298671f..969d782 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/IconButton.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/IconButton.kt
@@ -36,41 +36,42 @@
import androidx.wear.compose.material3.tokens.OutlinedIconButtonTokens
/**
- * Wear Material [IconButton] is a circular, icon-only button with transparent background and
- * no border. It offers a single slot to take icon or image content.
+ * Wear Material [IconButton] is a circular, icon-only button with transparent background and no
+ * border. It offers a single slot to take icon or image content.
*
- * Set the size of the [IconButton] with Modifier.[touchTargetAwareSize]
- * to ensure that the recommended minimum touch target size is available.
+ * Set the size of the [IconButton] with Modifier.[touchTargetAwareSize] to ensure that the
+ * recommended minimum touch target size is available.
*
* The recommended [IconButton] sizes are [IconButtonDefaults.DefaultButtonSize],
* [IconButtonDefaults.LargeButtonSize], [IconButtonDefaults.SmallButtonSize] and
* [IconButtonDefaults.ExtraSmallButtonSize].
*
- * Use [IconButtonDefaults.iconSizeFor] to determine the icon size for a
- * given [IconButtonDefaults] size, or refer to icon sizes [IconButtonDefaults.SmallIconSize],
+ * Use [IconButtonDefaults.iconSizeFor] to determine the icon size for a given [IconButtonDefaults]
+ * size, or refer to icon sizes [IconButtonDefaults.SmallIconSize],
* [IconButtonDefaults.DefaultIconSize], [IconButtonDefaults.LargeButtonSize] directly.
*
* [IconButton] can be enabled or disabled. A disabled button will not respond to click events.
*
- * TODO(b/261838497) Add Material3 samples and UX guidance links
- *
* Example of an [IconButton]:
+ *
* @sample androidx.wear.compose.material3.samples.IconButtonSample
*
* @param onClick Will be called when the user clicks the button.
* @param modifier Modifier to be applied to the button.
- * @param enabled Controls the enabled state of the button. When `false`, this button will not
- * be clickable.
- * @param shape Defines the icon button's shape. It is strongly recommended to use the default
- * as this shape is a key characteristic of the Wear Material3 design.
+ * @param enabled Controls the enabled state of the button. When `false`, this button will not be
+ * clickable.
+ * @param shape Defines the icon button's shape. It is strongly recommended to use the default as
+ * this shape is a key characteristic of the Wear Material3 design.
* @param colors [IconButtonColors] that will be used to resolve the background and icon color for
- * this button in different states.
+ * this button in different states.
* @param border Optional [BorderStroke] for the icon button border.
* @param interactionSource an optional hoisted [MutableInteractionSource] for observing and
- * emitting [Interaction]s for this button. You can use this to change the button's appearance
- * or preview the button in different states. Note that if `null` is provided, interactions will
- * still happen internally.
+ * emitting [Interaction]s for this button. You can use this to change the button's appearance or
+ * preview the button in different states. Note that if `null` is provided, interactions will
+ * still happen internally.
* @param content The content displayed on the icon button, expected to be icon or image.
+ *
+ * TODO(b/261838497) Add Material3 samples and UX guidance links
*/
@Composable
fun IconButton(
@@ -93,50 +94,48 @@
border = { border },
buttonSize = IconButtonDefaults.DefaultButtonSize,
ripple = rippleOrFallbackImplementation(),
- content = provideScopeContent(
- colors.contentColor(enabled = enabled),
- content
- )
+ content = provideScopeContent(colors.contentColor(enabled = enabled), content)
)
}
/**
- * Wear Material [FilledIconButton] is a circular, icon-only button with a colored background
- * and a contrasting content color. It offers a single slot to take an icon or image.
+ * Wear Material [FilledIconButton] is a circular, icon-only button with a colored background and a
+ * contrasting content color. It offers a single slot to take an icon or image.
*
- * Set the size of the [FilledIconButton] with Modifier.[touchTargetAwareSize]
- * to ensure that the recommended minimum touch target size is available.
+ * Set the size of the [FilledIconButton] with Modifier.[touchTargetAwareSize] to ensure that the
+ * recommended minimum touch target size is available.
*
* The recommended [IconButton] sizes are [IconButtonDefaults.DefaultButtonSize],
* [IconButtonDefaults.LargeButtonSize], [IconButtonDefaults.SmallButtonSize] and
* [IconButtonDefaults.ExtraSmallButtonSize].
*
- * Use [IconButtonDefaults.iconSizeFor] to determine the icon size for a
- * given [IconButton] size, or refer to icon sizes [IconButtonDefaults.SmallIconSize],
- * [IconButtonDefaults.DefaultIconSize], [IconButtonDefaults.LargeIconSize] directly.
+ * Use [IconButtonDefaults.iconSizeFor] to determine the icon size for a given [IconButton] size, or
+ * refer to icon sizes [IconButtonDefaults.SmallIconSize], [IconButtonDefaults.DefaultIconSize],
+ * [IconButtonDefaults.LargeIconSize] directly.
*
- * [FilledIconButton] can be enabled or disabled. A disabled button will not respond to
- * click events.
- *
- * TODO(b/261838497) Add Material3 samples and UX guidance links
+ * [FilledIconButton] can be enabled or disabled. A disabled button will not respond to click
+ * events.
*
* Example of [FilledIconButton]:
+ *
* @sample androidx.wear.compose.material3.samples.FilledIconButtonSample
*
* @param onClick Will be called when the user clicks the button.
* @param modifier Modifier to be applied to the button.
- * @param enabled Controls the enabled state of the button. When `false`, this button will not
- * be clickable.
- * @param shape Defines the icon button's shape. It is strongly recommended to use the default
- * as this shape is a key characteristic of the Wear Material3 design.
+ * @param enabled Controls the enabled state of the button. When `false`, this button will not be
+ * clickable.
+ * @param shape Defines the icon button's shape. It is strongly recommended to use the default as
+ * this shape is a key characteristic of the Wear Material3 design.
* @param colors [IconButtonColors] that will be used to resolve the container and content color for
- * this icon button in different states.
+ * this icon button in different states.
* @param border Optional [BorderStroke] for the icon button border.
* @param interactionSource an optional hoisted [MutableInteractionSource] for observing and
- * emitting [Interaction]s for this button. You can use this to change the button's appearance
- * or preview the button in different states. Note that if `null` is provided, interactions will
- * still happen internally.
+ * emitting [Interaction]s for this button. You can use this to change the button's appearance or
+ * preview the button in different states. Note that if `null` is provided, interactions will
+ * still happen internally.
* @param content The content displayed on the icon button, expected to be icon or image.
+ *
+ * TODO(b/261838497) Add Material3 samples and UX guidance links
*/
@Composable
fun FilledIconButton(
@@ -154,39 +153,40 @@
* Wear Material [FilledTonalIconButton] is a circular, icon-only button with a muted, colored
* background and a contrasting icon color. It offers a single slot to take an icon or image.
*
- * Set the size of the [FilledTonalIconButton] with Modifier.[touchTargetAwareSize]
- * to ensure that the recommended minimum touch target size is available.
+ * Set the size of the [FilledTonalIconButton] with Modifier.[touchTargetAwareSize] to ensure that
+ * the recommended minimum touch target size is available.
*
* The recommended icon button sizes are [IconButtonDefaults.DefaultButtonSize],
* [IconButtonDefaults.LargeButtonSize], [IconButtonDefaults.SmallButtonSize] and
* [IconButtonDefaults.ExtraSmallButtonSize].
*
- * Use [IconButtonDefaults.iconSizeFor] to determine the icon size for a
- * given [IconButtonDefaults] size, or refer to icon sizes [IconButtonDefaults.SmallIconSize],
+ * Use [IconButtonDefaults.iconSizeFor] to determine the icon size for a given [IconButtonDefaults]
+ * size, or refer to icon sizes [IconButtonDefaults.SmallIconSize],
* [IconButtonDefaults.DefaultIconSize], [IconButtonDefaults.LargeButtonSize] directly.
*
- * [FilledTonalIconButton] can be enabled or disabled.
- * A disabled button will not respond to click events.
- *
- * TODO(b/261838497) Add Material3 samples and UX guidance links
+ * [FilledTonalIconButton] can be enabled or disabled. A disabled button will not respond to click
+ * events.
*
* Example of [FilledTonalIconButton]:
+ *
* @sample androidx.wear.compose.material3.samples.FilledTonalIconButtonSample
*
* @param onClick Will be called when the user clicks the button.
* @param modifier Modifier to be applied to the button.
- * @param enabled Controls the enabled state of the button. When `false`, this button will not
- * be clickable.
- * @param shape Defines the icon button's shape. It is strongly recommended to use the default
- * as this shape is a key characteristic of the Wear Material3 design.
+ * @param enabled Controls the enabled state of the button. When `false`, this button will not be
+ * clickable.
+ * @param shape Defines the icon button's shape. It is strongly recommended to use the default as
+ * this shape is a key characteristic of the Wear Material3 design.
* @param colors [IconButtonColors] that will be used to resolve the background and icon color for
- * this button in different states.
+ * this button in different states.
* @param border Optional [BorderStroke] for the icon button border.
* @param interactionSource an optional hoisted [MutableInteractionSource] for observing and
- * emitting [Interaction]s for this button. You can use this to change the button's appearance
- * or preview the button in different states. Note that if `null` is provided, interactions will
- * still happen internally.
+ * emitting [Interaction]s for this button. You can use this to change the button's appearance or
+ * preview the button in different states. Note that if `null` is provided, interactions will
+ * still happen internally.
* @param content The content displayed on the icon button, expected to be icon or image.
+ *
+ * TODO(b/261838497) Add Material3 samples and UX guidance links
*/
@Composable
fun FilledTonalIconButton(
@@ -204,43 +204,44 @@
* Wear Material [OutlinedIconButton] is a circular, icon-only button with a transparent background,
* contrasting icon color and border. It offers a single slot to take an icon or image.
*
- * Set the size of the [OutlinedIconButton] with Modifier.[touchTargetAwareSize]
- * to ensure that the recommended minimum touch target size is available.
+ * Set the size of the [OutlinedIconButton] with Modifier.[touchTargetAwareSize] to ensure that the
+ * recommended minimum touch target size is available.
*
* The recommended icon button sizes are [IconButtonDefaults.DefaultButtonSize],
* [IconButtonDefaults.LargeButtonSize], [IconButtonDefaults.SmallButtonSize] and
* [IconButtonDefaults.ExtraSmallButtonSize].
*
- * Use [IconButtonDefaults.iconSizeFor] to determine the icon size for a
- * given [IconButtonDefaults] size, or refer to icon sizes [IconButtonDefaults.SmallIconSize],
+ * Use [IconButtonDefaults.iconSizeFor] to determine the icon size for a given [IconButtonDefaults]
+ * size, or refer to icon sizes [IconButtonDefaults.SmallIconSize],
* [IconButtonDefaults.DefaultIconSize], [IconButtonDefaults.LargeButtonSize] directly.
*
- * [OutlinedIconButton] can be enabled or disabled.
- * A disabled button will not respond to click events.
+ * [OutlinedIconButton] can be enabled or disabled. A disabled button will not respond to click
+ * events.
*
- * An [OutlinedIconButton] has a transparent background and a thin border by default with
- * content taking the theme primary color.
- *
- * TODO(b/261838497) Add Material3 samples and UX guidance links
+ * An [OutlinedIconButton] has a transparent background and a thin border by default with content
+ * taking the theme primary color.
*
* Example of [OutlinedIconButton]:
+ *
* @sample androidx.wear.compose.material3.samples.OutlinedIconButtonSample
*
* @param onClick Will be called when the user clicks the button.
* @param modifier Modifier to be applied to the button.
- * @param enabled Controls the enabled state of the button. When `false`, this button will not
- * be clickable.
- * @param shape Defines the icon button's shape. It is strongly recommended to use the default
- * as this shape is a key characteristic of the Wear Material3 design.
+ * @param enabled Controls the enabled state of the button. When `false`, this button will not be
+ * clickable.
+ * @param shape Defines the icon button's shape. It is strongly recommended to use the default as
+ * this shape is a key characteristic of the Wear Material3 design.
* @param colors [IconButtonColors] that will be used to resolve the background and icon color for
- * this button in different states. See [IconButtonDefaults.outlinedIconButtonColors].
- * @param border Optional [BorderStroke] for the icon button border -
- * [ButtonDefaults.outlinedButtonBorder] by default.
+ * this button in different states. See [IconButtonDefaults.outlinedIconButtonColors].
+ * @param border Optional [BorderStroke] for the icon button
+ * border - [ButtonDefaults.outlinedButtonBorder] by default.
* @param interactionSource an optional hoisted [MutableInteractionSource] for observing and
- * emitting [Interaction]s for this button. You can use this to change the button's appearance
- * or preview the button in different states. Note that if `null` is provided, interactions will
- * still happen internally.
+ * emitting [Interaction]s for this button. You can use this to change the button's appearance or
+ * preview the button in different states. Note that if `null` is provided, interactions will
+ * still happen internally.
* @param content The content displayed on the icon button, expected to be icon or image.
+ *
+ * TODO(b/261838497) Add Material3 samples and UX guidance links
*/
@Composable
fun OutlinedIconButton(
@@ -256,39 +257,38 @@
/**
* Wear Material [IconToggleButton] is a filled icon toggle button which switches between primary
- * colors and tonal colors depending on [checked] value, and offers a single slot for
- * icon or image.
+ * colors and tonal colors depending on [checked] value, and offers a single slot for icon or image.
*
- * Set the size of the [IconToggleButton] with Modifier.[touchTargetAwareSize]
- * to ensure that the background padding will correctly reach the edge of the minimum touch target.
- * The recommended text button sizes are [IconButtonDefaults.DefaultButtonSize],
+ * Set the size of the [IconToggleButton] with Modifier.[touchTargetAwareSize] to ensure that the
+ * background padding will correctly reach the edge of the minimum touch target. The recommended
+ * text button sizes are [IconButtonDefaults.DefaultButtonSize],
* [IconButtonDefaults.LargeButtonSize], [IconButtonDefaults.SmallButtonSize] and
* [IconButtonDefaults.ExtraSmallButtonSize].
*
- * Use [IconButtonDefaults.iconSizeFor] to determine the icon size for a
- * given [IconToggleButton] size, or refer to icon sizes
- * [IconButtonDefaults.SmallIconSize], [IconButtonDefaults.DefaultIconSize],
- * [IconButtonDefaults.LargeIconSize] directly.
+ * Use [IconButtonDefaults.iconSizeFor] to determine the icon size for a given [IconToggleButton]
+ * size, or refer to icon sizes [IconButtonDefaults.SmallIconSize],
+ * [IconButtonDefaults.DefaultIconSize], [IconButtonDefaults.LargeIconSize] directly.
*
- * [IconToggleButton] can be enabled or disabled. A disabled button will not respond to
- * click events. When enabled, the checked and unchecked events are propagated by [onCheckedChange].
+ * [IconToggleButton] can be enabled or disabled. A disabled button will not respond to click
+ * events. When enabled, the checked and unchecked events are propagated by [onCheckedChange].
*
* A simple icon toggle button using the default colors
+ *
* @sample androidx.wear.compose.material3.samples.IconToggleButtonSample
*
* @param checked Boolean flag indicating whether this toggle button is currently checked.
* @param onCheckedChange Callback to be invoked when this toggle button is clicked.
* @param modifier Modifier to be applied to the toggle button.
- * @param enabled Controls the enabled state of the toggle button. When `false`,
- * this toggle button will not be clickable.
- * @param colors [ToggleButtonColors] that will be used to resolve the container and
- * content color for this toggle button.
+ * @param enabled Controls the enabled state of the toggle button. When `false`, this toggle button
+ * will not be clickable.
+ * @param colors [ToggleButtonColors] that will be used to resolve the container and content color
+ * for this toggle button.
* @param interactionSource an optional hoisted [MutableInteractionSource] for observing and
- * emitting [Interaction]s for this button. You can use this to change the button's appearance
- * or preview the button in different states. Note that if `null` is provided, interactions will
- * still happen internally.
+ * emitting [Interaction]s for this button. You can use this to change the button's appearance or
+ * preview the button in different states. Note that if `null` is provided, interactions will
+ * still happen internally.
* @param shape Defines the shape for this toggle button. It is strongly recommended to use the
- * default as this shape is a key characteristic of the Wear Material 3 Theme.
+ * default as this shape is a key characteristic of the Wear Material 3 Theme.
* @param border Optional [BorderStroke] for the [IconToggleButton].
* @param content The content to be drawn inside the toggle button.
*/
@@ -317,20 +317,14 @@
interactionSource = interactionSource,
shape = shape,
ripple = rippleOrFallbackImplementation(),
- content = provideScopeContent(
- colors.contentColor(enabled = enabled, checked = checked),
- content
- )
+ content =
+ provideScopeContent(colors.contentColor(enabled = enabled, checked = checked), content)
)
}
-/**
- * Contains the default values used by [IconButton].
- */
+/** Contains the default values used by [IconButton]. */
object IconButtonDefaults {
- /**
- * Recommended [Shape] for [IconButton].
- */
+ /** Recommended [Shape] for [IconButton]. */
val shape: Shape
@Composable get() = IconButtonTokens.ContainerShape.value
@@ -339,31 +333,30 @@
*
* Ensures that the minimum recommended icon size is applied.
*
- * Examples: for size [LargeButtonSize], returns [LargeIconSize],
- * for size [ExtraSmallButtonSize] returns [SmallIconSize].
+ * Examples: for size [LargeButtonSize], returns [LargeIconSize], for size
+ * [ExtraSmallButtonSize] returns [SmallIconSize].
*
* @param size The size of the icon button
*/
- fun iconSizeFor(size: Dp): Dp = if (size >= LargeButtonSize) {
- LargeIconSize
- } else {
- max(SmallIconSize, size / 2f)
- }
+ fun iconSizeFor(size: Dp): Dp =
+ if (size >= LargeButtonSize) {
+ LargeIconSize
+ } else {
+ max(SmallIconSize, size / 2f)
+ }
/**
- * Creates a [IconButtonColors] with the colors for [FilledIconButton] - by default,
- * a colored background with a contrasting icon color.
- * If the icon button is disabled then the colors will default to
- * the MaterialTheme onSurface color with suitable alpha values applied.
+ * Creates a [IconButtonColors] with the colors for [FilledIconButton] - by default, a colored
+ * background with a contrasting icon color. If the icon button is disabled then the colors will
+ * default to the MaterialTheme onSurface color with suitable alpha values applied.
*/
@Composable
fun filledIconButtonColors() = MaterialTheme.colorScheme.defaultFilledIconButtonColors
/**
- * Creates a [IconButtonColors] with the colors for [FilledIconButton] - by default,
- * a colored background with a contrasting icon color.
- * If the icon button is disabled then the colors will default to
- * the MaterialTheme onSurface color with suitable alpha values applied.
+ * Creates a [IconButtonColors] with the colors for [FilledIconButton] - by default, a colored
+ * background with a contrasting icon color. If the icon button is disabled then the colors will
+ * default to the MaterialTheme onSurface color with suitable alpha values applied.
*
* @param containerColor The background color of this icon button when enabled.
* @param contentColor The color of this icon when enabled.
@@ -376,27 +369,26 @@
contentColor: Color = Color.Unspecified,
disabledContainerColor: Color = Color.Unspecified,
disabledContentColor: Color = Color.Unspecified
- ): IconButtonColors = MaterialTheme.colorScheme.defaultFilledIconButtonColors.copy(
- containerColor = containerColor,
- contentColor = contentColor,
- disabledContainerColor = disabledContainerColor,
- disabledContentColor = disabledContentColor
- )
+ ): IconButtonColors =
+ MaterialTheme.colorScheme.defaultFilledIconButtonColors.copy(
+ containerColor = containerColor,
+ contentColor = contentColor,
+ disabledContainerColor = disabledContainerColor,
+ disabledContentColor = disabledContentColor
+ )
/**
- * Creates a [IconButtonColors] with the colors for [FilledTonalIconButton]- by default,
- * a muted colored background with a contrasting icon color.
- * If the icon button is disabled then the colors will default to
- * the MaterialTheme onSurface color with suitable alpha values applied.
+ * Creates a [IconButtonColors] with the colors for [FilledTonalIconButton]- by default, a muted
+ * colored background with a contrasting icon color. If the icon button is disabled then the
+ * colors will default to the MaterialTheme onSurface color with suitable alpha values applied.
*/
@Composable
fun filledTonalIconButtonColors() = MaterialTheme.colorScheme.defaultFilledTonalIconButtonColors
/**
- * Creates a [IconButtonColors] with the colors for [FilledTonalIconButton]- by default,
- * a muted colored background with a contrasting icon color.
- * If the icon button is disabled then the colors will default to
- * the MaterialTheme onSurface color with suitable alpha values applied.
+ * Creates a [IconButtonColors] with the colors for [FilledTonalIconButton]- by default, a muted
+ * colored background with a contrasting icon color. If the icon button is disabled then the
+ * colors will default to the MaterialTheme onSurface color with suitable alpha values applied.
*
* @param containerColor The background color of this icon button when enabled.
* @param contentColor The color of this icon when enabled.
@@ -409,27 +401,26 @@
contentColor: Color = Color.Unspecified,
disabledContainerColor: Color = Color.Unspecified,
disabledContentColor: Color = Color.Unspecified
- ): IconButtonColors = MaterialTheme.colorScheme.defaultFilledTonalIconButtonColors.copy(
- containerColor = containerColor,
- contentColor = contentColor,
- disabledContainerColor = disabledContainerColor,
- disabledContentColor = disabledContentColor
- )
+ ): IconButtonColors =
+ MaterialTheme.colorScheme.defaultFilledTonalIconButtonColors.copy(
+ containerColor = containerColor,
+ contentColor = contentColor,
+ disabledContainerColor = disabledContainerColor,
+ disabledContentColor = disabledContentColor
+ )
/**
- * Creates a [IconButtonColors] with the colors for [OutlinedIconButton]- by default,
- * a transparent background with contrasting icon color.
- * If the icon button is disabled then the colors will default to
- * the MaterialTheme onSurface color with suitable alpha values applied.
+ * Creates a [IconButtonColors] with the colors for [OutlinedIconButton]- by default, a
+ * transparent background with contrasting icon color. If the icon button is disabled then the
+ * colors will default to the MaterialTheme onSurface color with suitable alpha values applied.
*/
@Composable
fun outlinedIconButtonColors() = MaterialTheme.colorScheme.defaultOutlinedIconButtonColors
/**
- * Creates a [IconButtonColors] with the colors for [OutlinedIconButton]- by default,
- * a transparent background with contrasting icon color.
- * If the icon button is disabled then the colors will default to
- * the MaterialTheme onSurface color with suitable alpha values applied.
+ * Creates a [IconButtonColors] with the colors for [OutlinedIconButton]- by default, a
+ * transparent background with contrasting icon color. If the icon button is disabled then the
+ * colors will default to the MaterialTheme onSurface color with suitable alpha values applied.
*
* @param contentColor The color of this icon button when enabled.
* @param disabledContentColor The color of this icon when not enabled.
@@ -438,27 +429,25 @@
fun outlinedIconButtonColors(
contentColor: Color = Color.Unspecified,
disabledContentColor: Color = Color.Unspecified
- ): IconButtonColors = MaterialTheme.colorScheme.defaultOutlinedIconButtonColors.copy(
- containerColor = Color.Transparent,
- contentColor = contentColor,
- disabledContainerColor = Color.Transparent,
- disabledContentColor = disabledContentColor
- )
+ ): IconButtonColors =
+ MaterialTheme.colorScheme.defaultOutlinedIconButtonColors.copy(
+ containerColor = Color.Transparent,
+ contentColor = contentColor,
+ disabledContainerColor = Color.Transparent,
+ disabledContentColor = disabledContentColor
+ )
/**
- * Creates a [IconButtonColors] with the colors for [IconButton] - by default,
- * a transparent background with a contrasting icon color.
- * If the icon button is disabled then the colors will default to
- * the MaterialTheme onSurface color with suitable alpha values applied.
+ * Creates a [IconButtonColors] with the colors for [IconButton] - by default, a transparent
+ * background with a contrasting icon color. If the icon button is disabled then the colors will
+ * default to the MaterialTheme onSurface color with suitable alpha values applied.
*/
- @Composable
- fun iconButtonColors() = MaterialTheme.colorScheme.defaultIconButtonColors
+ @Composable fun iconButtonColors() = MaterialTheme.colorScheme.defaultIconButtonColors
/**
- * Creates a [IconButtonColors] with the colors for [IconButton] - by default,
- * a transparent background with a contrasting icon color.
- * If the icon button is disabled then the colors will default to
- * the MaterialTheme onSurface color with suitable alpha values applied.
+ * Creates a [IconButtonColors] with the colors for [IconButton] - by default, a transparent
+ * background with a contrasting icon color. If the icon button is disabled then the colors will
+ * default to the MaterialTheme onSurface color with suitable alpha values applied.
*
* @param containerColor The background color of this icon button when enabled.
* @param contentColor The color of this icon when enabled.
@@ -471,19 +460,20 @@
contentColor: Color = Color.Unspecified,
disabledContainerColor: Color = Color.Transparent,
disabledContentColor: Color = Color.Unspecified
- ): IconButtonColors = MaterialTheme.colorScheme.defaultIconButtonColors.copy(
- containerColor = containerColor,
- contentColor = contentColor,
- disabledContainerColor = disabledContainerColor,
- disabledContentColor = disabledContentColor,
- )
+ ): IconButtonColors =
+ MaterialTheme.colorScheme.defaultIconButtonColors.copy(
+ containerColor = containerColor,
+ contentColor = contentColor,
+ disabledContainerColor = disabledContainerColor,
+ disabledContentColor = disabledContentColor,
+ )
/**
* Creates a [ToggleButtonColors] for a [IconToggleButton]
* - by default, a colored background with a contrasting content color.
*
- * If the button is disabled, then the colors will have an alpha
- * ([DisabledContentAlpha] and [DisabledContainerAlpha]) value applied.
+ * If the button is disabled, then the colors will have an alpha ([DisabledContentAlpha] and
+ * [DisabledContainerAlpha]) value applied.
*/
@Composable
fun iconToggleButtonColors() = MaterialTheme.colorScheme.defaultIconToggleButtonColors
@@ -492,25 +482,25 @@
* Creates a [ToggleButtonColors] for a [IconToggleButton]
* - by default, a colored background with a contrasting content color.
*
- * If the button is disabled, then the colors will have an alpha
- * ([DisabledContentAlpha] and [DisabledContainerAlpha]) value applied.
+ * If the button is disabled, then the colors will have an alpha ([DisabledContentAlpha] and
+ * [DisabledContainerAlpha]) value applied.
*
- * @param checkedContainerColor The container color of this [IconToggleButton] when enabled
- * and checked
+ * @param checkedContainerColor The container color of this [IconToggleButton] when enabled and
+ * checked
* @param checkedContentColor The content color of this [IconToggleButton] when enabled and
- * checked
+ * checked
* @param uncheckedContainerColor The container color of this [IconToggleButton] when enabled
- * and unchecked
+ * and unchecked
* @param uncheckedContentColor The content color of this [IconToggleButton] when enabled and
- * unchecked
+ * unchecked
* @param disabledCheckedContainerColor The container color of this [IconToggleButton] when
- * checked and not enabled
+ * checked and not enabled
* @param disabledCheckedContentColor The content color of this [IconToggleButton] when checked
- * and not enabled
+ * and not enabled
* @param disabledUncheckedContainerColor The container color of this [IconToggleButton] when
- * unchecked and not enabled
+ * unchecked and not enabled
* @param disabledUncheckedContentColor The content color of this [IconToggleButton] when
- * unchecked and not enabled
+ * unchecked and not enabled
*/
@Composable
fun iconToggleButtonColors(
@@ -522,152 +512,181 @@
disabledCheckedContentColor: Color = Color.Unspecified,
disabledUncheckedContainerColor: Color = Color.Unspecified,
disabledUncheckedContentColor: Color = Color.Unspecified,
- ): ToggleButtonColors = MaterialTheme.colorScheme.defaultIconToggleButtonColors.copy(
- checkedContainerColor = checkedContainerColor,
- checkedContentColor = checkedContentColor,
- uncheckedContainerColor = uncheckedContainerColor,
- uncheckedContentColor = uncheckedContentColor,
- disabledCheckedContainerColor = disabledCheckedContainerColor,
- disabledCheckedContentColor = disabledCheckedContentColor,
- disabledUncheckedContainerColor = disabledUncheckedContainerColor,
- disabledUncheckedContentColor = disabledUncheckedContentColor,
- )
+ ): ToggleButtonColors =
+ MaterialTheme.colorScheme.defaultIconToggleButtonColors.copy(
+ checkedContainerColor = checkedContainerColor,
+ checkedContentColor = checkedContentColor,
+ uncheckedContainerColor = uncheckedContainerColor,
+ uncheckedContentColor = uncheckedContentColor,
+ disabledCheckedContainerColor = disabledCheckedContainerColor,
+ disabledCheckedContentColor = disabledCheckedContentColor,
+ disabledUncheckedContainerColor = disabledUncheckedContainerColor,
+ disabledUncheckedContentColor = disabledUncheckedContentColor,
+ )
/**
- * The recommended size of an icon when used inside an icon button with size
- * [SmallButtonSize] or [ExtraSmallButtonSize].
- * Use [iconSizeFor] to easily determine the icon size.
+ * The recommended size of an icon when used inside an icon button with size [SmallButtonSize]
+ * or [ExtraSmallButtonSize]. Use [iconSizeFor] to easily determine the icon size.
*/
val SmallIconSize = IconButtonTokens.IconSmallSize
/**
- * The default size of an icon when used inside an icon button of size DefaultButtonSize.
- * Use [iconSizeFor] to easily determine the icon size.
+ * The default size of an icon when used inside an icon button of size DefaultButtonSize. Use
+ * [iconSizeFor] to easily determine the icon size.
*/
val DefaultIconSize = IconButtonTokens.IconDefaultSize
/**
- * The size of an icon when used inside an icon button with size [LargeButtonSize].
- * Use [iconSizeFor] to easily determine the icon size.
+ * The size of an icon when used inside an icon button with size [LargeButtonSize]. Use
+ * [iconSizeFor] to easily determine the icon size.
*/
val LargeIconSize = IconButtonTokens.IconLargeSize
/**
- * The recommended background size of an extra small, compact button.
- * It is recommended to apply this size using Modifier.touchTargetAwareSize.
+ * The recommended background size of an extra small, compact button. It is recommended to apply
+ * this size using Modifier.touchTargetAwareSize.
*/
val ExtraSmallButtonSize = IconButtonTokens.ContainerExtraSmallSize
/**
- * The recommended size for a small button.
- * It is recommended to apply this size using Modifier.touchTargetAwareSize.
+ * The recommended size for a small button. It is recommended to apply this size using
+ * Modifier.touchTargetAwareSize.
*/
val SmallButtonSize = IconButtonTokens.ContainerSmallSize
/**
- * The default size applied for buttons.
- * It is recommended to apply this size using Modifier.touchTargetAwareSize.
+ * The default size applied for buttons. It is recommended to apply this size using
+ * Modifier.touchTargetAwareSize.
*/
val DefaultButtonSize = IconButtonTokens.ContainerDefaultSize
/**
- * The recommended size for a large button.
- * It is recommended to apply this size using Modifier.touchTargetAwareSize.
+ * The recommended size for a large button. It is recommended to apply this size using
+ * Modifier.touchTargetAwareSize.
*/
val LargeButtonSize = IconButtonTokens.ContainerLargeSize
private val ColorScheme.defaultFilledIconButtonColors: IconButtonColors
get() {
- return defaultFilledIconButtonColorsCached ?: IconButtonColors(
- containerColor = fromToken(FilledIconButtonTokens.ContainerColor),
- contentColor = fromToken(FilledIconButtonTokens.ContentColor),
- disabledContainerColor = fromToken(FilledIconButtonTokens.DisabledContainerColor)
- .toDisabledColor(
- disabledAlpha = FilledIconButtonTokens.DisabledContainerOpacity
- ),
- disabledContentColor = fromToken(FilledIconButtonTokens.DisabledContentColor)
- .toDisabledColor(disabledAlpha = FilledIconButtonTokens.DisabledContentOpacity)
- ).also { defaultFilledIconButtonColorsCached = it }
+ return defaultFilledIconButtonColorsCached
+ ?: IconButtonColors(
+ containerColor = fromToken(FilledIconButtonTokens.ContainerColor),
+ contentColor = fromToken(FilledIconButtonTokens.ContentColor),
+ disabledContainerColor =
+ fromToken(FilledIconButtonTokens.DisabledContainerColor)
+ .toDisabledColor(
+ disabledAlpha = FilledIconButtonTokens.DisabledContainerOpacity
+ ),
+ disabledContentColor =
+ fromToken(FilledIconButtonTokens.DisabledContentColor)
+ .toDisabledColor(
+ disabledAlpha = FilledIconButtonTokens.DisabledContentOpacity
+ )
+ )
+ .also { defaultFilledIconButtonColorsCached = it }
}
private val ColorScheme.defaultFilledTonalIconButtonColors: IconButtonColors
get() {
- return defaultFilledTonalIconButtonColorsCached ?: IconButtonColors(
- containerColor = fromToken(FilledTonalIconButtonTokens.ContainerColor),
- contentColor = fromToken(FilledTonalIconButtonTokens.ContentColor),
- disabledContainerColor =
- fromToken(FilledTonalIconButtonTokens.DisabledContainerColor)
- .toDisabledColor(
- disabledAlpha = FilledTonalIconButtonTokens.DisabledContainerOpacity
- ),
- disabledContentColor = fromToken(FilledTonalIconButtonTokens.DisabledContentColor)
- .toDisabledColor(
- disabledAlpha = FilledTonalIconButtonTokens.DisabledContentOpacity
+ return defaultFilledTonalIconButtonColorsCached
+ ?: IconButtonColors(
+ containerColor = fromToken(FilledTonalIconButtonTokens.ContainerColor),
+ contentColor = fromToken(FilledTonalIconButtonTokens.ContentColor),
+ disabledContainerColor =
+ fromToken(FilledTonalIconButtonTokens.DisabledContainerColor)
+ .toDisabledColor(
+ disabledAlpha =
+ FilledTonalIconButtonTokens.DisabledContainerOpacity
+ ),
+ disabledContentColor =
+ fromToken(FilledTonalIconButtonTokens.DisabledContentColor)
+ .toDisabledColor(
+ disabledAlpha =
+ FilledTonalIconButtonTokens.DisabledContentOpacity
+ )
)
- ).also { defaultFilledTonalIconButtonColorsCached = it }
+ .also { defaultFilledTonalIconButtonColorsCached = it }
}
private val ColorScheme.defaultOutlinedIconButtonColors: IconButtonColors
get() {
- return defaultOutlinedIconButtonColorsCached ?: IconButtonColors(
- containerColor = Color.Transparent,
- contentColor = fromToken(OutlinedIconButtonTokens.ContentColor),
- disabledContainerColor = Color.Transparent,
- disabledContentColor = fromToken(OutlinedIconButtonTokens.DisabledContentColor)
- .toDisabledColor(
- disabledAlpha = OutlinedIconButtonTokens.DisabledContentOpacity
+ return defaultOutlinedIconButtonColorsCached
+ ?: IconButtonColors(
+ containerColor = Color.Transparent,
+ contentColor = fromToken(OutlinedIconButtonTokens.ContentColor),
+ disabledContainerColor = Color.Transparent,
+ disabledContentColor =
+ fromToken(OutlinedIconButtonTokens.DisabledContentColor)
+ .toDisabledColor(
+ disabledAlpha = OutlinedIconButtonTokens.DisabledContentOpacity
+ )
)
- ).also { defaultOutlinedIconButtonColorsCached = it }
+ .also { defaultOutlinedIconButtonColorsCached = it }
}
private val ColorScheme.defaultIconButtonColors: IconButtonColors
get() {
- return defaultIconButtonColorsCached ?: IconButtonColors(
- containerColor = Color.Transparent,
- contentColor = fromToken(IconButtonTokens.ContentColor),
- disabledContainerColor = Color.Transparent,
- disabledContentColor = fromToken(IconButtonTokens.DisabledContentColor)
- .toDisabledColor(disabledAlpha = IconButtonTokens.DisabledContentOpacity)
- ).also { defaultIconButtonColorsCached = it }
+ return defaultIconButtonColorsCached
+ ?: IconButtonColors(
+ containerColor = Color.Transparent,
+ contentColor = fromToken(IconButtonTokens.ContentColor),
+ disabledContainerColor = Color.Transparent,
+ disabledContentColor =
+ fromToken(IconButtonTokens.DisabledContentColor)
+ .toDisabledColor(
+ disabledAlpha = IconButtonTokens.DisabledContentOpacity
+ )
+ )
+ .also { defaultIconButtonColorsCached = it }
}
private val ColorScheme.defaultIconToggleButtonColors: ToggleButtonColors
get() {
- return defaultIconToggleButtonColorsCached ?: ToggleButtonColors(
- checkedContainerColor = fromToken(IconToggleButtonTokens.CheckedContainerColor),
- checkedContentColor = fromToken(IconToggleButtonTokens.CheckedContentColor),
- uncheckedContainerColor = fromToken(IconToggleButtonTokens.UncheckedContainerColor),
- uncheckedContentColor = fromToken(IconToggleButtonTokens.UncheckedContentColor),
- disabledCheckedContainerColor =
- fromToken(IconToggleButtonTokens.DisabledCheckedContainerColor).toDisabledColor(
- disabledAlpha = IconToggleButtonTokens.DisabledCheckedContainerOpacity
- ),
- disabledCheckedContentColor =
- fromToken(IconToggleButtonTokens.DisabledCheckedContentColor).toDisabledColor(
- disabledAlpha = IconToggleButtonTokens.DisabledCheckedContentOpacity
- ),
- disabledUncheckedContainerColor =
- fromToken(IconToggleButtonTokens.DisabledUncheckedContainerColor)
- .toDisabledColor(
- disabledAlpha = IconToggleButtonTokens.DisabledUncheckedContainerOpacity
- ),
- disabledUncheckedContentColor =
- fromToken(IconToggleButtonTokens.DisabledUncheckedContentColor)
- .toDisabledColor(
- disabledAlpha = IconToggleButtonTokens.DisabledUncheckedContentOpacity
- ),
- ).also { defaultIconToggleButtonColorsCached = it }
+ return defaultIconToggleButtonColorsCached
+ ?: ToggleButtonColors(
+ checkedContainerColor =
+ fromToken(IconToggleButtonTokens.CheckedContainerColor),
+ checkedContentColor = fromToken(IconToggleButtonTokens.CheckedContentColor),
+ uncheckedContainerColor =
+ fromToken(IconToggleButtonTokens.UncheckedContainerColor),
+ uncheckedContentColor =
+ fromToken(IconToggleButtonTokens.UncheckedContentColor),
+ disabledCheckedContainerColor =
+ fromToken(IconToggleButtonTokens.DisabledCheckedContainerColor)
+ .toDisabledColor(
+ disabledAlpha =
+ IconToggleButtonTokens.DisabledCheckedContainerOpacity
+ ),
+ disabledCheckedContentColor =
+ fromToken(IconToggleButtonTokens.DisabledCheckedContentColor)
+ .toDisabledColor(
+ disabledAlpha =
+ IconToggleButtonTokens.DisabledCheckedContentOpacity
+ ),
+ disabledUncheckedContainerColor =
+ fromToken(IconToggleButtonTokens.DisabledUncheckedContainerColor)
+ .toDisabledColor(
+ disabledAlpha =
+ IconToggleButtonTokens.DisabledUncheckedContainerOpacity
+ ),
+ disabledUncheckedContentColor =
+ fromToken(IconToggleButtonTokens.DisabledUncheckedContentColor)
+ .toDisabledColor(
+ disabledAlpha =
+ IconToggleButtonTokens.DisabledUncheckedContentOpacity
+ ),
+ )
+ .also { defaultIconToggleButtonColorsCached = it }
}
}
/**
* Represents the container and content colors used in an icon button in different states.
- *
* - See [IconButtonDefaults.filledIconButtonColors] and
- * [IconButtonDefaults.filledTonalIconButtonColors] for the default colors used in a
- * [FilledIconButton].
+ * [IconButtonDefaults.filledTonalIconButtonColors] for the default colors used in a
+ * [FilledIconButton].
* - See [IconButtonDefaults.outlinedIconButtonColors] for the default colors used in an
- * [OutlinedIconButton].
+ * [OutlinedIconButton].
*
* @param containerColor the background color of this icon button when enabled.
* @param contentColor the color of this icon when enabled.
@@ -675,7 +694,8 @@
* @param disabledContentColor the color of this icon when not enabled.
*/
@Immutable
-class IconButtonColors constructor(
+class IconButtonColors
+constructor(
val containerColor: Color,
val contentColor: Color,
val disabledContainerColor: Color,
@@ -687,12 +707,15 @@
contentColor: Color,
disabledContainerColor: Color,
disabledContentColor: Color
- ) = IconButtonColors(
- containerColor = containerColor.takeOrElse { this.containerColor },
- contentColor = contentColor.takeOrElse { this.contentColor },
- disabledContainerColor = disabledContainerColor.takeOrElse { this.disabledContainerColor },
- disabledContentColor = disabledContentColor.takeOrElse { this.disabledContentColor }
- )
+ ) =
+ IconButtonColors(
+ containerColor = containerColor.takeOrElse { this.containerColor },
+ contentColor = contentColor.takeOrElse { this.contentColor },
+ disabledContainerColor =
+ disabledContainerColor.takeOrElse { this.disabledContainerColor },
+ disabledContentColor = disabledContentColor.takeOrElse { this.disabledContentColor }
+ )
+
/**
* Represents the container color for this icon button, depending on [enabled].
*
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/InteractiveComponentSize.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/InteractiveComponentSize.kt
index cb3ace1..263852c 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/InteractiveComponentSize.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/InteractiveComponentSize.kt
@@ -55,18 +55,18 @@
name = "minimumInteractiveComponentSize"
// TODO: b/214589635 - surface this information through the layout inspector in a better way
// - for now just add some information to help developers debug what this size represents.
- properties["README"] = "Reserves at least 48.dp in size to disambiguate touch " +
- "interactions if the element would measure smaller"
+ properties["README"] =
+ "Reserves at least 48.dp in size to disambiguate touch " +
+ "interactions if the element would measure smaller"
}
override fun hashCode(): Int = System.identityHashCode(this)
+
override fun equals(other: Any?): Boolean = (other === this)
}
internal class MinimumInteractiveModifierNode :
- Modifier.Node(),
- CompositionLocalConsumerModifierNode,
- LayoutModifierNode {
+ Modifier.Node(), CompositionLocalConsumerModifierNode, LayoutModifierNode {
@OptIn(ExperimentalWearMaterial3Api::class)
override fun MeasureScope.measure(
@@ -78,16 +78,18 @@
val placeable = measurable.measure(constraints)
// Be at least as big as the minimum dimension in both dimensions
- val width = if (enforcement) {
- maxOf(placeable.width, size.width.roundToPx())
- } else {
- placeable.width
- }
- val height = if (enforcement) {
- maxOf(placeable.height, size.height.roundToPx())
- } else {
- placeable.height
- }
+ val width =
+ if (enforcement) {
+ maxOf(placeable.width, size.width.roundToPx())
+ } else {
+ placeable.width
+ }
+ val height =
+ if (enforcement) {
+ maxOf(placeable.height, size.height.roundToPx())
+ } else {
+ placeable.height
+ }
return layout(width, height) {
val centerX = ((width - placeable.width) / 2f).roundToInt()
@@ -99,16 +101,18 @@
/**
* CompositionLocal that configures whether Wear Material components that have a visual size that is
- * lower than the minimum touch target size for accessibility (such as Button) will include
- * extra space outside the component to ensure that they are accessible. If set to false there
- * will be no extra space, and so it is possible that if the component is placed near the edge of
- * a layout / near to another component without any padding, there will not be enough space for
- * an accessible touch target.
+ * lower than the minimum touch target size for accessibility (such as Button) will include extra
+ * space outside the component to ensure that they are accessible. If set to false there will be no
+ * extra space, and so it is possible that if the component is placed near the edge of a layout /
+ * near to another component without any padding, there will not be enough space for an accessible
+ * touch target.
*/
@Suppress("OPT_IN_MARKER_ON_WRONG_TARGET")
@get:ExperimentalWearMaterial3Api
@ExperimentalWearMaterial3Api
val LocalMinimumInteractiveComponentEnforcement: ProvidableCompositionLocal<Boolean> =
- staticCompositionLocalOf { true }
+ staticCompositionLocalOf {
+ true
+ }
private val minimumInteractiveComponentSize: DpSize = DpSize(48.dp, 48.dp)
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/ListHeader.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/ListHeader.kt
index 389b520..dbe6bc4 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/ListHeader.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/ListHeader.kt
@@ -43,21 +43,21 @@
import androidx.wear.compose.material3.tokens.ListSubHeaderTokens
/**
- * A slot based composable for creating a list header item. [ListHeader]s are typically expected
- * to be a few words of text on a single line.
- * The contents will be start and end padded.
- *
- * TODO(b/261838497) Add Material3 UX guidance links
+ * A slot based composable for creating a list header item. [ListHeader]s are typically expected to
+ * be a few words of text on a single line. The contents will be start and end padded.
*
* Example of a [ListHeader]:
+ *
* @sample androidx.wear.compose.material3.samples.ListHeaderSample
*
* @param modifier The modifier for the [ListHeader].
* @param backgroundColor The background color to apply - typically Color.Transparent
* @param contentColor The color to apply to content.
- * @param contentPadding The spacing values to apply internally between the container
- * and the content.
+ * @param contentPadding The spacing values to apply internally between the container and the
+ * content.
* @param content Slot for [ListHeader] content, expected to be a single line of text.
+ *
+ * TODO(b/261838497) Add Material3 UX guidance links
*/
@Composable
fun ListHeader(
@@ -69,13 +69,14 @@
) {
Row(
horizontalArrangement = Arrangement.Center,
- modifier = modifier
- .defaultMinSize(minHeight = ListHeaderTokens.Height)
- .height(IntrinsicSize.Min)
- .wrapContentSize()
- .background(backgroundColor)
- .padding(contentPadding)
- .semantics(mergeDescendants = true) { heading() }
+ modifier =
+ modifier
+ .defaultMinSize(minHeight = ListHeaderTokens.Height)
+ .height(IntrinsicSize.Min)
+ .wrapContentSize()
+ .background(backgroundColor)
+ .padding(contentPadding)
+ .semantics(mergeDescendants = true) { heading() }
) {
CompositionLocalProvider(
LocalContentColor provides contentColor,
@@ -87,25 +88,26 @@
}
/**
- * A two slot based composable for creating a list subheader item.
- * [ListSubheader]s offer slots for an icon and for a text label.
- * The contents will be start and end padded.
- *
- * TODO(b/261838497) Add Material3 UX guidance links
+ * A two slot based composable for creating a list subheader item. [ListSubheader]s offer slots for
+ * an icon and for a text label. The contents will be start and end padded.
*
* Example of a [ListSubheader]:
+ *
* @sample androidx.wear.compose.material3.samples.ListSubheaderSample
*
* Example of a [ListSubheader] with an icon:
+ *
* @sample androidx.wear.compose.material3.samples.ListSubheaderWithIconSample
*
* @param modifier The modifier for the [ListSubheader].
* @param backgroundColor The background color to apply - typically Color.Transparent
* @param contentColor The color to apply to content.
- * @param contentPadding The spacing values to apply internally between the container
- * and the content.
+ * @param contentPadding The spacing values to apply internally between the container and the
+ * content.
* @param icon A slot for providing icon to the [ListSubheader].
* @param label A slot for providing label to the [ListSubheader].
+ *
+ * TODO(b/261838497) Add Material3 UX guidance links
*/
@Composable
fun ListSubheader(
@@ -119,14 +121,15 @@
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Start,
- modifier = modifier
- .defaultMinSize(minHeight = ListSubHeaderTokens.Height)
- .height(IntrinsicSize.Min)
- .fillMaxWidth()
- .wrapContentSize(align = Alignment.CenterStart)
- .background(backgroundColor)
- .padding(contentPadding)
- .semantics(mergeDescendants = true) { heading() }
+ modifier =
+ modifier
+ .defaultMinSize(minHeight = ListSubHeaderTokens.Height)
+ .height(IntrinsicSize.Min)
+ .fillMaxWidth()
+ .wrapContentSize(align = Alignment.CenterStart)
+ .background(backgroundColor)
+ .padding(contentPadding)
+ .semantics(mergeDescendants = true) { heading() }
) {
CompositionLocalProvider(
LocalContentColor provides contentColor,
@@ -150,16 +153,8 @@
private val HeaderBottomPadding = 12.dp
private val HorizontalPadding = 14.dp
- val HeaderContentPadding = PaddingValues(
- HorizontalPadding,
- TopPadding,
- HorizontalPadding,
- HeaderBottomPadding
- )
- val SubheaderContentPadding = PaddingValues(
- HorizontalPadding,
- TopPadding,
- HorizontalPadding,
- SubheaderBottomPadding
- )
+ val HeaderContentPadding =
+ PaddingValues(HorizontalPadding, TopPadding, HorizontalPadding, HeaderBottomPadding)
+ val SubheaderContentPadding =
+ PaddingValues(HorizontalPadding, TopPadding, HorizontalPadding, SubheaderBottomPadding)
}
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/MaterialTheme.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/MaterialTheme.kt
index 9ef0bde..954b6ea 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/MaterialTheme.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/MaterialTheme.kt
@@ -26,31 +26,30 @@
import androidx.wear.compose.foundation.LocalSwipeToDismissContentScrimColor
/**
- * MaterialTheme defines the styling principles from the Wear Material3 design specification
- * which extends the Material design specification.
+ * MaterialTheme defines the styling principles from the Wear Material3 design specification which
+ * extends the Material design specification.
*
- * Wear Material components from package/sub-packages in [androidx.wear.compose.material3]
- * use values provided here when retrieving default values.
- *
- * TODO(b/273543423) Update references to Material3 design specs
+ * Wear Material components from package/sub-packages in [androidx.wear.compose.material3] use
+ * values provided here when retrieving default values.
*
* All values may be set by providing this component with the [colors][ColorScheme],
- * [typography][Typography], and [shapes][Shapes] attributes. Use this to configure the
- * overall theme of elements within this MaterialTheme.
+ * [typography][Typography], and [shapes][Shapes] attributes. Use this to configure the overall
+ * theme of elements within this MaterialTheme.
*
* Any values that are not set will inherit the current value from the theme, falling back to the
- * defaults if there is no parent MaterialTheme. This allows using a MaterialTheme at the
- * top of your application, and then separate MaterialTheme(s) for different screens / parts of
- * your UI, overriding only the parts of the theme definition that need to change.
+ * defaults if there is no parent MaterialTheme. This allows using a MaterialTheme at the top of
+ * your application, and then separate MaterialTheme(s) for different screens / parts of your UI,
+ * overriding only the parts of the theme definition that need to change.
*
* For more information, see the
- * [Theming](https://developer.android.com/training/wearables/components/theme)
- * guide.
+ * [Theming](https://developer.android.com/training/wearables/components/theme) guide.
*
* @param colorScheme A complete definition of the Wear Material Color theme for this hierarchy
* @param typography A set of text styles to be used as this hierarchy's typography system
* @param shapes A set of shapes to be used by the components in this hierarchy
* @param content Slot for composable content displayed with this theme
+ *
+ * TODO(b/273543423) Update references to Material3 design specs
*/
@Composable
fun MaterialTheme(
@@ -72,26 +71,20 @@
LocalTextSelectionColors provides selectionColors,
LocalSwipeToDismissBackgroundScrimColor provides colorScheme.background,
LocalSwipeToDismissContentScrimColor provides colorScheme.background
- ) {
+ ) {
ProvideTextStyle(value = typography.bodyLarge, content = content)
}
}
object MaterialTheme {
val colorScheme: ColorScheme
- @ReadOnlyComposable
- @Composable
- get() = LocalColorScheme.current
+ @ReadOnlyComposable @Composable get() = LocalColorScheme.current
val typography: Typography
- @ReadOnlyComposable
- @Composable
- get() = LocalTypography.current
+ @ReadOnlyComposable @Composable get() = LocalTypography.current
val shapes: Shapes
- @ReadOnlyComposable
- @Composable
- get() = LocalShapes.current
+ @ReadOnlyComposable @Composable get() = LocalShapes.current
}
@Composable
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/ProgressIndicator.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/ProgressIndicator.kt
index 5942a54..2b9c252 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/ProgressIndicator.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/ProgressIndicator.kt
@@ -50,12 +50,15 @@
*
* Example of a full screen [CircularProgressIndicator]. Note that the padding
* [ProgressIndicatorDefaults.FullScreenPadding] should be applied:
+ *
* @sample androidx.wear.compose.material3.samples.FullScreenProgressIndicatorSample
*
* Example of progress showing overflow value (more than 1) by [CircularProgressIndicator]:
+ *
* @sample androidx.wear.compose.material3.samples.OverflowProgressIndicatorSample
*
* Example of progress indicator wrapping media control by [CircularProgressIndicator]:
+ *
* @sample androidx.wear.compose.material3.samples.MediaButtonProgressIndicatorSample
*
* Progress indicators express the proportion of completion of an ongoing task.
@@ -65,8 +68,8 @@
* @param modifier Modifier to be applied to the CircularProgressIndicator.
* @param startAngle The starting position of the progress arc, measured clockwise in degrees (0
* to 360) from the 3 o'clock position. For example, 0 and 360 represent 3 o'clock, 90 and 180
- * represent 6 o'clock and 9 o'clock respectively.
- * Default is 270 degrees [ProgressIndicatorDefaults.StartAngle] (top of the screen).
+ * represent 6 o'clock and 9 o'clock respectively. Default is 270 degrees
+ * [ProgressIndicatorDefaults.StartAngle] (top of the screen).
* @param endAngle The ending position of the progress arc, measured clockwise in degrees (0 to 360)
* from the 3 o'clock position. For example, 0 and 360 represent 3 o'clock, 90 and 180 represent 6
* o'clock and 9 o'clock respectively. By default equal to [startAngle].
@@ -102,8 +105,8 @@
val minSize = min(size.height, size.width)
// Sweep angle between two progress indicator segments.
val gapSweep =
- asin((stroke.width + gapSize.toPx()) / (minSize - stroke.width))
- .toDegrees() * 2f
+ asin((stroke.width + gapSize.toPx()) / (minSize - stroke.width)).toDegrees() *
+ 2f
onDrawWithContent {
// Draw an indicator.
@@ -164,11 +167,10 @@
val FullScreenPadding = 2.dp
/**
- * Creates a [ProgressIndicatorColors] that represents the default arc colors used in
- * a [CircularProgressIndicator].
+ * Creates a [ProgressIndicatorColors] that represents the default arc colors used in a
+ * [CircularProgressIndicator].
*/
- @Composable
- fun colors() = MaterialTheme.colorScheme.defaultProgressIndicatorColors
+ @Composable fun colors() = MaterialTheme.colorScheme.defaultProgressIndicatorColors
/**
* Creates a [ProgressIndicatorColors] with modified colors used in a
@@ -200,12 +202,12 @@
private val ColorScheme.defaultProgressIndicatorColors: ProgressIndicatorColors
get() {
- return defaultProgressIndicatorColorsCached ?: ProgressIndicatorColors(
- indicatorBrush = SolidColor(fromToken(ColorSchemeKeyTokens.Primary)),
- trackBrush = SolidColor(fromToken(ColorSchemeKeyTokens.SurfaceContainer)),
- ).also {
- defaultProgressIndicatorColorsCached = it
- }
+ return defaultProgressIndicatorColorsCached
+ ?: ProgressIndicatorColors(
+ indicatorBrush = SolidColor(fromToken(ColorSchemeKeyTokens.Primary)),
+ trackBrush = SolidColor(fromToken(ColorSchemeKeyTokens.SurfaceContainer)),
+ )
+ .also { defaultProgressIndicatorColorsCached = it }
}
}
@@ -219,19 +221,21 @@
internal fun copy(
indicatorColor: Color = Color.Unspecified,
trackColor: Color = Color.Unspecified,
- ) = ProgressIndicatorColors(
- indicatorBrush =
- if (indicatorColor.isSpecified) SolidColor(indicatorColor) else indicatorBrush,
- trackBrush = if (trackColor.isSpecified) SolidColor(trackColor) else trackBrush
- )
+ ) =
+ ProgressIndicatorColors(
+ indicatorBrush =
+ if (indicatorColor.isSpecified) SolidColor(indicatorColor) else indicatorBrush,
+ trackBrush = if (trackColor.isSpecified) SolidColor(trackColor) else trackBrush
+ )
internal fun copy(
indicatorBrush: Brush? = null,
trackBrush: Brush? = null,
- ) = ProgressIndicatorColors(
- indicatorBrush = indicatorBrush ?: this.indicatorBrush,
- trackBrush = trackBrush ?: this.trackBrush
- )
+ ) =
+ ProgressIndicatorColors(
+ indicatorBrush = indicatorBrush ?: this.indicatorBrush,
+ trackBrush = trackBrush ?: this.trackBrush
+ )
override fun equals(other: Any?): Boolean {
if (this === other) return true
@@ -278,10 +282,10 @@
brushWithAlpha,
circleRadius,
center =
- Offset(
- radius * cos(angle) + size.minDimension / 2,
- radius * sin(angle) + size.minDimension / 2
- )
+ Offset(
+ radius * cos(angle) + size.minDimension / 2,
+ radius * sin(angle) + size.minDimension / 2
+ )
)
} else {
// To draw this circle we need a rect with edges that line up with the midpoint of the
@@ -297,10 +301,10 @@
sweepAngle = sweep - gapSweep,
useCenter = false,
topLeft =
- Offset(
- diameterOffset + (size.width - diameter) / 2,
- diameterOffset + (size.height - diameter) / 2
- ),
+ Offset(
+ diameterOffset + (size.width - diameter) / 2,
+ diameterOffset + (size.height - diameter) / 2
+ ),
size = Size(arcDimen, arcDimen),
style = stroke
)
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Providers.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Providers.kt
index 82d990d..7b0346b 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Providers.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Providers.kt
@@ -75,28 +75,30 @@
contentColor: State<Color>,
textStyle: TextStyle,
content: (@Composable T.() -> Unit)?
-): (@Composable T.() -> Unit)? = content?.let {
- {
- val color = contentColor.value
- CompositionLocalProvider(
- LocalContentColor provides color,
- LocalTextStyle provides textStyle
- ) {
- content()
+): (@Composable T.() -> Unit)? =
+ content?.let {
+ {
+ val color = contentColor.value
+ CompositionLocalProvider(
+ LocalContentColor provides color,
+ LocalTextStyle provides textStyle
+ ) {
+ content()
+ }
}
}
-}
internal fun <T> provideNullableScopeContent(
contentColor: State<Color>,
content: (@Composable T.() -> Unit)?
-): (@Composable T.() -> Unit)? = content?.let {
- {
- val color = contentColor.value
- CompositionLocalProvider(
- LocalContentColor provides color,
- ) {
- content()
+): (@Composable T.() -> Unit)? =
+ content?.let {
+ {
+ val color = contentColor.value
+ CompositionLocalProvider(
+ LocalContentColor provides color,
+ ) {
+ content()
+ }
}
}
-}
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/RangeSemantics.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/RangeSemantics.kt
index c6e3aa8..e5109ff 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/RangeSemantics.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/RangeSemantics.kt
@@ -27,14 +27,14 @@
* Modifier to add semantics signifying progress of the Stepper/Slider.
*
* @param value Current value of the ProgressIndicator/Slider. If outside of [valueRange] provided,
- * value will be coerced to this range. Must not be NaN.
+ * value will be coerced to this range. Must not be NaN.
* @param enabled If false then semantics will not be added.
* @param onValueChange Lambda which updates [value].
* @param valueRange Range of values that value can take. Passed [value] will be coerced to this
- * range.
+ * range.
* @param steps If greater than 0, specifies the amounts of discrete values, evenly distributed
- * between across the whole value range. If 0, any value from the range specified is allowed.
- * Must not be negative.
+ * between across the whole value range. If 0, any value from the range specified is allowed. Must
+ * not be negative.
*/
public fun Modifier.rangeSemantics(
value: Float,
@@ -45,21 +45,24 @@
): Modifier {
val step = RangeDefaults.snapValueToStep(value, valueRange, steps)
return semantics(mergeDescendants = true) {
- if (!enabled) disabled()
- setProgress(
- action = { targetValue ->
- val newStepIndex = RangeDefaults.snapValueToStep(targetValue, valueRange, steps)
- if (step == newStepIndex) {
- false
- } else {
- onValueChange(targetValue)
- true
+ if (!enabled) disabled()
+ setProgress(
+ action = { targetValue ->
+ val newStepIndex = RangeDefaults.snapValueToStep(targetValue, valueRange, steps)
+ if (step == newStepIndex) {
+ false
+ } else {
+ onValueChange(targetValue)
+ true
+ }
}
- }
+ )
+ }
+ .progressSemantics(
+ RangeDefaults.calculateCurrentStepValue(step, steps, valueRange),
+ valueRange,
+ steps
)
- }.progressSemantics(
- RangeDefaults.calculateCurrentStepValue(step, steps, valueRange), valueRange, steps
- )
}
internal fun IntProgression.stepsNumber(): Int = (last - first) / step - 1
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Ripple.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Ripple.kt
index f88b805..940aa2b 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Ripple.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Ripple.kt
@@ -40,17 +40,17 @@
/**
* Creates a Ripple using the provided values and values inferred from the theme.
*
- * A Ripple is a Material implementation of [Indication] that expresses different [Interaction]s
- * by drawing ripple animations and state layers.
+ * A Ripple is a Material implementation of [Indication] that expresses different [Interaction]s by
+ * drawing ripple animations and state layers.
*
- * A Ripple responds to [PressInteraction.Press] by starting a new ripple animation, and
- * responds to other [Interaction]s by showing a fixed state layer with varying alpha values
- * depending on the [Interaction].
+ * A Ripple responds to [PressInteraction.Press] by starting a new ripple animation, and responds to
+ * other [Interaction]s by showing a fixed state layer with varying alpha values depending on the
+ * [Interaction].
*
* [MaterialTheme] provides Ripples using [androidx.compose.foundation.LocalIndication], so a Ripple
* will be used as the default [Indication] inside components such as
- * [androidx.compose.foundation.clickable] and [androidx.compose.foundation.indication], in
- * addition to Material provided components that use a Ripple as well.
+ * [androidx.compose.foundation.clickable] and [androidx.compose.foundation.indication], in addition
+ * to Material provided components that use a Ripple as well.
*
* You can also explicitly create a Ripple and provide it to custom components in order to change
* the parameters from the default, such as to create an unbounded ripple with a fixed size.
@@ -59,15 +59,14 @@
* [ripple] overload with a [ColorProducer] parameter. This will avoid unnecessary recompositions
* when changing the color, and preserve existing ripple state when the color changes.
*
- * @param bounded If true, ripples are clipped by the bounds of the target layout. Unbounded
- * ripples always animate from the target layout center, bounded ripples animate from the touch
- * position.
+ * @param bounded If true, ripples are clipped by the bounds of the target layout. Unbounded ripples
+ * always animate from the target layout center, bounded ripples animate from the touch position.
* @param radius the radius for the ripple. If [Dp.Unspecified] is provided then the size will be
- * calculated based on the target layout size.
+ * calculated based on the target layout size.
* @param color the color of the ripple. This color is usually the same color used by the text or
- * iconography in the component. This color will then have alpha applied to calculate the final
- * color used to draw the ripple. If [Color.Unspecified] is provided the color used will be
- * [LocalContentColor] instead.
+ * iconography in the component. This color will then have alpha applied to calculate the final
+ * color used to draw the ripple. If [Color.Unspecified] is provided the color used will be
+ * [LocalContentColor] instead.
*/
@Stable
fun ripple(
@@ -85,17 +84,17 @@
/**
* Creates a Ripple using the provided values and values inferred from the theme.
*
- * A Ripple is a Material implementation of [Indication] that expresses different [Interaction]s
- * by drawing ripple animations and state layers.
+ * A Ripple is a Material implementation of [Indication] that expresses different [Interaction]s by
+ * drawing ripple animations and state layers.
*
- * A Ripple responds to [PressInteraction.Press] by starting a new ripple animation, and
- * responds to other [Interaction]s by showing a fixed state layer with varying alpha values
- * depending on the [Interaction].
+ * A Ripple responds to [PressInteraction.Press] by starting a new ripple animation, and responds to
+ * other [Interaction]s by showing a fixed state layer with varying alpha values depending on the
+ * [Interaction].
*
* [MaterialTheme] provides Ripples using [androidx.compose.foundation.LocalIndication], so a Ripple
* will be used as the default [Indication] inside components such as
- * [androidx.compose.foundation.clickable] and [androidx.compose.foundation.indication], in
- * addition to Material provided components that use a Ripple as well.
+ * [androidx.compose.foundation.clickable] and [androidx.compose.foundation.indication], in addition
+ * to Material provided components that use a Ripple as well.
*
* You can also explicitly create a Ripple and provide it to custom components in order to change
* the parameters from the default, such as to create an unbounded ripple with a fixed size.
@@ -105,16 +104,15 @@
* unnecessary recompositions.
*
* @param color the color of the ripple. This color is usually the same color used by the text or
- * iconography in the component. This color will then have alpha applied to calculate the final
- * color used to draw the ripple. If you are creating this [ColorProducer] outside of composition
- * (where it will be automatically remembered), make sure that its instance is stable
- * (such as by remembering the object that holds it), or remember the returned [ripple] object to
- * make sure that ripple nodes are not being created each recomposition.
- * @param bounded If true, ripples are clipped by the bounds of the target layout. Unbounded
- * ripples always animate from the target layout center, bounded ripples animate from the touch
- * position.
+ * iconography in the component. This color will then have alpha applied to calculate the final
+ * color used to draw the ripple. If you are creating this [ColorProducer] outside of composition
+ * (where it will be automatically remembered), make sure that its instance is stable (such as by
+ * remembering the object that holds it), or remember the returned [ripple] object to make sure
+ * that ripple nodes are not being created each recomposition.
+ * @param bounded If true, ripples are clipped by the bounds of the target layout. Unbounded ripples
+ * always animate from the target layout center, bounded ripples animate from the touch position.
* @param radius the radius for the ripple. If [Dp.Unspecified] is provided then the size will be
- * calculated based on the target layout size.
+ * calculated based on the target layout size.
*/
@Stable
fun ripple(
@@ -128,8 +126,8 @@
/**
* Temporary CompositionLocal to allow configuring whether the old ripple implementation that uses
* the deprecated [androidx.compose.material.ripple.RippleTheme] API should be used in Material
- * components and LocalIndication, instead of the new [ripple] API. This flag defaults to false,
- * and will be removed after one stable release: it should only be used to temporarily unblock
+ * components and LocalIndication, instead of the new [ripple] API. This flag defaults to false, and
+ * will be removed after one stable release: it should only be used to temporarily unblock
* upgrading.
*
* Provide this CompositionLocal before you provide [MaterialTheme] to make sure it is correctly
@@ -140,7 +138,9 @@
@get:ExperimentalWearMaterial3Api
@ExperimentalWearMaterial3Api
val LocalUseFallbackRippleImplementation: ProvidableCompositionLocal<Boolean> =
- staticCompositionLocalOf { false }
+ staticCompositionLocalOf {
+ false
+ }
// TODO: b/304985887 - remove after one stable release
@Suppress("DEPRECATION_ERROR")
@@ -166,13 +166,12 @@
@Composable
override fun defaultColor() = LocalContentColor.current
- @Deprecated("Super method is deprecated")
- @Composable
- override fun rippleAlpha() = RippleAlpha
+ @Deprecated("Super method is deprecated") @Composable override fun rippleAlpha() = RippleAlpha
}
@Stable
-private class RippleNodeFactory private constructor(
+private class RippleNodeFactory
+private constructor(
private val bounded: Boolean,
private val radius: Dp,
private val colorProducer: ColorProducer?,
@@ -184,11 +183,7 @@
colorProducer: ColorProducer
) : this(bounded, radius, colorProducer, Color.Unspecified)
- constructor(
- bounded: Boolean,
- radius: Dp,
- color: Color
- ) : this(bounded, radius, null, color)
+ constructor(bounded: Boolean, radius: Dp, color: Color) : this(bounded, radius, null, color)
override fun create(interactionSource: InteractionSource): DelegatableNode {
val colorProducer = colorProducer ?: ColorProducer { color }
@@ -241,22 +236,17 @@
}
}
-private val RippleAlpha: RippleAlpha = RippleAlpha(
- pressedAlpha = 0.10f,
- focusedAlpha = 0.10f,
- draggedAlpha = 0.16f,
- hoveredAlpha = 0.08f
-)
+private val RippleAlpha: RippleAlpha =
+ RippleAlpha(
+ pressedAlpha = 0.10f,
+ focusedAlpha = 0.10f,
+ draggedAlpha = 0.16f,
+ hoveredAlpha = 0.08f
+ )
private val CalculateRippleAlpha = { RippleAlpha }
-private val DefaultBoundedRipple = RippleNodeFactory(
- bounded = true,
- radius = Dp.Unspecified,
- color = Color.Unspecified
-)
-private val DefaultUnboundedRipple = RippleNodeFactory(
- bounded = false,
- radius = Dp.Unspecified,
- color = Color.Unspecified
-)
+private val DefaultBoundedRipple =
+ RippleNodeFactory(bounded = true, radius = Dp.Unspecified, color = Color.Unspecified)
+private val DefaultUnboundedRipple =
+ RippleNodeFactory(bounded = false, radius = Dp.Unspecified, color = Color.Unspecified)
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/SelectableButton.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/SelectableButton.kt
index abe09d8..c66b2f5 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/SelectableButton.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/SelectableButton.kt
@@ -65,52 +65,52 @@
/**
* The Wear Material [SelectableButton] offers four slots and a specific layout for an icon, a
- * label, a secondaryLabel and selection control (such as [RadioButton]).
- * The icon and secondaryLabel are optional.
- * The items are laid out in a row with the optional icon at the start, a column containing the two
- * label slots in the middle and a slot for the selection control at the end.
+ * label, a secondaryLabel and selection control (such as [RadioButton]). The icon and
+ * secondaryLabel are optional. The items are laid out in a row with the optional icon at the start,
+ * a column containing the two label slots in the middle and a slot for the selection control at the
+ * end.
*
- * The [SelectableButton] is Stadium shaped and has a max height designed to take no more than
- * two lines of text.
- * With localisation and/or large font sizes, the [SelectableButton] height adjusts to
- * accommodate the contents. The label and secondary label should be start aligned.
+ * The [SelectableButton] is Stadium shaped and has a max height designed to take no more than two
+ * lines of text. With localisation and/or large font sizes, the [SelectableButton] height adjusts
+ * to accommodate the contents. The label and secondary label should be start aligned.
*
- * Note that Modifier.selectableGroup() must be present on the parent control (such as
- * Column) to ensure correct accessibility behavior.
+ * Note that Modifier.selectableGroup() must be present on the parent control (such as Column) to
+ * ensure correct accessibility behavior.
*
- * Samples:
- * Example of a SelectableButton with a [RadioButton] control:
+ * Samples: Example of a SelectableButton with a [RadioButton] control:
+ *
* @sample androidx.wear.compose.material3.samples.SelectableButtonSample
*
- * [SelectableButton] can be enabled or disabled. A disabled button will not respond to click events.
+ * [SelectableButton] can be enabled or disabled. A disabled button will not respond to click
+ * events.
*
- * The recommended set of [SelectableButton] colors can be obtained from
- * [SelectableButtonDefaults], e.g. [SelectableButtonDefaults.selectableButtonColors].
+ * The recommended set of [SelectableButton] colors can be obtained from [SelectableButtonDefaults],
+ * e.g. [SelectableButtonDefaults.selectableButtonColors].
*
* @param selected Boolean flag indicating whether this button is currently selected.
* @param onSelect Callback to be invoked when this button has been selected by clicking.
- * @param selectionControl A slot for the button's selection control.
- * The [RadioButton] selection control is provided for this purpose.
+ * @param selectionControl A slot for the button's selection control. The [RadioButton] selection
+ * control is provided for this purpose.
* @param modifier Modifier to be applied to the [SelectableButton].
- * @param enabled Controls the enabled state of the button. When `false`, this button will not
- * be clickable.
+ * @param enabled Controls the enabled state of the button. When `false`, this button will not be
+ * clickable.
* @param shape Defines the button's shape. It is strongly recommended to use the default as this
- * shape is a key characteristic of the Wear Material Theme.
- * @param colors [SelectableButtonColors] that will be used to resolve the background and
- * content color for this button in different states.
+ * shape is a key characteristic of the Wear Material Theme.
+ * @param colors [SelectableButtonColors] that will be used to resolve the background and content
+ * color for this button in different states.
* @param contentPadding The spacing values to apply internally between the container and the
- * content.
+ * content.
* @param interactionSource an optional hoisted [MutableInteractionSource] for observing and
- * emitting [Interaction]s for this radio button. You can use this to change the radio button's
- * appearance or preview the radio button in different states. Note that if `null` is provided,
- * interactions will still happen internally.
- * @param icon An optional slot for providing an icon to indicate the purpose of the button.
- * The contents are expected to be center-aligned, both horizontally and vertically, and should be
- * an icon of size 24.dp.
+ * emitting [Interaction]s for this radio button. You can use this to change the radio button's
+ * appearance or preview the radio button in different states. Note that if `null` is provided,
+ * interactions will still happen internally.
+ * @param icon An optional slot for providing an icon to indicate the purpose of the button. The
+ * contents are expected to be center-aligned, both horizontally and vertically, and should be an
+ * icon of size 24.dp.
* @param secondaryLabel A slot for providing the button's secondary label. The contents are
- * expected to be text which is "start" aligned.
+ * expected to be text which is "start" aligned.
* @param label A slot for providing the button's main label. The contents are expected to be text
- * which is "start" aligned.
+ * which is "start" aligned.
*/
@Composable
fun SelectableButton(
@@ -118,9 +118,7 @@
onSelect: () -> Unit,
modifier: Modifier = Modifier,
enabled: Boolean = true,
- selectionControl: @Composable SelectionControlScope.() -> Unit = {
- RadioButton()
- },
+ selectionControl: @Composable SelectionControlScope.() -> Unit = { RadioButton() },
shape: Shape = SelectableButtonDefaults.selectableButtonShape,
colors: SelectableButtonColors = SelectableButtonDefaults.selectableButtonColors(),
contentPadding: PaddingValues = SelectableButtonDefaults.ContentPadding,
@@ -131,60 +129,61 @@
) {
// Stadium/Pill shaped toggle button
Row(
- modifier = modifier
- .defaultMinSize(minHeight = MIN_HEIGHT)
- .height(IntrinsicSize.Min)
- .width(IntrinsicSize.Max)
- .clip(shape = shape)
- .background(colors.containerColor(enabled = enabled, selected = selected).value)
- .selectable(
- enabled = enabled,
- selected = selected,
- onClick = onSelect,
- indication = rippleOrFallbackImplementation(),
- interactionSource = interactionSource
- )
- .padding(contentPadding)
- .semantics {
- // For a selectable button, the role is always RadioButton.
- // See also b/330869742 for issue with setting the SelectableButton role
- // within the selection control.
- role = Role.RadioButton
- },
+ modifier =
+ modifier
+ .defaultMinSize(minHeight = MIN_HEIGHT)
+ .height(IntrinsicSize.Min)
+ .width(IntrinsicSize.Max)
+ .clip(shape = shape)
+ .background(colors.containerColor(enabled = enabled, selected = selected).value)
+ .selectable(
+ enabled = enabled,
+ selected = selected,
+ onClick = onSelect,
+ indication = rippleOrFallbackImplementation(),
+ interactionSource = interactionSource
+ )
+ .padding(contentPadding)
+ .semantics {
+ // For a selectable button, the role is always RadioButton.
+ // See also b/330869742 for issue with setting the SelectableButton role
+ // within the selection control.
+ role = Role.RadioButton
+ },
verticalAlignment = Alignment.CenterVertically
) {
if (icon != null) {
Box(
modifier = Modifier.wrapContentSize(align = Alignment.Center),
- content = provideScopeContent(
- color = colors.iconColor(enabled = enabled, selected = selected),
- content = icon
- )
+ content =
+ provideScopeContent(
+ color = colors.iconColor(enabled = enabled, selected = selected),
+ content = icon
+ )
)
Spacer(modifier = Modifier.size(ICON_SPACING))
}
Labels(
- label = provideScopeContent(
- contentColor = colors.contentColor(enabled = enabled, selected = selected),
- textStyle = SelectableButtonTokens.LabelFont.value,
- content = label
- ),
- secondaryLabel = provideNullableScopeContent(
- contentColor = colors.secondaryContentColor(enabled = enabled, selected = selected),
- textStyle = SelectableButtonTokens.SecondaryLabelFont.value,
- content = secondaryLabel
- )
+ label =
+ provideScopeContent(
+ contentColor = colors.contentColor(enabled = enabled, selected = selected),
+ textStyle = SelectableButtonTokens.LabelFont.value,
+ content = label
+ ),
+ secondaryLabel =
+ provideNullableScopeContent(
+ contentColor =
+ colors.secondaryContentColor(enabled = enabled, selected = selected),
+ textStyle = SelectableButtonTokens.SecondaryLabelFont.value,
+ content = secondaryLabel
+ )
)
- Spacer(
- modifier = Modifier.size(
- SELECTION_CONTROL_SPACING
- )
- )
+ Spacer(modifier = Modifier.size(SELECTION_CONTROL_SPACING))
Box(
- modifier = Modifier
- .align(Alignment.CenterVertically)
- .size(width = SELECTION_CONTROL_WIDTH, height = SELECTION_CONTROL_HEIGHT)
- .wrapContentWidth(align = Alignment.End),
+ modifier =
+ Modifier.align(Alignment.CenterVertically)
+ .size(width = SELECTION_CONTROL_WIDTH, height = SELECTION_CONTROL_HEIGHT)
+ .wrapContentWidth(align = Alignment.End),
) {
val scope = remember(enabled, selected) { SelectionControlScope(enabled, selected) }
selectionControl(scope)
@@ -194,60 +193,59 @@
/**
* The Wear Material [SplitSelectableButton] offers three slots and a specific layout for a label,
- * secondaryLabel and selection control. The secondaryLabel is optional. The items are laid out
- * with a column containing the two label slots and a slot for the selection control at the
- * end.
+ * secondaryLabel and selection control. The secondaryLabel is optional. The items are laid out with
+ * a column containing the two label slots and a slot for the selection control at the end.
*
* The [SplitSelectableButton] is Stadium shaped and has a max height designed to take no more than
- * two lines of text.
- * With localisation and/or large font sizes, the [SplitSelectableButton] height adjusts to
- * accommodate the contents. The label and secondary label should be consistently aligned.
+ * two lines of text. With localisation and/or large font sizes, the [SplitSelectableButton] height
+ * adjusts to accommodate the contents. The label and secondary label should be consistently
+ * aligned.
*
* A [SplitSelectableButton] has two tappable areas, one tap area for the labels and another for the
* selection control. The [onContainerClick] listener will be associated with the main body of the
* split radio button with the [onSelectionClick] listener associated with the selection control
* area only.
*
- * Samples:
- * Example of a SplitSelectableButton with a [RadioButton] control:
+ * Samples: Example of a SplitSelectableButton with a [RadioButton] control:
+ *
* @sample androidx.wear.compose.material3.samples.SplitSelectableButtonSample
*
* For a SplitSelectableButton the background of the tappable background area behind the selection
* control will have a visual effect applied to provide a "divider" between the two tappable areas.
*
- * The recommended set of colors can be obtained from
- * [SelectableButtonDefaults], e.g. [SelectableButtonDefaults.splitSelectableButtonColors].
+ * The recommended set of colors can be obtained from [SelectableButtonDefaults], e.g.
+ * [SelectableButtonDefaults.splitSelectableButtonColors].
*
- * [SplitSelectableButton] can be enabled or disabled. A disabled button will not respond to
- * click events.
+ * [SplitSelectableButton] can be enabled or disabled. A disabled button will not respond to click
+ * events.
*
* @param selected Boolean flag indicating whether this button is currently selected.
* @param onSelectionClick Callback to be invoked when this button has been selected.
* @param onContainerClick Click listener called when the user clicks the main body of the button,
- * the area containing the labels.
- * @param selectionControl A slot for providing the button's selection control.
- * The [RadioButton] selection control is provided for this purpose.
+ * the area containing the labels.
+ * @param selectionControl A slot for providing the button's selection control. The [RadioButton]
+ * selection control is provided for this purpose.
* @param modifier Modifier to be applied to the button.
- * @param enabled Controls the enabled state of the button. When `false`, this button will not
- * be clickable.
+ * @param enabled Controls the enabled state of the button. When `false`, this button will not be
+ * clickable.
* @param shape Defines the button's shape. It is strongly recommended to use the default as this
- * shape is a key characteristic of the Wear Material Theme.
+ * shape is a key characteristic of the Wear Material Theme.
* @param colors [SplitSelectableButtonColors] that will be used to resolve the background and
- * content color for this button in different states.
+ * content color for this button in different states.
* @param contentPadding The spacing values to apply internally between the container and the
- * content.
+ * content.
* @param selectionInteractionSource an optional hoisted [MutableInteractionSource] for observing
- * and emitting [Interaction]s for this button's "selectable" tap area. You can use this to change
- * the button's appearance or preview the button in different states. Note that if `null` is
- * provided, interactions will still happen internally.
- * @param containerInteractionSource an optional hoisted [MutableInteractionSource] for observing and
- * emitting [Interaction]s for this button's "clickable" tap area. You can use this to change the
- * button's appearance or preview the button in different states. Note that if `null` is provided,
- * interactions will still happen internally.
+ * and emitting [Interaction]s for this button's "selectable" tap area. You can use this to change
+ * the button's appearance or preview the button in different states. Note that if `null` is
+ * provided, interactions will still happen internally.
+ * @param containerInteractionSource an optional hoisted [MutableInteractionSource] for observing
+ * and emitting [Interaction]s for this button's "clickable" tap area. You can use this to change
+ * the button's appearance or preview the button in different states. Note that if `null` is
+ * provided, interactions will still happen internally.
* @param secondaryLabel A slot for providing the button's secondary label. The contents are
- * expected to be "start" aligned.
+ * expected to be "start" aligned.
* @param label A slot for providing the button's main label. The contents are expected to be text
- * which is "start" aligned.
+ * which is "start" aligned.
*/
@Composable
fun SplitSelectableButton(
@@ -256,9 +254,7 @@
onContainerClick: () -> Unit,
modifier: Modifier = Modifier,
enabled: Boolean = true,
- selectionControl: @Composable SelectionControlScope.() -> Unit = {
- RadioButton()
- },
+ selectionControl: @Composable SelectionControlScope.() -> Unit = { RadioButton() },
shape: Shape = SelectableButtonDefaults.splitSelectableButtonShape,
colors: SplitSelectableButtonColors = SelectableButtonDefaults.splitSelectableButtonColors(),
selectionInteractionSource: MutableInteractionSource? = null,
@@ -271,77 +267,75 @@
Row(
verticalAlignment = Alignment.CenterVertically,
- modifier = modifier
- .defaultMinSize(minHeight = MIN_HEIGHT)
- .height(IntrinsicSize.Min)
- .width(IntrinsicSize.Max)
- .clip(shape = shape)
- .background(colors.containerColor(enabled, selected).value)
+ modifier =
+ modifier
+ .defaultMinSize(minHeight = MIN_HEIGHT)
+ .height(IntrinsicSize.Min)
+ .width(IntrinsicSize.Max)
+ .clip(shape = shape)
+ .background(colors.containerColor(enabled, selected).value)
) {
Row(
- modifier = Modifier
- .clickable(
- enabled = enabled,
- onClick = onContainerClick,
- indication = rippleOrFallbackImplementation(),
- interactionSource = containerInteractionSource,
- )
- .semantics {
- role = Role.Button
- }
- .fillMaxHeight()
- .then(startPadding)
- .weight(1.0f),
+ modifier =
+ Modifier.clickable(
+ enabled = enabled,
+ onClick = onContainerClick,
+ indication = rippleOrFallbackImplementation(),
+ interactionSource = containerInteractionSource,
+ )
+ .semantics { role = Role.Button }
+ .fillMaxHeight()
+ .then(startPadding)
+ .weight(1.0f),
verticalAlignment = Alignment.CenterVertically,
) {
Labels(
- label = provideScopeContent(
- contentColor = colors.contentColor(enabled = enabled, selected = selected),
- textStyle = SplitSelectableButtonTokens.LabelFont.value,
- content = label
- ),
- secondaryLabel = provideNullableScopeContent(
- contentColor =
- colors.secondaryContentColor(enabled = enabled, selected = selected),
- textStyle = SplitSelectableButtonTokens.SecondaryLabelFont.value,
- content = secondaryLabel
- ),
+ label =
+ provideScopeContent(
+ contentColor = colors.contentColor(enabled = enabled, selected = selected),
+ textStyle = SplitSelectableButtonTokens.LabelFont.value,
+ content = label
+ ),
+ secondaryLabel =
+ provideNullableScopeContent(
+ contentColor =
+ colors.secondaryContentColor(enabled = enabled, selected = selected),
+ textStyle = SplitSelectableButtonTokens.SecondaryLabelFont.value,
+ content = secondaryLabel
+ ),
)
- Spacer(
- modifier = Modifier
- .size(SELECTION_CONTROL_SPACING)
- )
+ Spacer(modifier = Modifier.size(SELECTION_CONTROL_SPACING))
}
val splitContainerColor =
colors.splitContainerColor(enabled = enabled, selected = selected).value
Box(
- modifier = Modifier
- .selectable(
- enabled = enabled,
- selected = selected,
- onClick = onSelectionClick,
- indication = rippleOrFallbackImplementation(),
- interactionSource = selectionInteractionSource
- )
- .fillMaxHeight()
- .drawWithCache {
- onDrawWithContent {
- drawRect(color = splitContainerColor)
- drawContent()
+ modifier =
+ Modifier.selectable(
+ enabled = enabled,
+ selected = selected,
+ onClick = onSelectionClick,
+ indication = rippleOrFallbackImplementation(),
+ interactionSource = selectionInteractionSource
+ )
+ .fillMaxHeight()
+ .drawWithCache {
+ onDrawWithContent {
+ drawRect(color = splitContainerColor)
+ drawContent()
+ }
}
- }
- .align(Alignment.CenterVertically)
- .width(SPLIT_WIDTH)
- .wrapContentHeight(align = Alignment.CenterVertically)
- .wrapContentWidth(align = Alignment.End)
- .then(endPadding)
- .semantics {
- // For a selectable button, the role is always RadioButton.
- // See also b/330869742 for issue with setting the SelectableButton role
- // within the selection control.
- role = Role.RadioButton
- },
+ .align(Alignment.CenterVertically)
+ .width(SPLIT_WIDTH)
+ .wrapContentHeight(align = Alignment.CenterVertically)
+ .wrapContentWidth(align = Alignment.End)
+ .then(endPadding)
+ .semantics {
+ // For a selectable button, the role is always RadioButton.
+ // See also b/330869742 for issue with setting the SelectableButton role
+ // within the selection control.
+ role = Role.RadioButton
+ },
) {
val scope = remember(enabled, selected) { SelectionControlScope(enabled, selected) }
selectionControl(scope)
@@ -349,63 +343,54 @@
}
}
-/**
- * Contains the default values used by [SelectableButton]s and [SplitSelectableButton]s
- */
+/** Contains the default values used by [SelectableButton]s and [SplitSelectableButton]s */
object SelectableButtonDefaults {
- /**
- * Recommended [Shape] for [SelectableButton].
- */
+ /** Recommended [Shape] for [SelectableButton]. */
val selectableButtonShape: Shape
@Composable get() = SelectableButtonTokens.Shape.value
- /**
- * Recommended [Shape] for [SplitSelectableButton].
- */
+ /** Recommended [Shape] for [SplitSelectableButton]. */
val splitSelectableButtonShape: Shape
@Composable get() = SplitSelectableButtonTokens.Shape.value
- /**
- * Creates a [SelectableButtonColors] for use in a [SelectableButton].
- */
+ /** Creates a [SelectableButtonColors] for use in a [SelectableButton]. */
@Composable
fun selectableButtonColors() = MaterialTheme.colorScheme.defaultSelectableButtonColors
/**
* Creates a [SelectableButtonColors] for use in a [SelectableButton].
*
- * @param selectedContainerColor The container color of the [SelectableButton]
- * when enabled and selected.
- * @param selectedContentColor The content color of the [SelectableButton]
- * when enabled and selected.
+ * @param selectedContainerColor The container color of the [SelectableButton] when enabled and
+ * selected.
+ * @param selectedContentColor The content color of the [SelectableButton] when enabled and
+ * selected.
* @param selectedSecondaryContentColor The secondary content color of the [SelectableButton]
- * when enabled and selected, used for secondaryLabel content.
- * @param selectedIconColor The icon color of the [SelectableButton]
- * when enabled and selected.
- * @param unselectedContainerColor The container color of the [SelectableButton]
- * when enabled and not selected.
- * @param unselectedContentColor The content color of a [SelectableButton]
- * when enabled and not selected.
+ * when enabled and selected, used for secondaryLabel content.
+ * @param selectedIconColor The icon color of the [SelectableButton] when enabled and selected.
+ * @param unselectedContainerColor The container color of the [SelectableButton] when enabled
+ * and not selected.
+ * @param unselectedContentColor The content color of a [SelectableButton] when enabled and not
+ * selected.
* @param unselectedSecondaryContentColor The secondary content color of this [SelectableButton]
- * when enabled and not selected, used for secondaryLabel content
- * @param unselectedIconColor The icon color of the [SelectableButton]
- * when enabled and not selected.
- * @param disabledSelectedContainerColor The container color of the [SelectableButton] when disabled
- * and selected.
+ * when enabled and not selected, used for secondaryLabel content
+ * @param unselectedIconColor The icon color of the [SelectableButton] when enabled and not
+ * selected.
+ * @param disabledSelectedContainerColor The container color of the [SelectableButton] when
+ * disabled and selected.
* @param disabledSelectedContentColor The content color of the [SelectableButton] when disabled
- * and selected.
- * @param disabledSelectedSecondaryContentColor The secondary content color of the [SelectableButton]
- * when disabled and selected, used for the secondary content.
+ * and selected.
+ * @param disabledSelectedSecondaryContentColor The secondary content color of the
+ * [SelectableButton] when disabled and selected, used for the secondary content.
* @param disabledSelectedIconColor The icon color of the [SelectableButton] when disabled and
- * selected.
+ * selected.
* @param disabledUnselectedContainerColor The container color of the [SelectableButton] when
- * disabled and not selected.
- * @param disabledUnselectedContentColor The content color of the [SelectableButton] when disabled
- * and not selected.
+ * disabled and not selected.
+ * @param disabledUnselectedContentColor The content color of the [SelectableButton] when
+ * disabled and not selected.
* @param disabledUnselectedSecondaryContentColor The secondary content color of the
- * [SelectableButton] when disabled and not selected, used for secondary label content.
+ * [SelectableButton] when disabled and not selected, used for secondary label content.
* @param disabledUnselectedIconColor The icon color of the [SelectableButton] when disabled and
- * not selected.
+ * not selected.
*/
@Composable
fun selectableButtonColors(
@@ -425,7 +410,8 @@
disabledUnselectedContentColor: Color = Color.Unspecified,
disabledUnselectedSecondaryContentColor: Color = Color.Unspecified,
disabledUnselectedIconColor: Color = Color.Unspecified
- ) = MaterialTheme.colorScheme.defaultSelectableButtonColors.copy(
+ ) =
+ MaterialTheme.colorScheme.defaultSelectableButtonColors.copy(
selectedContainerColor = selectedContainerColor,
selectedContentColor = selectedContentColor,
selectedSecondaryContentColor = selectedSecondaryContentColor,
@@ -444,47 +430,45 @@
disabledUnselectedIconColor = disabledUnselectedIconColor,
)
- /**
- * Creates a [SplitSelectableButtonColors] for use in a [SplitSelectableButton].
- */
+ /** Creates a [SplitSelectableButtonColors] for use in a [SplitSelectableButton]. */
@Composable
fun splitSelectableButtonColors() = MaterialTheme.colorScheme.defaultSplitSelectableButtonColors
/**
* Creates a [SplitSelectableButtonColors] for use in a [SplitSelectableButton].
*
- * @param selectedContainerColor The container color of the [SplitSelectableButton] when enabled and
- * selected.
+ * @param selectedContainerColor The container color of the [SplitSelectableButton] when enabled
+ * and selected.
* @param selectedContentColor The content color of the [SplitSelectableButton] when enabled and
- * selected.
- * @param selectedSecondaryContentColor The secondary content color of the [SplitSelectableButton]
- * when enabled and selected, used for secondaryLabel content.
+ * selected.
+ * @param selectedSecondaryContentColor The secondary content color of the
+ * [SplitSelectableButton] when enabled and selected, used for secondaryLabel content.
* @param selectedSplitContainerColor The split container color of the [SplitSelectableButton]
- * when enabled and selected.
- * @param unselectedContainerColor The container color of the [SplitSelectableButton] when enabled
- * and not selected.
- * @param unselectedContentColor The content color of the [SplitSelectableButton] when enabled and
- * not selected.
- * @param unselectedSecondaryContentColor The secondary content color of the [SplitSelectableButton]
- * when enabled and not selected, used for secondaryLabel content.
- * @param unselectedSplitContainerColor The split container color of the [SplitSelectableButton] when
- * enabled and not selected.
+ * when enabled and selected.
+ * @param unselectedContainerColor The container color of the [SplitSelectableButton] when
+ * enabled and not selected.
+ * @param unselectedContentColor The content color of the [SplitSelectableButton] when enabled
+ * and not selected.
+ * @param unselectedSecondaryContentColor The secondary content color of the
+ * [SplitSelectableButton] when enabled and not selected, used for secondaryLabel content.
+ * @param unselectedSplitContainerColor The split container color of the [SplitSelectableButton]
+ * when enabled and not selected.
* @param disabledSelectedContainerColor The container color of the [SplitSelectableButton] when
- * disabled and selected.
- * @param disabledSelectedContentColor The content color of the [SplitSelectableButton] when disabled
- * and selected.
+ * disabled and selected.
+ * @param disabledSelectedContentColor The content color of the [SplitSelectableButton] when
+ * disabled and selected.
* @param disabledSelectedSecondaryContentColor The secondary content color of the
- * [SplitSelectableButton] when disabled and selected, used for secondaryLabel content.
+ * [SplitSelectableButton] when disabled and selected, used for secondaryLabel content.
* @param disabledSelectedSplitContainerColor The split container color of the
- * [SplitSelectableButton] when disabled and selected.
- * @param disabledUnselectedContainerColor The container color of the [SplitSelectableButton] when
- * disabled and not selected.
+ * [SplitSelectableButton] when disabled and selected.
+ * @param disabledUnselectedContainerColor The container color of the [SplitSelectableButton]
+ * when disabled and not selected.
* @param disabledUnselectedContentColor The content color of the [SplitSelectableButton] when
- * disabled and not selected.
+ * disabled and not selected.
* @param disabledUnselectedSecondaryContentColor The secondary content color of the
- * [SplitSelectableButton] when disabled and not selected, used for secondaryLabel content.
+ * [SplitSelectableButton] when disabled and not selected, used for secondaryLabel content.
* @param disabledUnselectedSplitContainerColor The split container color of the
- * [SplitSelectableButton] when disabled and not selected.
+ * [SplitSelectableButton] when disabled and not selected.
*/
@Composable
fun splitSelectableButtonColors(
@@ -504,7 +488,8 @@
disabledUnselectedContentColor: Color = Color.Unspecified,
disabledUnselectedSecondaryContentColor: Color = Color.Unspecified,
disabledUnselectedSplitContainerColor: Color = Color.Unspecified
- ) = MaterialTheme.colorScheme.defaultSplitSelectableButtonColors.copy(
+ ) =
+ MaterialTheme.colorScheme.defaultSplitSelectableButtonColors.copy(
selectedContainerColor = selectedContainerColor,
selectedContentColor = selectedContentColor,
selectedSecondaryContentColor = selectedSecondaryContentColor,
@@ -527,148 +512,207 @@
private val HorizontalPadding = 14.dp
private val VerticalPadding = 8.dp
- /**
- * The default content padding used by [SelectableButton]
- */
- val ContentPadding: PaddingValues = PaddingValues(
- start = HorizontalPadding,
- top = VerticalPadding,
- end = HorizontalPadding,
- bottom = VerticalPadding
- )
+ /** The default content padding used by [SelectableButton] */
+ val ContentPadding: PaddingValues =
+ PaddingValues(
+ start = HorizontalPadding,
+ top = VerticalPadding,
+ end = HorizontalPadding,
+ bottom = VerticalPadding
+ )
private val ColorScheme.defaultSelectableButtonColors: SelectableButtonColors
get() {
- return defaultSelectableButtonColorsCached ?: SelectableButtonColors(
- selectedContainerColor = fromToken(SelectableButtonTokens.SelectedContainerColor),
- selectedContentColor = fromToken(SelectableButtonTokens.SelectedContentColor),
- selectedSecondaryContentColor =
- fromToken(SelectableButtonTokens.SelectedSecondaryLabelColor)
- .copy(alpha = SelectableButtonTokens.SelectedSecondaryLabelOpacity),
- selectedIconColor = fromToken(SelectableButtonTokens.SelectedIconColor),
- unselectedContainerColor = fromToken(
- SelectableButtonTokens.UnselectedContainerColor
- ),
- unselectedContentColor = fromToken(SelectableButtonTokens.UnselectedContentColor),
- unselectedSecondaryContentColor =
- fromToken(SelectableButtonTokens.UnselectedSecondaryLabelColor),
- unselectedIconColor = fromToken(SelectableButtonTokens.UnselectedIconColor),
- disabledSelectedContainerColor =
- fromToken(SelectableButtonTokens.DisabledSelectedContainerColor)
- .toDisabledColor(
- disabledAlpha = SelectableButtonTokens.DisabledSelectedContainerOpacity
- ),
- disabledSelectedContentColor =
- fromToken(SelectableButtonTokens.DisabledSelectedContentColor)
- .toDisabledColor(disabledAlpha = SelectableButtonTokens.DisabledOpacity),
- disabledSelectedSecondaryContentColor =
- fromToken(SelectableButtonTokens.DisabledSelectedSecondaryLabelColor)
- .toDisabledColor(disabledAlpha = SelectableButtonTokens.DisabledOpacity),
- disabledSelectedIconColor =
- fromToken(SelectableButtonTokens.DisabledSelectedIconColor)
- .toDisabledColor(disabledAlpha = SelectableButtonTokens.DisabledOpacity),
- disabledUnselectedContainerColor =
- fromToken(SelectableButtonTokens.DisabledUnselectedContainerColor)
- .toDisabledColor(
- disabledAlpha = SelectableButtonTokens.DisabledUnselectedContainerOpacity
- ),
- disabledUnselectedContentColor =
- fromToken(SelectableButtonTokens.DisabledUnselectedContentColor)
- .toDisabledColor(disabledAlpha = SelectableButtonTokens.DisabledOpacity),
- disabledUnselectedSecondaryContentColor =
- fromToken(SelectableButtonTokens.DisabledUnselectedSecondaryLabelColor)
- .toDisabledColor(disabledAlpha = SelectableButtonTokens.DisabledOpacity),
- disabledUnselectedIconColor =
- fromToken(SelectableButtonTokens.DisabledUnselectedIconColor)
- .toDisabledColor(disabledAlpha = SelectableButtonTokens.DisabledOpacity)
- ).also { defaultSelectableButtonColorsCached = it }
+ return defaultSelectableButtonColorsCached
+ ?: SelectableButtonColors(
+ selectedContainerColor =
+ fromToken(SelectableButtonTokens.SelectedContainerColor),
+ selectedContentColor =
+ fromToken(SelectableButtonTokens.SelectedContentColor),
+ selectedSecondaryContentColor =
+ fromToken(SelectableButtonTokens.SelectedSecondaryLabelColor)
+ .copy(alpha = SelectableButtonTokens.SelectedSecondaryLabelOpacity),
+ selectedIconColor = fromToken(SelectableButtonTokens.SelectedIconColor),
+ unselectedContainerColor =
+ fromToken(SelectableButtonTokens.UnselectedContainerColor),
+ unselectedContentColor =
+ fromToken(SelectableButtonTokens.UnselectedContentColor),
+ unselectedSecondaryContentColor =
+ fromToken(SelectableButtonTokens.UnselectedSecondaryLabelColor),
+ unselectedIconColor = fromToken(SelectableButtonTokens.UnselectedIconColor),
+ disabledSelectedContainerColor =
+ fromToken(SelectableButtonTokens.DisabledSelectedContainerColor)
+ .toDisabledColor(
+ disabledAlpha =
+ SelectableButtonTokens.DisabledSelectedContainerOpacity
+ ),
+ disabledSelectedContentColor =
+ fromToken(SelectableButtonTokens.DisabledSelectedContentColor)
+ .toDisabledColor(
+ disabledAlpha = SelectableButtonTokens.DisabledOpacity
+ ),
+ disabledSelectedSecondaryContentColor =
+ fromToken(SelectableButtonTokens.DisabledSelectedSecondaryLabelColor)
+ .toDisabledColor(
+ disabledAlpha = SelectableButtonTokens.DisabledOpacity
+ ),
+ disabledSelectedIconColor =
+ fromToken(SelectableButtonTokens.DisabledSelectedIconColor)
+ .toDisabledColor(
+ disabledAlpha = SelectableButtonTokens.DisabledOpacity
+ ),
+ disabledUnselectedContainerColor =
+ fromToken(SelectableButtonTokens.DisabledUnselectedContainerColor)
+ .toDisabledColor(
+ disabledAlpha =
+ SelectableButtonTokens.DisabledUnselectedContainerOpacity
+ ),
+ disabledUnselectedContentColor =
+ fromToken(SelectableButtonTokens.DisabledUnselectedContentColor)
+ .toDisabledColor(
+ disabledAlpha = SelectableButtonTokens.DisabledOpacity
+ ),
+ disabledUnselectedSecondaryContentColor =
+ fromToken(SelectableButtonTokens.DisabledUnselectedSecondaryLabelColor)
+ .toDisabledColor(
+ disabledAlpha = SelectableButtonTokens.DisabledOpacity
+ ),
+ disabledUnselectedIconColor =
+ fromToken(SelectableButtonTokens.DisabledUnselectedIconColor)
+ .toDisabledColor(
+ disabledAlpha = SelectableButtonTokens.DisabledOpacity
+ )
+ )
+ .also { defaultSelectableButtonColorsCached = it }
}
private val ColorScheme.defaultSplitSelectableButtonColors: SplitSelectableButtonColors
get() {
- return defaultSplitSelectableButtonColorsCached ?: SplitSelectableButtonColors(
- selectedContainerColor = fromToken(
- SplitSelectableButtonTokens.SelectedContainerColor
- ),
- selectedContentColor = fromToken(SplitSelectableButtonTokens.SelectedContentColor),
- selectedSecondaryContentColor =
- fromToken(SplitSelectableButtonTokens.SelectedSecondaryLabelColor)
- .copy(alpha = SplitSelectableButtonTokens.SelectedSecondaryLabelOpacity),
- selectedSplitContainerColor =
- fromToken(SplitSelectableButtonTokens.SelectedSplitContainerColor)
- .copy(alpha = SplitSelectableButtonTokens.SelectedSplitContainerOpacity),
- unselectedContainerColor =
- fromToken(SplitSelectableButtonTokens.UnselectedContainerColor),
- unselectedContentColor = fromToken(
- SplitSelectableButtonTokens.UnselectedContentColor
- ),
- unselectedSecondaryContentColor =
- fromToken(SplitSelectableButtonTokens.UnselectedSecondaryLabelColor),
- unselectedSplitContainerColor =
- fromToken(SplitSelectableButtonTokens.UnselectedSplitContainerColor),
- disabledSelectedContainerColor =
- fromToken(SplitSelectableButtonTokens.DisabledSelectedContainerColor)
- .toDisabledColor(disabledAlpha = SplitSelectableButtonTokens.DisabledOpacity),
- disabledSelectedContentColor =
- fromToken(SplitSelectableButtonTokens.DisabledSelectedContentColor)
- .toDisabledColor(disabledAlpha = SplitSelectableButtonTokens.DisabledOpacity),
- disabledSelectedSecondaryContentColor =
- fromToken(SplitSelectableButtonTokens.DisabledSelectedSecondaryLabelColor)
- .copy(alpha = SplitSelectableButtonTokens.DisabledSelectedSecondaryLabelOpacity)
- .toDisabledColor(disabledAlpha = SplitSelectableButtonTokens.DisabledOpacity),
- disabledSelectedSplitContainerColor =
- fromToken(SplitSelectableButtonTokens.DisabledSelectedSplitContainerColor)
- .copy(alpha = SplitSelectableButtonTokens.DisabledSelectedSplitContainerOpacity)
- .toDisabledColor(disabledAlpha = SplitSelectableButtonTokens.DisabledOpacity),
- disabledUnselectedContainerColor =
- fromToken(SplitSelectableButtonTokens.DisabledUnselectedContainerColor)
- .toDisabledColor(disabledAlpha = SplitSelectableButtonTokens.DisabledOpacity),
- disabledUnselectedContentColor =
- fromToken(SplitSelectableButtonTokens.DisabledUnselectedContentColor)
- .toDisabledColor(disabledAlpha = SplitSelectableButtonTokens.DisabledOpacity),
- disabledUnselectedSecondaryContentColor =
- fromToken(SplitSelectableButtonTokens.DisabledUnselectedSecondaryLabelColor)
- .toDisabledColor(disabledAlpha = SplitSelectableButtonTokens.DisabledOpacity),
- disabledUnselectedSplitContainerColor =
- fromToken(SplitSelectableButtonTokens.DisabledUnselectedSplitContainerColor)
- .toDisabledColor(disabledAlpha = SplitSelectableButtonTokens.DisabledOpacity)
- ).also { defaultSplitSelectableButtonColorsCached = it }
+ return defaultSplitSelectableButtonColorsCached
+ ?: SplitSelectableButtonColors(
+ selectedContainerColor =
+ fromToken(SplitSelectableButtonTokens.SelectedContainerColor),
+ selectedContentColor =
+ fromToken(SplitSelectableButtonTokens.SelectedContentColor),
+ selectedSecondaryContentColor =
+ fromToken(SplitSelectableButtonTokens.SelectedSecondaryLabelColor)
+ .copy(
+ alpha =
+ SplitSelectableButtonTokens.SelectedSecondaryLabelOpacity
+ ),
+ selectedSplitContainerColor =
+ fromToken(SplitSelectableButtonTokens.SelectedSplitContainerColor)
+ .copy(
+ alpha =
+ SplitSelectableButtonTokens.SelectedSplitContainerOpacity
+ ),
+ unselectedContainerColor =
+ fromToken(SplitSelectableButtonTokens.UnselectedContainerColor),
+ unselectedContentColor =
+ fromToken(SplitSelectableButtonTokens.UnselectedContentColor),
+ unselectedSecondaryContentColor =
+ fromToken(SplitSelectableButtonTokens.UnselectedSecondaryLabelColor),
+ unselectedSplitContainerColor =
+ fromToken(SplitSelectableButtonTokens.UnselectedSplitContainerColor),
+ disabledSelectedContainerColor =
+ fromToken(SplitSelectableButtonTokens.DisabledSelectedContainerColor)
+ .toDisabledColor(
+ disabledAlpha = SplitSelectableButtonTokens.DisabledOpacity
+ ),
+ disabledSelectedContentColor =
+ fromToken(SplitSelectableButtonTokens.DisabledSelectedContentColor)
+ .toDisabledColor(
+ disabledAlpha = SplitSelectableButtonTokens.DisabledOpacity
+ ),
+ disabledSelectedSecondaryContentColor =
+ fromToken(
+ SplitSelectableButtonTokens.DisabledSelectedSecondaryLabelColor
+ )
+ .copy(
+ alpha =
+ SplitSelectableButtonTokens
+ .DisabledSelectedSecondaryLabelOpacity
+ )
+ .toDisabledColor(
+ disabledAlpha = SplitSelectableButtonTokens.DisabledOpacity
+ ),
+ disabledSelectedSplitContainerColor =
+ fromToken(
+ SplitSelectableButtonTokens.DisabledSelectedSplitContainerColor
+ )
+ .copy(
+ alpha =
+ SplitSelectableButtonTokens
+ .DisabledSelectedSplitContainerOpacity
+ )
+ .toDisabledColor(
+ disabledAlpha = SplitSelectableButtonTokens.DisabledOpacity
+ ),
+ disabledUnselectedContainerColor =
+ fromToken(SplitSelectableButtonTokens.DisabledUnselectedContainerColor)
+ .toDisabledColor(
+ disabledAlpha = SplitSelectableButtonTokens.DisabledOpacity
+ ),
+ disabledUnselectedContentColor =
+ fromToken(SplitSelectableButtonTokens.DisabledUnselectedContentColor)
+ .toDisabledColor(
+ disabledAlpha = SplitSelectableButtonTokens.DisabledOpacity
+ ),
+ disabledUnselectedSecondaryContentColor =
+ fromToken(
+ SplitSelectableButtonTokens
+ .DisabledUnselectedSecondaryLabelColor
+ )
+ .toDisabledColor(
+ disabledAlpha = SplitSelectableButtonTokens.DisabledOpacity
+ ),
+ disabledUnselectedSplitContainerColor =
+ fromToken(
+ SplitSelectableButtonTokens
+ .DisabledUnselectedSplitContainerColor
+ )
+ .toDisabledColor(
+ disabledAlpha = SplitSelectableButtonTokens.DisabledOpacity
+ )
+ )
+ .also { defaultSplitSelectableButtonColorsCached = it }
}
}
/**
- * Represents the different container and content colors used for [SelectableButton] in various states,
- * that are selected, unselected, enabled and disabled.
+ * Represents the different container and content colors used for [SelectableButton] in various
+ * states, that are selected, unselected, enabled and disabled.
*
- * @constructor [SelectableButtonColors] constructor to be used with [SelectableButton]
* @param selectedContainerColor Container or background color when the radio button is selected
* @param selectedContentColor Color of the content (e.g. label) when the radio button is selected
- * @param selectedSecondaryContentColor Color of the secondary content (e.g. secondary label)
- * when the radio button is selected
+ * @param selectedSecondaryContentColor Color of the secondary content (e.g. secondary label) when
+ * the radio button is selected
* @param selectedIconColor Color of the icon when the radio button is selected
* @param unselectedContainerColor Container or background color when the radio button is unselected
* @param unselectedContentColor Color of the content (e.g. label) when the radio button is
- * unselected
- * @param unselectedSecondaryContentColor Color of the secondary content (e.g. secondary label)
- * when the radio button is unselected
+ * unselected
+ * @param unselectedSecondaryContentColor Color of the secondary content (e.g. secondary label) when
+ * the radio button is unselected
* @param unselectedIconColor Color of the icon when the radio button is unselected
* @param disabledSelectedContainerColor Container or background color when the radio button is
- * disabled and selected
+ * disabled and selected
* @param disabledSelectedContentColor Color of content (e.g. label) when the radio button is
- * disabled and selected
+ * disabled and selected
* @param disabledSelectedSecondaryContentColor Color of the secondary content like secondary label
- * when the radio button is disabled and selected
+ * when the radio button is disabled and selected
* @param disabledSelectedIconColor Icon color when the radio button is disabled and selected
* @param disabledUnselectedContainerColor Container or background color when the radio button is
- * disabled and unselected
+ * disabled and unselected
* @param disabledUnselectedContentColor Color of the content (e.g. label) when the radio button is
- * disabled and unselected
+ * disabled and unselected
* @param disabledUnselectedSecondaryContentColor Color of the secondary content like secondary
- * label when the radio button is disabled and unselected
+ * label when the radio button is disabled and unselected
* @param disabledUnselectedIconColor Icon color when the radio button is disabled and unselected
+ * @constructor [SelectableButtonColors] constructor to be used with [SelectableButton]
*/
@Immutable
-class SelectableButtonColors constructor(
+class SelectableButtonColors
+constructor(
val selectedContainerColor: Color,
val selectedContentColor: Color,
val selectedSecondaryContentColor: Color,
@@ -704,39 +748,47 @@
disabledUnselectedContentColor: Color,
disabledUnselectedSecondaryContentColor: Color,
disabledUnselectedIconColor: Color,
- ): SelectableButtonColors = SelectableButtonColors(
- selectedContainerColor = selectedContainerColor.takeOrElse { this.selectedContainerColor },
- selectedContentColor = selectedContentColor.takeOrElse { this.selectedContentColor },
- selectedSecondaryContentColor = selectedSecondaryContentColor
- .takeOrElse { this.selectedSecondaryContentColor },
- selectedIconColor = selectedIconColor.takeOrElse { this.selectedIconColor },
- unselectedContainerColor = unselectedContainerColor
- .takeOrElse { this.unselectedContainerColor },
- unselectedContentColor = unselectedContentColor.takeOrElse { this.unselectedContentColor },
- unselectedSecondaryContentColor = unselectedSecondaryContentColor
- .takeOrElse { this.unselectedSecondaryContentColor },
- unselectedIconColor = unselectedIconColor.takeOrElse { this.unselectedIconColor },
- disabledSelectedContainerColor = disabledSelectedContainerColor
- .takeOrElse { this.disabledSelectedContainerColor },
- disabledSelectedContentColor = disabledSelectedContentColor
- .takeOrElse { this.disabledSelectedContentColor },
- disabledSelectedSecondaryContentColor = disabledSelectedSecondaryContentColor
- .takeOrElse { this.disabledSelectedSecondaryContentColor },
- disabledSelectedIconColor = disabledSelectedIconColor
- .takeOrElse { this.disabledSelectedIconColor },
- disabledUnselectedContainerColor = disabledUnselectedContainerColor
- .takeOrElse { this.disabledUnselectedContainerColor },
- disabledUnselectedContentColor = disabledUnselectedContentColor
- .takeOrElse { this.disabledUnselectedContentColor },
- disabledUnselectedSecondaryContentColor = disabledUnselectedSecondaryContentColor
- .takeOrElse { this.disabledUnselectedSecondaryContentColor },
- disabledUnselectedIconColor = disabledUnselectedIconColor
- .takeOrElse { this.disabledUnselectedIconColor },
- )
+ ): SelectableButtonColors =
+ SelectableButtonColors(
+ selectedContainerColor =
+ selectedContainerColor.takeOrElse { this.selectedContainerColor },
+ selectedContentColor = selectedContentColor.takeOrElse { this.selectedContentColor },
+ selectedSecondaryContentColor =
+ selectedSecondaryContentColor.takeOrElse { this.selectedSecondaryContentColor },
+ selectedIconColor = selectedIconColor.takeOrElse { this.selectedIconColor },
+ unselectedContainerColor =
+ unselectedContainerColor.takeOrElse { this.unselectedContainerColor },
+ unselectedContentColor =
+ unselectedContentColor.takeOrElse { this.unselectedContentColor },
+ unselectedSecondaryContentColor =
+ unselectedSecondaryContentColor.takeOrElse { this.unselectedSecondaryContentColor },
+ unselectedIconColor = unselectedIconColor.takeOrElse { this.unselectedIconColor },
+ disabledSelectedContainerColor =
+ disabledSelectedContainerColor.takeOrElse { this.disabledSelectedContainerColor },
+ disabledSelectedContentColor =
+ disabledSelectedContentColor.takeOrElse { this.disabledSelectedContentColor },
+ disabledSelectedSecondaryContentColor =
+ disabledSelectedSecondaryContentColor.takeOrElse {
+ this.disabledSelectedSecondaryContentColor
+ },
+ disabledSelectedIconColor =
+ disabledSelectedIconColor.takeOrElse { this.disabledSelectedIconColor },
+ disabledUnselectedContainerColor =
+ disabledUnselectedContainerColor.takeOrElse {
+ this.disabledUnselectedContainerColor
+ },
+ disabledUnselectedContentColor =
+ disabledUnselectedContentColor.takeOrElse { this.disabledUnselectedContentColor },
+ disabledUnselectedSecondaryContentColor =
+ disabledUnselectedSecondaryContentColor.takeOrElse {
+ this.disabledUnselectedSecondaryContentColor
+ },
+ disabledUnselectedIconColor =
+ disabledUnselectedIconColor.takeOrElse { this.disabledUnselectedIconColor },
+ )
/**
- * Determines the container color based on whether the radio button is [enabled]
- * and [selected].
+ * Determines the container color based on whether the radio button is [enabled] and [selected].
*
* @param enabled Whether the radio button is enabled
* @param selected Whether the radio button is checked
@@ -754,8 +806,7 @@
)
/**
- * Determines the content color based on whether the radio button is [enabled]
- * and [selected].
+ * Determines the content color based on whether the radio button is [enabled] and [selected].
*
* @param enabled Whether the radio button is enabled
* @param selected Whether the radio button is checked
@@ -791,8 +842,8 @@
)
/**
- * Represents the icon color for the [SelectableButton] depending on the
- * [enabled] and [selected] properties.
+ * Represents the icon color for the [SelectableButton] depending on the [enabled] and
+ * [selected] properties.
*
* @param enabled Whether the SelectableButton is enabled.
* @param selected Whether the SelectableButton is currently selected or unselected.
@@ -826,17 +877,16 @@
if (unselectedIconColor != other.unselectedIconColor) return false
if (disabledSelectedContainerColor != other.disabledSelectedContainerColor) return false
if (disabledSelectedContentColor != other.disabledSelectedContentColor) return false
- if (disabledSelectedSecondaryContentColor !=
- other.disabledSelectedSecondaryContentColor
- ) return false
+ if (disabledSelectedSecondaryContentColor != other.disabledSelectedSecondaryContentColor)
+ return false
if (disabledSelectedIconColor != other.disabledSelectedIconColor) return false
if (disabledUnselectedContainerColor != other.disabledUnselectedContainerColor) return false
if (disabledUnselectedContentColor != other.disabledUnselectedContentColor) return false
- if (disabledUnselectedSecondaryContentColor !=
- other.disabledUnselectedSecondaryContentColor
- ) return false
- if (disabledUnselectedIconColor != other.disabledUnselectedIconColor)
+ if (
+ disabledUnselectedSecondaryContentColor != other.disabledUnselectedSecondaryContentColor
+ )
return false
+ if (disabledUnselectedIconColor != other.disabledUnselectedIconColor) return false
return true
}
@@ -865,40 +915,42 @@
/**
* Represents the different colors used in [SplitSelectableButton] in different states.
*
- * @constructor [SplitSelectableButtonColors] constructor to be used with [SplitSelectableButton]
* @param selectedContainerColor Container or background color when the [SplitSelectableButton] is
- * selected
+ * selected
* @param selectedContentColor Color of the content (e.g. label) when the [SplitSelectableButton] is
- * selected
- * @param selectedSecondaryContentColor Color of the secondary content (e.g. secondary label)
- * when the [SplitSelectableButton] is selected
- * @param selectedSplitContainerColor Split container color when the [SplitSelectableButton] is selected
+ * selected
+ * @param selectedSecondaryContentColor Color of the secondary content (e.g. secondary label) when
+ * the [SplitSelectableButton] is selected
+ * @param selectedSplitContainerColor Split container color when the [SplitSelectableButton] is
+ * selected
* @param unselectedContainerColor Container or background color when the [SplitSelectableButton] is
- * unselected
- * @param unselectedContentColor Color of the content (e.g. label) when the [SplitSelectableButton] is
- * unselected
- * @param unselectedSecondaryContentColor Color of the secondary content (e.g. secondary label)
- * when the [SplitSelectableButton] is unselected
+ * unselected
+ * @param unselectedContentColor Color of the content (e.g. label) when the [SplitSelectableButton]
+ * is unselected
+ * @param unselectedSecondaryContentColor Color of the secondary content (e.g. secondary label) when
+ * the [SplitSelectableButton] is unselected
* @param unselectedSplitContainerColor Split container color when the [SplitSelectableButton] is
- * unselected
- * @param disabledSelectedContainerColor Container color when the [SplitSelectableButton] is disabled
- * and selected
- * @param disabledSelectedContentColor Color of the content (e.g. label) when the [SplitSelectableButton]
- * is disabled and selected
- * @param disabledSelectedSecondaryContentColor Color of the secondary content
- * (e.g. secondary label) when the [SplitSelectableButton] is disabled and selected
- * @param disabledSelectedSplitContainerColor Split container color when the [SplitSelectableButton] is
- * disabled and selected
- * @param disabledUnselectedContainerColor Container color when the [SplitSelectableButton] is unselected
- * and disabled
+ * unselected
+ * @param disabledSelectedContainerColor Container color when the [SplitSelectableButton] is
+ * disabled and selected
+ * @param disabledSelectedContentColor Color of the content (e.g. label) when the
+ * [SplitSelectableButton] is disabled and selected
+ * @param disabledSelectedSecondaryContentColor Color of the secondary content (e.g. secondary
+ * label) when the [SplitSelectableButton] is disabled and selected
+ * @param disabledSelectedSplitContainerColor Split container color when the [SplitSelectableButton]
+ * is disabled and selected
+ * @param disabledUnselectedContainerColor Container color when the [SplitSelectableButton] is
+ * unselected and disabled
* @param disabledUnselectedContentColor Color of the content (e.g. label) when the split radio
- * button is unselected and disabled
+ * button is unselected and disabled
* @param disabledUnselectedSecondaryContentColor Color of the secondary content (e.g. secondary
- * label) when the [SplitSelectableButton] is unselected and disabled
- * @param disabledUnselectedSplitContainerColor Split container color when the [SplitSelectableButton]
- * is unselected and disabled
+ * label) when the [SplitSelectableButton] is unselected and disabled
+ * @param disabledUnselectedSplitContainerColor Split container color when the
+ * [SplitSelectableButton] is unselected and disabled
+ * @constructor [SplitSelectableButtonColors] constructor to be used with [SplitSelectableButton]
*/
-class SplitSelectableButtonColors constructor(
+class SplitSelectableButtonColors
+constructor(
val selectedContainerColor: Color,
val selectedContentColor: Color,
val selectedSecondaryContentColor: Color,
@@ -934,41 +986,54 @@
disabledUnselectedContentColor: Color,
disabledUnselectedSecondaryContentColor: Color,
disabledUnselectedSplitContainerColor: Color,
- ): SplitSelectableButtonColors = SplitSelectableButtonColors(
- selectedContainerColor = selectedContainerColor.takeOrElse { this.selectedContainerColor },
- selectedContentColor = selectedContentColor.takeOrElse { this.selectedContentColor },
- selectedSecondaryContentColor = selectedSecondaryContentColor
- .takeOrElse { this.selectedSecondaryContentColor },
- selectedSplitContainerColor = selectedSplitContainerColor
- .takeOrElse { this.selectedSplitContainerColor },
- unselectedContainerColor = unselectedContainerColor
- .takeOrElse { this.unselectedContainerColor },
- unselectedContentColor = unselectedContentColor.takeOrElse { this.unselectedContentColor },
- unselectedSecondaryContentColor = unselectedSecondaryContentColor
- .takeOrElse { this.unselectedSecondaryContentColor },
- unselectedSplitContainerColor = unselectedSplitContainerColor
- .takeOrElse { this.unselectedSplitContainerColor },
- disabledSelectedContainerColor = disabledSelectedContainerColor
- .takeOrElse { this.disabledSelectedContainerColor },
- disabledSelectedContentColor = disabledSelectedContentColor
- .takeOrElse { this.disabledSelectedContentColor },
- disabledSelectedSecondaryContentColor = disabledSelectedSecondaryContentColor
- .takeOrElse { this.disabledSelectedSecondaryContentColor },
- disabledSelectedSplitContainerColor = disabledSelectedSplitContainerColor
- .takeOrElse { this.disabledSelectedSplitContainerColor },
- disabledUnselectedContainerColor = disabledUnselectedContainerColor
- .takeOrElse { this.disabledUnselectedContainerColor },
- disabledUnselectedContentColor = disabledUnselectedContentColor
- .takeOrElse { this.disabledUnselectedContentColor },
- disabledUnselectedSecondaryContentColor = disabledUnselectedSecondaryContentColor
- .takeOrElse { this.disabledUnselectedSecondaryContentColor },
- disabledUnselectedSplitContainerColor = disabledUnselectedSplitContainerColor
- .takeOrElse { this.disabledUnselectedSplitContainerColor },
- )
+ ): SplitSelectableButtonColors =
+ SplitSelectableButtonColors(
+ selectedContainerColor =
+ selectedContainerColor.takeOrElse { this.selectedContainerColor },
+ selectedContentColor = selectedContentColor.takeOrElse { this.selectedContentColor },
+ selectedSecondaryContentColor =
+ selectedSecondaryContentColor.takeOrElse { this.selectedSecondaryContentColor },
+ selectedSplitContainerColor =
+ selectedSplitContainerColor.takeOrElse { this.selectedSplitContainerColor },
+ unselectedContainerColor =
+ unselectedContainerColor.takeOrElse { this.unselectedContainerColor },
+ unselectedContentColor =
+ unselectedContentColor.takeOrElse { this.unselectedContentColor },
+ unselectedSecondaryContentColor =
+ unselectedSecondaryContentColor.takeOrElse { this.unselectedSecondaryContentColor },
+ unselectedSplitContainerColor =
+ unselectedSplitContainerColor.takeOrElse { this.unselectedSplitContainerColor },
+ disabledSelectedContainerColor =
+ disabledSelectedContainerColor.takeOrElse { this.disabledSelectedContainerColor },
+ disabledSelectedContentColor =
+ disabledSelectedContentColor.takeOrElse { this.disabledSelectedContentColor },
+ disabledSelectedSecondaryContentColor =
+ disabledSelectedSecondaryContentColor.takeOrElse {
+ this.disabledSelectedSecondaryContentColor
+ },
+ disabledSelectedSplitContainerColor =
+ disabledSelectedSplitContainerColor.takeOrElse {
+ this.disabledSelectedSplitContainerColor
+ },
+ disabledUnselectedContainerColor =
+ disabledUnselectedContainerColor.takeOrElse {
+ this.disabledUnselectedContainerColor
+ },
+ disabledUnselectedContentColor =
+ disabledUnselectedContentColor.takeOrElse { this.disabledUnselectedContentColor },
+ disabledUnselectedSecondaryContentColor =
+ disabledUnselectedSecondaryContentColor.takeOrElse {
+ this.disabledUnselectedSecondaryContentColor
+ },
+ disabledUnselectedSplitContainerColor =
+ disabledUnselectedSplitContainerColor.takeOrElse {
+ this.disabledUnselectedSplitContainerColor
+ },
+ )
/**
- * Determines the container color based on whether the [SplitSelectableButton] is [enabled]
- * and [selected].
+ * Determines the container color based on whether the [SplitSelectableButton] is [enabled] and
+ * [selected].
*
* @param enabled Whether the [SplitSelectableButton] is enabled
* @param selected Whether the [SplitSelectableButton] is currently checked/selected
@@ -986,8 +1051,8 @@
)
/**
- * Determines the content color based on whether the [SplitSelectableButton] is [enabled]
- * and [selected].
+ * Determines the content color based on whether the [SplitSelectableButton] is [enabled] and
+ * [selected].
*
* @param enabled Whether the [SplitSelectableButton] is enabled
* @param selected Whether the [SplitSelectableButton] is currently selected
@@ -1059,16 +1124,16 @@
if (unselectedSplitContainerColor != other.unselectedSplitContainerColor) return false
if (disabledSelectedContainerColor != other.disabledSelectedContainerColor) return false
if (disabledSelectedContentColor != other.disabledSelectedContentColor) return false
- if (disabledSelectedSecondaryContentColor !=
- other.disabledSelectedSecondaryContentColor
- ) return false
+ if (disabledSelectedSecondaryContentColor != other.disabledSelectedSecondaryContentColor)
+ return false
if (disabledSelectedSplitContainerColor != other.disabledSelectedSplitContainerColor)
return false
if (disabledUnselectedContainerColor != other.disabledUnselectedContainerColor) return false
if (disabledUnselectedContentColor != other.disabledUnselectedContentColor) return false
- if (disabledUnselectedSecondaryContentColor !=
- other.disabledUnselectedSecondaryContentColor
- ) return false
+ if (
+ disabledUnselectedSecondaryContentColor != other.disabledUnselectedSecondaryContentColor
+ )
+ return false
if (disabledUnselectedSplitContainerColor != other.disabledUnselectedSplitContainerColor)
return false
@@ -1097,17 +1162,14 @@
}
/**
- * [SelectionControlScope] provides enabled and selected properties. This allows
- * selection controls to omit enabled/selected parameters as they given by the scope.
+ * [SelectionControlScope] provides enabled and selected properties. This allows selection controls
+ * to omit enabled/selected parameters as they given by the scope.
*
- * @param isEnabled Controls the enabled state of the selection control.
- * When `false`, the control is displayed with disabled colors
+ * @param isEnabled Controls the enabled state of the selection control. When `false`, the control
+ * is displayed with disabled colors
* @param isSelected Indicates whether the control is currently selected
*/
-class SelectionControlScope(
- val isEnabled: Boolean,
- val isSelected: Boolean
-)
+class SelectionControlScope(val isEnabled: Boolean, val isSelected: Boolean)
@Composable
private fun RowScope.Labels(
@@ -1130,14 +1192,13 @@
end = 0.dp,
top = calculateTopPadding(),
bottom = calculateBottomPadding()
- ) to Modifier.padding(
- start = 0.dp,
- end = calculateEndPadding(
- layoutDirection = LocalLayoutDirection.current
- ),
- top = calculateTopPadding(),
- bottom = calculateBottomPadding()
- )
+ ) to
+ Modifier.padding(
+ start = 0.dp,
+ end = calculateEndPadding(layoutDirection = LocalLayoutDirection.current),
+ top = calculateTopPadding(),
+ bottom = calculateBottomPadding()
+ )
private val COLOR_ANIMATION_SPEC: AnimationSpec<Color> =
tween(MotionTokens.DurationMedium1, 0, MotionTokens.EasingStandardDecelerate)
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/SelectionControls.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/SelectionControls.kt
index 6998bf2..428c4a8 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/SelectionControls.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/SelectionControls.kt
@@ -28,48 +28,44 @@
import androidx.wear.compose.materialcore.animateSelectionColor
/**
- * [RadioButton] provides an animated radio selection control for use in [SelectableButton]
- * or [SplitSelectableButton].
+ * [RadioButton] provides an animated radio selection control for use in [SelectableButton] or
+ * [SplitSelectableButton].
*
* RadioButton sample:
+ *
* @sample androidx.wear.compose.material3.samples.SelectableButtonSample
*
* @param modifier Modifier to be applied to the radio button control. This can be used to provide a
- * content description for accessibility.
+ * content description for accessibility.
* @param colors [RadioButtonColors] from which the [RadioButton] control colors will be obtained.
*/
@Composable
fun SelectionControlScope.RadioButton(
modifier: Modifier = Modifier,
colors: RadioButtonColors = RadioButtonDefaults.colors(),
-) = androidx.wear.compose.materialcore.RadioButton(
- modifier = modifier,
- selected = isSelected,
- enabled = isEnabled,
- ringColor = { isEnabled, isSelected ->
- colors.color(
- enabled = isEnabled,
- selected = isSelected
- )
- },
- dotColor = { isEnabled, isSelected ->
- colors.color(
- enabled = isEnabled,
- selected = isSelected
- )
- },
- onClick = null,
- interactionSource = null,
- dotRadiusProgressDuration = {
- isSelected -> if (isSelected) MotionTokens.DurationMedium1 else MotionTokens.DurationShort3
- },
- dotAlphaProgressDuration = MotionTokens.DurationShort3,
- dotAlphaProgressDelay = MotionTokens.DurationShort2,
- easing = MotionTokens.EasingStandardDecelerate,
- width = WIDTH,
- height = HEIGHT,
- ripple = rippleOrFallbackImplementation()
-)
+) =
+ androidx.wear.compose.materialcore.RadioButton(
+ modifier = modifier,
+ selected = isSelected,
+ enabled = isEnabled,
+ ringColor = { isEnabled, isSelected ->
+ colors.color(enabled = isEnabled, selected = isSelected)
+ },
+ dotColor = { isEnabled, isSelected ->
+ colors.color(enabled = isEnabled, selected = isSelected)
+ },
+ onClick = null,
+ interactionSource = null,
+ dotRadiusProgressDuration = { isSelected ->
+ if (isSelected) MotionTokens.DurationMedium1 else MotionTokens.DurationShort3
+ },
+ dotAlphaProgressDuration = MotionTokens.DurationShort3,
+ dotAlphaProgressDelay = MotionTokens.DurationShort2,
+ easing = MotionTokens.EasingStandardDecelerate,
+ width = WIDTH,
+ height = HEIGHT,
+ ripple = rippleOrFallbackImplementation()
+ )
/**
* Represents the content colors used in the [RadioButton] selection control in different states.
@@ -87,15 +83,16 @@
val disabledUnselectedColor: Color
) {
@Composable
- internal fun color(enabled: Boolean, selected: Boolean): State<Color> = animateSelectionColor(
- enabled = enabled,
- checked = selected,
- checkedColor = selectedColor,
- uncheckedColor = unselectedColor,
- disabledCheckedColor = disabledSelectedColor,
- disabledUncheckedColor = disabledUnselectedColor,
- animationSpec = COLOR_ANIMATION_SPEC
- )
+ internal fun color(enabled: Boolean, selected: Boolean): State<Color> =
+ animateSelectionColor(
+ enabled = enabled,
+ checked = selected,
+ checkedColor = selectedColor,
+ uncheckedColor = unselectedColor,
+ disabledCheckedColor = disabledSelectedColor,
+ disabledUncheckedColor = disabledUnselectedColor,
+ animationSpec = COLOR_ANIMATION_SPEC
+ )
override fun equals(other: Any?): Boolean {
if (this === other) return true
@@ -118,9 +115,7 @@
}
}
-/**
- * Contains the default values used by the [RadioButton] selection control.
- */
+/** Contains the default values used by the [RadioButton] selection control. */
object RadioButtonDefaults {
/**
* Creates a [RadioButtonColors] for use in a [RadioButton] selection control.
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Shapes.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Shapes.kt
index 8fd786d..178aba6 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Shapes.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Shapes.kt
@@ -30,34 +30,32 @@
* Material surfaces can be displayed in different shapes. Shapes direct attention, identify
* components, communicate state, and express brand.
*
- * The shape scale defines the style of container, offering a range of
- * curved shapes (mostly polygonal). The default [Shapes] theme for Material3 is rounded rectangles,
- * with various degrees of corner roundness:
- *
+ * The shape scale defines the style of container, offering a range of curved shapes (mostly
+ * polygonal). The default [Shapes] theme for Material3 is rounded rectangles, with various degrees
+ * of corner roundness:
* - Extra Small
* - Small
* - Medium
* - Large
* - Extra Large
*
- * You can customize the shape system for all components in the [MaterialTheme] or you can do it
- * on a per component basis by overriding the shape parameter for that
- * component. For example, by default, buttons use the shape style "large". If your product requires
- * a smaller amount of roundness, you can override the shape parameter with a different shape
- * value like [Shapes.small].
+ * You can customize the shape system for all components in the [MaterialTheme] or you can do it on
+ * a per component basis by overriding the shape parameter for that component. For example, by
+ * default, buttons use the shape style "large". If your product requires a smaller amount of
+ * roundness, you can override the shape parameter with a different shape value like [Shapes.small].
+ *
+ * @param extraSmall By default, provides [ShapeDefaults.ExtraSmall], a [RoundedCornerShape] with
+ * 4dp [CornerSize] (used by bundled Cards).
+ * @param small By default, provides [ShapeDefaults.Small], a [RoundedCornerShape] with 8dp
+ * [CornerSize].
+ * @param medium By default, provides [ShapeDefaults.Medium], a [RoundedCornerShape] with 16dp
+ * [CornerSize] (used by shape-shifting Buttons and rounded rectangle buttons).
+ * @param large By default, provides [ShapeDefaults.Large], a [RoundedCornerShape] with 24dp
+ * [CornerSize] (used by Cards).
+ * @param extraLarge By default, provides [ShapeDefaults.ExtraLarge], a [RoundedCornerShape] with
+ * 32dp [CornerSize].
*
* TODO(b/273226734) Review documentation with references to components that use the shape themes.
- *
- * @param extraSmall By default, provides [ShapeDefaults.ExtraSmall], a [RoundedCornerShape]
- * with 4dp [CornerSize] (used by bundled Cards).
- * @param small By default, provides [ShapeDefaults.Small], a [RoundedCornerShape]
- * with 8dp [CornerSize].
- * @param medium By default, provides [ShapeDefaults.Medium], a [RoundedCornerShape] with
- * 16dp [CornerSize] (used by shape-shifting Buttons and rounded rectangle buttons).
- * @param large By default, provides [ShapeDefaults.Large], a [RoundedCornerShape]
- * with 24dp [CornerSize] (used by Cards).
- * @param extraLarge By default, provides [ShapeDefaults.ExtraLarge], a
- * [RoundedCornerShape] with 32dp [CornerSize].
*/
@Immutable
class Shapes(
@@ -74,13 +72,14 @@
medium: CornerBasedShape = this.medium,
large: CornerBasedShape = this.large,
extraLarge: CornerBasedShape = this.extraLarge,
- ): Shapes = Shapes(
- extraSmall = extraSmall,
- small = small,
- medium = medium,
- large = large,
- extraLarge = extraLarge,
- )
+ ): Shapes =
+ Shapes(
+ extraSmall = extraSmall,
+ small = small,
+ medium = medium,
+ large = large,
+ extraLarge = extraLarge,
+ )
override fun equals(other: Any?): Boolean {
if (this === other) return true
@@ -112,9 +111,7 @@
}
}
-/**
- * Contains the default values used by [Shapes]
- */
+/** Contains the default values used by [Shapes] */
object ShapeDefaults {
/** Extra small sized corner shape */
@@ -135,8 +132,7 @@
/**
* Helper function for component shape tokens. Here is an example on how to use component color
- * tokens:
- * ``MaterialTheme.shapes.fromToken(FabPrimarySmallTokens.ContainerShape)``
+ * tokens: ``MaterialTheme.shapes.fromToken(FabPrimarySmallTokens.ContainerShape)``
*/
internal fun Shapes.fromToken(value: ShapeKeyTokens): Shape {
return when (value) {
@@ -151,13 +147,11 @@
}
/**
- * Converts a shape token key to the local shape provided by the theme
- * The shape references the [LocalShapes].
+ * Converts a shape token key to the local shape provided by the theme The shape references the
+ * [LocalShapes].
*/
internal val ShapeKeyTokens.value: Shape
- @Composable
- @ReadOnlyComposable
- get() = MaterialTheme.shapes.fromToken(this)
+ @Composable @ReadOnlyComposable get() = MaterialTheme.shapes.fromToken(this)
/** CompositionLocal used to specify the default shapes for the surfaces. */
internal val LocalShapes = staticCompositionLocalOf { Shapes() }
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Slider.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Slider.kt
index 133d447..72552ca 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Slider.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Slider.kt
@@ -73,31 +73,33 @@
* [steps] + 1 value.
*
* A continuous non-segmented slider sample:
+ *
* @sample androidx.wear.compose.material3.samples.InlineSliderSample
*
* A segmented slider sample:
+ *
* @sample androidx.wear.compose.material3.samples.InlineSliderSegmentedSample
*
* @param value Current value of the Slider. If outside of [valueRange] provided, value will be
- * coerced to this range.
+ * coerced to this range.
* @param onValueChange Lambda in which value should be updated.
* @param steps Specifies the number of discrete values, excluding min and max values, evenly
- * distributed across the whole value range. Must not be negative. If 0, slider will have only min
- * and max values and no steps in between.
+ * distributed across the whole value range. Must not be negative. If 0, slider will have only min
+ * and max values and no steps in between.
* @param decreaseIcon A slot for an icon which is placed on the decrease (start) button such as
- * [InlineSliderDefaults.Decrease].
+ * [InlineSliderDefaults.Decrease].
* @param increaseIcon A slot for an icon which is placed on the increase (end) button such as
- * [InlineSliderDefaults.Increase].
+ * [InlineSliderDefaults.Increase].
* @param modifier Modifiers for the Slider layout.
* @param enabled Controls the enabled state of the slider. When `false`, this slider will not be
- * clickable.
+ * clickable.
* @param valueRange Range of values that Slider value can take. Passed [value] will be coerced to
- * this range.
+ * this range.
* @param segmented A boolean value which specifies whether a bar will be split into segments or
- * not. Recommendation is while using this flag do not have more than 8 [steps] as it might affect
- * user experience. By default true if number of [steps] is <=8.
+ * not. Recommendation is while using this flag do not have more than 8 [steps] as it might affect
+ * user experience. By default true if number of [steps] is <=8.
* @param colors [InlineSliderColors] that will be used to resolve the background and content color
- * for this slider in different states.
+ * for this slider in different states.
*/
@ExperimentalWearMaterial3Api
@Composable
@@ -117,13 +119,12 @@
val currentStep =
remember(value, valueRange, steps) { snapValueToStep(value, valueRange, steps) }
BoxWithConstraints(
- modifier = modifier
- .fillMaxWidth()
- .rangeSemantics(
- value, enabled, onValueChange, valueRange, steps
- )
- .height(InlineSliderDefaults.SliderHeight)
- .clip(CircleShape) // TODO(b/290625297) Replace with tokens
+ modifier =
+ modifier
+ .fillMaxWidth()
+ .rangeSemantics(value, enabled, onValueChange, valueRange, steps)
+ .height(InlineSliderDefaults.SliderHeight)
+ .clip(CircleShape) // TODO(b/290625297) Replace with tokens
) {
val visibleSegments = if (segmented) steps + 1 else 1
@@ -136,17 +137,13 @@
val containerColor = colors.containerColor(enabled)
val barSeparatorColor = colors.barSeparatorColor(enabled)
CompositionLocalProvider(
- LocalIndication provides rippleOrFallbackImplementation(
- bounded = false,
- radius = this.maxWidth / 2
- )
+ LocalIndication provides
+ rippleOrFallbackImplementation(bounded = false, radius = this.maxWidth / 2)
) {
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Start,
- modifier = Modifier
- .fillMaxWidth()
- .background(containerColor.value)
+ modifier = Modifier.fillMaxWidth().background(containerColor.value)
) {
val increaseButtonEnabled = enabled && currentStep < steps + 1
val decreaseButtonEnabled = enabled && currentStep > 0
@@ -166,37 +163,39 @@
}
)
- val valueRatio by animateFloatAsState(
- targetValue = currentStep.toFloat() / (steps + 1).toFloat(),
- animationSpec = tween(
- durationMillis = MotionTokens.DurationShort3,
- delayMillis = 0,
- easing = MotionTokens.EasingStandardDecelerate
+ val valueRatio by
+ animateFloatAsState(
+ targetValue = currentStep.toFloat() / (steps + 1).toFloat(),
+ animationSpec =
+ tween(
+ durationMillis = MotionTokens.DurationShort3,
+ delayMillis = 0,
+ easing = MotionTokens.EasingStandardDecelerate
+ )
)
- )
Box(
- modifier = Modifier
- .height(InlineSliderDefaults.BarHeight)
- .weight(1f)
- .clip(CircleShape) // TODO(b/290625297) Replace with token
- .drawProgressBar(
- selectedBarColor = selectedBarColor,
- unselectedBarColor = unselectedBarColor,
- barSeparatorColor = barSeparatorColor,
- visibleSegments = visibleSegments,
- valueRatio = valueRatio,
- direction = LocalLayoutDirection.current,
- drawSelectedProgressBar = { color, ratio, direction, drawScope ->
- drawScope.drawSelectedProgressBar(color, ratio, direction)
- },
- drawUnselectedProgressBar = { color, ratio, direction, drawScope ->
- drawScope.drawUnselectedProgressBar(color, ratio, direction)
- },
- drawProgressBarSeparator = { color, position, drawScope ->
- drawScope.drawProgressBarSeparator(color, position)
- }
- )
+ modifier =
+ Modifier.height(InlineSliderDefaults.BarHeight)
+ .weight(1f)
+ .clip(CircleShape) // TODO(b/290625297) Replace with token
+ .drawProgressBar(
+ selectedBarColor = selectedBarColor,
+ unselectedBarColor = unselectedBarColor,
+ barSeparatorColor = barSeparatorColor,
+ visibleSegments = visibleSegments,
+ valueRatio = valueRatio,
+ direction = LocalLayoutDirection.current,
+ drawSelectedProgressBar = { color, ratio, direction, drawScope ->
+ drawScope.drawSelectedProgressBar(color, ratio, direction)
+ },
+ drawUnselectedProgressBar = { color, ratio, direction, drawScope ->
+ drawScope.drawUnselectedProgressBar(color, ratio, direction)
+ },
+ drawProgressBarSeparator = { color, position, drawScope ->
+ drawScope.drawProgressBarSeparator(color, position)
+ }
+ )
)
InlineSliderButton(
@@ -237,28 +236,30 @@
* example, 1..13 range and a step = 5, steps will be 1(first) , 6 , 11(last)
*
* A continuous non-segmented slider sample:
+ *
* @sample androidx.wear.compose.material3.samples.InlineSliderWithIntegerSample
*
* A segmented slider sample:
+ *
* @sample androidx.wear.compose.material3.samples.InlineSliderSegmentedSample
*
* @param value Current value of the Slider. If outside of [valueProgression] provided, value will
- * be coerced to this range.
+ * be coerced to this range.
* @param onValueChange Lambda in which value should be updated.
* @param valueProgression Progression of values that Slider value can take. Consists of rangeStart,
- * rangeEnd and step. Range will be equally divided by step size.
+ * rangeEnd and step. Range will be equally divided by step size.
* @param decreaseIcon A slot for an icon which is placed on the decrease (start) button such as
- * [InlineSliderDefaults.Decrease].
+ * [InlineSliderDefaults.Decrease].
* @param increaseIcon A slot for an icon which is placed on the increase (end) button such as
- * [InlineSliderDefaults.Increase].
+ * [InlineSliderDefaults.Increase].
* @param modifier Modifiers for the Slider layout.
* @param enabled Controls the enabled state of the slider. When `false`, this slider will not be
- * clickable.
+ * clickable.
* @param segmented A boolean value which specifies whether a bar will be split into segments or
- * not. Recommendation is while using this flag do not have more than 8 steps as it might affect
- * user experience. By default true if number of steps is <=8.
+ * not. Recommendation is while using this flag do not have more than 8 steps as it might affect
+ * user experience. By default true if number of steps is <=8.
* @param colors [InlineSliderColors] that will be used to resolve the background and content color
- * for this slider in different states.
+ * for this slider in different states.
*/
@ExperimentalWearMaterial3Api
@Composable
@@ -290,9 +291,7 @@
/** Defaults used by slider. */
@ExperimentalWearMaterial3Api
object InlineSliderDefaults {
- /**
- * Default slider measurements.
- */
+ /** Default slider measurements. */
internal val SliderHeight = 52.dp
internal val ControlSize = 36.dp
@@ -307,9 +306,7 @@
internal val BarSeparatorRadius = 2.dp
- /**
- * The recommended size for Slider [Decrease] and [Increase] button icons.
- */
+ /** The recommended size for Slider [Decrease] and [Increase] button icons. */
val IconSize = 24.dp
/**
@@ -325,7 +322,8 @@
* @param disabledButtonIconColor The color of the icon of buttons when disabled
* @param disabledSelectedBarColor The color of the progress bar when disabled
* @param disabledUnselectedBarColor The background color of the progress bar when disabled
- * @param disabledBarSeparatorColor The color of separator between visible segments when disabled
+ * @param disabledBarSeparatorColor The color of separator between visible segments when
+ * disabled
*/
@Composable
fun colors(
@@ -334,27 +332,26 @@
selectedBarColor: Color = MaterialTheme.colorScheme.primary,
unselectedBarColor: Color = MaterialTheme.colorScheme.background.copy(alpha = 0.3f),
barSeparatorColor: Color = MaterialTheme.colorScheme.primaryDim,
- disabledContainerColor: Color = containerColor.toDisabledColor(
- disabledAlpha = DisabledContainerAlpha
- ),
+ disabledContainerColor: Color =
+ containerColor.toDisabledColor(disabledAlpha = DisabledContainerAlpha),
disabledButtonIconColor: Color = buttonIconColor.toDisabledColor(),
disabledSelectedBarColor: Color = selectedBarColor.toDisabledColor(),
disabledUnselectedBarColor: Color = unselectedBarColor.toDisabledColor(),
- disabledBarSeparatorColor: Color = barSeparatorColor.toDisabledColor(
- disabledAlpha = DisabledContainerAlpha
+ disabledBarSeparatorColor: Color =
+ barSeparatorColor.toDisabledColor(disabledAlpha = DisabledContainerAlpha)
+ ): InlineSliderColors =
+ InlineSliderColors(
+ containerColor = containerColor,
+ buttonIconColor = buttonIconColor,
+ selectedBarColor = selectedBarColor,
+ unselectedBarColor = unselectedBarColor,
+ barSeparatorColor = barSeparatorColor,
+ disabledContainerColor = disabledContainerColor,
+ disabledButtonIconColor = disabledButtonIconColor,
+ disabledSelectedBarColor = disabledSelectedBarColor,
+ disabledUnselectedBarColor = disabledUnselectedBarColor,
+ disabledBarSeparatorColor = disabledBarSeparatorColor
)
- ): InlineSliderColors = InlineSliderColors(
- containerColor = containerColor,
- buttonIconColor = buttonIconColor,
- selectedBarColor = selectedBarColor,
- unselectedBarColor = unselectedBarColor,
- barSeparatorColor = barSeparatorColor,
- disabledContainerColor = disabledContainerColor,
- disabledButtonIconColor = disabledButtonIconColor,
- disabledSelectedBarColor = disabledSelectedBarColor,
- disabledUnselectedBarColor = disabledUnselectedBarColor,
- disabledBarSeparatorColor = disabledBarSeparatorColor
- )
/** Decrease [ImageVector]. */
val Decrease = RangeIcons.Minus
@@ -366,10 +363,6 @@
/**
* Represents the background and content colors used in [InlineSlider] in different states.
*
- * @constructor create an instance with arbitrary colors.
- * See [InlineSliderDefaults.colors] for the default implementation that follows Material
- * specifications.
- *
* @param containerColor The background color of this [InlineSlider] when enabled.
* @param buttonIconColor The color of the icon of buttons when enabled.
* @param selectedBarColor The color of the progress bar when enabled.
@@ -380,10 +373,13 @@
* @param disabledSelectedBarColor The color of the progress bar when disabled.
* @param disabledUnselectedBarColor The background color of the progress bar when disabled.
* @param disabledBarSeparatorColor The color of separator between visible segments when disabled.
+ * @constructor create an instance with arbitrary colors. See [InlineSliderDefaults.colors] for the
+ * default implementation that follows Material specifications.
*/
@ExperimentalWearMaterial3Api
@Immutable
-class InlineSliderColors constructor(
+class InlineSliderColors
+constructor(
val containerColor: Color,
val buttonIconColor: Color,
val selectedBarColor: Color,
@@ -417,13 +413,15 @@
)
@Composable
- internal fun barColor(enabled: Boolean, selected: Boolean): State<Color> = animateColorAsState(
- if (enabled) {
- if (selected) selectedBarColor else unselectedBarColor
- } else {
- if (selected) disabledSelectedBarColor else disabledUnselectedBarColor
- }, label = "sliderBarColorAnimation"
- )
+ internal fun barColor(enabled: Boolean, selected: Boolean): State<Color> =
+ animateColorAsState(
+ if (enabled) {
+ if (selected) selectedBarColor else unselectedBarColor
+ } else {
+ if (selected) disabledSelectedBarColor else disabledUnselectedBarColor
+ },
+ label = "sliderBarColorAnimation"
+ )
override fun equals(other: Any?): Boolean {
if (this === other) return true
@@ -470,10 +468,11 @@
val barHeightInPx = InlineSliderDefaults.SelectedBarHeight.toPx()
drawRoundRect(
color = color,
- topLeft = Offset(
- directedValue(direction, 0f, size.width * (1 - valueRatio)),
- (size.height - barHeightInPx) / 2
- ),
+ topLeft =
+ Offset(
+ directedValue(direction, 0f, size.width * (1 - valueRatio)),
+ (size.height - barHeightInPx) / 2
+ ),
size = Size(size.width * valueRatio, barHeightInPx),
cornerRadius = CornerRadius(barHeightInPx / 2)
)
@@ -488,9 +487,11 @@
val barHeightInPx = InlineSliderDefaults.UnselectedBarHeight.toPx()
drawRoundRect(
color = color,
- topLeft = Offset(
- directedValue(direction, size.width * valueRatio, 0f), (size.height - barHeightInPx) / 2
- ),
+ topLeft =
+ Offset(
+ directedValue(direction, size.width * valueRatio, 0f),
+ (size.height - barHeightInPx) / 2
+ ),
size = Size(size.width * (1 - valueRatio), barHeightInPx),
cornerRadius = CornerRadius(barHeightInPx / 2)
)
@@ -511,7 +512,8 @@
enabled: Boolean,
buttonIconColor: @Composable (enabled: Boolean) -> State<Color>,
content: @Composable () -> Unit
-) = CompositionLocalProvider(
- LocalContentColor provides buttonIconColor(enabled).value,
- content = content
-)
+) =
+ CompositionLocalProvider(
+ LocalContentColor provides buttonIconColor(enabled).value,
+ content = content
+ )
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Stepper.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Stepper.kt
index e75009b..12f9f1e 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Stepper.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Stepper.kt
@@ -27,40 +27,40 @@
import kotlin.math.roundToInt
/**
- * [Stepper] allows users to make a selection from a range of values.
- * It's a full-screen control with increase button on the top, decrease button on the bottom and
- * a slot (expected to have either [Text] or [Button]) in the middle.
- * Value can be increased and decreased by clicking on the increase and decrease buttons.
- * Buttons can have custom icons - [decreaseIcon] and [increaseIcon].
+ * [Stepper] allows users to make a selection from a range of values. It's a full-screen control
+ * with increase button on the top, decrease button on the bottom and a slot (expected to have
+ * either [Text] or [Button]) in the middle. Value can be increased and decreased by clicking on the
+ * increase and decrease buttons. Buttons can have custom icons - [decreaseIcon] and [increaseIcon].
* Step value is calculated as the difference between min and max values divided by [steps]+1.
* Stepper itself doesn't show the current value but can be displayed via the content slot or
- * [PositionIndicator] if required.
- * If [value] is not equal to any step value, then it will be coerced to the closest step value.
- * However, the [value] itself will not be changed and [onValueChange] in this case will
- * not be triggered.
- * To add range semantics on Stepper, use [Modifier.rangeSemantics].
+ * [PositionIndicator] if required. If [value] is not equal to any step value, then it will be
+ * coerced to the closest step value. However, the [value] itself will not be changed and
+ * [onValueChange] in this case will not be triggered. To add range semantics on Stepper, use
+ * [Modifier.rangeSemantics].
*
* Example of a simple [Stepper]:
+ *
* @sample androidx.wear.compose.material3.samples.StepperSample
*
* Example of a [Stepper] with range semantics:
+ *
* @sample androidx.wear.compose.material3.samples.StepperWithRangeSemanticsSample
*
* @param value Current value of the Stepper. If outside of [valueRange] provided, value will be
- * coerced to this range.
+ * coerced to this range.
* @param onValueChange Lambda in which value should be updated
* @param steps Specifies the number of discrete values, excluding min and max values, evenly
- * distributed across the whole value range. Must not be negative. If 0, stepper will have only
- * min and max values and no steps in between
+ * distributed across the whole value range. Must not be negative. If 0, stepper will have only
+ * min and max values and no steps in between
* @param decreaseIcon A slot for an icon which is placed on the decrease (bottom) button
* @param increaseIcon A slot for an icon which is placed on the increase (top) button
* @param modifier Modifiers for the Stepper layout
* @param valueRange Range of values that Stepper value can take. Passed [value] will be coerced to
- * this range
+ * this range
* @param backgroundColor [Color] representing the background color for the stepper.
* @param contentColor [Color] representing the color for [content] in the middle.
- * @param iconColor Icon tint [Color] which used by [increaseIcon] and [decreaseIcon]
- * that defaults to [contentColor], unless specifically overridden.
+ * @param iconColor Icon tint [Color] which used by [increaseIcon] and [decreaseIcon] that defaults
+ * to [contentColor], unless specifically overridden.
* @param content Content body for the Stepper.
*/
@ExperimentalWearMaterial3Api
@@ -87,60 +87,58 @@
valueRange = valueRange,
modifier = modifier,
backgroundColor = backgroundColor,
- enabledButtonProviderValues = arrayOf(
- LocalContentColor provides iconColor,
- ),
- disabledButtonProviderValues = arrayOf(
- LocalContentColor provides iconColor.copy(alpha = DisabledContentAlpha),
- ),
+ enabledButtonProviderValues =
+ arrayOf(
+ LocalContentColor provides iconColor,
+ ),
+ disabledButtonProviderValues =
+ arrayOf(
+ LocalContentColor provides iconColor.copy(alpha = DisabledContentAlpha),
+ ),
buttonRipple = rippleOrFallbackImplementation(bounded = false)
) {
- CompositionLocalProvider(
- LocalContentColor provides contentColor
- ) {
- content()
- }
+ CompositionLocalProvider(LocalContentColor provides contentColor) { content() }
}
}
/**
- * [Stepper] allows users to make a selection from a range of values.
- * It's a full-screen control with increase button on the top, decrease button on the bottom and
- * a slot (expected to have either [Text] or [Button]) in the middle.
- * Value can be increased and decreased by clicking on the increase and decrease buttons.
- * Buttons can have custom icons - [decreaseIcon] and [increaseIcon].
+ * [Stepper] allows users to make a selection from a range of values. It's a full-screen control
+ * with increase button on the top, decrease button on the bottom and a slot (expected to have
+ * either [Text] or [Button]) in the middle. Value can be increased and decreased by clicking on the
+ * increase and decrease buttons. Buttons can have custom icons - [decreaseIcon] and [increaseIcon].
* Stepper itself doesn't show the current value but can be displayed via the content slot or
- * [PositionIndicator] if required.
- * To add range semantics on Stepper, use [Modifier.rangeSemantics].
+ * [PositionIndicator] if required. To add range semantics on Stepper, use
+ * [Modifier.rangeSemantics].
*
* Example of a [Stepper] with integer values:
+ *
* @sample androidx.wear.compose.material3.samples.StepperWithIntegerSample
*
* A number of steps is calculated as the difference between max and min values of
- * [valueProgression] divided by [valueProgression].step - 1.
- * For example, with a range of 100..120 and a step 5,
- * number of steps will be (120-100)/ 5 - 1 = 3. Steps are 100(first), 105, 110, 115, 120(last)
+ * [valueProgression] divided by [valueProgression].step - 1. For example, with a range of 100..120
+ * and a step 5, number of steps will be (120-100)/ 5 - 1 = 3. Steps are 100(first), 105, 110, 115,
+ * 120(last)
*
- * If [valueProgression] range is not equally divisible by [valueProgression].step,
- * then [valueProgression].last will be adjusted to the closest divisible value in the range.
- * For example, 1..13 range and a step = 5, steps will be 1(first) , 6 , 11(last)
+ * If [valueProgression] range is not equally divisible by [valueProgression].step, then
+ * [valueProgression].last will be adjusted to the closest divisible value in the range. For
+ * example, 1..13 range and a step = 5, steps will be 1(first) , 6 , 11(last)
*
* If [value] is not equal to any step value, then it will be coerced to the closest step value.
- * However, the [value] itself will not be changed and [onValueChange] in this case will
- * not be triggered.
+ * However, the [value] itself will not be changed and [onValueChange] in this case will not be
+ * triggered.
*
- * @param value Current value of the Stepper. If outside of [valueProgression] provided, value will be
- * coerced to this range.
+ * @param value Current value of the Stepper. If outside of [valueProgression] provided, value will
+ * be coerced to this range.
* @param onValueChange Lambda in which value should be updated
* @param valueProgression Progression of values that Stepper value can take. Consists of
- * rangeStart, rangeEnd and step. Range will be equally divided by step size
+ * rangeStart, rangeEnd and step. Range will be equally divided by step size
* @param decreaseIcon A slot for an icon which is placed on the decrease (bottom) button
* @param increaseIcon A slot for an icon which is placed on the increase (top) button
* @param modifier Modifiers for the Stepper layout
* @param backgroundColor [Color] representing the background color for the stepper.
* @param contentColor [Color] representing the color for [content] in the middle.
- * @param iconColor Icon tint [Color] which used by [increaseIcon] and [decreaseIcon]
- * that defaults to [contentColor], unless specifically overridden.
+ * @param iconColor Icon tint [Color] which used by [increaseIcon] and [decreaseIcon] that defaults
+ * to [contentColor], unless specifically overridden.
* @param content Content body for the Stepper.
*/
@ExperimentalWearMaterial3Api
@@ -172,18 +170,12 @@
)
}
-/**
- * Defaults used by stepper.
- */
+/** Defaults used by stepper. */
@ExperimentalWearMaterial3Api
object StepperDefaults {
- /**
- * Decrease [ImageVector].
- */
+ /** Decrease [ImageVector]. */
val Decrease = androidx.wear.compose.materialcore.RangeIcons.Minus
- /**
- * Increase [ImageVector].
- */
+ /** Increase [ImageVector]. */
val Increase = Icons.Filled.Add
}
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/SwipeToDismissBox.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/SwipeToDismissBox.kt
index eb16a31..baa5c62 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/SwipeToDismissBox.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/SwipeToDismissBox.kt
@@ -26,7 +26,6 @@
import androidx.wear.compose.foundation.LocalSwipeToDismissContentScrimColor
import androidx.wear.compose.foundation.SwipeToDismissBoxState
import androidx.wear.compose.foundation.SwipeToDismissKeys
-import androidx.wear.compose.foundation.edgeSwipeToDismiss
import androidx.wear.compose.foundation.rememberSwipeToDismissBoxState
/**
@@ -34,9 +33,11 @@
* slot for the background (only displayed during the swipe gesture) and the foreground content.
*
* Example of a [SwipeToDismissBox] with stateful composables:
+ *
* @sample androidx.wear.compose.material3.samples.StatefulSwipeToDismissBox
*
* Example of using [Modifier.edgeSwipeToDismiss] with [SwipeToDismissBox]:
+ *
* @sample androidx.wear.compose.material3.samples.EdgeSwipeForSwipeToDismiss
*
* For more information, see the
@@ -46,21 +47,21 @@
* @param state State containing information about ongoing swipe or animation.
* @param modifier [Modifier] for this component.
* @param backgroundScrimColor [Color] for background scrim.
- * @param contentScrimColor [Color] used for the scrim over the content composable during
- * the swipe gesture.
- * @param backgroundKey [key] which identifies the content currently composed in
- * the [content] block when isBackground == true. Provide the backgroundKey if your background
- * content will be displayed as a foreground after the swipe animation ends
- * (as is common when [SwipeToDismissBox] is used for the navigation). This allows
- * remembered state to be correctly moved between background and foreground.
- * @param contentKey [key] which identifies the content currently composed in the
- * [content] block when isBackground == false. See [backgroundKey].
- * @param userSwipeEnabled Whether the swipe gesture is enabled.
- * (e.g. when there is no background screen, set userSwipeEnabled = false)
- * @param content Slot for content, with the isBackground parameter enabling content to be
- * displayed behind the foreground content - the background is normally hidden, is shown behind a
- * scrim during the swipe gesture, and is shown without scrim once the finger passes the
- * swipe-to-dismiss threshold.
+ * @param contentScrimColor [Color] used for the scrim over the content composable during the swipe
+ * gesture.
+ * @param backgroundKey [key] which identifies the content currently composed in the [content] block
+ * when isBackground == true. Provide the backgroundKey if your background content will be
+ * displayed as a foreground after the swipe animation ends (as is common when [SwipeToDismissBox]
+ * is used for the navigation). This allows remembered state to be correctly moved between
+ * background and foreground.
+ * @param contentKey [key] which identifies the content currently composed in the [content] block
+ * when isBackground == false. See [backgroundKey].
+ * @param userSwipeEnabled Whether the swipe gesture is enabled. (e.g. when there is no background
+ * screen, set userSwipeEnabled = false)
+ * @param content Slot for content, with the isBackground parameter enabling content to be displayed
+ * behind the foreground content - the background is normally hidden, is shown behind a scrim
+ * during the swipe gesture, and is shown without scrim once the finger passes the
+ * swipe-to-dismiss threshold.
*/
@Composable
fun SwipeToDismissBox(
@@ -89,14 +90,16 @@
}
/**
- * Wear Material 3 [SwipeToDismissBox] that handles the swipe-to-dismiss gesture.
- * This overload takes an [onDismissed] parameter which is used to execute a command when the
- * swipe to dismiss has completed, such as navigating to another screen.
+ * Wear Material 3 [SwipeToDismissBox] that handles the swipe-to-dismiss gesture. This overload
+ * takes an [onDismissed] parameter which is used to execute a command when the swipe to dismiss has
+ * completed, such as navigating to another screen.
*
* Example of a simple SwipeToDismissBox:
+ *
* @sample androidx.wear.compose.material3.samples.SimpleSwipeToDismissBox
*
* Example of using [Modifier.edgeSwipeToDismiss] with [SwipeToDismissBox]:
+ *
* @sample androidx.wear.compose.material3.samples.EdgeSwipeForSwipeToDismiss
*
* For more information, see the
@@ -107,21 +110,21 @@
* @param modifier [Modifier] for this component.
* @param state State containing information about ongoing swipe or animation.
* @param backgroundScrimColor [Color] for background scrim.
- * @param contentScrimColor [Color] used for the scrim over the content composable during
- * the swipe gesture.
- * @param backgroundKey [key] which identifies the content currently composed in
- * the [content] block when isBackground == true. Provide the backgroundKey if your background
- * content will be displayed as a foreground after the swipe animation ends
- * (as is common when [SwipeToDismissBox] is used for the navigation). This allows
- * remembered state to be correctly moved between background and foreground.
- * @param contentKey [key] which identifies the content currently composed in the
- * [content] block when isBackground == false. See [backgroundKey].
- * @param userSwipeEnabled Whether the swipe gesture is enabled.
- * (e.g. when there is no background screen, set userSwipeEnabled = false)
- * @param content Slot for content, with the isBackground parameter enabling content to be
- * displayed behind the foreground content - the background is normally hidden, is shown behind a
- * scrim during the swipe gesture, and is shown without scrim once the finger passes the
- * swipe-to-dismiss threshold.
+ * @param contentScrimColor [Color] used for the scrim over the content composable during the swipe
+ * gesture.
+ * @param backgroundKey [key] which identifies the content currently composed in the [content] block
+ * when isBackground == true. Provide the backgroundKey if your background content will be
+ * displayed as a foreground after the swipe animation ends (as is common when [SwipeToDismissBox]
+ * is used for the navigation). This allows remembered state to be correctly moved between
+ * background and foreground.
+ * @param contentKey [key] which identifies the content currently composed in the [content] block
+ * when isBackground == false. See [backgroundKey].
+ * @param userSwipeEnabled Whether the swipe gesture is enabled. (e.g. when there is no background
+ * screen, set userSwipeEnabled = false)
+ * @param content Slot for content, with the isBackground parameter enabling content to be displayed
+ * behind the foreground content - the background is normally hidden, is shown behind a scrim
+ * during the swipe gesture, and is shown without scrim once the finger passes the
+ * swipe-to-dismiss threshold.
*/
@Composable
fun SwipeToDismissBox(
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Text.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Text.kt
index e587e4e..3a02e12 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Text.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Text.kt
@@ -41,16 +41,16 @@
* High level element that displays text and provides semantics / accessibility information.
*
* The default [style] uses the [LocalTextStyle] provided by the [MaterialTheme] / components. If
- * you are setting your own style, you may want to consider first retrieving [LocalTextStyle],
- * and using [TextStyle.copy] to keep any theme defined attributes, only modifying the specific
+ * you are setting your own style, you may want to consider first retrieving [LocalTextStyle], and
+ * using [TextStyle.copy] to keep any theme defined attributes, only modifying the specific
* attributes you want to override.
*
* For ease of use, commonly used parameters from [TextStyle] are also present here. The order of
* precedence is as follows:
- * - If a parameter is explicitly set here (i.e, it is _not_ `null` or [TextUnit.Unspecified]),
- * then this parameter will always be used.
+ * - If a parameter is explicitly set here (i.e, it is _not_ `null` or [TextUnit.Unspecified]), then
+ * this parameter will always be used.
* - If a parameter is _not_ set, (`null` or [TextUnit.Unspecified]), then the corresponding value
- * from [style] will be used instead.
+ * from [style] will be used instead.
*
* Additionally, for [color], if [color] is not set, and [style] does not have a color, then
* [LocalContentColor] will be used.
@@ -58,33 +58,33 @@
* @param text The text to be displayed.
* @param modifier [Modifier] to apply to this layout node.
* @param color [Color] to apply to the text. If [Color.Unspecified], and [style] has no color set,
- * this will be [LocalContentColor].
+ * this will be [LocalContentColor].
* @param fontSize The size of glyphs to use when painting the text. See [TextStyle.fontSize].
- * @param fontStyle The typeface variant to use when drawing the letters (e.g., italic).
- * See [TextStyle.fontStyle].
+ * @param fontStyle The typeface variant to use when drawing the letters (e.g., italic). See
+ * [TextStyle.fontStyle].
* @param fontWeight The typeface thickness to use when painting the text (e.g., [FontWeight.Bold]).
* @param fontFamily The font family to be used when rendering the text. See [TextStyle.fontFamily].
- * @param letterSpacing The amount of space to add between each letter.
- * See [TextStyle.letterSpacing].
- * @param textDecoration The decorations to paint on the text (e.g., an underline).
- * See [TextStyle.textDecoration].
- * @param textAlign The alignment of the text within the lines of the paragraph.
- * See [TextStyle.textAlign].
- * @param lineHeight Line height for the [Paragraph] in [TextUnit] unit, e.g. SP or EM.
- * See [TextStyle.lineHeight].
+ * @param letterSpacing The amount of space to add between each letter. See
+ * [TextStyle.letterSpacing].
+ * @param textDecoration The decorations to paint on the text (e.g., an underline). See
+ * [TextStyle.textDecoration].
+ * @param textAlign The alignment of the text within the lines of the paragraph. See
+ * [TextStyle.textAlign].
+ * @param lineHeight Line height for the [Paragraph] in [TextUnit] unit, e.g. SP or EM. See
+ * [TextStyle.lineHeight].
* @param overflow How visual overflow should be handled.
* @param softWrap Whether the text should break at soft line breaks. If false, the glyphs in the
- * text will be positioned as if there was unlimited horizontal space. If [softWrap] is false,
- * [overflow] and TextAlign may have unexpected effects.
- * @param maxLines An optional maximum number of lines for the text to span, wrapping if
- * necessary. If the text exceeds the given number of lines, it will be truncated according to
- * [overflow] and [softWrap]. If it is not null, then it must be greater than zero.
+ * text will be positioned as if there was unlimited horizontal space. If [softWrap] is false,
+ * [overflow] and TextAlign may have unexpected effects.
+ * @param maxLines An optional maximum number of lines for the text to span, wrapping if necessary.
+ * If the text exceeds the given number of lines, it will be truncated according to [overflow] and
+ * [softWrap]. If it is not null, then it must be greater than zero.
* @param minLines The minimum height in terms of minimum number of visible lines. It is required
- * that 1 <= [minLines] <= [maxLines].
+ * that 1 <= [minLines] <= [maxLines].
* @param onTextLayout Callback that is executed when a new text layout is calculated. A
- * [TextLayoutResult] object that callback provides contains paragraph information, size of the
- * text, baselines and other details. The callback can be used to add additional decoration or
- * functionality to the text. For example, to draw selection around the text.
+ * [TextLayoutResult] object that callback provides contains paragraph information, size of the
+ * text, baselines and other details. The callback can be used to add additional decoration or
+ * functionality to the text. For example, to draw selection around the text.
* @param style Style configuration for the text such as color, font, line height etc.
*/
@Composable
@@ -133,16 +133,16 @@
* High level element that displays text and provides semantics / accessibility information.
*
* The default [style] uses the [LocalTextStyle] provided by the [MaterialTheme] / components. If
- * you are setting your own style, you may want to consider first retrieving [LocalTextStyle],
- * and using [TextStyle.copy] to keep any theme defined attributes, only modifying the specific
+ * you are setting your own style, you may want to consider first retrieving [LocalTextStyle], and
+ * using [TextStyle.copy] to keep any theme defined attributes, only modifying the specific
* attributes you want to override.
*
* For ease of use, commonly used parameters from [TextStyle] are also present here. The order of
* precedence is as follows:
- * - If a parameter is explicitly set here (i.e, it is _not_ `null` or [TextUnit.Unspecified]),
- * then this parameter will always be used.
+ * - If a parameter is explicitly set here (i.e, it is _not_ `null` or [TextUnit.Unspecified]), then
+ * this parameter will always be used.
* - If a parameter is _not_ set, (`null` or [TextUnit.Unspecified]), then the corresponding value
- * from [style] will be used instead.
+ * from [style] will be used instead.
*
* Additionally, for [color], if [color] is not set, and [style] does not have a color, then
* [LocalContentColor] will be used.
@@ -150,35 +150,35 @@
* @param text The text to be displayed, where [AnnotatedString] allows multiple styles to be used.
* @param modifier [Modifier] to apply to this layout node.
* @param color [Color] to apply to the text. If [Color.Unspecified], and [style] has no color set,
- * this will be [LocalContentColor].
+ * this will be [LocalContentColor].
* @param fontSize The size of glyphs to use when painting the text. See [TextStyle.fontSize].
- * @param fontStyle The typeface variant to use when drawing the letters (e.g., italic).
- * See [TextStyle.fontStyle].
+ * @param fontStyle The typeface variant to use when drawing the letters (e.g., italic). See
+ * [TextStyle.fontStyle].
* @param fontWeight The typeface thickness to use when painting the text (e.g., [FontWeight.Bold]).
* @param fontFamily The font family to be used when rendering the text. See [TextStyle.fontFamily].
- * @param letterSpacing The amount of space to add between each letter.
- * See [TextStyle.letterSpacing].
- * @param textDecoration The decorations to paint on the text (e.g., an underline).
- * See [TextStyle.textDecoration].
- * @param textAlign The alignment of the text within the lines of the paragraph.
- * See [TextStyle.textAlign].
- * @param lineHeight Line height for the [Paragraph] in [TextUnit] unit, e.g. SP or EM.
- * See [TextStyle.lineHeight].
+ * @param letterSpacing The amount of space to add between each letter. See
+ * [TextStyle.letterSpacing].
+ * @param textDecoration The decorations to paint on the text (e.g., an underline). See
+ * [TextStyle.textDecoration].
+ * @param textAlign The alignment of the text within the lines of the paragraph. See
+ * [TextStyle.textAlign].
+ * @param lineHeight Line height for the [Paragraph] in [TextUnit] unit, e.g. SP or EM. See
+ * [TextStyle.lineHeight].
* @param overflow How visual overflow should be handled.
* @param softWrap Whether the text should break at soft line breaks. If false, the glyphs in the
- * text will be positioned as if there was unlimited horizontal space. If [softWrap] is false,
- * [overflow] and TextAlign may have unexpected effects.
- * @param maxLines An optional maximum number of lines for the text to span, wrapping if
- * necessary. If the text exceeds the given number of lines, it will be truncated according to
- * [overflow] and [softWrap]. If it is not null, then it must be greater than zero.
+ * text will be positioned as if there was unlimited horizontal space. If [softWrap] is false,
+ * [overflow] and TextAlign may have unexpected effects.
+ * @param maxLines An optional maximum number of lines for the text to span, wrapping if necessary.
+ * If the text exceeds the given number of lines, it will be truncated according to [overflow] and
+ * [softWrap]. If it is not null, then it must be greater than zero.
* @param minLines The minimum height in terms of minimum number of visible lines. It is required
- * that 1 <= [minLines] <= [maxLines].
- * @param inlineContent A map store composables that replaces certain ranges of the text. It's
- * used to insert composables into text layout. Check [InlineTextContent] for more information.
+ * that 1 <= [minLines] <= [maxLines].
+ * @param inlineContent A map store composables that replaces certain ranges of the text. It's used
+ * to insert composables into text layout. Check [InlineTextContent] for more information.
* @param onTextLayout Callback that is executed when a new text layout is calculated. A
- * [TextLayoutResult] object that callback provides contains paragraph information, size of the
- * text, baselines and other details. The callback can be used to add additional decoration or
- * functionality to the text. For example, to draw selection around the text.
+ * [TextLayoutResult] object that callback provides contains paragraph information, size of the
+ * text, baselines and other details. The callback can be used to add additional decoration or
+ * functionality to the text. For example, to draw selection around the text.
* @param style Style configuration for the text such as color, font, line height etc.
*/
@Composable
@@ -202,11 +202,7 @@
onTextLayout: (TextLayoutResult) -> Unit = {},
style: TextStyle = LocalTextStyle.current
) {
- val textColor = color.takeOrElse {
- style.color.takeOrElse {
- LocalContentColor.current
- }
- }
+ val textColor = color.takeOrElse { style.color.takeOrElse { LocalContentColor.current } }
androidx.wear.compose.materialcore.Text(
text = text,
@@ -241,9 +237,9 @@
compositionLocalOf(structuralEqualityPolicy()) { DefaultTextStyle }
/**
- * This function is used to set the current value of [LocalTextStyle], merging the given style
- * with the current style values for any missing attributes. Any [Text] components included in
- * this component's [content] will be styled with this style unless styled explicitly.
+ * This function is used to set the current value of [LocalTextStyle], merging the given style with
+ * the current style values for any missing attributes. Any [Text] components included in this
+ * component's [content] will be styled with this style unless styled explicitly.
*
* @see LocalTextStyle
*/
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/TextButton.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/TextButton.kt
index 6a94211..1cd57f9 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/TextButton.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/TextButton.kt
@@ -35,50 +35,49 @@
import androidx.wear.compose.material3.tokens.TextToggleButtonTokens
/**
- * Wear Material [TextButton] is a circular, text-only button with transparent background and
- * no border. It offers a single slot for text.
+ * Wear Material [TextButton] is a circular, text-only button with transparent background and no
+ * border. It offers a single slot for text.
*
- * Set the size of the [TextButton] with [Modifier.touchTargetAwareSize]
- * to ensure that the recommended minimum touch target size is available. The recommended
- * [TextButton] sizes are [TextButtonDefaults.DefaultButtonSize],
- * [TextButtonDefaults.LargeButtonSize] and [TextButtonDefaults.SmallButtonSize].
- * The recommended text styles for each corresponding button size are
- * [TextButtonDefaults.defaultButtonTextStyle], [TextButtonDefaults.largeButtonTextStyle] and
- * [TextButtonDefaults.smallButtonTextStyle].
+ * Set the size of the [TextButton] with [Modifier.touchTargetAwareSize] to ensure that the
+ * recommended minimum touch target size is available. The recommended [TextButton] sizes are
+ * [TextButtonDefaults.DefaultButtonSize], [TextButtonDefaults.LargeButtonSize] and
+ * [TextButtonDefaults.SmallButtonSize]. The recommended text styles for each corresponding button
+ * size are [TextButtonDefaults.defaultButtonTextStyle], [TextButtonDefaults.largeButtonTextStyle]
+ * and [TextButtonDefaults.smallButtonTextStyle].
*
- * The default [TextButton] has no border and a transparent background for low emphasis actions.
- * For actions that require high emphasis, set [colors] to
- * [TextButtonDefaults.filledTextButtonColors].
+ * The default [TextButton] has no border and a transparent background for low emphasis actions. For
+ * actions that require high emphasis, set [colors] to [TextButtonDefaults.filledTextButtonColors].
* For a medium-emphasis, outlined [TextButton], set [border] to
- * [ButtonDefaults.outlinedButtonBorder].
- * For a middle ground between outlined and filled, set [colors] to
- * [TextButtonDefaults.filledTonalTextButtonColors].
+ * [ButtonDefaults.outlinedButtonBorder]. For a middle ground between outlined and filled, set
+ * [colors] to [TextButtonDefaults.filledTonalTextButtonColors].
*
* [TextButton] can be enabled or disabled. A disabled button will not respond to click events.
*
- * TODO(b/261838497) Add Material3 UX guidance links
- *
* Example of a [TextButton]:
+ *
* @sample androidx.wear.compose.material3.samples.TextButtonSample
*
* Example of a large, filled tonal [TextButton]:
+ *
* @sample androidx.wear.compose.material3.samples.LargeFilledTonalTextButtonSample
*
* @param onClick Will be called when the user clicks the button.
* @param modifier Modifier to be applied to the button.
- * @param enabled Controls the enabled state of the button. When `false`, this button will not
- * be clickable.
- * @param shape Defines the text button's shape. It is strongly recommended to use the default
- * as this shape is a key characteristic of the Wear Material3 Theme.
+ * @param enabled Controls the enabled state of the button. When `false`, this button will not be
+ * clickable.
+ * @param shape Defines the text button's shape. It is strongly recommended to use the default as
+ * this shape is a key characteristic of the Wear Material3 Theme.
* @param colors [TextButtonColors] that will be used to resolve the background and content color
- * for this button in different states.
+ * for this button in different states.
* @param border Optional [BorderStroke] that will be used to resolve the text button border in
- * different states. See [ButtonDefaults.outlinedButtonBorder].
+ * different states. See [ButtonDefaults.outlinedButtonBorder].
* @param interactionSource an optional hoisted [MutableInteractionSource] for observing and
- * emitting [Interaction]s for this button. You can use this to change the button's appearance
- * or preview the button in different states. Note that if `null` is provided, interactions will
- * still happen internally.
+ * emitting [Interaction]s for this button. You can use this to change the button's appearance or
+ * preview the button in different states. Note that if `null` is provided, interactions will
+ * still happen internally.
* @param content The content displayed on the text button, expected to be text or image.
+ *
+ * TODO(b/261838497) Add Material3 UX guidance links
*/
@Composable
fun TextButton(
@@ -101,49 +100,50 @@
border = { border },
buttonSize = TextButtonDefaults.DefaultButtonSize,
ripple = rippleOrFallbackImplementation(),
- content = provideScopeContent(
- colors.contentColor(enabled = enabled),
- TextButtonTokens.ContentFont.value,
- content
- )
+ content =
+ provideScopeContent(
+ colors.contentColor(enabled = enabled),
+ TextButtonTokens.ContentFont.value,
+ content
+ )
)
}
/**
* Wear Material [TextToggleButton] is a filled text toggle button which switches between primary
- * colors and tonal colors depending on [checked] value, and offers a single slot for
- * text.
+ * colors and tonal colors depending on [checked] value, and offers a single slot for text.
*
- * Set the size of the [TextToggleButton] with Modifier.[touchTargetAwareSize]
- * to ensure that the background padding will correctly reach the edge of the minimum touch target.
- * The recommended [TextToggleButton] sizes are [TextButtonDefaults.DefaultButtonSize],
- * [TextButtonDefaults.LargeButtonSize] and [TextButtonDefaults.SmallButtonSize].
- * The recommended text styles for each corresponding button size are
- * [TextButtonDefaults.defaultButtonTextStyle], [TextButtonDefaults.largeButtonTextStyle] and
- * [TextButtonDefaults.smallButtonTextStyle].
+ * Set the size of the [TextToggleButton] with Modifier.[touchTargetAwareSize] to ensure that the
+ * background padding will correctly reach the edge of the minimum touch target. The recommended
+ * [TextToggleButton] sizes are [TextButtonDefaults.DefaultButtonSize],
+ * [TextButtonDefaults.LargeButtonSize] and [TextButtonDefaults.SmallButtonSize]. The recommended
+ * text styles for each corresponding button size are [TextButtonDefaults.defaultButtonTextStyle],
+ * [TextButtonDefaults.largeButtonTextStyle] and [TextButtonDefaults.smallButtonTextStyle].
*
- * [TextToggleButton] can be enabled or disabled. A disabled button will not respond to
- * click events. When enabled, the checked and unchecked events are propagated by [onCheckedChange].
+ * [TextToggleButton] can be enabled or disabled. A disabled button will not respond to click
+ * events. When enabled, the checked and unchecked events are propagated by [onCheckedChange].
*
* A simple text toggle button using the default colors:
+ *
* @sample androidx.wear.compose.material3.samples.TextToggleButtonSample
*
* Example of a large text toggle button:
+ *
* @sample androidx.wear.compose.material3.samples.LargeTextToggleButtonSample
*
* @param checked Boolean flag indicating whether this toggle button is currently checked.
* @param onCheckedChange Callback to be invoked when this toggle button is clicked.
* @param modifier Modifier to be applied to the toggle button.
- * @param enabled Controls the enabled state of the toggle button. When `false`,
- * this toggle button will not be clickable.
- * @param colors [ToggleButtonColors] that will be used to resolve the container and
- * content color for this toggle button.
+ * @param enabled Controls the enabled state of the toggle button. When `false`, this toggle button
+ * will not be clickable.
+ * @param colors [ToggleButtonColors] that will be used to resolve the container and content color
+ * for this toggle button.
* @param interactionSource an optional hoisted [MutableInteractionSource] for observing and
- * emitting [Interaction]s for this toggle button. You can use this to change the toggle button's
- * appearance or preview the toggle button in different states. Note that if `null` is provided,
- * interactions will still happen internally.
+ * emitting [Interaction]s for this toggle button. You can use this to change the toggle button's
+ * appearance or preview the toggle button in different states. Note that if `null` is provided,
+ * interactions will still happen internally.
* @param shape Defines the shape for this toggle button. It is strongly recommended to use the
- * default as this shape is a key characteristic of the Wear Material 3 Theme.
+ * default as this shape is a key characteristic of the Wear Material 3 Theme.
* @param border Optional [BorderStroke] for the [TextToggleButton].
* @param content The text to be drawn inside the toggle button.
*/
@@ -172,39 +172,36 @@
interactionSource = interactionSource,
shape = shape,
ripple = rippleOrFallbackImplementation(),
- content = provideScopeContent(
- colors.contentColor(enabled = enabled, checked = checked),
- TextToggleButtonTokens.ContentFont.value,
- content
- )
+ content =
+ provideScopeContent(
+ colors.contentColor(enabled = enabled, checked = checked),
+ TextToggleButtonTokens.ContentFont.value,
+ content
+ )
)
}
-/**
- * Contains the default values used by [TextButton].
- */
+/** Contains the default values used by [TextButton]. */
object TextButtonDefaults {
- /**
- * Recommended [Shape] for [TextButton].
- */
- val shape: Shape @Composable get() = TextButtonTokens.ContainerShape.value
+ /** Recommended [Shape] for [TextButton]. */
+ val shape: Shape
+ @Composable get() = TextButtonTokens.ContainerShape.value
/**
- * Creates a [TextButtonColors] with the colors for a filled [TextButton]- by default, a
- * colored background with a contrasting content color.
- * If the text button is disabled then the colors will default to [ColorScheme.onSurface] with
- * suitable alpha values applied.
+ * Creates a [TextButtonColors] with the colors for a filled [TextButton]- by default, a colored
+ * background with a contrasting content color. If the text button is disabled then the colors
+ * will default to [ColorScheme.onSurface] with suitable alpha values applied.
*/
@Composable
fun filledTextButtonColors() = MaterialTheme.colorScheme.defaultFilledTextButtonColors
/**
- * Creates a [TextButtonColors] with the colors for a filled [TextButton]- by default, a
- * colored background with a contrasting content color.
- * If the text button is disabled then the colors will default to [ColorScheme.onSurface] with
- * suitable alpha values applied.
+ * Creates a [TextButtonColors] with the colors for a filled [TextButton]- by default, a colored
+ * background with a contrasting content color. If the text button is disabled then the colors
+ * will default to [ColorScheme.onSurface] with suitable alpha values applied.
*
* Example of [TextButton] with [filledTextButtonColors]:
+ *
* @sample androidx.wear.compose.material3.samples.FilledTextButtonSample
*
* @param containerColor The background color of this text button when enabled
@@ -218,29 +215,29 @@
contentColor: Color = Color.Unspecified,
disabledContainerColor: Color = Color.Unspecified,
disabledContentColor: Color = Color.Unspecified,
- ): TextButtonColors = MaterialTheme.colorScheme.defaultFilledTextButtonColors.copy(
- containerColor = containerColor,
- contentColor = contentColor,
- disabledContainerColor = disabledContainerColor,
- disabledContentColor = disabledContentColor
- )
+ ): TextButtonColors =
+ MaterialTheme.colorScheme.defaultFilledTextButtonColors.copy(
+ containerColor = containerColor,
+ contentColor = contentColor,
+ disabledContainerColor = disabledContainerColor,
+ disabledContentColor = disabledContentColor
+ )
/**
- * Creates a [TextButtonColors] with the colors for a filled, tonal [TextButton]- by default,
- * a muted colored background with a contrasting content color.
- * If the text button is disabled then the colors will default to [ColorScheme.onSurface] with
- * suitable alpha values applied.
+ * Creates a [TextButtonColors] with the colors for a filled, tonal [TextButton]- by default, a
+ * muted colored background with a contrasting content color. If the text button is disabled
+ * then the colors will default to [ColorScheme.onSurface] with suitable alpha values applied.
*/
@Composable
fun filledTonalTextButtonColors() = MaterialTheme.colorScheme.defaultFilledTonalTextButtonColors
/**
- * Creates a [TextButtonColors] with the colors for a filled, tonal [TextButton]- by default,
- * a muted colored background with a contrasting content color.
- * If the text button is disabled then the colors will default to [ColorScheme.onSurface] with
- * suitable alpha values applied.
+ * Creates a [TextButtonColors] with the colors for a filled, tonal [TextButton]- by default, a
+ * muted colored background with a contrasting content color. If the text button is disabled
+ * then the colors will default to [ColorScheme.onSurface] with suitable alpha values applied.
*
* Example of [TextButton] with [filledTonalTextButtonColors]:
+ *
* @sample androidx.wear.compose.material3.samples.FilledTonalTextButtonSample
*
* @param containerColor The background color of this text button when enabled
@@ -254,28 +251,30 @@
contentColor: Color = Color.Unspecified,
disabledContainerColor: Color = Color.Unspecified,
disabledContentColor: Color = Color.Unspecified,
- ): TextButtonColors = MaterialTheme.colorScheme.defaultFilledTextButtonColors.copy(
- containerColor = containerColor,
- contentColor = contentColor,
- disabledContainerColor = disabledContainerColor,
- disabledContentColor = disabledContentColor
- )
+ ): TextButtonColors =
+ MaterialTheme.colorScheme.defaultFilledTextButtonColors.copy(
+ containerColor = containerColor,
+ contentColor = contentColor,
+ disabledContainerColor = disabledContainerColor,
+ disabledContentColor = disabledContentColor
+ )
/**
- * Creates a [TextButtonColors] with the colors for an outlined [TextButton]- by default,
- * a transparent background with contrasting content color. If the button is disabled,
- * then the colors will default to [ColorScheme.onSurface] with suitable alpha values applied.
+ * Creates a [TextButtonColors] with the colors for an outlined [TextButton]- by default, a
+ * transparent background with contrasting content color. If the button is disabled, then the
+ * colors will default to [ColorScheme.onSurface] with suitable alpha values applied.
*/
@Composable
fun outlinedTextButtonColors() = MaterialTheme.colorScheme.defaultOutlinedTextButtonColors
/**
- * Creates a [TextButtonColors] with the colors for an outlined [TextButton]- by default,
- * a transparent background with contrasting content color. If the button is disabled,
- * then the colors will default to [ColorScheme.onSurface] with suitable alpha values applied.
+ * Creates a [TextButtonColors] with the colors for an outlined [TextButton]- by default, a
+ * transparent background with contrasting content color. If the button is disabled, then the
+ * colors will default to [ColorScheme.onSurface] with suitable alpha values applied.
*
* Example of [TextButton] with [outlinedTextButtonColors] and
* [ButtonDefaults.outlinedButtonBorder]:
+ *
* @sample androidx.wear.compose.material3.samples.OutlinedTextButtonSample
*
* @param contentColor The content color of this text button when enabled
@@ -285,25 +284,25 @@
fun outlinedTextButtonColors(
contentColor: Color = Color.Unspecified,
disabledContentColor: Color = Color.Unspecified,
- ): TextButtonColors = MaterialTheme.colorScheme.defaultOutlinedTextButtonColors.copy(
- containerColor = Color.Transparent,
- contentColor = contentColor,
- disabledContainerColor = Color.Transparent,
- disabledContentColor = disabledContentColor
- )
+ ): TextButtonColors =
+ MaterialTheme.colorScheme.defaultOutlinedTextButtonColors.copy(
+ containerColor = Color.Transparent,
+ contentColor = contentColor,
+ disabledContainerColor = Color.Transparent,
+ disabledContentColor = disabledContentColor
+ )
/**
- * Creates a [TextButtonColors] for a text button - by default, a transparent
- * background with contrasting content color. If the button is disabled
- * then the colors default to [ColorScheme.onSurface] with suitable alpha values applied.
+ * Creates a [TextButtonColors] for a text button - by default, a transparent background with
+ * contrasting content color. If the button is disabled then the colors default to
+ * [ColorScheme.onSurface] with suitable alpha values applied.
*/
- @Composable
- fun textButtonColors() = MaterialTheme.colorScheme.defaultTextButtonColors
+ @Composable fun textButtonColors() = MaterialTheme.colorScheme.defaultTextButtonColors
/**
- * Creates a [TextButtonColors] for a text button - by default, a transparent
- * background with contrasting content color. If the button is disabled
- * then the colors default to [ColorScheme.onSurface] with suitable alpha values applied.
+ * Creates a [TextButtonColors] for a text button - by default, a transparent background with
+ * contrasting content color. If the button is disabled then the colors default to
+ * [ColorScheme.onSurface] with suitable alpha values applied.
*
* @param containerColor the background color of this text button when enabled
* @param contentColor the content color of this text button when enabled
@@ -316,44 +315,45 @@
contentColor: Color = Color.Unspecified,
disabledContainerColor: Color = Color.Transparent,
disabledContentColor: Color = Color.Unspecified,
- ): TextButtonColors = MaterialTheme.colorScheme.defaultTextButtonColors.copy(
- containerColor = containerColor,
- contentColor = contentColor,
- disabledContainerColor = disabledContainerColor,
- disabledContentColor = disabledContentColor,
- )
+ ): TextButtonColors =
+ MaterialTheme.colorScheme.defaultTextButtonColors.copy(
+ containerColor = containerColor,
+ contentColor = contentColor,
+ disabledContainerColor = disabledContainerColor,
+ disabledContentColor = disabledContentColor,
+ )
/**
* Creates a [ToggleButtonColors] for a [TextToggleButton]
- * - by default, a colored background with a contrasting content color.
- * If the button is disabled, then the colors will have an alpha ([DisabledContainerAlpha]
- * or [DisabledContentAlpha]) value applied.
+ * - by default, a colored background with a contrasting content color. If the button is
+ * disabled, then the colors will have an alpha ([DisabledContainerAlpha] or
+ * [DisabledContentAlpha]) value applied.
*/
@Composable
fun textToggleButtonColors() = MaterialTheme.colorScheme.defaultTextToggleButtonColors
/**
* Creates a [ToggleButtonColors] for a [TextToggleButton]
- * - by default, a colored background with a contrasting content color.
- * If the button is disabled, then the colors will have an alpha ([DisabledContainerAlpha]
- * or [DisabledContentAlpha]) value applied.
+ * - by default, a colored background with a contrasting content color. If the button is
+ * disabled, then the colors will have an alpha ([DisabledContainerAlpha] or
+ * [DisabledContentAlpha]) value applied.
*
- * @param checkedContainerColor the container color of this [TextToggleButton] when enabled
- * and checked
+ * @param checkedContainerColor the container color of this [TextToggleButton] when enabled and
+ * checked
* @param checkedContentColor the content color of this [TextToggleButton] when enabled and
- * checked
+ * checked
* @param uncheckedContainerColor the container color of this [TextToggleButton] when enabled
- * and unchecked
+ * and unchecked
* @param uncheckedContentColor the content color of this [TextToggleButton] when enabled and
- * unchecked
+ * unchecked
* @param disabledCheckedContainerColor the container color of this [TextToggleButton] when
- * checked and not enabled
+ * checked and not enabled
* @param disabledCheckedContentColor the content color of this [TextToggleButton] when checked
- * and not enabled
+ * and not enabled
* @param disabledUncheckedContainerColor the container color of this [TextToggleButton] when
- * unchecked and not enabled
+ * unchecked and not enabled
* @param disabledUncheckedContentColor the content color of this [TextToggleButton] when
- * unchecked and not enabled
+ * unchecked and not enabled
*/
@Composable
fun textToggleButtonColors(
@@ -365,133 +365,159 @@
disabledCheckedContentColor: Color = Color.Unspecified,
disabledUncheckedContainerColor: Color = Color.Unspecified,
disabledUncheckedContentColor: Color = Color.Unspecified,
- ): ToggleButtonColors = MaterialTheme.colorScheme.defaultTextToggleButtonColors.copy(
- checkedContainerColor = checkedContainerColor,
- checkedContentColor = checkedContentColor,
- uncheckedContainerColor = uncheckedContainerColor,
- uncheckedContentColor = uncheckedContentColor,
- disabledCheckedContainerColor = disabledCheckedContainerColor,
- disabledCheckedContentColor = disabledCheckedContentColor,
- disabledUncheckedContainerColor = disabledUncheckedContainerColor,
- disabledUncheckedContentColor = disabledUncheckedContentColor,
- )
+ ): ToggleButtonColors =
+ MaterialTheme.colorScheme.defaultTextToggleButtonColors.copy(
+ checkedContainerColor = checkedContainerColor,
+ checkedContentColor = checkedContentColor,
+ uncheckedContainerColor = uncheckedContainerColor,
+ uncheckedContentColor = uncheckedContentColor,
+ disabledCheckedContainerColor = disabledCheckedContainerColor,
+ disabledCheckedContentColor = disabledCheckedContentColor,
+ disabledUncheckedContainerColor = disabledUncheckedContainerColor,
+ disabledUncheckedContentColor = disabledUncheckedContentColor,
+ )
/**
- * The recommended size for a small button.
- * It is recommended to apply this size using [Modifier.touchTargetAwareSize].
+ * The recommended size for a small button. It is recommended to apply this size using
+ * [Modifier.touchTargetAwareSize].
*/
val SmallButtonSize = TextButtonTokens.ContainerSmallSize
/**
- * The default size applied for buttons.
- * It is recommended to apply this size using [Modifier.touchTargetAwareSize].
+ * The default size applied for buttons. It is recommended to apply this size using
+ * [Modifier.touchTargetAwareSize].
*/
val DefaultButtonSize = TextButtonTokens.ContainerDefaultSize
/**
- * The recommended size for a large button.
- * It is recommended to apply this size using [Modifier.touchTargetAwareSize].
+ * The recommended size for a large button. It is recommended to apply this size using
+ * [Modifier.touchTargetAwareSize].
*/
val LargeButtonSize = TextButtonTokens.ContainerLargeSize
/** The recommended text style for a small button. */
val smallButtonTextStyle
- @ReadOnlyComposable
- @Composable
- get() = MaterialTheme.typography.labelMedium
+ @ReadOnlyComposable @Composable get() = MaterialTheme.typography.labelMedium
/** The default text style applied for buttons. */
val defaultButtonTextStyle
- @ReadOnlyComposable
- @Composable
- get() = MaterialTheme.typography.labelMedium
+ @ReadOnlyComposable @Composable get() = MaterialTheme.typography.labelMedium
/** The recommended text style for a large button. */
val largeButtonTextStyle
- @ReadOnlyComposable
- @Composable
- get() = MaterialTheme.typography.labelLarge
+ @ReadOnlyComposable @Composable get() = MaterialTheme.typography.labelLarge
private val ColorScheme.defaultFilledTextButtonColors: TextButtonColors
get() {
- return defaultFilledTextButtonColorsCached ?: TextButtonColors(
- containerColor = fromToken(FilledTextButtonTokens.ContainerColor),
- contentColor = fromToken(FilledTextButtonTokens.ContentColor),
- disabledContainerColor = fromToken(FilledTextButtonTokens.DisabledContainerColor)
- .toDisabledColor(
- disabledAlpha = FilledTextButtonTokens.DisabledContainerOpacity
- ),
- disabledContentColor = fromToken(FilledTextButtonTokens.DisabledContentColor)
- .toDisabledColor(disabledAlpha = FilledTextButtonTokens.DisabledContentOpacity)
- ).also { defaultFilledTextButtonColorsCached = it }
+ return defaultFilledTextButtonColorsCached
+ ?: TextButtonColors(
+ containerColor = fromToken(FilledTextButtonTokens.ContainerColor),
+ contentColor = fromToken(FilledTextButtonTokens.ContentColor),
+ disabledContainerColor =
+ fromToken(FilledTextButtonTokens.DisabledContainerColor)
+ .toDisabledColor(
+ disabledAlpha = FilledTextButtonTokens.DisabledContainerOpacity
+ ),
+ disabledContentColor =
+ fromToken(FilledTextButtonTokens.DisabledContentColor)
+ .toDisabledColor(
+ disabledAlpha = FilledTextButtonTokens.DisabledContentOpacity
+ )
+ )
+ .also { defaultFilledTextButtonColorsCached = it }
}
private val ColorScheme.defaultFilledTonalTextButtonColors: TextButtonColors
get() {
- return defaultFilledTonalTextButtonColorsCached ?: TextButtonColors(
- containerColor = fromToken(FilledTonalTextButtonTokens.ContainerColor),
- contentColor = fromToken(FilledTonalTextButtonTokens.ContentColor),
- disabledContainerColor =
- fromToken(FilledTonalTextButtonTokens.DisabledContainerColor).toDisabledColor(
- disabledAlpha = FilledTonalTextButtonTokens.DisabledContainerOpacity
- ),
- disabledContentColor = fromToken(FilledTonalTextButtonTokens.DisabledContentColor)
- .toDisabledColor(
- disabledAlpha = FilledTonalTextButtonTokens.DisabledContentOpacity
+ return defaultFilledTonalTextButtonColorsCached
+ ?: TextButtonColors(
+ containerColor = fromToken(FilledTonalTextButtonTokens.ContainerColor),
+ contentColor = fromToken(FilledTonalTextButtonTokens.ContentColor),
+ disabledContainerColor =
+ fromToken(FilledTonalTextButtonTokens.DisabledContainerColor)
+ .toDisabledColor(
+ disabledAlpha =
+ FilledTonalTextButtonTokens.DisabledContainerOpacity
+ ),
+ disabledContentColor =
+ fromToken(FilledTonalTextButtonTokens.DisabledContentColor)
+ .toDisabledColor(
+ disabledAlpha =
+ FilledTonalTextButtonTokens.DisabledContentOpacity
+ )
)
- ).also { defaultFilledTonalTextButtonColorsCached = it }
+ .also { defaultFilledTonalTextButtonColorsCached = it }
}
private val ColorScheme.defaultOutlinedTextButtonColors: TextButtonColors
get() {
- return defaultOutlinedTextButtonColorsCached ?: TextButtonColors(
- containerColor = Color.Transparent,
- contentColor = fromToken(OutlinedTextButtonTokens.ContentColor),
- disabledContainerColor = Color.Transparent,
- disabledContentColor = fromToken(OutlinedTextButtonTokens.DisabledContentColor)
- .toDisabledColor(
- disabledAlpha = OutlinedTextButtonTokens.DisabledContentOpacity
+ return defaultOutlinedTextButtonColorsCached
+ ?: TextButtonColors(
+ containerColor = Color.Transparent,
+ contentColor = fromToken(OutlinedTextButtonTokens.ContentColor),
+ disabledContainerColor = Color.Transparent,
+ disabledContentColor =
+ fromToken(OutlinedTextButtonTokens.DisabledContentColor)
+ .toDisabledColor(
+ disabledAlpha = OutlinedTextButtonTokens.DisabledContentOpacity
+ )
)
- ).also { defaultOutlinedTextButtonColorsCached = it }
+ .also { defaultOutlinedTextButtonColorsCached = it }
}
private val ColorScheme.defaultTextButtonColors: TextButtonColors
get() {
- return defaultTextButtonColorsCached ?: TextButtonColors(
- containerColor = Color.Transparent,
- contentColor = fromToken(TextButtonTokens.ContentColor),
- disabledContainerColor = Color.Transparent,
- disabledContentColor = fromToken(TextButtonTokens.DisabledContentColor)
- .toDisabledColor(disabledAlpha = TextButtonTokens.DisabledContentOpacity)
- ).also { defaultTextButtonColorsCached = it }
+ return defaultTextButtonColorsCached
+ ?: TextButtonColors(
+ containerColor = Color.Transparent,
+ contentColor = fromToken(TextButtonTokens.ContentColor),
+ disabledContainerColor = Color.Transparent,
+ disabledContentColor =
+ fromToken(TextButtonTokens.DisabledContentColor)
+ .toDisabledColor(
+ disabledAlpha = TextButtonTokens.DisabledContentOpacity
+ )
+ )
+ .also { defaultTextButtonColorsCached = it }
}
private val ColorScheme.defaultTextToggleButtonColors: ToggleButtonColors
get() {
- return defaultTextToggleButtonColorsCached ?: ToggleButtonColors(
- checkedContainerColor = fromToken(TextToggleButtonTokens.CheckedContainerColor),
- checkedContentColor = fromToken(TextToggleButtonTokens.CheckedContentColor),
- uncheckedContainerColor = fromToken(TextToggleButtonTokens.UncheckedContainerColor),
- uncheckedContentColor = fromToken(TextToggleButtonTokens.UncheckedContentColor),
- disabledCheckedContainerColor =
- fromToken(TextToggleButtonTokens.DisabledCheckedContainerColor).toDisabledColor(
- disabledAlpha = TextToggleButtonTokens.DisabledCheckedContainerOpacity
- ),
- disabledCheckedContentColor =
- fromToken(TextToggleButtonTokens.DisabledCheckedContentColor).toDisabledColor(
- disabledAlpha = TextToggleButtonTokens.DisabledCheckedContentOpacity
- ),
- disabledUncheckedContainerColor =
- fromToken(TextToggleButtonTokens.DisabledUncheckedContainerColor)
- .toDisabledColor(
- disabledAlpha = TextToggleButtonTokens.DisabledUncheckedContainerOpacity
- ),
- disabledUncheckedContentColor =
- fromToken(TextToggleButtonTokens.DisabledUncheckedContentColor)
- .toDisabledColor(
- disabledAlpha = TextToggleButtonTokens.DisabledUncheckedContentOpacity
- ),
- ).also { defaultTextToggleButtonColorsCached = it }
+ return defaultTextToggleButtonColorsCached
+ ?: ToggleButtonColors(
+ checkedContainerColor =
+ fromToken(TextToggleButtonTokens.CheckedContainerColor),
+ checkedContentColor = fromToken(TextToggleButtonTokens.CheckedContentColor),
+ uncheckedContainerColor =
+ fromToken(TextToggleButtonTokens.UncheckedContainerColor),
+ uncheckedContentColor =
+ fromToken(TextToggleButtonTokens.UncheckedContentColor),
+ disabledCheckedContainerColor =
+ fromToken(TextToggleButtonTokens.DisabledCheckedContainerColor)
+ .toDisabledColor(
+ disabledAlpha =
+ TextToggleButtonTokens.DisabledCheckedContainerOpacity
+ ),
+ disabledCheckedContentColor =
+ fromToken(TextToggleButtonTokens.DisabledCheckedContentColor)
+ .toDisabledColor(
+ disabledAlpha =
+ TextToggleButtonTokens.DisabledCheckedContentOpacity
+ ),
+ disabledUncheckedContainerColor =
+ fromToken(TextToggleButtonTokens.DisabledUncheckedContainerColor)
+ .toDisabledColor(
+ disabledAlpha =
+ TextToggleButtonTokens.DisabledUncheckedContainerOpacity
+ ),
+ disabledUncheckedContentColor =
+ fromToken(TextToggleButtonTokens.DisabledUncheckedContentColor)
+ .toDisabledColor(
+ disabledAlpha =
+ TextToggleButtonTokens.DisabledUncheckedContentOpacity
+ ),
+ )
+ .also { defaultTextToggleButtonColorsCached = it }
}
}
@@ -500,8 +526,8 @@
*
* See [TextButtonDefaults.filledTextButtonColors],
* [TextButtonDefaults.filledTonalTextButtonColors], [TextButtonDefaults.textButtonColors] and
- * [TextButtonDefaults.outlinedTextButtonColors] for [TextButtonColors] with different levels
- * of emphasis.
+ * [TextButtonDefaults.outlinedTextButtonColors] for [TextButtonColors] with different levels of
+ * emphasis.
*
* @param containerColor the background color of this text button when enabled.
* @param contentColor the content color of this text button when enabled.
@@ -521,12 +547,14 @@
contentColor: Color,
disabledContainerColor: Color,
disabledContentColor: Color
- ) = TextButtonColors(
- containerColor = containerColor.takeOrElse { this.containerColor },
- contentColor = contentColor.takeOrElse { this.contentColor },
- disabledContainerColor = disabledContainerColor.takeOrElse { this.disabledContainerColor },
- disabledContentColor = disabledContentColor.takeOrElse { this.disabledContentColor }
- )
+ ) =
+ TextButtonColors(
+ containerColor = containerColor.takeOrElse { this.containerColor },
+ contentColor = contentColor.takeOrElse { this.contentColor },
+ disabledContainerColor =
+ disabledContainerColor.takeOrElse { this.disabledContainerColor },
+ disabledContentColor = disabledContentColor.takeOrElse { this.disabledContentColor }
+ )
/**
* Represents the container color for this text button, depending on [enabled].
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/TimeText.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/TimeText.kt
index 0337f45..534aeb0 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/TimeText.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/TimeText.kt
@@ -68,29 +68,30 @@
import java.util.Locale
/**
- * Layout to show the current time and a label at the top of the screen.
- * If device has a round screen, then the time will be curved along the top edge of the screen,
- * if rectangular - then the text and the time will be straight.
+ * Layout to show the current time and a label at the top of the screen. If device has a round
+ * screen, then the time will be curved along the top edge of the screen, if rectangular - then the
+ * text and the time will be straight.
*
- * Note that Wear Material UX guidance recommends that time text
- * should not be larger than [TimeTextDefaults.MaxSweepAngle] of the screen edge
- * on round devices, which is enforced by default.
- * It is recommended that additional content, if any, is limited to short status messages before
- * the [TimeTextScope.time] using the MaterialTheme.colorScheme.primary color.
+ * Note that Wear Material UX guidance recommends that time text should not be larger than
+ * [TimeTextDefaults.MaxSweepAngle] of the screen edge on round devices, which is enforced by
+ * default. It is recommended that additional content, if any, is limited to short status messages
+ * before the [TimeTextScope.time] using the MaterialTheme.colorScheme.primary color.
*
* For more information, see the
- * [Curved Text](https://developer.android.com/training/wearables/components/curved-text)
- * guide.
+ * [Curved Text](https://developer.android.com/training/wearables/components/curved-text) guide.
*
* Different components of [TimeText] can be added through methods of [TimeTextScope].
*
* A simple [TimeText] which shows the current time:
+ *
* @sample androidx.wear.compose.material3.samples.TimeTextClockOnly
*
* A [TimeText] with a short app status message shown:
+ *
* @sample androidx.wear.compose.material3.samples.TimeTextWithStatus
*
* An example of a [TimeText] with an icon along with the clock:
+ *
* @sample androidx.wear.compose.material3.samples.TimeTextWithIcon
*
* @param modifier The modifier to be applied to the component.
@@ -99,7 +100,7 @@
* @param timeSource [TimeSource] which retrieves the current time and formats it.
* @param timeTextStyle [TextStyle] for the time text itself.
* @param contentColor [Color] of content of displayed through [TimeTextScope.text] and
- * [TimeTextScope.composable].
+ * [TimeTextScope.composable].
* @param contentPadding The spacing values between the container and the content.
* @param content The content of the [TimeText].
*/
@@ -119,18 +120,17 @@
if (isRoundDevice()) {
CurvedLayout(modifier = modifier) {
curvedRow(
- modifier = curvedModifier
- .sizeIn(maxSweepDegrees = maxSweepAngle)
- .padding(contentPadding.toArcPadding())
+ modifier =
+ curvedModifier
+ .sizeIn(maxSweepDegrees = maxSweepAngle)
+ .padding(contentPadding.toArcPadding())
) {
CurvedTimeTextScope(this, timeText, timeTextStyle, contentColor).content()
}
}
} else {
Row(
- modifier = modifier
- .fillMaxSize()
- .padding(contentPadding),
+ modifier = modifier.fillMaxSize().padding(contentPadding),
verticalAlignment = Alignment.Top,
horizontalArrangement = Arrangement.Center
) {
@@ -142,9 +142,7 @@
}
}
-/**
- * Receiver scope which is used by [TimeText].
- */
+/** Receiver scope which is used by [TimeText]. */
sealed class TimeTextScope {
/**
* Adds a composable [Text] for non-round devices and [curvedText] for round devices to
@@ -155,23 +153,22 @@
*/
abstract fun text(text: String, style: TextStyle? = null)
- /**
- * Adds a text displaying current time.
- */
+ /** Adds a text displaying current time. */
abstract fun time()
/**
- * Adds a separator in [TimeText].
+ * Adds a separator in [TimeText].
*
* @param style configuration for the [separator] such as color, font etc.
*/
abstract fun separator(style: TextStyle? = null)
/**
- * Adds a composable in content of [TimeText].
- * This can be used to display non-text information such as an icon.
+ * Adds a composable in content of [TimeText]. This can be used to display non-text information
+ * such as an icon.
*
* An example of a [TimeText] with an icon along with the clock:
+ *
* @sample androidx.wear.compose.material3.samples.TimeTextWithIcon
*
* @param content Slot for the [composable] to be displayed.
@@ -179,53 +176,44 @@
abstract fun composable(content: @Composable () -> Unit)
}
-/**
- * Contains the default values used by [TimeText].
- */
+/** Contains the default values used by [TimeText]. */
object TimeTextDefaults {
- /**
- * By default, TimeText has 2.dp screen padding from the top.
- */
+ /** By default, TimeText has 2.dp screen padding from the top. */
private val Padding = 2.dp
- /**
- * Default format for 24h clock.
- */
+ /** Default format for 24h clock. */
const val TimeFormat24Hours = "HH:mm"
- /**
- * Default format for 12h clock.
- */
+ /** Default format for 12h clock. */
const val TimeFormat12Hours = "h:mm"
/**
* The default maximum sweep angle in degrees used by [TimeText].
*
- * This is calculated by keeping the length of the corresponding chord
- * on the circle to be approximately 57% of the screen width.
+ * This is calculated by keeping the length of the corresponding chord on the circle to be
+ * approximately 57% of the screen width.
*/
const val MaxSweepAngle: Float = 70f
- /**
- * The default content padding used by [TimeText].
- */
+ /** The default content padding used by [TimeText]. */
val ContentPadding: PaddingValues = PaddingValues(top = Padding)
/**
- * Retrieves default timeFormat for the device. Depending on settings, it can be either
- * 12h or 24h format.
+ * Retrieves default timeFormat for the device. Depending on settings, it can be either 12h or
+ * 24h format.
*/
@Composable
fun timeFormat(): String {
val format = if (is24HourFormat()) TimeFormat24Hours else TimeFormat12Hours
return DateFormat.getBestDateTimePattern(Locale.getDefault(), format)
- .replace("a", "").trim()
+ .replace("a", "")
+ .trim()
}
/**
- * Creates a [TextStyle] with default parameters used for showing time
- * on square screens. By default a copy of MaterialTheme.typography.labelSmall style is created.
+ * Creates a [TextStyle] with default parameters used for showing time on square screens. By
+ * default a copy of MaterialTheme.typography.labelSmall style is created.
*
* @param background The background color.
* @param color The main color.
@@ -236,32 +224,31 @@
background: Color = Color.Unspecified,
color: Color = MaterialTheme.colorScheme.onBackground,
fontSize: TextUnit = TextUnit.Unspecified,
- ) = MaterialTheme.typography.labelSmall +
- TextStyle(color = color, background = background, fontSize = fontSize)
+ ) =
+ MaterialTheme.typography.labelSmall +
+ TextStyle(color = color, background = background, fontSize = fontSize)
/**
- * Creates a default implementation of [TimeSource] and remembers it.
- * Once the system time changes, it triggers an update of the [TimeSource.currentTime]
- * which is formatted using [timeFormat] param.
+ * Creates a default implementation of [TimeSource] and remembers it. Once the system time
+ * changes, it triggers an update of the [TimeSource.currentTime] which is formatted using
+ * [timeFormat] param.
*
- * [DefaultTimeSource] for Android uses [android.text.format.DateFormat]
- * [timeFormat] should follow the standard
+ * [DefaultTimeSource] for Android uses [android.text.format.DateFormat] [timeFormat] should
+ * follow the standard
* [Date and Time patterns](https://developer.android.com/reference/java/text/SimpleDateFormat#date-and-time-patterns)
- * Examples:
- * "h:mm a" - 12:08 PM
- * "yyyy.MM.dd HH:mm:ss" - 2021.11.01 14:08:56
- * More examples can be found [here](https://developer.android.com/reference/java/text/SimpleDateFormat#examples).
+ * Examples: "h:mm a" - 12:08 PM "yyyy.MM.dd HH:mm:ss" - 2021.11.01 14:08:56 More examples can
+ * be found [here](https://developer.android.com/reference/java/text/SimpleDateFormat#examples).
*
* @param timeFormat Date and time string pattern.
*/
@Composable
- fun rememberTimeSource(timeFormat: String): TimeSource = remember(timeFormat) {
- DefaultTimeSource(timeFormat)
- }
+ fun rememberTimeSource(timeFormat: String): TimeSource =
+ remember(timeFormat) { DefaultTimeSource(timeFormat) }
/**
- * A default implementation of Separator shown between any text/composable and the time
- * on non-round screens.
+ * A default implementation of Separator shown between any text/composable and the time on
+ * non-round screens.
+ *
* @param modifier A default modifier for the separator.
* @param textStyle A [TextStyle] for the separator.
* @param contentPadding The spacing values between the container and the separator.
@@ -272,16 +259,13 @@
textStyle: TextStyle = timeTextStyle(),
contentPadding: PaddingValues = PaddingValues(horizontal = 4.dp)
) {
- Text(
- text = "·",
- style = textStyle,
- modifier = modifier.padding(contentPadding)
- )
+ Text(text = "·", style = textStyle, modifier = modifier.padding(contentPadding))
}
/**
- * A default implementation of Separator shown between any text/composable and the time
- * on round screens.
+ * A default implementation of Separator shown between any text/composable and the time on round
+ * screens.
+ *
* @param curvedTextStyle A [CurvedTextStyle] for the separator.
* @param contentArcPadding [ArcPaddingValues] for the separator text.
*/
@@ -301,15 +285,13 @@
/**
* A method responsible for returning updated time string.
+ *
* @return Formatted time string.
*/
- @Composable
- fun currentTime(): String
+ @Composable fun currentTime(): String
}
-/**
- * Implementation of [TimeTextScope] for round devices.
- */
+/** Implementation of [TimeTextScope] for round devices. */
internal class CurvedTimeTextScope(
private val scope: CurvedScope,
private val timeText: String,
@@ -346,9 +328,7 @@
}
}
-/**
- * Implementation of [TimeTextScope] for non-round devices.
- */
+/** Implementation of [TimeTextScope] for non-round devices. */
internal class LinearTimeTextScope(
private val timeText: String,
private val timeTextStyle: TextStyle,
@@ -358,24 +338,15 @@
private val contentTextStyle = timeTextStyle.merge(contentColor)
override fun text(text: String, style: TextStyle?) {
- pending.add {
- Text(
- text = text,
- style = contentTextStyle.merge(style)
- )
- }
+ pending.add { Text(text = text, style = contentTextStyle.merge(style)) }
}
override fun time() {
- pending.add {
- Text(timeText, style = timeTextStyle)
- }
+ pending.add { Text(timeText, style = timeTextStyle) }
}
override fun separator(style: TextStyle?) {
- pending.add {
- TextSeparator(textStyle = timeTextStyle.merge(style))
- }
+ pending.add { TextSeparator(textStyle = timeTextStyle.merge(style)) }
}
override fun composable(content: @Composable () -> Unit) {
@@ -398,64 +369,54 @@
private val _timeFormat = timeFormat
@Composable
- override fun currentTime(): String =
- currentTime({ currentTimeMillis() }, _timeFormat).value
+ override fun currentTime(): String = currentTime({ currentTimeMillis() }, _timeFormat).value
}
@Composable
@VisibleForTesting
-internal fun currentTime(
- time: () -> Long,
- timeFormat: String
-): State<String> {
+internal fun currentTime(time: () -> Long, timeFormat: String): State<String> {
var calendar by remember { mutableStateOf(Calendar.getInstance()) }
var currentTime by remember { mutableLongStateOf(time()) }
- val timeText = remember {
- derivedStateOf { formatTime(calendar, currentTime, timeFormat) }
- }
+ val timeText = remember { derivedStateOf { formatTime(calendar, currentTime, timeFormat) } }
val context = LocalContext.current
val updatedTimeLambda by rememberUpdatedState(time)
DisposableEffect(context, updatedTimeLambda) {
- val receiver = TimeBroadcastReceiver(
- onTimeChanged = { currentTime = updatedTimeLambda() },
- onTimeZoneChanged = { calendar = Calendar.getInstance() }
- )
+ val receiver =
+ TimeBroadcastReceiver(
+ onTimeChanged = { currentTime = updatedTimeLambda() },
+ onTimeZoneChanged = { calendar = Calendar.getInstance() }
+ )
receiver.register(context)
- onDispose {
- receiver.unregister(context)
- }
+ onDispose { receiver.unregister(context) }
}
return timeText
}
-/**
- * An extension function, which converts [PaddingValues] into [ArcPaddingValues].
- */
-private fun PaddingValues.toArcPadding() = object : ArcPaddingValues {
- override fun calculateOuterPadding(radialDirection: CurvedDirection.Radial) =
- calculateTopPadding()
+/** An extension function, which converts [PaddingValues] into [ArcPaddingValues]. */
+private fun PaddingValues.toArcPadding() =
+ object : ArcPaddingValues {
+ override fun calculateOuterPadding(radialDirection: CurvedDirection.Radial) =
+ calculateTopPadding()
- override fun calculateInnerPadding(radialDirection: CurvedDirection.Radial) =
- calculateBottomPadding()
+ override fun calculateInnerPadding(radialDirection: CurvedDirection.Radial) =
+ calculateBottomPadding()
- override fun calculateAfterPadding(
- layoutDirection: LayoutDirection,
- angularDirection: CurvedDirection.Angular
- ) = calculateRightPadding(layoutDirection)
+ override fun calculateAfterPadding(
+ layoutDirection: LayoutDirection,
+ angularDirection: CurvedDirection.Angular
+ ) = calculateRightPadding(layoutDirection)
- override fun calculateBeforePadding(
- layoutDirection: LayoutDirection,
- angularDirection: CurvedDirection.Angular
- ) = calculateLeftPadding(layoutDirection)
-}
+ override fun calculateBeforePadding(
+ layoutDirection: LayoutDirection,
+ angularDirection: CurvedDirection.Angular
+ ) = calculateLeftPadding(layoutDirection)
+ }
-/**
- * A [BroadcastReceiver] to receive time tick, time change, and time zone change events.
- */
+/** A [BroadcastReceiver] to receive time tick, time change, and time zone change events. */
private class TimeBroadcastReceiver(
val onTimeChanged: () -> Unit,
val onTimeZoneChanged: () -> Unit
@@ -489,11 +450,7 @@
}
}
-private fun formatTime(
- calendar: Calendar,
- currentTime: Long,
- timeFormat: String
-): String {
+private fun formatTime(calendar: Calendar, currentTime: Long, timeFormat: String): String {
calendar.timeInMillis = currentTime
return DateFormat.format(timeFormat, calendar).toString()
}
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/ToggleButton.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/ToggleButton.kt
index 27bec96..c66f7d3 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/ToggleButton.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/ToggleButton.kt
@@ -42,53 +42,51 @@
import androidx.wear.compose.materialcore.animateSelectionColor
/**
- * The Wear Material [ToggleButton] offers four slots and a specific layout for an icon, a
- * label, a secondaryLabel and toggle control (such as [Checkbox] or [Switch]).
- * The icon and secondaryLabel are optional.
- * The items are laid out in a row with the optional icon at the start, a column containing the two
- * label slots in the middle and a slot for the toggle control at the end.
+ * The Wear Material [ToggleButton] offers four slots and a specific layout for an icon, a label, a
+ * secondaryLabel and toggle control (such as [Checkbox] or [Switch]). The icon and secondaryLabel
+ * are optional. The items are laid out in a row with the optional icon at the start, a column
+ * containing the two label slots in the middle and a slot for the toggle control at the end.
*
- * The [ToggleButton] is Stadium shaped and has a max height designed to take no more than
- * two lines of text.
- * With localisation and/or large font sizes, the [ToggleButton] height adjusts to
+ * The [ToggleButton] is Stadium shaped and has a max height designed to take no more than two lines
+ * of text. With localisation and/or large font sizes, the [ToggleButton] height adjusts to
* accommodate the contents. The label and secondary label should be start aligned.
*
- * Samples:
- * Example of a ToggleButton with a Checkbox:
+ * Samples: Example of a ToggleButton with a Checkbox:
+ *
* @sample androidx.wear.compose.material3.samples.ToggleButtonWithCheckbox
*
* Example of a ToggleButton with a Switch:
+ *
* @sample androidx.wear.compose.material3.samples.ToggleButtonWithSwitch
*
* [ToggleButton] can be enabled or disabled. A disabled button will not respond to click events.
*
- * The recommended set of [ToggleButton] colors can be obtained from
- * [ToggleButtonDefaults], e.g. [ToggleButtonDefaults.toggleButtonColors].
+ * The recommended set of [ToggleButton] colors can be obtained from [ToggleButtonDefaults], e.g.
+ * [ToggleButtonDefaults.toggleButtonColors].
*
* @param checked Boolean flag indicating whether this button is currently checked.
* @param onCheckedChange Callback to be invoked when this buttons checked status is changed.
- * @param toggleControl A slot for providing the button's toggle control.
- * Two built-in types of toggle control are supported: [Checkbox] and [Switch].
+ * @param toggleControl A slot for providing the button's toggle control. Two built-in types of
+ * toggle control are supported: [Checkbox] and [Switch].
* @param modifier Modifier to be applied to the [ToggleButton].
- * @param enabled Controls the enabled state of the button. When `false`, this button will not
- * be clickable.
+ * @param enabled Controls the enabled state of the button. When `false`, this button will not be
+ * clickable.
* @param shape Defines the button's shape. It is strongly recommended to use the default as this
- * shape is a key characteristic of the Wear Material Theme.
- * @param colors [ToggleButtonColors] that will be used to resolve the background and
- * content color for this button in different states.
+ * shape is a key characteristic of the Wear Material Theme.
+ * @param colors [ToggleButtonColors] that will be used to resolve the background and content color
+ * for this button in different states.
* @param contentPadding The spacing values to apply internally between the container and the
- * content.
+ * content.
* @param interactionSource an optional hoisted [MutableInteractionSource] for observing and
- * emitting [Interaction]s for this button's "toggleable" tap area. You can use this to change the
- * button's appearance or preview the button in different states. Note that if `null` is provided,
- * interactions will still happen internally.
+ * emitting [Interaction]s for this button's "toggleable" tap area. You can use this to change the
+ * button's appearance or preview the button in different states. Note that if `null` is provided,
+ * interactions will still happen internally.
* @param icon An optional slot for providing an icon to indicate the purpose of the button. The
- * contents are expected to be a horizontally and vertically center aligned icon of size
- * 24.dp.
+ * contents are expected to be a horizontally and vertically center aligned icon of size 24.dp.
* @param secondaryLabel A slot for providing the button's secondary label. The contents are
- * expected to be text which is "start" aligned.
+ * expected to be text which is "start" aligned.
* @param label A slot for providing the button's main label. The contents are expected to be text
- * which is "start" aligned.
+ * which is "start" aligned.
*/
@Composable
fun ToggleButton(
@@ -108,28 +106,29 @@
androidx.wear.compose.materialcore.ToggleButton(
checked = checked,
onCheckedChange = onCheckedChange,
- label = provideScopeContent(
- contentColor = colors.contentColor(enabled = enabled, checked),
- textStyle = ToggleButtonTokens.LabelFont.value,
- content = label
- ),
+ label =
+ provideScopeContent(
+ contentColor = colors.contentColor(enabled = enabled, checked),
+ textStyle = ToggleButtonTokens.LabelFont.value,
+ content = label
+ ),
toggleControl = {
val scope = remember(enabled, checked) { ToggleControlScope(enabled, checked) }
toggleControl(scope)
},
selectionControl = null,
- modifier = modifier
- .defaultMinSize(minHeight = MIN_HEIGHT)
- .height(IntrinsicSize.Min),
- icon = provideNullableScopeContent(
- contentColor = colors.iconColor(enabled = enabled, checked),
- content = icon
- ),
- secondaryLabel = provideNullableScopeContent(
- contentColor = colors.secondaryContentColor(enabled = enabled, checked),
- textStyle = ToggleButtonTokens.SecondaryLabelFont.value,
- content = secondaryLabel
- ),
+ modifier = modifier.defaultMinSize(minHeight = MIN_HEIGHT).height(IntrinsicSize.Min),
+ icon =
+ provideNullableScopeContent(
+ contentColor = colors.iconColor(enabled = enabled, checked),
+ content = icon
+ ),
+ secondaryLabel =
+ provideNullableScopeContent(
+ contentColor = colors.secondaryContentColor(enabled = enabled, checked),
+ textStyle = ToggleButtonTokens.SecondaryLabelFont.value,
+ content = secondaryLabel
+ ),
background = { isEnabled, isChecked ->
val backgroundColor =
colors.containerColor(enabled = isEnabled, checked = isChecked).value
@@ -150,63 +149,61 @@
/**
* The Wear Material [SplitToggleButton] offers three slots and a specific layout for a label,
- * secondaryLabel and toggle control. The secondaryLabel is optional. The items are laid out
- * with a column containing the two label slots and a slot for the toggle control at the
- * end.
+ * secondaryLabel and toggle control. The secondaryLabel is optional. The items are laid out with a
+ * column containing the two label slots and a slot for the toggle control at the end.
*
- * The [SplitToggleButton] is Stadium shaped and has a max height designed to take no more than
- * two lines of text.
- * With localisation and/or large font sizes, the [SplitToggleButton] height adjusts to
- * accommodate the contents. The label and secondary label should be start aligned.
+ * The [SplitToggleButton] is Stadium shaped and has a max height designed to take no more than two
+ * lines of text. With localisation and/or large font sizes, the [SplitToggleButton] height adjusts
+ * to accommodate the contents. The label and secondary label should be start aligned.
*
* A [SplitToggleButton] has two tappable areas, one tap area for the labels and another for the
* toggle control. The [onClick] listener will be associated with the main body of the split toggle
* button with the [onCheckedChange] listener associated with the toggle control area only.
*
- * Samples:
- * Example of a SplitToggleButton with a Checkbox:
+ * Samples: Example of a SplitToggleButton with a Checkbox:
+ *
* @sample androidx.wear.compose.material3.samples.SplitToggleButtonWithCheckbox
*
* Example of a SplitToggleButton with a Switch:
+ *
* @sample androidx.wear.compose.material3.samples.SplitToggleButtonWithSwitch
*
* For a SplitToggleButton the background of the tappable background area behind the toggle control
* will have a visual effect applied to provide a "divider" between the two tappable areas.
*
- * The recommended set of colors can be obtained from
- * [ToggleButtonDefaults], e.g. [ToggleButtonDefaults.splitToggleButtonColors].
+ * The recommended set of colors can be obtained from [ToggleButtonDefaults], e.g.
+ * [ToggleButtonDefaults.splitToggleButtonColors].
*
- * [SplitToggleButton] can be enabled or disabled. A disabled button will not respond to
- * click events.
+ * [SplitToggleButton] can be enabled or disabled. A disabled button will not respond to click
+ * events.
*
* @param checked Boolean flag indicating whether this button is currently checked.
- * @param onCheckedChange Callback to be invoked when this buttons checked status is
- * changed.
+ * @param onCheckedChange Callback to be invoked when this buttons checked status is changed.
* @param onClick Click listener called when the user clicks the main body of the button, the area
- * behind the labels.
- * @param toggleControl A slot for providing the button's toggle control.
- * Two built-in types of toggle control are supported: [Checkbox] and [Switch].
+ * behind the labels.
+ * @param toggleControl A slot for providing the button's toggle control. Two built-in types of
+ * toggle control are supported: [Checkbox] and [Switch].
* @param modifier Modifier to be applied to the button.
- * @param enabled Controls the enabled state of the button. When `false`, this button will not
- * be clickable.
+ * @param enabled Controls the enabled state of the button. When `false`, this button will not be
+ * clickable.
* @param shape Defines the button's shape. It is strongly recommended to use the default as this
- * shape is a key characteristic of the Wear Material Theme.
- * @param colors [SplitToggleButtonColors] that will be used to resolve the background and
- * content color for this button in different states.
+ * shape is a key characteristic of the Wear Material Theme.
+ * @param colors [SplitToggleButtonColors] that will be used to resolve the background and content
+ * color for this button in different states.
* @param contentPadding The spacing values to apply internally between the container and the
- * content.
+ * content.
* @param checkedInteractionSource an optional hoisted [MutableInteractionSource] for observing and
- * emitting [Interaction]s for this button's "toggleable" tap area. You can use this to change the
- * button's appearance or preview the button in different states. Note that if `null` is provided,
- * interactions will still happen internally.
+ * emitting [Interaction]s for this button's "toggleable" tap area. You can use this to change the
+ * button's appearance or preview the button in different states. Note that if `null` is provided,
+ * interactions will still happen internally.
* @param clickInteractionSource an optional hoisted [MutableInteractionSource] for observing and
- * emitting [Interaction]s for this button's "clickable" tap area. You can use this to change the
- * button's appearance or preview the button in different states. Note that if `null` is provided,
- * interactions will still happen internally.
+ * emitting [Interaction]s for this button's "clickable" tap area. You can use this to change the
+ * button's appearance or preview the button in different states. Note that if `null` is provided,
+ * interactions will still happen internally.
* @param secondaryLabel A slot for providing the button's secondary label. The contents are
- * expected to be "start" aligned.
+ * expected to be "start" aligned.
* @param label A slot for providing the button's main label. The contents are expected to be text
- * which is "start" aligned.
+ * which is "start" aligned.
*/
@Composable
fun SplitToggleButton(
@@ -223,106 +220,89 @@
contentPadding: PaddingValues = ToggleButtonDefaults.ContentPadding,
secondaryLabel: @Composable (RowScope.() -> Unit)? = null,
label: @Composable RowScope.() -> Unit
-) = androidx.wear.compose.materialcore.SplitToggleButton(
- checked = checked,
- onCheckedChange = onCheckedChange,
- label = provideScopeContent(
- contentColor = colors.contentColor(enabled = enabled, checked = checked),
- textStyle = SplitToggleButtonTokens.LabelFont.value,
- content = label
- ),
- onClick = onClick,
- toggleControl = {
- val scope = remember(enabled, checked) { ToggleControlScope(enabled, checked) }
- toggleControl(scope)
- },
- selectionControl = null,
- modifier = modifier
- .defaultMinSize(minHeight = MIN_HEIGHT)
- .height(IntrinsicSize.Min),
- secondaryLabel = provideNullableScopeContent(
- contentColor = colors.secondaryContentColor(enabled = enabled, checked = checked),
- textStyle = SplitToggleButtonTokens.SecondaryLabelFont.value,
- content = secondaryLabel
- ),
- backgroundColor = { isEnabled, isChecked ->
- colors.containerColor(
- enabled = isEnabled,
- checked = isChecked
- )
- },
- splitBackgroundColor = { isEnabled, isChecked ->
- colors.splitContainerColor(
- enabled = isEnabled,
- checked = isChecked
- )
- },
- enabled = enabled,
- checkedInteractionSource = checkedInteractionSource,
- clickInteractionSource = clickInteractionSource,
- contentPadding = contentPadding,
- shape = shape,
- labelSpacerSize = ToggleButtonDefaults.LabelSpacerSize,
- ripple = rippleOrFallbackImplementation()
-)
+) =
+ androidx.wear.compose.materialcore.SplitToggleButton(
+ checked = checked,
+ onCheckedChange = onCheckedChange,
+ label =
+ provideScopeContent(
+ contentColor = colors.contentColor(enabled = enabled, checked = checked),
+ textStyle = SplitToggleButtonTokens.LabelFont.value,
+ content = label
+ ),
+ onClick = onClick,
+ toggleControl = {
+ val scope = remember(enabled, checked) { ToggleControlScope(enabled, checked) }
+ toggleControl(scope)
+ },
+ selectionControl = null,
+ modifier = modifier.defaultMinSize(minHeight = MIN_HEIGHT).height(IntrinsicSize.Min),
+ secondaryLabel =
+ provideNullableScopeContent(
+ contentColor = colors.secondaryContentColor(enabled = enabled, checked = checked),
+ textStyle = SplitToggleButtonTokens.SecondaryLabelFont.value,
+ content = secondaryLabel
+ ),
+ backgroundColor = { isEnabled, isChecked ->
+ colors.containerColor(enabled = isEnabled, checked = isChecked)
+ },
+ splitBackgroundColor = { isEnabled, isChecked ->
+ colors.splitContainerColor(enabled = isEnabled, checked = isChecked)
+ },
+ enabled = enabled,
+ checkedInteractionSource = checkedInteractionSource,
+ clickInteractionSource = clickInteractionSource,
+ contentPadding = contentPadding,
+ shape = shape,
+ labelSpacerSize = ToggleButtonDefaults.LabelSpacerSize,
+ ripple = rippleOrFallbackImplementation()
+ )
-/**
- * Contains the default values used by [ToggleButton]s and [SplitToggleButton]s
- */
+/** Contains the default values used by [ToggleButton]s and [SplitToggleButton]s */
object ToggleButtonDefaults {
- /**
- * Recommended [Shape] for [ToggleButton].
- */
+ /** Recommended [Shape] for [ToggleButton]. */
val toggleButtonShape: Shape
@Composable get() = ToggleButtonTokens.ContainerShape.value
- /**
- * Recommended [Shape] for [SplitToggleButton].
- */
+ /** Recommended [Shape] for [SplitToggleButton]. */
val splitToggleButtonShape: Shape
@Composable get() = SplitToggleButtonTokens.ContainerShape.value
- /**
- * Creates a [ToggleButtonColors] for use in a [ToggleButton].
- */
- @Composable
- fun toggleButtonColors() = MaterialTheme.colorScheme.defaultToggleButtonColors
+ /** Creates a [ToggleButtonColors] for use in a [ToggleButton]. */
+ @Composable fun toggleButtonColors() = MaterialTheme.colorScheme.defaultToggleButtonColors
/**
* Creates a [ToggleButtonColors] for use in a [ToggleButton].
*
- * @param checkedContainerColor The container color of the [ToggleButton]
- * when enabled and checked.
- * @param checkedContentColor The content color of the [ToggleButton]
- * when enabled and checked.
- * @param checkedSecondaryContentColor The secondary content color of the [ToggleButton]
- * when enabled and checked, used for secondaryLabel content.
- * @param checkedIconColor The icon color of the [ToggleButton]
- * when enabled and checked.
- * @param uncheckedContainerColor The container color of the [ToggleButton]
- * when enabled and unchecked.
- * @param uncheckedContentColor The content color of a [ToggleButton]
- * when enabled and unchecked.
- * @param uncheckedSecondaryContentColor The secondary content color of this [ToggleButton]
- * when enabled and unchecked, used for secondaryLabel content
- * @param uncheckedIconColor The icon color of the [ToggleButton]
- * when enabled and unchecked.
- * @param disabledCheckedContainerColor The container color of the [ToggleButton]
- * when disabled and checked.
- * @param disabledCheckedContentColor The content color of the [ToggleButton]
- * when disabled and checked.
- * @param disabledCheckedSecondaryContentColor The secondary content color of the
- * [ToggleButton] when disabled and checked, used for secondaryLabel content.
- * @param disabledCheckedIconColor The icon color of the [ToggleButton]
- * when disabled and checked.
- * @param disabledUncheckedContainerColor The container color of the [ToggleButton]
- * when disabled and unchecked.
- * @param disabledUncheckedContentColor The content color of a [ToggleButton]
- * when disabled and unchecked.
+ * @param checkedContainerColor The container color of the [ToggleButton] when enabled and
+ * checked.
+ * @param checkedContentColor The content color of the [ToggleButton] when enabled and checked.
+ * @param checkedSecondaryContentColor The secondary content color of the [ToggleButton] when
+ * enabled and checked, used for secondaryLabel content.
+ * @param checkedIconColor The icon color of the [ToggleButton] when enabled and checked.
+ * @param uncheckedContainerColor The container color of the [ToggleButton] when enabled and
+ * unchecked.
+ * @param uncheckedContentColor The content color of a [ToggleButton] when enabled and
+ * unchecked.
+ * @param uncheckedSecondaryContentColor The secondary content color of this [ToggleButton] when
+ * enabled and unchecked, used for secondaryLabel content
+ * @param uncheckedIconColor The icon color of the [ToggleButton] when enabled and unchecked.
+ * @param disabledCheckedContainerColor The container color of the [ToggleButton] when disabled
+ * and checked.
+ * @param disabledCheckedContentColor The content color of the [ToggleButton] when disabled and
+ * checked.
+ * @param disabledCheckedSecondaryContentColor The secondary content color of the [ToggleButton]
+ * when disabled and checked, used for secondaryLabel content.
+ * @param disabledCheckedIconColor The icon color of the [ToggleButton] when disabled and
+ * checked.
+ * @param disabledUncheckedContainerColor The container color of the [ToggleButton] when
+ * disabled and unchecked.
+ * @param disabledUncheckedContentColor The content color of a [ToggleButton] when disabled and
+ * unchecked.
* @param disabledUncheckedSecondaryContentColor The secondary content color of this
- * [ToggleButton] when disabled and unchecked, used for secondaryLabel content
- * @param disabledUncheckedIconColor The icon color of the [ToggleButton]
- * when disabled and unchecked.
+ * [ToggleButton] when disabled and unchecked, used for secondaryLabel content
+ * @param disabledUncheckedIconColor The icon color of the [ToggleButton] when disabled and
+ * unchecked.
*/
@Composable
fun toggleButtonColors(
@@ -342,7 +322,8 @@
disabledUncheckedContentColor: Color = Color.Unspecified,
disabledUncheckedSecondaryContentColor: Color = Color.Unspecified,
disabledUncheckedIconColor: Color = Color.Unspecified,
- ) = MaterialTheme.colorScheme.defaultToggleButtonColors.copy(
+ ) =
+ MaterialTheme.colorScheme.defaultToggleButtonColors.copy(
checkedContainerColor = checkedContainerColor,
checkedContentColor = checkedContentColor,
checkedSecondaryContentColor = checkedSecondaryContentColor,
@@ -361,9 +342,7 @@
disabledUncheckedIconColor = disabledUncheckedIconColor,
)
- /**
- * Creates a [SplitToggleButtonColors] for use in a [SplitToggleButton].
- */
+ /** Creates a [SplitToggleButtonColors] for use in a [SplitToggleButton]. */
@Composable
fun splitToggleButtonColors() = MaterialTheme.colorScheme.defaultSplitToggleButtonColors
@@ -371,37 +350,37 @@
* Creates a [SplitToggleButtonColors] for use in a [SplitToggleButton].
*
* @param checkedContainerColor The container color of the [SplitToggleButton] when enabled and
- * checked.
+ * checked.
* @param checkedContentColor The content color of the [SplitToggleButton] when enabled and
- * checked.
+ * checked.
* @param checkedSecondaryContentColor The secondary content color of the [SplitToggleButton]
- * when enabled and checked, used for secondaryLabel content.
- * @param checkedSplitContainerColor The split container color of the [SplitToggleButton]
- * when enabled and checked.
+ * when enabled and checked, used for secondaryLabel content.
+ * @param checkedSplitContainerColor The split container color of the [SplitToggleButton] when
+ * enabled and checked.
* @param uncheckedContainerColor The container color of the [SplitToggleButton] when enabled
- * and unchecked.
+ * and unchecked.
* @param uncheckedContentColor The content color of the [SplitToggleButton] when enabled and
- * unchecked.
+ * unchecked.
* @param uncheckedSecondaryContentColor The secondary content color of the [SplitToggleButton]
- * when enabled and unchecked, used for secondaryLabel content.
+ * when enabled and unchecked, used for secondaryLabel content.
* @param uncheckedSplitContainerColor The split container color of the [SplitToggleButton] when
- * enabled and unchecked.
+ * enabled and unchecked.
* @param disabledCheckedContainerColor The container color of the [SplitToggleButton] when
- * disabled and checked.
- * @param disabledCheckedContentColor The content color of the [SplitToggleButton] when
- * disabled and checked.
+ * disabled and checked.
+ * @param disabledCheckedContentColor The content color of the [SplitToggleButton] when disabled
+ * and checked.
* @param disabledCheckedSecondaryContentColor The secondary content color of the
- * [SplitToggleButton] when disabled and checked, used for secondaryLabel content.
- * @param disabledCheckedSplitContainerColor The split container color of the [
- * SplitToggleButton] when disabled and checked.
+ * [SplitToggleButton] when disabled and checked, used for secondaryLabel content.
+ * @param disabledCheckedSplitContainerColor The split container color of the
+ * [ SplitToggleButton] when disabled and checked.
* @param disabledUncheckedContainerColor The container color of the [SplitToggleButton] when
- * disabled and unchecked.
+ * disabled and unchecked.
* @param disabledUncheckedContentColor The content color of the [SplitToggleButton] when
- * disabled and unchecked.
+ * disabled and unchecked.
* @param disabledUncheckedSecondaryContentColor The secondary content color of the
- * [SplitToggleButton] when disabled and unchecked, used for secondaryLabel content.
+ * [SplitToggleButton] when disabled and unchecked, used for secondaryLabel content.
* @param disabledUncheckedSplitContainerColor The split container color of the
- * [SplitToggleButton] when disabled and unchecked.
+ * [SplitToggleButton] when disabled and unchecked.
*/
@Composable
fun splitToggleButtonColors(
@@ -421,7 +400,8 @@
disabledUncheckedContentColor: Color = Color.Unspecified,
disabledUncheckedSecondaryContentColor: Color = Color.Unspecified,
disabledUncheckedSplitContainerColor: Color = Color.Unspecified,
- ) = MaterialTheme.colorScheme.defaultSplitToggleButtonColors.copy(
+ ) =
+ MaterialTheme.colorScheme.defaultSplitToggleButtonColors.copy(
checkedContainerColor = checkedContainerColor,
checkedContentColor = checkedContentColor,
checkedSecondaryContentColor = checkedSecondaryContentColor,
@@ -444,141 +424,186 @@
private val HorizontalPadding = 14.dp
private val VerticalPadding = 8.dp
- /**
- * The default content padding used by [ToggleButton]
- */
- val ContentPadding: PaddingValues = PaddingValues(
- start = HorizontalPadding,
- top = VerticalPadding,
- end = HorizontalPadding,
- bottom = VerticalPadding
- )
+ /** The default content padding used by [ToggleButton] */
+ val ContentPadding: PaddingValues =
+ PaddingValues(
+ start = HorizontalPadding,
+ top = VerticalPadding,
+ end = HorizontalPadding,
+ bottom = VerticalPadding
+ )
private val ColorScheme.defaultToggleButtonColors: ToggleButtonColors
get() {
- return defaultToggleButtonColorsCached ?: ToggleButtonColors(
- checkedContainerColor = fromToken(ToggleButtonTokens.CheckedContainerColor),
- checkedContentColor = fromToken(ToggleButtonTokens.CheckedContentColor),
- checkedSecondaryContentColor =
- fromToken(ToggleButtonTokens.CheckedSecondaryLabelColor)
- .copy(alpha = ToggleButtonTokens.CheckedSecondaryLabelOpacity),
- checkedIconColor = fromToken(ToggleButtonTokens.CheckedIconColor),
- uncheckedContainerColor = fromToken(ToggleButtonTokens.UncheckedContainerColor),
- uncheckedContentColor = fromToken(ToggleButtonTokens.UncheckedContentColor),
- uncheckedSecondaryContentColor =
- fromToken(ToggleButtonTokens.UncheckedSecondaryLabelColor),
- uncheckedIconColor = fromToken(ToggleButtonTokens.UncheckedIconColor),
- disabledCheckedContainerColor =
- fromToken(ToggleButtonTokens.DisabledCheckedContainerColor).toDisabledColor(
- disabledAlpha = ToggleButtonTokens.DisabledCheckedContainerOpacity
- ),
- disabledCheckedContentColor =
- fromToken(ToggleButtonTokens.DisabledCheckedContentColor).toDisabledColor(
- disabledAlpha = ToggleButtonTokens.DisabledOpacity
- ),
- disabledCheckedSecondaryContentColor =
- fromToken(ToggleButtonTokens.DisabledCheckedSecondaryLabelColor)
- .toDisabledColor(disabledAlpha = ToggleButtonTokens.DisabledOpacity),
- disabledCheckedIconColor = fromToken(ToggleButtonTokens.DisabledCheckedIconColor)
- .toDisabledColor(disabledAlpha = ToggleButtonTokens.DisabledOpacity),
- disabledUncheckedContainerColor =
- fromToken(ToggleButtonTokens.DisabledUncheckedContainerColor)
- .toDisabledColor(
- disabledAlpha = ToggleButtonTokens.DisabledUncheckedContainerOpacity
- ),
- disabledUncheckedContentColor =
- fromToken(ToggleButtonTokens.DisabledUncheckedContentColor)
- .toDisabledColor(disabledAlpha = ToggleButtonTokens.DisabledOpacity),
- disabledUncheckedSecondaryContentColor =
- fromToken(ToggleButtonTokens.DisabledUncheckedSecondaryLabelColor)
- .toDisabledColor(disabledAlpha = ToggleButtonTokens.DisabledOpacity),
- disabledUncheckedIconColor =
- fromToken(ToggleButtonTokens.DisabledUncheckedIconColor)
- .toDisabledColor(disabledAlpha = ToggleButtonTokens.DisabledOpacity),
- ).also { defaultToggleButtonColorsCached = it }
+ return defaultToggleButtonColorsCached
+ ?: ToggleButtonColors(
+ checkedContainerColor = fromToken(ToggleButtonTokens.CheckedContainerColor),
+ checkedContentColor = fromToken(ToggleButtonTokens.CheckedContentColor),
+ checkedSecondaryContentColor =
+ fromToken(ToggleButtonTokens.CheckedSecondaryLabelColor)
+ .copy(alpha = ToggleButtonTokens.CheckedSecondaryLabelOpacity),
+ checkedIconColor = fromToken(ToggleButtonTokens.CheckedIconColor),
+ uncheckedContainerColor =
+ fromToken(ToggleButtonTokens.UncheckedContainerColor),
+ uncheckedContentColor = fromToken(ToggleButtonTokens.UncheckedContentColor),
+ uncheckedSecondaryContentColor =
+ fromToken(ToggleButtonTokens.UncheckedSecondaryLabelColor),
+ uncheckedIconColor = fromToken(ToggleButtonTokens.UncheckedIconColor),
+ disabledCheckedContainerColor =
+ fromToken(ToggleButtonTokens.DisabledCheckedContainerColor)
+ .toDisabledColor(
+ disabledAlpha =
+ ToggleButtonTokens.DisabledCheckedContainerOpacity
+ ),
+ disabledCheckedContentColor =
+ fromToken(ToggleButtonTokens.DisabledCheckedContentColor)
+ .toDisabledColor(
+ disabledAlpha = ToggleButtonTokens.DisabledOpacity
+ ),
+ disabledCheckedSecondaryContentColor =
+ fromToken(ToggleButtonTokens.DisabledCheckedSecondaryLabelColor)
+ .toDisabledColor(
+ disabledAlpha = ToggleButtonTokens.DisabledOpacity
+ ),
+ disabledCheckedIconColor =
+ fromToken(ToggleButtonTokens.DisabledCheckedIconColor)
+ .toDisabledColor(
+ disabledAlpha = ToggleButtonTokens.DisabledOpacity
+ ),
+ disabledUncheckedContainerColor =
+ fromToken(ToggleButtonTokens.DisabledUncheckedContainerColor)
+ .toDisabledColor(
+ disabledAlpha =
+ ToggleButtonTokens.DisabledUncheckedContainerOpacity
+ ),
+ disabledUncheckedContentColor =
+ fromToken(ToggleButtonTokens.DisabledUncheckedContentColor)
+ .toDisabledColor(
+ disabledAlpha = ToggleButtonTokens.DisabledOpacity
+ ),
+ disabledUncheckedSecondaryContentColor =
+ fromToken(ToggleButtonTokens.DisabledUncheckedSecondaryLabelColor)
+ .toDisabledColor(
+ disabledAlpha = ToggleButtonTokens.DisabledOpacity
+ ),
+ disabledUncheckedIconColor =
+ fromToken(ToggleButtonTokens.DisabledUncheckedIconColor)
+ .toDisabledColor(
+ disabledAlpha = ToggleButtonTokens.DisabledOpacity
+ ),
+ )
+ .also { defaultToggleButtonColorsCached = it }
}
private val ColorScheme.defaultSplitToggleButtonColors: SplitToggleButtonColors
get() {
- return defaultSplitToggleButtonColorsCached ?: SplitToggleButtonColors(
- checkedContainerColor = fromToken(SplitToggleButtonTokens.CheckedContainerColor),
- checkedContentColor = fromToken(SplitToggleButtonTokens.CheckedContentColor),
- checkedSecondaryContentColor =
- fromToken(SplitToggleButtonTokens.CheckedSecondaryLabelColor)
- .copy(alpha = SplitToggleButtonTokens.CheckedSecondaryLabelOpacity),
- checkedSplitContainerColor =
- fromToken(SplitToggleButtonTokens.CheckedSplitContainerColor)
- .copy(alpha = SplitToggleButtonTokens.CheckedSplitContainerOpacity),
- uncheckedContainerColor =
- fromToken(SplitToggleButtonTokens.UncheckedContainerColor),
- uncheckedContentColor = fromToken(SplitToggleButtonTokens.UncheckedContentColor),
- uncheckedSecondaryContentColor =
- fromToken(SplitToggleButtonTokens.UncheckedSecondaryLabelColor),
- uncheckedSplitContainerColor =
- fromToken(SplitToggleButtonTokens.UncheckedSplitContainerColor),
- disabledCheckedContainerColor =
- fromToken(SplitToggleButtonTokens.DisabledCheckedContainerColor)
- .toDisabledColor(disabledAlpha = SplitToggleButtonTokens.DisabledOpacity),
- disabledCheckedContentColor =
- fromToken(SplitToggleButtonTokens.DisabledCheckedContentColor)
- .toDisabledColor(disabledAlpha = SplitToggleButtonTokens.DisabledOpacity),
- disabledCheckedSecondaryContentColor =
- fromToken(SplitToggleButtonTokens.DisabledCheckedSecondaryLabelColor)
- .copy(alpha = SplitToggleButtonTokens.DisabledCheckedSecondaryLabelOpacity)
- .toDisabledColor(disabledAlpha = SplitToggleButtonTokens.DisabledOpacity),
- disabledCheckedSplitContainerColor =
- fromToken(SplitToggleButtonTokens.DisabledCheckedSplitContainerColor)
- .copy(alpha = SplitToggleButtonTokens.DisabledCheckedSplitContainerOpacity)
- .toDisabledColor(disabledAlpha = SplitToggleButtonTokens.DisabledOpacity),
- disabledUncheckedContainerColor =
- fromToken(SplitToggleButtonTokens.DisabledUncheckedContainerColor)
- .toDisabledColor(disabledAlpha = SplitToggleButtonTokens.DisabledOpacity),
- disabledUncheckedContentColor =
- fromToken(SplitToggleButtonTokens.DisabledUncheckedContentColor)
- .toDisabledColor(disabledAlpha = SplitToggleButtonTokens.DisabledOpacity),
- disabledUncheckedSecondaryContentColor =
- fromToken(SplitToggleButtonTokens.DisabledUncheckedSecondaryLabelColor)
- .toDisabledColor(disabledAlpha = SplitToggleButtonTokens.DisabledOpacity),
- disabledUncheckedSplitContainerColor =
- fromToken(SplitToggleButtonTokens.DisabledUncheckedSplitContainerColor)
- .toDisabledColor(disabledAlpha = SplitToggleButtonTokens.DisabledOpacity)
- ).also { defaultSplitToggleButtonColorsCached = it }
+ return defaultSplitToggleButtonColorsCached
+ ?: SplitToggleButtonColors(
+ checkedContainerColor =
+ fromToken(SplitToggleButtonTokens.CheckedContainerColor),
+ checkedContentColor =
+ fromToken(SplitToggleButtonTokens.CheckedContentColor),
+ checkedSecondaryContentColor =
+ fromToken(SplitToggleButtonTokens.CheckedSecondaryLabelColor)
+ .copy(alpha = SplitToggleButtonTokens.CheckedSecondaryLabelOpacity),
+ checkedSplitContainerColor =
+ fromToken(SplitToggleButtonTokens.CheckedSplitContainerColor)
+ .copy(alpha = SplitToggleButtonTokens.CheckedSplitContainerOpacity),
+ uncheckedContainerColor =
+ fromToken(SplitToggleButtonTokens.UncheckedContainerColor),
+ uncheckedContentColor =
+ fromToken(SplitToggleButtonTokens.UncheckedContentColor),
+ uncheckedSecondaryContentColor =
+ fromToken(SplitToggleButtonTokens.UncheckedSecondaryLabelColor),
+ uncheckedSplitContainerColor =
+ fromToken(SplitToggleButtonTokens.UncheckedSplitContainerColor),
+ disabledCheckedContainerColor =
+ fromToken(SplitToggleButtonTokens.DisabledCheckedContainerColor)
+ .toDisabledColor(
+ disabledAlpha = SplitToggleButtonTokens.DisabledOpacity
+ ),
+ disabledCheckedContentColor =
+ fromToken(SplitToggleButtonTokens.DisabledCheckedContentColor)
+ .toDisabledColor(
+ disabledAlpha = SplitToggleButtonTokens.DisabledOpacity
+ ),
+ disabledCheckedSecondaryContentColor =
+ fromToken(SplitToggleButtonTokens.DisabledCheckedSecondaryLabelColor)
+ .copy(
+ alpha =
+ SplitToggleButtonTokens.DisabledCheckedSecondaryLabelOpacity
+ )
+ .toDisabledColor(
+ disabledAlpha = SplitToggleButtonTokens.DisabledOpacity
+ ),
+ disabledCheckedSplitContainerColor =
+ fromToken(SplitToggleButtonTokens.DisabledCheckedSplitContainerColor)
+ .copy(
+ alpha =
+ SplitToggleButtonTokens.DisabledCheckedSplitContainerOpacity
+ )
+ .toDisabledColor(
+ disabledAlpha = SplitToggleButtonTokens.DisabledOpacity
+ ),
+ disabledUncheckedContainerColor =
+ fromToken(SplitToggleButtonTokens.DisabledUncheckedContainerColor)
+ .toDisabledColor(
+ disabledAlpha = SplitToggleButtonTokens.DisabledOpacity
+ ),
+ disabledUncheckedContentColor =
+ fromToken(SplitToggleButtonTokens.DisabledUncheckedContentColor)
+ .toDisabledColor(
+ disabledAlpha = SplitToggleButtonTokens.DisabledOpacity
+ ),
+ disabledUncheckedSecondaryContentColor =
+ fromToken(SplitToggleButtonTokens.DisabledUncheckedSecondaryLabelColor)
+ .toDisabledColor(
+ disabledAlpha = SplitToggleButtonTokens.DisabledOpacity
+ ),
+ disabledUncheckedSplitContainerColor =
+ fromToken(SplitToggleButtonTokens.DisabledUncheckedSplitContainerColor)
+ .toDisabledColor(
+ disabledAlpha = SplitToggleButtonTokens.DisabledOpacity
+ )
+ )
+ .also { defaultSplitToggleButtonColorsCached = it }
}
}
/**
- * Represents the different container and content colors used for toggle buttons
- * ([ToggleButton], [IconToggleButton], and [TextToggleButton]) in various states,
- * that are checked, unchecked, enabled and disabled.
+ * Represents the different container and content colors used for toggle buttons ([ToggleButton],
+ * [IconToggleButton], and [TextToggleButton]) in various states, that are checked, unchecked,
+ * enabled and disabled.
*
- * @constructor [ToggleButtonColors] constructor to be used with [ToggleButton]
* @param checkedContainerColor Container or background color when the toggle button is checked
* @param checkedContentColor Color of the content like label when the toggle button is checked
* @param checkedSecondaryContentColor Color of the secondary content like secondary label when the
- * toggle button is checked
+ * toggle button is checked
* @param checkedIconColor Color of the icon when the toggle button is checked
* @param uncheckedContainerColor Container or background color when the toggle button is unchecked
* @param uncheckedContentColor Color of the content like label when the toggle button is unchecked
* @param uncheckedSecondaryContentColor Color of the secondary content like secondary label when
- * the toggle button is unchecked
+ * the toggle button is unchecked
* @param uncheckedIconColor Color of the icon when the toggle button is unchecked
* @param disabledCheckedContainerColor Container or background color when the toggle button is
- * disabled and checked
- * @param disabledCheckedContentColor Color of content like label when the toggle button is
- * disabled and checked
+ * disabled and checked
+ * @param disabledCheckedContentColor Color of content like label when the toggle button is disabled
+ * and checked
* @param disabledCheckedSecondaryContentColor Color of the secondary content like secondary label
- * when the toggle button is disabled and checked
+ * when the toggle button is disabled and checked
* @param disabledCheckedIconColor Icon color when the toggle button is disabled and checked
* @param disabledUncheckedContainerColor Container or background color when the toggle button is
- * disabled and unchecked
+ * disabled and unchecked
* @param disabledUncheckedContentColor Color of the content like label when the toggle button is
- * disabled and unchecked
+ * disabled and unchecked
* @param disabledUncheckedSecondaryContentColor Color of the secondary content like secondary label
- * when the toggle button is disabled and unchecked
+ * when the toggle button is disabled and unchecked
* @param disabledUncheckedIconColor Icon color when the toggle button is disabled and unchecked
+ * @constructor [ToggleButtonColors] constructor to be used with [ToggleButton]
*/
@Immutable
-class ToggleButtonColors constructor(
+class ToggleButtonColors
+constructor(
val checkedContainerColor: Color,
val checkedContentColor: Color,
val checkedSecondaryContentColor: Color,
@@ -601,19 +626,19 @@
*
* @param checkedContainerColor Container or background color of the toggle button when checked
* @param checkedContentColor Color of the content (text or icon) of the toggle button when
- * checked
+ * checked
* @param uncheckedContainerColor Container or background color of the toggle button when
- * unchecked
+ * unchecked
* @param uncheckedContentColor Color of the content (text or icon) of the toggle button when
- * unchecked
+ * unchecked
* @param disabledCheckedContainerColor Container or background color of the toggle button when
- * disabled and checked
+ * disabled and checked
* @param disabledCheckedContentColor Color of the content (icon or text) toggle button when
- * disabled and unchecked
+ * disabled and unchecked
* @param disabledUncheckedContainerColor Container or background color of the toggle button
- * when disabled and unchecked
+ * when disabled and unchecked
* @param disabledUncheckedContentColor Color of the content (icon or text) toggle button when
- * disabled and unchecked
+ * disabled and unchecked
*/
constructor(
checkedContainerColor: Color,
@@ -660,35 +685,40 @@
disabledUncheckedContentColor: Color,
disabledUncheckedSecondaryContentColor: Color,
disabledUncheckedIconColor: Color,
- ): ToggleButtonColors = ToggleButtonColors(
- checkedContainerColor = checkedContainerColor.takeOrElse { this.checkedContainerColor },
- checkedContentColor = checkedContentColor.takeOrElse { this.checkedContentColor },
- checkedSecondaryContentColor = checkedSecondaryContentColor
- .takeOrElse { this.checkedSecondaryContentColor },
- checkedIconColor = checkedIconColor.takeOrElse { this.checkedIconColor },
- uncheckedContainerColor = uncheckedContainerColor
- .takeOrElse { this.uncheckedContainerColor },
- uncheckedContentColor = uncheckedContentColor.takeOrElse { this.uncheckedContentColor },
- uncheckedSecondaryContentColor = uncheckedSecondaryContentColor
- .takeOrElse { this.uncheckedSecondaryContentColor },
- uncheckedIconColor = uncheckedIconColor.takeOrElse { this.uncheckedIconColor },
- disabledCheckedContainerColor = disabledCheckedContainerColor
- .takeOrElse { this.disabledCheckedContainerColor },
- disabledCheckedContentColor = disabledCheckedContentColor
- .takeOrElse { this.disabledCheckedContentColor },
- disabledCheckedSecondaryContentColor = disabledCheckedSecondaryContentColor
- .takeOrElse { this.disabledCheckedSecondaryContentColor },
- disabledCheckedIconColor = disabledCheckedIconColor
- .takeOrElse { this.disabledCheckedIconColor },
- disabledUncheckedContainerColor = disabledUncheckedContainerColor
- .takeOrElse { this.disabledUncheckedContainerColor },
- disabledUncheckedContentColor = disabledUncheckedContentColor
- .takeOrElse { this.disabledUncheckedContentColor },
- disabledUncheckedSecondaryContentColor = disabledUncheckedSecondaryContentColor
- .takeOrElse { this.disabledUncheckedSecondaryContentColor },
- disabledUncheckedIconColor = disabledUncheckedIconColor
- .takeOrElse { this.disabledUncheckedIconColor },
- )
+ ): ToggleButtonColors =
+ ToggleButtonColors(
+ checkedContainerColor = checkedContainerColor.takeOrElse { this.checkedContainerColor },
+ checkedContentColor = checkedContentColor.takeOrElse { this.checkedContentColor },
+ checkedSecondaryContentColor =
+ checkedSecondaryContentColor.takeOrElse { this.checkedSecondaryContentColor },
+ checkedIconColor = checkedIconColor.takeOrElse { this.checkedIconColor },
+ uncheckedContainerColor =
+ uncheckedContainerColor.takeOrElse { this.uncheckedContainerColor },
+ uncheckedContentColor = uncheckedContentColor.takeOrElse { this.uncheckedContentColor },
+ uncheckedSecondaryContentColor =
+ uncheckedSecondaryContentColor.takeOrElse { this.uncheckedSecondaryContentColor },
+ uncheckedIconColor = uncheckedIconColor.takeOrElse { this.uncheckedIconColor },
+ disabledCheckedContainerColor =
+ disabledCheckedContainerColor.takeOrElse { this.disabledCheckedContainerColor },
+ disabledCheckedContentColor =
+ disabledCheckedContentColor.takeOrElse { this.disabledCheckedContentColor },
+ disabledCheckedSecondaryContentColor =
+ disabledCheckedSecondaryContentColor.takeOrElse {
+ this.disabledCheckedSecondaryContentColor
+ },
+ disabledCheckedIconColor =
+ disabledCheckedIconColor.takeOrElse { this.disabledCheckedIconColor },
+ disabledUncheckedContainerColor =
+ disabledUncheckedContainerColor.takeOrElse { this.disabledUncheckedContainerColor },
+ disabledUncheckedContentColor =
+ disabledUncheckedContentColor.takeOrElse { this.disabledUncheckedContentColor },
+ disabledUncheckedSecondaryContentColor =
+ disabledUncheckedSecondaryContentColor.takeOrElse {
+ this.disabledUncheckedSecondaryContentColor
+ },
+ disabledUncheckedIconColor =
+ disabledUncheckedIconColor.takeOrElse { this.disabledUncheckedIconColor },
+ )
/** Copy function for [IconToggleButton] and [TextToggleButton]. */
internal fun copy(
@@ -700,25 +730,25 @@
disabledCheckedContentColor: Color,
disabledUncheckedContainerColor: Color,
disabledUncheckedContentColor: Color,
- ): ToggleButtonColors = ToggleButtonColors(
- checkedContainerColor = checkedContainerColor.takeOrElse { this.checkedContainerColor },
- checkedContentColor = checkedContentColor.takeOrElse { this.checkedContentColor },
- uncheckedContainerColor = uncheckedContainerColor
- .takeOrElse { this.uncheckedContainerColor },
- uncheckedContentColor = uncheckedContentColor.takeOrElse { this.uncheckedContentColor },
- disabledCheckedContainerColor = disabledCheckedContainerColor
- .takeOrElse { this.disabledCheckedContainerColor },
- disabledCheckedContentColor = disabledCheckedContentColor
- .takeOrElse { this.disabledCheckedContentColor },
- disabledUncheckedContainerColor = disabledUncheckedContainerColor
- .takeOrElse { this.disabledUncheckedContainerColor },
- disabledUncheckedContentColor = disabledUncheckedContentColor
- .takeOrElse { this.disabledUncheckedContentColor },
- )
+ ): ToggleButtonColors =
+ ToggleButtonColors(
+ checkedContainerColor = checkedContainerColor.takeOrElse { this.checkedContainerColor },
+ checkedContentColor = checkedContentColor.takeOrElse { this.checkedContentColor },
+ uncheckedContainerColor =
+ uncheckedContainerColor.takeOrElse { this.uncheckedContainerColor },
+ uncheckedContentColor = uncheckedContentColor.takeOrElse { this.uncheckedContentColor },
+ disabledCheckedContainerColor =
+ disabledCheckedContainerColor.takeOrElse { this.disabledCheckedContainerColor },
+ disabledCheckedContentColor =
+ disabledCheckedContentColor.takeOrElse { this.disabledCheckedContentColor },
+ disabledUncheckedContainerColor =
+ disabledUncheckedContainerColor.takeOrElse { this.disabledUncheckedContainerColor },
+ disabledUncheckedContentColor =
+ disabledUncheckedContentColor.takeOrElse { this.disabledUncheckedContentColor },
+ )
/**
- * Determines the container color based on whether the toggle button is [enabled]
- * and [checked].
+ * Determines the container color based on whether the toggle button is [enabled] and [checked].
*
* @param enabled Whether the toggle button is enabled
* @param checked Whether the toggle button is checked
@@ -736,8 +766,7 @@
)
/**
- * Determines the content color based on whether the toggle button is [enabled]
- * and [checked].
+ * Determines the content color based on whether the toggle button is [enabled] and [checked].
*
* @param enabled Whether the toggle button is enabled
* @param checked Whether the toggle button is checked
@@ -773,8 +802,8 @@
)
/**
- * Represents the icon color for the [ToggleButton] depending on the
- * [enabled] and [checked] properties.
+ * Represents the icon color for the [ToggleButton] depending on the [enabled] and [checked]
+ * properties.
*
* @param enabled Whether the ToggleButton is enabled.
* @param checked Whether the ToggleButton is currently checked or unchecked.
@@ -808,17 +837,14 @@
if (uncheckedIconColor != other.uncheckedIconColor) return false
if (disabledCheckedContainerColor != other.disabledCheckedContainerColor) return false
if (disabledCheckedContentColor != other.disabledCheckedContentColor) return false
- if (disabledCheckedSecondaryContentColor !=
- other.disabledCheckedSecondaryContentColor
- ) return false
+ if (disabledCheckedSecondaryContentColor != other.disabledCheckedSecondaryContentColor)
+ return false
if (disabledCheckedIconColor != other.disabledCheckedIconColor) return false
if (disabledUncheckedContainerColor != other.disabledUncheckedContainerColor) return false
if (disabledUncheckedContentColor != other.disabledUncheckedContentColor) return false
- if (disabledUncheckedSecondaryContentColor !=
- other.disabledUncheckedSecondaryContentColor
- ) return false
- if (disabledUncheckedIconColor != other.disabledUncheckedIconColor)
+ if (disabledUncheckedSecondaryContentColor != other.disabledUncheckedSecondaryContentColor)
return false
+ if (disabledUncheckedIconColor != other.disabledUncheckedIconColor) return false
return true
}
@@ -847,40 +873,41 @@
/**
* Represents the different colors used in [SplitToggleButton] in different states.
*
- * @constructor [SplitToggleButtonColors] constructor to be used with [SplitToggleButton]
* @param checkedContainerColor Container or background color when the split toggle button is
- * checked
+ * checked
* @param checkedContentColor Color of the content like label when the split toggle button is
- * checked
+ * checked
* @param checkedSecondaryContentColor Color of the secondary content like secondary label when the
- * split toggle button is checked
+ * split toggle button is checked
* @param checkedSplitContainerColor Split container color when the split toggle button is checked
* @param uncheckedContainerColor Container or background color when the split toggle button is
- * unchecked
+ * unchecked
* @param uncheckedContentColor Color of the content like label when the split toggle button is
- * unchecked
+ * unchecked
* @param uncheckedSecondaryContentColor Color of the secondary content like secondary label when
- * the split toggle button is unchecked
+ * the split toggle button is unchecked
* @param uncheckedSplitContainerColor Split container color when the split toggle button is
- * unchecked
- * @param disabledCheckedContainerColor Container color when the split toggle button is disabled
- * and checked
+ * unchecked
+ * @param disabledCheckedContainerColor Container color when the split toggle button is disabled and
+ * checked
* @param disabledCheckedContentColor Color of the content like label when the split toggle button
- * is disabled and checked
+ * is disabled and checked
* @param disabledCheckedSecondaryContentColor Color of the secondary content like secondary label
- * when the split toggle button is disabled and checked
+ * when the split toggle button is disabled and checked
* @param disabledCheckedSplitContainerColor Split container color when the split toggle button is
- * disabled and checked
+ * disabled and checked
* @param disabledUncheckedContainerColor Container color when the split toggle button is unchecked
- * and disabled
- * @param disabledUncheckedContentColor Color of the content like label when the split toggle
- * button is unchecked and disabled
- * @param disabledUncheckedSecondaryContentColor Color of the secondary content like secondary
- * label when the split toggle button is unchecked and disabled
- * @param disabledUncheckedSplitContainerColor Split container color when the split toggle button
- * is unchecked and disabled
+ * and disabled
+ * @param disabledUncheckedContentColor Color of the content like label when the split toggle button
+ * is unchecked and disabled
+ * @param disabledUncheckedSecondaryContentColor Color of the secondary content like secondary label
+ * when the split toggle button is unchecked and disabled
+ * @param disabledUncheckedSplitContainerColor Split container color when the split toggle button is
+ * unchecked and disabled
+ * @constructor [SplitToggleButtonColors] constructor to be used with [SplitToggleButton]
*/
-class SplitToggleButtonColors constructor(
+class SplitToggleButtonColors
+constructor(
val checkedContainerColor: Color,
val checkedContentColor: Color,
val checkedSecondaryContentColor: Color,
@@ -916,41 +943,50 @@
disabledUncheckedContentColor: Color,
disabledUncheckedSecondaryContentColor: Color,
disabledUncheckedSplitContainerColor: Color,
- ): SplitToggleButtonColors = SplitToggleButtonColors(
- checkedContainerColor = checkedContainerColor.takeOrElse { this.checkedContainerColor },
- checkedContentColor = checkedContentColor.takeOrElse { this.checkedContentColor },
- checkedSecondaryContentColor = checkedSecondaryContentColor
- .takeOrElse { this.checkedSecondaryContentColor },
- checkedSplitContainerColor = checkedSplitContainerColor
- .takeOrElse { this.checkedSplitContainerColor },
- uncheckedContainerColor = uncheckedContainerColor
- .takeOrElse { this.uncheckedContainerColor },
- uncheckedContentColor = uncheckedContentColor.takeOrElse { this.uncheckedContentColor },
- uncheckedSecondaryContentColor = uncheckedSecondaryContentColor
- .takeOrElse { this.uncheckedSecondaryContentColor },
- uncheckedSplitContainerColor = uncheckedSplitContainerColor
- .takeOrElse { this.uncheckedSplitContainerColor },
- disabledCheckedContainerColor = disabledCheckedContainerColor
- .takeOrElse { this.disabledCheckedContainerColor },
- disabledCheckedContentColor = disabledCheckedContentColor
- .takeOrElse { this.disabledCheckedContentColor },
- disabledCheckedSecondaryContentColor = disabledCheckedSecondaryContentColor
- .takeOrElse { this.disabledCheckedSecondaryContentColor },
- disabledCheckedSplitContainerColor = disabledCheckedSplitContainerColor
- .takeOrElse { this.disabledCheckedSplitContainerColor },
- disabledUncheckedContainerColor = disabledUncheckedContainerColor
- .takeOrElse { this.disabledUncheckedContainerColor },
- disabledUncheckedContentColor = disabledUncheckedContentColor
- .takeOrElse { this.disabledUncheckedContentColor },
- disabledUncheckedSecondaryContentColor = disabledUncheckedSecondaryContentColor
- .takeOrElse { this.disabledUncheckedSecondaryContentColor },
- disabledUncheckedSplitContainerColor = disabledUncheckedSplitContainerColor
- .takeOrElse { this.disabledUncheckedSplitContainerColor },
- )
+ ): SplitToggleButtonColors =
+ SplitToggleButtonColors(
+ checkedContainerColor = checkedContainerColor.takeOrElse { this.checkedContainerColor },
+ checkedContentColor = checkedContentColor.takeOrElse { this.checkedContentColor },
+ checkedSecondaryContentColor =
+ checkedSecondaryContentColor.takeOrElse { this.checkedSecondaryContentColor },
+ checkedSplitContainerColor =
+ checkedSplitContainerColor.takeOrElse { this.checkedSplitContainerColor },
+ uncheckedContainerColor =
+ uncheckedContainerColor.takeOrElse { this.uncheckedContainerColor },
+ uncheckedContentColor = uncheckedContentColor.takeOrElse { this.uncheckedContentColor },
+ uncheckedSecondaryContentColor =
+ uncheckedSecondaryContentColor.takeOrElse { this.uncheckedSecondaryContentColor },
+ uncheckedSplitContainerColor =
+ uncheckedSplitContainerColor.takeOrElse { this.uncheckedSplitContainerColor },
+ disabledCheckedContainerColor =
+ disabledCheckedContainerColor.takeOrElse { this.disabledCheckedContainerColor },
+ disabledCheckedContentColor =
+ disabledCheckedContentColor.takeOrElse { this.disabledCheckedContentColor },
+ disabledCheckedSecondaryContentColor =
+ disabledCheckedSecondaryContentColor.takeOrElse {
+ this.disabledCheckedSecondaryContentColor
+ },
+ disabledCheckedSplitContainerColor =
+ disabledCheckedSplitContainerColor.takeOrElse {
+ this.disabledCheckedSplitContainerColor
+ },
+ disabledUncheckedContainerColor =
+ disabledUncheckedContainerColor.takeOrElse { this.disabledUncheckedContainerColor },
+ disabledUncheckedContentColor =
+ disabledUncheckedContentColor.takeOrElse { this.disabledUncheckedContentColor },
+ disabledUncheckedSecondaryContentColor =
+ disabledUncheckedSecondaryContentColor.takeOrElse {
+ this.disabledUncheckedSecondaryContentColor
+ },
+ disabledUncheckedSplitContainerColor =
+ disabledUncheckedSplitContainerColor.takeOrElse {
+ this.disabledUncheckedSplitContainerColor
+ },
+ )
/**
- * Determines the container color based on whether the [SplitToggleButton] is [enabled]
- * and [checked].
+ * Determines the container color based on whether the [SplitToggleButton] is [enabled] and
+ * [checked].
*
* @param enabled Whether the [SplitToggleButton] is enabled
* @param checked Whether the [SplitToggleButton] is currently checked
@@ -968,8 +1004,8 @@
)
/**
- * Determines the content color based on whether the [SplitToggleButton] is [enabled]
- * and [checked].
+ * Determines the content color based on whether the [SplitToggleButton] is [enabled] and
+ * [checked].
*
* @param enabled Whether the [SplitToggleButton] is enabled
* @param checked Whether the [SplitToggleButton] is currently checked
@@ -987,8 +1023,8 @@
)
/**
- * Represents the secondary content color for the [SplitToggleButton] depending on the
- * [enabled] and [checked] properties.
+ * Represents the secondary content color for the [SplitToggleButton] depending on the [enabled]
+ * and [checked] properties.
*
* @param enabled Whether the [SplitToggleButton] is enabled.
* @param checked Whether the [SplitToggleButton] is currently checked or unchecked.
@@ -1006,8 +1042,8 @@
)
/**
- * Represents the split container for the [SplitToggleButton] color depending on the
- * [enabled] and [checked] properties.
+ * Represents the split container for the [SplitToggleButton] color depending on the [enabled]
+ * and [checked] properties.
*
* @param enabled Whether the [SplitToggleButton] is enabled.
* @param checked Whether the [SplitToggleButton] is currently checked or unchecked.
@@ -1041,16 +1077,14 @@
if (uncheckedSplitContainerColor != other.uncheckedSplitContainerColor) return false
if (disabledCheckedContainerColor != other.disabledCheckedContainerColor) return false
if (disabledCheckedContentColor != other.disabledCheckedContentColor) return false
- if (disabledCheckedSecondaryContentColor !=
- other.disabledCheckedSecondaryContentColor
- ) return false
+ if (disabledCheckedSecondaryContentColor != other.disabledCheckedSecondaryContentColor)
+ return false
if (disabledCheckedSplitContainerColor != other.disabledCheckedSplitContainerColor)
return false
if (disabledUncheckedContainerColor != other.disabledUncheckedContainerColor) return false
if (disabledUncheckedContentColor != other.disabledUncheckedContentColor) return false
- if (disabledUncheckedSecondaryContentColor !=
- other.disabledUncheckedSecondaryContentColor
- ) return false
+ if (disabledUncheckedSecondaryContentColor != other.disabledUncheckedSecondaryContentColor)
+ return false
if (disabledUncheckedSplitContainerColor != other.disabledUncheckedSplitContainerColor)
return false
@@ -1079,17 +1113,14 @@
}
/**
- * [ToggleControlScope] provides enabled and checked properties.
- * This allows toggle controls to omit enabled/checked parameters as they given by the scope.
+ * [ToggleControlScope] provides enabled and checked properties. This allows toggle controls to omit
+ * enabled/checked parameters as they given by the scope.
*
- * @param isEnabled Controls the enabled state of the toggle control.
- * When `false`, the control is displayed with disabled colors.
+ * @param isEnabled Controls the enabled state of the toggle control. When `false`, the control is
+ * displayed with disabled colors.
* @param isChecked Indicates whether the control is currently checked.
*/
-class ToggleControlScope(
- val isEnabled: Boolean,
- val isChecked: Boolean
-)
+class ToggleControlScope(val isEnabled: Boolean, val isChecked: Boolean)
private val TOGGLE_CONTROL_WIDTH = 32.dp
private val TOGGLE_CONTROL_HEIGHT = 24.dp
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/ToggleControls.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/ToggleControls.kt
index 7180119..eb214e9 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/ToggleControls.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/ToggleControls.kt
@@ -53,60 +53,53 @@
import androidx.wear.compose.materialcore.isLayoutDirectionRtl
/**
- * [Checkbox] provides an animated checkbox for use as a toggle control in
- * [ToggleButton] or [SplitToggleButton].
+ * [Checkbox] provides an animated checkbox for use as a toggle control in [ToggleButton] or
+ * [SplitToggleButton].
*
* Checkbox sample:
+ *
* @sample androidx.wear.compose.material3.samples.ToggleButtonWithCheckbox
*
- * @param modifier Modifier to be applied to the checkbox. This can be used to provide a
- * content description for accessibility.
+ * @param modifier Modifier to be applied to the checkbox. This can be used to provide a content
+ * description for accessibility.
* @param colors [CheckboxColors] from which the box and checkmark colors will be obtained.
*/
@Composable
fun ToggleControlScope.Checkbox(
modifier: Modifier = Modifier,
colors: CheckboxColors = CheckboxDefaults.colors(),
-) = androidx.wear.compose.materialcore.Checkbox(
- checked = isChecked,
- modifier = modifier,
- boxColor = { isEnabled, isChecked ->
- colors.boxColor(
- enabled = isEnabled,
- checked = isChecked
- )
- },
- checkmarkColor = { isEnabled, isChecked ->
- colors.checkmarkColor(
- enabled = isEnabled,
- checked = isChecked
- )
- },
- enabled = isEnabled,
- onCheckedChange = null,
- interactionSource = null,
- drawBox = { drawScope, color, progress, isRtl ->
- drawScope.drawBox(
- color = color,
- progress = progress,
- isRtl = isRtl
- )
- },
- progressAnimationSpec = PROGRESS_ANIMATION_SPEC,
- width = WIDTH,
- height = CHECKBOX_HEIGHT,
- ripple = rippleOrFallbackImplementation()
-)
+) =
+ androidx.wear.compose.materialcore.Checkbox(
+ checked = isChecked,
+ modifier = modifier,
+ boxColor = { isEnabled, isChecked ->
+ colors.boxColor(enabled = isEnabled, checked = isChecked)
+ },
+ checkmarkColor = { isEnabled, isChecked ->
+ colors.checkmarkColor(enabled = isEnabled, checked = isChecked)
+ },
+ enabled = isEnabled,
+ onCheckedChange = null,
+ interactionSource = null,
+ drawBox = { drawScope, color, progress, isRtl ->
+ drawScope.drawBox(color = color, progress = progress, isRtl = isRtl)
+ },
+ progressAnimationSpec = PROGRESS_ANIMATION_SPEC,
+ width = WIDTH,
+ height = CHECKBOX_HEIGHT,
+ ripple = rippleOrFallbackImplementation()
+ )
/**
- * [Switch] provides an animated switch for use as a toggle control in
- * [ToggleButton] or [SplitToggleButton].
+ * [Switch] provides an animated switch for use as a toggle control in [ToggleButton] or
+ * [SplitToggleButton].
*
* Switch samples:
+ *
* @sample androidx.wear.compose.material3.samples.ToggleButtonWithSwitch
*
- * @param modifier Modifier to be applied to the switch. This can be used to provide a
- * content description for accessibility.
+ * @param modifier Modifier to be applied to the switch. This can be used to provide a content
+ * description for accessibility.
* @param colors [SwitchColors] from which the colors of the thumb and track will be obtained.
*/
@Composable
@@ -117,43 +110,44 @@
val isRtl = isLayoutDirectionRtl()
val targetState = if (isChecked) SelectionStage.Checked else SelectionStage.Unchecked
val transition = updateTransition(targetState, label = "switchTransition")
- val thumbProgress = transition.animateFloat(
- transitionSpec = { SWITCH_PROGRESS_ANIMATION_SPEC }, label = "switchTransition"
- ) {
- when (it) {
- SelectionStage.Unchecked -> 0f
- SelectionStage.Checked -> 1f
+ val thumbProgress =
+ transition.animateFloat(
+ transitionSpec = { SWITCH_PROGRESS_ANIMATION_SPEC },
+ label = "switchTransition"
+ ) {
+ when (it) {
+ SelectionStage.Unchecked -> 0f
+ SelectionStage.Checked -> 1f
+ }
}
- }
val thumbColor = colors.thumbColor(enabled = isEnabled, checked = isChecked).value
val thumbIconColor = colors.thumbIconColor(enabled = isEnabled, checked = isChecked).value
val trackColor = colors.trackColor(enabled = isEnabled, checked = isChecked).value
val trackBorderColor = colors.trackBorderColor(enabled = isEnabled, checked = isChecked).value
Box(
- modifier = modifier
- .semantics { this.role = Role.Switch }
- .height(SWITCH_HEIGHT)
- .width(WIDTH)
- .border(
- width = SWITCH_TRACK_WIDTH,
- shape = CircleShape,
- color = if (trackColor == trackBorderColor) Color.Transparent else trackBorderColor
- )
- .background(
- color = trackColor,
- shape = CircleShape
- )
- .drawBehind {
- drawThumbAndTick(
- isEnabled,
- isChecked,
- thumbColor,
- thumbProgress.value,
- thumbIconColor,
- isRtl
+ modifier =
+ modifier
+ .semantics { this.role = Role.Switch }
+ .height(SWITCH_HEIGHT)
+ .width(WIDTH)
+ .border(
+ width = SWITCH_TRACK_WIDTH,
+ shape = CircleShape,
+ color =
+ if (trackColor == trackBorderColor) Color.Transparent else trackBorderColor
)
- }
- .wrapContentSize(Alignment.CenterEnd)
+ .background(color = trackColor, shape = CircleShape)
+ .drawBehind {
+ drawThumbAndTick(
+ isEnabled,
+ isChecked,
+ thumbColor,
+ thumbProgress.value,
+ thumbIconColor,
+ isRtl
+ )
+ }
+ .wrapContentSize(Alignment.CenterEnd)
)
}
@@ -161,17 +155,15 @@
* Represents the content colors used in [Checkbox] in different states.
*
* @param checkedBoxColor The box color of [Checkbox] when enabled and checked.
- * @param checkedCheckmarkColor The check mark color of [Checkbox] when enabled
- * and checked.
+ * @param checkedCheckmarkColor The check mark color of [Checkbox] when enabled and checked.
* @param uncheckedBoxColor The box color of [Checkbox] when enabled and unchecked.
- * @param uncheckedCheckmarkColor The check mark color of [Checkbox] when enabled
- * and unchecked.
+ * @param uncheckedCheckmarkColor The check mark color of [Checkbox] when enabled and unchecked.
* @param disabledCheckedBoxColor The box color of [Checkbox] when disabled and checked.
- * @param disabledCheckedCheckmarkColor The check mark color of [Checkbox] when disabled
- * and checked.
+ * @param disabledCheckedCheckmarkColor The check mark color of [Checkbox] when disabled and
+ * checked.
* @param disabledUncheckedBoxColor The box color of [Checkbox] when disabled and unchecked.
- * @param disabledUncheckedCheckmarkColor The check mark color of [Checkbox] when disabled
- * and unchecked.
+ * @param disabledUncheckedCheckmarkColor The check mark color of [Checkbox] when disabled and
+ * unchecked.
*/
@Immutable
class CheckboxColors(
@@ -193,15 +185,16 @@
* @param checked Whether the [Checkbox] is currently checked or unchecked
*/
@Composable
- internal fun boxColor(enabled: Boolean, checked: Boolean): State<Color> = animateSelectionColor(
- enabled = enabled,
- checked = checked,
- checkedColor = checkedBoxColor,
- uncheckedColor = uncheckedBoxColor,
- disabledCheckedColor = disabledCheckedBoxColor,
- disabledUncheckedColor = disabledUncheckedBoxColor,
- animationSpec = COLOR_ANIMATION_SPEC
- )
+ internal fun boxColor(enabled: Boolean, checked: Boolean): State<Color> =
+ animateSelectionColor(
+ enabled = enabled,
+ checked = checked,
+ checkedColor = checkedBoxColor,
+ uncheckedColor = uncheckedBoxColor,
+ disabledCheckedColor = disabledCheckedBoxColor,
+ disabledUncheckedColor = disabledUncheckedBoxColor,
+ animationSpec = COLOR_ANIMATION_SPEC
+ )
/**
* Represents the checkmark color for this [Checkbox], depending on the [enabled] and [checked]
@@ -265,14 +258,14 @@
* @param disabledCheckedThumbColor The thumb color of [Switch] when disabled and checked.
* @param disabledCheckedThumbIconColor The thumb icon color of [Switch] when disabled and checked.
* @param disabledCheckedTrackColor The track color of [Switch] when disabled and checked.
- * @param disabledCheckedTrackBorderColor The track border color of [Switch] when disabled
- * and checked.
+ * @param disabledCheckedTrackBorderColor The track border color of [Switch] when disabled and
+ * checked.
* @param disabledUncheckedThumbColor The thumb color of [Switch] when disabled and unchecked.
- * @param disabledUncheckedThumbIconColor The thumb icon color of [Switch] when disabled
- * and unchecked.
+ * @param disabledUncheckedThumbIconColor The thumb icon color of [Switch] when disabled and
+ * unchecked.
* @param disabledUncheckedTrackColor The track color of [Switch] when disabled and unchecked.
- * @param disabledUncheckedTrackBorderColor The track border color of [Switch] when disabled
- * and unchecked.
+ * @param disabledUncheckedTrackBorderColor The track border color of [Switch] when disabled and
+ * unchecked.
*/
@Immutable
class SwitchColors(
@@ -386,26 +379,23 @@
}
}
-/**
- * Contains the default values used by [Checkbox].
- */
+/** Contains the default values used by [Checkbox]. */
object CheckboxDefaults {
/**
* Creates a [CheckboxColors] for use in a [Checkbox].
*
* @param checkedBoxColor The box color of this [Checkbox] when enabled and checked.
- * @param checkedCheckmarkColor The check mark color of this [Checkbox] when enabled
- * and checked.
+ * @param checkedCheckmarkColor The check mark color of this [Checkbox] when enabled and
+ * checked.
* @param uncheckedBoxColor The box color of this [Checkbox] when enabled and unchecked.
- * @param uncheckedCheckmarkColor The check mark color of this [Checkbox] when enabled
- * and unchecked.
+ * @param uncheckedCheckmarkColor The check mark color of this [Checkbox] when enabled and
+ * unchecked.
* @param disabledCheckedBoxColor The box color of this [Checkbox] when disabled and checked
* @param disabledCheckedCheckmarkColor The check mark color of this [Checkbox] when disabled
- * and checked
- * @param disabledUncheckedBoxColor The box color of this [Checkbox] when disabled and
- * unchecked
+ * and checked
+ * @param disabledUncheckedBoxColor The box color of this [Checkbox] when disabled and unchecked
* @param disabledUncheckedCheckmarkColor The check mark color of this [Checkbox] when disabled
- * and unchecked
+ * and unchecked
*/
@Composable
fun colors(
@@ -420,21 +410,20 @@
disabledUncheckedBoxColor: Color =
MaterialTheme.colorScheme.onSurface.toDisabledColor(disabledAlpha = 0.12f),
disabledUncheckedCheckmarkColor: Color = Color.Transparent
- ): CheckboxColors = CheckboxColors(
- checkedBoxColor = checkedBoxColor,
- checkedCheckmarkColor = checkedCheckmarkColor,
- uncheckedBoxColor = uncheckedBoxColor,
- uncheckedCheckmarkColor = uncheckedCheckmarkColor,
- disabledCheckedBoxColor = disabledCheckedBoxColor,
- disabledCheckedCheckmarkColor = disabledCheckedCheckmarkColor,
- disabledUncheckedBoxColor = disabledUncheckedBoxColor,
- disabledUncheckedCheckmarkColor = disabledUncheckedCheckmarkColor
- )
+ ): CheckboxColors =
+ CheckboxColors(
+ checkedBoxColor = checkedBoxColor,
+ checkedCheckmarkColor = checkedCheckmarkColor,
+ uncheckedBoxColor = uncheckedBoxColor,
+ uncheckedCheckmarkColor = uncheckedCheckmarkColor,
+ disabledCheckedBoxColor = disabledCheckedBoxColor,
+ disabledCheckedCheckmarkColor = disabledCheckedCheckmarkColor,
+ disabledUncheckedBoxColor = disabledUncheckedBoxColor,
+ disabledUncheckedCheckmarkColor = disabledUncheckedCheckmarkColor
+ )
}
-/**
- * Contains the default values used by [Switch].
- */
+/** Contains the default values used by [Switch]. */
object SwitchDefaults {
/**
* Creates a [SwitchColors] for use in a [Switch].
@@ -445,24 +434,24 @@
* @param checkedTrackBorderColor The border color of this [Switch] when enabled and checked.
* @param uncheckedThumbColor The thumb color of this [Switch] when enabled and unchecked.
* @param uncheckedThumbIconColor The thumb icon color of this [Switch] when enabled and
- * checked.
+ * checked.
* @param uncheckedTrackColor The track color of this [Switch] when enabled and unchecked.
* @param uncheckedTrackBorderColor The border color of this [Switch] when enabled and
- * unchecked.
+ * unchecked.
* @param disabledCheckedThumbColor The thumb color of this [Switch] when disabled and checked.
- * @param disabledCheckedThumbIconColor The thumb icon color of this [Switch] when disabled
- * and checked.
+ * @param disabledCheckedThumbIconColor The thumb icon color of this [Switch] when disabled and
+ * checked.
* @param disabledCheckedTrackColor The track color of this [Switch] when disabled and checked.
* @param disabledCheckedTrackBorderColor The border color of this [Switch] when disabled and
- * unchecked.
+ * unchecked.
* @param disabledUncheckedThumbColor The thumb color of this [Switch] when disabled and
- * unchecked.
+ * unchecked.
* @param disabledUncheckedThumbIconColor The thumb icon color of this [Switch] when disabled
- * and unchecked.
+ * and unchecked.
* @param disabledUncheckedTrackColor The track color of this [Switch] when disabled and
- * unchecked.
- * @param disabledUncheckedTrackBorderColor The border color of this [Switch] when disabled
- * and unchecked.
+ * unchecked.
+ * @param disabledUncheckedTrackBorderColor The border color of this [Switch] when disabled and
+ * unchecked.
*/
@Composable
fun colors(
@@ -487,24 +476,25 @@
disabledUncheckedTrackColor: Color = Color.Transparent,
disabledUncheckedTrackBorderColor: Color =
MaterialTheme.colorScheme.onSurface.toDisabledColor(disabledAlpha = 0.12f)
- ): SwitchColors = SwitchColors(
- checkedThumbColor = checkedThumbColor,
- checkedThumbIconColor = checkedThumbIconColor,
- checkedTrackColor = checkedTrackColor,
- checkedTrackBorderColor = checkedTrackBorderColor,
- uncheckedThumbColor = uncheckedThumbColor,
- uncheckedThumbIconColor = uncheckedThumbIconColor,
- uncheckedTrackColor = uncheckedTrackColor,
- uncheckedTrackBorderColor = uncheckedTrackBorderColor,
- disabledCheckedThumbColor = disabledCheckedThumbColor,
- disabledCheckedThumbIconColor = disabledCheckedThumbIconColor,
- disabledCheckedTrackColor = disabledCheckedTrackColor,
- disabledCheckedTrackBorderColor = disabledCheckedTrackBorderColor,
- disabledUncheckedThumbColor = disabledUncheckedThumbColor,
- disabledUncheckedThumbIconColor = disabledUncheckedThumbIconColor,
- disabledUncheckedTrackColor = disabledUncheckedTrackColor,
- disabledUncheckedTrackBorderColor = disabledUncheckedTrackBorderColor
- )
+ ): SwitchColors =
+ SwitchColors(
+ checkedThumbColor = checkedThumbColor,
+ checkedThumbIconColor = checkedThumbIconColor,
+ checkedTrackColor = checkedTrackColor,
+ checkedTrackBorderColor = checkedTrackBorderColor,
+ uncheckedThumbColor = uncheckedThumbColor,
+ uncheckedThumbIconColor = uncheckedThumbIconColor,
+ uncheckedTrackColor = uncheckedTrackColor,
+ uncheckedTrackBorderColor = uncheckedTrackBorderColor,
+ disabledCheckedThumbColor = disabledCheckedThumbColor,
+ disabledCheckedThumbIconColor = disabledCheckedThumbIconColor,
+ disabledCheckedTrackColor = disabledCheckedTrackColor,
+ disabledCheckedTrackBorderColor = disabledCheckedTrackBorderColor,
+ disabledUncheckedThumbColor = disabledUncheckedThumbColor,
+ disabledUncheckedThumbIconColor = disabledUncheckedThumbIconColor,
+ disabledUncheckedTrackColor = disabledUncheckedTrackColor,
+ disabledUncheckedTrackBorderColor = disabledUncheckedTrackBorderColor
+ )
}
private fun DrawScope.drawBox(color: Color, progress: Float, isRtl: Boolean) {
@@ -520,9 +510,11 @@
// Draw the outline of the box.
drawRoundRect(
color,
- topLeft = Offset(
- topCornerPx + halfStrokeWidthPx + startXOffsetPx, topCornerPx + halfStrokeWidthPx
- ),
+ topLeft =
+ Offset(
+ topCornerPx + halfStrokeWidthPx + startXOffsetPx,
+ topCornerPx + halfStrokeWidthPx
+ ),
size = Size(checkboxSizePx - strokeWidthPx, checkboxSizePx - strokeWidthPx),
cornerRadius = CornerRadius(radiusPx - halfStrokeWidthPx),
alpha = 1 - progress,
@@ -552,25 +544,29 @@
val thumbPaddingUnchecked = SWITCH_HEIGHT / 2 - THUMB_RADIUS_UNCHECKED
val thumbPaddingChecked = SWITCH_HEIGHT / 2 - THUMB_RADIUS_CHECKED
- val switchThumbRadiusPx = lerp(
- start = THUMB_RADIUS_UNCHECKED.toPx(),
- stop = THUMB_RADIUS_CHECKED.toPx(),
- fraction = progress
- )
+ val switchThumbRadiusPx =
+ lerp(
+ start = THUMB_RADIUS_UNCHECKED.toPx(),
+ stop = THUMB_RADIUS_CHECKED.toPx(),
+ fraction = progress
+ )
val switchTrackLengthPx = WIDTH.toPx()
// For Rtl mode the thumb progress will start from the end of the switch.
- val thumbProgressPx = if (isRtl) lerp(
- start = switchTrackLengthPx - switchThumbRadiusPx - thumbPaddingUnchecked.toPx(),
- stop = switchThumbRadiusPx + thumbPaddingChecked.toPx(),
- fraction = progress
- )
- else lerp(
- start = switchThumbRadiusPx + thumbPaddingUnchecked.toPx(),
- stop = switchTrackLengthPx - switchThumbRadiusPx - thumbPaddingChecked.toPx(),
- fraction = progress
- )
+ val thumbProgressPx =
+ if (isRtl)
+ lerp(
+ start = switchTrackLengthPx - switchThumbRadiusPx - thumbPaddingUnchecked.toPx(),
+ stop = switchThumbRadiusPx + thumbPaddingChecked.toPx(),
+ fraction = progress
+ )
+ else
+ lerp(
+ start = switchThumbRadiusPx + thumbPaddingUnchecked.toPx(),
+ stop = switchTrackLengthPx - switchThumbRadiusPx - thumbPaddingChecked.toPx(),
+ fraction = progress
+ )
drawCircle(
color = thumbColor,
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/TouchTargetAwareSize.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/TouchTargetAwareSize.kt
index 45dda91..3fb3b44 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/TouchTargetAwareSize.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/TouchTargetAwareSize.kt
@@ -24,13 +24,8 @@
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.max
-/**
- * Modifier to set both the size and recommended touch target for
- * [IconButton] and TextButton.
- */
+/** Modifier to set both the size and recommended touch target for [IconButton] and TextButton. */
fun Modifier.touchTargetAwareSize(size: Dp): Modifier =
- this
- .padding(PaddingValues(max(0.dp, (minimumTouchTarget - size) * 0.5f)))
- .size(size)
+ this.padding(PaddingValues(max(0.dp, (minimumTouchTarget - size) * 0.5f))).size(size)
private val minimumTouchTarget = 48.dp
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Typography.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Typography.kt
index f379773..21ab4bc 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Typography.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Typography.kt
@@ -29,59 +29,49 @@
/**
* Class holding typography definitions as defined by the Wear Material typography specification.
*
- * The text styles in this typography are scaled according to the user's preferred font size in
- * the system settings. Larger font sizes can be fixed if necessary in order to avoid pressure on
- * screen space, because they are already sufficiently accessible.
- * Here is an example of fixing the font size for DisplayLarge:
+ * The text styles in this typography are scaled according to the user's preferred font size in the
+ * system settings. Larger font sizes can be fixed if necessary in order to avoid pressure on screen
+ * space, because they are already sufficiently accessible. Here is an example of fixing the font
+ * size for DisplayLarge:
+ *
* @sample androidx.wear.compose.material3.samples.FixedFontSize
*
- * TODO(b/273526150) Review documentation for typography, add examples for each size.
- *
- * @property displayLarge DisplayLarge is the largest headline. Displays are the largest text
- * on the screen, reserved for short, important text or numerals.
- *
- * @property displayMedium DisplayMedium is the second largest headline. Displays are the
- * largest text on the screen, reserved for short, important text or numerals.
- *
- * @property displaySmall DisplaySmall is the smallest headline. Displays are the largest
- * text on the screen, reserved for short, important text or numerals.
- *
+ * @property displayLarge DisplayLarge is the largest headline. Displays are the largest text on the
+ * screen, reserved for short, important text or numerals.
+ * @property displayMedium DisplayMedium is the second largest headline. Displays are the largest
+ * text on the screen, reserved for short, important text or numerals.
+ * @property displaySmall DisplaySmall is the smallest headline. Displays are the largest text on
+ * the screen, reserved for short, important text or numerals.
* @property titleLarge TitleLarge is the largest title. Titles are smaller than Displays. They are
- * typically reserved for medium-emphasis text that is shorter in length.
- *
+ * typically reserved for medium-emphasis text that is shorter in length.
* @property titleMedium TitleMedium is the medium title. Titles are smaller than Displays. They are
- * typically reserved for medium-emphasis text that is shorter in length.
- *
+ * typically reserved for medium-emphasis text that is shorter in length.
* @property titleSmall TitleSmall is the smallest title. Titles are smaller than Displays. They are
- * typically reserved for medium-emphasis text that is shorter in length.
- *
+ * typically reserved for medium-emphasis text that is shorter in length.
* @property labelLarge LabelLarge is the largest label. They are used for displaying prominent
- * texts like label on title buttons.
- *
+ * texts like label on title buttons.
* @property labelMedium LabelMedium is the medium label. They are used for displaying texts like
- * primary label on buttons.
- *
+ * primary label on buttons.
* @property labelSmall LabelSmall is the small label. They are used for displaying texts like
- * secondary label on buttons, labels on compact buttons.
- *
+ * secondary label on buttons, labels on compact buttons.
* @property bodyLarge BodyLarge is the largest body. Body texts are typically used for long-form
- * writing as it works well for small text sizes. For longer sections of text, a serif or
- * sans serif typeface is recommended.
- *
+ * writing as it works well for small text sizes. For longer sections of text, a serif or sans
+ * serif typeface is recommended.
* @property bodyMedium BodyMedium is second largest body. Body texts are typically used for
- * long-form writing as it works well for small text sizes. For longer sections of text, a serif
- * or sans serif typeface is recommended.
- *
+ * long-form writing as it works well for small text sizes. For longer sections of text, a serif
+ * or sans serif typeface is recommended.
* @property bodySmall BodySmall is third largest body. Body texts are typically used for long-form
- * writing as it works well for small text sizes. For longer sections of text, a serif or sans serif
- * typeface is recommended.
- *
+ * writing as it works well for small text sizes. For longer sections of text, a serif or sans
+ * serif typeface is recommended.
* @property bodyExtraSmall BodyExtraSmall is the smallest body. Body texts are typically used for
- * long-form writing as it works well for small text sizes. For longer sections of text, a serif
- * or sans serif typeface is recommended.
+ * long-form writing as it works well for small text sizes. For longer sections of text, a serif
+ * or sans serif typeface is recommended.
+ *
+ * TODO(b/273526150) Review documentation for typography, add examples for each size.
*/
@Immutable
- class Typography internal constructor(
+class Typography
+internal constructor(
val displayLarge: TextStyle,
val displayMedium: TextStyle,
val displaySmall: TextStyle,
@@ -96,7 +86,7 @@
val bodySmall: TextStyle,
val bodyExtraSmall: TextStyle
) {
- constructor (
+ constructor(
defaultFontFamily: FontFamily = FontFamily.Default,
displayLarge: TextStyle = TypographyTokens.DisplayLarge,
displayMedium: TextStyle = TypographyTokens.DisplayMedium,
@@ -127,9 +117,7 @@
bodyExtraSmall = bodyExtraSmall.withDefaultFontFamily(defaultFontFamily)
)
- /**
- * Returns a copy of this Typography, optionally overriding some of the values.
- */
+ /** Returns a copy of this Typography, optionally overriding some of the values. */
fun copy(
displayLarge: TextStyle = this.displayLarge,
displayMedium: TextStyle = this.displayMedium,
@@ -144,21 +132,22 @@
bodyMedium: TextStyle = this.bodyMedium,
bodySmall: TextStyle = this.bodySmall,
bodyExtraSmall: TextStyle = this.bodyExtraSmall
- ): Typography = Typography(
- displayLarge,
- displayMedium,
- displaySmall,
- titleLarge,
- titleMedium,
- titleSmall,
- labelLarge,
- labelMedium,
- labelSmall,
- bodyLarge,
- bodyMedium,
- bodySmall,
- bodyExtraSmall
- )
+ ): Typography =
+ Typography(
+ displayLarge,
+ displayMedium,
+ displaySmall,
+ titleLarge,
+ titleMedium,
+ titleSmall,
+ labelLarge,
+ labelMedium,
+ labelSmall,
+ bodyLarge,
+ bodyMedium,
+ bodySmall,
+ bodyExtraSmall
+ )
override fun equals(other: Any?): Boolean {
if (this === other) return true
@@ -208,8 +197,8 @@
}
/**
- * @return [this] if there is a [FontFamily] defined, otherwise copies [this] with [default] as
- * the [FontFamily].
+ * @return [this] if there is a [FontFamily] defined, otherwise copies [this] with [default] as the
+ * [FontFamily].
*/
private fun TextStyle.withDefaultFontFamily(default: FontFamily): TextStyle {
return if (fontFamily != null) this else copy(fontFamily = default)
@@ -217,24 +206,20 @@
private const val DefaultIncludeFontPadding = false
-internal val DefaultLineHeightStyle = LineHeightStyle(
- alignment = LineHeightStyle.Alignment.Center,
- trim = LineHeightStyle.Trim.None,
-)
+internal val DefaultLineHeightStyle =
+ LineHeightStyle(
+ alignment = LineHeightStyle.Alignment.Center,
+ trim = LineHeightStyle.Trim.None,
+ )
-/**
- * Returns theme default [TextStyle] with default [PlatformTextStyle].
- */
-internal val DefaultTextStyle = TextStyle.Default.copy(
- platformStyle = PlatformTextStyle(
- includeFontPadding = DefaultIncludeFontPadding
- ),
- lineHeightStyle = DefaultLineHeightStyle,
-)
+/** Returns theme default [TextStyle] with default [PlatformTextStyle]. */
+internal val DefaultTextStyle =
+ TextStyle.Default.copy(
+ platformStyle = PlatformTextStyle(includeFontPadding = DefaultIncludeFontPadding),
+ lineHeightStyle = DefaultLineHeightStyle,
+ )
-/**
- * Helper function for typography tokens.
- */
+/** Helper function for typography tokens. */
internal fun Typography.fromToken(value: TypographyKeyTokens): TextStyle {
return when (value) {
TypographyKeyTokens.DisplayLarge -> displayLarge
@@ -254,20 +239,18 @@
}
/**
- * Converts the [TypographyKeyTokens] to the local text style provided by the theme.
- * The text style refers to the [LocalTypography].
+ * Converts the [TypographyKeyTokens] to the local text style provided by the theme. The text style
+ * refers to the [LocalTypography].
*/
internal val TypographyKeyTokens.value: TextStyle
- @Composable
- @ReadOnlyComposable
- get() = MaterialTheme.typography.fromToken(this)
+ @Composable @ReadOnlyComposable get() = MaterialTheme.typography.fromToken(this)
/**
* This Ambient holds on to the current definition of typography for this application as described
* by the Wear Material spec. You can read the values in it when creating custom components that
* want to use Wear Material types, as well as override the values when you want to re-style a part
- * of your hierarchy. Material components related to text such as Button will use this Ambient
- * to set values with which to style children text components.
+ * of your hierarchy. Material components related to text such as Button will use this Ambient to
+ * set values with which to style children text components.
*
* To access values within this ambient, use [MaterialTheme.typography].
*/
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/FilledIconButtonTokens.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/FilledIconButtonTokens.kt
index 82324a5..efed6a6 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/FilledIconButtonTokens.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/FilledIconButtonTokens.kt
@@ -20,10 +20,10 @@
package androidx.wear.compose.material3.tokens
internal object FilledIconButtonTokens {
- val ContainerColor = ColorSchemeKeyTokens.Primary
- val ContentColor = ColorSchemeKeyTokens.OnPrimary
- val DisabledContainerColor = ColorSchemeKeyTokens.OnSurface
- val DisabledContainerOpacity = 0.12f
- val DisabledContentColor = ColorSchemeKeyTokens.OnSurface
- val DisabledContentOpacity = 0.38f
+ val ContainerColor = ColorSchemeKeyTokens.Primary
+ val ContentColor = ColorSchemeKeyTokens.OnPrimary
+ val DisabledContainerColor = ColorSchemeKeyTokens.OnSurface
+ val DisabledContainerOpacity = 0.12f
+ val DisabledContentColor = ColorSchemeKeyTokens.OnSurface
+ val DisabledContentOpacity = 0.38f
}
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/IconButtonTokens.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/IconButtonTokens.kt
index 1b7d093..76c1b63 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/IconButtonTokens.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/IconButtonTokens.kt
@@ -22,15 +22,15 @@
import androidx.compose.ui.unit.dp
internal object IconButtonTokens {
- val ContainerDefaultSize = 52.0.dp
- val ContainerExtraSmallSize = 32.0.dp
- val ContainerLargeSize = 60.0.dp
- val ContainerShape = ShapeKeyTokens.CornerFull
- val ContainerSmallSize = 48.0.dp
- val ContentColor = ColorSchemeKeyTokens.OnSurface
- val DisabledContentColor = ColorSchemeKeyTokens.OnSurface
- val DisabledContentOpacity = 0.38f
- val IconDefaultSize = 26.0.dp
- val IconLargeSize = 32.0.dp
- val IconSmallSize = 24.0.dp
+ val ContainerDefaultSize = 52.0.dp
+ val ContainerExtraSmallSize = 32.0.dp
+ val ContainerLargeSize = 60.0.dp
+ val ContainerShape = ShapeKeyTokens.CornerFull
+ val ContainerSmallSize = 48.0.dp
+ val ContentColor = ColorSchemeKeyTokens.OnSurface
+ val DisabledContentColor = ColorSchemeKeyTokens.OnSurface
+ val DisabledContentOpacity = 0.38f
+ val IconDefaultSize = 26.0.dp
+ val IconLargeSize = 32.0.dp
+ val IconSmallSize = 24.0.dp
}
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/OutlinedIconButtonTokens.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/OutlinedIconButtonTokens.kt
index 60e343b..9ec0db9 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/OutlinedIconButtonTokens.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/tokens/OutlinedIconButtonTokens.kt
@@ -20,7 +20,7 @@
package androidx.wear.compose.material3.tokens
internal object OutlinedIconButtonTokens {
- val ContentColor = ColorSchemeKeyTokens.OnSurface
- val DisabledContentColor = ColorSchemeKeyTokens.OnSurface
- val DisabledContentOpacity = 0.38f
+ val ContentColor = ColorSchemeKeyTokens.OnSurface
+ val DisabledContentColor = ColorSchemeKeyTokens.OnSurface
+ val DisabledContentOpacity = 0.38f
}
diff --git a/wear/compose/compose-navigation/samples/src/main/java/androidx/wear/compose/navigation/samples/SwipeDismissableNavHostSample.kt b/wear/compose/compose-navigation/samples/src/main/java/androidx/wear/compose/navigation/samples/SwipeDismissableNavHostSample.kt
index 5e7b3f48..a635251 100644
--- a/wear/compose/compose-navigation/samples/src/main/java/androidx/wear/compose/navigation/samples/SwipeDismissableNavHostSample.kt
+++ b/wear/compose/compose-navigation/samples/src/main/java/androidx/wear/compose/navigation/samples/SwipeDismissableNavHostSample.kt
@@ -43,15 +43,13 @@
fun SimpleNavHost() {
// Example of using a NavHost where each destination in the NavGraph has a unique name.
val navController = rememberSwipeDismissableNavController()
- SwipeDismissableNavHost(
- navController = navController,
- startDestination = "off"
- ) {
+ SwipeDismissableNavHost(navController = navController, startDestination = "off") {
composable("off") {
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
- verticalArrangement = Arrangement.Center) {
+ verticalArrangement = Arrangement.Center
+ ) {
Button(onClick = { navController.navigate("on") }) { Text("On") }
}
}
@@ -59,7 +57,8 @@
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
- verticalArrangement = Arrangement.Center) {
+ verticalArrangement = Arrangement.Center
+ ) {
Button(onClick = { navController.navigate("off") }) { Text("Off") }
}
}
@@ -71,21 +70,14 @@
fun NavHostWithNamedArgument() {
// Example of using a NavHost where we pass an argument to a destination in the NavGraph.
val navController = rememberSwipeDismissableNavController()
- SwipeDismissableNavHost(
- navController = navController,
- startDestination = "list"
- ) {
+ SwipeDismissableNavHost(navController = navController, startDestination = "list") {
composable("list") {
ScalingLazyColumn(
modifier = Modifier.fillMaxSize(),
contentPadding = PaddingValues(horizontal = 8.dp, vertical = 32.dp),
verticalArrangement = Arrangement.Center,
) {
- item {
- ListHeader {
- Text("List Screen")
- }
- }
+ item { ListHeader { Text("List Screen") } }
items(5) { index ->
CompactChip(
modifier = Modifier.padding(vertical = 4.dp),
@@ -96,17 +88,14 @@
textAlign = TextAlign.Center,
modifier = Modifier.fillMaxSize()
)
- })
+ }
+ )
}
}
}
composable(
route = "detail/{Id}",
- arguments = listOf(
- navArgument("Id") {
- type = NavType.IntType
- }
- )
+ arguments = listOf(navArgument("Id") { type = NavType.IntType })
) { backStackEntry ->
val itemId = backStackEntry.arguments?.getInt("Id") ?: 0
Column(
@@ -114,9 +103,7 @@
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
- ListHeader {
- Text("Details Screen")
- }
+ ListHeader { Text("Details Screen") }
Text("Item $itemId")
}
}
diff --git a/wear/compose/compose-navigation/src/androidTest/kotlin/androidx/wear/compose/navigation/SwipeDismissableNavHostSampleTest.kt b/wear/compose/compose-navigation/src/androidTest/kotlin/androidx/wear/compose/navigation/SwipeDismissableNavHostSampleTest.kt
index d0a004e..78e5dd1 100644
--- a/wear/compose/compose-navigation/src/androidTest/kotlin/androidx/wear/compose/navigation/SwipeDismissableNavHostSampleTest.kt
+++ b/wear/compose/compose-navigation/src/androidTest/kotlin/androidx/wear/compose/navigation/SwipeDismissableNavHostSampleTest.kt
@@ -27,14 +27,11 @@
import org.junit.Test
class SwipeDismissableNavHostSampleTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
@Test
fun toggles_between_destinations_in_simplenavhost() {
- rule.setContentWithTheme {
- SimpleNavHost()
- }
+ rule.setContentWithTheme { SimpleNavHost() }
rule.onNodeWithText("On").performClick()
rule.onNodeWithText("Off").performClick()
@@ -44,9 +41,7 @@
@Test
fun navigates_to_named_arguments() {
- rule.setContentWithTheme {
- NavHostWithNamedArgument()
- }
+ rule.setContentWithTheme { NavHostWithNamedArgument() }
rule.onNodeWithText("Item 1").performClick()
@@ -55,9 +50,7 @@
@Test
fun swipes_back_from_named_arguments() {
- rule.setContentWithTheme {
- NavHostWithNamedArgument()
- }
+ rule.setContentWithTheme { NavHostWithNamedArgument() }
rule.onNodeWithText("Item 1").performClick()
rule.onRoot().performTouchInput { swipeRight() }
diff --git a/wear/compose/compose-navigation/src/androidTest/kotlin/androidx/wear/compose/navigation/SwipeDismissableNavHostTest.kt b/wear/compose/compose-navigation/src/androidTest/kotlin/androidx/wear/compose/navigation/SwipeDismissableNavHostTest.kt
index 64a5666..08f6c25 100644
--- a/wear/compose/compose-navigation/src/androidTest/kotlin/androidx/wear/compose/navigation/SwipeDismissableNavHostTest.kt
+++ b/wear/compose/compose-navigation/src/androidTest/kotlin/androidx/wear/compose/navigation/SwipeDismissableNavHostTest.kt
@@ -62,23 +62,18 @@
import org.junit.Test
class SwipeDismissableNavHostTest {
- @get:Rule
- val rule = createComposeRule()
+ @get:Rule val rule = createComposeRule()
@Test
fun supports_testtag() {
- rule.setContentWithTheme {
- SwipeDismissWithNavigation()
- }
+ rule.setContentWithTheme { SwipeDismissWithNavigation() }
rule.onNodeWithTag(TEST_TAG).assertExists()
}
@Test
fun navigates_to_next_level() {
- rule.setContentWithTheme {
- SwipeDismissWithNavigation()
- }
+ rule.setContentWithTheme { SwipeDismissWithNavigation() }
// Click to move to next destination.
rule.onNodeWithText(START).performClick()
@@ -89,9 +84,7 @@
@Test
fun navigates_back_to_previous_level_after_swipe() {
- rule.setContentWithTheme {
- SwipeDismissWithNavigation()
- }
+ rule.setContentWithTheme { SwipeDismissWithNavigation() }
// Click to move to next destination then swipe to dismiss.
rule.onNodeWithText(START).performClick()
@@ -103,9 +96,7 @@
@Test
fun does_not_navigate_back_to_previous_level_when_swipe_disabled() {
- rule.setContentWithTheme {
- SwipeDismissWithNavigation(userSwipeEnabled = false)
- }
+ rule.setContentWithTheme { SwipeDismissWithNavigation(userSwipeEnabled = false) }
// Click to move to next destination then swipe to dismiss.
rule.onNodeWithText(START).performClick()
@@ -135,9 +126,7 @@
rule.onNodeWithText(START).performClick()
// Now trigger the back button
- rule.runOnIdle {
- onBackPressedDispatcher.onBackPressed()
- }
+ rule.runOnIdle { onBackPressedDispatcher.onBackPressed() }
rule.waitForIdle()
// Should now display "start".
@@ -147,9 +136,7 @@
@Test
fun hides_previous_level_when_not_swiping() {
- rule.setContentWithTheme {
- SwipeDismissWithNavigation()
- }
+ rule.setContentWithTheme { SwipeDismissWithNavigation() }
// Click to move to next destination then swipe to dismiss.
rule.onNodeWithText(START).performClick()
@@ -161,21 +148,17 @@
@ExperimentalTestApi
@Test
fun displays_previous_screen_during_swipe_gesture() {
- rule.setContentWithTheme {
- WithTouchSlop(0f) {
- SwipeDismissWithNavigation()
- }
- }
+ rule.setContentWithTheme { WithTouchSlop(0f) { SwipeDismissWithNavigation() } }
// Click to move to next destination.
rule.onNodeWithText(START).performClick()
// Click and drag to being a swipe gesture, but do not release the finger.
- rule.onNodeWithTag(TEST_TAG).performTouchInput(
- {
+ rule
+ .onNodeWithTag(TEST_TAG)
+ .performTouchInput({
down(Offset(x = 0f, y = height / 2f))
moveTo(Offset(x = width / 4f, y = height / 2f))
- }
- )
+ })
// As the finger is still 'down', the background should be visible.
rule.onNodeWithText(START).assertExists()
@@ -203,9 +186,7 @@
Column {
ToggleButton(
checked = toggle,
- onCheckedChange = {
- toggle = !toggle
- },
+ onCheckedChange = { toggle = !toggle },
content = { Text(text = if (toggle) "On" else "Off") },
modifier = Modifier.testTag("ToggleButton"),
)
@@ -219,10 +200,7 @@
}
composable(NEXT) {
screenId.value = NEXT
- CompactChip(
- onClick = {},
- label = { Text(text = NEXT) }
- )
+ CompactChip(onClick = {}, label = { Text(text = NEXT) })
}
}
}
@@ -241,64 +219,55 @@
val screenId = mutableStateOf(START)
rule.setContentWithTheme {
val holder = rememberSaveableStateHolder()
- val navController = rememberSwipeDismissableNavController()
- SwipeDismissableNavHost(
- navController = navController,
- startDestination = START,
- modifier = Modifier.testTag(TEST_TAG),
- ) {
- composable(START) {
- screenId.value = START
- holder.SaveableStateProvider(START) {
- var toggle by rememberSaveable { mutableStateOf(false) }
- Column(
- modifier = Modifier
- .fillMaxSize()
- .padding(horizontal = 20.dp),
- verticalArrangement = Arrangement.Center,
- horizontalAlignment = Alignment.CenterHorizontally
+ val navController = rememberSwipeDismissableNavController()
+ SwipeDismissableNavHost(
+ navController = navController,
+ startDestination = START,
+ modifier = Modifier.testTag(TEST_TAG),
+ ) {
+ composable(START) {
+ screenId.value = START
+ holder.SaveableStateProvider(START) {
+ var toggle by rememberSaveable { mutableStateOf(false) }
+ Column(
+ modifier = Modifier.fillMaxSize().padding(horizontal = 20.dp),
+ verticalArrangement = Arrangement.Center,
+ horizontalAlignment = Alignment.CenterHorizontally
+ ) {
+ ToggleButton(
+ checked = toggle,
+ onCheckedChange = { toggle = !toggle },
+ content = { Text(text = if (toggle) "On" else "Off") },
+ modifier = Modifier.testTag("ToggleButton"),
+ )
+ Button(
+ onClick = { navController.navigate(NEXT) },
) {
- ToggleButton(
- checked = toggle,
- onCheckedChange = {
- toggle = !toggle
- },
- content = { Text(text = if (toggle) "On" else "Off") },
- modifier = Modifier.testTag("ToggleButton"),
- )
- Button(
- onClick = { navController.navigate(NEXT) },
- ) {
- Text("Go")
- }
+ Text("Go")
}
}
}
- composable(NEXT) {
- screenId.value = NEXT
- holder.SaveableStateProvider(NEXT) {
- var counter by rememberSaveable { mutableStateOf(0) }
- Column(
- modifier = Modifier
- .fillMaxSize()
- .padding(horizontal = 20.dp),
- verticalArrangement = Arrangement.Center,
- horizontalAlignment = Alignment.CenterHorizontally
+ }
+ composable(NEXT) {
+ screenId.value = NEXT
+ holder.SaveableStateProvider(NEXT) {
+ var counter by rememberSaveable { mutableStateOf(0) }
+ Column(
+ modifier = Modifier.fillMaxSize().padding(horizontal = 20.dp),
+ verticalArrangement = Arrangement.Center,
+ horizontalAlignment = Alignment.CenterHorizontally
+ ) {
+ Button(onClick = { ++counter }, modifier = Modifier.testTag(COUNTER)) {
+ Text("$counter")
+ }
+ Button(
+ onClick = { navController.navigate(START) },
) {
- Button(
- onClick = { ++counter },
- modifier = Modifier.testTag(COUNTER)
- ) {
- Text("$counter")
- }
- Button(
- onClick = { navController.navigate(START) },
- ) {
- Text("Jump")
- }
+ Text("Jump")
}
}
}
+ }
}
}
@@ -389,9 +358,7 @@
rule.waitForIdle()
rule.onNodeWithText(START).performClick()
- rule.runOnIdle {
- navController.popBackStack()
- }
+ rule.runOnIdle { navController.popBackStack() }
rule.runOnIdle {
assertThat(navController.currentBackStackEntry?.lifecycle?.currentState)
@@ -411,10 +378,7 @@
rule.onNodeWithText(START).performClick()
- rule.runOnIdle {
- assertThat(backStackEntry.value?.destination?.route)
- .isEqualTo(NEXT)
- }
+ rule.runOnIdle { assertThat(backStackEntry.value?.destination?.route).isEqualTo(NEXT) }
}
@Test
@@ -458,10 +422,7 @@
userSwipeEnabled = userSwipeEnabled
) {
composable(START) {
- Box(
- modifier = Modifier.fillMaxSize(),
- contentAlignment = Alignment.Center
- ) {
+ Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
CompactChip(
onClick = { navController.navigate(NEXT) },
label = { Text(text = START) }
@@ -469,10 +430,7 @@
}
}
composable("next") {
- Box(
- modifier = Modifier.fillMaxSize(),
- contentAlignment = Alignment.Center
- ) {
+ Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
Text(NEXT)
}
}
@@ -480,14 +438,8 @@
}
}
-fun ComposeContentTestRule.setContentWithTheme(
- composable: @Composable () -> Unit
-) {
- setContent {
- MaterialTheme {
- composable()
- }
- }
+fun ComposeContentTestRule.setContentWithTheme(composable: @Composable () -> Unit) {
+ setContent { MaterialTheme { composable() } }
}
private const val NEXT = "next"
diff --git a/wear/compose/compose-navigation/src/main/java/androidx/wear/compose/navigation/NavGraphBuilder.kt b/wear/compose/compose-navigation/src/main/java/androidx/wear/compose/navigation/NavGraphBuilder.kt
index 2f007ab..a115fa7 100644
--- a/wear/compose/compose-navigation/src/main/java/androidx/wear/compose/navigation/NavGraphBuilder.kt
+++ b/wear/compose/compose-navigation/src/main/java/androidx/wear/compose/navigation/NavGraphBuilder.kt
@@ -42,12 +42,8 @@
addDestination(
WearNavigator.Destination(provider[WearNavigator::class], content).apply {
this.route = route
- arguments.forEach { (argumentName, argument) ->
- addArgument(argumentName, argument)
- }
- deepLinks.forEach { deepLink ->
- addDeepLink(deepLink)
- }
+ arguments.forEach { (argumentName, argument) -> addArgument(argumentName, argument) }
+ deepLinks.forEach { deepLink -> addDeepLink(deepLink) }
}
)
}
diff --git a/wear/compose/compose-navigation/src/main/java/androidx/wear/compose/navigation/SwipeDismissableNavHost.kt b/wear/compose/compose-navigation/src/main/java/androidx/wear/compose/navigation/SwipeDismissableNavHost.kt
index 11bf649..8df8ef2 100644
--- a/wear/compose/compose-navigation/src/main/java/androidx/wear/compose/navigation/SwipeDismissableNavHost.kt
+++ b/wear/compose/compose-navigation/src/main/java/androidx/wear/compose/navigation/SwipeDismissableNavHost.kt
@@ -67,8 +67,8 @@
import androidx.wear.compose.foundation.rememberSwipeToDismissBoxState
/**
- * Provides a place in the Compose hierarchy for self-contained navigation to occur,
- * with backwards navigation provided by a swipe gesture.
+ * Provides a place in the Compose hierarchy for self-contained navigation to occur, with backwards
+ * navigation provided by a swipe gesture.
*
* Once this is called, any Composable within the given [NavGraphBuilder] can be navigated to from
* the provided [navController].
@@ -77,14 +77,16 @@
* contents of the builder cannot be changed.
*
* Content is displayed within a [BasicSwipeToDismissBox], showing the current navigation level.
- * During a swipe-to-dismiss gesture, the previous navigation level (if any) is shown in
- * the background. BackgroundScrimColor and ContentScrimColor of it are taken from
+ * During a swipe-to-dismiss gesture, the previous navigation level (if any) is shown in the
+ * background. BackgroundScrimColor and ContentScrimColor of it are taken from
* [LocalSwipeToDismissBackgroundScrimColor] and [LocalSwipeToDismissContentScrimColor].
*
* Example of a [SwipeDismissableNavHost] alternating between 2 screens:
+ *
* @sample androidx.wear.compose.navigation.samples.SimpleNavHost
*
* Example of a [SwipeDismissableNavHost] for which a destination has a named argument:
+ *
* @sample androidx.wear.compose.navigation.samples.NavHostWithNamedArgument
*
* @param navController The navController for this host
@@ -104,19 +106,20 @@
state: SwipeDismissableNavHostState = rememberSwipeDismissableNavHostState(),
route: String? = null,
builder: NavGraphBuilder.() -> Unit
-) = SwipeDismissableNavHost(
- navController,
- remember(route, startDestination, builder) {
- navController.createGraph(startDestination, route, builder)
- },
- modifier,
- userSwipeEnabled,
- state = state,
-)
+) =
+ SwipeDismissableNavHost(
+ navController,
+ remember(route, startDestination, builder) {
+ navController.createGraph(startDestination, route, builder)
+ },
+ modifier,
+ userSwipeEnabled,
+ state = state,
+ )
/**
- * Provides a place in the Compose hierarchy for self-contained navigation to occur,
- * with backwards navigation provided by a swipe gesture.
+ * Provides a place in the Compose hierarchy for self-contained navigation to occur, with backwards
+ * navigation provided by a swipe gesture.
*
* Once this is called, any Composable within the given [NavGraphBuilder] can be navigated to from
* the provided [navController].
@@ -125,14 +128,16 @@
* contents of the builder cannot be changed.
*
* Content is displayed within a [BasicSwipeToDismissBox], showing the current navigation level.
- * During a swipe-to-dismiss gesture, the previous navigation level (if any) is shown in
- * the background. BackgroundScrimColor and ContentScrimColor of it are taken from
+ * During a swipe-to-dismiss gesture, the previous navigation level (if any) is shown in the
+ * background. BackgroundScrimColor and ContentScrimColor of it are taken from
* [LocalSwipeToDismissBackgroundScrimColor] and [LocalSwipeToDismissContentScrimColor].
*
* Example of a [SwipeDismissableNavHost] alternating between 2 screens:
+ *
* @sample androidx.wear.compose.navigation.samples.SimpleNavHost
*
* Example of a [SwipeDismissableNavHost] for which a destination has a named argument:
+ *
* @sample androidx.wear.compose.navigation.samples.NavHostWithNamedArgument
*
* @param navController [NavHostController] for this host
@@ -140,7 +145,6 @@
* @param modifier [Modifier] to be applied to the layout
* @param userSwipeEnabled [Boolean] Whether swipe-to-dismiss gesture is enabled.
* @param state State containing information about ongoing swipe and animation.
- *
* @throws IllegalArgumentException if no WearNavigation.Destination is on the navigation backstack.
*/
@OptIn(ExperimentalWearFoundationApi::class)
@@ -153,10 +157,11 @@
state: SwipeDismissableNavHostState = rememberSwipeDismissableNavHostState(),
) {
val lifecycleOwner = LocalLifecycleOwner.current
- val viewModelStoreOwner = checkNotNull(LocalViewModelStoreOwner.current) {
- "SwipeDismissableNavHost requires a ViewModelStoreOwner to be provided " +
- "via LocalViewModelStoreOwner"
- }
+ val viewModelStoreOwner =
+ checkNotNull(LocalViewModelStoreOwner.current) {
+ "SwipeDismissableNavHost requires a ViewModelStoreOwner to be provided " +
+ "via LocalViewModelStoreOwner"
+ }
navController.setViewModelStore(viewModelStoreOwner.viewModelStore)
@@ -165,9 +170,9 @@
// Find the WearNavigator, returning early if it isn't found
// (such as is the case when using TestNavHostController).
- val wearNavigator = navController.navigatorProvider.get<Navigator<out NavDestination>>(
- WearNavigator.NAME
- ) as? WearNavigator ?: return
+ val wearNavigator =
+ navController.navigatorProvider.get<Navigator<out NavDestination>>(WearNavigator.NAME)
+ as? WearNavigator ?: return
val backStack by wearNavigator.backStack.collectAsState()
@@ -180,7 +185,7 @@
DisposableEffect(lifecycleOwner) {
// Setup the navController with proper owners
navController.setLifecycleOwner(lifecycleOwner)
- onDispose { }
+ onDispose {}
}
val stateHolder = rememberSaveableStateHolder()
@@ -213,28 +218,25 @@
// This effect marks the transitions completed when swipe animations finish,
// so that the navigation backstack entries can go to Lifecycle.State.RESUMED.
if (!swipeState.isAnimationRunning) {
- transitionsInProgress.forEach { entry ->
- wearNavigator.onTransitionComplete(entry)
- }
+ transitionsInProgress.forEach { entry -> wearNavigator.onTransitionComplete(entry) }
}
}
val isRoundDevice = isRoundDevice()
val reduceMotionEnabled = LocalReduceMotion.current.enabled()
- val animationProgress = remember(current) {
- if (!wearNavigator.isPop.value) {
- Animatable(0f)
- } else {
- Animatable(1f)
+ val animationProgress =
+ remember(current) {
+ if (!wearNavigator.isPop.value) {
+ Animatable(0f)
+ } else {
+ Animatable(1f)
+ }
}
- }
LaunchedEffect(animationProgress.isRunning) {
if (!animationProgress.isRunning) {
- transitionsInProgress.forEach { entry ->
- wearNavigator.onTransitionComplete(entry)
- }
+ transitionsInProgress.forEach { entry -> wearNavigator.onTransitionComplete(entry) }
}
}
@@ -245,11 +247,13 @@
} else {
animationProgress.animateTo(
targetValue = 1f,
- animationSpec = tween(
- durationMillis = NAV_HOST_ENTER_TRANSITION_DURATION_MEDIUM +
- NAV_HOST_ENTER_TRANSITION_DURATION_SHORT,
- easing = LinearEasing
- )
+ animationSpec =
+ tween(
+ durationMillis =
+ NAV_HOST_ENTER_TRANSITION_DURATION_MEDIUM +
+ NAV_HOST_ENTER_TRANSITION_DURATION_SHORT,
+ easing = LinearEasing
+ )
)
}
}
@@ -266,28 +270,34 @@
BoxedStackEntryContent(
entry = if (isBackground) previous else current,
saveableStateHolder = stateHolder,
- modifier = modifier.then(
- if (isBackground) {
- Modifier // Not applying graphicsLayer on the background.
- } else {
- Modifier.graphicsLayer {
- val scaleProgression = NAV_HOST_ENTER_TRANSITION_EASING_STANDARD
- .transform((animationProgress.value / 0.75f))
- val opacityProgression = NAV_HOST_ENTER_TRANSITION_EASING_STANDARD
- .transform((animationProgress.value / 0.25f))
- val scale = lerp(0.75f, 1f, scaleProgression).coerceAtMost(1f)
- val opacity = lerp(0.1f, 1f, opacityProgression).coerceIn(0f, 1f)
- scaleX = scale
- scaleY = scale
- alpha = opacity
- clip = true
- shape = if (isRoundDevice) CircleShape else RectangleShape
+ modifier =
+ modifier.then(
+ if (isBackground) {
+ Modifier // Not applying graphicsLayer on the background.
+ } else {
+ Modifier.graphicsLayer {
+ val scaleProgression =
+ NAV_HOST_ENTER_TRANSITION_EASING_STANDARD.transform(
+ (animationProgress.value / 0.75f)
+ )
+ val opacityProgression =
+ NAV_HOST_ENTER_TRANSITION_EASING_STANDARD.transform(
+ (animationProgress.value / 0.25f)
+ )
+ val scale = lerp(0.75f, 1f, scaleProgression).coerceAtMost(1f)
+ val opacity = lerp(0.1f, 1f, opacityProgression).coerceIn(0f, 1f)
+ scaleX = scale
+ scaleY = scale
+ alpha = opacity
+ clip = true
+ shape = if (isRoundDevice) CircleShape else RectangleShape
+ }
}
- }
- ),
- layerColor = if (isBackground || wearNavigator.isPop.value) {
- Color.Unspecified
- } else FLASH_COLOR,
+ ),
+ layerColor =
+ if (isBackground || wearNavigator.isPop.value) {
+ Color.Unspecified
+ } else FLASH_COLOR,
animatable = animationProgress
)
}
@@ -296,22 +306,18 @@
if (initialContent) {
// There are no animations for showing the initial content, so mark transitions
// complete, allowing the navigation backstack entry to go to Lifecycle.State.RESUMED.
- transitionsInProgress.forEach { entry ->
- wearNavigator.onTransitionComplete(entry)
- }
+ transitionsInProgress.forEach { entry -> wearNavigator.onTransitionComplete(entry) }
initialContent = false
}
onDispose {
- transitionsInProgress.forEach { entry ->
- wearNavigator.onTransitionComplete(entry)
- }
+ transitionsInProgress.forEach { entry -> wearNavigator.onTransitionComplete(entry) }
}
}
}
/**
- * Provides a place in the Compose hierarchy for self-contained navigation to occur,
- * with backwards navigation provided by a swipe gesture.
+ * Provides a place in the Compose hierarchy for self-contained navigation to occur, with backwards
+ * navigation provided by a swipe gesture.
*
* Once this is called, any Composable within the given [NavGraphBuilder] can be navigated to from
* the provided [navController].
@@ -320,14 +326,16 @@
* contents of the builder cannot be changed.
*
* Content is displayed within a [BasicSwipeToDismissBox], showing the current navigation level.
- * During a swipe-to-dismiss gesture, the previous navigation level (if any) is shown in
- * the background. BackgroundScrimColor and ContentScrimColor of it are taken from
+ * During a swipe-to-dismiss gesture, the previous navigation level (if any) is shown in the
+ * background. BackgroundScrimColor and ContentScrimColor of it are taken from
* [LocalSwipeToDismissBackgroundScrimColor] and [LocalSwipeToDismissContentScrimColor].
*
* Example of a [SwipeDismissableNavHost] alternating between 2 screens:
+ *
* @sample androidx.wear.compose.navigation.samples.SimpleNavHost
*
* Example of a [SwipeDismissableNavHost] for which a destination has a named argument:
+ *
* @sample androidx.wear.compose.navigation.samples.NavHostWithNamedArgument
*
* @param navController The navController for this host
@@ -350,19 +358,20 @@
state: SwipeDismissableNavHostState = rememberSwipeDismissableNavHostState(),
route: String? = null,
builder: NavGraphBuilder.() -> Unit
-) = SwipeDismissableNavHost(
- navController = navController,
- startDestination = startDestination,
- modifier = modifier,
- userSwipeEnabled = true,
- state = state,
- route = route,
- builder = builder
-)
+) =
+ SwipeDismissableNavHost(
+ navController = navController,
+ startDestination = startDestination,
+ modifier = modifier,
+ userSwipeEnabled = true,
+ state = state,
+ route = route,
+ builder = builder
+ )
/**
- * Provides a place in the Compose hierarchy for self-contained navigation to occur,
- * with backwards navigation provided by a swipe gesture.
+ * Provides a place in the Compose hierarchy for self-contained navigation to occur, with backwards
+ * navigation provided by a swipe gesture.
*
* Once this is called, any Composable within the given [NavGraphBuilder] can be navigated to from
* the provided [navController].
@@ -371,21 +380,22 @@
* contents of the builder cannot be changed.
*
* Content is displayed within a [BasicSwipeToDismissBox], showing the current navigation level.
- * During a swipe-to-dismiss gesture, the previous navigation level (if any) is shown in
- * the background. BackgroundScrimColor and ContentScrimColor of it are taken from
+ * During a swipe-to-dismiss gesture, the previous navigation level (if any) is shown in the
+ * background. BackgroundScrimColor and ContentScrimColor of it are taken from
* [LocalSwipeToDismissBackgroundScrimColor] and [LocalSwipeToDismissContentScrimColor].
*
* Example of a [SwipeDismissableNavHost] alternating between 2 screens:
+ *
* @sample androidx.wear.compose.navigation.samples.SimpleNavHost
*
* Example of a [SwipeDismissableNavHost] for which a destination has a named argument:
+ *
* @sample androidx.wear.compose.navigation.samples.NavHostWithNamedArgument
*
* @param navController [NavHostController] for this host
* @param graph Graph for this host
* @param modifier [Modifier] to be applied to the layout
* @param state State containing information about ongoing swipe and animation.
- *
* @throws IllegalArgumentException if no WearNavigation.Destination is on the navigation backstack.
*/
@Deprecated(
@@ -399,20 +409,21 @@
graph: NavGraph,
modifier: Modifier = Modifier,
state: SwipeDismissableNavHostState = rememberSwipeDismissableNavHostState(),
-) = SwipeDismissableNavHost(
- navController = navController,
- graph = graph,
- modifier = modifier,
- userSwipeEnabled = true,
- state = state
-)
+) =
+ SwipeDismissableNavHost(
+ navController = navController,
+ graph = graph,
+ modifier = modifier,
+ userSwipeEnabled = true,
+ state = state
+ )
/**
* State for [SwipeDismissableNavHost]
*
* @param swipeToDismissBoxState State for [BasicSwipeToDismissBox], which is used to support the
- * swipe-to-dismiss gesture in [SwipeDismissableNavHost] and can also be used to support
- * edge-swiping, using [edgeSwipeToDismiss].
+ * swipe-to-dismiss gesture in [SwipeDismissableNavHost] and can also be used to support
+ * edge-swiping, using [edgeSwipeToDismiss].
*/
public class SwipeDismissableNavHostState(
internal val swipeToDismissBoxState: SwipeToDismissBoxState
@@ -423,24 +434,23 @@
"A newer overload is available which uses SwipeToDismissBoxState " +
"from androidx.wear.compose.foundation package."
)
- constructor(swipeToDismissBoxState: androidx.wear.compose.material.SwipeToDismissBoxState) :
- this(swipeToDismissBoxState.foundationState)
+ constructor(
+ swipeToDismissBoxState: androidx.wear.compose.material.SwipeToDismissBoxState
+ ) : this(swipeToDismissBoxState.foundationState)
}
/**
* Create a [SwipeToDismissBoxState] and remember it.
*
* @param swipeToDismissBoxState State for [BasicSwipeToDismissBox], which is used to support the
- * swipe-to-dismiss gesture in [SwipeDismissableNavHost] and can also be used to support
- * edge-swiping, using [edgeSwipeToDismiss].
+ * swipe-to-dismiss gesture in [SwipeDismissableNavHost] and can also be used to support
+ * edge-swiping, using [edgeSwipeToDismiss].
*/
@Composable
public fun rememberSwipeDismissableNavHostState(
swipeToDismissBoxState: SwipeToDismissBoxState = rememberSwipeToDismissBoxState()
): SwipeDismissableNavHostState {
- return remember(swipeToDismissBoxState) {
- SwipeDismissableNavHostState(swipeToDismissBoxState)
- }
+ return remember(swipeToDismissBoxState) { SwipeDismissableNavHostState(swipeToDismissBoxState) }
}
@Suppress("DEPRECATION")
@@ -454,9 +464,7 @@
swipeToDismissBoxState: androidx.wear.compose.material.SwipeToDismissBoxState =
androidx.wear.compose.material.rememberSwipeToDismissBoxState()
): SwipeDismissableNavHostState {
- return remember(swipeToDismissBoxState) {
- SwipeDismissableNavHostState(swipeToDismissBoxState)
- }
+ return remember(swipeToDismissBoxState) { SwipeDismissableNavHostState(swipeToDismissBoxState) }
}
@Composable
@@ -469,31 +477,23 @@
) {
if (entry != null) {
val isRoundDevice = isRoundDevice()
- var lifecycleState by remember {
- mutableStateOf(entry.lifecycle.currentState)
- }
+ var lifecycleState by remember { mutableStateOf(entry.lifecycle.currentState) }
DisposableEffect(entry.lifecycle) {
- val observer = LifecycleEventObserver { _, event ->
- lifecycleState = event.targetState
- }
+ val observer = LifecycleEventObserver { _, event -> lifecycleState = event.targetState }
entry.lifecycle.addObserver(observer)
- onDispose {
- entry.lifecycle.removeObserver(observer)
- }
+ onDispose { entry.lifecycle.removeObserver(observer) }
}
if (lifecycleState.isAtLeast(Lifecycle.State.CREATED)) {
Box(modifier, propagateMinConstraints = true) {
val destination = entry.destination as WearNavigator.Destination
- entry.LocalOwnersProvider(saveableStateHolder) {
- destination.content(entry)
- }
+ entry.LocalOwnersProvider(saveableStateHolder) { destination.content(entry) }
// Adding a flash effect when a new screen opens
if (layerColor != Color.Unspecified) {
Canvas(Modifier.fillMaxSize()) {
val absoluteProgression =
((animatable.value - 0.25f) / 0.75f).coerceIn(0f, 1f)
- val easedProgression = NAV_HOST_ENTER_TRANSITION_EASING_STANDARD
- .transform(absoluteProgression)
+ val easedProgression =
+ NAV_HOST_ENTER_TRANSITION_EASING_STANDARD.transform(absoluteProgression)
val alpha = lerp(0.07f, 0f, easedProgression).coerceIn(0f, 1f)
if (isRoundDevice) {
drawCircle(color = layerColor.copy(alpha))
@@ -510,9 +510,7 @@
@Composable
private fun isRoundDevice(): Boolean {
val configuration = LocalConfiguration.current
- return remember(configuration) {
- configuration.isScreenRound
- }
+ return remember(configuration) { configuration.isScreenRound }
}
private const val TAG = "SwipeDismissableNavHost"
diff --git a/wear/compose/compose-navigation/src/main/java/androidx/wear/compose/navigation/SwipeDismissableNavHostController.kt b/wear/compose/compose-navigation/src/main/java/androidx/wear/compose/navigation/SwipeDismissableNavHostController.kt
index 781efde..164e72d 100644
--- a/wear/compose/compose-navigation/src/main/java/androidx/wear/compose/navigation/SwipeDismissableNavHostController.kt
+++ b/wear/compose/compose-navigation/src/main/java/androidx/wear/compose/navigation/SwipeDismissableNavHostController.kt
@@ -26,8 +26,8 @@
import androidx.navigation.compose.rememberNavController
/**
- * Creates a NavHostController that handles the adding of the [WearNavigator]
- * from androidx.wear.compose.navigation.
+ * Creates a NavHostController that handles the adding of the [WearNavigator] from
+ * androidx.wear.compose.navigation.
*/
@Composable
public fun rememberSwipeDismissableNavController(): NavHostController {
@@ -35,9 +35,9 @@
}
/**
- * Gets the current navigation back stack entry as a [State]. When the given navController
- * changes the back stack due to a [NavController.navigate] or [NavController.popBackStack] this
- * will trigger a recompose and return the top entry on the back stack.
+ * Gets the current navigation back stack entry as a [State]. When the given navController changes
+ * the back stack due to a [NavController.navigate] or [NavController.popBackStack] this will
+ * trigger a recompose and return the top entry on the back stack.
*
* @return state of the current back stack entry
*/
diff --git a/wear/compose/compose-navigation/src/main/java/androidx/wear/compose/navigation/WearNavigator.kt b/wear/compose/compose-navigation/src/main/java/androidx/wear/compose/navigation/WearNavigator.kt
index 11b3934..f09d557 100644
--- a/wear/compose/compose-navigation/src/main/java/androidx/wear/compose/navigation/WearNavigator.kt
+++ b/wear/compose/compose-navigation/src/main/java/androidx/wear/compose/navigation/WearNavigator.kt
@@ -24,25 +24,21 @@
import androidx.navigation.Navigator
/**
- * Navigator that navigates through [Composable]s. Every destination using this Navigator must
- * set a valid [Composable] by setting it directly on an instantiated [Destination] or calling
+ * Navigator that navigates through [Composable]s. Every destination using this Navigator must set a
+ * valid [Composable] by setting it directly on an instantiated [Destination] or calling
* [composable].
*/
@Navigator.Name("wear-navigator")
public class WearNavigator : Navigator<WearNavigator.Destination>() {
- /**
- * Get the map of transitions currently in progress from the [state].
- */
- internal val transitionsInProgress get() = state.transitionsInProgress
+ /** Get the map of transitions currently in progress from the [state]. */
+ internal val transitionsInProgress
+ get() = state.transitionsInProgress
- /**
- * Get the back stack from the [state].
- */
- internal val backStack get() = state.backStack
+ /** Get the back stack from the [state]. */
+ internal val backStack
+ get() = state.backStack
- /**
- * Indicates if an entry is being popped from [backStack].
- */
+ /** Indicates if an entry is being popped from [backStack]. */
internal val isPop = mutableStateOf(false)
override fun navigate(
@@ -50,9 +46,7 @@
navOptions: NavOptions?,
navigatorExtras: Extras?
) {
- entries.forEach { entry ->
- state.pushWithTransition(entry)
- }
+ entries.forEach { entry -> state.pushWithTransition(entry) }
isPop.value = false
}
@@ -64,20 +58,19 @@
}
/**
- * Callback that removes the given [NavBackStackEntry] from the [map of the transitions in
- * progress][transitionsInProgress]. This should be called in conjunction with [navigate] and
- * [popBackStack] as those call are responsible for adding entries to [transitionsInProgress].
+ * Callback that removes the given [NavBackStackEntry] from the
+ * [map of the transitions in progress][transitionsInProgress]. This should be called in
+ * conjunction with [navigate] and [popBackStack] as those call are responsible for adding
+ * entries to [transitionsInProgress].
*
- * Failing to call this method could result in entries being prevented from reaching their
- * final Lifecycle.State.
+ * Failing to call this method could result in entries being prevented from reaching their final
+ * Lifecycle.State.
*/
internal fun onTransitionComplete(entry: NavBackStackEntry) {
state.markTransitionComplete(entry)
}
- /**
- * NavDestination specific to [WearNavigator]
- */
+ /** NavDestination specific to [WearNavigator] */
@NavDestination.ClassType(Composable::class)
public class Destination(
navigator: WearNavigator,
diff --git a/wear/compose/compose-ui-tooling/src/main/java/androidx/wear/compose/ui/tooling/preview/WearPreviewDevices.kt b/wear/compose/compose-ui-tooling/src/main/java/androidx/wear/compose/ui/tooling/preview/WearPreviewDevices.kt
index 762ee43..d0bb479 100644
--- a/wear/compose/compose-ui-tooling/src/main/java/androidx/wear/compose/ui/tooling/preview/WearPreviewDevices.kt
+++ b/wear/compose/compose-ui-tooling/src/main/java/androidx/wear/compose/ui/tooling/preview/WearPreviewDevices.kt
@@ -25,6 +25,7 @@
* [WearDevices.SQUARE].
*
* @sample androidx.wear.compose.material.samples.ToggleButtonWithIconPreview
+ *
* @see WearDevices.SMALL_ROUND
* @see WearDevices.LARGE_ROUND
* @see WearDevices.SQUARE
diff --git a/wear/compose/compose-ui-tooling/src/main/java/androidx/wear/compose/ui/tooling/preview/WearPreviewFontScales.kt b/wear/compose/compose-ui-tooling/src/main/java/androidx/wear/compose/ui/tooling/preview/WearPreviewFontScales.kt
index 6bcfdeb..d296a3e 100644
--- a/wear/compose/compose-ui-tooling/src/main/java/androidx/wear/compose/ui/tooling/preview/WearPreviewFontScales.kt
+++ b/wear/compose/compose-ui-tooling/src/main/java/androidx/wear/compose/ui/tooling/preview/WearPreviewFontScales.kt
@@ -23,13 +23,14 @@
* [WearPreviewFontScales] is a multi-preview annotation for the Wear devices of following font
* scales
* <ul>
- * <li> Fonts - Small: 0.94f </li>
- * <li> Fonts - Normal: 1f </li>
- * <li> Fonts - Medium: 1.06f </li>
- * <li> Fonts - Large: 1.12f </li>
- * <li> Fonts - Larger: 1.18f </li>
- * <li> Fonts - Largest: 1.24f </li>
+ * <li> Fonts - Small: 0.94f </li>
+ * <li> Fonts - Normal: 1f </li>
+ * <li> Fonts - Medium: 1.06f </li>
+ * <li> Fonts - Large: 1.12f </li>
+ * <li> Fonts - Larger: 1.18f </li>
+ * <li> Fonts - Largest: 1.24f </li>
* </ul>
+ *
* Font scales represent the scaling factor for fonts, relative to the base density scaling. Please
* note, the above list is not exhaustive. It previews the composables on a small round Wear device.
*
diff --git a/wear/compose/compose-ui-tooling/src/main/java/androidx/wear/compose/ui/tooling/preview/WearPreviewLargeRound.kt b/wear/compose/compose-ui-tooling/src/main/java/androidx/wear/compose/ui/tooling/preview/WearPreviewLargeRound.kt
index 2718138..a40e37a 100644
--- a/wear/compose/compose-ui-tooling/src/main/java/androidx/wear/compose/ui/tooling/preview/WearPreviewLargeRound.kt
+++ b/wear/compose/compose-ui-tooling/src/main/java/androidx/wear/compose/ui/tooling/preview/WearPreviewLargeRound.kt
@@ -24,6 +24,7 @@
* round Wear device ([WearDevices.LARGE_ROUND]).
*
* @sample androidx.wear.compose.material.samples.ButtonWithIconPreview
+ *
* @see [WearDevices.LARGE_ROUND]
*/
@Preview(
diff --git a/wear/compose/compose-ui-tooling/src/main/java/androidx/wear/compose/ui/tooling/preview/WearPreviewSmallRound.kt b/wear/compose/compose-ui-tooling/src/main/java/androidx/wear/compose/ui/tooling/preview/WearPreviewSmallRound.kt
index a390175..853d836 100644
--- a/wear/compose/compose-ui-tooling/src/main/java/androidx/wear/compose/ui/tooling/preview/WearPreviewSmallRound.kt
+++ b/wear/compose/compose-ui-tooling/src/main/java/androidx/wear/compose/ui/tooling/preview/WearPreviewSmallRound.kt
@@ -24,6 +24,7 @@
* round Wear device ([WearDevices.SMALL_ROUND]).
*
* @sample androidx.wear.compose.material.samples.ButtonWithIconPreview
+ *
* @see [WearDevices.SMALL_ROUND]
*/
@Preview(
diff --git a/wear/compose/compose-ui-tooling/src/main/java/androidx/wear/compose/ui/tooling/preview/WearPreviewSquare.kt b/wear/compose/compose-ui-tooling/src/main/java/androidx/wear/compose/ui/tooling/preview/WearPreviewSquare.kt
index 1e96371..1e4eac9 100644
--- a/wear/compose/compose-ui-tooling/src/main/java/androidx/wear/compose/ui/tooling/preview/WearPreviewSquare.kt
+++ b/wear/compose/compose-ui-tooling/src/main/java/androidx/wear/compose/ui/tooling/preview/WearPreviewSquare.kt
@@ -24,6 +24,7 @@
* Wear screen ([WearDevices.SQUARE]).
*
* @sample androidx.wear.compose.material.samples.ButtonWithIconPreview
+ *
* @see [WearDevices.SQUARE]
*/
@Preview(
diff --git a/wear/compose/integration-tests/demos/common/src/main/java/androidx/wear/compose/integration/demos/common/Demo.kt b/wear/compose/integration-tests/demos/common/src/main/java/androidx/wear/compose/integration/demos/common/Demo.kt
index 0dddd13..d89ada5 100644
--- a/wear/compose/integration-tests/demos/common/src/main/java/androidx/wear/compose/integration/demos/common/Demo.kt
+++ b/wear/compose/integration-tests/demos/common/src/main/java/androidx/wear/compose/integration/demos/common/Demo.kt
@@ -29,9 +29,7 @@
import androidx.wear.compose.foundation.lazy.ScalingLazyListState
import kotlin.reflect.KClass
-/**
- * Generic demo with a [title] that will be displayed in the list of demos.
- */
+/** Generic demo with a [title] that will be displayed in the list of demos. */
sealed class Demo(val title: String, val description: String? = null) {
override fun toString() = title
}
@@ -42,38 +40,33 @@
* This should only be used for demos that need to customize the activity, the large majority of
* demos should just use [ComposableDemo] instead.
*
- * @property activityClass the KClass (Foo::class) of the activity that will be launched when
- * this demo is selected.
+ * @property activityClass the KClass (Foo::class) of the activity that will be launched when this
+ * demo is selected.
*/
-class ActivityDemo<T : ComponentActivity>(title: String, val activityClass: KClass<T>) : Demo(title)
+class ActivityDemo<T : ComponentActivity>(title: String, val activityClass: KClass<T>) :
+ Demo(title)
-/**
- * A category of [Demo]s, that will display a list of [demos] when selected.
- */
-class DemoCategory(
- title: String,
- val demos: List<Demo>
-) : Demo(title) {
+/** A category of [Demo]s, that will display a list of [demos] when selected. */
+class DemoCategory(title: String, val demos: List<Demo>) : Demo(title) {
private var scrollState: ScalingLazyListState? = null
@Composable
- fun getScrollStateOrInit(factory: @Composable () -> ScalingLazyListState):
- ScalingLazyListState {
+ fun getScrollStateOrInit(
+ factory: @Composable () -> ScalingLazyListState
+ ): ScalingLazyListState {
return scrollState ?: (factory().also { scrollState = it })
}
}
-/**
- * Parameters which are used by [Demo] screens.
- */
+/** Parameters which are used by [Demo] screens. */
class DemoParameters(
val navigateBack: () -> Unit,
val swipeToDismissBoxState: SwipeToDismissBoxState
)
/**
- * Demo that displays [Composable] [content] when selected,
- * with a method to navigate back to the parent.
+ * Demo that displays [Composable] [content] when selected, with a method to navigate back to the
+ * parent.
*/
class ComposableDemo(
title: String,
diff --git a/wear/compose/integration-tests/demos/src/androidTest/java/androidx/wear/compose/integration/demos/test/DemoTest.kt b/wear/compose/integration-tests/demos/src/androidTest/java/androidx/wear/compose/integration/demos/test/DemoTest.kt
index 8b9b028..74219ea 100644
--- a/wear/compose/integration-tests/demos/src/androidTest/java/androidx/wear/compose/integration/demos/test/DemoTest.kt
+++ b/wear/compose/integration-tests/demos/src/androidTest/java/androidx/wear/compose/integration/demos/test/DemoTest.kt
@@ -37,9 +37,10 @@
import org.junit.Test
import org.junit.runner.RunWith
-private val ignoredDemos = listOf<String>(
- // Not ignoring any of them \o/
-)
+private val ignoredDemos =
+ listOf<String>(
+ // Not ignoring any of them \o/
+ )
// Run this test on a phone emulator.
// There are issues running on Watch emulators that menu items off screen are not found,
@@ -48,8 +49,7 @@
@RunWith(AndroidJUnit4::class)
class DemoTest {
// We need to provide the recompose factory first to use new clock.
- @get:Rule
- val rule = createAndroidComposeRule<DemoActivity>()
+ @get:Rule val rule = createAndroidComposeRule<DemoActivity>()
@Test
fun navigateThroughAllDemos() {
@@ -92,8 +92,8 @@
/**
* Visits a [Demo], and then navigates back up to the [DemoCategory] it was inside.
*
- * If this [Demo] is a [DemoCategory], this will visit sub-[Demo]s first before continuing
- * in the current category.
+ * If this [Demo] is a [DemoCategory], this will visit sub-[Demo]s first before continuing in
+ * the current category.
*
* @param path The path of categories that leads to this demo
*/
@@ -108,7 +108,8 @@
fastForwardClock()
}
- rule.onNode(hasScrollToNodeAction())
+ rule
+ .onNode(hasScrollToNodeAction())
.performScrollToNode(hasText(title) and hasClickAction())
rule.onNode(hasText(title) and hasClickAction()).performClick()
@@ -169,9 +170,7 @@
}
private val AllButIgnoredDemos =
- WearComposeDemos.filter { path, demo ->
- demo.navigationTitle(path) !in ignoredDemos
- }
+ WearComposeDemos.filter { path, demo -> demo.navigationTitle(path) !in ignoredDemos }
private fun Demo.navigationTitle(path: List<DemoCategory>): String {
return path.plus(this).navigationTitle
@@ -181,8 +180,8 @@
get() = if (size == 1) first().title else drop(1).joinToString(" > ")
/**
- * Trims the tree of [Demo]s represented by this [DemoCategory] by cutting all leave demos for
- * which the [predicate] returns `false` and recursively removing all empty categories as a result.
+ * Trims the tree of [Demo]s represented by this [DemoCategory] by cutting all leave demos for which
+ * the [predicate] returns `false` and recursively removing all empty categories as a result.
*/
private fun DemoCategory.filter(
path: List<DemoCategory> = emptyList(),
@@ -204,9 +203,7 @@
)
}
-/**
- * Flattened recursive DFS [List] of every demo in [this].
- */
+/** Flattened recursive DFS [List] of every demo in [this]. */
fun DemoCategory.allDemos(): List<Demo> {
val allDemos = mutableListOf<Demo>()
fun DemoCategory.addAllDemos() {
diff --git a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/ButtonDemo.kt b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/ButtonDemo.kt
index 22fa29d..0475e2d 100644
--- a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/ButtonDemo.kt
+++ b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/ButtonDemo.kt
@@ -92,16 +92,10 @@
horizontalArrangement = Arrangement.spacedBy(4.dp, Alignment.CenterHorizontally),
verticalAlignment = Alignment.CenterVertically
) {
- Text(
- text = "Enabled",
- style = MaterialTheme.typography.caption2,
- color = Color.White
- )
+ Text(text = "Enabled", style = MaterialTheme.typography.caption2, color = Color.White)
ToggleButton(
checked = enabled,
- onCheckedChange = {
- enabled = it
- },
+ onCheckedChange = { enabled = it },
modifier = Modifier.size(ButtonDefaults.SmallButtonSize)
) {
Text(text = if (enabled) "Yes" else "No")
@@ -133,10 +127,8 @@
) {
Button(
onClick = {
- Toast.makeText(
- context,
- "Button: Secondary, $enabled", Toast.LENGTH_LONG
- ).show()
+ Toast.makeText(context, "Button: Secondary, $enabled", Toast.LENGTH_LONG)
+ .show()
},
colors = ButtonDefaults.secondaryButtonColors(),
enabled = enabled,
@@ -145,10 +137,7 @@
}
Button(
onClick = {
- Toast.makeText(
- context,
- "Button: Primary colors", Toast.LENGTH_LONG
- ).show()
+ Toast.makeText(context, "Button: Primary colors", Toast.LENGTH_LONG).show()
},
colors = ButtonDefaults.primaryButtonColors(),
enabled = enabled,
@@ -165,9 +154,11 @@
Button(
onClick = {
Toast.makeText(
- context,
- "Button: Small, icon only, $enabled", Toast.LENGTH_LONG
- ).show()
+ context,
+ "Button: Small, icon only, $enabled",
+ Toast.LENGTH_LONG
+ )
+ .show()
},
colors = ButtonDefaults.iconButtonColors(),
modifier = Modifier.size(ButtonDefaults.SmallButtonSize),
@@ -178,9 +169,11 @@
Button(
onClick = {
Toast.makeText(
- context,
- "Button: Large, icon only, $enabled", Toast.LENGTH_LONG
- ).show()
+ context,
+ "Button: Large, icon only, $enabled",
+ Toast.LENGTH_LONG
+ )
+ .show()
},
colors = ButtonDefaults.iconButtonColors(),
modifier = Modifier.size(ButtonDefaults.LargeButtonSize),
@@ -197,10 +190,8 @@
) {
OutlinedButton(
onClick = {
- Toast.makeText(
- context,
- "Button: Outlined, $enabled", Toast.LENGTH_LONG
- ).show()
+ Toast.makeText(context, "Button: Outlined, $enabled", Toast.LENGTH_LONG)
+ .show()
},
enabled = enabled,
) {
@@ -209,9 +200,11 @@
OutlinedCompactButton(
onClick = {
Toast.makeText(
- context,
- "Button: Outlined Compact, $enabled", Toast.LENGTH_LONG
- ).show()
+ context,
+ "Button: Outlined Compact, $enabled",
+ Toast.LENGTH_LONG
+ )
+ .show()
},
enabled = enabled,
) {
@@ -226,10 +219,7 @@
) {
Button(
onClick = {
- Toast.makeText(
- context,
- "Button: Custom Shape", Toast.LENGTH_LONG
- ).show()
+ Toast.makeText(context, "Button: Custom Shape", Toast.LENGTH_LONG).show()
},
colors = ButtonDefaults.secondaryButtonColors(),
modifier = Modifier,
@@ -241,9 +231,11 @@
CompactButton(
onClick = {
Toast.makeText(
- context,
- "Button: Compact Button with Custom Shape", Toast.LENGTH_LONG
- ).show()
+ context,
+ "Button: Compact Button with Custom Shape",
+ Toast.LENGTH_LONG
+ )
+ .show()
},
colors = ButtonDefaults.secondaryButtonColors(),
modifier = Modifier,
@@ -262,9 +254,11 @@
OutlinedCompactButton(
onClick = {
Toast.makeText(
- context,
- "Button: Outlined Compact Button with Custom Shape", Toast.LENGTH_LONG
- ).show()
+ context,
+ "Button: Outlined Compact Button with Custom Shape",
+ Toast.LENGTH_LONG
+ )
+ .show()
},
modifier = Modifier,
enabled = enabled,
@@ -275,13 +269,16 @@
Button(
onClick = {
Toast.makeText(
- context,
- "Button: Override primary colors", Toast.LENGTH_LONG
- ).show()
+ context,
+ "Button: Override primary colors",
+ Toast.LENGTH_LONG
+ )
+ .show()
},
- colors = ButtonDefaults.primaryButtonColors(
- backgroundColor = AlternatePrimaryColor1,
- ),
+ colors =
+ ButtonDefaults.primaryButtonColors(
+ backgroundColor = AlternatePrimaryColor1,
+ ),
enabled = enabled,
) {
DemoIcon(R.drawable.ic_accessibility_24px)
@@ -300,9 +297,7 @@
)
ToggleButton(
checked = enabled,
- onCheckedChange = {
- enabled = it
- },
+ onCheckedChange = { enabled = it },
modifier = Modifier.size(ButtonDefaults.SmallButtonSize),
) {
DemoIcon(R.drawable.ic_check_24px)
@@ -320,9 +315,7 @@
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.fillMaxSize(),
) {
- item {
- ListHeader { Text("Large - 60 x 60") }
- }
+ item { ListHeader { Text("Large - 60 x 60") } }
item {
Row(horizontalArrangement = Arrangement.spacedBy(16.dp)) {
Button(
@@ -354,9 +347,7 @@
}
}
- item {
- ListHeader { Text("Default - 52 x 52") }
- }
+ item { ListHeader { Text("Default - 52 x 52") } }
item {
Row(horizontalArrangement = Arrangement.spacedBy(16.dp)) {
Button(
@@ -369,10 +360,7 @@
onClick = {},
colors = ButtonDefaults.secondaryButtonColors(),
) {
- DemoIcon(
- resourceId = R.drawable.ic_clear_24px,
- contentDescription = "Cross"
- )
+ DemoIcon(resourceId = R.drawable.ic_clear_24px, contentDescription = "Cross")
}
}
}
@@ -382,18 +370,13 @@
onClick = {},
colors = ButtonDefaults.iconButtonColors(),
) {
- DemoIcon(
- resourceId = R.drawable.ic_devices_24,
- contentDescription = "Devices"
- )
+ DemoIcon(resourceId = R.drawable.ic_devices_24, contentDescription = "Devices")
}
Spacer(Modifier.width(ButtonDefaults.DefaultButtonSize))
}
}
- item {
- ListHeader { Text("Small - 48 x 48") }
- }
+ item { ListHeader { Text("Small - 48 x 48") } }
item {
Row(horizontalArrangement = Arrangement.spacedBy(16.dp)) {
Button(
@@ -419,18 +402,13 @@
colors = ButtonDefaults.iconButtonColors(),
modifier = Modifier.size(ButtonDefaults.SmallButtonSize),
) {
- DemoIcon(
- resourceId = R.drawable.ic_volume_up_24px,
- contentDescription = "Vol"
- )
+ DemoIcon(resourceId = R.drawable.ic_volume_up_24px, contentDescription = "Vol")
}
Spacer(Modifier.width(ButtonDefaults.SmallButtonSize))
}
}
- item {
- ListHeader { Text("Extra small - 32 x 32") }
- }
+ item { ListHeader { Text("Extra small - 32 x 32") } }
item {
Row(horizontalArrangement = Arrangement.spacedBy(16.dp)) {
CompactButton(
diff --git a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/CardDemo.kt b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/CardDemo.kt
index fc7b485..a196f5b 100644
--- a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/CardDemo.kt
+++ b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/CardDemo.kt
@@ -44,17 +44,12 @@
fun CardDemo() {
ScalingLazyColumn(
horizontalAlignment = Alignment.CenterHorizontally,
- verticalArrangement = Arrangement.spacedBy(
- space = 4.dp,
- alignment = Alignment.CenterVertically
- ),
+ verticalArrangement =
+ Arrangement.spacedBy(space = 4.dp, alignment = Alignment.CenterVertically),
modifier = Modifier.fillMaxSize()
) {
item {
- Card(
- onClick = {},
- modifier = Modifier.fillMaxWidth()
- ) {
+ Card(onClick = {}, modifier = Modifier.fillMaxWidth()) {
Column(modifier = Modifier.fillMaxWidth()) {
Text("Basic unopinionated chip")
Text("Sets the shape")
@@ -169,18 +164,17 @@
TitleCard(
onClick = {},
title = { Text("TitleCard With an ImageBackground") },
- backgroundPainter = CardDefaults.imageWithScrimBackgroundPainter(
- backgroundImagePainter = painterResource(id = R.drawable.backgroundimage1)
- ),
+ backgroundPainter =
+ CardDefaults.imageWithScrimBackgroundPainter(
+ backgroundImagePainter = painterResource(id = R.drawable.backgroundimage1)
+ ),
contentColor = MaterialTheme.colors.onSurface,
titleColor = MaterialTheme.colors.onSurface,
) {
// Apply 24.dp padding in bottom for TitleCard with an ImageBackground.
// Already 12.dp padding exists. Ref - [CardDefaults.ContentPadding]
Column(
- modifier = Modifier
- .fillMaxSize()
- .padding(bottom = 12.dp),
+ modifier = Modifier.fillMaxSize().padding(bottom = 12.dp),
) {
Text("Text coloured to stand out on the image")
}
diff --git a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/ChipDemo.kt b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/ChipDemo.kt
index 0c549bd..f4478b5 100644
--- a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/ChipDemo.kt
+++ b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/ChipDemo.kt
@@ -92,8 +92,9 @@
item {
DemoLabelChip(
style = chipStyle,
- label = "Standard chip with long label to show truncation which does not fit into" +
- " 2 lines",
+ label =
+ "Standard chip with long label to show truncation which does not fit into" +
+ " 2 lines",
colors = chipColors(chipStyle),
enabled = enabled,
)
@@ -111,16 +112,19 @@
colors = chipColors(chipStyle),
label = "Label with icon",
enabled = enabled,
- ) { DemoIcon(resourceId = R.drawable.ic_accessibility_24px) }
+ ) {
+ DemoIcon(resourceId = R.drawable.ic_accessibility_24px)
+ }
}
item {
DemoIconChip(
style = chipStyle,
colors = chipColors(chipStyle),
- label = "Long label to show truncation which does not fit into" +
- " 2 lines",
+ label = "Long label to show truncation which does not fit into" + " 2 lines",
enabled = enabled,
- ) { DemoIcon(resourceId = R.drawable.ic_accessibility_24px) }
+ ) {
+ DemoIcon(resourceId = R.drawable.ic_accessibility_24px)
+ }
}
item {
Text(
@@ -141,8 +145,7 @@
item {
DemoLabelChip(
style = chipStyle,
- label = "Long label to show truncation which does not fit into" +
- " 1 line",
+ label = "Long label to show truncation which does not fit into" + " 1 line",
secondaryLabel = "Long Secondary Label that will fit over multiple lines",
colors = chipColors(chipStyle),
enabled = enabled,
@@ -155,17 +158,21 @@
label = "Label with icon and",
secondaryLabel = "Secondary Label",
enabled = enabled,
- ) { DemoIcon(resourceId = R.drawable.ic_accessibility_24px) }
+ ) {
+ DemoIcon(resourceId = R.drawable.ic_accessibility_24px)
+ }
}
item {
DemoIconChip(
style = chipStyle,
colors = chipColors(chipStyle),
label = "Long label that will span multiple lines and more than 2 lines",
- secondaryLabel = "Long secondary label to show truncation which does not fit into" +
- "1 line",
+ secondaryLabel =
+ "Long secondary label to show truncation which does not fit into" + "1 line",
enabled = enabled,
- ) { DemoIcon(resourceId = R.drawable.ic_accessibility_24px) }
+ ) {
+ DemoIcon(resourceId = R.drawable.ic_accessibility_24px)
+ }
}
item {
DemoLabelChip(
@@ -195,12 +202,7 @@
ScalingLazyColumn(
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.spacedBy(4.dp, Alignment.CenterVertically),
- contentPadding = PaddingValues(
- start = 8.dp,
- end = 8.dp,
- top = 15.dp,
- bottom = 50.dp
- )
+ contentPadding = PaddingValues(start = 8.dp, end = 8.dp, top = 15.dp, bottom = 50.dp)
) {
item {
Text(
@@ -238,9 +240,9 @@
) {
DemoIcon(
resourceId = R.drawable.ic_accessibility_24px,
- modifier = Modifier
- .size(ChipDefaults.SmallIconSize)
- .wrapContentSize(align = Alignment.Center)
+ modifier =
+ Modifier.size(ChipDefaults.SmallIconSize)
+ .wrapContentSize(align = Alignment.Center)
)
}
}
@@ -248,16 +250,15 @@
DemoIconCompactChip(
onClick = {},
colors = chipColors(chipStyle),
- label =
- "Label with icon to show truncation which does not fit into 1 line",
+ label = "Label with icon to show truncation which does not fit into 1 line",
enabled = enabled,
style = chipStyle
) {
DemoIcon(
resourceId = R.drawable.ic_accessibility_24px,
- modifier = Modifier
- .size(ChipDefaults.SmallIconSize)
- .wrapContentSize(align = Alignment.Center)
+ modifier =
+ Modifier.size(ChipDefaults.SmallIconSize)
+ .wrapContentSize(align = Alignment.Center)
)
}
}
@@ -290,11 +291,7 @@
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.spacedBy(4.dp, Alignment.CenterVertically),
) {
- item {
- ListHeader {
- Text(text = "Chips with avatars")
- }
- }
+ item { ListHeader { Text(text = "Chips with avatars") } }
item {
DemoIconChip(
style = ChipStyle.Secondary,
@@ -324,11 +321,7 @@
)
}
}
- item {
- ListHeader {
- Text(text = "Small Avatar Chips")
- }
- }
+ item { ListHeader { Text(text = "Small Avatar Chips") } }
item {
DemoIconChip(
style = ChipStyle.Secondary,
@@ -357,10 +350,12 @@
label = "Custom Gradient Color",
secondaryLabel = "Matching Secondary Label Color",
secondaryLabelColor = AlternatePrimaryColor3,
- colors = ChipDefaults.gradientBackgroundChipColors(
- startBackgroundColor = AlternatePrimaryColor3.copy(alpha = 0.325f)
- .compositeOver(MaterialTheme.colors.surface.copy(alpha = 0.75f)),
- ),
+ colors =
+ ChipDefaults.gradientBackgroundChipColors(
+ startBackgroundColor =
+ AlternatePrimaryColor3.copy(alpha = 0.325f)
+ .compositeOver(MaterialTheme.colors.surface.copy(alpha = 0.75f)),
+ ),
enabled = enabled,
) {
DemoImage(resourceId = R.drawable.ic_maps_icon)
@@ -370,15 +365,14 @@
ToggleChip(
checked = enabled,
onCheckedChange = { enabled = it },
- label = {
- Text("Chips enabled")
- },
+ label = { Text("Chips enabled") },
// For Switch toggle controls the Wear Material UX guidance is to set the
// unselected toggle control color to ToggleChipDefaults.switchUncheckedIconColor()
// rather than the default.
- colors = ToggleChipDefaults.toggleChipColors(
- uncheckedToggleControlColor = ToggleChipDefaults.SwitchUncheckedIconColor
- ),
+ colors =
+ ToggleChipDefaults.toggleChipColors(
+ uncheckedToggleControlColor = ToggleChipDefaults.SwitchUncheckedIconColor
+ ),
toggleControl = {
Icon(
imageVector = ToggleChipDefaults.switchIcon(checked = enabled),
@@ -396,12 +390,7 @@
ScalingLazyColumn(
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.spacedBy(4.dp, Alignment.CenterVertically),
- contentPadding = PaddingValues(
- start = 8.dp,
- end = 8.dp,
- top = 15.dp,
- bottom = 50.dp
- )
+ contentPadding = PaddingValues(start = 8.dp, end = 8.dp, top = 15.dp, bottom = 50.dp)
) {
item {
Text(
@@ -421,8 +410,9 @@
item {
DemoLabelChip(
style = ChipStyle.Primary,
- label = "Standard chip with long label to show truncation " +
- "which does not fit into 2 lines",
+ label =
+ "Standard chip with long label to show truncation " +
+ "which does not fit into 2 lines",
colors = ChipDefaults.primaryChipColors(),
)
}
@@ -432,7 +422,9 @@
colors = ChipDefaults.primaryChipColors(),
label = "Standard chip with ",
secondaryLabel = "Secondary Label",
- ) { DemoIcon(resourceId = R.drawable.ic_accessibility_24px) }
+ ) {
+ DemoIcon(resourceId = R.drawable.ic_accessibility_24px)
+ }
}
item {
CompactChip(
@@ -440,7 +432,8 @@
colors = ChipDefaults.primaryChipColors(),
label = {
Text(
- "Compact chip with label & icon", maxLines = 1,
+ "Compact chip with label & icon",
+ maxLines = 1,
overflow = TextOverflow.Ellipsis
)
},
@@ -487,12 +480,7 @@
ScalingLazyColumn(
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.spacedBy(4.dp, Alignment.CenterVertically),
- contentPadding = PaddingValues(
- start = 8.dp,
- end = 8.dp,
- top = 15.dp,
- bottom = 50.dp
- )
+ contentPadding = PaddingValues(start = 8.dp, end = 8.dp, top = 15.dp, bottom = 50.dp)
) {
item {
MaterialTheme(colors = MaterialTheme.colors.copy(primary = AlternatePrimaryColor1)) {
@@ -501,25 +489,24 @@
label = "Overridden Theme Primary + Icon",
colors = ChipDefaults.primaryChipColors(),
enabled = enabled,
- ) { DemoIcon(resourceId = R.drawable.ic_accessibility_24px) }
+ ) {
+ DemoIcon(resourceId = R.drawable.ic_accessibility_24px)
+ }
}
}
item {
- Row(
- modifier = Modifier
- .fillMaxWidth()
- .wrapContentWidth(Alignment.CenterHorizontally)
- ) {
+ Row(modifier = Modifier.fillMaxWidth().wrapContentWidth(Alignment.CenterHorizontally)) {
CompactChip(
onClick = {
Toast.makeText(
- applicationContext, "Compact chip with custom color",
- Toast.LENGTH_LONG
- ).show()
+ applicationContext,
+ "Compact chip with custom color",
+ Toast.LENGTH_LONG
+ )
+ .show()
},
- colors = ChipDefaults.secondaryChipColors(
- contentColor = AlternatePrimaryColor2
- ),
+ colors =
+ ChipDefaults.secondaryChipColors(contentColor = AlternatePrimaryColor2),
icon = {
DemoIcon(
resourceId = R.drawable.ic_accessibility_24px,
@@ -531,22 +518,19 @@
}
}
item {
- Row(
- modifier = Modifier
- .fillMaxWidth()
- .wrapContentWidth(Alignment.CenterHorizontally)
- ) {
+ Row(modifier = Modifier.fillMaxWidth().wrapContentWidth(Alignment.CenterHorizontally)) {
CompactChip(
onClick = {
Toast.makeText(
- applicationContext, "Fixed width chip with custom icon color",
- Toast.LENGTH_LONG
- ).show()
+ applicationContext,
+ "Fixed width chip with custom icon color",
+ Toast.LENGTH_LONG
+ )
+ .show()
},
modifier = Modifier.width(100.dp),
- colors = ChipDefaults.secondaryChipColors(
- contentColor = AlternatePrimaryColor3
- ),
+ colors =
+ ChipDefaults.secondaryChipColors(contentColor = AlternatePrimaryColor3),
icon = {
DemoIcon(
resourceId = R.drawable.ic_accessibility_24px,
@@ -561,15 +545,14 @@
ToggleChip(
checked = enabled,
onCheckedChange = { enabled = it },
- label = {
- Text("Chips enabled")
- },
+ label = { Text("Chips enabled") },
// For Switch toggle controls the Wear Material UX guidance is to set the
// unselected toggle control color to ToggleChipDefaults.switchUncheckedIconColor()
// rather than the default.
- colors = ToggleChipDefaults.toggleChipColors(
- uncheckedToggleControlColor = ToggleChipDefaults.SwitchUncheckedIconColor
- ),
+ colors =
+ ToggleChipDefaults.toggleChipColors(
+ uncheckedToggleControlColor = ToggleChipDefaults.SwitchUncheckedIconColor
+ ),
toggleControl = {
Icon(
imageVector = ToggleChipDefaults.switchIcon(checked = enabled),
@@ -588,20 +571,16 @@
ScalingLazyColumn(
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.spacedBy(4.dp, Alignment.CenterVertically),
- contentPadding = PaddingValues(
- start = 8.dp,
- end = 8.dp,
- top = 15.dp,
- bottom = 50.dp
- )
+ contentPadding = PaddingValues(start = 8.dp, end = 8.dp, top = 15.dp, bottom = 50.dp)
) {
item {
DemoLabelChip(
style = ChipStyle.Secondary,
label = "Custom background image",
- colors = ChipDefaults.imageBackgroundChipColors(
- backgroundImagePainter = painterResource(id = R.drawable.backgroundimage1),
- ),
+ colors =
+ ChipDefaults.imageBackgroundChipColors(
+ backgroundImagePainter = painterResource(id = R.drawable.backgroundimage1),
+ ),
enabled = enabled,
)
}
@@ -610,9 +589,10 @@
style = ChipStyle.Secondary,
label = "Custom background image",
secondaryLabel = "with secondary label",
- colors = ChipDefaults.imageBackgroundChipColors(
- backgroundImagePainter = painterResource(id = R.drawable.backgroundimage1),
- ),
+ colors =
+ ChipDefaults.imageBackgroundChipColors(
+ backgroundImagePainter = painterResource(id = R.drawable.backgroundimage1),
+ ),
enabled = enabled,
)
}
@@ -620,15 +600,14 @@
ToggleChip(
checked = enabled,
onCheckedChange = { enabled = it },
- label = {
- Text("Chips enabled")
- },
+ label = { Text("Chips enabled") },
// For Switch toggle controls the Wear Material UX guidance is to set the
// unselected toggle control color to ToggleChipDefaults.switchUncheckedIconColor()
// rather than the default.
- colors = ToggleChipDefaults.toggleChipColors(
- uncheckedToggleControlColor = ToggleChipDefaults.SwitchUncheckedIconColor
- ),
+ colors =
+ ToggleChipDefaults.toggleChipColors(
+ uncheckedToggleControlColor = ToggleChipDefaults.SwitchUncheckedIconColor
+ ),
toggleControl = {
Icon(
imageVector = ToggleChipDefaults.switchIcon(checked = enabled),
@@ -647,9 +626,7 @@
onEnabledChanged: ((enabled: Boolean) -> Unit),
onChipStyleChanged: ((chipStyle: ChipStyle) -> Unit),
) {
- Column(
- verticalArrangement = Arrangement.spacedBy(8.dp, Alignment.CenterVertically)
- ) {
+ Column(verticalArrangement = Arrangement.spacedBy(8.dp, Alignment.CenterVertically)) {
Text(
text = "Chip color",
style = MaterialTheme.typography.body2,
@@ -660,9 +637,7 @@
while (i < ChipStyle.values().size) {
Row(
horizontalArrangement = Arrangement.spacedBy(4.dp, Alignment.CenterHorizontally),
- modifier = Modifier
- .align(Alignment.CenterHorizontally)
- .height(35.dp),
+ modifier = Modifier.align(Alignment.CenterHorizontally).height(35.dp),
) {
ChipStyleChip(
chipStyle = ChipStyle.values()[i],
@@ -682,15 +657,14 @@
ToggleChip(
checked = enabled,
onCheckedChange = onEnabledChanged,
- label = {
- Text("Chips enabled")
- },
+ label = { Text("Chips enabled") },
// For Switch toggle controls the Wear Material UX guidance is to set the
// unselected toggle control color to ToggleChipDefaults.switchUncheckedIconColor()
// rather than the default.
- colors = ToggleChipDefaults.toggleChipColors(
- uncheckedToggleControlColor = ToggleChipDefaults.SwitchUncheckedIconColor
- ),
+ colors =
+ ToggleChipDefaults.toggleChipColors(
+ uncheckedToggleControlColor = ToggleChipDefaults.SwitchUncheckedIconColor
+ ),
toggleControl = {
Icon(
imageVector = ToggleChipDefaults.switchIcon(checked = enabled),
@@ -709,9 +683,7 @@
) {
ToggleButton(
checked = selectedChipStyle == chipStyle,
- onCheckedChange = {
- onChipStyleChanged(chipStyle)
- },
+ onCheckedChange = { onChipStyleChanged(chipStyle) },
) {
Text(
style = MaterialTheme.typography.caption2,
@@ -755,10 +727,7 @@
modifier = modifier,
colors = colors,
label = {
- Text(
- text = label, maxLines = maxLabelLines,
- overflow = TextOverflow.Ellipsis
- )
+ Text(text = label, maxLines = maxLabelLines, overflow = TextOverflow.Ellipsis)
},
icon = content,
shape = shape,
@@ -770,10 +739,7 @@
modifier = modifier,
colors = colors,
label = {
- Text(
- text = label, maxLines = maxLabelLines,
- overflow = TextOverflow.Ellipsis
- )
+ Text(text = label, maxLines = maxLabelLines, overflow = TextOverflow.Ellipsis)
},
icon = content,
shape = shape,
@@ -800,26 +766,23 @@
onClick = onClick,
modifier = modifier,
colors = colors,
- label = {
- Text(
- text = label, maxLines = 3,
- overflow = TextOverflow.Ellipsis
- )
- },
- secondaryLabel = secondaryLabel?.let {
- {
- CompositionLocalProvider(
- LocalContentColor provides
- (secondaryLabelColor ?: colors.contentColor(enabled = enabled).value)
- ) {
- Text(
- text = secondaryLabel,
- maxLines = 2,
- overflow = TextOverflow.Ellipsis
- )
+ label = { Text(text = label, maxLines = 3, overflow = TextOverflow.Ellipsis) },
+ secondaryLabel =
+ secondaryLabel?.let {
+ {
+ CompositionLocalProvider(
+ LocalContentColor provides
+ (secondaryLabelColor
+ ?: colors.contentColor(enabled = enabled).value)
+ ) {
+ Text(
+ text = secondaryLabel,
+ maxLines = 2,
+ overflow = TextOverflow.Ellipsis
+ )
+ }
}
- }
- },
+ },
icon = content,
shape = shape,
enabled = enabled,
@@ -829,27 +792,23 @@
onClick = onClick,
modifier = modifier,
colors = colors,
- label = {
- Text(
- text = label,
- maxLines = 3,
- overflow = TextOverflow.Ellipsis
- )
- },
- secondaryLabel = secondaryLabel?.let {
- {
- CompositionLocalProvider(
- LocalContentColor provides
- (secondaryLabelColor ?: colors.contentColor(enabled = enabled).value)
- ) {
- Text(
- text = secondaryLabel,
- maxLines = 2,
- overflow = TextOverflow.Ellipsis
- )
+ label = { Text(text = label, maxLines = 3, overflow = TextOverflow.Ellipsis) },
+ secondaryLabel =
+ secondaryLabel?.let {
+ {
+ CompositionLocalProvider(
+ LocalContentColor provides
+ (secondaryLabelColor
+ ?: colors.contentColor(enabled = enabled).value)
+ ) {
+ Text(
+ text = secondaryLabel,
+ maxLines = 2,
+ overflow = TextOverflow.Ellipsis
+ )
+ }
}
- }
- },
+ },
icon = content,
shape = shape,
enabled = enabled,
diff --git a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/CurvedLayoutDemo.kt b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/CurvedLayoutDemo.kt
index 041d056..e28fe59 100644
--- a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/CurvedLayoutDemo.kt
+++ b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/CurvedLayoutDemo.kt
@@ -64,22 +64,15 @@
@Composable
fun CurvedWorldDemo() {
CurvedLayout(modifier = Modifier.fillMaxSize()) {
- curvedComposable {
- Box(
- modifier = Modifier
- .size(20.dp)
- .background(Color.Red)
- )
- }
+ curvedComposable { Box(modifier = Modifier.size(20.dp).background(Color.Red)) }
curvedComposable {
Column(
- modifier = Modifier
- .background(Color.Gray)
- .padding(3.dp),
+ modifier = Modifier.background(Color.Gray).padding(3.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
- text = "A", color = Color.Black,
+ text = "A",
+ color = Color.Black,
fontSize = 16.sp,
modifier = Modifier.background(Color.Blue)
)
@@ -99,13 +92,7 @@
}
}
}
- curvedComposable {
- Box(
- modifier = Modifier
- .size(20.dp)
- .background(Color.Red)
- )
- }
+ curvedComposable { Box(modifier = Modifier.size(20.dp).background(Color.Red)) }
}
CurvedLayout(
anchor = 90F,
@@ -156,35 +143,19 @@
private fun CurvedScope.SeparatorBlock() {
curvedComposable(radialAlignment = CurvedAlignment.Radial.Outer) {
- Box(
- modifier = Modifier
- .size(10.dp, 40.dp)
- .background(Color.Gray)
- )
+ Box(modifier = Modifier.size(10.dp, 40.dp).background(Color.Gray))
}
}
private fun CurvedScope.RgbBlocks() {
curvedComposable(radialAlignment = CurvedAlignment.Radial.Outer) {
- Box(
- modifier = Modifier
- .size(20.dp)
- .background(Color.Red)
- )
+ Box(modifier = Modifier.size(20.dp).background(Color.Red))
}
curvedComposable(radialAlignment = CurvedAlignment.Radial.Center) {
- Box(
- modifier = Modifier
- .size(20.dp)
- .background(Color.Green)
- )
+ Box(modifier = Modifier.size(20.dp).background(Color.Green))
}
curvedComposable(radialAlignment = CurvedAlignment.Radial.Inner) {
- Box(
- modifier = Modifier
- .size(20.dp)
- .background(Color.Blue)
- )
+ Box(modifier = Modifier.size(20.dp).background(Color.Blue))
}
}
@@ -196,19 +167,12 @@
SeparatorBlock()
(0..10).forEach {
curvedComposable(radialAlignment = CurvedAlignment.Radial.Custom(it / 10.0f)) {
- Box(
- modifier = Modifier
- .size(10.dp)
- .background(Color.White)
- )
+ Box(modifier = Modifier.size(10.dp).background(Color.White))
}
}
SeparatorBlock()
}
- CurvedLayout(
- anchor = 90f,
- angularDirection = CurvedDirection.Angular.Reversed
- ) {
+ CurvedLayout(anchor = 90f, angularDirection = CurvedDirection.Angular.Reversed) {
SeparatorBlock()
RgbBlocks()
SeparatorBlock()
@@ -221,18 +185,14 @@
SeparatorBlock()
basicCurvedText(
"Curved Text",
- CurvedTextStyle(
- fontSize = 18.sp
- ),
+ CurvedTextStyle(fontSize = 18.sp),
// TODO: Re-add when we implement alignment modifiers.
// modifier = Modifier.radialAlignment(RadialAlignment.Outer)
)
SeparatorBlock()
basicCurvedText(
"And More",
- CurvedTextStyle(
- fontSize = 24.sp
- ),
+ CurvedTextStyle(fontSize = 24.sp),
angularDirection = CurvedDirection.Angular.Reversed,
modifier = CurvedModifier.padding(angular = 5.dp),
// TODO: Re-add when we implement alignment modifiers.
@@ -251,9 +211,7 @@
modifier = CurvedModifier.weight(1f),
overflow = TextOverflow.Ellipsis
)
- curvedText(
- "10:00"
- )
+ curvedText("10:00")
}
}
}
@@ -261,9 +219,7 @@
@Composable
fun CurvedLayoutDirection() {
var layoutDirection by remember { mutableStateOf(false) }
- val actualLayoutDirection =
- if (layoutDirection) LayoutDirection.Rtl
- else LayoutDirection.Ltr
+ val actualLayoutDirection = if (layoutDirection) LayoutDirection.Rtl else LayoutDirection.Ltr
CompositionLocalProvider(LocalLayoutDirection provides actualLayoutDirection) {
Box {
Row(modifier = Modifier.align(Alignment.Center)) {
@@ -271,29 +227,24 @@
ToggleButton(
checked = layoutDirection,
onCheckedChange = { layoutDirection = !layoutDirection }
- ) { Text(if (layoutDirection) "Rtl" else "Ltr") }
+ ) {
+ Text(if (layoutDirection) "Rtl" else "Ltr")
+ }
}
repeat(2) { topDown ->
CurvedLayout(
anchor = listOf(270f, 90f)[topDown],
- angularDirection = listOf(
- CurvedDirection.Angular.Normal,
- CurvedDirection.Angular.Reversed
- )[topDown]
+ angularDirection =
+ listOf(CurvedDirection.Angular.Normal, CurvedDirection.Angular.Reversed)[
+ topDown]
) {
curvedRow(CurvedModifier.background(Color.White)) {
basicCurvedText(
"Before",
- CurvedTextStyle(
- fontSize = 24.sp
- ),
+ CurvedTextStyle(fontSize = 24.sp),
modifier = CurvedModifier.padding(angular = 5.dp),
)
- curvedColumn {
- repeat(3) {
- basicCurvedText("#$it")
- }
- }
+ curvedColumn { repeat(3) { basicCurvedText("#$it") } }
curvedRow {
curvedComposable {
Text(
@@ -326,36 +277,18 @@
angularAlignment = CurvedAlignment.Angular.End
) {
curvedComposable {
- Box(
- modifier = Modifier
- .width(60.dp)
- .height(40.dp)
- .background(Color.Green)
- )
+ Box(modifier = Modifier.width(60.dp).height(40.dp).background(Color.Green))
}
- curvedComposable {
- WhiteCircle()
- }
+ curvedComposable { WhiteCircle() }
}
}
CurvedLayout(
modifier = Modifier.fillMaxSize(),
anchor = 180f,
) {
- curvedBox(
- modifier = CurvedModifier
- .background(Color.Red)
- ) {
- curvedComposable {
- Box(
- modifier = Modifier
- .size(60.dp)
- .background(Color.Green)
- )
- }
- curvedComposable {
- WhiteCircle()
- }
+ curvedBox(modifier = CurvedModifier.background(Color.Red)) {
+ curvedComposable { Box(modifier = Modifier.size(60.dp).background(Color.Green)) }
+ curvedComposable { WhiteCircle() }
}
}
CurvedLayout(modifier = Modifier.fillMaxSize()) {
@@ -365,26 +298,14 @@
angularAlignment = CurvedAlignment.Angular.Start
) {
curvedComposable {
- Box(
- modifier = Modifier
- .width(40.dp)
- .height(60.dp)
- .background(Color.Green)
- )
+ Box(modifier = Modifier.width(40.dp).height(60.dp).background(Color.Green))
}
- curvedComposable {
- WhiteCircle()
- }
+ curvedComposable { WhiteCircle() }
}
}
}
@Composable
private fun WhiteCircle() {
- Box(
- modifier = Modifier
- .size(30.dp)
- .clip(CircleShape)
- .background(Color.White)
- )
+ Box(modifier = Modifier.size(30.dp).clip(CircleShape).background(Color.White))
}
diff --git a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/DemoActivity.kt b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/DemoActivity.kt
index c1808e2..85f81ed 100644
--- a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/DemoActivity.kt
+++ b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/DemoActivity.kt
@@ -41,9 +41,7 @@
import androidx.wear.compose.integration.demos.common.DemoCategory
import androidx.wear.compose.material.MaterialTheme
-/**
- * Main [Activity] for Wear Compose related demos.
- */
+/** Main [Activity] for Wear Compose related demos. */
class DemoActivity : ComponentActivity() {
lateinit var hostView: View
lateinit var focusManager: FocusManager
@@ -52,38 +50,44 @@
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- ComposeView(this).also {
- setContentView(it)
- }.setContent {
- hostView = LocalView.current
- focusManager = LocalFocusManager.current
- val activityStarter = fun(demo: ActivityDemo<*>) {
- startActivity(Intent(this, demo.activityClass.java))
- }
- val navigator = rememberSaveable(
- saver = Navigator.Saver(WearComposeDemos, onBackPressedDispatcher, activityStarter)
- ) {
- Navigator(WearComposeDemos, onBackPressedDispatcher, activityStarter)
- }
- MaterialTheme {
- DemoApp(
- currentDemo = navigator.currentDemo,
- parentDemo = navigator.parentDemo,
- onNavigateTo = { demo ->
- navigator.navigateTo(demo)
- },
- onNavigateBack = {
- if (!navigator.navigateBack()) {
- ActivityCompat.finishAffinity(this)
- }
+ ComposeView(this)
+ .also { setContentView(it) }
+ .setContent {
+ hostView = LocalView.current
+ focusManager = LocalFocusManager.current
+ val activityStarter =
+ fun(demo: ActivityDemo<*>) {
+ startActivity(Intent(this, demo.activityClass.java))
}
- )
+ val navigator =
+ rememberSaveable(
+ saver =
+ Navigator.Saver(
+ WearComposeDemos,
+ onBackPressedDispatcher,
+ activityStarter
+ )
+ ) {
+ Navigator(WearComposeDemos, onBackPressedDispatcher, activityStarter)
+ }
+ MaterialTheme {
+ DemoApp(
+ currentDemo = navigator.currentDemo,
+ parentDemo = navigator.parentDemo,
+ onNavigateTo = { demo -> navigator.navigateTo(demo) },
+ onNavigateBack = {
+ if (!navigator.navigateBack()) {
+ ActivityCompat.finishAffinity(this)
+ }
+ }
+ )
+ }
}
- }
}
}
-private class Navigator private constructor(
+private class Navigator
+private constructor(
private val backDispatcher: OnBackPressedDispatcher,
private val launchActivityDemo: (ActivityDemo<*>) -> Unit,
initialDemo: Demo,
@@ -95,14 +99,16 @@
launchActivityDemo: (ActivityDemo<*>) -> Unit
) : this(backDispatcher, launchActivityDemo, rootDemo, mutableListOf<Demo>())
- private val onBackPressed = object : OnBackPressedCallback(false) {
- override fun handleOnBackPressed() {
- navigateBack()
- }
- }.apply {
- isEnabled = !isRoot
- backDispatcher.addCallback(this)
- }
+ private val onBackPressed =
+ object : OnBackPressedCallback(false) {
+ override fun handleOnBackPressed() {
+ navigateBack()
+ }
+ }
+ .apply {
+ isEnabled = !isRoot
+ backDispatcher.addCallback(this)
+ }
private var _currentDemo by mutableStateOf(initialDemo)
var currentDemo: Demo
@@ -115,7 +121,8 @@
val parentDemo: Demo?
get() = backStack.lastOrNull()
- val isRoot: Boolean get() = backStack.isEmpty()
+ val isRoot: Boolean
+ get() = backStack.isEmpty()
fun navigateTo(demo: Demo) {
if (demo is ActivityDemo<*>) {
@@ -140,21 +147,21 @@
rootDemo: DemoCategory,
backDispatcher: OnBackPressedDispatcher,
launchActivityDemo: (ActivityDemo<*>) -> Unit
- ): Saver<Navigator, *> = listSaver<Navigator, String>(
- save = { navigator ->
- (navigator.backStack + navigator.currentDemo).map { it.title }
- },
- restore = { restored ->
- require(restored.isNotEmpty()) { "restored demo is empty" }
- val backStack = restored.mapTo(mutableListOf()) {
- requireNotNull(findDemo(rootDemo, it)) { "No root demo" }
+ ): Saver<Navigator, *> =
+ listSaver<Navigator, String>(
+ save = { navigator ->
+ (navigator.backStack + navigator.currentDemo).map { it.title }
+ },
+ restore = { restored ->
+ require(restored.isNotEmpty()) { "restored demo is empty" }
+ val backStack =
+ restored.mapTo(mutableListOf()) {
+ requireNotNull(findDemo(rootDemo, it)) { "No root demo" }
+ }
+ val initial = backStack.removeAt(backStack.lastIndex)
+ Navigator(backDispatcher, launchActivityDemo, initial, backStack)
}
- val initial = backStack.removeAt(backStack.lastIndex)
- Navigator(
- backDispatcher, launchActivityDemo, initial, backStack
- )
- }
- )
+ )
private fun findDemo(demo: Demo, title: String): Demo? {
if (demo.title == title) {
@@ -162,8 +169,9 @@
}
if (demo is DemoCategory) {
demo.demos.forEach { child ->
- findDemo(child, title)
- ?.let { return it }
+ findDemo(child, title)?.let {
+ return it
+ }
}
}
return null
diff --git a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/DemoApp.kt b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/DemoApp.kt
index 10c1435..d05ed51 100644
--- a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/DemoApp.kt
+++ b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/DemoApp.kt
@@ -54,8 +54,7 @@
onNavigateBack: () -> Unit,
) {
val swipeToDismissState = swipeDismissStateWithNavigation(onNavigateBack)
- DisplayDemo(
- swipeToDismissState, currentDemo, parentDemo, onNavigateTo, onNavigateBack)
+ DisplayDemo(swipeToDismissState, currentDemo, parentDemo, onNavigateTo, onNavigateBack)
}
@Composable
@@ -72,12 +71,7 @@
backgroundKey = parentDemo?.title ?: SwipeToDismissKeys.Background,
contentKey = currentDemo.title,
) { isBackground ->
- BoxDemo(
- state,
- if (isBackground) parentDemo else currentDemo,
- onNavigateTo,
- onNavigateBack
- )
+ BoxDemo(state, if (isBackground) parentDemo else currentDemo, onNavigateTo, onNavigateBack)
}
}
@@ -92,32 +86,23 @@
is ActivityDemo<*> -> {
/* should never get here as activity demos are not added to the backstack*/
}
-
is ComposableDemo -> {
demo.content(DemoParameters(onNavigateBack, state))
}
-
is DemoCategory -> {
DisplayDemoList(demo, onNavigateTo)
}
-
- else -> {
- }
+ else -> {}
}
}
@Composable
-internal fun BoxScope.DisplayDemoList(
- category: DemoCategory,
- onNavigateTo: (Demo) -> Unit
-) {
+internal fun BoxScope.DisplayDemoList(category: DemoCategory, onNavigateTo: (Demo) -> Unit) {
val state = category.getScrollStateOrInit { rememberScalingLazyListState() }
ScalingLazyColumn(
horizontalAlignment = Alignment.CenterHorizontally,
- modifier = Modifier
- .fillMaxWidth()
- .testTag(DemoListTag),
+ modifier = Modifier.fillMaxWidth().testTag(DemoListTag),
state = state,
autoCentering = AutoCenteringParams(itemIndex = if (category.demos.size >= 2) 2 else 1),
) {
@@ -129,23 +114,16 @@
color = Color.White,
textAlign = TextAlign.Center,
modifier = Modifier.fillMaxWidth()
-
)
}
}
category.demos.forEach { demo ->
item {
Chip(
- onClick = {
- onNavigateTo(demo)
- },
+ onClick = { onNavigateTo(demo) },
colors = ChipDefaults.secondaryChipColors(),
label = {
- Text(
- text = demo.title,
- modifier = Modifier.fillMaxWidth(),
- maxLines = 2
- )
+ Text(text = demo.title, modifier = Modifier.fillMaxWidth(), maxLines = 2)
},
modifier = Modifier.fillMaxWidth()
)
@@ -157,9 +135,7 @@
) {
Text(
text = description,
- modifier = Modifier
- .fillMaxWidth()
- .align(Alignment.Center),
+ modifier = Modifier.fillMaxWidth().align(Alignment.Center),
textAlign = TextAlign.Center
)
}
@@ -170,9 +146,7 @@
}
@Composable
-internal fun swipeDismissStateWithNavigation(
- onNavigateBack: () -> Unit
-): SwipeToDismissBoxState {
+internal fun swipeDismissStateWithNavigation(onNavigateBack: () -> Unit): SwipeToDismissBoxState {
val state = rememberSwipeToDismissBoxState()
LaunchedEffect(state.currentValue) {
if (state.currentValue == SwipeToDismissValue.Dismissed) {
diff --git a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/DemoComponents.kt b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/DemoComponents.kt
index 5fb5a79..f26572b 100644
--- a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/DemoComponents.kt
+++ b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/DemoComponents.kt
@@ -39,9 +39,7 @@
import androidx.wear.compose.material.MaterialTheme
import androidx.wear.compose.material.Text
-/**
- * A simple [Icon] with default size
- */
+/** A simple [Icon] with default size */
@Composable
fun DemoIcon(
resourceId: Int,
@@ -52,9 +50,7 @@
Icon(
painter = painterResource(id = resourceId),
contentDescription = contentDescription,
- modifier = modifier
- .size(size)
- .wrapContentSize(align = Alignment.Center),
+ modifier = modifier.size(size).wrapContentSize(align = Alignment.Center),
)
}
@@ -74,31 +70,24 @@
}
@Composable
-fun TextIcon(
- text: String,
- size: Dp = 24.dp,
- style: TextStyle = MaterialTheme.typography.button
-) {
+fun TextIcon(text: String, size: Dp = 24.dp, style: TextStyle = MaterialTheme.typography.button) {
Button(
- modifier = Modifier
- .padding(0.dp)
- .requiredSize(32.dp),
+ modifier = Modifier.padding(0.dp).requiredSize(32.dp),
onClick = {},
- colors = ButtonDefaults.buttonColors(
- disabledBackgroundColor = MaterialTheme.colors.primary.copy(
- alpha = LocalContentAlpha.current
+ colors =
+ ButtonDefaults.buttonColors(
+ disabledBackgroundColor =
+ MaterialTheme.colors.primary.copy(alpha = LocalContentAlpha.current),
+ disabledContentColor =
+ MaterialTheme.colors.onPrimary.copy(alpha = LocalContentAlpha.current)
),
- disabledContentColor = MaterialTheme.colors.onPrimary.copy(
- alpha = LocalContentAlpha.current
- )
- ),
enabled = false
) {
Box(
- modifier = Modifier
- .padding(all = 0.dp)
- .requiredSize(size)
- .wrapContentSize(align = Alignment.Center)
+ modifier =
+ Modifier.padding(all = 0.dp)
+ .requiredSize(size)
+ .wrapContentSize(align = Alignment.Center)
) {
Text(
text = text,
diff --git a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/Demos.kt b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/Demos.kt
index 8efc582..6f18557 100644
--- a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/Demos.kt
+++ b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/Demos.kt
@@ -28,38 +28,34 @@
import androidx.wear.compose.material.Text
import androidx.wear.compose.material3.demos.WearMaterial3Demos
-val Info = DemoCategory(
- "App Info",
- listOf(
- ComposableDemo("App Version") {
- val version =
- @Suppress("DEPRECATION")
- LocalContext.current.packageManager
- .getPackageInfo(LocalContext.current.packageName, 0).versionName
+val Info =
+ DemoCategory(
+ "App Info",
+ listOf(
+ ComposableDemo("App Version") {
+ val version =
+ @Suppress("DEPRECATION")
+ LocalContext.current.packageManager
+ .getPackageInfo(LocalContext.current.packageName, 0)
+ .versionName
- Column(
- modifier = Modifier.fillMaxSize(),
- verticalArrangement = Arrangement.Center,
- horizontalAlignment = Alignment.CenterHorizontally
- ) {
- Text(
- text = "Version: $version",
- textAlign = TextAlign.Center,
- )
+ Column(
+ modifier = Modifier.fillMaxSize(),
+ verticalArrangement = Arrangement.Center,
+ horizontalAlignment = Alignment.CenterHorizontally
+ ) {
+ Text(
+ text = "Version: $version",
+ textAlign = TextAlign.Center,
+ )
+ }
}
- }
- ),
-)
-
-/**
- * [DemoCategory] containing all the top level demo categories.
- */
-val WearComposeDemos = DemoCategory(
- "Wear Compose Demos",
- listOf(
- WearFoundationDemos,
- WearMaterialDemos,
- WearMaterial3Demos,
- Info
+ ),
)
-)
+
+/** [DemoCategory] containing all the top level demo categories. */
+val WearComposeDemos =
+ DemoCategory(
+ "Wear Compose Demos",
+ listOf(WearFoundationDemos, WearMaterialDemos, WearMaterial3Demos, Info)
+ )
diff --git a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/DialogDemo.kt b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/DialogDemo.kt
index 8d61b3f..4e9d88f 100644
--- a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/DialogDemo.kt
+++ b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/DialogDemo.kt
@@ -205,12 +205,13 @@
icon = {
DemoIcon(resourceId = R.drawable.ic_baseline_error_24, contentDescription = "Error")
},
- title = { Text(
- text = "You need to grant location permission to use this app",
- textAlign = TextAlign.Center
- ) },
- contentPadding =
- PaddingValues(start = 10.dp, end = 10.dp, top = 0.dp, bottom = 16.dp),
+ title = {
+ Text(
+ text = "You need to grant location permission to use this app",
+ textAlign = TextAlign.Center
+ )
+ },
+ contentPadding = PaddingValues(start = 10.dp, end = 10.dp, top = 0.dp, bottom = 16.dp),
) {
item {
Chip(
@@ -245,8 +246,10 @@
contentPadding = PaddingValues(start = 10.dp, end = 10.dp, top = 36.dp, bottom = 52.dp),
scrollState = scrollState,
title = {
- Row(modifier = Modifier.fillMaxWidth(),
- horizontalArrangement = Arrangement.Center) {
+ Row(
+ modifier = Modifier.fillMaxWidth(),
+ horizontalArrangement = Arrangement.Center
+ ) {
Text(text = "Title that is quite long", textAlign = TextAlign.Center)
}
},
@@ -273,7 +276,8 @@
icon = {
DemoIcon(
resourceId = R.drawable.ic_clear_24px,
- contentDescription = "Cross")
+ contentDescription = "Cross"
+ )
},
label = { Text("Keep \"while app is in use\"") },
onClick = { showDialog = false },
@@ -298,13 +302,11 @@
DemoIcon(
resourceId = R.drawable.ic_check_48px,
size = 48.dp,
- contentDescription = "Tick")
+ contentDescription = "Tick"
+ )
},
) {
- Text(
- text = "Success",
- textAlign = TextAlign.Center
- )
+ Text(text = "Success", textAlign = TextAlign.Center)
}
}
}
diff --git a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/ExpandableDemo.kt b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/ExpandableDemo.kt
index 4f65da3..23cf41c 100644
--- a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/ExpandableDemo.kt
+++ b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/ExpandableDemo.kt
@@ -60,12 +60,8 @@
val rest = items.drop(3)
val color = MaterialTheme.colors.secondary
ContainingScalingLazyColumn {
- items(top.size) {
- DemoItem(top[it], color = color)
- }
- expandableItems(state, rest.size) {
- DemoItem(rest[it], color = color)
- }
+ items(top.size) { DemoItem(top[it], color = color) }
+ expandableItems(state, rest.size) { DemoItem(rest[it], color = color) }
expandButton(state, outline = true)
}
}
@@ -88,13 +84,17 @@
val states = rememberExpandableStateMapping<Int>()
- ScalingLazyColumn(
- modifier = Modifier.fillMaxSize()
- ) {
+ ScalingLazyColumn(modifier = Modifier.fillMaxSize()) {
items.forEachIndexed { ix, item ->
val state = states.getOrPutNew(item.key)
expandableItem(state, item.key) { expanded ->
- Text((if (expanded) { "Expanded " } else { "" }) + item)
+ Text(
+ (if (expanded) {
+ "Expanded "
+ } else {
+ ""
+ }) + item
+ )
}
item(key = item.key + 1_000_000) {
Row(
@@ -102,16 +102,16 @@
horizontalArrangement = Arrangement.spacedBy(5.dp)
) {
Button(onClick = { state.expanded = !state.expanded }) {
- Text(if (state.expanded) { "-" } else { "+" })
+ Text(
+ if (state.expanded) {
+ "-"
+ } else {
+ "+"
+ }
+ )
}
- Button(onClick = { items.removeAt(ix) }) {
- Text("Del")
- }
- Button(onClick = {
- items.add(ix, ItemsToShow("New"))
- }) {
- Text("Add")
- }
+ Button(onClick = { items.removeAt(ix) }) { Text("Del") }
+ Button(onClick = { items.add(ix, ItemsToShow("New")) }) { Text("Add") }
}
}
}
@@ -139,11 +139,7 @@
expandButton(state, outline = false)
demoSeparator()
- item {
- ListHeader {
- Text("Inline expandable.")
- }
- }
+ item { ListHeader { Text("Inline expandable.") } }
expandableItem(state2) { expanded ->
Row(verticalAlignment = CenterVertically) {
Text(if (expanded) "Expanded" else "Collapsed")
@@ -159,38 +155,22 @@
@Composable
private fun ContainingScalingLazyColumn(content: ScalingLazyListScope.() -> Unit) {
val color = MaterialTheme.colors.primary
- ScalingLazyColumn(
- modifier = Modifier.fillMaxSize()
- ) {
- repeat(10) {
- item {
- DemoItem("Item $it - before", color)
- }
- }
+ ScalingLazyColumn(modifier = Modifier.fillMaxSize()) {
+ repeat(10) { item { DemoItem("Item $it - before", color) } }
demoSeparator()
content()
demoSeparator()
- repeat(10) {
- item {
- DemoItem("Item $it - after", color)
- }
- }
+ repeat(10) { item { DemoItem("Item $it - after", color) } }
}
}
-private fun ScalingLazyListScope.expandButton(
- state: ExpandableState,
- outline: Boolean = true
-) {
+private fun ScalingLazyListScope.expandButton(state: ExpandableState, outline: Boolean = true) {
expandableButton(state) {
CompactChip(
label = {
Text("Show More")
Spacer(Modifier.size(6.dp))
- DemoIcon(
- resourceId = R.drawable.ic_expand_more_24,
- contentDescription = "Expand"
- )
+ DemoIcon(resourceId = R.drawable.ic_expand_more_24, contentDescription = "Expand")
},
onClick = { state.expanded = true },
border = if (outline) ChipDefaults.outlinedChipBorder() else ChipDefaults.chipBorder()
@@ -200,8 +180,7 @@
private fun ScalingLazyListScope.demoSeparator() = item {
Box(
- Modifier
- .padding(horizontal = 10.dp, vertical = 5.dp)
+ Modifier.padding(horizontal = 10.dp, vertical = 5.dp)
.background(Color.White)
.fillMaxWidth()
.height(2.dp)
@@ -209,13 +188,11 @@
}
@Composable
-private fun DemoItem(
- label: String,
- color: Color
-) = Chip(
- label = { Text(label) },
- onClick = { },
- secondaryLabel = { Text("line 2 - Secondary") },
- icon = { DemoIcon(resourceId = R.drawable.ic_play) },
- colors = ChipDefaults.primaryChipColors(backgroundColor = color)
-)
+private fun DemoItem(label: String, color: Color) =
+ Chip(
+ label = { Text(label) },
+ onClick = {},
+ secondaryLabel = { Text("line 2 - Secondary") },
+ icon = { DemoIcon(resourceId = R.drawable.ic_play) },
+ colors = ChipDefaults.primaryChipColors(backgroundColor = color)
+ )
diff --git a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/FoundationDemos.kt b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/FoundationDemos.kt
index 2276907..ef0992d 100644
--- a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/FoundationDemos.kt
+++ b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/FoundationDemos.kt
@@ -77,127 +77,134 @@
ComposableDemo("EdgeSwipeToDismiss modifier") { params ->
EdgeSwipeDemo(params.swipeToDismissBoxState)
},
- ComposableDemo("Nested SwipeToDismissBox") {
- NestedSwipeToDismissDemo()
- }
+ ComposableDemo("Nested SwipeToDismissBox") { NestedSwipeToDismissDemo() }
)
)
)
)
-val WearFoundationDemos = DemoCategory(
- "Foundation",
- listOf(
- DemoCategory(
- "Expandables",
- listOf(
- ComposableDemo("Items in SLC") { ExpandableListItems() },
- ComposableDemo("Multiple Items") { ExpandableMultipleItems() },
- ComposableDemo("Expandable Text") { ExpandableText() },
- ComposableDemo("Items Sample") { ExpandableWithItemsSample() },
- ComposableDemo("Text Sample") { ExpandableTextSample() },
- )
- ),
- DemoCategory("CurvedLayout", listOf(
- ComposableDemo("Curved Row") { CurvedWorldDemo() },
- ComposableDemo("Curved Row and Column") { CurvedRowAndColumn() },
- ComposableDemo("Curved Box") { CurvedBoxDemo() },
- ComposableDemo("Simple") { SimpleCurvedWorld() },
- ComposableDemo("Alignment") { CurvedRowAlignmentDemo() },
- ComposableDemo("Curved Text") { BasicCurvedTextDemo() },
- ComposableDemo("Curved and Normal Text") { CurvedAndNormalText() },
- ComposableDemo("Fixed size") { CurvedFixedSize() },
- ComposableDemo("Oversize composable") { OversizeComposable() },
- ComposableDemo("Weights") { CurvedWeight() },
- ComposableDemo("Ellipsis Demo") { CurvedEllipsis() },
- ComposableDemo("Bottom layout") { CurvedBottomLayout() },
- ComposableDemo("Curved layout direction") { CurvedLayoutDirection() },
- ComposableDemo("Background") { CurvedBackground() },
- ComposableDemo("Font Weight") { CurvedFontWeight() },
- ComposableDemo("Fonts") { CurvedFonts() },
- )),
- ComposableDemo("Scrollable Column") { ScrollableColumnDemo() },
- ComposableDemo("Scrollable Row") { ScrollableRowDemo() },
- DemoCategory("Rotary Input", listOf(
- DemoCategory("Samples", listOf(
- ComposableDemo(".rotary with scroll") { RotaryScrollSample() },
- ComposableDemo(".rotary with snap") { RotarySnapSample() },
- ComposableDemo("RotaryEvent") { ScrollUsingRotatingCrownDemo() },
- ComposableDemo("PreRotaryEvent") { InterceptScrollDemo() }
- )),
- DemoCategory("Demos", listOf())
- )),
- ComposableDemo("Focus Sample") { HierarchicalFocusCoordinatorSample() },
- DemoCategory("Scaling Lazy Column", listOf(
- ComposableDemo(
- "Defaults",
- "Basic ScalingLazyColumn using default values"
- ) {
- SimpleScalingLazyColumn()
- },
- ComposableDemo(
- "With Content Padding",
- "Basic ScalingLazyColumn with autoCentering disabled and explicit " +
- "content padding of top = 20.dp, bottom = 20.dp"
- ) {
- SimpleScalingLazyColumnWithContentPadding()
- },
- ComposableDemo(
- "With Snap",
- "Basic ScalingLazyColumn, center aligned with snap enabled"
- ) {
- SimpleScalingLazyColumnWithSnap()
- },
- ComposableDemo(
- "Edge Anchor",
- "A ScalingLazyColumn with Edge (rather than center) item anchoring. " +
- "If you click on an item there will be an animated scroll of the " +
- "items edge to the center"
- ) {
- ScalingLazyColumnEdgeAnchoredAndAnimatedScrollTo()
- },
+val WearFoundationDemos =
+ DemoCategory(
+ "Foundation",
+ listOf(
+ DemoCategory(
+ "Expandables",
+ listOf(
+ ComposableDemo("Items in SLC") { ExpandableListItems() },
+ ComposableDemo("Multiple Items") { ExpandableMultipleItems() },
+ ComposableDemo("Expandable Text") { ExpandableText() },
+ ComposableDemo("Items Sample") { ExpandableWithItemsSample() },
+ ComposableDemo("Text Sample") { ExpandableTextSample() },
+ )
),
- ),
- SwipeToDismissDemos,
- DemoCategory(
- "Swipe To Reveal",
- listOf(
- DemoCategory(
- "Samples",
- listOf(
- ComposableDemo("Material S2R Chip") { params ->
- Centralize {
- SwipeToRevealChipSample(params.swipeToDismissBoxState)
- }
- },
- ComposableDemo("Material S2R Card") { params ->
- Centralize {
- SwipeToRevealCardSample(params.swipeToDismissBoxState)
- }
- },
- )
+ DemoCategory(
+ "CurvedLayout",
+ listOf(
+ ComposableDemo("Curved Row") { CurvedWorldDemo() },
+ ComposableDemo("Curved Row and Column") { CurvedRowAndColumn() },
+ ComposableDemo("Curved Box") { CurvedBoxDemo() },
+ ComposableDemo("Simple") { SimpleCurvedWorld() },
+ ComposableDemo("Alignment") { CurvedRowAlignmentDemo() },
+ ComposableDemo("Curved Text") { BasicCurvedTextDemo() },
+ ComposableDemo("Curved and Normal Text") { CurvedAndNormalText() },
+ ComposableDemo("Fixed size") { CurvedFixedSize() },
+ ComposableDemo("Oversize composable") { OversizeComposable() },
+ ComposableDemo("Weights") { CurvedWeight() },
+ ComposableDemo("Ellipsis Demo") { CurvedEllipsis() },
+ ComposableDemo("Bottom layout") { CurvedBottomLayout() },
+ ComposableDemo("Curved layout direction") { CurvedLayoutDirection() },
+ ComposableDemo("Background") { CurvedBackground() },
+ ComposableDemo("Font Weight") { CurvedFontWeight() },
+ ComposableDemo("Fonts") { CurvedFonts() },
+ )
+ ),
+ ComposableDemo("Scrollable Column") { ScrollableColumnDemo() },
+ ComposableDemo("Scrollable Row") { ScrollableRowDemo() },
+ DemoCategory(
+ "Rotary Input",
+ listOf(
+ DemoCategory(
+ "Samples",
+ listOf(
+ ComposableDemo(".rotary with scroll") { RotaryScrollSample() },
+ ComposableDemo(".rotary with snap") { RotarySnapSample() },
+ ComposableDemo("RotaryEvent") { ScrollUsingRotatingCrownDemo() },
+ ComposableDemo("PreRotaryEvent") { InterceptScrollDemo() }
+ )
+ ),
+ DemoCategory("Demos", listOf())
+ )
+ ),
+ ComposableDemo("Focus Sample") { HierarchicalFocusCoordinatorSample() },
+ DemoCategory(
+ "Scaling Lazy Column",
+ listOf(
+ ComposableDemo("Defaults", "Basic ScalingLazyColumn using default values") {
+ SimpleScalingLazyColumn()
+ },
+ ComposableDemo(
+ "With Content Padding",
+ "Basic ScalingLazyColumn with autoCentering disabled and explicit " +
+ "content padding of top = 20.dp, bottom = 20.dp"
+ ) {
+ SimpleScalingLazyColumnWithContentPadding()
+ },
+ ComposableDemo(
+ "With Snap",
+ "Basic ScalingLazyColumn, center aligned with snap enabled"
+ ) {
+ SimpleScalingLazyColumnWithSnap()
+ },
+ ComposableDemo(
+ "Edge Anchor",
+ "A ScalingLazyColumn with Edge (rather than center) item anchoring. " +
+ "If you click on an item there will be an animated scroll of the " +
+ "items edge to the center"
+ ) {
+ ScalingLazyColumnEdgeAnchoredAndAnimatedScrollTo()
+ },
),
- DemoCategory(
- "Demos",
- listOf(
- ComposableDemo("S2R Chip, 2 actions") { params ->
- SwipeToRevealChips(
- params.swipeToDismissBoxState,
- includeSecondaryAction = true
- )
- },
- ComposableDemo("S2R Chip, 1 action") { params ->
- SwipeToRevealChips(
- params.swipeToDismissBoxState,
- includeSecondaryAction = false
- )
- },
- ComposableDemo("S2R Card") { params ->
- SwipeToRevealCards(params.swipeToDismissBoxState)
- },
+ ),
+ SwipeToDismissDemos,
+ DemoCategory(
+ "Swipe To Reveal",
+ listOf(
+ DemoCategory(
+ "Samples",
+ listOf(
+ ComposableDemo("Material S2R Chip") { params ->
+ Centralize {
+ SwipeToRevealChipSample(params.swipeToDismissBoxState)
+ }
+ },
+ ComposableDemo("Material S2R Card") { params ->
+ Centralize {
+ SwipeToRevealCardSample(params.swipeToDismissBoxState)
+ }
+ },
+ )
+ ),
+ DemoCategory(
+ "Demos",
+ listOf(
+ ComposableDemo("S2R Chip, 2 actions") { params ->
+ SwipeToRevealChips(
+ params.swipeToDismissBoxState,
+ includeSecondaryAction = true
+ )
+ },
+ ComposableDemo("S2R Chip, 1 action") { params ->
+ SwipeToRevealChips(
+ params.swipeToDismissBoxState,
+ includeSecondaryAction = false
+ )
+ },
+ ComposableDemo("S2R Card") { params ->
+ SwipeToRevealCards(params.swipeToDismissBoxState)
+ },
+ )
)
)
)
- )
- ),
-)
+ ),
+ )
diff --git a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/HorizontalPageIndicatorDemo.kt b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/HorizontalPageIndicatorDemo.kt
index 45c2016..fbf3f4d 100644
--- a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/HorizontalPageIndicatorDemo.kt
+++ b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/HorizontalPageIndicatorDemo.kt
@@ -56,17 +56,21 @@
fun CustomizedHorizontalPageIndicator() {
val maxPages = 6
var selectedPage by remember { mutableIntStateOf(0) }
- val animatedSelectedPage by animateFloatAsState(
- targetValue = selectedPage.toFloat(),
- animationSpec = TweenSpec(durationMillis = 500), label = "page-indicator"
- )
+ val animatedSelectedPage by
+ animateFloatAsState(
+ targetValue = selectedPage.toFloat(),
+ animationSpec = TweenSpec(durationMillis = 500),
+ label = "page-indicator"
+ )
val pageIndicatorState: PageIndicatorState = remember {
object : PageIndicatorState {
override val pageOffset: Float
get() = animatedSelectedPage - selectedPage
+
override val selectedPage: Int
get() = selectedPage
+
override val pageCount: Int
get() = maxPages
}
@@ -98,18 +102,22 @@
val pagerState = rememberPagerState { pagesCount }
var background by remember { mutableStateOf(Color.Black) }
var selectedPage by remember { mutableIntStateOf(0) }
- val animatedSelectedPage by animateFloatAsState(
- targetValue = pagerState.targetPage.toFloat(), label = "page-indicator",
- ) {
- selectedPage = it.toInt()
- }
+ val animatedSelectedPage by
+ animateFloatAsState(
+ targetValue = pagerState.targetPage.toFloat(),
+ label = "page-indicator",
+ ) {
+ selectedPage = it.toInt()
+ }
val pageIndicatorState: PageIndicatorState = remember {
object : PageIndicatorState {
override val pageOffset: Float
get() = animatedSelectedPage - selectedPage
+
override val selectedPage: Int
get() = selectedPage
+
override val pageCount: Int
get() = pagesCount
}
@@ -126,13 +134,8 @@
)
) { page ->
val scrollState = rememberScalingLazyListState()
- ScalingLazyColumn(
- state = scrollState,
- modifier = Modifier.fillMaxWidth()
- ) {
- item {
- ListHeader { Text("Page $page") }
- }
+ ScalingLazyColumn(state = scrollState, modifier = Modifier.fillMaxWidth()) {
+ item { ListHeader { Text("Page $page") } }
items(4) {
Row(
modifier = Modifier.fillMaxWidth(),
@@ -143,9 +146,7 @@
background =
if (background == Color.Black) Color.DarkGray else Color.Black
},
- label = {
- Text(text = "Click", color = Color.Black)
- },
+ label = { Text(text = "Click", color = Color.Black) },
enabled = !pagerState.isScrollInProgress
)
}
diff --git a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/MaterialDemos.kt b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/MaterialDemos.kt
index 2bdff56..9c2032d 100644
--- a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/MaterialDemos.kt
+++ b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/MaterialDemos.kt
@@ -96,643 +96,629 @@
import java.time.LocalTime
@SuppressLint("ClassVerificationFailure")
-val WearMaterialDemos = DemoCategory(
- "Material",
- listOf(
- DemoCategory(
- "Page Indicator",
- listOf(
- DemoCategory(
- "Samples",
- listOf(
- ComposableDemo("Sample with InlineSlider") {
- Centralize { HorizontalPageIndicatorSample() }
- },
- )
- ),
- DemoCategory(
- "Demos",
- listOf(
- ComposableDemo("Customized PageIndicator") {
- CustomizedHorizontalPageIndicator()
- },
- ComposableDemo("Pager with Indicator") { params ->
- PagerWithIndicator(params.swipeToDismissBoxState)
- }
- )
- )
- )
- ),
- DemoCategory(
- "ScrollAway",
- listOf(
- ComposableDemo("Column") { ScrollAwayColumnDemo() },
- ComposableDemo("Column (delay)") { ScrollAwayColumnDelayDemo() },
- ComposableDemo("Lazy Column") { ScrollAwayLazyColumnDemo() },
- ComposableDemo("Lazy Column offset<0") { ScrollAwayLazyColumnDemo2() },
- ComposableDemo("Lazy Column offset>0") { ScrollAwayLazyColumnDelayDemo() },
- ComposableDemo("SLC Cards") {
- ScrollAwayScalingLazyColumnCardDemo()
- },
- ComposableDemo("SLC Cards offset<0") {
- ScrollAwayScalingLazyColumnCardDemo2()
- },
- ComposableDemo("SLC Cards offset>0") {
- ScrollAwayScalingLazyColumnCardDemoMismatch()
- },
- ComposableDemo("Out of range") {
- ScrollAwayScalingLazyColumnCardDemoOutOfRange()
- },
- ComposableDemo("SLC Chips") {
- ScrollAwayScalingLazyColumnChipDemo()
- },
- ComposableDemo("SLC Chips offset<0") {
- ScrollAwayScalingLazyColumnChipDemo2()
- },
- )
- ),
- DemoCategory(
- "Picker",
- if (Build.VERSION.SDK_INT > 25) {
+val WearMaterialDemos =
+ DemoCategory(
+ "Material",
+ listOf(
+ DemoCategory(
+ "Page Indicator",
listOf(
- ComposableDemo("Time HH:MM:SS") { params ->
- var timePickerTime by remember { mutableStateOf(LocalTime.now()) }
- TimePicker(
- onTimeConfirm = {
- timePickerTime = it
- params.navigateBack()
+ DemoCategory(
+ "Samples",
+ listOf(
+ ComposableDemo("Sample with InlineSlider") {
+ Centralize { HorizontalPageIndicatorSample() }
},
- time = timePickerTime,
)
- },
- ComposableDemo("Time 12 Hour") { params ->
- var timePickerTime by remember { mutableStateOf(LocalTime.now()) }
- TimePickerWith12HourClock(
- onTimeConfirm = {
- timePickerTime = it
- params.navigateBack()
+ ),
+ DemoCategory(
+ "Demos",
+ listOf(
+ ComposableDemo("Customized PageIndicator") {
+ CustomizedHorizontalPageIndicator()
},
- time = timePickerTime,
+ ComposableDemo("Pager with Indicator") { params ->
+ PagerWithIndicator(params.swipeToDismissBoxState)
+ }
)
- },
- ComposableDemo("Date Picker") { params ->
- var datePickerDate by remember { mutableStateOf(LocalDate.now()) }
- DatePicker(
- onDateConfirm = {
- datePickerDate = it
- params.navigateBack()
- },
- date = datePickerDate
- )
- },
- ComposableDemo("From Date Picker") { params ->
- var datePickerDate by remember { mutableStateOf(LocalDate.now()) }
- DatePicker(
- onDateConfirm = {
- datePickerDate = it
- params.navigateBack()
- },
- date = datePickerDate,
- fromDate = datePickerDate
- )
- },
- ComposableDemo("To Date Picker") { params ->
- var datePickerDate by remember { mutableStateOf(LocalDate.now()) }
- DatePicker(
- onDateConfirm = {
- datePickerDate = it
- params.navigateBack()
- },
- date = datePickerDate,
- toDate = datePickerDate
- )
- },
- ComposableDemo("Simple Picker") { SimplePicker() },
- ComposableDemo("No gradient") { PickerWithoutGradient() },
- ComposableDemo("Animate picker change") { AnimateOptionChangePicker() },
- ComposableDemo("Sample Picker Group") { PickerGroup24Hours() },
- ComposableDemo("Autocentering Picker Group") { AutoCenteringPickerGroup() }
+ )
)
- } else {
+ ),
+ DemoCategory(
+ "ScrollAway",
listOf(
- ComposableDemo("Simple Picker") { SimplePicker() },
+ ComposableDemo("Column") { ScrollAwayColumnDemo() },
+ ComposableDemo("Column (delay)") { ScrollAwayColumnDelayDemo() },
+ ComposableDemo("Lazy Column") { ScrollAwayLazyColumnDemo() },
+ ComposableDemo("Lazy Column offset<0") { ScrollAwayLazyColumnDemo2() },
+ ComposableDemo("Lazy Column offset>0") { ScrollAwayLazyColumnDelayDemo() },
+ ComposableDemo("SLC Cards") { ScrollAwayScalingLazyColumnCardDemo() },
+ ComposableDemo("SLC Cards offset<0") { ScrollAwayScalingLazyColumnCardDemo2() },
+ ComposableDemo("SLC Cards offset>0") {
+ ScrollAwayScalingLazyColumnCardDemoMismatch()
+ },
+ ComposableDemo("Out of range") {
+ ScrollAwayScalingLazyColumnCardDemoOutOfRange()
+ },
+ ComposableDemo("SLC Chips") { ScrollAwayScalingLazyColumnChipDemo() },
+ ComposableDemo("SLC Chips offset<0") { ScrollAwayScalingLazyColumnChipDemo2() },
)
- }
- ),
- DemoCategory(
- "Slider",
- listOf(
- DemoCategory(
- "Samples",
+ ),
+ DemoCategory(
+ "Picker",
+ if (Build.VERSION.SDK_INT > 25) {
listOf(
- ComposableDemo("Inline slider") {
- Centralize(Modifier.padding(horizontal = 10.dp)) {
- InlineSliderSample()
- }
- },
- ComposableDemo("Segmented inline slider") {
- Centralize(Modifier.padding(horizontal = 10.dp)) {
- InlineSliderSegmentedSample()
- }
- },
- ComposableDemo("Integer inline slider") {
- Centralize(Modifier.padding(horizontal = 10.dp)) {
- InlineSliderWithIntegerSample()
- }
- },
- )
- ),
- DemoCategory(
- "Demos",
- listOf(
- ComposableDemo("Inline slider") { InlineSliderDemo() },
- ComposableDemo("RTL Inline slider") { InlineSliderRTLDemo() },
- ComposableDemo("With custom color") { InlineSliderCustomColorsDemo() },
- ComposableDemo("Inline slider segmented") { InlineSliderSegmented() },
- ComposableDemo("Inline slider with integers") {
- InlineSliderWithIntegersDemo()
- },
- )
- )
- )
- ),
- DemoCategory(
- "Stepper",
- listOf(
- DemoCategory(
- "Samples",
- listOf(
- ComposableDemo("Stepper") { Centralize { StepperSample() } },
- ComposableDemo("Integer Stepper") {
- Centralize { StepperWithIntegerSample() }
- },
- ComposableDemo("Stepper without RangeSemantics") {
- Centralize { StepperWithoutRangeSemanticsSample() }
- },
- ComposableDemo("Stepper with customSemantics") {
- Centralize { StepperWithCustomSemanticsSample() }
- }
- )
- ),
- DemoCategory(
- "Demos",
- listOf(
- ComposableDemo("Simple stepper") { StepperDemo() },
- ComposableDemo("Stepper with integer") { StepperWithIntegerDemo() },
- ComposableDemo("With scrollbar") { StepperWithScrollBarDemo() },
- ComposableDemo("With custom color") { StepperWithCustomColors() },
- )
- )
- )
- ),
- DemoCategory(
- "Time Text",
- listOf(
- DemoCategory(
- "Samples",
- listOf(
- ComposableDemo("Clock with Status") { TimeTextWithStatus() },
- ComposableDemo("Clock with custom time format") {
- TimeTextWithFullDateAndTimeFormat()
- },
- ComposableDemo("Clock with animated status",
- "A TimeText with status that animates in/out when tapping " +
- "the central button."
- ) {
- TimeTextAnimation()
- },
- )
- ),
- DemoCategory(
- "Demos",
- listOf(
- ComposableDemo("Clock only") { TimeTextClockOnly() },
- ComposableDemo("Clock with leading text") { TimeTextWithLeadingText() },
- ComposableDemo("Clock with shadow") { TimeTextWithShadow() },
- ComposableDemo("Clock with localised format") {
- TimeTextWithLocalisedFormat()
- },
- )
- ),
- )
- ),
- DemoCategory(
- "Dialogs",
- listOf(
- DemoCategory(
- "Samples",
- listOf(
- ComposableDemo("Alert Dialog") { AlertDialogSample() },
- ComposableDemo("Confirmation Dialog") { ConfirmationDialogSample() },
- ComposableDemo("Alert - Buttons") { AlertWithButtons() },
- ComposableDemo("Alert - Chips") { AlertWithChips() },
- ComposableDemo("Confirmation") { ConfirmationWithAnimation() },
- )
- ),
- DemoCategory(
- "Demos",
- listOf(
- ComposableDemo("Power Off") { DialogPowerOff() },
- ComposableDemo("Access Location") { DialogAccessLocation() },
- ComposableDemo("Grant Permission") { DialogGrantPermission() },
- ComposableDemo("Long Chips") { DialogLongChips() },
- ComposableDemo("Dialog Background") {
- DialogBackground(Color.Green)
- },
- ComposableDemo("Confirmation") { DialogSuccessConfirmation() },
- )
- )
- )
- ),
- DemoCategory(
- "Button",
- listOf(
- DemoCategory(
- "Samples",
- listOf(
- ComposableDemo("Button With Icon") { Centralize { ButtonWithIcon() } },
- ComposableDemo("Button With Large Icon") {
- Centralize { LargeButtonWithIcon() }
- },
- ComposableDemo("Button With Text") { Centralize { ButtonWithText() } },
- ComposableDemo("Outlined Button With Icon") {
- Centralize { OutlinedButtonWithIcon() }
- },
- ComposableDemo("Compact Button With Icon") {
- Centralize { CompactButtonWithIcon() }
- },
- ComposableDemo("Outline Compact Button With Icon") {
- Centralize { OutlinedCompactButtonWithIcon() }
- },
- )
- ),
- DemoCategory(
- "Demos",
- listOf(
- ComposableDemo("Button Gallery") { ButtonGallery() },
- ComposableDemo("Button Sizes") { ButtonSizes() },
- ComposableDemo("Button Styles") { ButtonStyles() },
- )
- )
- )
- ),
- DemoCategory(
- "Toggle Button",
- listOf(
- ComposableDemo("Sample") { Centralize { ToggleButtonWithIcon() } },
- ComposableDemo("Demos") { ToggleButtons() },
- )
- ),
- DemoCategory(
- "Chips",
- listOf(
- DemoCategory(
- "Samples",
- listOf(
- ComposableDemo("Chip With Icon And long Label") {
- Centralize(Modifier.padding(horizontal = 10.dp)) {
- ChipWithIconAndLabel()
- }
- },
- ComposableDemo("Chip With Icon And Labels") {
- Centralize(Modifier.padding(horizontal = 10.dp)) {
- ChipWithIconAndLabels()
- }
- },
- ComposableDemo("Outlined Chip With Icon And long Label") {
- Centralize(Modifier.padding(horizontal = 10.dp)) {
- OutlinedChipWithIconAndLabel()
- }
- },
- ComposableDemo("Compact Chip With Icon And Label") {
- Centralize(Modifier.padding(horizontal = 10.dp)) {
- CompactChipWithIconAndLabel()
- }
- },
- ComposableDemo("Compact Chip With Label Only") {
- Centralize(Modifier.padding(horizontal = 10.dp)) {
- CompactChipWithLabel()
- }
- },
- ComposableDemo("Compact Chip Icon Only") {
- Centralize(Modifier.padding(horizontal = 10.dp)) {
- CompactChipWithIcon()
- }
- },
- ComposableDemo("Outlined Compact Chip With Icon and Label") {
- Centralize(Modifier.padding(horizontal = 10.dp)) {
- OutlinedCompactChipWithIconAndLabel()
- }
- },
- )
- ),
- DemoCategory(
- "Demos",
- listOf(
- ComposableDemo("Chip") { StandardChips() },
- ComposableDemo("Compact chip") { SmallChips() },
- ComposableDemo("Avatar chip") { AvatarChips() },
- ComposableDemo("Rtl chips") { RtlChips() },
- ComposableDemo("Custom chips") { CustomChips() },
- ComposableDemo("Image background chips") { ImageBackgroundChips() },
- )
- )
- )
- ),
- DemoCategory(
- "Placeholders",
- listOf(
- DemoCategory(
- "Samples",
- listOf(
- ComposableDemo("Content Placeholders") {
- Centralize(Modifier.padding(horizontal = 10.dp)) {
- ChipWithIconAndLabelAndPlaceholders()
- }
- },
- ComposableDemo("Overlaid Placeholder") {
- Centralize(Modifier.padding(horizontal = 10.dp)) {
- ChipWithIconAndLabelsAndOverlaidPlaceholder()
- }
- },
- ComposableDemo("Simple Text Placeholder") {
- Centralize(Modifier.padding(horizontal = 10.dp)) {
- TextPlaceholder()
- }
- },
- )
- ),
- DemoCategory(
- "Demos",
- listOf(
- ComposableDemo("Chips") { PlaceholderChips() },
- ComposableDemo("Cards") { PlaceholderCards() },
- )
- )
- )
- ),
- DemoCategory(
- "Toggle Chip",
- listOf(
- DemoCategory("Samples",
- listOf(
- ComposableDemo("ToggleChip With Switch") {
- Centralize(Modifier.padding(horizontal = 10.dp)) {
- ToggleChipWithSwitch()
- }
- },
- ComposableDemo("SplitToggleChip With Checkbox") {
- Centralize(Modifier.padding(horizontal = 10.dp)) {
- SplitToggleChipWithCheckbox()
- }
- },
- )
- ),
- DemoCategory(
- "Demos",
- listOf(
- ComposableDemo("Toggle chip") { ToggleChips() },
- ComposableDemo("RTL Toggle chip") {
- ToggleChips(
- layoutDirection = LayoutDirection.Rtl,
- description = "RTL ToggleChips"
+ ComposableDemo("Time HH:MM:SS") { params ->
+ var timePickerTime by remember { mutableStateOf(LocalTime.now()) }
+ TimePicker(
+ onTimeConfirm = {
+ timePickerTime = it
+ params.navigateBack()
+ },
+ time = timePickerTime,
)
},
- )
- )
- )
- ),
- DemoCategory(
- "Selectable Chip",
- listOf(
- DemoCategory("Samples",
- listOf(
- ComposableDemo("SelectableChip With RadioButton") {
- Centralize(Modifier.padding(horizontal = 10.dp)) {
- SelectableChipWithRadioButton()
- }
- },
- ComposableDemo("SplitSelectableChip With RadioButton") {
- Centralize(Modifier.padding(horizontal = 10.dp)) {
- SplitSelectableChipWithRadioButton()
- }
- },
- )
- ),
- DemoCategory(
- "Demos",
- listOf(
- ComposableDemo("Selectable chip") { SelectableChips() },
- ComposableDemo("RTL Selectable chip") {
- SelectableChips(
- layoutDirection = LayoutDirection.Rtl,
- description = "RTL ToggleChips"
+ ComposableDemo("Time 12 Hour") { params ->
+ var timePickerTime by remember { mutableStateOf(LocalTime.now()) }
+ TimePickerWith12HourClock(
+ onTimeConfirm = {
+ timePickerTime = it
+ params.navigateBack()
+ },
+ time = timePickerTime,
)
},
- )
- )
- )
- ),
- DemoCategory(
- "Card",
- listOf(
- DemoCategory(
- "Samples",
- listOf(
- ComposableDemo("AppCard") {
- Centralize(Modifier.padding(horizontal = 10.dp)) {
- AppCardWithIcon()
- }
- },
- ComposableDemo("AppCard With Image") {
- Centralize(Modifier.padding(horizontal = 10.dp)) {
- AppCardWithImage()
- }
- },
- ComposableDemo("TitleCard") {
- Centralize(Modifier.padding(horizontal = 10.dp)) {
- TitleCardStandard()
- }
- },
- ComposableDemo("TitleCard With Image Background") {
- Centralize(Modifier.padding(horizontal = 10.dp)) {
- TitleCardWithImageBackground()
- }
- },
- )
- ),
- ComposableDemo("Demos") { CardDemo() },
- )
- ),
- DemoCategory(
- "Progress Indicator",
- listOf(
- DemoCategory(
- "Samples",
- listOf(
- ComposableDemo("Indeterminate") {
- Centralize { IndeterminateCircularProgressIndicator() }
- },
- ComposableDemo("Animation") {
- Centralize { CircularProgressIndicatorWithAnimation() }
- },
- ComposableDemo("Fullscreen with a gap") {
- Centralize { CircularProgressIndicatorFullscreenWithGap() }
- }
- )
- ),
- DemoCategory(
- "Demos",
- listOf(
- ComposableDemo("Indeterminate progress") {
- Centralize { IndeterminateProgress() }
- },
- ComposableDemo("Custom angles") {
- Centralize { ProgressWithCustomAngles() }
- },
- ComposableDemo("Media controls") { Centralize { ProgressWithMedia() } },
- ComposableDemo("Transforming progress indicator") {
- Centralize { TransformingCustomProgressIndicator() }
- },
- )
- )
- )
- ),
- DemoCategory(
- title = "Swipe To Dismiss",
- listOf(
- ComposableDemo("Simple") { SimpleSwipeToDismissBox(it.navigateBack) },
- ComposableDemo("Stateful") { StatefulSwipeToDismissBox() },
- ComposableDemo("Edge swipe") { EdgeSwipeForSwipeToDismiss(it.navigateBack) },
- )
- ),
- DemoCategory(
- "List (Scaling Lazy Column)",
- listOf(
- ComposableDemo(
- "Defaults",
- "Basic ScalingLazyColumn using default values"
- ) {
- SimpleScalingLazyColumn()
- },
- ComposableDemo(
- "With Content Padding",
- "Basic ScalingLazyColumn with autoCentering disabled and explicit " +
- "content padding of top = 20.dp, bottom = 20.dp"
- ) {
- SimpleScalingLazyColumnWithContentPadding()
- },
- ComposableDemo(
- "With Snap",
- "Basic ScalingLazyColumn, center aligned with snap enabled"
- ) {
- SimpleScalingLazyColumnWithSnap()
- },
- ComposableDemo(
- "Edge Anchor",
- "A ScalingLazyColumn with Edge (rather than center) item anchoring. " +
- "If you click on an item there will be an animated scroll of the " +
- "items edge to the center"
- ) {
- ScalingLazyColumnEdgeAnchoredAndAnimatedScrollTo()
- },
- ComposableDemo(
- "Edge Anchor (G)",
- "A ScalingLazyColumn with Edge (rather than center) item anchoring. " +
- "If you click on an item there will be an animated scroll of the " +
- "items edge to the center and guidelines drawn on top"
- ) {
- ScalingLazyColumnEdgeAnchoredAndAnimatedScrollTo()
- GuideLines()
- },
- ComposableDemo(
- "Scaling Details (G)",
- "A ScalingLazyColumn with items that show their position and size as" +
- "well as guidelines"
- ) {
- ScalingLazyColumnDetail()
- GuideLines()
- },
- ComposableDemo(
- "Stress Test",
- "A ScalingLazyColumn with a mixture of different types of items"
- ) {
- ScalingLazyColumnMixedTypes()
- },
- ComposableDemo(
- "Stress Test [G]",
- "A ScalingLazyColumn with a mixture of different types of items with " +
- "guidelines"
- ) {
- ScalingLazyColumnMixedTypes()
- GuideLines()
- },
- )
- ),
- DemoCategory(
- "Scaffold",
- listOf(
- ComposableDemo("Scaffold with Scrollbar") {
- SimpleScaffoldWithScrollIndicator()
- },
- )
- ),
- DemoCategory(
- "Position Indicator",
- listOf(
- ComposableDemo("Hide when no scrollable") { HideWhenFullDemo() },
- ComposableDemo("Hide when no scrollable SLC") {
- HideWhenFullSLCDemo()
- },
- ComposableDemo("SLC with PositionIndicator") {
- SLCWithPositionIndicatorDemo()
- },
- ComposableDemo("Controllable PI") { ControllablePositionIndicator() },
- ComposableDemo("Shared PI") { SharedPositionIndicator() }
- )
- ),
- DemoCategory(
- "Curved Text",
- listOf(
- ComposableDemo("Basic Styling") { CurvedTextDemo() },
- ComposableDemo("Provider Styling") { CurvedTextProviderDemo() },
- )
- ),
- DemoCategory(
- "Theme",
- listOf(
- ComposableDemo("Fonts") { ThemeFonts() },
- ComposableDemo(
- title = "Fixed Font Size",
- description =
- "Display1 font size not impacted by changes to user font selection",
- ) { Centralize { FixedFontSize() } },
- ComposableDemo("Colors") { ThemeColors() },
- )
- ),
- ComposableDemo("Settings Demo") { SettingsDemo() },
- DemoCategory(
- "ListHeader",
- listOf(
- ComposableDemo("Sample") {
- Centralize {
- ListHeader {
- Text("Header", maxLines = 3)
- }
- }
- },
- ComposableDemo("MultiLine Sample") {
- Centralize {
- ListHeader {
- Text(
- text = "ListHeader that spans multiple lines in a large " +
- "font and should expand to fit the contents",
- style = MaterialTheme.typography.title3
+ ComposableDemo("Date Picker") { params ->
+ var datePickerDate by remember { mutableStateOf(LocalDate.now()) }
+ DatePicker(
+ onDateConfirm = {
+ datePickerDate = it
+ params.navigateBack()
+ },
+ date = datePickerDate
)
- }
- }
+ },
+ ComposableDemo("From Date Picker") { params ->
+ var datePickerDate by remember { mutableStateOf(LocalDate.now()) }
+ DatePicker(
+ onDateConfirm = {
+ datePickerDate = it
+ params.navigateBack()
+ },
+ date = datePickerDate,
+ fromDate = datePickerDate
+ )
+ },
+ ComposableDemo("To Date Picker") { params ->
+ var datePickerDate by remember { mutableStateOf(LocalDate.now()) }
+ DatePicker(
+ onDateConfirm = {
+ datePickerDate = it
+ params.navigateBack()
+ },
+ date = datePickerDate,
+ toDate = datePickerDate
+ )
+ },
+ ComposableDemo("Simple Picker") { SimplePicker() },
+ ComposableDemo("No gradient") { PickerWithoutGradient() },
+ ComposableDemo("Animate picker change") { AnimateOptionChangePicker() },
+ ComposableDemo("Sample Picker Group") { PickerGroup24Hours() },
+ ComposableDemo("Autocentering Picker Group") { AutoCenteringPickerGroup() }
+ )
+ } else {
+ listOf(
+ ComposableDemo("Simple Picker") { SimplePicker() },
+ )
}
+ ),
+ DemoCategory(
+ "Slider",
+ listOf(
+ DemoCategory(
+ "Samples",
+ listOf(
+ ComposableDemo("Inline slider") {
+ Centralize(Modifier.padding(horizontal = 10.dp)) {
+ InlineSliderSample()
+ }
+ },
+ ComposableDemo("Segmented inline slider") {
+ Centralize(Modifier.padding(horizontal = 10.dp)) {
+ InlineSliderSegmentedSample()
+ }
+ },
+ ComposableDemo("Integer inline slider") {
+ Centralize(Modifier.padding(horizontal = 10.dp)) {
+ InlineSliderWithIntegerSample()
+ }
+ },
+ )
+ ),
+ DemoCategory(
+ "Demos",
+ listOf(
+ ComposableDemo("Inline slider") { InlineSliderDemo() },
+ ComposableDemo("RTL Inline slider") { InlineSliderRTLDemo() },
+ ComposableDemo("With custom color") { InlineSliderCustomColorsDemo() },
+ ComposableDemo("Inline slider segmented") { InlineSliderSegmented() },
+ ComposableDemo("Inline slider with integers") {
+ InlineSliderWithIntegersDemo()
+ },
+ )
+ )
+ )
+ ),
+ DemoCategory(
+ "Stepper",
+ listOf(
+ DemoCategory(
+ "Samples",
+ listOf(
+ ComposableDemo("Stepper") { Centralize { StepperSample() } },
+ ComposableDemo("Integer Stepper") {
+ Centralize { StepperWithIntegerSample() }
+ },
+ ComposableDemo("Stepper without RangeSemantics") {
+ Centralize { StepperWithoutRangeSemanticsSample() }
+ },
+ ComposableDemo("Stepper with customSemantics") {
+ Centralize { StepperWithCustomSemanticsSample() }
+ }
+ )
+ ),
+ DemoCategory(
+ "Demos",
+ listOf(
+ ComposableDemo("Simple stepper") { StepperDemo() },
+ ComposableDemo("Stepper with integer") { StepperWithIntegerDemo() },
+ ComposableDemo("With scrollbar") { StepperWithScrollBarDemo() },
+ ComposableDemo("With custom color") { StepperWithCustomColors() },
+ )
+ )
+ )
+ ),
+ DemoCategory(
+ "Time Text",
+ listOf(
+ DemoCategory(
+ "Samples",
+ listOf(
+ ComposableDemo("Clock with Status") { TimeTextWithStatus() },
+ ComposableDemo("Clock with custom time format") {
+ TimeTextWithFullDateAndTimeFormat()
+ },
+ ComposableDemo(
+ "Clock with animated status",
+ "A TimeText with status that animates in/out when tapping " +
+ "the central button."
+ ) {
+ TimeTextAnimation()
+ },
+ )
+ ),
+ DemoCategory(
+ "Demos",
+ listOf(
+ ComposableDemo("Clock only") { TimeTextClockOnly() },
+ ComposableDemo("Clock with leading text") { TimeTextWithLeadingText() },
+ ComposableDemo("Clock with shadow") { TimeTextWithShadow() },
+ ComposableDemo("Clock with localised format") {
+ TimeTextWithLocalisedFormat()
+ },
+ )
+ ),
+ )
+ ),
+ DemoCategory(
+ "Dialogs",
+ listOf(
+ DemoCategory(
+ "Samples",
+ listOf(
+ ComposableDemo("Alert Dialog") { AlertDialogSample() },
+ ComposableDemo("Confirmation Dialog") { ConfirmationDialogSample() },
+ ComposableDemo("Alert - Buttons") { AlertWithButtons() },
+ ComposableDemo("Alert - Chips") { AlertWithChips() },
+ ComposableDemo("Confirmation") { ConfirmationWithAnimation() },
+ )
+ ),
+ DemoCategory(
+ "Demos",
+ listOf(
+ ComposableDemo("Power Off") { DialogPowerOff() },
+ ComposableDemo("Access Location") { DialogAccessLocation() },
+ ComposableDemo("Grant Permission") { DialogGrantPermission() },
+ ComposableDemo("Long Chips") { DialogLongChips() },
+ ComposableDemo("Dialog Background") { DialogBackground(Color.Green) },
+ ComposableDemo("Confirmation") { DialogSuccessConfirmation() },
+ )
+ )
+ )
+ ),
+ DemoCategory(
+ "Button",
+ listOf(
+ DemoCategory(
+ "Samples",
+ listOf(
+ ComposableDemo("Button With Icon") { Centralize { ButtonWithIcon() } },
+ ComposableDemo("Button With Large Icon") {
+ Centralize { LargeButtonWithIcon() }
+ },
+ ComposableDemo("Button With Text") { Centralize { ButtonWithText() } },
+ ComposableDemo("Outlined Button With Icon") {
+ Centralize { OutlinedButtonWithIcon() }
+ },
+ ComposableDemo("Compact Button With Icon") {
+ Centralize { CompactButtonWithIcon() }
+ },
+ ComposableDemo("Outline Compact Button With Icon") {
+ Centralize { OutlinedCompactButtonWithIcon() }
+ },
+ )
+ ),
+ DemoCategory(
+ "Demos",
+ listOf(
+ ComposableDemo("Button Gallery") { ButtonGallery() },
+ ComposableDemo("Button Sizes") { ButtonSizes() },
+ ComposableDemo("Button Styles") { ButtonStyles() },
+ )
+ )
+ )
+ ),
+ DemoCategory(
+ "Toggle Button",
+ listOf(
+ ComposableDemo("Sample") { Centralize { ToggleButtonWithIcon() } },
+ ComposableDemo("Demos") { ToggleButtons() },
+ )
+ ),
+ DemoCategory(
+ "Chips",
+ listOf(
+ DemoCategory(
+ "Samples",
+ listOf(
+ ComposableDemo("Chip With Icon And long Label") {
+ Centralize(Modifier.padding(horizontal = 10.dp)) {
+ ChipWithIconAndLabel()
+ }
+ },
+ ComposableDemo("Chip With Icon And Labels") {
+ Centralize(Modifier.padding(horizontal = 10.dp)) {
+ ChipWithIconAndLabels()
+ }
+ },
+ ComposableDemo("Outlined Chip With Icon And long Label") {
+ Centralize(Modifier.padding(horizontal = 10.dp)) {
+ OutlinedChipWithIconAndLabel()
+ }
+ },
+ ComposableDemo("Compact Chip With Icon And Label") {
+ Centralize(Modifier.padding(horizontal = 10.dp)) {
+ CompactChipWithIconAndLabel()
+ }
+ },
+ ComposableDemo("Compact Chip With Label Only") {
+ Centralize(Modifier.padding(horizontal = 10.dp)) {
+ CompactChipWithLabel()
+ }
+ },
+ ComposableDemo("Compact Chip Icon Only") {
+ Centralize(Modifier.padding(horizontal = 10.dp)) {
+ CompactChipWithIcon()
+ }
+ },
+ ComposableDemo("Outlined Compact Chip With Icon and Label") {
+ Centralize(Modifier.padding(horizontal = 10.dp)) {
+ OutlinedCompactChipWithIconAndLabel()
+ }
+ },
+ )
+ ),
+ DemoCategory(
+ "Demos",
+ listOf(
+ ComposableDemo("Chip") { StandardChips() },
+ ComposableDemo("Compact chip") { SmallChips() },
+ ComposableDemo("Avatar chip") { AvatarChips() },
+ ComposableDemo("Rtl chips") { RtlChips() },
+ ComposableDemo("Custom chips") { CustomChips() },
+ ComposableDemo("Image background chips") { ImageBackgroundChips() },
+ )
+ )
+ )
+ ),
+ DemoCategory(
+ "Placeholders",
+ listOf(
+ DemoCategory(
+ "Samples",
+ listOf(
+ ComposableDemo("Content Placeholders") {
+ Centralize(Modifier.padding(horizontal = 10.dp)) {
+ ChipWithIconAndLabelAndPlaceholders()
+ }
+ },
+ ComposableDemo("Overlaid Placeholder") {
+ Centralize(Modifier.padding(horizontal = 10.dp)) {
+ ChipWithIconAndLabelsAndOverlaidPlaceholder()
+ }
+ },
+ ComposableDemo("Simple Text Placeholder") {
+ Centralize(Modifier.padding(horizontal = 10.dp)) {
+ TextPlaceholder()
+ }
+ },
+ )
+ ),
+ DemoCategory(
+ "Demos",
+ listOf(
+ ComposableDemo("Chips") { PlaceholderChips() },
+ ComposableDemo("Cards") { PlaceholderCards() },
+ )
+ )
+ )
+ ),
+ DemoCategory(
+ "Toggle Chip",
+ listOf(
+ DemoCategory(
+ "Samples",
+ listOf(
+ ComposableDemo("ToggleChip With Switch") {
+ Centralize(Modifier.padding(horizontal = 10.dp)) {
+ ToggleChipWithSwitch()
+ }
+ },
+ ComposableDemo("SplitToggleChip With Checkbox") {
+ Centralize(Modifier.padding(horizontal = 10.dp)) {
+ SplitToggleChipWithCheckbox()
+ }
+ },
+ )
+ ),
+ DemoCategory(
+ "Demos",
+ listOf(
+ ComposableDemo("Toggle chip") { ToggleChips() },
+ ComposableDemo("RTL Toggle chip") {
+ ToggleChips(
+ layoutDirection = LayoutDirection.Rtl,
+ description = "RTL ToggleChips"
+ )
+ },
+ )
+ )
+ )
+ ),
+ DemoCategory(
+ "Selectable Chip",
+ listOf(
+ DemoCategory(
+ "Samples",
+ listOf(
+ ComposableDemo("SelectableChip With RadioButton") {
+ Centralize(Modifier.padding(horizontal = 10.dp)) {
+ SelectableChipWithRadioButton()
+ }
+ },
+ ComposableDemo("SplitSelectableChip With RadioButton") {
+ Centralize(Modifier.padding(horizontal = 10.dp)) {
+ SplitSelectableChipWithRadioButton()
+ }
+ },
+ )
+ ),
+ DemoCategory(
+ "Demos",
+ listOf(
+ ComposableDemo("Selectable chip") { SelectableChips() },
+ ComposableDemo("RTL Selectable chip") {
+ SelectableChips(
+ layoutDirection = LayoutDirection.Rtl,
+ description = "RTL ToggleChips"
+ )
+ },
+ )
+ )
+ )
+ ),
+ DemoCategory(
+ "Card",
+ listOf(
+ DemoCategory(
+ "Samples",
+ listOf(
+ ComposableDemo("AppCard") {
+ Centralize(Modifier.padding(horizontal = 10.dp)) {
+ AppCardWithIcon()
+ }
+ },
+ ComposableDemo("AppCard With Image") {
+ Centralize(Modifier.padding(horizontal = 10.dp)) {
+ AppCardWithImage()
+ }
+ },
+ ComposableDemo("TitleCard") {
+ Centralize(Modifier.padding(horizontal = 10.dp)) {
+ TitleCardStandard()
+ }
+ },
+ ComposableDemo("TitleCard With Image Background") {
+ Centralize(Modifier.padding(horizontal = 10.dp)) {
+ TitleCardWithImageBackground()
+ }
+ },
+ )
+ ),
+ ComposableDemo("Demos") { CardDemo() },
+ )
+ ),
+ DemoCategory(
+ "Progress Indicator",
+ listOf(
+ DemoCategory(
+ "Samples",
+ listOf(
+ ComposableDemo("Indeterminate") {
+ Centralize { IndeterminateCircularProgressIndicator() }
+ },
+ ComposableDemo("Animation") {
+ Centralize { CircularProgressIndicatorWithAnimation() }
+ },
+ ComposableDemo("Fullscreen with a gap") {
+ Centralize { CircularProgressIndicatorFullscreenWithGap() }
+ }
+ )
+ ),
+ DemoCategory(
+ "Demos",
+ listOf(
+ ComposableDemo("Indeterminate progress") {
+ Centralize { IndeterminateProgress() }
+ },
+ ComposableDemo("Custom angles") {
+ Centralize { ProgressWithCustomAngles() }
+ },
+ ComposableDemo("Media controls") { Centralize { ProgressWithMedia() } },
+ ComposableDemo("Transforming progress indicator") {
+ Centralize { TransformingCustomProgressIndicator() }
+ },
+ )
+ )
+ )
+ ),
+ DemoCategory(
+ title = "Swipe To Dismiss",
+ listOf(
+ ComposableDemo("Simple") { SimpleSwipeToDismissBox(it.navigateBack) },
+ ComposableDemo("Stateful") { StatefulSwipeToDismissBox() },
+ ComposableDemo("Edge swipe") { EdgeSwipeForSwipeToDismiss(it.navigateBack) },
+ )
+ ),
+ DemoCategory(
+ "List (Scaling Lazy Column)",
+ listOf(
+ ComposableDemo("Defaults", "Basic ScalingLazyColumn using default values") {
+ SimpleScalingLazyColumn()
+ },
+ ComposableDemo(
+ "With Content Padding",
+ "Basic ScalingLazyColumn with autoCentering disabled and explicit " +
+ "content padding of top = 20.dp, bottom = 20.dp"
+ ) {
+ SimpleScalingLazyColumnWithContentPadding()
+ },
+ ComposableDemo(
+ "With Snap",
+ "Basic ScalingLazyColumn, center aligned with snap enabled"
+ ) {
+ SimpleScalingLazyColumnWithSnap()
+ },
+ ComposableDemo(
+ "Edge Anchor",
+ "A ScalingLazyColumn with Edge (rather than center) item anchoring. " +
+ "If you click on an item there will be an animated scroll of the " +
+ "items edge to the center"
+ ) {
+ ScalingLazyColumnEdgeAnchoredAndAnimatedScrollTo()
+ },
+ ComposableDemo(
+ "Edge Anchor (G)",
+ "A ScalingLazyColumn with Edge (rather than center) item anchoring. " +
+ "If you click on an item there will be an animated scroll of the " +
+ "items edge to the center and guidelines drawn on top"
+ ) {
+ ScalingLazyColumnEdgeAnchoredAndAnimatedScrollTo()
+ GuideLines()
+ },
+ ComposableDemo(
+ "Scaling Details (G)",
+ "A ScalingLazyColumn with items that show their position and size as" +
+ "well as guidelines"
+ ) {
+ ScalingLazyColumnDetail()
+ GuideLines()
+ },
+ ComposableDemo(
+ "Stress Test",
+ "A ScalingLazyColumn with a mixture of different types of items"
+ ) {
+ ScalingLazyColumnMixedTypes()
+ },
+ ComposableDemo(
+ "Stress Test [G]",
+ "A ScalingLazyColumn with a mixture of different types of items with " +
+ "guidelines"
+ ) {
+ ScalingLazyColumnMixedTypes()
+ GuideLines()
+ },
+ )
+ ),
+ DemoCategory(
+ "Scaffold",
+ listOf(
+ ComposableDemo("Scaffold with Scrollbar") {
+ SimpleScaffoldWithScrollIndicator()
+ },
+ )
+ ),
+ DemoCategory(
+ "Position Indicator",
+ listOf(
+ ComposableDemo("Hide when no scrollable") { HideWhenFullDemo() },
+ ComposableDemo("Hide when no scrollable SLC") { HideWhenFullSLCDemo() },
+ ComposableDemo("SLC with PositionIndicator") { SLCWithPositionIndicatorDemo() },
+ ComposableDemo("Controllable PI") { ControllablePositionIndicator() },
+ ComposableDemo("Shared PI") { SharedPositionIndicator() }
+ )
+ ),
+ DemoCategory(
+ "Curved Text",
+ listOf(
+ ComposableDemo("Basic Styling") { CurvedTextDemo() },
+ ComposableDemo("Provider Styling") { CurvedTextProviderDemo() },
+ )
+ ),
+ DemoCategory(
+ "Theme",
+ listOf(
+ ComposableDemo("Fonts") { ThemeFonts() },
+ ComposableDemo(
+ title = "Fixed Font Size",
+ description =
+ "Display1 font size not impacted by changes to user font selection",
+ ) {
+ Centralize { FixedFontSize() }
+ },
+ ComposableDemo("Colors") { ThemeColors() },
+ )
+ ),
+ ComposableDemo("Settings Demo") { SettingsDemo() },
+ DemoCategory(
+ "ListHeader",
+ listOf(
+ ComposableDemo("Sample") {
+ Centralize { ListHeader { Text("Header", maxLines = 3) } }
+ },
+ ComposableDemo("MultiLine Sample") {
+ Centralize {
+ ListHeader {
+ Text(
+ text =
+ "ListHeader that spans multiple lines in a large " +
+ "font and should expand to fit the contents",
+ style = MaterialTheme.typography.title3
+ )
+ }
+ }
+ }
+ )
)
- )
- ),
-)
+ ),
+ )
diff --git a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/PickerDemo.kt b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/PickerDemo.kt
index b68787e..5ef0915 100644
--- a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/PickerDemo.kt
+++ b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/PickerDemo.kt
@@ -90,8 +90,7 @@
*
* This component is designed to take most/all of the screen and utilizes large fonts. In order to
* ensure that it will draw properly on smaller screens it does not take account of user font size
- * overrides for MaterialTheme.typography.display3 which is used to display the main picker
- * value.
+ * overrides for MaterialTheme.typography.display3 which is used to display the main picker value.
*
* @param onTimeConfirm the button event handler.
* @param modifier the modifiers for the `Box` containing the UI elements.
@@ -108,35 +107,31 @@
val fullyDrawn = remember { Animatable(0f) }
// Omit scaling according to Settings > Display > Font size for this screen
- val typography = MaterialTheme.typography.copy(
- display3 = MaterialTheme.typography.display3.copy(
- fontSize = with(LocalDensity.current) { 30.dp.toSp() }
+ val typography =
+ MaterialTheme.typography.copy(
+ display3 =
+ MaterialTheme.typography.display3.copy(
+ fontSize = with(LocalDensity.current) { 30.dp.toSp() }
+ )
)
- )
- val hourState = rememberPickerState(
- initialNumberOfOptions = 24,
- initiallySelectedOption = time.hour
- )
- val minuteState = rememberPickerState(
- initialNumberOfOptions = 60,
- initiallySelectedOption = time.minute
- )
- val secondState = rememberPickerState(
- initialNumberOfOptions = 60,
- initiallySelectedOption = time.second
- )
+ val hourState =
+ rememberPickerState(initialNumberOfOptions = 24, initiallySelectedOption = time.hour)
+ val minuteState =
+ rememberPickerState(initialNumberOfOptions = 60, initiallySelectedOption = time.minute)
+ val secondState =
+ rememberPickerState(initialNumberOfOptions = 60, initiallySelectedOption = time.second)
val touchExplorationStateProvider = remember { DefaultTouchExplorationStateProvider() }
- val touchExplorationServicesEnabled by touchExplorationStateProvider
- .touchExplorationState()
+ val touchExplorationServicesEnabled by touchExplorationStateProvider.touchExplorationState()
MaterialTheme(typography = typography) {
// When the time picker loads, none of the individual pickers are selected in talkback mode,
// otherwise hours picker should be focused.
- val pickerGroupState = if (touchExplorationServicesEnabled) {
- rememberPickerGroupState(FocusableElementsTimePicker.NONE.index)
- } else {
- rememberPickerGroupState(FocusableElementsTimePicker.HOURS.index)
- }
+ val pickerGroupState =
+ if (touchExplorationServicesEnabled) {
+ rememberPickerGroupState(FocusableElementsTimePicker.NONE.index)
+ } else {
+ rememberPickerGroupState(FocusableElementsTimePicker.HOURS.index)
+ }
val textStyle = MaterialTheme.typography.display3
val optionColor = MaterialTheme.colors.secondary
val pickerOption = pickerTextOption(textStyle) { "%02d".format(it) }
@@ -169,22 +164,19 @@
) {
Spacer(Modifier.height(12.dp))
Text(
- text = when (FocusableElementsTimePicker[pickerGroupState.selectedIndex]) {
- FocusableElementsTimePicker.HOURS -> "Hour"
- FocusableElementsTimePicker.MINUTES -> "Minute"
- FocusableElementsTimePicker.SECONDS -> "Second"
- else -> ""
- },
+ text =
+ when (FocusableElementsTimePicker[pickerGroupState.selectedIndex]) {
+ FocusableElementsTimePicker.HOURS -> "Hour"
+ FocusableElementsTimePicker.MINUTES -> "Minute"
+ FocusableElementsTimePicker.SECONDS -> "Second"
+ else -> ""
+ },
color = optionColor,
style = MaterialTheme.typography.button,
maxLines = 1,
)
val weightsToCenterVertically = 0.5f
- Spacer(
- Modifier
- .fillMaxWidth()
- .weight(weightsToCenterVertically)
- )
+ Spacer(Modifier.fillMaxWidth().weight(weightsToCenterVertically))
Row(
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
@@ -193,8 +185,7 @@
PickerGroup(
PickerGroupItem(
pickerState = hourState,
- modifier = Modifier
- .size(40.dp, 100.dp),
+ modifier = Modifier.size(40.dp, 100.dp),
onSelected = {
onPickerSelected(
FocusableElementsTimePicker.HOURS,
@@ -206,8 +197,7 @@
),
PickerGroupItem(
pickerState = minuteState,
- modifier = Modifier
- .size(40.dp, 100.dp),
+ modifier = Modifier.size(40.dp, 100.dp),
onSelected = {
onPickerSelected(
FocusableElementsTimePicker.MINUTES,
@@ -219,8 +209,7 @@
),
PickerGroupItem(
pickerState = secondState,
- modifier = Modifier
- .size(40.dp, 100.dp),
+ modifier = Modifier.size(40.dp, 100.dp),
onSelected = {
onPickerSelected(
FocusableElementsTimePicker.SECONDS,
@@ -236,34 +225,30 @@
touchExplorationStateProvider = touchExplorationStateProvider
)
}
- Spacer(
- Modifier
- .fillMaxWidth()
- .weight(weightsToCenterVertically)
- )
+ Spacer(Modifier.fillMaxWidth().weight(weightsToCenterVertically))
Button(
onClick = {
- val confirmedTime = LocalTime.of(
- hourState.selectedOption,
- minuteState.selectedOption,
- secondState.selectedOption
- )
+ val confirmedTime =
+ LocalTime.of(
+ hourState.selectedOption,
+ minuteState.selectedOption,
+ secondState.selectedOption
+ )
onTimeConfirm(confirmedTime)
},
- modifier = Modifier
- .semantics {
- focused = pickerGroupState.selectedIndex ==
- FocusableElementsTimePicker.CONFIRM_BUTTON.index
- }
- .focusRequester(focusRequesterConfirmButton)
- .focusable()
+ modifier =
+ Modifier.semantics {
+ focused =
+ pickerGroupState.selectedIndex ==
+ FocusableElementsTimePicker.CONFIRM_BUTTON.index
+ }
+ .focusRequester(focusRequesterConfirmButton)
+ .focusable()
) {
Icon(
imageVector = Icons.Filled.Check,
contentDescription = "confirm",
- modifier = Modifier
- .size(24.dp)
- .wrapContentSize(align = Alignment.Center),
+ modifier = Modifier.size(24.dp).wrapContentSize(align = Alignment.Center),
)
}
Spacer(Modifier.height(12.dp))
@@ -271,9 +256,7 @@
}
}
- LaunchedEffect(Unit) {
- fullyDrawn.animateTo(1f)
- }
+ LaunchedEffect(Unit) { fullyDrawn.animateTo(1f) }
}
/**
@@ -281,8 +264,7 @@
*
* This component is designed to take most/all of the screen and utilizes large fonts. In order to
* ensure that it will draw properly on smaller screens it does not take account of user font size
- * overrides for MaterialTheme.typography.display1 which is used to display the main picker
- * value.
+ * overrides for MaterialTheme.typography.display1 which is used to display the main picker value.
*
* @param onTimeConfirm the button event handler.
* @param modifier the modifiers for the `Column` containing the UI elements.
@@ -299,29 +281,30 @@
val fullyDrawn = remember { Animatable(0f) }
// Omit scaling according to Settings > Display > Font size for this screen,
- val typography = MaterialTheme.typography.copy(
- display1 = MaterialTheme.typography.display1.copy(
- fontSize = with(LocalDensity.current) { 40.dp.toSp() }
+ val typography =
+ MaterialTheme.typography.copy(
+ display1 =
+ MaterialTheme.typography.display1.copy(
+ fontSize = with(LocalDensity.current) { 40.dp.toSp() }
+ )
)
- )
- val hourState = rememberPickerState(
- initialNumberOfOptions = 12,
- initiallySelectedOption = time[ChronoField.CLOCK_HOUR_OF_AMPM] - 1
- )
- val minuteState = rememberPickerState(
- initialNumberOfOptions = 60,
- initiallySelectedOption = time.minute
- )
- val periodState = rememberPickerState(
- initialNumberOfOptions = 2,
- initiallySelectedOption = time[ChronoField.AMPM_OF_DAY],
- repeatItems = false
- )
+ val hourState =
+ rememberPickerState(
+ initialNumberOfOptions = 12,
+ initiallySelectedOption = time[ChronoField.CLOCK_HOUR_OF_AMPM] - 1
+ )
+ val minuteState =
+ rememberPickerState(initialNumberOfOptions = 60, initiallySelectedOption = time.minute)
+ val periodState =
+ rememberPickerState(
+ initialNumberOfOptions = 2,
+ initiallySelectedOption = time[ChronoField.AMPM_OF_DAY],
+ repeatItems = false
+ )
val touchExplorationStateProvider = remember { DefaultTouchExplorationStateProvider() }
- val touchExplorationServicesEnabled by touchExplorationStateProvider
- .touchExplorationState()
+ val touchExplorationServicesEnabled by touchExplorationStateProvider.touchExplorationState()
MaterialTheme(typography = typography) {
// When the time picker loads, none of the individual pickers are selected in talkback mode,
@@ -343,18 +326,16 @@
val amString = "AM"
val pmString = "PM"
- val periodContentDescription by remember(
- pickerGroupState.selectedIndex,
- periodState.selectedOption
- ) {
- derivedStateOf {
- if (pickerGroupState.selectedIndex == FocusableElement12Hour.NONE.index) {
- "Period"
- } else if (periodState.selectedOption == 0) {
- amString
- } else pmString
+ val periodContentDescription by
+ remember(pickerGroupState.selectedIndex, periodState.selectedOption) {
+ derivedStateOf {
+ if (pickerGroupState.selectedIndex == FocusableElement12Hour.NONE.index) {
+ "Period"
+ } else if (periodState.selectedOption == 0) {
+ amString
+ } else pmString
+ }
}
- }
Box(modifier = modifier.fillMaxSize().alpha(fullyDrawn.value)) {
Column(
modifier = modifier.fillMaxSize(),
@@ -363,21 +344,18 @@
) {
Spacer(Modifier.height(12.dp))
Text(
- text = when (FocusableElement12Hour[pickerGroupState.selectedIndex]) {
- FocusableElement12Hour.HOURS -> "Hour"
- FocusableElement12Hour.MINUTES -> "Minute"
- else -> ""
- },
+ text =
+ when (FocusableElement12Hour[pickerGroupState.selectedIndex]) {
+ FocusableElement12Hour.HOURS -> "Hour"
+ FocusableElement12Hour.MINUTES -> "Minute"
+ else -> ""
+ },
color = MaterialTheme.colors.secondary,
style = MaterialTheme.typography.button,
maxLines = 1
)
val weightsToCenterVertically = 0.5f
- Spacer(
- Modifier
- .fillMaxWidth()
- .weight(weightsToCenterVertically)
- )
+ Spacer(Modifier.fillMaxWidth().weight(weightsToCenterVertically))
Row(
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
@@ -388,7 +366,8 @@
if (pickerGroupState.selectedIndex != current.index) {
pickerGroupState.selectedIndex = current.index
} else {
- // Double tapping on selected column moves the focus to the next column
+ // Double tapping on selected column moves the focus to the next
+ // column
pickerGroupState.selectedIndex = next.index
if (next == FocusableElement12Hour.CONFIRM_BUTTON) {
focusRequesterConfirmButton.requestFocus()
@@ -431,9 +410,8 @@
FocusableElement12Hour.CONFIRM_BUTTON
)
},
- option = pickerTextOption(textStyle) {
- if (it == 0) amString else pmString
- }
+ option =
+ pickerTextOption(textStyle) { if (it == 0) amString else pmString }
),
autoCenter = false,
pickerGroupState = pickerGroupState,
@@ -445,34 +423,31 @@
touchExplorationStateProvider = touchExplorationStateProvider
)
}
- Spacer(
- Modifier
- .fillMaxWidth()
- .weight(weightsToCenterVertically)
- )
+ Spacer(Modifier.fillMaxWidth().weight(weightsToCenterVertically))
Button(
onClick = {
- val confirmedTime = LocalTime.of(
- hourState.selectedOption + 1,
- minuteState.selectedOption,
- 0
- ).with(ChronoField.AMPM_OF_DAY, periodState.selectedOption.toLong())
+ val confirmedTime =
+ LocalTime.of(
+ hourState.selectedOption + 1,
+ minuteState.selectedOption,
+ 0
+ )
+ .with(ChronoField.AMPM_OF_DAY, periodState.selectedOption.toLong())
onTimeConfirm(confirmedTime)
},
- modifier = Modifier
- .semantics {
- focused = pickerGroupState.selectedIndex ==
- FocusableElement12Hour.CONFIRM_BUTTON.index
- }
- .focusRequester(focusRequesterConfirmButton)
- .focusable()
+ modifier =
+ Modifier.semantics {
+ focused =
+ pickerGroupState.selectedIndex ==
+ FocusableElement12Hour.CONFIRM_BUTTON.index
+ }
+ .focusRequester(focusRequesterConfirmButton)
+ .focusable()
) {
Icon(
imageVector = Icons.Filled.Check,
contentDescription = "confirm",
- modifier = Modifier
- .size(24.dp)
- .wrapContentSize(align = Alignment.Center)
+ modifier = Modifier.size(24.dp).wrapContentSize(align = Alignment.Center)
)
}
Spacer(Modifier.height(8.dp))
@@ -480,9 +455,7 @@
}
}
- LaunchedEffect(Unit) {
- fullyDrawn.animateTo(1f)
- }
+ LaunchedEffect(Unit) { fullyDrawn.animateTo(1f) }
}
/**
@@ -490,8 +463,7 @@
*
* This component is designed to take most/all of the screen and utilizes large fonts. In order to
* ensure that it will draw properly on smaller screens it does not take account of user font size
- * overrides for MaterialTheme.typography.display2 which is used to display the main picker
- * value.
+ * overrides for MaterialTheme.typography.display2 which is used to display the main picker value.
*
* @param onDateConfirm the button event handler.
* @param modifier the modifiers for the `Box` containing the UI elements.
@@ -515,34 +487,37 @@
verifyDates(date, fromDate, toDate)
}
- val datePickerState = remember(date) {
- if (fromDate != null && toDate == null) {
- DatePickerState(date = date, fromDate = fromDate, toDate = fromDate.plusYears(3000))
- } else if (fromDate == null && toDate != null) {
- DatePickerState(date = date, fromDate = toDate.minusYears(3000), toDate = toDate)
- } else {
- DatePickerState(date, fromDate, toDate)
+ val datePickerState =
+ remember(date) {
+ if (fromDate != null && toDate == null) {
+ DatePickerState(date = date, fromDate = fromDate, toDate = fromDate.plusYears(3000))
+ } else if (fromDate == null && toDate != null) {
+ DatePickerState(date = date, fromDate = toDate.minusYears(3000), toDate = toDate)
+ } else {
+ DatePickerState(date, fromDate, toDate)
+ }
}
- }
// Omit scaling according to Settings > Display > Font size for this screen
- val typography = MaterialTheme.typography.copy(
- display2 = MaterialTheme.typography.display2.copy(
- fontSize = with(LocalDensity.current) { 34.dp.toSp() }
+ val typography =
+ MaterialTheme.typography.copy(
+ display2 =
+ MaterialTheme.typography.display2.copy(
+ fontSize = with(LocalDensity.current) { 34.dp.toSp() }
+ )
)
- )
val touchExplorationStateProvider = remember { DefaultTouchExplorationStateProvider() }
- val touchExplorationServicesEnabled by touchExplorationStateProvider
- .touchExplorationState()
+ val touchExplorationServicesEnabled by touchExplorationStateProvider.touchExplorationState()
MaterialTheme(typography = typography) {
// When the time picker loads, none of the individual pickers are selected in talkback mode,
// otherwise day picker should be focused.
- val pickerGroupState = if (touchExplorationServicesEnabled) {
- rememberPickerGroupState(FocusableElementDatePicker.NONE.index)
- } else {
- rememberPickerGroupState(FocusableElementDatePicker.DAY.index)
- }
+ val pickerGroupState =
+ if (touchExplorationServicesEnabled) {
+ rememberPickerGroupState(FocusableElementDatePicker.NONE.index)
+ } else {
+ rememberPickerGroupState(FocusableElementDatePicker.DAY.index)
+ }
val textStyle = MaterialTheme.typography.display3
val optionColor = MaterialTheme.colors.secondary
val focusRequesterConfirmButton = remember { FocusRequester() }
@@ -567,42 +542,36 @@
}
val shortMonthNames = remember { getMonthNames("MMM") }
val fullMonthNames = remember { getMonthNames("MMMM") }
- val yearContentDescription by remember(
- pickerGroupState.selectedIndex,
- datePickerState.currentYear()
- ) {
- derivedStateOf {
- createDescriptionDatePicker(
- pickerGroupState,
- datePickerState.currentYear(),
- yearString
- )
- }
- }
- val monthContentDescription by remember(
- pickerGroupState.selectedIndex,
- datePickerState.currentMonth()
- ) {
- derivedStateOf {
- if (pickerGroupState.selectedIndex == FocusableElementDatePicker.NONE.index) {
- monthString
- } else {
- fullMonthNames[(datePickerState.currentMonth() - 1) % 12]
+ val yearContentDescription by
+ remember(pickerGroupState.selectedIndex, datePickerState.currentYear()) {
+ derivedStateOf {
+ createDescriptionDatePicker(
+ pickerGroupState,
+ datePickerState.currentYear(),
+ yearString
+ )
}
}
- }
- val dayContentDescription by remember(
- pickerGroupState.selectedIndex,
- datePickerState.currentDay()
- ) {
- derivedStateOf {
- createDescriptionDatePicker(
- pickerGroupState,
- datePickerState.currentDay(),
- dayString
- )
+ val monthContentDescription by
+ remember(pickerGroupState.selectedIndex, datePickerState.currentMonth()) {
+ derivedStateOf {
+ if (pickerGroupState.selectedIndex == FocusableElementDatePicker.NONE.index) {
+ monthString
+ } else {
+ fullMonthNames[(datePickerState.currentMonth() - 1) % 12]
+ }
+ }
}
- }
+ val dayContentDescription by
+ remember(pickerGroupState.selectedIndex, datePickerState.currentDay()) {
+ derivedStateOf {
+ createDescriptionDatePicker(
+ pickerGroupState,
+ datePickerState.currentDay(),
+ dayString
+ )
+ }
+ }
BoxWithConstraints(modifier = modifier.fillMaxSize().alpha(fullyDrawn.value)) {
val boxConstraints = this
Column(
@@ -611,22 +580,19 @@
) {
Spacer(Modifier.height(16.dp))
Text(
- text = when (FocusableElementDatePicker[pickerGroupState.selectedIndex]) {
- FocusableElementDatePicker.DAY -> dayString
- FocusableElementDatePicker.MONTH -> monthString
- FocusableElementDatePicker.YEAR -> yearString
- else -> ""
- },
+ text =
+ when (FocusableElementDatePicker[pickerGroupState.selectedIndex]) {
+ FocusableElementDatePicker.DAY -> dayString
+ FocusableElementDatePicker.MONTH -> monthString
+ FocusableElementDatePicker.YEAR -> yearString
+ else -> ""
+ },
color = optionColor,
style = MaterialTheme.typography.button,
maxLines = 1
)
val weightsToCenterVertically = 0.5f
- Spacer(
- Modifier
- .fillMaxWidth()
- .weight(weightsToCenterVertically)
- )
+ Spacer(Modifier.fillMaxWidth().weight(weightsToCenterVertically))
val spacerWidth = 8.dp
val dayWidth = 54.dp
val monthWidth = 80.dp
@@ -636,29 +602,29 @@
{ current: FocusableElementDatePicker, next: FocusableElementDatePicker ->
if (pickerGroupState.selectedIndex != current.index) {
pickerGroupState.selectedIndex = current.index
- } else {
- pickerGroupState.selectedIndex = next.index
- if (next == FocusableElementDatePicker.CONFIRM_BUTTON) {
- focusRequesterConfirmButton.requestFocus()
+ } else {
+ pickerGroupState.selectedIndex = next.index
+ if (next == FocusableElementDatePicker.CONFIRM_BUTTON) {
+ focusRequesterConfirmButton.requestFocus()
+ }
}
}
- }
Row(
- modifier = Modifier
- .fillMaxWidth()
- .offset(
- getPickerGroupRowOffset(
- boxConstraints.maxWidth,
- dayWidth,
- monthWidth,
- yearWidth,
- spacerWidth,
- numberOfSpacers,
- touchExplorationServicesEnabled,
- pickerGroupState
- )
- ),
+ modifier =
+ Modifier.fillMaxWidth()
+ .offset(
+ getPickerGroupRowOffset(
+ boxConstraints.maxWidth,
+ dayWidth,
+ monthWidth,
+ yearWidth,
+ spacerWidth,
+ numberOfSpacers,
+ touchExplorationServicesEnabled,
+ pickerGroupState
+ )
+ ),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Center
) {
@@ -673,9 +639,10 @@
FocusableElementDatePicker.MONTH
)
},
- option = pickerTextOption(textStyle) {
- "%d".format(datePickerState.currentDay(it))
- }
+ option =
+ pickerTextOption(textStyle) {
+ "%d".format(datePickerState.currentDay(it))
+ }
),
PickerGroupItem(
pickerState = datePickerState.monthState,
@@ -687,9 +654,10 @@
)
},
contentDescription = monthContentDescription,
- option = pickerTextOption(textStyle) {
- shortMonthNames[(datePickerState.currentMonth(it) - 1) % 12]
- }
+ option =
+ pickerTextOption(textStyle) {
+ shortMonthNames[(datePickerState.currentMonth(it) - 1) % 12]
+ }
),
PickerGroupItem(
pickerState = datePickerState.yearState,
@@ -701,9 +669,10 @@
)
},
contentDescription = yearContentDescription,
- option = pickerTextOption(textStyle) {
- "%4d".format(datePickerState.currentYear(it))
- }
+ option =
+ pickerTextOption(textStyle) {
+ "%4d".format(datePickerState.currentYear(it))
+ }
),
pickerGroupState = pickerGroupState,
autoCenter = true,
@@ -711,11 +680,7 @@
touchExplorationStateProvider = touchExplorationStateProvider
)
}
- Spacer(
- Modifier
- .fillMaxWidth()
- .weight(weightsToCenterVertically)
- )
+ Spacer(Modifier.fillMaxWidth().weight(weightsToCenterVertically))
Button(
onClick = {
if (pickerGroupState.selectedIndex >= 2) {
@@ -725,38 +690,39 @@
val confirmedDate =
LocalDate.of(confirmedYear, confirmedMonth, confirmedDay)
onDateConfirm(confirmedDate)
- } else if (pickerGroupState.selectedIndex ==
- FocusableElementDatePicker.DAY.index) {
+ } else if (
+ pickerGroupState.selectedIndex == FocusableElementDatePicker.DAY.index
+ ) {
onPickerSelected(
FocusableElementDatePicker.DAY,
FocusableElementDatePicker.MONTH
)
- } else if (pickerGroupState.selectedIndex ==
- FocusableElementDatePicker.MONTH.index) {
+ } else if (
+ pickerGroupState.selectedIndex == FocusableElementDatePicker.MONTH.index
+ ) {
onPickerSelected(
FocusableElementDatePicker.MONTH,
FocusableElementDatePicker.YEAR
)
}
},
- modifier = Modifier
- .semantics {
- focused = pickerGroupState.selectedIndex ==
- FocusableElementDatePicker.CONFIRM_BUTTON.index
- }
- .focusRequester(focusRequesterConfirmButton)
- .focusable()
+ modifier =
+ Modifier.semantics {
+ focused =
+ pickerGroupState.selectedIndex ==
+ FocusableElementDatePicker.CONFIRM_BUTTON.index
+ }
+ .focusRequester(focusRequesterConfirmButton)
+ .focusable()
) {
Icon(
- imageVector = if (pickerGroupState.selectedIndex < 2)
- Icons.AutoMirrored.Filled.KeyboardArrowRight else Icons.Filled.Check,
- contentDescription = if (pickerGroupState.selectedIndex < 2)
- "next"
- else
- "confirm",
- modifier = Modifier
- .size(24.dp)
- .wrapContentSize(align = Alignment.Center)
+ imageVector =
+ if (pickerGroupState.selectedIndex < 2)
+ Icons.AutoMirrored.Filled.KeyboardArrowRight
+ else Icons.Filled.Check,
+ contentDescription =
+ if (pickerGroupState.selectedIndex < 2) "next" else "confirm",
+ modifier = Modifier.size(24.dp).wrapContentSize(align = Alignment.Center)
)
}
Spacer(Modifier.height(12.dp))
@@ -764,9 +730,7 @@
}
}
- LaunchedEffect(Unit) {
- fullyDrawn.animateTo(1f)
- }
+ LaunchedEffect(Unit) { fullyDrawn.animateTo(1f) }
}
// getPickerGroupRowOffset function calculates the offset of the picker group row in talkback mode.
@@ -782,21 +746,29 @@
touchExplorationServicesEnabled: Boolean,
pickerGroupState: PickerGroupState
): Dp {
- // Calculates the extra offset named currentOffset because the total content width is more than the screen width
+ // Calculates the extra offset named currentOffset because the total content width is more than
+ // the screen width
var finalRowOffset = 0.dp
val totalContentWidth =
(dayPickerWidth + monthPickerWidth + yearPickerWidth + (spacerWidth * numberOfSpacers))
val currentOffset = (rowWidth - totalContentWidth) / 2
- if (touchExplorationServicesEnabled &&
- pickerGroupState.selectedIndex < 0 // When talkback is on and no picker is selected
+ if (
+ touchExplorationServicesEnabled &&
+ pickerGroupState.selectedIndex < 0 // When talkback is on and no picker is selected
) {
finalRowOffset = ((rowWidth - dayPickerWidth) / 2) - currentOffset
- } else if (touchExplorationServicesEnabled &&
- pickerGroupState.selectedIndex > 2 // When talkback is on and focus goes to confirm button
+ } else if (
+ touchExplorationServicesEnabled &&
+ pickerGroupState.selectedIndex >
+ 2 // When talkback is on and focus goes to confirm button
) {
- finalRowOffset = ((rowWidth - yearPickerWidth) / 2) -
- (dayPickerWidth + monthPickerWidth + (spacerWidth * numberOfSpacers) + currentOffset)
+ finalRowOffset =
+ ((rowWidth - yearPickerWidth) / 2) -
+ (dayPickerWidth +
+ monthPickerWidth +
+ (spacerWidth * numberOfSpacers) +
+ currentOffset)
}
return finalRowOffset
@@ -818,13 +790,8 @@
fun PickerWithoutGradient() {
val items = listOf("One", "Two", "Three", "Four", "Five")
val state = rememberPickerState(items.size)
- val contentDescription by remember { derivedStateOf {
- "${state.selectedOption + 1}"
- } }
- Box(
- modifier = Modifier.fillMaxSize(),
- contentAlignment = Alignment.Center
- ) {
+ val contentDescription by remember { derivedStateOf { "${state.selectedOption + 1}" } }
+ Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
Picker(
readOnly = false,
modifier = Modifier.size(100.dp, 100.dp),
@@ -837,23 +804,23 @@
}
}
-private fun pickerTextOption(textStyle: TextStyle, indexToText: (Int) -> String):
- (@Composable PickerScope.(optionIndex: Int, pickerSelected: Boolean) -> Unit) = {
- value: Int, pickerSelected: Boolean ->
- Box(modifier = Modifier.fillMaxSize()) {
- Text(
- text = indexToText(value),
- maxLines = 1,
- style = textStyle,
- color =
- if (pickerSelected) MaterialTheme.colors.secondary
- else MaterialTheme.colors.onBackground,
- modifier = Modifier
- .align(Alignment.Center)
- .wrapContentSize()
- )
+private fun pickerTextOption(
+ textStyle: TextStyle,
+ indexToText: (Int) -> String
+): (@Composable PickerScope.(optionIndex: Int, pickerSelected: Boolean) -> Unit) =
+ { value: Int, pickerSelected: Boolean ->
+ Box(modifier = Modifier.fillMaxSize()) {
+ Text(
+ text = indexToText(value),
+ maxLines = 1,
+ style = textStyle,
+ color =
+ if (pickerSelected) MaterialTheme.colors.secondary
+ else MaterialTheme.colors.onBackground,
+ modifier = Modifier.align(Alignment.Center).wrapContentSize()
+ )
+ }
}
-}
private fun createDescription(
pickerGroupState: PickerGroupState,
@@ -862,11 +829,12 @@
): String {
return when (pickerGroupState.selectedIndex) {
FocusableElementsTimePicker.NONE.index -> label
- else -> if (selectedValue == 1) {
- "$selectedValue $label"
- } else {
- "$selectedValue ${label}s"
- }
+ else ->
+ if (selectedValue == 1) {
+ "$selectedValue $label"
+ } else {
+ "$selectedValue ${label}s"
+ }
}
}
@@ -877,11 +845,12 @@
): String {
return when (pickerGroupState.selectedIndex) {
FocusableElement12Hour.NONE.index -> label
- else -> if (selectedValue == 1) {
- "$selectedValue $label"
- } else {
- "$selectedValue ${label}s"
- }
+ else ->
+ if (selectedValue == 1) {
+ "$selectedValue $label"
+ } else {
+ "$selectedValue ${label}s"
+ }
}
}
@@ -897,11 +866,7 @@
}
@RequiresApi(Build.VERSION_CODES.O)
-private fun verifyDates(
- date: LocalDate,
- fromDate: LocalDate,
- toDate: LocalDate
-) {
+private fun verifyDates(date: LocalDate, fromDate: LocalDate, toDate: LocalDate) {
require(toDate >= fromDate) { "toDate should be greater than or equal to fromDate" }
require(date in fromDate..toDate) { "date should lie between fromDate and toDate" }
}
@@ -911,13 +876,12 @@
private fun getMonthNames(pattern: String): List<String> {
val monthFormatter = DateTimeFormatter.ofPattern(pattern)
val months = 1..12
- return months.map {
- LocalDate.of(2022, it, 1).format(monthFormatter)
- }
+ return months.map { LocalDate.of(2022, it, 1).format(monthFormatter) }
}
@RequiresApi(Build.VERSION_CODES.O)
-internal class DatePickerState constructor(
+internal class DatePickerState
+constructor(
private val date: LocalDate,
private val fromDate: LocalDate?,
private val toDate: LocalDate?
@@ -931,15 +895,19 @@
)
val selectedYearEqualsFromYear: Boolean
get() = (yearState.selectedOption == 0)
+
val selectedYearEqualsToYear: Boolean
get() = (yearState.selectedOption == yearState.numberOfOptions - 1)
private val monthOffset: Int
get() = (if (selectedYearEqualsFromYear) (fromDate?.monthValue ?: 1) else 1)
+
private val maxMonths: Int
get() = (if (selectedYearEqualsToYear) (toDate?.monthValue ?: 12) else 12)
+
val numOfMonths: Int
get() = (maxMonths.minus(monthOffset - 1))
+
val monthState =
PickerState(
initialNumberOfOptions = numOfMonths,
@@ -947,26 +915,26 @@
)
val selectedMonthEqualsFromMonth: Boolean
get() = (selectedYearEqualsFromYear && monthState.selectedOption == 0)
+
val selectedMonthEqualsToMonth: Boolean
- get() = (selectedYearEqualsToYear &&
- monthState.selectedOption == monthState.numberOfOptions - 1)
+ get() =
+ (selectedYearEqualsToYear &&
+ monthState.selectedOption == monthState.numberOfOptions - 1)
private val dayOffset: Int
get() = (if (selectedMonthEqualsFromMonth) (fromDate?.dayOfMonth ?: 1) else 1)
+
private val firstDayOfMonth: LocalDate
- get() = LocalDate.of(
- currentYear(),
- currentMonth(),
- 1
- )
+ get() = LocalDate.of(currentYear(), currentMonth(), 1)
+
private val maxDaysInMonth: Int
- get() = (
- if (toDate != null && selectedMonthEqualsToMonth) {
+ get() =
+ (if (toDate != null && selectedMonthEqualsToMonth) {
toDate.dayOfMonth
} else {
firstDayOfMonth.with(TemporalAdjusters.lastDayOfMonth()).dayOfMonth
- }
- )
+ })
+
val numOfDays: Int
get() = maxDaysInMonth.minus(dayOffset - 1)
@@ -979,16 +947,19 @@
fun currentYear(year: Int = yearState.selectedOption): Int {
return year + yearOffset
}
+
fun currentMonth(month: Int = monthState.selectedOption): Int {
return month + monthOffset
}
+
fun currentDay(day: Int = dayState.selectedOption): Int {
return day + dayOffset
}
}
/**
- * This is copied from [TouchExplorationStateProvider]. Please updated if something changes over there.
+ * This is copied from [TouchExplorationStateProvider]. Please updated if something changes over
+ * there.
*/
private class DefaultTouchExplorationStateProvider : TouchExplorationStateProvider {
@@ -1007,9 +978,7 @@
listener.register(accessibilityManager)
}
},
- onDispose = {
- listener.unregister(accessibilityManager)
- }
+ onDispose = { listener.unregister(accessibilityManager) }
)
return remember { derivedStateOf { listener.isEnabled() } }
@@ -1021,9 +990,7 @@
onDispose: () -> Unit = {}
) {
DisposableEffect(this) {
- val observer = LifecycleEventObserver { _, event ->
- handleEvent(event)
- }
+ val observer = LifecycleEventObserver { _, event -> handleEvent(event) }
[email protected](observer)
onDispose {
onDispose()
@@ -1070,6 +1037,7 @@
companion object {
private val map = FocusableElementsTimePicker.values().associateBy { it.index }
+
operator fun get(value: Int) = map[value]
}
}
@@ -1080,8 +1048,10 @@
PERIOD(2),
CONFIRM_BUTTON(3),
NONE(-1);
+
companion object {
private val map = FocusableElement12Hour.values().associateBy { it.index }
+
operator fun get(value: Int) = map[value]
}
}
@@ -1092,8 +1062,10 @@
YEAR(2),
CONFIRM_BUTTON(3),
NONE(-1);
+
companion object {
private val map = FocusableElementDatePicker.values().associateBy { it.index }
+
operator fun get(value: Int) = map[value]
}
}
diff --git a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/PlaceholderDemo.kt b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/PlaceholderDemo.kt
index a736de1..363ba95 100644
--- a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/PlaceholderDemo.kt
+++ b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/PlaceholderDemo.kt
@@ -71,10 +71,7 @@
item {
var labelText by remember { mutableStateOf("") }
- ChipWithContentPlaceholders(
- label = labelText,
- textAlignment = TextAlign.Center
- )
+ ChipWithContentPlaceholders(label = labelText, textAlignment = TextAlign.Center)
LaunchedEffect(resetCount) {
labelText = ""
delay(3000)
@@ -109,10 +106,7 @@
}
item {
var labelText by remember { mutableStateOf("") }
- ChipWithOverlaidPlaceholder(
- label = labelText,
- textAlignment = TextAlign.Center
- )
+ ChipWithOverlaidPlaceholder(label = labelText, textAlignment = TextAlign.Center)
LaunchedEffect(resetCount) {
labelText = ""
delay(3000)
@@ -233,10 +227,11 @@
ChipWithOverlaidPlaceholder(
label = label,
icon = R.drawable.ic_accessibility_24px,
- colors = ChipDefaults.chipColors(
- backgroundColor = MaterialTheme.colors.surface,
- iconColor = AlternatePrimaryColor2.copy(alpha = 0.5f),
- ),
+ colors =
+ ChipDefaults.chipColors(
+ backgroundColor = MaterialTheme.colors.surface,
+ iconColor = AlternatePrimaryColor2.copy(alpha = 0.5f),
+ ),
)
LaunchedEffect(resetCount) {
label = ""
@@ -251,9 +246,7 @@
label = label,
icon = R.drawable.ic_accessibility_24px,
secondaryLabel = secondaryLabel,
- colors = ChipDefaults.chipColors(
- backgroundColor = AlternatePrimaryColor2
- ),
+ colors = ChipDefaults.chipColors(backgroundColor = AlternatePrimaryColor2),
)
LaunchedEffect(resetCount) {
label = ""
@@ -278,8 +271,9 @@
label =
"Primary that is long, to show truncation, we shouldn't be able to see " +
"more than 1 line"
- secondaryLabel = "Long Secondary that is long, to show truncation, we " +
- "shouldn't be able to see more than 1 line"
+ secondaryLabel =
+ "Long Secondary that is long, to show truncation, we " +
+ "shouldn't be able to see more than 1 line"
}
}
}
@@ -289,10 +283,7 @@
verticalArrangement = Arrangement.Bottom,
horizontalAlignment = Alignment.CenterHorizontally
) {
- CompactChip(
- label = { Text("Reset") },
- onClick = { resetCount++ }
- )
+ CompactChip(label = { Text("Reset") }, onClick = { resetCount++ })
}
}
}
@@ -314,25 +305,13 @@
}
ScalingLazyColumn {
- item {
- ListHeader {
- Text("Overlaid Placeholders", textAlign = TextAlign.Center)
- }
- }
- item {
- Centralize {
- Chip(
- label = { Text("Reset") },
- onClick = { resetCount++ }
- )
- }
- }
+ item { ListHeader { Text("Overlaid Placeholders", textAlign = TextAlign.Center) } }
+ item { Centralize { Chip(label = { Text("Reset") }, onClick = { resetCount++ }) } }
repeat(4) { itemIndex ->
item {
CardWithOverlaidPlaceholder(
contentReady = { showContent[itemIndex].value },
- content =
- {
+ content = {
Text("Some content $refreshCount")
Text("Some more content")
}
@@ -358,14 +337,12 @@
var iconReady by remember { mutableStateOf(icon == null) }
val maxLabelLines = if (secondaryLabel != null) 1 else 2
val chipPlaceholderState = rememberPlaceholderState {
- label.isNotEmpty() &&
- ((secondaryLabel == null) || secondaryLabel.isNotEmpty()) && iconReady
+ label.isNotEmpty() && ((secondaryLabel == null) || secondaryLabel.isNotEmpty()) && iconReady
}
Box {
Chip(
- modifier = modifier
- .fillMaxWidth(),
+ modifier = modifier.fillMaxWidth(),
onClick = onClick,
label = {
Text(
@@ -373,98 +350,101 @@
textAlign = textAlignment,
maxLines = maxLabelLines,
overflow = TextOverflow.Clip,
-
- modifier = Modifier
- .fillMaxWidth()
- .wrapContentHeight(align = Alignment.CenterVertically)
+ modifier =
+ Modifier.fillMaxWidth()
+ .wrapContentHeight(align = Alignment.CenterVertically)
)
},
- secondaryLabel = if (secondaryLabel != null) {
- {
- Text(
- text = secondaryLabel,
- textAlign = textAlignment,
- maxLines = 1,
- overflow = TextOverflow.Ellipsis,
- modifier = Modifier
- .fillMaxWidth()
- )
- }
- } else {
- null
- },
- icon = if (icon != null) {
- {
- DemoIcon(
- resourceId = icon,
- )
- if (!iconReady) {
- LaunchedEffect(Unit) {
- delay(2000)
- iconReady = true
+ secondaryLabel =
+ if (secondaryLabel != null) {
+ {
+ Text(
+ text = secondaryLabel,
+ textAlign = textAlignment,
+ maxLines = 1,
+ overflow = TextOverflow.Ellipsis,
+ modifier = Modifier.fillMaxWidth()
+ )
+ }
+ } else {
+ null
+ },
+ icon =
+ if (icon != null) {
+ {
+ DemoIcon(
+ resourceId = icon,
+ )
+ if (!iconReady) {
+ LaunchedEffect(Unit) {
+ delay(2000)
+ iconReady = true
+ }
}
}
- }
- } else {
- null
- },
+ } else {
+ null
+ },
enabled = true,
- colors = PlaceholderDefaults.placeholderChipColors(
- originalChipColors = colors,
- placeholderState = chipPlaceholderState
- )
+ colors =
+ PlaceholderDefaults.placeholderChipColors(
+ originalChipColors = colors,
+ placeholderState = chipPlaceholderState
+ )
)
- if (! chipPlaceholderState.isShowContent) {
+ if (!chipPlaceholderState.isShowContent) {
Chip(
- modifier = modifier
- .fillMaxWidth()
- .placeholderShimmer(
- placeholderState = chipPlaceholderState,
- ),
+ modifier =
+ modifier
+ .fillMaxWidth()
+ .placeholderShimmer(
+ placeholderState = chipPlaceholderState,
+ ),
onClick = onClick,
label = {
Box(
- modifier = Modifier
- .fillMaxWidth()
- .height(16.dp)
- .padding(top = 1.dp, bottom = 1.dp)
- .placeholder(placeholderState = chipPlaceholderState)
- )
- },
- secondaryLabel = if (hasSecondaryLabel) {
- {
- Box(
- modifier = Modifier
- .fillMaxWidth()
+ modifier =
+ Modifier.fillMaxWidth()
.height(16.dp)
.padding(top = 1.dp, bottom = 1.dp)
- .placeholder(chipPlaceholderState)
- )
- }
- } else {
- null
+ .placeholder(placeholderState = chipPlaceholderState)
+ )
},
- icon = if (hasIcon) {
- {
- Box(
- modifier = Modifier
- .size(ChipDefaults.IconSize)
- .placeholder(chipPlaceholderState)
- )
- }
- } else {
- null
- },
+ secondaryLabel =
+ if (hasSecondaryLabel) {
+ {
+ Box(
+ modifier =
+ Modifier.fillMaxWidth()
+ .height(16.dp)
+ .padding(top = 1.dp, bottom = 1.dp)
+ .placeholder(chipPlaceholderState)
+ )
+ }
+ } else {
+ null
+ },
+ icon =
+ if (hasIcon) {
+ {
+ Box(
+ modifier =
+ Modifier.size(ChipDefaults.IconSize)
+ .placeholder(chipPlaceholderState)
+ )
+ }
+ } else {
+ null
+ },
enabled = true,
- colors = PlaceholderDefaults.placeholderChipColors(
- placeholderState = chipPlaceholderState
- )
+ colors =
+ PlaceholderDefaults.placeholderChipColors(
+ placeholderState = chipPlaceholderState
+ )
)
}
}
- LaunchedEffect(chipPlaceholderState) {
- chipPlaceholderState.startPlaceholderAnimation()
- }
+ LaunchedEffect(chipPlaceholderState) { chipPlaceholderState.startPlaceholderAnimation() }
}
@OptIn(ExperimentalWearMaterialApi::class)
@@ -481,75 +461,65 @@
val maxLabelLines = if (secondaryLabel != null) 1 else 2
var iconReady by remember { mutableStateOf(icon == null) }
val chipPlaceholderState = rememberPlaceholderState {
- label.isNotEmpty() &&
- ((secondaryLabel == null) || secondaryLabel.isNotEmpty()) && iconReady
+ label.isNotEmpty() && ((secondaryLabel == null) || secondaryLabel.isNotEmpty()) && iconReady
}
Chip(
- modifier = modifier
- .fillMaxWidth()
- .placeholderShimmer(chipPlaceholderState),
+ modifier = modifier.fillMaxWidth().placeholderShimmer(chipPlaceholderState),
onClick = onClick,
label = {
- Box(
- modifier = Modifier
- .fillMaxWidth()
- .height(IntrinsicSize.Max)
- ) {
+ Box(modifier = Modifier.fillMaxWidth().height(IntrinsicSize.Max)) {
Text(
text = label,
textAlign = textAlignment,
maxLines = maxLabelLines,
overflow = TextOverflow.Clip,
-
- modifier = Modifier
- .fillMaxSize()
- .wrapContentHeight(align = Alignment.CenterVertically)
- .placeholder(placeholderState = chipPlaceholderState)
+ modifier =
+ Modifier.fillMaxSize()
+ .wrapContentHeight(align = Alignment.CenterVertically)
+ .placeholder(placeholderState = chipPlaceholderState)
)
}
},
- secondaryLabel = if (secondaryLabel != null) {
- {
- Text(
- text = secondaryLabel,
- textAlign = textAlignment,
- maxLines = 1,
- overflow = TextOverflow.Ellipsis,
- modifier = Modifier
- .fillMaxWidth()
- .placeholder(chipPlaceholderState)
- )
- }
- } else {
- null
- },
- icon = if (icon != null) {
- {
- DemoIcon(
- resourceId = icon,
- modifier = Modifier
- .placeholder(chipPlaceholderState)
- )
- if (!iconReady) {
- LaunchedEffect(Unit) {
- delay(2000)
- iconReady = true
+ secondaryLabel =
+ if (secondaryLabel != null) {
+ {
+ Text(
+ text = secondaryLabel,
+ textAlign = textAlignment,
+ maxLines = 1,
+ overflow = TextOverflow.Ellipsis,
+ modifier = Modifier.fillMaxWidth().placeholder(chipPlaceholderState)
+ )
+ }
+ } else {
+ null
+ },
+ icon =
+ if (icon != null) {
+ {
+ DemoIcon(
+ resourceId = icon,
+ modifier = Modifier.placeholder(chipPlaceholderState)
+ )
+ if (!iconReady) {
+ LaunchedEffect(Unit) {
+ delay(2000)
+ iconReady = true
+ }
}
}
- }
- } else {
- null
- },
+ } else {
+ null
+ },
enabled = true,
- colors = PlaceholderDefaults.placeholderChipColors(
- originalChipColors = colors,
- placeholderState = chipPlaceholderState
- )
+ colors =
+ PlaceholderDefaults.placeholderChipColors(
+ originalChipColors = colors,
+ placeholderState = chipPlaceholderState
+ )
)
- LaunchedEffect(chipPlaceholderState) {
- chipPlaceholderState.startPlaceholderAnimation()
- }
+ LaunchedEffect(chipPlaceholderState) { chipPlaceholderState.startPlaceholderAnimation() }
}
@OptIn(ExperimentalWearMaterialApi::class)
@@ -567,56 +537,43 @@
title = { Text("AppCard") },
time = { Text("now") },
modifier = Modifier.fillMaxHeight()
-
) {
if (content != null) content()
}
- if (! cardPlaceholderState.isShowContent) {
+ if (!cardPlaceholderState.isShowContent) {
AppCard(
onClick = {},
appName = {
- Text(" ",
- modifier = Modifier
- .weight(2f, true)
- .placeholder(cardPlaceholderState)
+ Text(
+ " ",
+ modifier = Modifier.weight(2f, true).placeholder(cardPlaceholderState)
)
},
title = {
- Text(" ",
- modifier = Modifier
- .fillMaxWidth()
- .placeholder(cardPlaceholderState)
- )
+ Text(" ", modifier = Modifier.fillMaxWidth().placeholder(cardPlaceholderState))
},
time = {
- Text(" ",
- modifier = Modifier
- .weight(1f, true)
- .placeholder(cardPlaceholderState)
+ Text(
+ " ",
+ modifier = Modifier.weight(1f, true).placeholder(cardPlaceholderState)
)
},
- modifier = Modifier
- .fillMaxHeight()
- .placeholderShimmer(
- cardPlaceholderState,
- MaterialTheme.shapes.large
- ),
- backgroundPainter = PlaceholderDefaults.placeholderBackgroundBrush(
- placeholderState = cardPlaceholderState
- )
+ modifier =
+ Modifier.fillMaxHeight()
+ .placeholderShimmer(cardPlaceholderState, MaterialTheme.shapes.large),
+ backgroundPainter =
+ PlaceholderDefaults.placeholderBackgroundBrush(
+ placeholderState = cardPlaceholderState
+ )
) {
Spacer(modifier = Modifier.height(4.dp))
- Box(modifier = Modifier
- .fillMaxSize()
- .placeholder(
- cardPlaceholderState,
- MaterialTheme.shapes.medium
- )
+ Box(
+ modifier =
+ Modifier.fillMaxSize()
+ .placeholder(cardPlaceholderState, MaterialTheme.shapes.medium)
)
}
- }
+ }
}
- LaunchedEffect(cardPlaceholderState) {
- cardPlaceholderState.startPlaceholderAnimation()
- }
+ LaunchedEffect(cardPlaceholderState) { cardPlaceholderState.startPlaceholderAnimation() }
}
diff --git a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/PositionIndicatorDemos.kt b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/PositionIndicatorDemos.kt
index 780a7c7..89c1c90 100644
--- a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/PositionIndicatorDemos.kt
+++ b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/PositionIndicatorDemos.kt
@@ -63,21 +63,13 @@
var smallList by remember { mutableStateOf(true) }
val listState = rememberScrollState()
- Scaffold(
- positionIndicator = { PositionIndicator(scrollState = listState) }
- ) {
+ Scaffold(positionIndicator = { PositionIndicator(scrollState = listState) }) {
Column(
verticalArrangement = Arrangement.spacedBy(8.dp),
- modifier = Modifier
- .fillMaxHeight()
- .wrapContentWidth()
- .verticalScroll(listState)
+ modifier = Modifier.fillMaxHeight().wrapContentWidth().verticalScroll(listState)
) {
repeat(if (smallList) 3 else 10) {
- Chip(
- onClick = { smallList = !smallList },
- label = { Text("Item #$it") }
- )
+ Chip(onClick = { smallList = !smallList }, label = { Text("Item #$it") })
}
}
}
@@ -89,23 +81,12 @@
val listState = rememberScalingLazyListState()
Scaffold(
positionIndicator = {
- PositionIndicator(
- scalingLazyListState = listState,
- modifier = Modifier
- )
+ PositionIndicator(scalingLazyListState = listState, modifier = Modifier)
}
) {
- ScalingLazyColumn(
- state = listState,
- autoCentering = null
- ) {
- items(
- count = if (smallList) 3 else 10
- ) {
- Chip(
- onClick = { smallList = !smallList },
- label = { Text("Item #$it") }
- )
+ ScalingLazyColumn(state = listState, autoCentering = null) {
+ items(count = if (smallList) 3 else 10) {
+ Chip(onClick = { smallList = !smallList }, label = { Text("Item #$it") })
}
}
}
@@ -116,24 +97,11 @@
val listState = rememberScalingLazyListState(5)
Scaffold(
positionIndicator = {
- PositionIndicator(
- scalingLazyListState = listState,
- modifier = Modifier
- )
+ PositionIndicator(scalingLazyListState = listState, modifier = Modifier)
}
) {
- ScalingLazyColumn(
- state = listState,
- autoCentering = null
- ) {
- items(
- count = 15
- ) {
- Chip(
- onClick = {},
- label = { Text("SLC Item #$it") }
- )
- }
+ ScalingLazyColumn(state = listState, autoCentering = null) {
+ items(count = 15) { Chip(onClick = {}, label = { Text("SLC Item #$it") }) }
}
}
}
@@ -149,15 +117,14 @@
var alignment by remember { mutableIntStateOf(0) }
var reverseDirection by remember { mutableStateOf(false) }
var layoutDirection by remember { mutableStateOf(false) }
- val actualLayoutDirection =
- if (layoutDirection) LayoutDirection.Rtl
- else LayoutDirection.Ltr
- val alignmentValues = listOf(
- PositionIndicatorAlignment.End,
- PositionIndicatorAlignment.OppositeRsb,
- PositionIndicatorAlignment.Left,
- PositionIndicatorAlignment.Right
- )
+ val actualLayoutDirection = if (layoutDirection) LayoutDirection.Rtl else LayoutDirection.Ltr
+ val alignmentValues =
+ listOf(
+ PositionIndicatorAlignment.End,
+ PositionIndicatorAlignment.OppositeRsb,
+ PositionIndicatorAlignment.Left,
+ PositionIndicatorAlignment.Right
+ )
val alignmentNames = listOf("End", "!Rsb", "Left", "Right")
CompositionLocalProvider(LocalLayoutDirection provides actualLayoutDirection) {
Scaffold(
@@ -167,21 +134,24 @@
indicatorHeight = 76.dp,
indicatorWidth = 6.dp,
paddingHorizontal = 5.dp,
- fadeInAnimationSpec = if (showFadeInAnimation) {
- PositionIndicatorDefaults.visibilityAnimationSpec
- } else {
- snap()
- },
- fadeOutAnimationSpec = if (showFadeOutAnimation) {
- PositionIndicatorDefaults.visibilityAnimationSpec
- } else {
- snap()
- },
- positionAnimationSpec = if (showPositionAnimation) {
- PositionIndicatorDefaults.positionAnimationSpec
- } else {
- snap()
- },
+ fadeInAnimationSpec =
+ if (showFadeInAnimation) {
+ PositionIndicatorDefaults.visibilityAnimationSpec
+ } else {
+ snap()
+ },
+ fadeOutAnimationSpec =
+ if (showFadeOutAnimation) {
+ PositionIndicatorDefaults.visibilityAnimationSpec
+ } else {
+ snap()
+ },
+ positionAnimationSpec =
+ if (showPositionAnimation) {
+ PositionIndicatorDefaults.positionAnimationSpec
+ } else {
+ snap()
+ },
color = MaterialTheme.colors.secondary,
reverseDirection = reverseDirection,
position = alignmentValues[alignment]
@@ -189,9 +159,7 @@
}
) {
Box(
- modifier = Modifier
- .fillMaxHeight()
- .padding(horizontal = 20.dp),
+ modifier = Modifier.fillMaxHeight().padding(horizontal = 20.dp),
contentAlignment = Alignment.Center
) {
Column(
@@ -204,14 +172,16 @@
value = position.floatValue,
valueRange = 0f..1f,
steps = 9,
- onValueChange = { position.floatValue = it })
+ onValueChange = { position.floatValue = it }
+ )
Text("Size")
DefaultInlineSlider(
modifier = Modifier.height(40.dp),
value = size.floatValue,
valueRange = 0f..1f,
steps = 9,
- onValueChange = { size.floatValue = it })
+ onValueChange = { size.floatValue = it }
+ )
Row(modifier = Modifier.align(Alignment.CenterHorizontally)) {
Button(onClick = { alignment = (alignment + 1) % 3 }) {
Text(alignmentNames[alignment])
@@ -219,29 +189,28 @@
ToggleButton(
checked = layoutDirection,
onCheckedChange = { layoutDirection = !layoutDirection }
- ) { Text(if (layoutDirection) "Rtl" else "Ltr") }
+ ) {
+ Text(if (layoutDirection) "Rtl" else "Ltr")
+ }
ToggleButton(
checked = reverseDirection,
onCheckedChange = { reverseDirection = !reverseDirection }
) {
- Text(
- text = "Rev Dir",
- textAlign = TextAlign.Center
- )
+ Text(text = "Rev Dir", textAlign = TextAlign.Center)
}
}
- Button(onClick = {
- visibility.value = when (visibility.value) {
- PositionIndicatorVisibility.Show ->
- PositionIndicatorVisibility.AutoHide
-
- PositionIndicatorVisibility.AutoHide ->
- PositionIndicatorVisibility.Hide
-
- else ->
- PositionIndicatorVisibility.Show
+ Button(
+ onClick = {
+ visibility.value =
+ when (visibility.value) {
+ PositionIndicatorVisibility.Show ->
+ PositionIndicatorVisibility.AutoHide
+ PositionIndicatorVisibility.AutoHide ->
+ PositionIndicatorVisibility.Hide
+ else -> PositionIndicatorVisibility.Show
+ }
}
- }) {
+ ) {
Text(
when (visibility.value) {
PositionIndicatorVisibility.AutoHide -> "AutoHide"
@@ -281,25 +250,16 @@
fun SharedPositionIndicator() {
val listStates = listOf(rememberScrollState(), rememberScrollState())
val selected = remember { mutableIntStateOf(0) }
- Scaffold(
- positionIndicator = {
- PositionIndicator(listStates[selected.intValue])
- }
- ) {
+ Scaffold(positionIndicator = { PositionIndicator(listStates[selected.intValue]) }) {
Row(modifier = Modifier.fillMaxSize()) {
repeat(2) { listIndex ->
Column(
verticalArrangement = Arrangement.spacedBy(8.dp),
- modifier = Modifier
- .fillMaxHeight()
- .width(80.dp)
- .verticalScroll(listStates[listIndex])
+ modifier =
+ Modifier.fillMaxHeight().width(80.dp).verticalScroll(listStates[listIndex])
) {
repeat(10) {
- Chip(
- onClick = { selected.intValue = listIndex },
- label = { Text("#$it") }
- )
+ Chip(onClick = { selected.intValue = listIndex }, label = { Text("#$it") })
}
}
}
@@ -312,8 +272,11 @@
private val size: State<Float>,
private val visibility: State<PositionIndicatorVisibility>
) : PositionIndicatorState {
- override val positionFraction get() = position.value
+ override val positionFraction
+ get() = position.value
+
override fun sizeFraction(scrollableContainerSizePx: Float) = size.value
+
override fun visibility(scrollableContainerSizePx: Float) = visibility.value
override fun equals(other: Any?) =
@@ -322,7 +285,6 @@
size == other.size &&
visibility == other.visibility
- override fun hashCode(): Int = position.hashCode() +
- 31 * size.hashCode() +
- 31 * visibility.hashCode()
+ override fun hashCode(): Int =
+ position.hashCode() + 31 * size.hashCode() + 31 * visibility.hashCode()
}
diff --git a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/ProgressIndicatorDemo.kt b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/ProgressIndicatorDemo.kt
index 628206c..b583b53 100644
--- a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/ProgressIndicatorDemo.kt
+++ b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/ProgressIndicatorDemo.kt
@@ -59,9 +59,7 @@
Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
ScalingLazyColumn(
- modifier = Modifier
- .fillMaxSize()
- .padding(horizontal = 8.dp),
+ modifier = Modifier.fillMaxSize().padding(horizontal = 8.dp),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
@@ -152,17 +150,17 @@
}
},
colors = ButtonDefaults.secondaryButtonColors(),
- modifier = Modifier
- .fillMaxSize()
+ modifier = Modifier.fillMaxSize()
) {
Icon(
- painter = painterResource(
- if (status == Status.Playing) R.drawable.ic_pause
- else R.drawable.ic_play
- ),
+ painter =
+ painterResource(
+ if (status == Status.Playing) R.drawable.ic_pause
+ else R.drawable.ic_play
+ ),
contentDescription = "Play",
- modifier = Modifier.size(24.dp)
- .wrapContentSize(align = Alignment.Center),
+ modifier =
+ Modifier.size(24.dp).wrapContentSize(align = Alignment.Center),
)
}
if (status == Status.Loading)
@@ -204,16 +202,15 @@
CompactChip(
modifier = Modifier.width(110.dp),
label = { Text(text = "Start loading") },
- onClick = {
- status = Status.Loading
- })
+ onClick = { status = Status.Loading }
+ )
}
}
}
/**
- * This is an example of possible smooth transition between indeterminate progress state
- * to determinate
+ * This is an example of possible smooth transition between indeterminate progress state to
+ * determinate
*/
@Composable
public fun TransformingCustomProgressIndicator() {
@@ -225,18 +222,15 @@
Row(verticalAlignment = Alignment.CenterVertically) {
Box(modifier = Modifier.size(ButtonDefaults.LargeButtonSize)) {
Button(
- onClick = {
- scope.launch { transformState.stopPlayingStartLoading() }
- },
+ onClick = { scope.launch { transformState.stopPlayingStartLoading() } },
colors = ButtonDefaults.secondaryButtonColors(),
- modifier = Modifier
- .fillMaxSize()
+ modifier = Modifier.fillMaxSize()
) {
Icon(
painter = painterResource(R.drawable.ic_play),
contentDescription = "Play",
- modifier = Modifier.size(24.dp)
- .wrapContentSize(align = Alignment.Center),
+ modifier =
+ Modifier.size(24.dp).wrapContentSize(align = Alignment.Center),
)
}
CircularProgressIndicator(
@@ -276,9 +270,7 @@
}
private suspend fun startPlaying(progress: Animatable<Float, AnimationVector1D>) {
- progress.animateTo(
- 1f, TweenSpec(durationMillis = 20000, easing = LinearEasing)
- )
+ progress.animateTo(1f, TweenSpec(durationMillis = 20000, easing = LinearEasing))
}
private suspend fun pausePlaying(progress: Animatable<Float, AnimationVector1D>) {
@@ -316,10 +308,7 @@
_startOffsetAngle.snapTo(-90f)
}
launch {
- progress.animateTo(
- 0f,
- animationSpec = TweenSpec(easing = LinearOutSlowInEasing)
- )
+ progress.animateTo(0f, animationSpec = TweenSpec(easing = LinearOutSlowInEasing))
}
}
}
@@ -337,12 +326,7 @@
// position -270 or 630 degrees. After that startAngle snapped to -90 to
// make animation easier
coroutineScope {
- launch {
- progress.animateTo(
- 0f,
- TweenSpec(easing = LinearOutSlowInEasing)
- )
- }
+ launch { progress.animateTo(0f, TweenSpec(easing = LinearOutSlowInEasing)) }
launch {
_startAngle.animateTo(
targetValue = if (_startAngle.value < 180) 270f else 630f,
@@ -374,30 +358,34 @@
launch {
progress.animateTo(
targetValue = 0.8f,
- animationSpec = InfiniteRepeatableSpec(
- animation = TweenSpec(
- delay = 200,
- easing = CubicBezierEasing(0.4f, 0.0f, 0.7f, 1.0f),
- // This duration is set as a half of startAngle duration because
- // it reverts
- durationMillis = 800
- ),
- repeatMode = RepeatMode.Reverse,
- initialStartOffset = StartOffset(200)
- )
+ animationSpec =
+ InfiniteRepeatableSpec(
+ animation =
+ TweenSpec(
+ delay = 200,
+ easing = CubicBezierEasing(0.4f, 0.0f, 0.7f, 1.0f),
+ // This duration is set as a half of startAngle duration because
+ // it reverts
+ durationMillis = 800
+ ),
+ repeatMode = RepeatMode.Reverse,
+ initialStartOffset = StartOffset(200)
+ )
)
}
launch {
_startAngle.animateTo(
targetValue = 630f,
- animationSpec = InfiniteRepeatableSpec(
- animation = TweenSpec(
- delay = 400,
- easing = CubicBezierEasing(0.7f, 0.0f, 0.75f, 1.0f),
- durationMillis = 1600
- ),
- repeatMode = RepeatMode.Restart
- )
+ animationSpec =
+ InfiniteRepeatableSpec(
+ animation =
+ TweenSpec(
+ delay = 400,
+ easing = CubicBezierEasing(0.7f, 0.0f, 0.75f, 1.0f),
+ durationMillis = 1600
+ ),
+ repeatMode = RepeatMode.Restart
+ )
)
}
}
@@ -413,10 +401,7 @@
_startAngle.snapTo(-90f)
}
launch {
- progress.animateTo(
- 0f,
- animationSpec = TweenSpec(easing = LinearOutSlowInEasing)
- )
+ progress.animateTo(0f, animationSpec = TweenSpec(easing = LinearOutSlowInEasing))
}
}
}
diff --git a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/ScalingLazyColumnDemo.kt b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/ScalingLazyColumnDemo.kt
index 7597a57..16c8bdc 100644
--- a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/ScalingLazyColumnDemo.kt
+++ b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/ScalingLazyColumnDemo.kt
@@ -42,30 +42,29 @@
@Composable
fun GuideLines() {
Canvas(
- modifier = Modifier
- .fillMaxSize(),
+ modifier = Modifier.fillMaxSize(),
onDraw = {
for (i in 1..9) {
drawLine(
- Color.Magenta, Offset(0f, (size.height / 10f) * i),
+ Color.Magenta,
+ Offset(0f, (size.height / 10f) * i),
Offset(size.width - 1, (size.height / 10f) * i)
)
}
- })
+ }
+ )
}
@Composable
fun ScalingLazyColumnDetail() {
val state = rememberScalingLazyListState()
val applicationContext = LocalContext.current
- val screenHeightPx = with(LocalDensity.current) {
- Dp(applicationContext.resources.configuration.screenHeightDp.toFloat()).roundToPx()
- }
+ val screenHeightPx =
+ with(LocalDensity.current) {
+ Dp(applicationContext.resources.configuration.screenHeightDp.toFloat()).roundToPx()
+ }
val halfScreenHeightPx = screenHeightPx / 2f
- ScalingLazyColumn(
- modifier = Modifier.fillMaxWidth(),
- state = state
- ) {
+ ScalingLazyColumn(modifier = Modifier.fillMaxWidth(), state = state) {
item {
Text(
text = "Screen height: ${screenHeightPx}px",
@@ -103,15 +102,8 @@
@Composable
fun ScalingLazyColumnMixedTypes() {
ScalingLazyColumn {
- item {
- ListHeader { Text("Activity") }
- }
- item {
- Text(
- text = "2 hours of listening 400mb of 2.8gb",
- textAlign = TextAlign.Center
- )
- }
+ item { ListHeader { Text("Activity") } }
+ item { Text(text = "2 hours of listening 400mb of 2.8gb", textAlign = TextAlign.Center) }
item {
DemoIconChip(
style = ChipStyle.Secondary,
@@ -151,9 +143,7 @@
DemoImage(resourceId = R.drawable.ic_maps_icon)
}
}
- item {
- ListHeader { Text("Activity") }
- }
+ item { ListHeader { Text("Activity") } }
item {
AppCard(
onClick = {},
@@ -169,20 +159,16 @@
) {
Column(modifier = Modifier.fillMaxWidth()) {
Text(
- text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do " +
- "eiusmod tempor incididunt ut labore et dolore magna aliqua. Lorem " +
- "ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod " +
- "tempor incididunt ut labore et dolore magna aliqua."
+ text =
+ "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do " +
+ "eiusmod tempor incididunt ut labore et dolore magna aliqua. Lorem " +
+ "ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod " +
+ "tempor incididunt ut labore et dolore magna aliqua."
)
}
}
}
- item {
- Text(
- text = "2 hours of listening 400mb of 2.8gb",
- textAlign = TextAlign.Center
- )
- }
+ item { Text(text = "2 hours of listening 400mb of 2.8gb", textAlign = TextAlign.Center) }
item {
AppCard(
onClick = {},
@@ -196,9 +182,7 @@
title = { Text("AppCard") },
time = { Text("now") },
) {
- Column(modifier = Modifier.fillMaxWidth()) {
- Text("Some body content")
- }
+ Column(modifier = Modifier.fillMaxWidth()) { Text("Some body content") }
}
}
}
diff --git a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/ScrollAwayDemos.kt b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/ScrollAwayDemos.kt
index 7bb195c..a0990a5 100644
--- a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/ScrollAwayDemos.kt
+++ b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/ScrollAwayDemos.kt
@@ -53,10 +53,14 @@
import androidx.wear.compose.material.scrollAway
@Composable
-fun ScrollAwayColumnDemo() { ColumnCardDemo(0.dp) }
+fun ScrollAwayColumnDemo() {
+ ColumnCardDemo(0.dp)
+}
@Composable
-fun ScrollAwayColumnDelayDemo() { ColumnCardDemo(offset = 20.dp) }
+fun ScrollAwayColumnDelayDemo() {
+ ColumnCardDemo(offset = 20.dp)
+}
@Composable
fun ScrollAwayLazyColumnDemo() {
@@ -65,11 +69,7 @@
@Composable
fun ScrollAwayLazyColumnDemo2() {
- LazyColumnCardDemo(
- offset = -100.dp,
- itemIndex = 1,
- initialVisibleItemIndex = 2
- )
+ LazyColumnCardDemo(offset = -100.dp, itemIndex = 1, initialVisibleItemIndex = 2)
}
@Composable
@@ -142,31 +142,28 @@
modifier = Modifier.fillMaxSize(),
timeText = {
TimeText(
- modifier = Modifier.scrollAway(
- scrollState = scrollState,
- offset = offset,
- )
+ modifier =
+ Modifier.scrollAway(
+ scrollState = scrollState,
+ offset = offset,
+ )
)
},
- positionIndicator = {
- PositionIndicator(scrollState = scrollState)
- }
+ positionIndicator = { PositionIndicator(scrollState = scrollState) }
) {
Column(
- modifier = Modifier
- .verticalScroll(scrollState)
- .rotaryScrollable(
- RotaryScrollableDefaults.behavior(
- scrollableState = scrollState,
- flingBehavior = ScrollableDefaults.flingBehavior()
- ),
- focusRequester = focusRequester
- )
+ modifier =
+ Modifier.verticalScroll(scrollState)
+ .rotaryScrollable(
+ RotaryScrollableDefaults.behavior(
+ scrollableState = scrollState,
+ flingBehavior = ScrollableDefaults.flingBehavior()
+ ),
+ focusRequester = focusRequester
+ )
) {
val modifier = Modifier.height(LocalConfiguration.current.screenHeightDp.dp / 2)
- repeat(10) { i ->
- ExampleCard(modifier, i)
- }
+ repeat(10) { i -> ExampleCard(modifier, i) }
}
}
}
@@ -181,25 +178,27 @@
Scaffold(
modifier = Modifier.fillMaxSize(),
timeText = {
- TimeText(modifier = Modifier.scrollAway(
- scrollState = scrollState,
- offset = offset,
- itemIndex = itemIndex
- ))
+ TimeText(
+ modifier =
+ Modifier.scrollAway(
+ scrollState = scrollState,
+ offset = offset,
+ itemIndex = itemIndex
+ )
+ )
},
- positionIndicator = {
- PositionIndicator(lazyListState = scrollState)
- }
+ positionIndicator = { PositionIndicator(lazyListState = scrollState) }
) {
LazyColumn(
state = scrollState,
- modifier = Modifier.rotaryScrollable(
- RotaryScrollableDefaults.behavior(
- scrollableState = scrollState,
- flingBehavior = ScrollableDefaults.flingBehavior()
- ),
- focusRequester = focusRequester
- )
+ modifier =
+ Modifier.rotaryScrollable(
+ RotaryScrollableDefaults.behavior(
+ scrollableState = scrollState,
+ flingBehavior = ScrollableDefaults.flingBehavior()
+ ),
+ focusRequester = focusRequester
+ )
) {
items(10) { i ->
val modifier = Modifier.fillParentMaxHeight(0.5f)
@@ -224,29 +223,25 @@
Scaffold(
modifier = Modifier.fillMaxSize(),
timeText = {
- TimeText(modifier =
- Modifier.scrollAway(
- scrollState = scrollState,
- itemIndex = itemIndex,
- offset = offset,
- ))
+ TimeText(
+ modifier =
+ Modifier.scrollAway(
+ scrollState = scrollState,
+ itemIndex = itemIndex,
+ offset = offset,
+ )
+ )
},
- positionIndicator = {
- PositionIndicator(scalingLazyListState = scrollState)
- }
+ positionIndicator = { PositionIndicator(scalingLazyListState = scrollState) }
) {
ScalingLazyColumn(
contentPadding = PaddingValues(10.dp),
state = scrollState,
autoCentering = AutoCenteringParams(itemIndex = 1, itemOffset = 0)
) {
- item {
- ListHeader { Text("Cards") }
- }
+ item { ListHeader { Text("Cards") } }
- items(10) { i ->
- ExampleCard(Modifier.fillParentMaxHeight(0.5f), i)
- }
+ items(10) { i -> ExampleCard(Modifier.fillParentMaxHeight(0.5f), i) }
}
}
}
@@ -266,42 +261,33 @@
Scaffold(
modifier = Modifier.fillMaxSize(),
timeText = {
- TimeText(modifier =
- Modifier.scrollAway(
- scrollState = scrollState,
- itemIndex = itemIndex,
- offset = offset,
- ))
+ TimeText(
+ modifier =
+ Modifier.scrollAway(
+ scrollState = scrollState,
+ itemIndex = itemIndex,
+ offset = offset,
+ )
+ )
},
- positionIndicator = {
- PositionIndicator(scalingLazyListState = scrollState)
- }
+ positionIndicator = { PositionIndicator(scalingLazyListState = scrollState) }
) {
ScalingLazyColumn(
contentPadding = PaddingValues(10.dp),
state = scrollState,
) {
- item {
- ListHeader { Text("Chips") }
- }
+ item { ListHeader { Text("Chips") } }
- items(10) { i ->
- ExampleChip(Modifier.fillMaxWidth(), i)
- }
+ items(10) { i -> ExampleChip(Modifier.fillMaxWidth(), i) }
}
}
}
@Composable
private fun ExampleCard(modifier: Modifier, i: Int) {
- Card(
- modifier = modifier,
- onClick = { }
- ) {
+ Card(modifier = modifier, onClick = {}) {
Box(
- modifier = Modifier
- .fillMaxSize()
- .background(MaterialTheme.colors.surface),
+ modifier = Modifier.fillMaxSize().background(MaterialTheme.colors.surface),
contentAlignment = Alignment.Center
) {
Text(text = "Card $i")
@@ -313,7 +299,7 @@
private fun ExampleChip(modifier: Modifier, i: Int) {
Chip(
modifier = modifier,
- onClick = { },
+ onClick = {},
colors = ChipDefaults.primaryChipColors(),
border = ChipDefaults.chipBorder()
) {
diff --git a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/ScrollableColumnDemo.kt b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/ScrollableColumnDemo.kt
index fdee274..30d431f 100644
--- a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/ScrollableColumnDemo.kt
+++ b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/ScrollableColumnDemo.kt
@@ -40,12 +40,12 @@
NotScrollableLabel(Modifier.weight(1f))
Column(
verticalArrangement = Arrangement.spacedBy(8.dp),
- modifier = Modifier
- .fillMaxHeight()
- .wrapContentWidth()
- .verticalScroll(rememberScrollState())
- .background(Color.Green.copy(alpha = 0.1f))
- .padding(horizontal = 24.dp)
+ modifier =
+ Modifier.fillMaxHeight()
+ .wrapContentWidth()
+ .verticalScroll(rememberScrollState())
+ .background(Color.Green.copy(alpha = 0.1f))
+ .padding(horizontal = 24.dp)
) {
for (i in 0 until 100) {
Text("$i")
@@ -61,9 +61,6 @@
"Not scrollable",
color = Color.Red,
textAlign = TextAlign.Center,
- modifier = modifier
- .fillMaxSize()
- .background(Color.Red.copy(alpha = 0.1f))
- .wrapContentSize()
+ modifier = modifier.fillMaxSize().background(Color.Red.copy(alpha = 0.1f)).wrapContentSize()
)
}
diff --git a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/ScrollableRowDemo.kt b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/ScrollableRowDemo.kt
index f717ce2..e671cec 100644
--- a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/ScrollableRowDemo.kt
+++ b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/ScrollableRowDemo.kt
@@ -46,12 +46,12 @@
NotScrollableLabel(Modifier.weight(1f))
Row(
horizontalArrangement = Arrangement.spacedBy(8.dp),
- modifier = Modifier
- .fillMaxWidth()
- .wrapContentHeight()
- .horizontalScroll(rememberScrollState())
- .background(Color.Green.copy(alpha = 0.1f))
- .padding(vertical = 24.dp)
+ modifier =
+ Modifier.fillMaxWidth()
+ .wrapContentHeight()
+ .horizontalScroll(rememberScrollState())
+ .background(Color.Green.copy(alpha = 0.1f))
+ .padding(vertical = 24.dp)
) {
for (i in 0 until 100) {
Text("$i")
@@ -66,9 +66,6 @@
Text(
"Not scrollable",
color = Color.Red,
- modifier = modifier
- .fillMaxSize()
- .background(Color.Red.copy(alpha = 0.1f))
- .wrapContentSize()
+ modifier = modifier.fillMaxSize().background(Color.Red.copy(alpha = 0.1f)).wrapContentSize()
)
}
diff --git a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/SelectableChipDemo.kt b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/SelectableChipDemo.kt
index 72f78c5..7352027 100644
--- a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/SelectableChipDemo.kt
+++ b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/SelectableChipDemo.kt
@@ -83,9 +83,7 @@
SelectableChip(
selected = selectedRadioIndex == 0,
onClick = { selectedRadioIndex = 0 },
- label = {
- Text("Selectable", maxLines = 2, overflow = TextOverflow.Ellipsis)
- },
+ label = { Text("Selectable", maxLines = 2, overflow = TextOverflow.Ellipsis) },
enabled = enabled,
)
}
@@ -95,13 +93,7 @@
SelectableChip(
selected = selectedRadioIndex == 1,
onClick = { selectedRadioIndex = 1 },
- label = {
- Text(
- "Selectable",
- maxLines = 1,
- overflow = TextOverflow.Ellipsis
- )
- },
+ label = { Text("Selectable", maxLines = 1, overflow = TextOverflow.Ellipsis) },
secondaryLabel = {
Text("Custom", maxLines = 1, overflow = TextOverflow.Ellipsis)
},
@@ -109,19 +101,21 @@
RadioButton(
selected = selectedRadioIndex == 1,
enabled = enabled,
- colors = RadioButtonDefaults.colors(
- selectedRingColor = MaterialTheme.colors.primary,
- selectedDotColor = Color.Green,
- unselectedRingColor = Color.Magenta,
- unselectedDotColor = Color.Red,
- ),
+ colors =
+ RadioButtonDefaults.colors(
+ selectedRingColor = MaterialTheme.colors.primary,
+ selectedDotColor = Color.Green,
+ unselectedRingColor = Color.Magenta,
+ unselectedDotColor = Color.Red,
+ ),
)
},
enabled = enabled,
- colors = SelectableChipDefaults.selectableChipColors(
- selectedSelectionControlColor = AlternatePrimaryColor3,
- selectedEndBackgroundColor = AlternatePrimaryColor3.copy(alpha = 0.325f)
- )
+ colors =
+ SelectableChipDefaults.selectableChipColors(
+ selectedSelectionControlColor = AlternatePrimaryColor3,
+ selectedEndBackgroundColor = AlternatePrimaryColor3.copy(alpha = 0.325f)
+ )
)
}
}
@@ -162,16 +156,15 @@
ToggleChip(
checked = enabled,
onCheckedChange = { enabled = it },
- label = {
- Text("Chips enabled")
- },
+ label = { Text("Chips enabled") },
// For Switch toggle controls the Wear Material UX guidance is to set the
// unselected toggle control color to
// ToggleChipDefaults.switchUncheckedIconColor() rather than the default.
- colors = ToggleChipDefaults.toggleChipColors(
- uncheckedToggleControlColor = ToggleChipDefaults
- .SwitchUncheckedIconColor
- ),
+ colors =
+ ToggleChipDefaults.toggleChipColors(
+ uncheckedToggleControlColor =
+ ToggleChipDefaults.SwitchUncheckedIconColor
+ ),
toggleControl = {
Switch(
checked = enabled,
@@ -204,9 +197,8 @@
RadioButton(
selected = selected,
enabled = true,
- modifier = Modifier.semantics {
- contentDescription = primaryLabel
- })
+ modifier = Modifier.semantics { contentDescription = primaryLabel }
+ )
}
)
}
diff --git a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/SettingsDemo.kt b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/SettingsDemo.kt
index cb68ec5..a52192f 100644
--- a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/SettingsDemo.kt
+++ b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/SettingsDemo.kt
@@ -36,24 +36,14 @@
@Composable
fun SettingsDemo() {
val scalingLazyListState = rememberScalingLazyListState()
- Scaffold(
- timeText = {
- TimeText(modifier = Modifier.scrollAway(scalingLazyListState))
- }
- ) {
+ Scaffold(timeText = { TimeText(modifier = Modifier.scrollAway(scalingLazyListState)) }) {
ScalingLazyColumn(
state = scalingLazyListState,
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally
) {
- item {
- ListHeader(
- modifier = Modifier.fillMaxWidth()
- ) {
- Text("Settings")
- }
- }
- // Connectivity
+ item { ListHeader(modifier = Modifier.fillMaxWidth()) { Text("Settings") } }
+ // Connectivity
item {
SettingsChip(
painterResourceId = R.drawable.ic_settings_connectivity,
@@ -69,10 +59,7 @@
}
// Gestures
item {
- SettingsChip(
- painterResourceId = R.drawable.ic_settings_gestures,
- text = "Gestures"
- )
+ SettingsChip(painterResourceId = R.drawable.ic_settings_gestures, text = "Gestures")
}
// Apps & Notifications
item {
@@ -83,18 +70,10 @@
}
// Google
item {
- SettingsChip(
- painterResourceId = R.drawable.ic_settings_googleg,
- text = "Google"
- )
+ SettingsChip(painterResourceId = R.drawable.ic_settings_googleg, text = "Google")
}
// Sound
- item {
- SettingsChip(
- painterResourceId = R.drawable.ic_settings_sound,
- text = "Sound"
- )
- }
+ item { SettingsChip(painterResourceId = R.drawable.ic_settings_sound, text = "Sound") }
// Vibration
item {
SettingsChip(
@@ -104,10 +83,7 @@
}
// Battery
item {
- SettingsChip(
- painterResourceId = R.drawable.ic_settings_battery,
- text = "Battery"
- )
+ SettingsChip(painterResourceId = R.drawable.ic_settings_battery, text = "Battery")
}
// General
item {
@@ -125,10 +101,7 @@
}
// Location
item {
- SettingsChip(
- painterResourceId = R.drawable.ic_settings_location,
- text = "Location"
- )
+ SettingsChip(painterResourceId = R.drawable.ic_settings_location, text = "Location")
}
// Safety and Emergency
item {
@@ -146,37 +119,23 @@
}
// Security
item {
- SettingsChip(
- painterResourceId = R.drawable.ic_settings_security,
- text = "Security"
- )
+ SettingsChip(painterResourceId = R.drawable.ic_settings_security, text = "Security")
}
// System
item {
- SettingsChip(
- painterResourceId = R.drawable.ic_settings_system,
- text = "System"
- )
+ SettingsChip(painterResourceId = R.drawable.ic_settings_system, text = "System")
}
}
}
}
@Composable
-private fun SettingsChip(
- painterResourceId: Int,
- text: String
-) {
+private fun SettingsChip(painterResourceId: Int, text: String) {
Chip(
onClick = { /* */ },
modifier = Modifier.fillMaxSize(),
colors = ChipDefaults.secondaryChipColors(),
- icon = {
- Icon(
- painter = painterResource(painterResourceId),
- contentDescription = text
- )
- },
+ icon = { Icon(painter = painterResource(painterResourceId), contentDescription = text) },
label = { Text(text) }
)
}
diff --git a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/SliderDemo.kt b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/SliderDemo.kt
index 585c7d1..a374353 100644
--- a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/SliderDemo.kt
+++ b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/SliderDemo.kt
@@ -51,10 +51,8 @@
ScalingLazyColumn(
horizontalAlignment = Alignment.CenterHorizontally,
- verticalArrangement = Arrangement.spacedBy(
- space = 4.dp,
- alignment = Alignment.CenterVertically
- ),
+ verticalArrangement =
+ Arrangement.spacedBy(space = 4.dp, alignment = Alignment.CenterVertically),
modifier = Modifier.fillMaxSize(),
autoCentering = AutoCenteringParams(itemIndex = 0)
) {
@@ -65,7 +63,8 @@
enabled = enabled,
valueRange = 1f..100f,
steps = 98,
- onValueChange = { valueWithoutSegments = it })
+ onValueChange = { valueWithoutSegments = it }
+ )
}
item { Text("With segments, value = $valueWithSegments") }
item {
@@ -86,9 +85,10 @@
// For Switch toggle controls the Wear Material UX guidance is to set the
// unselected toggle control color to ToggleChipDefaults.switchUncheckedIconColor()
// rather than the default.
- colors = ToggleChipDefaults.toggleChipColors(
- uncheckedToggleControlColor = ToggleChipDefaults.SwitchUncheckedIconColor
- ),
+ colors =
+ ToggleChipDefaults.toggleChipColors(
+ uncheckedToggleControlColor = ToggleChipDefaults.SwitchUncheckedIconColor
+ ),
toggleControl = {
Icon(
imageVector = ToggleChipDefaults.switchIcon(checked = enabled),
@@ -107,10 +107,8 @@
ScalingLazyColumn(
horizontalAlignment = Alignment.CenterHorizontally,
- verticalArrangement = Arrangement.spacedBy(
- space = 4.dp,
- alignment = Alignment.CenterVertically
- ),
+ verticalArrangement =
+ Arrangement.spacedBy(space = 4.dp, alignment = Alignment.CenterVertically),
modifier = Modifier.fillMaxSize(),
autoCentering = AutoCenteringParams(itemIndex = 0)
) {
@@ -120,7 +118,8 @@
value = valueWithoutSegments,
valueProgression = IntProgression.fromClosedRange(0, 15, 3),
segmented = false,
- onValueChange = { valueWithoutSegments = it })
+ onValueChange = { valueWithoutSegments = it }
+ )
}
item { Text("With segments, value = $valueWithSegments") }
item {
@@ -144,19 +143,17 @@
@Composable
fun InlineSliderCustomColorsDemo() {
var value by remember { mutableFloatStateOf(4.5f) }
- Box(
- contentAlignment = Alignment.Center,
- modifier = Modifier.fillMaxSize()
- ) {
+ Box(contentAlignment = Alignment.Center, modifier = Modifier.fillMaxSize()) {
DefaultInlineSlider(
value = value,
onValueChange = { value = it },
valueRange = 3f..6f,
steps = 5,
segmented = false,
- colors = InlineSliderDefaults.colors(
- selectedBarColor = AlternatePrimaryColor1,
- ),
+ colors =
+ InlineSliderDefaults.colors(
+ selectedBarColor = AlternatePrimaryColor1,
+ ),
modifier = Modifier.padding(horizontal = 10.dp)
)
}
@@ -169,10 +166,8 @@
ScalingLazyColumn(
horizontalAlignment = Alignment.CenterHorizontally,
- verticalArrangement = Arrangement.spacedBy(
- space = 4.dp,
- alignment = Alignment.CenterVertically
- ),
+ verticalArrangement =
+ Arrangement.spacedBy(space = 4.dp, alignment = Alignment.CenterVertically),
modifier = Modifier.fillMaxSize(),
autoCentering = AutoCenteringParams(itemIndex = 0)
) {
diff --git a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/StepperDemo.kt b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/StepperDemo.kt
index 3f6af0a..89e08de 100644
--- a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/StepperDemo.kt
+++ b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/StepperDemo.kt
@@ -44,7 +44,9 @@
increaseIcon = { Icon(StepperDefaults.Increase, "Increase") },
decreaseIcon = { Icon(StepperDefaults.Decrease, "Decrease") },
steps = 2
- ) { Text("Value: $value") }
+ ) {
+ Text("Value: $value")
+ }
}
@Composable
@@ -56,7 +58,9 @@
increaseIcon = { Icon(StepperDefaults.Increase, "Increase") },
decreaseIcon = { Icon(StepperDefaults.Decrease, "Decrease") },
valueProgression = 1..10
- ) { Text("Value: $value") }
+ ) {
+ Text("Value: $value")
+ }
}
@Composable
@@ -79,21 +83,19 @@
label = { Text("Volume : $valueState") },
icon = {
Icon(
- painter = painterResource(
- id = if (valueState > 0)
- R.drawable.ic_volume_up_24px
- else R.drawable.ic_volume_off_24px
- ),
+ painter =
+ painterResource(
+ id =
+ if (valueState > 0) R.drawable.ic_volume_up_24px
+ else R.drawable.ic_volume_off_24px
+ ),
contentDescription = null,
)
}
)
}
- PositionIndicator(
- value = { valueState },
- range = range
- )
+ PositionIndicator(value = { valueState }, range = range)
}
@Composable
@@ -113,8 +115,5 @@
Text("Volume : $valueState")
}
- PositionIndicator(
- value = { valueState },
- range = range
- )
+ PositionIndicator(value = { valueState }, range = range)
}
diff --git a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/SwipeToDismissDemo.kt b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/SwipeToDismissDemo.kt
index 96572c1..b0bf569 100644
--- a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/SwipeToDismissDemo.kt
+++ b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/SwipeToDismissDemo.kt
@@ -50,10 +50,10 @@
import androidx.wear.compose.material.Text
/**
- * SwipeToDismiss demo - manages its own navigation between a List screen and a Detail screen,
- * using SwipeToDismissBox to recognise the swipe gesture and navigate backwards.
- * During the swipe gesture, a background is displayed that shows the previous screen.
- * Uses LaunchedEffect to reset the offset of the swipe by snapping back to original position.
+ * SwipeToDismiss demo - manages its own navigation between a List screen and a Detail screen, using
+ * SwipeToDismissBox to recognise the swipe gesture and navigate backwards. During the swipe
+ * gesture, a background is displayed that shows the previous screen. Uses LaunchedEffect to reset
+ * the offset of the swipe by snapping back to original position.
*/
@Composable
fun SwipeToDismissDemo(
@@ -84,7 +84,7 @@
// What to show behind the content whilst swiping.
when (demoState.value) {
SwipeDismissDemoState.List -> {
- DisplayDemoList(SwipeToDismissDemos) { }
+ DisplayDemoList(SwipeToDismissDemos) {}
}
SwipeDismissDemoState.Detail -> {
SwipeToDismissOptionsList()
@@ -107,9 +107,10 @@
// When using Modifier.edgeSwipeToDismiss, it is required that the element on which the
// modifier applies exists within a SwipeToDismissBox which shares the same state.
// Here, we share the swipeToDismissBoxState used by DemoApp's SwipeToDismissBox.
- modifier = Modifier.border(4.dp, Color.DarkGray)
- .fillMaxSize()
- .edgeSwipeToDismiss(swipeToDismissBoxState),
+ modifier =
+ Modifier.border(4.dp, Color.DarkGray)
+ .fillMaxSize()
+ .edgeSwipeToDismiss(swipeToDismissBoxState),
horizontalArrangement = Arrangement.spacedBy(12.dp),
) {
items(5) { index ->
@@ -123,10 +124,8 @@
}
Box(
- modifier = Modifier
- .fillMaxHeight()
- .width(30.dp)
- .background(Color.White.copy(alpha = 0.5f))
+ modifier =
+ Modifier.fillMaxHeight().width(30.dp).background(Color.White.copy(alpha = 0.5f))
)
}
}
@@ -146,17 +145,19 @@
hasBackground = previous != null,
onDismissed = { items.removeLastOrNull() }
) { isBackground ->
- val item = if (isBackground) {
- previous
- } else {
- current
- }
+ val item =
+ if (isBackground) {
+ previous
+ } else {
+ current
+ }
Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
if (item != null) {
Chip(
onClick = { items.add(items.size + 1) },
- label = { Text("Screen number $item") })
+ label = { Text("Screen number $item") }
+ )
} else {
Text("Empty Screen")
}
@@ -170,16 +171,12 @@
}
@Composable
-private fun SwipeToDismissOptionsList(
- state: MutableState<SwipeDismissDemoState>? = null
-) {
+private fun SwipeToDismissOptionsList(state: MutableState<SwipeDismissDemoState>? = null) {
Column(
- modifier = Modifier
- .fillMaxSize()
- .padding(horizontal = 8.dp, vertical = 8.dp)
- .verticalScroll(
- rememberScrollState()
- ),
+ modifier =
+ Modifier.fillMaxSize()
+ .padding(horizontal = 8.dp, vertical = 8.dp)
+ .verticalScroll(rememberScrollState()),
verticalArrangement = Arrangement.spacedBy(4.dp, Alignment.CenterVertically),
horizontalAlignment = Alignment.CenterHorizontally
) {
@@ -203,9 +200,10 @@
) {
Text(text = "Swipe Dismiss Demo Detail", textAlign = TextAlign.Center)
Text(
- text = "Start swiping to reveal the previous level menu. " +
- "Complete the swipe to " +
- "dismiss this screen."
+ text =
+ "Start swiping to reveal the previous level menu. " +
+ "Complete the swipe to " +
+ "dismiss this screen."
)
}
}
diff --git a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/SwipeToDismissDemoWithState.kt b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/SwipeToDismissDemoWithState.kt
index 4496c21..7dd2880 100644
--- a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/SwipeToDismissDemoWithState.kt
+++ b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/SwipeToDismissDemoWithState.kt
@@ -40,9 +40,7 @@
import androidx.wear.compose.material.ToggleButton
@Composable
-fun SwipeToDismissBoxWithState(
- quit: () -> Unit
-) {
+fun SwipeToDismissBoxWithState(quit: () -> Unit) {
// This sample flips between 2 stateful composables when you swipe:
// 1) ToggleScreen - displays a ToggleButton that alternates between On/Off
// 2) CounterScreen - displays a counter Button that increments when clicked
diff --git a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/SwipeToRevealDemo.kt b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/SwipeToRevealDemo.kt
index aaa66be..1129c2d 100644
--- a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/SwipeToRevealDemo.kt
+++ b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/SwipeToRevealDemo.kt
@@ -74,23 +74,17 @@
swipeToDismissBoxState: SwipeToDismissBoxState,
includeSecondaryAction: Boolean
) {
- val expandableStateMapping = rememberExpandableStateMapping<Int>(
- initiallyExpanded = { true }
- )
+ val expandableStateMapping = rememberExpandableStateMapping<Int>(initiallyExpanded = { true })
var itemCount by remember { mutableIntStateOf(3) }
- ScalingLazyColumn(
- modifier = Modifier.fillMaxSize()
- ) {
+ ScalingLazyColumn(modifier = Modifier.fillMaxSize()) {
item {
Text(text = "Swipe To Reveal Chips - Undo")
Spacer(Modifier.size(15.dp))
}
repeat(itemCount) {
val currentState = expandableStateMapping.getOrPutNew(it)
- expandableItem(
- state = currentState
- ) { expanded ->
+ expandableItem(state = currentState) { expanded ->
var undoActionEnabled by remember { mutableStateOf(true) }
val revealState = rememberRevealState()
val coroutineScope = rememberCoroutineScope()
@@ -167,46 +161,42 @@
onUndoDuplicate: (() -> Unit)?
) {
SwipeToRevealChip(
- modifier = modifier.semantics {
- customActions = listOfNotNull(
- CustomAccessibilityAction("Delete") {
- onDeleteAction()
- true
- },
- onDuplicateAction?.let {
- CustomAccessibilityAction("Duplicate") {
- onDuplicateAction()
+ modifier =
+ modifier.semantics {
+ customActions =
+ listOfNotNull(
+ CustomAccessibilityAction("Delete") {
+ onDeleteAction()
true
+ },
+ onDuplicateAction?.let {
+ CustomAccessibilityAction("Duplicate") {
+ onDuplicateAction()
+ true
+ }
}
- }
- )
+ )
},
revealState = revealState,
onFullSwipe = onDeleteAction,
primaryAction = {
SwipeToRevealPrimaryAction(
revealState = revealState,
- icon = {
- Icon(
- SwipeToRevealDefaults.Delete,
- contentDescription = "Delete"
- )
- },
+ icon = { Icon(SwipeToRevealDefaults.Delete, contentDescription = "Delete") },
label = { Text(text = "Delete") },
onClick = onDeleteAction,
)
},
- secondaryAction = onDuplicateAction?.let {
- {
- SwipeToRevealSecondaryAction(
- revealState = revealState,
- content = {
- Icon(Icons.Outlined.Add, contentDescription = "Duplicate")
- },
- onClick = onDuplicateAction
- )
- }
- },
+ secondaryAction =
+ onDuplicateAction?.let {
+ {
+ SwipeToRevealSecondaryAction(
+ revealState = revealState,
+ content = { Icon(Icons.Outlined.Add, contentDescription = "Duplicate") },
+ onClick = onDuplicateAction
+ )
+ }
+ },
undoPrimaryAction = {
SwipeToRevealUndoAction(
revealState = revealState,
@@ -214,41 +204,37 @@
onClick = onUndoDelete
)
},
- undoSecondaryAction = onUndoDuplicate?.let {
- {
- SwipeToRevealUndoAction(
- revealState = revealState,
- label = { Text("Undo Duplicate") },
- onClick = onUndoDuplicate
- )
+ undoSecondaryAction =
+ onUndoDuplicate?.let {
+ {
+ SwipeToRevealUndoAction(
+ revealState = revealState,
+ label = { Text("Undo Duplicate") },
+ onClick = onUndoDuplicate
+ )
+ }
}
- }
) {
Chip(
onClick = { /*TODO*/ },
colors = ChipDefaults.secondaryChipColors(),
modifier = Modifier.fillMaxWidth(),
- label = {
- Text(text)
- }
+ label = { Text(text) }
)
}
}
@Composable
fun SwipeToRevealCards(swipeToDismissBoxState: SwipeToDismissBoxState) {
- val emailMap = mutableMapOf(
- "Android In" to
- "Please add Swipe to dismiss to the demo.",
- "Google Bangalore" to
- "Hey everyone, We are pleased to inform that we are starting a new batch.",
- "Google India" to
- "Hi Googlers, Please be prepared for the new changes."
- )
+ val emailMap =
+ mutableMapOf(
+ "Android In" to "Please add Swipe to dismiss to the demo.",
+ "Google Bangalore" to
+ "Hey everyone, We are pleased to inform that we are starting a new batch.",
+ "Google India" to "Hi Googlers, Please be prepared for the new changes."
+ )
val expandableStates = List(emailMap.size) { rememberExpandableState(initiallyExpanded = true) }
- ScalingLazyColumn(
- modifier = Modifier.fillMaxSize()
- ) {
+ ScalingLazyColumn(modifier = Modifier.fillMaxSize()) {
item {
Text(text = "Swipe To Reveal Cards")
Spacer(Modifier.size(10.dp))
@@ -257,9 +243,7 @@
val currentState = expandableStates[it]
val currentFrom = emailMap.keys.elementAt(it)
val currentEmail = emailMap.values.elementAt(it)
- expandableItem(
- state = currentState
- ) { expanded ->
+ expandableItem(state = currentState) { expanded ->
if (expanded) {
SwipeToRevealCardExpandable(
expandableState = currentState,
@@ -304,36 +288,28 @@
onDismiss = { showDialog = false },
)
SwipeToRevealCard(
- modifier = modifier.semantics {
- customActions = listOf(
- CustomAccessibilityAction("Delete") {
- coroutineScope.launch {
- revealState.animateTo(RevealValue.Revealed)
- }
- true
- },
- CustomAccessibilityAction("More Options") {
- showDialog = true
- true
- }
- )
- },
+ modifier =
+ modifier.semantics {
+ customActions =
+ listOf(
+ CustomAccessibilityAction("Delete") {
+ coroutineScope.launch { revealState.animateTo(RevealValue.Revealed) }
+ true
+ },
+ CustomAccessibilityAction("More Options") {
+ showDialog = true
+ true
+ }
+ )
+ },
revealState = revealState,
- onFullSwipe = {
- coroutineScope.launch {
- revealState.animateTo(RevealValue.Revealed)
- }
- },
+ onFullSwipe = { coroutineScope.launch { revealState.animateTo(RevealValue.Revealed) } },
primaryAction = {
SwipeToRevealPrimaryAction(
revealState = revealState,
icon = { Icon(SwipeToRevealDefaults.Delete, contentDescription = "Delete") },
label = { Text(text = "Delete") },
- onClick = {
- coroutineScope.launch {
- revealState.animateTo(RevealValue.Revealed)
- }
- }
+ onClick = { coroutineScope.launch { revealState.animateTo(RevealValue.Revealed) } }
)
},
secondaryAction = {
@@ -376,11 +352,7 @@
time = { Text("now") },
title = { Text("From: $from", maxLines = 1, overflow = TextOverflow.Ellipsis) }
) {
- Text(
- text = email,
- maxLines = 2,
- overflow = TextOverflow.Ellipsis
- )
+ Text(text = email, maxLines = 2, overflow = TextOverflow.Ellipsis)
}
}
}
@@ -395,9 +367,7 @@
showDialog = showDialog,
onDismissRequest = onDismiss,
) {
- Alert(
- title = { Text("Other options", textAlign = TextAlign.Center) }
- ) {
+ Alert(title = { Text("Other options", textAlign = TextAlign.Center) }) {
repeat(3) {
item {
Chip(
diff --git a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/ThemeDemo.kt b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/ThemeDemo.kt
index 0306e38..89f3bde 100644
--- a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/ThemeDemo.kt
+++ b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/ThemeDemo.kt
@@ -36,52 +36,24 @@
@Composable
fun ThemeFonts() {
ScalingLazyColumn {
- item {
- ThemeFontRow(style = MaterialTheme.typography.display1, description = "display1")
- }
- item {
- ThemeFontRow(style = MaterialTheme.typography.display2, description = "display2")
- }
- item {
- ThemeFontRow(style = MaterialTheme.typography.display3, description = "display3")
- }
- item {
- ThemeFontRow(style = MaterialTheme.typography.title1, description = "title1")
- }
- item {
- ThemeFontRow(style = MaterialTheme.typography.title2, description = "title2")
- }
- item {
- ThemeFontRow(style = MaterialTheme.typography.title3, description = "title3")
- }
- item {
- ThemeFontRow(style = MaterialTheme.typography.body1, description = "body1")
- }
- item {
- ThemeFontRow(style = MaterialTheme.typography.body2, description = "body2")
- }
- item {
- ThemeFontRow(style = MaterialTheme.typography.button, description = "button")
- }
- item {
- ThemeFontRow(style = MaterialTheme.typography.caption1, description = "caption1")
- }
- item {
- ThemeFontRow(style = MaterialTheme.typography.caption2, description = "caption2")
- }
- item {
- ThemeFontRow(style = MaterialTheme.typography.caption3, description = "caption3")
- }
+ item { ThemeFontRow(style = MaterialTheme.typography.display1, description = "display1") }
+ item { ThemeFontRow(style = MaterialTheme.typography.display2, description = "display2") }
+ item { ThemeFontRow(style = MaterialTheme.typography.display3, description = "display3") }
+ item { ThemeFontRow(style = MaterialTheme.typography.title1, description = "title1") }
+ item { ThemeFontRow(style = MaterialTheme.typography.title2, description = "title2") }
+ item { ThemeFontRow(style = MaterialTheme.typography.title3, description = "title3") }
+ item { ThemeFontRow(style = MaterialTheme.typography.body1, description = "body1") }
+ item { ThemeFontRow(style = MaterialTheme.typography.body2, description = "body2") }
+ item { ThemeFontRow(style = MaterialTheme.typography.button, description = "button") }
+ item { ThemeFontRow(style = MaterialTheme.typography.caption1, description = "caption1") }
+ item { ThemeFontRow(style = MaterialTheme.typography.caption2, description = "caption2") }
+ item { ThemeFontRow(style = MaterialTheme.typography.caption3, description = "caption3") }
}
}
@Composable
fun ThemeFontRow(style: TextStyle, description: String) {
- Row(
- modifier = Modifier
- .fillMaxWidth()
- .wrapContentWidth(align = Alignment.CenterHorizontally)
- ) {
+ Row(modifier = Modifier.fillMaxWidth().wrapContentWidth(align = Alignment.CenterHorizontally)) {
Text(text = description, style = style)
}
}
@@ -164,12 +136,12 @@
foregroundColorName: String
) {
Row(
- modifier = Modifier
- .padding(vertical = 2.dp)
- .background(color = backgroundColor)
- .fillMaxWidth()
- .wrapContentWidth(align = Alignment.CenterHorizontally)
- .border(width = 1.dp, color = MaterialTheme.colors.onBackground)
+ modifier =
+ Modifier.padding(vertical = 2.dp)
+ .background(color = backgroundColor)
+ .fillMaxWidth()
+ .wrapContentWidth(align = Alignment.CenterHorizontally)
+ .border(width = 1.dp, color = MaterialTheme.colors.onBackground)
) {
Text(
text = "foreground=$foregroundColorName background=$backgroundColorName",
diff --git a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/TimeTextDemo.kt b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/TimeTextDemo.kt
index bac9f497..8c784ec 100644
--- a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/TimeTextDemo.kt
+++ b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/TimeTextDemo.kt
@@ -43,17 +43,9 @@
fun TimeTextWithLeadingText() {
val textStyle = TimeTextDefaults.timeTextStyle(color = AlternatePrimaryColor1)
TimeText(
- startLinearContent = {
- Text(
- text = "ETA 12:48",
- style = textStyle
- )
- },
+ startLinearContent = { Text(text = "ETA 12:48", style = textStyle) },
startCurvedContent = {
- basicCurvedText(
- text = "ETA 12:48",
- style = CurvedTextStyle(textStyle)
- )
+ basicCurvedText(text = "ETA 12:48", style = CurvedTextStyle(textStyle))
}
)
}
@@ -63,44 +55,36 @@
val textStyle = TimeTextDefaults.timeTextStyle(color = AlternatePrimaryColor1)
val radiusCoeff = 0.8f
val linearGradientHeight = 30.dp
- val timeTextModifier = if (LocalConfiguration.current.isScreenRound) {
- Modifier.drawBehind {
- drawRect(
- Brush
- .radialGradient(
+ val timeTextModifier =
+ if (LocalConfiguration.current.isScreenRound) {
+ Modifier.drawBehind {
+ drawRect(
+ Brush.radialGradient(
0.8f to Color.Transparent,
1.0f to Color.Black,
center = Offset(size.width / 2, size.height * radiusCoeff),
radius = size.height * radiusCoeff
)
- )
- }
- } else {
- Modifier.drawBehind {
- drawRect(
- Brush.linearGradient(
- colors = listOf(Color.Black, Color.Transparent),
- start = Offset(x = size.width / 2, y = 0f),
- end = Offset(x = size.width / 2, y = linearGradientHeight.toPx())
)
- )
+ }
+ } else {
+ Modifier.drawBehind {
+ drawRect(
+ Brush.linearGradient(
+ colors = listOf(Color.Black, Color.Transparent),
+ start = Offset(x = size.width / 2, y = 0f),
+ end = Offset(x = size.width / 2, y = linearGradientHeight.toPx())
+ )
+ )
+ }
}
- }
Box(modifier = Modifier.background(Color.Red)) {
TimeText(
modifier = timeTextModifier,
- startLinearContent = {
- Text(
- text = "ETA 12:48",
- style = textStyle
- )
- },
+ startLinearContent = { Text(text = "ETA 12:48", style = textStyle) },
startCurvedContent = {
- basicCurvedText(
- text = "ETA 12:48",
- style = CurvedTextStyle(textStyle)
- )
+ basicCurvedText(text = "ETA 12:48", style = CurvedTextStyle(textStyle))
}
)
}
@@ -109,8 +93,9 @@
@Composable
fun TimeTextWithLocalisedFormat() {
TimeText(
- timeSource = TimeTextDefaults.timeSource(
- DateFormat.getBestDateTimePattern(Locale.getDefault(), "yyyy.MM.dd HH:mm")
- )
+ timeSource =
+ TimeTextDefaults.timeSource(
+ DateFormat.getBestDateTimePattern(Locale.getDefault(), "yyyy.MM.dd HH:mm")
+ )
)
}
diff --git a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/ToggleButtonDemo.kt b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/ToggleButtonDemo.kt
index 0802699..a42f5c5 100644
--- a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/ToggleButtonDemo.kt
+++ b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/ToggleButtonDemo.kt
@@ -46,28 +46,24 @@
var singularButton3Enabled by remember { mutableStateOf(true) }
Column(
- modifier = Modifier.fillMaxSize(), verticalArrangement = Arrangement.Center,
+ modifier = Modifier.fillMaxSize(),
+ verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Row(
horizontalArrangement = Arrangement.Center,
verticalAlignment = Alignment.CenterVertically
) {
- Text(
- text = "Singular",
- style = MaterialTheme.typography.body2,
- color = Color.White
- )
+ Text(text = "Singular", style = MaterialTheme.typography.body2, color = Color.White)
Spacer(modifier = Modifier.size(4.dp))
ToggleButton(
checked = singularButton1Enabled,
- onCheckedChange = {
- singularButton1Enabled = it
- },
+ onCheckedChange = { singularButton1Enabled = it },
enabled = toggleButtonsEnabled,
- colors = ToggleButtonDefaults.toggleButtonColors(
- checkedBackgroundColor = AlternatePrimaryColor2,
- ),
+ colors =
+ ToggleButtonDefaults.toggleButtonColors(
+ checkedBackgroundColor = AlternatePrimaryColor2,
+ ),
modifier = Modifier.size(ButtonDefaults.SmallButtonSize)
) {
if (singularButton1Enabled) {
@@ -79,13 +75,12 @@
Spacer(modifier = Modifier.size(4.dp))
ToggleButton(
checked = singularButton2Enabled,
- onCheckedChange = {
- singularButton2Enabled = it
- },
+ onCheckedChange = { singularButton2Enabled = it },
enabled = toggleButtonsEnabled,
- colors = ToggleButtonDefaults.toggleButtonColors(
- checkedBackgroundColor = AlternatePrimaryColor3,
- ),
+ colors =
+ ToggleButtonDefaults.toggleButtonColors(
+ checkedBackgroundColor = AlternatePrimaryColor3,
+ ),
modifier = Modifier.size(ButtonDefaults.SmallButtonSize),
) {
DemoIcon(R.drawable.ic_airplanemode_active_24px)
@@ -93,13 +88,12 @@
Spacer(modifier = Modifier.size(4.dp))
ToggleButton(
checked = singularButton3Enabled,
- onCheckedChange = {
- singularButton3Enabled = it
- },
+ onCheckedChange = { singularButton3Enabled = it },
enabled = toggleButtonsEnabled,
- colors = ToggleButtonDefaults.toggleButtonColors(
- checkedBackgroundColor = AlternatePrimaryColor3
- ),
+ colors =
+ ToggleButtonDefaults.toggleButtonColors(
+ checkedBackgroundColor = AlternatePrimaryColor3
+ ),
modifier = Modifier,
shape = CutCornerShape(4.dp)
) {
@@ -119,9 +113,7 @@
Spacer(modifier = Modifier.size(4.dp))
ToggleButton(
checked = toggleButtonsEnabled,
- onCheckedChange = {
- toggleButtonsEnabled = it
- },
+ onCheckedChange = { toggleButtonsEnabled = it },
modifier = Modifier.size(ButtonDefaults.SmallButtonSize),
) {
DemoIcon(R.drawable.ic_check_24px)
diff --git a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/ToggleChipDemo.kt b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/ToggleChipDemo.kt
index b241a0c..5e31198 100644
--- a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/ToggleChipDemo.kt
+++ b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/ToggleChipDemo.kt
@@ -108,12 +108,13 @@
checked = checkBoxIconCustomColorChecked,
toggleControl = {
Checkbox(
- colors = CheckboxDefaults.colors(
- checkedBoxColor = MaterialTheme.colors.primary,
- checkedCheckmarkColor = Color.Green,
- uncheckedBoxColor = Color.Magenta,
- uncheckedCheckmarkColor = Color.Red,
- ),
+ colors =
+ CheckboxDefaults.colors(
+ checkedBoxColor = MaterialTheme.colors.primary,
+ checkedCheckmarkColor = Color.Green,
+ uncheckedBoxColor = Color.Magenta,
+ uncheckedCheckmarkColor = Color.Red,
+ ),
checked = checkBoxIconCustomColorChecked,
enabled = enabled,
)
@@ -147,12 +148,13 @@
checked = switchIconCustomColorChecked,
toggleControl = {
Switch(
- colors = SwitchDefaults.colors(
- checkedThumbColor = MaterialTheme.colors.primary,
- checkedTrackColor = Color.Green,
- uncheckedThumbColor = Color.Red,
- uncheckedTrackColor = Color.Magenta,
- ),
+ colors =
+ SwitchDefaults.colors(
+ checkedThumbColor = MaterialTheme.colors.primary,
+ checkedTrackColor = Color.Green,
+ uncheckedThumbColor = Color.Red,
+ uncheckedTrackColor = Color.Magenta,
+ ),
checked = switchIconCustomColorChecked,
enabled = enabled,
)
@@ -165,9 +167,7 @@
item {
CompositionLocalProvider(LocalLayoutDirection provides layoutDirection) {
ToggleChip(
- label = {
- Text("Switch", maxLines = 1, overflow = TextOverflow.Ellipsis)
- },
+ label = { Text("Switch", maxLines = 1, overflow = TextOverflow.Ellipsis) },
secondaryLabel = {
Text("With secondary label", maxLines = 1, overflow = TextOverflow.Ellipsis)
},
@@ -175,16 +175,17 @@
// For Switch toggle controls the Wear Material UX guidance is to set the
// unselected toggle control color to
// ToggleChipDefaults.switchUncheckedIconColor() rather than the default.
- colors = ToggleChipDefaults.toggleChipColors(
- uncheckedToggleControlColor = ToggleChipDefaults
- .SwitchUncheckedIconColor
- ),
+ colors =
+ ToggleChipDefaults.toggleChipColors(
+ uncheckedToggleControlColor =
+ ToggleChipDefaults.SwitchUncheckedIconColor
+ ),
toggleControl = {
Switch(
checked = switchIconWithSecondaryChecked,
enabled = enabled,
)
- },
+ },
onCheckedChange = { switchIconWithSecondaryChecked = it },
appIcon = { DemoIcon(R.drawable.ic_airplanemode_active_24px) },
enabled = enabled,
@@ -202,10 +203,11 @@
// For Switch toggle controls the Wear Material UX guidance is to set the
// unselected toggle control color to
// ToggleChipDefaults.switchUncheckedIconColor() rather than the default.
- colors = ToggleChipDefaults.toggleChipColors(
- uncheckedToggleControlColor = ToggleChipDefaults
- .SwitchUncheckedIconColor
- ),
+ colors =
+ ToggleChipDefaults.toggleChipColors(
+ uncheckedToggleControlColor =
+ ToggleChipDefaults.SwitchUncheckedIconColor
+ ),
toggleControl = {
Switch(
checked = switchIconWithIconChecked,
@@ -214,8 +216,8 @@
},
onCheckedChange = { switchIconWithIconChecked = it },
appIcon = {
- if (switchIconWithIconChecked) DemoIcon(R.drawable.ic_volume_up_24px) else
- DemoIcon(R.drawable.ic_volume_off_24px)
+ if (switchIconWithIconChecked) DemoIcon(R.drawable.ic_volume_up_24px)
+ else DemoIcon(R.drawable.ic_volume_off_24px)
},
enabled = enabled,
)
@@ -242,10 +244,11 @@
// For Switch toggle controls the Wear Material UX guidance is to set the
// unselected toggle control color to
// ToggleChipDefaults.switchUncheckedIconColor() rather than the default.
- colors = ToggleChipDefaults.toggleChipColors(
- uncheckedToggleControlColor = ToggleChipDefaults
- .SwitchUncheckedIconColor
- ),
+ colors =
+ ToggleChipDefaults.toggleChipColors(
+ uncheckedToggleControlColor =
+ ToggleChipDefaults.SwitchUncheckedIconColor
+ ),
toggleControl = {
Switch(
checked = switchIconWithIconChecked,
@@ -277,15 +280,18 @@
// For Switch toggle controls the Wear Material UX guidance is to set the
// unselected toggle control color to
// ToggleChipDefaults.switchUncheckedIconColor() rather than the default.
- colors = ToggleChipDefaults.splitToggleChipColors(
- uncheckedToggleControlColor = ToggleChipDefaults
- .SwitchUncheckedIconColor
- ),
- ) { Switch(
- modifier = Modifier.semantics { contentDescription = "Primary Label" },
- checked = splitWithSwitchIconChecked,
- enabled = enabled,
- ) }
+ colors =
+ ToggleChipDefaults.splitToggleChipColors(
+ uncheckedToggleControlColor =
+ ToggleChipDefaults.SwitchUncheckedIconColor
+ ),
+ ) {
+ Switch(
+ modifier = Modifier.semantics { contentDescription = "Primary Label" },
+ checked = splitWithSwitchIconChecked,
+ enabled = enabled,
+ )
+ }
}
}
item {
@@ -315,15 +321,18 @@
// For Switch toggle controls the Wear Material UX guidance is to set the
// unselected toggle control color to
// ToggleChipDefaults.switchUncheckedIconColor() rather than the default.
- colors = ToggleChipDefaults.splitToggleChipColors(
- uncheckedToggleControlColor = ToggleChipDefaults
- .SwitchUncheckedIconColor
- ),
- ) { Switch(
- modifier = Modifier.semantics { contentDescription = "Primary Label" },
- checked = splitWithSwitchIconChecked,
- enabled = enabled,
- ) }
+ colors =
+ ToggleChipDefaults.splitToggleChipColors(
+ uncheckedToggleControlColor =
+ ToggleChipDefaults.SwitchUncheckedIconColor
+ ),
+ ) {
+ Switch(
+ modifier = Modifier.semantics { contentDescription = "Primary Label" },
+ checked = splitWithSwitchIconChecked,
+ enabled = enabled,
+ )
+ }
}
}
item {
@@ -331,16 +340,15 @@
ToggleChip(
checked = enabled,
onCheckedChange = { enabled = it },
- label = {
- Text("Chips enabled")
- },
+ label = { Text("Chips enabled") },
// For Switch toggle controls the Wear Material UX guidance is to set the
// unselected toggle control color to
// ToggleChipDefaults.switchUncheckedIconColor() rather than the default.
- colors = ToggleChipDefaults.toggleChipColors(
- uncheckedToggleControlColor = ToggleChipDefaults
- .SwitchUncheckedIconColor
- ),
+ colors =
+ ToggleChipDefaults.toggleChipColors(
+ uncheckedToggleControlColor =
+ ToggleChipDefaults.SwitchUncheckedIconColor
+ ),
toggleControl = {
Switch(
checked = enabled,
@@ -365,26 +373,14 @@
val context = LocalContext.current
SplitToggleChip(
- label = {
- Text(
- primaryLabel,
- maxLines = 3,
- overflow = TextOverflow.Ellipsis
- )
+ label = { Text(primaryLabel, maxLines = 3, overflow = TextOverflow.Ellipsis) },
+ secondaryLabel = {
+ secondaryLabel?.let { Text(it, maxLines = 2, overflow = TextOverflow.Ellipsis) }
},
- secondaryLabel = { secondaryLabel?.let {
- Text(
- it,
- maxLines = 2,
- overflow = TextOverflow.Ellipsis
- )
- } },
checked = checked,
toggleControl = content,
onCheckedChange = onCheckedChange,
- onClick = {
- Toast.makeText(context, "Text was clicked", Toast.LENGTH_SHORT).show()
- },
+ onClick = { Toast.makeText(context, "Text was clicked", Toast.LENGTH_SHORT).show() },
colors = colors,
enabled = enabled,
)
diff --git a/wear/compose/integration-tests/macrobenchmark-target/src/main/java/androidx/wear/compose/integration/macrobenchmark/target/BaselineActivity.kt b/wear/compose/integration-tests/macrobenchmark-target/src/main/java/androidx/wear/compose/integration/macrobenchmark/target/BaselineActivity.kt
index 8662ed5..dd87e59 100644
--- a/wear/compose/integration-tests/macrobenchmark-target/src/main/java/androidx/wear/compose/integration/macrobenchmark/target/BaselineActivity.kt
+++ b/wear/compose/integration-tests/macrobenchmark-target/src/main/java/androidx/wear/compose/integration/macrobenchmark/target/BaselineActivity.kt
@@ -161,9 +161,7 @@
MaterialTheme {
Scaffold(
timeText = {
- TimeText(
- modifier = Modifier.scrollAway(scrollState = scrollState)
- )
+ TimeText(modifier = Modifier.scrollAway(scrollState = scrollState))
},
positionIndicator = { PositionIndicator(scrollState = scrollState) },
vignette = { Vignette(vignettePosition = VignettePosition.TopAndBottom) },
@@ -171,14 +169,13 @@
SwipeDismissableNavHost(
navController = navController,
startDestination = START_INDEX,
- modifier = Modifier
- .background(MaterialTheme.colors.background)
- .semantics { contentDescription = SWIPE_DISMISS }
+ modifier =
+ Modifier.background(MaterialTheme.colors.background).semantics {
+ contentDescription = SWIPE_DISMISS
+ }
) {
composable(START_INDEX) { StartIndex(navController, scrollState) }
- composable(DIALOGS) {
- Dialogs(navController)
- }
+ composable(DIALOGS) { Dialogs(navController) }
composable(ALERT_DIALOG) {
Alert(
title = { Text("Alert") },
@@ -232,11 +229,11 @@
Box {
CurvedTexts()
Column(
- modifier = Modifier
- .fillMaxSize()
- .verticalScroll(state = scrollState)
- .padding(vertical = 32.dp)
- .semantics { contentDescription = CONTENT_DESCRIPTION },
+ modifier =
+ Modifier.fillMaxSize()
+ .verticalScroll(state = scrollState)
+ .padding(vertical = 32.dp)
+ .semantics { contentDescription = CONTENT_DESCRIPTION },
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
@@ -249,15 +246,18 @@
Spacer(modifier = Modifier.height(4.dp))
Row(horizontalArrangement = Arrangement.spacedBy(4.dp)) {
Widget(navController, EXPANDABLES, "E", EXPANDABLES)
- Widget(navController, HIERARCHICAL_FOCUS_COORDINATOR, "HF",
- HIERARCHICAL_FOCUS_COORDINATOR)
+ Widget(
+ navController,
+ HIERARCHICAL_FOCUS_COORDINATOR,
+ "HF",
+ HIERARCHICAL_FOCUS_COORDINATOR
+ )
Widget(navController, PICKER, "PI", PICKER)
Widget(navController, PLACEHOLDERS, "PL", PLACEHOLDERS)
}
Spacer(modifier = Modifier.height(4.dp))
Row(horizontalArrangement = Arrangement.spacedBy(4.dp)) {
- Widget(navController, PROGRESSINDICATORS,
- "PR", PROGRESSINDICATORS)
+ Widget(navController, PROGRESSINDICATORS, "PR", PROGRESSINDICATORS)
Widget(navController, SLIDER, "SL", SLIDER)
Widget(navController, STEPPER, "ST", STEPPER)
Widget(navController, SWIPE_TO_REVEAL, "SW", SWIPE_TO_REVEAL)
@@ -277,18 +277,14 @@
onClick = { navController.navigate(ALERT_DIALOG) },
colors = ChipDefaults.primaryChipColors(),
label = { Text(ALERT_DIALOG) },
- modifier = Modifier.semantics {
- contentDescription = ALERT_DIALOG
- },
+ modifier = Modifier.semantics { contentDescription = ALERT_DIALOG },
)
Spacer(Modifier.height(4.dp))
CompactChip(
onClick = { navController.navigate(CONFIRMATION_DIALOG) },
colors = ChipDefaults.primaryChipColors(),
label = { Text(CONFIRMATION_DIALOG) },
- modifier = Modifier.semantics {
- contentDescription = CONFIRMATION_DIALOG
- },
+ modifier = Modifier.semantics { contentDescription = CONFIRMATION_DIALOG },
)
}
}
@@ -310,9 +306,7 @@
OutlinedCompactButton(onClick = {}) { Text("OCB") }
}
Row(horizontalArrangement = Arrangement.spacedBy(4.dp)) {
- ToggleButton(
- checked = true,
- onCheckedChange = {}) { Text("TB") }
+ ToggleButton(checked = true, onCheckedChange = {}) { Text("TB") }
}
}
}
@@ -325,14 +319,10 @@
) {
ListHeader { Text("Cards") }
Card(onClick = {}) { Text("Card") }
- AppCard(onClick = {},
- appName = { Text("AppName") }, title = {},
- time = { Text("02:34") }) {
+ AppCard(onClick = {}, appName = { Text("AppName") }, title = {}, time = { Text("02:34") }) {
Text("AppCard")
}
- TitleCard(onClick = {}, title = { Text("Title") }) {
- Text("TitleCard")
- }
+ TitleCard(onClick = {}, title = { Text("Title") }) { Text("TitleCard") }
}
}
@@ -349,11 +339,7 @@
colors = ChipDefaults.primaryChipColors(),
label = { Text("C") }
)
- OutlinedChip(
- modifier = Modifier.height(32.dp),
- onClick = {},
- label = { Text("OC") }
- )
+ OutlinedChip(modifier = Modifier.height(32.dp), onClick = {}, label = { Text("OC") })
}
Row(horizontalArrangement = Arrangement.spacedBy(4.dp)) {
CompactChip(onClick = {}, label = { Text("CC") })
@@ -367,8 +353,7 @@
label = { Text("R") },
toggleControl = {
Icon(
- imageVector =
- ToggleChipDefaults.radioIcon(checked = radioState),
+ imageVector = ToggleChipDefaults.radioIcon(checked = radioState),
contentDescription = null
)
}
@@ -380,8 +365,7 @@
label = { Text("S") },
toggleControl = {
Icon(
- imageVector =
- ToggleChipDefaults.switchIcon(checked = switchState),
+ imageVector = ToggleChipDefaults.switchIcon(checked = switchState),
contentDescription = null
)
}
@@ -393,8 +377,7 @@
label = { Text("C") },
toggleControl = {
Icon(
- imageVector =
- ToggleChipDefaults.checkboxIcon(checked = checkboxState),
+ imageVector = ToggleChipDefaults.checkboxIcon(checked = checkboxState),
contentDescription = null
)
}
@@ -434,8 +417,7 @@
onClick = {},
toggleControl = {
Icon(
- imageVector =
- ToggleChipDefaults.radioIcon(checked = true),
+ imageVector = ToggleChipDefaults.radioIcon(checked = true),
contentDescription = null
)
}
@@ -458,12 +440,8 @@
val expandableItemsState = rememberExpandableState()
val expandableTextState = rememberExpandableState()
- ScalingLazyColumn(
- modifier = Modifier.fillMaxSize()
- ) {
- item {
- CompactChip(label = { Text("Expandables") }, onClick = {})
- }
+ ScalingLazyColumn(modifier = Modifier.fillMaxSize()) {
+ item { CompactChip(label = { Text("Expandables") }, onClick = {}) }
expandableItems(expandableItemsState, 2) { it ->
CompactChip(label = { Text("$it") }, onClick = {})
}
@@ -475,10 +453,11 @@
)
}
expandableItem(expandableTextState) { expanded ->
- Text("Some long text goes here " +
- "that will span across multiple lines and " +
- "we don't want to always show all of it " +
- "so we have an expand button",
+ Text(
+ "Some long text goes here " +
+ "that will span across multiple lines and " +
+ "we don't want to always show all of it " +
+ "so we have an expand button",
maxLines = if (expanded) 10 else 1
)
}
@@ -504,19 +483,19 @@
val focusRequester = rememberActiveFocusRequester()
Text(
text = "$ix",
- modifier = Modifier
- .weight(1f)
- .clickable { selected = ix }
- .onFocusChanged { focused = it.isFocused }
- .focusRequester(focusRequester)
- .focusable()
- .then(
- if (focused) {
- Modifier.border(BorderStroke(2.dp, Color.Red))
- } else {
- Modifier
- }
- )
+ modifier =
+ Modifier.weight(1f)
+ .clickable { selected = ix }
+ .onFocusChanged { focused = it.isFocused }
+ .focusRequester(focusRequester)
+ .focusable()
+ .then(
+ if (focused) {
+ Modifier.border(BorderStroke(2.dp, Color.Red))
+ } else {
+ Modifier
+ }
+ )
)
}
}
@@ -559,9 +538,7 @@
fun Placeholders() {
var labelText by remember { mutableStateOf("") }
var iconContent: @Composable () -> Unit = { Checkbox(true) }
- val chipPlaceholderState = rememberPlaceholderState {
- labelText.isNotEmpty()
- }
+ val chipPlaceholderState = rememberPlaceholderState { labelText.isNotEmpty() }
Chip(
onClick = { /* Do something */ },
@@ -571,27 +548,22 @@
text = labelText,
maxLines = 2,
overflow = TextOverflow.Ellipsis,
- modifier = Modifier
- .fillMaxWidth()
- .placeholder(chipPlaceholderState)
+ modifier = Modifier.fillMaxWidth().placeholder(chipPlaceholderState)
)
},
icon = {
Box(
- modifier = Modifier
- .size(ChipDefaults.IconSize)
- .placeholder(chipPlaceholderState),
+ modifier = Modifier.size(ChipDefaults.IconSize).placeholder(chipPlaceholderState),
) {
iconContent()
}
},
- colors = PlaceholderDefaults.placeholderChipColors(
- originalChipColors = ChipDefaults.primaryChipColors(),
- placeholderState = chipPlaceholderState
- ),
- modifier = Modifier
- .fillMaxWidth()
- .placeholderShimmer(chipPlaceholderState)
+ colors =
+ PlaceholderDefaults.placeholderChipColors(
+ originalChipColors = ChipDefaults.primaryChipColors(),
+ placeholderState = chipPlaceholderState
+ ),
+ modifier = Modifier.fillMaxWidth().placeholderShimmer(chipPlaceholderState)
)
LaunchedEffect(Unit) {
delay(50)
@@ -600,9 +572,7 @@
labelText = "A label"
}
if (!chipPlaceholderState.isShowContent) {
- LaunchedEffect(chipPlaceholderState) {
- chipPlaceholderState.startPlaceholderAnimation()
- }
+ LaunchedEffect(chipPlaceholderState) { chipPlaceholderState.startPlaceholderAnimation() }
}
}
@@ -618,22 +588,14 @@
onClick = { navController.navigate(PROGRESS_INDICATOR) },
colors = ChipDefaults.primaryChipColors(),
label = { Text(PROGRESS_INDICATOR) },
- modifier = Modifier.semantics {
- contentDescription = PROGRESS_INDICATOR
- },
+ modifier = Modifier.semantics { contentDescription = PROGRESS_INDICATOR },
)
Spacer(Modifier.height(4.dp))
CompactChip(
- onClick = {
- navController.navigate(
- PROGRESS_INDICATOR_INDETERMINATE
- )
- },
+ onClick = { navController.navigate(PROGRESS_INDICATOR_INDETERMINATE) },
colors = ChipDefaults.primaryChipColors(),
label = { Text(PROGRESS_INDICATOR_INDETERMINATE) },
- modifier = Modifier.semantics {
- contentDescription = PROGRESS_INDICATOR_INDETERMINATE
- },
+ modifier = Modifier.semantics { contentDescription = PROGRESS_INDICATOR_INDETERMINATE },
)
}
}
@@ -649,18 +611,8 @@
InlineSlider(
value = value,
onValueChange = { value = it },
- increaseIcon = {
- Icon(
- InlineSliderDefaults.Increase,
- "Increase"
- )
- },
- decreaseIcon = {
- Icon(
- InlineSliderDefaults.Decrease,
- "Decrease"
- )
- },
+ increaseIcon = { Icon(InlineSliderDefaults.Increase, "Increase") },
+ decreaseIcon = { Icon(InlineSliderDefaults.Decrease, "Decrease") },
valueRange = 3f..6f,
steps = 5,
segmented = false
@@ -678,7 +630,9 @@
decreaseIcon = { Icon(StepperDefaults.Decrease, "Decrease") },
valueRange = 1f..4f,
steps = 7
- ) { Text("Value: $value") }
+ ) {
+ Text("Value: $value")
+ }
}
@OptIn(ExperimentalWearFoundationApi::class)
@@ -689,9 +643,7 @@
state = state,
primaryAction = {
Box(
- modifier = Modifier
- .fillMaxSize()
- .clickable { /* Add the primary action */ },
+ modifier = Modifier.fillMaxSize().clickable { /* Add the primary action */ },
) {
if (abs(state.offset) > revealOffset) {
Spacer(Modifier.size(5.dp))
@@ -723,17 +675,11 @@
CurvedLayout(anchor = 235f) {
basicCurvedText(
"Basic",
- CurvedTextStyle(
- fontSize = 16.sp,
- color = Color.White,
- background = background
- ),
+ CurvedTextStyle(fontSize = 16.sp, color = Color.White, background = background),
modifier = CurvedModifier.padding(2.dp)
)
}
- CurvedLayout(anchor = 310f) {
- curvedText(text = "Curved")
- }
+ CurvedLayout(anchor = 310f) { curvedText(text = "Curved") }
}
@Composable
diff --git a/wear/compose/integration-tests/macrobenchmark-target/src/main/java/androidx/wear/compose/integration/macrobenchmark/target/PositionIndicatorActivity.kt b/wear/compose/integration-tests/macrobenchmark-target/src/main/java/androidx/wear/compose/integration/macrobenchmark/target/PositionIndicatorActivity.kt
index 91720b1..045431b 100644
--- a/wear/compose/integration-tests/macrobenchmark-target/src/main/java/androidx/wear/compose/integration/macrobenchmark/target/PositionIndicatorActivity.kt
+++ b/wear/compose/integration-tests/macrobenchmark-target/src/main/java/androidx/wear/compose/integration/macrobenchmark/target/PositionIndicatorActivity.kt
@@ -45,100 +45,84 @@
super.onCreate(savedInstanceState)
setContent {
- val fraction = remember {
- mutableFloatStateOf(0f)
- }
- val sizeFraction = remember {
- mutableFloatStateOf(.25f)
- }
+ val fraction = remember { mutableFloatStateOf(0f) }
+ val sizeFraction = remember { mutableFloatStateOf(.25f) }
- val visibility = remember {
- mutableStateOf(PositionIndicatorVisibility.Show)
- }
+ val visibility = remember { mutableStateOf(PositionIndicatorVisibility.Show) }
val pIState = remember { CustomState(fraction, sizeFraction, visibility) }
- Scaffold(modifier = Modifier.fillMaxSize(), positionIndicator = {
- PositionIndicator(
- state = pIState,
- indicatorHeight = 50.dp,
- indicatorWidth = 4.dp,
- paddingHorizontal = 5.dp
- )
- }) {
+ Scaffold(
+ modifier = Modifier.fillMaxSize(),
+ positionIndicator = {
+ PositionIndicator(
+ state = pIState,
+ indicatorHeight = 50.dp,
+ indicatorWidth = 4.dp,
+ paddingHorizontal = 5.dp
+ )
+ }
+ ) {
Column(
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
- Box(modifier = Modifier
- .size(30.dp)
- .clickable {
- visibility.value = when (visibility.value) {
- PositionIndicatorVisibility.Show ->
- PositionIndicatorVisibility.AutoHide
-
- PositionIndicatorVisibility.AutoHide ->
- PositionIndicatorVisibility.Hide
-
- PositionIndicatorVisibility.Hide ->
- PositionIndicatorVisibility.Show
-
- else -> throw IllegalArgumentException("Invalid visibility type")
- }
- }
- .semantics {
- contentDescription = CHANGE_VISIBILITY
- }
+ Box(
+ modifier =
+ Modifier.size(30.dp)
+ .clickable {
+ visibility.value =
+ when (visibility.value) {
+ PositionIndicatorVisibility.Show ->
+ PositionIndicatorVisibility.AutoHide
+ PositionIndicatorVisibility.AutoHide ->
+ PositionIndicatorVisibility.Hide
+ PositionIndicatorVisibility.Hide ->
+ PositionIndicatorVisibility.Show
+ else ->
+ throw IllegalArgumentException(
+ "Invalid visibility type"
+ )
+ }
+ }
+ .semantics { contentDescription = CHANGE_VISIBILITY }
)
- Box(modifier = Modifier
- .size(30.dp)
- .clickable {
- visibility.value = PositionIndicatorVisibility.Hide
- }
- .semantics {
- contentDescription = CHANGE_VISIBILITY_HIDE
- }
+ Box(
+ modifier =
+ Modifier.size(30.dp)
+ .clickable { visibility.value = PositionIndicatorVisibility.Hide }
+ .semantics { contentDescription = CHANGE_VISIBILITY_HIDE }
)
- Box(modifier = Modifier
- .size(30.dp)
- .clickable {
- visibility.value = PositionIndicatorVisibility.Show
- }
- .semantics {
- contentDescription = CHANGE_VISIBILITY_SHOW
- }
+ Box(
+ modifier =
+ Modifier.size(30.dp)
+ .clickable { visibility.value = PositionIndicatorVisibility.Show }
+ .semantics { contentDescription = CHANGE_VISIBILITY_SHOW }
)
- Box(modifier = Modifier
- .size(30.dp)
- .clickable {
- visibility.value = PositionIndicatorVisibility.AutoHide
- }
- .semantics {
- contentDescription = CHANGE_VISIBILITY_AUTO_HIDE
- }
+ Box(
+ modifier =
+ Modifier.size(30.dp)
+ .clickable {
+ visibility.value = PositionIndicatorVisibility.AutoHide
+ }
+ .semantics { contentDescription = CHANGE_VISIBILITY_AUTO_HIDE }
)
- Box(modifier = Modifier
- .size(30.dp)
- .clickable {
- fraction.floatValue += 0.05f
- }
- .semantics {
- contentDescription = INCREASE_POSITION
- }
+ Box(
+ modifier =
+ Modifier.size(30.dp)
+ .clickable { fraction.floatValue += 0.05f }
+ .semantics { contentDescription = INCREASE_POSITION }
)
- Box(modifier = Modifier
- .size(30.dp)
- .clickable {
- fraction.floatValue -= 0.05f
- }
- .semantics {
- contentDescription = DECREASE_POSITION
- }
+ Box(
+ modifier =
+ Modifier.size(30.dp)
+ .clickable { fraction.floatValue -= 0.05f }
+ .semantics { contentDescription = DECREASE_POSITION }
)
}
}
diff --git a/wear/compose/integration-tests/macrobenchmark-target/src/main/java/androidx/wear/compose/integration/macrobenchmark/target/ScrollActivity.kt b/wear/compose/integration-tests/macrobenchmark-target/src/main/java/androidx/wear/compose/integration/macrobenchmark/target/ScrollActivity.kt
index 13d0551..589fc62 100644
--- a/wear/compose/integration-tests/macrobenchmark-target/src/main/java/androidx/wear/compose/integration/macrobenchmark/target/ScrollActivity.kt
+++ b/wear/compose/integration-tests/macrobenchmark-target/src/main/java/androidx/wear/compose/integration/macrobenchmark/target/ScrollActivity.kt
@@ -47,18 +47,18 @@
MaterialTheme {
ScalingLazyColumn(
horizontalAlignment = Alignment.CenterHorizontally,
- verticalArrangement = Arrangement.spacedBy(
- space = defaultItemSpacingDp,
- alignment = Alignment.CenterVertically
- ),
+ verticalArrangement =
+ Arrangement.spacedBy(
+ space = defaultItemSpacingDp,
+ alignment = Alignment.CenterVertically
+ ),
contentPadding = PaddingValues(horizontal = 8.dp, vertical = 30.dp),
state = rememberScalingLazyListState(),
modifier = Modifier.semantics { contentDescription = CONTENT_DESCRIPTION }
) {
items(5000) { it ->
Box(
- Modifier
- .requiredHeight(itemHeightDp)
+ Modifier.requiredHeight(itemHeightDp)
.background(MaterialTheme.colors.surface)
.fillMaxSize()
) {
diff --git a/wear/compose/integration-tests/macrobenchmark-target/src/main/java/androidx/wear/compose/integration/macrobenchmark/target/StartupActivity.kt b/wear/compose/integration-tests/macrobenchmark-target/src/main/java/androidx/wear/compose/integration/macrobenchmark/target/StartupActivity.kt
index aaf1043..b10cabf 100644
--- a/wear/compose/integration-tests/macrobenchmark-target/src/main/java/androidx/wear/compose/integration/macrobenchmark/target/StartupActivity.kt
+++ b/wear/compose/integration-tests/macrobenchmark-target/src/main/java/androidx/wear/compose/integration/macrobenchmark/target/StartupActivity.kt
@@ -26,8 +26,6 @@
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- setContent {
- Text("Wear Compose Macrobenchmark Target")
- }
+ setContent { Text("Wear Compose Macrobenchmark Target") }
}
}
diff --git a/wear/compose/integration-tests/macrobenchmark-target/src/main/java/androidx/wear/compose/integration/macrobenchmark/target/SwipeToRevealActivity.kt b/wear/compose/integration-tests/macrobenchmark-target/src/main/java/androidx/wear/compose/integration/macrobenchmark/target/SwipeToRevealActivity.kt
index 9d60ecd..524a54c 100644
--- a/wear/compose/integration-tests/macrobenchmark-target/src/main/java/androidx/wear/compose/integration/macrobenchmark/target/SwipeToRevealActivity.kt
+++ b/wear/compose/integration-tests/macrobenchmark-target/src/main/java/androidx/wear/compose/integration/macrobenchmark/target/SwipeToRevealActivity.kt
@@ -47,30 +47,32 @@
Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
val revealState = rememberRevealState()
SwipeToRevealChip(
- modifier = Modifier
- .fillMaxWidth()
- .semantics { contentDescription = CONTENT_DESCRIPTION },
+ modifier =
+ Modifier.fillMaxWidth().semantics {
+ contentDescription = CONTENT_DESCRIPTION
+ },
revealState = revealState,
primaryAction = {
- SwipeToRevealPrimaryAction(revealState = revealState,
+ SwipeToRevealPrimaryAction(
+ revealState = revealState,
icon = { Icon(SwipeToRevealDefaults.Delete, "Delete") },
label = { Text("Delete") },
- onClick = { })
+ onClick = {}
+ )
},
secondaryAction = {
- SwipeToRevealSecondaryAction(revealState = revealState, onClick = { }) {
+ SwipeToRevealSecondaryAction(revealState = revealState, onClick = {}) {
Icon(SwipeToRevealDefaults.MoreOptions, "More Options")
}
},
- onFullSwipe = { }
+ onFullSwipe = {}
) {
- Chip(modifier = Modifier.fillMaxWidth(),
- onClick = { },
+ Chip(
+ modifier = Modifier.fillMaxWidth(),
+ onClick = {},
colors = ChipDefaults.primaryChipColors(),
border = ChipDefaults.outlinedChipBorder(),
- label = {
- Text("SwipeToReveal Chip", maxLines = 3)
- }
+ label = { Text("SwipeToReveal Chip", maxLines = 3) }
)
}
}
diff --git a/wear/compose/integration-tests/macrobenchmark/src/main/java/androidx/wear/compose/integration/macrobenchmark/BaselineProfile.kt b/wear/compose/integration-tests/macrobenchmark/src/main/java/androidx/wear/compose/integration/macrobenchmark/BaselineProfile.kt
index c8b7a80..f961dd9 100644
--- a/wear/compose/integration-tests/macrobenchmark/src/main/java/androidx/wear/compose/integration/macrobenchmark/BaselineProfile.kt
+++ b/wear/compose/integration-tests/macrobenchmark/src/main/java/androidx/wear/compose/integration/macrobenchmark/BaselineProfile.kt
@@ -41,7 +41,8 @@
// 4) Run profileparser for each of wear.compose.material, wear.compose.foundation and
// wear.compose.navigation. From <workspace>/frameworks/support:
// /usr/bin/java -jar
-// ../../out/androidx/wear/compose/integration-tests/profileparser/build/libs/profileparser-all.jar
+//
+// ../../out/androidx/wear/compose/integration-tests/profileparser/build/libs/profileparser-all.jar
// <input-generated-file eg ./wear/compose/BaselineProfile_profile-baseline-prof.txt>
// <library-name e.g. androidx/wear/compose/material>
// <output-file eg ./wear/compose/compose-material/src/main/baseline-prof.txt>
@@ -49,8 +50,7 @@
@SdkSuppress(minSdkVersion = 29)
class BaselineProfile {
- @get:Rule
- val baselineRule = BaselineProfileRule()
+ @get:Rule val baselineRule = BaselineProfileRule()
private val ALERT_DIALOG = "alert-dialog"
private val BUTTONS = "buttons"
diff --git a/wear/compose/integration-tests/macrobenchmark/src/main/java/androidx/wear/compose/integration/macrobenchmark/Common.kt b/wear/compose/integration-tests/macrobenchmark/src/main/java/androidx/wear/compose/integration/macrobenchmark/Common.kt
index 41a14f7..1cfa14d 100644
--- a/wear/compose/integration-tests/macrobenchmark/src/main/java/androidx/wear/compose/integration/macrobenchmark/Common.kt
+++ b/wear/compose/integration-tests/macrobenchmark/src/main/java/androidx/wear/compose/integration/macrobenchmark/Common.kt
@@ -24,15 +24,19 @@
internal fun disableChargingExperience() {
val instrumentation = InstrumentationRegistry.getInstrumentation()
val device = UiDevice.getInstance(instrumentation)
- device.executeShellCommand("am broadcast -a " +
- "com.google.android.clockwork.sysui.charging.ENABLE_CHARGING_EXPERIENCE " +
- "--ez value \"false\" com.google.android.wearable.sysui")
+ device.executeShellCommand(
+ "am broadcast -a " +
+ "com.google.android.clockwork.sysui.charging.ENABLE_CHARGING_EXPERIENCE " +
+ "--ez value \"false\" com.google.android.wearable.sysui"
+ )
}
internal fun enableChargingExperience() {
val instrumentation = InstrumentationRegistry.getInstrumentation()
val device = UiDevice.getInstance(instrumentation)
- device.executeShellCommand("am broadcast -a " +
- "com.google.android.clockwork.sysui.charging.ENABLE_CHARGING_EXPERIENCE " +
- "--ez value \"true\" com.google.android.wearable.sysui")
+ device.executeShellCommand(
+ "am broadcast -a " +
+ "com.google.android.clockwork.sysui.charging.ENABLE_CHARGING_EXPERIENCE " +
+ "--ez value \"true\" com.google.android.wearable.sysui"
+ )
}
diff --git a/wear/compose/integration-tests/macrobenchmark/src/main/java/androidx/wear/compose/integration/macrobenchmark/CompositionMetric.kt b/wear/compose/integration-tests/macrobenchmark/src/main/java/androidx/wear/compose/integration/macrobenchmark/CompositionMetric.kt
index 5ea1fc5..25f237b 100644
--- a/wear/compose/integration-tests/macrobenchmark/src/main/java/androidx/wear/compose/integration/macrobenchmark/CompositionMetric.kt
+++ b/wear/compose/integration-tests/macrobenchmark/src/main/java/androidx/wear/compose/integration/macrobenchmark/CompositionMetric.kt
@@ -31,16 +31,20 @@
): List<Measurement> {
val shortName = composable.substringAfterLast(".")
- val durationsNs = traceSession.query(
- """
+ val durationsNs =
+ traceSession
+ .query(
+ """
SELECT * FROM slice
INNER JOIN thread_track on slice.track_id = thread_track.id
INNER JOIN thread USING(utid)
INNER JOIN process USING(upid)
WHERE process.name LIKE "${captureInfo.targetPackageName}"
AND slice.name LIKE "$composable (%)"
- """.trimIndent()
- ).map { it.long("dur") }
+ """
+ .trimIndent()
+ )
+ .map { it.long("dur") }
return listOf(
Measurement(
diff --git a/wear/compose/integration-tests/macrobenchmark/src/main/java/androidx/wear/compose/integration/macrobenchmark/PositionIndicatorBenchmark.kt b/wear/compose/integration-tests/macrobenchmark/src/main/java/androidx/wear/compose/integration/macrobenchmark/PositionIndicatorBenchmark.kt
index a4dae95..ca88618 100644
--- a/wear/compose/integration-tests/macrobenchmark/src/main/java/androidx/wear/compose/integration/macrobenchmark/PositionIndicatorBenchmark.kt
+++ b/wear/compose/integration-tests/macrobenchmark/src/main/java/androidx/wear/compose/integration/macrobenchmark/PositionIndicatorBenchmark.kt
@@ -36,11 +36,8 @@
@LargeTest
@RunWith(Parameterized::class)
-class PositionIndicatorBenchmark(
- private val compilationMode: CompilationMode
-) {
- @get:Rule
- val benchmarkRule = MacrobenchmarkRule()
+class PositionIndicatorBenchmark(private val compilationMode: CompilationMode) {
+ @get:Rule val benchmarkRule = MacrobenchmarkRule()
@Before
fun setUp() {
@@ -56,9 +53,7 @@
fun start() {
benchmarkRule.measureRepeated(
packageName = PACKAGE_NAME,
- metrics = listOf(
- FrameTimingMetric()
- ),
+ metrics = listOf(FrameTimingMetric()),
compilationMode = compilationMode,
iterations = 5,
setupBlock = {
diff --git a/wear/compose/integration-tests/macrobenchmark/src/main/java/androidx/wear/compose/integration/macrobenchmark/ScrollBenchmark.kt b/wear/compose/integration-tests/macrobenchmark/src/main/java/androidx/wear/compose/integration/macrobenchmark/ScrollBenchmark.kt
index f79e38c..bf26054 100644
--- a/wear/compose/integration-tests/macrobenchmark/src/main/java/androidx/wear/compose/integration/macrobenchmark/ScrollBenchmark.kt
+++ b/wear/compose/integration-tests/macrobenchmark/src/main/java/androidx/wear/compose/integration/macrobenchmark/ScrollBenchmark.kt
@@ -33,11 +33,8 @@
@LargeTest
@RunWith(Parameterized::class)
-class ScrollBenchmark(
- private val compilationMode: CompilationMode
-) {
- @get:Rule
- val benchmarkRule = MacrobenchmarkRule()
+class ScrollBenchmark(private val compilationMode: CompilationMode) {
+ @get:Rule val benchmarkRule = MacrobenchmarkRule()
@Before
fun setUp() {
diff --git a/wear/compose/integration-tests/macrobenchmark/src/main/java/androidx/wear/compose/integration/macrobenchmark/StartupBenchmark.kt b/wear/compose/integration-tests/macrobenchmark/src/main/java/androidx/wear/compose/integration/macrobenchmark/StartupBenchmark.kt
index d123474..9a05809 100644
--- a/wear/compose/integration-tests/macrobenchmark/src/main/java/androidx/wear/compose/integration/macrobenchmark/StartupBenchmark.kt
+++ b/wear/compose/integration-tests/macrobenchmark/src/main/java/androidx/wear/compose/integration/macrobenchmark/StartupBenchmark.kt
@@ -35,8 +35,7 @@
private val startupMode: StartupMode,
private val compilationMode: CompilationMode
) {
- @get:Rule
- val benchmarkRule = MacrobenchmarkRule()
+ @get:Rule val benchmarkRule = MacrobenchmarkRule()
@Before
fun setUp() {
@@ -49,13 +48,14 @@
}
@Test
- fun startup() = benchmarkRule.measureStartup(
- compilationMode = compilationMode,
- startupMode = startupMode,
- packageName = "androidx.wear.compose.integration.macrobenchmark.target"
- ) {
- action = "androidx.wear.compose.integration.macrobenchmark.target.WEAR_STARTUP_ACTIVITY"
- }
+ fun startup() =
+ benchmarkRule.measureStartup(
+ compilationMode = compilationMode,
+ startupMode = startupMode,
+ packageName = "androidx.wear.compose.integration.macrobenchmark.target"
+ ) {
+ action = "androidx.wear.compose.integration.macrobenchmark.target.WEAR_STARTUP_ACTIVITY"
+ }
companion object {
@Parameterized.Parameters(name = "startup={0},compilation={1}")
diff --git a/wear/compose/integration-tests/macrobenchmark/src/main/java/androidx/wear/compose/integration/macrobenchmark/SwipeToDismissBenchmark.kt b/wear/compose/integration-tests/macrobenchmark/src/main/java/androidx/wear/compose/integration/macrobenchmark/SwipeToDismissBenchmark.kt
index f3abcb4..c8e9044 100644
--- a/wear/compose/integration-tests/macrobenchmark/src/main/java/androidx/wear/compose/integration/macrobenchmark/SwipeToDismissBenchmark.kt
+++ b/wear/compose/integration-tests/macrobenchmark/src/main/java/androidx/wear/compose/integration/macrobenchmark/SwipeToDismissBenchmark.kt
@@ -33,11 +33,8 @@
@LargeTest
@RunWith(Parameterized::class)
-class SwipeToDismissBenchmark(
- private val compilationMode: CompilationMode
-) {
- @get:Rule
- val benchmarkRule = MacrobenchmarkRule()
+class SwipeToDismissBenchmark(private val compilationMode: CompilationMode) {
+ @get:Rule val benchmarkRule = MacrobenchmarkRule()
@Before
fun setUp() {
diff --git a/wear/compose/integration-tests/macrobenchmark/src/main/java/androidx/wear/compose/integration/macrobenchmark/SwipeToRevealBenchmark.kt b/wear/compose/integration-tests/macrobenchmark/src/main/java/androidx/wear/compose/integration/macrobenchmark/SwipeToRevealBenchmark.kt
index 8ce70c5..2908e234 100644
--- a/wear/compose/integration-tests/macrobenchmark/src/main/java/androidx/wear/compose/integration/macrobenchmark/SwipeToRevealBenchmark.kt
+++ b/wear/compose/integration-tests/macrobenchmark/src/main/java/androidx/wear/compose/integration/macrobenchmark/SwipeToRevealBenchmark.kt
@@ -36,11 +36,8 @@
@LargeTest
@RunWith(Parameterized::class)
-class SwipeToRevealBenchmark(
- private val compilationMode: CompilationMode
-) {
- @get:Rule
- val benchmarkRule = MacrobenchmarkRule()
+class SwipeToRevealBenchmark(private val compilationMode: CompilationMode) {
+ @get:Rule val benchmarkRule = MacrobenchmarkRule()
@Before
fun setUp() {
diff --git a/wear/compose/integration-tests/navigation/src/main/java/androidx/wear/compose/integration/navigation/MainActivity.kt b/wear/compose/integration-tests/navigation/src/main/java/androidx/wear/compose/integration/navigation/MainActivity.kt
index d8c4163..21ba986 100644
--- a/wear/compose/integration-tests/navigation/src/main/java/androidx/wear/compose/integration/navigation/MainActivity.kt
+++ b/wear/compose/integration-tests/navigation/src/main/java/androidx/wear/compose/integration/navigation/MainActivity.kt
@@ -103,13 +103,15 @@
val horizontalScrollState = rememberScrollState(0)
Box(modifier = Modifier.fillMaxSize()) {
Text(
- modifier = Modifier.align(Alignment.Center)
- .edgeSwipeToDismiss(swipeToDismissBoxState)
- .horizontalScroll(horizontalScrollState),
- text = "This text can be scrolled horizontally - " +
- "to dismiss, swipe " +
- "right from the left edge of the screen" +
- " (called Edge Swiping)",
+ modifier =
+ Modifier.align(Alignment.Center)
+ .edgeSwipeToDismiss(swipeToDismissBoxState)
+ .horizontalScroll(horizontalScrollState),
+ text =
+ "This text can be scrolled horizontally - " +
+ "to dismiss, swipe " +
+ "right from the left edge of the screen" +
+ " (called Edge Swiping)",
)
}
}
diff --git a/wear/tiles/tiles-renderer/src/main/java/androidx/wear/tiles/checkers/CheckAccessibilityAvailable.kt b/wear/tiles/tiles-renderer/src/main/java/androidx/wear/tiles/checkers/CheckAccessibilityAvailable.kt
index 2fd843f..66ce06a 100644
--- a/wear/tiles/tiles-renderer/src/main/java/androidx/wear/tiles/checkers/CheckAccessibilityAvailable.kt
+++ b/wear/tiles/tiles-renderer/src/main/java/androidx/wear/tiles/checkers/CheckAccessibilityAvailable.kt
@@ -24,8 +24,8 @@
* Checks a [TimelineBuilders.TimelineEntry] to ensure that at least one element within it has an
* accessibility description registered.
*
- * At least one element on each tile should have a machine-readable content description
- * associated with it, which can be read out using screen readers.
+ * At least one element on each tile should have a machine-readable content description associated
+ * with it, which can be read out using screen readers.
*/
internal class CheckAccessibilityAvailable : TimelineEntryChecker {
override val name: String
@@ -43,9 +43,7 @@
}
}
- private fun checkElement(
- element: LayoutElementBuilders.LayoutElement
- ): Boolean {
+ private fun checkElement(element: LayoutElementBuilders.LayoutElement): Boolean {
val modifiers =
when (element) {
is LayoutElementBuilders.Row -> element.modifiers
@@ -67,21 +65,15 @@
// Note that individual Spannable elements cannot have semantics; the parent should have
// these.
return when (element) {
- is LayoutElementBuilders.Row ->
- element.contents.any(this::checkElement)
- is LayoutElementBuilders.Column ->
- element.contents.any(this::checkElement)
- is LayoutElementBuilders.Box ->
- element.contents.any(this::checkElement)
- is LayoutElementBuilders.Arc ->
- element.contents.any(this::checkArcLayoutElement)
+ is LayoutElementBuilders.Row -> element.contents.any(this::checkElement)
+ is LayoutElementBuilders.Column -> element.contents.any(this::checkElement)
+ is LayoutElementBuilders.Box -> element.contents.any(this::checkElement)
+ is LayoutElementBuilders.Arc -> element.contents.any(this::checkArcLayoutElement)
else -> false
}
}
- private fun checkArcLayoutElement(
- element: LayoutElementBuilders.ArcLayoutElement
- ): Boolean {
+ private fun checkArcLayoutElement(element: LayoutElementBuilders.ArcLayoutElement): Boolean {
val modifiers =
when (element) {
// Note that ArcAdapter should be handled by taking the modifiers from the inner
diff --git a/wear/tiles/tiles-renderer/src/main/java/androidx/wear/tiles/checkers/TimelineChecker.kt b/wear/tiles/tiles-renderer/src/main/java/androidx/wear/tiles/checkers/TimelineChecker.kt
index 17aadaf..7a4e3cd 100644
--- a/wear/tiles/tiles-renderer/src/main/java/androidx/wear/tiles/checkers/TimelineChecker.kt
+++ b/wear/tiles/tiles-renderer/src/main/java/androidx/wear/tiles/checkers/TimelineChecker.kt
@@ -20,15 +20,13 @@
import androidx.wear.protolayout.TimelineBuilders
import kotlin.jvm.Throws
-/**
- * Exception thrown when a TimelineEntryChecker fails.
- */
+/** Exception thrown when a TimelineEntryChecker fails. */
internal class CheckerException(message: String) : Exception(message)
/**
* Checker for a Tile's TimelineEntries. Instances of this interface should check for a certain
- * condition on the given [TimelineEntry], and throw an instance of [CheckerException] if there
- * is a problem with that [TimelineEntry].
+ * condition on the given [TimelineEntry], and throw an instance of [CheckerException] if there is a
+ * problem with that [TimelineEntry].
*/
internal interface TimelineEntryChecker {
/** The name of this TimelineEntryChecker. This will be printed in any error output. */
@@ -39,13 +37,12 @@
*
* @throws CheckerException if there was an issue while checking the [TimelineEntry]
*/
- @Throws(CheckerException::class)
- fun check(entry: TimelineBuilders.TimelineEntry)
+ @Throws(CheckerException::class) fun check(entry: TimelineBuilders.TimelineEntry)
}
/**
- * Checker for a given [Timeline]. This will run all provided [TimelineEntryChecker]s on the
- * given [Timeline], and if any fail, log an error to logcat.
+ * Checker for a given [Timeline]. This will run all provided [TimelineEntryChecker]s on the given
+ * [Timeline], and if any fail, log an error to logcat.
*
* @param entryCheckers The list of checkers to use. Defaults to all built in checks.
*/
diff --git a/wear/tiles/tiles-renderer/src/main/java/androidx/wear/tiles/connection/DefaultTileClient.kt b/wear/tiles/tiles-renderer/src/main/java/androidx/wear/tiles/connection/DefaultTileClient.kt
index 6fad649..4d183be 100644
--- a/wear/tiles/tiles-renderer/src/main/java/androidx/wear/tiles/connection/DefaultTileClient.kt
+++ b/wear/tiles/tiles-renderer/src/main/java/androidx/wear/tiles/connection/DefaultTileClient.kt
@@ -55,40 +55,43 @@
import kotlinx.coroutines.withTimeout
/**
- * Implementation of [TileClient] which can connect to a `TileService` in either the local
- * process, or in a remote app.
+ * Implementation of [TileClient] which can connect to a `TileService` in either the local process,
+ * or in a remote app.
*
* This implementation will only stay connected for as long as required. Each call will cause this
* client to connect to the `TileService`, and call the specified remote method. It will then
- * disconnect again after one second of inactivity (so calls in quick succession will share the
- * same binder).
+ * disconnect again after one second of inactivity (so calls in quick succession will share the same
+ * binder).
*
* Note that there is a timeout of 10s when connecting to the `TileService`, and a timeout of 30s
* for [requestTile] and [requestResources] to return a payload.
*/
public class DefaultTileClient : TileClient {
internal companion object {
- @VisibleForTesting
- internal const val TIMEOUT_MILLIS = 30000L // 30s
+ @VisibleForTesting internal const val TIMEOUT_MILLIS = 30000L // 30s
private const val TILE_ID = -1
// These don't contain a useful payload right now, so just pre-build them.
- private val TILE_ADD_EVENT = TileAddEventData(
- EventBuilders.TileAddEvent.Builder().build().toProto().toByteArray(),
- TileAddEventData.VERSION_PROTOBUF
- )
- private val TILE_REMOVE_EVENT = TileRemoveEventData(
- EventBuilders.TileRemoveEvent.Builder().build().toProto().toByteArray(),
- TileRemoveEventData.VERSION_PROTOBUF
- )
- private val TILE_ENTER_EVENT = TileEnterEventData(
- EventBuilders.TileEnterEvent.Builder().build().toProto().toByteArray(),
- TileEnterEventData.VERSION_PROTOBUF
- )
- private val TILE_LEAVE_EVENT = TileLeaveEventData(
- EventBuilders.TileLeaveEvent.Builder().build().toProto().toByteArray(),
- TileLeaveEventData.VERSION_PROTOBUF
- )
+ private val TILE_ADD_EVENT =
+ TileAddEventData(
+ EventBuilders.TileAddEvent.Builder().build().toProto().toByteArray(),
+ TileAddEventData.VERSION_PROTOBUF
+ )
+ private val TILE_REMOVE_EVENT =
+ TileRemoveEventData(
+ EventBuilders.TileRemoveEvent.Builder().build().toProto().toByteArray(),
+ TileRemoveEventData.VERSION_PROTOBUF
+ )
+ private val TILE_ENTER_EVENT =
+ TileEnterEventData(
+ EventBuilders.TileEnterEvent.Builder().build().toProto().toByteArray(),
+ TileEnterEventData.VERSION_PROTOBUF
+ )
+ private val TILE_LEAVE_EVENT =
+ TileLeaveEventData(
+ EventBuilders.TileLeaveEvent.Builder().build().toProto().toByteArray(),
+ TileLeaveEventData.VERSION_PROTOBUF
+ )
}
private val coroutineScope: CoroutineScope
@@ -100,9 +103,8 @@
*
* @param context The application context to use when binding to the [TileService].
* @param componentName The [ComponentName] of the [TileService] to bind to.
- * @param coroutineScope A [CoroutineScope] to use when dispatching calls to the
- * [TileService]. Cancelling the passed [CoroutineScope] will also cancel any pending
- * work in this class.
+ * @param coroutineScope A [CoroutineScope] to use when dispatching calls to the [TileService].
+ * Cancelling the passed [CoroutineScope] will also cancel any pending work in this class.
* @param coroutineDispatcher A [CoroutineDispatcher] to use when dispatching work from this
* class.
*/
@@ -140,10 +142,11 @@
requestParams: RequestBuilders.TileRequest
): ListenableFuture<TileBuilders.Tile> {
return runForFuture {
- val params = TileRequestData(
- requestParams.toProto().toByteArray(),
- TileRequestData.VERSION_PROTOBUF
- )
+ val params =
+ TileRequestData(
+ requestParams.toProto().toByteArray(),
+ TileRequestData.VERSION_PROTOBUF
+ )
suspendCancellableCoroutine<TileBuilders.Tile> { continuation ->
it.onTileRequest(TILE_ID, params, TileResultCallback(continuation))
@@ -155,34 +158,33 @@
requestParams: RequestBuilders.ResourcesRequest
): ListenableFuture<ResourceBuilders.Resources> {
return runForFuture {
- val params = ResourcesRequestData(
- requestParams.toProto().toByteArray(),
- ResourcesRequestData.VERSION_PROTOBUF
- )
+ val params =
+ ResourcesRequestData(
+ requestParams.toProto().toByteArray(),
+ ResourcesRequestData.VERSION_PROTOBUF
+ )
suspendCancellableCoroutine { continuation ->
- it.onResourcesRequest(
- TILE_ID, params,
- ResourcesResultCallback(continuation)
- )
+ it.onResourcesRequest(TILE_ID, params, ResourcesResultCallback(continuation))
}
}
}
@Deprecated(
"Use requestTileResourcesAsync instead.",
- replaceWith = ReplaceWith("requestTileResourcesAsync"))
+ replaceWith = ReplaceWith("requestTileResourcesAsync")
+ )
@Suppress("deprecation")
public override fun requestResources(
requestParams: RequestBuilders.ResourcesRequest
): ListenableFuture<androidx.wear.tiles.ResourceBuilders.Resources> {
- return FluentFuture.from(requestTileResourcesAsync(requestParams)).transform(
- { res: ResourceBuilders.Resources ->
- androidx.wear.tiles.ResourceBuilders.Resources.fromProto(
- res.toProto()
- )
- }, MoreExecutors.directExecutor()
- )
+ return FluentFuture.from(requestTileResourcesAsync(requestParams))
+ .transform(
+ { res: ResourceBuilders.Resources ->
+ androidx.wear.tiles.ResourceBuilders.Resources.fromProto(res.toProto())
+ },
+ MoreExecutors.directExecutor()
+ )
}
public override fun sendOnTileAddedEvent(): ListenableFuture<Void?> {
@@ -213,9 +215,8 @@
}
}
- private class TileResultCallback(
- private val continuation: Continuation<TileBuilders.Tile>
- ) : TileCallback.Stub() {
+ private class TileResultCallback(private val continuation: Continuation<TileBuilders.Tile>) :
+ TileCallback.Stub() {
override fun updateTileData(tileData: TileData?) {
when {
tileData == null -> {
@@ -227,7 +228,9 @@
continuation.resumeWithException(
IllegalArgumentException(
"Returned Tile Data " +
- "has unexpected version (" + tileData.version + ")"
+ "has unexpected version (" +
+ tileData.version +
+ ")"
)
)
}
@@ -257,15 +260,16 @@
continuation.resumeWithException(
IllegalArgumentException(
"Returned Resources " +
- "Data has unexpected version (" + resourcesData.version + ")"
+ "Data has unexpected version (" +
+ resourcesData.version +
+ ")"
)
)
}
else -> {
try {
val resources = ResourceProto.Resources.parseFrom(resourcesData.contents)
- continuation.resume(
- ResourceBuilders.Resources.fromProto(resources))
+ continuation.resume(ResourceBuilders.Resources.fromProto(resources))
} catch (ex: InvalidProtocolBufferException) {
continuation.resumeWithException(ex)
}
@@ -274,17 +278,13 @@
}
}
- private fun <T> runForFuture(
- fn: suspend (TileProvider) -> T
- ): ListenableFuture<T> {
+ private fun <T> runForFuture(fn: suspend (TileProvider) -> T): ListenableFuture<T> {
val future = ResolvableFuture.create<T>()
coroutineScope.launch(coroutineDispatcher) {
try {
withTimeout(TIMEOUT_MILLIS) {
- connectionBinder.runWithTilesConnection {
- future.set(fn(it))
- }
+ connectionBinder.runWithTilesConnection { future.set(fn(it)) }
}
} catch (ex: Exception) {
future.setException(ex)
diff --git a/wear/tiles/tiles-renderer/src/main/java/androidx/wear/tiles/connection/TilesConnectionBinder.kt b/wear/tiles/tiles-renderer/src/main/java/androidx/wear/tiles/connection/TilesConnectionBinder.kt
index f8f051a..1238586 100644
--- a/wear/tiles/tiles-renderer/src/main/java/androidx/wear/tiles/connection/TilesConnectionBinder.kt
+++ b/wear/tiles/tiles-renderer/src/main/java/androidx/wear/tiles/connection/TilesConnectionBinder.kt
@@ -77,44 +77,41 @@
* Bind to the tile provider, if needed, then call the given coroutine, passing the tile
* provider to it.
*/
- suspend fun <T> runWithTilesConnection(
- fn: suspend CoroutineScope.(TileProvider) -> T
- ): T = coroutineScope {
- // Cache the original context, then use withContext to dispatch fn on it. The alternative is
- // to update mRefCnt in a withContext(mDispatcher), then putting the rest of the function
- // in a try/finally, which itself uses withContext to call getBinder/releaseBinder and
- // decrement mRefCnt again.
- val originalContext = coroutineContext
- withContext(backgroundCoroutineDispatcher) {
- activeCoroutines++
+ suspend fun <T> runWithTilesConnection(fn: suspend CoroutineScope.(TileProvider) -> T): T =
+ coroutineScope {
+ // Cache the original context, then use withContext to dispatch fn on it. The
+ // alternative is
+ // to update mRefCnt in a withContext(mDispatcher), then putting the rest of the
+ // function
+ // in a try/finally, which itself uses withContext to call getBinder/releaseBinder and
+ // decrement mRefCnt again.
+ val originalContext = coroutineContext
+ withContext(backgroundCoroutineDispatcher) {
+ activeCoroutines++
- try {
- if (activeCoroutines == 1) {
- cancelBinderRelease()
- }
+ try {
+ if (activeCoroutines == 1) {
+ cancelBinderRelease()
+ }
- val binder = getBinder()
+ val binder = getBinder()
- withContext(originalContext) {
- fn(binder)
- }
- } finally {
- activeCoroutines--
- if (activeCoroutines == 0) {
- scheduleBinderRelease()
+ withContext(originalContext) { fn(binder) }
+ } finally {
+ activeCoroutines--
+ if (activeCoroutines == 0) {
+ scheduleBinderRelease()
+ }
}
}
}
- }
/**
- * Run cleanup tasks. This should be called when the given coroutine scope is being
- * destroyed, as that will also cancel the cleanup task.
+ * Run cleanup tasks. This should be called when the given coroutine scope is being destroyed,
+ * as that will also cancel the cleanup task.
*/
suspend fun cleanUp() {
- withContext(backgroundCoroutineDispatcher) {
- disconnectFromService()
- }
+ withContext(backgroundCoroutineDispatcher) { disconnectFromService() }
}
/**
@@ -133,31 +130,35 @@
}
private suspend fun connectToService(): TileProvider = coroutineScope {
- val bindJob = async(backgroundCoroutineDispatcher) {
- suspendCancellableCoroutine<TileProvider> { continuation ->
- val bindIntent = Intent(TileService.ACTION_BIND_TILE_PROVIDER)
- bindIntent.component = componentName
+ val bindJob =
+ async(backgroundCoroutineDispatcher) {
+ suspendCancellableCoroutine<TileProvider> { continuation ->
+ val bindIntent = Intent(TileService.ACTION_BIND_TILE_PROVIDER)
+ bindIntent.component = componentName
- val myConnection = object : ServiceConnection {
- override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
- val boundTileProvider = TileProvider.Stub.asInterface(service)
- continuation.resume(boundTileProvider)
- }
+ val myConnection =
+ object : ServiceConnection {
+ override fun onServiceConnected(
+ name: ComponentName?,
+ service: IBinder?
+ ) {
+ val boundTileProvider = TileProvider.Stub.asInterface(service)
+ continuation.resume(boundTileProvider)
+ }
- override fun onServiceDisconnected(name: ComponentName?) {
- // This is called when the remote side hangs up, but will be dispatched
- // from an unknown thread. Ignore it for now.
- }
- }
+ override fun onServiceDisconnected(name: ComponentName?) {
+ // This is called when the remote side hangs up, but will be
+ // dispatched
+ // from an unknown thread. Ignore it for now.
+ }
+ }
- connection = myConnection
- context.bindService(bindIntent, myConnection, Context.BIND_AUTO_CREATE)
+ connection = myConnection
+ context.bindService(bindIntent, myConnection, Context.BIND_AUTO_CREATE)
- continuation.invokeOnCancellation {
- disconnectFromService()
+ continuation.invokeOnCancellation { disconnectFromService() }
}
}
- }
connectBinderJob = bindJob
@@ -179,14 +180,15 @@
}
private fun scheduleBinderRelease() {
- releaseBinderJob = coroutineScope.launch(backgroundCoroutineDispatcher) {
- delay(INACTIVITY_TIMEOUT_MILLIS)
+ releaseBinderJob =
+ coroutineScope.launch(backgroundCoroutineDispatcher) {
+ delay(INACTIVITY_TIMEOUT_MILLIS)
- // Only run the unbind if we didn't get cancelled.
- if (isActive) {
- disconnectFromService()
+ // Only run the unbind if we didn't get cancelled.
+ if (isActive) {
+ disconnectFromService()
+ }
}
- }
}
private suspend fun cancelBinderRelease() {
diff --git a/wear/tiles/tiles-renderer/src/main/java/androidx/wear/tiles/manager/TileUiClient.kt b/wear/tiles/tiles-renderer/src/main/java/androidx/wear/tiles/manager/TileUiClient.kt
index 5eff066..f2c442a 100644
--- a/wear/tiles/tiles-renderer/src/main/java/androidx/wear/tiles/manager/TileUiClient.kt
+++ b/wear/tiles/tiles-renderer/src/main/java/androidx/wear/tiles/manager/TileUiClient.kt
@@ -79,13 +79,16 @@
context = context,
componentName = component,
coroutineScope = coroutineScope,
- coroutineDispatcher = Executors.newSingleThreadExecutor().asCoroutineDispatcher())
+ coroutineDispatcher = Executors.newSingleThreadExecutor().asCoroutineDispatcher()
+ )
private var timelineManager: TilesTimelineManager? = null
private var tileResources: ResourceBuilders.Resources? = null
private val updateScheduler =
UpdateScheduler(
- context.getSystemService(AlarmManager::class.java), SystemClock::elapsedRealtime)
+ context.getSystemService(AlarmManager::class.java),
+ SystemClock::elapsedRealtime
+ )
private val updateReceiver =
object : BroadcastReceiver() {
@@ -170,9 +173,10 @@
System::currentTimeMillis,
tile.tileTimeline ?: TimelineBuilders.Timeline.Builder().build(),
0,
- ContextCompat.getMainExecutor(context)) { _, layout ->
- coroutineScope.launch { updateContents(layout) }
- }
+ ContextCompat.getMainExecutor(context)
+ ) { _, layout ->
+ coroutineScope.launch { updateContents(layout) }
+ }
timelineManager = localTimelineManager
val freshnessInterval = tile.freshnessIntervalMillis
@@ -214,7 +218,8 @@
.setScreenDensity(displayMetrics.density)
.setScreenShape(
if (isScreenRound) DeviceParametersBuilders.SCREEN_SHAPE_ROUND
- else DeviceParametersBuilders.SCREEN_SHAPE_RECT)
+ else DeviceParametersBuilders.SCREEN_SHAPE_RECT
+ )
.setDevicePlatform(DeviceParametersBuilders.DEVICE_PLATFORM_WEAR_OS)
.build()
}
diff --git a/wear/tiles/tiles-renderer/src/test/java/androidx/wear/tiles/checkers/CheckAccessibilityAvailableTest.kt b/wear/tiles/tiles-renderer/src/test/java/androidx/wear/tiles/checkers/CheckAccessibilityAvailableTest.kt
index 10c8080..54239a9 100644
--- a/wear/tiles/tiles-renderer/src/test/java/androidx/wear/tiles/checkers/CheckAccessibilityAvailableTest.kt
+++ b/wear/tiles/tiles-renderer/src/test/java/androidx/wear/tiles/checkers/CheckAccessibilityAvailableTest.kt
@@ -28,8 +28,7 @@
class CheckAccessibilityAvailableTest {
@Test
fun check_throwsWithNoSemantics() {
- val entry = buildTimelineEntry(
- LayoutElementBuilders.Box.Builder().build())
+ val entry = buildTimelineEntry(LayoutElementBuilders.Box.Builder().build())
var exception: CheckerException? = null
@@ -102,12 +101,8 @@
assertThat(exception).isNull()
}
- private fun buildTimelineEntry(
- layout: LayoutElementBuilders.LayoutElement
- ) =
+ private fun buildTimelineEntry(layout: LayoutElementBuilders.LayoutElement) =
TimelineBuilders.TimelineEntry.Builder()
- .setLayout(
- LayoutElementBuilders.Layout.Builder().setRoot(layout).build()
- )
+ .setLayout(LayoutElementBuilders.Layout.Builder().setRoot(layout).build())
.build()
}
diff --git a/wear/tiles/tiles-renderer/src/test/java/androidx/wear/tiles/checkers/TimelineCheckerTest.kt b/wear/tiles/tiles-renderer/src/test/java/androidx/wear/tiles/checkers/TimelineCheckerTest.kt
index 632f85e..7439dc4 100644
--- a/wear/tiles/tiles-renderer/src/test/java/androidx/wear/tiles/checkers/TimelineCheckerTest.kt
+++ b/wear/tiles/tiles-renderer/src/test/java/androidx/wear/tiles/checkers/TimelineCheckerTest.kt
@@ -34,13 +34,9 @@
class TimelineCheckerTest {
@Test
fun doCheck_callsAllCheckersOnSuccess() {
- val mockChecker1 = mock<TimelineEntryChecker> {
- on { name } doReturn "MockChecker1"
- }
+ val mockChecker1 = mock<TimelineEntryChecker> { on { name } doReturn "MockChecker1" }
- val mockChecker2 = mock<TimelineEntryChecker> {
- on { name } doReturn "MockChecker2"
- }
+ val mockChecker2 = mock<TimelineEntryChecker> { on { name } doReturn "MockChecker2" }
val checker = TimelineChecker(listOf(mockChecker1, mockChecker2))
val timeline = buildTimeline()
@@ -63,15 +59,17 @@
@Test
fun doCheck_callsAllCheckersOnFailure() {
- val mockChecker1 = mock<TimelineEntryChecker> {
- on { name } doReturn "MockChecker1"
- on { check(any()) } doThrow CheckerException("Invalid...")
- }
+ val mockChecker1 =
+ mock<TimelineEntryChecker> {
+ on { name } doReturn "MockChecker1"
+ on { check(any()) } doThrow CheckerException("Invalid...")
+ }
- val mockChecker2 = mock<TimelineEntryChecker> {
- on { name } doReturn "MockChecker2"
- on { check(any()) } doThrow CheckerException("Invalid...")
- }
+ val mockChecker2 =
+ mock<TimelineEntryChecker> {
+ on { name } doReturn "MockChecker2"
+ on { check(any()) } doThrow CheckerException("Invalid...")
+ }
val checker = TimelineChecker(listOf(mockChecker1, mockChecker2))
val timeline = buildTimeline()
@@ -94,21 +92,24 @@
}
private fun buildTimeline() =
- TimelineBuilders.Timeline.Builder().addTimelineEntry(
- TimelineBuilders.TimelineEntry.Builder().setLayout(
- LayoutElementBuilders.Layout.Builder().setRoot(
- LayoutElementBuilders.Text.Builder()
- .setText("Hello")
- .build()
- ).build()
- ).build()
- ).addTimelineEntry(
- TimelineBuilders.TimelineEntry.Builder().setLayout(
- LayoutElementBuilders.Layout.Builder().setRoot(
- LayoutElementBuilders.Text.Builder()
- .setText("World")
- .build()
- ).build()
- ).build()
- ).build()
+ TimelineBuilders.Timeline.Builder()
+ .addTimelineEntry(
+ TimelineBuilders.TimelineEntry.Builder()
+ .setLayout(
+ LayoutElementBuilders.Layout.Builder()
+ .setRoot(LayoutElementBuilders.Text.Builder().setText("Hello").build())
+ .build()
+ )
+ .build()
+ )
+ .addTimelineEntry(
+ TimelineBuilders.TimelineEntry.Builder()
+ .setLayout(
+ LayoutElementBuilders.Layout.Builder()
+ .setRoot(LayoutElementBuilders.Text.Builder().setText("World").build())
+ .build()
+ )
+ .build()
+ )
+ .build()
}
diff --git a/wear/tiles/tiles-renderer/src/test/java/androidx/wear/tiles/connection/DefaultTileClientTest.kt b/wear/tiles/tiles-renderer/src/test/java/androidx/wear/tiles/connection/DefaultTileClientTest.kt
index 64395dd..12d39a7d 100644
--- a/wear/tiles/tiles-renderer/src/test/java/androidx/wear/tiles/connection/DefaultTileClientTest.kt
+++ b/wear/tiles/tiles-renderer/src/test/java/androidx/wear/tiles/connection/DefaultTileClientTest.kt
@@ -83,10 +83,13 @@
Shadows.shadowOf(appContext as Application)
.setComponentNameAndServiceForBindService(TILE_PROVIDER, fakeTileService.asBinder())
- clientUnderTest = DefaultTileClient(
- appContext, TILE_PROVIDER,
- fakeCoroutineScope, fakeCoroutineDispatcher
- )
+ clientUnderTest =
+ DefaultTileClient(
+ appContext,
+ TILE_PROVIDER,
+ fakeCoroutineScope,
+ fakeCoroutineDispatcher
+ )
}
@After
@@ -95,18 +98,19 @@
}
@Test
- public fun getTileContents_canGetTileContents(): Unit = fakeCoroutineScope.runTest {
- val expectedTile = TileBuilders.Tile.Builder().setResourcesVersion("5").build()
- fakeTileService.returnTile = expectedTile.toProto().toByteArray()
+ public fun getTileContents_canGetTileContents(): Unit =
+ fakeCoroutineScope.runTest {
+ val expectedTile = TileBuilders.Tile.Builder().setResourcesVersion("5").build()
+ fakeTileService.returnTile = expectedTile.toProto().toByteArray()
- val result = async {
- clientUnderTest.requestTile(RequestBuilders.TileRequest.Builder().build()).await()
+ val result = async {
+ clientUnderTest.requestTile(RequestBuilders.TileRequest.Builder().build()).await()
+ }
+ Shadows.shadowOf(Looper.getMainLooper()).idle()
+
+ // We don't override #equals; check the proto forms for equality instead.
+ assertThat(result.await().toProto()).isEqualTo(expectedTile.toProto())
}
- Shadows.shadowOf(Looper.getMainLooper()).idle()
-
- // We don't override #equals; check the proto forms for equality instead.
- assertThat(result.await().toProto()).isEqualTo(expectedTile.toProto())
- }
@Test
public fun getTileContents_failsIfUnparsableResult(): Unit =
@@ -114,33 +118,39 @@
// Put some random payload in and see if it breaks.
fakeTileService.returnTile = byteArrayOf(127)
- val result = async(Job()) {
- clientUnderTest.requestTile(RequestBuilders.TileRequest.Builder().build()).await()
- }
+ val result =
+ async(Job()) {
+ clientUnderTest
+ .requestTile(RequestBuilders.TileRequest.Builder().build())
+ .await()
+ }
Shadows.shadowOf(Looper.getMainLooper()).idle()
assertThat(result.isCompleted).isTrue()
- assertThat(result.getCompletionExceptionOrNull()).isInstanceOf(
- InvalidProtocolBufferException::class.java
- )
+ assertThat(result.getCompletionExceptionOrNull())
+ .isInstanceOf(InvalidProtocolBufferException::class.java)
}
@Test
- public fun getTileContents_failsIfVersionMismatch(): Unit = fakeCoroutineScope.runTest {
- // Put some random payload in and see if it breaks.
- val expectedTile = TileProto.Tile.newBuilder().setResourcesVersion("5").build()
- fakeTileService.returnTile = expectedTile.toByteArray()
- fakeTileService.returnTileVersion = -1
+ public fun getTileContents_failsIfVersionMismatch(): Unit =
+ fakeCoroutineScope.runTest {
+ // Put some random payload in and see if it breaks.
+ val expectedTile = TileProto.Tile.newBuilder().setResourcesVersion("5").build()
+ fakeTileService.returnTile = expectedTile.toByteArray()
+ fakeTileService.returnTileVersion = -1
- val result = async(Job()) {
- clientUnderTest.requestTile(RequestBuilders.TileRequest.Builder().build()).await()
+ val result =
+ async(Job()) {
+ clientUnderTest
+ .requestTile(RequestBuilders.TileRequest.Builder().build())
+ .await()
+ }
+ Shadows.shadowOf(Looper.getMainLooper()).idle()
+
+ assertThat(result.isCompleted).isTrue()
+ assertThat(result.getCompletionExceptionOrNull())
+ .isInstanceOf(IllegalArgumentException::class.java)
}
- Shadows.shadowOf(Looper.getMainLooper()).idle()
-
- assertThat(result.isCompleted).isTrue()
- assertThat(result.getCompletionExceptionOrNull())
- .isInstanceOf(IllegalArgumentException::class.java)
- }
@Test
public fun getTileContents_failsOnTimeout(): Unit = runTest {
@@ -149,15 +159,13 @@
fakeTileService.shouldReturnTile = false
val stdDispatcher = StandardTestDispatcher(testScheduler)
- clientUnderTest = DefaultTileClient(
- appContext, TILE_PROVIDER,
- this, stdDispatcher
- )
+ clientUnderTest = DefaultTileClient(appContext, TILE_PROVIDER, this, stdDispatcher)
// This has to be dispatched on the correct dispatcher, so we can fully control its timing.
- val result = async(stdDispatcher + Job()) {
- clientUnderTest.requestTile(RequestBuilders.TileRequest.Builder().build()).await()
- }
+ val result =
+ async(stdDispatcher + Job()) {
+ clientUnderTest.requestTile(RequestBuilders.TileRequest.Builder().build()).await()
+ }
stdDispatcher.scheduler.runCurrent()
Shadows.shadowOf(Looper.getMainLooper()).idle() // Ensure it actually binds...
@@ -176,79 +184,79 @@
}
@Test
- public fun getResources_canGetResources(): Unit = fakeCoroutineScope.runTest {
- val expectedResources = ResourceBuilders.Resources.Builder()
- .setVersion("5")
- .build()
- fakeTileService.returnResources = expectedResources.toProto().toByteArray()
+ public fun getResources_canGetResources(): Unit =
+ fakeCoroutineScope.runTest {
+ val expectedResources = ResourceBuilders.Resources.Builder().setVersion("5").build()
+ fakeTileService.returnResources = expectedResources.toProto().toByteArray()
- val result = async {
- clientUnderTest.requestTileResourcesAsync(
- RequestBuilders.ResourcesRequest.Builder().build()
- ).await()
+ val result = async {
+ clientUnderTest
+ .requestTileResourcesAsync(RequestBuilders.ResourcesRequest.Builder().build())
+ .await()
+ }
+ Shadows.shadowOf(Looper.getMainLooper()).idle()
+
+ assertThat(result.await().toProto()).isEqualTo(expectedResources.toProto())
}
- Shadows.shadowOf(Looper.getMainLooper()).idle()
-
- assertThat(result.await().toProto()).isEqualTo(expectedResources.toProto())
- }
@Test
- public fun getResources_failsIfUnparsableResult(): Unit = fakeCoroutineScope.runTest {
- fakeTileService.returnResources = byteArrayOf(127)
+ public fun getResources_failsIfUnparsableResult(): Unit =
+ fakeCoroutineScope.runTest {
+ fakeTileService.returnResources = byteArrayOf(127)
- val result = async(Job()) {
- clientUnderTest.requestTileResourcesAsync(
- RequestBuilders.ResourcesRequest.Builder().build()
- ).await()
+ val result =
+ async(Job()) {
+ clientUnderTest
+ .requestTileResourcesAsync(
+ RequestBuilders.ResourcesRequest.Builder().build()
+ )
+ .await()
+ }
+ Shadows.shadowOf(Looper.getMainLooper()).idle()
+
+ assertThat(result.isCompleted).isTrue()
+ assertThat(result.getCompletionExceptionOrNull())
+ .isInstanceOf(InvalidProtocolBufferException::class.java)
}
- Shadows.shadowOf(Looper.getMainLooper()).idle()
-
- assertThat(result.isCompleted).isTrue()
- assertThat(result.getCompletionExceptionOrNull()).isInstanceOf(
- InvalidProtocolBufferException::class.java
- )
- }
@Test
- public fun getResources_failsIfVersionMismatch(): Unit = fakeCoroutineScope.runTest {
- val expectedResources = ResourceBuilders.Resources.Builder()
- .setVersion("5")
- .build()
- fakeTileService.returnResources = expectedResources.toProto().toByteArray()
- fakeTileService.returnResourcesVersion = -2
+ public fun getResources_failsIfVersionMismatch(): Unit =
+ fakeCoroutineScope.runTest {
+ val expectedResources = ResourceBuilders.Resources.Builder().setVersion("5").build()
+ fakeTileService.returnResources = expectedResources.toProto().toByteArray()
+ fakeTileService.returnResourcesVersion = -2
- val result = async(Job()) {
- clientUnderTest.requestTileResourcesAsync(
- RequestBuilders.ResourcesRequest.Builder().build()
- ).await()
+ val result =
+ async(Job()) {
+ clientUnderTest
+ .requestTileResourcesAsync(
+ RequestBuilders.ResourcesRequest.Builder().build()
+ )
+ .await()
+ }
+ Shadows.shadowOf(Looper.getMainLooper()).idle()
+
+ assertThat(result.isCompleted).isTrue()
+ assertThat(result.getCompletionExceptionOrNull())
+ .isInstanceOf(IllegalArgumentException::class.java)
}
- Shadows.shadowOf(Looper.getMainLooper()).idle()
-
- assertThat(result.isCompleted).isTrue()
- assertThat(result.getCompletionExceptionOrNull())
- .isInstanceOf(IllegalArgumentException::class.java)
- }
@Test
public fun getResources_failsOnTimeout(): Unit = runTest {
- val expectedResources = ResourceBuilders.Resources.Builder()
- .setVersion("5")
- .build()
+ val expectedResources = ResourceBuilders.Resources.Builder().setVersion("5").build()
fakeTileService.returnResources = expectedResources.toProto().toByteArray()
fakeTileService.shouldReturnResources = false
val stdDispatcher = StandardTestDispatcher(testScheduler)
- clientUnderTest = DefaultTileClient(
- appContext, TILE_PROVIDER,
- this, stdDispatcher
- )
+ clientUnderTest = DefaultTileClient(appContext, TILE_PROVIDER, this, stdDispatcher)
// This has to be dispatched on the correct dispatcher, so we can fully control its timing.
- val result = async(stdDispatcher + Job()) {
- clientUnderTest.requestTileResourcesAsync(
- RequestBuilders.ResourcesRequest.Builder().build()
- ).await()
- }
+ val result =
+ async(stdDispatcher + Job()) {
+ clientUnderTest
+ .requestTileResourcesAsync(RequestBuilders.ResourcesRequest.Builder().build())
+ .await()
+ }
stdDispatcher.scheduler.runCurrent()
Shadows.shadowOf(Looper.getMainLooper()).idle() // Ensure it actually binds...
@@ -267,53 +275,49 @@
}
@Test
- public fun onTileAdd_callsThrough(): Unit = fakeCoroutineScope.runTest {
- val job = launch {
- clientUnderTest.sendOnTileAddedEvent().await()
+ public fun onTileAdd_callsThrough(): Unit =
+ fakeCoroutineScope.runTest {
+ val job = launch { clientUnderTest.sendOnTileAddedEvent().await() }
+
+ Shadows.shadowOf(Looper.getMainLooper()).idle() // Ensure it actually binds...
+ job.join()
+
+ assertThat(fakeTileService.onTileAddCalled).isTrue()
}
- Shadows.shadowOf(Looper.getMainLooper()).idle() // Ensure it actually binds...
- job.join()
-
- assertThat(fakeTileService.onTileAddCalled).isTrue()
- }
-
@Test
- public fun onTileRemove_callsThrough(): Unit = fakeCoroutineScope.runTest {
- val job = launch {
- clientUnderTest.sendOnTileRemovedEvent().await()
+ public fun onTileRemove_callsThrough(): Unit =
+ fakeCoroutineScope.runTest {
+ val job = launch { clientUnderTest.sendOnTileRemovedEvent().await() }
+
+ Shadows.shadowOf(Looper.getMainLooper()).idle() // Ensure it actually binds...
+ job.join()
+
+ assertThat(fakeTileService.onTileRemoveCalled).isTrue()
}
- Shadows.shadowOf(Looper.getMainLooper()).idle() // Ensure it actually binds...
- job.join()
-
- assertThat(fakeTileService.onTileRemoveCalled).isTrue()
- }
-
@Test
- public fun onTileEnter_callsThrough(): Unit = fakeCoroutineScope.runTest {
- val job = launch {
- clientUnderTest.sendOnTileEnterEvent().await()
+ public fun onTileEnter_callsThrough(): Unit =
+ fakeCoroutineScope.runTest {
+ val job = launch { clientUnderTest.sendOnTileEnterEvent().await() }
+
+ Shadows.shadowOf(Looper.getMainLooper()).idle() // Ensure it actually binds...
+ job.join()
+
+ assertThat(fakeTileService.onTileEnterCalled).isTrue()
}
- Shadows.shadowOf(Looper.getMainLooper()).idle() // Ensure it actually binds...
- job.join()
-
- assertThat(fakeTileService.onTileEnterCalled).isTrue()
- }
-
@Test
- public fun onTileLeave_callsThrough(): Unit = fakeCoroutineScope.runTest {
- val job = launch {
- clientUnderTest.sendOnTileLeaveEvent().await()
+ public fun onTileLeave_callsThrough(): Unit =
+ fakeCoroutineScope.runTest {
+ val job = launch { clientUnderTest.sendOnTileLeaveEvent().await() }
+
+ Shadows.shadowOf(Looper.getMainLooper()).idle() // Ensure it actually binds...
+ job.join()
+
+ assertThat(fakeTileService.onTileLeaveCalled).isTrue()
}
- Shadows.shadowOf(Looper.getMainLooper()).idle() // Ensure it actually binds...
- job.join()
-
- assertThat(fakeTileService.onTileLeaveCalled).isTrue()
- }
-
private class FakeTileService : TileProvider.Stub() {
var shouldReturnTile = true
var returnTile = ByteArray(0)
diff --git a/wear/tiles/tiles-renderer/src/test/java/androidx/wear/tiles/connection/TilesConnectionBinderTest.kt b/wear/tiles/tiles-renderer/src/test/java/androidx/wear/tiles/connection/TilesConnectionBinderTest.kt
index 6f5d200..43fc218 100644
--- a/wear/tiles/tiles-renderer/src/test/java/androidx/wear/tiles/connection/TilesConnectionBinderTest.kt
+++ b/wear/tiles/tiles-renderer/src/test/java/androidx/wear/tiles/connection/TilesConnectionBinderTest.kt
@@ -75,10 +75,13 @@
shadowOf(appContext as Application)
.setComponentNameAndServiceForBindService(TILE_PROVIDER, fakeTileService.asBinder())
- connectionBinderUnderTest = TilesConnectionBinder(
- appContext, TILE_PROVIDER,
- fakeCoroutineScope, fakeCoroutineDispatcher
- )
+ connectionBinderUnderTest =
+ TilesConnectionBinder(
+ appContext,
+ TILE_PROVIDER,
+ fakeCoroutineScope,
+ fakeCoroutineDispatcher
+ )
}
@After
@@ -87,213 +90,202 @@
}
@Test
- public fun canCallTileProvider(): Unit = fakeCoroutineScope.runTest {
- val result = async {
- connectionBinderUnderTest.runWithTilesConnection {
- it.apiVersion
+ public fun canCallTileProvider(): Unit =
+ fakeCoroutineScope.runTest {
+ val result = async {
+ connectionBinderUnderTest.runWithTilesConnection { it.apiVersion }
}
+
+ // This is a little nasty, as we have to handle the interactions between the fake looper
+ // and the fake coroutine dispatcher. TestCoroutineDispatcher should run everything
+ // eagerly, so we now need to idle the main looper to get bind to be called.
+ shadowOf(Looper.getMainLooper()).idle()
+
+ assertThat(result.await()).isEqualTo(5)
}
- // This is a little nasty, as we have to handle the interactions between the fake looper
- // and the fake coroutine dispatcher. TestCoroutineDispatcher should run everything
- // eagerly, so we now need to idle the main looper to get bind to be called.
- shadowOf(Looper.getMainLooper()).idle()
-
- assertThat(result.await()).isEqualTo(5)
- }
-
@Test
- public fun binderLeftOpen(): Unit = fakeCoroutineScope.runTest {
- val result = async {
- connectionBinderUnderTest.runWithTilesConnection {
- it.apiVersion
+ public fun binderLeftOpen(): Unit =
+ fakeCoroutineScope.runTest {
+ val result = async {
+ connectionBinderUnderTest.runWithTilesConnection { it.apiVersion }
}
+
+ shadowOf(Looper.getMainLooper()).idle()
+ result.await()
+
+ // Ensure that the binder is still bound.
+ assertThat(shadowOf(appContext as Application).boundServiceConnections).hasSize(1)
+ assertThat(shadowOf(appContext as Application).unboundServiceConnections).isEmpty()
}
- shadowOf(Looper.getMainLooper()).idle()
- result.await()
-
- // Ensure that the binder is still bound.
- assertThat(shadowOf(appContext as Application).boundServiceConnections).hasSize(1)
- assertThat(shadowOf(appContext as Application).unboundServiceConnections).isEmpty()
- }
-
@Test
- public fun binderClosesAfterTimeout(): Unit = fakeCoroutineScope.runTest {
- val result = async {
- connectionBinderUnderTest.runWithTilesConnection {
- it.apiVersion
+ public fun binderClosesAfterTimeout(): Unit =
+ fakeCoroutineScope.runTest {
+ val result = async {
+ connectionBinderUnderTest.runWithTilesConnection { it.apiVersion }
}
+
+ shadowOf(Looper.getMainLooper()).idle()
+ result.await()
+
+ // Wait for the timeout
+ advanceTimeBy(TilesConnectionBinder.INACTIVITY_TIMEOUT_MILLIS)
+ runCurrent()
+
+ shadowOf(Looper.getMainLooper()).idle()
+
+ assertThat(shadowOf(appContext as Application).boundServiceConnections).isEmpty()
+ assertThat(shadowOf(appContext as Application).unboundServiceConnections).hasSize(1)
}
- shadowOf(Looper.getMainLooper()).idle()
- result.await()
-
- // Wait for the timeout
- advanceTimeBy(TilesConnectionBinder.INACTIVITY_TIMEOUT_MILLIS)
- runCurrent()
-
- shadowOf(Looper.getMainLooper()).idle()
-
- assertThat(shadowOf(appContext as Application).boundServiceConnections).isEmpty()
- assertThat(shadowOf(appContext as Application).unboundServiceConnections).hasSize(1)
- }
-
@Test
- public fun twoCallsShareSameBinder(): Unit = fakeCoroutineScope.runTest {
- val result1 = async {
- connectionBinderUnderTest.runWithTilesConnection {
- it.apiVersion
+ public fun twoCallsShareSameBinder(): Unit =
+ fakeCoroutineScope.runTest {
+ val result1 = async {
+ connectionBinderUnderTest.runWithTilesConnection { it.apiVersion }
}
- }
- shadowOf(Looper.getMainLooper()).idle()
- result1.await()
+ shadowOf(Looper.getMainLooper()).idle()
+ result1.await()
- val result2 = async {
- connectionBinderUnderTest.runWithTilesConnection {
- it.apiVersion
+ val result2 = async {
+ connectionBinderUnderTest.runWithTilesConnection { it.apiVersion }
}
+
+ result2.await()
+
+ assertThat(shadowOf(appContext as Application).boundServiceConnections).hasSize(1)
+ assertThat(shadowOf(appContext as Application).unboundServiceConnections).isEmpty()
}
- result2.await()
-
- assertThat(shadowOf(appContext as Application).boundServiceConnections).hasSize(1)
- assertThat(shadowOf(appContext as Application).unboundServiceConnections).isEmpty()
- }
-
@Test
- public fun longRunningCallsSuspendsBinderKill(): Unit = fakeCoroutineScope.runTest {
- val result = async {
- connectionBinderUnderTest.runWithTilesConnection {
- delay(TilesConnectionBinder.INACTIVITY_TIMEOUT_MILLIS * 2)
- it.apiVersion
+ public fun longRunningCallsSuspendsBinderKill(): Unit =
+ fakeCoroutineScope.runTest {
+ val result = async {
+ connectionBinderUnderTest.runWithTilesConnection {
+ delay(TilesConnectionBinder.INACTIVITY_TIMEOUT_MILLIS * 2)
+ it.apiVersion
+ }
}
+
+ shadowOf(Looper.getMainLooper()).idle()
+
+ // Binder should be shut down by this time, if there's nothing outstanding
+ advanceTimeBy(TilesConnectionBinder.INACTIVITY_TIMEOUT_MILLIS)
+ runCurrent()
+
+ assertThat(result.isCompleted).isFalse()
+
+ // Binder should still be alive...
+ assertThat(shadowOf(appContext as Application).boundServiceConnections).hasSize(1)
+ assertThat(shadowOf(appContext as Application).unboundServiceConnections).isEmpty()
+
+ advanceTimeBy(TilesConnectionBinder.INACTIVITY_TIMEOUT_MILLIS)
+ runCurrent()
+ assertThat(result.isCompleted).isTrue()
+
+ // Still alive...
+ assertThat(shadowOf(appContext as Application).boundServiceConnections).hasSize(1)
+ assertThat(shadowOf(appContext as Application).unboundServiceConnections).isEmpty()
+
+ // Shut down.
+ advanceTimeBy(TilesConnectionBinder.INACTIVITY_TIMEOUT_MILLIS)
+ runCurrent()
+ shadowOf(Looper.getMainLooper()).idle()
+
+ assertThat(shadowOf(appContext as Application).boundServiceConnections).isEmpty()
+ assertThat(shadowOf(appContext as Application).unboundServiceConnections).hasSize(1)
}
- shadowOf(Looper.getMainLooper()).idle()
-
- // Binder should be shut down by this time, if there's nothing outstanding
- advanceTimeBy(TilesConnectionBinder.INACTIVITY_TIMEOUT_MILLIS)
- runCurrent()
-
- assertThat(result.isCompleted).isFalse()
-
- // Binder should still be alive...
- assertThat(shadowOf(appContext as Application).boundServiceConnections).hasSize(1)
- assertThat(shadowOf(appContext as Application).unboundServiceConnections).isEmpty()
-
- advanceTimeBy(TilesConnectionBinder.INACTIVITY_TIMEOUT_MILLIS)
- runCurrent()
- assertThat(result.isCompleted).isTrue()
-
- // Still alive...
- assertThat(shadowOf(appContext as Application).boundServiceConnections).hasSize(1)
- assertThat(shadowOf(appContext as Application).unboundServiceConnections).isEmpty()
-
- // Shut down.
- advanceTimeBy(TilesConnectionBinder.INACTIVITY_TIMEOUT_MILLIS)
- runCurrent()
- shadowOf(Looper.getMainLooper()).idle()
-
- assertThat(shadowOf(appContext as Application).boundServiceConnections).isEmpty()
- assertThat(shadowOf(appContext as Application).unboundServiceConnections).hasSize(1)
- }
-
@Test
- public fun anotherCallPostponesUnbind(): Unit = fakeCoroutineScope.runTest {
- val result1 = async {
- connectionBinderUnderTest.runWithTilesConnection {
- it.apiVersion
+ public fun anotherCallPostponesUnbind(): Unit =
+ fakeCoroutineScope.runTest {
+ val result1 = async {
+ connectionBinderUnderTest.runWithTilesConnection { it.apiVersion }
}
- }
- shadowOf(Looper.getMainLooper()).idle()
- result1.await()
+ shadowOf(Looper.getMainLooper()).idle()
+ result1.await()
- // Wait a while...
- advanceTimeBy(TilesConnectionBinder.INACTIVITY_TIMEOUT_MILLIS / 2)
- runCurrent()
+ // Wait a while...
+ advanceTimeBy(TilesConnectionBinder.INACTIVITY_TIMEOUT_MILLIS / 2)
+ runCurrent()
- val result2 = async {
- connectionBinderUnderTest.runWithTilesConnection {
- it.apiVersion
+ val result2 = async {
+ connectionBinderUnderTest.runWithTilesConnection { it.apiVersion }
}
+
+ result2.await()
+
+ // Wait for the rest of the inactivity period.
+ advanceTimeBy(TilesConnectionBinder.INACTIVITY_TIMEOUT_MILLIS / 2)
+ runCurrent()
+
+ assertThat(shadowOf(appContext as Application).boundServiceConnections).hasSize(1)
+ assertThat(shadowOf(appContext as Application).unboundServiceConnections).isEmpty()
+
+ advanceTimeBy(TilesConnectionBinder.INACTIVITY_TIMEOUT_MILLIS / 2)
+ runCurrent()
+
+ assertThat(shadowOf(appContext as Application).boundServiceConnections).isEmpty()
+ assertThat(shadowOf(appContext as Application).unboundServiceConnections).hasSize(1)
}
- result2.await()
-
- // Wait for the rest of the inactivity period.
- advanceTimeBy(TilesConnectionBinder.INACTIVITY_TIMEOUT_MILLIS / 2)
- runCurrent()
-
- assertThat(shadowOf(appContext as Application).boundServiceConnections).hasSize(1)
- assertThat(shadowOf(appContext as Application).unboundServiceConnections).isEmpty()
-
- advanceTimeBy(TilesConnectionBinder.INACTIVITY_TIMEOUT_MILLIS / 2)
- runCurrent()
-
- assertThat(shadowOf(appContext as Application).boundServiceConnections).isEmpty()
- assertThat(shadowOf(appContext as Application).unboundServiceConnections).hasSize(1)
- }
-
@Test
- public fun canRebindAfterUnbind(): Unit = fakeCoroutineScope.runTest {
- val result1 = async {
- connectionBinderUnderTest.runWithTilesConnection {
- it.apiVersion
+ public fun canRebindAfterUnbind(): Unit =
+ fakeCoroutineScope.runTest {
+ val result1 = async {
+ connectionBinderUnderTest.runWithTilesConnection { it.apiVersion }
}
- }
- shadowOf(Looper.getMainLooper()).idle()
- result1.await()
+ shadowOf(Looper.getMainLooper()).idle()
+ result1.await()
- // Wait a while...
- advanceTimeBy(TilesConnectionBinder.INACTIVITY_TIMEOUT_MILLIS)
- runCurrent()
+ // Wait a while...
+ advanceTimeBy(TilesConnectionBinder.INACTIVITY_TIMEOUT_MILLIS)
+ runCurrent()
- val result2 = async {
- connectionBinderUnderTest.runWithTilesConnection {
- it.apiVersion
+ val result2 = async {
+ connectionBinderUnderTest.runWithTilesConnection { it.apiVersion }
}
+
+ shadowOf(Looper.getMainLooper()).idle()
+ result2.await()
+
+ assertThat(shadowOf(appContext as Application).boundServiceConnections).hasSize(1)
+ assertThat(shadowOf(appContext as Application).unboundServiceConnections).hasSize(1)
}
- shadowOf(Looper.getMainLooper()).idle()
- result2.await()
-
- assertThat(shadowOf(appContext as Application).boundServiceConnections).hasSize(1)
- assertThat(shadowOf(appContext as Application).unboundServiceConnections).hasSize(1)
- }
-
@Test
- public fun exceptionInCallPropagates(): Unit = fakeCoroutineScope.runTest {
- val result1 = async(Job()) {
- connectionBinderUnderTest.runWithTilesConnection {
- throw IllegalStateException("Hello")
- }
+ public fun exceptionInCallPropagates(): Unit =
+ fakeCoroutineScope.runTest {
+ val result1 =
+ async(Job()) {
+ connectionBinderUnderTest.runWithTilesConnection {
+ throw IllegalStateException("Hello")
+ }
+ }
+
+ shadowOf(Looper.getMainLooper()).idle()
+
+ assertThat(result1.getCompletionExceptionOrNull())
+ .isInstanceOf(IllegalStateException::class.java)
}
- shadowOf(Looper.getMainLooper()).idle()
-
- assertThat(result1.getCompletionExceptionOrNull())
- .isInstanceOf(IllegalStateException::class.java)
- }
-
@Test(expected = TimeoutCancellationException::class)
- public fun bindCanTimeOut(): Unit = fakeCoroutineScope.runTest {
- val result1 = async {
- connectionBinderUnderTest.runWithTilesConnection {
- 5
- }
+ public fun bindCanTimeOut(): Unit =
+ fakeCoroutineScope.runTest {
+ val result1 = async { connectionBinderUnderTest.runWithTilesConnection { 5 } }
+
+ // Never idle Robolectric's looper, so it can't call
+ // ServiceConnection#onServiceConnected.
+ advanceTimeBy(TilesConnectionBinder.BIND_TIMEOUT_MILLIS * 2)
+
+ // Await to throw the exception.
+ result1.await()
}
- // Never idle Robolectric's looper, so it can't call ServiceConnection#onServiceConnected.
- advanceTimeBy(TilesConnectionBinder.BIND_TIMEOUT_MILLIS * 2)
-
- // Await to throw the exception.
- result1.await()
- }
-
private class FakeTileService : TileProvider.Stub() {
override fun getApiVersion(): Int {
return 5
diff --git a/wear/tiles/tiles-testing/src/main/java/androidx/wear/tiles/testing/TestTileClient.kt b/wear/tiles/tiles-testing/src/main/java/androidx/wear/tiles/testing/TestTileClient.kt
index bb0168e..e973792 100644
--- a/wear/tiles/tiles-testing/src/main/java/androidx/wear/tiles/testing/TestTileClient.kt
+++ b/wear/tiles/tiles-testing/src/main/java/androidx/wear/tiles/testing/TestTileClient.kt
@@ -41,10 +41,10 @@
*
* Note that this class will not drive the full service lifecycle for the passed service instance.
* On the first call to any of these methods, it will call your service's [Service.onCreate] method,
- * however, it will never call [Service.onDestroy]. Equally, where [DefaultTileClient] will
- * unbind after a period of time, potentially destroying the service, this class wil Client will
- * unbind, but not destroy the service. If you wish to test service destruction, you can instead
- * call [Service.onDestroy] on the passed in `service` instance.
+ * however, it will never call [Service.onDestroy]. Equally, where [DefaultTileClient] will unbind
+ * after a period of time, potentially destroying the service, this class wil Client will unbind,
+ * but not destroy the service. If you wish to test service destruction, you can instead call
+ * [Service.onDestroy] on the passed in `service` instance.
*/
public class TestTileClient<T : TileService> : TileClient {
private val controller: ServiceController<T>
@@ -56,9 +56,8 @@
* Build a [TestTileClient] for use with a coroutine dispatcher.
*
* @param service An instance of the [TileService] class to bind to.
- * @param coroutineScope A [CoroutineScope] to use when dispatching calls to the
- * [TileService]. Cancelling the passed [CoroutineScope] will also cancel any pending
- * work in this class.
+ * @param coroutineScope A [CoroutineScope] to use when dispatching calls to the [TileService].
+ * Cancelling the passed [CoroutineScope] will also cancel any pending work in this class.
* @param coroutineDispatcher A [CoroutineDispatcher] to use when dispatching work from this
* class.
*/
@@ -73,12 +72,13 @@
bindIntent.component = componentName
this.controller = ServiceController.of(service, bindIntent)
- this.innerTileService = DefaultTileClient(
- getApplicationContext(),
- componentName,
- coroutineScope,
- coroutineDispatcher
- )
+ this.innerTileService =
+ DefaultTileClient(
+ getApplicationContext(),
+ componentName,
+ coroutineScope,
+ coroutineDispatcher
+ )
}
/**
@@ -94,11 +94,7 @@
bindIntent.component = componentName
this.controller = ServiceController.of(service, bindIntent)
- this.innerTileService = DefaultTileClient(
- getApplicationContext(),
- componentName,
- executor
- )
+ this.innerTileService = DefaultTileClient(getApplicationContext(), componentName, executor)
}
override fun requestApiVersion(): ListenableFuture<Int> {
@@ -122,7 +118,8 @@
@Deprecated(
"Use requestTileResourcesAsync instead.",
- replaceWith = ReplaceWith("requestTileResourcesAsync"))
+ replaceWith = ReplaceWith("requestTileResourcesAsync")
+ )
@Suppress("deprecation")
override fun requestResources(
requestParams: RequestBuilders.ResourcesRequest
diff --git a/wear/tiles/tiles-testing/src/test/java/androidx/wear/tiles/testing/TestTileClientTest.kt b/wear/tiles/tiles-testing/src/test/java/androidx/wear/tiles/testing/TestTileClientTest.kt
index f1c6f06d1..eca75b0 100644
--- a/wear/tiles/tiles-testing/src/test/java/androidx/wear/tiles/testing/TestTileClientTest.kt
+++ b/wear/tiles/tiles-testing/src/test/java/androidx/wear/tiles/testing/TestTileClientTest.kt
@@ -39,6 +39,7 @@
private companion object {
private val RESOURCES_VERSION = "10"
}
+
private val fakeTileService = FakeTileService()
private lateinit var clientUnderTest: TestTileClient<FakeTileService>
@@ -68,9 +69,10 @@
@Test
public fun canCallOnResourcesRequest() {
- val future = clientUnderTest.requestTileResourcesAsync(
- RequestBuilders.ResourcesRequest.Builder().build()
- )
+ val future =
+ clientUnderTest.requestTileResourcesAsync(
+ RequestBuilders.ResourcesRequest.Builder().build()
+ )
shadowOf(Looper.getMainLooper()).idle()
assertThat(future.isDone).isTrue()
diff --git a/wear/tiles/tiles-tooling-preview/src/main/java/androidx/wear/tiles/tooling/preview/Preview.kt b/wear/tiles/tiles-tooling-preview/src/main/java/androidx/wear/tiles/tooling/preview/Preview.kt
index e90f3e4..1b9767a 100644
--- a/wear/tiles/tiles-tooling-preview/src/main/java/androidx/wear/tiles/tooling/preview/Preview.kt
+++ b/wear/tiles/tiles-tooling-preview/src/main/java/androidx/wear/tiles/tooling/preview/Preview.kt
@@ -34,6 +34,7 @@
* return TilePreviewData { request -> myTile(request) }
* }
* ```
+ *
* or:
* ```kotlin
* @Preview
@@ -48,7 +49,7 @@
* * No network access
* * No file access
* * Some [Context] APIs may not be fully available, such as launching activities or retrieving
- * services
+ * services
*
* For more information, see
* https://developer.android.com/jetpack/compose/tooling/previews#preview-limitations
@@ -58,21 +59,18 @@
* preview.
*
* @param name Display name of this preview allowing to identify it in the panel.
- * @param group Group name for this @[Preview]. This allows grouping them in the UI and
- * displaying only one or more of them.
+ * @param group Group name for this @[Preview]. This allows grouping them in the UI and displaying
+ * only one or more of them.
* @param locale Current user preference for the locale, corresponding to
- * [locale](https://d.android.com/guide/topics/resources/providing-resources.html#LocaleQualifier)
- * resource qualifier. By default, the `default` folder will be used.
+ * [locale](https://d.android.com/guide/topics/resources/providing-resources.html#LocaleQualifier)
+ * resource qualifier. By default, the `default` folder will be used.
* @param device Device identifier indicating the device to use in the preview. For example
- * "id:wearos_small_round".See the available devices in [WearDevices].
+ * "id:wearos_small_round".See the available devices in [WearDevices].
* @param fontScale User preference for the linear scaling factor for fonts, relative to the base
- * density scaling.
+ * density scaling.
*/
@Retention(AnnotationRetention.BINARY)
-@Target(
- AnnotationTarget.ANNOTATION_CLASS,
- AnnotationTarget.FUNCTION
-)
+@Target(AnnotationTarget.ANNOTATION_CLASS, AnnotationTarget.FUNCTION)
@Repeatable
@MustBeDocumented
annotation class Preview(
diff --git a/wear/tiles/tiles-tooling-preview/src/main/java/androidx/wear/tiles/tooling/preview/TilePreviewData.kt b/wear/tiles/tiles-tooling-preview/src/main/java/androidx/wear/tiles/tooling/preview/TilePreviewData.kt
index 3fa390a..cbf0dd8 100644
--- a/wear/tiles/tiles-tooling-preview/src/main/java/androidx/wear/tiles/tooling/preview/TilePreviewData.kt
+++ b/wear/tiles/tiles-tooling-preview/src/main/java/androidx/wear/tiles/tooling/preview/TilePreviewData.kt
@@ -25,26 +25,24 @@
import java.util.Objects
internal const val PERMANENT_RESOURCES_VERSION = "0"
-private val defaultResources = Resources.Builder()
- .setVersion(PERMANENT_RESOURCES_VERSION)
- .build()
+private val defaultResources = Resources.Builder().setVersion(PERMANENT_RESOURCES_VERSION).build()
/**
* Container class storing data required to render previews for methods annotated with [Preview].
*
* @param onTileResourceRequest callback that provides a [Resources]. It will be called before
- * rendering the preview of the [TileBuilders.Tile]. By default, this callback will return a
- * [Resources] with the version "0".
+ * rendering the preview of the [TileBuilders.Tile]. By default, this callback will return a
+ * [Resources] with the version "0".
* @param platformDataValues allows overriding platform data values for any [PlatformDataKey].
- * Default platform data values will be set for all platform health sources that have not been
- * overridden.
+ * Default platform data values will be set for all platform health sources that have not been
+ * overridden.
* @param onTileRequest callback that provides the [TileBuilders.Tile] to be previewed. It will be
- * called before rendering the preview.
- *
+ * called before rendering the preview.
* @see [TilePreviewHelper.singleTimelineEntryTileBuilder]
*/
class TilePreviewData
-@JvmOverloads constructor(
+@JvmOverloads
+constructor(
val onTileResourceRequest: (ResourcesRequest) -> Resources = { defaultResources },
val platformDataValues: PlatformDataValues? = null,
val onTileRequest: (TileRequest) -> TileBuilders.Tile,
@@ -67,9 +65,5 @@
return true
}
- override fun hashCode() = Objects.hash(
- onTileResourceRequest,
- platformDataValues,
- onTileRequest
- )
+ override fun hashCode() = Objects.hash(onTileResourceRequest, platformDataValues, onTileRequest)
}
diff --git a/wear/tiles/tiles-tooling-preview/src/main/java/androidx/wear/tiles/tooling/preview/TilePreviewHelper.kt b/wear/tiles/tiles-tooling-preview/src/main/java/androidx/wear/tiles/tooling/preview/TilePreviewHelper.kt
index a19f155..64f2575 100644
--- a/wear/tiles/tiles-tooling-preview/src/main/java/androidx/wear/tiles/tooling/preview/TilePreviewHelper.kt
+++ b/wear/tiles/tiles-tooling-preview/src/main/java/androidx/wear/tiles/tooling/preview/TilePreviewHelper.kt
@@ -25,26 +25,25 @@
object TilePreviewHelper {
/**
* Helper method that creates a [TileBuilders.Tile.Builder] with a timeline consisting of a
- * single timeline entry. The provided [LayoutElementBuilders.Layout] is used as the layout
- * of the timeline entry.
+ * single timeline entry. The provided [LayoutElementBuilders.Layout] is used as the layout of
+ * the timeline entry.
*
* @param layout The layout that will be used to create the single timeline entry in the
- * [TileBuilders.Tile.Builder].
+ * [TileBuilders.Tile.Builder].
*/
@JvmStatic
fun singleTimelineEntryTileBuilder(
layout: LayoutElementBuilders.Layout,
- ): TileBuilders.Tile.Builder = TileBuilders.Tile.Builder()
- .setResourcesVersion(PERMANENT_RESOURCES_VERSION)
- .setTileTimeline(
- TimelineBuilders.Timeline.Builder()
- .addTimelineEntry(
- TimelineBuilders.TimelineEntry.Builder()
- .setLayout(layout)
- .build()
- )
- .build()
- )
+ ): TileBuilders.Tile.Builder =
+ TileBuilders.Tile.Builder()
+ .setResourcesVersion(PERMANENT_RESOURCES_VERSION)
+ .setTileTimeline(
+ TimelineBuilders.Timeline.Builder()
+ .addTimelineEntry(
+ TimelineBuilders.TimelineEntry.Builder().setLayout(layout).build()
+ )
+ .build()
+ )
/**
* Helper method that creates a [TileBuilders.Tile.Builder] with a timeline consisting of a
@@ -52,25 +51,27 @@
* [LayoutElementBuilders.Box] and used as the timeline entry's layout.
*
* @param layoutElement The layout element that will be used to create a single entry timeline
- * [TileBuilders.Tile.Builder]. This layout element will be added to a
- * [LayoutElementBuilders.Box] which will then be used as the layout root of the
- * [TileBuilders.Tile.Builder]'s timeline entry. The layout element will be aligned in the
- * center of the [LayoutElementBuilders.Box].
+ * [TileBuilders.Tile.Builder]. This layout element will be added to a
+ * [LayoutElementBuilders.Box] which will then be used as the layout root of the
+ * [TileBuilders.Tile.Builder]'s timeline entry. The layout element will be aligned in the
+ * center of the [LayoutElementBuilders.Box].
*/
@JvmStatic
fun singleTimelineEntryTileBuilder(
layoutElement: LayoutElementBuilders.LayoutElement,
- ): TileBuilders.Tile.Builder = singleTimelineEntryTileBuilder(
- layout = LayoutElementBuilders.Layout.Builder()
- .setRoot(
- LayoutElementBuilders.Box.Builder()
- .setWidth(DimensionBuilders.ExpandedDimensionProp.Builder().build())
- .setHeight(DimensionBuilders.ExpandedDimensionProp.Builder().build())
- .setHorizontalAlignment(LayoutElementBuilders.HORIZONTAL_ALIGN_CENTER)
- .setVerticalAlignment(LayoutElementBuilders.VERTICAL_ALIGN_CENTER)
- .addContent(layoutElement)
+ ): TileBuilders.Tile.Builder =
+ singleTimelineEntryTileBuilder(
+ layout =
+ LayoutElementBuilders.Layout.Builder()
+ .setRoot(
+ LayoutElementBuilders.Box.Builder()
+ .setWidth(DimensionBuilders.ExpandedDimensionProp.Builder().build())
+ .setHeight(DimensionBuilders.ExpandedDimensionProp.Builder().build())
+ .setHorizontalAlignment(LayoutElementBuilders.HORIZONTAL_ALIGN_CENTER)
+ .setVerticalAlignment(LayoutElementBuilders.VERTICAL_ALIGN_CENTER)
+ .addContent(layoutElement)
+ .build()
+ )
.build()
- )
- .build()
- )
+ )
}
diff --git a/wear/tiles/tiles-tooling/src/androidTest/java/androidx/wear/tiles/tooling/TestTilePreviews.kt b/wear/tiles/tiles-tooling/src/androidTest/java/androidx/wear/tiles/tooling/TestTilePreviews.kt
index 557b3dd..50b6594 100644
--- a/wear/tiles/tiles-tooling/src/androidTest/java/androidx/wear/tiles/tooling/TestTilePreviews.kt
+++ b/wear/tiles/tiles-tooling/src/androidTest/java/androidx/wear/tiles/tooling/TestTilePreviews.kt
@@ -31,87 +31,84 @@
import androidx.wear.tiles.tooling.preview.TilePreviewHelper.singleTimelineEntryTileBuilder
private const val RESOURCES_VERSION = "1"
-private val resources = ResourceBuilders.Resources.Builder()
- .setVersion(RESOURCES_VERSION)
- .build()
+private val resources = ResourceBuilders.Resources.Builder().setVersion(RESOURCES_VERSION).build()
-private fun layoutElement() = LayoutElementBuilders.Text.Builder()
- .setText("Hello world!")
- .setFontStyle(
- LayoutElementBuilders.FontStyle.Builder()
- .setColor(argb(0xFF000000.toInt()))
- .build()
- ).build()
+private fun layoutElement() =
+ LayoutElementBuilders.Text.Builder()
+ .setText("Hello world!")
+ .setFontStyle(
+ LayoutElementBuilders.FontStyle.Builder().setColor(argb(0xFF000000.toInt())).build()
+ )
+ .build()
private fun layout() = LayoutElementBuilders.Layout.Builder().setRoot(layoutElement()).build()
-private fun tile() = TileBuilders.Tile.Builder()
- .setResourcesVersion(RESOURCES_VERSION)
- .setTileTimeline(
- TimelineBuilders.Timeline.Builder().addTimelineEntry(
- TimelineBuilders.TimelineEntry.Builder().setLayout(
- layout()
- ).build()
- ).build()
- ).build()
+private fun tile() =
+ TileBuilders.Tile.Builder()
+ .setResourcesVersion(RESOURCES_VERSION)
+ .setTileTimeline(
+ TimelineBuilders.Timeline.Builder()
+ .addTimelineEntry(
+ TimelineBuilders.TimelineEntry.Builder().setLayout(layout()).build()
+ )
+ .build()
+ )
+ .build()
@Preview
-fun tilePreview() = TilePreviewData(
- onTileResourceRequest = { resources },
- onTileRequest = { tile() },
-)
+fun tilePreview() =
+ TilePreviewData(
+ onTileResourceRequest = { resources },
+ onTileRequest = { tile() },
+ )
@Preview
-fun tileLayoutPreview() = TilePreviewData {
- singleTimelineEntryTileBuilder(layout()).build()
-}
+fun tileLayoutPreview() = TilePreviewData { singleTimelineEntryTileBuilder(layout()).build() }
@Preview
fun tileLayoutElementPreview() = TilePreviewData {
singleTimelineEntryTileBuilder(layoutElement()).build()
}
-@Preview
-private fun tilePreviewWithPrivateVisibility() = TilePreviewData { tile() }
+@Preview private fun tilePreviewWithPrivateVisibility() = TilePreviewData { tile() }
fun duplicateFunctionName(x: Int) = x
-@Preview
-fun duplicateFunctionName() = TilePreviewData { tile() }
+@Preview fun duplicateFunctionName() = TilePreviewData { tile() }
@Preview
fun tilePreviewWithContextParameter(@Suppress("UNUSED_PARAMETER") context: Context) =
- TilePreviewData { tile() }
+ TilePreviewData {
+ tile()
+ }
+
+@Preview fun tilePreviewWithWrongReturnType() = Unit
@Preview
-fun tilePreviewWithWrongReturnType() = Unit
-
-@Preview
-fun tilePreviewWithNonContextParameter(@Suppress("UNUSED_PARAMETER") i: Int) =
- TilePreviewData { tile() }
-
-class SomeClass {
- @Preview
- fun nonStaticMethod() = TilePreviewData { tile() }
+fun tilePreviewWithNonContextParameter(@Suppress("UNUSED_PARAMETER") i: Int) = TilePreviewData {
+ tile()
}
-private fun heartRateText() = LayoutElementBuilders.Text.Builder()
- .setText(
- TypeBuilders.StringProp.Builder("--")
- .setDynamicValue(PlatformHealthSources.heartRateBpm().format())
- .build()
- )
- .setLayoutConstraintsForDynamicText(
- TypeBuilders.StringLayoutConstraint.Builder("XX")
- .setAlignment(LayoutElementBuilders.TEXT_ALIGN_CENTER)
- .build()
- )
- .setFontStyle(
- LayoutElementBuilders.FontStyle.Builder()
- .setColor(argb(0xFF000000.toInt()))
- .build()
- )
- .build()
+class SomeClass {
+ @Preview fun nonStaticMethod() = TilePreviewData { tile() }
+}
+
+private fun heartRateText() =
+ LayoutElementBuilders.Text.Builder()
+ .setText(
+ TypeBuilders.StringProp.Builder("--")
+ .setDynamicValue(PlatformHealthSources.heartRateBpm().format())
+ .build()
+ )
+ .setLayoutConstraintsForDynamicText(
+ TypeBuilders.StringLayoutConstraint.Builder("XX")
+ .setAlignment(LayoutElementBuilders.TEXT_ALIGN_CENTER)
+ .build()
+ )
+ .setFontStyle(
+ LayoutElementBuilders.FontStyle.Builder().setColor(argb(0xFF000000.toInt())).build()
+ )
+ .build()
private fun tileWithPlatformData() =
TileBuilders.Tile.Builder()
@@ -121,9 +118,7 @@
.addTimelineEntry(
TimelineBuilders.TimelineEntry.Builder()
.setLayout(
- LayoutElementBuilders.Layout.Builder()
- .setRoot(heartRateText())
- .build()
+ LayoutElementBuilders.Layout.Builder().setRoot(heartRateText()).build()
)
.build()
)
@@ -131,13 +126,16 @@
)
.build()
-@Preview
-fun tilePreviewWithDefaultPlatformData() = TilePreviewData { tileWithPlatformData() }
+@Preview fun tilePreviewWithDefaultPlatformData() = TilePreviewData { tileWithPlatformData() }
@Preview
-fun tilePreviewWithOverriddenPlatformData() = TilePreviewData(
- platformDataValues = PlatformDataValues.of(
- PlatformHealthSources.Keys.HEART_RATE_BPM,
- DynamicDataValue.fromFloat(180f)
- )
-) { tileWithPlatformData() }
+fun tilePreviewWithOverriddenPlatformData() =
+ TilePreviewData(
+ platformDataValues =
+ PlatformDataValues.of(
+ PlatformHealthSources.Keys.HEART_RATE_BPM,
+ DynamicDataValue.fromFloat(180f)
+ )
+ ) {
+ tileWithPlatformData()
+ }
diff --git a/wear/tiles/tiles-tooling/src/androidTest/java/androidx/wear/tiles/tooling/TileServiceViewAdapterTest.kt b/wear/tiles/tiles-tooling/src/androidTest/java/androidx/wear/tiles/tooling/TileServiceViewAdapterTest.kt
index 5d19992..548ae3d 100644
--- a/wear/tiles/tiles-tooling/src/androidTest/java/androidx/wear/tiles/tooling/TileServiceViewAdapterTest.kt
+++ b/wear/tiles/tiles-tooling/src/androidTest/java/androidx/wear/tiles/tooling/TileServiceViewAdapterTest.kt
@@ -141,31 +141,31 @@
private fun assertThatTileHasInflatedSuccessfully(expectedText: String = "Hello world!") {
activityTestRule.runOnUiThread {
- val textView = when (
- val child = (tileServiceViewAdapter.getChildAt(0) as ViewGroup).getChildAt(0)
- ) {
- is TextView -> child
- // layout elements are wrapped with a FrameLayout
- else -> (child as? FrameLayout)?.getChildAt(0) as? TextView
- }
+ val textView =
+ when (
+ val child = (tileServiceViewAdapter.getChildAt(0) as ViewGroup).getChildAt(0)
+ ) {
+ is TextView -> child
+ // layout elements are wrapped with a FrameLayout
+ else -> (child as? FrameLayout)?.getChildAt(0) as? TextView
+ }
assertNotNull(textView)
assertEquals(expectedText, textView?.text.toString())
}
}
private fun assertThatTileHasNotInflated() {
- activityTestRule.runOnUiThread {
- assertEquals(0, tileServiceViewAdapter.childCount)
- }
+ activityTestRule.runOnUiThread { assertEquals(0, tileServiceViewAdapter.childCount) }
}
companion object {
@Parameterized.Parameters
@JvmStatic
- fun parameters() = listOf(
- TEST_TILE_PREVIEWS_KOTLIN_FILE,
- TEST_TILE_PREVIEWS_JAVA_FILE,
- )
+ fun parameters() =
+ listOf(
+ TEST_TILE_PREVIEWS_KOTLIN_FILE,
+ TEST_TILE_PREVIEWS_JAVA_FILE,
+ )
class TestActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {
diff --git a/wear/tiles/tiles-tooling/src/main/java/androidx/wear/tiles/tooling/StaticPlatformDataProvider.kt b/wear/tiles/tiles-tooling/src/main/java/androidx/wear/tiles/tooling/StaticPlatformDataProvider.kt
index 7e068ab..5cd758f 100644
--- a/wear/tiles/tiles-tooling/src/main/java/androidx/wear/tiles/tooling/StaticPlatformDataProvider.kt
+++ b/wear/tiles/tiles-tooling/src/main/java/androidx/wear/tiles/tooling/StaticPlatformDataProvider.kt
@@ -22,9 +22,8 @@
import java.util.concurrent.Executor
/** A [PlatformDataProvider] that provides [values] as static data. */
-internal class StaticPlatformDataProvider(
- private val values: PlatformDataValues
-) : PlatformDataProvider {
+internal class StaticPlatformDataProvider(private val values: PlatformDataValues) :
+ PlatformDataProvider {
private var receiver: PlatformDataReceiver? = null
diff --git a/wear/tiles/tiles-tooling/src/main/java/androidx/wear/tiles/tooling/TileServiceViewAdapter.kt b/wear/tiles/tiles-tooling/src/main/java/androidx/wear/tiles/tooling/TileServiceViewAdapter.kt
index b3ff5d6f..ae26735 100644
--- a/wear/tiles/tiles-tooling/src/main/java/androidx/wear/tiles/tooling/TileServiceViewAdapter.kt
+++ b/wear/tiles/tiles-tooling/src/main/java/androidx/wear/tiles/tooling/TileServiceViewAdapter.kt
@@ -42,17 +42,18 @@
private const val TOOLS_NS_URI = "http://schemas.android.com/tools"
-private val defaultPlatformDataValues = PlatformDataValues.Builder()
- .put(PlatformHealthSources.Keys.HEART_RATE_BPM, DynamicDataValue.fromFloat(80f))
- .put(
- PlatformHealthSources.Keys.HEART_RATE_ACCURACY,
- DynamicHeartRateAccuracy.dynamicDataValueOf(HEART_RATE_ACCURACY_MEDIUM)
- )
- .put(PlatformHealthSources.Keys.DAILY_STEPS, DynamicDataValue.fromInt(4710))
- .put(PlatformHealthSources.Keys.DAILY_FLOORS, DynamicDataValue.fromFloat(12.5f))
- .put(PlatformHealthSources.Keys.DAILY_CALORIES, DynamicDataValue.fromFloat(245.3f))
- .put(PlatformHealthSources.Keys.DAILY_DISTANCE_METERS, DynamicDataValue.fromFloat(3670.8f))
- .build()
+private val defaultPlatformDataValues =
+ PlatformDataValues.Builder()
+ .put(PlatformHealthSources.Keys.HEART_RATE_BPM, DynamicDataValue.fromFloat(80f))
+ .put(
+ PlatformHealthSources.Keys.HEART_RATE_ACCURACY,
+ DynamicHeartRateAccuracy.dynamicDataValueOf(HEART_RATE_ACCURACY_MEDIUM)
+ )
+ .put(PlatformHealthSources.Keys.DAILY_STEPS, DynamicDataValue.fromInt(4710))
+ .put(PlatformHealthSources.Keys.DAILY_FLOORS, DynamicDataValue.fromFloat(12.5f))
+ .put(PlatformHealthSources.Keys.DAILY_CALORIES, DynamicDataValue.fromFloat(245.3f))
+ .put(PlatformHealthSources.Keys.DAILY_DISTANCE_METERS, DynamicDataValue.fromFloat(3670.8f))
+ .build()
/**
* A method extending functionality of [Class.getDeclaredMethod] allowing to finding the methods
@@ -71,7 +72,8 @@
}
val methodSignature = "$name(${parameterTypes.joinToString { ", " }})"
throw NoSuchMethodException(
- "Could not find method $methodSignature neither in $this nor in its superclasses.")
+ "Could not find method $methodSignature neither in $this nor in its superclasses."
+ )
}
/**
@@ -88,8 +90,8 @@
}
private fun init(attrs: AttributeSet) {
- val tilePreviewMethodFqn = attrs.getAttributeValue(TOOLS_NS_URI, "tilePreviewMethodFqn")
- ?: return
+ val tilePreviewMethodFqn =
+ attrs.getAttributeValue(TOOLS_NS_URI, "tilePreviewMethodFqn") ?: return
init(tilePreviewMethodFqn)
}
@@ -99,14 +101,15 @@
val platformDataValues = getPlatformDataValues(tilePreview)
lateinit var tileRenderer: TileRenderer
- tileRenderer = TileRenderer.Builder(context, executor) { newState ->
- tileRenderer.previewTile(tilePreview, newState)
- }
- .addPlatformDataProvider(
- StaticPlatformDataProvider(platformDataValues),
- *platformDataValues.all.keys.toTypedArray()
- )
- .build()
+ tileRenderer =
+ TileRenderer.Builder(context, executor) { newState ->
+ tileRenderer.previewTile(tilePreview, newState)
+ }
+ .addPlatformDataProvider(
+ StaticPlatformDataProvider(platformDataValues),
+ *platformDataValues.all.keys.toTypedArray()
+ )
+ .build()
tileRenderer.previewTile(tilePreview)
}
@@ -116,31 +119,34 @@
currentState: StateBuilders.State? = null
) {
val deviceParams = context.buildDeviceParameters()
- val tileRequest = RequestBuilders.TileRequest
- .Builder()
- .apply {
- currentState?.let { setCurrentState(it) }
- }
- .setDeviceConfiguration(deviceParams)
- .build()
+ val tileRequest =
+ RequestBuilders.TileRequest.Builder()
+ .apply { currentState?.let { setCurrentState(it) } }
+ .setDeviceConfiguration(deviceParams)
+ .build()
- val tile = tilePreview.onTileRequest(tileRequest).also { tile ->
- tile.state?.let { setState(it.keyToValueMapping) }
- }
+ val tile =
+ tilePreview.onTileRequest(tileRequest).also { tile ->
+ tile.state?.let { setState(it.keyToValueMapping) }
+ }
val layout = tile.tileTimeline?.getCurrentLayout() ?: return
- val resourcesRequest = ResourcesRequest.Builder()
- .setDeviceConfiguration(deviceParams)
- .setVersion(tile.resourcesVersion)
- .build()
+ val resourcesRequest =
+ ResourcesRequest.Builder()
+ .setDeviceConfiguration(deviceParams)
+ .setVersion(tile.resourcesVersion)
+ .build()
val resources = tilePreview.onTileResourceRequest(resourcesRequest)
val inflateFuture = inflateAsync(layout, resources, this@TileServiceViewAdapter)
- inflateFuture.addListener({
- inflateFuture.get()?.let {
- (it.layoutParams as LayoutParams).gravity = Gravity.CENTER
- }
- }, executor)
+ inflateFuture.addListener(
+ {
+ inflateFuture.get()?.let {
+ (it.layoutParams as LayoutParams).gravity = Gravity.CENTER
+ }
+ },
+ executor
+ )
}
@SuppressLint("BanUncheckedReflection")
@@ -149,17 +155,19 @@
val methodName = tilePreviewMethodFqn.substringAfterLast('.')
val methods = Class.forName(className).declaredMethods.filter { it.name == methodName }
- methods.firstOrNull {
- it.parameterCount == 1 && it.parameters.first().type == Context::class.java
- }?.let { methodWithContextParameter ->
- return invokeTilePreviewMethod(methodWithContextParameter, context)
- }
+ methods
+ .firstOrNull {
+ it.parameterCount == 1 && it.parameters.first().type == Context::class.java
+ }
+ ?.let { methodWithContextParameter ->
+ return invokeTilePreviewMethod(methodWithContextParameter, context)
+ }
- return methods.firstOrNull {
- it.name == methodName && it.parameterCount == 0
- }?.let { methodWithoutContextParameter ->
- return invokeTilePreviewMethod(methodWithoutContextParameter)
- }
+ return methods
+ .firstOrNull { it.name == methodName && it.parameterCount == 0 }
+ ?.let { methodWithoutContextParameter ->
+ return invokeTilePreviewMethod(methodWithoutContextParameter)
+ }
}
@SuppressLint("BanUncheckedReflection")
@@ -188,22 +196,19 @@
internal fun TimelineBuilders.Timeline?.getCurrentLayout(): LayoutElementBuilders.Layout? {
val now = System.currentTimeMillis()
return this?.let {
- val cache = TilesTimelineCache(it)
- cache.findTileTimelineEntryForTime(now) ?: cache.findClosestTileTimelineEntry(now)
- }?.layout
+ val cache = TilesTimelineCache(it)
+ cache.findTileTimelineEntryForTime(now) ?: cache.findClosestTileTimelineEntry(now)
+ }
+ ?.layout
}
-/**
- * Creates an instance of [DeviceParametersBuilders.DeviceParameters] from the [Context].
- */
+/** Creates an instance of [DeviceParametersBuilders.DeviceParameters] from the [Context]. */
internal fun Context.buildDeviceParameters(): DeviceParametersBuilders.DeviceParameters {
val displayMetrics = resources.displayMetrics
val isScreenRound = resources.configuration.isScreenRound
return DeviceParametersBuilders.DeviceParameters.Builder()
- .setScreenWidthDp(
- (displayMetrics.widthPixels / displayMetrics.density).roundToInt())
- .setScreenHeightDp(
- (displayMetrics.heightPixels / displayMetrics.density).roundToInt())
+ .setScreenWidthDp((displayMetrics.widthPixels / displayMetrics.density).roundToInt())
+ .setScreenHeightDp((displayMetrics.heightPixels / displayMetrics.density).roundToInt())
.setScreenDensity(displayMetrics.density)
.setScreenShape(
if (isScreenRound) DeviceParametersBuilders.SCREEN_SHAPE_ROUND
diff --git a/wear/tiles/tiles-tooling/src/test/java/androidx/wear/tiles/tooling/FindMethodTest.kt b/wear/tiles/tiles-tooling/src/test/java/androidx/wear/tiles/tooling/FindMethodTest.kt
index b9b5986..106e48a 100644
--- a/wear/tiles/tiles-tooling/src/test/java/androidx/wear/tiles/tooling/FindMethodTest.kt
+++ b/wear/tiles/tiles-tooling/src/test/java/androidx/wear/tiles/tooling/FindMethodTest.kt
@@ -22,22 +22,36 @@
@Suppress("unused")
open class A {
- open fun aOpen(): String { return "aOpen" }
+ open fun aOpen(): String {
+ return "aOpen"
+ }
- fun aFinal(): String { return "aFinal" }
+ fun aFinal(): String {
+ return "aFinal"
+ }
- protected open fun aOpenProtected(): String { return "aOpenProtected" }
+ protected open fun aOpenProtected(): String {
+ return "aOpenProtected"
+ }
- protected fun aFinalProtected(): String { return "aFinalProtected" }
+ protected fun aFinalProtected(): String {
+ return "aFinalProtected"
+ }
- protected open fun aOpenProtected2(): String { return "aOpenProtected2" }
+ protected open fun aOpenProtected2(): String {
+ return "aOpenProtected2"
+ }
}
@Suppress("unused")
class B : A() {
- override fun aOpen(): String { return "bOpen" }
+ override fun aOpen(): String {
+ return "bOpen"
+ }
- override fun aOpenProtected(): String { return "bOpenProtected" }
+ override fun aOpenProtected(): String {
+ return "bOpenProtected"
+ }
}
class FindMethodTest {
@@ -51,7 +65,7 @@
try {
A::class.java.findMethod("noSuchMethod")
fail()
- } catch (_: NoSuchMethodException) { }
+ } catch (_: NoSuchMethodException) {}
val b = B()
assertEquals("bOpen", B::class.java.findMethod("aOpen").invoke(b))
diff --git a/wear/tiles/tiles-tooling/src/test/java/androidx/wear/tiles/tooling/StaticPlatformDataProviderTest.kt b/wear/tiles/tiles-tooling/src/test/java/androidx/wear/tiles/tooling/StaticPlatformDataProviderTest.kt
index 35476c1..673d0cd 100644
--- a/wear/tiles/tiles-tooling/src/test/java/androidx/wear/tiles/tooling/StaticPlatformDataProviderTest.kt
+++ b/wear/tiles/tiles-tooling/src/test/java/androidx/wear/tiles/tooling/StaticPlatformDataProviderTest.kt
@@ -31,10 +31,11 @@
internal class StaticPlatformDataProviderTest {
- private val platformDataValues = PlatformDataValues.Builder()
- .put(PlatformHealthSources.Keys.DAILY_CALORIES, DynamicDataValue.fromFloat(1000f))
- .put(PlatformHealthSources.Keys.DAILY_STEPS, DynamicDataValue.fromInt(256))
- .build()
+ private val platformDataValues =
+ PlatformDataValues.Builder()
+ .put(PlatformHealthSources.Keys.DAILY_CALORIES, DynamicDataValue.fromFloat(1000f))
+ .put(PlatformHealthSources.Keys.DAILY_STEPS, DynamicDataValue.fromInt(256))
+ .build()
private val staticPlatformDataProvider = StaticPlatformDataProvider(platformDataValues)
diff --git a/wear/watchface/watchface-client-guava/src/androidTest/java/androidx/wear/watchface/client/guava/ListenableWatchFaceControlClientTest.kt b/wear/watchface/watchface-client-guava/src/androidTest/java/androidx/wear/watchface/client/guava/ListenableWatchFaceControlClientTest.kt
index 00ef1e5..96eb2f6 100644
--- a/wear/watchface/watchface-client-guava/src/androidTest/java/androidx/wear/watchface/client/guava/ListenableWatchFaceControlClientTest.kt
+++ b/wear/watchface/watchface-client-guava/src/androidTest/java/androidx/wear/watchface/client/guava/ListenableWatchFaceControlClientTest.kt
@@ -57,8 +57,7 @@
@MediumTest
public class ListenableWatchFaceControlClientTest {
- @get:Rule
- val mocks = MockitoJUnit.rule()
+ @get:Rule val mocks = MockitoJUnit.rule()
@Mock private lateinit var surfaceHolder: SurfaceHolder
@Mock private lateinit var surface: Surface
diff --git a/wear/watchface/watchface-client-guava/src/main/java/androidx/wear/watchface/client/ListenableWatchFaceControlClient.kt b/wear/watchface/watchface-client-guava/src/main/java/androidx/wear/watchface/client/ListenableWatchFaceControlClient.kt
index 11fa95b..bbe26b7 100644
--- a/wear/watchface/watchface-client-guava/src/main/java/androidx/wear/watchface/client/ListenableWatchFaceControlClient.kt
+++ b/wear/watchface/watchface-client-guava/src/main/java/androidx/wear/watchface/client/ListenableWatchFaceControlClient.kt
@@ -140,11 +140,11 @@
* control service to bind to.
* @param resourceOnlyWatchFacePackageName The name of the package from which to load the
* resource only watch face. This is exposed to the runtime via the
- * `resourceOnlyWatchFacePackageName` parameter passed to
- * [WatchFaceRuntimeService.createUserStyleSchema],
- * [WatchFaceRuntimeService.createComplicationSlotsManager],
- * [WatchFaceRuntimeService.createUserStyleFlavors] and
- * [WatchFaceRuntimeService.createWatchFace]).
+ * `resourceOnlyWatchFacePackageName` parameter passed to
+ * [WatchFaceRuntimeService.createUserStyleSchema],
+ * [WatchFaceRuntimeService.createComplicationSlotsManager],
+ * [WatchFaceRuntimeService.createUserStyleFlavors] and
+ * [WatchFaceRuntimeService.createWatchFace]).
* @return [ListenableFuture]<[ListenableWatchFaceControlClient]> which on success resolves
* to a [ListenableWatchFaceControlClient] or throws a [ServiceNotBoundException] if the
* watch face control service can not be bound.
diff --git a/wear/watchface/watchface-client-guava/src/main/java/androidx/wear/watchface/client/ListenableWatchFaceMetadataClient.kt b/wear/watchface/watchface-client-guava/src/main/java/androidx/wear/watchface/client/ListenableWatchFaceMetadataClient.kt
index 5a49cbb..6a8bc3c 100644
--- a/wear/watchface/watchface-client-guava/src/main/java/androidx/wear/watchface/client/ListenableWatchFaceMetadataClient.kt
+++ b/wear/watchface/watchface-client-guava/src/main/java/androidx/wear/watchface/client/ListenableWatchFaceMetadataClient.kt
@@ -55,7 +55,7 @@
/**
* Constructs a [WatchFaceMetadataClient] for fetching metadata for the specified resource
- * only watch face runtime. A resource only watch face runtime, is a special kind of watch
+ * only watch face runtime. A resource only watch face runtime, is a special kind of watch
* face that is the runtime for a watch face defined by another package that contains only
* resources and no executable code.
*
diff --git a/wear/watchface/watchface-client/src/androidTest/java/androidx/wear/watchface/client/test/TestWatchFaceServices.kt b/wear/watchface/watchface-client/src/androidTest/java/androidx/wear/watchface/client/test/TestWatchFaceServices.kt
index 27c7bda..4f5714a 100644
--- a/wear/watchface/watchface-client/src/androidTest/java/androidx/wear/watchface/client/test/TestWatchFaceServices.kt
+++ b/wear/watchface/watchface-client/src/androidTest/java/androidx/wear/watchface/client/test/TestWatchFaceServices.kt
@@ -316,11 +316,7 @@
CanvasType.HARDWARE,
16
) {
- override fun render(
- canvas: Canvas,
- bounds: Rect,
- zonedDateTime: ZonedDateTime
- ) {
+ override fun render(canvas: Canvas, bounds: Rect, zonedDateTime: ZonedDateTime) {
// Actually rendering something isn't required.
}
@@ -405,11 +401,7 @@
CanvasType.HARDWARE,
16
) {
- override fun render(
- canvas: Canvas,
- bounds: Rect,
- zonedDateTime: ZonedDateTime
- ) {
+ override fun render(canvas: Canvas, bounds: Rect, zonedDateTime: ZonedDateTime) {
// Actually rendering something isn't required.
}
diff --git a/wear/watchface/watchface-client/src/androidTest/java/androidx/wear/watchface/client/test/WatchFaceControlClientTest.kt b/wear/watchface/watchface-client/src/androidTest/java/androidx/wear/watchface/client/test/WatchFaceControlClientTest.kt
index 2aa7dbe..34cedd73 100644
--- a/wear/watchface/watchface-client/src/androidTest/java/androidx/wear/watchface/client/test/WatchFaceControlClientTest.kt
+++ b/wear/watchface/watchface-client/src/androidTest/java/androidx/wear/watchface/client/test/WatchFaceControlClientTest.kt
@@ -140,8 +140,7 @@
)
}
- @get:Rule
- val mocks = MockitoJUnit.rule()
+ @get:Rule val mocks = MockitoJUnit.rule()
@Mock protected lateinit var surfaceHolder: SurfaceHolder
@@ -530,15 +529,16 @@
)
}
- val deferredInteractiveInstance = handlerCoroutineScope.async {
- service.getOrCreateInteractiveWatchFaceClient(
- "testId",
- deviceConfig,
- systemState,
- userStyle = null,
- complications
- )
- }
+ val deferredInteractiveInstance =
+ handlerCoroutineScope.async {
+ service.getOrCreateInteractiveWatchFaceClient(
+ "testId",
+ deviceConfig,
+ systemState,
+ userStyle = null,
+ complications
+ )
+ }
// Create the engine which triggers construction of the interactive instance.
handler.post {
@@ -550,8 +550,10 @@
// Make sure watch face init has completed.
assertTrue(
- watchFaceService.lastResourceOnlyWatchFacePackageNameLatch
- .await(UPDATE_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)
+ watchFaceService.lastResourceOnlyWatchFacePackageNameLatch.await(
+ UPDATE_TIMEOUT_MILLIS,
+ TimeUnit.MILLISECONDS
+ )
)
assertThat(watchFaceService.lastResourceOnlyWatchFacePackageName)
@@ -574,15 +576,16 @@
)
}
- val deferredInteractiveInstance = handlerCoroutineScope.async {
- service.getOrCreateInteractiveWatchFaceClient(
- "testId",
- deviceConfig,
- systemState,
- userStyle = null,
- complications
- )
- }
+ val deferredInteractiveInstance =
+ handlerCoroutineScope.async {
+ service.getOrCreateInteractiveWatchFaceClient(
+ "testId",
+ deviceConfig,
+ systemState,
+ userStyle = null,
+ complications
+ )
+ }
// Create the engine which triggers construction of the interactive instance.
handler.post {
@@ -594,8 +597,10 @@
// Make sure watch face init has completed.
assertTrue(
- watchFaceService.lastResourceOnlyWatchFacePackageNameLatch
- .await(UPDATE_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)
+ watchFaceService.lastResourceOnlyWatchFacePackageNameLatch.await(
+ UPDATE_TIMEOUT_MILLIS,
+ TimeUnit.MILLISECONDS
+ )
)
assertThat(watchFaceService.lastResourceOnlyWatchFacePackageName)
@@ -1371,9 +1376,9 @@
mapOf(
123 to
ShortTextComplicationData.Builder(
- PlainComplicationText.Builder("TEST").build(),
- ComplicationText.EMPTY
- )
+ PlainComplicationText.Builder("TEST").build(),
+ ComplicationText.EMPTY
+ )
.build()
)
)
@@ -1403,9 +1408,9 @@
mapOf(
123 to
ShortTextComplicationData.Builder(
- PlainComplicationText.Builder("TEST").build(),
- ComplicationText.EMPTY
- )
+ PlainComplicationText.Builder("TEST").build(),
+ ComplicationText.EMPTY
+ )
.build(),
)
)
@@ -1693,35 +1698,36 @@
fun userStyleFlavors() {
val interactiveInstance = getOrCreateTestSubject()
- assertThat(interactiveInstance.getUserStyleFlavors().flavors).contains(
- UserStyleFlavor(
- "exampleFlavor",
- UserStyleData(
- mapOf(
- "color_style_setting" to UserStyleSetting.Option.Id("blue_style").value,
- "watch_hand_length_style_setting" to DoubleRangeOption(1.0).id.value
- )
- ),
- mapOf(
- EXAMPLE_CANVAS_WATCHFACE_LEFT_COMPLICATION_ID to
- DefaultComplicationDataSourcePolicy(
- SystemDataSources.DATA_SOURCE_DAY_OF_WEEK,
- ComplicationType.SHORT_TEXT
- ),
- EXAMPLE_CANVAS_WATCHFACE_RIGHT_COMPLICATION_ID to
- DefaultComplicationDataSourcePolicy(
- ComponentName(
- "androidx.wear.watchface.complications.datasource.samples",
- "androidx.wear.watchface.complications.datasource.samples" +
- ".ConfigurableDataSourceService"
- ),
- ComplicationType.SHORT_TEXT,
- SystemDataSources.DATA_SOURCE_SUNRISE_SUNSET,
- ComplicationType.SHORT_TEXT
+ assertThat(interactiveInstance.getUserStyleFlavors().flavors)
+ .contains(
+ UserStyleFlavor(
+ "exampleFlavor",
+ UserStyleData(
+ mapOf(
+ "color_style_setting" to UserStyleSetting.Option.Id("blue_style").value,
+ "watch_hand_length_style_setting" to DoubleRangeOption(1.0).id.value
)
+ ),
+ mapOf(
+ EXAMPLE_CANVAS_WATCHFACE_LEFT_COMPLICATION_ID to
+ DefaultComplicationDataSourcePolicy(
+ SystemDataSources.DATA_SOURCE_DAY_OF_WEEK,
+ ComplicationType.SHORT_TEXT
+ ),
+ EXAMPLE_CANVAS_WATCHFACE_RIGHT_COMPLICATION_ID to
+ DefaultComplicationDataSourcePolicy(
+ ComponentName(
+ "androidx.wear.watchface.complications.datasource.samples",
+ "androidx.wear.watchface.complications.datasource.samples" +
+ ".ConfigurableDataSourceService"
+ ),
+ ComplicationType.SHORT_TEXT,
+ SystemDataSources.DATA_SOURCE_SUNRISE_SUNSET,
+ ComplicationType.SHORT_TEXT
+ )
+ )
)
)
- )
interactiveInstance.close()
}
}
diff --git a/wear/watchface/watchface-client/src/main/java/androidx/wear/watchface/client/HeadlessWatchFaceClient.kt b/wear/watchface/watchface-client/src/main/java/androidx/wear/watchface/client/HeadlessWatchFaceClient.kt
index 9b624f7..8742add 100644
--- a/wear/watchface/watchface-client/src/main/java/androidx/wear/watchface/client/HeadlessWatchFaceClient.kt
+++ b/wear/watchface/watchface-client/src/main/java/androidx/wear/watchface/client/HeadlessWatchFaceClient.kt
@@ -117,7 +117,8 @@
): Bitmap
/** Whether or not the watch face supports [renderWatchFaceToSurface]. */
- public val isRenderWatchFaceToSurfaceSupported: Boolean get() = false
+ public val isRenderWatchFaceToSurfaceSupported: Boolean
+ get() = false
/**
* Renders the [androidx.wear.watchface.ComplicationSlot] to a shared memory backed [Bitmap]
diff --git a/wear/watchface/watchface-client/src/main/java/androidx/wear/watchface/client/InteractiveWatchFaceClient.kt b/wear/watchface/watchface-client/src/main/java/androidx/wear/watchface/client/InteractiveWatchFaceClient.kt
index efc1570..7a7ed25 100644
--- a/wear/watchface/watchface-client/src/main/java/androidx/wear/watchface/client/InteractiveWatchFaceClient.kt
+++ b/wear/watchface/watchface-client/src/main/java/androidx/wear/watchface/client/InteractiveWatchFaceClient.kt
@@ -152,25 +152,18 @@
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
public fun overrideComplicationData(slotIdToComplicationData: Map<Int, ComplicationData>) {}
- /**
- * Clears any overrides set by [overrideComplicationData].
- */
- @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
- public fun clearComplicationDataOverride() {}
+ /** Clears any overrides set by [overrideComplicationData]. */
+ @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) public fun clearComplicationDataOverride() {}
/**
* Pauses all animation on the watch face (including time ticks) until either [unpauseAnimation]
* or [close] is called or the client process exits. Requires a compatible watchface, does
* nothing on an older watch face.
*/
- @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
- public fun pauseAnimation() {}
+ @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) public fun pauseAnimation() {}
- /**
- * Restarts animations paused by [pauseAnimation].
- */
- @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
- public fun unpauseAnimation() {}
+ /** Restarts animations paused by [pauseAnimation]. */
+ @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) public fun unpauseAnimation() {}
/**
* Renders the watchface to a shared memory backed [Bitmap] with the given settings. Note this
@@ -194,7 +187,8 @@
): Bitmap
/** Whether or not the watch face supports [RemoteWatchFaceViewHost]. */
- public val isRemoteWatchFaceViewHostSupported: Boolean get() = false
+ public val isRemoteWatchFaceViewHostSupported: Boolean
+ get() = false
/**
* Constructs a [RemoteWatchFaceViewHost] whose [RemoteWatchFaceViewHost.surfacePackage] can be
@@ -228,16 +222,15 @@
/**
* The watchface's [OverlayStyle] which may be null.
*
- * Note while this plumbing got built, it was never used by the system ui on any platform
- * and it will be removed.
+ * Note while this plumbing got built, it was never used by the system ui on any platform and it
+ * will be removed.
*/
@Deprecated("OverlayStyle will be removed in a future release.")
@get:Throws(RemoteException::class)
@Suppress("Deprecation")
public val overlayStyle: OverlayStyle
// Default implementation, overridden below.
- @Suppress("Deprecation")
- get() = OverlayStyle()
+ @Suppress("Deprecation") get() = OverlayStyle()
/**
* Renames this instance to [newInstanceId] (must be unique, usually this would be different
@@ -253,9 +246,7 @@
/**
* Renames this instance to [newInstanceId] (must be unique, usually this would be different
* from the old ID but that's not a requirement). Sets the current [UserStyle] represented as a
- * [UserStyleData> and clears any complication data. Setting the new UserStyle may have a side
- * effect of enabling or disabling complicationSlots, which will be visible via
- * [ComplicationSlotState.isEnabled].
+ * [UserStyleData> and clears any complication data. Setting the new UserStyle may have a side effect of enabling or disabling complicationSlots, which will be visible via [ComplicationSlotState.isEnabled].
*/
@Throws(RemoteException::class)
public fun updateWatchFaceInstance(newInstanceId: String, userStyle: UserStyleData)
@@ -545,10 +536,7 @@
if (apiVersion >= 12) {
iInteractiveWatchFace.overrideComplicationData(
slotIdToComplicationData.map {
- IdAndComplicationDataWireFormat(
- it.key,
- it.value.asWireComplicationData()
- )
+ IdAndComplicationDataWireFormat(it.key, it.value.asWireComplicationData())
}
)
} else {
@@ -581,15 +569,16 @@
instant.toEpochMilli(),
userStyle?.toWireFormat(),
if (apiVersion >= 12) {
- idAndComplicationData
- } else {
- mergeWithOverrideComplicationData(idAndComplicationData)
- }?.map {
- IdAndComplicationDataWireFormat(
- it.key,
- it.value.asWireComplicationData()
- )
- }
+ idAndComplicationData
+ } else {
+ mergeWithOverrideComplicationData(idAndComplicationData)
+ }
+ ?.map {
+ IdAndComplicationDataWireFormat(
+ it.key,
+ it.value.asWireComplicationData()
+ )
+ }
)
)
)
@@ -727,8 +716,7 @@
get() =
iInteractiveWatchFace.contentDescriptionLabels?.map {
ContentDescriptionLabel(it.text.toApiComplicationText(), it.bounds, it.tapAction)
- }
- ?: emptyList()
+ } ?: emptyList()
override fun setWatchUiState(watchUiState: androidx.wear.watchface.client.WatchUiState) =
TraceEvent("InteractiveWatchFaceClientImpl.setSystemState").use {
diff --git a/wear/watchface/watchface-client/src/main/java/androidx/wear/watchface/client/OverlayStyle.kt b/wear/watchface/watchface-client/src/main/java/androidx/wear/watchface/client/OverlayStyle.kt
index 45a30b07..2263ba6 100644
--- a/wear/watchface/watchface-client/src/main/java/androidx/wear/watchface/client/OverlayStyle.kt
+++ b/wear/watchface/watchface-client/src/main/java/androidx/wear/watchface/client/OverlayStyle.kt
@@ -21,8 +21,8 @@
/**
* This class reflects a snapshot of [androidx.wear.watchface.WatchFace.OverlayStyle].
*
- * Note while this plumbing got built, it was never used by the system ui on any platform
- * and it will be removed.
+ * Note while this plumbing got built, it was never used by the system ui on any platform and it
+ * will be removed.
*/
@Deprecated("OverlayStyle will be removed in a future release.")
public class OverlayStyle(
diff --git a/wear/watchface/watchface-client/src/main/java/androidx/wear/watchface/client/WatchFaceControlClient.kt b/wear/watchface/watchface-client/src/main/java/androidx/wear/watchface/client/WatchFaceControlClient.kt
index 833269b..936a2b6 100644
--- a/wear/watchface/watchface-client/src/main/java/androidx/wear/watchface/client/WatchFaceControlClient.kt
+++ b/wear/watchface/watchface-client/src/main/java/androidx/wear/watchface/client/WatchFaceControlClient.kt
@@ -100,7 +100,7 @@
* control service to bind to.
* @param resourceOnlyWatchFacePackageName The name of the package from which to load the
* resource only watch face. This is exposed to the runtime via
- * [WatchFaceService.resourceOnlyWatchFacePackageName]. Note only one watch face
+ * [WatchFaceService.resourceOnlyWatchFacePackageName]. Note only one watch face
* definition per resource only watch face package is supported.
* @return The [WatchFaceControlClient] if there is one.
* @throws [ServiceNotBoundException] if the watch face control service can not be bound or
diff --git a/wear/watchface/watchface-complications-data-source-samples/src/main/java/androidx/wear/watchface/complications/datasource/samples/dynamic/RequestPermissionActivity.kt b/wear/watchface/watchface-complications-data-source-samples/src/main/java/androidx/wear/watchface/complications/datasource/samples/dynamic/RequestPermissionActivity.kt
index 037c838..ad425f2 100644
--- a/wear/watchface/watchface-complications-data-source-samples/src/main/java/androidx/wear/watchface/complications/datasource/samples/dynamic/RequestPermissionActivity.kt
+++ b/wear/watchface/watchface-complications-data-source-samples/src/main/java/androidx/wear/watchface/complications/datasource/samples/dynamic/RequestPermissionActivity.kt
@@ -54,9 +54,9 @@
private val ACTION_TO_PERMISSION: Map<String, String> =
mapOf(
"androidx.wear.watchface.complications.datasource.samples.dynamic.REQUEST_ACTIVITY_RECOGNITION_PERMISSION" to // ktlint-disable max-line-length
- permission.ACTIVITY_RECOGNITION,
+ permission.ACTIVITY_RECOGNITION,
"androidx.wear.watchface.complications.datasource.samples.dynamic.REQUEST_BODY_SENSORS_PERMISSION" to // ktlint-disable max-line-length
- permission.BODY_SENSORS,
+ permission.BODY_SENSORS,
)
}
}
diff --git a/wear/watchface/watchface-complications-data-source/src/main/java/androidx/wear/watchface/complications/datasource/ComplicationDataSourceService.kt b/wear/watchface/watchface-complications-data-source/src/main/java/androidx/wear/watchface/complications/datasource/ComplicationDataSourceService.kt
index 6ba3f2f..692aeb9 100644
--- a/wear/watchface/watchface-complications-data-source/src/main/java/androidx/wear/watchface/complications/datasource/ComplicationDataSourceService.kt
+++ b/wear/watchface/watchface-complications-data-source/src/main/java/androidx/wear/watchface/complications/datasource/ComplicationDataSourceService.kt
@@ -470,8 +470,7 @@
bundle?.getInt(
IComplicationProvider.BUNDLE_KEY_IS_SAFE_FOR_WATCHFACE,
TargetWatchFaceSafety.UNKNOWN
- )
- ?: TargetWatchFaceSafety.UNKNOWN
+ ) ?: TargetWatchFaceSafety.UNKNOWN
val expectedDataType = fromWireType(type)
val iComplicationManager = IComplicationManager.Stub.asInterface(manager)
mainThreadHandler.post {
@@ -669,8 +668,7 @@
bundle?.getInt(
IComplicationProvider.BUNDLE_KEY_IS_SAFE_FOR_WATCHFACE,
TargetWatchFaceSafety.UNKNOWN
- )
- ?: TargetWatchFaceSafety.UNKNOWN
+ ) ?: TargetWatchFaceSafety.UNKNOWN
val expectedDataType = fromWireType(type)
val complicationType = fromWireType(type)
val latch = CountDownLatch(1)
diff --git a/wear/watchface/watchface-complications-data/src/main/java/androidx/wear/watchface/complications/data/Data.kt b/wear/watchface/watchface-complications-data/src/main/java/androidx/wear/watchface/complications/data/Data.kt
index 236def1..966a173 100644
--- a/wear/watchface/watchface-complications-data/src/main/java/androidx/wear/watchface/complications/data/Data.kt
+++ b/wear/watchface/watchface-complications-data/src/main/java/androidx/wear/watchface/complications/data/Data.kt
@@ -325,8 +325,8 @@
placeholder?.tapAction,
cachedWireComplicationData,
dataSource = null,
- persistencePolicy = placeholder?.persistencePolicy
- ?: ComplicationPersistencePolicies.CACHING_ALLOWED,
+ persistencePolicy =
+ placeholder?.persistencePolicy ?: ComplicationPersistencePolicies.CACHING_ALLOWED,
displayPolicy = placeholder?.displayPolicy ?: ComplicationDisplayPolicies.ALWAYS_DISPLAY,
dynamicValueInvalidationFallback = placeholder,
) {
@@ -1194,7 +1194,7 @@
override fun getContentDescription(context: Context): TimeDependentText? =
_contentDescription?.emptyToNull()?.toWireComplicationText()
?: ComplicationTextTemplate.Builder().addTextAndTitle(text, title).buildOrNull()
- ?: WireComplicationText(context.getString(R.string.a11y_template_range, value, max))
+ ?: WireComplicationText(context.getString(R.string.a11y_template_range, value, max))
/** The content description field for accessibility. */
val contentDescription: ComplicationText? = _contentDescription ?: ComplicationText.EMPTY
@@ -1549,7 +1549,7 @@
override fun getContentDescription(context: Context): TimeDependentText? =
_contentDescription?.emptyToNull()?.toWireComplicationText()
?: ComplicationTextTemplate.Builder().addTextAndTitle(text, title).buildOrNull()
- ?: WireComplicationText(
+ ?: WireComplicationText(
context.getString(R.string.a11y_template_range, value, targetValue)
)
diff --git a/wear/watchface/watchface-complications-data/src/test/java/androidx/wear/watchface/complications/data/DataTest.kt b/wear/watchface/watchface-complications-data/src/test/java/androidx/wear/watchface/complications/data/DataTest.kt
index 95bbeec..35e73db 100644
--- a/wear/watchface/watchface-complications-data/src/test/java/androidx/wear/watchface/complications/data/DataTest.kt
+++ b/wear/watchface/watchface-complications-data/src/test/java/androidx/wear/watchface/complications/data/DataTest.kt
@@ -2252,7 +2252,7 @@
.that(
case.data
.getContentDescription(context)
- ?.getTextAt(context.resources, /* dateTimeMillis = */ 0)
+ ?.getTextAt(context.resources, /* dateTimeMillis= */ 0)
)
.isEqualTo(case.contentDescription)
}
diff --git a/wear/watchface/watchface-complications-rendering/src/main/java/androidx/wear/watchface/complications/rendering/CanvasComplicationDrawable.kt b/wear/watchface/watchface-complications-rendering/src/main/java/androidx/wear/watchface/complications/rendering/CanvasComplicationDrawable.kt
index 96ea902..c46e94d 100644
--- a/wear/watchface/watchface-complications-rendering/src/main/java/androidx/wear/watchface/complications/rendering/CanvasComplicationDrawable.kt
+++ b/wear/watchface/watchface-complications-rendering/src/main/java/androidx/wear/watchface/complications/rendering/CanvasComplicationDrawable.kt
@@ -125,8 +125,7 @@
val startTime = it.tapTime.toEpochMilli()
val endTime = it.tapTime.toEpochMilli() + COMPLICATION_HIGHLIGHT_DURATION_MS
zonedDateTime.toInstant().toEpochMilli() in startTime until endTime
- }
- ?: false
+ } ?: false
drawable.draw(canvas)
}
diff --git a/wear/watchface/watchface-complications/src/main/java/androidx/wear/watchface/complications/SystemDataSources.kt b/wear/watchface/watchface-complications/src/main/java/androidx/wear/watchface/complications/SystemDataSources.kt
index 4d2f25a..c567de2 100644
--- a/wear/watchface/watchface-complications/src/main/java/androidx/wear/watchface/complications/SystemDataSources.kt
+++ b/wear/watchface/watchface-complications/src/main/java/androidx/wear/watchface/complications/SystemDataSources.kt
@@ -213,7 +213,7 @@
* [ComplicationType.ICON] too since OEMs may choose to serve a shortcut to their health app
* instead of the live value.
*
- * Starting in Wear OS 5, this complication data source can only be configured with
+ * Starting in Wear OS 5, this complication data source can only be configured with
* [ComplicationType.ICON] type, if used in a watch face that isn't built using Watch Face
* Format. Depending on the device manufacturer, this data source in [ComplicationType.ICON]
* type may or may not be available.
diff --git a/wear/watchface/watchface-complications/src/test/java/androidx/wear/watchface/complications/ComplicationDataSourceInfoRetrieverTest.kt b/wear/watchface/watchface-complications/src/test/java/androidx/wear/watchface/complications/ComplicationDataSourceInfoRetrieverTest.kt
index a948b2e..b707914 100644
--- a/wear/watchface/watchface-complications/src/test/java/androidx/wear/watchface/complications/ComplicationDataSourceInfoRetrieverTest.kt
+++ b/wear/watchface/watchface-complications/src/test/java/androidx/wear/watchface/complications/ComplicationDataSourceInfoRetrieverTest.kt
@@ -369,7 +369,8 @@
)
// Test two identical ComplicationDataSourceInfo with different references.
- // The icon's equals was added from Android P(see IconKt.kt#iconEquals), so this assertion only works from Android P.
+ // The icon's equals was added from Android P(see IconKt.kt#iconEquals), so this assertion
+ // only works from Android P.
assertThat(a).isEqualTo(b)
// Test two ComplicationDataSourceInfos with different contents.
diff --git a/wear/watchface/watchface-editor/src/androidTest/java/androidx/wear/watchface/editor/EditorSessionTest.kt b/wear/watchface/watchface-editor/src/androidTest/java/androidx/wear/watchface/editor/EditorSessionTest.kt
index 062b061..519311f 100644
--- a/wear/watchface/watchface-editor/src/androidTest/java/androidx/wear/watchface/editor/EditorSessionTest.kt
+++ b/wear/watchface/watchface-editor/src/androidTest/java/androidx/wear/watchface/editor/EditorSessionTest.kt
@@ -676,11 +676,9 @@
lastOverrideComplications = slotIdToComplicationData
}
- override fun clearComplicationSlotAfterEditing(slotId: Int) {
- }
+ override fun clearComplicationSlotAfterEditing(slotId: Int) {}
- override fun dontClearAnyComplicationSlotsAfterEditing() {
- }
+ override fun dontClearAnyComplicationSlotsAfterEditing() {}
}
if (!shouldTimeout) {
WatchFace.registerEditorDelegate(watchComponentName, editorDelegate)
@@ -1658,25 +1656,29 @@
@Test
public fun setOverrideComplications() {
- val scenario = createOnWatchFaceEditingTestActivity(
- emptyList(),
- listOf(leftComplication, rightComplication)
- )
- val leftComplicationData = ShortTextComplicationData.Builder(
- PlainComplicationText.Builder("Left").build(),
- ComplicationText.EMPTY
- )
- .build()
- val rightComplicationData = ShortTextComplicationData.Builder(
- PlainComplicationText.Builder("Right").build(),
- ComplicationText.EMPTY
- )
- .build()
+ val scenario =
+ createOnWatchFaceEditingTestActivity(
+ emptyList(),
+ listOf(leftComplication, rightComplication)
+ )
+ val leftComplicationData =
+ ShortTextComplicationData.Builder(
+ PlainComplicationText.Builder("Left").build(),
+ ComplicationText.EMPTY
+ )
+ .build()
+ val rightComplicationData =
+ ShortTextComplicationData.Builder(
+ PlainComplicationText.Builder("Right").build(),
+ ComplicationText.EMPTY
+ )
+ .build()
- val complicationsMap = mapOf(
- leftComplication.id to leftComplicationData,
- rightComplication.id to rightComplicationData
- )
+ val complicationsMap =
+ mapOf(
+ leftComplication.id to leftComplicationData,
+ rightComplication.id to rightComplicationData
+ )
scenario.onActivity {
it.editorSession.setOverrideComplications(complicationsMap)
diff --git a/wear/watchface/watchface-editor/src/main/java/androidx/wear/watchface/editor/EditorSession.kt b/wear/watchface/watchface-editor/src/main/java/androidx/wear/watchface/editor/EditorSession.kt
index c5be83f..21ce97f 100644
--- a/wear/watchface/watchface-editor/src/main/java/androidx/wear/watchface/editor/EditorSession.kt
+++ b/wear/watchface/watchface-editor/src/main/java/androidx/wear/watchface/editor/EditorSession.kt
@@ -209,7 +209,7 @@
* editor session has ended.
*
* @param slotIdToComplicationData The complications you wish to set. Any slots not covered by
- * this map will be unchanged.
+ * this map will be unchanged.
*/
public fun setOverrideComplications(slotIdToComplicationData: Map<Int, ComplicationData>) {
// We expect this to be overridden.
@@ -710,8 +710,7 @@
// Coerce to a Map<Int, ComplicationData> omitting null values.
// If mapNotNullValues existed we would use it here.
)
- ?.mapValues { it.value.await() ?: EmptyComplicationData() }
- ?: emptyMap()
+ ?.mapValues { it.value.await() ?: EmptyComplicationData() } ?: emptyMap()
deferredComplicationPreviewDataAvailable.complete(Unit)
} finally {
complicationDataSourceInfoRetriever.close()
@@ -1162,7 +1161,8 @@
*/
internal class ComplicationDataSourceChooserContract :
ActivityResultContract<
- ComplicationDataSourceChooserRequest, ComplicationDataSourceChooserResult?
+ ComplicationDataSourceChooserRequest,
+ ComplicationDataSourceChooserResult?
>() {
internal companion object {
@@ -1212,8 +1212,7 @@
val extras =
intent.extras?.let { extras ->
Bundle(extras).apply { remove(EXTRA_PROVIDER_INFO) }
- }
- ?: Bundle.EMPTY
+ } ?: Bundle.EMPTY
ComplicationDataSourceChooserResult(
it.getParcelableExtra<
android.support.wearable.complications.ComplicationProviderInfo
diff --git a/wear/watchface/watchface-editor/src/main/java/androidx/wear/watchface/editor/WatchFaceEditorContract.kt b/wear/watchface/watchface-editor/src/main/java/androidx/wear/watchface/editor/WatchFaceEditorContract.kt
index d0c4fee..b911b76 100644
--- a/wear/watchface/watchface-editor/src/main/java/androidx/wear/watchface/editor/WatchFaceEditorContract.kt
+++ b/wear/watchface/watchface-editor/src/main/java/androidx/wear/watchface/editor/WatchFaceEditorContract.kt
@@ -202,8 +202,7 @@
ComponentName(watchfacePackageName, WATCHFACE_CONTROL_SERVICE),
PackageManager.GET_META_DATA
)
- .metaData
- ?: return false
+ .metaData ?: return false
return metaData.getInt(ANDROIDX_WATCHFACE_API_VERSION) >= 4
}
}
diff --git a/wear/watchface/watchface-guava/src/androidTest/java/androidx/wear/watchface/AsyncListenableWatchFaceServiceTest.kt b/wear/watchface/watchface-guava/src/androidTest/java/androidx/wear/watchface/AsyncListenableWatchFaceServiceTest.kt
index 6ce078a..3345e29 100644
--- a/wear/watchface/watchface-guava/src/androidTest/java/androidx/wear/watchface/AsyncListenableWatchFaceServiceTest.kt
+++ b/wear/watchface/watchface-guava/src/androidTest/java/androidx/wear/watchface/AsyncListenableWatchFaceServiceTest.kt
@@ -125,9 +125,9 @@
getUiThreadHandler().post {
future.set(
WatchFace(
- WatchFaceType.DIGITAL,
- FakeRenderer(surfaceHolder, watchState, currentUserStyleRepository)
- )
+ WatchFaceType.DIGITAL,
+ FakeRenderer(surfaceHolder, watchState, currentUserStyleRepository)
+ )
.apply { setOverridePreviewReferenceInstant(REFERENCE_PREVIEW_TIME) }
)
}
@@ -183,9 +183,9 @@
getUiThreadHandler().post {
future.set(
WatchFace(
- WatchFaceType.DIGITAL,
- FakeRenderer(surfaceHolder, watchState, currentUserStyleRepository)
- )
+ WatchFaceType.DIGITAL,
+ FakeRenderer(surfaceHolder, watchState, currentUserStyleRepository)
+ )
.apply { setOverridePreviewReferenceInstant(REFERENCE_PREVIEW_TIME) }
)
}
diff --git a/wear/watchface/watchface-guava/src/androidTest/java/androidx/wear/watchface/WatchFaceControlTestService.kt b/wear/watchface/watchface-guava/src/androidTest/java/androidx/wear/watchface/WatchFaceControlTestService.kt
index 029435f..7c2ff14 100644
--- a/wear/watchface/watchface-guava/src/androidTest/java/androidx/wear/watchface/WatchFaceControlTestService.kt
+++ b/wear/watchface/watchface-guava/src/androidTest/java/androidx/wear/watchface/WatchFaceControlTestService.kt
@@ -91,16 +91,15 @@
val glSurface = Surface(surfaceTexture)
val glSurfaceHolder = Mockito.mock(SurfaceHolder::class.java)
- fun createWatchFaceControlClientService() =
- runBlocking {
- WatchFaceControlClient.createWatchFaceControlClientImpl(
- context,
- Intent(context, WatchFaceControlTestService::class.java).apply {
- action = WatchFaceControlService.ACTION_WATCHFACE_CONTROL_SERVICE
- },
- resourceOnlyWatchFacePackageName = null
- )
- }
+ fun createWatchFaceControlClientService() = runBlocking {
+ WatchFaceControlClient.createWatchFaceControlClientImpl(
+ context,
+ Intent(context, WatchFaceControlTestService::class.java).apply {
+ action = WatchFaceControlService.ACTION_WATCHFACE_CONTROL_SERVICE
+ },
+ resourceOnlyWatchFacePackageName = null
+ )
+ }
fun createWatchFaceRuntimeControlClientService(resourceOnlyWatchFacePackageName: String) =
runBlocking {
diff --git a/wear/watchface/watchface-guava/src/main/java/androidx/wear/watchface/ListenableWatchFaceService.kt b/wear/watchface/watchface-guava/src/main/java/androidx/wear/watchface/ListenableWatchFaceService.kt
index c4a8b4d..966cf49 100644
--- a/wear/watchface/watchface-guava/src/main/java/androidx/wear/watchface/ListenableWatchFaceService.kt
+++ b/wear/watchface/watchface-guava/src/main/java/androidx/wear/watchface/ListenableWatchFaceService.kt
@@ -81,13 +81,12 @@
* [ListenableFuture]-based compatibility wrapper around [StatefulWatchFaceService]'s suspending
* [WatchFaceService.createWatchFace].
*
- * [ListenableWatchFaceService] is required to be stateless as multiple can be created in
- * parallel. ListenableStatefulWatchFaceService allows for metadata to be associated with
- * watch faces on a per instance basis. This state is created by [createExtra] and is passed into
- * other methods.
+ * [ListenableWatchFaceService] is required to be stateless as multiple can be created in parallel.
+ * ListenableStatefulWatchFaceService allows for metadata to be associated with watch faces on a per
+ * instance basis. This state is created by [createExtra] and is passed into other methods.
*/
-public abstract class
-ListenableStatefulWatchFaceService<Extra> : StatefulWatchFaceService<Extra>() {
+public abstract class ListenableStatefulWatchFaceService<Extra> :
+ StatefulWatchFaceService<Extra>() {
/**
* Override this factory method to create your WatchFaceImpl. This method will be called by the
* library on a background thread, if possible any expensive initialization should be done
@@ -207,8 +206,8 @@
* watch faces on a per instance basis. This state is created by [createExtra] and is passed into
* other methods.
*/
-public abstract class
-ListenableStatefulWatchFaceRuntimeService<Extra> : StatefulWatchFaceRuntimeService<Extra>() {
+public abstract class ListenableStatefulWatchFaceRuntimeService<Extra> :
+ StatefulWatchFaceRuntimeService<Extra>() {
/**
* Override this factory method to create your WatchFaceImpl. This method will be called by the
* library on a background thread, if possible any expensive initialization should be done
diff --git a/wear/watchface/watchface-style/src/androidTest/java/androidx/wear/watchface/style/TestHelper.kt b/wear/watchface/watchface-style/src/androidTest/java/androidx/wear/watchface/style/TestHelper.kt
index adc51af..1ba780f 100644
--- a/wear/watchface/watchface-style/src/androidTest/java/androidx/wear/watchface/style/TestHelper.kt
+++ b/wear/watchface/watchface-style/src/androidTest/java/androidx/wear/watchface/style/TestHelper.kt
@@ -52,8 +52,7 @@
InstrumentationRegistry.getInstrumentation().context.cacheDir
}
else -> InstrumentationRegistry.getInstrumentation().context.externalCacheDir
- }
- ?: throw IllegalStateException("Unable to select a directory for writing files.")
+ } ?: throw IllegalStateException("Unable to select a directory for writing files.")
}
public fun uninstall() = executeCommand("pm uninstall $packageName")
diff --git a/wear/watchface/watchface-style/src/main/java/androidx/wear/watchface/style/UserStyleSetting.kt b/wear/watchface/watchface-style/src/main/java/androidx/wear/watchface/style/UserStyleSetting.kt
index 96e2d2f5..389c0c0 100644
--- a/wear/watchface/watchface-style/src/main/java/androidx/wear/watchface/style/UserStyleSetting.kt
+++ b/wear/watchface/watchface-style/src/main/java/androidx/wear/watchface/style/UserStyleSetting.kt
@@ -421,7 +421,7 @@
val id =
getStringRefAttribute(resources, parser, "id")
?: parent?.id?.value
- ?: throw IllegalArgumentException("$settingType must have id")
+ ?: throw IllegalArgumentException("$settingType must have id")
val displayName =
createDisplayText(resources, parser, "displayName", parent?.displayNameInternal)
val description =
@@ -1114,8 +1114,7 @@
perComplicationTypeBounds.mapKeys { ComplicationType.fromWireType(it.key) },
perComplicationTypeMargins?.let { margins ->
margins.mapKeys { ComplicationType.fromWireType(it.key) }
- }
- ?: emptyMap()
+ } ?: emptyMap()
)
},
wireFormat.accessibilityTraversalIndex,
@@ -1678,8 +1677,7 @@
PerComplicationTypeMargins(
overlay.complicationSlotBounds?.perComplicationTypeMargins?.mapKeys {
it.key.toWireComplicationType()
- }
- ?: emptyMap()
+ } ?: emptyMap()
)
},
complicationSlotOverlays.map { it.nameResourceId ?: 0 },
diff --git a/wear/watchface/watchface/samples/src/main/java/androidx/wear/watchface/samples/ExampleOpenGLWatchFaceService.kt b/wear/watchface/watchface/samples/src/main/java/androidx/wear/watchface/samples/ExampleOpenGLWatchFaceService.kt
index c4ff067..3831a29 100644
--- a/wear/watchface/watchface/samples/src/main/java/androidx/wear/watchface/samples/ExampleOpenGLWatchFaceService.kt
+++ b/wear/watchface/watchface/samples/src/main/java/androidx/wear/watchface/samples/ExampleOpenGLWatchFaceService.kt
@@ -154,7 +154,7 @@
)
class ExampleSharedAssets : Renderer.SharedAssets {
- override fun onDestroy() { }
+ override fun onDestroy() {}
}
@OptIn(WatchFaceExperimental::class)
@@ -172,36 +172,37 @@
watchState,
FRAME_PERIOD_MS,
// Try a config with 4x MSAA if supported and if necessary fall back to one without.
- eglConfigAttribListList = listOf(
- intArrayOf(
- EGL14.EGL_RENDERABLE_TYPE,
- EGL14.EGL_OPENGL_ES2_BIT,
- EGL14.EGL_RED_SIZE,
- 8,
- EGL14.EGL_GREEN_SIZE,
- 8,
- EGL14.EGL_BLUE_SIZE,
- 8,
- EGL14.EGL_ALPHA_SIZE,
- 8,
- EGL14.EGL_SAMPLES, // 4x MSAA (anti-aliasing)
- 4,
- EGL14.EGL_NONE
+ eglConfigAttribListList =
+ listOf(
+ intArrayOf(
+ EGL14.EGL_RENDERABLE_TYPE,
+ EGL14.EGL_OPENGL_ES2_BIT,
+ EGL14.EGL_RED_SIZE,
+ 8,
+ EGL14.EGL_GREEN_SIZE,
+ 8,
+ EGL14.EGL_BLUE_SIZE,
+ 8,
+ EGL14.EGL_ALPHA_SIZE,
+ 8,
+ EGL14.EGL_SAMPLES, // 4x MSAA (anti-aliasing)
+ 4,
+ EGL14.EGL_NONE
+ ),
+ intArrayOf(
+ EGL14.EGL_RENDERABLE_TYPE,
+ EGL14.EGL_OPENGL_ES2_BIT,
+ EGL14.EGL_RED_SIZE,
+ 8,
+ EGL14.EGL_GREEN_SIZE,
+ 8,
+ EGL14.EGL_BLUE_SIZE,
+ 8,
+ EGL14.EGL_ALPHA_SIZE,
+ 8,
+ EGL14.EGL_NONE
+ )
),
- intArrayOf(
- EGL14.EGL_RENDERABLE_TYPE,
- EGL14.EGL_OPENGL_ES2_BIT,
- EGL14.EGL_RED_SIZE,
- 8,
- EGL14.EGL_GREEN_SIZE,
- 8,
- EGL14.EGL_BLUE_SIZE,
- 8,
- EGL14.EGL_ALPHA_SIZE,
- 8,
- EGL14.EGL_NONE
- )
- ),
eglSurfaceAttribList = intArrayOf(EGL14.EGL_NONE),
eglContextAttribList = intArrayOf(EGL14.EGL_CONTEXT_CLIENT_VERSION, 2, EGL14.EGL_NONE)
) {
diff --git a/wear/watchface/watchface/samples/src/main/java/androidx/wear/watchface/samples/SampleWatchFaceService.kt b/wear/watchface/watchface/samples/src/main/java/androidx/wear/watchface/samples/SampleWatchFaceService.kt
index 71127d9..23cc08e 100644
--- a/wear/watchface/watchface/samples/src/main/java/androidx/wear/watchface/samples/SampleWatchFaceService.kt
+++ b/wear/watchface/watchface/samples/src/main/java/androidx/wear/watchface/samples/SampleWatchFaceService.kt
@@ -26,8 +26,8 @@
/**
* Common base class for the androidx sample watch faces.
*
- * You can trigger these to quit with:
- * `adb shell am broadcast -a androidx.wear.watchface.samples.QUIT`
+ * You can trigger these to quit with: `adb shell am broadcast -a
+ * androidx.wear.watchface.samples.QUIT`
*/
abstract class SampleWatchFaceService : WatchFaceService() {
override fun onCreate() {
diff --git a/wear/watchface/watchface/src/androidTest/java/androidx/wear/watchface/test/WatchFaceControlServiceTest.kt b/wear/watchface/watchface/src/androidTest/java/androidx/wear/watchface/test/WatchFaceControlServiceTest.kt
index 8ffc3ef..aadb9c8 100644
--- a/wear/watchface/watchface/src/androidTest/java/androidx/wear/watchface/test/WatchFaceControlServiceTest.kt
+++ b/wear/watchface/watchface/src/androidTest/java/androidx/wear/watchface/test/WatchFaceControlServiceTest.kt
@@ -154,19 +154,13 @@
CanvasType.SOFTWARE,
16
) {
- override fun render(
- canvas: Canvas,
- bounds: Rect,
- zonedDateTime: ZonedDateTime
- ) {
- }
+ override fun render(canvas: Canvas, bounds: Rect, zonedDateTime: ZonedDateTime) {}
override fun renderHighlightLayer(
canvas: Canvas,
bounds: Rect,
zonedDateTime: ZonedDateTime
- ) {
- }
+ ) {}
}
)
}
diff --git a/wear/watchface/watchface/src/androidTest/java/androidx/wear/watchface/test/WatchFaceServiceImageTest.kt b/wear/watchface/watchface/src/androidTest/java/androidx/wear/watchface/test/WatchFaceServiceImageTest.kt
index 6d2a482..9e28747 100644
--- a/wear/watchface/watchface/src/androidTest/java/androidx/wear/watchface/test/WatchFaceServiceImageTest.kt
+++ b/wear/watchface/watchface/src/androidTest/java/androidx/wear/watchface/test/WatchFaceServiceImageTest.kt
@@ -133,8 +133,7 @@
@RequiresApi(Build.VERSION_CODES.O_MR1)
public class WatchFaceServiceImageTest {
- @get:Rule
- val mocks = MockitoJUnit.rule()
+ @get:Rule val mocks = MockitoJUnit.rule()
@Mock private lateinit var surfaceHolder: SurfaceHolder
diff --git a/wear/watchface/watchface/src/androidTest/java/androidx/wear/watchface/test/XmlDefinedUserStyleSchemaAndComplicationSlotsTest.kt b/wear/watchface/watchface/src/androidTest/java/androidx/wear/watchface/test/XmlDefinedUserStyleSchemaAndComplicationSlotsTest.kt
index 08d59d3..70f430a 100644
--- a/wear/watchface/watchface/src/androidTest/java/androidx/wear/watchface/test/XmlDefinedUserStyleSchemaAndComplicationSlotsTest.kt
+++ b/wear/watchface/watchface/src/androidTest/java/androidx/wear/watchface/test/XmlDefinedUserStyleSchemaAndComplicationSlotsTest.kt
@@ -245,8 +245,7 @@
@MediumTest
public class XmlDefinedUserStyleSchemaAndComplicationSlotsTest {
- @get:Rule
- val mocks = MockitoJUnit.rule()
+ @get:Rule val mocks = MockitoJUnit.rule()
@Mock private lateinit var surfaceHolder: SurfaceHolder
@Mock private lateinit var surface: Surface
@@ -504,11 +503,10 @@
runBlocking {
val watchFaceImpl = wrapper.deferredWatchFaceImpl.await()
- val factory = watchFaceImpl
- .complicationSlotsManager
- .complicationSlots[10]!!
- .canvasComplicationFactory as
- TestStatefulXmlWatchFaceService.TestCanvasComplicationFactory
+ val factory =
+ watchFaceImpl.complicationSlotsManager.complicationSlots[10]!!
+ .canvasComplicationFactory
+ as TestStatefulXmlWatchFaceService.TestCanvasComplicationFactory
// Assert the extra was passed to the TestCanvasComplicationFactory.
assertThat(factory.extra.value).isEqualTo(123)
diff --git a/wear/watchface/watchface/src/main/java/androidx/wear/watchface/BroadcastsReceiver.kt b/wear/watchface/watchface/src/main/java/androidx/wear/watchface/BroadcastsReceiver.kt
index aec9b5c..f1047ca 100644
--- a/wear/watchface/watchface/src/main/java/androidx/wear/watchface/BroadcastsReceiver.kt
+++ b/wear/watchface/watchface/src/main/java/androidx/wear/watchface/BroadcastsReceiver.kt
@@ -146,8 +146,7 @@
val level: Int = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1)
val scale: Int = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1)
level * 100 / scale.toFloat()
- }
- ?: 100.0f
+ } ?: 100.0f
if (batteryPercent < INITIAL_LOW_BATTERY_THRESHOLD) {
observer.onActionBatteryLow()
} else {
diff --git a/wear/watchface/watchface/src/main/java/androidx/wear/watchface/ComplicationSlot.kt b/wear/watchface/watchface/src/main/java/androidx/wear/watchface/ComplicationSlot.kt
index 51c73f0..398ed47 100644
--- a/wear/watchface/watchface/src/main/java/androidx/wear/watchface/ComplicationSlot.kt
+++ b/wear/watchface/watchface/src/main/java/androidx/wear/watchface/ComplicationSlot.kt
@@ -1088,9 +1088,8 @@
private fun setTimelineData(data: ComplicationData, instant: Instant) {
lastComplicationUpdate = instant
timelineComplicationData = data
- timelineEntries = data.asWireComplicationData()
- .timelineEntries
- ?.mapTo(ArrayList<ApiTimelineEntry>()) {
+ timelineEntries =
+ data.asWireComplicationData().timelineEntries?.mapTo(ArrayList<ApiTimelineEntry>()) {
ApiTimelineEntry(
it.timelineStartEpochSecond,
it.timelineEndEpochSecond,
diff --git a/wear/watchface/watchface/src/main/java/androidx/wear/watchface/ComplicationSlotsManager.kt b/wear/watchface/watchface/src/main/java/androidx/wear/watchface/ComplicationSlotsManager.kt
index f9f9636..0c484d0 100644
--- a/wear/watchface/watchface/src/main/java/androidx/wear/watchface/ComplicationSlotsManager.kt
+++ b/wear/watchface/watchface/src/main/java/androidx/wear/watchface/ComplicationSlotsManager.kt
@@ -97,14 +97,13 @@
for ((_, complication) in complicationSlots) {
require(
complication.defaultDataSourcePolicy.systemDataSourceFallback !=
- SystemDataSources.DATA_SOURCE_HEART_RATE ||
- Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE
+ SystemDataSources.DATA_SOURCE_HEART_RATE ||
+ Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE
) {
"DATA_SOURCE_HEART_RATE requires Android U or above."
}
}
}
-
get() = watchFaceHostApi_
internal lateinit var renderer: Renderer
@@ -517,11 +516,9 @@
it.value.defaultDataSourcePolicy.systemDataSourceFallback,
systemDataSourceFallbackDefaultType,
it.value.defaultDataSourcePolicy.primaryDataSourceDefaultType
- ?.toWireComplicationType()
- ?: systemDataSourceFallbackDefaultType,
+ ?.toWireComplicationType() ?: systemDataSourceFallbackDefaultType,
it.value.defaultDataSourcePolicy.secondaryDataSourceDefaultType
- ?.toWireComplicationType()
- ?: systemDataSourceFallbackDefaultType,
+ ?.toWireComplicationType() ?: systemDataSourceFallbackDefaultType,
it.value.enabled,
it.value.initiallyEnabled,
it.value.renderer.getData().type.toWireComplicationType(),
diff --git a/wear/watchface/watchface/src/main/java/androidx/wear/watchface/RenderParameters.kt b/wear/watchface/watchface/src/main/java/androidx/wear/watchface/RenderParameters.kt
index 0368ba4..6559cb9 100644
--- a/wear/watchface/watchface/src/main/java/androidx/wear/watchface/RenderParameters.kt
+++ b/wear/watchface/watchface/src/main/java/androidx/wear/watchface/RenderParameters.kt
@@ -254,8 +254,7 @@
},
wireFormat.idAndTapEventWireFormat?.associate {
Pair(it.id, TapEvent(it.x, it.y, Instant.ofEpochMilli(it.calendarTapTimeMillis)))
- }
- ?: emptyMap()
+ } ?: emptyMap()
)
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
diff --git a/wear/watchface/watchface/src/main/java/androidx/wear/watchface/Renderer.kt b/wear/watchface/watchface/src/main/java/androidx/wear/watchface/Renderer.kt
index 998c26b..412051f 100644
--- a/wear/watchface/watchface/src/main/java/androidx/wear/watchface/Renderer.kt
+++ b/wear/watchface/watchface/src/main/java/androidx/wear/watchface/Renderer.kt
@@ -72,15 +72,15 @@
public const val SOFTWARE: Int = 0
/**
- * A hardware canvas will be requested. This is usually faster than software rendering,
- * however it can sometimes increase battery usage by rendering at a higher frame rate.
+ * A hardware canvas will be requested. This is usually faster than software rendering, however
+ * it can sometimes increase battery usage by rendering at a higher frame rate.
*
- * NOTE this is only supported on API level 26 and above. On lower API levels we fall back
- * to a software canvas.
+ * NOTE this is only supported on API level 26 and above. On lower API levels we fall back to a
+ * software canvas.
*
- * NOTE the system takes screenshots for use in the watch face picker UI and these will be
- * taken using software rendering for API level 27 and below. This means on API level 27 and
- * below [Bitmap]s with [Bitmap.Config.HARDWARE] must be avoided.
+ * NOTE the system takes screenshots for use in the watch face picker UI and these will be taken
+ * using software rendering for API level 27 and below. This means on API level 27 and below
+ * [Bitmap]s with [Bitmap.Config.HARDWARE] must be avoided.
*/
public const val HARDWARE: Int = 1
}
@@ -551,8 +551,8 @@
* into [render].
* @param currentUserStyleRepository The watch face's associated [CurrentUserStyleRepository].
* @param watchState The watch face's associated [WatchState].
- * @param canvasType The [CanvasTypeIntDef] to request. Note even if [CanvasType.HARDWARE] is used,
- * screenshots will taken using the software rendering pipeline, as such [Bitmap]s with
+ * @param canvasType The [CanvasTypeIntDef] to request. Note even if [CanvasType.HARDWARE] is
+ * used, screenshots will taken using the software rendering pipeline, as such [Bitmap]s with
* [Bitmap.Config.HARDWARE] must be avoided.
* @param interactiveDrawModeUpdateDelayMillis The interval in milliseconds between frames in
* interactive [DrawMode]s. To render at 60hz set to 16. Note when battery is low, the frame
@@ -588,8 +588,7 @@
surfaceHolder.lockHardwareCanvas()
} else {
surfaceHolder.lockCanvas()
- })
- ?: return
+ }) ?: return
try {
if (Build.VERSION.SDK_INT >= 30 || watchState.isVisible.value!!) {
renderAndComposite(canvas, zonedDateTime)
@@ -685,18 +684,20 @@
}
renderHighlightLayer(highlightCanvas, screenBounds, zonedDateTime)
picture.endRecording()
- highlightLayerBitmap = Api28CreateBitmapHelper.createBitmap(
- picture,
- screenBounds.width(),
- screenBounds.height(),
- Bitmap.Config.ARGB_8888
- )
+ highlightLayerBitmap =
+ Api28CreateBitmapHelper.createBitmap(
+ picture,
+ screenBounds.width(),
+ screenBounds.height(),
+ Bitmap.Config.ARGB_8888
+ )
} else {
- highlightLayerBitmap = Bitmap.createBitmap(
- screenBounds.width(),
- screenBounds.height(),
- Bitmap.Config.ARGB_8888
- )
+ highlightLayerBitmap =
+ Bitmap.createBitmap(
+ screenBounds.width(),
+ screenBounds.height(),
+ Bitmap.Config.ARGB_8888
+ )
val highlightCanvas = Canvas(highlightLayerBitmap)
if (clearWithBackgroundTintBeforeRenderingHighlightLayer) {
highlightCanvas.drawColor(highlightLayer.backgroundTint)
@@ -834,8 +835,8 @@
* into [render].
* @param currentUserStyleRepository The watch face's associated [CurrentUserStyleRepository].
* @param watchState The watch face's associated [WatchState].
- * @param canvasType The [CanvasTypeIntDef] to request. Note even if [CanvasType.HARDWARE] is used,
- * screenshots will taken using the software rendering pipeline, as such [Bitmap]s with
+ * @param canvasType The [CanvasTypeIntDef] to request. Note even if [CanvasType.HARDWARE] is
+ * used, screenshots will taken using the software rendering pipeline, as such [Bitmap]s with
* [Bitmap.Config.HARDWARE] must be avoided.
* @param interactiveDrawModeUpdateDelayMillis The interval in milliseconds between frames in
* interactive [DrawMode]s. To render at 60hz set to 16. Note when battery is low, the frame
@@ -1008,7 +1009,8 @@
private val eglConfigAttribListList: List<IntArray>,
private val eglSurfaceAttribList: IntArray,
private val eglContextAttribList: IntArray
- ) : Renderer(
+ ) :
+ Renderer(
surfaceHolder,
currentUserStyleRepository,
watchState,
@@ -1163,7 +1165,8 @@
// Select the first successful config.
for ((i, eglConfigAttribList) in eglConfigAttribListList.withIndex()) {
- if (!EGL14.eglChooseConfig(
+ if (
+ !EGL14.eglChooseConfig(
eglDisplay,
eglConfigAttribList,
0,
@@ -1172,7 +1175,7 @@
eglConfigs.size,
numEglConfigs,
0
- )
+ )
) {
if (this is GlesRenderer2<*>) {
selectedEglConfigAttribListIndexInternal = Integer(i)
@@ -1909,10 +1912,6 @@
/** Helper to allow class verification. */
@RequiresApi(28)
internal object Api28CreateBitmapHelper {
- fun createBitmap(
- picture: Picture,
- width: Int,
- height: Int,
- config: Bitmap.Config
- ) = Bitmap.createBitmap(picture, width, height, config)
+ fun createBitmap(picture: Picture, width: Int, height: Int, config: Bitmap.Config) =
+ Bitmap.createBitmap(picture, width, height, config)
}
diff --git a/wear/watchface/watchface/src/main/java/androidx/wear/watchface/TapEvent.kt b/wear/watchface/watchface/src/main/java/androidx/wear/watchface/TapEvent.kt
index ca3fe0e..3988bfa 100644
--- a/wear/watchface/watchface/src/main/java/androidx/wear/watchface/TapEvent.kt
+++ b/wear/watchface/watchface/src/main/java/androidx/wear/watchface/TapEvent.kt
@@ -32,8 +32,8 @@
* Used to indicate a "down" touch event on the watch face.
*
* The watch face will receive an [UP] or a [CANCEL] event to follow this event, to indicate
- * whether this down event corresponds to a tap gesture to be handled by the watch face, or
- * a different type of gesture that is handled by the system, respectively.
+ * whether this down event corresponds to a tap gesture to be handled by the watch face, or a
+ * different type of gesture that is handled by the system, respectively.
*/
public const val DOWN: Int = IInteractiveWatchFace.TAP_TYPE_DOWN
@@ -47,12 +47,12 @@
public const val CANCEL: Int = IInteractiveWatchFace.TAP_TYPE_CANCEL
/**
- * Used to indicate that an "up" event on the watch face has occurred that has not been
- * consumed by the system. A [TapType.DOWN] will always occur first. This event will not be
- * sent if a [TapType.CANCEL] is sent.
+ * Used to indicate that an "up" event on the watch face has occurred that has not been consumed
+ * by the system. A [TapType.DOWN] will always occur first. This event will not be sent if a
+ * [TapType.CANCEL] is sent.
*
- * Therefore, a [TapType.DOWN] event and the successive [TapType.UP] event are guaranteed to
- * be close enough to be considered a tap according to the value returned by
+ * Therefore, a [TapType.DOWN] event and the successive [TapType.UP] event are guaranteed to be
+ * close enough to be considered a tap according to the value returned by
* [android.view.ViewConfiguration.getScaledTouchSlop].
*/
public const val UP: Int = IInteractiveWatchFace.TAP_TYPE_UP
diff --git a/wear/watchface/watchface/src/main/java/androidx/wear/watchface/WatchFace.kt b/wear/watchface/watchface/src/main/java/androidx/wear/watchface/WatchFace.kt
index e8026a4..df51d40 100644
--- a/wear/watchface/watchface/src/main/java/androidx/wear/watchface/WatchFace.kt
+++ b/wear/watchface/watchface/src/main/java/androidx/wear/watchface/WatchFace.kt
@@ -689,23 +689,24 @@
init {
val context = watchFaceHostApi.getContext()
- displayManager = context.getSystemService(Context.DISPLAY_SERVICE) as DisplayManager
- displayListener = object : DisplayManager.DisplayListener {
- override fun onDisplayAdded(displayId: Int) {}
+ displayManager = context.getSystemService(Context.DISPLAY_SERVICE) as DisplayManager
+ displayListener =
+ object : DisplayManager.DisplayListener {
+ override fun onDisplayAdded(displayId: Int) {}
- override fun onDisplayChanged(displayId: Int) {
- val display = displayManager.getDisplay(Display.DEFAULT_DISPLAY)!!
- if (display.state == Display.STATE_OFF && watchState.isVisible.value == false) {
- // We want to avoid a glimpse of a stale time when transitioning from
- // hidden to visible, so we render two black frames to clear the buffers
- // when the display has been turned off and the watch is not visible.
- renderer.renderBlackFrame()
- renderer.renderBlackFrame()
+ override fun onDisplayChanged(displayId: Int) {
+ val display = displayManager.getDisplay(Display.DEFAULT_DISPLAY)!!
+ if (display.state == Display.STATE_OFF && watchState.isVisible.value == false) {
+ // We want to avoid a glimpse of a stale time when transitioning from
+ // hidden to visible, so we render two black frames to clear the buffers
+ // when the display has been turned off and the watch is not visible.
+ renderer.renderBlackFrame()
+ renderer.renderBlackFrame()
+ }
}
- }
- override fun onDisplayRemoved(displayId: Int) {}
- }
+ override fun onDisplayRemoved(displayId: Int) {}
+ }
displayManager.registerDisplayListener(
displayListener,
watchFaceHostApi.getUiThreadHandler()
@@ -919,8 +920,7 @@
get() =
InteractiveInstanceManager.getCurrentInteractiveInstance()
?.engine
- ?.editorObscuresWatchFace
- ?: false
+ ?.editorObscuresWatchFace ?: false
set(value) {
InteractiveInstanceManager.getCurrentInteractiveInstance()?.engine?.let {
it.editorObscuresWatchFace = value
@@ -952,22 +952,19 @@
override fun setOverrideComplications(
slotIdToComplicationData: Map<Int, ComplicationData>
) {
- InteractiveInstanceManager
- .getCurrentInteractiveInstance()
+ InteractiveInstanceManager.getCurrentInteractiveInstance()
?.engine
?.overrideComplicationsForEditing(slotIdToComplicationData)
}
override fun clearComplicationSlotAfterEditing(slotId: Int) {
- InteractiveInstanceManager
- .getCurrentInteractiveInstance()
+ InteractiveInstanceManager.getCurrentInteractiveInstance()
?.engine
?.clearComplicationSlotAfterEditing(slotId)
}
override fun dontClearAnyComplicationSlotsAfterEditing() {
- InteractiveInstanceManager
- .getCurrentInteractiveInstance()
+ InteractiveInstanceManager.getCurrentInteractiveInstance()
?.engine
?.dontClearAnyComplicationSlotsAfterEditing()
}
diff --git a/wear/watchface/watchface/src/main/java/androidx/wear/watchface/WatchFaceService.kt b/wear/watchface/watchface/src/main/java/androidx/wear/watchface/WatchFaceService.kt
index 51a25931..84939b2 100644
--- a/wear/watchface/watchface/src/main/java/androidx/wear/watchface/WatchFaceService.kt
+++ b/wear/watchface/watchface/src/main/java/androidx/wear/watchface/WatchFaceService.kt
@@ -1200,12 +1200,11 @@
val userStyleFlavors: UserStyleFlavors
)
- internal class ChoreographerCallback(
- val watchFaceImpl: WatchFaceImpl
- ) : Choreographer.FrameCallback {
+ internal class ChoreographerCallback(val watchFaceImpl: WatchFaceImpl) :
+ Choreographer.FrameCallback {
/**
- * Whether we already have a frameCallback posted and waiting in the [Choreographer]
- * queue. This protects us from drawing multiple times in a single frame.
+ * Whether we already have a frameCallback posted and waiting in the [Choreographer] queue.
+ * This protects us from drawing multiple times in a single frame.
*/
var frameCallbackPending = false
@@ -1213,8 +1212,8 @@
frameCallbackPending = false
/**
- * It's possible we went ambient by the time our callback occurred in which case
- * there's no point drawing.
+ * It's possible we went ambient by the time our callback occurred in which case there's
+ * no point drawing.
*/
if (watchFaceImpl.renderer.shouldAnimate()) {
try {
@@ -1720,17 +1719,13 @@
*/
@AnyThread
internal fun clearComplicationSlotAfterEditing(slotId: Int) {
- synchronized(lock) {
- complicationSlotsToClearAfterEditing.add(slotId)
- }
+ synchronized(lock) { complicationSlotsToClearAfterEditing.add(slotId) }
}
/** Forgets any calls to [clearComplicationSlotAfterEditing]. */
@AnyThread
internal fun dontClearAnyComplicationSlotsAfterEditing() {
- synchronized(lock) {
- complicationSlotsToClearAfterEditing.clear()
- }
+ synchronized(lock) { complicationSlotsToClearAfterEditing.clear() }
}
/**
@@ -1761,18 +1756,15 @@
}
complicationSlotsToClearAfterEditing.clear()
- complicationsFlow.update {
- overriddenComplications!!
- }
+ complicationsFlow.update { overriddenComplications!! }
overriddenComplications = null
}
}
/** Used to keep track of whether the client has died while animation is paused. */
- private inner class PauseAnimationDeathRecipient(
- val binder: IBinder
- ) : IBinder.DeathRecipient {
+ private inner class PauseAnimationDeathRecipient(val binder: IBinder) :
+ IBinder.DeathRecipient {
override fun binderDied() {
synchronized(lock) {
// Remove the isVisible override. Typically privIsVisible will be true.
@@ -1794,9 +1786,7 @@
}
internal fun unpauseAnimation() {
- synchronized(lock) {
- pauseAnimationDeathRecipient?.binderDied()
- }
+ synchronized(lock) { pauseAnimationDeathRecipient?.binderDied() }
}
@WorkerThread
@@ -2120,7 +2110,7 @@
extra
),
resourceOnlyWatchFacePackageName,
- extra
+ extra
)
.toWireFormat()
}
@@ -2128,16 +2118,16 @@
/** This will be called from a binder thread. */
@OptIn(ComplicationExperimental::class)
@WorkerThread
- internal fun
- getComplicationSlotMetadataWireFormats(): Array<ComplicationSlotMetadataWireFormat> {
+ internal fun getComplicationSlotMetadataWireFormats():
+ Array<ComplicationSlotMetadataWireFormat> {
val extra = createExtraInternal()
return createComplicationSlotsManagerInternal(
- CurrentUserStyleRepository(
- createUserStyleSchemaInternal(resourceOnlyWatchFacePackageName, extra)
- ),
- resourceOnlyWatchFacePackageName,
- extra
- )
+ CurrentUserStyleRepository(
+ createUserStyleSchemaInternal(resourceOnlyWatchFacePackageName, extra)
+ ),
+ resourceOnlyWatchFacePackageName,
+ extra
+ )
.complicationSlots
.map {
val systemDataSourceFallbackDefaultType =
@@ -2157,11 +2147,9 @@
it.value.defaultDataSourcePolicy.systemDataSourceFallback,
systemDataSourceFallbackDefaultType,
it.value.defaultDataSourcePolicy.primaryDataSourceDefaultType
- ?.toWireComplicationType()
- ?: systemDataSourceFallbackDefaultType,
+ ?.toWireComplicationType() ?: systemDataSourceFallbackDefaultType,
it.value.defaultDataSourcePolicy.secondaryDataSourceDefaultType
- ?.toWireComplicationType()
- ?: systemDataSourceFallbackDefaultType,
+ ?.toWireComplicationType() ?: systemDataSourceFallbackDefaultType,
it.value.initiallyEnabled,
it.value.fixedComplicationDataSource,
it.value.configExtras,
@@ -2346,9 +2334,7 @@
val userStyleFlavors: UserStyleFlavors
try {
- extra = TraceEvent("WatchFaceService.createExtra").use {
- createExtraInternal()
- }
+ extra = TraceEvent("WatchFaceService.createExtra").use { createExtraInternal() }
currentUserStyleRepository =
TraceEvent("WatchFaceService.createUserStyleSchema").use {
CurrentUserStyleRepository(
@@ -3140,9 +3126,8 @@
* to [createComplicationSlotsManager] and [createWatchFace].
*/
@WorkerThread
- protected open fun createUserStyleSchema(
- extra: Extra
- ): UserStyleSchema = super.createUserStyleSchema()
+ protected open fun createUserStyleSchema(extra: Extra): UserStyleSchema =
+ super.createUserStyleSchema()
override fun createUserStyleSchemaInternal(
resourceOnlyWatchFacePackageName: String?,
@@ -3561,8 +3546,7 @@
override fun createUserStyleSchemaInternal(
resourceOnlyWatchFacePackageName: String?,
extra: Any?
- ): UserStyleSchema =
- createUserStyleSchema(resourceOnlyWatchFacePackageName!!, extra!! as Extra)
+ ): UserStyleSchema = createUserStyleSchema(resourceOnlyWatchFacePackageName!!, extra!! as Extra)
@Suppress("DocumentExceptions") // NB this method isn't expected to be called from user code.
final override fun createUserStyleSchema(): UserStyleSchema {
diff --git a/wear/watchface/watchface/src/main/java/androidx/wear/watchface/XmlSchemaAndComplicationSlotsDefinition.kt b/wear/watchface/watchface/src/main/java/androidx/wear/watchface/XmlSchemaAndComplicationSlotsDefinition.kt
index e9891be..9d26ee2 100644
--- a/wear/watchface/watchface/src/main/java/androidx/wear/watchface/XmlSchemaAndComplicationSlotsDefinition.kt
+++ b/wear/watchface/watchface/src/main/java/androidx/wear/watchface/XmlSchemaAndComplicationSlotsDefinition.kt
@@ -125,16 +125,17 @@
) {
companion object {
@Suppress("NewApi")
- private val typesMap = mapOf(
- "SHORT_TEXT" to ComplicationType.SHORT_TEXT,
- "LONG_TEXT" to ComplicationType.LONG_TEXT,
- "RANGED_VALUE" to ComplicationType.RANGED_VALUE,
- "MONOCHROMATIC_IMAGE" to ComplicationType.MONOCHROMATIC_IMAGE,
- "SMALL_IMAGE" to ComplicationType.SMALL_IMAGE,
- "PHOTO_IMAGE" to ComplicationType.PHOTO_IMAGE,
- "GOAL_PROGRESS" to ComplicationType.GOAL_PROGRESS,
- "WEIGHTED_ELEMENTS" to ComplicationType.WEIGHTED_ELEMENTS
- )
+ private val typesMap =
+ mapOf(
+ "SHORT_TEXT" to ComplicationType.SHORT_TEXT,
+ "LONG_TEXT" to ComplicationType.LONG_TEXT,
+ "RANGED_VALUE" to ComplicationType.RANGED_VALUE,
+ "MONOCHROMATIC_IMAGE" to ComplicationType.MONOCHROMATIC_IMAGE,
+ "SMALL_IMAGE" to ComplicationType.SMALL_IMAGE,
+ "PHOTO_IMAGE" to ComplicationType.PHOTO_IMAGE,
+ "GOAL_PROGRESS" to ComplicationType.GOAL_PROGRESS,
+ "WEIGHTED_ELEMENTS" to ComplicationType.WEIGHTED_ELEMENTS
+ )
fun inflate(
resources: Resources,
diff --git a/wear/watchface/watchface/src/main/java/androidx/wear/watchface/control/HeadlessWatchFaceImpl.kt b/wear/watchface/watchface/src/main/java/androidx/wear/watchface/control/HeadlessWatchFaceImpl.kt
index e3b1597..017e4bb 100644
--- a/wear/watchface/watchface/src/main/java/androidx/wear/watchface/control/HeadlessWatchFaceImpl.kt
+++ b/wear/watchface/watchface/src/main/java/androidx/wear/watchface/control/HeadlessWatchFaceImpl.kt
@@ -89,8 +89,7 @@
"HeadlessWatchFaceImpl.getPreviewReferenceTimeMillis"
) {
it.previewReferenceInstant.toEpochMilli()
- }
- ?: 0
+ } ?: 0
}
override fun getComplicationState() =
diff --git a/wear/watchface/watchface/src/main/java/androidx/wear/watchface/control/InteractiveInstanceManager.kt b/wear/watchface/watchface/src/main/java/androidx/wear/watchface/control/InteractiveInstanceManager.kt
index 2952487..bb9e298 100644
--- a/wear/watchface/watchface/src/main/java/androidx/wear/watchface/control/InteractiveInstanceManager.kt
+++ b/wear/watchface/watchface/src/main/java/androidx/wear/watchface/control/InteractiveInstanceManager.kt
@@ -201,9 +201,10 @@
// Note prior to android U, auxiliaryComponentPackageName may be non null for regular
// watch faces.
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE &&
- engine.resourceOnlyWatchFacePackageName !=
- value.params.auxiliaryComponentPackageName
+ if (
+ Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE &&
+ engine.resourceOnlyWatchFacePackageName !=
+ value.params.auxiliaryComponentPackageName
) {
val message =
"Existing instance has the resourceOnlyWatchFacePackageName of " +
diff --git a/wear/watchface/watchface/src/main/java/androidx/wear/watchface/control/InteractiveWatchFaceImpl.kt b/wear/watchface/watchface/src/main/java/androidx/wear/watchface/control/InteractiveWatchFaceImpl.kt
index b26c45c..a5290b5 100644
--- a/wear/watchface/watchface/src/main/java/androidx/wear/watchface/control/InteractiveWatchFaceImpl.kt
+++ b/wear/watchface/watchface/src/main/java/androidx/wear/watchface/control/InteractiveWatchFaceImpl.kt
@@ -146,8 +146,7 @@
"InteractiveWatchFaceImpl.getPreviewReferenceTimeMillis"
) { watchFaceImpl ->
watchFaceImpl.previewReferenceInstant.toEpochMilli()
- }
- ?: 0
+ } ?: 0
}
override fun setWatchUiState(watchUiState: WatchUiState): Unit =
@@ -301,8 +300,7 @@
"InteractiveWatchFaceImpl.getComplicationIdAt"
) {
it.complicationSlotsManager.getComplicationSlotAt(xPos, yPos)?.id?.toLong()
- }
- ?: Long.MIN_VALUE
+ } ?: Long.MIN_VALUE
}
override fun getUserStyleFlavors() =
@@ -318,19 +316,18 @@
override fun overrideComplicationData(
complicationDatumWireFormats: List<IdAndComplicationDataWireFormat>
- ): Unit = aidlMethod(TAG, "overrideComplicationData") {
- engine?.overrideComplicationsForEditing(
- complicationDatumWireFormats.associateBy(
- { it.id },
- { it.complicationData.toApiComplicationData() }
+ ): Unit =
+ aidlMethod(TAG, "overrideComplicationData") {
+ engine?.overrideComplicationsForEditing(
+ complicationDatumWireFormats.associateBy(
+ { it.id },
+ { it.complicationData.toApiComplicationData() }
+ )
)
- )
- }
+ }
override fun clearComplicationDataOverride(): Unit =
- aidlMethod(TAG, "overrideComplicationData") {
- engine?.onEditSessionFinished()
- }
+ aidlMethod(TAG, "overrideComplicationData") { engine?.onEditSessionFinished() }
override fun pauseAnimation(binder: IBinder): Unit =
aidlMethod(TAG, "pauseAnimation") { engine?.pauseAnimation(binder) }
diff --git a/wear/watchface/watchface/src/test/java/androidx/wear/watchface/WatchFaceServiceTest.kt b/wear/watchface/watchface/src/test/java/androidx/wear/watchface/WatchFaceServiceTest.kt
index d68e74a..c354c84 100644
--- a/wear/watchface/watchface/src/test/java/androidx/wear/watchface/WatchFaceServiceTest.kt
+++ b/wear/watchface/watchface/src/test/java/androidx/wear/watchface/WatchFaceServiceTest.kt
@@ -3024,7 +3024,7 @@
public fun updateComplicationData_interactive_loadsAsync() {
initWallpaperInteractiveWatchFaceInstance(complicationSlots = listOf(mockComplication))
interactiveWatchFaceInstance.setWatchUiState(
- WatchUiState(/* inAmbientMode = */ false, /* interruptionFilter= */ 0)
+ WatchUiState(/* inAmbientMode= */ false, /* interruptionFilter= */ 0)
)
val data =
WireComplicationData.Builder(WireComplicationData.TYPE_LONG_TEXT)
@@ -3043,7 +3043,7 @@
public fun updateComplicationData_interactive_loadsSync() {
initWallpaperInteractiveWatchFaceInstance(complicationSlots = listOf(mockComplication))
interactiveWatchFaceInstance.setWatchUiState(
- WatchUiState(/* inAmbientMode = */ true, /* interruptionFilter= */ 0)
+ WatchUiState(/* inAmbientMode= */ true, /* interruptionFilter= */ 0)
)
val data =
WireComplicationData.Builder(WireComplicationData.TYPE_LONG_TEXT)
@@ -6339,26 +6339,30 @@
// In initEngine we fill initial complication data using
// setComplicationViaWallpaperCommand, that's why lastComplications initially is not empty
- assertThat(engineWrapper.complicationsFlow.value).containsAtLeast(
- leftComplication1.id, leftComplication1.complicationData.toApiComplicationData()
- )
+ assertThat(engineWrapper.complicationsFlow.value)
+ .containsAtLeast(
+ leftComplication1.id,
+ leftComplication1.complicationData.toApiComplicationData()
+ )
// Check merges are working as expected.
engineWrapper.setComplicationDataList(listOf(rightComplication1))
- assertThat(engineWrapper.complicationsFlow.value).containsExactly(
- leftComplication1.id,
- leftComplication1.complicationData.toApiComplicationData(),
- rightComplication1.id,
- rightComplication1.complicationData.toApiComplicationData()
- )
+ assertThat(engineWrapper.complicationsFlow.value)
+ .containsExactly(
+ leftComplication1.id,
+ leftComplication1.complicationData.toApiComplicationData(),
+ rightComplication1.id,
+ rightComplication1.complicationData.toApiComplicationData()
+ )
engineWrapper.setComplicationDataList(listOf(leftComplication2))
- assertThat(engineWrapper.complicationsFlow.value).containsExactly(
- leftComplication2.id,
- leftComplication2.complicationData.toApiComplicationData(),
- rightComplication1.id,
- rightComplication1.complicationData.toApiComplicationData()
- )
+ assertThat(engineWrapper.complicationsFlow.value)
+ .containsExactly(
+ leftComplication2.id,
+ leftComplication2.complicationData.toApiComplicationData(),
+ rightComplication1.id,
+ rightComplication1.complicationData.toApiComplicationData()
+ )
}
@Test
@@ -6379,21 +6383,23 @@
)
)
- assertThat(engineWrapper.complicationsFlow.value).containsExactly(
- leftComplication2.id,
- leftComplication2.complicationData.toApiComplicationData(),
- rightComplication2.id,
- rightComplication2.complicationData.toApiComplicationData()
- )
+ assertThat(engineWrapper.complicationsFlow.value)
+ .containsExactly(
+ leftComplication2.id,
+ leftComplication2.complicationData.toApiComplicationData(),
+ rightComplication2.id,
+ rightComplication2.complicationData.toApiComplicationData()
+ )
engineWrapper.onEditSessionFinished()
- assertThat(engineWrapper.complicationsFlow.value).containsExactly(
- leftComplication1.id,
- leftComplication1.complicationData.toApiComplicationData(),
- rightComplication1.id,
- rightComplication1.complicationData.toApiComplicationData()
- )
+ assertThat(engineWrapper.complicationsFlow.value)
+ .containsExactly(
+ leftComplication1.id,
+ leftComplication1.complicationData.toApiComplicationData(),
+ rightComplication1.id,
+ rightComplication1.complicationData.toApiComplicationData()
+ )
}
@Test
@@ -6415,21 +6421,23 @@
// This should not change the value of the complicationsFlow
engineWrapper.setComplicationDataList(listOf(rightComplication1))
- assertThat(engineWrapper.complicationsFlow.value).containsExactly(
- leftComplication2.id,
- leftComplication2.complicationData.toApiComplicationData(),
- rightComplication2.id,
- rightComplication2.complicationData.toApiComplicationData()
- )
+ assertThat(engineWrapper.complicationsFlow.value)
+ .containsExactly(
+ leftComplication2.id,
+ leftComplication2.complicationData.toApiComplicationData(),
+ rightComplication2.id,
+ rightComplication2.complicationData.toApiComplicationData()
+ )
engineWrapper.onEditSessionFinished()
- assertThat(engineWrapper.complicationsFlow.value).containsExactly(
- leftComplication1.id,
- leftComplication1.complicationData.toApiComplicationData(),
- rightComplication1.id,
- rightComplication1.complicationData.toApiComplicationData()
- )
+ assertThat(engineWrapper.complicationsFlow.value)
+ .containsExactly(
+ leftComplication1.id,
+ leftComplication1.complicationData.toApiComplicationData(),
+ rightComplication1.id,
+ rightComplication1.complicationData.toApiComplicationData()
+ )
}
@Test
diff --git a/wear/wear-input/samples/src/main/java/androidx/wear/input/samples/WearableRemoteInputExtenderSample.kt b/wear/wear-input/samples/src/main/java/androidx/wear/input/samples/WearableRemoteInputExtenderSample.kt
index f82948c..172aff6 100644
--- a/wear/wear-input/samples/src/main/java/androidx/wear/input/samples/WearableRemoteInputExtenderSample.kt
+++ b/wear/wear-input/samples/src/main/java/androidx/wear/input/samples/WearableRemoteInputExtenderSample.kt
@@ -28,5 +28,6 @@
.wearableExtender {
setEmojisAllowed(false)
setInputActionType(EditorInfo.IME_ACTION_GO)
- }.build()
+ }
+ .build()
}
diff --git a/wear/wear-input/src/main/java/androidx/wear/input/RemoteInputIntentHelper.kt b/wear/wear-input/src/main/java/androidx/wear/input/RemoteInputIntentHelper.kt
index 542604f..846972c 100644
--- a/wear/wear-input/src/main/java/androidx/wear/input/RemoteInputIntentHelper.kt
+++ b/wear/wear-input/src/main/java/androidx/wear/input/RemoteInputIntentHelper.kt
@@ -23,9 +23,8 @@
/**
* Helper functions for supporting remote inputs through starting an [android.content.Intent].
*
- *
- * The following example prompts the user to provide input for one `RemoteInput` by
- * starting an input activity.
+ * The following example prompts the user to provide input for one `RemoteInput` by starting an
+ * input activity.
*
* ```
* public const val KEY_QUICK_REPLY_TEXT: String = "quick_reply";
@@ -39,7 +38,6 @@
*
* The intent returned via [android.app.Activity.onActivityResult] will contain the input results if
* collected, for example:
- *
* ```
* override fun onActivityResult(requestCode: Int, resultCode: Int, intentResults: Intent?) {
* val results: Bundle = RemoteInput.getResultsFromIntent(intentResults)
@@ -84,21 +82,19 @@
@NonNull
public fun createActionRemoteInputIntent(): Intent = Intent(ACTION_REMOTE_INPUT)
- /**
- * Checks whether the action of the given intent is for remote input.
- */
+ /** Checks whether the action of the given intent is for remote input. */
@JvmStatic
public fun isActionRemoteInput(intent: Intent): Boolean =
intent.action == ACTION_REMOTE_INPUT
/**
* Returns the array of [RemoteInput] from the given [Intent] that specifies inputs to be
- * collected from a user. Should be used with [Intent] created with [
- * .createActionRemoteInputIntent].
+ * collected from a user. Should be used with [Intent] created with
+ * [ .createActionRemoteInputIntent].
*
* @param intent The intent with given data.
* @return The array of [RemoteInput] previously added with [putRemoteInputsExtra] or null
- * which means no user input required.
+ * which means no user input required.
*/
@Suppress("DEPRECATION")
@JvmStatic
@@ -106,9 +102,7 @@
public fun getRemoteInputsExtra(intent: Intent): List<RemoteInput>? =
intent.getParcelableArrayExtra(EXTRA_REMOTE_INPUTS)?.map { it as RemoteInput }
- /**
- * Checks whether the given [Intent] has extra for the array of [RemoteInput].
- */
+ /** Checks whether the given [Intent] has extra for the array of [RemoteInput]. */
@JvmStatic
public fun hasRemoteInputsExtra(intent: Intent): Boolean =
intent.hasExtra(EXTRA_REMOTE_INPUTS)
@@ -122,10 +116,8 @@
*/
@JvmStatic
@NonNull
- public fun putRemoteInputsExtra(
- intent: Intent,
- remoteInputs: List<RemoteInput>
- ): Intent = intent.putExtra(EXTRA_REMOTE_INPUTS, remoteInputs.toTypedArray())
+ public fun putRemoteInputsExtra(intent: Intent, remoteInputs: List<RemoteInput>): Intent =
+ intent.putExtra(EXTRA_REMOTE_INPUTS, remoteInputs.toTypedArray())
/**
* Returns the [CharSequence] from the given [Intent] that specifies what is displayed on
@@ -133,7 +125,7 @@
*
* @param intent The intent with given data.
* @return The CharSequence previously added with [putTitleExtra] or null if no value is
- * found.
+ * found.
*/
@JvmStatic
@Nullable
@@ -159,7 +151,7 @@
*
* @param intent The intent with given data.
* @return The CharSequence previously added with [putCancelLabelExtra] or null if no value
- * is found.
+ * is found.
*/
@JvmStatic
@Nullable
@@ -185,7 +177,7 @@
*
* @param intent The intent with given data.
* @return The CharSequence previously added with [putConfirmLabelExtra] or null if no value
- * is found.
+ * is found.
*/
@JvmStatic
@Nullable
@@ -212,7 +204,7 @@
*
* @param intent The intent with given data.
* @return The CharSequence previously added with [putInProgressLabelExtra] or null if no
- * value is found.
+ * value is found.
*/
@JvmStatic
@Nullable
@@ -221,8 +213,8 @@
/**
* Adds the [CharSequence] to the given [Intent] that specifies what is displayed while the
- * wearable is preparing to automatically execute the action. This is usually a 'ing'
- * verb ending in ellipsis like "Sending...". Defaults to "Sending...".
+ * wearable is preparing to automatically execute the action. This is usually a 'ing' verb
+ * ending in ellipsis like "Sending...". Defaults to "Sending...".
*
* @param intent The intent with given data.
* @param label The CharSequence to be added.
@@ -239,7 +231,7 @@
*
* @param intent The intent with given data.
* @return The array of [CharSequence] previously added with [putSmartReplyContextExtra] or
- * [putSmartReplyContextExtra] or null if no value is found.
+ * [putSmartReplyContextExtra] or null if no value is found.
*/
@JvmStatic
@Nullable
@@ -247,15 +239,15 @@
intent.getCharSequenceArrayListExtra(EXTRA_SMART_REPLY_CONTEXT)
/**
- * Adds the array of [CharSequence] to the given [Intent] that provides context for
- * creating Smart Reply choices within a RemoteInput session. The context should be
- * incoming chat messages that a user will reply to using RemoteInput. Only incoming
- * messages (messages from other users) should be passed via this extra.
+ * Adds the array of [CharSequence] to the given [Intent] that provides context for creating
+ * Smart Reply choices within a RemoteInput session. The context should be incoming chat
+ * messages that a user will reply to using RemoteInput. Only incoming messages (messages
+ * from other users) should be passed via this extra.
*
- * The messages should be in the order that they were received with the newest messages
- * at the highest index of the CharSequence[]. For example, a possible value for this
- * extra would be: ["hey", "where are you?"]. In this case, "where are you?" was the most
- * recently received message.
+ * The messages should be in the order that they were received with the newest messages at
+ * the highest index of the CharSequence[]. For example, a possible value for this extra
+ * would be: ["hey", "where are you?"]. In this case, "where are you?" was the most recently
+ * received message.
*
* Passing a chat context into RemoteInput using this method does not guarantee that Smart
* Reply choices will be shown to a user.
diff --git a/wear/wear-input/src/main/java/androidx/wear/input/WearableRemoteInputExtender.kt b/wear/wear-input/src/main/java/androidx/wear/input/WearableRemoteInputExtender.kt
index 6ccbcde..e1b29e1 100644
--- a/wear/wear-input/src/main/java/androidx/wear/input/WearableRemoteInputExtender.kt
+++ b/wear/wear-input/src/main/java/androidx/wear/input/WearableRemoteInputExtender.kt
@@ -36,84 +36,77 @@
* Adding extra to a [RemoteInput] for allowing or disallowing showing emoji-only options (e.g.
* the Draw Emoji option).
*
- * If set to false, the Draw Emoji option will not be shown. If set to true or not set, the
- * Draw Emoji option will be shown as long as the [RemoteInput] allows free form input.
+ * If set to false, the Draw Emoji option will not be shown. If set to true or not set, the Draw
+ * Emoji option will be shown as long as the [RemoteInput] allows free form input.
*
* @param emojisAllowed Whether the emoji-only options is shown. If not set, it will be allowed.
*/
- public fun setEmojisAllowed(emojisAllowed: Boolean): WearableRemoteInputExtender =
- apply { extras.putBoolean(EXTRA_DISALLOW_EMOJI, !emojisAllowed) }
+ public fun setEmojisAllowed(emojisAllowed: Boolean): WearableRemoteInputExtender = apply {
+ extras.putBoolean(EXTRA_DISALLOW_EMOJI, !emojisAllowed)
+ }
/**
* Adding specified input action type to a [RemoteInput] to modify the action type of the
* RemoteInput session (e.g. "send" or "search"). The default action type is "send."
*
* @param imeActionType Action type to be set on RemoteInput session. Should be one of the
- * following values: [EditorInfo.IME_ACTION_SEND], [EditorInfo.IME_ACTION_SEARCH],
- * [EditorInfo.IME_ACTION_DONE], [EditorInfo.IME_ACTION_GO]. If not, send action will be set.
+ * following values: [EditorInfo.IME_ACTION_SEND], [EditorInfo.IME_ACTION_SEARCH],
+ * [EditorInfo.IME_ACTION_DONE], [EditorInfo.IME_ACTION_GO]. If not, send action will be set.
*/
public fun setInputActionType(imeActionType: Int): WearableRemoteInputExtender = apply {
- extras.putInt(
- EXTRA_INPUT_ACTION_TYPE, getInputActionTypeForImeActionType(imeActionType)
- )
+ extras.putInt(EXTRA_INPUT_ACTION_TYPE, getInputActionTypeForImeActionType(imeActionType))
}
- /**
- * Returns the [RemoteInput.Builder] with set options.
- */
+ /** Returns the [RemoteInput.Builder] with set options. */
public fun get(): RemoteInput.Builder = remoteInput.addExtras(extras)
@VisibleForTesting
internal companion object {
/**
- * Key for a boolean extra that can be added to a [RemoteInput] to cause emoji-only
- * options (e.g. the Draw Emoji option) to not be shown.
+ * Key for a boolean extra that can be added to a [RemoteInput] to cause emoji-only options
+ * (e.g. the Draw Emoji option) to not be shown.
*
- * If this extra has value true, the Draw Emoji option will not be shown. If this extra
- * is not present or has any other value, the Draw Emoji option will be shown as long as
- * the [RemoteInput] allows free form input.
+ * If this extra has value true, the Draw Emoji option will not be shown. If this extra is
+ * not present or has any other value, the Draw Emoji option will be shown as long as the
+ * [RemoteInput] allows free form input.
*/
@VisibleForTesting
internal const val EXTRA_DISALLOW_EMOJI =
"android.support.wearable.input.extra.DISALLOW_EMOJI"
/**
- * Key for an integer extra that can be added to a [RemoteInput] to modify the action
- * type of the RemoteInput session (e.g. "send" or "search"). The default action type is
- * "send."
+ * Key for an integer extra that can be added to a [RemoteInput] to modify the action type
+ * of the RemoteInput session (e.g. "send" or "search"). The default action type is "send."
*/
@VisibleForTesting
internal const val EXTRA_INPUT_ACTION_TYPE =
"android.support.wearable.input.extra.INPUT_ACTION_TYPE"
/** Send action type. */
- @VisibleForTesting
- internal const val INPUT_ACTION_TYPE_SEND = 0
+ @VisibleForTesting internal const val INPUT_ACTION_TYPE_SEND = 0
/** Search action type. */
- @VisibleForTesting
- internal const val INPUT_ACTION_TYPE_SEARCH = 1
+ @VisibleForTesting internal const val INPUT_ACTION_TYPE_SEARCH = 1
/** Done action type. */
- @VisibleForTesting
- internal const val INPUT_ACTION_TYPE_DONE = 2
+ @VisibleForTesting internal const val INPUT_ACTION_TYPE_DONE = 2
/** Go action type. */
- @VisibleForTesting
- internal const val INPUT_ACTION_TYPE_GO = 3
+ @VisibleForTesting internal const val INPUT_ACTION_TYPE_GO = 3
- internal fun getInputActionTypeForImeActionType(imeActionType: Int) = when (imeActionType) {
- EditorInfo.IME_ACTION_SEND -> INPUT_ACTION_TYPE_SEND
- EditorInfo.IME_ACTION_SEARCH -> INPUT_ACTION_TYPE_SEARCH
- EditorInfo.IME_ACTION_DONE -> INPUT_ACTION_TYPE_DONE
- EditorInfo.IME_ACTION_GO -> INPUT_ACTION_TYPE_GO
- // If any other action is passed which is not support on Wear OS, use the default
- // send action.
- else -> INPUT_ACTION_TYPE_SEND
- }
+ internal fun getInputActionTypeForImeActionType(imeActionType: Int) =
+ when (imeActionType) {
+ EditorInfo.IME_ACTION_SEND -> INPUT_ACTION_TYPE_SEND
+ EditorInfo.IME_ACTION_SEARCH -> INPUT_ACTION_TYPE_SEARCH
+ EditorInfo.IME_ACTION_DONE -> INPUT_ACTION_TYPE_DONE
+ EditorInfo.IME_ACTION_GO -> INPUT_ACTION_TYPE_GO
+ // If any other action is passed which is not support on Wear OS, use the default
+ // send action.
+ else -> INPUT_ACTION_TYPE_SEND
+ }
}
}
-public fun RemoteInput.Builder.wearableExtender(block: WearableRemoteInputExtender.() -> Unit):
- RemoteInput.Builder =
- WearableRemoteInputExtender(this).apply { block() }.get()
+public fun RemoteInput.Builder.wearableExtender(
+ block: WearableRemoteInputExtender.() -> Unit
+): RemoteInput.Builder = WearableRemoteInputExtender(this).apply { block() }.get()
diff --git a/wear/wear-input/src/test/java/androidx/wear/input/RemoteInputIntentHelperTest.kt b/wear/wear-input/src/test/java/androidx/wear/input/RemoteInputIntentHelperTest.kt
index c066fb4..dcbf5873 100644
--- a/wear/wear-input/src/test/java/androidx/wear/input/RemoteInputIntentHelperTest.kt
+++ b/wear/wear-input/src/test/java/androidx/wear/input/RemoteInputIntentHelperTest.kt
@@ -26,9 +26,8 @@
@RunWith(WearInputTestRunner::class)
class RemoteInputIntentHelperTest {
- private val remoteInputs: List<RemoteInput> = listOf(
- RemoteInput.Builder("ri1").build(), RemoteInput.Builder("ri2").build()
- )
+ private val remoteInputs: List<RemoteInput> =
+ listOf(RemoteInput.Builder("ri1").build(), RemoteInput.Builder("ri2").build())
@Test
fun testCreateIntentWithRemoteInputAction() {
diff --git a/wear/wear-input/src/test/java/androidx/wear/input/WearInputTestRunner.kt b/wear/wear-input/src/test/java/androidx/wear/input/WearInputTestRunner.kt
index 426feb0..da056f3 100644
--- a/wear/wear-input/src/test/java/androidx/wear/input/WearInputTestRunner.kt
+++ b/wear/wear-input/src/test/java/androidx/wear/input/WearInputTestRunner.kt
@@ -25,16 +25,13 @@
*
* It has instrumentation turned off for the [androidx.wear.input] package.
*
- * Robolectric tries to instrument Kotlin classes, and it throws errors when it encounters
- * companion objects, constructors with default values for parameters, and data classes with
- * inline classes. We don't need shadowing of our classes because we want to use the actual
- * objects in our tests.
+ * Robolectric tries to instrument Kotlin classes, and it throws errors when it encounters companion
+ * objects, constructors with default values for parameters, and data classes with inline classes.
+ * We don't need shadowing of our classes because we want to use the actual objects in our tests.
*/
class WearInputTestRunner(testClass: Class<*>) : RobolectricTestRunner(testClass) {
override fun createClassLoaderConfig(method: FrameworkMethod): InstrumentationConfiguration =
- InstrumentationConfiguration.Builder(
- super.createClassLoaderConfig(method)
- )
+ InstrumentationConfiguration.Builder(super.createClassLoaderConfig(method))
.doNotInstrumentPackage("androidx.wear.input")
.build()
}
diff --git a/wear/wear-input/src/test/java/androidx/wear/input/WearableRemoteInputExtenderTest.kt b/wear/wear-input/src/test/java/androidx/wear/input/WearableRemoteInputExtenderTest.kt
index 5c410ac..6143d5e 100644
--- a/wear/wear-input/src/test/java/androidx/wear/input/WearableRemoteInputExtenderTest.kt
+++ b/wear/wear-input/src/test/java/androidx/wear/input/WearableRemoteInputExtenderTest.kt
@@ -36,59 +36,54 @@
class WearableRemoteInputExtenderTest {
@Test
fun testDisallowEmoji() {
- val remoteInput = RemoteInput.Builder("resultKey")
- .wearableExtender {
- setEmojisAllowed(false)
- }.build()
+ val remoteInput =
+ RemoteInput.Builder("resultKey").wearableExtender { setEmojisAllowed(false) }.build()
- assertTrue(
- remoteInput.extras.getBoolean(WearableRemoteInputExtender.EXTRA_DISALLOW_EMOJI)
- )
+ assertTrue(remoteInput.extras.getBoolean(WearableRemoteInputExtender.EXTRA_DISALLOW_EMOJI))
// Test that input action type is not set.
assertEquals(
- -1, remoteInput.extras.getInt(WearableRemoteInputExtender.EXTRA_INPUT_ACTION_TYPE, -1)
+ -1,
+ remoteInput.extras.getInt(WearableRemoteInputExtender.EXTRA_INPUT_ACTION_TYPE, -1)
)
}
@Test
fun testSetEmojisAllowed() {
- val remoteInput: RemoteInput = RemoteInput.Builder("resultKey")
- .wearableExtender {
- setEmojisAllowed(true)
- }.build()
+ val remoteInput: RemoteInput =
+ RemoteInput.Builder("resultKey").wearableExtender { setEmojisAllowed(true) }.build()
- assertFalse(
- remoteInput.extras.getBoolean(WearableRemoteInputExtender.EXTRA_DISALLOW_EMOJI)
- )
+ assertFalse(remoteInput.extras.getBoolean(WearableRemoteInputExtender.EXTRA_DISALLOW_EMOJI))
// Test that input action type is not set.
assertEquals(
- -1, remoteInput.extras.getInt(WearableRemoteInputExtender.EXTRA_INPUT_ACTION_TYPE, -1)
+ -1,
+ remoteInput.extras.getInt(WearableRemoteInputExtender.EXTRA_INPUT_ACTION_TYPE, -1)
)
}
@Test
fun testSetEmojisAllowed_notSet() {
- val remoteInput: RemoteInput = RemoteInput.Builder("resultKey")
- .wearableExtender {
- // empty
- }.build()
+ val remoteInput: RemoteInput =
+ RemoteInput.Builder("resultKey")
+ .wearableExtender {
+ // empty
+ }
+ .build()
- assertFalse(
- remoteInput.extras.getBoolean(WearableRemoteInputExtender.EXTRA_DISALLOW_EMOJI)
- )
+ assertFalse(remoteInput.extras.getBoolean(WearableRemoteInputExtender.EXTRA_DISALLOW_EMOJI))
// Test that input action type is not set.
assertEquals(
- -1, remoteInput.extras.getInt(WearableRemoteInputExtender.EXTRA_INPUT_ACTION_TYPE, -1)
+ -1,
+ remoteInput.extras.getInt(WearableRemoteInputExtender.EXTRA_INPUT_ACTION_TYPE, -1)
)
}
@Test
fun testSetInputActionType() {
for ((ime, iat) in imeToActionTypeMap) {
- val remoteInput = RemoteInput.Builder("resultKey")
- .wearableExtender {
- setInputActionType(ime)
- }.build()
+ val remoteInput =
+ RemoteInput.Builder("resultKey")
+ .wearableExtender { setInputActionType(ime) }
+ .build()
assertEquals(
iat,
@@ -104,15 +99,15 @@
@Test
fun testDisallowEmoji_SetInputActionType() {
- val remoteInput = RemoteInput.Builder("resultKey")
- .wearableExtender {
- setEmojisAllowed(false)
- setInputActionType(IME_ACTION_GO)
- }.build()
+ val remoteInput =
+ RemoteInput.Builder("resultKey")
+ .wearableExtender {
+ setEmojisAllowed(false)
+ setInputActionType(IME_ACTION_GO)
+ }
+ .build()
- assertTrue(
- remoteInput.extras.getBoolean(WearableRemoteInputExtender.EXTRA_DISALLOW_EMOJI)
- )
+ assertTrue(remoteInput.extras.getBoolean(WearableRemoteInputExtender.EXTRA_DISALLOW_EMOJI))
assertEquals(
INPUT_ACTION_TYPE_GO,
remoteInput.extras.getInt(WearableRemoteInputExtender.EXTRA_INPUT_ACTION_TYPE)
@@ -120,12 +115,13 @@
}
companion object {
- val imeToActionTypeMap = hashMapOf(
- IME_ACTION_SEND to INPUT_ACTION_TYPE_SEND,
- IME_ACTION_SEARCH to INPUT_ACTION_TYPE_SEARCH,
- IME_ACTION_DONE to INPUT_ACTION_TYPE_DONE,
- IME_ACTION_GO to INPUT_ACTION_TYPE_GO,
- IME_ACTION_NEXT to INPUT_ACTION_TYPE_SEND // other value
- )
+ val imeToActionTypeMap =
+ hashMapOf(
+ IME_ACTION_SEND to INPUT_ACTION_TYPE_SEND,
+ IME_ACTION_SEARCH to INPUT_ACTION_TYPE_SEARCH,
+ IME_ACTION_DONE to INPUT_ACTION_TYPE_DONE,
+ IME_ACTION_GO to INPUT_ACTION_TYPE_GO,
+ IME_ACTION_NEXT to INPUT_ACTION_TYPE_SEND // other value
+ )
}
}
diff --git a/wear/wear-ongoing/src/test/java/androidx/wear/ongoing/OngoingActivityPartTest.kt b/wear/wear-ongoing/src/test/java/androidx/wear/ongoing/OngoingActivityPartTest.kt
index 9af8adf..7278c71 100644
--- a/wear/wear-ongoing/src/test/java/androidx/wear/ongoing/OngoingActivityPartTest.kt
+++ b/wear/wear-ongoing/src/test/java/androidx/wear/ongoing/OngoingActivityPartTest.kt
@@ -40,77 +40,35 @@
assertNotEquals(Status.TextPart("Other"), textStatus)
assertEquals(Status.TextPart(text).hashCode(), textStatus.hashCode())
- assertEquals(
- Status.TextPart("Other").hashCode(),
- Status.TextPart("Other").hashCode()
- )
+ assertEquals(Status.TextPart("Other").hashCode(), Status.TextPart("Other").hashCode())
}
@Test
fun testTimerOngoingActivityStatusBasic() {
- assertEquals(
- Status.StopwatchPart(1234L),
- Status.StopwatchPart(1234L)
- )
- assertEquals(
- Status.StopwatchPart(1234L).hashCode(),
- Status.StopwatchPart(1234L).hashCode()
- )
- assertNotEquals(
- Status.StopwatchPart(1234L),
- Status.StopwatchPart(1235L)
- )
+ assertEquals(Status.StopwatchPart(1234L), Status.StopwatchPart(1234L))
+ assertEquals(Status.StopwatchPart(1234L).hashCode(), Status.StopwatchPart(1234L).hashCode())
+ assertNotEquals(Status.StopwatchPart(1234L), Status.StopwatchPart(1235L))
- assertEquals(
- Status.TimerPart(1234L),
- Status.TimerPart(1234L)
- )
- assertEquals(
- Status.TimerPart(1234L).hashCode(),
- Status.TimerPart(1234L).hashCode()
- )
- assertNotEquals(
- Status.StopwatchPart(1234L),
- Status.TimerPart(1234L)
- )
+ assertEquals(Status.TimerPart(1234L), Status.TimerPart(1234L))
+ assertEquals(Status.TimerPart(1234L).hashCode(), Status.TimerPart(1234L).hashCode())
+ assertNotEquals(Status.StopwatchPart(1234L), Status.TimerPart(1234L))
- assertEquals(
- Status.TimerPart(1234L, 5678L),
- Status.TimerPart(1234L, 5678L)
- )
+ assertEquals(Status.TimerPart(1234L, 5678L), Status.TimerPart(1234L, 5678L))
assertEquals(
Status.TimerPart(1234L, 5678L).hashCode(),
Status.TimerPart(1234L, 5678L).hashCode()
)
- assertNotEquals(
- Status.TimerPart(1234L, 5678L),
- Status.TimerPart(1234L, 5679L)
- )
- assertNotEquals(
- Status.TimerPart(1234L, 5678L),
- Status.TimerPart(1234L)
- )
+ assertNotEquals(Status.TimerPart(1234L, 5678L), Status.TimerPart(1234L, 5679L))
+ assertNotEquals(Status.TimerPart(1234L, 5678L), Status.TimerPart(1234L))
- assertEquals(
- Status.TimerPart(1234L, 5678L, 100L),
- Status.TimerPart(1234L, 5678L, 100L)
- )
+ assertEquals(Status.TimerPart(1234L, 5678L, 100L), Status.TimerPart(1234L, 5678L, 100L))
assertEquals(
Status.TimerPart(1234L, 5678L, 100L).hashCode(),
Status.TimerPart(1234L, 5678L, 100L).hashCode()
)
- assertNotEquals(
- Status.TimerPart(1234L, 5678L, 100L),
- Status.TimerPart(1234L, 5678L, 101L)
- )
- assertNotEquals(
- Status.TimerPart(1234L, 5678L, 100L),
- Status.TimerPart(1234L, 5678L)
- )
- assertNotEquals(
- Status.TimerPart(1234L, 5678L, 100L),
- Status.TimerPart(1234L)
- )
+ assertNotEquals(Status.TimerPart(1234L, 5678L, 100L), Status.TimerPart(1234L, 5678L, 101L))
+ assertNotEquals(Status.TimerPart(1234L, 5678L, 100L), Status.TimerPart(1234L, 5678L))
+ assertNotEquals(Status.TimerPart(1234L, 5678L, 100L), Status.TimerPart(1234L))
}
@Suppress("deprecation")
@@ -118,28 +76,30 @@
fun testOngoingActivityStatusSerialization() {
val key = "KEY"
listOf(
- Status.StopwatchPart(1234L),
- Status.TextPart("Text1"),
- Status.TimerPart(1234L),
- Status.TimerPart(1234L, 5678L),
- Status.TextPart("Text2"),
- Status.StopwatchPart(1234L, 5678L, 100L)
- ).forEach { original ->
- val bundle = Bundle()
- ParcelUtils.putVersionedParcelable(bundle, key, original.toVersionedParcelable())
+ Status.StopwatchPart(1234L),
+ Status.TextPart("Text1"),
+ Status.TimerPart(1234L),
+ Status.TimerPart(1234L, 5678L),
+ Status.TextPart("Text2"),
+ Status.StopwatchPart(1234L, 5678L, 100L)
+ )
+ .forEach { original ->
+ val bundle = Bundle()
+ ParcelUtils.putVersionedParcelable(bundle, key, original.toVersionedParcelable())
- val p = Parcel.obtain()
- p.writeParcelable(bundle, 0)
- p.setDataPosition(0)
+ val p = Parcel.obtain()
+ p.writeParcelable(bundle, 0)
+ p.setDataPosition(0)
- val receivedBundle = p.readParcelable<Bundle>(Bundle::class.java.classLoader)!!
+ val receivedBundle = p.readParcelable<Bundle>(Bundle::class.java.classLoader)!!
- val received = Status.Part.fromVersionedParcelable(
- ParcelUtils.getVersionedParcelable<StatusPart>(receivedBundle, key)
- )!!
- assertEquals(original, received)
- assertEquals(original.hashCode(), received.hashCode())
- }
+ val received =
+ Status.Part.fromVersionedParcelable(
+ ParcelUtils.getVersionedParcelable<StatusPart>(receivedBundle, key)
+ )!!
+ assertEquals(original, received)
+ assertEquals(original.hashCode(), received.hashCode())
+ }
}
@Test
@@ -181,8 +141,7 @@
// Create a chronometer, starting at the given timestamp (around 2 minutes after
// timestamp 0).
val t0 = 123456L
- val timerStatus =
- Status.StopwatchPart(/* timeZeroMillis = */ t0)
+ val timerStatus = Status.StopwatchPart(/* timeZeroMillis= */ t0)
// The chronometer is not paused.
assertFalse(timerStatus.isPaused)
@@ -243,10 +202,7 @@
@Test
fun testTimerOngoingActivityStatusChronometerPaused() {
val t0 = 123456L
- var timerStatus = Status.StopwatchPart(
- /* timeZeroMillis = */ t0,
- /* pausedAt = */ t0 + 1999
- )
+ var timerStatus = Status.StopwatchPart(/* timeZeroMillis= */ t0, /* pausedAt= */ t0 + 1999)
// The Timer is paused.
assertTrue(timerStatus.isPaused())
@@ -267,10 +223,7 @@
@Test
fun testTimerOngoingActivityStatusTimerPaused() {
val t0 = 123456L
- var timerStatus = Status.TimerPart(
- /* timeZeroMillis = */ t0,
- /* pausedAt = */ t0 + 1999
- )
+ var timerStatus = Status.TimerPart(/* timeZeroMillis= */ t0, /* pausedAt= */ t0 + 1999)
// The Timer is paused.
assertTrue(timerStatus.isPaused())
diff --git a/wear/wear-ongoing/src/test/java/androidx/wear/ongoing/OngoingActivityStatusTest.kt b/wear/wear-ongoing/src/test/java/androidx/wear/ongoing/OngoingActivityStatusTest.kt
index ca17fe6..8a212cb 100644
--- a/wear/wear-ongoing/src/test/java/androidx/wear/ongoing/OngoingActivityStatusTest.kt
+++ b/wear/wear-ongoing/src/test/java/androidx/wear/ongoing/OngoingActivityStatusTest.kt
@@ -25,10 +25,11 @@
@Test
fun testTextOngoingActivityStatusText() {
- val status = Status.Builder()
- .addPart("1", Status.TextPart("First Text"))
- .addPart("2", Status.TextPart("Second Text"))
- .build()
+ val status =
+ Status.Builder()
+ .addPart("1", Status.TextPart("First Text"))
+ .addPart("2", Status.TextPart("Second Text"))
+ .build()
assertEquals(Long.MAX_VALUE, status.getNextChangeTimeMillis(0))
@@ -37,42 +38,41 @@
@Test
fun testTextOngoingActivityStatusTextAndTemplate() {
- val status = Status.Builder()
- .addPart("one", Status.TextPart("First Text"))
- .addPart("two", Status.TextPart("Second Text"))
- .addTemplate("#one# | #two#").build()
+ val status =
+ Status.Builder()
+ .addPart("one", Status.TextPart("First Text"))
+ .addPart("two", Status.TextPart("Second Text"))
+ .addTemplate("#one# | #two#")
+ .build()
assertEquals(Long.MAX_VALUE, status.getNextChangeTimeMillis(0))
- assertEquals(
- "First Text | Second Text",
- status.getText(context, 0).toString()
- )
+ assertEquals("First Text | Second Text", status.getText(context, 0).toString())
}
@Test
fun testTextOngoingActivityStatusTextAndTemplate2() {
- val status = Status.Builder()
- .addPart("a", Status.TextPart("A"))
- .addPart("b", Status.TextPart("B"))
- .addTemplate("#a##b#").build()
+ val status =
+ Status.Builder()
+ .addPart("a", Status.TextPart("A"))
+ .addPart("b", Status.TextPart("B"))
+ .addTemplate("#a##b#")
+ .build()
assertEquals(Long.MAX_VALUE, status.getNextChangeTimeMillis(0))
- assertEquals(
- "AB",
- status.getText(context, 0).toString()
- )
+ assertEquals("AB", status.getText(context, 0).toString())
}
@Test
fun testTextOngoingActivityStatusMixed() {
val t0 = 123456L
- val status = Status.Builder()
- .addPart("type", Status.TextPart("Workout"))
- .addPart("time", Status.StopwatchPart(t0))
- .addTemplate("The time on your #type# is #time#")
- .build()
+ val status =
+ Status.Builder()
+ .addPart("type", Status.TextPart("Workout"))
+ .addPart("time", Status.StopwatchPart(t0))
+ .addTemplate("The time on your #type# is #time#")
+ .build()
assertEquals(t0 + 1000, status.getNextChangeTimeMillis(t0))
@@ -84,28 +84,21 @@
@Test
fun testProcessTemplate() {
- val values = mapOf(
- "1" to "One",
- "2" to "Two",
- "3" to "Three",
- "Long" to "LongValue",
- "Foo" to "Bar"
- )
+ val values =
+ mapOf("1" to "One", "2" to "Two", "3" to "Three", "Long" to "LongValue", "Foo" to "Bar")
listOf(
- "#1# #2# #3#" to "One Two Three",
- "#1####2####3#" to "One#Two#Three",
- "###1####2####3###" to "#One#Two#Three#",
- "#1##Long##Foo#" to "OneLongValueBar",
- // Unclosed variables are ignored
- "#1# #2# #3" to "One Two #3",
- "#1##" to "One#"
- ).forEach { (template, expected) ->
- assertEquals(
- expected,
- Status.processTemplate(template, values).toString()
+ "#1# #2# #3#" to "One Two Three",
+ "#1####2####3#" to "One#Two#Three",
+ "###1####2####3###" to "#One#Two#Three#",
+ "#1##Long##Foo#" to "OneLongValueBar",
+ // Unclosed variables are ignored
+ "#1# #2# #3" to "One Two #3",
+ "#1##" to "One#"
)
- }
+ .forEach { (template, expected) ->
+ assertEquals(expected, Status.processTemplate(template, values).toString())
+ }
// Check that when undefined values are used, returns null
assertNull(Status.processTemplate("#NOT#", values))
@@ -113,29 +106,21 @@
@Test
fun testMultipleTemplates() {
- val values = mapOf(
- "1" to "One",
- "2" to "Two",
- "3" to "Three",
- "Long" to "LongValue",
- "Foo" to "Bar"
- )
+ val values =
+ mapOf("1" to "One", "2" to "Two", "3" to "Three", "Long" to "LongValue", "Foo" to "Bar")
// list of (list of template -> expected output)
listOf(
- listOf("#1#", "#2#", "#3#") to "One",
- listOf("#5#", "#4#", "#3#", "#2#") to "Three",
- listOf("#1##11#", "2=#2#") to "2=Two",
- ).forEach { (templates, expected) ->
- val status = Status(
- templates,
- values.map { (k, v) ->
- k to TextStatusPart(v)
- }.toMap()
+ listOf("#1#", "#2#", "#3#") to "One",
+ listOf("#5#", "#4#", "#3#", "#2#") to "Three",
+ listOf("#1##11#", "2=#2#") to "2=Two",
)
+ .forEach { (templates, expected) ->
+ val status =
+ Status(templates, values.map { (k, v) -> k to TextStatusPart(v) }.toMap())
- assertEquals(expected, status.getText(context, 0).toString())
- }
+ assertEquals(expected, status.getText(context, 0).toString())
+ }
}
@Test(expected = IllegalStateException::class)
@@ -161,6 +146,7 @@
private class SampleStatusPartImpl : StatusPart() {
override fun getText(context: Context, timeNowMillis: Long) = "Sample"
+
override fun getNextChangeTimeMillis(fromTimeMillis: Long) = Long.MAX_VALUE
}
@@ -169,8 +155,10 @@
override fun getText(context: Context, timeNowMillis: Long) =
mPart.getText(context, timeNowMillis)
+
override fun getNextChangeTimeMillis(fromTimeMillis: Long) =
mPart.getNextChangeTimeMillis(fromTimeMillis)
+
override fun toVersionedParcelable(): StatusPart = mPart
}
}
diff --git a/wear/wear-ongoing/src/test/java/androidx/wear/ongoing/OngoingActivityTest.kt b/wear/wear-ongoing/src/test/java/androidx/wear/ongoing/OngoingActivityTest.kt
index 91f80752..62903f1 100644
--- a/wear/wear-ongoing/src/test/java/androidx/wear/ongoing/OngoingActivityTest.kt
+++ b/wear/wear-ongoing/src/test/java/androidx/wear/ongoing/OngoingActivityTest.kt
@@ -29,11 +29,7 @@
private val StaticIconResourceId = 456
private val LocusIdValue = LocusIdCompat("TestLocusId")
private val OaId = 123456
- private val BasicStatus = androidx.wear.ongoing.Status.forPart(
- Status.TextPart(
- "Basic Status"
- )
- )
+ private val BasicStatus = androidx.wear.ongoing.Status.forPart(Status.TextPart("Basic Status"))
private val NotificationId = 4321
private val ChannelId = "ChannelId"
private val Title = "AppTitle"
@@ -46,18 +42,19 @@
@Before
fun setUp() {
context = ApplicationProvider.getApplicationContext()
- notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE)
- as NotificationManager
+ notificationManager =
+ context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
PendingIntentValue = PendingIntent.getBroadcast(context, 0, Intent(), 0)
}
@Test
fun testMinimalOngoingActivity() {
val builder = NotificationCompat.Builder(context, ChannelId)
- val oa = OngoingActivity.Builder(context, 1, builder)
- .setStaticIcon(StaticIconResourceId)
- .setTouchIntent(PendingIntentValue)
- .build()
+ val oa =
+ OngoingActivity.Builder(context, 1, builder)
+ .setStaticIcon(StaticIconResourceId)
+ .setTouchIntent(PendingIntentValue)
+ .build()
oa.apply(context)
val notification = builder.build()
@@ -75,16 +72,17 @@
@Test
fun testOngoingActivityApply() {
val builder = NotificationCompat.Builder(context, ChannelId)
- val oa = OngoingActivity.Builder(context, 1, builder)
- .setAnimatedIcon(AnimatedIconResourceId)
- .setStaticIcon(StaticIconResourceId)
- .setLocusId(LocusIdValue)
- .setOngoingActivityId(OaId)
- .setStatus(BasicStatus)
- .setTouchIntent(PendingIntentValue)
- .setTitle(Title)
- .setContentDescription(ContentDescription)
- .build()
+ val oa =
+ OngoingActivity.Builder(context, 1, builder)
+ .setAnimatedIcon(AnimatedIconResourceId)
+ .setStaticIcon(StaticIconResourceId)
+ .setLocusId(LocusIdValue)
+ .setOngoingActivityId(OaId)
+ .setStatus(BasicStatus)
+ .setTouchIntent(PendingIntentValue)
+ .setTitle(Title)
+ .setContentDescription(ContentDescription)
+ .build()
oa.apply(context)
val notification = builder.build()
@@ -104,25 +102,22 @@
@Test
fun testOngoingActivityUpdate() {
val builder = NotificationCompat.Builder(context, ChannelId)
- val oa = OngoingActivity.Builder(context, NotificationId, builder)
- .setAnimatedIcon(AnimatedIconResourceId)
- .setStaticIcon(StaticIconResourceId)
- .setLocusId(LocusIdValue)
- .setOngoingActivityId(OaId)
- .setStatus(BasicStatus)
- .setTouchIntent(PendingIntentValue)
- .setTitle(Title)
- .setContentDescription(ContentDescription)
- .build()
+ val oa =
+ OngoingActivity.Builder(context, NotificationId, builder)
+ .setAnimatedIcon(AnimatedIconResourceId)
+ .setStaticIcon(StaticIconResourceId)
+ .setLocusId(LocusIdValue)
+ .setOngoingActivityId(OaId)
+ .setStatus(BasicStatus)
+ .setTouchIntent(PendingIntentValue)
+ .setTitle(Title)
+ .setContentDescription(ContentDescription)
+ .build()
oa.apply(context)
notificationManager.notify(NotificationId, builder.build())
// After posting, send an update.
- val newStatus = androidx.wear.ongoing.Status.forPart(
- Status.StopwatchPart(
- 12345
- )
- )
+ val newStatus = androidx.wear.ongoing.Status.forPart(Status.StopwatchPart(12345))
oa.update(context, newStatus)
// Get the notification and check that the status, and only the status has been updated.
@@ -178,15 +173,23 @@
for (i in 1..n) {
val status = "New Status $i"
statuses.add(status)
- OngoingActivity.recoverOngoingActivity(context, i)!!
- .update(context, Status.forPart(Status.TextPart(status)))
+ OngoingActivity.recoverOngoingActivity(context, i)!!.update(
+ context,
+ Status.forPart(Status.TextPart(status))
+ )
}
assertEquals(n, statuses.size) // Just in case.
// Get status from notifications.
- val notificationStatuses = notificationManager.activeNotifications.mapNotNull { sbn ->
- SerializationHelper.create(sbn.notification)?.status?.getText(context, 0).toString()
- }.toSet()
+ val notificationStatuses =
+ notificationManager.activeNotifications
+ .mapNotNull { sbn ->
+ SerializationHelper.create(sbn.notification)
+ ?.status
+ ?.getText(context, 0)
+ .toString()
+ }
+ .toSet()
// Check.
assertEquals(statuses, notificationStatuses)
@@ -198,16 +201,17 @@
@Test
fun testBlackBoxCopy() {
val builder = NotificationCompat.Builder(context, ChannelId)
- val oa = OngoingActivity.Builder(context, 1, builder)
- .setAnimatedIcon(AnimatedIconResourceId)
- .setStaticIcon(StaticIconResourceId)
- .setLocusId(LocusIdValue)
- .setOngoingActivityId(OaId)
- .setStatus(BasicStatus)
- .setTouchIntent(PendingIntentValue)
- .setTitle(Title)
- .setContentDescription(ContentDescription)
- .build()
+ val oa =
+ OngoingActivity.Builder(context, 1, builder)
+ .setAnimatedIcon(AnimatedIconResourceId)
+ .setStaticIcon(StaticIconResourceId)
+ .setLocusId(LocusIdValue)
+ .setOngoingActivityId(OaId)
+ .setStatus(BasicStatus)
+ .setTouchIntent(PendingIntentValue)
+ .setTitle(Title)
+ .setContentDescription(ContentDescription)
+ .build()
oa.apply(context)
val notification = builder.build()
@@ -230,23 +234,20 @@
@Test
fun testCreateFromExistingOngoingActivityUpdate() {
val builder = NotificationCompat.Builder(context, ChannelId)
- val oa = OngoingActivity.Builder(context, NotificationId, builder)
- .setAnimatedIcon(AnimatedIconResourceId)
- .setStaticIcon(StaticIconResourceId)
- .setLocusId(LocusIdValue)
- .setOngoingActivityId(OaId)
- .setStatus(BasicStatus)
- .setTouchIntent(PendingIntentValue)
- .build()
+ val oa =
+ OngoingActivity.Builder(context, NotificationId, builder)
+ .setAnimatedIcon(AnimatedIconResourceId)
+ .setStaticIcon(StaticIconResourceId)
+ .setLocusId(LocusIdValue)
+ .setOngoingActivityId(OaId)
+ .setStatus(BasicStatus)
+ .setTouchIntent(PendingIntentValue)
+ .build()
oa.apply(context)
notificationManager.notify(NotificationId, builder.build())
// After posting, send an update.
- val newStatus = androidx.wear.ongoing.Status.forPart(
- Status.StopwatchPart(
- 12345
- )
- )
+ val newStatus = androidx.wear.ongoing.Status.forPart(Status.StopwatchPart(12345))
OngoingActivity.recoverOngoingActivity(context)!!.update(context, newStatus)
// Get the notification and check that the status, and only the status has been updated.
@@ -270,10 +271,11 @@
// Test that icons, status and intent are taken from the notification when not specified in
// the OngoingActivity.
val contentText = "Default Content"
- val builder = NotificationCompat.Builder(context, ChannelId)
- .setSmallIcon(StaticIconResourceId)
- .setContentIntent(PendingIntentValue)
- .setContentText(contentText)
+ val builder =
+ NotificationCompat.Builder(context, ChannelId)
+ .setSmallIcon(StaticIconResourceId)
+ .setContentIntent(PendingIntentValue)
+ .setContentText(contentText)
val oa = OngoingActivity.Builder(context, NotificationId, builder).build()
oa.apply(context)
notificationManager.notify(NotificationId, builder.build())
@@ -295,20 +297,22 @@
// Test that icons, status and intent are taken from the OngoingActivity when specified both
// in the notification and OngoingActivity.
val contentText = "Default Content"
- val builder = NotificationCompat.Builder(context, ChannelId)
- .setSmallIcon(StaticIconResourceId)
- .setContentIntent(PendingIntentValue)
- .setContentText(contentText)
+ val builder =
+ NotificationCompat.Builder(context, ChannelId)
+ .setSmallIcon(StaticIconResourceId)
+ .setContentIntent(PendingIntentValue)
+ .setContentText(contentText)
val newStaticIconResourceId = StaticIconResourceId + 1
val newAnimatedIconResourceId = StaticIconResourceId + 2
val newPendingIntentValue = PendingIntent.getBroadcast(context, 1, Intent(), 0)
- val oa = OngoingActivity.Builder(context, NotificationId, builder)
- .setAnimatedIcon(newAnimatedIconResourceId)
- .setStaticIcon(newStaticIconResourceId)
- .setStatus(BasicStatus)
- .setTouchIntent(newPendingIntentValue)
- .build()
+ val oa =
+ OngoingActivity.Builder(context, NotificationId, builder)
+ .setAnimatedIcon(newAnimatedIconResourceId)
+ .setStaticIcon(newStaticIconResourceId)
+ .setStatus(BasicStatus)
+ .setTouchIntent(newPendingIntentValue)
+ .build()
oa.apply(context)
notificationManager.notify(NotificationId, builder.build())
@@ -326,17 +330,16 @@
@Test
fun testHasOngoingActivity() {
- val builder = NotificationCompat.Builder(context, ChannelId)
- .setSmallIcon(StaticIconResourceId)
- .setContentIntent(PendingIntentValue)
- .setContentText("Text")
+ val builder =
+ NotificationCompat.Builder(context, ChannelId)
+ .setSmallIcon(StaticIconResourceId)
+ .setContentIntent(PendingIntentValue)
+ .setContentText("Text")
var notification = builder.build()
assertFalse(SerializationHelper.hasOngoingActivity(notification))
- OngoingActivity.Builder(context, NotificationId, builder)
- .build()
- .apply(context)
+ OngoingActivity.Builder(context, NotificationId, builder).build().apply(context)
notification = builder.build()
assertTrue(SerializationHelper.hasOngoingActivity(notification))
@@ -346,43 +349,37 @@
fun testTagSupport() {
val tag = "TAG"
val builder1 = NotificationCompat.Builder(context, ChannelId)
- val oa1 = OngoingActivity.Builder(context, NotificationId, builder1)
- .setStaticIcon(StaticIconResourceId)
- .setStatus(Status.forPart(Status.TextPart("status1")))
- .setOngoingActivityId(1)
- .setTouchIntent(PendingIntentValue)
- .build()
+ val oa1 =
+ OngoingActivity.Builder(context, NotificationId, builder1)
+ .setStaticIcon(StaticIconResourceId)
+ .setStatus(Status.forPart(Status.TextPart("status1")))
+ .setOngoingActivityId(1)
+ .setTouchIntent(PendingIntentValue)
+ .build()
oa1.apply(context)
notificationManager.notify(NotificationId, builder1.build())
val builder2 = NotificationCompat.Builder(context, ChannelId)
- val oa2 = OngoingActivity.Builder(context, tag, NotificationId, builder2)
- .setStaticIcon(StaticIconResourceId)
- .setStatus(Status.forPart(Status.TextPart("status2")))
- .setOngoingActivityId(2)
- .setTouchIntent(PendingIntentValue)
- .build()
+ val oa2 =
+ OngoingActivity.Builder(context, tag, NotificationId, builder2)
+ .setStaticIcon(StaticIconResourceId)
+ .setStatus(Status.forPart(Status.TextPart("status2")))
+ .setOngoingActivityId(2)
+ .setTouchIntent(PendingIntentValue)
+ .build()
oa2.apply(context)
notificationManager.notify(tag, NotificationId, builder2.build())
assertEquals(2, notificationManager.activeNotifications.size)
// After posting, send an update to the second OA and check the statuses.
- val newStatus2 = androidx.wear.ongoing.Status.forPart(
- Status.TextPart(
- "update2"
- )
- )
+ val newStatus2 = androidx.wear.ongoing.Status.forPart(Status.TextPart("update2"))
OngoingActivity.recoverOngoingActivity(context, 2)?.update(context, newStatus2)
assertEquals("status1, update2", getStatuses())
// Update the first OA, and check the statuses.
- val newStatus1 = androidx.wear.ongoing.Status.forPart(
- Status.TextPart(
- "updated-one"
- )
- )
+ val newStatus1 = androidx.wear.ongoing.Status.forPart(Status.TextPart("updated-one"))
oa1.update(context, newStatus1)
assertEquals("updated-one, update2", getStatuses())
diff --git a/wear/wear-phone-interactions/samples/src/main/java/androidx/wear/phone/interactions/samples/RemoteAuthClientSample.kt b/wear/wear-phone-interactions/samples/src/main/java/androidx/wear/phone/interactions/samples/RemoteAuthClientSample.kt
index baeafa8..823e698 100644
--- a/wear/wear-phone-interactions/samples/src/main/java/androidx/wear/phone/interactions/samples/RemoteAuthClientSample.kt
+++ b/wear/wear-phone-interactions/samples/src/main/java/androidx/wear/phone/interactions/samples/RemoteAuthClientSample.kt
@@ -26,18 +26,21 @@
oAuthRequest: OAuthRequest,
myAuthCallback: RemoteAuthClient.Callback
) {
- remoteAuthClient.availabilityStatus.collect {
- status -> when (status) {
+ remoteAuthClient.availabilityStatus.collect { status ->
+ when (status) {
RemoteAuthClient.STATUS_UNAVAILABLE ->
TODO("Present alternative flow as remote auth is not available")
RemoteAuthClient.STATUS_TEMPORARILY_UNAVAILABLE ->
TODO("Present education to user to connect devices or bring to proximity.")
- RemoteAuthClient.STATUS_AVAILABLE, RemoteAuthClient.STATUS_UNKNOWN ->
+ RemoteAuthClient.STATUS_AVAILABLE,
+ RemoteAuthClient.STATUS_UNKNOWN ->
// Present normal auth flow when we don't know (old devices)
// or when we know it is available.
remoteAuthClient.sendAuthorizationRequest(
oAuthRequest,
Runnable::run,
- myAuthCallback)
- } }
+ myAuthCallback
+ )
+ }
+ }
}
diff --git a/wear/wear-phone-interactions/src/main/java/androidx/wear/phone/interactions/PhoneTypeHelper.kt b/wear/wear-phone-interactions/src/main/java/androidx/wear/phone/interactions/PhoneTypeHelper.kt
index 084d416..69bc024 100644
--- a/wear/wear-phone-interactions/src/main/java/androidx/wear/phone/interactions/PhoneTypeHelper.kt
+++ b/wear/wear-phone-interactions/src/main/java/androidx/wear/phone/interactions/PhoneTypeHelper.kt
@@ -21,50 +21,51 @@
import android.provider.Settings
import androidx.annotation.IntDef
-/** Provides helper methods for determining the type of phone we are paired to. */
+/** Provides helper methods for determining the type of phone we are paired to. */
public class PhoneTypeHelper private constructor() {
public companion object {
internal const val BLUETOOTH_MODE = "bluetooth_mode"
internal const val PAIRED_DEVICE_OS_TYPE = "paired_device_os_type"
internal const val SETTINGS_AUTHORITY = "com.google.android.wearable.settings"
- private val BLUETOOTH_MODE_URI = Uri.Builder()
- .scheme("content")
- .authority(SETTINGS_AUTHORITY)
- .path(BLUETOOTH_MODE)
- .build()
+ private val BLUETOOTH_MODE_URI =
+ Uri.Builder()
+ .scheme("content")
+ .authority(SETTINGS_AUTHORITY)
+ .path(BLUETOOTH_MODE)
+ .build()
internal const val UNKNOWN_MODE = 0
internal const val ANDROID_MODE = 1
internal const val IOS_MODE = 2
- /** Indicates an error returned retrieving the type of phone we are paired to. */
+ /** Indicates an error returned retrieving the type of phone we are paired to. */
public const val DEVICE_TYPE_ERROR: Int = 0
- /** Indicates that we are paired to an Android phone. */
+ /** Indicates that we are paired to an Android phone. */
public const val DEVICE_TYPE_ANDROID: Int = 1
- /** Indicates that we are paired to an iOS phone. */
+ /** Indicates that we are paired to an iOS phone. */
public const val DEVICE_TYPE_IOS: Int = 2
- /** Indicates unknown type of phone we are paired to. */
+ /** Indicates unknown type of phone we are paired to. */
public const val DEVICE_TYPE_UNKNOWN: Int = 3
/**
* Returns the type of phone handset this Wear OS device has been paired with.
*
* @return one of `DEVICE_TYPE_ERROR`, `DEVICE_TYPE_ANDROID`, `DEVICE_TYPE_IOS` or
- * `DEVICE_TYPE_UNKNOWN` indicating we had an error while determining the phone type, we
- * are paired to an Android phone, we are paired to an iOS phone or we could not determine
- * the phone type respectively.
+ * `DEVICE_TYPE_UNKNOWN` indicating we had an error while determining the phone type, we
+ * are paired to an Android phone, we are paired to an iOS phone or we could not determine
+ * the phone type respectively.
*/
@DeviceFamily
@JvmStatic
public fun getPhoneDeviceType(context: Context): Int {
var bluetoothMode = UNKNOWN_MODE
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P) {
- val cursor = context.contentResolver.query(
- BLUETOOTH_MODE_URI, null, null, null, null
- ) ?: return DEVICE_TYPE_ERROR
+ val cursor =
+ context.contentResolver.query(BLUETOOTH_MODE_URI, null, null, null, null)
+ ?: return DEVICE_TYPE_ERROR
cursor.use {
while (it.moveToNext()) {
if (BLUETOOTH_MODE == it.getString(0)) {
@@ -88,7 +89,7 @@
}
}
- /** Annotates a value of DeviceType. */
+ /** Annotates a value of DeviceType. */
@Retention(AnnotationRetention.SOURCE)
@IntDef(DEVICE_TYPE_ERROR, DEVICE_TYPE_ANDROID, DEVICE_TYPE_IOS, DEVICE_TYPE_UNKNOWN)
internal annotation class DeviceFamily
diff --git a/wear/wear-phone-interactions/src/main/java/androidx/wear/phone/interactions/authentication/CodeChallenge.kt b/wear/wear-phone-interactions/src/main/java/androidx/wear/phone/interactions/authentication/CodeChallenge.kt
index d503ebd..6147d74 100644
--- a/wear/wear-phone-interactions/src/main/java/androidx/wear/phone/interactions/authentication/CodeChallenge.kt
+++ b/wear/wear-phone-interactions/src/main/java/androidx/wear/phone/interactions/authentication/CodeChallenge.kt
@@ -31,17 +31,11 @@
*/
/* ktlint-enable max-line-length */
@RequiresApi(Build.VERSION_CODES.O)
-public class CodeChallenge constructor(
- codeVerifier: CodeVerifier
-) {
- /**
- * The challenge value.
- */
+public class CodeChallenge constructor(codeVerifier: CodeVerifier) {
+ /** The challenge value. */
public val value: String
- /**
- * Computes the code challenge value using the specified verifier with SHA-256.
- */
+ /** Computes the code challenge value using the specified verifier with SHA-256. */
init {
val md = MessageDigest.getInstance("SHA-256")
val hash: ByteArray = md.digest(codeVerifier.getValueBytes())
diff --git a/wear/wear-phone-interactions/src/main/java/androidx/wear/phone/interactions/authentication/CodeVerifier.kt b/wear/wear-phone-interactions/src/main/java/androidx/wear/phone/interactions/authentication/CodeVerifier.kt
index b6728e0..d66c54f 100644
--- a/wear/wear-phone-interactions/src/main/java/androidx/wear/phone/interactions/authentication/CodeVerifier.kt
+++ b/wear/wear-phone-interactions/src/main/java/androidx/wear/phone/interactions/authentication/CodeVerifier.kt
@@ -33,43 +33,31 @@
@RequiresApi(Build.VERSION_CODES.O)
public class CodeVerifier {
private companion object {
- /**
- * The minimum byte length of a code verifier.
- */
+ /** The minimum byte length of a code verifier. */
private const val MIN_LENGTH_BYTE = 32
- /**
- * The maximum character length of a code verifier.
- */
+ /** The maximum character length of a code verifier. */
private const val MAX_LENGTH_BYTE = 96
- /**
- * The minimum character length of a code verifier with base64url-encoded.
- */
+ /** The minimum character length of a code verifier with base64url-encoded. */
private const val MIN_LENGTH_BASE64URL = 43
- /**
- * The maximum character length of a code verifier with base64url-encoded.
- */
+ /** The maximum character length of a code verifier with base64url-encoded. */
private const val MAX_LENGTH_BASE64URL = 128
- /**
- * The secure random generator.
- */
+ /** The secure random generator. */
private val SECURE_RANDOM: SecureRandom = SecureRandom()
}
- /**
- * The verifier value.
- */
+ /** The verifier value. */
public val value: String
@JvmOverloads
public constructor(
/**
* It is RECOMMENDED that the output of a suitable random number generator be used to create
- * a 32-octet sequence. The octet sequence is then base64url-encoded to produce a
- * 43-octet URL safe string to use as the code verifier.
+ * a 32-octet sequence. The octet sequence is then base64url-encoded to produce a 43-octet
+ * URL safe string to use as the code verifier.
*/
byteLength: Int = 32
) {
diff --git a/wear/wear-phone-interactions/src/main/java/androidx/wear/phone/interactions/authentication/IRemoteInteractionsManager.kt b/wear/wear-phone-interactions/src/main/java/androidx/wear/phone/interactions/authentication/IRemoteInteractionsManager.kt
index 48b046e..69482c4 100644
--- a/wear/wear-phone-interactions/src/main/java/androidx/wear/phone/interactions/authentication/IRemoteInteractionsManager.kt
+++ b/wear/wear-phone-interactions/src/main/java/androidx/wear/phone/interactions/authentication/IRemoteInteractionsManager.kt
@@ -19,17 +19,21 @@
import java.util.concurrent.Executor
import java.util.function.Consumer
-/**
- * Forwards remote auth interaction availabilities to [RemoteInteractionsManager].
- */
+/** Forwards remote auth interaction availabilities to [RemoteInteractionsManager]. */
internal interface IRemoteInteractionsManager {
/** Whether the availability status API is supported. */
val isAvailabilityStatusApiSupported: Boolean
- /** Forwards a call [registerRemoteAuthClientStatusListener] to [RemoteInteractionsManager.registerRemoteAuthClientStatusListener]. */
+ /**
+ * Forwards a call [registerRemoteAuthClientStatusListener] to
+ * [RemoteInteractionsManager.registerRemoteAuthClientStatusListener].
+ */
fun registerRemoteAuthClientStatusListener(executor: Executor, listener: Consumer<Int>)
- /** Forwards a call [unregisterRemoteAuthClientStatusListener] to [RemoteInteractionsManager.unregisterRemoteAuthClientStatusListener]. */
+ /**
+ * Forwards a call [unregisterRemoteAuthClientStatusListener] to
+ * [RemoteInteractionsManager.unregisterRemoteAuthClientStatusListener].
+ */
fun unregisterRemoteAuthClientStatusListener(listener: Consumer<Int>)
}
diff --git a/wear/wear-phone-interactions/src/main/java/androidx/wear/phone/interactions/authentication/OAuthRequest.kt b/wear/wear-phone-interactions/src/main/java/androidx/wear/phone/interactions/authentication/OAuthRequest.kt
index cada788..ac6af3d 100644
--- a/wear/wear-phone-interactions/src/main/java/androidx/wear/phone/interactions/authentication/OAuthRequest.kt
+++ b/wear/wear-phone-interactions/src/main/java/androidx/wear/phone/interactions/authentication/OAuthRequest.kt
@@ -24,10 +24,9 @@
import androidx.annotation.RequiresApi
import androidx.wear.utils.WearTypeHelper
-/**
- * The OAuth request to be sent to the server to start the OAuth 2 authentication flow.
- */
-public class OAuthRequest internal constructor(
+/** The OAuth request to be sent to the server to start the OAuth 2 authentication flow. */
+public class OAuthRequest
+internal constructor(
/** The package name of the app sending the auth request. */
public val packageName: String,
@@ -35,7 +34,6 @@
* The Url of the auth request.
*
* The request is expected to create a URL with the following format:
- *
* ```
* https://authorization-server.com/auth?client_id=XXXXX
* &redirect_uri=https://wear.googleapis.com/3p_auth/mypackagename
@@ -48,16 +46,16 @@
) {
public companion object {
/**
- * The default google-specific custom URL to route the response from the auth
- * server back to the 1P companion app, which then forwards it to the 3P app that made
- * the request on the wear device.
+ * The default google-specific custom URL to route the response from the auth server back to
+ * the 1P companion app, which then forwards it to the 3P app that made the request on the
+ * wear device.
*/
public const val WEAR_REDIRECT_URL_PREFIX: String = "https://wear.googleapis.com/3p_auth/"
/**
* The default google-specific custom URL in China to route the response from the auth
- * server back to the 1P companion app, which then forwards it to the 3P app that made
- * the request on the wear device.
+ * server back to the 1P companion app, which then forwards it to the 3P app that made the
+ * request on the wear device.
*/
public const val WEAR_REDIRECT_URL_PREFIX_CN: String =
"https://wear.googleapis-cn.com/3p_auth/"
@@ -78,54 +76,45 @@
private val packageName: String = context.packageName
/**
- * Set the url of the auth provider site.
- * Appending query parameters in this uri is optional, it is recommended to let the
- * builder append query parameters automatically through the use of setters (no setter is
- * required for the builder to append the redirect_uri).
+ * Set the url of the auth provider site. Appending query parameters in this uri is
+ * optional, it is recommended to let the builder append query parameters automatically
+ * through the use of setters (no setter is required for the builder to append the
+ * redirect_uri).
*/
@SuppressLint("MissingGetterMatchingBuilder")
public fun setAuthProviderUrl(authProviderUrl: Uri): Builder =
- this.apply {
- this.authProviderUrl = authProviderUrl
- }
+ this.apply { this.authProviderUrl = authProviderUrl }
/**
- * Set the code challenge for authentication with PKCE (proof key for code exchange).
- * With this setter called, the builder appends the "code_challenge",
- * "code_challenge_method" and "response_type" queries to the requestUrl.
+ * Set the code challenge for authentication with PKCE (proof key for code exchange). With
+ * this setter called, the builder appends the "code_challenge", "code_challenge_method" and
+ * "response_type" queries to the requestUrl.
*/
@SuppressLint("MissingGetterMatchingBuilder")
public fun setCodeChallenge(codeChallenge: CodeChallenge): Builder =
- this.apply {
- this.codeChallenge = codeChallenge
- }
+ this.apply { this.codeChallenge = codeChallenge }
/**
- * Set the client id of this OAuth request.
- * With this setter called. the builder appends the "client_id" to the requestUrl.
+ * Set the client id of this OAuth request. With this setter called. the builder appends the
+ * "client_id" to the requestUrl.
*/
@SuppressLint("MissingGetterMatchingBuilder")
- public fun setClientId(clientId: String): Builder =
- this.apply {
- this.clientId = clientId
- }
+ public fun setClientId(clientId: String): Builder = this.apply { this.clientId = clientId }
/**
- * Set the redirect url the companion app registered to, so that the response will be
- * routed from the auth server back to the companion.
+ * Set the redirect url the companion app registered to, so that the response will be routed
+ * from the auth server back to the companion.
*
* Calling this method is optional. If the redirect URL is not specified, it will be
- * automatically set to [WEAR_REDIRECT_URL_PREFIX] or [WEAR_REDIRECT_URL_PREFIX_CN] for
- * rest of the world or China, respectively.
+ * automatically set to [WEAR_REDIRECT_URL_PREFIX] or [WEAR_REDIRECT_URL_PREFIX_CN] for rest
+ * of the world or China, respectively.
*
- * Note, the app package name should NOT be included here, it will be appended to the end
- * of redirect_uri automatically in [Builder.build].
+ * Note, the app package name should NOT be included here, it will be appended to the end of
+ * redirect_uri automatically in [Builder.build].
*/
@SuppressLint("MissingGetterMatchingBuilder")
public fun setRedirectUrl(redirectUrl: Uri): Builder =
- this.apply {
- this.redirectUrl = redirectUrl
- }
+ this.apply { this.redirectUrl = redirectUrl }
@RequiresApi(Build.VERSION_CODES.O)
internal fun composeRequestUrl(): Uri {
@@ -134,41 +123,35 @@
}
val requestUriBuilder = authProviderUrl!!.buildUpon()
- clientId?.let {
- appendQueryParameter(requestUriBuilder, "client_id", clientId!!)
- }
+ clientId?.let { appendQueryParameter(requestUriBuilder, "client_id", clientId!!) }
/**
- * Set the request url by redirecting the auth provider URL with the WearOS auth
- * site [WEAR_REDIRECT_URL_PREFIX].
- * The receiving app's package name is also required as the 3rd path component in the
- * redirect_uri, this allows Wear to ensure other apps cannot reuse your redirect_uri
- * to receive responses.
+ * Set the request url by redirecting the auth provider URL with the WearOS auth site
+ * [WEAR_REDIRECT_URL_PREFIX]. The receiving app's package name is also required as the
+ * 3rd path component in the redirect_uri, this allows Wear to ensure other apps cannot
+ * reuse your redirect_uri to receive responses.
*/
appendQueryParameter(
requestUriBuilder,
REDIRECT_URI_KEY,
Uri.withAppendedPath(
- if (redirectUrl == null) {
- if (WearTypeHelper.isChinaBuild(context)) {
- Uri.parse(WEAR_REDIRECT_URL_PREFIX_CN)
+ if (redirectUrl == null) {
+ if (WearTypeHelper.isChinaBuild(context)) {
+ Uri.parse(WEAR_REDIRECT_URL_PREFIX_CN)
+ } else {
+ Uri.parse(WEAR_REDIRECT_URL_PREFIX)
+ }
} else {
- Uri.parse(WEAR_REDIRECT_URL_PREFIX)
- }
- } else {
- redirectUrl
- },
- packageName
- ).toString()
+ redirectUrl
+ },
+ packageName
+ )
+ .toString()
)
codeChallenge?.let {
appendQueryParameter(requestUriBuilder, "response_type", "code")
- appendQueryParameter(
- requestUriBuilder,
- "code_challenge",
- it.value
- )
+ appendQueryParameter(requestUriBuilder, "code_challenge", it.value)
appendQueryParameter(requestUriBuilder, "code_challenge_method", "S256")
}
@@ -239,8 +222,9 @@
*/
public val redirectUrl: String = requestUrl.getQueryParameter(REDIRECT_URI_KEY) ?: ""
- internal fun toBundle(): Bundle = Bundle().apply {
- putParcelable(RemoteAuthClient.KEY_REQUEST_URL, requestUrl)
- putString(RemoteAuthClient.KEY_PACKAGE_NAME, packageName)
- }
+ internal fun toBundle(): Bundle =
+ Bundle().apply {
+ putParcelable(RemoteAuthClient.KEY_REQUEST_URL, requestUrl)
+ putString(RemoteAuthClient.KEY_PACKAGE_NAME, packageName)
+ }
}
diff --git a/wear/wear-phone-interactions/src/main/java/androidx/wear/phone/interactions/authentication/OAuthResponse.kt b/wear/wear-phone-interactions/src/main/java/androidx/wear/phone/interactions/authentication/OAuthResponse.kt
index 426bf31..ee6e7e5 100644
--- a/wear/wear-phone-interactions/src/main/java/androidx/wear/phone/interactions/authentication/OAuthResponse.kt
+++ b/wear/wear-phone-interactions/src/main/java/androidx/wear/phone/interactions/authentication/OAuthResponse.kt
@@ -19,36 +19,29 @@
import android.net.Uri
import androidx.wear.phone.interactions.authentication.RemoteAuthClient.Companion.ErrorCode
-/**
- * The authentication response to be sent back to the client after completing the OAuth2 flow.
- */
-public class OAuthResponse internal constructor(
+/** The authentication response to be sent back to the client after completing the OAuth2 flow. */
+public class OAuthResponse
+internal constructor(
/** The error code that indicated the request result status. */
@ErrorCode public val errorCode: Int = RemoteAuthClient.NO_ERROR,
/** The Url of the auth response. In case of an error it will be null. */
public val responseUrl: Uri?
) {
- /**
- * Builder for constructing new instance of authentication response.
- */
+ /** Builder for constructing new instance of authentication response. */
public class Builder {
- @ErrorCode
- private var errorCode: Int = RemoteAuthClient.NO_ERROR
+ @ErrorCode private var errorCode: Int = RemoteAuthClient.NO_ERROR
private var responseUrl: Uri? = null
/** Set the error code to indicate the request result status */
public fun setErrorCode(@ErrorCode errorCode: Int): Builder =
- this.apply {
- this.errorCode = errorCode
- }
+ this.apply { this.errorCode = errorCode }
/** Set the Url of the auth response */
- public fun setResponseUrl(responseUrl: Uri): Builder = this.apply {
- this.responseUrl = responseUrl
- }
+ public fun setResponseUrl(responseUrl: Uri): Builder =
+ this.apply { this.responseUrl = responseUrl }
- /** Build the response instance specified by this builder*/
+ /** Build the response instance specified by this builder */
public fun build(): OAuthResponse = OAuthResponse(errorCode, responseUrl)
}
}
diff --git a/wear/wear-phone-interactions/src/main/java/androidx/wear/phone/interactions/authentication/RemoteAuthClient.kt b/wear/wear-phone-interactions/src/main/java/androidx/wear/phone/interactions/authentication/RemoteAuthClient.kt
index 0b2a3b0..a6cbaca 100644
--- a/wear/wear-phone-interactions/src/main/java/androidx/wear/phone/interactions/authentication/RemoteAuthClient.kt
+++ b/wear/wear-phone-interactions/src/main/java/androidx/wear/phone/interactions/authentication/RemoteAuthClient.kt
@@ -39,10 +39,10 @@
import kotlinx.coroutines.flow.flowOf
/**
- * Provides a client for supporting remote authentication on Wear. The authentication session
- * will be opened on the user's paired phone.
- *
+ * Provides a client for supporting remote authentication on Wear. The authentication session will
+ * be opened on the user's paired phone.
* * The following example triggers an authorization session to open on the phone.
+ *
* ```
* // PKCE (Proof Key for Code Exchange) is required for the auth
* private var codeVerifier: CodeVerifier
@@ -90,41 +90,35 @@
* }
* ```
*/
-public class RemoteAuthClient internal constructor(
+public class RemoteAuthClient
+internal constructor(
private val remoteInteractionsManager: IRemoteInteractionsManager,
private val serviceBinder: ServiceBinder,
private val uiThreadExecutor: Executor,
private val packageName: String
) : AutoCloseable {
public companion object {
- /**
- * The URL to be opened in a web browser on the companion.
- * Value type: Uri
- */
+ /** The URL to be opened in a web browser on the companion. Value type: Uri */
internal const val KEY_REQUEST_URL: String = "requestUrl"
/**
* The package name obtained from calling getPackageName() on the context passed into
- * [create].
- * Value type: String
+ * [create]. Value type: String
*/
internal const val KEY_PACKAGE_NAME: String = "packageName"
/**
- * The URL that the web browser is directed to that triggered the companion to open.
- * Value type: Uri
+ * The URL that the web browser is directed to that triggered the companion to open. Value
+ * type: Uri
*/
internal const val KEY_RESPONSE_URL: String = "responseUrl"
- /**
- * The error code explaining why the request failed.
- * Value type: [ErrorCode]
- */
+ /** The error code explaining why the request failed. Value type: [ErrorCode] */
internal const val KEY_ERROR_CODE: String = "errorCode"
/**
- * Package name for the service provider on Wearable.
- * Home app for Wear 2, and Wear Core Service for wear 3
+ * Package name for the service provider on Wearable. Home app for Wear 2, and Wear Core
+ * Service for wear 3
*/
internal const val WEARABLE_PACKAGE_NAME: String = "com.google.android.wearable.app"
@@ -139,42 +133,42 @@
/**
* The remote auth's availability is unknown.
*
- * On older devices, [STATUS_UNKNOWN] is returned as we can not determine the availability states. To preserve
- * compatibility with existing devices behavior, try [sendAuthorizationRequest] and handle
- * error codes accordingly.
+ * On older devices, [STATUS_UNKNOWN] is returned as we can not determine the availability
+ * states. To preserve compatibility with existing devices behavior, try
+ * [sendAuthorizationRequest] and handle error codes accordingly.
*/
public const val STATUS_UNKNOWN = 0
/**
- * Indicates that remote auth is unavailable because there is no paired device capable of handling the remote interaction.
+ * Indicates that remote auth is unavailable because there is no paired device capable of
+ * handling the remote interaction.
*/
public const val STATUS_UNAVAILABLE = 1
/**
* Indicates that remote auth is temporarily unavailable.
*
- * There is a known paired device, but it is not currently connected or reachable to handle the remote interaction.
+ * There is a known paired device, but it is not currently connected or reachable to handle
+ * the remote interaction.
*/
public const val STATUS_TEMPORARILY_UNAVAILABLE = 2
/**
- * Indicates that remote auth is available with a connected device capable to handle the remote interaction.
+ * Indicates that remote auth is available with a connected device capable to handle the
+ * remote interaction.
*/
public const val STATUS_AVAILABLE = 3
- /** Indicates 3p authentication is finished without error */
+ /** Indicates 3p authentication is finished without error */
public const val NO_ERROR: Int = -1
- /** Indicates 3p authentication isn't supported by Wear OS */
+ /** Indicates 3p authentication isn't supported by Wear OS */
public const val ERROR_UNSUPPORTED: Int = 0
/** Indicates no phone is connected, or the phone connected doesn't support 3p auth */
public const val ERROR_PHONE_UNAVAILABLE: Int = 1
- /**
- * Errors returned in [Callback.onAuthorizationError].
- *
- */
+ /** Errors returned in [Callback.onAuthorizationError]. */
@IntDef(NO_ERROR, ERROR_UNSUPPORTED, ERROR_PHONE_UNAVAILABLE)
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
@Retention(AnnotationRetention.SOURCE)
@@ -243,28 +237,30 @@
}
/**
- * Returns status indicating whether remote auth operation (such as [sendAuthorizationRequest]) is available.
+ * Returns status indicating whether remote auth operation (such as [sendAuthorizationRequest])
+ * is available.
*
- * In scenarios of restricted connection or temporary disconnection with a paired device,
- * remote auth operations will not be available. Please check status before [sendAuthorizationRequest]
+ * In scenarios of restricted connection or temporary disconnection with a paired device, remote
+ * auth operations will not be available. Please check status before [sendAuthorizationRequest]
* to provide better experience for the user.
*
- * On older wear devices which do not support availability status, it will always return [STATUS_UNKNOWN].
- * Wear devices start to support determining the availability status from Wear Sdk WEAR_TIRAMISU_4.
+ * On older wear devices which do not support availability status, it will always return
+ * [STATUS_UNKNOWN]. Wear devices start to support determining the availability status from Wear
+ * Sdk WEAR_TIRAMISU_4.
*
* @sample androidx.wear.phone.interactions.samples.AuthAvailabilitySample
*
* @return a [Flow] with a stream of status updates that could be one of [STATUS_UNKNOWN],
* [STATUS_UNAVAILABLE], [STATUS_TEMPORARILY_UNAVAILABLE], [STATUS_AVAILABLE].
- *
*/
- public val availabilityStatus: Flow<Int> get() {
- if (!remoteInteractionsManager.isAvailabilityStatusApiSupported) {
- return flowOf(STATUS_UNKNOWN)
- }
+ public val availabilityStatus: Flow<Int>
+ get() {
+ if (!remoteInteractionsManager.isAvailabilityStatusApiSupported) {
+ return flowOf(STATUS_UNKNOWN)
+ }
- return getRemoteAuthAvailableInternal()
- }
+ return getRemoteAuthAvailableInternal()
+ }
private fun getRemoteAuthAvailableInternal(): Flow<Int> {
return callbackFlow {
@@ -276,27 +272,26 @@
}
}
- remoteInteractionsManager
- .registerRemoteAuthClientStatusListener(Runnable::run, callback)
+ remoteInteractionsManager.registerRemoteAuthClientStatusListener(
+ Runnable::run,
+ callback
+ )
awaitClose {
- remoteInteractionsManager
- .unregisterRemoteAuthClientStatusListener(callback)
+ remoteInteractionsManager.unregisterRemoteAuthClientStatusListener(callback)
}
}
}
/**
- * Send a remote auth request. This will cause an authorization UI to be presented on
- * the user's phone.
- * This request is asynchronous; the callback provided will be be notified when the request
- * completes.
+ * Send a remote auth request. This will cause an authorization UI to be presented on the user's
+ * phone. This request is asynchronous; the callback provided will be be notified when the
+ * request completes.
*
- * @param request Request that will be sent to the phone. The auth response should redirect
- * to the Wear OS companion. See [OAuthRequest.WEAR_REDIRECT_URL_PREFIX]
+ * @param request Request that will be sent to the phone. The auth response should redirect to
+ * the Wear OS companion. See [OAuthRequest.WEAR_REDIRECT_URL_PREFIX]
* @param executor The executor that callback will called on.
* @param clientCallback The callback that will be notified when request is completed.
- *
* @Throws RuntimeException if the service has error to open the request
*/
@UiThread
@@ -327,7 +322,7 @@
/**
* Check that the explicit termination method 'close' is called
*
- * @Throws RuntimeException if the 'close' method was not called
+ * @Throws RuntimeException if the 'close' method was not called
*/
protected fun finalize() {
if (allocationSite != null) {
@@ -339,8 +334,8 @@
}
/**
- * Frees any resources used by the client, dropping any outstanding requests. The client
- * cannot be used to make requests thereafter.
+ * Frees any resources used by the client, dropping any outstanding requests. The client cannot
+ * be used to make requests thereafter.
*/
@UiThread
override fun close() {
@@ -351,10 +346,10 @@
}
internal interface ServiceBinder {
- /** See [Context.bindService]. */
+ /** See [Context.bindService]. */
fun bindService(intent: Intent, connection: ServiceConnection, flags: Int): Boolean
- /** See [Context.unbindService]. */
+ /** See [Context.unbindService]. */
fun unbindService(connection: ServiceConnection?)
}
@@ -379,8 +374,7 @@
private fun connect() {
check(connectionState == STATE_DISCONNECTED) { "State is $connectionState" }
- val intent =
- Intent(ACTION_AUTH).setPackage(WEARABLE_PACKAGE_NAME)
+ val intent = Intent(ACTION_AUTH).setPackage(WEARABLE_PACKAGE_NAME)
val success: Boolean =
serviceBinder.bindService(intent, connection, Context.BIND_AUTO_CREATE)
if (success) {
@@ -398,8 +392,9 @@
}
}
- /** Receives results of async requests to the remote auth service. */
- internal inner class RequestCallback internal constructor(
+ /** Receives results of async requests to the remote auth service. */
+ internal inner class RequestCallback
+ internal constructor(
private val request: OAuthRequest,
private val clientCallback: Callback,
private val executor: Executor
@@ -410,8 +405,7 @@
/**
* Called when an aync remote authentication request is completed.
*
- * Bundle contents:
- * <ul><li>"responseUrl": the response URL from the Auth request (Uri)
+ * Bundle contents: <ul><li>"responseUrl": the response URL from the Auth request (Uri)
* <ul><li>"error": an error code explaining why the request failed (int)
*/
@Suppress("DEPRECATION")
@@ -440,7 +434,7 @@
}
}
- /** Manages the connection with Wearable Auth service. */
+ /** Manages the connection with Wearable Auth service. */
private inner class RemoteAuthConnection : ServiceConnection {
@UiThread
override fun onServiceConnected(name: ComponentName, boundService: IBinder) {
diff --git a/wear/wear-phone-interactions/src/main/java/androidx/wear/phone/interactions/authentication/RemoteAuthService.kt b/wear/wear-phone-interactions/src/main/java/androidx/wear/phone/interactions/authentication/RemoteAuthService.kt
index 0761dd3..bbf9acc 100644
--- a/wear/wear-phone-interactions/src/main/java/androidx/wear/phone/interactions/authentication/RemoteAuthService.kt
+++ b/wear/wear-phone-interactions/src/main/java/androidx/wear/phone/interactions/authentication/RemoteAuthService.kt
@@ -32,31 +32,24 @@
import androidx.wear.phone.interactions.authentication.RemoteAuthClient.Companion.KEY_RESPONSE_URL
import java.security.SecureRandom
-/**
- * Interface for specifying how the service handles the remote auth requests.
- */
+/** Interface for specifying how the service handles the remote auth requests. */
public interface RemoteAuthRequestHandler {
/**
- * Whether the auth service is enabled, return false would give an early out by sending the
- * 3p app a response with error code of ERROR_UNSUPPORTED
+ * Whether the auth service is enabled, return false would give an early out by sending the 3p
+ * app a response with error code of ERROR_UNSUPPORTED
*/
public fun isAuthSupported(): Boolean
/**
- * Handle the auth request by sending it to the phone.
- * Typically, if the paired phone is not connected, send a response with error code of
- * [RemoteAuthClient.ERROR_PHONE_UNAVAILABLE]; otherwise listening for the response from the
- * phone and send it back to the 3p app.
+ * Handle the auth request by sending it to the phone. Typically, if the paired phone is not
+ * connected, send a response with error code of [RemoteAuthClient.ERROR_PHONE_UNAVAILABLE];
+ * otherwise listening for the response from the phone and send it back to the 3p app.
*
* [RemoteAuthService.sendResponseToCallback] is provided for sending response back to the
* callback provided by the 3p app.
- *
*/
- public fun sendAuthRequest(
- request: OAuthRequest,
- packageNameAndRequestId: Pair<String, Int>
- )
+ public fun sendAuthRequest(request: OAuthRequest, packageNameAndRequestId: Pair<String, Int>)
}
/*
@@ -82,11 +75,10 @@
public companion object {
@JvmStatic
private val callbacksByPackageNameAndRequestID:
- MutableMap<Pair<String, Int>, IAuthenticationRequestCallback> = HashMap()
+ MutableMap<Pair<String, Int>, IAuthenticationRequestCallback> =
+ HashMap()
- /**
- * To be called by the child class to invoke the callback with Response
- */
+ /** To be called by the child class to invoke the callback with Response */
@SuppressLint("DocumentExceptions")
@JvmStatic
public fun sendResponseToCallback(
@@ -103,9 +95,10 @@
}
}
- internal fun getCallback(packageNameAndRequestId: Pair<String, Int>):
- IAuthenticationRequestCallback? =
- callbacksByPackageNameAndRequestID[packageNameAndRequestId]
+ internal fun getCallback(
+ packageNameAndRequestId: Pair<String, Int>
+ ): IAuthenticationRequestCallback? =
+ callbacksByPackageNameAndRequestID[packageNameAndRequestId]
internal fun buildBundleFromResponse(response: OAuthResponse, packageName: String): Bundle =
Bundle().apply {
@@ -126,9 +119,7 @@
remoteAuthRequestHandler: RemoteAuthRequestHandler
): IBinder = RemoteAuthServiceBinder(this, remoteAuthRequestHandler)
- /**
- * Implementation of [Service.onUnbind]
- */
+ /** Implementation of [Service.onUnbind] */
public override fun onUnbind(intent: Intent): Boolean {
callbacksByPackageNameAndRequestID.clear()
return super.onUnbind(intent)
@@ -142,11 +133,9 @@
protected open fun verifyPackageName(context: Context, requestPackageName: String?): Boolean {
val packagesForUID: Array<String>? =
context.packageManager.getPackagesForUid(Binder.getCallingUid())
- return !(
- requestPackageName.isNullOrEmpty() ||
- packagesForUID.isNullOrEmpty() ||
- !(packagesForUID.contains(requestPackageName))
- )
+ return !(requestPackageName.isNullOrEmpty() ||
+ packagesForUID.isNullOrEmpty() ||
+ !(packagesForUID.contains(requestPackageName)))
}
internal inner class RemoteAuthServiceBinder(
@@ -156,9 +145,7 @@
override fun getApiVersion(): Int = IAuthenticationRequestService.API_VERSION
- /**
- * @throws SecurityException
- */
+ /** @throws SecurityException */
@Suppress("DEPRECATION")
override fun openUrl(
request: Bundle,
diff --git a/wear/wear-phone-interactions/src/main/java/androidx/wear/phone/interactions/authentication/RemoteInteractionsManagerCompat.kt b/wear/wear-phone-interactions/src/main/java/androidx/wear/phone/interactions/authentication/RemoteInteractionsManagerCompat.kt
index 44b0fcb..b49665c 100644
--- a/wear/wear-phone-interactions/src/main/java/androidx/wear/phone/interactions/authentication/RemoteInteractionsManagerCompat.kt
+++ b/wear/wear-phone-interactions/src/main/java/androidx/wear/phone/interactions/authentication/RemoteInteractionsManagerCompat.kt
@@ -21,9 +21,7 @@
import java.util.concurrent.Executor
import java.util.function.Consumer
-/**
- * Forwards remote auth interaction availabilities to [RemoteInteractionsManager].
- */
+/** Forwards remote auth interaction availabilities to [RemoteInteractionsManager]. */
internal open class RemoteInteractionsManagerCompat(context: Context) : IRemoteInteractionsManager {
// TODO(b/307543793): Reuse the generalized `WearApiVersionHelper` once available.
@@ -32,8 +30,7 @@
private val remoteInteractionsManager: RemoteInteractionsManager? =
if (isAvailabilityStatusApiSupported)
Sdk.getWearManager(context, RemoteInteractionsManager::class.java)
- else
- null
+ else null
override val isAvailabilityStatusApiSupported: Boolean
get() = wearApiVersion.wearSdkVersion >= 4
@@ -43,10 +40,7 @@
listener: Consumer<Int>
) {
if (isAvailabilityStatusApiSupported) {
- remoteInteractionsManager!!.registerRemoteAuthClientStatusListener(
- executor,
- listener
- )
+ remoteInteractionsManager!!.registerRemoteAuthClientStatusListener(executor, listener)
} else {
throw UnsupportedOperationException("Should not call wear sdk when not supported.")
}
@@ -54,9 +48,7 @@
override fun unregisterRemoteAuthClientStatusListener(listener: Consumer<Int>) {
if (isAvailabilityStatusApiSupported) {
- remoteInteractionsManager!!.unregisterRemoteAuthClientStatusListener(
- listener
- )
+ remoteInteractionsManager!!.unregisterRemoteAuthClientStatusListener(listener)
} else {
throw UnsupportedOperationException("Should not call wear sdk when not supported.")
}
diff --git a/wear/wear-phone-interactions/src/main/java/androidx/wear/phone/interactions/authentication/WearApiVersion.kt b/wear/wear-phone-interactions/src/main/java/androidx/wear/phone/interactions/authentication/WearApiVersion.kt
index 79a2ada..fe39223 100644
--- a/wear/wear-phone-interactions/src/main/java/androidx/wear/phone/interactions/authentication/WearApiVersion.kt
+++ b/wear/wear-phone-interactions/src/main/java/androidx/wear/phone/interactions/authentication/WearApiVersion.kt
@@ -18,9 +18,7 @@
import android.os.Build
import com.google.wear.Sdk
-/**
- * Provides wear sdk api version.
- */
+/** Provides wear sdk api version. */
internal class WearApiVersion {
// TODO(b/307543793): Reuse the generalized `WearApiVersionHelper` once available.
@@ -28,7 +26,8 @@
val wearSdkVersion: Int
get() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
- // Wear SDK INT can only be accessed safely from UPSIDE_DOWN_CAKE, introduced from tiramisu kr2.
+ // Wear SDK INT can only be accessed safely from UPSIDE_DOWN_CAKE, introduced from
+ // tiramisu kr2.
// Or crashes with `NoSuchField` will be experienced.
return Sdk.VERSION.WEAR_SDK_INT
}
diff --git a/wear/wear-phone-interactions/src/main/java/androidx/wear/phone/interactions/notifications/BridgingConfig.kt b/wear/wear-phone-interactions/src/main/java/androidx/wear/phone/interactions/notifications/BridgingConfig.kt
index da4eed0..85df6ad 100644
--- a/wear/wear-phone-interactions/src/main/java/androidx/wear/phone/interactions/notifications/BridgingConfig.kt
+++ b/wear/wear-phone-interactions/src/main/java/androidx/wear/phone/interactions/notifications/BridgingConfig.kt
@@ -27,9 +27,9 @@
*
* Specifying a bridging configuration at runtime overrides a bridging-related setting in the
* Android manifest file.
- *
*/
-public class BridgingConfig internal constructor(
+public class BridgingConfig
+internal constructor(
/** Name of the package of the current context */
internal val packageName: String?,
/** Whether notification bridging is enabled in the configuration. */
@@ -64,15 +64,17 @@
putString(EXTRA_ORIGINAL_PACKAGE, context.packageName)
putBoolean(EXTRA_BRIDGING_ENABLED, isBridgingEnabled)
putStringArrayList(
- EXTRA_EXCLUDED_TAGS, excludedTags?.let { ArrayList(it) } ?: ArrayList()
+ EXTRA_EXCLUDED_TAGS,
+ excludedTags?.let { ArrayList(it) } ?: ArrayList()
)
}
override fun equals(other: Any?): Boolean {
if (other is BridgingConfig) {
- return other.isBridgingEnabled == isBridgingEnabled and
- (other.excludedTags == excludedTags) and
- (other.packageName == packageName)
+ return other.isBridgingEnabled ==
+ isBridgingEnabled and
+ (other.excludedTags == excludedTags) and
+ (other.packageName == packageName)
}
return false
@@ -90,7 +92,7 @@
* Builder for BridgingConfig. The set of excluded tags is empty, unless added with
* [addExcludedTag] or [addExcludedTags].
*
- * @param context The [Context] of the application requesting a BridgingConfig change.
+ * @param context The [Context] of the application requesting a BridgingConfig change.
* @param isBridgingEnabled Whether notification bridging is enabled in the configuration.
*/
public class Builder(context: Context, private val isBridgingEnabled: Boolean) {
@@ -101,14 +103,12 @@
* Adds a tag for which the bridging mode is the opposite as the default mode.
*
* Examples:
- *
* ```
* new BridgingConfig.Builder(context, false) // bridging disabled by default
* .addExcludedTag("foo")
* .addExcludedTag("bar")
* .build());
* ```
- *
* ```
* new BridgingConfig.Builder(context, true) // bridging enabled by default
* .addExcludedTag("foo")
@@ -125,16 +125,15 @@
}
/**
- * Sets a collection of tags for which the bridging mode is the opposite as the default mode.
+ * Sets a collection of tags for which the bridging mode is the opposite as the default
+ * mode.
*
* Examples:
- *
* ```
* new BridgingConfig.Builder(context, false) // bridging disabled by default
* .addExcludedTags(Arrays.asList("foo", "bar", "baz"))
* .build());
- *```
- *
+ * ```
* ```
* new BridgingConfig.Builder(context, true) // bridging enabled by default
* .addExcludedTags(Arrays.asList("foo", "bar", "baz"))
diff --git a/wear/wear-phone-interactions/src/main/java/androidx/wear/phone/interactions/notifications/BridgingManager.kt b/wear/wear-phone-interactions/src/main/java/androidx/wear/phone/interactions/notifications/BridgingManager.kt
index 76b4ad7..bdf7bdf 100644
--- a/wear/wear-phone-interactions/src/main/java/androidx/wear/phone/interactions/notifications/BridgingManager.kt
+++ b/wear/wear-phone-interactions/src/main/java/androidx/wear/phone/interactions/notifications/BridgingManager.kt
@@ -29,20 +29,16 @@
/**
* APIs to enable/disable notification bridging at runtime.
*
- *
* Using a BridgingManager object, you can set a bridging mode, and optionally set tags for
* notifications that are exempt from the bridging mode. Specifically, create a [BridgingConfig]
* object and set is as shown in the example usages below:
- *
- *
- * * Disable bridging at runtime:
+ * * Disable bridging at runtime:
* ```
* BridgingManager.fromContext(context).setConfig(
* new BridgingConfig.Builder(context, false).build()
* );
* ```
- *
- * * Disable bridging at runtime except for the tags "foo" and "bar":
+ * * Disable bridging at runtime except for the tags "foo" and "bar":
* ```
* BridgingManager.fromContext(context).setConfig(
* new BridgingConfig.Builder(context, false)
@@ -51,8 +47,7 @@
* .build()
* );
* ```
- *
- * * Disable bridging at runtime except for the tags "foo" and "bar" and "baz":
+ * * Disable bridging at runtime except for the tags "foo" and "bar" and "baz":
* ```
* BridgingManager.fromContext(context).setConfig(
* new BridgingConfig.Builder(context, false)
@@ -60,8 +55,7 @@
* .build()
* );
* ```
- *
- * * Adding a bridge tag to a notification posted on a phone:
+ * * Adding a bridge tag to a notification posted on a phone:
* ```
* NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(context)
* // ... set other fields ...
@@ -82,7 +76,6 @@
* Sets the BridgingConfig object.
*
* @param bridgingConfig The BridgingConfig object.
- *
* @throws RuntimeException if the service binding is failed.
*/
public fun setConfig(bridgingConfig: BridgingConfig) {
@@ -96,11 +89,10 @@
}
}
- /** Class responsible for sending the bridge mode to ClockworkHome. */
- private class BridgingConfigServiceConnection internal constructor(
- private val context: Context,
- bridgingConfig: BridgingConfig
- ) : ServiceConnection {
+ /** Class responsible for sending the bridge mode to ClockworkHome. */
+ private class BridgingConfigServiceConnection
+ internal constructor(private val context: Context, bridgingConfig: BridgingConfig) :
+ ServiceConnection {
private val bundle: Bundle = bridgingConfig.toBundle(context)
override fun onServiceConnected(className: ComponentName, binder: IBinder) {
@@ -126,6 +118,7 @@
/**
* Create a BridgingManager instance with the passed in Context.
+ *
* @param context Context object.
*/
@JvmStatic
diff --git a/wear/wear-phone-interactions/src/main/java/androidx/wear/phone/interactions/notifications/BridgingManagerService.kt b/wear/wear-phone-interactions/src/main/java/androidx/wear/phone/interactions/notifications/BridgingManagerService.kt
index fe55f41..6665060 100644
--- a/wear/wear-phone-interactions/src/main/java/androidx/wear/phone/interactions/notifications/BridgingManagerService.kt
+++ b/wear/wear-phone-interactions/src/main/java/androidx/wear/phone/interactions/notifications/BridgingManagerService.kt
@@ -24,12 +24,11 @@
import android.os.IBinder
import android.support.wearable.notifications.IBridgingManagerService
-/**
- * Handler for applying the notification bridging configuration when received by the service.
- */
+/** Handler for applying the notification bridging configuration when received by the service. */
public fun interface BridgingConfigurationHandler {
/**
* Apply the notification bridging configurations.
+ *
* @param bridgingConfig The received bridging configuration
*/
public fun applyBridgingConfiguration(bridgingConfig: BridgingConfig)
@@ -38,9 +37,9 @@
/**
* Service class receiving notification bridging configurations.
*
- * @param context The [Context] of the application.
+ * @param context The [Context] of the application.
* @param bridgingConfigurationHandler The handler for applying the notification bridging
- * configuration.
+ * configuration.
*/
public class BridgingManagerService(
private val context: Context,
@@ -49,8 +48,7 @@
override fun onBind(intent: Intent?): IBinder? =
if (intent?.action == BridgingManager.ACTION_BIND_BRIDGING_MANAGER)
BridgingManagerServiceImpl(context, bridgingConfigurationHandler)
- else
- null
+ else null
}
internal class BridgingManagerServiceImpl(
@@ -63,12 +61,10 @@
override fun setBridgingConfig(bridgingConfigBundle: Bundle) {
val bridgingConfig = BridgingConfig.fromBundle(bridgingConfigBundle)
val packageName = bridgingConfig.packageName
- val senderAppPackage: String? =
- context.packageManager.getNameForUid(Binder.getCallingUid())
+ val senderAppPackage: String? = context.packageManager.getNameForUid(Binder.getCallingUid())
require(senderAppPackage == packageName) {
"Package invalid: $senderAppPackage not equals $packageName"
}
- bridgingConfigurationHandler
- .applyBridgingConfiguration(bridgingConfig)
+ bridgingConfigurationHandler.applyBridgingConfiguration(bridgingConfig)
}
}
diff --git a/wear/wear-phone-interactions/src/test/java/androidx/wear/phone/interactions/PhoneTypeHelperTest.kt b/wear/wear-phone-interactions/src/test/java/androidx/wear/phone/interactions/PhoneTypeHelperTest.kt
index 4a5b80f0..a4e3801 100644
--- a/wear/wear-phone-interactions/src/test/java/androidx/wear/phone/interactions/PhoneTypeHelperTest.kt
+++ b/wear/wear-phone-interactions/src/test/java/androidx/wear/phone/interactions/PhoneTypeHelperTest.kt
@@ -40,17 +40,16 @@
@RunWith(WearPhoneInteractionsTestRunner::class)
@DoNotInstrument // Stop Robolectric instrumenting this class due to it being in package "android".
class PhoneTypeHelperTest {
- private val bluetoothModeUri = Uri.Builder()
- .scheme("content")
- .authority(PhoneTypeHelper.SETTINGS_AUTHORITY)
- .path(PhoneTypeHelper.BLUETOOTH_MODE)
- .build()
+ private val bluetoothModeUri =
+ Uri.Builder()
+ .scheme("content")
+ .authority(PhoneTypeHelper.SETTINGS_AUTHORITY)
+ .path(PhoneTypeHelper.BLUETOOTH_MODE)
+ .build()
- @get:Rule
- val mocks = MockitoJUnit.rule()
+ @get:Rule val mocks = MockitoJUnit.rule()
- @Mock
- var mockContentProvider: ContentProvider? = null
+ @Mock var mockContentProvider: ContentProvider? = null
private var contentResolver: ContentResolver? = null
@Before
@@ -67,64 +66,63 @@
@Config(maxSdk = 28)
fun testGetDeviceType_returnsIosWhenAltMode() {
createFakePhoneTypeQuery(PhoneTypeHelper.IOS_MODE)
- assertThat(
- getPhoneDeviceType(ApplicationProvider.getApplicationContext())
- ).isEqualTo(PhoneTypeHelper.DEVICE_TYPE_IOS)
+ assertThat(getPhoneDeviceType(ApplicationProvider.getApplicationContext()))
+ .isEqualTo(PhoneTypeHelper.DEVICE_TYPE_IOS)
}
@Test
@Config(maxSdk = 28)
fun testGetDeviceType_returnsAndroidWhenNonAltMode() {
createFakePhoneTypeQuery(PhoneTypeHelper.ANDROID_MODE)
- assertThat(
- getPhoneDeviceType(ApplicationProvider.getApplicationContext())
- ).isEqualTo(PhoneTypeHelper.DEVICE_TYPE_ANDROID)
+ assertThat(getPhoneDeviceType(ApplicationProvider.getApplicationContext()))
+ .isEqualTo(PhoneTypeHelper.DEVICE_TYPE_ANDROID)
}
@Test
@Config(maxSdk = 28)
fun testGetDeviceType_returnsErrorWhenModeUnknown() {
createFakePhoneTypeQuery(PhoneTypeHelper.DEVICE_TYPE_UNKNOWN)
- assertThat(
- getPhoneDeviceType(ApplicationProvider.getApplicationContext())
- ).isEqualTo(PhoneTypeHelper.DEVICE_TYPE_UNKNOWN)
+ assertThat(getPhoneDeviceType(ApplicationProvider.getApplicationContext()))
+ .isEqualTo(PhoneTypeHelper.DEVICE_TYPE_UNKNOWN)
}
@Test
@Config(maxSdk = 28)
fun testGetDeviceType_returnsErrorWhenContentMissing() {
- assertThat(
- getPhoneDeviceType(ApplicationProvider.getApplicationContext())
- ).isEqualTo(PhoneTypeHelper.DEVICE_TYPE_ERROR)
+ assertThat(getPhoneDeviceType(ApplicationProvider.getApplicationContext()))
+ .isEqualTo(PhoneTypeHelper.DEVICE_TYPE_ERROR)
}
@Test
@Config(minSdk = 29)
fun testGetDeviceType_returnsIosWhenAltMode_fromQ() {
createFakePhoneTypeQuery(PhoneTypeHelper.IOS_MODE)
- Settings.Global.putInt(contentResolver, PhoneTypeHelper.PAIRED_DEVICE_OS_TYPE,
- PhoneTypeHelper.IOS_MODE)
- assertThat(
- getPhoneDeviceType(ApplicationProvider.getApplicationContext())
- ).isEqualTo(PhoneTypeHelper.DEVICE_TYPE_IOS)
+ Settings.Global.putInt(
+ contentResolver,
+ PhoneTypeHelper.PAIRED_DEVICE_OS_TYPE,
+ PhoneTypeHelper.IOS_MODE
+ )
+ assertThat(getPhoneDeviceType(ApplicationProvider.getApplicationContext()))
+ .isEqualTo(PhoneTypeHelper.DEVICE_TYPE_IOS)
}
@Test
@Config(minSdk = 29)
fun testGetDeviceType_returnsAndroidWhenNonAltMode_fromQ() {
- Settings.Global.putInt(contentResolver, PhoneTypeHelper.PAIRED_DEVICE_OS_TYPE,
- PhoneTypeHelper.ANDROID_MODE)
- assertThat(
- getPhoneDeviceType(ApplicationProvider.getApplicationContext())
- ).isEqualTo(PhoneTypeHelper.DEVICE_TYPE_ANDROID)
+ Settings.Global.putInt(
+ contentResolver,
+ PhoneTypeHelper.PAIRED_DEVICE_OS_TYPE,
+ PhoneTypeHelper.ANDROID_MODE
+ )
+ assertThat(getPhoneDeviceType(ApplicationProvider.getApplicationContext()))
+ .isEqualTo(PhoneTypeHelper.DEVICE_TYPE_ANDROID)
}
@Test
@Config(minSdk = 29)
fun testGetDeviceType_returnsErrorWhenContentMissing_fromQ() {
- assertThat(
- getPhoneDeviceType(ApplicationProvider.getApplicationContext())
- ).isEqualTo(PhoneTypeHelper.DEVICE_TYPE_UNKNOWN)
+ assertThat(getPhoneDeviceType(ApplicationProvider.getApplicationContext()))
+ .isEqualTo(PhoneTypeHelper.DEVICE_TYPE_UNKNOWN)
}
@Test
@@ -135,9 +133,8 @@
PhoneTypeHelper.PAIRED_DEVICE_OS_TYPE,
PhoneTypeHelper.ANDROID_MODE
)
- assertThat(
- getPhoneDeviceType(ApplicationProvider.getApplicationContext())
- ).isEqualTo(PhoneTypeHelper.DEVICE_TYPE_ANDROID)
+ assertThat(getPhoneDeviceType(ApplicationProvider.getApplicationContext()))
+ .isEqualTo(PhoneTypeHelper.DEVICE_TYPE_ANDROID)
}
@Test
@@ -148,9 +145,8 @@
PhoneTypeHelper.PAIRED_DEVICE_OS_TYPE,
PhoneTypeHelper.UNKNOWN_MODE
)
- assertThat(
- getPhoneDeviceType(ApplicationProvider.getApplicationContext())
- ).isEqualTo(PhoneTypeHelper.DEVICE_TYPE_UNKNOWN)
+ assertThat(getPhoneDeviceType(ApplicationProvider.getApplicationContext()))
+ .isEqualTo(PhoneTypeHelper.DEVICE_TYPE_UNKNOWN)
}
@Test
@@ -161,9 +157,8 @@
PhoneTypeHelper.PAIRED_DEVICE_OS_TYPE,
PhoneTypeHelper.IOS_MODE
)
- assertThat(
- getPhoneDeviceType(ApplicationProvider.getApplicationContext())
- ).isEqualTo(PhoneTypeHelper.DEVICE_TYPE_IOS)
+ assertThat(getPhoneDeviceType(ApplicationProvider.getApplicationContext()))
+ .isEqualTo(PhoneTypeHelper.DEVICE_TYPE_IOS)
}
companion object {
@@ -176,14 +171,14 @@
private fun createFakePhoneTypeQuery(phoneType: Int) {
Mockito.`when`(
- mockContentProvider!!.query(
- ArgumentMatchers.eq(bluetoothModeUri),
- ArgumentMatchers.any(),
- ArgumentMatchers.any(),
- ArgumentMatchers.any(),
- ArgumentMatchers.any()
+ mockContentProvider!!.query(
+ ArgumentMatchers.eq(bluetoothModeUri),
+ ArgumentMatchers.any(),
+ ArgumentMatchers.any(),
+ ArgumentMatchers.any(),
+ ArgumentMatchers.any()
+ )
)
- )
.thenReturn(createFakeBluetoothModeCursor(phoneType))
}
}
diff --git a/wear/wear-phone-interactions/src/test/java/androidx/wear/phone/interactions/WearPhoneInteractionsTestRunner.kt b/wear/wear-phone-interactions/src/test/java/androidx/wear/phone/interactions/WearPhoneInteractionsTestRunner.kt
index fdff318..697c4a4 100644
--- a/wear/wear-phone-interactions/src/test/java/androidx/wear/phone/interactions/WearPhoneInteractionsTestRunner.kt
+++ b/wear/wear-phone-interactions/src/test/java/androidx/wear/phone/interactions/WearPhoneInteractionsTestRunner.kt
@@ -24,18 +24,14 @@
*
* It has instrumentation turned off for the [androidx.wear.phone.interactions] package.
*
- * Robolectric tries to instrument Kotlin classes, and it throws errors when it encounters
- * companion objects, constructors with default values for parameters, and data classes with
- * inline classes. We don't need shadowing of our classes because we want to use the actual
- * objects in our tests.
+ * Robolectric tries to instrument Kotlin classes, and it throws errors when it encounters companion
+ * objects, constructors with default values for parameters, and data classes with inline classes.
+ * We don't need shadowing of our classes because we want to use the actual objects in our tests.
*/
-internal class WearPhoneInteractionsTestRunner(
- testClass: Class<*>
-) : RobolectricTestRunner(testClass) {
+internal class WearPhoneInteractionsTestRunner(testClass: Class<*>) :
+ RobolectricTestRunner(testClass) {
override fun createClassLoaderConfig(method: FrameworkMethod): InstrumentationConfiguration =
- InstrumentationConfiguration.Builder(
- super.createClassLoaderConfig(method)
- )
+ InstrumentationConfiguration.Builder(super.createClassLoaderConfig(method))
.doNotInstrumentPackage("androidx.wear.phone.interactions")
.build()
}
diff --git a/wear/wear-phone-interactions/src/test/java/androidx/wear/phone/interactions/authentication/CodeVerifierCodeChallengeTest.kt b/wear/wear-phone-interactions/src/test/java/androidx/wear/phone/interactions/authentication/CodeVerifierCodeChallengeTest.kt
index 2e333f7..2e3601f 100644
--- a/wear/wear-phone-interactions/src/test/java/androidx/wear/phone/interactions/authentication/CodeVerifierCodeChallengeTest.kt
+++ b/wear/wear-phone-interactions/src/test/java/androidx/wear/phone/interactions/authentication/CodeVerifierCodeChallengeTest.kt
@@ -73,9 +73,8 @@
@Test
public fun testChallengeEquality() {
val verifierValue = "jdshfkshg-8973834_SDFSSGE"
- assertThat(
- CodeChallenge(CodeVerifier(verifierValue))
- ).isEqualTo(CodeChallenge(CodeVerifier(verifierValue)))
+ assertThat(CodeChallenge(CodeVerifier(verifierValue)))
+ .isEqualTo(CodeChallenge(CodeVerifier(verifierValue)))
}
@Test
diff --git a/wear/wear-phone-interactions/src/test/java/androidx/wear/phone/interactions/authentication/OAuthRequestResponseTest.kt b/wear/wear-phone-interactions/src/test/java/androidx/wear/phone/interactions/authentication/OAuthRequestResponseTest.kt
index ff346ef..54bb71a 100644
--- a/wear/wear-phone-interactions/src/test/java/androidx/wear/phone/interactions/authentication/OAuthRequestResponseTest.kt
+++ b/wear/wear-phone-interactions/src/test/java/androidx/wear/phone/interactions/authentication/OAuthRequestResponseTest.kt
@@ -100,10 +100,11 @@
public fun testRequestBuildSuccessWithSetters() {
setSystemFeatureChina(false)
val codeChallenge = CodeChallenge(CodeVerifier())
- val requestBuilder = OAuthRequest.Builder(context)
- .setAuthProviderUrl(Uri.parse(authProviderUrl))
- .setClientId(clientId)
- .setCodeChallenge(codeChallenge)
+ val requestBuilder =
+ OAuthRequest.Builder(context)
+ .setAuthProviderUrl(Uri.parse(authProviderUrl))
+ .setClientId(clientId)
+ .setCodeChallenge(codeChallenge)
checkBuildSuccess(
requestBuilder,
@@ -118,10 +119,11 @@
public fun testRequestBuildSuccessWithSetters_cn() {
setSystemFeatureChina(true)
val codeChallenge = CodeChallenge(CodeVerifier())
- val requestBuilder = OAuthRequest.Builder(context)
- .setAuthProviderUrl(Uri.parse(authProviderUrl))
- .setClientId(clientId)
- .setCodeChallenge(codeChallenge)
+ val requestBuilder =
+ OAuthRequest.Builder(context)
+ .setAuthProviderUrl(Uri.parse(authProviderUrl))
+ .setClientId(clientId)
+ .setCodeChallenge(codeChallenge)
checkBuildSuccess(
requestBuilder,
@@ -136,11 +138,12 @@
public fun testRequestBuildSuccessWithCustomRedirectUri() {
setSystemFeatureChina(false)
val codeChallenge = CodeChallenge(CodeVerifier())
- val requestBuilder = OAuthRequest.Builder(context)
- .setAuthProviderUrl(Uri.parse(authProviderUrl))
- .setClientId(clientId)
- .setRedirectUrl(Uri.parse(customRedirectUrl))
- .setCodeChallenge(codeChallenge)
+ val requestBuilder =
+ OAuthRequest.Builder(context)
+ .setAuthProviderUrl(Uri.parse(authProviderUrl))
+ .setClientId(clientId)
+ .setRedirectUrl(Uri.parse(customRedirectUrl))
+ .setCodeChallenge(codeChallenge)
checkBuildSuccess(
requestBuilder,
@@ -155,11 +158,12 @@
public fun testRequestBuildSuccessWithCustomRedirectUri_cn() {
setSystemFeatureChina(true)
val codeChallenge = CodeChallenge(CodeVerifier())
- val requestBuilder = OAuthRequest.Builder(context)
- .setAuthProviderUrl(Uri.parse(authProviderUrl))
- .setClientId(clientId)
- .setRedirectUrl(Uri.parse(customRedirectUrl))
- .setCodeChallenge(codeChallenge)
+ val requestBuilder =
+ OAuthRequest.Builder(context)
+ .setAuthProviderUrl(Uri.parse(authProviderUrl))
+ .setClientId(clientId)
+ .setRedirectUrl(Uri.parse(customRedirectUrl))
+ .setCodeChallenge(codeChallenge)
checkBuildSuccess(
requestBuilder,
@@ -174,16 +178,17 @@
public fun testRequestBuildSuccessWithCompleteUrl() {
setSystemFeatureChina(false)
val codeChallenge = CodeChallenge(CodeVerifier())
- val requestBuilder = OAuthRequest.Builder(context)
- .setAuthProviderUrl(
- Uri.parse(
- "$authProviderUrl?client_id=$clientId" +
- "&redirect_uri=$redirectUrlWithPackageName" +
- "&response_type=code" +
- "&code_challenge=${codeChallenge.value}" +
- "&code_challenge_method=S256"
+ val requestBuilder =
+ OAuthRequest.Builder(context)
+ .setAuthProviderUrl(
+ Uri.parse(
+ "$authProviderUrl?client_id=$clientId" +
+ "&redirect_uri=$redirectUrlWithPackageName" +
+ "&response_type=code" +
+ "&code_challenge=${codeChallenge.value}" +
+ "&code_challenge_method=S256"
+ )
)
- )
checkBuildSuccess(
requestBuilder,
@@ -197,22 +202,21 @@
@Test
public fun testRequestBuildFailureWithoutAuthProviderUrl() {
setSystemFeatureChina(false)
- val builder = OAuthRequest.Builder(context)
- .setClientId(clientId)
- .setCodeChallenge(CodeChallenge(CodeVerifier()))
+ val builder =
+ OAuthRequest.Builder(context)
+ .setClientId(clientId)
+ .setCodeChallenge(CodeChallenge(CodeVerifier()))
- checkBuildFailure(
- builder,
- "The request requires the auth provider url to be provided."
- )
+ checkBuildFailure(builder, "The request requires the auth provider url to be provided.")
}
@Test
public fun testRequestBuildFailureWithoutClientId() {
setSystemFeatureChina(false)
- val builder = OAuthRequest.Builder(context)
- .setAuthProviderUrl(Uri.parse(authProviderUrl))
- .setCodeChallenge(CodeChallenge(CodeVerifier()))
+ val builder =
+ OAuthRequest.Builder(context)
+ .setAuthProviderUrl(Uri.parse(authProviderUrl))
+ .setCodeChallenge(CodeChallenge(CodeVerifier()))
checkBuildFailure(
builder,
@@ -224,12 +228,11 @@
@Test
public fun testRequestBuildFailureWithConflictedClientId() {
setSystemFeatureChina(false)
- val builder = OAuthRequest.Builder(context)
- .setAuthProviderUrl(
- Uri.parse("$authProviderUrl?client_id=XXX")
- )
- .setClientId(clientId)
- .setCodeChallenge(CodeChallenge(CodeVerifier()))
+ val builder =
+ OAuthRequest.Builder(context)
+ .setAuthProviderUrl(Uri.parse("$authProviderUrl?client_id=XXX"))
+ .setClientId(clientId)
+ .setCodeChallenge(CodeChallenge(CodeVerifier()))
checkBuildFailure(
builder,
@@ -244,12 +247,11 @@
public fun testRequestBuildSuccessWithDuplicatedClientId() {
setSystemFeatureChina(false)
val codeChallenge = CodeChallenge(CodeVerifier())
- val builder = OAuthRequest.Builder(context)
- .setAuthProviderUrl(
- Uri.parse("$authProviderUrl?client_id=$clientId")
- )
- .setClientId(clientId)
- .setCodeChallenge(codeChallenge)
+ val builder =
+ OAuthRequest.Builder(context)
+ .setAuthProviderUrl(Uri.parse("$authProviderUrl?client_id=$clientId"))
+ .setClientId(clientId)
+ .setCodeChallenge(codeChallenge)
checkBuildSuccess(
builder,
@@ -263,9 +265,10 @@
@Test
public fun testRequestBuildFailureWithoutCodeChallenge() {
setSystemFeatureChina(false)
- val builder = OAuthRequest.Builder(context)
- .setAuthProviderUrl(Uri.parse(authProviderUrl))
- .setClientId(clientId)
+ val builder =
+ OAuthRequest.Builder(context)
+ .setAuthProviderUrl(Uri.parse(authProviderUrl))
+ .setClientId(clientId)
checkBuildFailure(
builder,
@@ -278,12 +281,11 @@
public fun testRequestBuildFailureWithConflictedCodeChallenge() {
setSystemFeatureChina(false)
val codeChallenge = CodeChallenge(CodeVerifier())
- val builder = OAuthRequest.Builder(context)
- .setAuthProviderUrl(
- Uri.parse("$authProviderUrl?code_challenge=XXX")
- )
- .setClientId(clientId)
- .setCodeChallenge(codeChallenge)
+ val builder =
+ OAuthRequest.Builder(context)
+ .setAuthProviderUrl(Uri.parse("$authProviderUrl?code_challenge=XXX"))
+ .setClientId(clientId)
+ .setCodeChallenge(codeChallenge)
checkBuildFailure(
builder,
@@ -298,12 +300,13 @@
public fun testRequestBuildSuccessWithDuplicatedCodeChallenge() {
setSystemFeatureChina(false)
val codeChallenge = CodeChallenge(CodeVerifier())
- val builder = OAuthRequest.Builder(context)
- .setAuthProviderUrl(
- Uri.parse("$authProviderUrl?code_challenge=${codeChallenge.value}")
- )
- .setClientId(clientId)
- .setCodeChallenge(codeChallenge)
+ val builder =
+ OAuthRequest.Builder(context)
+ .setAuthProviderUrl(
+ Uri.parse("$authProviderUrl?code_challenge=${codeChallenge.value}")
+ )
+ .setClientId(clientId)
+ .setCodeChallenge(codeChallenge)
checkBuildSuccess(
builder,
@@ -317,12 +320,11 @@
@Test
public fun testRequestBuildFailureWithWrongResponseType() {
setSystemFeatureChina(false)
- val builder = OAuthRequest.Builder(context)
- .setAuthProviderUrl(
- Uri.parse("$authProviderUrl?response_type=XXX")
- )
- .setClientId(clientId)
- .setCodeChallenge(CodeChallenge(CodeVerifier()))
+ val builder =
+ OAuthRequest.Builder(context)
+ .setAuthProviderUrl(Uri.parse("$authProviderUrl?response_type=XXX"))
+ .setClientId(clientId)
+ .setCodeChallenge(CodeChallenge(CodeVerifier()))
checkBuildFailure(
builder,
@@ -337,12 +339,11 @@
public fun testRequestBuildFailureWithDuplicatedResponseType() {
setSystemFeatureChina(false)
val codeChallenge = CodeChallenge(CodeVerifier())
- val builder = OAuthRequest.Builder(context)
- .setAuthProviderUrl(
- Uri.parse("$authProviderUrl?response_type=code")
- )
- .setClientId(clientId)
- .setCodeChallenge(codeChallenge)
+ val builder =
+ OAuthRequest.Builder(context)
+ .setAuthProviderUrl(Uri.parse("$authProviderUrl?response_type=code"))
+ .setClientId(clientId)
+ .setCodeChallenge(codeChallenge)
checkBuildSuccess(
builder,
@@ -356,12 +357,11 @@
@Test
public fun testRequestBuildFailureWithWrongCodeChallengeMethod() {
setSystemFeatureChina(false)
- val builder = OAuthRequest.Builder(context)
- .setAuthProviderUrl(
- Uri.parse("$authProviderUrl?code_challenge_method=PLAIN")
- )
- .setClientId(clientId)
- .setCodeChallenge(CodeChallenge(CodeVerifier()))
+ val builder =
+ OAuthRequest.Builder(context)
+ .setAuthProviderUrl(Uri.parse("$authProviderUrl?code_challenge_method=PLAIN"))
+ .setClientId(clientId)
+ .setCodeChallenge(CodeChallenge(CodeVerifier()))
checkBuildFailure(
builder,
@@ -376,12 +376,11 @@
public fun testRequestBuildFailureWithDuplicatedCodeChallengeMethod() {
setSystemFeatureChina(false)
val codeChallenge = CodeChallenge(CodeVerifier())
- val builder = OAuthRequest.Builder(context)
- .setAuthProviderUrl(
- Uri.parse("$authProviderUrl?code_challenge_method=S256")
- )
- .setClientId(clientId)
- .setCodeChallenge(codeChallenge)
+ val builder =
+ OAuthRequest.Builder(context)
+ .setAuthProviderUrl(Uri.parse("$authProviderUrl?code_challenge_method=S256"))
+ .setClientId(clientId)
+ .setCodeChallenge(codeChallenge)
checkBuildSuccess(
builder,
@@ -396,13 +395,14 @@
public fun testRequestBuildFailureWithConflictedRedirectUri() {
setSystemFeatureChina(false)
val codeChallenge = CodeChallenge(CodeVerifier())
- val builder = OAuthRequest.Builder(context)
- .setAuthProviderUrl(
- Uri.parse("$authProviderUrl?redirect_uri=$redirectUrlWithPackageName")
- )
- .setRedirectUrl(Uri.parse(customRedirectUrl))
- .setClientId(clientId)
- .setCodeChallenge(codeChallenge)
+ val builder =
+ OAuthRequest.Builder(context)
+ .setAuthProviderUrl(
+ Uri.parse("$authProviderUrl?redirect_uri=$redirectUrlWithPackageName")
+ )
+ .setRedirectUrl(Uri.parse(customRedirectUrl))
+ .setClientId(clientId)
+ .setCodeChallenge(codeChallenge)
checkBuildFailure(
builder,
@@ -423,16 +423,14 @@
@Test
public fun testErrorResponseBuild() {
- val response1 = OAuthResponse.Builder()
- .setErrorCode(RemoteAuthClient.ERROR_UNSUPPORTED)
- .build()
+ val response1 =
+ OAuthResponse.Builder().setErrorCode(RemoteAuthClient.ERROR_UNSUPPORTED).build()
assertThat(response1.errorCode).isEqualTo(RemoteAuthClient.ERROR_UNSUPPORTED)
assertThat(response1.responseUrl).isNull()
- val response2 = OAuthResponse.Builder()
- .setErrorCode(RemoteAuthClient.ERROR_PHONE_UNAVAILABLE)
- .build()
+ val response2 =
+ OAuthResponse.Builder().setErrorCode(RemoteAuthClient.ERROR_PHONE_UNAVAILABLE).build()
assertThat(response2.errorCode).isEqualTo(RemoteAuthClient.ERROR_PHONE_UNAVAILABLE)
assertThat(response2.responseUrl).isNull()
@@ -442,10 +440,11 @@
public fun testGetRedirectUrl() {
setSystemFeatureChina(false)
val codeChallenge = CodeChallenge(CodeVerifier())
- val builder = OAuthRequest.Builder(context)
- .setAuthProviderUrl(Uri.parse(authProviderUrl))
- .setClientId(clientId)
- .setCodeChallenge(codeChallenge)
+ val builder =
+ OAuthRequest.Builder(context)
+ .setAuthProviderUrl(Uri.parse(authProviderUrl))
+ .setClientId(clientId)
+ .setCodeChallenge(codeChallenge)
// Building should always be successful and it's already tested in the previous tests, so
// no need for try-catch block as in #checkBuildFailure.
@@ -457,10 +456,11 @@
public fun testGetRedirectUrl_cn() {
setSystemFeatureChina(true)
val codeChallenge = CodeChallenge(CodeVerifier())
- val builder = OAuthRequest.Builder(context)
- .setAuthProviderUrl(Uri.parse(authProviderUrl))
- .setClientId(clientId)
- .setCodeChallenge(codeChallenge)
+ val builder =
+ OAuthRequest.Builder(context)
+ .setAuthProviderUrl(Uri.parse(authProviderUrl))
+ .setClientId(clientId)
+ .setCodeChallenge(codeChallenge)
// Building should always be successful and it's already tested in the previous tests, so
// no need for try-catch block as in #checkBuildFailure.
@@ -472,11 +472,12 @@
public fun testGetRedirectUrlWithCustomRedirectUri() {
setSystemFeatureChina(false)
val codeChallenge = CodeChallenge(CodeVerifier())
- val builder = OAuthRequest.Builder(context)
- .setAuthProviderUrl(Uri.parse(authProviderUrl))
- .setClientId(clientId)
- .setRedirectUrl(Uri.parse(customRedirectUrl))
- .setCodeChallenge(codeChallenge)
+ val builder =
+ OAuthRequest.Builder(context)
+ .setAuthProviderUrl(Uri.parse(authProviderUrl))
+ .setClientId(clientId)
+ .setRedirectUrl(Uri.parse(customRedirectUrl))
+ .setCodeChallenge(codeChallenge)
// Building should always be successful and it's already tested in the previous tests, so
// no need for try-catch block as in #checkBuildFailure.
@@ -486,8 +487,11 @@
@Test
public fun testGetRedirectUrl_builtWithConstructor() {
- val requestUrl = Uri.parse(authProviderUrl).buildUpon()
- .appendQueryParameter(OAuthRequest.REDIRECT_URI_KEY, customRedirectUrl).build()
+ val requestUrl =
+ Uri.parse(authProviderUrl)
+ .buildUpon()
+ .appendQueryParameter(OAuthRequest.REDIRECT_URI_KEY, customRedirectUrl)
+ .build()
val request = OAuthRequest(appPackageName, requestUrl)
assertThat(request.redirectUrl).isEqualTo(customRedirectUrl)
diff --git a/wear/wear-phone-interactions/src/test/java/androidx/wear/phone/interactions/authentication/RemoteAuthTest.kt b/wear/wear-phone-interactions/src/test/java/androidx/wear/phone/interactions/authentication/RemoteAuthTest.kt
index 6c881c7..0b22717 100644
--- a/wear/wear-phone-interactions/src/test/java/androidx/wear/phone/interactions/authentication/RemoteAuthTest.kt
+++ b/wear/wear-phone-interactions/src/test/java/androidx/wear/phone/interactions/authentication/RemoteAuthTest.kt
@@ -47,7 +47,7 @@
import org.robolectric.annotation.Config
import org.robolectric.annotation.internal.DoNotInstrument
-/** Unit tests for [RemoteAuthClient]. */
+/** Unit tests for [RemoteAuthClient]. */
@RunWith(WearPhoneInteractionsTestRunner::class)
@DoNotInstrument // Needed because it is defined in the "android" package.
@Config(minSdk = 26)
@@ -87,9 +87,8 @@
private val response = OAuthResponse.Builder().setResponseUrl(responseUrl).build()
// Note: This can't be static as Robolectric isn't set up at class init time.
- private val mServiceName = ComponentName(
- "com.google.android.wearable.app", "auth_lib_shouldnt_care_about_this"
- )
+ private val mServiceName =
+ ComponentName("com.google.android.wearable.app", "auth_lib_shouldnt_care_about_this")
private val mockCallback: RemoteAuthClient.Callback =
Mockito.mock(RemoteAuthClient.Callback::class.java)
@@ -106,7 +105,8 @@
remoteInteractionsManager,
fakeServiceBinder,
DIRECT_EXECUTOR,
- appPackageName)
+ appPackageName
+ )
private val executor: Executor = SyncExecutor()
@Test
@@ -185,10 +185,7 @@
fakeServiceBinder.completeConnection()
clientUnderTest.sendAuthorizationRequest(requestB, executor, mockCallback)
// WHEN the first one completes
- RemoteAuthService.sendResponseToCallback(
- response,
- fakeService.requests[0].second
- )
+ RemoteAuthService.sendResponseToCallback(response, fakeService.requests[0].second)
// THEN the service remains connected (as there's still a request ongoing, and we won't get
// the callback for the other request if we unbind now)
assertThat(fakeServiceBinder.state).isEqualTo(ConnectionState.CONNECTED)
@@ -202,15 +199,9 @@
// GIVEN the async binding to Clockwork Home completed after the 1st but before the 2nd
fakeServiceBinder.completeConnection()
clientUnderTest.sendAuthorizationRequest(requestB, executor, mockCallback)
- RemoteAuthService.sendResponseToCallback(
- response,
- fakeService.requests[0].second
- )
+ RemoteAuthService.sendResponseToCallback(response, fakeService.requests[0].second)
// WHEN the other completes
- RemoteAuthService.sendResponseToCallback(
- response,
- fakeService.requests[1].second
- )
+ RemoteAuthService.sendResponseToCallback(response, fakeService.requests[1].second)
// THEN the OAuth library disconnects from Clockwork Home
assertThat(fakeServiceBinder.state).isEqualTo(ConnectionState.DISCONNECTED)
}
@@ -218,9 +209,7 @@
@Test
fun remoteAuthClientStatus_notSupported_unknown() {
whenever(remoteInteractionsManager.isAvailabilityStatusApiSupported).thenReturn(false)
- val isAvailable = runBlocking {
- clientUnderTest.availabilityStatus.first()
- }
+ val isAvailable = runBlocking { clientUnderTest.availabilityStatus.first() }
assertThat(isAvailable).isEqualTo(RemoteAuthClient.STATUS_UNKNOWN)
verify(remoteInteractionsManager, never())
@@ -229,11 +218,13 @@
@Test
fun remoteAuthClientStatus_isSupported_propagateListenerValues() {
- for (remoteStatus in listOf(
- RemoteAuthClient.STATUS_AVAILABLE,
- RemoteAuthClient.STATUS_UNAVAILABLE,
- RemoteAuthClient.STATUS_TEMPORARILY_UNAVAILABLE)) {
- whenever(remoteInteractionsManager.isAvailabilityStatusApiSupported).thenReturn(true)
+ for (remoteStatus in
+ listOf(
+ RemoteAuthClient.STATUS_AVAILABLE,
+ RemoteAuthClient.STATUS_UNAVAILABLE,
+ RemoteAuthClient.STATUS_TEMPORARILY_UNAVAILABLE
+ )) {
+ whenever(remoteInteractionsManager.isAvailabilityStatusApiSupported).thenReturn(true)
doAnswer {
@Suppress("UNCHECKED_CAST")
val consumer: Consumer<Int> = it.arguments[1] as (Consumer<Int>)
@@ -242,9 +233,7 @@
.whenever(remoteInteractionsManager)
.registerRemoteAuthClientStatusListener(any(), any())
- val isAvailable = runBlocking {
- clientUnderTest.availabilityStatus.first()
- }
+ val isAvailable = runBlocking { clientUnderTest.availabilityStatus.first() }
assertThat(isAvailable).isEqualTo(remoteStatus)
verify(remoteInteractionsManager).registerRemoteAuthClientStatusListener(any(), any())
@@ -254,13 +243,16 @@
}
internal enum class ConnectionState {
- DISCONNECTED, CONNECTING, CONNECTED
+ DISCONNECTED,
+ CONNECTING,
+ CONNECTED
}
- /** Fakes binding to Clockwork Home. */
+ /** Fakes binding to Clockwork Home. */
private inner class FakeServiceBinder : RemoteAuthClient.ServiceBinder {
var state = ConnectionState.DISCONNECTED
private var serviceConnection: ServiceConnection? = null
+
override fun bindService(
intent: Intent,
connection: ServiceConnection,
@@ -299,8 +291,7 @@
private inner class FakeClockworkHomeAuthService : RemoteAuthService() {
private val requestHandler: RemoteAuthRequestHandler
- val requests: MutableList<Pair<OAuthRequest, kotlin.Pair<String, Int>>> =
- ArrayList()
+ val requests: MutableList<Pair<OAuthRequest, kotlin.Pair<String, Int>>> = ArrayList()
init {
requestHandler = AuthenticationRequestHandler()
diff --git a/wear/wear-phone-interactions/src/test/java/androidx/wear/phone/interactions/notifications/BridgingManagerServiceTest.kt b/wear/wear-phone-interactions/src/test/java/androidx/wear/phone/interactions/notifications/BridgingManagerServiceTest.kt
index 6089338..9a9937a 100644
--- a/wear/wear-phone-interactions/src/test/java/androidx/wear/phone/interactions/notifications/BridgingManagerServiceTest.kt
+++ b/wear/wear-phone-interactions/src/test/java/androidx/wear/phone/interactions/notifications/BridgingManagerServiceTest.kt
@@ -31,7 +31,7 @@
import org.robolectric.shadows.ShadowBinder
import org.robolectric.shadows.ShadowPackageManager
-/** Unit tests for [BridgingManagerService] and [BridgingManagerServiceImpl] classes. */
+/** Unit tests for [BridgingManagerService] and [BridgingManagerServiceImpl] classes. */
@RunWith(WearPhoneInteractionsTestRunner::class)
@DoNotInstrument // Needed because it is defined in the "android" package.
class BridgingManagerServiceTest {
@@ -73,9 +73,8 @@
val bridgingManagerService =
BridgingManagerService(context, testBridgingConfigurationHandler)
val intent = Intent(BridgingManager.ACTION_BIND_BRIDGING_MANAGER)
- val bridgingConfig = BridgingConfig.Builder(
- context /* packageName = PACKAGE_NAME */, false
- ).build()
+ val bridgingConfig =
+ BridgingConfig.Builder(context /* packageName = PACKAGE_NAME */, false).build()
val binder = bridgingManagerService.onBind(intent)
@@ -83,9 +82,7 @@
val bridgingManagerServiceImpl = IBridgingManagerService.Stub.asInterface(binder)
assertThat(bridgingManagerServiceImpl).isNotNull()
- assertThrows(
- IllegalArgumentException::class.java
- ) {
+ assertThrows(IllegalArgumentException::class.java) {
bridgingManagerServiceImpl.setBridgingConfig(bridgingConfig.toBundle(context))
}
}
diff --git a/wear/wear-phone-interactions/src/test/java/androidx/wear/phone/interactions/notifications/BridgingManagerTest.kt b/wear/wear-phone-interactions/src/test/java/androidx/wear/phone/interactions/notifications/BridgingManagerTest.kt
index c4c4762..8dd0e4d 100644
--- a/wear/wear-phone-interactions/src/test/java/androidx/wear/phone/interactions/notifications/BridgingManagerTest.kt
+++ b/wear/wear-phone-interactions/src/test/java/androidx/wear/phone/interactions/notifications/BridgingManagerTest.kt
@@ -27,7 +27,7 @@
import org.mockito.Mockito.`when`
import org.robolectric.annotation.internal.DoNotInstrument
-/** Unit tests for [BridgingManager]. */
+/** Unit tests for [BridgingManager]. */
@RunWith(WearPhoneInteractionsTestRunner::class)
@DoNotInstrument // Needed because it is defined in the "android" package.
public class BridgingManagerTest {
@@ -43,124 +43,104 @@
@Test
public fun disableBridging() {
- val bridgingConfig = BridgingConfig.Builder(
- mContext, false
- ).build()
+ val bridgingConfig = BridgingConfig.Builder(mContext, false).build()
assertThat(bridgingConfig).isEqualTo(BridgingConfig(PACKAGE_NAME, false, HashSet()))
// Test that conversion to and from bundle works as expected.
- assertThat(
- BridgingConfig.fromBundle(bridgingConfig.toBundle(mContext))
- ).isEqualTo(bridgingConfig)
+ assertThat(BridgingConfig.fromBundle(bridgingConfig.toBundle(mContext)))
+ .isEqualTo(bridgingConfig)
}
@Test
public fun enableBridging() {
- val bridgingConfig = BridgingConfig.Builder(
- mContext, true
- ).build()
+ val bridgingConfig = BridgingConfig.Builder(mContext, true).build()
assertThat(bridgingConfig).isEqualTo(BridgingConfig(PACKAGE_NAME, true, HashSet()))
// Test that conversion to and from bundle works as expected.
- assertThat(
- BridgingConfig.fromBundle(bridgingConfig.toBundle(mContext))
- ).isEqualTo(bridgingConfig)
+ assertThat(BridgingConfig.fromBundle(bridgingConfig.toBundle(mContext)))
+ .isEqualTo(bridgingConfig)
}
@Test
public fun bridgingEnableByDefault() {
- val bridgingConfig = BridgingConfig.Builder(
- mContext, true
- ).build()
+ val bridgingConfig = BridgingConfig.Builder(mContext, true).build()
assertThat(bridgingConfig).isEqualTo(BridgingConfig(PACKAGE_NAME, true, HashSet()))
// Test that conversion to and from bundle works as expected.
- assertThat(
- BridgingConfig.fromBundle(bridgingConfig.toBundle(mContext))
- ).isEqualTo(bridgingConfig)
+ assertThat(BridgingConfig.fromBundle(bridgingConfig.toBundle(mContext)))
+ .isEqualTo(bridgingConfig)
}
@Test
public fun addTagsWithoutSettingBridging() {
- val bridgingConfig = BridgingConfig.Builder(
- mContext, true
- ).addExcludedTag("foo").build()
+ val bridgingConfig = BridgingConfig.Builder(mContext, true).addExcludedTag("foo").build()
- assertThat(
- bridgingConfig
- ).isEqualTo(BridgingConfig(PACKAGE_NAME, true, HashSet(listOf("foo"))))
+ assertThat(bridgingConfig)
+ .isEqualTo(BridgingConfig(PACKAGE_NAME, true, HashSet(listOf("foo"))))
// Test that conversion to and from bundle works as expected.
- assertThat(
- BridgingConfig.fromBundle(bridgingConfig.toBundle(mContext))
- ).isEqualTo(bridgingConfig)
+ assertThat(BridgingConfig.fromBundle(bridgingConfig.toBundle(mContext)))
+ .isEqualTo(bridgingConfig)
}
@Test
public fun disableBridgingWithTagsInSeparateCalls() {
- val bridgingConfig = BridgingConfig.Builder(
- mContext, false
- )
- .addExcludedTag("foo")
- .addExcludedTag("bar")
- .addExcludedTag("foo")
- .build()
+ val bridgingConfig =
+ BridgingConfig.Builder(mContext, false)
+ .addExcludedTag("foo")
+ .addExcludedTag("bar")
+ .addExcludedTag("foo")
+ .build()
- assertThat(
- bridgingConfig
- ).isEqualTo(BridgingConfig(PACKAGE_NAME, false, HashSet(Arrays.asList("foo", "bar"))))
+ assertThat(bridgingConfig)
+ .isEqualTo(BridgingConfig(PACKAGE_NAME, false, HashSet(Arrays.asList("foo", "bar"))))
// Test that conversion to and from bundle works as expected.
- assertThat(
- BridgingConfig.fromBundle(bridgingConfig.toBundle(mContext))
- ).isEqualTo(bridgingConfig)
+ assertThat(BridgingConfig.fromBundle(bridgingConfig.toBundle(mContext)))
+ .isEqualTo(bridgingConfig)
}
@Test
public fun disableBridgingWithTagsInOneCall() {
- val bridgingConfig = BridgingConfig.Builder(
- mContext, false
- )
- .addExcludedTags(Arrays.asList("foo", "bar", "foo"))
- .build()
+ val bridgingConfig =
+ BridgingConfig.Builder(mContext, false)
+ .addExcludedTags(Arrays.asList("foo", "bar", "foo"))
+ .build()
- assertThat(
- bridgingConfig
- ).isEqualTo(BridgingConfig(PACKAGE_NAME, false, HashSet(Arrays.asList("foo", "bar"))))
+ assertThat(bridgingConfig)
+ .isEqualTo(BridgingConfig(PACKAGE_NAME, false, HashSet(Arrays.asList("foo", "bar"))))
// Test that conversion to and from bundle works as expected.
- assertThat(
- BridgingConfig.fromBundle(bridgingConfig.toBundle(mContext))
- ).isEqualTo(bridgingConfig)
+ assertThat(BridgingConfig.fromBundle(bridgingConfig.toBundle(mContext)))
+ .isEqualTo(bridgingConfig)
}
@Test
public fun disableBridgingWithTagsInMixOfCalls() {
- val bridgingConfig = BridgingConfig.Builder(
- mContext, false
- )
- .addExcludedTag("123")
- .addExcludedTags(Arrays.asList("foo", "bar", "foo"))
- .addExcludedTags(Arrays.asList("foo", "bar", "abc"))
- .addExcludedTag("aaa")
- .addExcludedTag("foo")
- .build()
+ val bridgingConfig =
+ BridgingConfig.Builder(mContext, false)
+ .addExcludedTag("123")
+ .addExcludedTags(Arrays.asList("foo", "bar", "foo"))
+ .addExcludedTags(Arrays.asList("foo", "bar", "abc"))
+ .addExcludedTag("aaa")
+ .addExcludedTag("foo")
+ .build()
- assertThat(
- bridgingConfig
- ).isEqualTo(
- BridgingConfig(
- PACKAGE_NAME, false, HashSet(Arrays.asList("foo", "bar", "123", "aaa", "abc"))
+ assertThat(bridgingConfig)
+ .isEqualTo(
+ BridgingConfig(
+ PACKAGE_NAME,
+ false,
+ HashSet(Arrays.asList("foo", "bar", "123", "aaa", "abc"))
+ )
)
- )
// Test that conversion to and from bundle works as expected.
- assertThat(
- BridgingConfig.fromBundle(bridgingConfig.toBundle(mContext))
- ).isEqualTo(bridgingConfig)
+ assertThat(BridgingConfig.fromBundle(bridgingConfig.toBundle(mContext)))
+ .isEqualTo(bridgingConfig)
}
private companion object {
diff --git a/wear/wear-remote-interactions/samples/src/main/java/androidx/wear/remote/interactions/samples/RemoteActivityHelperSamples.kt b/wear/wear-remote-interactions/samples/src/main/java/androidx/wear/remote/interactions/samples/RemoteActivityHelperSamples.kt
index 193c29e..aa01ee9 100644
--- a/wear/wear-remote-interactions/samples/src/main/java/androidx/wear/remote/interactions/samples/RemoteActivityHelperSamples.kt
+++ b/wear/wear-remote-interactions/samples/src/main/java/androidx/wear/remote/interactions/samples/RemoteActivityHelperSamples.kt
@@ -24,15 +24,17 @@
remoteActivityHelper: RemoteActivityHelper,
remoteIntent: Intent
) {
- remoteActivityHelper.availabilityStatus.collect {
- status -> when (status) {
+ remoteActivityHelper.availabilityStatus.collect { status ->
+ when (status) {
RemoteActivityHelper.STATUS_UNAVAILABLE ->
TODO("Hide or present alternative flow as remote flow is not available.")
RemoteActivityHelper.STATUS_TEMPORARILY_UNAVAILABLE ->
TODO("Present education to user to connect devices or bring to proximity.")
- RemoteActivityHelper.STATUS_AVAILABLE, RemoteActivityHelper.STATUS_UNKNOWN ->
+ RemoteActivityHelper.STATUS_AVAILABLE,
+ RemoteActivityHelper.STATUS_UNKNOWN ->
// Present normal remote device flow when we don't know (old devices)
// or when we know it is available.
remoteActivityHelper.startRemoteActivity(remoteIntent)
- } }
+ }
+ }
}
diff --git a/wear/wear-remote-interactions/src/main/java/androidx/wear/remote/interactions/IRemoteInteractionsManager.kt b/wear/wear-remote-interactions/src/main/java/androidx/wear/remote/interactions/IRemoteInteractionsManager.kt
index 3aded42..bd735c9 100644
--- a/wear/wear-remote-interactions/src/main/java/androidx/wear/remote/interactions/IRemoteInteractionsManager.kt
+++ b/wear/wear-remote-interactions/src/main/java/androidx/wear/remote/interactions/IRemoteInteractionsManager.kt
@@ -19,17 +19,19 @@
import java.util.concurrent.Executor
import java.util.function.Consumer
-/**
- * Forwards remote auth interaction availabilities to [RemoteInteractionsManager].
- */
+/** Forwards remote auth interaction availabilities to [RemoteInteractionsManager]. */
internal interface IRemoteInteractionsManager {
/** Whether the availability status API is supported. */
val isAvailabilityStatusApiSupported: Boolean
- /** Forwards a call to [RemoteInteractionsManager.registerRemoteActivityHelperStatusListener]. */
+ /**
+ * Forwards a call to [RemoteInteractionsManager.registerRemoteActivityHelperStatusListener].
+ */
fun registerRemoteActivityHelperStatusListener(executor: Executor, listener: Consumer<Int>)
- /** Forwards a call to [RemoteInteractionsManager.unregisterRemoteActivityHelperStatusListener]. */
+ /**
+ * Forwards a call to [RemoteInteractionsManager.unregisterRemoteActivityHelperStatusListener].
+ */
fun unregisterRemoteActivityHelperStatusListener(listener: Consumer<Int>)
}
diff --git a/wear/wear-remote-interactions/src/main/java/androidx/wear/remote/interactions/RemoteActivityHelper.kt b/wear/wear-remote-interactions/src/main/java/androidx/wear/remote/interactions/RemoteActivityHelper.kt
index 969c473..2f43168 100644
--- a/wear/wear-remote-interactions/src/main/java/androidx/wear/remote/interactions/RemoteActivityHelper.kt
+++ b/wear/wear-remote-interactions/src/main/java/androidx/wear/remote/interactions/RemoteActivityHelper.kt
@@ -43,9 +43,7 @@
/**
* Support for opening android intents on other devices.
*
- *
* The following example opens play store for the given app on another device:
- *
* ```
* val remoteActivityHelper = RemoteActivityHelper(context, executor)
*
@@ -57,23 +55,24 @@
* nodeId)
* ```
*
- * [startRemoteActivity] returns a [ListenableFuture], which is completed after the intent has
- * been sent or failed if there was an issue with sending the intent.
+ * [startRemoteActivity] returns a [ListenableFuture], which is completed after the intent has been
+ * sent or failed if there was an issue with sending the intent.
*
* nodeId is the opaque string that represents a
- * [node](https://developers.google.com/android/reference/com/google/android/gms/wearable/Node)
- * in the Android Wear network. For the given device, it can obtained by `NodeClient.getLocalNode()`
+ * [node](https://developers.google.com/android/reference/com/google/android/gms/wearable/Node) in
+ * the Android Wear network. For the given device, it can obtained by `NodeClient.getLocalNode()`
* and the list of nodes to which this device is currently connected can be obtained by
* `NodeClient.getConnectedNodes()`. More information about this can be found
* [here](https://developers.google.com/android/reference/com/google/android/gms/wearable/NodeClient).
*
* @param context The [Context] of the application for sending the intent.
- * @param executor [Executor] used for getting data to be passed in remote intent. If not
- * specified, default will be `Executors.newSingleThreadExecutor()`.
+ * @param executor [Executor] used for getting data to be passed in remote intent. If not specified,
+ * default will be `Executors.newSingleThreadExecutor()`.
*/
/* ktlint-enable max-line-length */
public class RemoteActivityHelper
- @JvmOverloads constructor(
+@JvmOverloads
+constructor(
private val context: Context,
private val executor: Executor = Executors.newSingleThreadExecutor()
) {
@@ -88,9 +87,9 @@
/**
* The remote auth's availability is unknown.
*
- * On older devices, [STATUS_UNKNOWN] is returned as we can not determine the availability states. To preserve
- * compatibility with existing devices behavior, try [startRemoteActivity] and handle
- * error codes accordingly.
+ * On older devices, [STATUS_UNKNOWN] is returned as we can not determine the availability
+ * states. To preserve compatibility with existing devices behavior, try
+ * [startRemoteActivity] and handle error codes accordingly.
*/
public const val STATUS_UNAVAILABLE = 1
@@ -121,7 +120,7 @@
*/
public const val RESULT_OK: Int = 0
- /** Result code passed to [ResultReceiver.send] when a remote intent failed to send. */
+ /** Result code passed to [ResultReceiver.send] when a remote intent failed to send. */
public const val RESULT_FAILED: Int = 1
internal const val DEFAULT_PACKAGE = "com.google.android.wearable.app"
@@ -144,8 +143,7 @@
* @return The node id, or null if none was set.
*/
@JvmStatic
- public fun getTargetNodeId(intent: Intent): String? =
- intent.getStringExtra(EXTRA_NODE_ID)
+ public fun getTargetNodeId(intent: Intent): String? = intent.getStringExtra(EXTRA_NODE_ID)
/**
* Returns the [android.os.ResultReceiver] extra of remote intent.
@@ -158,7 +156,7 @@
internal fun getRemoteIntentResultReceiver(intent: Intent): ResultReceiver? =
intent.getParcelableExtra(EXTRA_RESULT_RECEIVER)
- /** Re-package a result receiver as a vanilla version for cross-process sending */
+ /** Re-package a result receiver as a vanilla version for cross-process sending */
@JvmStatic
internal fun getResultReceiverForSending(receiver: ResultReceiver): ResultReceiver {
val parcel = Parcel.obtain()
@@ -170,48 +168,50 @@
}
}
- /**
- * Used for testing only, so we can set mock NodeClient.
- */
- @VisibleForTesting
- internal var nodeClient: NodeClient = Wearable.getNodeClient(context)
+ /** Used for testing only, so we can set mock NodeClient. */
+ @VisibleForTesting internal var nodeClient: NodeClient = Wearable.getNodeClient(context)
/** Used for testing only, so we can mock wear sdk dependency. */
- @VisibleForTesting internal var remoteInteractionsManager: IRemoteInteractionsManager = RemoteInteractionsManagerCompat(context)
+ @VisibleForTesting
+ internal var remoteInteractionsManager: IRemoteInteractionsManager =
+ RemoteInteractionsManagerCompat(context)
/**
* Status of whether [RemoteActivityHelper] can [startRemoteActivity], if known.
*
* In scenarios of restricted connection or temporary disconnection with a paired device,
- * [startRemoteActivity] will not be available. Please check [availabilityStatus] before calling [startRemoteActivity] to
- * provide better experience for the user.
+ * [startRemoteActivity] will not be available. Please check [availabilityStatus] before calling
+ * [startRemoteActivity] to provide better experience for the user.
*
- * Wear devices start to support determining the availability status from Wear Sdk WEAR_TIRAMISU_4.
- * On older wear devices, it will always return [STATUS_UNKNOWN].
- * On phone devices, it will always return [STATUS_UNKNOWN].
+ * Wear devices start to support determining the availability status from Wear Sdk
+ * WEAR_TIRAMISU_4. On older wear devices, it will always return [STATUS_UNKNOWN]. On phone
+ * devices, it will always return [STATUS_UNKNOWN].
*
* @sample androidx.wear.remote.interactions.samples.RemoteActivityAvailabilitySample
*
* @return a [Flow] with a stream of status updates that could be one of [STATUS_UNKNOWN],
* [STATUS_UNAVAILABLE], [STATUS_TEMPORARILY_UNAVAILABLE], [STATUS_AVAILABLE].
*/
- public val availabilityStatus: Flow<Int> get() {
- if (!isCurrentDeviceAWatch(context)) {
- // Currently, we do not support knowing the startRemoteActivity's availability on a non-watch device.
- return flowOf(STATUS_UNKNOWN)
- }
- if (!remoteInteractionsManager.isAvailabilityStatusApiSupported) {
- return flowOf(STATUS_UNKNOWN)
- }
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
- // This should never be reached as the check above wouldn't pass below T.
- // `Consumer<Int>` requires min API 25 but library min API is 23, this hints to lint that the code below
- // only executes on T+.
- return flowOf(STATUS_UNKNOWN)
- }
+ public val availabilityStatus: Flow<Int>
+ get() {
+ if (!isCurrentDeviceAWatch(context)) {
+ // Currently, we do not support knowing the startRemoteActivity's availability on a
+ // non-watch device.
+ return flowOf(STATUS_UNKNOWN)
+ }
+ if (!remoteInteractionsManager.isAvailabilityStatusApiSupported) {
+ return flowOf(STATUS_UNKNOWN)
+ }
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
+ // This should never be reached as the check above wouldn't pass below T.
+ // `Consumer<Int>` requires min API 25 but library min API is 23, this hints to lint
+ // that the code below
+ // only executes on T+.
+ return flowOf(STATUS_UNKNOWN)
+ }
- return getRemoteActivityHelperStatusInternal()
- }
+ return getRemoteActivityHelperStatusInternal()
+ }
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
private fun getRemoteActivityHelperStatusInternal(): Flow<Int> {
@@ -226,29 +226,30 @@
remoteInteractionsManager.registerRemoteActivityHelperStatusListener(executor, callback)
- awaitClose { remoteInteractionsManager.unregisterRemoteActivityHelperStatusListener(callback) }
+ awaitClose {
+ remoteInteractionsManager.unregisterRemoteActivityHelperStatusListener(callback)
+ }
}
}
/**
- * Start an activity on another device. This api currently supports sending intents with
- * action set to [android.content.Intent.ACTION_VIEW], a data uri populated using
+ * Start an activity on another device. This api currently supports sending intents with action
+ * set to [android.content.Intent.ACTION_VIEW], a data uri populated using
* [android.content.Intent.setData], and with the category
- * [android.content.Intent.CATEGORY_BROWSABLE] present. If the current device is a watch,
- * the activity will start on the companion phone device. Otherwise, the activity will
- * start on all connected watch devices.
+ * [android.content.Intent.CATEGORY_BROWSABLE] present. If the current device is a watch, the
+ * activity will start on the companion phone device. Otherwise, the activity will start on all
+ * connected watch devices.
*
- * @param targetIntent The intent to open on the remote device. Action must be set to
- * [android.content.Intent.ACTION_VIEW], a data uri must be populated
- * using [android.content.Intent.setData], and the category
- * [android.content.Intent.CATEGORY_BROWSABLE] must be present.
- * @param targetNodeId Wear OS node id for the device where the activity should be
- * started. If null, and the current device is a watch, the
- * activity will start on the companion phone device. Otherwise,
- * the activity will start on all connected watch devices.
- * @return The [ListenableFuture] which resolves if starting activity was successful or
- * throws [Exception] if any errors happens. If there's a problem with starting remote
- * activity, [RemoteIntentException] will be thrown.
+ * @param targetIntent The intent to open on the remote device. Action must be set to
+ * [android.content.Intent.ACTION_VIEW], a data uri must be populated using
+ * [android.content.Intent.setData], and the category
+ * [android.content.Intent.CATEGORY_BROWSABLE] must be present.
+ * @param targetNodeId Wear OS node id for the device where the activity should be started. If
+ * null, and the current device is a watch, the activity will start on the companion phone
+ * device. Otherwise, the activity will start on all connected watch devices.
+ * @return The [ListenableFuture] which resolves if starting activity was successful or throws
+ * [Exception] if any errors happens. If there's a problem with starting remote activity,
+ * [RemoteIntentException] will be thrown.
*/
@JvmOverloads
public fun startRemoteActivity(
@@ -268,7 +269,10 @@
}
startCreatingIntentForRemoteActivity(
- targetIntent, targetNodeId, it, nodeClient,
+ targetIntent,
+ targetNodeId,
+ it,
+ nodeClient,
object : Callback {
override fun intentCreated(intent: Intent) {
context.sendBroadcast(intent)
@@ -302,10 +306,9 @@
}
if (nodeId != null) {
- nodeClient.getCompanionPackageForNode(nodeId)
- .addOnSuccessListener(
- executor
- ) { taskPackageName ->
+ nodeClient
+ .getCompanionPackageForNode(nodeId)
+ .addOnSuccessListener(executor) { taskPackageName ->
val packageName = taskPackageName ?: DEFAULT_PACKAGE
if (packageName.isEmpty()) {
@@ -320,35 +323,37 @@
)
)
}
- }.addOnFailureListener(executor) { callback.onFailure(it) }
+ }
+ .addOnFailureListener(executor) { callback.onFailure(it) }
return
}
- nodeClient.connectedNodes.addOnSuccessListener(
- executor
- ) { connectedNodes ->
- if (connectedNodes.size == 0) {
- callback.onFailure(NotFoundException("No devices connected"))
- } else {
- val resultReceiver = RemoteIntentResultReceiver(completer, connectedNodes.size)
- for (node in connectedNodes) {
- nodeClient.getCompanionPackageForNode(node.id).addOnSuccessListener(
- executor
- ) { taskPackageName ->
- val packageName = taskPackageName ?: DEFAULT_PACKAGE
- callback.intentCreated(
- createIntent(intent, resultReceiver, node.id, packageName)
- )
- }.addOnFailureListener(executor) { callback.onFailure(it) }
+ nodeClient.connectedNodes
+ .addOnSuccessListener(executor) { connectedNodes ->
+ if (connectedNodes.size == 0) {
+ callback.onFailure(NotFoundException("No devices connected"))
+ } else {
+ val resultReceiver = RemoteIntentResultReceiver(completer, connectedNodes.size)
+ for (node in connectedNodes) {
+ nodeClient
+ .getCompanionPackageForNode(node.id)
+ .addOnSuccessListener(executor) { taskPackageName ->
+ val packageName = taskPackageName ?: DEFAULT_PACKAGE
+ callback.intentCreated(
+ createIntent(intent, resultReceiver, node.id, packageName)
+ )
+ }
+ .addOnFailureListener(executor) { callback.onFailure(it) }
+ }
}
}
- }.addOnFailureListener(executor) { callback.onFailure(it) }
+ .addOnFailureListener(executor) { callback.onFailure(it) }
}
/**
- * Creates [android.content.Intent] with action specifying remote intent. If any of
- * additional extras are specified, they will be added to it. If specified, [ResultReceiver]
- * will be re-packed to be parcelable. If specified, packageName will be set.
+ * Creates [android.content.Intent] with action specifying remote intent. If any of additional
+ * extras are specified, they will be added to it. If specified, [ResultReceiver] will be
+ * re-packed to be parcelable. If specified, packageName will be set.
*/
@VisibleForTesting
internal fun createIntent(
@@ -371,9 +376,7 @@
return remoteIntent
}
- /**
- * Result code passed to [ResultReceiver.send] for the status of remote intent.
- */
+ /** Result code passed to [ResultReceiver.send] for the status of remote intent. */
@IntDef(RESULT_OK, RESULT_FAILED)
@Retention(AnnotationRetention.SOURCE)
internal annotation class SendResult
@@ -382,6 +385,7 @@
private interface Callback {
fun intentCreated(intent: Intent)
+
fun onFailure(exception: Exception)
}
diff --git a/wear/wear-remote-interactions/src/main/java/androidx/wear/remote/interactions/RemoteInteractionsManagerCompat.kt b/wear/wear-remote-interactions/src/main/java/androidx/wear/remote/interactions/RemoteInteractionsManagerCompat.kt
index 1c0fb33..50e0b0b 100644
--- a/wear/wear-remote-interactions/src/main/java/androidx/wear/remote/interactions/RemoteInteractionsManagerCompat.kt
+++ b/wear/wear-remote-interactions/src/main/java/androidx/wear/remote/interactions/RemoteInteractionsManagerCompat.kt
@@ -21,9 +21,7 @@
import java.util.concurrent.Executor
import java.util.function.Consumer
-/**
- * Forwards remote auth interaction availabilities to [RemoteInteractionsManager].
- */
+/** Forwards remote auth interaction availabilities to [RemoteInteractionsManager]. */
internal open class RemoteInteractionsManagerCompat(context: Context) : IRemoteInteractionsManager {
// TODO(b/307543793): Reuse the generalized `WearApiVersionHelper` once available.
@@ -32,8 +30,7 @@
private val remoteInteractionsManager: RemoteInteractionsManager? =
if (isAvailabilityStatusApiSupported)
Sdk.getWearManager(context, RemoteInteractionsManager::class.java)
- else
- null
+ else null
override val isAvailabilityStatusApiSupported: Boolean
get() = wearApiVersion.wearSdkVersion >= 4
@@ -54,9 +51,7 @@
override fun unregisterRemoteActivityHelperStatusListener(listener: Consumer<Int>) {
if (isAvailabilityStatusApiSupported) {
- remoteInteractionsManager!!.unregisterRemoteActivityHelperStatusListener(
- listener
- )
+ remoteInteractionsManager!!.unregisterRemoteActivityHelperStatusListener(listener)
} else {
throw UnsupportedOperationException("Should not call wear sdk when not supported.")
}
diff --git a/wear/wear-remote-interactions/src/main/java/androidx/wear/remote/interactions/WatchFaceConfigIntentHelper.kt b/wear/wear-remote-interactions/src/main/java/androidx/wear/remote/interactions/WatchFaceConfigIntentHelper.kt
index d36cd18..85a2586 100644
--- a/wear/wear-remote-interactions/src/main/java/androidx/wear/remote/interactions/WatchFaceConfigIntentHelper.kt
+++ b/wear/wear-remote-interactions/src/main/java/androidx/wear/remote/interactions/WatchFaceConfigIntentHelper.kt
@@ -26,19 +26,17 @@
* * ones creating Intents
* * ones receiving and responding to those Intents.
*
- *
- * To register a configuration activity for a watch face, add a `<meta-data>` entry to the
- * watch face component in its Android Manifest file with an intent action to be fired to start the
+ * To register a configuration activity for a watch face, add a `<meta-data>` entry to the watch
+ * face component in its Android Manifest file with an intent action to be fired to start the
* activity. The following meta-data will register the
- * `androidx.wear.watchface.editor.action.WATCH_FACE_EDITOR` action to be started when
- * configuring a watch face on the wearable device:
+ * `androidx.wear.watchface.editor.action.WATCH_FACE_EDITOR` action to be started when configuring a
+ * watch face on the wearable device:
* ```
* <meta-data
* android:name="com.google.android.wearable.watchface.wearableConfigurationAction"
* android:value="androidx.wear.watchface.editor.action.WATCH_FACE_EDITOR" />
* ```
*
- *
* To register a configuration activity to be started on a companion phone, add the following
* alternative meta-data entry to the watch face component:
* ```
@@ -47,9 +45,8 @@
* android:value="androidx.wear.watchface.editor.action.WATCH_FACE_EDITOR" />
* ```
*
- *
- * The activity should have an intent filter which lists the action specified in the meta-data
- * block above, in addition to the two categories present in the following example:
+ * The activity should have an intent filter which lists the action specified in the meta-data block
+ * above, in addition to the two categories present in the following example:
* ```
* <activity android:name=".MyWatchFaceConfigActivity">
* <intent-filter>
@@ -61,7 +58,6 @@
* </activity>
* ```
*
- *
* For phone side configuration activities, substitute the category
* `com.google.android.wearable.watchface.category.COMPANION_CONFIGURATION` for
* `com.google.android.wearable.watchface.category.WEARABLE_CONFIGURATION`.
@@ -81,9 +77,9 @@
* given [Intent]. [ComponentName] is being used to identify the APK and the class of the
* watch face service.
*
- * @param watchFaceIntent The intent holding config activity launch.
- * @return the value of an item previously added with [putWatchFaceComponentExtra], or
- * null if no value was found.
+ * @param watchFaceIntent The intent holding config activity launch.
+ * @return the value of an item previously added with [putWatchFaceComponentExtra], or null
+ * if no value was found.
*/
@Suppress("DEPRECATION")
@JvmStatic
@@ -111,7 +107,7 @@
*
* @param watchFaceIntent The intent holding config activity launch.
* @return the value of an item previously added with [putPeerIdExtra], or null if no value
- * was found.
+ * was found.
*/
@JvmStatic
@Nullable
diff --git a/wear/wear-remote-interactions/src/main/java/androidx/wear/remote/interactions/WearApiVersion.kt b/wear/wear-remote-interactions/src/main/java/androidx/wear/remote/interactions/WearApiVersion.kt
index 5b48d07..8631512 100644
--- a/wear/wear-remote-interactions/src/main/java/androidx/wear/remote/interactions/WearApiVersion.kt
+++ b/wear/wear-remote-interactions/src/main/java/androidx/wear/remote/interactions/WearApiVersion.kt
@@ -20,9 +20,7 @@
import androidx.wear.remote.interactions.RemoteInteractionsUtil.isCurrentDeviceAWatch
import com.google.wear.Sdk
-/**
- * Provides wear sdk api version.
- */
+/** Provides wear sdk api version. */
internal class WearApiVersion(val context: Context) {
// TODO(b/307543793): Reuse the generalized `WearApiVersionHelper` once available.
@@ -31,10 +29,11 @@
get() {
if (!isCurrentDeviceAWatch(context)) {
// No wear sdk on non-watch device.
- return 0;
+ return 0
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
- // Wear SDK INT can only be accessed safely from UPSIDE_DOWN_CAKE, introduced from tiramisu kr2.
+ // Wear SDK INT can only be accessed safely from UPSIDE_DOWN_CAKE, introduced from
+ // tiramisu kr2.
// Or crashes with `NoSuchField` will be experienced.
return Sdk.VERSION.WEAR_SDK_INT
}
diff --git a/wear/wear-remote-interactions/src/test/java/androidx/wear/remote/interactions/RemoteActivityHelperTest.kt b/wear/wear-remote-interactions/src/test/java/androidx/wear/remote/interactions/RemoteActivityHelperTest.kt
index 45a06ecee..9e4aa43 100644
--- a/wear/wear-remote-interactions/src/test/java/androidx/wear/remote/interactions/RemoteActivityHelperTest.kt
+++ b/wear/wear-remote-interactions/src/test/java/androidx/wear/remote/interactions/RemoteActivityHelperTest.kt
@@ -86,9 +86,7 @@
private var altResult = RESULT_OK
override fun onReceive(context: Context?, intent: Intent?) {
- val resultReceiver = intent?.let {
- getRemoteIntentResultReceiver(it)
- }
+ val resultReceiver = intent?.let { getRemoteIntentResultReceiver(it) }
if (result == DIFFERENT_RESULT) {
altResult = (altResult + 1) % 2
resultReceiver?.send(result, null)
@@ -104,9 +102,8 @@
private val testNodeId2 = "Test Node ID2"
private val testUri = Uri.parse("market://details?id=com.google.android.wearable.app")
private val context: Context = ApplicationProvider.getApplicationContext()
- private val testExtraIntent = Intent(Intent.ACTION_VIEW)
- .addCategory(Intent.CATEGORY_BROWSABLE)
- .setData(testUri)
+ private val testExtraIntent =
+ Intent(Intent.ACTION_VIEW).addCategory(Intent.CATEGORY_BROWSABLE).setData(testUri)
private lateinit var mRemoteActivityHelper: RemoteActivityHelper
@Mock private var mockNodeClient: NodeClient = mock()
@@ -124,7 +121,8 @@
private fun setSystemFeatureWatch(isWatch: Boolean) {
val shadowPackageManager = shadowOf(context.packageManager)
shadowPackageManager!!.setSystemFeature(
- RemoteInteractionsUtil.SYSTEM_FEATURE_WATCH, isWatch
+ RemoteInteractionsUtil.SYSTEM_FEATURE_WATCH,
+ isWatch
)
}
@@ -142,28 +140,24 @@
@Test
fun testStartRemoteActivity_notActionViewIntent() {
- assertThrows(
- ExecutionException::class.java
- ) { mRemoteActivityHelper.startRemoteActivity(Intent(), testNodeId).get() }
+ assertThrows(ExecutionException::class.java) {
+ mRemoteActivityHelper.startRemoteActivity(Intent(), testNodeId).get()
+ }
}
@Test
fun testStartRemoteActivity_dataNull() {
- assertThrows(
- ExecutionException::class.java
- ) {
+ assertThrows(ExecutionException::class.java) {
mRemoteActivityHelper.startRemoteActivity(Intent(Intent.ACTION_VIEW), testNodeId).get()
}
}
@Test
fun testStartRemoteActivity_notCategoryBrowsable() {
- assertThrows(
- ExecutionException::class.java
- ) {
- mRemoteActivityHelper.startRemoteActivity(
- Intent(Intent.ACTION_VIEW).setData(Uri.EMPTY), testNodeId
- ).get()
+ assertThrows(ExecutionException::class.java) {
+ mRemoteActivityHelper
+ .startRemoteActivity(Intent(Intent.ACTION_VIEW).setData(Uri.EMPTY), testNodeId)
+ .get()
}
}
@@ -185,8 +179,7 @@
}
val broadcastIntents =
- shadowOf(ApplicationProvider.getApplicationContext() as Application)
- .broadcastIntents
+ shadowOf(ApplicationProvider.getApplicationContext() as Application).broadcastIntents
assertEquals(1, broadcastIntents.size)
val intent = broadcastIntents[0]
assertEquals(testExtraIntent, getTargetIntent(intent))
@@ -229,8 +222,7 @@
}
val broadcastIntents =
- shadowOf(ApplicationProvider.getApplicationContext() as Application)
- .broadcastIntents
+ shadowOf(ApplicationProvider.getApplicationContext() as Application).broadcastIntents
assertEquals(1, broadcastIntents.size)
assertRemoteIntentEqual(testExtraIntent, testNodeId, testPackageName, broadcastIntents[0])
}
@@ -254,8 +246,7 @@
}
val broadcastIntents =
- shadowOf(ApplicationProvider.getApplicationContext() as Application)
- .broadcastIntents
+ shadowOf(ApplicationProvider.getApplicationContext() as Application).broadcastIntents
assertEquals(1, broadcastIntents.size)
val intent = broadcastIntents[0]
assertEquals(testExtraIntent, getTargetIntent(intent))
@@ -273,9 +264,8 @@
context.registerReceiver(receiver, IntentFilter(ACTION_REMOTE_INTENT))
try {
- val future = mRemoteActivityHelper.startRemoteActivity(
- testExtraIntent, targetNodeId = null
- )
+ val future =
+ mRemoteActivityHelper.startRemoteActivity(testExtraIntent, targetNodeId = null)
shadowOf(Looper.getMainLooper()).idle()
assertTrue(future.isDone)
future.get()
@@ -287,8 +277,7 @@
shadowOf(Looper.getMainLooper()).idle()
val broadcastIntents =
- shadowOf(ApplicationProvider.getApplicationContext() as Application)
- .broadcastIntents
+ shadowOf(ApplicationProvider.getApplicationContext() as Application).broadcastIntents
assertEquals(2, broadcastIntents.size)
assertRemoteIntentEqual(testExtraIntent, testNodeId, testPackageName, broadcastIntents[0])
@@ -305,9 +294,8 @@
context.registerReceiver(receiver, IntentFilter(ACTION_REMOTE_INTENT))
assertThrows(ExecutionException::class.java) {
- val future = mRemoteActivityHelper.startRemoteActivity(
- testExtraIntent, targetNodeId = null
- )
+ val future =
+ mRemoteActivityHelper.startRemoteActivity(testExtraIntent, targetNodeId = null)
shadowOf(Looper.getMainLooper()).idle()
assertTrue(future.isDone)
future.get()
@@ -316,8 +304,7 @@
shadowOf(Looper.getMainLooper()).idle()
val broadcastIntents =
- shadowOf(ApplicationProvider.getApplicationContext() as Application)
- .broadcastIntents
+ shadowOf(ApplicationProvider.getApplicationContext() as Application).broadcastIntents
assertEquals(2, broadcastIntents.size)
assertRemoteIntentEqual(testExtraIntent, testNodeId, testPackageName, broadcastIntents[0])
assertRemoteIntentEqual(testExtraIntent, testNodeId2, testPackageName2, broadcastIntents[1])
@@ -333,9 +320,8 @@
context.registerReceiver(receiver, IntentFilter(ACTION_REMOTE_INTENT))
assertThrows(ExecutionException::class.java) {
- val future = mRemoteActivityHelper.startRemoteActivity(
- testExtraIntent, targetNodeId = null
- )
+ val future =
+ mRemoteActivityHelper.startRemoteActivity(testExtraIntent, targetNodeId = null)
shadowOf(Looper.getMainLooper()).idle()
assertTrue(future.isDone)
future.get()
@@ -344,8 +330,7 @@
shadowOf(Looper.getMainLooper()).idle()
val broadcastIntents =
- shadowOf(ApplicationProvider.getApplicationContext() as Application)
- .broadcastIntents
+ shadowOf(ApplicationProvider.getApplicationContext() as Application).broadcastIntents
assertEquals(2, broadcastIntents.size)
assertRemoteIntentEqual(testExtraIntent, testNodeId, testPackageName, broadcastIntents[0])
assertRemoteIntentEqual(testExtraIntent, testNodeId2, testPackageName2, broadcastIntents[1])
@@ -384,9 +369,7 @@
shadowOf(Looper.getMainLooper()).idle()
assertTrue(future.isDone)
- val actualException = assertThrows(ExecutionException::class.java) {
- future.get()
- }
+ val actualException = assertThrows(ExecutionException::class.java) { future.get() }
assertTrue(actualException.cause is IllegalStateException)
}
@@ -404,9 +387,7 @@
shadowOf(Looper.getMainLooper()).idle()
assertTrue(future.isDone)
- val actualException = assertThrows(ExecutionException::class.java) {
- future.get()
- }
+ val actualException = assertThrows(ExecutionException::class.java) { future.get() }
assertTrue(actualException.cause is IllegalStateException)
}
@@ -425,9 +406,7 @@
shadowOf(Looper.getMainLooper()).idle()
assertTrue(future.isDone)
- val actualException = assertThrows(ExecutionException::class.java) {
- future.get()
- }
+ val actualException = assertThrows(ExecutionException::class.java) { future.get() }
assertTrue(actualException.cause is IllegalStateException)
}
@@ -442,9 +421,7 @@
shadowOf(Looper.getMainLooper()).idle()
assertTrue(future.isDone)
- val actualException = assertThrows(ExecutionException::class.java) {
- future.get()
- }
+ val actualException = assertThrows(ExecutionException::class.java) { future.get() }
assertTrue(actualException.cause is NotFoundException)
}
@@ -452,16 +429,13 @@
@Test
fun testStartRemoveActivity_noNodes() {
setSystemFeatureWatch(false)
- Mockito.`when`(mockNodeClient.connectedNodes)
- .thenReturn(Tasks.forResult(listOf()))
+ Mockito.`when`(mockNodeClient.connectedNodes).thenReturn(Tasks.forResult(listOf()))
val future = mRemoteActivityHelper.startRemoteActivity(testExtraIntent)
shadowOf(Looper.getMainLooper()).idle()
assertTrue(future.isDone)
- val actualException = assertThrows(ExecutionException::class.java) {
- future.get()
- }
+ val actualException = assertThrows(ExecutionException::class.java) { future.get() }
assertTrue(actualException.cause is NotFoundException)
}
@@ -482,7 +456,7 @@
@Config(minSdk = VERSION_CODES.TIRAMISU)
fun remoteActivityHelperStatus_notSupported_unknown() {
setSystemFeatureWatch(true)
- whenever(remoteInteractionsManager.isAvailabilityStatusApiSupported).thenReturn(false)
+ whenever(remoteInteractionsManager.isAvailabilityStatusApiSupported).thenReturn(false)
val remoteActivityHelperStatus = runBlocking {
mRemoteActivityHelper.availabilityStatus.first()
}
@@ -497,10 +471,12 @@
fun remoteActivityHelperStatus_supported_propagateStatus() {
setSystemFeatureWatch(true)
- for (remoteStatus in listOf(
- RemoteActivityHelper.STATUS_AVAILABLE,
- RemoteActivityHelper.STATUS_UNAVAILABLE,
- RemoteActivityHelper.STATUS_TEMPORARILY_UNAVAILABLE)) {
+ for (remoteStatus in
+ listOf(
+ RemoteActivityHelper.STATUS_AVAILABLE,
+ RemoteActivityHelper.STATUS_UNAVAILABLE,
+ RemoteActivityHelper.STATUS_TEMPORARILY_UNAVAILABLE
+ )) {
whenever(remoteInteractionsManager.isAvailabilityStatusApiSupported).thenReturn(true)
doAnswer {
@Suppress("UNCHECKED_CAST")
diff --git a/wear/wear-remote-interactions/src/test/java/androidx/wear/remote/interactions/WearRemoteInteractionsTestRunner.kt b/wear/wear-remote-interactions/src/test/java/androidx/wear/remote/interactions/WearRemoteInteractionsTestRunner.kt
index f25150bd..1222251 100644
--- a/wear/wear-remote-interactions/src/test/java/androidx/wear/remote/interactions/WearRemoteInteractionsTestRunner.kt
+++ b/wear/wear-remote-interactions/src/test/java/androidx/wear/remote/interactions/WearRemoteInteractionsTestRunner.kt
@@ -24,16 +24,13 @@
*
* It has instrumentation turned off for the [androidx.wear.remote.interactions] package.
*
- * Robolectric tries to instrument Kotlin classes, and it throws errors when it encounters
- * companion objects, constructors with default values for parameters, and data classes with
- * inline classes. We don't need shadowing of our classes because we want to use the actual
- * objects in our tests.
+ * Robolectric tries to instrument Kotlin classes, and it throws errors when it encounters companion
+ * objects, constructors with default values for parameters, and data classes with inline classes.
+ * We don't need shadowing of our classes because we want to use the actual objects in our tests.
*/
class WearRemoteInteractionsTestRunner(testClass: Class<*>) : RobolectricTestRunner(testClass) {
override fun createClassLoaderConfig(method: FrameworkMethod): InstrumentationConfiguration =
- InstrumentationConfiguration.Builder(
- super.createClassLoaderConfig(method)
- )
+ InstrumentationConfiguration.Builder(super.createClassLoaderConfig(method))
.doNotInstrumentPackage("androidx.wear.remote.interactions")
.build()
}
diff --git a/wear/wear-samples-ambient/src/main/java/androidx/wear/samples/ambient/MainActivity.kt b/wear/wear-samples-ambient/src/main/java/androidx/wear/samples/ambient/MainActivity.kt
index 2ec5a44..04c7b24 100644
--- a/wear/wear-samples-ambient/src/main/java/androidx/wear/samples/ambient/MainActivity.kt
+++ b/wear/wear-samples-ambient/src/main/java/androidx/wear/samples/ambient/MainActivity.kt
@@ -13,8 +13,7 @@
import java.util.Date
/** Sample activity that provides an ambient experience. */
-class MainActivity :
- ComponentActivity() {
+class MainActivity : ComponentActivity() {
/** Used to dispatch periodic updates when the activity is in active mode. */
private val activeUpdatesHandler = Handler(Looper.getMainLooper())
@@ -31,37 +30,37 @@
private val timestampTextView by lazy { findViewById<TextView>(R.id.timestamp) }
private val updatesTextView by lazy { findViewById<TextView>(R.id.updates) }
- private val ambientCallback = object : AmbientLifecycleCallback {
- override fun onEnterAmbient(ambientDetails: AmbientDetails) {
- Log.d(TAG, "onEnterAmbient()")
- model.setStatus(Status.AMBIENT)
- model.publishUpdate()
- }
+ private val ambientCallback =
+ object : AmbientLifecycleCallback {
+ override fun onEnterAmbient(ambientDetails: AmbientDetails) {
+ Log.d(TAG, "onEnterAmbient()")
+ model.setStatus(Status.AMBIENT)
+ model.publishUpdate()
+ }
- override fun onUpdateAmbient() {
- Log.d(TAG, "onUpdateAmbient()")
- model.publishUpdate()
- }
+ override fun onUpdateAmbient() {
+ Log.d(TAG, "onUpdateAmbient()")
+ model.publishUpdate()
+ }
- override fun onExitAmbient() {
- Log.d(TAG, "onExitAmbient()")
- model.setStatus(Status.ACTIVE)
- model.publishUpdate()
- schedule()
+ override fun onExitAmbient() {
+ Log.d(TAG, "onExitAmbient()")
+ model.setStatus(Status.ACTIVE)
+ model.publishUpdate()
+ schedule()
+ }
}
- }
/** Invoked on [activeUpdatesHandler], posts an update when the activity is in active mode. */
- private val mActiveUpdatesRunnable: Runnable =
- Runnable {
- // If invoked in ambient mode, do nothing.
- if (ambientObserver.isAmbient) {
- return@Runnable
- }
- model.publishUpdate()
- // Schedule the next update.
- schedule()
+ private val mActiveUpdatesRunnable: Runnable = Runnable {
+ // If invoked in ambient mode, do nothing.
+ if (ambientObserver.isAmbient) {
+ return@Runnable
}
+ model.publishUpdate()
+ // Schedule the next update.
+ schedule()
+ }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -102,15 +101,9 @@
}
private fun observeModel() {
- model.observeStartTime(this) {
- timerTextView.text = formatTimer(model.getTimer())
- }
- model.observeStatus(this) { status ->
- statusTextView.text = "Status: $status"
- }
- model.observeUpdates(this) { updates ->
- updatesTextView.text = formatUpdates(updates)
- }
+ model.observeStartTime(this) { timerTextView.text = formatTimer(model.getTimer()) }
+ model.observeStatus(this) { status -> statusTextView.text = "Status: $status" }
+ model.observeUpdates(this) { updates -> updatesTextView.text = formatUpdates(updates) }
model.observeUpdateTimestamp(this) { timestamp ->
timestampTextView.text = formatTimestamp(timestamp)
timerTextView.text = formatTimer(model.getTimer())
diff --git a/wear/wear-samples-ambient/src/main/java/androidx/wear/samples/ambient/MainViewModel.kt b/wear/wear-samples-ambient/src/main/java/androidx/wear/samples/ambient/MainViewModel.kt
index 4613969..f8eb5f7 100644
--- a/wear/wear-samples-ambient/src/main/java/androidx/wear/samples/ambient/MainViewModel.kt
+++ b/wear/wear-samples-ambient/src/main/java/androidx/wear/samples/ambient/MainViewModel.kt
@@ -22,7 +22,8 @@
import androidx.lifecycle.ViewModel
internal enum class Status {
- ACTIVE, AMBIENT
+ ACTIVE,
+ AMBIENT
}
internal class MainViewModel : ViewModel() {
diff --git a/wear/wear-tooling-preview/src/main/java/androidx/wear/tooling/preview/devices/WearDevice.kt b/wear/wear-tooling-preview/src/main/java/androidx/wear/tooling/preview/devices/WearDevice.kt
index 3916557..630dfa1 100644
--- a/wear/wear-tooling-preview/src/main/java/androidx/wear/tooling/preview/devices/WearDevice.kt
+++ b/wear/wear-tooling-preview/src/main/java/androidx/wear/tooling/preview/devices/WearDevice.kt
@@ -19,35 +19,35 @@
import androidx.annotation.RestrictTo
import androidx.annotation.StringDef
-/**
- * List with the pre-defined devices available to be used in previews.
- */
+/** List with the pre-defined devices available to be used in previews. */
object WearDevices {
// Make sure to update any @StringDefs that reference this object.
/** Round device with 227x227dp (454x454px) dimensions, 1.39" size and xhdpi density. */
const val LARGE_ROUND = "id:wearos_large_round"
/** Round device with 192x192dp (384x384px) dimensions, 1.2" size and xhdpi density. */
const val SMALL_ROUND = "id:wearos_small_round"
- /** Square device with 180x180dp (360x360px) dimensions, 1.2" size and xhdpi density. If
- * you are targeting Wear 3 or later, it is recommended to use [LARGE_ROUND] or [SMALL_ROUND]
- * instead. */
+ /**
+ * Square device with 180x180dp (360x360px) dimensions, 1.2" size and xhdpi density. If you are
+ * targeting Wear 3 or later, it is recommended to use [LARGE_ROUND] or [SMALL_ROUND] instead.
+ */
const val SQUARE = "id:wearos_square"
- /** Rectangular device with 201x238dp (402x476px) dimensions, 1.2" size and xhdpi density. If
- * you are targeting Wear 3 or later, it is recommended to use [LARGE_ROUND] or [SMALL_ROUND]
- * instead. */
+ /**
+ * Rectangular device with 201x238dp (402x476px) dimensions, 1.2" size and xhdpi density. If you
+ * are targeting Wear 3 or later, it is recommended to use [LARGE_ROUND] or [SMALL_ROUND]
+ * instead.
+ */
const val RECT = "id:wearos_rect"
}
-/**
- * Annotation for defining the device to use.
- */
+/** Annotation for defining the device to use. */
@Retention(AnnotationRetention.SOURCE)
@StringDef(
open = true,
- value = [
- WearDevices.LARGE_ROUND,
- WearDevices.SMALL_ROUND,
- ]
+ value =
+ [
+ WearDevices.LARGE_ROUND,
+ WearDevices.SMALL_ROUND,
+ ]
)
@RestrictTo(RestrictTo.Scope.LIBRARY)
annotation class WearDevice
diff --git a/wear/wear/src/androidTest/java/androidx/wear/widget/ArcLayoutTest.kt b/wear/wear/src/androidTest/java/androidx/wear/widget/ArcLayoutTest.kt
index 0c16c1a..c2bfcf3 100644
--- a/wear/wear/src/androidTest/java/androidx/wear/widget/ArcLayoutTest.kt
+++ b/wear/wear/src/androidTest/java/androidx/wear/widget/ArcLayoutTest.kt
@@ -72,15 +72,13 @@
private val testWidth: Int = SCREEN_SIZE_DEFAULT
private val renderDoneLatch = CountDownLatch(1)
- @get:Rule
- val screenshotRule = AndroidXScreenshotTestRule("wear/wear")
+ @get:Rule val screenshotRule = AndroidXScreenshotTestRule("wear/wear")
private fun doOneTest(
key: String,
views: List<View>,
backgroundColor: Int = Color.GRAY,
interactiveFunction: (FrameLayout.() -> Unit)? = null
-
) {
val bitmap = Bitmap.createBitmap(testWidth, testHeight, Bitmap.Config.ARGB_8888)
val canvas = Canvas(bitmap)
@@ -109,89 +107,82 @@
}
private fun createArc(text1: String = "SWEEP", text2: String = "Default") =
- ArcLayout(ApplicationProvider.getApplicationContext())
- .apply {
- addView(
- CurvedTextView(ApplicationProvider.getApplicationContext())
- .apply {
- text = text1
- textColor = Color.BLUE
- setBackgroundColor(Color.rgb(100, 100, 0))
- setSweepRangeDegrees(45f, 360f)
- }
- )
- addView(
- TextView(ApplicationProvider.getApplicationContext()).apply {
- text = "TXT"
- setTextColor(Color.GREEN)
- layoutParams =
- ArcLayout.LayoutParams(
+ ArcLayout(ApplicationProvider.getApplicationContext()).apply {
+ addView(
+ CurvedTextView(ApplicationProvider.getApplicationContext()).apply {
+ text = text1
+ textColor = Color.BLUE
+ setBackgroundColor(Color.rgb(100, 100, 0))
+ setSweepRangeDegrees(45f, 360f)
+ }
+ )
+ addView(
+ TextView(ApplicationProvider.getApplicationContext()).apply {
+ text = "TXT"
+ setTextColor(Color.GREEN)
+ layoutParams =
+ ArcLayout.LayoutParams(
+ ViewGroup.LayoutParams.WRAP_CONTENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT
+ )
+ }
+ )
+ addView(
+ CurvedTextView(ApplicationProvider.getApplicationContext()).apply {
+ text = text2
+ textColor = Color.RED
+ setBackgroundColor(Color.rgb(0, 100, 100))
+ }
+ )
+ }
+
+ private fun createMixedArc() =
+ ArcLayout(ApplicationProvider.getApplicationContext()).apply {
+ addView(
+ CurvedTextView(ApplicationProvider.getApplicationContext()).apply {
+ text = "One"
+ setBackgroundColor(Color.rgb(100, 100, 100))
+ setSweepRangeDegrees(0f, 20f)
+ isClockwise = true
+ }
+ )
+ addView(
+ CurvedTextView(ApplicationProvider.getApplicationContext()).apply {
+ text = "Two"
+ setBackgroundColor(Color.rgb(150, 150, 150))
+ setSweepRangeDegrees(0f, 20f)
+ isClockwise = false
+ }
+ )
+ addView(
+ TextView(ApplicationProvider.getApplicationContext()).apply {
+ text = "TXT"
+ setTextColor(Color.GREEN)
+ layoutParams =
+ ArcLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT
)
- }
- )
- addView(
- CurvedTextView(ApplicationProvider.getApplicationContext())
- .apply {
- text = text2
- textColor = Color.RED
- setBackgroundColor(Color.rgb(0, 100, 100))
- }
- )
- }
-
- private fun createMixedArc() =
- ArcLayout(ApplicationProvider.getApplicationContext())
- .apply {
- addView(
- CurvedTextView(ApplicationProvider.getApplicationContext())
- .apply {
- text = "One"
- setBackgroundColor(Color.rgb(100, 100, 100))
- setSweepRangeDegrees(0f, 20f)
- isClockwise = true
- }
- )
- addView(
- CurvedTextView(ApplicationProvider.getApplicationContext())
- .apply {
- text = "Two"
- setBackgroundColor(Color.rgb(150, 150, 150))
- setSweepRangeDegrees(0f, 20f)
- isClockwise = false
- }
- )
- addView(
- TextView(ApplicationProvider.getApplicationContext()).apply {
- text = "TXT"
- setTextColor(Color.GREEN)
- layoutParams =
- ArcLayout.LayoutParams(
- ViewGroup.LayoutParams.WRAP_CONTENT,
- ViewGroup.LayoutParams.WRAP_CONTENT
- ).apply { isRotated = false }
- }
- )
- addView(
- CurvedTextView(ApplicationProvider.getApplicationContext())
- .apply {
- text = "Three"
- setBackgroundColor(Color.rgb(100, 100, 100))
- setSweepRangeDegrees(0f, 20f)
- isClockwise = true
- }
- )
- addView(
- CurvedTextView(ApplicationProvider.getApplicationContext())
- .apply {
- text = "Four"
- setBackgroundColor(Color.rgb(150, 150, 150))
- setSweepRangeDegrees(0f, 20f)
- isClockwise = false
- }
- )
- }
+ .apply { isRotated = false }
+ }
+ )
+ addView(
+ CurvedTextView(ApplicationProvider.getApplicationContext()).apply {
+ text = "Three"
+ setBackgroundColor(Color.rgb(100, 100, 100))
+ setSweepRangeDegrees(0f, 20f)
+ isClockwise = true
+ }
+ )
+ addView(
+ CurvedTextView(ApplicationProvider.getApplicationContext()).apply {
+ text = "Four"
+ setBackgroundColor(Color.rgb(150, 150, 150))
+ setSweepRangeDegrees(0f, 20f)
+ isClockwise = false
+ }
+ )
+ }
@Test
@Throws(Exception::class)
@@ -222,20 +213,21 @@
doOneTest(
"basic_arcs_ccw_screenshot",
listOf(
- createArc(),
- createArc("SWEEP", "Start").apply {
- anchorAngleDegrees = 270f
- anchorType = ArcLayout.ANCHOR_START
- },
- createArc("SWEEP", "End").apply {
- anchorAngleDegrees = 90f
- anchorType = ArcLayout.ANCHOR_END
- },
- createArc("SWEEP", "Center").apply {
- anchorAngleDegrees = 45f
- anchorType = ArcLayout.ANCHOR_CENTER
- }
- ).apply { forEach { it.isClockwise = false } }
+ createArc(),
+ createArc("SWEEP", "Start").apply {
+ anchorAngleDegrees = 270f
+ anchorType = ArcLayout.ANCHOR_START
+ },
+ createArc("SWEEP", "End").apply {
+ anchorAngleDegrees = 90f
+ anchorType = ArcLayout.ANCHOR_END
+ },
+ createArc("SWEEP", "Center").apply {
+ anchorAngleDegrees = 45f
+ anchorType = ArcLayout.ANCHOR_CENTER
+ }
+ )
+ .apply { forEach { it.isClockwise = false } }
)
}
@@ -244,12 +236,7 @@
fun testArcsMixed() {
doOneTest(
"basic_arcs_mix_screenshot",
- listOf(
- createMixedArc(),
- createMixedArc().apply {
- isClockwise = false
- }
- )
+ listOf(createMixedArc(), createMixedArc().apply { isClockwise = false })
)
}
@@ -271,14 +258,13 @@
// Extension functions to make the margin test more readable.
fun ArcLayout.addSeparator(angle: Float = 10f) {
addView(
- CurvedTextView(ApplicationProvider.getApplicationContext())
- .apply {
- text = " "
- setSweepRangeDegrees(angle, 360f)
- setBackgroundColor(Color.rgb(100, 100, 100))
- isClockwise = true
- textSize = 40f
- }
+ CurvedTextView(ApplicationProvider.getApplicationContext()).apply {
+ text = " "
+ setSweepRangeDegrees(angle, 360f)
+ setBackgroundColor(Color.rgb(100, 100, 100))
+ isClockwise = true
+ textSize = 40f
+ }
)
testColors.add(colorProcessor(Color.rgb(150, 150, 150)))
}
@@ -303,8 +289,8 @@
minSweep: Float = 0f,
weight: Float = 0f
): CurvedTextView {
- val curvedTextView = CurvedTextView(ApplicationProvider.getApplicationContext())
- .also {
+ val curvedTextView =
+ CurvedTextView(ApplicationProvider.getApplicationContext()).also {
it.text = text
it.setBackgroundColor(color)
it.isClockwise = clockwise
@@ -317,30 +303,28 @@
paddingRight ?: padding ?: 0,
paddingBottom ?: padding ?: 0
)
- it.layoutParams = ArcLayout.LayoutParams(
- ViewGroup.LayoutParams.MATCH_PARENT,
- ViewGroup.LayoutParams.MATCH_PARENT
- ).apply {
- setMargins(
- marginLeft ?: margin ?: 0,
- marginTop ?: margin ?: 0,
- marginRight ?: margin ?: 0,
- marginBottom ?: margin ?: 0
- )
- verticalAlignment = vAlign
- this.weight = weight
- }
+ it.layoutParams =
+ ArcLayout.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.MATCH_PARENT
+ )
+ .apply {
+ setMargins(
+ marginLeft ?: margin ?: 0,
+ marginTop ?: margin ?: 0,
+ marginRight ?: margin ?: 0,
+ marginBottom ?: margin ?: 0
+ )
+ verticalAlignment = vAlign
+ this.weight = weight
+ }
}
addView(curvedTextView)
testColors.add(colorProcessor(color))
return curvedTextView
}
- fun ArcLayout.addTextView(
- text: String,
- color: Int,
- textSize: Float = 14f
- ) {
+ fun ArcLayout.addTextView(text: String, color: Int, textSize: Float = 14f) {
addView(
TextView(context).also {
it.text = text
@@ -372,54 +356,52 @@
}
private fun createArcWithMargin() =
- ArcLayout(ApplicationProvider.getApplicationContext())
- .apply {
- anchorType = ArcLayout.ANCHOR_CENTER
- addSeparator()
- addCurvedText("RI", Color.RED, marginTop = 16, vAlign = VERTICAL_ALIGN_INNER)
- addCurvedText(
- "GI",
- Color.GREEN,
- marginTop = 8,
- marginBottom = 8,
- vAlign = VERTICAL_ALIGN_INNER
- )
- addCurvedText("BI", Color.BLUE, marginBottom = 16, vAlign = VERTICAL_ALIGN_INNER)
- addSeparator()
- addCurvedText("Red", Color.RED, marginTop = 16)
- addCurvedText("Green", Color.GREEN, marginTop = 8, marginBottom = 8)
- addCurvedText("Blue", Color.BLUE, marginBottom = 16)
- addSeparator()
- addCurvedText("RO", Color.RED, marginTop = 16, vAlign = VERTICAL_ALIGN_OUTER)
- addCurvedText(
- "GO",
- Color.GREEN,
- marginTop = 8,
- marginBottom = 8,
- vAlign = VERTICAL_ALIGN_OUTER
- )
- addCurvedText("BO", Color.BLUE, marginBottom = 16, vAlign = VERTICAL_ALIGN_OUTER)
- addSeparator()
- addCurvedText("L", Color.WHITE, marginRight = 20)
- addSeparator()
- addCurvedText("C", Color.WHITE, marginRight = 10, marginLeft = 10)
- addSeparator()
- addCurvedText("R", Color.WHITE, marginLeft = 20)
- addSeparator()
- }
-
- private fun createTwoArcsWithMargin() = listOf(
- // First arc goes on top
- createArcWithMargin(),
-
- // Second arc in the bottom, and we change al children to go counterclockwise.
- createArcWithMargin().apply {
- anchorAngleDegrees = 180f
- children.forEach {
- (it as? CurvedTextView)?.isClockwise = false
- }
+ ArcLayout(ApplicationProvider.getApplicationContext()).apply {
+ anchorType = ArcLayout.ANCHOR_CENTER
+ addSeparator()
+ addCurvedText("RI", Color.RED, marginTop = 16, vAlign = VERTICAL_ALIGN_INNER)
+ addCurvedText(
+ "GI",
+ Color.GREEN,
+ marginTop = 8,
+ marginBottom = 8,
+ vAlign = VERTICAL_ALIGN_INNER
+ )
+ addCurvedText("BI", Color.BLUE, marginBottom = 16, vAlign = VERTICAL_ALIGN_INNER)
+ addSeparator()
+ addCurvedText("Red", Color.RED, marginTop = 16)
+ addCurvedText("Green", Color.GREEN, marginTop = 8, marginBottom = 8)
+ addCurvedText("Blue", Color.BLUE, marginBottom = 16)
+ addSeparator()
+ addCurvedText("RO", Color.RED, marginTop = 16, vAlign = VERTICAL_ALIGN_OUTER)
+ addCurvedText(
+ "GO",
+ Color.GREEN,
+ marginTop = 8,
+ marginBottom = 8,
+ vAlign = VERTICAL_ALIGN_OUTER
+ )
+ addCurvedText("BO", Color.BLUE, marginBottom = 16, vAlign = VERTICAL_ALIGN_OUTER)
+ addSeparator()
+ addCurvedText("L", Color.WHITE, marginRight = 20)
+ addSeparator()
+ addCurvedText("C", Color.WHITE, marginRight = 10, marginLeft = 10)
+ addSeparator()
+ addCurvedText("R", Color.WHITE, marginLeft = 20)
+ addSeparator()
}
- )
+
+ private fun createTwoArcsWithMargin() =
+ listOf(
+ // First arc goes on top
+ createArcWithMargin(),
+
+ // Second arc in the bottom, and we change al children to go counterclockwise.
+ createArcWithMargin().apply {
+ anchorAngleDegrees = 180f
+ children.forEach { (it as? CurvedTextView)?.isClockwise = false }
+ }
+ )
@Test
fun testMargins() {
@@ -430,9 +412,7 @@
fun testMarginsCcw() {
doOneTest(
"margin_ccw_test",
- createTwoArcsWithMargin().map {
- it.apply { isClockwise = false }
- }
+ createTwoArcsWithMargin().map { it.apply { isClockwise = false } }
)
}
@@ -443,13 +423,12 @@
doOneTest(
"layout_weight_180",
listOf(
- ArcLayout(ApplicationProvider.getApplicationContext())
- .apply {
- anchorType = ArcLayout.ANCHOR_START
- maxAngleDegrees = 180f
- child1 = addCurvedText("1/4", Color.RED, textSize = 30f, weight = 1f)
- child2 = addCurvedText("3/4", Color.GREEN, textSize = 30f, weight = 3f)
- }
+ ArcLayout(ApplicationProvider.getApplicationContext()).apply {
+ anchorType = ArcLayout.ANCHOR_START
+ maxAngleDegrees = 180f
+ child1 = addCurvedText("1/4", Color.RED, textSize = 30f, weight = 1f)
+ child2 = addCurvedText("3/4", Color.GREEN, textSize = 30f, weight = 3f)
+ }
)
)
@@ -462,25 +441,12 @@
doOneTest(
"layout_weight_180_padding",
listOf(
- ArcLayout(ApplicationProvider.getApplicationContext())
- .apply {
- anchorType = ArcLayout.ANCHOR_START
- maxAngleDegrees = 180f
- addCurvedText(
- "1/4",
- Color.RED,
- textSize = 30f,
- weight = 1f,
- padding = 20
- )
- addCurvedText(
- "3/4",
- Color.GREEN,
- textSize = 30f,
- weight = 3f,
- padding = 20
- )
- }
+ ArcLayout(ApplicationProvider.getApplicationContext()).apply {
+ anchorType = ArcLayout.ANCHOR_START
+ maxAngleDegrees = 180f
+ addCurvedText("1/4", Color.RED, textSize = 30f, weight = 1f, padding = 20)
+ addCurvedText("3/4", Color.GREEN, textSize = 30f, weight = 3f, padding = 20)
+ }
)
)
}
@@ -490,14 +456,13 @@
doOneTest(
"layout_weight_180_rtl",
listOf(
- ArcLayout(ApplicationProvider.getApplicationContext())
- .apply {
- anchorType = ArcLayout.ANCHOR_START
- layoutDirection = View.LAYOUT_DIRECTION_RTL
- maxAngleDegrees = 180f
- addCurvedText("1/4", Color.RED, textSize = 30f, weight = 1f)
- addCurvedText("3/4", Color.GREEN, textSize = 30f, weight = 3f)
- }
+ ArcLayout(ApplicationProvider.getApplicationContext()).apply {
+ anchorType = ArcLayout.ANCHOR_START
+ layoutDirection = View.LAYOUT_DIRECTION_RTL
+ maxAngleDegrees = 180f
+ addCurvedText("1/4", Color.RED, textSize = 30f, weight = 1f)
+ addCurvedText("3/4", Color.GREEN, textSize = 30f, weight = 3f)
+ }
)
)
}
@@ -507,14 +472,13 @@
doOneTest(
"mixed_layout_weight",
listOf(
- ArcLayout(ApplicationProvider.getApplicationContext())
- .apply {
- anchorType = ArcLayout.ANCHOR_START
- maxAngleDegrees = 180f
- addCurvedText("Fixed", Color.BLUE, textSize = 30f)
- addCurvedText("1/4", Color.RED, textSize = 30f, weight = 1f)
- addCurvedText("3/4", Color.GREEN, textSize = 30f, weight = 3f)
- }
+ ArcLayout(ApplicationProvider.getApplicationContext()).apply {
+ anchorType = ArcLayout.ANCHOR_START
+ maxAngleDegrees = 180f
+ addCurvedText("Fixed", Color.BLUE, textSize = 30f)
+ addCurvedText("1/4", Color.RED, textSize = 30f, weight = 1f)
+ addCurvedText("3/4", Color.GREEN, textSize = 30f, weight = 3f)
+ }
)
)
}
@@ -524,14 +488,13 @@
doOneTest(
"mixed_layout_weight_anchor_end",
listOf(
- ArcLayout(ApplicationProvider.getApplicationContext())
- .apply {
- anchorType = ArcLayout.ANCHOR_END
- maxAngleDegrees = 180f
- addCurvedText("Fixed", Color.BLUE, textSize = 30f)
- addCurvedText("1/4", Color.RED, textSize = 30f, weight = 1f)
- addCurvedText("3/4", Color.GREEN, textSize = 30f, weight = 3f)
- }
+ ArcLayout(ApplicationProvider.getApplicationContext()).apply {
+ anchorType = ArcLayout.ANCHOR_END
+ maxAngleDegrees = 180f
+ addCurvedText("Fixed", Color.BLUE, textSize = 30f)
+ addCurvedText("1/4", Color.RED, textSize = 30f, weight = 1f)
+ addCurvedText("3/4", Color.GREEN, textSize = 30f, weight = 3f)
+ }
)
)
}
@@ -541,28 +504,27 @@
doOneTest(
"inivisible_gone_test",
listOf(
- ArcLayout(ApplicationProvider.getApplicationContext())
- .apply {
- anchorType = ArcLayout.ANCHOR_CENTER
- addCurvedText("Initial", Color.RED, textSize = 30f)
- addInvisibleTextView()
- addCurvedText("Second", Color.GREEN, textSize = 30f)
- addGoneTextView()
- addCurvedText("Third", Color.BLUE, textSize = 30f)
- addSeparator()
- addCurvedText("Initial", Color.RED, textSize = 30f, clockwise = false)
- addInvisibleTextView()
- addCurvedText("Second", Color.GREEN, textSize = 30f, clockwise = false)
- addGoneTextView()
- addCurvedText("Third", Color.BLUE, textSize = 30f, clockwise = false)
- }
+ ArcLayout(ApplicationProvider.getApplicationContext()).apply {
+ anchorType = ArcLayout.ANCHOR_CENTER
+ addCurvedText("Initial", Color.RED, textSize = 30f)
+ addInvisibleTextView()
+ addCurvedText("Second", Color.GREEN, textSize = 30f)
+ addGoneTextView()
+ addCurvedText("Third", Color.BLUE, textSize = 30f)
+ addSeparator()
+ addCurvedText("Initial", Color.RED, textSize = 30f, clockwise = false)
+ addInvisibleTextView()
+ addCurvedText("Second", Color.GREEN, textSize = 30f, clockwise = false)
+ addGoneTextView()
+ addCurvedText("Third", Color.BLUE, textSize = 30f, clockwise = false)
+ }
)
)
}
- private fun createArcsWithPaddingAndMargins() = listOf(
- ArcLayout(ApplicationProvider.getApplicationContext())
- .apply {
+ private fun createArcsWithPaddingAndMargins() =
+ listOf(
+ ArcLayout(ApplicationProvider.getApplicationContext()).apply {
anchorType = ArcLayout.ANCHOR_CENTER
listOf(VERTICAL_ALIGN_INNER, VERTICAL_ALIGN_CENTER, VERTICAL_ALIGN_OUTER).forEach {
align ->
@@ -583,8 +545,7 @@
}
addSeparator()
},
- ArcLayout(ApplicationProvider.getApplicationContext())
- .apply {
+ ArcLayout(ApplicationProvider.getApplicationContext()).apply {
anchorType = ArcLayout.ANCHOR_CENTER
anchorAngleDegrees = 180f
addSeparator()
@@ -597,14 +558,11 @@
addCurvedText("Right", 0xFF8000FF.toInt(), paddingRight = 16)
addSeparator()
}
- )
+ )
@Test
fun testMarginsAndPadding() {
- doOneTest(
- "margin_padding_test",
- createArcsWithPaddingAndMargins()
- )
+ doOneTest("margin_padding_test", createArcsWithPaddingAndMargins())
}
@Test
@@ -652,19 +610,20 @@
}
// Generates a click in the x,y coordinates in the view's coordinate system.
- fun customClick(x: Float, y: Float) = ViewActions.actionWithAssertions(
- GeneralClickAction(
- Tap.SINGLE,
- { view ->
- val xy = IntArray(2)
- view.getLocationOnScreen(xy)
- floatArrayOf(x + xy[0], y + xy[1])
- },
- Press.PINPOINT,
- InputDevice.SOURCE_UNKNOWN,
- MotionEvent.BUTTON_PRIMARY
+ fun customClick(x: Float, y: Float) =
+ ViewActions.actionWithAssertions(
+ GeneralClickAction(
+ Tap.SINGLE,
+ { view ->
+ val xy = IntArray(2)
+ view.getLocationOnScreen(xy)
+ floatArrayOf(x + xy[0], y + xy[1])
+ },
+ Press.PINPOINT,
+ InputDevice.SOURCE_UNKNOWN,
+ MotionEvent.BUTTON_PRIMARY
+ )
)
- )
// Sending clicks is slow, around a quarter of a second each, on a desktop emulator.
@Test(timeout = 100000)
@@ -678,37 +637,37 @@
DrawableSurface.radius = 6f
// Find the main FrameLayout that contains all widgets under test.
- val theView = Espresso.onView(withId(R.id.curved_frame))
- .perform(
- waitForMatchingView(
- allOf(
- withId(R.id.curved_frame),
- isDisplayed()
- ),
- 2000
- )
- )
+ val theView =
+ Espresso.onView(withId(R.id.curved_frame))
+ .perform(waitForMatchingView(allOf(withId(R.id.curved_frame), isDisplayed()), 2000))
- theView.perform(object : ViewAction {
- override fun getConstraints(): Matcher<View> = any(View::class.java)
- override fun getDescription(): String = "Resize view to fit the test."
- override fun perform(uiController: UiController?, view: View?) {
- (view as? FrameLayout)?.layoutParams =
- FrameLayout.LayoutParams(testWidth, testHeight)
+ theView.perform(
+ object : ViewAction {
+ override fun getConstraints(): Matcher<View> = any(View::class.java)
+
+ override fun getDescription(): String = "Resize view to fit the test."
+
+ override fun perform(uiController: UiController?, view: View?) {
+ (view as? FrameLayout)?.layoutParams =
+ FrameLayout.LayoutParams(testWidth, testHeight)
+ }
}
- })
+ )
// Setup on-click handlers for each view so we can get the index of the clicked view.
var clicked: Int
scenario.onActivity {
listOf(
- R.id.curved_text1, R.id.curved_text2, R.id.curved_text3,
- R.id.curved_text4, R.id.text5, R.id.curved_text6
- ).mapIndexed { ix, viewId ->
- it.findViewById<View>(viewId)?.setOnClickListener {
- clicked = ix
+ R.id.curved_text1,
+ R.id.curved_text2,
+ R.id.curved_text3,
+ R.id.curved_text4,
+ R.id.text5,
+ R.id.curved_text6
+ )
+ .mapIndexed { ix, viewId ->
+ it.findViewById<View>(viewId)?.setOnClickListener { clicked = ix }
}
- }
}
// Simulate clicks in a grid all over the screen and draw a circle centered in the
@@ -722,32 +681,41 @@
theView.perform(customClick(x.toFloat(), y.toFloat()))
points.add(
ColoredPoint(
- x.toFloat(), y.toFloat(),
+ x.toFloat(),
+ y.toFloat(),
// Color the circle.
listOf(
- Color.BLACK, // no view got the event.
- Color.RED, Color.GREEN, Color.BLUE,
- Color.YELLOW, Color.MAGENTA, Color.CYAN
- ).elementAtOrNull(clicked + 1) ?: Color.WHITE
+ Color.BLACK, // no view got the event.
+ Color.RED,
+ Color.GREEN,
+ Color.BLUE,
+ Color.YELLOW,
+ Color.MAGENTA,
+ Color.CYAN
+ )
+ .elementAtOrNull(clicked + 1) ?: Color.WHITE
)
)
}
// Add all circles on the current line to the DrawableSurface.
// Points are batched to improve performance a bit.
- Espresso.onView(withId(R.id.drawable_surface)).perform(object : ViewAction {
- override fun getConstraints(): Matcher<View> = any(View::class.java)
- override fun getDescription(): String = "Add Points"
- override fun perform(uiController: UiController?, view: View?) {
- (view as? DrawableSurface)?.addPoints(points)
- }
- })
+ Espresso.onView(withId(R.id.drawable_surface))
+ .perform(
+ object : ViewAction {
+ override fun getConstraints(): Matcher<View> = any(View::class.java)
+
+ override fun getDescription(): String = "Add Points"
+
+ override fun perform(uiController: UiController?, view: View?) {
+ (view as? DrawableSurface)?.addPoints(points)
+ }
+ }
+ )
}
// At the end, get a screenshot to compare against the golden
- scenario.onActivity {
- it.findViewById<View>(R.id.curved_frame).draw(canvas)
- }
+ scenario.onActivity { it.findViewById<View>(R.id.curved_frame).draw(canvas) }
bitmap.assertAgainstGolden(screenshotRule, "touch_screenshot" + "_" + testHeight)
}
@@ -787,10 +755,7 @@
// Do the test, sending the events
var time = 0L
DrawableSurface.radius = 1.5f
- doOneTest(
- key, views,
- backgroundColor = Color.rgb(0xFF, 0xFF, 0xC0)
- ) {
+ doOneTest(key, views, backgroundColor = Color.rgb(0xFF, 0xFF, 0xC0)) {
val STEP = 4
// Simulate clicks in a grid all over the screen and draw a circle centered in the
@@ -798,19 +763,30 @@
// Black means no view got the click event, white means a out of range value.
for (y in STEP / 2 until testHeight step STEP) {
for (x in STEP / 2 until testWidth step STEP) {
- // Perform a click, and record a point colored according to which view was clicked.
+ // Perform a click, and record a point colored according to which view was
+ // clicked.
clicked = -1
- val down_event = MotionEvent.obtain(
- time, time, MotionEvent.ACTION_DOWN,
- x.toFloat(), y.toFloat(), 0
- )
+ val down_event =
+ MotionEvent.obtain(
+ time,
+ time,
+ MotionEvent.ACTION_DOWN,
+ x.toFloat(),
+ y.toFloat(),
+ 0
+ )
dispatchTouchEvent(down_event)
- val up_event = MotionEvent.obtain(
- time, time + 5, MotionEvent.ACTION_UP,
- x.toFloat(), y.toFloat(), 0
- )
+ val up_event =
+ MotionEvent.obtain(
+ time,
+ time + 5,
+ MotionEvent.ACTION_UP,
+ x.toFloat(),
+ y.toFloat(),
+ 0
+ )
dispatchTouchEvent(up_event)
time += 10
@@ -818,7 +794,8 @@
drawableSurface.addPoints(
listOf(
ColoredPoint(
- x.toFloat(), y.toFloat(),
+ x.toFloat(),
+ y.toFloat(),
// Color the circle.
// We use Transparent for not touched and white for out of index
testColors.elementAtOrNull(clicked + 1) ?: Color.WHITE
@@ -835,42 +812,59 @@
fun testBasicTouch() {
val context: Context = ApplicationProvider.getApplicationContext()
// This views are the same as the test testTouchEvents()
- val views = listOf(
- ArcLayout(context).apply {
- anchorAngleDegrees = 0f
- anchorType = ArcLayout.ANCHOR_CENTER
- isClockwise = true
- addCurvedText(
- "Left", color = 0x66FF0000, textSize = 48f, minSweep = 60f,
- textAlignment = View.TEXT_ALIGNMENT_TEXT_START
- )
- addGoneTextView()
- addCurvedText(
- "Center", color = 0x6600FF00, textSize = 48f, minSweep = 60f,
- textAlignment = View.TEXT_ALIGNMENT_CENTER
- )
- addCurvedText(
- "Right", color = 0x660000FF, textSize = 48f, minSweep = 60f,
- textAlignment = View.TEXT_ALIGNMENT_TEXT_END
- )
- addGoneTextView()
- },
- ArcLayout(context).apply {
- anchorAngleDegrees = 180f
- anchorType = ArcLayout.ANCHOR_CENTER
- isClockwise = true
- addGoneTextView()
- addCurvedText(
- "ACL", color = 0x66FFFF00, textSize = 48f, minSweep = 40f,
- textAlignment = View.TEXT_ALIGNMENT_TEXT_START
- )
- addTextView(text = "N-TXT", color = 0x66FF00FF, textSize = 20f)
- addCurvedText(
- "ACR", color = 0x6600FFFF, textSize = 60f, minSweep = 50f,
- textAlignment = View.TEXT_ALIGNMENT_TEXT_END, clockwise = false
- )
- }
- )
+ val views =
+ listOf(
+ ArcLayout(context).apply {
+ anchorAngleDegrees = 0f
+ anchorType = ArcLayout.ANCHOR_CENTER
+ isClockwise = true
+ addCurvedText(
+ "Left",
+ color = 0x66FF0000,
+ textSize = 48f,
+ minSweep = 60f,
+ textAlignment = View.TEXT_ALIGNMENT_TEXT_START
+ )
+ addGoneTextView()
+ addCurvedText(
+ "Center",
+ color = 0x6600FF00,
+ textSize = 48f,
+ minSweep = 60f,
+ textAlignment = View.TEXT_ALIGNMENT_CENTER
+ )
+ addCurvedText(
+ "Right",
+ color = 0x660000FF,
+ textSize = 48f,
+ minSweep = 60f,
+ textAlignment = View.TEXT_ALIGNMENT_TEXT_END
+ )
+ addGoneTextView()
+ },
+ ArcLayout(context).apply {
+ anchorAngleDegrees = 180f
+ anchorType = ArcLayout.ANCHOR_CENTER
+ isClockwise = true
+ addGoneTextView()
+ addCurvedText(
+ "ACL",
+ color = 0x66FFFF00,
+ textSize = 48f,
+ minSweep = 40f,
+ textAlignment = View.TEXT_ALIGNMENT_TEXT_START
+ )
+ addTextView(text = "N-TXT", color = 0x66FF00FF, textSize = 20f)
+ addCurvedText(
+ "ACR",
+ color = 0x6600FFFF,
+ textSize = 60f,
+ minSweep = 50f,
+ textAlignment = View.TEXT_ALIGNMENT_TEXT_END,
+ clockwise = false
+ )
+ }
+ )
testEventsFast("touch_fast_screenshot", views)
}
@@ -888,11 +882,12 @@
@JvmStatic
@Parameterized.Parameters(name = "testHeight={0}")
- fun initParameters() = listOf(
- SCREEN_SIZE_DEFAULT,
- SCREEN_SIZE_DEFAULT + SCREEN_SIZE_DIFF,
- SCREEN_SIZE_DEFAULT - SCREEN_SIZE_DIFF
- )
+ fun initParameters() =
+ listOf(
+ SCREEN_SIZE_DEFAULT,
+ SCREEN_SIZE_DEFAULT + SCREEN_SIZE_DIFF,
+ SCREEN_SIZE_DEFAULT - SCREEN_SIZE_DIFF
+ )
}
}
@@ -908,19 +903,19 @@
data class ColoredPoint(val x: Float, val y: Float, val c: Int)
// Helper class to draw some point/circles of different colors. Used by the touch test.
-open class DrawableSurface @JvmOverloads constructor(
- context: Context,
- attrs: AttributeSet? = null,
- defStyleAttr: Int = 0
-) : View(context, attrs, defStyleAttr) {
+open class DrawableSurface
+@JvmOverloads
+constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) :
+ View(context, attrs, defStyleAttr) {
private var points = mutableListOf<ColoredPoint>()
override fun onDraw(canvas: Canvas) {
- val paint = Paint().apply {
- strokeWidth = radius / 2f
- style = Paint.Style.STROKE
- alpha = 0
- }
+ val paint =
+ Paint().apply {
+ strokeWidth = radius / 2f
+ style = Paint.Style.STROKE
+ alpha = 0
+ }
points.forEach { p ->
paint.color = p.c
canvas.drawCircle(p.x, p.y, radius, paint)
diff --git a/wear/wear/src/androidTest/java/androidx/wear/widget/CurvedTextViewTest.kt b/wear/wear/src/androidTest/java/androidx/wear/widget/CurvedTextViewTest.kt
index 96c10c8..d84a390 100644
--- a/wear/wear/src/androidTest/java/androidx/wear/widget/CurvedTextViewTest.kt
+++ b/wear/wear/src/androidTest/java/androidx/wear/widget/CurvedTextViewTest.kt
@@ -43,8 +43,7 @@
private val canvas = Canvas(bitmap)
private val renderDoneLatch = CountDownLatch(1)
- @get:Rule
- val screenshotRule = AndroidXScreenshotTestRule("wear/wear")
+ @get:Rule val screenshotRule = AndroidXScreenshotTestRule("wear/wear")
private fun doOneTest(key: String, views: List<View>) {
// Set the main frame.
@@ -63,41 +62,37 @@
bitmap.assertAgainstGolden(screenshotRule, key)
}
- private fun createThree(centerStr: String, leftStr: String, rightStr: String) = listOf(
- CurvedTextView(ApplicationProvider.getApplicationContext())
- .apply {
+ private fun createThree(centerStr: String, leftStr: String, rightStr: String) =
+ listOf(
+ CurvedTextView(ApplicationProvider.getApplicationContext()).apply {
text = centerStr
textColor = Color.BLUE
setBackgroundColor(Color.rgb(100, 100, 0))
anchorType = ArcLayout.ANCHOR_CENTER
anchorAngleDegrees = 0f
},
- CurvedTextView(ApplicationProvider.getApplicationContext())
- .apply {
+ CurvedTextView(ApplicationProvider.getApplicationContext()).apply {
text = leftStr
textColor = Color.RED
setBackgroundColor(Color.rgb(0, 100, 100))
anchorAngleDegrees = 240f
anchorType = ArcLayout.ANCHOR_START
},
- CurvedTextView(ApplicationProvider.getApplicationContext())
- .apply {
+ CurvedTextView(ApplicationProvider.getApplicationContext()).apply {
text = rightStr
textColor = Color.GREEN
setBackgroundColor(Color.rgb(100, 0, 100))
anchorType = ArcLayout.ANCHOR_END
anchorAngleDegrees = 120f
}
- )
+ )
- private fun createThree(): List<CurvedTextView> =
- createThree("Center", "Left", "Right")
+ private fun createThree(): List<CurvedTextView> = createThree("Center", "Left", "Right")
@Test
@Throws(Exception::class)
fun testDefaults() {
- val textView =
- CurvedTextView(ApplicationProvider.getApplicationContext())
+ val textView = CurvedTextView(ApplicationProvider.getApplicationContext())
textView.text = "Hello World!"
doOneTest("hello_world_screenshot", listOf(textView))
}
@@ -113,11 +108,7 @@
fun testMaxSweepDegree() {
doOneTest(
"max_sweep_degree_screenshot",
- createThree(
- "center long string",
- "left string",
- "right"
- ).apply {
+ createThree("center long string", "left string", "right").apply {
forEach {
it.setSweepRangeDegrees(0f, 55f)
it.ellipsize = TextUtils.TruncateAt.END
@@ -131,11 +122,7 @@
fun testMinSweepDegree() {
doOneTest(
"min_sweep_degree_screenshot",
- createThree(
- "center long string",
- "left string",
- "right"
- ).apply {
+ createThree("center long string", "left string", "right").apply {
forEach {
it.setSweepRangeDegrees(55f, 360f)
it.ellipsize = TextUtils.TruncateAt.END
@@ -149,19 +136,16 @@
fun tesSweepDegree() {
doOneTest(
"sweep_degree_screenshot",
- createThree(
- "center long string",
- "left string",
- "right"
- ).apply {
+ createThree("center long string", "left string", "right").apply {
forEachIndexed { ix, v ->
v.setSweepRangeDegrees(50f, 60f)
v.ellipsize = TextUtils.TruncateAt.END
- v.textAlignment = listOf(
- View.TEXT_ALIGNMENT_CENTER,
- View.TEXT_ALIGNMENT_TEXT_START,
- View.TEXT_ALIGNMENT_TEXT_END
- )[ix]
+ v.textAlignment =
+ listOf(
+ View.TEXT_ALIGNMENT_CENTER,
+ View.TEXT_ALIGNMENT_TEXT_START,
+ View.TEXT_ALIGNMENT_TEXT_END
+ )[ix]
}
}
)
@@ -181,9 +165,7 @@
fun testTextSize() {
doOneTest(
"text_size_screenshot",
- createThree().apply {
- forEachIndexed { ix, it -> it.textSize = 20f + ix * 4f }
- }
+ createThree().apply { forEachIndexed { ix, it -> it.textSize = 20f + ix * 4f } }
)
}
@@ -192,16 +174,13 @@
fun testEllipsize() {
doOneTest(
"ellipsize_screenshot",
- (
- createThree() zip
+ (createThree() zip
listOf(
TextUtils.TruncateAt.START,
TextUtils.TruncateAt.MIDDLE,
TextUtils.TruncateAt.END
- )
- )
- .map
- { (v, e) ->
+ ))
+ .map { (v, e) ->
v.ellipsize = e
v.setSweepRangeDegrees(0f, 50f)
v.text += " but Longer"
@@ -218,8 +197,10 @@
createThree().apply {
forEachIndexed { ix, it ->
it.setPadding(
- ix * 10, ((ix + 1) % 4) * 10,
- ((ix + 2) % 4) * 10, ((ix + 3) % 4) * 10
+ ix * 10,
+ ((ix + 1) % 4) * 10,
+ ((ix + 2) % 4) * 10,
+ ((ix + 3) % 4) * 10
)
}
}
@@ -232,22 +213,20 @@
doOneTest(
"cw_text_background_screenshot",
listOf(
- CurvedTextView(ApplicationProvider.getApplicationContext())
- .apply {
- text = "This is a clockwise text for testing background"
- isClockwise = true
- anchorAngleDegrees = 170.0f
- anchorType = ArcLayout.ANCHOR_START
- setBackgroundColor(Color.rgb(0, 100, 100))
- },
- CurvedTextView(ApplicationProvider.getApplicationContext())
- .apply {
- text = "Another clockwise text"
- isClockwise = true
- anchorAngleDegrees = 70.0f
- anchorType = ArcLayout.ANCHOR_START
- setBackgroundColor(Color.rgb(0, 100, 100))
- }
+ CurvedTextView(ApplicationProvider.getApplicationContext()).apply {
+ text = "This is a clockwise text for testing background"
+ isClockwise = true
+ anchorAngleDegrees = 170.0f
+ anchorType = ArcLayout.ANCHOR_START
+ setBackgroundColor(Color.rgb(0, 100, 100))
+ },
+ CurvedTextView(ApplicationProvider.getApplicationContext()).apply {
+ text = "Another clockwise text"
+ isClockwise = true
+ anchorAngleDegrees = 70.0f
+ anchorType = ArcLayout.ANCHOR_START
+ setBackgroundColor(Color.rgb(0, 100, 100))
+ }
)
)
}
@@ -258,22 +237,20 @@
doOneTest(
"ccw_text_background_screenshot",
listOf(
- CurvedTextView(ApplicationProvider.getApplicationContext())
- .apply {
- text = "This is a counterclockwise text for testing background"
- isClockwise = false
- anchorAngleDegrees = 100.0f
- anchorType = ArcLayout.ANCHOR_START
- setBackgroundColor(Color.rgb(0, 100, 100))
- },
- CurvedTextView(ApplicationProvider.getApplicationContext())
- .apply {
- text = "Another counterclockwise text"
- isClockwise = false
- anchorAngleDegrees = 230.0f
- anchorType = ArcLayout.ANCHOR_START
- setBackgroundColor(Color.rgb(0, 100, 100))
- }
+ CurvedTextView(ApplicationProvider.getApplicationContext()).apply {
+ text = "This is a counterclockwise text for testing background"
+ isClockwise = false
+ anchorAngleDegrees = 100.0f
+ anchorType = ArcLayout.ANCHOR_START
+ setBackgroundColor(Color.rgb(0, 100, 100))
+ },
+ CurvedTextView(ApplicationProvider.getApplicationContext()).apply {
+ text = "Another counterclockwise text"
+ isClockwise = false
+ anchorAngleDegrees = 230.0f
+ anchorType = ArcLayout.ANCHOR_START
+ setBackgroundColor(Color.rgb(0, 100, 100))
+ }
)
)
}
@@ -283,27 +260,24 @@
doOneTest(
"styles_test",
listOf(
- CurvedTextView(ApplicationProvider.getApplicationContext())
- .apply {
- text = "Bold"
- anchorAngleDegrees = 0.0f
- anchorType = ArcLayout.ANCHOR_START
- setTypeface(null, Typeface.BOLD)
- },
- CurvedTextView(ApplicationProvider.getApplicationContext())
- .apply {
- text = "Italic"
- anchorAngleDegrees = 60.0f
- anchorType = ArcLayout.ANCHOR_START
- setTypeface(null, Typeface.ITALIC)
- },
- CurvedTextView(ApplicationProvider.getApplicationContext())
- .apply {
- text = "ItalicBold"
- anchorAngleDegrees = 120.0f
- anchorType = ArcLayout.ANCHOR_START
- setTypeface(null, Typeface.BOLD_ITALIC)
- },
+ CurvedTextView(ApplicationProvider.getApplicationContext()).apply {
+ text = "Bold"
+ anchorAngleDegrees = 0.0f
+ anchorType = ArcLayout.ANCHOR_START
+ setTypeface(null, Typeface.BOLD)
+ },
+ CurvedTextView(ApplicationProvider.getApplicationContext()).apply {
+ text = "Italic"
+ anchorAngleDegrees = 60.0f
+ anchorType = ArcLayout.ANCHOR_START
+ setTypeface(null, Typeface.ITALIC)
+ },
+ CurvedTextView(ApplicationProvider.getApplicationContext()).apply {
+ text = "ItalicBold"
+ anchorAngleDegrees = 120.0f
+ anchorType = ArcLayout.ANCHOR_START
+ setTypeface(null, Typeface.BOLD_ITALIC)
+ },
)
)
}
diff --git a/wear/wear/src/main/java/androidx/wear/ambient/AmbientLifecycleObserver.kt b/wear/wear/src/main/java/androidx/wear/ambient/AmbientLifecycleObserver.kt
index 8e9ec40..4f3254f 100644
--- a/wear/wear/src/main/java/androidx/wear/ambient/AmbientLifecycleObserver.kt
+++ b/wear/wear/src/main/java/androidx/wear/ambient/AmbientLifecycleObserver.kt
@@ -28,11 +28,10 @@
* In addition, the app needs to declare that it uses the [android.Manifest.permission.WAKE_LOCK]
* permission in its manifest.
*
- * The created [AmbientLifecycleObserver] can also be used to query whether the device is in
- * ambient mode.
+ * The created [AmbientLifecycleObserver] can also be used to query whether the device is in ambient
+ * mode.
*
* As an example of how to use this class, see the following example:
- *
* ```
* class MyActivity : ComponentActivity() {
* private val callbacks = object : AmbientLifecycleObserver.AmbientLifecycleCallback {
@@ -48,16 +47,15 @@
* }
* ```
*
- * If the observer is registered while the device is in ambient mode, the registered callback
- * will immediately receive a call to
- * [AmbientLifecycleObserver.AmbientLifecycleCallback.onEnterAmbient]. If the device is in active
- * mode, the callbacks will be registered, and `onEnterAmbient` will be called when the device next
- * enters ambient mode.
+ * If the observer is registered while the device is in ambient mode, the registered callback will
+ * immediately receive a call to [AmbientLifecycleObserver.AmbientLifecycleCallback.onEnterAmbient].
+ * If the device is in active mode, the callbacks will be registered, and `onEnterAmbient` will be
+ * called when the device next enters ambient mode.
*
* @param activity The activity that this observer is being attached to.
* @param callbackExecutor The executor to run the provided callbacks on.
* @param callbacks An instance of [AmbientLifecycleObserver.AmbientLifecycleCallback], used to
- * notify the observer about changes to the ambient state.
+ * notify the observer about changes to the ambient state.
*/
fun AmbientLifecycleObserver(
activity: Activity,
@@ -73,11 +71,10 @@
* In addition, the app needs to declare that it uses the [android.Manifest.permission.WAKE_LOCK]
* permission in its manifest.
*
- * The created [AmbientLifecycleObserver] can also be used to query whether the device is in
- * ambient mode.
+ * The created [AmbientLifecycleObserver] can also be used to query whether the device is in ambient
+ * mode.
*
* As an example of how to use this class, see the following example:
- *
* ```
* class MyActivity : ComponentActivity() {
* private val callbacks = object : AmbientLifecycleObserver.AmbientLifecycleCallback {
@@ -95,7 +92,7 @@
*
* @param activity The activity that this observer is being attached to.
* @param callbacks An instance of [AmbientLifecycleObserver.AmbientLifecycleCallback], used to
- * notify the observer about changes to the ambient state.
+ * notify the observer about changes to the ambient state.
*/
fun AmbientLifecycleObserver(
activity: Activity,
@@ -116,14 +113,14 @@
* [AmbientLifecycleCallback.onEnterAmbient].
*
* @param burnInProtectionRequired whether the ambient layout must implement burn-in protection.
- * When this property is set to true, views must be shifted around periodically in ambient
- * mode. To ensure that content isn't shifted off the screen, avoid placing content within
- * 10 pixels of the edge of the screen. Activities should also avoid solid white areas to
- * prevent pixel burn-in. Both of these requirements only apply in ambient mode, and only
- * when this property is set to true.
+ * When this property is set to true, views must be shifted around periodically in ambient
+ * mode. To ensure that content isn't shifted off the screen, avoid placing content within 10
+ * pixels of the edge of the screen. Activities should also avoid solid white areas to prevent
+ * pixel burn-in. Both of these requirements only apply in ambient mode, and only when this
+ * property is set to true.
* @param deviceHasLowBitAmbient whether this device has low-bit ambient mode. When this
- * property is set to true, the screen supports fewer bits for each color in ambient mode.
- * In this case, activities should disable anti-aliasing in ambient mode.
+ * property is set to true, the screen supports fewer bits for each color in ambient mode. In
+ * this case, activities should disable anti-aliasing in ambient mode.
*/
class AmbientDetails(
val burnInProtectionRequired: Boolean,
@@ -143,7 +140,7 @@
* lower-power mode.
*
* @param ambientDetails instance of [AmbientDetails] containing information about the
- * display being used.
+ * display being used.
*/
fun onEnterAmbient(ambientDetails: AmbientDetails) {}
@@ -160,8 +157,6 @@
fun onExitAmbient() {}
}
- /**
- * @return {@code true} if the activity is currently in ambient.
- */
+ /** @return {@code true} if the activity is currently in ambient. */
val isAmbient: Boolean
}
diff --git a/wear/wear/src/main/java/androidx/wear/ambient/AmbientLifecycleObserverImpl.kt b/wear/wear/src/main/java/androidx/wear/ambient/AmbientLifecycleObserverImpl.kt
index 29a29e2..afc26e7 100644
--- a/wear/wear/src/main/java/androidx/wear/ambient/AmbientLifecycleObserverImpl.kt
+++ b/wear/wear/src/main/java/androidx/wear/ambient/AmbientLifecycleObserverImpl.kt
@@ -34,7 +34,6 @@
* ambient mode.
*
* As an example of how to use this class, see the following example:
- *
* ```
* class MyActivity : ComponentActivity() {
* private val callback = object : AmbientLifecycleObserver.AmbientLifecycleCallback {
@@ -52,7 +51,7 @@
* @param activity The activity that this observer is being attached to.
* @param callbackExecutor The executor to run the provided callback on.
* @param callback An instance of [AmbientLifecycleObserver.AmbientLifecycleCallback], used to
- * notify the observer about changes to the ambient state.
+ * notify the observer about changes to the ambient state.
*/
@Suppress("CallbackName")
internal class AmbientLifecycleObserverImpl(
@@ -61,39 +60,42 @@
callback: AmbientLifecycleObserver.AmbientLifecycleCallback,
) : AmbientLifecycleObserver {
private val delegate: AmbientDelegate
- private val callbackTranslator = object : AmbientDelegate.AmbientCallback {
- override fun onEnterAmbient(ambientDetails: Bundle?) {
- val burnInProtection = ambientDetails?.getBoolean(
- WearableActivityController.EXTRA_BURN_IN_PROTECTION) ?: false
- val lowBitAmbient = ambientDetails?.getBoolean(
- WearableActivityController.EXTRA_LOWBIT_AMBIENT) ?: false
- callbackExecutor.run {
- callback.onEnterAmbient(AmbientLifecycleObserver.AmbientDetails(
- burnInProtectionRequired = burnInProtection,
- deviceHasLowBitAmbient = lowBitAmbient
- ))
+ private val callbackTranslator =
+ object : AmbientDelegate.AmbientCallback {
+ override fun onEnterAmbient(ambientDetails: Bundle?) {
+ val burnInProtection =
+ ambientDetails?.getBoolean(WearableActivityController.EXTRA_BURN_IN_PROTECTION)
+ ?: false
+ val lowBitAmbient =
+ ambientDetails?.getBoolean(WearableActivityController.EXTRA_LOWBIT_AMBIENT)
+ ?: false
+ callbackExecutor.run {
+ callback.onEnterAmbient(
+ AmbientLifecycleObserver.AmbientDetails(
+ burnInProtectionRequired = burnInProtection,
+ deviceHasLowBitAmbient = lowBitAmbient
+ )
+ )
+ }
}
- }
- override fun onUpdateAmbient() {
- callbackExecutor.run { callback.onUpdateAmbient() }
- }
+ override fun onUpdateAmbient() {
+ callbackExecutor.run { callback.onUpdateAmbient() }
+ }
- override fun onExitAmbient() {
- callbackExecutor.run { callback.onExitAmbient() }
- }
+ override fun onExitAmbient() {
+ callbackExecutor.run { callback.onExitAmbient() }
+ }
- override fun onAmbientOffloadInvalidated() {
+ override fun onAmbientOffloadInvalidated() {}
}
- }
/**
- * Construct a [AmbientLifecycleObserverImpl], using the UI thread to dispatch ambient
- * callback.
+ * Construct a [AmbientLifecycleObserverImpl], using the UI thread to dispatch ambient callback.
*
* @param activity The activity that this observer is being attached to.
* @param callback An instance of [AmbientLifecycleObserver.AmbientLifecycleCallback], used to
- * notify the observer about changes to the ambient state.
+ * notify the observer about changes to the ambient state.
*/
constructor(
activity: Activity,
diff --git a/wear/wear/src/test/java/androidx/wear/ambient/AmbientLifecycleObserverImplTest.kt b/wear/wear/src/test/java/androidx/wear/ambient/AmbientLifecycleObserverImplTest.kt
index 78617df..acb910c 100644
--- a/wear/wear/src/test/java/androidx/wear/ambient/AmbientLifecycleObserverImplTest.kt
+++ b/wear/wear/src/test/java/androidx/wear/ambient/AmbientLifecycleObserverImplTest.kt
@@ -34,8 +34,8 @@
@Before
fun setUp() {
- scenario = AmbientTestActivityUtil.launchActivity(
- AmbientLifecycleObserverTestActivity::class.java)
+ scenario =
+ AmbientTestActivityUtil.launchActivity(AmbientLifecycleObserverTestActivity::class.java)
}
private fun resetState(controller: WearableActivityController) {
diff --git a/wear/wear/src/test/java/androidx/wear/ambient/AmbientLifecycleObserverTestActivity.kt b/wear/wear/src/test/java/androidx/wear/ambient/AmbientLifecycleObserverTestActivity.kt
index e6a4ea6..98b5ee2 100644
--- a/wear/wear/src/test/java/androidx/wear/ambient/AmbientLifecycleObserverTestActivity.kt
+++ b/wear/wear/src/test/java/androidx/wear/ambient/AmbientLifecycleObserverTestActivity.kt
@@ -20,22 +20,21 @@
import androidx.activity.ComponentActivity
class AmbientLifecycleObserverTestActivity : ComponentActivity() {
- private val callback = object : AmbientLifecycleObserver.AmbientLifecycleCallback {
- override fun onEnterAmbient(
- ambientDetails: AmbientLifecycleObserver.AmbientDetails
- ) {
- enterAmbientCalled = true
- enterAmbientArgs = ambientDetails
- }
+ private val callback =
+ object : AmbientLifecycleObserver.AmbientLifecycleCallback {
+ override fun onEnterAmbient(ambientDetails: AmbientLifecycleObserver.AmbientDetails) {
+ enterAmbientCalled = true
+ enterAmbientArgs = ambientDetails
+ }
- override fun onUpdateAmbient() {
- updateAmbientCalled = true
- }
+ override fun onUpdateAmbient() {
+ updateAmbientCalled = true
+ }
- override fun onExitAmbient() {
- exitAmbientCalled = true
+ override fun onExitAmbient() {
+ exitAmbientCalled = true
+ }
}
- }
val observer = AmbientLifecycleObserver(this, { r -> r.run() }, callback)
diff --git a/wear/wear/src/test/java/androidx/wear/utils/WearUtilsTestRunner.kt b/wear/wear/src/test/java/androidx/wear/utils/WearUtilsTestRunner.kt
index 3c30025..d82b383 100644
--- a/wear/wear/src/test/java/androidx/wear/utils/WearUtilsTestRunner.kt
+++ b/wear/wear/src/test/java/androidx/wear/utils/WearUtilsTestRunner.kt
@@ -24,16 +24,13 @@
*
* It has instrumentation turned off for the [androidx.wear.utils] package.
*
- * Robolectric tries to instrument Kotlin classes, and it throws errors when it encounters
- * companion objects, constructors with default values for parameters, and data classes with
- * inline classes. We don't need shadowing of our classes because we want to use the actual
- * objects in our tests.
+ * Robolectric tries to instrument Kotlin classes, and it throws errors when it encounters companion
+ * objects, constructors with default values for parameters, and data classes with inline classes.
+ * We don't need shadowing of our classes because we want to use the actual objects in our tests.
*/
class WearUtilsTestRunner(testClass: Class<*>) : RobolectricTestRunner(testClass) {
override fun createClassLoaderConfig(method: FrameworkMethod): InstrumentationConfiguration =
- InstrumentationConfiguration.Builder(
- super.createClassLoaderConfig(method)
- )
+ InstrumentationConfiguration.Builder(super.createClassLoaderConfig(method))
.doNotInstrumentPackage("androidx.wear.utils")
.build()
}