Skip to content

Commit 5cfd757

Browse files
authored
Merge branch 'main' into trambui/pb-snippets-edits
2 parents d328a5d + 0d07b08 commit 5cfd757

File tree

61 files changed

+1334
-170
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+1334
-170
lines changed

.github/workflows/apply_spotless.yml

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,13 @@ jobs:
4444
- name: Run spotlessApply
4545
run: ./gradlew :compose:spotlessApply --init-script gradle/init.gradle.kts --no-configuration-cache --stacktrace
4646

47+
- name: Run spotlessApply for Wear
48+
run: ./gradlew :wear:spotlessApply --init-script gradle/init.gradle.kts --no-configuration-cache --stacktrace
49+
50+
- name: Run spotlessApply for Misc
51+
run: ./gradlew :misc:spotlessApply --init-script gradle/init.gradle.kts --no-configuration-cache --stacktrace
52+
4753
- name: Auto-commit if spotlessApply has changes
4854
uses: stefanzweifel/git-auto-commit-action@v5
4955
with:
50-
commit_message: Apply Spotless
51-
52-
- name: Run spotlessApply for Wear
53-
run: ./gradlew :wear:spotlessApply --init-script gradle/init.gradle.kts --no-configuration-cache --stacktrace
56+
commit_message: Apply Spotless

