본문 바로가기
프로그래밍 놀이터/안드로이드, Java

[android] Transition animations

by 돼지왕 왕돼지 2019. 1. 21.
반응형

[android] Transition animations


https://blog.stylingandroid.com/transition-animation-part-1/

addtransition, animationset, autotransition, begindelayedtransition, beginDelayedTransition multiple times, changebounds, changetext, ChangeTransform, Crossfade, Fade, Fade In, Fade Out, ORDERING_SEQUENTIAL, ordering_together, RECOLOR, rotate, scaleanimation, Scene, setordering, setreparent, slide, transition, transition animation, transition id, transitionanimation compat, transitionmanager, transitionset, translate animation, translatey, view static state, ViewOverlay, [android] Transition animations


-

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 을 수행한다.



-

cf) https://developer.android.com/reference/android/transition/TransitionManager.html#beginDelayedTransition(android.view.ViewGroup,%20android.transition.Transition)

동일한 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 만 가졌다.)




반응형

댓글