* 안드로이드에서의 에니메이션은 전통적인 프레임 방식 에니메이션과
Tweening 을 통한 에니메이션 방식이 있다.
* 에니메이션
안드로이드는 아이폰과 같이 뷰의 간단한 변형에 관련한 에니메이션 처리를 지원한다.
레이아웃 에니메이션과 각 구성요소의 에니메이션으로 나눌수 있다.
처리할 수 있는 에니메이션은 아래와 같으며, 코드상에서의 클래스명이다.
AlphaAnimation - 투명도 변환
RotateAnimation - 회전
ScaleAnimation - 크기 변환
TranslateAnimation - 위치 이동
* 이 클래스들은 android.view.animation.Animation 의 하위 클래스이다. 즉, Animation 객체를
상속받아 다양한 에니메이션을 구현할 수 있다.
이번 포스트에서는 이미 구현되어 있는 에니메이션만 언급한다.
1. xml 정의
에니메이션 순서를 XML 로 정의해 놓고, 해당 XML 을 불러 에니메이션을 동작케 하는 형태로
구성되는데 프로젝트내의 res/anim/ 폴더에 정의된다.
아마도 가장 많이 사용되는게 페이드 인일것 같은데..아닌가? 음..
암튼 페이드인의 경우 알파 에니메이션을
사용하면 된다.
페이드인 에니메이션
<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/accelerate_interpolator"
android:fromAlpha="0.0"
android:toAlpha="1.0"
android:duration="300" />
해당 에니메이션을 지정하고, 각 값들을 설정하는 것으로 끝이다..
페이드 인은 투명값이 0에서 완전 투명인 1로 이동하는 것을 말하는데,
fromAlpha="0.0" / toAlpha="1.0" 으로 페이드 인
반대로 아래와 같은 경우는 페이드 아웃 에니메이션이다.
<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/accelerate_interpolator"
android:fromAlpha="1.0"
android:toAlpha="0.0"
android:duration="300" />
각 에니메이션별로 속성값이 있는데,
alpha
fromAlpha
toAlpha
scale
fromXScale
toXScale
fromYScale
toYScale
pivotX
pivotY
fillAfter
fillBefore
rotate
fromDegrees
toDegrees
toYScale
pivotX
pivotY
startOffset
translate
toXDelta
toYDelta
등 에니메이션에 따른 속성이 정의되어 있다.
만약 여러 에니메이션을 설정하고 한다면
<set> 태그를 사용할 수 있다.
왼쪽에서 미끄러져 나오는 에니메이션과 회전 에니메이션
<set xmln:android:="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/accelerate_interpolator"
<translate android:fromXDelta="100%p"
android:toXDelta="0"
android:duration="150" />
<rotate andriod:fromDegrees="0"
android:toDegrees="90"
android:fillAfter="true"
android:startOffset="800"
android:duration="150" />
</set>
이처럼 <set> 태그로 여러 에니메이션을 정의할 수 있고, 각각의 에니메이션에
공통적으로 적용할 내용을 set 에서 지정할 수 있다. 위의경우 duration이 동일하므로
<set android:duration="150"
으로 공통사항으로 지정해도 된다.
// ApiDemos 의 회전 에니메이션 xml 예제
<set
android:shareInterpolator="false">
<scale
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:fromXScale="1.0"
android:toXScale="1.4"
android:fromYScale="1.0"
android:toYScale="0.6"
android:pivotX="50%"
android:pivotY="50%"
android:fillAfter="false"
android:duration="700" />
<set
android:interpolator="@android:anim/decelerate_interpolator">
<scale
android:fromXScale="1.4"
android:toXScale="0.0"
android:fromYScale="0.6"
android:toYScale="0.0"
android:pivotX="50%"
android:pivotY="50%"
android:startOffset="700"
android:duration="400"
android:fillBefore="false"
/>
<rotate
android:fromDegrees="0"
android:toDegrees="-45"
android:toYScale="0.0"
android:pivotX="50%"
android:pivotY="50%"
android:startOffset="700"
android:duration="400"
/>
</set>
</set>
참조 : interpolator
관련포스트
2. 코드로 에니메이션 구현
코드상에서는 AnimationSet 객체를 선언해 기본 설정을 하고,
각 에니메이션에 해당하는 객체를 설정해 addAnimation() 을 하면 해당 순서대로 에니메이션이 설정된다.
AnimationSet set = new AnimationSet( true );
set.setInterpolator( new AccelerateInterpolator() );
// 각 에니메이션별로 클래스가 존재한다. 페이드인의 경우 AlphaAnimation()
Animation animation = new AlphaAnimation( 0.0f, 1.0f );
animation.setDuration(100);
set.addAnimation(animation);
.
.
.
// xml 과 동일하게.. 하나의 에니메이션은 Animation 객체만 생성하면 되나
// 여러개의 에니메이션은 AnimationSet 객체에 연결한다.
// 에니메이션 설정
this.setAnimation(set);
3. 코드에서 XML 에니메이션 부르기
xml에 정의한 에니메이션 정보를 설정하려면 AnimationUtils 객체를 사용해 해당 에니메이션에 바로 설정할 수 있다.
일단... 에니메이션이 두가지가 있는데..
레이아웃이 구성되고 화면에 보일때 레이아웃과 각 차일드에 대한 에니메이션을 설정하는것과
수행 중 뷰들의 에니메이션을 설정하는 것.
Animation animation = AnimationUtils.loadAnimation( context, R.anim.ani_name );
4. 에니메이션 보이기
어찌되었건 에니메이션이 설정되었으면 해당 에니메이션을 동작시켜야 한다.
animationset, animation 동일하게 아래와 같이 시작시킬수 있다.
View.startAnimation( animation );
5. AnimationListener
에니메이션관련 이벤트를 수신하기 위해 setAnimationListener() 를 통해
리스너를 등록할 수 있다.
수신할 수 있는 이벤트는 에니메이션 종료, 반복,시작에 해당하는 이벤트이다.
일반적인 리스너처럼 익명 클래스로~
Animation ani = new AlphaAnimation( 0.0f, 1.0f );
ani.setAnimationListener( new AnimationListener() {
@Override
public void onAnimationEnd(Animation arg0) {
}
@Override
public void onAnimationRepeat(Animation arg0) {
}
@Override
public void onAnimationStart(Animation arg0) {
}
});
6. 레이아웃 에니메이션
뷰에니메이션과 같은 형태로 구성한다. 단, 아래의 에니메이션은 레이아웃 자체의 움직임과는 관계가 없고, 하위 뷰의 추가시 해당 에니메이션이 발생하게 된다.
* xml에 구성
res/anim/에니메이션명.xml
페이드되면서 나타나는 아이템의 경우 아래와 같이 작성한다.
<layoutAnimation xmlns:android=http://schemas.android.com/apk/res/android
android:delay=""
android:animationOrder="random" // reverse
android:animation="@anim/에니메이션" />
해당 레이아웃에니메이션을 적용하고자 하는 레이아웃에 지정.
<ListView
.
android:layoutAnimation="@anim/에니메이션명"
.
./>
* 코드에서 구성
// 레이아웃이나 에니메이션셋의 경우 컨트롤러가 필요하다. 단일한 뷰에니메이션은 필요없음.
LayoutAnimationController controller = new LayoutAnimationController( animation, 0.25f );
에니메이션 지정
ViewGroup.setLayoutAnimation( controller );
* 프레임 에니메이션
drawable 객체를 매 프레임단위로 변경해 에니메이션 효과를 나타내는 방식이다.
<animation-list> 태그를 사용해 구현되며, 각 항목을 <item> 태그로 정의하면 된다.
1. 레이아웃 구현
ex) simple_animation.xml
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="false">
<item android:drawable="@drawable/image1"
android:duration="50" />
<item android:drawable="@drawable/image2"
android:duration="50" />
</animation-list>
메인 레이아웃에 프레임 에니메이션이 표시될 ImageView를 하나 설정한다.
main.xml
<ImageView android:id=@+id/simple_ani"
android:layout_width="wrap_content"
android:layout_height="wrap_contnet"
android:gravity="center"
android:layout_centerHorizontal="true"
/>
2. 소스 구현
// 우선 이미지뷰를 얻어온다.
ImageView img = (ImageView) findViewById(R.id.simple_ani );
// 해당이미지 뷰의 배경을 에니메이션으로 지정
img.setBackground( R.anim.simple_animation );
에니메이션은 별도의 쓰레드로 구동되어야 하므로, 쓰레드나 TimerTask 혹은
리스너를 통한 콜백을 사용해 에니메이션을 동작시켜 준다.
ex) 타이머를 사용한 구현
MyAnimationTask task = new MyAnimationTask();
Timer t = new Timer(false);
t.schedule( task, 100 );
class MyAnimationTask extends TimerTask
{
public void run() {
ImageView img = (ImageView) findViewById( R.id.simple_ani );
AnimationDrawable frameAni = (AnimationDrawable) img.getBackground();
frameAni.start();
}
};
이처럼 별도의 쓰레드 클래스를 구성하고, 해당 쓰레드에서
AnimationDrawable 객체를 설정해주고 start() 메쏘드를 호출하면 된다.
중지의 경우도 별도의 태스크를 구동시켜 현재 재생중인 에니메이션을 가져온뒤
stop() 메쏘드를 호출해준다.
public void run() {
ImageView img = (ImageView) findViewById( R.id.simple_ani );
AnimationDrawable frameAni = (AnimationDrawable) img.getBackground();
frameAni.stop();
}