【问题标题】:Action bar icon size in Android 4.2Android 4.2 中的操作栏图标大小
【发布时间】:2012-11-11 06:22:09
【问题描述】:

Android 4.2 中的操作栏图标大小是否发生了变化? 我有一个 120x48px HDPI 图标,它在 Android 4.1 及更低版本中完美呈现。它仍然是。

但是,在任何 4.2 设备上,它都被压缩以适应我所看到的 48x48 像素。或类似的东西;这绝对是一个正方形。

有什么想法吗?谢谢!

【问题讨论】:

  • 我偶然发现了同样的问题。我发现以下提交添加了此“功能”:github.com/android/platform_frameworks_base/commit/…
  • 这是一个很棒的发现,非常感谢!所以猜我们真的什么都做不了,对吧?还是我错了?
  • 这有点可笑。非常感谢 Android。

标签: android android-actionbar android-icons


【解决方案1】:

这并不理想,但您似乎可以通过使用自定义操作视图来解决此限制。

类似这样的:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
  <item android:id="@+id/log_in"
    android:title="Login"
    android:showAsAction="always"
    android:actionLayout="@layout/log_in_button"/>
</menu>

@layout/log_in_button 指向一个布局文件,其中包含一个 ImageButton,您的图标设置为 src。

您必须在 OnCreateOptionsMenu 方法中绑定点击侦听器。这里有一个很好的例子:http://developer.android.com/guide/topics/ui/actionbar.html#ActionView

我才刚刚学会使用这种方法,所以我还不知道除了增加的复杂性之外是否有任何重大的失败。

【讨论】:

    【解决方案2】:

    所以,我找到了一个答案,它有点 hacky 但有效(TM):

    一般的想法是监听布局变化并将新的边界应用于可绘制对象。这可能如下所示:

    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
            }
        }
    

    然后,您必须在以下回调中在每个 Activity 中调用 updateActionBar(我建议创建一个从中扩展的抽象基础 Activity): 创建 onMenuOpened(我发现如果你把它称为延迟(例如 200 毫秒),它会提高性能并减少闪烁(可绘制对象的大小变化)) onPrepareOptionsMenu(我发现如果你调用这个延迟(例如 200 毫秒),它会提高性能并减少闪烁(可绘制对象的大小变化))

    这适用于我在 Nexus 7 和 Nexus 10 上运行 Android 4.2。您可以预期它会因未来的更新而失败,但至少目前它似乎可以工作。

    【讨论】:

    • “actionBarView.getChildAt(i3)”出现错误 - i3 无法解析为变量
    猜你喜欢
    • 2012-06-29
    • 2014-05-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-08
    • 1970-01-01
    • 2014-07-23
    相关资源
    最近更新 更多