Sunday, March 18, 2012

Search text within a WebView

This article is to explain how to search for text within a WebView. The functions used are built into the WebView Class already. This article will show the classes used for search within a WebView, and also show how to create user interface functionality similar to the web browser on Android phones. The search functionality will include a text box for search word entry, a next button, close button, and text highlighting of search words found within the WebView. Here is a screenshot of what it will look like once we are finished:


Basic WebView
First, we are going to want to set up a WebView to add search functionality to.

SearchDemoActivity.java
package com.search.demo;

import android.app.Activity;
import android.os.Bundle;
import android.webkit.WebView;

public class SearchDemoActivity extends Activity {
WebView mWebView;
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        mWebView = (WebView)findViewById(R.id.webview);
        mWebView.loadUrl("http://devemat-androidprogramming.blogspot.com/");
    }
}

main.xml

<?xml version="1.0" encoding="utf-8"?>
<WebView  xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/webview"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
  
/>

SearchDemo Manifest
In your manifest make sure to add the internet permission so your web page loads.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.search.demo"
      android:versionCode="1"
      android:versionName="1.0">
    <uses-sdk android:minSdkVersion="8" />

    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".SearchDemoActivity"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

    </application>
      <uses-permission android:name="android.permission.INTERNET"/>
</manifest>
Test to make sure that your WebView is functioning correctly before moving on to the next step.

Add A Menu Option for Search
Now that we have a webpage loaded in our WebView we will add a search menu option for when the user wants to search the web page. Here is what our SearchDemoActivity.java looks like with the search menu option added:

SearchDemoActivity.java with Search Menu Option
package com.search.demo;

import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.webkit.WebView;

public class SearchDemoActivity extends Activity {
WebView mWebView;
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        mWebView = (WebView)findViewById(R.id.webview);
        mWebView.loadUrl("http://devemat-androidprogramming.blogspot.com/");
    }
  
    private static final int SEARCH_MENU_ID = Menu.FIRST;
  
    @Override
    public boolean onCreateOptionsMenu(Menu menu){
    super.onCreateOptionsMenu(menu);
    
    menu.add(0, SEARCH_MENU_ID, 0, "Search");
    
    return true;
    }
  
    public boolean onPrepareOptionsMenu(Menu menu){
     super.onPrepareOptionsMenu(menu);
    return true;
    }
  
    public boolean onOptionsItemSelected(MenuItem item){
    switch(item.getItemId()){
    case SEARCH_MENU_ID:
    
    return true;
    }
    return true;
    }
}
Search User Interface
Now that we have a webpage to search and a menu option to select search we need to create a user interface to get the search word from the user. Also we will enable the user to cycle through the found words and to close the search interface. To do this I create a dynamic Linear Layout. I'm sure you could create a static UI using XML, but this is the way that made since to me. First add a Linear Layout to our main.xml:

Main.xml with Linear Layout
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<WebView 
    android:id="@+id/webview"
   android:layout_width="fill_parent"
    android:layout_height="fill_parent"
  
/>

<LinearLayout
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/layoutId"

></LinearLayout>


</RelativeLayout>
Next we will have our Edit Box and buttons appear when the user selects search from the options menu. We will add a function called search to contain all of our search functionality. Here is what our SearchDemoActivity.java looks like with the added Linear Layout items:

SearchDemoActivity.java with Edit Box and Buttons
 package com.search.demo;


import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.webkit.WebView;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;

public class SearchDemoActivity extends Activity {
WebView mWebView;
private LinearLayout container;
private Button nextButton, closeButton;
private EditText findBox;
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        mWebView = (WebView)findViewById(R.id.webview);
        mWebView.loadUrl("http://devemat-androidprogramming.blogspot.com/");
    }
  
    private static final int SEARCH_MENU_ID = Menu.FIRST;
  
    @Override
    public boolean onCreateOptionsMenu(Menu menu){
    super.onCreateOptionsMenu(menu);
    
    menu.add(0, SEARCH_MENU_ID, 0, "Search");
    
    return true;
    }
  
    public boolean onPrepareOptionsMenu(Menu menu){
    super.onPrepareOptionsMenu(menu);
    return true;
    }
  
    public boolean onOptionsItemSelected(MenuItem item){
    switch(item.getItemId()){
    case SEARCH_MENU_ID:
    search();
    return true;
    }
    return true;
    }
  
    public void search(){
    container = (LinearLayout)findViewById(R.id.layoutId);
    
    nextButton = new Button(this);
    nextButton.setText("Next");
    container.addView(nextButton);
    
    closeButton = new Button(this);
    closeButton.setText("Close");
    container.addView(closeButton);
    
    findBox = new EditText(this);
findBox.setMinEms(30);
findBox.setSingleLine(true);
container.addView(findBox);
    }
}
Search Functionality
Now we just need to add functionality to our buttons and edit box. To do this we will use the WebView built in search functionality. Most notably is the WebView.findall(). This is going to do the search functionality for us. Then we just have to provide the button functionality. To do this we will use WebView.findnext() and LinearLayout.removeAllViews(). We will also add a hint that is displayed in our edit box using EditText.setHint(). Here is what our SearchDemoActivity.java looks like with the added search functionality:

