반응형
블로그 이미지
개발자로서 현장에서 일하면서 새로 접하는 기술들이나 알게된 정보 등을 정리하기 위한 블로그입니다. 운 좋게 미국에서 큰 회사들의 프로젝트에서 컬설턴트로 일하고 있어서 새로운 기술들을 접할 기회가 많이 있습니다. 미국의 IT 프로젝트에서 사용되는 툴들에 대해 많은 분들과 정보를 공유하고 싶습니다.
솔웅

최근에 올라온 글

최근에 달린 댓글

최근에 받은 트랙백

글 보관함

카테고리


반응형


그러면 이번시간에는 TweeningAnimAppActivity.java 파일을 분석해 보겠습니다.


public class TweeningAnimAppActivity extends Activity {
    ImageView imgView;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_tweening_anim_app);
        Button alphaButton = (Button) findViewById(R.id.alpha_button);
        Button rotateButton = (Button) findViewById(R.id.rotate_button);
        Button scaleButton = (Button) findViewById(R.id.scale_button);
        Button translateButton = (Button) findViewById(R.id.translate_button);
        imgView = (ImageView)findViewById(R.id.imgview);
        rotateButton.setOnClickListener(new View.OnClickListener() {  
             @Override
             public void onClick(View v) {
                 RotateAnimation animation = new RotateAnimation(0,180, Animation.RELATIVE_TO_SELF,0.0f, Animation.ABSOLUTE, 0.2f);
                 animation.setDuration(3000);
                 imgView.setAnimation(animation);
                 animation.start();
             }
         });

        alphaButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Animation animation = new AlphaAnimation(1.0f, 0.1f);
                animation.setDuration(3000);
                imgView.setAnimation(animation);
                animation.start();
            }
        });

        scaleButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                AnimationSet set = new AnimationSet(true);
                Animation animation1 = new ScaleAnimation(1.0f, 2.0f,1.0f, 2.0f,Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
                animation1.setDuration(3000);
                set.addAnimation(animation1);
                Animation animation2 = new ScaleAnimation(1.0f, 0.5f, 1.0f, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
                animation2.setDuration(3000);
                animation2.setStartOffset(3000);
                set.addAnimation(animation2);
                imgView.startAnimation(set);
            }
        });
        translateButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                AnimationSet set = new AnimationSet(true);
                Animation animation1 = new TranslateAnimation(0,-150,0,0);
                animation1.setDuration(3000);
                animation1.setFillAfter(true);
                set.addAnimation(animation1);
                Animation animation2 = new TranslateAnimation(0,0,0,200);
                animation2.setDuration(3000);
                animation2.setStartOffset(3000);
                animation2.setFillAfter(true);
                set.addAnimation(animation2);
                imgView.startAnimation(set);
            }
        });
    }
}




우선 첫 줄에는 ImageView 를 초기화 시켰습니다.

이 ImageView에 애니메이션 효과를 적용할 겁니다.

그 다음 onCreate() 메소드를 봐야겠죠.
이전 글에서 다뤘던 activity_tweening_anim_app.xml 을 ContentView 로 세팅했습니다.
버튼 4개와 1개의 이미지뷰로 구성된 RelativeLayout 이었죠.

그 다음에는 버튼 4개에 대한 객체를 만들었습니다.
xml 에 있는 이런 view를 객체로 만들때는 findViewById()를 사용하죠.
그리고 아까 초기화 했던 imgView 객체도 만들구요.

그 다음에는 4개의 버튼들에 리스너를 달아주는 부분입니다.

rotateButton을 클릭했을 때는 어제 봤던 RotateAnimation 클래스를 실행시켜 줍니다.
애니메이션 시간은 3초로 하고 이 애니메이션은 imgView에 적용합니다.
마지막 animation.start()를 호출해서 실제 애니메이션을 실행합니다.

alphaButton에는 AlphaAnimation()클래스를 호출하는 부분을 넣었습니다.
그 이후는 rotateButton과 같습니다.

