compose에서는 웹뷰를 아주 간단히 띄울 수 있다.
@Composable
fun CustomWebView(
url: String,
) {
AndroidView(factory = {
val myWebView = WebView(it)
myWebView.apply {
layoutParams = ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT
)
}
}, update = {
it.loadUrl(url)
})
}
이렇게만 작성해두어도 CustomWebView에 url을 넘겨 간단히 웹뷰를 띄울 수 있다. 하지만 실제로 그럴싸한 웹뷰 사용성을 보이려면 몇가지 작업을 더 해주어야한다.
위 코드를 그대로 실행할 경우 compose application에서 웹뷰가 로드되는게 아니라 스마트폰 브라우저 앱이 실행되며 새창으로 url이 로드되는 경험을 했다. 서치 결과 WebViewClient를 할당해주어야한다는 사실을 알아냈다.
@Composable
fun CustomWebView(
url: String,
) {
AndroidView(factory = {
val myWebView = WebView(it)
// 스마트폰 browser로 실행되는게 아니라 인앱에서 웹뷰를 띄우기 위해 WebViewClient 할당
myWebView.webViewClient = CustomWebViewClient()
myWebView.apply {
layoutParams = ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT
)
}
}, update = {
it.loadUrl(url)
})
}
class CustomWebViewClient : WebViewClient() {
// TODO Something
}
webview를 사용할 때 기본적으로 넣어주는 웹뷰 셋팅들이 있다. 이부분은 각자 프로젝트에 맞게 설정해주면 된다.
@Composable
fun CustomWebView(
url: String,
) {
AndroidView(factory = {
val myWebView = WebView(it)
// 스마트폰 browser로 실행되는게 아니라 인앱에서 웹뷰를 띄우기 위해 WebViewClient 할당
myWebView.webViewClient = CustomWebViewClient()
// webview 설정
myWebView.settings.apply {
domStorageEnabled = true
mixedContentMode = WebSettings.MIXED_CONTENT_NEVER_ALLOW
loadsImagesAutomatically = true
cacheMode = WebSettings.LOAD_DEFAULT
textZoom = 100
mediaPlaybackRequiresUserGesture = false
}
myWebView.apply {
layoutParams = ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT
)
}
}, update = {
it.loadUrl(url)
})
}
class CustomWebViewClient : WebViewClient() {
// TODO Something
}
Android 기기는 기본적으로 뒤로가기 버튼을 누를 수 있다. 만약 WebView에 따로 BackHandler 설정을 해주지 않는다면 물리버튼을 눌렀을 때 브라우저의 뒤로가기가 아니라 navigation의 뒤로가기나 앱 종료 등 기본 동작이 실행되게 된다.
나는 webview에서 뒤로가기가 가능하다면 webview의 뒤로가기 실행, 만약 그렇지 않다면 navigation의 뒤로가기를 실행하도록 구성해주었다.
@Composable
fun CustomWebView(
url: String,
navigationGoBack: () -> Unit
) {
// webView에 접근하기 위해 state로 선언해주었다.
var webView: WebView? by remember { mutableStateOf(null) }
val onPressedBack = {
if (webView?.canGoBack() == true) {
webView?.goBack()
} else {
navigationGoBack()
}
}
BackHandler(enabled = true) {
onPressedBack()
}
AndroidView(factory = {
val myWebView = WebView(it)
...
myWebView.apply {
...
webView = this
}
}
}
BackHandler를 Composable의 최상단에서만 선언 가능하기 때문에 AndroidView 하위에서 선언하는 webView 객체에 접근하기 위해 state로 선언해서 초기화 후 할당해주었다.