본문 바로가기

안드로이드

[안드로이드] Custom View 커스텀 뷰 (3) - 애니메이션 추가 및 뻘 짓

[안드로이드] - [안드로이드] Custom View 커스텀 뷰 (2) - 화면 터치 시 생성

 

[안드로이드] Custom View 커스텀 뷰 (2) - 화면 터치 시 생성

[안드로이드] - [안드로이드] Custom View 커스텀 뷰 (1) - 만들기 [안드로이드] Custom View 커스텀 뷰 (1) - 만들기 안드로이드에서 제공하는 뷰에 필요한 기능을 추가하거나, 새로운 뷰를 만들어서 사용

dev-genue.tistory.com

이전 글에서 터치한 위치에 만든 커스텀 뷰를 찍어줬습니다. 그치만 아주아주 밋밋하기 그지없죠. 그래서, 좀 있어 보이게 하기 위해서 애니메이션을 추가해 보겠습니다. 적용할려는 애니메이션은 터치가 되면 확대가 되면서 나타나게 할려고 합니다.

 

[ MyCustomView.java ]

 

@Override
protected void onAttachedToWindow() {
    super.onAttachedToWindow();
    ScaleAnimation scaleAnimation = new ScaleAnimation(0, 1, 0, 1);
    scaleAnimation.setDuration(1000);
    mView.setAnimation(scaleAnimation);
}

 

ScaleAnimation 은 뷰를 확대 축소하는데 사용하는 애니메이션입니다.

생성자로 넘기는 0, 1, 0, 1은 

 

 

fromX, fromY 는 각각 X축, Y축 방향으로의 배율 시작

toX, toY 는 각각 X축, Y축 방향으로의 배율 마무리

즉, (fromX, fromY = 0) 배 부터 (toX, toX = 1) 배까지 늘리겠다는 것입니다.

 

setDuration()은 애니메이션을 몇 밀리세컨 까지 동작시킬지 정해주는 녀석입니다. 1000ms = 1s

한번 결과를 볼까요??

 

 

음? 다시 커스텀 뷰 기준 0, 0 에서 시작을 하네요??

ScaleAnimation 생성자 중에서 pivotX, pivotY가 있는 녀석이 있는데, 얘네들의 역할이 애니메이션의 시작 위치를 잡아주는 역할이라고 합니다. 그럼 저희는 중점을 애니메이션의 시작점으로 정해야하니

 

MyCustomView.java ]

 

@Override
protected void onAttachedToWindow() {
    super.onAttachedToWindow();
    
    int w = mView.getMeasuredWidth();
    int h = mView.getMeasuredHeight();
    ScaleAnimation scaleAnimation = new ScaleAnimation(0, 1, 0, 1, mView.getPivotX() + w/2, mView.getPivotY() + h/2);
    
    scaleAnimation.setDuration(1000);
    mView.setAnimation(scaleAnimation);
}

 

이렇게 바꾸고 다시 보면

 

.

아~주 만족스럽게 가운데에 찍히는 것을 볼 수 있습니다.

아쉬우니 좀 더 다양한 애니메이션을 적용해 볼까요??

뭔가 띠요옹 하는 느낌이 들게 해보겠습니다.

간단하게 순서를 보면

0배 -> 1.2배 -> 0.8배 -> 1.1배 -> 1배

이런 식으로 해보겠습니다.

여러 애니메이션을 연속적으로 사용하기 위해서는 AnimationSet 이라는 것을 사용하면 됩니다.

 

MyCustomView.java ]

 

@Override
protected void onAttachedToWindow() {
    super.onAttachedToWindow();
    int w = layoutMain.getMeasuredWidth();
    int h = layoutMain.getMeasuredHeight();
    animationSet = new AnimationSet(false);

    ScaleAnimation scaleAnimation = new ScaleAnimation(0.0f, 1.2f, 0.0f, 1.2f, mView.getPivotX() + w/2, mView.getPivotY() + h/2);
    scaleAnimation.setDuration(1000);
    animationSet.addAnimation(scaleAnimation);
        
    ScaleAnimation scaleAnimation2 = new ScaleAnimation(1.2f, 0.8f, 1.2f, 0.8f, mView.getPivotX() + w/2, mView.getPivotY() + h/2);
    scaleAnimation2.setDuration(1000);
    scaleAnimation2.setStartOffset(1000);
    animationSet.addAnimation(scaleAnimation2);

    ScaleAnimation scaleAnimation3 = new ScaleAnimation(0.8f, 1.1f, 0.8f, 1.1f, mView.getPivotX() + w/2, mView.getPivotY() + h/2);
    scaleAnimation3.setDuration(1000);
    scaleAnimation3.setStartOffset(2000);
    animationSet.addAnimation(scaleAnimation3);

    ScaleAnimation scaleAnimation4 = new ScaleAnimation(1.1f, 1.0f, 1.1f, 1.0f, mView.getPivotX() + w/2, mView.getPivotY() + h/2);
    scaleAnimation4.setDuration(1000);
    scaleAnimation4.setStartOffset(3000);
    animationSet.addAnimation(scaleAnimation4);

    mView.startAnimation(animationSet);
}

 

