안드로이드/이론

[ 안드로이드 ] WebView 동영상 전체화면 처리 ( + 상단바 숨기기)

dongx._.2 2023. 7. 12. 18:03

 

WebView 동영상 전체화면

안드로이드의 WebView에선 기본적으로 동영상 전체화면 처리를 해주지 않는다.

따라서, 별도로 커스텀을 해야하며 전체화면 버튼 클릭 시 새로운 화면을 위에 덮어 씌운다고 생각하면 된다.

 

WebChromeClient 클래스를 상속 받아서 커스텀해야하고, onShowCustomView, onHideCustomView 메소드를 통해 전체화면 처리를 할 수 있다.

 

FullScreenHolder 생성

동영상이 올라갈 배경을 지정한다. 이 클래스를 지정하지 않으면 동영상을 제외한 여백 부분이 투명하게 처리된다.

    private class FullScreenHolder(context:Context): FrameLayout(context) {
        init {
            setBackgroundColor(ContextCompat.getColor(context, R.color.black))
        }

        override fun onTouchEvent(event: MotionEvent?): Boolean {
            return super.onTouchEvent(event)
        }
    }

 

WebChromeClient 커스텀

class MyWebChromeClient(
    private val fragment: Fragment,
    private val container: FrameLayout,
    private val webView: CustomWebView,
): WebChromeClient() {
    companion object{
        val FULL_SCREEN_PARAMS = ViewGroup.LayoutParams(
            ViewGroup.LayoutParams.MATCH_PARENT,
            ViewGroup.LayoutParams.MATCH_PARENT,
        )
    }
    private var mCustomView: View? = null
    private var mVideoContainer: FrameLayout? = null
    private var mCustomViewCallback: CustomViewCallback? = null

    private val mActivity: Activity by lazy {
        fragment.requireActivity()
    }

    override fun onShowCustomView(view: View?, callback: CustomViewCallback?) {
        // 이미 전체화면인 경우
        if(mCustomView != null){
            callback?.onCustomViewHidden()
            return
        }

        // 전체화면 시 자동으로 화면으로 가로로 전환
        mActivity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
		
        // 전체화면 종료시 동영상을 닫아주기 위해 view 객체 저장
        mCustomView = view
        mCustomViewCallback = callback
        mVideoContainer = FullScreenHolder(mActivity).apply {
            addView(mCustomView, FULL_SCREEN_PARAMS)
        }

        // decorView => 최상위 뷰
        val decor = mActivity.window.decorView as FrameLayout
        decor.apply {
            hideSystemUI(mActivity.window)
            addView(mVideoContainer, FULL_SCREEN_PARAMS)
        }

        super.onShowCustomView(view, callback)
    }

    override fun onHideCustomView() {
        if(mCustomView == null) return

        val decor = mActivity.window.decorView as FrameLayout
        decor.apply {
            showSystemUI(mActivity.window)
            removeView(mVideoContainer) // 최상위 뷰에서 동영상 뷰 제거
        }

        mVideoContainer = null
        mCustomView = null
        mCustomViewCallback?.onCustomViewHidden()
        
        // 다시 화면을 세로로 전환
        mActivity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
    }

    private class FullScreenHolder(context:Context): FrameLayout(context) {
        init {
            setBackgroundColor(ContextCompat.getColor(context, R.color.black))
        }

        override fun onTouchEvent(event: MotionEvent?): Boolean {
            return super.onTouchEvent(event)
        }
    }
}

 

상단바 숨기기

동영상을 전체화면으로 시청할 경우 상단바가 사라지는 것이 일반적이다.

 

아래의 메소드를 통해 간단히 처리할 수 있다.

( 재사용을 위해 확장 함수로 선언 )

fun View.hideSystemUI(window: Window){
    WindowCompat.setDecorFitsSystemWindows(window, false)
    WindowInsetsControllerCompat(window, this).let {
        it.hide(WindowInsetsCompat.Type.systemBars())
        it.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
    }
}

fun View.showSystemUI(window: Window){
    WindowCompat.setDecorFitsSystemWindows(window, true)
    WindowInsetsControllerCompat(window, this).show(WindowInsetsCompat.Type.systemBars())
}