웹뷰에서 네이티브처럼 modal 띄우기
🕒 읽는 데 0분 예상forest_articles
forest_날짜
forest_분류
문서
웹뷰를 사용한 하이브리드 앱에서 전체가 WebView라면 문제가 없을지 모르지만, Bottom Navigation Bar와 같이 네이티브 Widget 요소가 포함된 경우 단순히 웹뷰에 띄울 웹페이지 내에서 modal을 띄우면 아래 사진처럼 심미적으로 매우 어색해진다.

따라서 네이티브 API를 사용하면서도 WebView를 통한 UI 구성의 편의를 유지할 수 있는 방법이 필요하다.
기존 네이티브 단의 BottomSheetDialogFragment를 사용하되, 내부를 WebView로 채워넣고 JavascriptInterface로 Bridge를 구성해 열고 닫기 등과 같은 동작을 구현해주면 된다.
먼저, Bottom Sheet 내에 들어갈 Layout을 다음과 같이 만들어주었다.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <LinearLayout android:id="@+id/webViewProgress" android:layout_width="match_parent" android:layout_height="150dp" android:gravity="center" android:visibility="visible"> <ProgressBar android:layout_width="wrap_content" android:layout_height="wrap_content" android:indeterminate="true" android:theme="@style/Widget.AppCompat.ProgressBar" /> </LinearLayout> <WebView android:id="@+id/webview" android:layout_width="match_parent" android:layout_height="match_parent" android:visibility="gone" tools:ignore="WebViewLayout" /> </LinearLayout>
코드에서는 다음과 같이 webView 속성들을 지정해주고 url을 표시해주기만 하면 된다. JavascriptInterface 구현은 생략하겠다.
class WebViewBottomSheetDialog(url: String, cancelable: Boolean = true):BottomSheetDialogFragment() { //... override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) val webViewProgress: LinearLayout = view.findViewById(R.id.webViewProgress) val webView: WebView = view.findViewById(R.id.webview) webView.settings.javaScriptEnabled = true webView.settings.domStorageEnabled = true webView.isVerticalScrollBarEnabled = false webView.isHorizontalScrollBarEnabled = false webView.overScrollMode = WebView.OVER_SCROLL_NEVER webView.setOnTouchListener { _, event -> event.action == MotionEvent.ACTION_MOVE } webView.setBackgroundColor(0) webView.addJavascriptInterface( JavaScriptInterfaceForWebViewModal(requireActivity(), this), "Android" ) webView.loadUrl(url) //... } }
이제 이렇게 만든 Modal을 WebView 내에서 호출하여 열 수 있어야 한다.
아래와 같이 Modal을 열기 위한 JavascriptInterface를 구성해준다.
@JavascriptInterface fun openCustomBottomSheet(url: String, isCancelable: Boolean = true) { homeActivity.runOnUiThread { homeActivity.main?.let { WebViewBottomSheetDialog(url, isCancelable).show(homeActivity.supportFragmentManager, MenuBottomSheetDialog.TAG) } } }
이제 WebView 내의 웹페이지에서 아래와 같이 Javascript를 호출해주면 된다.
Android.openCustomBottomSheet("https://klasplus.yuntae.in/modal/agreePolicy", false)

이제 화면을 완전히 덮는 네이티브처럼 동작하는 Modal을 WebVIew를 이용해 구현할 수 있게 되었다.