Table of contents
TLDR(Too long didn’t read)
Introduction
Real example
The state modeling
My app on the Google play store
Basically to model any sort of complex Jetpack Compose state do this:
fun rememberDraggableActions():ModViewDragState{
return remember {ModViewDragState()}
}
@Stable
class ModViewDragState(){
// all the complex state goes in here
}
Then you can use rememberDraggableActions() just like a normal remember function:
fun TestingComplexState(){
val state = rememberDraggableActions()
//all complex state can now be accessed through state
}
This blog post is not going to be an in-depth analysis of every little section of code. Instead, it will act as a simple visual demonstration and example on a alternative way to model compose state
This is my code before the state refactor:
fun DraggableText(
setDragging🙁Boolean)->Unit
){
var offsetX = remember { mutableStateOf(0f) }
val draggableState = rememberDraggableState { delta ->
if (offsetX.value >= 300f){
offsetX.value += delta/10
}
else if (offsetX.value <= –300f){
offsetX.value += delta/10
}
else{
offsetX.value += delta
}
}
Box(
modifier = Modifier
.fillMaxWidth()
.background(Color.Blue)
.draggable(
orientation = Orientation.Horizontal,
onDragStopped = {
draggableState.drag(MutatePriority.PreventUserInput) {
Animatable(offsetX.value).animateTo(
targetValue = 0f,
tween(durationMillis = 300)
) {
dragBy(value – offsetX.value)
}
}
},
enabled = true,
state = draggableState
)
){
CardDemo(
offsetX.value,
setDragging={newValue ->setDragging(newValue)}
)
}
}
after the state refactor:
fun DraggableText(
setDragging🙁Boolean)->Unit
){
val state = rememberDraggableActions()
Box(
modifier = Modifier
.fillMaxWidth()
.background(Color.Blue)
.draggable(
orientation = Orientation.Horizontal,
onDragStopped = {
state.resetOffset()
},
enabled = true,
state = state.draggableState
)
){
CardDemo(
state.offset.value,
setDragging={newValue ->setDragging(newValue)}
)
}
}
Which as you can see is a lot easier to read and just overall cleaner
All I did was just put all the complex state dealing with the draggable into a class marked with the Stable annotation(allowing compose to skip recomposition if needed).
class ModViewDragState(){
val offset: State<Float> get() = offsetX
private var offsetX = mutableStateOf(0f)
val draggableState = DraggableState { delta ->
if (offsetX.value >= 300f){
offsetX.value += delta/5
}
else if (offsetX.value <= –300f){
offsetX.value += delta/5
}
else{
offsetX.value += delta
}
}
suspend fun resetOffset(){
draggableState.drag(MutatePriority.PreventUserInput) {
Animatable(offsetX.value).animateTo(
targetValue = 0f,
tween(durationMillis = 300)
) {
dragBy(value – offsetX.value)
}
}
}
}
Conclusion
Thank you for taking the time out of your day to read this blog post of mine. If you have any questions or concerns please comment below or reach out to me on Twitter.