Skip to content

Commit 713e7f2

Browse files
1. Added more tag display property
2. Code refactoring 3. Bug fixes [more tag position issue]
1 parent 62bdb8c commit 713e7f2

File tree

4 files changed

+178
-111
lines changed

4 files changed

+178
-111
lines changed

core/ui/src/main/java/co/yml/coreui/core/ui/ytag/TagViewContainer.kt

Lines changed: 134 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,12 @@ import androidx.compose.ui.graphics.Color
1313
import androidx.compose.ui.layout.Layout
1414
import androidx.compose.ui.layout.Placeable
1515
import androidx.compose.ui.platform.LocalContext
16+
import androidx.compose.ui.platform.LocalDensity
1617
import androidx.compose.ui.platform.testTag
1718
import androidx.compose.ui.semantics.contentDescription
1819
import androidx.compose.ui.semantics.semantics
1920
import androidx.compose.ui.tooling.preview.Preview
20-
import androidx.compose.ui.unit.Dp
21-
import androidx.compose.ui.unit.IntOffset
22-
import androidx.compose.ui.unit.dp
21+
import androidx.compose.ui.unit.*
2322
import co.yml.coreui.core.ui.ytag.model.TagViewContainerModifiers
2423
import co.yml.coreui.core.ui.ytag.model.TagViewData
2524
import co.yml.coreui.core.ui.ytag.model.TagViewModifiers
@@ -41,38 +40,48 @@ fun TagViewContainer(
4140
updatedTagViewData.add(moreTag)
4241

4342
with(tagViewContainerModifiers) {
44-
val modifier = Modifier
4543
val context = LocalContext.current
44+
var modifier = if (tagViewContainerModifiers.width != Dp.Unspecified) {
45+
Modifier.width(tagViewContainerModifiers.width)
46+
} else {
47+
Modifier.wrapContentWidth()
48+
}
49+
50+
modifier = if (tagViewContainerModifiers.height != Dp.Unspecified) {
51+
modifier.then(Modifier.height(tagViewContainerModifiers.height))
52+
} else {
53+
modifier.then(Modifier.wrapContentHeight())
54+
}
55+
56+
modifier = modifier.then(Modifier
57+
.run {
58+
if (enableBorder) {
59+
border(
60+
width = borderWidth,
61+
color = borderColor,
62+
shape = shape
63+
)
64+
} else {
65+
background(color = backgroundColor, shape = shape)
66+
}
67+
}
68+
.defaultMinSize(minWidth, minHeight)
69+
.clickable { }
70+
.semantics {
71+
this.contentDescription =
72+
context.getString(co.yml.coreui.ui.R.string.tag_view_container_accessibility_title)
73+
}
74+
.testTag("tag_view_container")
75+
.background(
76+
color = backgroundColor,
77+
shape = shape
78+
)
79+
.padding(containerPaddingValues)
80+
)
81+
4682
Box(
4783
modifier = modifier
48-
.run {
49-
if (enableBorder) {
50-
border(
51-
width = borderWidth,
52-
color = borderColor,
53-
shape = shape
54-
)
55-
} else {
56-
background(color = backgroundColor, shape = shape)
57-
}
58-
}
59-
.width(width = width ?: Dp.Unspecified)
60-
.height(height = height)
61-
.defaultMinSize(minWidth = minWidth, minHeight = minHeight)
62-
.clickable { }
63-
.semantics {
64-
this.contentDescription =
65-
context.getString(co.yml.coreui.ui.R.string.tag_view_container_accessibility_title)
66-
}
67-
.testTag("tag_view_container")
68-
.background(
69-
color = backgroundColor,
70-
shape = shape
71-
)
72-
.padding(containerPaddingValues)
7384
) {
74-
75-
7685
TagViewContainerLayout(
7786
tagViewContainerModifiers = tagViewContainerModifiers,
7887
content = {
@@ -107,6 +116,8 @@ fun TagViewContainerLayout(
107116
tagViewContainerModifiers: TagViewContainerModifiers,
108117
content: @Composable () -> Unit
109118
) {
119+
val localDensity = LocalDensity.current
120+
110121
Layout(content = content) { measurables, constraints ->
111122
val looseConstraints = constraints.copy(
112123
minWidth = 0,
@@ -138,8 +149,6 @@ fun TagViewContainerLayout(
138149
.toInt()
139150
)
140151
}
141-
Log.i("check_measure", "common: ${currentOffset}")
142-
143152
placeAble to currentOffset.also {
144153
currentOffset = it.copy(
145154
x = it.x + placeAble.width + tagViewContainerModifiers.tagSpacingHorizontal.toPx()
@@ -148,34 +157,25 @@ fun TagViewContainerLayout(
148157
}
149158
}
150159

151-
layout(width = constraints.maxWidth,
152-
height = placeAbles.lastOrNull()?.run { first.height } ?: 0) {
160+
layout(
161+
width = constraints.maxWidth,
162+
height = constraints.maxHeight
163+
) {
153164
Log.i("check_placeAble", "size: ${placeAbles.size}")
154165
placeAbles.forEachIndexed { index, placeable ->
155166
val (placeable, offset) = placeable
156167
//check whether current item has enough space
157-
val currentItemHorizontalSpace =
158-
placeable.width + tagViewContainerModifiers.tagSpacingHorizontal.toPx()
159-
.toInt()
160-
val currentItemVerticalSpace =
161-
placeable.height + tagViewContainerModifiers.tagSpacingVertical.toPx()
162-
.toInt()
163-
164-
if (offset.x + currentItemHorizontalSpace < constraints.maxWidth && offset.y + currentItemVerticalSpace < constraints.maxHeight) {
168+
if (offset.x + placeable.width < constraints.maxWidth && offset.y + placeable.height < constraints.maxHeight) {
165169
//current item has space
166170
Log.i("check_placeable", "index: $index current item has space")
167171
val nextItemIndex = index + 1
168172
if (nextItemIndex <= placeAbles.lastIndex) {
169173
val nextItemOffset = placeAbles[nextItemIndex].second
170-
171-
val nextItemHorizontalSpace =
172-
placeAbles[nextItemIndex].first.width + tagViewContainerModifiers.tagSpacingHorizontal.toPx()
173-
.toInt()
174-
val nextItemVerticalSpace =
175-
placeAbles[nextItemIndex].first.height + tagViewContainerModifiers.tagSpacingVertical.toPx()
176-
.toInt()
177-
178-
if (nextItemOffset.x + nextItemHorizontalSpace < constraints.maxWidth && nextItemOffset.y + nextItemVerticalSpace < constraints.maxHeight) {
174+
Log.i(
175+
"check_placeable",
176+
"next index: $nextItemIndex nextItemOffset : $nextItemOffset Before checking"
177+
)
178+
if (nextItemOffset.x + placeAbles[nextItemIndex].first.width < constraints.maxWidth && nextItemOffset.y + placeAbles[nextItemIndex].first.height < constraints.maxHeight) {
179179
//next item has space
180180
Log.i(
181181
"check_placeable",
@@ -185,54 +185,99 @@ fun TagViewContainerLayout(
185185
} else {
186186
//next item has no space
187187
//check space to accommodate more tag
188-
Log.i("check_placeable", "index: $index next item has no space")
189-
val moreTagPlaceAble = placeAbles.last()
190-
val remainingTags = placeAbles.lastIndex - 1 - index
191-
192-
193-
// tagViewContainerModifiers.moreTagConfiguration.overFlowText.invoke(remainingTags)
194-
val moreTagHorizontalSpace =
195-
moreTagPlaceAble.first.width + tagViewContainerModifiers.tagSpacingHorizontal.toPx()
196-
.toInt()
197-
val moreTagVerticalSpace =
198-
moreTagPlaceAble.first.height + tagViewContainerModifiers.tagSpacingVertical.toPx()
199-
.toInt()
200-
201-
if (offset.x + moreTagHorizontalSpace < constraints.maxWidth && offset.y + moreTagVerticalSpace < constraints.maxHeight) {
202-
//place more tag
203-
Log.i("check_placeable", "index: $index more tag placed")
204-
moreTagPlaceAble.first.place(offset.x, offset.y)
205-
return@layout
206-
} else {
207-
Log.i("check_placeable", "index: $index more tag has no space")
188+
val overflow = showOverFlow(
189+
index,
190+
placeAbles,
191+
tagViewContainerModifiers,
192+
constraints,
193+
localDensity
194+
)
195+
overflow?.let {
196+
it.first.place(it.second)
208197
}
198+
return@layout
209199
}
210200
}
211201
} else {
212202
//current item has no space
213203
//check space to accommodate more tag
214-
Log.i("check_placeable", "index: $index current item has no space")
215-
val remainingTags = placeAbles.lastIndex - 1 - index
216-
val moreTagPlaceAble = placeAbles.last()
217-
val moreTagHorizontalSpace =
218-
moreTagPlaceAble.first.width + tagViewContainerModifiers.tagSpacingHorizontal.toPx()
219-
.toInt()
220-
val moreTagVerticalSpace =
221-
moreTagPlaceAble.first.height + tagViewContainerModifiers.tagSpacingVertical.toPx()
222-
.toInt()
223-
224-
if (offset.x + moreTagHorizontalSpace < constraints.maxWidth && offset.y + moreTagVerticalSpace < constraints.maxHeight) {
225-
//place more tag
226-
Log.i("check_placeable", "index: $index more tag placed")
227-
placeable.place(offset.x, offset.y)
228-
return@layout
229-
} else {
230-
Log.i("check_placeable", "index: $index more tag has no space")
204+
val overflow = showOverFlow(
205+
index,
206+
placeAbles,
207+
tagViewContainerModifiers,
208+
constraints,
209+
localDensity
210+
)
211+
overflow?.let {
212+
it.first.place(it.second)
231213
}
214+
return@layout
215+
}
216+
}
217+
}
218+
}
219+
}
220+
221+
/**
222+
* Used for displaying the over flow details when tags not fit in the container
223+
* @param index current placeAble index
224+
* @param placeAbles placeAble details of tags
225+
* @param tagViewContainerModifiers collection of modifier elements that decorate or add behavior to tag view container
226+
* @param constraints immutable constraints for measuring layouts
227+
* @param localDensity A density of the screen. Used for the conversions between pixels and Dp
228+
*/
229+
fun showOverFlow(
230+
index: Int,
231+
placeAbles: List<Pair<Placeable, IntOffset>>,
232+
tagViewContainerModifiers: TagViewContainerModifiers,
233+
constraints: Constraints,
234+
localDensity: Density
235+
): Pair<Placeable, IntOffset>? {
236+
val offset = placeAbles[index].second
237+
val placeable = placeAbles[index]
238+
239+
if (tagViewContainerModifiers.moreTagConfiguration.showOverFlow) {
240+
Log.i("check_placeable", "index: $index next item has no space")
241+
val moreTagPlaceAble = placeAbles.last()
242+
val remainingTags = placeAbles.lastIndex - 1 - index
243+
244+
if (offset.x + moreTagPlaceAble.first.width < constraints.maxWidth && offset.y + moreTagPlaceAble.first.height < constraints.maxHeight) {
245+
//place more tag
246+
Log.i(
247+
"check_placeable",
248+
"index: $index more tag placed offset: $offset"
249+
)
250+
251+
//check whether more tag can be placed in between current and previous offset
252+
val previousIndex = index - 1
253+
if (previousIndex >= 0) {
254+
val previousOffset = placeAbles[previousIndex].second
255+
val previousTag = placeAbles[previousIndex].first
256+
257+
val moreTagXOffset =
258+
previousOffset.x + localDensity.run { tagViewContainerModifiers.tagSpacingHorizontal.toPx() }
259+
.toInt() + previousTag.width
260+
val moreTagYOffset = previousOffset.y
261+
262+
if (moreTagXOffset + moreTagPlaceAble.first.width < constraints.maxWidth && moreTagYOffset + moreTagPlaceAble.first.height < constraints.maxHeight) {
263+
Log.i(
264+
"check_placeable",
265+
" prev index: $previousIndex more tag placed on in btw offset: $previousOffset"
266+
)
267+
268+
return Pair(moreTagPlaceAble.first, IntOffset(moreTagXOffset, moreTagYOffset))
232269
}
233270
}
271+
272+
return moreTagPlaceAble
273+
} else {
274+
Log.i("check_placeable", "index: $index more tag has no space")
234275
}
276+
} else {
277+
return placeable
235278
}
279+
280+
return null
236281
}
237282

238283
@Preview(name = "Default Tag container")

core/ui/src/main/java/co/yml/coreui/core/ui/ytag/model/TagViewContainerModifiers.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ import androidx.compose.ui.unit.dp
2828
data class TagViewContainerModifiers(
2929
val minWidth: Dp,
3030
val minHeight: Dp,
31-
val width: Dp?,
31+
val width: Dp,
3232
val height: Dp,
3333
val enableBorder: Boolean,
3434
val borderWidth: Dp,
@@ -45,8 +45,8 @@ data class TagViewContainerModifiers(
4545
class Builder {
4646
private var minWidth: Dp = 150.dp
4747
private var minHeight: Dp = 150.dp
48-
private var width: Dp? = null
49-
private var height: Dp = minHeight
48+
private var width: Dp = Dp.Unspecified
49+
private var height: Dp = Dp.Unspecified
5050
private var enableBorder: Boolean = false
5151
private var borderWidth: Dp = 1.dp
5252
private var borderColor: Color = Color.Black

core/ui/src/main/java/co/yml/coreui/core/ui/ytag/model/TagViewData.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,6 @@ data class TagViewData(
1717
val leadingIcon: @Composable ((enable: Boolean) -> Unit)? = null,
1818
val trailingIcon: @Composable ((enable: Boolean) -> Unit)? = null,
1919
val enabled: Boolean = true,
20+
val showOverFlow: Boolean = true,
2021
val overFlowText: (Int) -> String = { _ -> "" }
2122
)

0 commit comments

Comments
 (0)