[android] Transition animations |
https://blog.stylingandroid.com/transition-animation-part-1/
-
Kitkat(API 19) 부터 사용 가능한 새로운 transition API 가 있다.
( https://github.com/guerwan/TransitionsBackport 는 ICS (API 14)부터 지원가능한 compat open source )
기존의 transition 과 같은 일을 할 수 있고, 더 많은 일을 쉽게 추가할 수 있다.
-
예를 들어 박스 2개가 vertical 하게 놓여 있다고 하자. ( '=' 모양처럼 )
어느 박스던 클릭하면 위치를 바꾸는 애니메이션을 한다고 하면, 기존의 “translateY” 함수를 이용해주면 된다.
translateY 에 전달할 value 를 계산하고, animation 이 끝나면 이 박스를 포함한 layout 에서 실제 위치를 바꾸고 translation 을 제거해준다.
기존의 몇 단계의 step 을 새로운 transition API 를 이용하면 아주 쉽게 할 수 있다.
@Override public void onClick(View v) { int selectedBoxIndex = mContainer.indexOfChild(v); TransitionManager.beginDelayedTransition(mContainer, new ChangeBounds()); mContainer.removeView(v); mContainer.addView(v, selectedBoxIndex == 0 ? mContainer.getChildCount() : 0); }
-
우리가 새롭게 마딱뜨리는 녀석은 두가지.
TransitionManager 와 ChangeBounds 이다.
https://developer.android.com/reference/android/transition/TransitionManager.html
https://developer.android.com/reference/android/transition/ChangeBounds.html
ChangeBounds 는 Transition 을 상속했으며, Transition 은 animation type 을 정의하고, AnimatorSet 을 생성하는 역할을 맡는다.
ChangeBounds 는 target view 들의 layout bounds 전 후 상태를 capture 한 후 animation 을 생성한다. bounds 라는 단어에서 유추할 수 있듯이 scale 과 translate animation 을 생성한다.
TransitionManager.beginDelayedTransition(ViewGroup sceneRoot, Transition transition) 은 sceneRoot 의 현재 상태(current rendering frame)와 다음 상태(next rendering frame)를 감지해서 변화에 대해 animation 을 수행한다.
Transition 은 View 의 id 기반으로 작동하기 때문에 id 를 잘 명시해주어야 제대로 animation 이 작동한다.
이 예제에서는 현재 상태를 먼저 capture 하고, view hierarchy 가 변경되면 결과 value 를 다시 capture 한다.
그리고 나서 2개의 state 를 기준으로 AnimationSet 을 만들어 Animation 을 수행한다.
-
동일한 sceneRoot 에 beginDelayedTransition API 를 여러 번 부르면 첫 call 에 대한 상태만 저장하고 나머지 call 은 무시한다고 한다.
-
위의 코드의 단점은 공통 parent 를 가졌을 때만 잘 작동한다는 것.
-
Scene 이란 것이 있다. 이 녀석은 view 의 static state 를 참조하는 값이다.
이 Scene 을 이용해서 TransitionManager 가 transition 을 하게 할 수 있다.
아래 예는 box 를 3개 가지고 배치가 각각 다른 grid1, grid2, grid3 layout 가 있고,
grid1, grid2, grid3 간의 animation 을 Scene 을 통해 지원한다.
View view = inflater.inflate(R.layout.fragment_part2, container, false); mContainer = (ViewGroup)view.findViewById(R.id.container); mTxManager = new TransitionManager(); Transition transition = new ChangeBounds(); mScene1 = Scene.getSceneForLayout(mContainer, R.layout.grid1, context); // id 기반 작동 mScene1.setEnterAction(new Runnable() { // view inflate 를 보장한다 @Override public void run() { mScene1.getSceneRoot().findViewById(R.id.item2).setOnClickListener(Part2.this); mScene1.getSceneRoot().findViewById(R.id.item3).setOnClickListener(Part2.this); } }); … // mScene2, mScene3 정의 ... Transition transition = new ChangeBounds(); mTxManager.setTransition(mScene1, mScene2, transition); mTxManager.setTransition(mScene1, mScene3, transition); mTxManager.setTransition(mScene2, mScene1, transition); mTxManager.setTransition(mScene2, mScene3, transition); mTxManager.setTransition(mScene3, mScene1, transition); mTxManager.setTransition(mScene3, mScene2, transition); mScene1.enter(); // 첫 상태를 scene1 로 주고, click listener 를 주기 위해서 … @Override public void onClick(View v) { switch (v.getId()) { case R.id.item1: mTxManager.transitionTo(mScene1); // animation 수행 break; case R.id.item2: mTxManager.transitionTo(mScene2); // animation 수행 break; case R.id.item3: mTxManager.transitionTo(mScene3); // animation 수행 break; } }
-
ChangeBounds 외에도 Fade 도 있다.
두 Transition 을 한번에 수행하려면 TransitionSet 을 이용하면 된다.
TransitionSet 에 addTransition 메소드를 통해 transition 들을 넣어주면 된다.
add 된 transition 은 함께 작동한다. 순차적으로 수행되도록 바꾸려면 setOrdering() 을 이용하면 된다.
값은 ORDERING_TOGETHER 와 ORDERING_SEQUENTIAL 이 있다.
android framework 에는 이 둘을 묶어놓은 AutoTransition 이라는 것이 존재해서 이 녀석을 쓰면 편하다. ( Fade Out, ChangeBounds, Fade In 순서 )
-
그 외에도 ChangeText, Crossfade, Recolor, Rotate, Slide 등이 있다.
-
Transition 의 계산은 parent layout 으로부터 계산이 된다.
그래서 View 의 repositioning 이 parent 를 바꾼다면 애니메이션이 이상하게 된다.
ChangeBounds 에는 parent change 를 support 해주는 함수가 있다.
transition.setReparent(true) 를 줌으로서 현상 완화를 시킬 수 있다.
https://developer.android.com/reference/android/transition/ChangeBounds.html#setReparent(boolean)
( 이는 API 21 에서 deprecate. ChangeTransform 을 쓰라고 가이드한다. )
-
ChangeBounds 는 ViewOverlay 를 사용한다.
이 녀석은 Animation 전용 View 라고 보면 된다. (Bitmap 만 가졌다.)
'프로그래밍 놀이터 > 안드로이드, Java' 카테고리의 다른 글
[android] Curved motion (0) | 2019.01.23 |
---|---|
[android] 변경이 잦은 gradle 설정 분리하기 (0) | 2019.01.22 |
[android] Snackbar 를 써보자 (0) | 2019.01.20 |
[Android] SMS Retriever API - SMS 권한 없이 인증번호 읽어오기! (0) | 2019.01.18 |
연락처 계정 생성시 OEM 에서 연락처에서 추가/편집 가능한 Field 정의 (0) | 2019.01.17 |
댓글