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();
...
}
Related
I have a Fragment A which shows a MenuItem Mi in the toolbar. On clicking Mi, I am showing a DialogFragment Df to the user to set a value V.
I am passing this value to fragment A by implementing a callback listener interface.
Once the value is set, I want to hide Mi from toolbar menu of fragment A.
I wanted to handle this inside onPause() and onResume() of fragment A, but showing a DialogFragment doesn't change the lifecycle of fragment. I was wondering how to approach this problem.
How can I achieve this thing?
I did this using a callback listener in my fragment A which listens to DialogFragment Df. Once the value V is set, this callback method in A is invoked. Inside this method, I am using V and setting a flag to indicate V has been set and then calling invalidateOptionsMenu().
Refer this for implementing your own callback.
How to send data from DialogFragment to a Fragment?
public void myCallback(int V){
//Use V according to my logic
vIsSet = Boolean.TRUE;
getActivity().invalidateOptionsMenu();
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater){
super.onCreateOptionsMenu(menu,inflater);
if(vIsSet) {
menu.removeItem(MENU_ITEM_ID);//item id of Mi
}
}
I am developing a application that should support on both phone and tablet.
In this application i am using fragments from android.
Now the flow of the application is like
MainActivity --> Fragment1 --> Fragment2
In this application , i want a menu item that should show only in Fragment2 along with activity's menu items.
So i have tried one solution like adding globle menu items in MainActivity and in Fragment2 replacing the whole MainActivity's menu with Fragment2 specific Menu.
setHasOptionsMenu(true);
inside onCreateView , and implement this method.
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.menu_f, menu);
super.onCreateOptionsMenu(menu,inflater);
}
Now its work exactly fine for phone layout , but when its come to tablet problem arise.
Here is my ScreenShots.
Fragment 1
Fragment 1 and Fragment 2 combination when pressing 9 in keybord(Tablet mode ).
And Finally when i pressed 9 again to come back to pHone view it shows me extra menu item.
I just marked a extra menu item in Image. So why this me coming and how can i resolve it ?
You need to hide the menu group like this in your fragment 1
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
it'll make a call to onPrepareOptionsMenu where you can hide your menu group added by fragment2
#Override
public void onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
menu.setGroupVisible(0, false);
}
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.
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.
}
In some methods of my Activity I want to check the title of menu or know if it is checked or not. How can I get Activity's menu. I need something like this.getMenu()
Be wary of invalidateOptionsMenu(). It recreates the entire menu. This has a lot of overhead and will reset embedded components like the SearchView. It took me quite a while to track down why my SearchView would "randomly" close.
I ended up capturing the menu as posted by Dark and then call onPrepareOptionsMenu(Menu) as necessary. This met my requirement without an nasty side effects. Gotcha: Make sure to do a null check in case you call onPrepareOptionsMenu() before the menu is created. I did this as below:
private Menu mOptionsMenu;
#Override
public boolean onCreateOptionsMenu(final Menu menu) {
mOptionsMenu = menu
...
}
private void updateOptionsMenu() {
if (mOptionsMenu != null) {
onPrepareOptionsMenu(mOptionsMenu);
}
}
Call invalidateOptionsMenu() instead of passing menu object around.
you could do it by passing the Menu object to your Activity class
public class MainActivity extends Activity
{
...
...
private Menu _menu = null;
#Override
public boolean onCreateOptionsMenu(Menu menu)
{
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_main, menu);
_menu = menu;
return true;
}
private Menu getMenu()
{
//use it like this
return _menu;
}
}
There several callback methods that provide menu as a parameter.
You might wanna manipulate it there.
For example:
onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo)
onCreateOptionsMenu(Menu menu)
onCreatePanelMenu(int featureId, Menu menu)
There several more, best you take a look in activity documentation and look for your desired method:
http://developer.android.com/reference/android/app/Activity.html
As far as I could understand what you want here is which may help you:
1. Refer this tutorial over option menu.
2. Every time user presses menu button you can check it's title thru getTitle().
3. Or if you want to know the last menu item checked or selected when user has not pressed the menu button then you need to store the preferences when user presses.
Android now has the Toolbar widget which was a Menu you can set/get. Set the Toolbar in your Activity with some variation of setSupportActionBar(Toolbar) for stuff like onCreateOptionsMenu from a Fragment for example. Thread revived!