I want to have a superclass activity that defines what basic menu items each activity should have in addition to their own.
Here is my code so far:
public abstract class SuperActivity extends FragmentActivity {
protected List<TextView> textView = new ArrayList<TextView>();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(getContentResource());
setTextViews(textView);
}
protected abstract void setTextViews(List<TextView> textViews);
protected abstract int getContentResource();
#Override
public boolean onCreateOptionsMenu(Menu menu)
{
getMenuInflater().inflate(R.menu.menuitemsforallsubclasses, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.basicmenuitem1:
allSubclassActivitiesCanDoThis()
return true;
case R.id.basicmenuitem2:
allSubclassActivitiesCanDoThis2()
return true;
}
}
}
In the subclasses I would then just add something to onCreateOptionsMenu (an additional layout file) and onOptionsItemSelected, is that correct? Just want to make sure I am not on the wrong track here. Would it even be possible to load multiple layout file in the same activity?
FYI: In case you are wondering why I have a TextView array in the activity: In addition to this I want to have all TextViews of each subclass activity in an ArrayList, so that I can add listeners to all of them automatically so I know when something has changed in the activity or to do some other neat stuff.
Is what I am doing possible? Is it possible to load multiple menu layout files?
Related
Lets say I have two different activities, both using the same toolbar, making use of the same layout and menu options. This part is no problem.
If I want a menu option to execute a specific function, I would naturally create a function, foo(), and call it when the menu option is selected. Because the onOptionsItemSelected(MenuItem item) method i handled individually in each acitivity, would it be a good practice to use a separate class with static "toolbar functions"? E.g. having a logout() function accessible from the dropdown menu in the toolbar from any activity.
It may seem obvious, however, I cannot find any "best practices" on the matter. So what are the best practice(s) for handling multiple activities calling the same "toolbar function"?
Example code: lets say MainActivity and SecondActivity both have the same toolbar. In both onCreate() methods:
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
Somewhere else in both of the acitivites:
#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.item_foo:
ToolbarFunctions.foo(); //Is this a good way to do it?
default:
break;
}
return super.onOptionsItemSelected(item);
}
Good practice it's using main parent activity class and extend all other activities. Here is some example of your parent Activity:
public abstract class MyParentActivity extends Activity {
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu, menu);
return true;
}
// This is your abstract function for other activity!
public void foo();
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.item_foo:
foo(); //Is this a good way to do it? Yes, here it's okey!
default:
break;
}
return super.onOptionsItemSelected(item);
}
}
So you can define 10 your activity that extends from MyParentActivity as a code below. That is all:
public class MyOtherActivity extends MyParentActivity {
// Here your function will be called in every time
// when you click to Toolbar buttons!
//
// And you don't need write again about clicking menu!
#Ovveride
public void foo () {
//Any your behaviour
}
}
You can define a BaseActivity class and extend all other activities from the BaseActivity. You would include the common parts in the BaseActivity.
If your foo() function has only logic and no view logic, then is better to keep it in static class.It will be faster and unit testable. If it has view logic in it than go with BaseActivity example. If it has view and functional logic together may be is better to be static and also extend BaseActivity which must implement an interface with a method for your view updates.That interface you will pass to you static foo() method which will do the functional logic and will return with the interface to the activity called it, to let the activity update the view it self. Than you can still unit test your foo() method.
public interface FooInterface{
void onFooDone(Foo foo);
}
public static void foo(FooInterface fooInterface){
calculate...
if(fooInterface!=null)
fooInterface.onFooDone(fooObject);
}
Your activity must implement FooInterface
and call foo(this);
I've many activities in my project and one activity for Login but I want that only show menu in all activities except in activity login, because in that menu will be an icon of end session and when press, return to the login activity. And not how, could you help me?
I would recommend that the layout for login does not have the menu and the layout of other activities if the menu has
Better to an base activity which contains your code for menus and then you can extend it your activities instead of activity.
And for login you can extend activity. so all the activities which extend baseactivity will be reflected with menu with out need to write menus code in every activity. and for the will be no menu as it does not extend base activity.
Updated:::
public class BaseActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
}
/* Creates the menu items */
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.options_menu, menu);
return true;
}
/* Handles item selections */
public boolean onOptionsItemSelected(MenuItem item) {
switch(item.getItemId())
{
case R.id.menu1:
//your stuff
break;
case R.id.menu2:
//your stuff
break;
}
return true;
}
}
Is there a convenient way of showing the same Options menu options in multiple Activities?
Example: In my app, I display a TV Guide in one of three ways.
Seven day guide (TabActivity with 7 tabs)
All channels 'Now showing' (ListActivity)
All shows today by start time (Activity - could be changed easily to ListActivity)
For the Options menu in the TabActivity, the code is quite simple...
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
menu.clear();
inflater.inflate(R.menu.gv_options_menu, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.view:
...
...
}
}
...but at the moment it seems I need to copy/paste it to the other two Activities which I don't like doing. If I change the Options menu code for one I'll need to do it for the other two also.
The only alternative I can think of is I have a 'helper' class (POJO) to which I could add a method and pass the context into to allow use of the getMenuInflator() method and another method I could pass the result of item.getItemId() into to process with the switch-case.
What is the normal way of having multiple Activities with the same Options menu?
Create a simple separate class with these two methods:
public class MyMenuHandler {
private Activity mActivity;
public MyMenuHandler(Activity activity) {
mActivity = activity;
}
public boolean onPrepareOptionsMenu(Menu menu) {
MenuInflater inflater = mActivity.getMenuInflater();
menu.clear();
inflater.inflate(R.menu.gv_options_menu, menu);
return true;
}
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.view:
...
}
}
}
In your activities override those callback methods and redirect the call to an instance of your MyMenuHandler class:
public class MyActivity1 extends TabActivity {
private MyMenuHandler mMenuHandler;
#Override
public void onCreate(Bundle savedInstanceState) {
...
mMenuHandler = new MyMenuHandler(this);
}
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
// you may also add here some items which are specific
// for one activity, not for the others
...
return mMenuHandler.onPrepareOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// handle selection of your specific items here,
// if none of them has been selected call mMenuHandler method
...
return mMenuHandler.onOptionsItemSelected(item);
}
}
This will let you hold in one place the code which respond to selection of your basic menu items, so there will be no need to worry about copy-pasting it to all activities which are to have the same menu.
One approach is to use inheritance with your Activities. Create a base Activity that implements the options menu methods and then each child Activity will gain that functionality. This is the recommended approach on the Android developer site:
Tip: If your application contains multiple activities and some of them provide the same Options Menu, consider creating an activity that implements nothing except the onCreateOptionsMenu() and onOptionsItemSelected() methods. Then extend this class for each activity that should share the same Options Menu. This way, you have to manage only one set of code for handling menu actions and each descendant class inherits the menu behaviors.
Unfortunately this won't work for you as you are not inheriting from Activity itself but differing subclasses of it, but that is the 'normal' way to do it.
You can encapsulate your action menu in a fragment. In this way you only need to add the fragment in the onCreate menu of your activity.
You need to call setHasOptionsMenu once the fragment is created.
To add the add fragment use a tag instead of a layout id.
For an android application I need to have a single menu in common that can be displayed on every screen with its structure and functionality written in another class or activity that can be used in all other activities.
Create baseClass Activity. There you can implement the menu structure. After that each activity extends this baseClass activity.
Create a MainActivity which extends ActivityGroup class and all other activity as its sub activities . Use onCreateOptionsMenu(Menu menu) method to addmenu item in MainActivity.
All the other activity can show that menu items automatically.
see this:
public class MainActivity extends ActivityGroup {
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// TODO Auto-generated method stub
menu.add("1");
menu.add("2");
return super.onCreateOptionsMenu(menu);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//start other activity here
}
}
Hope this will give you some idea on the issue.
I have 10-15 activities in my project. I want to have the option menu mostly in all Activities. Then is their any way we can do it at one place and it appears in all activities.
Also, I will like to hide the option menu in some. So, is it possible or I have to write option menu code in all activities.
Regards
Sunil
Create a Class (say BaseActivity) that extends Activity, and override onCreateOptionsMenu and onOptionsItemSelected functions.
public class BaseActivity extends Activity {
// Activity code here
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.options_menu, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.item:
// do what you want here
return true;
default:
return super.onOptionsItemSelected(item);
}
}
}
Now, in the other 15-16 activities, instead of extending an Activity, you should extend BaseActivity.
public class FooActivity extends BaseActivity {
// Activity code here
}
This way, all your activities derive the options menu. For activities where you want the options menu disabled, you can override it again in that particular activity.
public class BarActivity extends BaseActivity {
// Activity code here
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Do Nothing
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Do Nothing
}
}
Hopefully, it doesn't give you problems in the manifest file.
The solution to this problem is in your new activity add this menu method.
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_home_page, menu);
menu.removeItem(R.id.logout);
return true;
}
In each activity this method will automatically appear.
If it doesn't then add it with the inflate call. It requires two parameters, an xml resource(the same one that you used in your original activity), and the menu object that is pass into the onCreateOptionsMenu method.
menu.removeItem will remove the menu item of whatever resource id you pass to it.
I hope this helps those who are facing this problem.
Thank you, and happy to share this post.
It is not enough to just extend the BaseActivity, you must also call super.onCreateOptionsMenu(menu) and super.onOptionsItemSelected(item) like this in your other activities:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
//getMenuInflater().inflate(R.menu.menu_second, menu); <- remove this
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
return super.onOptionsItemSelected(item);
}