화면 회전에 따른 애니메이션 효과 구현하기

by 조쉬 posted Jul 16, 2015
?

단축키

Prev이전 문서

Next다음 문서

ESC닫기

크게 작게 위로 아래로 댓글로 가기 인쇄

아이폰이나 안드로이드 단말기 사진 뷰어 등에서 단말기를 회전하면, 
단말기 속의 사진도 같이 회전을 하는 효과를 볼 수 있습니다.
애니메이션 효과와 함께 빙그르르 회전하는 모습을 보여주죠.

안드로이드에서 기본적으로 이 애니메이션 효과를 제공해주면 좋은데, 아무리 찾아봐도 도저히 모르겠더군요.
그래서 결국 직접 구현해보기로 마음 먹었습니다.


안드로이드에서 단말기의 회전을 감지하기 위해서는 몇 가지 설정이 필요합니다. 
(아마 기본적으로 시스템의 회전 잠금 설정을 따라서 자동으로 세팅되어 있을 겁니다.)
각 액티비티마다 다른 설정을 하기 위해서는 AndroidManifest.xml 파일을 건드려줍니다.

<activity

android:name=".activity.actImagePlayer"

android:configChanges="orientation"

android:launchMode="singleTop">

<intent-filter>

<action

android:name="android.intent.action.MAIN" />

</intent-filter>

</activity>

 

이런 식으로 화면 회전 변화를 감지할 수 있도록 미리 세팅을 해줍니다. 

그 다음부터는 각 액티비티에서 
public void onConfigurationChanged(Configuration newConfig) 함수를 통해서 화면 회전 이벤트를 획득할 수 있습니다.

다음과 같은 코드를 작성 할 수 있는거죠.

01.@Override
02.public void onConfigurationChanged(Configuration newConfig)
03.{
04.    // TODO Auto-generated method stub
05.    if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT)
06.    {
07.        setContentView(R.layout.act_image_player_layout);
08.    }
09.    else
10.    {
11.        setContentView(R.layout.act_image_player_layout_landscape);
12.    }
13.     
14.    m_ImageGallery.SetOrientation(newConfig.orientation);
15.    RotateImageGallery();
16.     
17.    Initialize();
18.     
19.    super.onConfigurationChanged(newConfig);
20.}

실제로 작동하는 코드의 일부분만 가져왔기 때문에 이 코드를 그대로 사용할 수는 없습니다. 
다만, 여기서 중요한 부분은  newConfig.orientation의 값을 이용해서 현재 화면 상태가 portrait 모드인지 landscape 모드인지를
체크할 수 있는 부분입니다. 그에 따라 레이아웃도 다르게 설정할 수도 있습니다. 
복잡하지 않은 프로그램이라면 굳이 레이아웃을 따로 가져갈 필요는 없습니다.


자, 여기까지는 아주 기본적인 형태입니다. 아무런 애니메이션 효과도 없으며, 단지
화면을 기울이면 그냥 화면이 회전된 모습만 보여줄 뿐이죠. 부드럽게 화면이 돌아가는 효과는 없습니다.


화면이 돌아가는 효과를 주기 위해서 안드로이드의 애니메이션 기능을 활용했습니다. 
각 애니메이션들을 미리 xml로 만들어놓고 화면이 회전할 때 각 애니메이션 효과를 적용했습니다.


미리 만들어놓은 애니메이션들은 다음과 같습니다. 
photoviewer_rotate_to_left.xml

<?xml version="1.0" encoding="utf-8"?>

<set 

xmlns:android="http://schemas.android.com/apk/res/android"

android:interpolator="@android:anim/accelerate_decelerate_interpolator">

<rotate

 android:fromDegrees="90"

 android:toDegrees="0"

 android:pivotX="50%"

 android:pivotY="50%"

 android:duration="300"/>

</set>



photoviewer_rotate_to_right.xml

<?xml version="1.0" encoding="utf-8"?>

<set 

xmlns:android="http://schemas.android.com/apk/res/android"

android:interpolator="@android:anim/accelerate_decelerate_interpolator">

<rotate

 android:fromDegrees="-90"

 android:toDegrees="0"

 android:pivotX="50%"

 android:pivotY="50%"

 android:duration="300"/>

</set>

애니메이션 효과가 1개뿐이라 굳이 <set> 태그를 사용하지 않아도 되지만,
나중에 다른 애니메이션 효과들을 적용할 수도 있기 때문에 확장성을 생각해볼 때, <set> 태그로 한 번 감싸는
습관을 기르는 것도 나쁘지 않은 것 같습니다.


그리고 java 코드에서 각각의 경우를 체크해서 위에서 작성한 애니메이션 효과를 적용합니다.

현재 화면의 방향 정보를 획득하는 함수는 다음과 같이 구현할 수 있습니다.

1.private int GetCurrentRotation()
2.{
3.    WindowManager windowManager = (WindowManager)getSystemService(Context.WINDOW_SERVICE);
4.    Display display = windowManager.getDefaultDisplay();
5. 
6.    return display.getRotation();
7.}

이렇게 획득한 값은 Integer 정수값이며, 각각

Surface.ROTATION_0
Surface.ROTATION_90
Surface.ROTATION_180 
Surface.ROTATION_270

으로 사용할 수 있습니다. 


화면이 회전하는 방향을 알기 위해서 이전 회전값과 현재 회전값을 비교해서 방향을 정하는 방식으로 코드를 작성했습니다.  

01.private void RotateImageGallery()
02.{
03.    Animation anim_left = AnimationUtils.loadAnimation(this, R.anim.photoviewer_rotate_to_left);
04.    Animation anim_right = AnimationUtils.loadAnimation(this, R.anim.photoviewer_rotate_to_right);
05.     
06.    int nCurrentRotation = GetCurrentRotation();
07.    if (((m_nOldRotation == Surface.ROTATION_0) && (nCurrentRotation == Surface.ROTATION_90))
08.        || ((m_nOldRotation == Surface.ROTATION_270) && (nCurrentRotation == Surface.ROTATION_0))
09.        || ((m_nOldRotation == Surface.ROTATION_270) && (nCurrentRotation == Surface.ROTATION_90)))
10.    {
11.        m_ImageGallery.startAnimation(anim_right);
12.    }
13.    else if (((m_nOldRotation == Surface.ROTATION_0) && (nCurrentRotation == Surface.ROTATION_270))
14.        || ((m_nOldRotation == Surface.ROTATION_90) && (nCurrentRotation == Surface.ROTATION_0))
15.        || ((m_nOldRotation == Surface.ROTATION_90) && (nCurrentRotation == Surface.ROTATION_270)))
16.    {
17.        m_ImageGallery.startAnimation(anim_left);
18.    }
19.     
20.    m_nOldRotation = nCurrentRotation;
21.}

대략 이 정도의 코드면, 화면이 회전하는 효과를 어느 정도 구현할 수 있습니다.

여기에 화면이 180도 회전하는 것에 대한 효과도 따로 xml로 만들어서 적용할 수 있지만, 저는 그냥 90도 회전하는 것으로
때워버렸습니다. ^^;;