Home » 2013 » July

Common menu in android apps

Little trick, that goes well with DRY rule.
Every activity on android can contain menu defined in onCreateOptionsMenu(Menu menu) and onOptionsItemSelected(MenuItem item) methods. But what to do if we have multiple activities that share the same menu? Copy and paste methods? Better not. API Guides at android developers come with a trick: when multiple activities need to provide the same, common, menu a best way to do it is through inheritance.

In Asokoban I wanted a common menu with “about” and “highscores” options, that would show basic info about program, and highscores activity. And in-game activity menu should also contain a restart option. How?
I created a MenuActivity as a “empty” activity that implemented only methods connected with menu. Standard and one that implements tasks specific for options item. Example:

public class MenuActivity extends Activity {

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		getMenuInflater().inflate(R.menu.menu, menu);
		return true;
	}
	
	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case R.id.menu_about:
			showAbout();
			return true;
		case R.id.menu_highscores:
			showScores();
			return true;
		}
		return super.onOptionsItemSelected(item);
	}
	
	private void showAbout(){
		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		builder.setMessage(R.string.about_content)
	       	   .setTitle(R.string.menu_about);
		AlertDialog dialog = builder.create();
		dialog.show();
	}
	
	private void showScores(){
		Intent intent = new Intent(this, HighscoreActivity.class);
		
		startActivity(intent);
	}
}

Then all that’s left is to extend this class for every activity in program. And – in case of ingame activity with reset function – override onCreate and OnSelected methods with additional menu content. Example:

	@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
menu.add(Menu.NONE,ID_MENU_RESTART,120,R.string.menu_restart);
return true;
}