[이전 포스팅]
[Android / Kotlin] MotionLayout - 1 ( 애니메이션을 쉽게 적용하기 )
[Android / Kotlin] MotionLayout - 2 ( 실제로 적용해보자. )
오랜 공백을 깨고 돌아왔습니다. ㅎㅎ
학교도 드디어 종강을 맞이했겠다. 다시 천천히 블로그 포스팅을 진행해보려고 합니다.
그 복귀의 첫 번째 포스팅으로 MotionLayout-2에서 언급했던 실습에 대해서 포스팅하려고 합니다.
( 약 3개월 만의 MotionLayout 시리즈 포스팅.. 가슴이 웅장해진다. )
이전 포스팅에서 언급했던 대로 이번에는 로티와 뷰 페이저를 연동하여 다음 웹툰의 메인 화면 애니메이션을 연출해보는 ( 비슷하게라도 따라 해 봅시다! ) 시간을 가져보려고 합니다.
결과 화면 먼저 보시죠.
결과 화면을 보시면 뷰 페이저의 전환에 따라서 로티 애니메이션의 진행 상태가 결정됩니다.
다음 웹툰 어플 메인 화면의 모습과 비슷한 느낌을 받죠?
다음 웹툰에서는 벡터 드로어블의 전환 작업을 일일이 작업했다...라는 소문을 들었습니다만
저희는 좀 더 쉬운 방법을 사용해보겠습니다. 해당 포스팅은 안드로이드 공식문서의 있는 MotionLayout 예제를 참고하여 작성했습니다.
ViewPager - Lottie 연동 실습
먼저 화면 상단에 Lottie 이미지, 그리고 그 아래에 탭 레이아웃과 뷰 페이저로 구성하도록 하겠습니다.
실습에 사용하실 로티 이미지는 무료로 배포해주는 사이트가 있으니 아래 사이트에서 취향껏 다운로드하시면 됩니다.
[로티 애니메이션 다운로드 사이트 Lottie Files]
layout.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.motion.widget.MotionLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/motion_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layoutDescription="@xml/activity_main2_scene">
<com.airbnb.lottie.LottieAnimationView
android:id="@+id/sample_lottie"
android:layout_width="0dp"
android:layout_height="100dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:lottie_fileName="sampleLottie.json" />
<com.google.android.material.tabs.TabLayout
android:id="@+id/sample_tab"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/sample_lottie" />
<androidx.viewpager.widget.ViewPager
android:id="@+id/sample_viewpager"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/sample_tab" />
</androidx.constraintlayout.motion.widget.MotionLayout>
그다음 해당 레이아웃과 연동된 MotionScene을 설정해줍니다.
xml/activity_main2_scene.xml
<?xml version="1.0" encoding="utf-8"?>
<MotionScene
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:motion="http://schemas.android.com/apk/res-auto">
<Transition
motion:constraintSetEnd="@+id/end"
motion:constraintSetStart="@id/start">
<KeyFrameSet>
<KeyAttribute
motion:motionTarget="@+id/sample_lottie"
motion:framePosition="0"
motion:motionProgress="0"/>
</KeyFrameSet>
<KeyFrameSet>
<KeyAttribute
motion:motionTarget="@+id/sample_lottie"
motion:framePosition="100"
motion:motionProgress="1"/>
</KeyFrameSet>
</Transition>
<ConstraintSet android:id="@+id/start">
</ConstraintSet>
<ConstraintSet android:id="@+id/end">
</ConstraintSet>
</MotionScene>
생각보다 많이 간단합니다. <KeyFrameSet> 태그를 통해서 맨 처음 그리고 맨 마지막 장면에서 각각 Lottie 애니메이션의 진행상황을 0과 1로 설정해주면 됩니다.
그 외의 클릭이나 스와이플 Toggle, <ConstraintSet> 설정은 안 해주셔도 됩니다.
메인 코드도 크게 어려움은 없습니다. 뷰페이저를 똑같이 세팅해주시고, addOnPageChageListener를 호출하여 작성해주시면 됩니다.
Activity.kt
class MainActivity2 : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main2)
...
sample_viewpager.addOnPageChangeListener(object : ViewPager.OnPageChangeListener{
override fun onPageScrolled(
position: Int,
positionOffset: Float,
positionOffsetPixels: Int
) {
val progress = (position + positionOffset) / (3 - 1)
motion_layout.progress = progress
}
override fun onPageScrollStateChanged(state: Int) {
}
override fun onPageSelected(position: Int) {
}
})
...
}
}
뷰페이저에서 스크롤이 감지될 경우 onPageScrolled()가 호출됩니다.
해당 함수 영역 내에서 progress 진행 정도를 계산하여 MotionLayout의 진행도를 변경시켜주면 부드럽게 동작하는 모습을 보실 수 있게 됩니다.
진행도 변경 공식에서 ( 3 - 1 ) 부분은 뷰 페이저의 페이지 개수가 N개일 경우 ( N - 1 )로 설정해주시면 됩니다.
오랜만의 포스팅이라 짧은 내용의 포스팅을 가지고 왔습니다.
저도 다시 제가 작성한 코드들을 보면서 고쳐야 할 점이 굉장히 많다고 느끼네요 ㅎㅎ ( 실습 전체 코드가 3개월 전에 작성한 거였으니... )
전체 코드에 대한 Git을 올려놓겠습니다. 궁금하신 분들은 들어가셔서 MainActivity2 부분을 보시면 됩니다!
'안드로이드' 카테고리의 다른 글
[Android/Kotlin] SharedPreferences 대신 쓰는 DataStore (3) | 2021.03.12 |
---|---|
[Android/Kotlin] 비동기 작업을 위한 Coroutine을 Araboza! (1) (0) | 2021.01.13 |
Android Studio 4.1로 오면서 사라진 Kotlin extension 대응법 (2) | 2020.10.15 |
[Android/Kotlin] MotionLayout - 2 ( 실제로 적용해보자.) (0) | 2020.09.17 |
[Android/Kotlin] MotionLayout (애니메이션을 쉽게 적용하기) (3) | 2020.09.06 |