Issue
In order to reduce complex, I need to split a big @Composable
function to small parts, and I need to share info such as variables among them.
At present, I use Code A to do it by using top variables, I don't think it's a good.
How can I share info among @Composable function in Android Studio?
Code A
private var paddingXAxis = 80f
private var paddingXLabelMargin = 8f
private var paddingYAxis =50f
private var xAxisLength = 100f
private var yAxisLength = 100f
private var maxPointCount = 40
@Composable
fun ScreenHome_Table(
modifier: Modifier = Modifier,
mViewMode: SoundViewModel
) {
Box( ) {
Canvas(
modifier = Modifier
.fillMaxSize()
.padding(10.dp)
) {
setParameterTable(this, mContext)
setProcess(this, uiMSoundDensity.soundList.toList())
setMainAxis(this)
setChildXAxis(this, xTime)
setChildYAxis(this)
}
}
}
fun setParameterTable(drawScope: DrawScope, mContext: Context) {
with(drawScope) {
xAxisLength = size.width - paddingXAxis * 2
yAxisLength = size.height - paddingYAxis * 2
}
maxPointCount = mContext.resources.getInteger(R.integer.maxCount)
divisionUnit = mContext.getString(R.string.divisionUnit)
...
}
fun setMainAxis(drawScope: DrawScope) {
...
}
Solution
You can do this by creating a class that contains properties as default Composables such as Text, TextField or Button use. A class wraps many properties.
TextStyle(
color = textColor,
fontSize = fontSize,
fontWeight = fontWeight,
textAlign = textAlign,
lineHeight = lineHeight,
fontFamily = fontFamily,
textDecoration = textDecoration,
fontStyle = fontStyle,
letterSpacing = letterSpacing
)
this class is used by BasicText
fun BasicText(
text: String,
modifier: Modifier = Modifier,
style: TextStyle = TextStyle.Default,
onTextLayout: (TextLayoutResult) -> Unit = {},
overflow: TextOverflow = TextOverflow.Clip,
softWrap: Boolean = true,
maxLines: Int = Int.MAX_VALUE,
)
TextFieldColors
is another example of this
private class DefaultTextFieldColors(
private val textColor: Color,
private val disabledTextColor: Color,
private val cursorColor: Color,
private val errorCursorColor: Color,
private val focusedIndicatorColor: Color,
private val unfocusedIndicatorColor: Color,
private val errorIndicatorColor: Color,
private val disabledIndicatorColor: Color,
private val leadingIconColor: Color,
private val disabledLeadingIconColor: Color,
private val errorLeadingIconColor: Color,
private val trailingIconColor: Color,
private val disabledTrailingIconColor: Color,
private val errorTrailingIconColor: Color,
private val backgroundColor: Color,
private val focusedLabelColor: Color,
private val unfocusedLabelColor: Color,
private val disabledLabelColor: Color,
private val errorLabelColor: Color,
private val placeholderColor: Color,
private val disabledPlaceholderColor: Color
)
Second option is to create a class that contains properties and can act a State
wrapper for other MutableState
s. With this approach can trigger recomposition on any individual property change, pass or observe latest properties unlike first approach.
class BadgeState(
var maxNumber: Int = 99,
var circleShapeThreshold: Int = 1,
@IntRange(from = 0, to = 99) var roundedRadiusPercent: Int = 50,
backgroundColor: Color,
var horizontalPadding: Dp = 4.dp,
var verticalPadding: Dp = 0.dp,
textColor: Color,
var fontSize: TextUnit,
var fontWeight: FontWeight? = null,
var fontFamily: FontFamily? = null,
var fontStyle: FontStyle? = null,
var textDecoration: TextDecoration? = null,
var shadow: MaterialShadow? = null,
var borderStroke: BorderStroke? = null,
showBadgeThreshold: Int = Int.MIN_VALUE,
) {
{
var backgroundColor by mutableStateOf(backgroundColor)
/*
Properties for Text
*/
var textColor by mutableStateOf(textColor)
var text by mutableStateOf("0")
private set
var numberOnBadge by mutableStateOf(0)
private set
var showBadgeThreshold by mutableStateOf(showBadgeThreshold)
...
}
And wrap it with remember to not create new instance on each recomposition
fun rememberBadgeState(
maxNumber: Int = 99,
circleShapeThreshold: Int = 1,
@IntRange(from = 0, to = 99) roundedRadiusPercent: Int = 50,
backgroundColor: Color = Color.Red,
horizontalPadding: Dp = 4.dp,
verticalPadding: Dp = 0.dp,
textColor: Color = Color.White,
fontSize: TextUnit = 14.sp,
fontWeight: FontWeight? = null,
fontFamily: FontFamily? = null,
fontStyle: FontStyle? = null,
textDecoration: TextDecoration? = null,
shadow: MaterialShadow? = null,
borderStroke: BorderStroke? = null,
showBadgeThreshold: Int = Int.MIN_VALUE,
): BadgeState {
return remember {
BadgeState(
maxNumber,
circleShapeThreshold,
roundedRadiusPercent,
backgroundColor,
horizontalPadding,
verticalPadding,
textColor,
fontSize,
fontWeight,
fontFamily,
fontStyle,
textDecoration,
shadow,
borderStroke,
showBadgeThreshold
)
}
}
You can pass this state between you Composables
@Composable
fun Badge(
modifier: Modifier = Modifier,
badgeState: BadgeState = rememberBadgeState(),
) {
val showBadge = remember {
derivedStateOf {
badgeState.showBadgeThreshold < badgeState.numberOnBadge
}
}
if (showBadge.value) {
BadgeComponent(badgeState = badgeState, modifier = modifier)
}
}
or you can pass to a Modifier
you created
private fun Modifier.getBadgeModifier(
badgeState: BadgeState,
shape: Shape
) = this
.materialShadow(badgeState = badgeState)
.then(
badgeState.borderStroke?.let { borderStroke ->
this.border(borderStroke, shape = shape)
} ?: this
)
.background(
badgeState.backgroundColor,
shape = shape
)
or another one
fun Modifier.materialShadow(badgeState: BadgeState) = composed(
inspectorInfo = {
name = "shadow"
value = badgeState.shadow
},
factory = {
// rest of the code
}
Answered By - Thracian
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.