반응형

액티비티는 기본적으로 진입할 때는 아래에서 위로, 빠져나올 때는 아래에서 위로 전환됩니다.

하지만 이는 어디까지나 기본사항인 것이고, 안드로이드는 액티비티 전환에 애니메이션을 적용할 수 있는 많은 방법을 제공합니다.

직접 animation과 관련된 xml을 정의하여 적용하는 방법도 있고, 안드로이드에서 제공해주는 Transition을 활용하는 방법이 있습니다.

 

이번 포스팅에서는 제목에 맞게끔 가로로 전환하는 방법에 대해서만 다루도록 하겠습니다. 이외에 다른 애니메이션이 필요하신 분은 공식문서를 참고하시면 되겠습니다.

 

Transition

트랜지션은 장면이 전환될 때의 애니메이션에 대한 정보를 담고 있는 추상 클래스입니다.

우리는 이 트랜지션 클래스를 상속함으로써 커스텀 트랜지션을 구현할 수도 있습니다.

안드로이드에서 제공하는 이 Transition 방식은 SDKVersion 21 이상부터 지원하기 때문에 그 이하의 버전에서는 사용이 불가능하며, minSDKVersion이 21보다 낮은 프로젝트를 진행하시는 분들은 별도의 분기를 통해서 따로 관리를 해줘야 합니다. 

 

트랜지션을 사용하는 방법에는 두 가지 방법이 있습니다.

하나는 res/transition 디렉토리를 두어 XML 파일로 사용하는 방식이고, 다른 하나는 코드 단위에서 직접 객체를 통해서 설정해주는 방법입니다.

 

방법이 없는 것은 아니나 우리가 오늘 적용해보고 싶은 "가로로 슬라이드"하는 트랜지션은 코드 단위에서 적용하는 것이 더 편하기 때문에 코드로 적용하는 방법을 살펴보겠습니다.

 

먼저, 액티비티의 onCreate() 함수로 가서 아래의 코드를 작성해줘야 합니다.

 

override fun onCreate(savedInstanceState: Bundle?) {
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            with(window) {
                requestFeature(Window.FEATURE_CONTENT_TRANSITIONS)
                // set an slide transition
                enterTransition = Slide(Gravity.END)
                exitTransition = Slide(Gravity.START)
            }
        }
    super.onCreate(savedInstanceState)
    setContentView(R.layout.main_activity)
    // ...
}

여기서 주의 깊게 살펴볼 것은 SDK Version을 Lollipop(API 21 버전) 이상일 때만 적용할 수 있도록 분기 처리한 것과 super.onCreate()보다 먼저 오게끔 코드를 위치했다는 것입니다.

 

이는 requestFeature() 메소드 때문인데요, 만약 이 메소드가 setContentView() 보다 아래에 위치했다면 아래와 같은 에러가 발생했을 것입니다.

requestFeature() must be called before adding content

 

그렇기 때문에 저 코드를 넣을 때는 항상 위치에 유의해주시면 되겠습니다.

 

이제 코드를 살펴보시면, startTransition과 exitTransition을 각각 Slide 객체를 통해서 등록하는 것을 볼 수 있는데요. 이때 진입과 진출 부분에서 각각 어떤 방향으로 전환할 것인가를 slideEdge를 통해 설정할 수 있습니다.

 

위 코드의 경우에는 액티비티가 빠져나갈 시 오른쪽에서 왼쪽으로 빠져나가고, 액티비티에 들어올 시에 왼쪽에서 오른쪽으로 들어오게 됩니다.

 

transition을 등록하기만 했다고 해서 자동으로 적용되는 것이 아닙니다. 우리가 흔히 사용하던 startActivity() 메소드에 변화를 주어야 합니다.

기존에 사용하던 startActivity(Intent)가 아닌, startActivity(Intent, Bundle) 형태의 다른 메소드를 사용해야 합니다.

 

예시는 아래와 같습니다.

 

val intent = Intent(this, NextActivity::class.java)

startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(this).toBundle())

 

여기서 ActivityOptions.makeSceneTransitionAnimation()의 파라미터로 this가 들어간 것은 Activity가 들어가야 하기 때문입니다. 따라서 액티비티가 아닌 다른 곳에서 startActivity를 호출하는 경우 위 코드의 this 부분에 액티비티 객체를 넣어줘야 한다는 것을 잊지 마세요.

 

<Transition 적용 전>

Transition 적용 전에는 기본적으로 아래에서 위로, 위에서 아래로 진입하고 빠져나오는 것을 확인할 수 있습니다.

 

이번에는 앞서 예시에서 다룬 코드를 토대로 Transition을 적용해보겠습니다.

 

<Transition 적용 후>

 

보시는 바와 같이 액티비티 전환시 가로로 진입하고 빠져나오는 것을 확인할 수 있습니다.

 

만약 슬라이드 되는 방향을 바꾸고 싶은 경우에는 Gravity 속성을 변경해주시면 되고, 슬라이드가 아닌 다른 애니메이션을 적용하고 싶으신 분들은 Slide 대신 Explode, Fade 등 다른 객체로 적용해주시면 되겠습니다.

 

그리고 만약 애니메이션을 적용하고 싶지 않다면 startActivity의 두 번째 파라미터에 null 값을 넣으면 됩니다.

 

참고로 트랜지션은 SurfaceView나 TextureView와 호환이 잘 안될 수 있습니다. 이유는 SurfaceView는 UI Thread가 아닌 non-UI Thread에서 관리되기 때문에 트랜지션 적용이 안 될 수 있고, TextureView는 트랜지션에서 사용하는 ViewOverlay가 TextureView에는 작동을 하지 않기 때문에 원하는 대로 적용이 안 될 가능성이 높습니다.


이 포스트에서 다루어진 예제 코드는 Github 저장소에서 확인할 수 있습니다.

 

반응형
반응형