更改ActionMode溢出图标

时间:2014-03-28 18:43:21

标签: android android-actionbar android-actionmode

有没有办法更改ActionMode Overflow图标而不更改“普通”ActionBar的图标?

6 个答案:

答案 0 :(得分:6)

  

我仍然需要弄清楚如何只更改ActionMode-Actionbar内部的Overflow-Icon,因为我在ActionMode-Actionbar中看不到默认Actionbar中的Overflow-Icon(不,我不喜欢#39;想要改变我的ActionMode-Actionbar的背景!)

好。

让我们从定义一些风格开始。我将尝试解释为什么我们以这种方式定义它们:

// This is just your base theme. It will probably include a lot more stuff.
// We are going to define the style 'OverflowActionBar' next.

<style name="BaseTheme" parent="android:Theme.Holo.Light">
    ....
    ....
    ....
    <item name="android:actionOverflowButtonStyle">@style/OverflowActionBar</item>
</style>

// Assigning a parent to this style is important - we will inherit two attributes -
// the background (state-selector) and the content description

<style name="OverflowActionBar" parent="@android:style/Widget.Holo.ActionButton.Overflow">
    <item name="android:src">@drawable/overflow_menu_light</item>
</style>

// Next up is an extension to our 'BaseTheme'. Notice the parent here.

<style name="ChangeOverflowToDark" parent="@style/BaseTheme">
    <item name="android:actionOverflowButtonStyle">@style/OverflowActionMode</item>
</style>

// One last thing is to define 'OverflowActionMode'. Again, we inherit useful
// attributes by assigning 'Widget.Holo.ActionButton.Overflow' as the parent.

<style name="OverflowActionMode" parent="@android:style/Widget.Holo.ActionButton.Overflow">
    <item name="android:src">@drawable/overflow_menu_dark</item>
</style>

我们与styles.xml的所有工作都已完成。最后一点发生在运行时。我想你已经实现了ActionMode.Callback

在您的活动中,定义一个方法 - changeOverflowIcon()

public void changeOverflowIcon() {
    getTheme().applyStyle(R.style.ChangeOverflowToDark, true);
}

您将从onCreateActionMode(...)实施的ActionMode.Callback调用此方法:

public class CustomActionModeCallback implements ActionMode.Callback {

    @Override
    public boolean onCreateActionMode(ActionMode mode, Menu menu) {
        changeOverflowIcon()

        // other initialization

        return true;
    }

    @Override
    public boolean onPrepareActionMode(final ActionMode mode, Menu menu) {
        return true;
    }

    @Override
    public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
        return false;
    }

    @Override
    public void onDestroyActionMode(ActionMode mode) {}
}

一点解释:

&#39; BaseTheme&#39;适用于ActionBar。它将选择drawable overflow_menu_light,因为我们将在您的应用的基本主题中分配它。

getTheme().applyStyle(R.style.ChangeOverflowToDark, true) 

第二个参数true强制当前主题用新的属性覆盖旧属性。由于我们只在ChangeOverflowToDark中定义了一个属性,因此会覆盖其值。 ActionBar不受影响,因为它已使用旧属性。但是,尚未创建操作模式(当我们从true返回onCreateActionMode(...)时将创建它。当操作模式检查此属性值时,它将获取新属性值。

还有......

Manish给出的答案非常棒。我从来没有想过使用内容描述来找到确切的ImageButton但如果您能够使用直截了当的ImageButton找到findViewById()该怎么办?

您可以在这里:

首先,我们需要独特的ID。如果您的项目当前没有res/values/ids.xml文件,请创建一个。{1}}。添加新ID:

<item type="id" name="my_custom_id" />

我上面讨论的设置将保持不变。唯一的区别是OverflowActionMode样式:

<style name="OverflowActionMode" parent="@android:style/Widget.Holo.ActionButton.Overflow">
    <item name="android:src">@drawable/overflow_menu_dark</item>
    <item name="android:id">@id/my_custom_id</item>
</style>

当我们致电ImageButton

时,我们上面定义的ID将被分配到getTheme().applyStyle(R.style.ChangeOverflowToDark, true);

我将从Manish的答案中借用代码片段:

private ActionMode.Callback mCallback = new ActionMode.Callback()
{
    @Override
    public boolean onPrepareActionMode( ActionMode mode, Menu menu )
    {

        mDecorView.postDelayed(new Runnable() {

            @Override
            public void run() {
                ImageButton btn = (ImageButton) mDecorView.findViewById(R.id.my_custom_id);
                // Update the image here.
                btn.setImageResource(R.drawable.custom);
            }          
        }, 500); // 500 ms is quite generous // I would say that 50 will work just fine

        return true;
    }  
}

两全其美?

我们需要R.drawable.overflow_menu_light的{​​{1}}和ActionBar的{​​{1}}。

样式:

R.drawable.overflow_menu_dark

根据我们的风格定义,ActionMode会选择<style name="BaseTheme" parent="android:Theme.Holo.Light"> .... .... .... <item name="android:actionOverflowButtonStyle">@style/OverflowActionMode</item> </style> <style name="OverflowActionMode" parent="@android:style/Widget.Holo.ActionButton.Overflow"> <item name="android:src">@drawable/overflow_menu_dark</item> <item name="android:id">@id/my_custom_id</item> </style> - 但我们不需要ActionBar light 版本吗?是的 - 我们会在活动的R.drawable.overflow_menu_dark回调中指定该内容:

ActionBar

