2014-03-28 58 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。對此有何更新? –