1 /*
<lambda>null2 * Copyright 2023 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 * http://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 @file:Suppress("DEPRECATION")
18
19 package androidx.compose.foundation.layout.samples
20
21 import androidx.annotation.Sampled
22 import androidx.compose.foundation.background
23 import androidx.compose.foundation.clickable
24 import androidx.compose.foundation.layout.Arrangement
25 import androidx.compose.foundation.layout.Box
26 import androidx.compose.foundation.layout.ContextualFlowRow
27 import androidx.compose.foundation.layout.ContextualFlowRowOverflow
28 import androidx.compose.foundation.layout.ContextualFlowRowOverflowScope
29 import androidx.compose.foundation.layout.ExperimentalLayoutApi
30 import androidx.compose.foundation.layout.fillMaxWidth
31 import androidx.compose.foundation.layout.height
32 import androidx.compose.foundation.layout.padding
33 import androidx.compose.foundation.layout.width
34 import androidx.compose.foundation.layout.wrapContentHeight
35 import androidx.compose.foundation.layout.wrapContentWidth
36 import androidx.compose.material.Text
37 import androidx.compose.runtime.Composable
38 import androidx.compose.runtime.getValue
39 import androidx.compose.runtime.mutableStateOf
40 import androidx.compose.runtime.remember
41 import androidx.compose.runtime.setValue
42 import androidx.compose.ui.Alignment
43 import androidx.compose.ui.Modifier
44 import androidx.compose.ui.graphics.Color
45 import androidx.compose.ui.text.font.FontWeight
46 import androidx.compose.ui.unit.dp
47 import androidx.compose.ui.unit.sp
48 import kotlin.random.Random
49
50 @OptIn(ExperimentalLayoutApi::class)
51 @Sampled
52 @Composable
53 fun ContextualFlowRowMaxLineDynamicSeeMore() {
54 val totalCount = 300
55 var maxLines by remember { mutableStateOf(2) }
56
57 Text(
58 modifier =
59 Modifier.fillMaxWidth(1f).padding(20.dp).wrapContentHeight(align = Alignment.Top),
60 text =
61 "ContextualFlowRow (based on Subcompose)" +
62 " is great for Large Items & +N dynamic labels",
63 fontWeight = FontWeight.Bold
64 )
65 val moreOrCollapseIndicator =
66 @Composable { scope: ContextualFlowRowOverflowScope ->
67 val remainingItems = totalCount - scope.shownItemCount
68 DynamicSeeMore(isHorizontal = true, remainingItems = remainingItems) {
69 if (remainingItems == 0) {
70 maxLines = 2
71 } else {
72 maxLines += 5
73 }
74 }
75 }
76 ContextualFlowRow(
77 modifier =
78 Modifier.fillMaxWidth(1f).padding(20.dp).wrapContentHeight(align = Alignment.Top),
79 horizontalArrangement = Arrangement.spacedBy(10.dp),
80 verticalArrangement = Arrangement.spacedBy(20.dp),
81 maxLines = maxLines,
82 overflow =
83 ContextualFlowRowOverflow.expandOrCollapseIndicator(
84 minRowsToShowCollapse = 4,
85 expandIndicator = moreOrCollapseIndicator,
86 collapseIndicator = moreOrCollapseIndicator
87 ),
88 itemCount = totalCount
89 ) {
90 Box(
91 Modifier.align(Alignment.CenterVertically)
92 .width(50.dp)
93 .height(50.dp)
94 .background(Color.Green)
95 ) {
96 Text(
97 text = it.toString(),
98 fontSize = 18.sp,
99 modifier = Modifier.padding(3.dp).align(Alignment.Center)
100 )
101 }
102 }
103 }
104
105 @OptIn(ExperimentalLayoutApi::class)
106 @Sampled
107 @Composable
ContextualFlowRow_ItemPositionnull108 fun ContextualFlowRow_ItemPosition() {
109 Text("Ln: Line No\nPs: Position No. in Line", modifier = Modifier.padding(20.dp))
110 ContextualFlowRow(
111 modifier = Modifier.fillMaxWidth(1f).height(210.dp).padding(20.dp),
112 horizontalArrangement = Arrangement.spacedBy(10.dp),
113 verticalArrangement = Arrangement.spacedBy(20.dp),
114 maxItemsInEachRow = 4,
115 itemCount = 12
116 ) {
117 val width = Random.nextInt(80, 100).dp.coerceAtMost(maxWidthInLine)
118 val height = 50.dp.coerceAtMost(maxHeight)
119 Box(
120 Modifier.width(width)
121 .height(height)
122 .background(MatchingColors.getByIndex(indexInLine)!!.color)
123 ) {
124 Text(
125 text =
126 "Ln: ${this@ContextualFlowRow.lineIndex}" +
127 "\nPs: ${this@ContextualFlowRow.indexInLine}",
128 fontSize = 18.sp,
129 modifier = Modifier.padding(3.dp)
130 )
131 }
132 }
133 }
134
135 enum class MatchingColors(val index: Int, val color: Color) {
136 ZERO(0, Color.Green),
137 ONE(1, Color.Yellow),
138 TWO(2, Color.Blue),
139 THREE(3, Color.Cyan);
140
141 companion object {
getByIndexnull142 fun getByIndex(index: Int): MatchingColors? {
143 return values().firstOrNull { it.index == index }
144 }
145 }
146 }
147
148 @Composable
DynamicSeeMorenull149 internal fun DynamicSeeMore(isHorizontal: Boolean, remainingItems: Int, onClick: () -> Unit) {
150 Box(
151 Modifier.clickable(onClick = onClick)
152 .wrapContentWidth()
153 .height(50.dp)
154 .background(Color.Green)
155 ) {
156 val collapseText = if (isHorizontal) "^" else "<"
157 Text(
158 modifier = Modifier.align(Alignment.Center).padding(3.dp),
159 text = if (remainingItems == 0) collapseText else "+$remainingItems",
160 fontSize = 18.sp
161 )
162 }
163 }
164