Hey people! 🙋‍♀️ Welcome to my blog on implementing WebView and WebKit in android.

Web view acts as an in-built browser which displays the webpages in Android. In other words, Web view turns your application into web application. WebView is an extension of Android’s View class.

It uses WebKit to display a web page which is a browser engine which provides tools for browsing the web. We have to add WebView widget to your xml layout file.

Preview

Preview image for article
WebView Android

1. Add dependencies and internet permissions

We need WebKit dependency since we need WebView to call.

implementation 'androidx.webkit:webkit:1.4.0'

Sync your project for gradle to download all required classes.

Also declare permission in project manifest file because we are loading data from internet, for that we need to declare internet permission.

<uses-permission android:name="android.permission.INTERNET" />

2. Showing simple WebView in activity

We can load web view content in both activity and fragments, in my case it’s an activity.
Lets’ get started with layout widget.

2.1 Declare WebView in layout

Inside you activity or fragments layout add a WebView.

<WebView
    android:id="@+id/simple_web_view" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" />

If the WebView is inside other parent layout, make sure you give proper size to fit inside the screen.

2.2 Load Url in activity

Get reference to the layouts view and declare a variable.
Call loadUrl to declared web view and pass the url we want it to load.
Call this inside onCreate( ) if you want to this load once user opens the activity.
If there is any user specified action then move loadUrl to that place it needs.

val webView: WebView = findViewById(R.id.simple_web_view)
webView.loadUrl("https://developersbreach.com")

3. Add ProgressBar while loading

Want to show progress until data is loading inside WebView ? We can make use of WebViewClient.Lets’ start by adding a horizontal progress bar to the top of the layout.

activity_main.xml :

<androidx.constraintlayout.widget.ConstraintLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ProgressBar
        android:id="@+id/progress_bar_simple_view"
        style="@android:style/Widget.Material.Light.ProgressBar.Horizontal"
        android:layout_width="match_parent"
        android:layout_height="5dp"
        android:indeterminate="true"
        app:layout_constraintTop_toTopOf="parent" />

    <WebView
        android:id="@+id/simple_web_view"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintTop_toBottomOf="@id/progress_bar_simple_view" />

</androidx.constraintlayout.widget.ConstraintLayout>

Implement a Client object to your WebView and override two functions. These functions knows when the data is still loaded and when it is completed loading.

In onPageStarted, show the progress bar because data is still being loaded.
In onPageFinished, hide the progress bar as page is completed loading.

// Find reference the ProgressBar
val progressBar: ProgressBar = view.findViewById(R.id.progress_bar_simple_view)

// Start the WebViewClient
webView.webViewClient = object : WebViewClient() {
    override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
        super.onPageStarted(view, url, favicon)
        progressBar.visibility = View.VISIBLE
    }

     override fun onPageFinished(view: WebView?, url: String?) {
        super.onPageFinished(view, url)
        progressBar.visibility = View.GONE
    }
}

This is how your MainActivity.kt should look like after these changes.

import android.graphics.Bitmap
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.webkit.WebView
import android.webkit.WebViewClient
import android.widget.ProgressBar

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val webView: WebView = findViewById(R.id.simple_web_view)
        val progressBar: ProgressBar = findViewById(R.id.progress_bar_simple_view)

        webView.loadUrl(WEB_URL_LINK)

        webView.webViewClient = object : WebViewClient() {
            override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
                super.onPageStarted(view, url, favicon)
                progressBar.visibility = View.VISIBLE
            }

            override fun onPageFinished(view: WebView?, url: String?) {
                super.onPageFinished(view, url)
                progressBar.visibility = View.GONE
            }
        }
    }

    companion object {
        const val WEB_URL_LINK: String = "https://developersbreach.com"
    }
}

4. Build interactive WebView

We need to enable JavaScript first in order to build a WebView which will be interactive. Next, a series of steps need to be followed.

4.1 Enable JavaScript

We need to enable JavaScript in a WebView. To achieve this, we must go to the web settings in our WebView. Then, we can retrieve WebSettings with getSettings() and finally enable JavaScript with setJavaScriptEnabled().
In your Activity/Fragment class , we enable JavaScript by assigning it to a boolean value as “true”.

