본문 바로가기

Android/공부

안드로이드 화면 전환 애니메이션(+ 화면에 보이는지 여부에 따라 애니메이션 다르게 설정)

안녕하세요? 닉네임간편입니다. 이번 시간에는 화면 전환 애니메이션에 대해서 알아보겠습니다.

화면을 전환할 때 사용되는 애니메이션은 정말 다양하지만, 전 그중에서도 '공유 요소'를 활용하여 화면을 전환하는 애니메이션에 대해 다루겠습니다.

다음 이미지와 같이 이전 화면의 이미지뷰가 전환되는 화면과 '공유'하여 마치 연속되는 것처럼 화면이 전환되는 애니메이션을 구현할 것입니다.

1. 화면 전환하기 전 화면 처리

화면 전환 애니메이션을 만들려면 먼저 화면을 전환하기 이전 화면에서 처리해야 하는 부분이 있습니다.

전체 코드는 아래와 같습니다.

val intent = Intent(this@SearchBeerActivity, BeerSpecificActivity::class.java)
intent.putExtra(BEER_ID, beerId)
intent.putExtra(BEER_INFO_ITEM, result)
    val activityOptions = ActivityOptionsCompat.makeSceneTransitionAnimation(
        this@SearchBeerActivity,
        androidx.core.util.Pair<View, String>(
            view.findViewById(R.id.search_result_image),
            "specific_image"
        )
    )
    ActivityCompat.startActivity(
        this@SearchBeerActivity,
        intent,
        activityOptions.toBundle()
    )

1) activityOptions

makeSceneTransitionAnimation 함수를 통해 화면 전환 애니메이션 옵션을 만들어줍니다.

이때 두 번째 파라미터로 Pair가 들어가는데, 이때 순서대로 화면을 전환할 뷰와 transitionName 을 설정하면 됩니다.

transitionName은 공유 요소의 이름이며, 이 이름은 화면 전환된 이후 화면에서의 공유 요소와 이름이 통일되어야 합니다.

2) ActivityCompat.startActivity

intent를 단지 startActivity로 시작하지 않고, ActivityCompat을 사용해서 공유 요소 전환을 제어해야 합니다.

그리고 intent와 함께 activityOptions.toBundle() 을 같이 전달합니다.

2. 화면 전환한 이후 화면 처리

해당 화면의 onCreate() 메서드 안에 다음 코드를 작성합니다.

ViewCompat.setTransitionName(binding.beerSpecificImage,"specific_image")

이를 통해 화면 전환될 뷰의 transitionName을 이전 화면과 통일해주도록 합니다.

그럼 이제 위 사진처럼 화면 전환이 잘 됩니다.

화면 전환한 이후에는 다시 뒤로 돌아가기 버튼을 누르면 애니메이션이 적용된 채로 돌아갑니다.

3. 화면에 뷰가 보이는 지 여부에 따라 애니메이션 다르게 설정하기

그러나 화면에 공유된 뷰가 보이지 않게 될 경우, 아래 그림처럼 애니메이션이 이상하게 적용된 채로 화면이 뒤로 전환될 수 있습니다.

따라서 이 경우엔 먼저 공유된 뷰가 화면에 보이는 지를 체크하고, 그 여부에 따라 다르게 애니메이션을 설정해주면 됩니다.

    override fun onBackPressed() {
        super.onBackPressed()
        val scrollBounds = Rect()
        binding.beerSpecificScroll.getHitRect(scrollBounds)
        if (binding.beerSpecificImage.getGlobalVisibleRect(scrollBounds)) {
            finishAfterTransition()
        } else {
            window.sharedElementsUseOverlay = false
            window.sharedElementExitTransition = null
            window.sharedElementEnterTransition = null
            finish()
            overridePendingTransition(R.anim.fade_in_200, R.anim.fade_out_200)
        }
    }

뒤로가기 버튼을 예시로 설명하겠습니다.

getHitRect() 메서드는 상위 요소의 좌표에서 하위 요소의 터치 가능한 사각형 영역을 가져옵니다. 원활한 설명을 위해 이 영역을 Rect라고 하겠습니다.
그리고 getGlobalVisibleRect() 메서드를 통해 특정 뷰가 Rect 안에서 보이는 지 여부를 알 수 있습니다.
위 예시로 설명하자면, 먼저 전체 스크롤뷰에서 터치 가능한 사각형 영역 Rect를 만듭니다.
이후 공유된 요소인 imageView가 이 영역 안에서 보인다면, 즉 화면에 보인다면 finishAfterTransition() 메서드를 통해 화면 전환 애니메이션을 적용합니다.

그러나 만약 imageView가 화면에 보이지 않는다면, 기존 화면 전환 애니메이션을 제거하고 페이드 인-아웃 애니메이션으로 바꿉니다.

그러면 아래 그림처럼 보다 자연스러운 화면 전환이 되는 걸 볼 수 있습니다.

728x90
반응형