Last active
March 9, 2023 09:53
-
-
Save KevinSchildhorn/c2c66b0d8760ebe0102c305e7413c717 to your computer and use it in GitHub Desktop.
Relay Compose Sample
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@Composable | |
fun RelayContainer( | |
// Shared properties | |
modifier: Modifier = Modifier, | |
padding: PaddingValues = PaddingValues(all = 0.0.dp), | |
radius: Double = 0.0, | |
elevation: Double = 0.0, | |
strokeWidth: Double = 0.0, | |
borderAlignment: BorderAlignment = BorderAlignment.Inside, | |
strokeColor: Color = Color.Transparent, | |
clip: Clip = Clip.None, | |
clipToParent: Boolean = true, | |
backgroundColor: Color = Color.Transparent, | |
// Container properties | |
isStructured: Boolean = true, | |
arrangement: RelayContainerArrangement = RelayContainerArrangement.Column, | |
itemSpacing: Double = 0.0, | |
mainAxisAlignment: MainAxisAlignment = MainAxisAlignment.Center, | |
crossAxisAlignment: CrossAxisAlignment = CrossAxisAlignment.Center, | |
scrollable: Boolean = false, | |
scrollAnchor: ScrollAnchor = ScrollAnchor.Start, | |
scrollPadding: PaddingValues = PaddingValues(all = 0.0.dp), | |
content: @Composable RelayContainerScope.() -> Unit, | |
) { | |
RelayBaseComposable( | |
modifier = modifier, | |
padding = padding, | |
clip = clip, | |
clipToParent = clipToParent, | |
radius = radius, | |
elevation = elevation, | |
backgroundColor = backgroundColor, | |
strokeWidth = strokeWidth, | |
borderAlignment = borderAlignment, | |
strokeColor = strokeColor, | |
) { | |
if (isStructured) { | |
when (arrangement) { | |
RelayContainerArrangement.Row -> { | |
val horizontalScrollModifier = | |
if (scrollable) it | |
.horizontalScroll( | |
enabled = scrollable, | |
state = ScrollState(0), | |
reverseScrolling = scrollAnchor == ScrollAnchor.End | |
) | |
.padding(scrollPadding) | |
else it | |
RelayRow( | |
modifier = horizontalScrollModifier, | |
// Note that the arrangement param for RelayRow and RelayColumn takes a value of | |
// type`Arrangement.Horizontal` or `Arrangement.Vertical` respectively, | |
// so logic cannot be shared between both. | |
horizontalArrangement = if (itemSpacing != 0.0) { | |
ComposeArrangement.spacedBy( | |
itemSpacing.dp, | |
when (mainAxisAlignment) { | |
MainAxisAlignment.Center -> | |
Alignment.CenterHorizontally | |
MainAxisAlignment.Start -> | |
Alignment.Start | |
MainAxisAlignment.End -> | |
Alignment.End | |
// SpaceEvenly, SpaceBetween, and SpaceAround are not valid | |
// when item spacing is applied, so we make them Alignment.Center | |
MainAxisAlignment.SpaceEvenly -> | |
Alignment.CenterHorizontally | |
MainAxisAlignment.SpaceBetween -> | |
Alignment.CenterHorizontally | |
MainAxisAlignment.SpaceAround -> | |
Alignment.CenterHorizontally | |
} | |
) | |
} else when (mainAxisAlignment) { | |
MainAxisAlignment.Center -> | |
ComposeArrangement.Center | |
MainAxisAlignment.Start -> | |
ComposeArrangement.Start | |
MainAxisAlignment.End -> | |
ComposeArrangement.End | |
MainAxisAlignment.SpaceEvenly -> | |
ComposeArrangement.SpaceEvenly | |
MainAxisAlignment.SpaceBetween -> | |
ComposeArrangement.SpaceBetween | |
MainAxisAlignment.SpaceAround -> | |
ComposeArrangement.SpaceAround | |
}, | |
// Note that the cross alignment for RelayRow and RelayColumn takes a value of type | |
// `Alignment.Vertical` or `Alignment.Horizontal` respectively, so logic | |
// cannot be shared between both. | |
verticalAlignment = when (crossAxisAlignment) { | |
CrossAxisAlignment.Center -> | |
Alignment.CenterVertically | |
CrossAxisAlignment.Start -> | |
Alignment.Top | |
CrossAxisAlignment.End -> | |
Alignment.Bottom | |
// TODO: Find a way to more accurately convey these | |
// cross axis alignment options | |
CrossAxisAlignment.Stretch -> Alignment.CenterVertically | |
CrossAxisAlignment.Baseline -> Alignment.CenterVertically | |
} | |
) { | |
RowScopeInstance.content() | |
} | |
} | |
RelayContainerArrangement.Column -> { | |
val verticalScrollModifier = | |
if (scrollable) it | |
.verticalScroll( | |
enabled = scrollable, | |
state = ScrollState(0), | |
reverseScrolling = scrollAnchor == ScrollAnchor.End | |
) | |
.padding(scrollPadding) | |
else it | |
RelayColumn( | |
modifier = verticalScrollModifier, | |
verticalArrangement = if (itemSpacing != 0.0) { | |
ComposeArrangement.spacedBy( | |
itemSpacing.dp, | |
when (mainAxisAlignment) { | |
MainAxisAlignment.Center -> | |
Alignment.CenterVertically | |
MainAxisAlignment.Start -> | |
Alignment.Top | |
MainAxisAlignment.End -> | |
Alignment.Bottom | |
// SpaceEvenly, SpaceBetween, and SpaceAround are not valid | |
// when item spacing is applied, so we make them Alignment.Center | |
MainAxisAlignment.SpaceEvenly -> | |
Alignment.CenterVertically | |
MainAxisAlignment.SpaceBetween -> | |
Alignment.CenterVertically | |
MainAxisAlignment.SpaceAround -> | |
Alignment.CenterVertically | |
} | |
) | |
} else when (mainAxisAlignment) { | |
MainAxisAlignment.Center -> | |
ComposeArrangement.Center | |
MainAxisAlignment.Start -> | |
ComposeArrangement.Top | |
MainAxisAlignment.End -> | |
ComposeArrangement.Bottom | |
MainAxisAlignment.SpaceEvenly -> | |
ComposeArrangement.SpaceEvenly | |
MainAxisAlignment.SpaceBetween -> | |
ComposeArrangement.SpaceBetween | |
MainAxisAlignment.SpaceAround -> | |
ComposeArrangement.SpaceAround | |
}, | |
horizontalAlignment = when (crossAxisAlignment) { | |
CrossAxisAlignment.Center -> | |
Alignment.CenterHorizontally | |
CrossAxisAlignment.Start -> | |
Alignment.Start | |
CrossAxisAlignment.End -> | |
Alignment.End | |
// TODO: Find a way to more accurately convey these | |
// cross axis alignment options | |
CrossAxisAlignment.Stretch -> Alignment.CenterHorizontally | |
CrossAxisAlignment.Baseline -> Alignment.CenterHorizontally | |
} | |
) { | |
ColumnScopeInstance.content() | |
} | |
} | |
} | |
} else { | |
RelayBox( | |
modifier = it | |
) { | |
BoxScopeInstance.content() | |
} | |
} | |
} | |
} | |
@Composable | |
fun RelayText( | |
modifier: Modifier = Modifier, | |
content: String = "Text Value", | |
fontSize: TextUnit = 14.sp, | |
height: TextUnit = 1.em, | |
letterSpacing: TextUnit = 0.sp, | |
fontWeight: FontWeight? = FontWeight.W400, | |
underline: Boolean = false, | |
strikethrough: Boolean = false, | |
italic: Boolean = false, | |
maxLines: Int = 1, | |
overflow: TextOverflow = TextOverflow.Visible, | |
color: Color = Color.Black, | |
textAlign: TextAlign = TextAlign.Center, | |
case: Case = Case.None, | |
fontFamily: FontFamily? = FontFamily.Default, // Roboto on most modern Android devices | |
padding: PaddingValues = PaddingValues(0.dp), | |
clip: Clip = Clip.None, | |
radius: Double = 0.0, | |
elevation: Double = 0.0, | |
style: TextStyle = LocalTextStyle.current, | |
) { | |
// Modify [String] content according to the semantics of VariantCase | |
fun maybeApplyCase(content: String, case: Case): String { | |
val WHITESPACE_INCLUDE_DELIMITERS = Pattern.compile("((?=\\s)|(?<=\\s))") | |
return when (case) { | |
Case.Upper -> content.uppercase(JavaLocale.getDefault()) | |
Case.Lower -> content.lowercase(JavaLocale.getDefault()) | |
Case.Capitalized -> content.replaceFirstChar { it.uppercase(JavaLocale.getDefault()) } | |
// Split the string on whitespace and include the whitespace | |
// in the resulting list. Capitalize each list element and re-join. | |
// This will capitalize the first letter of each word in the string | |
// while preserving the whitespace as it originally existed. | |
// (i.e. don't compress whitespace into a single space, swap | |
// spaces for tabs, etc.) | |
Case.Title -> WHITESPACE_INCLUDE_DELIMITERS.split(content) | |
.map { it.replaceFirstChar() { it.uppercase(JavaLocale.getDefault()) } } | |
.joinToString("") | |
else -> content | |
} | |
} | |
RelayText( | |
modifier = modifier, | |
content = AnnotatedString(maybeApplyCase(content, case)), | |
fontSize = fontSize, | |
height = height, | |
letterSpacing = letterSpacing, | |
fontWeight = fontWeight, | |
underline = underline, | |
strikethrough = strikethrough, | |
italic = italic, | |
maxLines = maxLines, | |
overflow = overflow, | |
color = color, | |
textAlign = textAlign, | |
case = Case.None, | |
fontFamily = fontFamily, | |
padding = padding, | |
clip = clip, | |
radius = radius, | |
elevation = elevation, | |
style = style | |
) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment