안녕하세요. Bucket Place의 개발자 Cloud Travel입니다.
오늘은 안드로이드를 사용하면서 애니메이션 리소스를 생성하고 적용하는 방법에 대해서 알아보도록 하겠습니다.
안드로이드에서는 사용자가 정의하여 다양한 에니메이션을 생성하고 활용이 가능합니다.
애니메이션을 사용하기 위해서 준비해야할 것이 있습니다.
첫번째로는 애니메이션을 저장할 공간을 만들어 주는 것입니다.
사용자가 정의한 에니메이션은 하나의 리소스로 저장이 되게 되는데, 프로젝트를 생성시에는 저장할 수 있는 공간이 없어서
공간을 새로 만들어 주셔야 합니다.
프로젝트를 생성한 후에 만들어진 res폴더(resource들을 저장하는 공간) 아래에
"anim"이라는 폴더를 하나 생성해줍니다.
다른 폴더명을 사용할 수는 없습니다. 왜냐하면, 안드로이드 시스템에 미리 정의된 명령에 의해서 리소스를 가져오는데, 애니메이션의 경우는 "anim"이 이에 해당합니다.
두번째로는 Frame Layout에 대한 기본적인 상식입니다.
Frame layout은 무지 간단한 레이아웃이지만 매우 강력한 기능을 제공해줍니다. 그 기능은 바로 "Overlay"가 가능하게 해주는 것입니다. 여러개의 View를 중첩해서 사용하여 뷰의 가시성만을 가지고 화면이 전환되는 효과를 낼 수도 있답니다. 애니메이션을 사용하는 페이지에서는 Frame layout을 많이 사용하는데 이는 옛날 필름영화나 만화를 제작하는 과정을 생각하면 쉽게 이해할 것입니다. 여러개의 사진, 그림 또는 이미지를 중첩시킨후 빠르게 움직이면 하나의 애니메이션이 탄생하게 됩니다.
자 이젠, 애니메이션을 정의해보도록 합시다. 위에서 준비한 /res/anim 폴더안에 자신이 원하는 이름으로 xml 파일을 생성해 주시면 됩니다. 하나의 애니메이션 당 하나의 파일이 생성한다고 보시면 됩니다. 파일을 생성한다면 아래에 나온 기본 형식(양식)을 작성해주시면 됩니다.
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
// 애니메이션을 실질적으로 정의하는 부분
</set>
수 많은 애니메이션 효과는 제가 설명하기엔 너무 방대하기 때문에 알고 있으면 유용한 애니메이션을 소개하도록 하겠습니다.
아래 애니메이션을 여러 개적용을 하여 하나의 애니메이션이 탄생하게 됩니다.
0. 공통적으로 사용되는 특성
- android:duration="정수" // 정수의 milisecond만큼의 시간을 갖고 애니메이션을 수행한다.
- android:repeatMode="reverse" // 반시계방향으로 다시실행을 한다.
- android:repeatCount="정수" // 정수만큼 애니메이션을 반복한다.
- 단위 기준은 "정수값"을 사용한다면 절대 좌표, "%"단위를 사용한다면 자신을 기준인 비율,
"%p"단위를 사용한다면 부모를 기준인 비율이다.
1. Translate
<translate
android:duration
=
"200"
android:fromXDelta
=
"-100%"
android:fromYDelta
=
"0%"
android:toXDelta
=
"0%"
android:toYDelta
=
"0%" />
- 예시설명 : 좌측에서 우측으로 전이시키는 애니메이션을 생성했다. 애니메이션 완료시간은 0.2초이다.
- From지점(좌표)에서 To지점(좌표)으로 이동을 시키는 애니메이션 입니다.
- 대부분은 %를 기준으로 하여 숨겼다 나오기, 또는 약간 이동하면서 생동감 표현에 사용을 한다.
2. Rotate
<
rotate
android:fromDegrees
=
"0"
android:toDegrees
=
"-45"
android:pivotX
=
"50%"
android:pivotY
=
"50%"
android:duration
=
"200"
/>
- 예시설명 : 중심좌표를 기준으로 0에서 -45도로 회전을 시킨다. 애니메이션 완료시간은 0.2초이다.
- From 각도에서 To 각도로 회전을 시키는 애니메이션 입니다.
- Point X, Y를 이용하여 회전을 시키는 중심각을 정할 수 있습니다.
3. alpha
<
alpha
android:fromAlpha
=
"1.0"
android:toAlpha
=
"0.0"
android:repeatCount
=
"3"
android:duration
=
"2000"
/>
- 예시설명 : 투명도가 1(불투명)에서 0(투명)으로 변환시키며, 이 행위를 3번 각 0.2초씩 수행한다. (빤짝빤짝~)
- 투명도를 From에서 to수치로 변환을 시켜준다.
- 수치는 1.0이 MAX(불투명)이고, 0.0이 MIN(투명)이다.
4. Scale
<
scale
android:fromXScale
=
"1.5"
android:toXScale
=
"0.0"
android:fromYScale
=
"1.5"
android:toYScale
=
"1.0"
android:pivotX
=
"50%"
android:pivotY
=
"50%"
android:duration
=
"200"
/>
- 예시설명 : 중심점을 기준으로 가로와 세로가 150%에서 0%로 변환한다. 만약, repeat이 있다면 요요같은 것도 만들 수 있다.
- From의 크기에서 To의 크기로 변경을 시킨다. 사이즈의 크기는 1.0을 본래의 사이즈로 잡는다.
- Point X, Y는 확대, 축소를 실행하는 기준 점이라고 생각하면된다.
*** 예시 : translate_left.xml ***
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="200"
android:fromXDelta="0%"
android:fromYDelta="0%"
android:toXDelta="-100%"
android:toYDelta="0%" />
<alpha
android:fromAlpha="1.0"
android:toAlpha="0.0"
android:duration="200"/>
</set>
지금까지 애니메이션을 정의하는 법에대해서 알아보았다. 이젠 이를 등록하고 사용하는 방법에 대해서 알아보도록하자.
1. 선언
- 애니메이션을 담고 사용할 변수를 선언해줍니다. 리스너를 달고 사용하는 경우도 있기 때문에, 클래스 변수로 선언해줍시다.
Animation [변수이름];
// ex) Animation menuOpen;
2. 등록
- 선언된 변수에 에니메이션을 등록해준다.
[변수 이름] = AnimationUtils.loadAnimation(this,R.anim.[xml파일 이름]);
// ex) menuOpen = AnimationUtils.loadAnimation(this, R.anim.translate_left);
// 위에서 예시로 만든 xml 사용을 기준으로...
3. 필요하다면 리스너를 등록해준다.
- 리스너는 자신이 새로 만들어준 리스너이다.
- 애니메이션이 동작하면서 함께 해야 할일을 정의해주면된다.
- 애니메이션 리스너 인터페이스 이름은 AnimationListener이다.
- 리스너를 생성하고, 리스너를 달아주면 끝~ 바로 예시만 보도록 하겠다.
- 인터페이스 메소드는 읽어보면 알수 있기 때문에 별도의 설명은 생략하기로 한다.
MenuSlideAnimationListener menuSlideListener = new MenuSlideAnimationListener();
mTranslateLeftAnim.setAnimationListener(menuSlideListener);
mTranslateRightAnim.setAnimationListener(menuSlideListener);
*** 예시 : MainActivity.java ***
public class BaseActivity extends Activity {
/* Menu slide bar variables */
boolean isMenuPageOpen = false; // Slide 페이지 Open여부
Animation mTranslateLeftAnim; // 메뉴 왼쪽 이동 에니메이션
Animation mTranslateRightAnim; // 메뉴 오른쪽 이용 에니메이션
LinearLayout menuSlide; // Slide page를 저장
/* End of variables Menu slide */
protected void onCreate(Bundle savedInstanceState,int layoutId) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/* menu bar slide */
menuSlide = (LinearLayout)findViewById(R.id.menuSlide);
mTranslateLeftAnim = AnimationUtils.loadAnimation(this, R.anim.menu_translate_left);
mTranslateRightAnim = AnimationUtils.loadAnimation(this, R.anim.menu_translate_right);
MenuSlideAnimationListener menuSlideListener = new MenuSlideAnimationListener();
mTranslateLeftAnim.setAnimationListener(menuSlideListener);
mTranslateRightAnim.setAnimationListener(menuSlideListener);
Button menuBtn = (Button)findViewById(R.id.menuBtn);
menuBtn.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
if ( isMenuPageOpen ) {
menuSlide.startAnimation(mTranslateLeftAnim);
}else{
menuSlide.setVisibility(View.VISIBLE);
menuSlide.startAnimation(mTranslateRightAnim);
}
}
});
/* end of menu bar & meun button */
}
private class MenuSlideAnimationListener implements AnimationListener {
@Override
public void onAnimationEnd(Animation arg0) {
if ( isMenuPageOpen ){
// page가 열려있다면, 보이지 않게 하고 닫아버린다.
menuSlide.setVisibility(View.INVISIBLE);
isMenuPageOpen = false;
}else{
// page가 닫혀있다면, 보이게 한다.
isMenuPageOpen = true;
}
}
@Override
public void onAnimationRepeat(Animation arg0) {
// TODO Auto-generated method stub
}
@Override
public void onAnimationStart(Animation arg0) {
// TODO Auto-generated method stub
}
}
}
이상으로 애니메이션을 만들고 다루는 법에 대해서 간략하게 알아 보았습니다.
부족한 부분도 많을 수 있습니다. 혹시나 질문이 있다면, 댓글이나 방명록에 남겨주길바랍니다.