.github/workflows/build.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,3 +45,5 @@ jobs:
4545
run: ./gradlew :kotlin:build
4646
- name: Build Wear snippets
4747
run: ./gradlew :wear:build
48+
- name: Build misc snippets
49+
run: ./gradlew :misc:build
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/*
2+
* Copyright 2024 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.example.compose.snippets.components
18+
19+
import androidx.compose.foundation.layout.Column
20+
import androidx.compose.foundation.layout.Row
21+
import androidx.compose.foundation.layout.fillMaxWidth
22+
import androidx.compose.foundation.layout.height
23+
import androidx.compose.foundation.layout.padding
24+
import androidx.compose.foundation.selection.selectable
25+
import androidx.compose.foundation.selection.selectableGroup
26+
import androidx.compose.material3.MaterialTheme
27+
import androidx.compose.material3.RadioButton
28+
import androidx.compose.material3.Text
29+
import androidx.compose.runtime.Composable
30+
import androidx.compose.runtime.mutableStateOf
31+
import androidx.compose.runtime.remember
32+
import androidx.compose.ui.Alignment
33+
import androidx.compose.ui.Modifier
34+
import androidx.compose.ui.semantics.Role
35+
import androidx.compose.ui.tooling.preview.Preview
36+
import androidx.compose.ui.unit.dp
37+
38+
// [START android_compose_components_radiobuttonsingleselection]
39+
@Composable
40+
fun RadioButtonSingleSelection(modifier: Modifier = Modifier) {
41+
val radioOptions = listOf("Calls", "Missed", "Friends")
42+
val (selectedOption, onOptionSelected) = remember { mutableStateOf(radioOptions[0]) }
43+
// Note that Modifier.selectableGroup() is essential to ensure correct accessibility behavior
44+
Column(modifier.selectableGroup()) {
45+
radioOptions.forEach { text ->
46+
Row(
47+
Modifier
48+
.fillMaxWidth()
49+
.height(56.dp)
50+
.selectable(
51+
selected = (text == selectedOption),
52+
onClick = { onOptionSelected(text) },
53+
role = Role.RadioButton
54+
)
55+
.padding(horizontal = 16.dp),
56+
verticalAlignment = Alignment.CenterVertically
57+
) {
58+
RadioButton(
59+
selected = (text == selectedOption),
60+
onClick = null // null recommended for accessibility with screen readers
61+
)
62+
Text(
63+
text = text,
64+
style = MaterialTheme.typography.bodyLarge,
65+
modifier = Modifier.padding(start = 16.dp)
66+
)
67+
}
68+
}
69+
}
70+
}
71+
// [END android_compose_components_radiobuttonsingleselection]
72+
73+
@Preview
74+
@Composable
75+
private fun RadioButtonSingleSelectionPreview() {
76+
RadioButtonSingleSelection()
77+
}

compose/snippets/src/main/java/com/example/compose/snippets/layouts/PagerSnippets.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,7 @@ fun PagerIndicator() {
413413
}
414414
}
415415

416+
// [START android_compose_autoadvancepager]
416417
@Composable
417418
fun AutoAdvancePager(pageItems: List<Color>, modifier: Modifier = Modifier) {
418419
Box(modifier = Modifier.fillMaxSize()) {
@@ -457,6 +458,7 @@ fun AutoAdvancePager(pageItems: List<Color>, modifier: Modifier = Modifier) {
457458
PagerIndicator(pageItems.size, pagerState.currentPage)
458459
}
459460
}
461+
// [END android_compose_autoadvancepager]
460462

461463
@Preview
462464
@Composable
@@ -470,6 +472,7 @@ private fun AutoAdvancePagerPreview() {
470472
AutoAdvancePager(pageItems = pageItems)
471473
}
472474

475+
// [START android_compose_pagerindicator]
473476
@Composable
474477
fun PagerIndicator(pageCount: Int, currentPageIndex: Int, modifier: Modifier = Modifier) {
475478
Box(modifier = Modifier.fillMaxSize()) {
@@ -494,6 +497,7 @@ fun PagerIndicator(pageCount: Int, currentPageIndex: Int, modifier: Modifier = M
494497
}
495498
}
496499
}
500+
// [END android_compose_pagerindicator]
497501

498502
@Preview
499503
@Composable
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
/*
2+
* Copyright 2024 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.example.compose.snippets.text
18+
19+
import androidx.compose.foundation.layout.Column
20+
import androidx.compose.foundation.layout.fillMaxSize
21+
import androidx.compose.foundation.layout.fillMaxWidth
22+
import androidx.compose.foundation.layout.padding
23+
import androidx.compose.foundation.lazy.LazyColumn
24+
import androidx.compose.material3.ListItem
25+
import androidx.compose.material3.OutlinedTextField
26+
import androidx.compose.material3.Text
27+
import androidx.compose.runtime.Composable
28+
import androidx.compose.runtime.getValue
29+
import androidx.compose.runtime.mutableStateOf
30+
import androidx.compose.runtime.saveable.rememberSaveable
31+
import androidx.compose.runtime.setValue
32+
import androidx.compose.ui.Modifier
33+
import androidx.compose.ui.tooling.preview.Preview
34+
import androidx.compose.ui.unit.dp
35+
import androidx.lifecycle.ViewModel
36+
import androidx.lifecycle.compose.collectAsStateWithLifecycle
37+
import androidx.lifecycle.viewmodel.compose.viewModel
38+
import kotlinx.coroutines.flow.MutableStateFlow
39+
import kotlinx.coroutines.flow.StateFlow
40+
41+
// [START android_compose_text_filtertextviewmodel]
42+
class FilterTextViewModel : ViewModel() {
43+
private val items = listOf(
44+
"Cupcake",
45+
"Donut",
46+
"Eclair",
47+
"Froyo",
48+
"Gingerbread",
49+
"Honeycomb",
50+
"Ice Cream Sandwich"
51+
)
52+
53+
private val _filteredItems = MutableStateFlow(items)
54+
var filteredItems: StateFlow<List<String>> = _filteredItems
55+
56+
fun filterText(input: String) {
57+
// This filter returns the full items list when input is an empty string.
58+
_filteredItems.value = items.filter { it.contains(input, ignoreCase = true) }
59+
}
60+
}
61+
// [END android_compose_text_filtertextviewmodel]
62+
63+
// [START android_compose_text_filtertextview]
64+
@Composable
65+
fun FilterTextView(modifier: Modifier = Modifier, viewModel: FilterTextViewModel = viewModel()) {
66+
val filteredItems by viewModel.filteredItems.collectAsStateWithLifecycle()
67+
var text by rememberSaveable { mutableStateOf("") }
68+
69+
Column(
70+
modifier = Modifier
71+
.fillMaxSize()
72+
.padding(all = 10.dp)
73+
) {
74+
OutlinedTextField(
75+
value = text,
76+
onValueChange = {
77+
text = it
78+
viewModel.filterText(text)
79+
},
80+
label = { Text("Filter Text") },
81+
modifier = Modifier.fillMaxWidth()
82+
)
83+
84+
LazyColumn {
85+
items(
86+
count = filteredItems.size,
87+
key = { index -> filteredItems[index] }
88+
) {
89+
ListItem(
90+
headlineContent = { Text(filteredItems[it]) },
91+
modifier = Modifier
92+
.fillParentMaxWidth()
93+
.padding(10.dp)
94+
)
95+
}
96+
}
97+
}
98+
}
99+
// [END android_compose_text_filtertextview]
100+
101+
@Preview(showBackground = true)
102+
@Composable
103+
private fun FilterTextViewPreview() {
104+
FilterTextView()
105+
}

gradle/libs.versions.toml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ coroutines = "1.9.0"
3030
glide = "1.0.0-beta01"
3131
google-maps = "19.0.0"
3232
gradle-versions = "0.51.0"
33+
guava = "33.2.1-android"
3334
hilt = "2.52"
3435
horologist = "0.6.20"
3536
junit = "4.13.2"
@@ -44,12 +45,22 @@ media3 = "1.4.1"
4445
# @keep
4546
minSdk = "21"
4647
playServicesWearable = "18.2.0"
48+
protolayout = "1.3.0-alpha04"
49+
protolayoutExpression = "1.3.0-alpha04"
50+
protolayoutMaterial = "1.3.0-alpha04"
4751
recyclerview = "1.3.2"
4852
# @keep
4953
targetSdk = "34"
54+
tiles = "1.5.0-alpha04"
55+
tilesRenderer = "1.5.0-alpha04"
56+
tilesTesting = "1.5.0-alpha04"
57+
tilesTooling = "1.5.0-alpha04"
58+
tilesToolingPreview = "1.5.0-alpha04"
5059
version-catalog-update = "0.8.5"
60+
wear = "1.3.0"
5161
wearComposeFoundation = "1.4.0"
5262
wearComposeMaterial = "1.4.0"
63+
wearToolingPreview = "1.0.0"
5364

5465
[libraries]
5566
accompanist-adaptive = { module = "com.google.accompanist:accompanist-adaptive", version.ref = "accompanist" }
@@ -103,10 +114,20 @@ androidx-media3-common = { module = "androidx.media3:media3-common", version.ref
103114
androidx-media3-exoplayer = { module = "androidx.media3:media3-exoplayer", version.ref = "media3" }
104115
androidx-navigation-compose = { module = "androidx.navigation:navigation-compose", version.ref = "androidx-navigation" }
105116
androidx-paging-compose = { module = "androidx.paging:paging-compose", version.ref = "androidx-paging" }
117+
androidx-protolayout = { module = "androidx.wear.protolayout:protolayout", version.ref = "protolayout" }
118+
androidx-protolayout-expression = { module = "androidx.wear.protolayout:protolayout-expression", version.ref = "protolayoutExpression" }
119+
androidx-protolayout-material = { module = "androidx.wear.protolayout:protolayout-material", version.ref = "protolayoutMaterial" }
106120
androidx-recyclerview = { module = "androidx.recyclerview:recyclerview", version.ref = "recyclerview" }
107121
androidx-test-core = { module = "androidx.test:core", version.ref = "androidx-test" }
108122
androidx-test-espresso-core = { module = "androidx.test.espresso:espresso-core", version.ref = "androidx-test-espresso" }
109123
androidx-test-runner = "androidx.test:runner:1.6.2"
124+
androidx-tiles = { module = "androidx.wear.tiles:tiles", version.ref = "tiles" }
125+
androidx-tiles-renderer = { module = "androidx.wear.tiles:tiles-renderer", version.ref = "tilesRenderer" }
126+
androidx-tiles-testing = { module = "androidx.wear.tiles:tiles-testing", version.ref = "tilesTesting" }
127+
androidx-tiles-tooling = { module = "androidx.wear.tiles:tiles-tooling", version.ref = "tilesTooling" }
128+
androidx-tiles-tooling-preview = { module = "androidx.wear.tiles:tiles-tooling-preview", version.ref = "tilesToolingPreview" }
129+
androidx-wear = { module = "androidx.wear:wear", version.ref = "wear" }
130+
androidx-wear-tooling-preview = { module = "androidx.wear:wear-tooling-preview", version.ref = "wearToolingPreview" }
110131
androidx-window-core = { module = "androidx.window:window-core", version.ref = "androidx-window" }
111132
androidx-work-runtime-ktx = "androidx.work:work-runtime-ktx:2.10.0"
112133
coil-kt-compose = { module = "io.coil-kt:coil-compose", version.ref = "coil" }
@@ -117,6 +138,7 @@ glide-compose = { module = "com.github.bumptech.glide:compose", version.ref = "g
117138
google-android-material = { module = "com.google.android.material:material", version.ref = "material" }
118139
googlemaps-compose = { module = "com.google.maps.android:maps-compose", version.ref = "maps-compose" }
119140
googlemaps-maps = { module = "com.google.android.gms:play-services-maps", version.ref = "google-maps" }
141+
guava = { module = "com.google.guava:guava", version.ref = "guava" }
120142
hilt-android = { module = "com.google.dagger:hilt-android", version.ref = "hilt" }
121143
hilt-compiler = { module = "com.google.dagger:hilt-android-compiler", version.ref = "hilt" }
122144
horologist-compose-layout = { module = "com.google.android.horologist:horologist-compose-layout", version.ref = "horologist" }

misc/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/build

misc/build.gradle.kts

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
plugins {
2+
alias(libs.plugins.android.application)
3+
alias(libs.plugins.kotlin.android)
4+
alias(libs.plugins.ksp)
5+
alias(libs.plugins.hilt)
6+
alias(libs.plugins.compose.compiler)
7+
}
8+
9+
android {
10+
compileSdk = libs.versions.compileSdk.get().toInt()
11+
namespace = "com.example.snippets"
12+
13+
defaultConfig {
14+
applicationId = "com.example.snippets"
15+
minSdk = libs.versions.minSdk.get().toInt()
16+
targetSdk = libs.versions.targetSdk.get().toInt()
17+
versionCode = 1
18+
versionName = "1.0"
19+
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
20+
}
21+
22+
kotlin {
23+
jvmToolchain(17)
24+
}
25+
26+
buildTypes {
27+
getByName("debug") {
28+
signingConfig = signingConfigs.getByName("debug")
29+
}
30+
31+
getByName("release") {
32+
isMinifyEnabled = false
33+
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"),
34+
"proguard-rules.pro")
35+
}
36+
}
37+
compileOptions {
38+
sourceCompatibility = JavaVersion.VERSION_17
39+
targetCompatibility = JavaVersion.VERSION_17
40+
}
41+
buildFeatures {
42+
compose = true
43+
// Disable unused AGP features
44+
viewBinding = true
45+
}
46+
47+
}
48+
dependencies {
49+
val composeBom = platform(libs.androidx.compose.bom)
50+
implementation(composeBom)
51+
androidTestImplementation(composeBom)
52+
implementation(libs.androidx.core.ktx)
53+
implementation(libs.androidx.activity.compose)
54+
implementation(libs.androidx.compose.runtime)
55+
implementation(libs.androidx.compose.foundation)
56+
implementation(libs.androidx.compose.foundation.layout)
57+
implementation(libs.androidx.compose.ui.util)
58+
implementation(libs.androidx.compose.ui.tooling.preview)
59+
implementation(libs.androidx.compose.material3)
60+
61+
implementation(libs.hilt.android)
62+
implementation(libs.androidx.hilt.navigation.compose)
63+
implementation(libs.kotlinx.serialization.json)
64+
ksp(libs.hilt.compiler)
65+
66+
implementation(libs.androidx.lifecycle.runtime)
67+
testImplementation(libs.junit)
68+
androidTestImplementation(libs.junit)
69+
androidTestImplementation(libs.androidx.test.core)
70+
androidTestImplementation(libs.androidx.test.runner)
71+
androidTestImplementation(libs.androidx.test.espresso.core)
72+
}
File renamed without changes.

0 commit comments

Comments
 (0)