2014-03-28 36 views

回答

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在清单中。

+1

是的,我为ActionBar做了这​​些,但我需要Holo。ActionBar的黑色图标和ActionMode的Holo.Light图标。 – TeKo

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溢出图标来完成的代码。您可以在ActionMode.Callback.onPrepareActionMode方法中将drawable分配给ImageButton

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

    } 
} 
+0

谢谢!我已经看到了这种实现方式,但认为必须有一种方法可以在xml中实现。然而,你的解释是非常好的,我现在认为你建议的方式是唯一的方法来做到这一点...与赏金乐趣(在14小时内...) – Frame91

+0

@ Frame91只是一个建议..完全使用你的赏金提供。你可以保持这个答案处于未被接受的状态,以便其他人将尝试提供(可能)更好的解决方案。当赏金接近到期时间时,您可以手动分配赏金。 –

+0

是的你是对的 - 但正如你解释的,没有人会提交一个简单的XML解决方案;) – Frame91

6

我还需要弄清楚如何为我的默认动作条是不是在ActionMode,动作条可见改变了我的溢出图标只改变内部ActionMode-动作条的溢出图标(不,我不想改变我的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); 
} 

你将调用从ActionMode.Callback实施onCreateActionMode(...)这个方法:

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

的解释了一下:

'BaseTheme'中的作业用于ActionBar。它会选择可绘制的overflow_menu_light,因为我们将其分配在应用程序的基本主题中。

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

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

还有更多...

通过马尼什给出的答案是相当真棒。我本可以从未想过使用内容描述来找到确切的ImageButton但是,如果您可以使用简单的findViewById()找到ImageButton

下面是如何,您可以:

首先,我们需要唯一的ID。如果您的项目目前没有res/values/ids.xml文件,请创建一个。添加一个新的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> 

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

我在这里借用Manish的答案代码段的ImageButton

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

两全其美?

比方说,我们需要为ActionModeR.drawable.overflow_menu_lightActionBarR.drawable.overflow_menu_dark

样式:

<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会挑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不会被创建。现在

,我们需要处理ActionMode - 因为它会选择从主题dark绘制。

我对这篇巨大的文章表示歉意。我真的希望它有帮助。

+2

这只是一个了不起的解释!你的第一个教程工作得很好!在我看来,这是一种比处理Handlers和Runnables更美丽的方式....谢谢! :)) – Frame91

+1

试用了样式的第一个解决方案,适用于Android 5.0以前的版本,但不适用于Android Lollipop 5.0。对此有何更新? –