scaleButton에는 위와 다른 부분이 있네요.
처음에 AnimationSet()에 대한 객체를 만들었습니다.
그리고 ScaleAnimation()를 3초간 실행한다는 것을 AnimationSet에 add를 하구요.
그 다음에 다시 ScaleAnimation() 을 3초간 실행하고 3초간 StartOffset()을 실행한다는 것을 AnimationSet 에 add를 했습니다.
마지막에는 이 AnimationSet를 start 했구요.

setStartOffset()은 해당 시간만큼 지연해서 애니메이션을 시작한다는 겁니다.
그러니까 여기서는 첫번째 ScaleAnimation()이 3초간 이뤄지니까 그 3초가 지난다음에 두번째 ScaleAnimation()이 시작된다는 얘기죠.

transateButton에도 AnimationSet 가 적용이 됐는데요. 여기는 또 다른 setFillAfter(true) 가 있습니다.
이것을 true로 하게 되면 애니메이션이 끝난 다음에 다시 원래 위치로 돌아가지 않고 종료된 위치에 정지해 있는 겁니다.
여기서는 첫번째 TranslateAnimation() 은 왼쪽으로 150 만큼 3초간 가고 그 다음은 아래로 200만큼 3초간 움직일 것 같네요.
첫번째 애니메이션이 끝난 후 그 끝난 위치에서 이 ImageView가 아래로 움직일 겁니다.
다시 원위치로 가서 아래로 움직이는게 아니라요.
ㄱ 자를 거울로 본 모양으로 ImageView가 움직이겠네요.

이 앱을 실행하면 아래와 같은 화면이 나옵니다.



처음에 Alpha 버튼을 누르면 그림이 3초간 점점 흐려졌다가 다시 원래로 돌아옵니다.
new AlphaAnimation(1.0f, 0.1f)
이게 그렇게 만든건데요.
1.0 에서 0.1 까지 투명도가 변한다는 겁니다.
이건 간단하게 이해할 수 있습니다.
숫자를 반대로 주면 흐린상태에서 점점 뚜렷한 상태로 변하게 되겠죠.
앱 시작할 때 로고를 이렇게 흐리게 했다가 다시 진하게 하는 효과를 줄 수도 있을 것 같네요.

두번째 Rotate 는 이미지를 가운데를 중심으로 바람개비 돌듯이 한바퀴 돌리는 겁니다.
예전에 제가 Spin the Bottle 앱을 만들 때 이 애니메이션으로 구현하려고 막 노력한적이 있었습니다.
막 for문 써서 계속 돌아가다가 일정 시간 지나면 천천히 돌다가 멈추도록 하는거요.

그러다가 이 애니메이션가지고는 Reality 를 살리지 못하겠다고 판단해서 다른 방법을 찾았습니다.
저는 SurfaceView를 사용해서 Spin the Bottle 에서 병 돌아가는 효과를 주었습니다.

