Skip to content

Commit 718d8b3

Browse files
committed
Merge branch 'main' into validate-input
# Conflicts: # compose/snippets/src/main/java/com/example/compose/snippets/text/TextSnippets.kt
2 parents abb4277 + 5e2384b commit 718d8b3

File tree

15 files changed

+326
-75
lines changed

15 files changed

+326
-75
lines changed

build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ plugins {
55
alias(libs.plugins.android.application) apply false
66
alias(libs.plugins.android.library) apply false
77
alias(libs.plugins.kotlin.android) apply false
8-
alias(libs.plugins.kapt) apply false
8+
alias(libs.plugins.ksp) apply false
99
alias(libs.plugins.hilt) apply false
1010
alias(libs.plugins.kotlin.parcelize) apply false
1111
alias(libs.plugins.compose.compiler) apply false

compose/snippets/build.gradle.kts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
plugins {
1818
alias(libs.plugins.android.application)
1919
alias(libs.plugins.kotlin.android)
20-
alias(libs.plugins.kapt)
20+
alias(libs.plugins.ksp)
2121
alias(libs.plugins.hilt)
2222
alias(libs.plugins.kotlin.parcelize)
2323
alias(libs.plugins.compose.compiler)
@@ -146,7 +146,7 @@ dependencies {
146146
implementation(libs.hilt.android)
147147
implementation(libs.glide.compose)
148148

149-
kapt(libs.hilt.compiler)
149+
ksp(libs.hilt.compiler)
150150

151151
testImplementation(libs.junit)
152152

compose/snippets/src/main/java/com/example/compose/snippets/animations/AnimationSnippets.kt

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,9 @@ import androidx.compose.ui.unit.Dp
109109
import androidx.compose.ui.unit.IntSize
110110
import androidx.compose.ui.unit.dp
111111
import com.example.compose.snippets.R
112+
import java.text.BreakIterator
113+
import java.text.StringCharacterIterator
114+
import kotlinx.coroutines.delay
112115

113116
/*
114117
* Copyright 2023 The Android Open Source Project
@@ -820,3 +823,39 @@ private fun Expanded() {
820823
@Composable
821824
private fun ContentIcon() {
822825
}
826+
827+
// [START android_compose_animations_char_by_char]
828+
@Composable
829+
private fun AnimatedText() {
830+
val text = "This text animates as though it is being typed \uD83E\uDDDE\u200D\uFE0F \uD83D\uDD10 \uD83D\uDC69\u200D\uFE0F\u200D\uD83D\uDC68 \uD83D\uDC74\uD83C\uDFFD"
831+
832+
// Use BreakIterator as it correctly iterates over characters regardless of how they are
833+
// stored, for example, some emojis are made up of multiple characters.
834+
// You don't want to break up an emoji as it animates, so using BreakIterator will ensure
835+
// this is correctly handled!
836+
val breakIterator = remember(text) { BreakIterator.getCharacterInstance() }
837+
838+
// Define how many milliseconds between each character should pause for. This will create the
839+
// illusion of an animation, as we delay the job after each character is iterated on.
840+
val typingDelayInMs = 50L
841+
842+
var substringText by remember {
843+
mutableStateOf("")
844+
}
845+
LaunchedEffect(text) {
846+
// Initial start delay of the typing animation
847+
delay(1000)
848+
breakIterator.text = StringCharacterIterator(text)
849+
850+
var nextIndex = breakIterator.next()
851+
// Iterate over the string, by index boundary
852+
while (nextIndex != BreakIterator.DONE) {
853+
substringText = text.subSequence(0, nextIndex).toString()
854+
// Go to the next logical character boundary
855+
nextIndex = breakIterator.next()
856+
delay(typingDelayInMs)
857+
}
858+
}
859+
Text(substringText)
860+
// [END android_compose_animations_char_by_char]
861+
}

compose/snippets/src/main/java/com/example/compose/snippets/interop/ComposeWithOtherLibraries.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ private object StreamData {
162162
}
163163
}
164164

165-
private object HiltExample3 {
165+
object HiltExample3 {
166166
// [START android_compose_libraries_hilt_3]
167167
@HiltViewModel
168168
class MyViewModel @Inject constructor(
@@ -180,7 +180,7 @@ private object HiltExample3 {
180180
interface ExampleRepository
181181
}
182182

183-
private object HiltViewModel {
183+
object HiltViewModel {
184184
@HiltViewModel
185185
class MyViewModel @Inject constructor() : ViewModel() { /* ... */ }
186186
// [START android_compose_libraries_hilt_viewmodel]
@@ -207,7 +207,7 @@ private object HiltViewModel {
207207
}
208208
}
209209

210-
private object HiltViewModelBackStack {
210+
object HiltViewModelBackStack {
211211
@HiltViewModel
212212
class MyViewModel @Inject constructor() : ViewModel() { /* ... */ }
213213

@@ -273,7 +273,7 @@ private object MapsExample {
273273
cameraPositionState = cameraPositionState
274274
) {
275275
Marker(
276-
state = MarkerState(position = singapore),
276+
state = remember { MarkerState(position = singapore) },
277277
title = "Singapore",
278278
snippet = "Marker in Singapore"
279279
)

compose/snippets/src/main/java/com/example/compose/snippets/lists/LazyListSnippets.kt

Lines changed: 63 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import androidx.compose.animation.core.Spring
2323
import androidx.compose.animation.core.spring
2424
import androidx.compose.animation.core.tween
2525
import androidx.compose.foundation.ExperimentalFoundationApi
26+
import androidx.compose.foundation.border
2627
import androidx.compose.foundation.horizontalScroll
2728
import androidx.compose.foundation.layout.Arrangement
2829
import androidx.compose.foundation.layout.Box
@@ -33,11 +34,14 @@ import androidx.compose.foundation.layout.fillMaxSize
3334
import androidx.compose.foundation.layout.fillMaxWidth
3435
import androidx.compose.foundation.layout.height
3536
import androidx.compose.foundation.layout.size
37+
import androidx.compose.foundation.layout.width
3638
import androidx.compose.foundation.layout.wrapContentHeight
39+
import androidx.compose.foundation.layout.wrapContentSize
3740
import androidx.compose.foundation.lazy.LazyColumn
3841
import androidx.compose.foundation.lazy.LazyRow
3942
import androidx.compose.foundation.lazy.grid.GridCells
4043
import androidx.compose.foundation.lazy.grid.GridItemSpan
44+
import androidx.compose.foundation.lazy.grid.LazyHorizontalGrid
4145
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
4246
import androidx.compose.foundation.lazy.grid.items
4347
import androidx.compose.foundation.lazy.items
@@ -47,6 +51,7 @@ import androidx.compose.foundation.lazy.staggeredgrid.StaggeredGridCells
4751
import androidx.compose.foundation.lazy.staggeredgrid.items
4852
import androidx.compose.foundation.rememberScrollState
4953
import androidx.compose.foundation.verticalScroll
54+
import androidx.compose.material3.Button
5055
import androidx.compose.material3.Text
5156
import androidx.compose.runtime.Composable
5257
import androidx.compose.runtime.LaunchedEffect
@@ -57,6 +62,7 @@ import androidx.compose.runtime.rememberCoroutineScope
5762
import androidx.compose.runtime.saveable.rememberSaveable
5863
import androidx.compose.runtime.snapshotFlow
5964
import androidx.compose.ui.Modifier
65+
import androidx.compose.ui.graphics.Color
6066
import androidx.compose.ui.layout.ContentScale
6167
import androidx.compose.ui.tooling.preview.Preview
6268
import androidx.compose.ui.unit.Density
@@ -644,7 +650,9 @@ fun LazyStaggeredGridSnippet() {
644650
model = photo,
645651
contentScale = ContentScale.Crop,
646652
contentDescription = null,
647-
modifier = Modifier.fillMaxWidth().wrapContentHeight()
653+
modifier = Modifier
654+
.fillMaxWidth()
655+
.wrapContentHeight()
648656
)
649657
}
650658
},
@@ -666,7 +674,9 @@ fun LazyStaggeredGridSnippetFixed() {
666674
model = photo,
667675
contentScale = ContentScale.Crop,
668676
contentDescription = null,
669-
modifier = Modifier.fillMaxWidth().wrapContentHeight()
677+
modifier = Modifier
678+
.fillMaxWidth()
679+
.wrapContentHeight()
670680
)
671681
}
672682
},
@@ -742,3 +752,54 @@ private val randomSizedPhotos = listOf(
742752
randomSampleImageUrl(width = 1600, height = 900),
743753
randomSampleImageUrl(width = 500, height = 500),
744754
)
755+
756+
// [START android_compose_lists_snap_scroll_button]
757+
@Composable
758+
fun MessageList(modifier: Modifier = Modifier) {
759+
val listState = rememberLazyListState()
760+
val coroutineScope = rememberCoroutineScope()
761+
762+
LazyColumn(state = listState, modifier = Modifier.height(120.dp)) {
763+
items(10) { index ->
764+
Text(
765+
modifier = Modifier.height(40.dp),
766+
text = "Item $index"
767+
)
768+
}
769+
}
770+
771+
Button(onClick = {
772+
coroutineScope.launch {
773+
listState.animateScrollToItem(index = 0)
774+
}
775+
}) {
776+
Text(text = "Go top")
777+
}
778+
}
779+
// [END android_compose_lists_snap_scroll_button]
780+
781+
// [START android_compose_layout_scrollable_grid]
782+
@Composable
783+
fun ScrollingGrid() {
784+
val itemsList = (0..15).toList()
785+
786+
val itemModifier = Modifier
787+
.border(1.dp, Color.Blue)
788+
.width(80.dp)
789+
.wrapContentSize()
790+
791+
LazyHorizontalGrid(
792+
rows = GridCells.Fixed(3),
793+
horizontalArrangement = Arrangement.spacedBy(16.dp),
794+
verticalArrangement = Arrangement.spacedBy(16.dp)
795+
) {
796+
items(itemsList) {
797+
Text("Item is $it", itemModifier)
798+
}
799+
800+
item {
801+
Text("Single item", itemModifier)
802+
}
803+
}
804+
}
805+
// [END android_compose_layout_scrollable_grid]
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
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.lists
18+
19+
import android.provider.MediaStore
20+
import androidx.compose.foundation.lazy.LazyColumn
21+
import androidx.compose.runtime.Composable
22+
import org.w3c.dom.Text
23+
24+
// [START android_compose_lists_multiple_item_types]
25+
@Composable
26+
fun ListWithMultipleItems(messages: List<Any>) {
27+
LazyColumn {
28+
items(
29+
messages.size,
30+
contentType = { it }
31+
) {
32+
for (message in messages)
33+
when (message) {
34+
is MediaStore.Audio -> AudioMessage(message)
35+
is Text -> TextMessage(message)
36+
}
37+
}
38+
}
39+
}
40+
41+
@Composable
42+
fun AudioMessage(message: MediaStore.Audio) {
43+
TODO("Not yet implemented.")
44+
}
45+
46+
@Composable
47+
fun TextMessage(message: Text) {
48+
TODO("Not yet implemented.")
49+
}
50+
51+
data class SampleMessage(val text: String, val content: Any)
52+
// [END android_compose_lists_multiple_item_types]
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
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.lists
18+
19+
import androidx.compose.foundation.layout.size
20+
import androidx.compose.foundation.lazy.LazyColumn
21+
import androidx.compose.foundation.lazy.LazyRow
22+
import androidx.compose.material3.Text
23+
import androidx.compose.runtime.Composable
24+
import androidx.compose.ui.Modifier
25+
import androidx.compose.ui.unit.dp
26+
import coil.compose.AsyncImage
27+
28+
// [START android_compose_layouts_nested_scrolling]
29+
@Composable
30+
fun NestedScrollingRowsList(urls: List<String>) {
31+
LazyColumn {
32+
items(10) {
33+
LazyRow {
34+
item { Text("Row: $it") }
35+
items(urls.size) { index ->
36+
// AsyncImage provided by Coil.
37+
AsyncImage(
38+
model = urls[index],
39+
modifier = Modifier.size(150.dp),
40+
contentDescription = null
41+
)
42+
}
43+
}
44+
}
45+
}
46+
}
47+
// [END android_compose_layouts_nested_scrolling]

