I mount my NavigationView dynamically like this:
#Override
protected void onPostCreate(Bundle savedInstanceState) {
//nvDrawer is mount
Menu menu = nvDrawer.getMenu();
for (MyMenuItem kmi : menus.values()) {
menu.add(kmi.getText());
MenuItem mi = menu.getItem(menu.size() - 1);
mi.setTitle(kmi.getText());
Drawable dIcon =
getResources().getDrawable(getResources()
.getIdentifier(S
tring.valueOf(kmi.getIconId()), "drawable", getPackageName()));
mi.setIcon(dIcon);
}
}
So, I debug and the dIcon is setted, but the icon there appears in running app.
Every menus appears, but none icon appears, just silver rectangles.
P.S: My icons are png images.
I'm waiting.
Dimmy,
If you're running your code on Android 3.0+, the icons in the menu are not shown by design. This is a design decision by Google.
You can read more about it below on Android developers blog.
Hope it helps.
http://android-developers.blogspot.in/2012/01/say-goodbye-to-menu-button.html
Related
I am trying to set the title of the actionBar in a activity. I have 3 layout views in one activity. Each View Layout shows a different state of the payment process. Now that I set the title, at one stage the actionbar background gets messed up. I wonder why.
This does not happen if I comment out the following line.
onClick() {
....
getActionBar().setTitle("Customer Payment");
....
In the onCreate of the activity I run the following to setup the actionbar background.
private void setupActionBar() {
Drawable backgroundColor;
switch (getIntent().getIntExtra(God.HOME_SCREEN_OPERATION,
God.INVALID_ID)) {
case God.OPERATION_RECHARGE:
getActionBar().setIcon(R.drawable.icon_mobile);
backgroundColor = new ColorDrawable(getResources().getColor(
R.color.RechargeBackgroundColor));
getActionBar().setBackgroundDrawable(backgroundColor);
mobileServiceSummary.setVisibility(View.VISIBLE);
serviceInfoLayout.setBackground(backgroundColor);
serviceInfoIcon.setImageResource(R.drawable.icon_mobile);
break;
case God.OPERATION_FACILITY:
getActionBar().setIcon(R.drawable.icon_facility);
backgroundColor = new ColorDrawable(getResources().getColor(
R.color.ToiletBackgroundColor));
getActionBar().setBackgroundDrawable(backgroundColor);
facilityServiceSummary.setVisibility(View.VISIBLE);
serviceInfoLayout.setBackground(backgroundColor);
serviceInfoIcon.setImageResource(R.drawable.icon_facility);
break;
case God.OPERATION_DTH:
getActionBar().setIcon(R.drawable.icon_dth);
backgroundColor = new ColorDrawable(getResources().getColor(
R.color.DthBackgroundColor));
getActionBar().setBackgroundDrawable(backgroundColor);
dthServiceSummary.setVisibility(View.VISIBLE);
serviceInfoLayout.setBackground(backgroundColor);
serviceInfoIcon.setImageResource(R.drawable.icon_dth);
break;
// case R.id.mseb_payment:
// getActionBar().setIcon(R.drawable.icon_mseb);
// msebServiceSummary.setVisibility(View.VISIBLE) ;
// break;
default:
break;
}
}
Some more code..
private void enableCustomerPayment() {
getActionBar().setTitle("Customer Payment");
getActionBar().setSubtitle(
"Pincode of customer needed for payment permission.");
getActionBar().setDisplayHomeAsUpEnabled(false);
getActionBar().setHomeButtonEnabled(false);
getActionBar().setDisplayShowCustomEnabled(false) ;
getActionBar().setDisplayUseLogoEnabled(false) ;
findViewById(R.id.next_button).setVisibility(View.GONE);
findViewById(R.id.payment_button).setVisibility(View.VISIBLE);
findViewById(R.id.done_button).setVisibility(View.GONE);
operatorLockLayout.setVisibility(View.GONE);
customerLoginAndConfirmationLayout.setVisibility(View.VISIBLE);
customerPaymentLayout.setVisibility(View.GONE);
customerConfirmLayout.setVisibility(View.VISIBLE);
// customerConfirmSpaceLayout.setVisibility(View.VISIBLE);
}
private void enablePaymentConfirmation() {
getActionBar().setTitle("Payment Confirmation");
getActionBar().setSubtitle("Thankyou for your payment.");
setupActionBar();
getActionBar().setDisplayHomeAsUpEnabled(false);
getActionBar().setHomeButtonEnabled(false);
findViewById(R.id.next_button).setVisibility(View.GONE);
findViewById(R.id.payment_button).setVisibility(View.GONE);
findViewById(R.id.done_button).setVisibility(View.VISIBLE);
operatorLockLayout.setVisibility(View.GONE);
customerLoginAndConfirmationLayout.setVisibility(View.VISIBLE);
customerPaymentLayout.setVisibility(View.VISIBLE);
customerConfirmLayout.setVisibility(View.GONE);
// customerConfirmSpaceLayout.setVisibility(View.GONE);
}
In styles.xml the color's are setup like this. And the colors are working fine.
<color name="NewWalletBackgroundColor">#FFD54E</color>
<color name="BalanceBackgroundColor">#FFD54E</color>
<color name="DepositBackgroundColor">#FFD54E</color>
<color name="MsebBackgroundColor">#E57272</color>
<color name="RechargeBackgroundColor">#81C784</color>
<color name="DthBackgroundColor">#AB6BAC</color>
<color name="ToiletBackgroundColor">#56C0ED</color>
The Action Bar is messed up
Here, the Action Bar background is completely blue. This is what I expect.
Edit
Seems like there is a issue with the height, it starts up with 96 and when its messed up the height is 0.
How do I fix this now ?
In my opinion the default action bar is expecting an icon for the navigation drawer icon on the right of action bar. I think there is a transparent button on the space you are talking about. Even if you set the drawer for this activity or not it will be there if you use default methods to set the action bar.First try these steps
setDrawerIndicatorEnabled(false).
actionBar.setDisplayHomeAsUpEnabled(false)
actionBar.setHomeButtonEnabled(false);
If that does not work go for a custom action bar.
Do something like this. Instead of using the default actionbar why do not you try to set a custom view (plain TextView where its width is set to match parent).
this.getActionBar().setDisplayShowCustomEnabled(true);
this.getActionBar().setDisplayShowTitleEnabled(false);
LayoutInflater inflator = LayoutInflater.from(this);
View v = inflator.inflate(R.layout.titleview, null);
//if you need to customize anything else about the text, do it here.
((TextView)v.findViewById(R.id.title)).setText(this.getTitle());
//assign the view to the actionbar
this.getActionBar().setCustomView(v);
I'm assuming from your question that the enablePaymentConfirmation is working code with getActionBar().setTitle("Customer Payment"); present and when it is commented out. If it too is playing up, then I will need to alter my answer.
Not seeing your xml makes it a bit more guess work, but from I can see, I would suggest the following.
1.
Call setupActionBar() from you OnCreate in your activity. This way it is set up for the duration of your activity. By not calling it in OnCreate if you call enableCustomerPayment() before enablePaymentConfirmation(), the actionbar setup will not have been called.
2.
Unless the following change in code you have not shown, these can go in your setupActionbar:
getActionBar().setDisplayHomeAsUpEnabled(false);
getActionBar().setHomeButtonEnabled(false);
3.
These are the two changes to the ActionBar between the two methods you show:
getActionBar().setDisplayShowCustomEnabled(false) ;
getActionBar().setDisplayUseLogoEnabled(false) ;
4.
I am not sure why you are only setting setDisplayShowCustomEnabled in your enableCustomerPayment(). I cannot see that you are using a customView.
- If not that can also go into your setup.
- Otherwise you will need to call it in all your methods with the changes.
- If you are using a custom view for your actionbar in some places and not others, this will be affecting how it is displayed. Particularly if you are not managing the bool changes.
5.
Same goes for the logo, I don't see where you are using it. So I would put it in setup. If you are using it for the others and you haven't got your xml set up correctly, it could be why there is a difference in the background color.
Hope this helps. Feel free to post more info, xml would be good.
I'd like to have all of the menu items that don't fit into the ActionBar go into the overflow menu (the one that is reached from the Action Bar not the menu button) even on devices that do have a Menu button. This seems much more intuitive for users than throwing them into a separate menu list that requires the user to jump from a touch(screen) interaction to a button based interaction simply because the layout of the ActionBar can't fit them on the bar.
On the emulator I can set the "Hardware Back/Home Keys" value to "no" and get this effect.
I've searched for a way to do this in code for an actual device that has a menu button but can't fine one. Can anyone help me?
You can also use this little hack here:
try {
ViewConfiguration config = ViewConfiguration.get(this);
Field menuKeyField = ViewConfiguration.class.getDeclaredField("sHasPermanentMenuKey");
if (menuKeyField != null) {
menuKeyField.setAccessible(true);
menuKeyField.setBoolean(config, false);
}
} catch (Exception ignored) {
}
Good place to put it would be the onCreate-Method of your Application class.
It will force the App to show the overflow menu. The menu button will still work, but it will open the menu in the top right corner.
[Edit] Since it has come up several times now: This hack only works for the native ActionBar introduced in Android 3.0, not ActionBarSherlock. The latter uses its own internal logic to decide whether to show the overflow menu. If you use ABS, all platforms < 4.0 are handled by ABS and are thus subjected to its logic. The hack will still work for all devices with Android 4.0 or greater (you can safely ignore Android 3.x, since there aren't really any tablets out there with a menu button).
There exists a special ForceOverflow-Theme that will force the menu in ABS, but apperently it is going to be removed in future versions due to complications.
EDIT: Modified to answer for the situation of physical menu button.
This is actually prevented by design. According to the Compatibility Section of the Android Design Guide,
"...the action overflow is available from the menu hardware key. The resulting actions popup... is displayed at the bottom of the screen."
You'll note in the screenshots, phones with a physical menu button don't have an overflow menu in the ActionBar. This avoids ambiguity for the user, essentially having two buttons available to open the exact same menu.
To address the issue of consistency across devices: Ultimately it's more important to the user experience that your app behave consistently with every other app on the same device, than that it behave consistently with itself across all devices.
I use to workaround it by defining my menu like this (also with ActionBarSherlock icon used in my example):
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="#+id/menu_overflow"
android:icon="#drawable/abs__ic_menu_moreoverflow_normal_holo_light"
android:orderInCategory="11111"
android:showAsAction="always">
<menu>
<item
android:id="#+id/menu_overflow_item1"
android:showAsAction="never"
android:title="#string/overflow_item1_title"/>
<item
android:id="#+id/menu_overflow_item2"
android:showAsAction="never"
android:title="#string/overflow_item2_title"/>
</menu>
</item>
</menu>
I admit that this may require manual "overflow-management" in your xml, but I found this solution useful.
You can also force device to use HW button to open the overflow menu, in your activity:
private Menu mainMenu;
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// TODO: init menu here...
// then:
mainMenu=menu;
return true;
}
#Override
public boolean onKeyUp(int keycode, KeyEvent e) {
switch(keycode) {
case KeyEvent.KEYCODE_MENU:
if (mainMenu !=null) {
mainMenu.performIdentifierAction(R.id.menu_overflow, 0);
}
}
return super.onKeyUp(keycode, e);
}
:-)
If you are using the action bar from the support library (android.support.v7.app.ActionBar), use the following:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:yorapp="http://schemas.android.com/apk/res-auto" >
<item
android:id="#+id/menu_overflow"
android:icon="#drawable/icon"
yourapp:showAsAction="always"
android:title="">
<menu>
<item
android:id="#+id/item1"
android:title="item1"/>
<item
android:id="#+id/item2"
android:title="item2"/>
</menu>
</item>
</menu>
This kind of method is prevented by the Android Developers Design System, but I found a way to pass it:
Add this to your XML menu file:
<item android:id="#+id/pick_action_provider"
android:showAsAction="always"
android:title="More"
android:icon="#drawable/ic_action_overflow"
android:actionProviderClass="com.example.AppPickActionProvider" />
Next, create a class named 'AppPickActionProvider', and copy the following code to it:
package com.example;
import android.content.Context;
import android.util.Log;
import android.view.ActionProvider;
import android.view.MenuItem;
import android.view.MenuItem.OnMenuItemClickListener;
import android.view.SubMenu;
import android.view.View;
public class AppPickActionProvider extends ActionProvider implements
OnMenuItemClickListener {
static final int LIST_LENGTH = 3;
Context mContext;
public AppPickActionProvider(Context context) {
super(context);
mContext = context;
}
#Override
public View onCreateActionView() {
Log.d(this.getClass().getSimpleName(), "onCreateActionView");
return null;
}
#Override
public boolean onPerformDefaultAction() {
Log.d(this.getClass().getSimpleName(), "onPerformDefaultAction");
return super.onPerformDefaultAction();
}
#Override
public boolean hasSubMenu() {
Log.d(this.getClass().getSimpleName(), "hasSubMenu");
return true;
}
#Override
public void onPrepareSubMenu(SubMenu subMenu) {
Log.d(this.getClass().getSimpleName(), "onPrepareSubMenu");
subMenu.clear();
subMenu.add(0, 1, 1, "Item1")
.setIcon(R.drawable.ic_action_home).setOnMenuItemClickListener(this);
subMenu.add(0, 2, 1, "Item2")
.setIcon(R.drawable.ic_action_downloads).setOnMenuItemClickListener(this);
}
#Override
public boolean onMenuItemClick(MenuItem item) {
switch(item.getItemId())
{
case 1:
// What will happen when the user presses the first menu item ( 'Item1' )
break;
case 2:
// What will happen when the user presses the second menu item ( 'Item2' )
break;
}
return true;
}
}
Well I think that Alexander Lucas has provided the (unfortunately) correct answer so I'm marking it as the "correct" one. The alternative answer I'm adding here is simply to point any new readers to this post in the Android Developers blog as a rather complete discussion of the topic with some specific suggestions as to how to deal with your code when transitioning from pre-level 11 to the new Action Bar.
I still believe it was a design mistake not have the menu button behave as a redundant "Action Overflow" button in menu button enabled devices as a better way to transition the user experience but its water under the bridge at this point.
I'm not sure if this is what you're looking for, but I built a Submenu within the ActionBar's Menu and set its icon to match the Overflow Menu's Icon. Although it wont have items automatically sent to it, (IE you have to choose what's always visible and what's always overflowed) it seems to me that this approach may help you.
In the gmail app that comes with ICS pre-installed, the menu button is disabled when you have multiple items selected. The overflow menu is here "forced" to be triggered by the use of the overflow button instead of the physical menu button. Theres a 3rd-party lib called ActionBarSherlock which lets you "force" the overflow menu. But this will only work on API level 14 or lower(pre-ICS)
If you use Toolbar, you can show the overflow on all versions and all devices, I've tried on some 2.x devices, it works.
Sorry if this problem is dead.
Here is what I did to resolve the error. I went to layouts and created two ones containing toolbars. One was a layout for sdk version 8 and the other was for sdk version 21. On version 8, I used the android.support.v7.widget.Toolbar while I used android.widget.Toolbar on the sdk 21 layout.
Then I inflate the toolbar in my activity. I check the sdk to see if it was 21 or higher. I then inflate the corresponding layout. This forces the hardware button to map onto the toolbar you actually designed.
For anyone using the new Toolbar:
private Toolbar mToolbar;
#Override
protected void onCreate(Bundle bundle) {
super.onCreate(bundle);
mToolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(mToolbar);
...
}
#Override
public boolean onKeyUp(int keycode, KeyEvent e) {
switch(keycode) {
case KeyEvent.KEYCODE_MENU:
mToolbar.showOverflowMenu();
return true;
}
return super.onKeyUp(keycode, e);
}
The new Android design docs mention use of an Up caret: http://developer.android.com/design/patterns/actionbar.html
The up caret seems to be proper for navigation throughout Android - is there a proper way to add this caret? It seems unintuitive that I should just modify the icon image to include it.
Any help would be much appreciated!
You can also add the caret by setting setDisplayHomeAsUpEnabled(true) on the ActionBar. Be sure to react to the menu item when selected.
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
ActionBar actionBar = getActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setDisplayShowTitleEnabled(true);
}
#Override
public boolean onOptionsItemSelected(MenuItem item)
{
switch( item.getItemId() ) {
case android.R.id.home:
Log.d(TAG, "Home Icon Item Selected");
return true;
default:
return super.onOptionsItemSelected(item);
}
}
I'm not exactly 100% sure what you're asking, but if you're asking where you can find the images for the "caret", they're in the platform/data/res/drawable-hdpi folder (in your SDK location). The files are called ic_ab_back_holo_[dark|light].png. You can see it in the github repo too. The standard procedure of copying to your local resources folder applies here, since you can't reference them (they're not exposed).
In my onCreateOptionsMenu() I have basically the following:
public boolean onCreateOptionsMenu(Menu menu) {
menu.add(Menu.NONE, MENU_ITEM_INSERT, Menu.NONE, R.string.item_menu_insert).setShortcut('3',
'a').setIcon(android.R.drawable.ic_menu_add);
PackageManager pm = getPackageManager();
if(pm.hasSystemFeature(PackageManager.FEATURE_CAMERA) && pm.hasSystemFeature(PackageManager.FEATURE_CAMERA_AUTOFOCUS)){
menu.add(Menu.NONE, MENU_ITEM_SCAN_ADD, Menu.NONE, ((Collectionista.DEBUG)?"DEBUG Scan and add item":getString(R.string.item_menu_scan_add))).setShortcut('4',
'a').setIcon(android.R.drawable.ic_menu_add);
}
...
}
And in onPrepareOptionsMenu among others the following:
final boolean scanAvailable = ScanIntent.isInstalled(this);
final MusicCDItemScanAddTask task = new MusicCDItemScanAddTask(this);
menu.findItem(MENU_ITEM_SCAN_ADD).setEnabled(scanAvailable && (tasks == null || !existsTask(task)));
As you see, two options items have the same drawable set (android.R.drawable.ic_menu_add). Now, if in onPrepareOptionsMenu the second menu item gets disabled, its label and icon become gray, but also the icon of the first menu item becomes gray, while the label of that first menu item stays black and it remains clickable. What is causing this crosstalk between the two icons/drawables? Shouldn't the system handle things like mutate() in this case?
I've included a screenshot:
http://www.curious-creature.org/2009/05/02/drawable-mutations/
The above article by Romain Guy explains this very situation and provides a work around.
Yes, this looks odd. I can not explain why this is as it is, however I can propose a workaround - instead of using internal drawable resourse, you could put the same image in your app drawable resourse dir AND you could duplicate the add image, so you have 2 images - add_for_menu_item_1.png and add_for_menu_item_2.png named differently, but having the same visual representation. I am sure this would do the trick.
Could it be that both menu items are sharing the same alphaChar which is causing the second menuItem to be disabled?
I am developing a simple application ,in that there is set of 6 buttons.
when i clicked on one of these button then the other buttons must be partially transparent. I tried to done that By setting alpha of 5 buttons
acre_button.getBackground().mutate().setAlpha(155);
Ui of the application not changed as i expected. i got only 3 out of 5 is get transparent.when clicking on that two button it is slowly changing it's transparency
Thanks in advance
regards,
kariyachan
Button btn;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
btn = (Button) findViewById(R.id.main_btn);
Drawable d = getResources().getDrawable(R.drawable.imagen);
d.setAlpha(60);
btn.setBackgroundDrawable(d);
}
This works for me :)
Find a button background in your android-sdk directory here: android-sdk\platforms\android-10\data\res\drawable-mdpi\btn_default_normal.9.png
You can modify it to make it semi transparent (Please note that this is a 9-patch and you shouldn't change the opacity of the black lines).
Once you have this changed button in your drawable directory you can add this to your code:
button.setBackgroundDrawable(getResources().getDrawable(R.drawable.transparentImage));
to make it semi transparent and
button.setBackgroundDrawable(getResources().getDrawable(Android.R.drawable.btn_default_normal));
to change it back.
For anyone still hunting for a solution to this:
The method setBackgroundDrawable(Drawable d) is deprecated as of API 16
Assuming your button's id is buttonId and your drawable is named button_img,
handle this by using the following within the onCreate method:
((Button)(findViewById(R.id.buttonId))).setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Drawable d = v.getResources().getDrawable(R.drawable.button_img);
d.setAlpha(40);
if (Build.VERSION.SDK_INT >= 16)
v.setBackground(d);
else
v.setBackgroundDrawable(d);
//Then call your next Intent or desired action.
}
});
Tested and works for me!
Try the following:
button.setBackgroundColor(android.R.color.transparent);