AnimationSet의 생성자의 경우

이렇게 있는데, 저희는 코드에서 만드니 밑에 생성자를 사용하겠습니다. Interplator는 애니메이션에 줄 수 있는 효과? 입니다. 점점 빠르게, 점점 느리게 등등 이 있는데 지금은 사용을 하지 않아서 나중에 다뤄보도록 하겠습니다.

 

setStartOffset()은 애니메이션을 몇 밀리세컨 후에 작동할지 입니다. AnimationSet을 start 하는 순간 모든 애니메이션이 작동하기 때문에, 순차적으로 작동시키기 위해서 각 애니메이션마다 대기할 시간을 정해줘야합니다. 자 그럼, 한번 작동시켜보면

 

 

이게 뭐야;;;;;;;; 만들면서 바로바로 글 쓰고 있는데 진짜 당황스럽네요;;;;; 하...

일단 잘리는것도 문제고, 마지막 애니메이션에서 끝나는 크기가 원 크기가 아니라는 문제도 있습니다.

 


 

일단 그래서 다른 방법으로 접근해봤습니다. 

  ScaleAnimation scaleAnimation = new ScaleAnimation(0.0f, 1.2f, 0.0f, 1.2f, Animation.RELATIVE_TO_SELF, 0.5f,Animation.RELATIVE_TO_SELF, 0.5f);
        scaleAnimation.setDuration(1000);
        animationSet.addAnimation(scaleAnimation);

        scaleAnimation.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {

            }

            @Override
            public void onAnimationEnd(Animation animation) {
                ScaleAnimation scaleAnimation = new ScaleAnimation(1.2f, 0.8f, 1.2f, 0.8f, Animation.RELATIVE_TO_SELF, 0.5f,Animation.RELATIVE_TO_SELF, 0.5f);
                scaleAnimation.setDuration(1000);
                scaleAnimation.setAnimationListener(new Animation.AnimationListener() {
                    @Override
                    public void onAnimationStart(Animation animation) {

                    }

                    @Override
                    public void onAnimationEnd(Animation animation) {
                        ScaleAnimation scaleAnimation = new ScaleAnimation(0.8f, 1.1f, 0.8f, 1.1f, Animation.RELATIVE_TO_SELF, 0.5f,Animation.RELATIVE_TO_SELF, 0.5f);
                        scaleAnimation.setDuration(1000);
                        scaleAnimation.setAnimationListener(new Animation.AnimationListener() {
                            @Override
                            public void onAnimationStart(Animation animation) {

                            }

                            @Override
                            public void onAnimationEnd(Animation animation) {
                                ScaleAnimation scaleAnimation = new ScaleAnimation(1.1f, 1.0f, 1.1f, 1.0f, Animation.RELATIVE_TO_SELF, 0.5f,Animation.RELATIVE_TO_SELF, 0.5f);
                                scaleAnimation.setDuration(1000);
                                mView.startAnimation(scaleAnimation);
                            }

                            @Override
                            public void onAnimationRepeat(Animation animation) {

                            }
                        });
                        mView.startAnimation(scaleAnimation);
                    }

                    @Override
                    public void onAnimationRepeat(Animation animation) {

                    }
                });
                mView.startAnimation(scaleAnimation);
            }

            @Override
            public void onAnimationRepeat(Animation animation) {

            }
        });

 

바로 애니메이션 리스너를 달아서 한 애니메이션이 끝날 때마다 다름 애니메이션을 작동 시키는 것입니다. 아주 코드가 별루죠?? 어차피 테스트용이니까☆

 

그리고 ScaleAnimation 생성자를 마지막 걸로 바꿨습니다. pivotXTypeAnimation.RELATIVE_TO_SELF 로 바꾸면, 현재 자기 뷰 영역을 기준으로 잡고, pivotXValue 에 0.5f = 50% 으로 정할 수 있습니다.

즉, 그 전에는 위치를 계산해야했지만, 바뀐 방식으로는 현재 뷰의 가로세로 중앙으로 위치를 편하게 잡을 수 있다는 것입니다.

 

다시 한번 볼까요?

그래도 잘리네;;;


일단 미루겠습니다... 머리 깨지겠네요

 

일단 결론을 하나 내리면, 순차적으로 애니메이션을 작동시킬려면 리스너를 달아서 하는 것이 낫다!