Action Bar Icon Size

Action Bar icon size

UPDATE: this answer is no longer valid, see the below answer for more up-to-date guidelines.

I believe they have to be 32x32dp, but the actual image itself should be 24dpx24dp centred. The Android design website has the correct guidelines.

I've submitted a bug report about this but have yet to hear anything...

What is the recommended ActionBar icon size in Material Design (Android API 21+)?

  1. There are recommendation for most features. Toolbar icons should always be 24dp, while as you say circular features (including images and floating buttons) should be 40dp. You might find different values for different views, in the page you linked or in the "Components" side menu.

    I downloaded material icons some time ago, from here or here. In both cases icons are provided in different sizes, 18dp, 24dp, 36dp and 48dp. It's up to you to choose the best size and to set an appropriate padding on the view, to ensure a 48dp clickable area. In most cases if you chose an AppCompat or Material theme it will handle sizing and padding for you.

    Apart from that, e.g. when sizing a button, I would choose Buttons from the "Components" menu, and get size info there.

  2. Yes.

  3. You are probably right, 48dp icons for xxhdpi should be 144x144 pixels.

Action bar icon size in Android 4.2

So, I found an answer, it's kinda hacky but works (TM):

The general idea is to listen for the layout changes and apply new bounds to the drawables. This could look like this:

public static void updateActionBar(final Activity activity) {
if (Build.VERSION.SDK_INT >= 17) {
try {
final View content = activity.findViewById(android.R.id.content);
if (content instanceof FrameLayout) {
final FrameLayout contentFrameLayout = (FrameLayout) content;
final ViewParent parent = contentFrameLayout.getParent();
if (parent instanceof LinearLayout) {
final LinearLayout parentLinearLayout = (LinearLayout) parent;
final Class<?> actionBarContainerClass = Class.forName("com.android.internal.widget.ActionBarContainer");
final Class<?> actionBarViewClass = Class.forName("com.android.internal.widget.ActionBarView");
final Class<?> actionMenuViewClass = Class.forName("com.android.internal.view.menu.ActionMenuView");
final Class<?> actionMenuItemViewClass = Class.forName("com.android.internal.view.menu.ActionMenuItemView");

for (int i = 0, childCount = parentLinearLayout.getChildCount(); i < childCount; i++) {
final View parentLinearLayoutChild = parentLinearLayout.getChildAt(i);
handleParentLinearLayoutChild(actionBarContainerClass, actionBarViewClass, actionMenuViewClass, actionMenuItemViewClass, parentLinearLayoutChild);
}
}
}
} catch (Exception e) {
// Handle or ignore
}
}
}

private static void handleParentLinearLayoutChild(final Class<?> actionBarContainerClass, final Class<?> actionBarViewClass, final Class<?> actionMenuViewClass, final Class<?> actionMenuItemViewClass, final View parentLinearLayoutChild) {
if (parentLinearLayoutChild instanceof FrameLayout && parentLinearLayoutChild.getClass().equals(actionBarContainerClass)) {
final FrameLayout actionBarContainer = (FrameLayout) parentLinearLayoutChild;
for (int i = 0, actionBarContainerChildCount = actionBarContainer.getChildCount(); i < actionBarContainerChildCount; i++) {
final View actionBarContainerChild = actionBarContainer.getChildAt(i);
handleActionBarContainerChild(actionBarViewClass, actionMenuViewClass, actionMenuItemViewClass, actionBarContainerChild);
}
}
}

private static void handleActionBarContainerChild(final Class<?> actionBarViewClass, final Class<?> actionMenuViewClass, final Class<?> actionMenuItemViewClass, final View actionBarContainerChild) {
if (actionBarContainerChild instanceof ViewGroup && actionBarContainerChild.getClass().equals(actionBarViewClass)) {
final ViewGroup actionBarView = (ViewGroup) actionBarContainerChild;
actionBarView.setOnHierarchyChangeListener(new ViewGroup.OnHierarchyChangeListener() {
@Override
public void onChildViewAdded(final View parent, final View child) {
handleActionBarViewChild(child, actionMenuViewClass, actionMenuItemViewClass);
}

@Override
public void onChildViewRemoved(final View parent, final View child) {
}
});
for (int i = 0, actionBarViewCount = actionBarView.getChildCount(); i < actionBarViewCount; i++) {
handleActionBarViewChild(actionBarView.getChildAt(i3), actionMenuViewClass, actionMenuItemViewClass);
}
}
}

private static void handleActionBarViewChild(final View child, final Class<?> actionMenuViewClass, final Class<?> actionMenuItemViewClass) {
try {
if (child instanceof LinearLayout && child.getClass().equals(actionMenuViewClass)) {
final LinearLayout actionMenuView = (LinearLayout) child;
actionMenuView.setOnHierarchyChangeListener(new ViewGroup.OnHierarchyChangeListener() {
@Override
public void onChildViewAdded(final View parent, final View child) {
handleActionMenuViewChild(child, actionMenuItemViewClass);
}

@Override
public void onChildViewRemoved(final View parent, final View child) {
}
});
for (int i = 0, actionMenuViewCount = actionMenuView.getChildCount(); i < actionMenuViewCount; i++) {
handleActionMenuViewChild(actionMenuView.getChildAt(i), actionMenuItemViewClass);
}
}
} catch (Exception e) {
// Handle or ignore
}
}

private static void handleActionMenuViewChild(final View child, final Class<?> actionMenuItemViewClass) {
try {
if (child instanceof TextView && child.getClass().equals(actionMenuItemViewClass)) {
final TextView menuViewChild = (TextView) child;
final Drawable[] compoundDrawables = menuViewChild.getCompoundDrawables();
final Drawable leftDrawable = compoundDrawables[0];
final int intrinsicWidth = leftDrawable.getIntrinsicWidth();
final int intrinsicHeight = leftDrawable.getIntrinsicHeight();
leftDrawable.setBounds(0, 0, intrinsicWidth , intrinsicHeight );
menuViewChild.setCompoundDrawables(leftDrawable, null, null, null);
menuViewChild.setPadding(menuViewChild.getPaddingLeft(), 0, menuViewChild.getPaddingRight(), 0);
menuViewChild.invalidate();
menuViewChild.requestLayout();
}
} catch (Exception e) {
// Handle or ignore
}
}

You then have to call updateActionBar in every Activity (I suggest making an abstract base activity from which you extend) in the following callbacks:
onCreate
onMenuOpened (I found that it would improve performance and reduce flickering (size changes of the drawables) if you call this delayed (e.g. 200ms))
onPrepareOptionsMenu (I found that it would improve performance and reduce flickering (size changes of the drawables) if you call this delayed (e.g. 200ms))

This works for me on Nexus 7 and Nexus 10 with Android 4.2. You can expect it to fail with future updates but at least for now it seems to work.

How big should Action Bar(Toolbar) icons be in the new Android Material design?

From Material Design Keylines Touch Target Size, size for icons is 24dp



Related Topics



Leave a reply



Submit