Why android:actionBarDivider doesn't work? - android

Having
<item name="android:actionBarDivider">#drawable/action_bar_divider</item>
in my Activity style has zero effect. Doesn't matter if I'm using native ActionBar or ActionBarSherlock. Why?

I worked around it by programatically inserting dividers into the view hierarchy. It occured to me later that dividers may be only visible in the bottom action bar (I needed them at the top bar). But I didn't verify that.
public boolean onCreateOptionsMenu(com.actionbarsherlock.view.Menu menu) {
MenuInflater inflater = getSupportMenuInflater();
inflater.inflate(R.menu.main_activity, menu);
new Handler().post(new Runnable() {
#Override
public void run() {
for (int id : new int[] { R.id.action_1, R.id.action_2 }) {
View actionView = findViewById(id);
insertDividerBefore(actionView);
}
}
});
return true;
}

android:actionBarDivider
Defines a drawable resource for the divider between action items. (Added in API level 14.)
Make sure whether you are using API level 14 or later.

Related

Get MenuItem's View reference for TapTargetView

I am trying to use TapTargetView for the menu items, but I can't get the view of it.
My code:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater menuInflater = getMenuInflater();
menuInflater.inflate(R.menu.menu, menu);
new TapTargetSequence(this)
.targets(
TapTarget.forView(menu.findItem(R.id.add).getActionView(), "Gonna"))
.listener(new TapTargetSequence.Listener() {
// This listener will tell us when interesting(tm) events happen in regards
// to the sequence
#Override
public void onSequenceFinish() {
// Yay
}
#Override
public void onSequenceStep(TapTarget lastTarget, boolean targetClicked) {
}
#Override
public void onSequenceCanceled(TapTarget lastTarget) {
// Boo
}
});
return true;
}
Error:
java.lang.IllegalArgumentException: Given null view to target
How can I resolve this issue?
I've tried adding android:actionViewClass to xml file, but no luck.
After repetitive search and testing finally came up with a working solution!
Just get the reference to your menu item inside the onCreateOptionsMenu(). Start a handler so that the view is inflated properly before you take the id reference. Otherwise you will be getting the null view error
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main_menu,menu);
new Handler().post(new Runnable() {
#Override
public void run() {
final View view = findViewById(R.id.askHelp);
TapTargetView.showFor(BasicInformation.this, // `this` is an Activity
TapTarget.forView(view, "You can tap here to get Chat Support")
// All options below are optional
.outerCircleColor(R.color.colorAccent) // Specify a color for the outer circle
.outerCircleAlpha(0.96f) // Specify the alpha amount for the outer circle
.targetCircleColor(R.color.white) // Specify a color for the target circle
.titleTextSize(30) // Specify the size (in sp) of the title text
.titleTextColor(R.color.white) // Specify the color of the title text
.textColor(R.color.white) // Specify a color for both the title and description text
.textTypeface(Typeface.SANS_SERIF) // Specify a typeface for the text
.dimColor(R.color.black) // If set, will dim behind the view with 30% opacity of the given color
.drawShadow(true) // Whether to draw a drop shadow or not
.cancelable(true) // Whether tapping outside the outer circle dismisses the view
.tintTarget(true) // Whether to tint the target view's color
.transparentTarget(false) // Specify whether the target is transparent (displays the content underneath)
.targetRadius(60), // Specify the target radius (in dp)
new TapTargetView.Listener() { // The listener can listen for regular clicks, long clicks or cancels
#Override
public void onTargetClick(TapTargetView view) {
super.onTargetClick(view); // This call is optional
//doSomething();
}
});
}
});
return true;
}
You can make use of View#findViewsWithText() API to get the reference of MenuItem's view.
Having following as menu's xml:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:id="#+id/action_settings"
android:title="#string/action_settings"
android:orderInCategory="100"
app:showAsAction="ifRoom"/>
</menu>
And assuming that MenuItem is being displayed, then:
#Override protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final View decorView = getWindow().getDecorView();
decorView.post(() -> {
ArrayList<View> list = new ArrayList<>();
decorView.findViewsWithText(list, getString(R.string.action_settings), View.FIND_VIEWS_WITH_TEXT);
// `itemView` is the actual view you should use to create your `TapTargetView`
View itemView = list.get(0);
});
}
Use TapTarget.forToolbarMenuItem insted of TapTarget.forView
Change the code like this...
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater menuInflater = getMenuInflater();
menuInflater.inflate(R.menu.menu, menu);
new TapTargetSequence(this)
.targets(
TapTarget.forToolbarMenuItem(toolbar,R.id.add, "Gonna"))
.listener(new TapTargetSequence.Listener() {
// This listener will tell us when interesting(tm) events happen in regards
// to the sequence
#Override
public void onSequenceFinish() {
// Yay
}
#Override
public void onSequenceStep(TapTarget lastTarget, boolean targetClicked) {
}
#Override
public void onSequenceCanceled(TapTarget lastTarget) {
// Boo
}
});
return true;
}
Another approach would be to use "app:actionLayout="#layout/some_layout" in menu item and some_layout can have the item as the view inside it. Then, in your activity you can use:
MenuItem menuItem = menu.findItem(R.id.menu_item); // get the menu item
ImageView menuView = menuItem.getActionView().findViewById(R.id.some_icon);
You can use this menuView for setting tap target
TapTargetView.showFor(activity, getTapTarget(menuView, title, message),
new TapTargetView.Listener()
{
#Override
public void onTargetClick(TapTargetView view)
{
super.onTargetClick(view);
view.dismiss(true);
}
#Override
public void onOuterCircleClick(TapTargetView view)
{
super.onOuterCircleClick(view);
view.dismiss(true);
}
});