SearchDemoActivity.java with Search Functionality
package com.search.demo;


import java.lang.reflect.Method;

import android.app.Activity;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnKeyListener;
import android.webkit.WebView;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;

public class SearchDemoActivity extends Activity {
WebView mWebView;
private LinearLayout container;
private Button nextButton, closeButton;
private EditText findBox;
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        mWebView = (WebView)findViewById(R.id.webview);
        mWebView.loadUrl("http://devemat-androidprogramming.blogspot.com/");
    }
  
    private static final int SEARCH_MENU_ID = Menu.FIRST;
  
    @Override
    public boolean onCreateOptionsMenu(Menu menu){
    super.onCreateOptionsMenu(menu);
    
    menu.add(0, SEARCH_MENU_ID, 0, "Search");
    
    return true;
    }
  
    public boolean onPrepareOptionsMenu(Menu menu){
    super.onPrepareOptionsMenu(menu);
    return true;
    }
  
    public boolean onOptionsItemSelected(MenuItem item){
    switch(item.getItemId()){
    case SEARCH_MENU_ID:
    search();
    return true;
    }
    return true;
    }
  
    public void search(){
    container = (LinearLayout)findViewById(R.id.layoutId);
    
    nextButton = new Button(this);
    nextButton.setText("Next");
    nextButton.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v){
mWebView.findNext(true);
}
});
    container.addView(nextButton);
    
    closeButton = new Button(this);
    closeButton.setText("Close");
    closeButton.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v){
container.removeAllViews();

}
});
    container.addView(closeButton);
    
    findBox = new EditText(this);
findBox.setMinEms(30);
findBox.setSingleLine(true);
findBox.setHint("Search");

findBox.setOnKeyListener(new OnKeyListener(){
public boolean onKey(View v, int keyCode, KeyEvent event){
if((event.getAction() == KeyEvent.ACTION_DOWN) && ((keyCode == KeyEvent.KEYCODE_ENTER))){
mWebView.findAll(findBox.getText().toString());

try{
Method m = WebView.class.getMethod("setFindIsUp", Boolean.TYPE);
m.invoke(mWebView, true);
}catch(Exception ignored){}
}
return false;
}
});

container.addView(findBox);
    }
}
And that's all there is to it. Your WebView should now have complete search functionality with search word highlighting similar to a web browser.

14 comments:

  1. I have problems with HTC Sense UI =/ can't use the Deletekey to delete chars from the entered string.. any advise ?

    ReplyDelete
    Replies
    1. I'm not sure. This design uses EditText which is standard android Class. I would try creating a new project to test EditText on that phone. It may be because it is being created dynamically. So I would try putting it in XML and see if that works.

      Delete
    2. This comment has been removed by the author.

      Delete
  2. dont hilight search word in webview please give correct way

    ReplyDelete
  3. it give mediaplayer error 2

    what's problem
    plz give solution my problem

    ReplyDelete
  4. Why It not highlight First world. If i want to search THE and write T than it not highlight but when i write H than it highlight T. How can solve this problem.

    ReplyDelete
  5. highlighted text not work for android 4.0

    ReplyDelete
  6. it working great for android 2.2 but it no show highlight for 4.0

    ReplyDelete
  7. Hi,The type is not advisable for a small business because the URL is not search engine friendly in Web Design Cochin and the limited server capabilities your ISP offer may not be sophisticated enough for a small business website.Thanks.....

    ReplyDelete
  8. The method findAll(String) from the type WebView is deprecated ? chane ?

    ReplyDelete
  9. This information is impressive; I am inspired with your post writing style & how continuously you describe this topic. After reading your post, thanks for taking the time to discuss this, I feel happy about it and I love learning more about this topic.Android Training in chennai | Android Training|Android Training in chennai with placement | Android Training in velachery

    ReplyDelete
  10. Your blog has given me that thing which I never expect to get from all over the websites. Nice post guys!

    Melbourne SEO Services

    ReplyDelete
  11. even after clicking the close button the search results color is not disappearing. Help me

    ReplyDelete