How i can dinamically change action button icon of Action Bar when i swipe fragments in ViewPager. Depending on fragment button must change state (icon).
You can set the correct icon in onPrepareOptionsMenu, and then invalidate your action bar with invalidateOptionsMenu (or ActivityCompat.invalidateOptionsMenu if you are using the support library) when you want the icon to update.
For example:
#Override
public boolean onPrepareOptionsMenu (Menu menu) {
MenuItem item = menu.findItem(R.id.my_menu_id);
item.setIcon(getMenuItemIconResId());
}
#Override
public void onPageSelected(int position) {
invalidateOptionsMenu();
}
I solved this problem:
1) I implement OnPageChangeLister
2) Invoke setIcon() in onPageScrollStateChanged()
3) MenuItem defined like global variable (field of class)
Related
I have been struggling to implement switching visibility of Share option on Menu between fragments. I am using sliding tab layout and has a fragment in each of the 2 tabs. First tab (uses list view) and when an item is selected, I am setting a flag as true and calls invalidateOptionsMenu() and it works fine by showing a share option on the App bar menu, but I am not able to cancel it when I move to the other fragment which has mainly preferences. Code is similar to the below.
public void setSharedIntentText(String text) {
sharedText = text;
if (shareOptionVisibility == false) {
shareOptionVisibility = true;
invalidateOptionsMenu();
}
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
// Locate MenuItem with ShareActionProvider
MenuItem shareItem = menu.findItem(R.id.menu_share);
// Fetch and store ShareActionProvider
mShareActionProvider = (ShareActionProvider) MenuItemCompat.getActionProvider(shareItem);
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.setType("text/plain");
sendIntent.putExtra(Intent.EXTRA_TEXT, sharedText);
mShareActionProvider.setShareIntent(sendIntent);
shareItem.setVisible(shareOptionVisibility);
When I switch between tabs, visibility should be set appropriately. I tried to set it onPause method of the first fragment, and then onResume method of second fragment, but control doesn't seem to go these methods when I look at the logcat. The code I have used to set visibility to false is as below in fragment2.
public void onResume() {
super.onResume();
Log.i(TAG, "On Resume ");
((MainActivity) getActivity()).shareOptionVisibility = false;
((MainActivity) getActivity()).invalidateOptionsMenu();
}
So would like to know where is the best place to put the code to control visibility when we switch between tabs. Here are the list of classes I use.
MainActivity, fragment1, fragment2, SlidingTabLayout, SlidingTabStrip and ViewPagerAdaptor. This code was implemented on top of the com.example.android.actionbarcompat.shareactionprovider example.
Thanks in advance
Issue now resolved by implementing the onCreateOptionsMenu method from the fragment rather than from the MainActivity.
Thanks
In my app I set the toolbar and status bar as shared objects as suggested in option #2 in this post
The general behavior and outline of the toolbar and tabs are excellent - the only issue is that when I move to activity B, some of the UI elements of the Toolbar are not participating in the content transition, particularly the Toolbar title and the menu icons.
I tried adding a SharedElementCallback and in it to loop over the children of the toolbar and tabs and add them all to a Fade transition - but it didn't affect the behaviour of the toolbar and tab content.
Any idea how to proceed from here? The desired effect is to have the elements of the Toolbar (title, up button, menu icons) participate in the content transition.
Added screenshots after comment:
Activity A
Activity B
Each activity has your own menu, so you have to create the menu for each one, even if they are the same.
However, if you prefer, you can create just one menu and create a custom class for manipulate the menu; Then you call this custom class on onCreateOptionsMenu and onOptionsItemSelected from whatever activity.
The following code is an example.
Custom class:
public class MenuActionBar {
public static void createOptionsMenu(final Activity activity, Menu menu) {
activity.getMenuInflater().inflate(R.menu.yourmenu, menu);
// Do whatever you wanna do
}
public static boolean optionsItemSelected(Activity activity, MenuItem item) {
// Do whatever you wanna do
}
}
Activity:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuActionBar.createOptionsMenu(this, menu);
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
return MenuActionBar.optionsItemSelected(this, item)
? true : super.onOptionsItemSelected(item);
}
I have one activity with 3 fragments (not tabs). I have several action bar items and I would like to hide them when a certain fragment is present. How can i go about this?
#Override
public void onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
MenuItem item3 = menu.findItem(R.id.ID OF MENU);
item3.setVisible(false);
}
If you wish to hide ALL menu items, just do:
#Override
public void onAttach(final Activity activity) {
super.onAttach(activity);
setHasOptionsMenu(true);
}
#Override
public void onPrepareOptionsMenu(final Menu menu) {
super.onPrepareOptionsMenu(menu);
menu.clear();//This removes all menu items (no need to know the id of each of them)
}
What i understand with your post is::
You have 3 fragments
You have 3 different set of actionbar buttons for 3 fragments
My preferred approach::You can also find the menu items which you dont want to display in your current fragment and set their visibility
MenuItem item = menu.findItem(<id>);
item.setVisible(<true/false>);
ex::
MenuItem item1 = menu.findItem(R.id.searchID);
item1.setVisible(false);
You can also use this post for a different approach to handle this problem
It's clear that for showing/hiding the indeterminate progress you have to use this method:
itemMenu.setActionView(...);
So:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_refresh:
item.setActionView(R.layout.indeterminate_progress_action);
runAsyncTask();
...
}
}
What is not clear to me is: how to set the action view back to null. I don't want to keep a reference to a MenuItem, I don't think it is correct since I don't want to assume anything about the OptionsMenu lifecycle.
How should I set back the action view to null on onPostExecute?
I do it like this :
refresh = false; // the future state of your indeterminate progress
invalidateOptionsMenu(); // trigger the recreation of the menu and call onCreateOptionsMenu(Menu)
then in your onCreateOptionsMenu(Menu) method :
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater)
{
super.onCreateOptionsMenu(menu, inflater);
MenuItem refreshItem = menu.add(Menu.NONE, R.id.action_bar_refresh, 1, "Refresh");
refreshItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
if(refresh)
refreshItem.setActionView(R.layout.indeterminate_progress_action);
else
refreshItem.setIcon(R.drawable.ic_menu_refresh);
}
How about invalidateOptionsMenu()? Your onCreateOptionsMenu() would probably always set it to null, then.
I believe you could just call setActionView(null) on that MenuItem
Then refresh the ActionBar with invalidateOptionsMenu()
There is no need to manipulate specific menu items if you would prefer not to.
I use a different approach that leverages off the system's indeterminate progress bar functionality (as ported to ActionBarSherlock). I explain it here to offer more options to future readers to use whichever way works best for them.
My base fragment has a method I call to turn my loading UI on & off. Here is a trimmed down version:
private void setLoading(final boolean isLoading)
{
final SherlockFragmentActivity sherlockActivity = getSherlockActivity();
sherlockActivity.runOnUiThread(new Runnable()
{
public void run()
{
// show loading progress bar
sherlockActivity
.setSupportProgressBarIndeterminateVisibility(isLoading);
// hide the rest of the menu
setMenuVisibility(!isLoading);
}
});
}
For this to work, your activity must be configured to use the correct style - call this from your SherlockFragmentActivity.onCreate() method:
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
The final trick is that on pre-HoneyComb devices, this causes the progress bar to show immediately by default (instead of being hidden by default from HC & above).
you must set it to be invisible
you must also create a Sherlock Action Bar instance before this code will work
The onCreate() thus becomes:
protected void onCreate(Bundle arg0)
{
super.onCreate(arg0);
// allow window to show progress spinner in the action bar
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
getSupportActionBar();
setSupportProgressBarIndeterminateVisibility(false);
}
For more details on this you can check my answer to
Intermediate Progress doesn't work with ActionBarSherlock running on Gingerbread (here).
If you don't want to keep a reference to the menu item, then you can simply keep a reference to the Menu object instead. A reference to the Menu is guaranteed to remain valid until the next time onCreateOptionsMenu() is called as mentioned in the docs (http://developer.android.com/reference/android/app/Activity.html#onCreateOptionsMenu(android.view.Menu)).
Then call:
MenuItem menuItem = mMenu.findItem(R.id.favourite_payment);
menuItem.setActionView(null);
Or alternatively if using AppCompat:
MenuItem menuItem = mMenu.findItem(R.id.favourite_payment);
MenuItemCompat.setActionView(menuItem, null);
There is no need to call invalidateOptionsMenu().
I have an Activity that extends ActionBarActivity taken from the ActionBarCompat code sample and I'm trying to show/hide menu items (actions) at runtime.
I've tried using setVisible() on the MenuItem and works for ICS, but in pre-ICS it only change visibility of menu items (menu button press) whereas the ActionBar doesn't get notified of menu changes.
Any solution? Thanks in advance!
I created multiple alternatives of the action bar items under /res/menu/. I keep a member to indicate which one I am using right now. to replace the menu, I call:
protected void setMenuResource(int newMenuResourceId)
{
_menuResource = newMenuResourceId;
invalidateOptionsMenu();
}
And I override onCreateOptionsMenu() to:
#Override
public boolean onCreateOptionsMenu(Menu menu)
{
if (_menuResource != 0)
{
getSupportMenuInflater().inflate(_menuResource, menu);
return true;
}
return super.onCreateOptionsMenu(menu);
}
Now, if I want to change the action Items, I call:
setMenuResource(R.menu.actionbar_menu_X);
This is how i solved it:
In ActionBarHelperBase.java of actionbarcompat project
...
private View addActionItemCompatFromMenuItem(final MenuItem item) {
final int itemId = item.getItemId();
....
The creator of this class copy properties of object, but didn't copy the id of item, so it is impossible to find it later with fiven id.
So i added it in that method:
...
actionButton.setId(itemId);
...
and in the same class i just use:
#Override
public void hideMenuItemById(int id, boolean show){
getActionBarCompat().findViewById(id).setVisibility(show? View.VISIBLE: View.GONE);
}
Hope it helps You.
You have to call supportInvalidateOptionsMenu() which is the relevant method for an ActionBarActivity:
http://developer.android.com/reference/android/support/v7/app/ActionBarActivity.html#supportInvalidateOptionsMenu()