我们这样做是因为在onPrepareOptionsMenu(Menu)之前,@Override public boolean onPrepareOptionsMenu(Menu menu) { new Handler().postDelayed(new Runnable() { @Override public void run() { ImageButton ib = (ImageButton) getWindow().getDecorView() .findViewById(R.id.my_custom_id); if (ib != null) ib.setImageResource(R.drawable.overflow_menu_light); } }, 50L); return super.onPrepareOptionsMenu(menu); } 不会被创建。

现在,我们需要处理onPrepareOptionsMenu(Menu) - 因为它会从主题中选择ImageButton drawable。

我为这个巨大的帖子道歉。我真的希望它有所帮助。

答案 1 :(得分:3)

ImageButton是用于显示菜单溢出的小部件。 actionOverflowButtonStyle用于为ImageButton设置样式。此样式应用于ActionMenuPresenter

private class OverflowMenuButton extends ImageButton implements ActionMenuChildView {
   public OverflowMenuButton(Context context) {
      super(context, null, com.android.internal.R.attr.actionOverflowButtonStyle);
      ...
   }
}

ActionMenuPresenter类用于在action baraction modes中构建操作菜单。因此,通过覆盖主题文件将在两种模式中应用相同的样式。唯一的方法是以编程方式hereaction bar完成。

以下是action mode溢出图标的完成方式代码。您可以使用drawable方法将ImageButton分配给ActionMode.Callback.onPrepareActionMode

public class MainActivity extends Activity {
    ViewGroup mDecorView;

    public void onCreate(Bundle savedInstanceState) {
        // Assign mDecorView to later use in action mode callback
        mDecorView = (ViewGroup) getWindow().getDecorView();
    }

    private ActionMode.Callback mCallback = new ActionMode.Callback()
    {
        @Override
        public boolean onPrepareActionMode( ActionMode mode, Menu menu )
        {
            // We have to update the icon after it is displayed, 
            // hence this postDelayed variant. 
            // This is what I don't like, but it is the only way to move forward.

            mDecorView.postDelayed(new Runnable() {

                @Override
                public void run() {
                    ArrayList<View> outViews = new ArrayList<View>();
                    // The content description of overflow button is "More options".
                    // If you want, you can override the style and assign custom content
                    // description and use it here.
                    mDecorView.findViewsWithText(outViews, "More Options", View.FIND_VIEWS_WITH_CONTENT_DESCRIPTION);
                    if(!outViews.isEmpty()) {
                        View v = outViews.get(0);
                        if(v instanceof ImageButton) {
                            ImageButton btn = (ImageButton) v;
                            // Update the image here.
                            btn.setImageResource(R.drawable.custom);
                        }                       
                    }
                }               
            }, 500);

            return true;
        }  

    }
}

答案 2 :(得分:1)

您应该能够使用样式:

<强> ActionBarSherlock:

<style name="MyTheme" parent="Theme.Sherlock.Light">
    <item name="actionOverflowButtonStyle">@style/MyTheme.OverFlow</item>
</style>

<style name="MyTheme.OverFlow" parent="Widget.Sherlock.ActionButton.Overflow">
    <item name="android:src">@drawable/YOUR_ICON_GOES_HERE</item>
</style>

<强> ActioBar:

<style name="MyTheme" parent="@android:style/Theme.Holo">
    <item name="android:actionOverflowButtonStyle">@style/MyTheme.OverFlow</item>
</style>

<style name="MyTheme.OverFlow" parent="@android:style/Widget.Holo.ActionButton.Overflow">
    <item name="android:src">@drawable/YOUR_ICON_GOES_HERE</item>
</style>

确保在清单中设置MyTheme。

答案 3 :(得分:0)

要更改操作模式栏的溢出图标,您只需创建一个自Widget.AppCompat.ActionButton.Overflow继承的自定义样式

例如: 在styles.xml

<style name="MyOverflowButtonStyle" parent="Widget.AppCompat.ActionButton.Overflow">
    <item name="android:src">@drawable/action_mode_overflow</item>
    <item name="srcCompat">@drawable/action_mode_overflow</item>
</style>

请注意同时使用android:srcsrcCompat属性。为了使这种样式显示在version >= 21上,您需要提供“ android:src”属性。

现在采用这种样式,并在您的AppTheme下添加:

<item name="actionOverflowButtonStyle">@style/ActionModeOverflowTheme</item>

答案 4 :(得分:0)

在我的情况下,我只想要三个点图标的颜色不同,要实现它,我在主题中设置了<item name="actionBarTheme">@style/Widget.ActionMode.ActionBar</item>,而Widget.ActionMode.ActionBar如下所示:

    <style name="Widget.ActionMode.ActionBar" parent="@style/ThemeOverlay.AppCompat.Light">
        <item name="colorControlNormal">the color I want</item>
    </style>

答案 5 :(得分:0)

是否可以在不更改“正常” ActionBar图标的情况下更改ActionMode溢出图标?

关于如何更改溢出图标,我认为上面有很多答案。

如果只想更改溢出图标的颜色,则可以使用一种简单的方法。

<style name="BaseAppTheme" parent="Theme.xxxx.Light.NoActionBar.xxx">
    ...           
    <item name="actionOverflowButtonStyle">@style/ActionMode.OverFlow</item>
</style>

<style name="ActionMode.OverFlow" parent="@style/Widget.AppCompat.ActionButton.Overflow">
    <item name="android:tint">@color/black</item>  #or any color you want.#
</style>

对我有用。我调查了一下,只需查看此屏幕截图http://prntscr.com/vqx1ov,您就会知道原因。

我不建议设置colorControlNormal的颜色,它会更改ActionBar上“后退箭头”和“溢出图标”的颜色。