How to use ActionMenuView?

Since SplitActionBar is no longer supported in Android 5.0, I am trying to use an ActionMenuView to achieve a SplitActionBar effect. But I could not find much information on how to use ActionMenuView.
I know I can add a ActionMenuView in the layout file, but I don't know how to add menu items. It doesn't seem like I could inflate them like I do with SplitActionBar.
Could you give some sample code on how to use ActonMenuView? Thanks!
Getting ActionMenuView to display a whole screen's width of icons is a chore. Here is an example to do what you want. Make sure your ActionMenuView XML item is wrap_content for height and width, then gravity to the right. Surround it in a LinearLayout which takes the whole width and provides background color.
Use this code to initialize the ActionMenuView (obviously you will need to change the button callbacks)
ActionMenuView actionMenuView = (ActionMenuView) findViewById(R.id.editBar);
final Context context = this;
MenuBuilder menuBuilder = new MenuBuilder(context);
menuBuilder.setCallback(new MenuBuilder.Callback() {
#Override
public boolean onMenuItemSelected(MenuBuilder menuBuilder, MenuItem menuItem) {
return onOptionsItemSelected(menuItem);
}
#Override
public void onMenuModeChange(MenuBuilder menuBuilder) {
}
});
// setup a actionMenuPresenter which will use up as much space as it can, even with width=wrap_content
ActionMenuPresenter presenter = new ActionMenuPresenter(context);
presenter.setReserveOverflow(true);
presenter.setWidthLimit(getResources().getDisplayMetrics().widthPixels, true);
presenter.setItemLimit(Integer.MAX_VALUE);
// open a menu xml into the menubuilder
getMenuInflater().inflate(R.menu.editbar, menuBuilder);
// runs presenter.initformenu(mMenu) too, setting up presenter's mmenu ref... this must be before setmenuview
menuBuilder.addMenuPresenter(presenter, this);
// runs menuview.initialize too, so menuview.mmenu = mpresenter.mmenu
actionMenuView.setPresenter(presenter);
presenter.updateMenuView(true);
For what it's worth, I had to read the support library source code for 8 hours to get this to work. The documentation is garbage.
It seems the API has changed in the meantime. Currently, the following code works:
ActionMenuView actions = new ActionMenuView(activity);
MenuBuilder menuBuilder = (MenuBuilder) actions.getMenu();
menuBuilder.setCallback(new MenuBuilder.Callback() {
#Override
public boolean onMenuItemSelected(MenuBuilder menuBuilder, MenuItem menuItem) {
return onOptionsItemSelected(menuItem);
}
#Override
public void onMenuModeChange(MenuBuilder menuBuilder) {
}
});
inflater.inflate(R.menu.my_menu, menuBuilder);
If you are using the v7 appCompat library make sure your activity extends from ActionBarActivity and that you use the support version of the ActionMenuView.
Likewise if you are not using the support library be sure to use the ActionMenuView outside the support library.
From there you can get the ActionMenuView from your layout and populate its menu using the following method:
getMenuInflater().inflate(R.menu.your_menu_here, actionMenuView.getMenu())
If you aren't in an activity where getMenuInflater() is accessible create your own MenuInflater or SupportMenuInflater.
In appcompat-v7:27.0.2, the ActionMenuView requires a minimum width of 56dp. Do not use android:layout_width="wrap_content".
If your popup theme is being ignored, make sure you call setPopupTheme(int) before any call to getMenu() on ActionMenuView.
Inflate
you can use this code in your activity :
menuInflater.inflate(R.menu.{your_menu_res_id}, {your_ActionMenuView_instance}.menu)
like this :
menuInflater.inflate(R.menu.settings_menu, settings_menu.menu)
Item Click Listener
then you can add item click listenter :
{your_ActionMenuView_instance}.setOnMenuItemClickListener()
like this :
settings_menu.setOnMenuItemClickListener { menuItem ->
when (menuItem.itemId) {
R.id.menu_settings_save -> {
// your code
return#setOnMenuItemClickListener true
}
else -> return#setOnMenuItemClickListener false
}
}

