일상

if(kakao) 2020 - 스토리 안드로이드 앱의 화면 전환 애니메이션 적용기

poppy 2020. 11. 19. 11:16
반응형

다음 링크의 영상을 보고 내용을 정리해보았습니다! 포스팅의 모든 사진의 출처는 다음 링크의 영상에 있습니다 :)

어떻게 코드가 구현되는지 궁금하시다면 영상을 참고해주세요!

if.kakao.com/session/109

 

if(kakao)2020

오늘도 카카오는 일상을 바꾸는 중

if.kakao.com

1. Shared Elements Transition이란?

안드로이드에서는 페이드나 슬라이드 효과를 씁니다. Shared Elements Transition는 화면과 화면의 공유요소를 통하여 하나의 액티비티에서 사용하는 듯한 효과를 줄 수 있습니다. 따라서 더 자연스럽고 부드러운 효과를 줄 수 있고, 사용자의 피로도를 줄여줍니다

 

※ 동작과정 ※

  1. Activty A의 View1을 클릭하여 Activity B를 시작할 때 클릭된 뷰의 위치나 형태, 크기 정보를 Activity B로 전달합니다.

  2. Activty B에 전달된 정보를 View2에 전달하여 View1과 동일한 크기, 위치로 실행하여 애니메이션을 실행합니다

  3. 최종적으로 View2의 원래 크기, 위치로 돌아가서 애니메이션을 시작합니다.

2. 적용방법

Shared Elements Transition는 안드로이드 5.0 롤리팝 이상부터 사용가능 하기 때문에 낮은 버전을 지원하고 있다면 코드 상에서 분기처리 해야합니다.

 

Transition 등록 부분에서 SharedElementExitTransition이 Activity A에 관한 효과이고, SharedElementEnterTransition이 Activity B에 적용되는 효과입니다.

MoveTransitionSet.xml은 스타일을 적용하는 것이고, TransitionSet은 원하는대로 직접 만들 수 있습니다.

- changeBounds: 위치와 크기를 변경하는 애니메이션
- changeTransform: 배열의 회전과 크기를 변경하는 애니메이션
- changeClipBounds: 지정된 영역을 변경하는 애니메이션
- changeImageTransform: 이미지의 크기 및 배열을 변경하는 애니메이션
- android: transitionOrdering은 TransitionSet의 Transition들을 한 번에 동작시킬지 순차적으로 동작시킬지 설정하는 것입니다.

여러개의 뷰를 공유할 때는 뷰와 뷰의 이름을 조합하여 생성한 페어객체를 넣어주면 됩니다.

 

3. 카카오스토리 적용 사례

① 피드 → 글 상세 화면

- 이미지를 공유 요소로 사용

- 피드에서 데이터, 이미지 캐싱

- 피드에서 캐시된 데이터를 글 상세에 사용

- 애니메이션 완료 후 고화질의 이미지로 교체

- RoundTransition: 자연스러운 라운드 애니메이션

- FaceTransition: 얼굴 위주의 애니메이션

 

FaceTransition을 적용하지 않는다면? 

끊기는 느낌이 듭니다. 그 이유는 얼굴 크롭으로 인하여 메트릭스가 변경된 상태에서 화면전환을 하게 
되면 피드의 공유요소로 사용되는 뷰와 글상세의 공유요소로 사용되는 뷰의 메트릭스값이 달라졌기 때문입니다

 

② 피드 → 동영상 뷰

- 현재 프레임을 Bitmap으로 추출

- 추출된 Bitmap으로 애니메이션 시작

 

③ 피드 → 프로필 진입

- Circle Transition 생성

 

4. 이슈 및 해결

① 모서리의 라운드 이슈

- 모서리의 동그란 부분에 애니메이션이 적용되지 않아 화면 전환이 시작될 때 모서리가 나와있는 상태로 애니메이션이 시작되고 다시 돌아올 때도 화면전환이 완료된 후 바로 사라져서 발생한 이슈

- 원인: 화면 전환 시 라운드 처리가 되어 있지 않아 발생

- 해결: 별도의 RoundAnimation 만들어 라운드가 서서히 생기고 사라지는 애니메이션 효과를 줍니다

Transtion 클래스를 상속받은 RoundTransition클래스에서 captureStartValues, captureEndValues, createAnimator, animator 메소드를 구현하고 동시에 Round Animation을 반환하는 Round Animation 인터페이스를 구현합니다.
createAnimator 메소드가 호출되면 라운드 효과를 주는 RoundImageView에  radius값을 변경할 수 있는 Round Aimator를 생성하여 반환합니다. 반환되는 애니메이터는 안드로이드 플랫폼에서 화면 전환시 동작시키게 됩니다. RoundTransition을 TransitionSet에 적용하면 라운드효과가 적용됩니다.

 

② 연속클릭 이슈

- 연속클릭으로 인하여 스타트액티비티가 여러번 호출되었고 그 결과 액티비티가 여러개 생성되어 제일 마지막에 호출된 액티비티는 피드로 돌아가게 되는 애니메이션이 실행되지 않아 공유뷰가 사라지는 현상입니다

- 원인: startActivity가 여러번 발생, 공유뷰가 돌아오지 못해 뷰 사라짐 현상

- 해결: RxJava를 이용하여 클릭이벤트 흐름 제어, 여러 개의 뷰가 하나의 Observable에 이벤트 전달, throttleFirst 사용

 

③ 공유 뷰의 생성 지연

- 리사이클러뷰나 뷰페이저의 어댑터에서 뷰를 생성하는 부분들이 공유뷰의 생성을 지연시켜 애니메이션이 동작하지 못하는 현상입니다

- 원인: 공유 뷰의 생성 지연으로 애니메이션이 동작하지 못하고 화면 전환

- 해결: postponeEnterTransition() (화면 전환 지연), startPostponedEnterTransition() (화면 전환 시작)

 

해결에서 주의할 점은 postponeEnterTransition을 호출하면 startPostponedEnterTransition이 호출될때까지 화면전환이 멈춰있으므로 startPostponedEnterTransition가 꼭 호출될 수 있도록 코드를 작성해야 합니다

 

④ 종료 위치 찾지 못하는 이슈

- 피드에서 글 상세로 진입하고 글 상세에서 글을 수정하여 피드로 돌아가니 애니메이션이 위치를 정확히 잡지 못하는 이슈

- 원인: 데이터 변경으로 UI 갱신 후 재 생성, UI 재생성으로 인해 공유뷰 연결 끊김

- 해결: 공유에 사용한 뷰는 사라지지 않도록 관리, ViewPager adapter의 notifyDataSetChanged()를 쓰지 않고 직접 UI에 접근하여 뷰 갱신

반응형