Reputation: 1
i just started the compose animation and now I'm confused I Have a login screen and ı want to with animation but ı noticed to performance issues on my code. When ı click the box on first time coming lagyly and ı dont wanna that what can do for this is there any other solution or it just like that ? How can I solve this?
enum class ViewState { WELCOME, SIGNING, SIGNUP }
@ExperimentalAnimationApi
@Composable
fun OnBoardView(deviceHeight: Dp, deviceWidth: Dp,activity: Activity) {
val baseState = remember { mutableStateOf(ViewState.WELCOME) }
val signUpTransition = updateTransition(targetState = baseState, "1")
val signInTransition = updateTransition(targetState = baseState, label = "2")
val focusManager = LocalFocusManager.current
val visible by remember { baseState }
val density = LocalDensity.current
val isRunning = !signUpTransition.isRunning || !signInTransition.isRunning
//SIGN UP
val signUpSize = sizeAnimate(
targetState = ViewState.SIGNUP,
deviceWidth = deviceWidth,
label = "3",
transition = signUpTransition,
)
val signUpOffset = offsetAnimate(
targetState = ViewState.SIGNUP,
label = "4",
transition = signUpTransition,
deviceWidth = deviceWidth
)
//SIGN IN
val signInSize = sizeAnimate(
targetState = ViewState.SIGNING,
deviceWidth = deviceWidth,
label = "5",
transition = signInTransition,
)
val signInOffset = offsetAnimate(
targetState = ViewState.SIGNING,
label = "6",
transition = signInTransition,
deviceWidth = deviceWidth
)
@Composable
fun TextView(label: String, targetState: ViewState, icon: ImageVector, color: Color) {
AnimatedVisibility(
visible = visible == targetState,
enter = slideInHorizontally(
animationSpec = tween(900),
initialOffsetX = {
with(density) {
when (targetState) {
ViewState.SIGNUP -> -deviceWidth.roundToPx()
ViewState.SIGNING -> deviceWidth.roundToPx()
else -> {
0
}
}
}
}
),
exit = slideOutHorizontally(
animationSpec = tween(900),
targetOffsetX = {
with(density) {
when (targetState) {
ViewState.SIGNUP -> -deviceWidth.roundToPx()
ViewState.SIGNING -> deviceWidth.roundToPx()
else -> {
0
}
}
}
}
)
) {
Column(
modifier = Modifier
.fillMaxHeight(0.5F)
.fillMaxWidth(),
verticalArrangement = Arrangement.SpaceBetween,
horizontalAlignment = Alignment.CenterHorizontally
) {
IconButton(
enabled = isRunning && [email protected],
onClick = {
baseState.value = ViewState.WELCOME
},
modifier = Modifier
.size(50.dp)
.clip(shape = CircleShape)
.background(color)
) {
Icon(
icon,
contentDescription = null,
tint = Color.White
)
}
Text(text = label, fontSize = 25.sp)
}
}
}
@Composable
fun MainBoxView(
offset: Offset,
deviceWidth: Dp,
backgroundColor: Color,
selectedState: ViewState,
content: @Composable () -> Unit
) {
Box(
modifier = Modifier
.size(
width = deviceWidth,
height = if (selectedState == ViewState.SIGNUP) deviceHeight / 1.5F else deviceHeight / 2.3F
)
.offset(offset.x.dp, offset.y.dp)
.clip(shapes.medium)
.background(backgroundColor)
.noRippleClickable(isEnabled = isRunning) {
baseState.value = selectedState
focusManager.clearFocus()
},
contentAlignment = Alignment.TopCenter
) {
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
) {
content()
}
}
}
@Composable
fun BoxColumnView(
targetState: ViewState,
content: @Composable () -> Unit,
) {
AnimatedVisibility(
visible = visible == targetState,
enter = slideInHorizontally(
animationSpec = tween(800),
initialOffsetX = { with(density) { if (targetState == ViewState.SIGNUP) (-deviceWidth / 2).roundToPx() else (deviceWidth / 2).roundToPx() } }
),
exit = slideOutHorizontally(
animationSpec = tween(800),
targetOffsetX = { with(density) { if (targetState == ViewState.SIGNUP) (-deviceWidth / 2).roundToPx() else (deviceWidth / 2).roundToPx() } }
)
) {
content()
}
}
@Composable
fun BoxPreTextView(label: String, targetState: ViewState) {
AnimatedVisibility(
visible = visible == ViewState.WELCOME,
enter = when (visible) {
ViewState.SIGNUP -> {
slideInHorizontally(
animationSpec = tween(800),
initialOffsetX = { with(density) { deviceWidth.roundToPx() } }
)
}
ViewState.WELCOME -> {
slideInHorizontally(
animationSpec = tween(800),
initialOffsetX = { with(density) { if (targetState == ViewState.SIGNUP) deviceWidth.roundToPx() else -deviceWidth.roundToPx() } }
)
}
else -> {
slideInHorizontally(
animationSpec = tween(800),
initialOffsetX = { with(density) { deviceWidth.roundToPx() } }
)
}
},
exit = when (visible) {
ViewState.SIGNUP -> {
slideOutHorizontally(
animationSpec = tween(800),
targetOffsetX = { with(density) { deviceWidth.roundToPx() } }
)
}
ViewState.WELCOME -> {
slideOutHorizontally(
animationSpec = tween(800),
targetOffsetX = { with(density) { if (targetState == ViewState.SIGNUP) -deviceWidth.roundToPx() else deviceWidth.roundToPx() } }
)
}
else -> {
slideOutHorizontally(
animationSpec = tween(800),
targetOffsetX = { with(density) { -deviceWidth.roundToPx() } }
)
}
}
) {
Text(
text = label,
color = Color.White,
)
}
}
@Composable
fun MainTextView(label: String, targetState: ViewState) {
AnimatedVisibility(
visible = visible == targetState || visible == ViewState.WELCOME,
enter = slideInHorizontally(
animationSpec = tween(800),
initialOffsetX = {
with(density) {
if (targetState == ViewState.SIGNUP) {
(-deviceWidth / 3).roundToPx()
} else {
(deviceWidth / 3).roundToPx()
}
}
}
),
exit = slideOutHorizontally(
animationSpec = tween(1200),
targetOffsetX = {
with(density) {
if (targetState == ViewState.SIGNUP) {
(-deviceWidth / 3).roundToPx()
} else {
(deviceWidth / 3).roundToPx()
}
}
})
) {
Text(
text = label,
color = Color.White,
fontSize = 24.sp,
)
}
}
Column(
modifier = Modifier
.fillMaxSize()
.noRippleClickable {
focusManager.clearFocus()
},
) {
Box(
modifier = Modifier
.weight(1.5F)
.fillMaxSize(),
contentAlignment = Alignment.Center
) {
TextView(
icon = Icons.Default.ArrowForward,
label = "WELCOME!",
targetState = ViewState.SIGNUP,
color = DarkBlue
)
TextView(
icon = Icons.Default.ArrowBack,
label = "WELCOME BACK!",
targetState = ViewState.SIGNING,
color = LightBlue
)
}
Row(
modifier = Modifier
.weight(3F)
.fillMaxSize()
.noRippleClickable {
focusManager.clearFocus()
},
//horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.Top,
) {
//SIGN UP
MainBoxView(
offset = signUpOffset,
deviceWidth = signUpSize,
backgroundColor = DarkBlue,
selectedState = ViewState.SIGNUP
) {
Box(
modifier = Modifier.weight(1F),
contentAlignment = Alignment.Center
) {
MainTextView(
label = "SIGN UP",
targetState = ViewState.SIGNUP,
)
}
Box(
modifier = Modifier.weight(6F),
contentAlignment = Alignment.TopCenter
) {
/*
BoxPreTextView(
label = "New here? come on, what are you waiting for, sign up and open up to new worlds",
targetState = ViewState.SIGNUP
)
*/
BoxColumnView(
targetState = ViewState.SIGNUP,
) {
}
}
}
//SIGN IN
MainBoxView(
offset = signInOffset,
deviceWidth = signInSize,
backgroundColor = LightBlue,
selectedState = ViewState.SIGNING
) {
Box(
modifier = Modifier.weight(1F),
contentAlignment = Alignment.Center
) {
MainTextView(
label = "SIGN IN",
targetState = ViewState.SIGNING,
)
}
Box(
modifier = Modifier.weight(4F),
contentAlignment = Alignment.TopCenter
) {
/*
BoxPreTextView(
label = "Returning? Just Sign in to resume what you were doing",
targetState = ViewState.SIGNING
)
*/
BoxColumnView(
targetState = ViewState.SIGNING,
) {
LoginView(activity)
}
}
}
}
Box(
modifier = Modifier
.weight(1F)
.fillMaxSize(),
contentAlignment = Alignment.Center
) {
Row(
modifier = Modifier.fillMaxSize(0.5F),
horizontalArrangement = Arrangement.SpaceAround,
verticalAlignment = Alignment.CenterVertically,
) {
IconButton(
onClick = { },
modifier = Modifier
.size(50.dp)
.clip(shape = CircleShape)
.background(Color.Blue)
) {
Icon(
painterResource(id = R.mipmap.facebook_foreground),
contentDescription = null,
tint = Color.White
)
}
IconButton(
onClick = { },
modifier = Modifier
.size(50.dp)
.clip(shape = CircleShape)
.background(GoogleRed)
) {
Icon(
painterResource(id = R.mipmap.google_foreground),
contentDescription = null,
tint = Color.White
)
}
IconButton(
onClick = { },
modifier = Modifier
.size(50.dp)
.clip(shape = CircleShape)
.background(LightBlue)
) {
Icon(
painterResource(id = R.mipmap.twitter_foreground),
contentDescription = null,
tint = Color.White
)
}
}
}
}
}
@Composable
fun offsetAnimate(
transition: Transition<MutableState<ViewState>>,
targetState: ViewState,
label: String,
deviceWidth: Dp
): Offset {
val offset by transition.animateOffset(
label = label,
transitionSpec = {
if (this.targetState.value == targetState) {
tween(900, 100)
} else {
tween(450)
}
},
) { animated ->
fun width(value: Double) = (deviceWidth.value * value).toFloat()
if (targetState == ViewState.SIGNUP) {
when (animated.value) {
ViewState.SIGNUP -> {
Offset(width(0.07), 0f)
}
ViewState.SIGNING -> {
Offset(-width(0.1), 0f)
}
else -> {
Offset(-width(0.06), 0f)
}
}
} else {
when (animated.value) {
ViewState.SIGNUP -> {
Offset(width(0.2), 0f)
}
ViewState.SIGNING -> {
Offset(width(0.00), 0f)
}
else -> {
Offset(width(0.04), 0f)
}
}
}
}
return offset
}
@Composable
fun sizeAnimate(
transition: Transition<MutableState<ViewState>>,
targetState: ViewState,
label: String,
deviceWidth: Dp
): Dp {
val sizeAnimate by transition.animateDp(
label = label,
transitionSpec = {
if (this.targetState.value == targetState)
tween(450) else tween(900)
},
) {
if (targetState == ViewState.SIGNUP) {
when (it.value) {
ViewState.WELCOME -> deviceWidth / 2F
ViewState.SIGNING -> deviceWidth / 16F
ViewState.SIGNUP -> deviceWidth / 1.15F
}
} else {
when (it.value) {
ViewState.WELCOME -> deviceWidth / 2F
ViewState.SIGNUP -> deviceWidth / 16F
ViewState.SIGNING -> deviceWidth / 1.15F
}
}
}
return sizeAnimate
}
Upvotes: 0
Views: 2423
Reputation: 601
I've had similar performance issue not so long ago and managed to fix it by switching the build variant from debug to release.
Firstly from the bottom left corner of your project click on 'Build Variants' and select 'release' as the 'Active Build Variant'.
Now you need to set a signing config for the release variant. Press Ctrl+Alt+Shift+S and this shortcut should open the Project Structure. Then from 'Modules' select 'app' and click on 'Default Config'. Find 'Signing Config' and select '$signingConfigs.debug'.
Click Apply and wait for Gradle to fetch the build models. Then click OK and wait for Gradle to sync the project.
Rebuild the project and performance issue should be gone.
Upvotes: 1