Jetpack Compose์™€ Animation

Inyeong Kangยท2021๋…„ 10์›” 5์ผ
1
post-thumbnail

๐Ÿ˜€ Simple Animations - Android Jetpack Compose - Part 11 ๊ณต๋ถ€ํ•˜๊ณ  ์ •๋ฆฌํ•œ ๋‚ด์šฉ ๐Ÿ˜€

Box ์ƒ์„ฑ

setContent{
	Box(modifier = Modifier
		.size(200.dp)
		.background(Color.Red),
contentAlignment = Alignment.Center) {
	Button(onClick = { /*To DO*/ }) {
		Text("Increase Size")
}

  • remember ์™€ mutableStateOf๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ•์Šค์˜ ํฌ๊ธฐ ์ƒํƒœ๋ฅผ ๊ธฐ์–ต
setContent{
	var sizeState by remember { mutableStateOf(200.dp) } 
	Box(modifier = Modifier
		.size(200.dp)
		.background(Color.Red),
contentAlignment = Alignment.Center) {
	Button(onClick = { /*To DO*/ }) {
		Text("Increase Size")

+) ์—๋Ÿฌ๊ฐ€ ์žˆ์„ ๊ฒฝ์šฐ, import ๋ถ€๋ถ„์—์„œ import androidx.compose.runtime.remember๋ฅผ import androidx.compose.runtime.*๋กœ ๋ณ€๊ฒฝ


  • size ์•ˆ์— 200.dp๋ฅผ sizeState๋กœ ๋ณ€๊ฒฝ
setContent{
	var sizeState by remember { mutableStateOf(200.dp) }
	Box(modifier = Modifier
		.size(sizeState)
		.background(Color.Red),
contentAlignment = Alignment.Center) {
	Button(onClick = { sizeState += 50.dp }) {
		Text("Increase Size")
}

-> ๋ฒ„ํŠผ ํด๋ฆญ ์‹œ sizeState๋ฅผ 50.dp ์”ฉ ์ฆ๊ฐ€ โ†’ ์•„์ง ์• ๋‹ˆ๋ฉ”์ด์…˜ X

์• ๋‹ˆ๋ฉ”์ด์…˜ ๋„ฃ๊ธฐ

setContent{
	var sizeState by remember { mutableStateOf(200.dp) }
	val size by animateDpAsState(targetValue = sizeState)
	Box(modifier = Modifier
		.size(size)
		.background(Color.Red),
contentAlignment = Alignment.Center) {
	Button(onClick = { sizeState += 50.dp }) {
		Text("Increase Size")
}
  • animateDpAsState์— targetValue์— sizeState๋ฅผ ๋„ฃ์–ด์คŒ โ†’ sizeState๋ฅผ ํ–ฅํ•ด์„œ ์• ๋‹ˆ๋ฉ”์ดํŠธํ•˜๊ธฐ๋ฅผ ์›ํ•จ. โ‡’ ์ดˆ๊ธฐ์— 200.dp์ธ๋ฐ ๊ฐ’์ด ์ฆ๊ฐ€ํ•  ๋•Œ, animateDpAsState ํ•จ์ˆ˜๊ฐ€ ๋ณ€ํ™”๋ฅผ ์ธ์ง€ํ•˜๊ณ , sizeState๋ฅผ 250.dp๊ฐ€ ๋  ๋•Œ๊นŒ์ง€ ๋ถ€๋“œ๋Ÿฝ๊ฒŒ ์ฆ๊ฐ€์‹œํ‚ด.

  • Box์˜ size๋ฅผ sizeState์—์„œ size๋กœ ๋ณ€๊ฒฝ

  • duration๊ณผ delay ๋“ฑ์˜ ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ๋„ฃ๊ณ  ์‹ถ๋‹ค๋ฉด animateDpAsState์˜ ๋‘ ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ์ธ "animationSpec"์„ ํ™œ์šฉ
    โ‘  tween : easing curve๋ฅผ ์‚ฌ์šฉํ•ด์„œ durationMillis ๋™์•ˆ ์‹œ์ž‘ ๊ฐ’๊ณผ ๋ ๊ฐ’ ๊ฐ„์— ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ์ฒ˜๋ฆฌ & delayMillis๋กœ ์• ๋‹ˆ๋ฉ”์ด์…˜ ์‹œ์ž‘์„ ์—ฐ๊ธฐํ•  ์ˆ˜๋„ ์žˆ์Œ.

setContent{
	var sizeState by remember { mutableStateOf(200.dp) }
	val size by animateDpAsState(
		targetValue = sizeState,
		tween(
			durationMillis = 3000,
			delayMillis - 300,
			easing = LinearOutSlowInEasing
)
	Box(modifier = Modifier
		.size(size)
		.background(Color.Red),
contentAlignment = Alignment.Center) {
	Button(onClick = { sizeState += 50.dp }) {
		Text("Increase Size")
}

300milliseconds ๋’ค์— ํฌ๊ธฐ๊ฐ€ 3์ดˆ๊ฐ„ ์ปค์ง€๋Š” ๊ฒƒ์ด ์ง€์†๋จ.

โ†’ ๊ธฐ๋ณธ์ ์œผ๋กœ ์—ฌ๋Ÿฌ ๋ฒˆ ํด๋ฆญํ•˜๋ฉด ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ๋ฐฉํ•ดํ•˜๊ณ  ์• ๋‹ˆ๋ฉ”์ดํ„ฐ๋Š” end value๊ฐ€ ๋จ.

โ‘ก spring : ์‹œ์ž‘ ๊ฐ’๊ณผ ๋ ๊ฐ’ ์‚ฌ์ด์— ๋ฌผ๋ฆฌํ•™ ๊ธฐ๋ฐ˜ ์• ๋‹ˆ๋ฉ”์ด์…˜ ๋งŒ๋“ค์–ด์คŒ. dampingRatio & stiffness ์„ค์ •.

dampingRatio๋Š” ์Šคํ”„๋ง์˜ ํƒ„์„ฑ / stiffness๋Š” ์Šคํ”„๋ง์ด ์ข…๋ฃŒ ๊ฐ’์œผ๋กœ ์ด๋™ํ•˜๋Š” ์†๋„

setContent{
	var sizeState by remember { mutableStateOf(200.dp) }
	val size by animateDpAsState(
		targetValue = sizeState,
		spring(
			Spring.DampingRatioHighBouncy
		)
	Box(modifier = Modifier
		.size(size)
		.background(Color.Red),
contentAlignment = Alignment.Center) {
	Button(onClick = { sizeState += 50.dp }) {
		Text("Increase Size")
}

DampingRatioHighBouncy๋Š” ๊ฐ€์žฅ ์„ผ ํƒ„์„ฑ

์ข…๋ฅ˜ โ†’ DampingRatioHighBouncy, DampingRatioMediumBouncy, DampingRatioLowBouncy,,, etc

โ‘ข keyframes : ์• ๋‹ˆ๋ฉ”์ด์…˜ ๊ธฐ๊ฐ„์— ์—ฌ๋Ÿฌ ํƒ€์ž„์Šคํƒฌํ”„์—์„œ ์ง€์ •๋œ ์Šค๋ƒ…์ƒท ๊ฐ’์„ ๊ธฐ๋ฐ˜์œผ๋กœ ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ์ฒ˜๋ฆฌ. ์–ธ์ œ๋‚˜ ์• ๋‹ˆ๋ฉ”์ด์…˜ ๊ฐ’์€ ๋‘ ํ‚คํ”„๋ ˆ์ž„ ๊ฐ’ ์‚ฌ์ด์— ๋ณด๊ฐ„๋จ. ํ‚คํ”„๋ ˆ์ž„๋งˆ๋‹ค easing์„ ์ง€์ •ํ•  ์ˆ˜๋„ ์žˆ์Œ. ์ง€์† ์‹œ๊ฐ„์„ ์ง€์ •ํ•  ์ˆ˜๋„ ์žˆ๋Š”๋ฐ ์„ค์ •ํ•˜์ง€ ์•Š์œผ๋ฉด ๊ธฐ๋ณธ ์„ค์ •์ด ์‚ฌ์šฉ๋จ.

setContent{
	var sizeState by remember { mutableStateOf(200.dp) }
	val size by animateDpAsState(
		targetValue = sizeState,
		keyframes{
			durationMillis = 5000
			sizeState at 0 with LinearEasing
			sizeState * 1.5f at 1000 with FastOutLinearInEasing
			sizeState * 2f at 5000
		}
	Box(modifier = Modifier
		.size(size)
		.background(Color.Red),
contentAlignment = Alignment.Center) {
	Button(onClick = { sizeState += 50.dp }) {
		Text("Increase Size")
}

์ฒ˜์Œ 1์ดˆ๊นŒ์ง€ ๋น ๋ฅธ easing, ๊ทธ ํ›„ 5์ดˆ๊นŒ์ง€

rememberinfiniteTransition

setContent{
	var sizeState by remember { mutableStateOf(200.dp) }
	val size by animateDpAsState(
		targetValue = sizeState,
		tween(
			durationMillis = 1000
)
	val infiniteTransition = rememberInfiniteTransition()
	val color by infiniteTransition.animateFloat(
			initialValue=Color.Red, 
			targetValue=Color.Green, 
      animationSpec=infinitRepeatable(
				tween(durationMillis = 2000),
				repeatMode = RepeatMode.Reverse
		)
 )
	Box(modifier = Modifier
		.size(size)
		.background(color),
contentAlignment = Alignment.Center) {
	Button(onClick = { sizeState += 50.dp }) {
		Text("Increase Size")
}

InfiniteTransition๋Š” Transition๊ณผ ๊ฐ™์€ ํ•˜์œ„ ์• ๋‹ˆ๋ฉ”์ด์…˜์ด ํ•˜๋‚˜ ์ด์ƒ ํฌํ•จ๋˜์ง€๋งŒ ์ปดํฌ์ง€์…˜์„ ์‹œ์ž‘ํ•˜๋Š” ์ฆ‰์‹œ ์• ๋‹ˆ๋ฉ”์ด์…˜์ด ์‹œ์ž‘๋˜๋ฉฐ ์‚ญ์ œ๋˜์ง€ ์•Š๋Š” ํ•œ ์ค‘๋‹จ๋˜์ง€ ์•Š์Œ. ํ•˜์œ„์— animatedColor, animatedFloat, animatedValue๊ฐ€ ์žˆ์Œ.

repeatable : ์ง€์ •๋œ ๋ฐ˜๋ณต ํšŸ์ˆ˜์— ๋„๋‹ฌํ•  ๋•Œ๊นŒ์ง€ tween ๋˜๋Š” keyframes ๊ฐ™์€ ๊ธฐ๊ฐ„ ๊ธฐ๋ฐ˜ ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ๋ฐ˜๋ณต์ ์œผ๋กœ ์‹คํ–‰. repeatMode ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ์ฒ˜์Œ(RepeatMode.Restart)๋ถ€ํ„ฐ ๋˜๋Š” ๋(RepeatMode.Reverse)๋ถ€ํ„ฐ ์‹œ์ž‘ํ•˜์—ฌ ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ๋ฐ˜๋ณตํ• ์ง€ ์—ฌ๋ถ€๋ฅผ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Œ.

infiniteRepeatable์€ repeatable๊ณผ ์œ ์‚ฌํ•˜์ง€๋งŒ ๋ฌดํ•œ ๋ฐ˜๋ณต๋˜๋Š” ๊ฒƒ.

๋นจ๊ฐ•์—์„œ ์ดˆ๋ก, ์ดˆ๋ก์—์„œ ๋นจ๊ฐ•์œผ๋กœ ๋ฐ”๋€œ. reverse๋ฅผ ํ•ด์„œ ์™”๋‹ค๋ฆฌ ๊ฐ”๋‹ค๋ฆฌ๊ฐ€ ๊ฐ€๋Šฅํ•œ ๊ฒƒ. ๋ฐ•์Šค์˜ background๋ฅผ Color.Red์—์„œ color๋กœ ๋ฐ”๊ฟ”์คŒ.

์‚ฌ์ง„ ์ถœ์ฒ˜ : https://developer.android.com/jetpack/compose/animation

profile
์•ˆ๋…•ํ•˜์„ธ์š”. ๊ฐ•์ธ์˜์ž…๋‹ˆ๋‹ค. GDSC์—์„œ ํ•„์š”ํ•œ ๊ฒƒ๋“ค์„ ์ž‘์—…ํ•˜๊ณ  ์—…๋กœ๋“œํ•˜๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค!

1๊ฐœ์˜ ๋Œ“๊ธ€

comment-user-thumbnail
2021๋…„ 10์›” 16์ผ

์—ญ์‰ฌ ์ธ์˜์ด~~!

๋‹ต๊ธ€ ๋‹ฌ๊ธฐ