val webSettings: WebSettings = webView.settings
webSettings.javaScriptEnabled = true

4.2 Add WebSettings

In the above block of code, we’ve added the WebSettings. Their main purpose is to provide access to the variety of other useful settings.

4.3 Search in WebView

If a user wants to search the webpage, we need to implement a search bar to get the query from the user. So, we design a layout using an XML file.

search_edit_text.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:paddingStart="?attr/dialogPreferredPadding"
    android:paddingTop="?attr/dialogPreferredPadding"
    android:paddingEnd="?attr/dialogPreferredPadding">

    <com.google.android.material.textfield.TextInputLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="4dp"
        android:hint="@string/enter_query_hint"
        app:errorEnabled="true">

        <com.google.android.material.textfield.TextInputEditText
            android:id="@+id/text_input_layout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />

    </com.google.android.material.textfield.TextInputLayout>

</FrameLayout>

Next, we have to add search function which will contain the search functionality.

private fun searchWebView() {
    val dialog: AlertDialog =
        MaterialAlertDialogBuilder(requireContext(), R.style.MaterialDialog)
            .setTitle(R.string.search_query_dialog_title)
            .setView(R.layout.search_edit_text)
            .setPositiveButton(R.string.search_query_dialog_positive_button, null)
            .setNegativeButton(R.string.search_query_dialog_negative_button, null)
            .create()

    dialog.setOnShowListener { alertDialog ->
        alertDialog as AlertDialog
        val positiveButton: Button = alertDialog.getButton(AlertDialog.BUTTON_POSITIVE)
        val negativeButton: Button = alertDialog.getButton(AlertDialog.BUTTON_NEGATIVE)
        val editText: TextInputEditText = alertDialog.findViewById(R.id.text_input_layout)!!

        positiveButton.setOnClickListener {
            val query: String = editText.text.toString()
            if (query.isEmpty()) {
                editText.error = getString(R.string.search_query_error_message)
            } else {
                webView.findAllAsync(query)
                dialog.dismiss()
                bottomAppBar.replaceMenu(R.menu.web_view_menu)
            }
        }

        negativeButton.setOnClickListener {
            alertDialog.dismiss()
        }
    }
    dialog.show()
    setDialogGravity(dialog)
}

Navigate or move to previous search entered query :

webView.findNext(false)

Navigate or move to Next search entered query :

webView.findNext(true)

4.4 Switch themes

WebView allows a user to switch between light theme and a dark theme according to the user’s preference. There are different states in ForceDark Setting. These include FORCE_DARK_OFF, FORCE_DARK_ON and FORCE_DARK_AUTO.

Keep track of current theme mode enabled and change values based on current state for correct theme to reflect on web view.

var themeMode = WebSettings.FORCE_DARK_OFF

private fun changeWebViewTheme() {
    if (themeMode == WebSettings.FORCE_DARK_ON) {
        webSettings.forceDark = WebSettings.FORCE_DARK_OFF
        themeMode = WebSettings.FORCE_DARK_OFF
    } else if (themeMode == WebSettings.FORCE_DARK_OFF) {
        webSettings.forceDark = WebSettings.FORCE_DARK_ON
        themeMode = WebSettings.FORCE_DARK_ON
    }
}

Stuck anywhere, we got you covered, refer to GitHub repository source code from below link.

That’s it people I hope you found this information useful, thanks for reading.

5. External Resources

Prathyusha M

Prathyusha will definitely match args with params. Is a student, pursuing her Bachelor’s degree in Computer Science and Engineering. She is a technophile, interested in Python, UI/UX Design and Android Development.


Connect with me

Heeba Shabreen

I’m not sure about mars, but definitely down to earth girl. Majoring in Computer Science. She is curious about new technologies, and is passionate about Android Development, UI/UX and Python.


Connect with me

Here We Go Again : (

if (article == helpful) {
    println("Like and subscribe to blog newsletter.")
} else {
    println("Let me know what i should blog on.")
}

This site uses Akismet to reduce spam. Learn how your comment data is processed.