어쨌든 이 RotateAnimation() 도 필요할 때가 있을 텐데요.
RotateAnimation animation = new RotateAnimation(0,360, Animation.RELATIVE_TO_SELF,0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
파라미터를 보면요.
처음 두 파라미터인 0도에서 360도 돈다는 것은 쉽게 이해할 수 있습니다.
세번째 파라미터는 해당 object가 돌아가는 중심이라고 했습니다. pivotXType인데요. 여기는 정수형이 들어갑니다.
이 값이 0이면 왼쪽을 나타냅니다.
여기에 들어가는 값은 Animation.ABSOLUTE와 Animation.RELATIVE_TO_SELF, Animation.RELATIVE_TO_PARENT. 등이 있습니다.
이 소스에는 Animation.RELATIVE_TO_SELF 가 적용됐는데요. 그 값은 1 입니다.
이 1이 적용됐을 때 그 객체는 자신의 가운데 포인트를 중심으로 Rotate 하게 됩니다. 바람개비처럼요.
이것을 Animation.ABSOLUTE로 바꿔주면 이미지 왼쪽을 중심으로 이미지가 한바퀴 빙 돌게 됩니다.
이 Animation.ABSOLUTE의 값이 0입니다.
다음에 나오는 Animation.RELATIVE_TO_PARENT 의 값은 2 입니다.
이 값을 여기에 넣으면 이미지가 아니라 화면의 오른쪽 끝을 중심으로 크게 원을 도네요.
여기에 Integer가 들어갈 수 있으니까 제가 한번 3도 넣어보고 4도 넣어 봤거든요.
그랬더니 0 (Animation.ABSOLUTE) 일때와 같은 결과가 나오네요.


그 다음 파라미터는 pivotXvalue 인데 여기서는 0.5f가 설정됐습니다.
이것을 0.9로 한번 바꾸면 어떻게 될까요?
그러면 바람개비 처럼 돌던것이 이미지 오른쪽을 중심으로 도네요.
아까 pivotXType을 Animation.ABSOLUTE로 했을 때 이미지 왼쪽을 중심으로 도는것과 딴 반대의 경우입니다.
1.5로 하면 이미지의 더 오른쪽을 중심으로 돌구요.
그 이후에 나오는 Parameter 인 pivotYType과 pivotYvalue 도 x,y 축만 바꿔서 비슷한 효과를 줍니다.
이 값들을 이것 저것 여러개 바꿔봤는데요.

이 애니메이션을 가지고 flipping 효과를 줄 수는 없겠네요.
이 방법은 다른데서 찾아봐야겠습니다.

그리고 에뮬레이터로 실행하니까 시간이 오래 걸려서 다양한 시도는 못 해 보겠습니다.

다음으로 ScaleAnimation()을 보죠.

ScaleAnimation(1.0f, 2.0f,1.0f, 2.0f,Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
처음부터 4번째까지의 파라미터들은 fromX,toX,fromY,toY 입니다.
그러니까 전체적으로 이미지가 2배 커지게 되겠네요.
그 다음 4개는 위 RotateAnimation 과 마찬가지로 pivotXType,pivotXvalue,pivotYType,pivotYvalue 입니다.
이것도 Scaling의 중심부분을 잡아주는 파라미터들입니다.

그 다음에 나오는 translate 애니메이션을 보죠.
TranslateAnimation(0,-150,0,0);
fromXDelta,toXDelta,fromYDelta,toYDelta 입니다.
이미지의 출발과 종료 지점을 나타내는 겁니다.
위의 값은 toXDelta만 -150이니까 왼쪽으로 150만큼 이동한다는 의미입니다.

flipping 애니메이션 효과를 찾으려고 하다가 보게 된 Tweening Animation 예제였었는데요.
어쨌던 이 4가지 안드로이드에서 제공하는 애니메이션 클래스에 대해 자세하게 배운것 같습니다.

이건 여기서 만족하고 책이나 인터넷 써칭을 통해서 flipping 효과를 어떻게 낼지에 대해서 더 research 해 봐야 겠습니다.



반응형


반응형

지금 참여하고 있는 프로젝트에서 TDD 관련 Role 을 맡고 있는데요.

안드로이드 Tablet 용 Native 애플리케이션 개발쪽 Role 을 맡을 수도 있을 것 같아서 얼마전 책 두권을 샀습니다.

그 중 하나가 B.M. Harwani 가 지은 The Android Tablet Developer's Cookbook 입니다.


기왕 샀으니 열심히 공부해야겠죠.


오늘은 책장을 넘기다가 눈에 띄는 부분을 공부하려구요.

Chapter 8에 있는 Tweening Animation 인데요.

이 앱을 공부해 보겠습니다.


이 앱에는 4가지 타입의 애니메이션이 있습니다.


Alpha animation - view 의 투명도를 바꿈

Rotate animation - 주어진 pivot point 나 axis 를 중심으로 특정 각도로 view를 rotate 시킴

Scale animation - X나 Y 축을 중심으로 view 를 축소하거나 확대 함.

Translate animation - X나 Y 축을 따라서 view를 움직임


원래 view 를 flipping 시키는 효과를 어디서 찾아보던 중이었거든요.

Rotate animation 이 바로 제가 원하는 효과인지 한번 봐야겠습니다.


그럼 일단 layout xml인 activity_tweening_anim_app.xml을 보겠습니다.


<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
    <ImageView android:id="@+id/imgview"
        android:layout_width="@dimen/image_width"
        android:layout_height="@dimen/image_height"
        android:src="@drawable/ic_launcher"
        android:layout_centerInParent="true" />
    <Button
        android:id="@+id/alpha_button"
        android:text="Alpha"
        android:textSize="@dimen/text_size"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"  />
    <Button
        android:id="@+id/rotate_button"
        android:text="Rotate"
        android:textSize="@dimen/text_size"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@id/alpha_button" />
    <Button
        android:id="@+id/scale_button"
        android:text="Scale"
        android:textSize="@dimen/text_size"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
         android:layout_toRightOf="@id/rotate_button" />
    <Button
        android:id="@+id/translate_button"
        android:text="Translate"
        android:textSize="@dimen/text_size"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@id/scale_button"  />
</RelativeLayout>



전체 Layout 은 RelativeLayout 으로 감쌌습니다.

그리고 그 안에 1개의 ImageView와 4개의 Button들이 있습니다.

각 버튼마다 위에 소개한 4개의 효과 중 하나를 동작하도록 할 거 같습니다.

각 view 마다 모두 id 가 있죠? 나중에 java에서 갖다가 사용할 겁니다.

각 뷰마다 size는  @dimen/ 으로 시작하는데 이것은 res-values 폴더 아래에 있는 dimens.xml 안에 설정한 값을 사용하겠다는 겁니다.


dimens.xml


<?xml version="1.0" encoding="utf-8"?>
<resources>
    <dimen name="text_size">14sp</dimen>
        <dimen name="image_width">100dp</dimen>
    <dimen name="image_height">120dp</dimen>
</resources>


이 크기들은 일반 phone 크기에 맞춘 것입니다. 


이 소스를 보면 values-sw600dp 라는 폴더가 있는데요. 이 안에 있는 dimens.xml을 보면 아래와 같습니다.


<?xml version="1.0" encoding="utf-8"?>
<resources>
    <dimen name="text_size">24sp</dimen>
        <dimen name="image_width">140dp</dimen>
    <dimen name="image_height">160dp</dimen>
</resources>


이것은 7인치 타블렛 용입니다.

그리고 values-sw720dp 는 10 인치 이상의 tablet 을 위한 겁니다.


<?xml version="1.0" encoding="utf-8"?>
<resources>
    <dimen name="text_size">32sp</dimen>
        <dimen name="image_width">180dp</dimen>
    <dimen name="image_height">200dp</dimen>
</resources>


크기의 비율을 잘 봐 두면 나중에 실무에 도움을 받을 수 있겠네요.

이렇게 설정을 해 놓으면 각 device 마다 해당 해상도에 맞는 dimens.xml 을 갖다가 쓰게 됩니다. 다양한 크기의 해상도를 가진 안드로이드 앱을 개발할 때는 이런 구성을 미리 생각하고 프로그래밍에 들어가야 겠습니다.


아까 소개했던 4개의 애니메이션 효과들은 각각 해당 class 를 가지고 있습니다.


* AlphaAnimation


먼저 AlphaAnimation 을 보겠습니다.


이 클래스는 view의 투명도를 조절하기 위해 만든 건데요. 그 구성은 아래와 같습니다.


public AlphaAnimation(float from_alpha, float to_alpha)


여기서 첫번째 파라미터인 from_alpha 는 이 애니메이션이 시작할 때의 alpha 값입니다. 값은 0.0에서 1.0까지 설정할 수 있습니다.  1.0은 제일 선명한 거고 0.0은 완전 투명한 겁니다.

두번째 파라미터인 to_alpha 는 이 애니메이션이 끝날 때의 alpha 값입니다.


예를 들어 Animation animation = new AlphaAnimation(1.0f,0.1f) 라고 선언하면 아주 뚜렷한 이미지에서 거의 투명한 이미지로 바뀌게 되겠죠.



* TranslateAnimation


이 클래스는 view를 움직이도록 합니다. syntax는 아래와 같습니다.


public TranslateAnimation (float fromXDelta, float toXDelta, float fromYDelta, float toYDelta)

fromXDelta Change in X coordinate to apply at the start of the animation
toXDelta Change in X coordinate to apply at the end of the animation
fromYDelta Change in Y coordinate to apply at the start of the animation
toYDelta Change in Y coordinate to apply at the end of the animation



* RotateAnimation


public RotateAnimation (float fromDegrees, float toDegrees, int pivotXType, float pivotXValue, int pivotYType, float pivotYValue)

Parameters
fromDegrees Rotation offset to apply at the start of the animation.
toDegrees Rotation offset to apply at the end of the animation.
pivotXType Specifies how pivotXValue should be interpreted. One of Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, or Animation.RELATIVE_TO_PARENT.
pivotXValue The X coordinate of the point about which the object is being rotated, specified as an absolute number where 0 is the left edge. This value can either be an absolute number if pivotXType is ABSOLUTE, or a percentage (where 1.0 is 100%) otherwise.
pivotYType Specifies how pivotYValue should be interpreted. One of Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, or Animation.RELATIVE_TO_PARENT.
pivotYValue The Y coordinate of the point about which the object is being rotated, specified as an absolute number where 0 is the top edge. This value can either be an absolute number if pivotYType is ABSOLUTE, or a percentage (where 1.0 is 100%) otherwise.



* ScaleAnimation


public ScaleAnimation (float fromX, float toX, float fromY, float toY, int pivotXType, float pivotXValue, int pivotYType, float pivotYValue)


Parameters
fromX Horizontal scaling factor to apply at the start of the animation
toX Horizontal scaling factor to apply at the end of the animation
fromY Vertical scaling factor to apply at the start of the animation
toY Vertical scaling factor to apply at the end of the animation
pivotXType Specifies how pivotXValue should be interpreted. One of Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, or Animation.RELATIVE_TO_PARENT.
pivotXValue The X coordinate of the point about which the object is being scaled, specified as an absolute number where 0 is the left edge. (This point remains fixed while the object changes size.) This value can either be an absolute number if pivotXType is ABSOLUTE, or a percentage (where 1.0 is 100%) otherwise.
pivotYType Specifies how pivotYValue should be interpreted. One of Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, or Animation.RELATIVE_TO_PARENT.
pivotYValue The Y coordinate of the point about which the object is being scaled, specified as an absolute number where 0 is the top edge. (This point remains fixed while the object changes size.) This value can either be an absolute number if pivotYType is ABSOLUTE, or a percentage (where 1.0 is 100%) otherwise.



4개의 애니메이션을 구현하기 위해 따로 코딩을 하지 않고 그냥 안드로이드 API 에서 해당 클래스를 불러다 쓰는 군요.

제가 원하는 flipping 효과를 낼 수 있을 지 어떨지 잘 모르겠네요.


다음 글에서 실제 자바 코드를 분석해 보고 어떻게 실행되는지도 살펴 보겠습니다.

그리고 실제 코드를 이것 저것 수정해서 어떤 효과들을 낼 수 있는지도 추가적으로 알아보겠습니다.


반응형


반응형

오늘도 Do it 안드로이드 프로그래밍에서 제공하는 예제로 공부를 했습니다.


예제소스는 http://android-town.org/ 로 가면 무료로 제공하고 있으니 필요하신 분들은 받으셔서 보셔도 됩니다.

동영상강좌는 http://www.youtube.com/user/easyspub 에서 제공되고 있습니다.

책을 직접 구입하셔서 보시면 훨씬 더 도움이 될 것 같네요.


이 예제 중 book3 에 있는 SamplePageSliding 을 공부했는데요.

지금 하고 있는 일과 관련해서 화면을 하나 만들어야 되서 이 예제를 바탕으로 좀 수정을 했습니다.


이 예제는 Android 의 Animation 기능을 이용해서 버튼을 누르면 오른쪽에 메뉴화면이 뜨고 또 버튼을 누르면 이 메뉴화면이 부드럽게 사라지는 효과를 주었습니다.


저는 이 메뉴를 오른쪽으로 옮기고 버튼을 없애는 대신 두 손가락으로 sliding을 할 경우 왼쪽에서 메뉴가 부드럽게 나타났다고 다시 두 손가락으로 sliding 하면 부드럽게 사라지는 기능을 만들었습니다.


우선 Layout xml 을 볼께요.


activity_main.xml


<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:background="#ffffffff">
        <TextView 
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="26px"
            android:text="AAA Bank Check - 9513   Available balance $2,354.32"
            android:textColor="#000000"
            android:layout_marginLeft="350dp"
            android:layout_marginTop="100dp"
            />
    </LinearLayout>
   
    <LinearLayout
        android:id="@+id/slidingPage01"
        android:layout_width="250dp"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:layout_gravity="left"
        android:background="#ff888888"
        android:visibility="gone">
        <TextView 
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:textSize="20px"
            android:text="Direct banking  $642.77 "
            android:textColor="#ff000000"
            android:layout_marginLeft="10dp"
            android:layout_marginTop="10dp"
            />
        <TextView 
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:textSize="20px"
            android:text="Money Market - 3670"
            android:textColor="#ff000000"
            android:layout_marginLeft="10dp"
            android:layout_marginTop="10dp"           
            />
                                       
    </LinearLayout>
 
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:layout_gravity="right|center_vertical"
        android:background="#00000000">
        <Button 
            android:id="@+id/openBtn01"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Open"
            android:visibility="invisible"
            />
    </LinearLayout>

</FrameLayout>



전체 화면은 FrameLayout 을 사용했습니다. Animation 기능을 구현해야 하기 때문에 이 FrameLayout 을 사용했을 겁니다.

FrameLayout 의 특징이 화면에 여러 뷰나 레이아웃을 겹쳐 놓고 한순간에 하나의 레이아웃을 보이도록 할 수 있습니다. 계속 이 레이아웃을 바꾸면 애니메이션 효과가 나올 수 있겠죠.


그 다음엔 LinearLayout 이 있고 orientation은 vertical 로 돼 있습니다.

이 LinearLayout 안에 있는 view들은 위에서 아래로 정렬이 될 겁니다.

그 아래 보니까 그냥 TextView 하나만 있네요.


일단 화면에 이 TextView가 표시 될 겁니다.


다음에 보니까 다시 LinearLayout 이 나왔습니다.

이것도 orientation이 vertical 이네요. view들이 위에서 아래로 배치가 될겁니다.

그런데 그 다음에 layout_gravity 가 left로 돼 있습니다. 이것은 기준이 왼쪽이 된다는 겁니다.

원래 소스에는 이것이 right로 돼 있었습니다.

그런데 저는 메뉴가 왼쪽에서 나오도록 하기 위해 이것을 right으로 바꿨습니다.

다음에는 TextView가 두개가 나오는데요.

이 두개는 아래 위로 배치될 겁니다.

이 두번째 LinearLayout 에 animation 효과가 적용되서 좌우로 sliding 될 겁니다.

이 LinearLayout 의 id 가 slidingPage01 이라는 것을 잘 봐 두세요.


그 다음에 LinearLayout 이 또 나오네요.

orientation은 vertical 이고 gravity 가 right|center_vertical 이네요.

이 의미는 가로로는 오른쪽으로 배치를 하는데 세로로는 가운데에 정렬한다는 뜻입니다.

이 Linear Layout 에는 Button 만 하나 있네요.

그런데 저는 이 버튼을 사용하지 않을거기 때문에 그냥 android:visibility="invisible" 로 해서 화면에서 없앴습니다.


이제 Java 파일을 볼까요?


MainActivity.java


public class MainActivity extends Activity {

    boolean isPageOpen = false;

    Animation translateLeftAnim;
    Animation translateRightAnim;

    LinearLayout slidingPage01;

    Button openBtn01;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        slidingPage01 = (LinearLayout) findViewById(R.id.slidingPage01);

        translateLeftAnim = AnimationUtils.loadAnimation(this, R.anim.translate_left);
        translateRightAnim = AnimationUtils.loadAnimation(this, R.anim.translate_right);

        SlidingPageAnimationListener animListener = new SlidingPageAnimationListener();
        translateLeftAnim.setAnimationListener(animListener);
        translateRightAnim.setAnimationListener(animListener);

        openBtn01 = (Button) findViewById(R.id.openBtn01);
        openBtn01.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                if (isPageOpen) {
                    slidingPage01.startAnimation(translateRightAnim);
                } else {
                    slidingPage01.setVisibility(View.VISIBLE);
                    slidingPage01.startAnimation(translateLeftAnim);
                }
            }
        });

    }

    private class SlidingPageAnimationListener implements AnimationListener {
        public void onAnimationEnd(Animation animation) {
            if (isPageOpen) {
                slidingPage01.setVisibility(View.INVISIBLE);

                openBtn01.setText("Open");
                isPageOpen = false;
            } else {
                openBtn01.setText("Close");
                isPageOpen = true;
            }
        }

        public void onAnimationRepeat(Animation animation) {
        }

        public void onAnimationStart(Animation animation) {
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }
   
    public boolean onTouchEvent(MotionEvent event) {
        if(event.getPointerCount() > 2) {
            return false;
        }
        else if (event.getPointerCount() == 2) {
        int action = event.getAction();
        float downX = 0;
        float upX = 0;

       
        int pureaction = action & MotionEvent.ACTION_MASK;
        if (isPageOpen) {
            slidingPage01.startAnimation(translateRightAnim);
        } else {
            slidingPage01.setVisibility(View.VISIBLE);
            slidingPage01.startAnimation(translateLeftAnim);
        }
      }
      return true;
    }
}



