Wednesday, November 28, 2012

Building a HTML Options Menu for PhoneGap Android

Alright, sorry it took me so long to get back to this but I was busy getting things done for the 2.3.0 release. This is a continuation of my series of posts on menus the previous ones were on Context and Option menus. Also, the code is not perfect there are some things I want to do that will support multiple image sizes and organize the menu in multiple rows but I figured I'd release what I was able to re-create. My original code is somewhere on another laptop. So the new code is now available in this github repo.

Okay, so if you want to use this component you will need to download OptionsMenu.js from the above link, place it in your assets/www folder then add the script tag after cordova.js in your HTML file.

Next you will want to create you menu. For my purposes I've used the settings/help example like the previous two posts on menus. To do it you add some code into your to the method that is listening for the "deviceready" event. Something like this:
and that will produce a menu that looks like this:


But let's dig in a bit of that call to create a new OptionsMenu. The magic is in the JSON object passed to the construction. Obviously the "id" is used to set the ID of the div that will hold the menu items. Then the items array will contain all of the menu items you want to display. Each menu item has three properties, image is a url the icon you want to display in the item, label which is the text which is shown under the image and finally action which is a JavaScript function that is called when the item is tapped.

So that's it, you have a fully functioning HTML/CSS/JS only options menu just by including an additional JavaScript file. Like I said the code is up on github and it is not perfect. Feel free to submit issues as I'm going to pick away at making it more robust after I take a mini vacation.

Update: So I realized the menu really should support multiple rows just like a real Android options menu so I just pushed an update to my code on Github to support it. Instead of an array being sent to the constructor of the OptionsMenu you send a multi-dimensional array like so:

and then it looks like this:


You will also notice the icons are a bit smaller. I'm checking for the size of the screen and adjusting the icon width and height accordingly.

15 comments:

webworker said...

Hi :)
the menu works fine and it is a really great alternative for the native menu but one thing that isn't working for me are the functions for each button. Pressing a menu button doesn't do anything, I tried to show an alert, but pressing the button just closes the menu.

Am I missing something?

Simon MacDonald said...

@webworker

Really, I can't reproduce that? What does your code look like?

jerone said...

I've updated your example with 2 fixes.
One is removing the trailing comma in the items array.
Second, define variables before using them, or define them as functions. This mite solve any issues @webworker mite have.
https://gist.github.com/4176054

Simon MacDonald said...

@jerone

Cool, thanks for catching the trailing comma. I fixed that in the gist as well. Then I moved the function definitions above the menu creation but I'm not sure if that will have any effect.

Rubén said...

Im trying to implement it on my android webapp but i cant. When i press the menu, it shows: UNDEFINED on a (3x2) table.

on index.html reference optionsMenu.js

on my js put the code at: function onDeviceReady() {

Can anyone help me??? Thanks

Simon MacDonald said...

@Rubén

Show the full error you are getting in "adb logcat".

Pavan Deshpande said...


Very nice tutorial you can also check this one at
http://www.pavanh.com/2012/10/android-menu.html

a srikanth said...

I am trying this example in my application but i can't get it.
when press menu option getting error like
-Can't open keycharmap file
-Error loading keycharmap file'system/usr/keychars/himax-touchscreen.kcm.bin'hw.keyboard.65537.devname='himax-touchscreen'

where am doing mistake can you please tell me

thanks in advance

Simon MacDonald said...

@a srikanth

When you are creating your emulator use the one listed as "Google API" for your Android level and this should go away.

a srikanth said...

I am running on device, not on emulater :(

Simon MacDonald said...

@a srikanth

Sorry, I've never seen that before, what device and version of Android does it run?

a srikanth said...

this is what my html page i used,please once go throw the following let me know any changes please,i am not able to move forward

my device is htc explorer version of android is 2.3.5

thanks in advance






function load() { document.addEventListener("deviceready", onDeviceReady, false);
}
function onDeviceReady() {
var optionsmenu = new OptionsMenu({
id : "optionsmenu",
items : [ [ { label : "Settings",
image : "images/settings.png",
action : onSettings
}, {
label : "Help",
image : "images/help.png",
action : onHelp
} ], [ {
label : "Row 2", image : "images/settings.png", action : onHelp
} ], [ {
label : "Row 3",
image : "images/settings.png",
action : onSettings
}, {
label : "More Help",
image : "images/help.png",
action : onHelp
}, {
label : "Even More Help",
image : "images/help.png",
action : onHelp
} ], ]
});
}






try hitting your menu button...



Simon MacDonald said...

@a srikanth

You need to put it in a gist as the html is escaped.

Paul F said...

Hi Simon, can you post all the files in this example, i.e. the full working example files. I’ve tried like hell to get this working but I’m struggling. My knowledge of CSS, HTML & JAVESCRIPT programming is somewhat limited as I am self taught. I’m using Adobe Dreamweaver 5.5, and need an ‘option menu’ button for my current app. I’m writing for android on my Galaxy S3 Mini. It would be great to have this app finished and working. Many thanks in advance for your help.

Simon MacDonald said...

@Paul F

Well all the JS code is posted and the steps to get it going are in the blog post. Why don't you post up a gist of your code and I'll see if I can point out where you are going wrong.