From aa4609503f75dfd4833018be9b6e6441857e47c7 Mon Sep 17 00:00:00 2001 From: Roy Chou Date: Thu, 9 Oct 2025 06:13:39 +0000 Subject: [PATCH 1/5] feat(scalable content): add code snippets Refer to go/ptz-compose-snippets-wip we put the code onto github then we can use them for new DAC page. --- .../accessibility/ScalableContentSnippets.kt | 178 ++++++++++++++++++ 1 file changed, 178 insertions(+) create mode 100644 compose/snippets/src/main/java/com/example/compose/snippets/accessibility/ScalableContentSnippets.kt diff --git a/compose/snippets/src/main/java/com/example/compose/snippets/accessibility/ScalableContentSnippets.kt b/compose/snippets/src/main/java/com/example/compose/snippets/accessibility/ScalableContentSnippets.kt new file mode 100644 index 000000000..57799a306 --- /dev/null +++ b/compose/snippets/src/main/java/com/example/compose/snippets/accessibility/ScalableContentSnippets.kt @@ -0,0 +1,178 @@ +package com.example.compose.snippets.accessibility + +import androidx.compose.foundation.background +import androidx.compose.foundation.gestures.TransformableState +import androidx.compose.foundation.gestures.transformable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Person +import androidx.compose.material3.Card +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Switch +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableFloatStateOf +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.Density +import androidx.compose.ui.unit.dp + +// [START android_compose_accessibility_scalable_content_density_scaling] +private class DensityScalingState( + private val minScale: Float = 1f, + private val maxScale: Float = 3f, + private val currentDensity: Density +) { + val transformableState = TransformableState { zoomChange, _, _ -> + scaleFactor.floatValue = + (scaleFactor.floatValue * zoomChange).coerceIn(minScale, maxScale) + } + val scaleFactor = mutableFloatStateOf(1f) + fun scaledDensity(): Density { + return Density( + currentDensity.density * scaleFactor.floatValue, + currentDensity.fontScale + ) + } +} + +// [START_EXCLUDE silent] +@Preview +// [END_EXCLUDE silent] +@Composable +fun DensityScalingSample() { + val currentDensity = LocalDensity.current + val scaleState = + remember(currentDensity) { DensityScalingState(currentDensity = currentDensity) } + + Box( + modifier = Modifier + .fillMaxSize() + .transformable(state = scaleState.transformableState), + contentAlignment = Alignment.TopCenter + ) { + CompositionLocalProvider( + LocalDensity provides scaleState.scaledDensity() + ) { + DemoCard() + } + } +} +// [END android_compose_accessibility_scalable_content_density_scaling] + +// [START android_compose_accessibility_scalable_content_font_scaling] +class FontScaleState( + private val minScale: Float = 1f, + private val maxScale: Float = 3f, + private val currentDensity: Density +) { + val transformableState = TransformableState { zoomChange, _, _ -> + scaleFactor.floatValue = + (scaleFactor.floatValue * zoomChange).coerceIn(minScale, maxScale) + } + val scaleFactor = mutableFloatStateOf(1f) + fun scaledFont(): Density { + return Density( + currentDensity.density, + currentDensity.fontScale * scaleFactor.floatValue + ) + } +} + +// [START_EXCLUDE silent] +@Preview +// [END_EXCLUDE silent] +@Composable +fun FontScalingSample() { + val currentDensity = LocalDensity.current + val scaleState = remember { FontScaleState(currentDensity = currentDensity) } + + Box( + modifier = Modifier + .fillMaxSize() + .transformable(state = scaleState.transformableState), + contentAlignment = Alignment.TopCenter + ) { + CompositionLocalProvider( + LocalDensity provides scaleState.scaledFont() + ) { + DemoCard() + } + } +} +// [END android_compose_accessibility_scalable_content_font_scaling] + +// [START android_compose_accessibility_scalable_content_demo_card] +@Composable +private fun DemoCard() { + Card( + modifier = Modifier + .width(360.dp) + .padding(16.dp), + shape = RoundedCornerShape(12.dp) + ) { + Column( + modifier = Modifier.padding(16.dp), + verticalArrangement = Arrangement.spacedBy(16.dp) + ) { + Text("Demo Card", style = MaterialTheme.typography.headlineMedium) + var isChecked by remember { mutableStateOf(true) } + Row(verticalAlignment = Alignment.CenterVertically) { + Text("Demo Switch", Modifier.weight(1f), style = MaterialTheme.typography.bodyLarge) + Switch(checked = isChecked, onCheckedChange = { isChecked = it }) + } + Row(verticalAlignment = Alignment.CenterVertically) { + Icon(Icons.Filled.Person, "Icon", Modifier.size(32.dp)) + Spacer(Modifier.width(8.dp)) + Text("Demo Icon", style = MaterialTheme.typography.bodyLarge) + } + Row( + Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceBetween + ) { + Box( + Modifier + .width(100.dp) + .weight(1f) + .height(80.dp) + .background(Color.Blue) + ) + Box( + Modifier + .width(100.dp) + .weight(1f) + .height(80.dp) + .background(Color.Red) + ) + } + Text( + "Demo Text: Lorem ipsum dolor sit amet, consectetur adipiscing elit," + + " sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.", + style = MaterialTheme.typography.bodyMedium, + textAlign = TextAlign.Justify + ) + } + } +} +// [END android_compose_accessibility_scalable_content_demo_card] \ No newline at end of file From f335fdf8c200b64cfa81c0ba77d95bb06bc17b93 Mon Sep 17 00:00:00 2001 From: Christopher Cartland Date: Fri, 17 Oct 2025 16:50:38 -0600 Subject: [PATCH 2/5] Remove project code style configuration (#661) --- .gitignore | 7 +- .idea/codeStyles/Project.xml | 129 ----------------------------------- 2 files changed, 1 insertion(+), 135 deletions(-) delete mode 100644 .idea/codeStyles/Project.xml diff --git a/.gitignore b/.gitignore index b984a9c26..7b190dc83 100644 --- a/.gitignore +++ b/.gitignore @@ -1,16 +1,11 @@ *.iml .gradle /local.properties -/.idea/caches/build_file_checksums.ser -/.idea/libraries -/.idea/modules.xml -/.idea/workspace.xml +.idea/ .DS_Store build /captures .externalNativeBuild -.idea/* -/.idea/* .kotlin ### Xcode ### diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml deleted file mode 100644 index af8871a7b..000000000 --- a/.idea/codeStyles/Project.xml +++ /dev/null @@ -1,129 +0,0 @@ - - - - - - - -
- - - - xmlns:android - - ^$ - - - -
-
- - - - xmlns:.* - - ^$ - - - BY_NAME - -
-
- - - - .*:id - - http://schemas.android.com/apk/res/android - - - -
-
- - - - .*:name - - http://schemas.android.com/apk/res/android - - - -
-
- - - - name - - ^$ - - - -
-
- - - - style - - ^$ - - - -
-
- - - - .* - - ^$ - - - BY_NAME - -
-
- - - - .* - - http://schemas.android.com/apk/res/android - - - ANDROID_ATTRIBUTE_ORDER - -
-
- - - - .* - - .* - - - BY_NAME - -
-
-
-
-
-
From b15e1d861a9ae949bd80c5bb847f56d3b34a8f57 Mon Sep 17 00:00:00 2001 From: Roy Chou Date: Thu, 9 Oct 2025 06:13:39 +0000 Subject: [PATCH 3/5] feat(scalable content): add code snippets Refer to go/ptz-compose-snippets-wip we put the code onto github then we can use them for new DAC page. --- .../snippets/accessibility/ScalableContentSnippets.kt | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/compose/snippets/src/main/java/com/example/compose/snippets/accessibility/ScalableContentSnippets.kt b/compose/snippets/src/main/java/com/example/compose/snippets/accessibility/ScalableContentSnippets.kt index 57799a306..99391bfd4 100644 --- a/compose/snippets/src/main/java/com/example/compose/snippets/accessibility/ScalableContentSnippets.kt +++ b/compose/snippets/src/main/java/com/example/compose/snippets/accessibility/ScalableContentSnippets.kt @@ -40,8 +40,9 @@ import androidx.compose.ui.unit.dp // [START android_compose_accessibility_scalable_content_density_scaling] private class DensityScalingState( - private val minScale: Float = 1f, - private val maxScale: Float = 3f, + // Note: For accessibility, typical min/max values are ~0.75x and ~3.5x. + private val minScale: Float = 0.75f, + private val maxScale: Float = 3.5f, private val currentDensity: Density ) { val transformableState = TransformableState { zoomChange, _, _ -> @@ -83,8 +84,9 @@ fun DensityScalingSample() { // [START android_compose_accessibility_scalable_content_font_scaling] class FontScaleState( - private val minScale: Float = 1f, - private val maxScale: Float = 3f, + // Note: For accessibility, typical min/max values are ~0.75x and ~3.5x. + private val minScale: Float = 0.75f, + private val maxScale: Float = 3.5f, private val currentDensity: Density ) { val transformableState = TransformableState { zoomChange, _, _ -> From 3ce0035a63aba806467e93b9384801ce5e2cc1bc Mon Sep 17 00:00:00 2001 From: compose-devrel-github-bot <118755852+compose-devrel-github-bot@users.noreply.github.com> Date: Mon, 27 Oct 2025 16:24:11 +0000 Subject: [PATCH 4/5] =?UTF-8?q?=F0=9F=A4=96=20Update=20Dependencies=20(#67?= =?UTF-8?q?5)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- gradle/libs.versions.toml | 42 +++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 2fc556ece..5724109e1 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -5,9 +5,9 @@ android-googleid = "1.1.1" androidGradlePlugin = "8.13.0" androidx-activity-compose = "1.11.0" androidx-appcompat = "1.7.0" -androidx-compose-bom = "2025.10.00" +androidx-compose-bom = "2025.10.01" androidx-compose-ui-test = "1.7.0-alpha08" -androidx-compose-ui-test-junit4-accessibility = "1.10.0-alpha05" +androidx-compose-ui-test-junit4-accessibility = "1.10.0-beta01" androidx-constraintlayout = "2.2.1" androidx-constraintlayout-compose = "1.1.1" androidx-coordinator-layout = "1.3.0" @@ -36,8 +36,8 @@ appcompat = "1.7.1" coil = "2.7.0" # @keep compileSdk = "36" -compose-latest = "1.9.3" -composeUiTooling = "1.5.3" +compose-latest = "1.9.4" +composeUiTooling = "1.5.4" coreSplashscreen = "1.0.1" coroutines = "1.10.2" firebase-bom = "34.4.0" @@ -45,29 +45,29 @@ glide = "1.0.0-beta08" google-maps = "19.2.0" gradle-versions = "0.53.0" guava = "33.5.0-jre" -guava-android = "31.0.1-android" -reactive-streams = "1.0.4" +guava-android = "33.5.0-jre" hilt = "2.57.2" horologist = "0.8.2-alpha" junit = "4.13.2" -kotlin = "2.2.20" +kotlin = "2.2.21" kotlinCoroutinesOkhttp = "1.0" kotlinxCoroutinesGuava = "1.10.2" kotlinxSerializationJson = "1.9.0" -ksp = "2.2.20-2.0.4" +ksp = "2.3.0" ktlint = "1.5.0" lifecycleService = "2.9.4" maps-compose = "6.12.1" -material = "1.14.0-alpha05" -material3-adaptive = "1.1.0" +material = "1.14.0-alpha06" +material3-adaptive = "1.2.0" material3-adaptive-navigation-suite = "1.4.0" media3 = "1.8.0" media3Ui = "1.8.0" # @keep minSdk = "35" -okHttp = "5.2.0" +okHttp = "5.2.1" playServicesWearable = "19.0.0" protolayout = "1.3.0" +reactive-streams = "1.0.4" recyclerview = "1.4.0" spotless = "8.0.0" targetSdk = "36" @@ -77,13 +77,13 @@ validatorPush = "1.0.0-alpha08" version-catalog-update = "1.0.1" watchfaceComplicationsDataSourceKtx = "1.2.1" wear = "1.3.0" -wearComposeFoundation = "1.5.3" -wearComposeMaterial = "1.5.3" -wearComposeMaterial3 = "1.5.3" +wearComposeFoundation = "1.5.4" +wearComposeMaterial = "1.5.4" +wearComposeMaterial3 = "1.5.4" +wearInput = "1.2.0" wearOngoing = "1.1.0" wearToolingPreview = "1.0.0" webkit = "1.14.0" -wearInput = "1.2.0" [libraries] accompanist-adaptive = "com.google.accompanist:accompanist-adaptive:0.37.3" @@ -133,7 +133,7 @@ androidx-glance-appwidget = { module = "androidx.glance:glance-appwidget", versi androidx-glance-appwidget-testing = { module = "androidx.glance:glance-appwidget-testing", version.ref = "androidx-glance-appwidget" } androidx-glance-material3 = { module = "androidx.glance:glance-material3", version.ref = "androidx-glance-appwidget" } androidx-glance-testing = { module = "androidx.glance:glance-testing", version.ref = "androidx-glance-appwidget" } -androidx-graphics-shapes = "androidx.graphics:graphics-shapes:1.0.1" +androidx-graphics-shapes = "androidx.graphics:graphics-shapes:1.1.0" androidx-hilt-navigation-compose = { module = "androidx.hilt:hilt-navigation-compose", version.ref = "androidxHiltNavigationCompose" } androidx-lifecycle-runtime = { module = "androidx.lifecycle:lifecycle-runtime-ktx", version.ref = "androidx-lifecycle-runtime-compose" } androidx-lifecycle-runtime-compose = { module = "androidx.lifecycle:lifecycle-runtime-compose", version.ref = "androidx-lifecycle-runtime-compose" } @@ -165,13 +165,14 @@ androidx-tiles-tooling-preview = { module = "androidx.wear.tiles:tiles-tooling-p androidx-tracing = { module = "androidx.tracing:tracing", version.ref = "tracing" } androidx-watchface-complications-data-source-ktx = { module = "androidx.wear.watchface:watchface-complications-data-source-ktx", version.ref = "watchfaceComplicationsDataSourceKtx" } androidx-wear = { module = "androidx.wear:wear", version.ref = "wear" } +androidx-wear-input = { module = "androidx.wear:wear-input", version.ref = "wearInput" } androidx-wear-ongoing = { module = "androidx.wear:wear-ongoing", version.ref = "wearOngoing" } androidx-wear-tooling-preview = { module = "androidx.wear:wear-tooling-preview", version.ref = "wearToolingPreview" } androidx-webkit = { module = "androidx.webkit:webkit", version.ref = "webkit" } androidx-window = { module = "androidx.window:window", version.ref = "androidx-window" } androidx-window-core = { module = "androidx.window:window-core", version.ref = "androidx-window-core" } androidx-window-java = { module = "androidx.window:window-java", version.ref = "androidx-window-java" } -androidx-work-runtime-ktx = "androidx.work:work-runtime-ktx:2.10.5" +androidx-work-runtime-ktx = "androidx.work:work-runtime-ktx:2.11.0" androidx-xr-arcore = { module = "androidx.xr.arcore:arcore", version.ref = "androidx-xr-arcore" } androidx-xr-compose = { module = "androidx.xr.compose:compose", version.ref = "androidx-xr-compose" } androidx-xr-scenecore = { module = "androidx.xr.scenecore:scenecore", version.ref = "androidx-xr-scenecore" } @@ -179,15 +180,14 @@ appcompat = { module = "androidx.appcompat:appcompat", version.ref = "appcompat" coil-kt-compose = { module = "io.coil-kt:coil-compose", version.ref = "coil" } compose-foundation = { module = "androidx.wear.compose:compose-foundation", version.ref = "wearComposeFoundation" } compose-ui-tooling = { module = "androidx.wear.compose:compose-ui-tooling", version.ref = "composeUiTooling" } -firebase-bom = { module = "com.google.firebase:firebase-bom", version.ref = "firebase-bom" } firebase-ai = { module = "com.google.firebase:firebase-ai" } +firebase-bom = { module = "com.google.firebase:firebase-bom", version.ref = "firebase-bom" } glide-compose = { module = "com.github.bumptech.glide:compose", version.ref = "glide" } google-android-material = { module = "com.google.android.material:material", version.ref = "material" } googlemaps-compose = { module = "com.google.maps.android:maps-compose", version.ref = "maps-compose" } googlemaps-maps = { module = "com.google.android.gms:play-services-maps", version.ref = "google-maps" } guava = { module = "com.google.guava:guava", version.ref = "guava" } guava-android = { module = "com.google.guava:guava", version.ref = "guava-android" } -reactive-streams = { module = "org.reactivestreams:reactive-streams", version.ref = "reactive-streams" } hilt-android = { module = "com.google.dagger:hilt-android", version.ref = "hilt" } hilt-compiler = { module = "com.google.dagger:hilt-android-compiler", version.ref = "hilt" } horologist-compose-layout = { module = "com.google.android.horologist:horologist-compose-layout", version.ref = "horologist" } @@ -203,10 +203,10 @@ kotlinx-coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-t kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinxSerializationJson" } okhttp = { module = "com.squareup.okhttp3:okhttp", version.ref = "okHttp" } play-services-wearable = { module = "com.google.android.gms:play-services-wearable", version.ref = "playServicesWearable" } +reactive-streams = { module = "org.reactivestreams:reactive-streams", version.ref = "reactive-streams" } validator-push = { module = "com.google.android.wearable.watchface.validator:validator-push", version.ref = "validatorPush" } wear-compose-material = { module = "androidx.wear.compose:compose-material", version.ref = "wearComposeMaterial" } wear-compose-material3 = { module = "androidx.wear.compose:compose-material3", version.ref = "wearComposeMaterial3" } -androidx-wear-input = { group = "androidx.wear", name = "wear-input", version.ref = "wearInput" } [plugins] android-application = { id = "com.android.application", version.ref = "androidGradlePlugin" } @@ -216,7 +216,7 @@ android-lint = { id = "com.android.lint", version.ref = "androidGradlePlugin" } compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" } gradle-versions = { id = "com.github.ben-manes.versions", version.ref = "gradle-versions" } hilt = { id = "com.google.dagger.hilt.android", version.ref = "hilt" } -kotlin-android = "org.jetbrains.kotlin.android:2.2.20" +kotlin-android = "org.jetbrains.kotlin.android:2.2.21" kotlin-multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" } kotlin-parcelize = { id = "org.jetbrains.kotlin.plugin.parcelize", version.ref = "kotlin" } kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" } From abfa1e97da0d1705180717b7bcbd49a3936090dc Mon Sep 17 00:00:00 2001 From: Roy Chou Date: Thu, 9 Oct 2025 06:13:39 +0000 Subject: [PATCH 5/5] feat(scalable content): add code snippets Refer to go/ptz-compose-snippets-wip we put the code onto github then we can use them for new DAC page. --- .../accessibility/ScalableContentSnippets.kt | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/compose/snippets/src/main/java/com/example/compose/snippets/accessibility/ScalableContentSnippets.kt b/compose/snippets/src/main/java/com/example/compose/snippets/accessibility/ScalableContentSnippets.kt index 99391bfd4..c929995b4 100644 --- a/compose/snippets/src/main/java/com/example/compose/snippets/accessibility/ScalableContentSnippets.kt +++ b/compose/snippets/src/main/java/com/example/compose/snippets/accessibility/ScalableContentSnippets.kt @@ -1,3 +1,19 @@ +/* + * Copyright 2025 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package com.example.compose.snippets.accessibility import androidx.compose.foundation.background