|
import androidx.compose.foundation.BorderStroke |
|
import androidx.compose.foundation.layout.Arrangement |
|
import androidx.compose.foundation.layout.Row |
|
import androidx.compose.foundation.layout.offset |
|
import androidx.compose.foundation.layout.padding |
|
import androidx.compose.foundation.shape.RoundedCornerShape |
|
import androidx.compose.material.ButtonDefaults |
|
import androidx.compose.material.OutlinedButton |
|
import androidx.compose.material.Text |
|
import androidx.compose.runtime.Composable |
|
import androidx.compose.ui.Alignment |
|
import androidx.compose.ui.Modifier |
|
import androidx.compose.ui.graphics.Color |
|
import androidx.compose.ui.unit.dp |
|
import androidx.compose.ui.zIndex |
|
|
|
private const val Z_INDEX_NEUTRAL = 0f |
|
private const val Z_INDEX = 1f |
|
private const val BUTTON_WEIGHT = 1f |
|
private const val CORNER_RADIUS = 10 |
|
|
|
@Composable |
|
fun <T> SegmentedControl( |
|
items: List<T>, |
|
defaultSelectedItemIndex: Int? = null, |
|
cornerRadius: Int = CORNER_RADIUS, |
|
onItemTapped: (T?) -> Unit |
|
) { |
|
|
|
var selectedIndex = defaultSelectedItemIndex |
|
|
|
Row( |
|
modifier = Modifier |
|
.padding(horizontal = 16.dp), |
|
horizontalArrangement = Arrangement.SpaceBetween, |
|
verticalAlignment = Alignment.CenterVertically |
|
) { |
|
items.forEachIndexed { index, item -> |
|
OutlinedButton( |
|
modifier = Modifier |
|
.weight(BUTTON_WEIGHT) |
|
.applyIf(0 == index) { |
|
offset(0.dp, 0.dp) |
|
} |
|
.applyIf(0 != index) { |
|
offset((-1 * index).dp, 0.dp) |
|
} |
|
.zIndex(if (selectedIndex == index) Z_INDEX else Z_INDEX_NEUTRAL), |
|
onClick = { |
|
selectedIndex = when (selectedIndex) { |
|
index -> null |
|
else -> index |
|
} |
|
onItemTapped(items.getOrNull(selectedIndex ?: -1)) |
|
}, |
|
shape = when (index) { |
|
// Left outer button |
|
0 -> RoundedCornerShape( |
|
topStartPercent = cornerRadius, |
|
topEndPercent = 0, |
|
bottomStartPercent = cornerRadius, |
|
bottomEndPercent = 0 |
|
) |
|
// Right outer button |
|
items.lastIndex -> RoundedCornerShape( |
|
topStartPercent = 0, |
|
topEndPercent = cornerRadius, |
|
bottomStartPercent = 0, |
|
bottomEndPercent = cornerRadius |
|
) |
|
// Remaining buttons (in between) |
|
else -> RoundedCornerShape( |
|
topStartPercent = 0, |
|
topEndPercent = 0, |
|
bottomStartPercent = 0, |
|
bottomEndPercent = 0 |
|
) |
|
}, |
|
border = BorderStroke( |
|
1.dp, |
|
when (selectedIndex) { |
|
index -> { The border color for the selected item } |
|
else -> { The border color for the unselected item } |
|
} |
|
), |
|
colors = ButtonDefaults.outlinedButtonColors( |
|
backgroundColor = when (selectedIndex) { |
|
index -> { The border color for the selected item } |
|
else -> { The border color for the unselected item } |
|
} |
|
) |
|
) { |
|
Text( |
|
text = item.toString(), |
|
style = TextStyle( |
|
color = when (selectedIndex) { |
|
index -> { Text color for selected item } |
|
else -> { Text color for unselected item } |
|
} |
|
) |
|
) |
|
} |
|
} |
|
} |
|
} |
|
|
|
fun Modifier.applyIf( |
|
condition: Boolean, |
|
then: Modifier.() -> Modifier |
|
): Modifier = |
|
if (condition) { |
|
then() |
|
} else { |
|
this |
|
} |