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