I have an application that works fine on different devices, including Google Nexus 4 (4.4.2), Nexus S (4.1.2) and Samsung S3 (4.1.*), but I am having display issues with menu inflation on S3 and S4 with 4.2.2+ (unconfirmed before that).
What is happening is that in Portrait mode, the menu appears and expands underneath the Tab Fragment (and possibly underneath the entire view). In Landscape, the menu appears and expands to cover the entire view, but above everything. In portrait, no text or icon appears (or at least they aren't visible in the top bit), but in Landscape they do.
A menu already exists and is being covered by the following:
public boolean onCreateActionMode(ActionMode actionMode, Menu menu) {
MenuInflater inflater = getActivity().getMenuInflater();
inflater.inflate(R.menu.actionmode, menu);
return true;
}
R.menu.actionmode:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:id="#+id/actionmode_delete"
android:title="#string/label_actionmode_delete"
android:icon="#drawable/actionmode_discard"
android:showAsAction="always|withText"/>
</menu>
I have no idea what is causing this issue with Samsung S3, S4 with 4.2+.
Update:
Turns out Samsung was doing something weird with this line of code within my style:
<item name="android:actionModeStyle">#style/MyActionMode</item>
Once I removed this line, the UI worked fine, but I still need to find a way to apply the styling I need.
Samsung was doing something weird with this line of code within my style:
<item name="android:actionModeStyle">#style/MyActionMode</item>
Luckily, I only required a background colour to be set, so I was able to do the following instead:
<item name="android:actionModeBackground">#color/custom_main_app_color</item>
I know this doesn't really fix the problem, it essentially sidesteps the issue, but it worked for me.
Related
I declared my menu items with android:showAsAction="ifRoom". My Activity is extending ActionBarActivity. In preview it is as expected but when run on my phone is it always in overflow.
From what I've seen nothing else is needed. My phone runs in Android 4.4.2 KitKat.
Am I missing anything else?
You have to define your own namespace, if you want to use the showAsAction attribute with ActionBarCompat(I assume you are using ActionBarCompat because you mentioned, that you're extending ActionBarActivity):
xmlns:app="http://schemas.android.com/apk/res-auto"
and use showAsAction like this:
<item [...] app:showAsAction="always"></item>
Just try this...
<item android:id="#+id/action_blah"
android:icon="#drawable/ic_c"
android:title="#string/action_blah"
app:showAsAction="(yourOptions)"/>
(yourOptions):
always = To force to show on the actionbar.
never = Not to show on your actionbar ever.
and
ifRoom = It will let your item if there is enough space on your action bar.
You can see these in Landscape mode.
HappyCoding
I have Activity with 3 tabs as Fragments. I also have 3 ActionBar items. On each tab only one item should be displayed and others should be in overflow menu. My code looks like this
private void updateMenuItemsVisibility()
{
MenuItem itemAddGate = menu.findItem(R.id.action_add_gate);
MenuItem itemAddLinking = menu.findItem(R.id.action_new_linking);
MenuItem itemNewConversation = menu.findItem(R.id.action_new_conversation);
MenuItemCompat.setShowAsAction(itemNewConversation,
MenuItemCompat.SHOW_AS_ACTION_NEVER);
MenuItemCompat.setShowAsAction(itemAddLinking, MenuItemCompat.SHOW_AS_ACTION_NEVER);
MenuItemCompat.setShowAsAction(itemAddGate, MenuItemCompat.SHOW_AS_ACTION_NEVER);
if (viewPager.getCurrentItem() == 0)
{
MenuItemCompat.setShowAsAction(itemNewConversation,
MenuItemCompat.SHOW_AS_ACTION_ALWAYS);
}
if (viewPager.getCurrentItem() == 1)
{
MenuItemCompat.setShowAsAction(itemAddLinking, MenuItemCompat.SHOW_AS_ACTION_ALWAYS);
}
if (viewPager.getCurrentItem() == 2)
{
MenuItemCompat.setShowAsAction(itemAddGate, MenuItemCompat.SHOW_AS_ACTION_ALWAYS);
}
}
and it works... on Android 4.x. On 2.1 line for hiding seems not to work. When I change tab to second tab 2 items appear, on third 3 items. Switching to previous tabs does not hide items. I'm using ActionBarCompat. Is it a bug?
edit: Actually it also behaves like this on Samsung Galaxy S (first one) running CyanogenMod on Android 4.1. So it might be connected to situation when we have physical button instead of software keys.
I'm not quite sure but the problem may be that API < 11 do not know the SHOW_AS_ACTION_ALWAYS as the the actionbar wasn't implemented yet.
That's why you have to add 2 additional lines of code in your menus like this:
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:yourapp="http://schemas.android.com/apk/res-auto">
<item
android:id="#+id/new_sms"
android:title="#string/create_sms"
android:orderInCategory="1"
android:showAsAction="always"
yourapp:showAsAction="always"
android:icon="#drawable/arrow_right" />
</menu>
The lines xmlns:yourapp="http://schemas.android.com/apk/res-auto" and yourapp:showAsAction="always" make it possible that the icons are always seen. Even for API 7 - 10.
Else the menu items will appear in the overflow menu.
I'm not sure how to implement this programmatically but you could write 3 menu ressources like that and call onSupportInvalidateOptionsMenu() to let the fragments show their own menus.
If you do so don't forget to call setHasOptionsMenu(true) in the fragments' onCreate().
After hours of browsing the internet, I am still having a problem showing a menu on my app.
I have a viewflipper with in it several scrollviews and they have several layouts as well.
The whole app works great, I can swipe from scrollview to scrollview without any problems.
Before I connected a Samsung Galaxy Tab to play with, I was running the app in the emulator. There if I pressed the menu button, the submenu was showing and I was able to run functions on menu item touch.
On the tablet, the menu is not showing anywhere.
Here is my menu file:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="#+id/KPNsites"
android:icon="#drawable/ic_menu_name"
android:title="KPN Sites"/>
<item
android:id="#+id/VDFsites"
android:icon="#drawable/ic_menu_name"
android:title="Vodafone sites"/>
</menu>
In my activity I have this code:
#Override
public boolean onCreateOptionsMenu(Menu my_menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu, my_menu);
return super.onCreateOptionsMenu(my_menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.KPNsites:
getKPNsiteInfo();
return true;
case R.id.VDFsites:
getVodafoneSiteInfo();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
When I run the app on the tablet, I only have a small bar at the top with only te app-name in it. I suspect the menu should be visible on that bar?
What else should I do / have done (differently)??
rg,
Eric
If your tablet is running Android 3.0 or greater you should change targetSdkVersion to <= 10 in manifest file.
You may want to consider using ActionBarSherlock this will give your app uniform and modern look on any Android version.
Try this example:
Menu Example
well gave it up for now.
every try messes up what I already got.
To get by, I've put buttons on the layout.
May be with the next project I get it working.
(but then by starting with it before I have all my layouts finished)
Thanks for the help!
rg,
Eric
I'm using the standard onCreateOptionsMenu, but on my Nexus w/ICS, when I tap the vertical menu button in the upper right corner, the dropdown context menu is 3/4 off the screen. Basically, I only see the first 3-4 letters in each menu items text.
Any ideas? Maybe I didn't get that memo!! I dont want to setup an ActionBar. I'd think by default, this should work fine?!?
Again, its pretty much standard menu code for < 3.0 SDK.
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
if (!isPro()) {
// add menu for ad-free Banner (launches Market)
inflater.inflate(R.menu.menu_pro, menu);
}
inflater.inflate(R.menu.menu, menu);
return true;
}
Using standard menu XML...
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="#+id/help"
android:icon="#drawable/ic_menu_help"
android:title="#string/menu_help"/>
<item
android:id="#+id/email"
android:icon="#drawable/email"
android:title="#string/menu_email"/>
I cant really say why its cutting off on the top, but I added this to my manifest.xml.
android:theme="#android:style/Theme.Black"
This basically reverts the style back to 2.x menus and places the vertical "dots" on the bottom right.
I actually prefer this over the default compatibility because I still have my icon menus as opposed to plain text-only dropdown menus.
I'd still like to know why the "default" conversion of my menu is screwed up though if anyone can chime in I'll award the solution to that person! (=
You can try to add this to you manifest:
supports-screens android:anyDensity="true"
I have an app using the ActionBar, where I handle orientation changes myself:
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
...and the menu should fit in the ActionBar without overflow in landscape, but not in portrait:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:title="#string/Game" android:id="#+id/game" android:icon="#android:drawable/ic_menu_manage" android:showAsAction="ifRoom|withText"/>
<item android:title="#string/Type" android:id="#+id/type" android:icon="#android:drawable/ic_menu_edit" android:showAsAction="ifRoom|withText"/>
<item android:title="#string/Other" android:id="#+id/other" android:icon="#android:drawable/ic_menu_gallery" android:showAsAction="ifRoom|withText"/>
<item android:title="#string/Solve" android:id="#+id/solve" android:icon="#android:drawable/ic_menu_directions" android:showAsAction="ifRoom|withText"/>
<item android:title="#string/Help" android:id="#+id/help" android:icon="#android:drawable/ic_menu_help" android:showAsAction="ifRoom"/>
</menu>
On startup, this works correctly:
Landscape:
Portrait:
(yes, I could force all items to always display and they would fit, as shown below, but that might break on a smaller tablet)
When the emulator changes orientation, the ActionBar's capacity doesn't seem to change:
Portrait, when I started in landscape:
(this is ok, but inconsistent)
Landscape, when I started in portrait:
This looks really silly and is the reason I want to fix this.
I added this call to invalidateOptionsMenu(), but it doesn't help:
#Override
public void onConfigurationChanged(Configuration newConfig)
{
maybeMoveSomeViewsAround(newConfig);
super.onConfigurationChanged(newConfig);
invalidateOptionsMenu();
}
(Actually I call it by reflection for backward compatibility, but the debugger tells me it really is called and does not encounter an exception.)
invalidateOptionsMenu() actually ends up calling onCreateOptionsMenu() (which re-inflates the menu) before returning, and I can see inside the latter that getResources().getConfiguration().orientation has already changed. So this is really puzzling. If the options menu is being recreated, when the orientation has changed, it must be ActionBar itself caching the width?
Is there a way to re-create the ActionBar without destroying/creating the Activity? (because the latter is a bit expensive in my case)
Edit: Here's a minimal sample project showing the issue.
Edit 2: I had thought of checking the screen width and programmatically adjusting the showAsAction flags between always and never appropriately, but that requires knowing (or guessing) the width of each item. ActionBar's public API does not help me on that point.
I ran into this problem to and came up with a hack which works 100%.
I eneded up calling invalidateOptionsMenu() two times. Look at the code below:
private boolean hackActionBarReset = false;
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
//a hack to reset the items in the action bar.
hackActionBarReset = true;
invalidateOptionsMenu();
hackActionBarReset = false;
invalidateOptionsMenu();
}
And in your onCreateOptionsMenu() set this on you menuitems you want to show:
item.setShowAsAction(MenuItem.SHOW_AS_ACTION_WITH_TEXT | (hackActionBarReset ? MenuItem.SHOW_AS_ACTION_NEVER : MenuItem.SHOW_AS_ACTION_IF_ROOM));
Not a pretty solution but it works.
I've cautiously worked around this: when the device's width is greater than 850dip, force showing all items in the ActionBar, otherwise continue to let the platform decide.
Here's the git commit. Edit: and the follow-up commit to fix using a field that's too new, oops. :-)
I'm definitely still interested in better answers (other than waiting for a fix to the platform).
I found that the simplest and most effective workaround was to clear the menu and then rebuild it.
For example:
Menu menu;
#Override
public boolean onCreateOptionsMenu(Menu menu) {
this.menu = menu;
// Setup code goes here...
}
#Override
public void onOrientationChanged() {
if (menu != null) {
menu.close(); // Ensure the menu is closed before changing its contents.
menu.clear();
onCreateOptionsMenu(menu); // Rebuild the menu.
}
}