change text color of menu item in options menu

I'm trying to change the text color of menu item in options menu.
i read here many similar question and answers saying it's impossible via theme and style and only via code. i also tried the code example and it didn't work.
I manage to change the background using these theme attributes:
#drawable/menu_hardkey_panel_holo_dark
#drawable/menu_hardkey_panel_holo_dark
#ffffff
#ffffff
but i can't make the text color to change.
i saw an answer suggesting using android:itemTextAppearance but it didn't work as well.
I'm using Android 4.0 SDK.
any help will be highly appreciated.
Thanks,
Gidi
You can not change this it comes by default in android API. If you make changes then it is not work for different version of android device.
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.my_menu, menu);
getLayoutInflater().setFactory(new Factory() {
#Override
public View onCreateView(String name, Context context, AttributeSet attrs) {
if (name .equalsIgnoreCase(“com.android.internal.view.menu.IconMenuItemView”)) {
try{
LayoutInflater f = getLayoutInflater();
final View view = f.createView(name, null, attrs);
new Handler().post(new Runnable() {
public void run() {
// set the background drawable
view .setBackgroundResource(R.drawable.my_ac_menu_background);
// set the text color
((TextView) view).setTextColor(Color.WHITE);
}
});
return view;
} catch (InflateException e) {
} catch (ClassNotFoundException e) {}
}
return null;
}
});
return super.onCreateOptionsMenu(menu);
}
I'm using Kotlin and the new Navigation component and I was able to change this by adding this line to my theme:
<item name="android:actionMenuTextColor">#color/white</item>
And then manually updating the theme applied to my toolbar like this:
toolbar = findViewById(R.id.toolbar)
toolbar.popupTheme = R.style.AppTheme
Here's the difference:

How to remove icons from an ActionBarSherlock's overflow menu on Android 2.3?

