본문 바로가기
안드로이드/코틀린

안드로이드 캡처 효과 예제 : CaptureEffectView

by 시작이반의반 2024. 5. 2.

안드로이드 캡처 효과
전원+볼륨다운 캡처 효과

최근 안드로이드 캡처 동작 관련해서 공부하다가 캡처는 잘되는데... 뭔가 심심한 느낌이 있습니다.

안드로이드 기기에서 지원하는 전원+볼륨 다운 버튼으로 screenshot을 했을 때 나오는 효과처럼

내가 작성한 캡처 동작에도 효과가 들어가면 좋을 것 같아서 애니메이션을 활용해서 캡처 효과를 추가하였습니다.

애니메이션을 활용한 캡처 효과 예제를 간략하게 정리해보려고 합니다.

 

 

 

 

 

애니메이션 : ObjectAnimator 사용

 

캡처 효과를 주기 위해 ObjectAnimator를 사용하려고 합니다.

ObjectAnimator는 속성 애니메이션(Property Animation)을 제어하기 위한 클래스입니다.

이 클래스를 사용하면 원하는 객체의 속성을 부드럽게 애니메이션화 할 수 있습니다.

대표적으로 다룰 수 있는 속성으로는 위치, 크기, 회전, 투명도 등등이 있습니다.

 

투명도 및 크기 속성을 제어해서 애니메이션 화하는 예시

val alphaAnimator = ObjectAnimator.ofFloat(
    view,
    View.ALPHA,
    fromAlpha,
    toAlpha
)
alphaAnimator.duration = durationAlpha
alphaAnimator.addListener(alphaListener)
alphaAnimator.start()

 

val scaleAnimator = ObjectAnimator.ofPropertyValuesHolder(
    view,
    PropertyValuesHolder.ofFloat(View.SCALE_X, scale),
    PropertyValuesHolder.ofFloat(View.SCALE_Y, scale)
)
scaleAnimator.duration = durationSizeDown
scaleAnimator.addListener(scaleListener)
scaleAnimator.start()

 

 

 

 

 

캡처 효과 : CaptureEffectView 만들기

 

애니메이션화 하는 방법을 알아봤으니 이제 캡처 효과를 주기 위한 실질적인 객체를 만들어 봅니다.

layout xml 및 View Class를 아래와 같이 작성합니다.

 

overlay_layout_capture_effect.xml

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

    <View
        android:id="@+id/captureEffectView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#FFFFFF"
        android:visibility="gone" />
</layout>

 

 

CaptureEffectView.kt

class CaptureEffectView(context: Context, attrs: AttributeSet) : LinearLayout(context, attrs) {

    private val binding: OverlayLayoutCaptureEffectBinding

    init {
        val layoutInflater =
            context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
        binding = DataBindingUtil.inflate(
            layoutInflater,
            R.layout.overlay_layout_capture_effect,
            this,
            true
        )
    }

    fun startCaptureEffect() {
        // Alpha Property
        val fromAlpha = 0f
        val toAlpha = 0.5f

        // Scale Property
        val scaleUp = 1f
        val scaleDown = 0.97f

        // Animator Duration
        val durationSizeDown = 200L
        val durationSizeUp = 200L
        val durationAlpha = durationSizeDown + durationSizeUp

        // Animator : 투명도(Alpha) 속성
        val alphaAnimator = ObjectAnimator.ofFloat(
            binding.captureEffectView,
            View.ALPHA,
            fromAlpha,
            toAlpha
        )
        alphaAnimator.duration = durationAlpha
        alphaAnimator.addListener(object : AnimatorListenerAdapter() {
            // AnimatorListenerAdapter 를 통해 필요한 리스너 등록
            override fun onAnimationStart(animation: Animator) {
                binding.captureEffectView.visibility = View.VISIBLE
            }

            override fun onAnimationEnd(animation: Animator) {
                binding.captureEffectView.visibility = View.GONE
            }
        })
        alphaAnimator.start()

        // Animator : 크기(Scale) 속성
        val scaleUpAnimator = ObjectAnimator.ofPropertyValuesHolder(
            binding.captureEffectView,
            PropertyValuesHolder.ofFloat(View.SCALE_X, scaleUp),
            PropertyValuesHolder.ofFloat(View.SCALE_Y, scaleUp)
        )
        scaleUpAnimator.duration = durationSizeUp

        val scaleDownAnimator = ObjectAnimator.ofPropertyValuesHolder(
            binding.captureEffectView,
            PropertyValuesHolder.ofFloat(View.SCALE_X, scaleDown),
            PropertyValuesHolder.ofFloat(View.SCALE_Y, scaleDown)
        )
        scaleDownAnimator.duration = durationSizeDown
        scaleDownAnimator.addListener(object : AnimatorListenerAdapter() {
            // AnimatorListenerAdapter 를 통해 필요한 리스너 등록
            override fun onAnimationEnd(animation: Animator) {
                scaleUpAnimator.start()
            }
        })
        scaleDownAnimator.start()
    }
}

 

 

 

 

 

캡처 효과 : 오버레이 레이아웃 구성

 

작성한 CaptureEffectView를 사용하실 때 오버레이 레이아웃으로 구성합니다.

캡처 효과를 주려는 영역을 FrameLayout으로 감싸고 CaptureEffectView를 사용하시면 됩니다.

 

activity_main.xml

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

    <!-- Use FrameLayout For Overlay -->
    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <!-- Customizing Layout -->
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">
            <ImageView
                android:id="@+id/imageView"
                android:layout_width="match_parent"
                android:layout_height="0dp"
                android:layout_margin="20dp"
                android:layout_weight="1"
                android:src="@drawable/tree" />

            <Button
                android:id="@+id/btnTest"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_margin="20dp"
                android:text="전체화면 캡처하기"
                android:textAllCaps="false" />
        </LinearLayout>

        <!-- Overlay -->
        <com.example.myapplication.CaptureEffectView
            android:id="@+id/captureEffectView"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    </FrameLayout>
</layout>

 

 

 

 

 

캡처 효과 결과

 

아래 그림은 테스트 버튼을 눌러서 캡처 효과를 동작시켰을 때 결과입니다.

애니메이션 캡처 효과
CaptureEffectView 캡처 효과

 

댓글