Ch5 Listings
satya - Thursday, June 11, 2009 3:58:15 PM
Listing 5-1: Signature for the onCreateOptionsMenu Method
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
// populate menu items
...
...return true;
}
satya - Thursday, June 11, 2009 4:00:54 PM
Listing 5-2: Adding Menu Items
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
//call the base class to include system menus
super.onCreateOptionsMenu(menu);
menu.add(0 // Group
,1 // item id
,0 //order
,"append"); // title
menu.add(0,2,1,"item2");
menu.add(0,3,2,"clear");
//It is important to return true to see the menu
return true;
}
satya - Thursday, June 11, 2009 4:02:21 PM
Listing 5-3. Using Group IDs to Create Menu Groups
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
//Group 1
int group1 = 1;
menu.add(group1,1,1,"g1.item1");
menu.add(group1,2,2,"g1.item2");
//Group 2
int group2 = 2;
menu.add(group2,3,3,"g2.item1");
menu.add(group2,4,4,"g2.item2");
return true; // it is important to return true
}
satya - Thursday, June 11, 2009 4:03:58 PM
Listing 5-4. Signature and Body of the onOptionsItemSelected Method
@Override
public boolean onOptionsItemSelected(MenuItem item)
{
switch(item.getItemId())
{
......
}
//for items handled
return true;
//for the rest
...return super.onOptionsItemSelected(item);
}
satya - Thursday, June 11, 2009 4:06:29 PM
Listing 5-5. Using a Listener as a Callback for a Menu-Item Click
//Step 1
public class MyResponse implements OnMenuClickListener
{
//some local variable to work on
//...
//Some constructors
@override
boolean onMenuItemClick(MenuItem item)
{
//do your thing
return true;
}
}
//Step 2
MyResponse myResponse = new MyResponse(...);
menuItem.setOnMenuItemClickListener(myResponse);
...
satya - Thursday, June 11, 2009 4:08:28 PM
Listing 5-6. XML Layout File for the Test Harness
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView android:id="@+id/textViewId"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Debugging Scratch Pad"
/>
</LinearLayout>
satya - Thursday, June 11, 2009 4:12:34 PM
Listing 5-7. Menu Test Harness Activity Class
public class SampleMenusActivity extends Activity
{
//Initialize this in onCreateOptions
Menu myMenu = null;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
//....other code
}
satya - Thursday, June 11, 2009 4:13:30 PM
Listing 5-8. Setting Up the Menu Programatically
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
//call the parent to attach any system level menus
super.onCreateOptionsMenu(menu);
this.myMenu = menu;
//add a few normal menus
addRegularMenuItems(menu);
//add a few secondary menus
add5SecondaryMenuItems(menu);
//it must return true to show the menu
//if it is false menu won't show
return true;
}
satya - Thursday, June 11, 2009 4:18:09 PM
Listing 5-9. The addRegularMenuItems Function
private void addRegularMenuItems(Menu menu)
{
int base=Menu.FIRST; // value is 1
menu.add(base,base,base,"append");
menu.add(base,base+1,base+1,"item 2");
menu.add(base,base+2,base+2,"clear");
menu.add(base,base+3,base+3,"hide secondary");
menu.add(base,base+4,base+4,"show secondary");
menu.add(base,base+5,base+5,"enable secondary");
menu.add(base,base+6,base+6,"disable secondary");
menu.add(base,base+7,base+7,"check secondary");
menu.add(base,base+8,base+8,"uncheck secondary");
}
satya - Thursday, June 11, 2009 4:20:34 PM
Listing 5-10. Adding Secondary Menu Items
private void add5SecondaryMenuItems(Menu menu)
{
//Secondary items are shown just like everything else
int base=Menu.CATEGORY_SECONDARY;
menu.add(base,base+1,base+1,"sec. item 1");
menu.add(base,base+2,base+2,"sec. item 2");
menu.add(base,base+3,base+3,"sec. item 3");
menu.add(base,base+3,base+3,"sec. item 4");
menu.add(base,base+4,base+4,"sec. item 5");
}
satya - Thursday, June 11, 2009 4:28:29 PM
Listing 5-11. Responding to Menu-Item Clicks
@Override
public boolean onOptionsItemSelected(MenuItem item)
{
if (item.getItemId() == 1) {
appendText("\nhello");
}
else if (item.getItemId() == 2) {
appendText("\nitem2");
}
else if (item.getItemId() == 3) {
emptyText();
}
else if (item.getItemId() == 4) {
//hide secondary
this.appendMenuItemText(item);
this.myMenu.setGroupVisible(Menu.CATEGORY_SECONDARY,false);
}
else if (item.getItemId() == 5) {
//show secondary
this.appendMenuItemText(item);
this.myMenu.setGroupVisible(Menu.CATEGORY_SECONDARY,true);
}
else if (item.getItemId() == 6) {
//enable secondary
this.appendMenuItemText(item);
this.myMenu.setGroupEnabled(Menu.CATEGORY_SECONDARY,true);
}
else if (item.getItemId() == 7) {
//disable secondary
this.appendMenuItemText(item);
this.myMenu.setGroupEnabled(Menu.CATEGORY_SECONDARY,false);
}
else if (item.getItemId() == 8) {
//check secondary
this.appendMenuItemText(item);
myMenu.setGroupCheckable(Menu.CATEGORY_SECONDARY,true,false);
}
else if (item.getItemId() == 9) {
//uncheck secondary
this.appendMenuItemText(item);
myMenu.setGroupCheckable(Menu.CATEGORY_SECONDARY,false,false);
}
else {
this.appendMenuItemText(item);
}
//should return true if the menu item
//is handled
return true;
}
satya - Thursday, June 11, 2009 4:30:51 PM
Listing 5-12. Utility Functions to Write to the Debug TextView
//Given a string of text append it to the TextView
private void appendText(String text)
{
TextView tv = (TextView)this.findViewById(R.id.textViewId);
tv.setText(tv.getText() + text);
}
//Given a menu item append its title to the TextView
private void appendMenuItemText(MenuItem menuItem)
{
String title = menuItem.getTitle().toString();
TextView tv = (TextView)this.findViewById(R.id.textViewId);
tv.setText(tv.getText() + "\n" + title);
}
//Empty the TextView of its contents
private void emptyText()
{
TextView tv = (TextView)this.findViewById(R.id.textViewId);
tv.setText("");
}
satya - Thursday, June 11, 2009 4:38:41 PM
Listing 5-13. The AndroidManifest.xml File for the Test Harness
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="your-package-name-goes-here "
android:versionCode="1"
android:versionName="1.0.0">
<application android:icon="@drawable/icon" android:label="Sample Menus">
<activity android:name=".SampleMenusActivity"
android:label="Sample Menus Application">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
satya - Thursday, June 11, 2009 4:43:20 PM
Listing 5-14. Adding Submenus
private void addSubMenu(Menu menu)
{
//Secondary items are shown just like everything else
int base=Menu.FIRST + 100;
SubMenu sm = menu.addSubMenu(base,base+1,Menu.NONE,"submenu");
sm.add(base,base+2,base+2,"sub item1");
sm.add(base,base+3,base+3, "sub item2");
sm.add(base,base+4,base+4, "sub item3");
//submenu item icons are not supported
item1.setIcon(R.drawable.icon48x48_2);
//the following is ok however
sm.setIcon(R.drawable.icon48x48_1);
//This will result in a runtime exception
//sm.addSubMenu("try this");
}
satya - Thursday, June 11, 2009 4:45:47 PM
Listing 5-15. Registering a TextView for a Context Menu
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
TextView tv = (TextView)this.findViewById(R.id.textViewId);
registerForContextMenu(this.getTextView());
}
satya - Thursday, June 11, 2009 4:49:39 PM
Listing 5-16. The onCreateContextMenu() Method
@Override
public void onCreateContextMenu(ContextMenu menu,
View v,
ContextMenuInfo menuInfo)
{
menu.setHeaderTitle("Sample Context Menu");
menu.add(200, 200, 200, "item1");
}
satya - Thursday, June 11, 2009 4:50:53 PM
Listing 5-17. Responding to Context Menus
@Override
public boolean onContextItemSelected(MenuItem item)
{
if (item.itemId() = some-menu-item-id)
{
//handle this menu item
return true;
}
//... other exception processing
}
satya - Thursday, June 11, 2009 4:54:45 PM
Listing 5-18. Populating a Menu with Alternative Menu Items
// Search for, and populate the menu with matching Activities.
menu.addIntentOptions(
Menu.CATEGORY_ALTERNATIVE, // Group
Menu.CATEGORY_ALTERNATIVE, // Any unique IDs we might care to add.
Menu.CATEGORY_ALTERNATIVE, // order
getComponentName(), // Name of the class displaying
//the menu--here, it's this class.
null, // No specifics.
criteriaIntent, // Previously created intent that
// describes our requirements.
0, // No flags.
null); // returned menu items
satya - Thursday, June 11, 2009 5:07:19 PM
Listing 5-19. MenuBuilder.addIntentOptions Method
public int addIntentOptions(int group, int id, int categoryOrder,
ComponentName caller,
Intent[] specifics,
Intent intent, int flags,
MenuItem[] outSpecificItems)
{
PackageManager pm = mContext.getPackageManager();
final List<ResolveInfo> lri =
pm.queryIntentActivityOptions(caller, specifics, intent, 0);
final int N = lri != null ? lri.size() : 0;
if ((flags & FLAG_APPEND_TO_GROUP) == 0)
{
removeGroup(group);
}
for (int i=0; i<N; i++)
{
final ResolveInfo ri = lri.get(i);
Intent rintent = new Intent(
ri.specificIndex < 0 ? intent : specifics[ri.specificIndex]);
rintent.setComponent(new ComponentName(
ri.activityInfo.applicationInfo.packageName,
ri.activityInfo.name));
final MenuItem item = add(group, id, categoryOrder, ri.loadLabel(pm));
item.setIntent(rintent);
if (outSpecificItems != null && ri.specificIndex >= 0)
{
outSpecificItems[ri.specificIndex] = item;
}
}
return N;
}
satya - Thursday, June 11, 2009 5:09:52 PM
Listing 5-20. An XML File with Menu Definitions
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<!-- This group uses the default category. -->
<group android:id="@+id/menuGroup_Main">
<item android:id="@+id/menu_testPick"
android:orderInCategory="5"
android:title="Test Pick" />
<item android:id="@+id/menu_testGetContent"
android:orderInCategory="5"
android:title="Test Get Content" />
<item android:id="@+id/menu_clear"
android:orderInCategory="10"
android:title="clear" />
<item android:id="@+id/menu_dial"
android:orderInCategory="7"
android:title="dial" />
<item android:id="@+id/menu_test"
android:orderInCategory="4"
android:title="@+string/test" />
<item android:id="@+id/menu_show_browser"
android:orderInCategory="5"
android:title="show browser" />
</group>
</menu>
satya - Thursday, June 11, 2009 5:14:43 PM
Listing 5-21. Building and Displaying an Alert Dialog
public class Alerts
{
public static void showAlert(String message, Context ctx)
{
//Create a builder
AlertDialog.Builder builder = new AlertDialog.Builder(ctx);
builder.setTitle("Alert Window");
//add buttons and listener
PromptListener pl = new EmptyListener();
builder.setPositiveButton("OK", pl);
//Create the dialog
AlertDialog ad = builder.create();
//show
ad.show();
}
}
public class EmptyListener
implements android.content.DialogInterface.OnClickListener
{
public void onClick(DialogInterface v, int buttonId)
{
}
}
satya - Thursday, June 11, 2009 11:16:51 PM
Listing 5-22. The prompt_layout.xml File
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/promptmessage"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_marginLeft="20dip"
android:layout_marginRight="20dip"
android:text="Your text goes here"
android:gravity="left"
android:textAppearance="?android:attr/textAppearanceMedium" />
<EditText
android:id="@+id/editText_prompt"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:layout_marginLeft="20dip"
android:layout_marginRight="20dip"
android:scrollHorizontally="true"
android:autoText="false"
android:capitalize="none"
android:gravity="fill_horizontal"
android:textAppearance="?android:attr/textAppearanceMedium" />
</LinearLayout>
satya - Thursday, June 11, 2009 11:19:23 PM
Listing 5-23. Inflating a Layout into a Dialog
LayoutInflater li = LayoutInflater.from(ctx);
View view = li.inflate(R.layout.promptdialog, null);
//get a builder and set the view
AlertDialog.Builder builder = new AlertDialog.Builder(ctx);
builder.setTitle("Prompt");
builder.setView(view);
satya - Thursday, June 11, 2009 11:22:48 PM
Listing 5-24. Setting Up OK and Cancel Buttons
//add buttons and listener
PromptListener pl = new PromptListener(view,ctx);
builder.setPositiveButton("OK", pl);
builder.setNegativeButton("Cancel", pl);
satya - Thursday, June 11, 2009 11:23:52 PM
Listing 5-25. Telling the Alert-Dialog Builder to Create the Dialog
//get the dialog
AlertDialog ad = builder.create();
ad.show();
//return the prompt
return pl.getPromptReply();
satya - Thursday, June 11, 2009 11:28:54 PM
Listing 5-26. PromptListener, the Listener Callback Class
public class PromptListener
implements android.content.DialogInterface.OnClickListener
{
// local variable to return the prompt reply value
private String promptReply = null;
//Keep a variable for the view to retrieve the prompt value
View promptDialogView = null;
//Take in the view in the constructor
public PromptListener(View inDialogView)
{
promptDialogView = inDialogView;
}
//Call back method from dialogs
public void onClick(DialogInterface v, int buttonId)
{
if (buttonId == DialogInterface.BUTTON1)
{
//ok button
promptReply = getPromptText();
}
else
{
//cancel button
promptValue = null;
}
}
//Just an access method for what is in the edit box
private String getPromptText()
{
EditText et = (EditText)
promptDialogView.findViewById(R.id.promptEditTextControlId);
return et.getText().toString();
}
public String getPromptReply() { return promptReply; }
}
satya - Thursday, June 11, 2009 11:32:34 PM
Listing 5-27. Code to Test the Prompt Dialog
public class Alerts
{
public static String prompt(String message, Context ctx)
{
//load some kind of a view
LayoutInflater li = LayoutInflater.from(ctx);
View view = li.inflate(R.layout.promptdialog, null);
//get a builder and set the view
AlertDialog.Builder builder = new AlertDialog.Builder(ctx);
builder.setTitle("Prompt");
builder.setView(view);
//add buttons and listener
PromptListener pl = new PromptListener(view,ctx);
builder.setPositiveButton("OK", pl);
builder.setNegativeButton("Cancel", pl);
//get the dialog
AlertDialog ad = builder.create();
//show
ad.show();
return pl.getPromptReply();
}
}
satya - Thursday, June 11, 2009 11:38:28 PM
Listing 5-28. The Abstraction of the Managed-Dialog Protocol
public class MainActivity extends ManagedDialogsActivity
{
//dialog 1
private GenericManagedAlertDialog gmad =
new GenericManagedAlertDialog(this,1,"InitialValue");
//dialog 2
private GenericPromptDialog gmpd =
new GenericPromptDialog(this,2,"InitialValue");
//menu items to start the dialogs
else if (item.getItemId() == R.id.menu_simple_alert)
{
gmad.show();
}
else if (item.getItemId() == R.id.menu_simple_prompt)
{
gmpd.show();
}
//dealing with call backs
public void dialogFinished(ManagedActivityDialog dialog, int buttonId)
{
if (dialog.getDialogId() == gmpd.getDialogId())
{
String replyString = gmpd.getReplyString();
}
}
}
satya - Thursday, June 11, 2009 11:41:52 PM
Listing 5-29. The ManagedActivityDialog Class
public abstract class ManagedActivityDialog implements IDialogProtocol
,android.content.DialogInterface.OnClickListener
{
private ManagedDialogsActivity mActivity;
private int mDialogId;
public ManagedActivityDialog(ManagedDialogsActivity a, int dialogId)
{
mActivity = a;
mDialogId = dialogId;
}
public int getDialogId()
{
return mDialogId;
}
public void show()
{
mActivity.showDialog(mDialogId);
}
public void onClick(DialogInterface v, int buttonId)
{
onClickHook(buttonId);
this.mActivity.dialogFinished(this, buttonId);
}
}
satya - Thursday, June 11, 2009 11:45:28 PM
Listing 5-30. The DialogRegistry Class
public class DialogRegistry
{
SparseArray<IDialogProtocol> idsToDialogs
= new SparseArray();
public void registerDialog(IDialogProtocol dialog)
{
idsToDialogs.put(dialog.getDialogId(),dialog);
}
public Dialog create(int id)
{
IDialogProtocol dp = idsToDialogs.get(id);
if (dp == null) return null;
return dp.create();
}
public void prepare(Dialog dialog, int id)
{
IDialogProtocol dp = idsToDialogs.get(id);
if (dp == null)
{
throw new RuntimeException("Dialog id is not registered:" + id);
}
dp.prepare(dialog);
}
}
satya - Thursday, June 11, 2009 11:49:13 PM
Listing 5-31. The ManagedDialogsActivity Class
public class ManagedDialogsActivity extends Activity
implements IDialogFinishedCallBack
{
//A registry for managed dialogs
private DialogRegistry dr = new DialogRegistry();
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.registerDialogs();
}
protected void registerDialogs()
{
// does nothing
// have the derived classes override this method
// to register their dialogs
// example:
// registerDialog(this.DIALOG_ALERT_ID_3, gmad);
}
public void registerDialog(IDialogProtocol dialog)
{
this.dr.registerDialog(dialog);
}
@Override
protected Dialog onCreateDialog(int id) {
return this.dr.create(id);
}
@Override
protected void onPrepareDialog(int id, Dialog dialog) {
this.dr.prepare(dialog, id);
}
public void dialogFinished(ManagedActivityDialog dialog, int buttonId)
{
//nothing to do
//have derived classes override this
}
}
satya - Thursday, June 11, 2009 11:51:05 PM
Listing 5-32. The IDialogFinishedCallBack Interface
public interface IDialogFinishedCallBack
{
public static int OK_BUTTON = -1;
public static int CANCEL_BUTTON = -2;
public void dialogFinished(ManagedActivityDialog dialog, int buttonId);
}
satya - Thursday, June 11, 2009 11:53:40 PM
Listing 5-33. The GenericManagedAlertDialog Class
public class GenericManagedAlertDialog extends ManagedActivityDialog
{
private String alertMessage = null;
private Context ctx = null;
public GenericManagedAlertDialog(ManagedDialogsActivity inActivity,
int dialogId,
String initialMessage)
{
super(inActivity,dialogId);
alertMessage = initialMessage;
ctx = inActivity;
}
public Dialog create()
{
AlertDialog.Builder builder = new AlertDialog.Builder(ctx);
builder.setTitle("Alert");
builder.setMessage(alertMessage);
builder.setPositiveButton("Ok", this );
AlertDialog ad = builder.create();
return ad;
}
public void prepare(Dialog dialog)
{
AlertDialog ad = (AlertDialog)dialog;
ad.setMessage(alertMessage);
}
public void setAlertMessage(String inAlertMessage)
{
alertMessage = inAlertMessage;
}
public void onClickHook(int buttonId)
{
//nothing to do
//no local variables to set
}
}
satya - Thursday, June 11, 2009 11:58:01 PM
Listing 5-34. The GenericPromptDialog Class
public class GenericPromptDialog extends ManagedActivityDialog
{
private String mPromptMessage = null;
private View promptView = null;
String promptValue = null;
private Context ctx = null;
public GenericPromptDialog(ManagedDialogsActivity inActivity,
int dialogId,
String promptMessage)
{
super(inActivity,dialogId);
mPromptMessage = promptMessage;
ctx = inActivity;
}
public Dialog create()
{
LayoutInflater li = LayoutInflater.from(ctx);
promptView = li.inflate(R.layout.promptdialog, null);
AlertDialog.Builder builder = new AlertDialog.Builder(ctx);
builder.setTitle("prompt");
builder.setView(promptView);
builder.setPositiveButton("OK", this);
builder.setNegativeButton("Cancel", this);
AlertDialog ad = builder.create();
return ad;
}
public void prepare(Dialog dialog)
{
//nothing for now
}
public void onClickHook(int buttonId)
{
if (buttonId == DialogInterface.BUTTON1)
{
//ok button
String promptValue = getEnteredText();
}
}
private String getEnteredText()
{
EditText et =
(EditText)
promptView.findViewById(R.id.editText_prompt);
String enteredText = et.getText().toString();
Log.d("xx",enteredText);
return enteredText;
}
}