I have an app with ActionBarSherlock using theme Theme.Sherlock.Light.DarkActionBar. Action bar is dark and my menu icons are light. When I run my app on small layouts, 2 or 3 menu items with icons are displayed in the overflow menu.
On Android 3+ the overflow menu items will not display their icons, but on Android 2.3 and earlier I see menu tiles with almost invisible icons, because the tile color is white and icons are close to be white.
As you can see, the light icons are invisible on a white background, but they must have light color to be visible on a dark action bar:
Can I remove icons when menu items are displayed in the overflow menu?
you could use configuration qualifiers.
e.g.
make a drawable folder
/res/drawable-v11/ put all the "light" icons in it.
and for the darker icons use the
/res/drawable/ folder.
be sure to use the same filenames in both folders.
I hope I have understood your problem and this might help you.
However, if you want to change the drawables JUST for the overflow menu, I don't think it's possible. Also because the menu icons are not intended to be used like that. ActionBarSherlock is probably also because of issues like this, not an official library.
I was also facing the same issue:
there are many ways you can achieve this rather than removing image:
1)you can use respective drawable folder to put light and dark image.
2)You can also change the background color by code of your menu by checking your device version.
If you device doen't support overflow menu, the, you can change the background color of your menu as well as you can also change menu text color.
I was also facing the same issue and resolved using following one:
static final Class<?>[] constructorSignature = new Class[] {Context.class, AttributeSet.class};
class MenuColorFix implements LayoutInflater.Factory {
public View onCreateView(String name, Context context, AttributeSet attrs) {
if (name.equalsIgnoreCase("com.android.internal.view.menu.ListMenuItemView")) {
try {
Class<? extends ViewGroup> clazz = context.getClassLoader().loadClass(name).asSubclass(ViewGroup.class);
Constructor<? extends ViewGroup> constructor = clazz.getConstructor(constructorSignature);
final ViewGroup view = constructor.newInstance(new Object[]{context,attrs});
new Handler().post(new Runnable() {
public void run() {
try {
view.setBackgroundColor(Color.BLACK);
List<View> children = getAllChildren(view);
for(int i = 0; i< children.size(); i++) {
View child = children.get(i);
if ( child instanceof TextView ) {
((TextView)child).setTextColor(Color.WHITE);
}
}
}
catch (Exception e) {
Log.i(TAG, "Caught Exception!",e);
}
}
});
return view;
}
catch (Exception e) {
Log.i(TAG, "Caught Exception!",e);
}
}
return null;
}
}
public List<View> getAllChildren(ViewGroup vg) {
ArrayList<View> result = new ArrayList<View>();
for ( int i = 0; i < vg.getChildCount(); i++ ) {
View child = vg.getChildAt(i);
if ( child instanceof ViewGroup) {
result.addAll(getAllChildren((ViewGroup)child));
}
else {
result.add(child);
}
}
return result;
}
#Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
LayoutInflater lInflater = getLayoutInflater();
if ( lInflater.getFactory() == null ) {
lInflater.setFactory(new MenuColorFix());
}
super.onCreateContextMenu(menu, v, menuInfo);
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.myMenu, menu);
}
3) change background color from styles.xml file
<style name="Theme.MyTheme" parent="Theme.Sherlock.ForceOverflow">
<item name="actionBarStyle">#style/Widget.MyTheme.ActionBar</item>
<item name="android:actionBarStyle">#style/Widget.MyTheme.ActionBar</item>
</style>
<style name="Widget.MyTheme.ActionBar" parent="Widget.Sherlock.ActionBar">
<item name="android:background">#ff000000</item>
<item name="background">#ff000000</item>
</style>
For me, all of the 3 worked fine
Hope, this will work for you as well
Another option is to remove the icons from the non-action items in onPrepareOptionsMenu.
The idea is to use actionbarsherlock's MenuItemImpl.isActionButton to figure out if each item is an action item, and if not to remove the icon. This is made a little bit tricky because onPrepareOptionsMenu is called (at least) twice by ABS - the first time when it is building the action bar, in which case MenuItemImpl.isActionButton has not yet been set and will always return false. If that's the case, you want to leave the icons alone. Once the action bar has been built the isActionButton method will return true for action bar items, false otherwise. So you want to remove the icons for the ones that return false. This is what I came up with:
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
boolean buildingOptionsMenu = false;
for (int i=0; i<menu.size(); ++i) {
MenuItemImpl mi = (MenuItemImpl)menu.getItem(i);
if (mi.isActionButton()) {
buildingOptionsMenu = true;
break;
}
}
if (buildingOptionsMenu) {
for (int i=0; i<menu.size(); ++i) {
MenuItemImpl mi = (MenuItemImpl)menu.getItem(i);
if (!mi.isActionButton()) {
mi.setIcon(null);
mi.setIcon(0);
}
}
}
}
return super.onPrepareOptionsMenu(menu);
}
You'll need these two imports:
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.internal.view.menu.MenuItemImpl;
This works in ABS 4.3.0, but since it uses internal library classes it might not work with other versions of the library.
OS 2.x was a mess since the options menu background could be black or white, depending on the device, with no way to know which for sure.
The easy fix was to use grey (#888888) icons for Android 2.x & under and put your modern (ICS/JB) icons in a v11 folder for modern devices:
drawable // old school icons
drawable-v11 // modern icons
Of course that means drawable-mdpi-v11, drawable-hdpi-v11, and so on.
A simple alternative to adding a whole set of duplicate dark icons for 2.x versions can be simply removing the icons from all the items that can go to the overflow menu. For example:
res/menu
<item
android:id="#+id/menu_send_email"
android:showAsAction="ifRoom"
android:title="#string/menu_send_email"/>
res/menu-v11 (or even res/menu-v9, because 2.3 usually has a dark menu)
<item
android:id="#+id/menu_send_email"
android:icon="#drawable/ic_action_send_email"
android:showAsAction="ifRoom"
android:title="#string/menu_send_email"/>
Of course, you need to make the titles short enough to fit into the ActionBar at least on some larger screens, or settle with the fact that they always go into the overflow.

Android - Draw badges on MenuItems

I would like to display badges on menu items. How do I do it?
Basically, I don't want to draw or use the canvas to do so.
You could try creating a LayerListDrawable, with your regular icon as the first layer and your badge as the second layer, then use that with setIcon() on MenuItem.
The options menu in Android can be customized to set the background or change the text appearance. The background and text color in the menu couldn’t be changed using themes and styles.
The Android source code (data\res\layout\icon_menu_item_layout.xml) uses a custom item of class “com.android.internal.view.menu.IconMenuItem”View for the menu layout. We can make changes in the above class to customize the menu. To achieve the same, use the LayoutInflater factory class and set the background and text color for the view.
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.my_menu, menu);
getLayoutInflater().setFactory(new Factory() {
#Override
public View onCreateView(String name, Context context, AttributeSet attrs) {
if (name .equalsIgnoreCase(“com.android.internal.view.menu.IconMenuItemView”)) {
try{
LayoutInflater f = getLayoutInflater();
final View view = f.createView(name, null, attrs);
new Handler().post(new Runnable() {
public void run() {
// Set the background drawable
view .setBackgroundResource(R.drawable.my_ac_menu_background);
// Set the text color
((TextView) view).setTextColor(Color.WHITE);
}
});
return view;
}
catch (InflateException e) {
}
catch (ClassNotFoundException e) {
}
}
return null;
}
});
return super.onCreateOptionsMenu(menu);
}
Menuitem has an attribute icon, for example:
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="#+id/mi_main_preferences"
android:title="#string/cmd_preferences"
android:icon="#android:drawable/ic_menu_preferences">
</item>
</menu>
Above example uses system icon (preferences menu).

Categories

Resources