Spring Animationとは
SpringAnimationを使うと物理的な動きのアニメーションを実現することができます。
物理的な要素として、 Dumping ratio
と Stiffness
を与えることができます。
Damping ratio
物体の弾みの程度を定義します。この値が大きいほどバネのようによく弾みます。
DAMPING_RATIO_HIGH_BOUNCY //(0.2)
DAMPING_RATIO_MEDIUM_BOUNCY //(0.5)
DAMPING_RATIO_LOW_BOUNCY //(0.75)
DAMPING_RATIO_NO_BOUNCY //(1.0)
Stiffness
バネの強度を定義します。この値が大きいほど伸縮時間が短くなります。
STIFFNESS_HIGH //(10000.0)
STIFFNESS_MEDIUM //(1500.0)
STIFFNESS_LOW //(200.0)
STIFFNESS_VERY_LOW //(50)
Spring Animation例
では実際にSpringAnimationを使った例を示していきます。githubにもコードを上げてます。
Spring Position
SpringAnimation.X
SpringAnimation.Y
を使うことでX軸、Y軸に対してSpringAnimationをかける事ができます。
class SpringPositionView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : View(context, attrs, defStyleAttr) {
private companion object Params {
private const val STIFFNESS = SpringForce.STIFFNESS_MEDIUM
private const val DAMPING_RATIO = SpringForce.DAMPING_RATIO_HIGH_BOUNCY
}
private lateinit var xAnim: SpringAnimation
private lateinit var yAnim: SpringAnimation
init {
viewTreeObserver.addOnGlobalLayoutListener {
xAnim = SpringAnimation(this, SpringAnimation.X).apply {
spring = SpringForce(x).apply {
stiffness = STIFFNESS
dampingRatio = DAMPING_RATIO
}
}
yAnim = SpringAnimation(this, SpringAnimation.Y).apply {
spring = SpringForce(y).apply {
stiffness = STIFFNESS
dampingRatio = DAMPING_RATIO
}
}
}
var dX = 0f
var dY = 0f
setOnTouchListener { view, event ->
when (event.actionMasked) {
MotionEvent.ACTION_DOWN -> {
dX = view.x - event.rawX
dY = view.y - event.rawY
xAnim.cancel()
yAnim.cancel()
}
MotionEvent.ACTION_MOVE -> {
animate()
.x(event.rawX + dX)
.y(event.rawY + dY)
.setDuration(0)
.start()
}
MotionEvent.ACTION_UP -> {
xAnim.start()
yAnim.start()
}
}
true
}
}
}
Spring Rotation
SpringAnimation.ROTATION
を使うことで回転に対してSpringAnimationをかける事ができます。
class SpringRotationView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : View(context, attrs, defStyleAttr) {
private companion object Params {
val INITIAL_ROTATION = 0f
val STIFFNESS = SpringForce.STIFFNESS_MEDIUM
val DAMPING_RATIO = SpringForce.DAMPING_RATIO_HIGH_BOUNCY
}
private val rotationAnim: SpringAnimation = SpringAnimation(this, SpringAnimation.ROTATION).apply {
spring = SpringForce(INITIAL_ROTATION).apply {
stiffness = STIFFNESS
dampingRatio = DAMPING_RATIO
}
}
init {
var currentRotation = 0f
setOnTouchListener { view, event ->
when (event.actionMasked) {
MotionEvent.ACTION_DOWN -> {
rotationAnim.cancel()
currentRotation = rotationAmount(event.x, event.y)
}
MotionEvent.ACTION_MOVE -> {
val previousRotation = currentRotation
currentRotation = rotationAmount(event.x, event.y)
view.rotation += currentRotation - previousRotation
}
MotionEvent.ACTION_UP -> rotationAnim.start()
}
true
}
}
}
Spring Scale
SpringAnimation.SCROLL_X
SpringAnimation.SCROLL_Y
を使うことで拡大縮小に対してSpringAnimationをかける事ができます。
class SpringScaleView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : View(context, attrs, defStyleAttr) {
private companion object Params {
val INITIAL_SCALE = 1f
val STIFFNESS = SpringForce.STIFFNESS_MEDIUM
val DAMPING_RATIO = SpringForce.DAMPING_RATIO_HIGH_BOUNCY
}
private val xAnim: SpringAnimation = SpringAnimation(this, SpringAnimation.SCALE_X).apply {
spring = SpringForce(INITIAL_SCALE).apply {
stiffness = STIFFNESS
dampingRatio = DAMPING_RATIO
}
}
private val yAnim: SpringAnimation = SpringAnimation(this, SpringAnimation.SCROLL_Y).apply {
spring = SpringForce(INITIAL_SCALE).apply {
stiffness = STIFFNESS
dampingRatio = DAMPING_RATIO
}
}
private val detector = ScaleGestureDetector(context,
object:ScaleGestureDetector.SimpleOnScaleGestureListener() {
override fun onScale(detector: ScaleGestureDetector): Boolean {
var scaleFactor = 1f
scaleFactor *= detector.scaleFactor
scaleX *= scaleFactor
scaleY *= scaleFactor
return true
}
})
init {
setOnTouchListener { _, event ->
if (event.action == MotionEvent.ACTION_UP) {
xAnim.start()
yAnim.start()
} else {
xAnim.cancel()
yAnim.cancel()
detector.onTouchEvent(event)
}
true
}
}
}
最後に
サンプルコードはgithubにあげてます。