Skip to content

Commit 49478a1

Browse files
committed
Add OverflowMenu implementation
1 parent f201bf1 commit 49478a1

File tree

3 files changed

+157
-0
lines changed

3 files changed

+157
-0
lines changed
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
package com.ceribe.compose.overflowmenu
2+
3+
import androidx.compose.foundation.layout.Box
4+
import androidx.compose.foundation.layout.Row
5+
import androidx.compose.material.*
6+
import androidx.compose.material.icons.Icons
7+
import androidx.compose.material.icons.filled.Warning
8+
import androidx.compose.runtime.*
9+
import androidx.compose.ui.Modifier
10+
import kotlin.math.min
11+
12+
@Composable
13+
fun OverflowMenu(params: OverflowMenuParamsDTO) {
14+
with(params) {
15+
val shownIcons = icons.subList(0, min(shownIconsCount, icons.size))
16+
val hiddenIcons =
17+
if(shownIconsCount >= icons.size)
18+
listOf()
19+
else
20+
icons.subList(shownIconsCount, icons.size)
21+
Row {
22+
shownIcons.forEach {
23+
IconButton(
24+
onClick = it.onClick ?: defaults.onClick ?: {},
25+
modifier = it.modifier ?: defaults.modifier ?: Modifier,
26+
enabled = it.enabled ?: defaults.enabled ?: true
27+
) {
28+
Icon(
29+
imageVector = it.imageVector ?: defaults.imageVector ?: Icons.Filled.Warning,
30+
contentDescription = it.contentDescription ?: defaults.contentDescription,
31+
tint = it.tint ?: defaults.tint ?: LocalContentColor.current.copy(alpha = LocalContentAlpha.current)
32+
)
33+
}
34+
}
35+
if(hiddenIcons.isNotEmpty()) {
36+
Box {
37+
var showDropDown by remember { mutableStateOf(false) }
38+
IconButton(
39+
onClick = {
40+
showDropDown = true
41+
(overflowIcon.onClick ?: defaults.onClick ?: {})()
42+
},
43+
modifier = overflowIcon.modifier ?: defaults.modifier ?: Modifier,
44+
enabled = overflowIcon.enabled ?: defaults.enabled ?: true
45+
) {
46+
Icon(
47+
imageVector = overflowIcon.imageVector ?: defaults.imageVector
48+
?: Icons.Filled.Warning,
49+
contentDescription = overflowIcon.contentDescription
50+
?: defaults.contentDescription,
51+
tint = overflowIcon.tint ?: defaults.tint
52+
?: LocalContentColor.current.copy(alpha = LocalContentAlpha.current)
53+
)
54+
}
55+
DropdownMenu(
56+
expanded = showDropDown,
57+
onDismissRequest = { showDropDown = false }
58+
) {
59+
hiddenIcons.forEach {
60+
DropdownMenuItem(
61+
modifier = it.modifier ?: defaults.modifier ?: Modifier,
62+
enabled = it.enabled ?: defaults.enabled ?: true,
63+
onClick = {
64+
showDropDown = false
65+
(it.onClick ?: defaults.onClick ?: {})()
66+
}
67+
) {
68+
Text(it.label ?: defaults.label ?: "")
69+
}
70+
}
71+
}
72+
}
73+
}
74+
}
75+
}
76+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package com.ceribe.compose.overflowmenu
2+
3+
import androidx.compose.material.icons.Icons
4+
import androidx.compose.material.icons.filled.MoreVert
5+
import androidx.compose.runtime.Composable
6+
import androidx.compose.ui.Modifier
7+
import androidx.compose.ui.graphics.Color
8+
import androidx.compose.ui.graphics.vector.ImageVector
9+
10+
@DslMarker
11+
annotation class OverflowMenuDSL
12+
13+
@Composable
14+
fun OverflowMenu(block: OverflowMenuParamsBuilder.() -> Unit) {
15+
OverflowMenu(OverflowMenuParamsBuilder().apply(block).build())
16+
}
17+
18+
@OverflowMenuDSL
19+
class OverflowMenuParamsBuilder {
20+
21+
var shownIconsCount = 1
22+
private val icons = mutableListOf<IconParamsDTO>()
23+
private var overflowIcon: IconParamsDTO = IconParamsDTO(imageVector = Icons.Filled.MoreVert)
24+
private var defaults: IconParamsDTO = IconParamsDTO()
25+
26+
27+
fun overflowIcon(block: IconParamsBuilder.() -> Unit) {
28+
overflowIcon = IconParamsBuilder(Icons.Filled.MoreVert).apply(block).build()
29+
}
30+
31+
fun defaults(block: IconParamsBuilder.() -> Unit) {
32+
defaults = IconParamsBuilder().apply(block).build()
33+
}
34+
35+
fun icons(block: IconsParamsBuilder.() -> Unit) {
36+
icons.addAll(IconsParamsBuilder().apply(block))
37+
}
38+
39+
fun build() = OverflowMenuParamsDTO(shownIconsCount, icons, overflowIcon, defaults)
40+
}
41+
42+
@OverflowMenuDSL
43+
class IconParamsBuilder(icon: ImageVector? = null) {
44+
var onClick: (() -> Unit)? = null
45+
var modifier: Modifier? = null
46+
var enabled: Boolean? = null
47+
var imageVector: ImageVector? = icon
48+
var label: String? = null
49+
var contentDescription: String? = null
50+
var tint: Color? = null
51+
fun build() = IconParamsDTO(onClick, modifier, enabled, imageVector, label, contentDescription, tint)
52+
}
53+
54+
@OverflowMenuDSL
55+
class IconsParamsBuilder: ArrayList<IconParamsDTO>() {
56+
fun icon(block: IconParamsBuilder.() -> Unit) {
57+
add(IconParamsBuilder().apply(block).build())
58+
}
59+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package com.ceribe.compose.overflowmenu
2+
3+
import androidx.compose.ui.Modifier
4+
import androidx.compose.ui.graphics.Color
5+
import androidx.compose.ui.graphics.vector.ImageVector
6+
7+
class OverflowMenuParamsDTO(
8+
val shownIconsCount: Int,
9+
val icons: List<IconParamsDTO>,
10+
val overflowIcon: IconParamsDTO,
11+
val defaults: IconParamsDTO
12+
)
13+
14+
class IconParamsDTO(
15+
val onClick: (() -> Unit)? = null,
16+
val modifier: Modifier? = null,
17+
val enabled: Boolean? = null,
18+
val imageVector: ImageVector? = null,
19+
val label: String? = null,
20+
val contentDescription: String? = null,
21+
val tint: Color? = null
22+
)

0 commit comments

Comments
 (0)