My application is basically an online store that has a cart. The button to start the cart is in the ActionBar. When someone presses on a product it starts an animation where the product quicly "slides" through the screen towards the ActionBar cart button. As soon as that finishes the cart "blinks". To blink the cart I use
ValueAnimator cartAnim = ObjectAnimator.ofFloat(mCartItem, "alpha", 1,
0.25f, 0);
Where mCartItem is the ActionBar Item View to be animated.
Now as it turns out getting the View of the actual ActionBar item is kinda hard. I can get the View in onOptionsItemSelected but that's basically it, however this won't work for me since the animation isn't triggered from the ActionBar, it's triggered from a ListView in the main UI. After some googling I did however find a hack around this, that works:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getSupportMenuInflater().inflate(R.menu.cartmenu, menu);
new Handler().post(new Runnable() {
#Override
public void run() {
mCartItem = findViewById(R.id.theitem);
}
});
return(super.onCreateOptionsMenu(menu));
}
Why is this way working? As opposed to:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getSupportMenuInflater().inflate(R.menu.cartmenu, menu);
mCartItem = findViewById(R.id.theitem); // Always ends up null.
return(super.onCreateOptionsMenu(menu));
}
How would you solve the problem I had?
findViewById()
searches for a child view with the given id in "this" view. When you call it in onCreateOptionsMenu() the menu is still not attached to the main view, so you it cannot find your item.
Using Handler().post(new Runnable()...) the findViewById(R.id.theitem) is executed after all your view is created and, of course, even the menu has been attached to your main view, so it can be found.
Better solution:
since you are inflating your cart menu in the menu object, you can use:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getSupportMenuInflater().inflate(R.menu.cartmenu, menu);
mCartItem = menu.findItem(R.id.theitem); //This will find your menu item! :-)
return(super.onCreateOptionsMenu(menu));
}
Related
I need to get a reference to a MenuItem's corresponding View without specifying a custom one. Using findViewById() with a menu item's ID returns null when called from Activity#onCreate() or onCreateOptionsMenu(). However, as a few answers to other questions point out, findViewById() does return the view when called from onOptionsItemSelected() or from a runnable posted in Activity#onCreate(), like so...
new Handler().post(new Runnable() {
#Override
public void run() {
findViewById(R.id.some_view);
}
});
So it seems that at some point, Android takes the Menu that you populate in onCreateOptionsMenu() and creates the corresponding Views that are shown on screen. A Runnable posted from onCreate() happens to get run after that happens. But it feels so hacky to assume that will always be the case instead of actually listening for some kind of menuViewsCreated() event.
So that brings me to my question – does Android provide an event that tells developers that the menu Views have been created?
It's late but it may help some one else
you must use new Handler() in the onCreateOptionsMenu(Menu menu)
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.section, menu);
new Handler().post(new Runnable() {
#Override
public void run() {
final View menuItemView = findViewById(R.id.menu_item);
//TODO
}
});
return true;
}
I have a MenuItem (set in a fragment, though I tried in activity and got pretty much the same results) which is supposed to spin like a ProgressBar until I receive a broadcast.
I animate the Item by settings an ImageView as actionView and starting an animation on it. the problem is when onCreateOptionsMenu() is called again (for example after invalidateOptionsMenu() or switching to another fragment) the animation is not cleared while all my item are inflated again thus I lose my pointer to the previous actionView and cannot even cancel the animation manually with cancelAction().
here's my code:
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.fragment_playlist_synch, menu);
}
public void onPrepareOptionsMenu(Menu menu){
ImageView syncView = (ImageView) MenuItemCompat.getActionView( menu.findItem(R.id.menu_item_sync));
Animation rotate = AnimationUtils.loadAnimation(getContext(), R.anim.rotate);
rotate.setRepeatCount(Animation.INFINITE);
if(animate)
syncView.startAnimation(rotate);
else
//here the animation would always be null because a new sync menuitem is created in onCreateOptionsMenu without clearing the last one
syncView.clearAnimation();
}
My menu has a item to Log in, but when you are logged in I want it to say Log out.
How?
If I'm going to change the item after its created, its probably through this method
#Override
public boolean onCreateOptionsMenu( Menu menu ) {
MenuInflater inflater = getMenuInflater();
inflater.inflate( R.menu.menu_main, menu );
return true;
}
Afaik the onCreateOptionsMenu() happens after the onCreate so putting any getItemId() for the menu there will give me a NullPointerException right away.
I want the app to find out if its supposed to use the string R.string.Logout if its logged in.
I dont even know what to search for for this issue. All I found was how to make a string implement names, like this answer https://stackoverflow.com/a/7646689/3064486
You should use onPrepareOptionsMenu(Menu menu) instead to update menu items
#Override
public boolean onPrepareOptionsMenu(Menu menu){
super.onPrepareOptionsMenu(menu);
MenuItem someMenuItem = menu.findItem(R.id.some_menu_item);
someMenuItem.setTitle("Log out");
return super.onPrepareOptionsMenu(menu);
}
To refresh Menu items call invalidateOptionsMenu();from Activity
From Android API guides: "If you want to modify the options menu based on events that occur during the activity lifecycle, you can do so in the onPrepareOptionsMenu() method. This method passes you the Menu object as it currently exists so you can modify it, such as add, remove, or disable items. (Fragments also provide an onPrepareOptionsMenu() callback.)"
After you inflate a menu, you can customize its items. To get each one, you must call findItem() with the item's id. In particular, you can use setTitle() to change the displayed string.
For example:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
if (mIsLoggedIn)
menu.findItem(R.id.action_login).setTitle("Log out");
return true;
}
where action_login is the id you set for this particular menu item in the menu's xml file.
private void updateUI() {
runOnUiThread(new Runnable() {
#Override
public void run() {
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
Menu menu = navigationView.getMenu();
MenuItem nav_signin = menu.findItem(R.id.nav_signin);
nav_signin.setTitle(MyApp.signedIn ? "Sign out" : "Sign in");
}
});
}
I have an ActionBarSherlock with one menu item in my bar. When I'm call
View item = findViewById(R.id.my_item);in activity's button onClick all works fine as expected.
But when I try to do this in onCreate or onResume or even in onPostResume it is always null. I also tryed do this in onCreateOptionsMenu(Menu menu) after inflating my menu from resource, but without any succes.
Therefore I can't understand when actionbar items created and how to catch this moment?
As it has been said here and here, getActionView returns the view that we sets in setActionView. Therefore, the only one way to customize action bar menu item described here
actually it is possible to get the view of the action item, even if it's not customized.
however, do note that sometimes action items get to be inside the overflow menu so you might get a null instead.
so, how can you do it?
here's a sample code:
public boolean onCreateOptionsMenu(final Menu menu) {
getSupportMenuInflater().inflate(R.menu.main, menu);
new Handler().post(new Runnable() {
#Override
public void run() {
final View syncItemView = findViewById(R.id.action_search);
...
this was tested when using actionBarSherlock library, on android 4.1.2 and android 2.3.5 .
another alternative is to use a more extensive way , used on the showcaseView library, here .
first of all get a menu reference as below:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.custom_menu, menu);
customMenu = menu;
return super.onCreateOptionsMenu(menu);
}
after that you can get the item you need as below
customMenu.getItem(0);
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!