first of all let's see how our example will be looking like :
it's actually just a WebView which is displaying a local Html page, this html page contains a java script slideshow component, I've actually used the very same code that i found over here. the original javascript component has two button which can be used to slide into the next or previous page, but what I wanted was to be able to slide through pages using Swiping Gestures, Like...Swipe Left...go to next page, Swipe Right ...previous page.
There are two javaScript functions , moveBackward() which replaces the current Item with previous one using a left to right sliding effect and moveForward() which does the exact opposite thing. all we need to do is to detect user Gestures, if it is a right to left gesture (swipe left) we will call moveForward()function and if it is a swipe right gesture we will call moveBackward() function, in this example I've used SimpleGestureFilter class (see my last post) and here is our onSwipe method implementation:
@Override
public void onSwipe(int direction) {
switch (direction) {
case SimpleGestureFilter.SWIPE_RIGHT : webView.loadUrl("javascript:moveBackward()");
break;
case SimpleGestureFilter.SWIPE_LEFT : webView.loadUrl("javascript:moveForward()");
break;
case SimpleGestureFilter.SWIPE_DOWN :
case SimpleGestureFilter.SWIPE_UP :
}
}
It's much easier than you though it would be, isn't it? we just need to pass the name of our javascript function (with 'javascript:' prefix) to loadUrl() method of the WebView instance.
as you can see in the pictures above, we have 3 buttons in our html form 'Add', 'Remove' and 'Report', we also have a Vector of Strings in our Activity; when 'Add' button is pressed the name of the current item will be sent to our activity and got stored in the Vector, when 'Remove' button is pressed the name of current item will be removed from Vector and in both cases a message will be shown afterwords that the operation has just been done :
if user presses the "Report" button a javascript popup box will be shown which says how many items are currently stored in our Vector:
here is the html and javascript code that is being used to render those 3 buttons:
.
.
.
var items = ["British Columbia", "Ontario", "Yukon","New Brunswick"];
function report(){
var contentStr = window.interface.getReportContent();
var contentDiv = document.getElementById("showBoxContent");
contentDiv.innerHTML = contentStr;
showBox();
}
.
.
.
<input type="button" onclick="window.interface.add(items[configParams.selected])" value="Add"/>
<input type="button" onclick="window.interface.remove(items[configParams.selected])" value="Remove"/>
<input type="button" onclick="report()" value="Report"/>
.
.
.
and here is our Activity source code :
public class WebViewSample extends Activity implements SimpleGestureListener{
private Handler handler = new Handler();
private WebView webView;
private SimpleGestureFilter filter;
private Vector<String> provinces = new Vector();
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.webview_layout);
webView = (WebView) findViewById(R.id.webview);
WebSettings webSettings = webView.getSettings();
webSettings.setSaveFormData(false);
webSettings.setJavaScriptEnabled(true);
this.filter = new SimpleGestureFilter(this,this);
this.filter.setMode(SimpleGestureFilter.MODE_TRANSPARENT);
webView.addJavascriptInterface(new MyJavaScriptInterface(), "interface");
webView.loadUrl("file:///android_asset/test.html");
}
@Override
public boolean dispatchTouchEvent(MotionEvent me){
this.filter.onTouchEvent(me);
return super.dispatchTouchEvent(me);
}
@Override
public void onSwipe(int direction) {
switch (direction) {
case SimpleGestureFilter.SWIPE_RIGHT : webView.loadUrl("javascript:moveBackward()");
break;
case SimpleGestureFilter.SWIPE_LEFT : webView.loadUrl("javascript:moveForward()");
break;
case SimpleGestureFilter.SWIPE_DOWN :
case SimpleGestureFilter.SWIPE_UP :
}
}
@Override
public void onDoubleTap() {
}
private void addOrRemove(String name,boolean add){
String msg = null;
boolean alreadyAdded = this.provinces.contains(name);
if(add){
if(!alreadyAdded){
this.provinces.add(name);
msg = name+" Has just been added to the List.";
}
else
msg = name+" Has already been added to the list.";
}
else{
if(alreadyAdded){
this.provinces.remove(name);
msg = name+" Has just been removed from the List.";
}
else
msg = name+" has never been added to the list!";
}
Toast.makeText(this, msg, Toast.LENGTH_LONG).show();
}
final class MyJavaScriptInterface {
MyJavaScriptInterface() {
}
public void add(final String name) {
handler.post(new Runnable() {
public void run() {
addOrRemove(name, true);
}
});
}
public void remove(final String name) {
handler.post(new Runnable() {
public void run() {
addOrRemove(name, false);
}
});
}
public String getReportContent() {
if(provinces.size() == 0)
return "<i> The list is empty. </i>";
String content = "<i>You have added these provinces into the list :<i><br/><br/>";
for(int i=0;i<provinces.size();i++)
content += (i+1)+"- "+provinces.get(i)+"<br/>";
return content;
}
}
}
as you can see all we have is a simple WebView instance which displays the content of 'test.html' file that is located in assets directory of our project.
we've called addJavascriptInterface() method of our WebView instance in order to be able to call java methods in javascript code this method has two parameters, the first one is an Object methods of which we want to call in our javascript code and the second parameter is an String which will be used as the name of that java object in javascript context. once addJavascriptInterface() method is called the specified java object will be attached to the Html document's window object and can be referred by its name.
Remember that when methods of the passed java object is called in javascript context, it's not gonna invoked in the Main(UI) thread, and if you need to get it called in the UI thread you will need to use a Handler and post a new runnable to run your code, just like what I've done for add() and remove() methods in this example (though it is not necessary in this example).
another important thing to remember is the fact that you cannot pass or return any complex object to or from javascript context, that is all you are allowed to use are primitive and String data types.