우선 onCreate() 메소드 부터 보겠습니다.

layout xml 로 activity_main 을 세팅했죠.

그 다음에 한 것이 sliding 효과를 줄 LinearLayout 객체에 넣은 겁니다.

아까 봤던 두번째 LinearLayout 인 slidingPage01 을요.


다음엔 animation 효과를 객체에 담은 건데요.

translate_left와 translate_right는 res의 amin 이라는 폴더안에 xml 형태로 있습니다.


translate_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"
    >
    <translate
        android:fromXDelta="-20%p"
        android:toXDelta="0%p"
        android:duration="500"
        android:repeatCount="0"
        android:fillAfter="true"
        />
</set>


translate_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"
    >
    <translate
        android:fromXDelta="0%p"
        android:toXDelta="-20%p"
        android:duration="500"
        android:repeatCount="0"
        android:fillAfter="false"
        />
</set>


저는 메뉴가 좌측에서 나오도록 하기 위해서 from, toXDelta 값들을 바꿨습니다.

애니메이션의 시작점과 끝점을 가리키는 겁니다.


그 다음에는 SlidingPageAnimationListener 의 객체를 만들어서 방금 만들었던 Animation에 이 리스너를 set 해 넣습니다.


그리고 Button 을 만들어서 이 버튼을 클릭하면 좌측 화면이 사라졌다가 나타났다가 하는 동작을 하도록 코딩을 해 줍니다.


