WebView allows you to display web content in your activity layout or Fragment but lacks some of the features of fully-developed browsers. A WebView is useful when you need to increase control over the UI and advanced configuration options that will allow you to embed web pages in a specially-designed environment for your app.
Note: To know more about WebView please refer to Android WebView in Kotlin or How to Use WebView in Android. In this article, we will see how we can search keywords(texts) inside a WebView using both Java and Kotlin.
A sample video is given below to get an idea about what we are going to do in this article.
Class Hierarchy
Java:
java.lang.Object
↳ android.view.View
↳ android.view.ViewGroup
↳ android.widget.AbsoluteLayout
↳ android.webkit.WebView
Kotlin:
kotlin.Any
↳ android.view.View
↳ android.view.ViewGroup
↳ android.widget.AbsoluteLayout
↳ android.webkit.WebView
Step by Step Implementation
Step 1: Create a new project in Android Studio
To create a new project in Android Studio please refer to How to Create/Start a New Project in Android Studio.
Step 2: Add Permissions in the AndroidManifest.xml File
In order to access the internet we have to add Internet permission in the AndroidManifest.xml file.
<uses-permission android:name=”android.permission.INTERNET” />
Step 3: Working with the activity_main.xml file
Navigate to app > res > layout > activity_main.xml and add the below code to it. Comments are added in the code to get to know in detail.
<? xml version = "1.0" encoding = "utf-8" ?>
< androidx.constraintlayout.widget.ConstraintLayout android:layout_width = "match_parent"
android:layout_height = "match_parent"
tools:context = ".MainActivity" >
<!-- Web-view on the Screen -->
< WebView
android:id = "@+id/webView"
android:layout_width = "match_parent"
android:layout_height = "match_parent" />
<!--ProgressBar for loading indicator-->
< ProgressBar
android:id = "@+id/progressBar"
style = "?android:attr/progressBarStyle"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
app:layout_constraintBottom_toBottomOf = "parent"
app:layout_constraintEnd_toEndOf = "parent"
app:layout_constraintStart_toStartOf = "parent"
app:layout_constraintTop_toTopOf = "@+id/webView" />
</ androidx.constraintlayout.widget.ConstraintLayout >
|
Step 4: Adding menu items in the Menu Resource file
In order to know what is menu items or how to add menu items please refer to Android Menus and How to Create Menu Folder & Menu File in Android Studio?
<? xml version = "1.0" encoding = "utf-8" ?>
<!--Search menu item-->
< item
android:id = "@+id/itemSearch"
android:icon = "@drawable/ic_search_24"
android:title = "Search"
app:actionViewClass = "androidx.appcompat.widget.SearchView"
app:showAsAction = "always|collapseActionView" />
<!--make sure you add the collapseActionView in showsAsAction-->
<!--menu item to jump to next keyword-->
< item
android:id = "@+id/itemNext"
android:icon = "@drawable/ic_arrow_down_24"
android:title = "Next Item"
android:visible = "false"
app:showAsAction = "always" />
<!--menu item to jump to previous keyword-->
< item
android:id = "@+id/itemPrevious"
android:icon = "@drawable/ic_arrow_up_24"
android:title = "Previous Item"
android:visible = "false"
app:showAsAction = "always" />
</ menu >
|
Step 5: Working with the MainActivity file
Navigate to app > java > your app’s package name > MainActivity file and add the below code to it. Comments are added in the code to get to know in detail.
Note: In the below code ViewBinding is used in order to reduce the boilerplate code and generated instances of the views of the current layout. This replaces the use of findViewById(). To know more about ViewBinding and how to enable ViewBinding please refer to View Binding in Android Jetpack.
import android.annotation.SuppressLint
import android.graphics.Bitmap
import android.os.Bundle
import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.webkit.WebView
import android.webkit.WebViewClient
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.SearchView
import com.example.geeksforgeeks.databinding.ActivityMainBinding
class MainActivity : AppCompatActivity() {
private var binding: ActivityMainBinding? = null
private var createMenu: Menu? = null
@SuppressLint ( "SetJavaScriptEnabled" )
override fun onCreate(savedInstanceState: Bundle?) {
super .onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding!!.getRoot())
// this will enable the javascript in the WebView
binding!!.webView.getSettings().setJavaScriptEnabled( true )
// load https://www.geeksforgeeks.org url in the WebView.
// WebViewClient allows you to handle
// onPageFinished and override Url loading.
binding!!.webView.setWebViewClient(object : WebViewClient() {
override fun onPageStarted(view: WebView, url: String, favicon: Bitmap) {
super .onPageStarted(view, url, favicon)
// set the visibility to visible when
// the page starts loading
binding!!.progressBar.setVisibility(View.VISIBLE)
}
override fun onPageFinished(view: WebView, url: String) {
super .onPageFinished(view, url)
// set the visibility to gone when
// the page gets loaded completely
binding!!.progressBar.setVisibility(View.GONE)
}
})
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
super .onCreateOptionsMenu(menu)
// create an reference of menu
createMenu = menu
val inflater = menuInflater
inflater.inflate(R.menu.menu, menu)
return true
}
@SuppressLint ( "NonConstantResourceId" )
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
R.id.itemSearch -> {
// create a searchView inside the actionbar
// when search menu item is clicked
val searchView = item.actionView as SearchView
// set the width to maximum
searchView.maxWidth = Int.MAX_VALUE
searchView.queryHint = "Search any keyword.."
// set a listener when the start typing in the SearchView
searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
override fun onQueryTextSubmit(query: String): Boolean {
// clear the focus when
// the text is submitted
searchView.clearFocus()
return false
}
override fun onQueryTextChange(query: String): Boolean {
// When the query length is greater
// than 0 we will perform the search
if (query.length > 0 ) {
// findAllAsync finds all instances
// on the page and
// highlights them,asynchronously.
binding!!.webView.findAllAsync(query)
// set the visibility of nextItem
// and previous item to true
createMenu!!.getItem( 1 ).isVisible = true
createMenu!!.getItem( 2 ).isVisible = true
} else {
binding!!.webView.clearMatches()
// set the visibility of nextItem
// and previous item to false
// when query length is 0
createMenu!!.getItem( 1 ).isVisible = false
createMenu!!.getItem( 2 ).isVisible = false
}
return true
}
})
}
R.id.itemNext ->
// findNext highlights and scrolls to the next match
// found by findAllAsync(String),
// wrapping around page boundaries as necessary.
// true scrolls to the next match
binding!!.webView.findNext( true )
R.id.itemPrevious ->
// findNext highlights and scrolls to the next match found
// by findAllAsync(String),
// wrapping around page boundaries as necessary.
// false scrolls to the previous match
binding!!.webView.findNext( false )
}
return super .onOptionsItemSelected(item)
}
} |
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.SearchView;
import android.annotation.SuppressLint;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import com.example.geeksforgeeks.databinding.ActivityMainBinding;
public class MainActivity extends AppCompatActivity {
private ActivityMainBinding binding;
private Menu createMenu;
@SuppressLint ( "SetJavaScriptEnabled" )
@Override
protected void onCreate(Bundle savedInstanceState) {
super .onCreate(savedInstanceState);
binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
// this will enable the javascript in the WebView
binding.webView.getSettings().setJavaScriptEnabled( true );
// load https://www.geeksforgeeks.org url in the WebView.
// WebViewClient allows you to handle
// onPageFinished and override Url loading.
binding.webView.setWebViewClient( new WebViewClient(){
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super .onPageStarted(view, url, favicon);
// set the visibility to visible when
// the page starts loading
binding.progressBar.setVisibility(View.VISIBLE);
}
@Override
public void onPageFinished(WebView view, String url) {
super .onPageFinished(view, url);
// set the visibility to gone when the page
// gets loaded completely
binding.progressBar.setVisibility(View.GONE);
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super .onCreateOptionsMenu(menu);
// create an reference of menu
createMenu = menu;
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu, menu);
return true ;
}
@SuppressLint ( "NonConstantResourceId" )
@Override
public boolean onOptionsItemSelected( @NonNull MenuItem item) {
switch (item.getItemId()){
case R.id.itemSearch:
// create a searchView inside the actionbar
// when search menu item is clicked
SearchView searchView = (SearchView) item.getActionView();
// set the width to maximum
searchView.setMaxWidth(Integer.MAX_VALUE);
searchView.setQueryHint( "Search any keyword.." );
// set a listener when the start typing in the SearchView
searchView.setOnQueryTextListener( new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
// clear the focus when
// the text is submitted
searchView.clearFocus();
return false ;
}
@Override
public boolean onQueryTextChange(String query) {
// When the query length is greater
// than 0 we will perform the search
if (query.length()> 0 ){
// findAllAsync finds all instances
// on the page and
// highlights them,asynchronously.
binding.webView.findAllAsync(query);
// set the visibility of nextItem
// and previous item to true
createMenu.getItem( 1 ).setVisible( true );
createMenu.getItem( 2 ).setVisible( true );
} else {
binding.webView.clearMatches();
// set the visibility of nextItem
// and previous item to false
// when query length is 0
createMenu.getItem( 1 ).setVisible( false );
createMenu.getItem( 2 ).setVisible( false );
}
return true ;
}
});
break ;
case R.id.itemNext:
// findNext highlights and scrolls to the next match
// found by findAllAsync(String),
// wrapping around page boundaries as necessary.
// true scrolls to the next match
binding.webView.findNext( true );
break ;
case R.id.itemPrevious:
// findNext highlights and scrolls to the next match
// found by findAllAsync(String),
// wrapping around page boundaries as necessary.
// false scrolls to the previous match
binding.webView.findNext( false );
}
return super .onOptionsItemSelected(item);
}
} |
Output: