diff --git a/README.md b/README.md index e5dbb345d..3ad7d502a 100644 --- a/README.md +++ b/README.md @@ -61,7 +61,7 @@ A library which provides a way to use Android Drawables as Jetpack Compose Paint ### ⬇️ [Swipe to Refresh](./swiperefresh/) A library that provides a layout implementing the swipe-to-refresh UX pattern, similar to Android's [SwipeRefreshLayout](https://developer.android.com/jetpack/androidx/releases/swiperefreshlayout). -### 🌏 [Web](./web/) +### 🌏 [Web](./webview/) A wrapper around WebView for basic WebView support in Jetpack Compose. ### 📜 [Adaptive](./adaptive/) diff --git a/docs/webview.md b/docs/webview.md index 50f073394..948eb2a28 100644 --- a/docs/webview.md +++ b/docs/webview.md @@ -45,6 +45,17 @@ WebView( ) ``` +### Using a subclass of WebView + +If you want to use a subclass of `WebView`, or simply require more control over its instantiation, you can provide a factory. + +```kotlin +WebView( + ... + factory = { context -> CustomWebView(context) } +) +``` + ## Download [![Maven Central](https://img.shields.io/maven-central/v/com.google.accompanist/accompanist-webview)](https://search.maven.org/search?q=g:com.google.accompanist) diff --git a/web/api/current.api b/web/api/current.api index d90966187..bd8c9f116 100644 --- a/web/api/current.api +++ b/web/api/current.api @@ -75,7 +75,7 @@ package com.google.accompanist.web { } public final class WebViewKt { - method @androidx.compose.runtime.Composable public static void WebView(com.google.accompanist.web.WebViewState state, optional androidx.compose.ui.Modifier modifier, optional boolean captureBackPresses, optional com.google.accompanist.web.WebViewNavigator navigator, optional kotlin.jvm.functions.Function1 onCreated, optional kotlin.jvm.functions.Function1 onDispose, optional com.google.accompanist.web.AccompanistWebViewClient client, optional com.google.accompanist.web.AccompanistWebChromeClient chromeClient); + method @androidx.compose.runtime.Composable public static void WebView(com.google.accompanist.web.WebViewState state, optional androidx.compose.ui.Modifier modifier, optional boolean captureBackPresses, optional com.google.accompanist.web.WebViewNavigator navigator, optional kotlin.jvm.functions.Function1 onCreated, optional kotlin.jvm.functions.Function1 onDispose, optional com.google.accompanist.web.AccompanistWebViewClient client, optional com.google.accompanist.web.AccompanistWebChromeClient chromeClient, optional kotlin.jvm.functions.Function1? factory); method @androidx.compose.runtime.Composable public static com.google.accompanist.web.WebViewNavigator rememberWebViewNavigator(optional kotlinx.coroutines.CoroutineScope coroutineScope); method @androidx.compose.runtime.Composable public static com.google.accompanist.web.WebViewState rememberWebViewState(String url, optional java.util.Map additionalHttpHeaders); method @androidx.compose.runtime.Composable public static com.google.accompanist.web.WebViewState rememberWebViewStateWithHTMLData(String data, optional String? baseUrl); diff --git a/web/src/androidTest/kotlin/com/google/accompanist/web/WebTest.kt b/web/src/androidTest/kotlin/com/google/accompanist/web/WebTest.kt index 747744473..0f265e5a2 100644 --- a/web/src/androidTest/kotlin/com/google/accompanist/web/WebTest.kt +++ b/web/src/androidTest/kotlin/com/google/accompanist/web/WebTest.kt @@ -16,6 +16,7 @@ package com.google.accompanist.web +import android.content.Context import android.graphics.Bitmap import android.webkit.WebView import androidx.compose.material.MaterialTheme @@ -619,6 +620,22 @@ class WebTest { private val webNode: SemanticsNodeInteraction get() = rule.onNodeWithTag(WebViewTag) + + @Test + fun testWebViewFactoryUsedIfSupplied() { + lateinit var constructedWebView: WebView + + rule.setContent { + WebTestContent( + rememberWebViewState(url = LINK_URL), + idleResource, + onCreated = { constructedWebView = it }, + factory = { context -> CustomWebView(context) } + ) + } + + assertThat(constructedWebView).isInstanceOf(CustomWebView::class.java) + } } private const val LINK_ID = "link" @@ -638,9 +655,11 @@ private fun WebTestContent( webViewState: WebViewState, idlingResource: WebViewIdlingResource, navigator: WebViewNavigator = rememberWebViewNavigator(), + onCreated: (WebView) -> Unit = { it.settings.javaScriptEnabled = true }, onDispose: (WebView) -> Unit = {}, client: AccompanistWebViewClient = remember { AccompanistWebViewClient() }, - chromeClient: AccompanistWebChromeClient = remember { AccompanistWebChromeClient() } + chromeClient: AccompanistWebChromeClient = remember { AccompanistWebChromeClient() }, + factory: ((Context) -> WebView)? = null ) { idlingResource.webviewLoading = webViewState.loadingState !is LoadingState.Finished @@ -649,10 +668,11 @@ private fun WebTestContent( state = webViewState, modifier = Modifier.testTag(WebViewTag), navigator = navigator, - onCreated = { it.settings.javaScriptEnabled = true }, + onCreated = onCreated, onDispose = onDispose, client = client, - chromeClient = chromeClient + chromeClient = chromeClient, + factory = factory ) } } @@ -663,3 +683,5 @@ private class WebViewIdlingResource : IdlingResource { override val isIdleNow: Boolean get() = !webviewLoading } + +private class CustomWebView(context: Context) : WebView(context) diff --git a/web/src/main/java/com/google/accompanist/web/WebView.kt b/web/src/main/java/com/google/accompanist/web/WebView.kt index 55f46fcae..a7d127f3b 100644 --- a/web/src/main/java/com/google/accompanist/web/WebView.kt +++ b/web/src/main/java/com/google/accompanist/web/WebView.kt @@ -16,6 +16,7 @@ package com.google.accompanist.web +import android.content.Context import android.graphics.Bitmap import android.view.ViewGroup import android.webkit.WebChromeClient @@ -62,6 +63,7 @@ import kotlinx.coroutines.withContext * subsequently overwritten after this lambda is called. * @param client Provides access to WebViewClient via subclassing * @param chromeClient Provides access to WebChromeClient via subclassing + * @param factory An optional WebView factory for using a custom subclass of WebView * @sample com.google.accompanist.sample.webview.BasicWebViewSample */ @Composable @@ -73,7 +75,8 @@ fun WebView( onCreated: (WebView) -> Unit = {}, onDispose: (WebView) -> Unit = {}, client: AccompanistWebViewClient = remember { AccompanistWebViewClient() }, - chromeClient: AccompanistWebChromeClient = remember { AccompanistWebChromeClient() } + chromeClient: AccompanistWebChromeClient = remember { AccompanistWebChromeClient() }, + factory: ((Context) -> WebView)? = null ) { var webView by remember { mutableStateOf(null) } @@ -104,7 +107,7 @@ fun WebView( AndroidView( factory = { context -> - WebView(context).apply { + (factory?.invoke(context) ?: WebView(context)).apply { onCreated(this) layoutParams = ViewGroup.LayoutParams(