Wagied Davids
Problem
Require a custom calendar using Javascript. Also shows how to interact between Java- script and Java.
Solution
Use a WebView component to load an HTML file containing the Epoch calendar java- script component. Steps involved:
• Download Epoch DHTML/Javascript calendar http://www.javascriptkit.com/ script/script2/epoch/index.shtml.
• Create an assets directory under your Android Project folder eg. TestCalendar/ assets/
• Code your main HTML file for referencing Epoch calendar • Create an Android Activity for launching the Epoch calendar.
Note that files placed in Android assets directory are referenced like this: file:///an- droid_asset/ (NOTE: triple leading slash and singular spelled asset )
Discussion
The solution - to make use of the WebView component for loading an HTML file containing the Epoch calendar javascript component. To enable interaction between the Javascript based view layer and the Java-based logic layer, a Java--Javascript bridge interface is required, MyJavaScriptInterface inner class. The onDayClick() function shows how to to call a javascript function from an Android actiivity eg. webview.loa- dUrl("javascript: popup();");
File: calendarview.html Example 1-17.
<html> <head>
<title>My Epoch DHTML Javascript Calendar</title> <style type="text/css"> dateheader { -background-color: #3399FF; -webkit-border-radius: 10px; -moz-border-radius: 10px; -border-radius: 10px; -padding: 5px; } </style>
<style type="text/css"> html {height:100%;}
body {height:100%; margin:0; padding:0;}
#bg {position:fixed; top:0; left:0; width:100%; height:100%;} #content {position:relative; z-index:1;}
</style> <!--[if IE 6]>
<style type="text/css"> html {overflow-y:hidden;} body {overflow-y:auto;}
#page-background {position:absolute; z-index:-1;} #content {position:static;padding:10px;}
</style> <![endif]-->
<link rel="stylesheet" type="text/css" href="epoch_v106/epoch_styles.css" /> <script type="text/javascript" src="epoch_v106/epoch_classes.js"></script> <script type="text/javascript">
/*You can also place this code in a separate file and link to it like epoch_classes.js*/ var my_cal;
window.onload = function () {
my_cal = new Epoch('epoch_basic','flat',document.getElementById('basic_container')); };
function popup() {
var weekday=new Array("Sun","Mon","Tue","Wed","Thur","Fri","Sat");
var monthname=new Array("Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"); var date = my_cal.selectedDates.length > 0 ? my_cal.selectedDates[0] : null;
if ( date != null ) {
var day = date.getDate(); var dayOfWeek= date.getDay(); var month = date.getMonth(); var yy = date.getYear();
var year = (yy < 1000) ? yy + 1900 : yy;
/* Set the User selected date in HTML form*/
var dateStr= weekday[dayOfWeek] + ", " + day + " " + monthname[month] + " " + year; document.getElementById("selected_date").value= dateStr;
/* IMPORTANT: Call Android Javascript->Java bridge setting a Java-field variable */ window.android.setSelectedDate( date ); window.android.setCalendarButton( date ); } } </script> </head> <body>
<div id="bg"><img src="bg.png" width="100%" height="100%" alt=""></div> <div id="content">
<form name="form_selected_date">
<span style="color:white">Selected day:</span>
<input id="selected_date" name="selected_date" type="text" readonly="true"> </form>
</div>
<div id="basic_container" onClick="popup()"></div> </div> </body> </head>> File: CalendarView.java Example 1-18. import java.util.Date; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.os.Handler; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.webkit.JsResult; import android.webkit.WebChromeClient; import android.webkit.WebSettings; import android.webkit.WebView; import android.widget.Button; import android.widget.ImageView; import android.widget.Toast; import com.pfizer.android.R; import com.pfizer.android.utils.DateUtils; import com.pfizer.android.view.screens.journal.CreateEntryScreen; public class CalendarViewActivity extends Activity
{
private static final String tag = "CalendarViewActivity"; private ImageView calendarToJournalButton;
private Button calendarDateButton; private WebView webview;
private Date selectedCalDate;
private final Handler jsHandler = new Handler(); /** Called when the activity is first created. */ @Override
public void onCreate(Bundle savedInstanceState) {
Log.d(tag, "Creating View ..."); super.onCreate(savedInstanceState); // Set the View Layer
Log.d(tag, "Setting-up the View Layer"); setContentView(R.layout.calendar_view);
// Go to CreateJournalEntry
calendarToJournalButton = (ImageView) this.findViewById(R.id.calendarToJournalButton); calendarToJournalButton.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v) {
Log.d(tag, "Re-directing -> CreateEntryScreen ...");
Intent intent = intent = new Intent(getApplicationContext(), CreateEntryScreen.class); startActivity(intent);
} });
// User-Selected Calendar Date
calendarDateButton = (Button) this.findViewById(R.id.calendarDateButton); // Get access to the WebView holder
webview = (WebView) this.findViewById(R.id.webview); // Get the settings
WebSettings settings = webview.getSettings(); // Enable Javascript
settings.setJavaScriptEnabled(true); // Enable ZoomControls visibility settings.setSupportZoom(true); // Add Javascript Interface
webview.addJavascriptInterface(new MyJavaScriptInterface(), "android"); // Set the Chrome Client
webview.setWebChromeClient(new MyWebChromeClient()); // Load the URL of the HTML file
webview.loadUrl("file:///android_asset/calendarview.html"); }
public void setCalendarButton(Date selectedCalDate) { Log.d(tag, jsHandler.obtainMessage().toString()); calendarDateButton.setText(DateUtils.convertDateToSectionHeaderFormat(selectedCalDate.getTime())); } /** * * @param selectedCalDate */
public void setSelectedCalDate(Date selectedCalDate) {
this.selectedCalDate = selectedCalDate; }
/** * * @return */
public Date getSelectedCalDate() { return selectedCalDate; } /** * JAVA->JAVASCRIPT INTERFACE * * @author wagied * */
final class MyJavaScriptInterface {
private Date jsSelectedDate; MyJavaScriptInterface() {
// EMPTY; }
public void onDayClick() {
jsHandler.post(new Runnable() {
public void run() {
// Java telling Javascript to do things webview.loadUrl("javascript: popup();"); }
}); }
/**
* NOTE: THIS FUNCTION IS BEING SET IN JAVASCRIPT User-selected Date in * WebView
*
* @param dateStr */
public void setSelectedDate(String dateStr) {
Toast.makeText(getApplicationContext(), dateStr, Toast.LENGTH_SHORT).show(); Log.d(tag, "User Selected Date: Javascript -> Java : " + dateStr);
// Set the User Selected Calendar date
setJsSelectedDate(new Date(Date.parse(dateStr)));
Log.d(tag, "java.util.Date Object: " + Date.parse(dateStr).toString()); }
private void setJsSelectedDate(Date userSelectedDate) {
jsSelectedDate = userSelectedDate; }
public Date getJsSelectedDate()
{
return jsSelectedDate; }
} /**
* Alert pop-up for debugging purposes *
* @author wdavid01 *
*/
final class MyWebChromeClient extends WebChromeClient {
@Override
public boolean onJsAlert(WebView view, String url, String message, JsResult result) { Log.d(tag, message); result.confirm(); return true; } } @Override
public void onDestroy() {
Log.d(tag, "Destroying View!"); super.onDestroy();
} }
For debugging purposes, a MyWebChromeClient is created and the onJsAlert() meth- od is overriden.