사실 이 부분은 원본 소스에서 사용되는 부분이구요.

저는 버튼클릭은 없애고 대신 두손가락으로 sliding 하는 이벤트를 Listening 하다가 그에 반응하는 기능을 넣고 싶었거든요.


그래서 onTouchEvent() 메소드를 구현한 겁니다.


이 메소드를 보죠.


public boolean onTouchEvent(MotionEvent event) {
        if(event.getPointerCount() > 2) {
            return false;
        }
        else if (event.getPointerCount() == 2) {
        int action = event.getAction();
        float downX = 0;
        float upX = 0;

       
        int pureaction = action & MotionEvent.ACTION_MASK;
        if (isPageOpen) {
            slidingPage01.startAnimation(translateRightAnim);
        } else {
            slidingPage01.setVisibility(View.VISIBLE);
            slidingPage01.startAnimation(translateLeftAnim);
        }
      }
      return true;
    }


화면에서 일어나는 이벤트를 감지해서 어떤 동작을 하고 싶으면 이 메소드를 구현하면 됩니다.


getPointerCount()는 화면에 닿은 손가락 갯수를 받는 거구요.

화면에 2개의 손가락이 닿았을 공우 isPageOpen 이 true 이면 translateRightAmin 이 실행되고 false 이면 translateLeftAnim 이 실행 되도록 만든 겁니다.


원본 샘플 파일을 받아서 실행해 보시고 위에서 제가 바꾼 것들을 따라서 바꿔가면서 결과를 단계별로 확인하시면 쉽게 이해하실 수 있을 겁니다.


그리고 이 두 소스를 기반으로 본인이 구현하고 싶은 기능을 나름대로 생각해서 구현하면 공부하는데 훨씬 도움이 될 겁니다.



반응형