All activities has similar "settings" button. OnClick, I want to show context menu. All clicks are handled by separate method:
case Tags.TAG_SETTINGS://if settings button clicked
a.registerForContextMenu(v);//a is activity
a.openContextMenu(v);//v is view(settings button imageview)
break;
I have tested this whether it is working or not. Tested in MainActivity
#Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
Toast.makeText(MainActivity.this, "Yeah", Toast.LENGTH_LONG).show();
}
This is showing toast with message "Yeah".
My question is how to create universal context menu which will be used in all activities?
You can create a subclass of Activity and then make all your activities be a class of that. Then you could implement your common context menu in that class. e.g.
public class BaseActivity extends FragmentActivity
{
#Override
public boolean onCreateOptionsMenu(Menu menu)
{
//common logic for menu
}
}
Then you would create your activity that would extend the base activity instead of activity.
You can create a base activity and implement it there. All other activities can extend your base activity, if they need the context menu.
Related
Strange, neither Fragment nor v4.Fragment implemented the "onContextMenuClosed". Other events are there, like onCreateContextMenu and onContextItemSelected.
I need to clean up something when the context menu is dismissed, which can be activated by back button, tapping on the blank area on screen, or select one menu item in the context menu.
How do I monitor the dismissal of a context menu in a fragment then?
The menu close event in a fragment will also trigger its parent activity's "onContextMenuClosed". So I just override the event and pass it to a self implemented event handling function in the fragment.
// The parent activity.java:
#Override
public void onContextMenuClosed(Menu menu) {
super.onContextMenuClosed(menu);
childFragment.onContextMenuClosed(menu);
}
// The child fragment.java:
public void onContextMenuClosed(Menu menu) {
// Do you business here.
}
Can anyone give a quick example of how to change the contents of an Activity action bar based on something that takes place in a fragment? My intent:
Normal menu items -> Something in the fragment is moved -> menu items change to save / discard buttons.
My first impulse is to setup Broadcast Receivers in both the activity and the fragment to cross talk, but I am not sure if this is correct.
Fragments can change menu in actionbar. For that you have to add necessary flag in fragment's oncreate() using method setHasOptionsMenu(true);
When your fragment is loaded you will get call at onCreateOptionsMenu(Menu menu, MenuInflater inflater) just like in an activity. Then do necessary changes to your menu.
Save you menu as global in fragment, and whenever you want to make a change, apply on it.
The following works for me. I have a custom class that implements ListView.MultiChoiceModeListener inside a Fragment:
public void onItemCheckedStateChanged(ActionMode mode, int position, long id, boolean checked) {
// Choose the correct Action Bar menu to display
int menu = myCondition == true ? R.menu.my_default_menu : R.menu.my_menu_2;
// Configure to use the desired menu
mode.getMenu().clear();
MenuInflater inflater = getActivity().getMenuInflater();
inflater.inflate(menu);
}
Given how you detect 'something in the fragment has moved', extending ListView.MultiChoiceModeListener may not work for you, but hopefully this illustrates how to change the menu. The key is to get access to a ActionMode instance.
I think you want to use a contextual action mode. On the drag event, you will start a new ActionMode which can replace the contents of the action bar with menu items specific to what you want to allow the user to do. Once the user chooses an action, you finish the action mode and the action bar returns to its previous state.
Not sure if an ActionBar instance would help with the menu you but would surely be useful.. Here's a way to get about it
Try this to get the ActionBar from the FragmentActivity using the onAttach(Activity activity) method in the Fragment.
First of all make a global object of your FragmentActivity in the Fragment like this
public class YourFragment extends Fragment {
private YourFragmentActivity context;
}
Override this in the YourFragment class
#Override
public void onAttach(Activity activity){
context = (YourFragmentActivity)activity;
super.onAttach(activity);
}
Then in the OnCreate method in the YourFragment do this
#Override
public View onCreateView(LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState){
...
android.support.v7.ActionBar actionBar = context.getSupportActionBar();
...
}
I'm an Android newbie, and working on an app which needs an Options menu. I have currently implemented the options menu by setting it as the primary activity and Extending it in the main activity.
But since I work in a team, this method doesn't work always with us since we need to extend another activity which is essential.
My Question
How do I implement this Options Menu across the application without Extending the activity in my Main activity?
My Current Setup
I have a MainActivity (This starts first) - MainActivity extends MenuClass
I have the OptionsMenu Class, MenuClass (I want this to be Application wide) - MenuClass extends Activity
I have three other Classes, that extends Activity itself! And these three activities are triggered from the MainActivity and when done, returns to the MainActivity.
If you don't want to, or can't create a base Activity which every other activity then extends - why don't you have a utilities class which has a public static void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {...} function and a public static boolean onOptionsItemSelected(MenuItem item) {...}?
public class Utils {
public static void onCreateOptionsMenu(Menu menu, MenuInflater inflater ){
//... create default options here
}
public static boolean onOptionsItemSelected(MenuItem item) {
//... see if you want to handle the selected option here, return true if handled
}
}
then from you Activity you can do this:
public class YourActivity extends Activity {
// ...
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater ){
Utils.onOptionsItemSelected(menu, inflater);
//... add other options here
}
public boolean onOptionsItemSelected(MenuItem item) {
boolean handled = Utils.onOptionsItemSelected(item);
if (!handled) {
switch(item.getItemId()) {
case R.id.menu_sign_out:
//... deal with option
break;
//.. deal with other options
}
}
return handled;
}
You may want to change the exact implementation of this depending on how you build it in to your app - ie you may not want the utils methods to be static as you may require some state to be maintained in there, but this should work.
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.
I am using a TabActivity (Main) with 3 TabSpecs
I am using Intents for the content of the 3 Tabs
TabA, TabB, TabC for example.
All these tab activities use common data that is stored in SharedPreferences
In the Main TabActivity I have an options menu which has a refresh option.
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.refresh_menu:
new updateCommonDataFromWeb().execute();
...
}
}
this refresh uses an AsyncTask (updateCommonDataFromWeb) to reload the common data from the web.
I need a way to tell the 3 tab activities to refresh their views and rebuild their content from the newly downloaded data.
When the tab activities are first created they load the data from SharedPreferences like so:
public class TabA extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.taba);
SharedPreferences prefs = getSharedPreferences(this.getString(R.string.prefs_name), 0);
String usage_data = prefs.getString("common_data", "");
}
}
I thought about making a common method on each of the tab activities
like.... reloadViewData()
I thought maybe I could use the activity manager from the Main TabActivity to get the activity of the current tab like so:
String tabTag = tabHost.getCurrentTabTag();
Activity activity = getLocalActivityManager().getActivity(tabTag);
# then call the reloadData() method of the tab activity
activity.reloadViewData();
Unfortunately i cant get this approach to work, whilst activity is the correct instance its an Activity instead of a TabA,TabB or TabC
Maybe i've completely taken the wrong approach to the whole thing.
I have also read alot about not using Activities for tab content instead using views.
However I dont know what view to use to replace my <RelativeLayout /> as i cant use my R.layout.* as views.
If you change the common_data in the sharedPreferences you can also implement OnSharedPreferenceChangeListener in the Activites and check for key.equals("common_data").
You can extend Activity and make all your child activities to inherit from your extended activity, as this way you will implement the same code (service handling) in 1 activity(the parent).
Activity -> MyParentActivity -> MyChildActivity1
This way you will be able to cast all your child activities to MyParentActivity and run your custom method (you want to be implemented)