16
16
17
17
package com.example.compose.snippets.components
18
18
19
+ import androidx.compose.foundation.ExperimentalFoundationApi
20
+ import androidx.compose.foundation.combinedClickable
21
+ import androidx.compose.foundation.interaction.MutableInteractionSource
19
22
import androidx.compose.foundation.layout.Arrangement
23
+ import androidx.compose.foundation.layout.Box
20
24
import androidx.compose.foundation.layout.Column
21
25
import androidx.compose.foundation.layout.PaddingValues
22
26
import androidx.compose.foundation.layout.fillMaxSize
23
27
import androidx.compose.foundation.layout.padding
24
28
import androidx.compose.foundation.lazy.LazyColumn
29
+ import androidx.compose.foundation.lazy.itemsIndexed
25
30
import androidx.compose.material.icons.Icons
26
31
import androidx.compose.material.icons.automirrored.filled.ArrowBack
27
32
import androidx.compose.material.icons.filled.Add
@@ -30,6 +35,7 @@ import androidx.compose.material.icons.filled.Edit
30
35
import androidx.compose.material.icons.filled.Image
31
36
import androidx.compose.material.icons.filled.Menu
32
37
import androidx.compose.material.icons.filled.Mic
38
+ import androidx.compose.material.icons.filled.Share
33
39
import androidx.compose.material3.BottomAppBar
34
40
import androidx.compose.material3.BottomAppBarDefaults
35
41
import androidx.compose.material3.Button
@@ -40,6 +46,7 @@ import androidx.compose.material3.FloatingActionButtonDefaults
40
46
import androidx.compose.material3.Icon
41
47
import androidx.compose.material3.IconButton
42
48
import androidx.compose.material3.LargeTopAppBar
49
+ import androidx.compose.material3.ListItem
43
50
import androidx.compose.material3.MaterialTheme
44
51
import androidx.compose.material3.MediumTopAppBar
45
52
import androidx.compose.material3.Scaffold
@@ -52,6 +59,7 @@ import androidx.compose.runtime.Composable
52
59
import androidx.compose.runtime.getValue
53
60
import androidx.compose.runtime.mutableStateOf
54
61
import androidx.compose.runtime.remember
62
+ import androidx.compose.runtime.saveable.rememberSaveable
55
63
import androidx.compose.runtime.setValue
56
64
import androidx.compose.ui.Modifier
57
65
import androidx.compose.ui.input.nestedscroll.nestedScroll
@@ -76,13 +84,15 @@ fun AppBarExamples(
76
84
" topBarMedium" -> MediumTopAppBarExample ()
77
85
" topBarLarge" -> LargeTopAppBarExample ()
78
86
" topBarNavigation" -> TopBarNavigationExample { navigateBack() }
87
+ " multiSelection" -> AppBarMultiSelectionExample ()
79
88
else -> AppBarOptions (
80
89
toBottom = { selection = " bottomBar" },
81
90
toTopBarSmall = { selection = " topBar" },
82
91
toTopBarCenter = { selection = " topBarCenter" },
83
92
toTopBarMedium = { selection = " topBarMedium" },
84
93
toTopBarLarge = { selection = " topBarLarge" },
85
94
toTopBarNavigation = { selection = " topBarNavigation" },
95
+ toMultiSelection = { selection = " multiSelection" },
86
96
)
87
97
}
88
98
}
@@ -96,6 +106,7 @@ fun AppBarOptions(
96
106
toTopBarMedium : () -> Unit ,
97
107
toTopBarLarge : () -> Unit ,
98
108
toTopBarNavigation : () -> Unit ,
109
+ toMultiSelection : () -> Unit ,
99
110
) {
100
111
Column () {
101
112
Button ({ toBottom() }) {
@@ -116,6 +127,9 @@ fun AppBarOptions(
116
127
Button ({ toTopBarNavigation() }) {
117
128
Text (" Top bar navigation example" )
118
129
}
130
+ Button ({ toMultiSelection() }) {
131
+ Text (" Top bar with multi selection list" )
132
+ }
119
133
}
120
134
}
121
135
@@ -382,3 +396,156 @@ fun ScrollContent(innerPadding: PaddingValues) {
382
396
}
383
397
}
384
398
}
399
+
400
+ @OptIn(ExperimentalMaterial3Api ::class )
401
+ // [START android_compose_components_appbarselectionactions]
402
+ @Composable
403
+ fun AppBarSelectionActions (
404
+ selectedItems : Set <Int >,
405
+ modifier : Modifier = Modifier ,
406
+ ) {
407
+ val hasSelection = selectedItems.isNotEmpty()
408
+ val topBarText = if (hasSelection) {
409
+ " Selected ${selectedItems.size} items"
410
+ } else {
411
+ " List of items"
412
+ }
413
+
414
+ TopAppBar (
415
+ title = {
416
+ Text (topBarText)
417
+ },
418
+ colors = TopAppBarDefaults .topAppBarColors(
419
+ containerColor = MaterialTheme .colorScheme.primaryContainer,
420
+ titleContentColor = MaterialTheme .colorScheme.primary,
421
+ ),
422
+ actions = {
423
+ if (hasSelection) {
424
+ IconButton (onClick = {
425
+ /* click action */
426
+ }) {
427
+ Icon (
428
+ imageVector = Icons .Filled .Share ,
429
+ contentDescription = " Share items"
430
+ )
431
+ }
432
+ }
433
+ },
434
+ )
435
+ }
436
+ // [END android_compose_components_appbarselectionactions]
437
+
438
+ @Preview
439
+ @Composable
440
+ private fun AppBarSelectionActionsPreview () {
441
+ val selectedItems = setOf (1 , 2 , 3 )
442
+
443
+ AppBarSelectionActions (selectedItems)
444
+ }
445
+
446
+ @OptIn(ExperimentalFoundationApi ::class )
447
+ @Preview
448
+ // [START android_compose_components_appbarmultiselectionexample]
449
+ @Composable
450
+ private fun AppBarMultiSelectionExample (
451
+ modifier : Modifier = Modifier ,
452
+ ) {
453
+ val listItems by remember { mutableStateOf(listOf (1 , 2 , 3 , 4 , 5 , 6 )) }
454
+ var selectedItems by rememberSaveable { mutableStateOf(setOf<Int >()) }
455
+
456
+ Scaffold (
457
+ topBar = { AppBarSelectionActions (selectedItems) }
458
+ ) { innerPadding ->
459
+ LazyColumn (contentPadding = innerPadding) {
460
+ itemsIndexed(listItems) { _, index ->
461
+ val isItemSelected = selectedItems.contains(index)
462
+ ListItemSelectable (
463
+ selected = isItemSelected,
464
+ Modifier
465
+ .combinedClickable(
466
+ interactionSource = remember { MutableInteractionSource () },
467
+ indication = null ,
468
+ onClick = {
469
+ /* click action */
470
+ },
471
+ onLongClick = {
472
+ if (isItemSelected) selectedItems - = index else selectedItems + = index
473
+ }
474
+ )
475
+ )
476
+ }
477
+ }
478
+ }
479
+ }
480
+ // [END android_compose_components_appbarmultiselectionexample]
481
+
482
+ // [START android_compose_components_listitemselectable]
483
+ @Composable
484
+ fun ListItemSelectable (
485
+ selected : Boolean ,
486
+ modifier : Modifier = Modifier
487
+ ) {
488
+ Box (modifier = modifier) {
489
+ ListItem (
490
+ headlineContent = { Text (" Long press to select or deselect item" ) },
491
+ leadingContent = {
492
+ if (selected) {
493
+ Icon (
494
+ Icons .Filled .Check ,
495
+ contentDescription = " Localized description" ,
496
+ )
497
+ }
498
+ }
499
+ )
500
+ }
501
+ }
502
+ // [END android_compose_components_listitemselectable]
503
+
504
+ @Preview
505
+ @Composable
506
+ private fun ListItemSelectablePreview () {
507
+ ListItemSelectable (true )
508
+ }
509
+
510
+ @OptIn(ExperimentalFoundationApi ::class )
511
+ // [START android_compose_components_lazylistmultiselection
512
+ @Composable
513
+ fun LazyListMultiSelection (
514
+ listItems : List <Int >,
515
+ modifier : Modifier = Modifier ,
516
+ contentPadding : PaddingValues = PaddingValues (0.dp),
517
+ ) {
518
+ var selectedItems by rememberSaveable { mutableStateOf(setOf<Int >()) }
519
+
520
+ LazyColumn (contentPadding = contentPadding) {
521
+ itemsIndexed(listItems) { _, index ->
522
+ val selected = selectedItems.contains(index)
523
+ ListItemSelectable (
524
+ selected = selected,
525
+ Modifier
526
+ .combinedClickable(
527
+ interactionSource = remember { MutableInteractionSource () },
528
+ indication = null ,
529
+ onClick = {
530
+ /* click action */
531
+ },
532
+ onLongClick = {
533
+ if (selected) selectedItems - = index else selectedItems + = index
534
+ }
535
+ )
536
+ )
537
+ }
538
+ }
539
+ }
540
+ // [END android_compose_components_lazylistmultiselection
541
+
542
+ @Preview
543
+ @Composable
544
+ private fun LazyListMultiSelectionPreview () {
545
+ val listItems = listOf (1 , 2 , 3 )
546
+
547
+ LazyListMultiSelection (
548
+ listItems,
549
+ modifier = Modifier
550
+ )
551
+ }
0 commit comments