Introduction
Jetpack Compose has become a popular framework for developing Android applications with its modern declarative approach. Despite its flexibility, there are still some scenarios where developers need to integrate traditional Android views, such as WebView
, into their Compose-based UI. This can be achieved by combining the power of Jetpack Compose with Android's AndroidView
interop feature, allowing developers to embed native Android views within a Compose layout. In this article, we’ll walk through how to use a WebView
inside a Jetpack Compose project and provide details on how to configure it effectively.
This Kotlin example demonstrates the use of WebView
within a Jetpack Compose UI. We will break down the code into sections, explaining the setup, how to integrate WebView
within Compose, and how to apply necessary settings for a smooth browsing experience. Let’s take a closer look at how this is done.
Main Structure: Setting Up Compose Scaffold
The entry point for the app is MainActivity
, which inherits from AppCompatActivity
. The onCreate()
method is overridden to set the content using Compose’s setContent
method. Inside this method, a composable function GetScaffold()
is called, which serves as the main layout of the app. This layout consists of a Scaffold
, a composable that provides a basic structure for a screen. The Scaffold
includes a TopAppBar
with a title and a content section that loads the MainContent()
function.
The TopAppBar
is styled with a custom background color using Color(0xFFC0E8D5)
, and the title text "Compose - Using WebView" is displayed. The background color for the overall content area is also customized, giving the UI a clean, modern look.
Main Content: Integrating WebView
In the MainContent()
composable function, the first key element is the remember
function, which stores the state of the URL the WebView
will load. This state, represented by url
, allows dynamic updates of the URL when the user interacts with buttons. The Box
and Column
composables are used to arrange the layout, where the Box
takes up the majority of the screen and holds the WebView
.
To integrate WebView
into Jetpack Compose, the AndroidView
composable is used. This allows embedding any Android view (such as WebView
) into a Compose layout. The AndroidView
’s factory
parameter creates the WebView
instance, and the applySettings()
extension method is called to configure the WebView
's behavior. Additionally, the update
parameter of AndroidView
reloads the URL whenever the url
state changes, ensuring the correct page is loaded based on user interactions.
Button Controls: Switching Between URLs
The bottom section of the UI features a row of buttons that allow the user to navigate between different websites. This is done using a Row
composable that contains three buttons: one for Google, one for Yahoo, and another for Example.com. Each button is associated with an onClick
listener that updates the url
state with the corresponding URL. Once the url
state is updated, the WebView
in the AndroidView
automatically reloads the new URL.
The buttons are styled with padding and rounded corners using RoundedCornerShape
, ensuring a visually appealing and user-friendly interface. The use of Arrangement.spacedBy(12.dp)
ensures proper spacing between the buttons.
Applying WebView Settings
The applySettings()
function is an extension method that configures various settings for the WebView
. These settings are essential for improving user experience and compatibility with modern web standards. For example, JavaScript is enabled with settings.javaScriptEnabled = true
, and caching is set up using setAppCacheEnabled(true)
and setAppCachePath()
, which helps optimize loading times.
Other important configurations include enabling zoom controls, setting text zoom to 100%, and ensuring that images are loaded automatically by setting loadsImagesAutomatically = true
. The method also includes checks for Android version compatibility, such as enabling safe browsing for devices running Android Oreo (API level 26) and above.
Additionally, the method enables important features like DOM storage, geolocation, multiple windows, and hardware acceleration. These settings help make the WebView
behave more like a fully functional browser, handling complex web pages effectively.
Summary
This Kotlin example demonstrates how to integrate a WebView
into a Jetpack Compose-based UI using the AndroidView
composable. By managing the URL state and applying comprehensive settings through an extension method, the WebView
offers a robust browsing experience within the app. The use of buttons to switch between URLs adds interactivity, and the overall structure of the code showcases the flexibility of combining Compose with traditional Android views.
In conclusion, this approach allows developers to maintain the declarative nature of Jetpack Compose while leveraging existing Android views like WebView
. Whether you're building a web-based app or simply need to display web content, this example provides a clear and effective method for achieving that in your Compose projects.
package com.cfsuman.jetpackcompose
import android.os.Build
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.webkit.WebSettings
import android.webkit.WebView
import android.widget.FrameLayout
import android.widget.LinearLayout
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.ui.graphics.Color
import androidx.compose.material.Text
import androidx.compose.material.TopAppBar
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.unit.dp
import androidx.compose.ui.viewinterop.AndroidView
class MainActivity : AppCompatActivity() {
override fun onCreate(savedObjectState: Bundle?) {
super.onCreate(savedObjectState)
setContent {
GetScaffold()
}
}
@Composable
fun GetScaffold(){
Scaffold(
topBar = {
TopAppBar(
title = { Text(
text = "Compose - Using WebView"
)},
backgroundColor = Color(0xFFC0E8D5),
)
},
content = {MainContent()},
backgroundColor = Color(0xFFEDEAE0),
)
}
@Composable
fun MainContent(){
val url = remember { mutableStateOf("https://www.google.com")}
Box(
modifier = Modifier.fillMaxSize(),
){
Column(
horizontalAlignment = Alignment.CenterHorizontally
) {
Box(
modifier = Modifier
.weight(2F)
) {
AndroidView(factory = { context ->
WebView(context).apply {
applySettings()
loadUrl("https://www.google.com")
}
},update = {
it.loadUrl(url.value)
})
}
Row(
modifier = Modifier
.padding(8.dp)
.clip(RoundedCornerShape(12.dp))
.wrapContentHeight(Alignment.CenterVertically),
horizontalArrangement = Arrangement.spacedBy(12.dp),
verticalAlignment = Alignment.CenterVertically
) {
Button(onClick = {
url.value = "https://www.google.com"
}) {
Text(text = "Google")
}
Button(onClick = {
url.value = "https://www.yahoo.com"
}) {
Text(text = "Yahoo")
}
Button(onClick = {
url.value = "https://example.com"
}) {
Text(text = "Example")
}
}
}
}
}
}
// extension method to apply web view settings
fun WebView.applySettings(){
val layoutParams = LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.MATCH_PARENT
)
// or use this
val linearlayoutParams = FrameLayout.LayoutParams(
FrameLayout.LayoutParams.MATCH_PARENT,
FrameLayout.LayoutParams.MATCH_PARENT
)
this.layoutParams = layoutParams
//clearCache(true)
clearCache(true)
// Get the web view settings instance
val settings = settings
// Enable java script in web view
settings.javaScriptEnabled = true
// Enable and setup web view cache
settings.setAppCacheEnabled(true)
settings.cacheMode = WebSettings.LOAD_DEFAULT
settings.setAppCachePath(context.cacheDir.path)
// Enable zooming in web view
settings.setSupportZoom(false)
settings.builtInZoomControls = true
settings.displayZoomControls = true
// Zoom web view text
settings.textZoom = 100
// Enable disable images in web view
settings.blockNetworkImage = false
// Whether the WebView should load image resources
settings.loadsImagesAutomatically = true
// More web view settings
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
settings.safeBrowsingEnabled = true // api 26
}
//settings.pluginState = WebSettings.PluginState.ON
settings.useWideViewPort = true
settings.loadWithOverviewMode = true
settings.javaScriptCanOpenWindowsAutomatically = true
settings.mediaPlaybackRequiresUserGesture = false
// More optional settings, you can enable it by yourself
settings.domStorageEnabled = true
settings.setSupportMultipleWindows(true)
settings.loadWithOverviewMode = true
settings.allowContentAccess = true
settings.setGeolocationEnabled(true)
settings.allowUniversalAccessFromFileURLs = true
settings.allowFileAccess = true
// WebView settings
fitsSystemWindows = true
setLayerType(View.LAYER_TYPE_HARDWARE, null)
}
- jetpack compose - Room add remove update
- jetpack compose - WebView ProgressIndicator
- jetpack compose - WebView progress percentage
- jetpack compose - Backdrop scaffold
- jetpack compose - Kotlinx serialization allow special floating point values
- jetpack compose - Kotlinx serialization build json element
- jetpack compose - Kotlinx serialization decode josn element
- jetpack compose - How to use kotlin flow
- jetpack compose - Random number flow
- jetpack compose - Icon from vector resource