밍맹의 생각날 때 적는 블로그

[Android/Kotlin] SpringAnimation - 2. 강성과 감쇠비 본문

안드로이드

[Android/Kotlin] SpringAnimation - 2. 강성과 감쇠비

mingmaeng 2021. 11. 3. 11:41

이전 포스팅에서 언급했다싶이

스프링 애니메이션은 스프링력이라는 특정 값과 속도에 따라서 계산되는 애니메이션입니다.

물리학 효과가 들어간 스프링 애니메이션에서 가장 중요한 부분인 강성과 감쇠비에 대해서 얘기해보고자 합니다.

이전 포스팅을 못 보신 분들이라면 보고 오시는 것을 추천드립니다.

 

참고 링크

https://developer.android.com/guide/topics/graphics/spring-animation?hl=ko

 

스프링 물리학으로 움직임 애니메이션화  |  Android 개발자  |  Android Developers

스프링 기반 애니메이션에서 스프링의 속성, 값, 속도는 애니메이션을 만드는 데 사용됩니다.

developer.android.com


강성과 감쇠비?

스프링 애니메이션을 적용할 때 사용자는 강성과 감쇠비를 적용할 수 있습니다.

사용자는 이 두 개의 속성을 임의로 조정하여 자신이 원하는 스프링 애니메이션을 만들 수 있게 됩니다.

스프링의 강도 '강성'

'강성'은 스프링의 강도를 나타냅니다.

스프링이 느슨하면 우리는 적은 힘으로도 스프링을 굉장히 크게 늘릴 수 있고, 반대로 스프링이 빡빡하다면 굉장히 많은 힘을 줘도 얼마 벌리지 못합니다.

 

시스템에서 Default로 설정할 수 있는 강성 상수는 총 4가지 입니다.

 

- STIFFNESS_HIGH

- STIFFNESS_MEDIUM

- STIFFNESS_LOW

- STIFFNESS_VERY_LOW

 

아무런 값도 넣어주지 않는다면 STIFFNESS_MEDIUM으로 설정되어있습니다.

스프링의 탄성 '감쇠비'

'감쇠비'는 스프링의 탄성을 나타냅니다.

쉽게 말해서 스프링을 땡겼다가 놓았을 때 스프링의 통통 튀는 정도에 영향을 미친다고 볼 수 있습니다.

 

강성과 마찬가지로 시스템에서 Default로 설정할 수 있는 감쇠비 상수는 총 4가지 입니다.

- DAMPING_RATIO_HIGH_BOUNCY

- DAMPING_RATIO_MEDIUM_BOUNCY

- DAMPING_RATIO_LOW_BOUNCY

- DAMPING_RATIO_NO_BOUNCY

 

아무런 값도 넣어주지 않는다면 DAMPING_RATIO_MEDIUM_BOUNCY으로 설정되어있습니다.

 

Spring Animation 적용 방법

스프링 애니메이션은 SpringAnimation 클래스를 사용하여 원하는 뷰 객체에 애니메이션을 적용시킬 수 있습니다.

View.let { view ->
	SpringAnimation(view, DynamicAnimation.TRANSLATION_Y, 0f)
}

스프링 애니메이션 속성에 대해서는 이전 포스팅에서 다뤘기 때문에 생략하도록 하겠습니다.

 

SpringAnimation 객체를 만들었다면 강성과 감쇠비 옵션을 추가해줍니다.

View.let { view ->
	SpringAnimation(view, DynamicAnimation.TRANSLATION_Y, 0f).apply {
    	// set Stiffness and DampingRatio
        stifness = SpringForce.STIFFNESS_LOW
        dampingRatio = SpringForce.DAMPING_RATIO_MEDIUM_BOUNCY
    }
}

적용한 애니메이션을 시작하는 방법은 start() 또는 animateToFinalPosition()을 호출하는 두 가지 방법이 있습니다.

 

여기서 animateToFinalPosition()에 대해서 조금 더 알아보자면

  • 스프링 애니메이션이 도착할 최종 위치를 설정해야합니다.
  • 애니메이션이 시작하지 않았다면 시작합니다.

연쇄 스프링 애니메이션 적용

animateToFinalPosition을 사용하여 여러개의 스프링 애니메이션을 연쇄적으로 사용 가능합니다.

미안하다... 이거 보여주려고 어그로 끌었다.. 스프링 애니메이션 수준 ㄹㅇ실화냐?

네 사실 이거 보여주려고 글 쓴겁니다.

최상단의 밝은 원을 드래그 하면 뒤이어 다른 원들도 스프링 애니메이션이 적용된 상태로 드래그하는 경로를 따라오게됩니다.

편의상 드래그 가능한 가장 위쪽 원을 1번, 중간의 원을 2번, 가장 아래쪽에 있는 원을 3번이라고 칭하겠습니다.

1번 원을 드래그 했을 때 변화하는 위치값을 받아 2번에 설정되어 있는 SpringAnimation 클래스에 위치를 전달하고,

OnAnimationUpdateListener를 추가해 3번에게 연쇄적으로 좌표값을 보내줍니다.

 

// 2번의 X축이동 속성이 변경됨에 따라 3번 X축이동 SpringAnimation 객체로 전달
animX.addUpdateListener { _, value, _ ->
	anim2x.animateToFinalPosition(value)
}
// 2번의 Y축이동 속성이 변경됨에 따라 3번 Y축이동 SpringAnimation 객체로 전달
animY.addUpdateListener { _, value, _ ->
	anim2y.animateToFinalPosition(
    	value + 
    	secondLayoutParams.topMargin + 
    	binding.imgBallSky700.height
    )
}
// 1번원을 드래그하면 변화하는 좌표값을 2번원의 SpringAnimation 객체로 전달
binding.imgBallSky200.setOnTouchListener { v, event ->

	when (event.actionMasked) {
		MotionEvent.ACTION_DOWN -> {
        
		xDown = binding.imgBallSky200.x - event.rawX
		yDown = binding.imgBallSky200.y - event.rawY
        
		}

        MotionEvent.ACTION_MOVE -> {
            val newX = event.rawX + xDown
            val newY = event.rawY + yDown

            binding.imgBallSky200.animate()
           		.x(newX)
                .y(newY)
                .setDuration(0)
                .start()

            animX.animateToFinalPosition(newX)
            animY.animateToFinalPosition(newY + firstLayoutParams.topMargin + binding.imgBallSky500.height)
         }

         MotionEvent.ACTION_UP -> {}
	}

	true
}

앱 서비스를 만들 때 애니메이션 효과는 무척이나 중요합니다. 사용자의 시각을 사로잡는데 가장 큰 요소라고 생각하기 때문이죠 ㅎㅎ

SpringAnimation이외에도 MotionLayout, VectorDrawableAnimation 등을 충분히 잘 활용하면

안드로이드에서도 보다 역동적인 애니메이션들을 구현할 수 있습니다. ( 물론 기본적인 앱 서비스의 로직이 정상적으로 돌아가는게 우선이지만요 ㅎㅎ )

Comments