compose/snippets/src/main/java/com/example/compose/snippets/mentalmodel/ThinkingInComposeSnippets.kt

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import androidx.compose.foundation.layout.Row
2525
import androidx.compose.foundation.lazy.LazyColumn
2626
import androidx.compose.foundation.lazy.items
2727
import androidx.compose.material3.Button
28+
import androidx.compose.material3.Card
2829
import androidx.compose.material3.Checkbox
2930
import androidx.compose.material3.HorizontalDivider
3031
import androidx.compose.material3.MaterialTheme
@@ -108,15 +109,16 @@ fun ListComposable(myList: List<String>) {
108109

109110
// [START android_compose_thinking_in_compose_incorrect]
110111
@Composable
111-
@Deprecated("Example with bug")
112112
fun ListWithBug(myList: List<String>) {
113113
var items = 0
114114

115115
Row(horizontalArrangement = Arrangement.SpaceBetween) {
116116
Column {
117117
for (item in myList) {
118-
Text("Item: $item")
119-
items++ // Avoid! Side-effect of the column recomposing.
118+
Card {
119+
Text("Item: $item")
120+
items++ // Avoid! Side-effect of the column recomposing.
121+
}
120122
}
121123
}
122124
Text("Count: $items")

compose/snippets/src/main/java/com/example/compose/snippets/sideeffects/SideEffectsSnippets.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -180,18 +180,18 @@ fun rememberFirebaseAnalytics(user: User): FirebaseAnalytics {
180180
}
181181
// [END android_compose_side_effects_sideeffect]
182182

183+
// b/368420773
184+
@Suppress("ProduceStateDoesNotAssignValue")
183185
// [START android_compose_side_effects_producestate]
184186
@Composable
185187
fun loadNetworkImage(
186188
url: String,
187189
imageRepository: ImageRepository = ImageRepository()
188190
): State<Result<Image>> {
189-
190191
// Creates a State<T> with Result.Loading as initial value
191192
// If either `url` or `imageRepository` changes, the running producer
192193
// will cancel and will be re-launched with the new inputs.
193194
return produceState<Result<Image>>(initialValue = Result.Loading, url, imageRepository) {
194-
195195
// In a coroutine, can make suspend calls
196196
val image = imageRepository.load(url)
197197

0 commit comments

Comments
 (0)