23

Tôi đã nhận thấy rằng bằng cách sử dụng các chủ đề của AppCompat, các biểu tượng thanh công cụ mặc định được tô màu theo thuộc tính colorControlNormal theo phong cách của tôi.Biểu tượng thanh công cụ tô màu trên Android

<style name="MyTheme" parent="Theme.AppCompat"> 
    <item name="colorControlNormal">@color/yellow</item> 
</style> 

enter image description here

Như bạn thấy ở trên, tuy nhiên, nó không xảy ra với tất cả các biểu tượng. Tôi cung cấp dấu "cộng", mà tôi nhận được từ các biểu tượng chính thức, và nó không bị nhuộm màu (tôi đã sử dụng phiên bản "trắng" của png). Từ những gì tôi đã hiểu từ question này, hệ thống chỉ tô màu các biểu tượng chỉ bằng một kênh alpha. Điều này có đúng không?

Nếu vậy: Có nơi nào tôi có thể tìm thấy biểu tượng tài liệu chính thức được xác định bằng alpha không? Nếu không - và nếu các biểu tượng của Thanh công cụ cần phải là chỉ alpha để được tô màu - Google mong muốn chúng tôi sử dụng các biểu tượng được cung cấp trong Thanh công cụ như thế nào?

Ở đâu đó trong SDK, tôi đã tìm thấy một số biểu tượng kết thúc bằng số _alpha.png và chúng thực sự được tô màu tốt. Tuy nhiên, tôi cần tập hợp đầy đủ các biểu tượng vật chất và từ các nguồn chính thức, tôi chỉ có thể tìm thấy các số white, grey600black.

Áp dụng ColorFilter khi chạy sẽ hơi đau và Thanh công cụ thực tế của tôi - với một số biểu tượng được tô màu, một số khác không - trông khá xấu.

+1

AppCompat chỉ mang lại màu biểu tượng của riêng mình. Bây giờ, bạn sẽ cần phải tự tay tô màu bất kỳ biểu tượng nào bạn đang cung cấp riêng biệt với AppCompat. – alanv

+0

Ngoài ra, câu hỏi được liên kết chỉ áp dụng cho các thông báo, không phải màu nhuộm chung. – alanv

+1

Xem thêm [bài đăng trên StackO này] (http://stackoverflow.com/questions/26780046/menuitem-tinting-on-appcompat-toolbar) để được giải thích kỹ lưỡng. – reVerse

Trả lời

4

Tôi thấy câu hỏi này đang nhận được một số lượt xem vì vậy tôi sẽ đăng câu trả lời cho những người không đọc nhận xét.

Giả thuyết của tôi trong câu hỏi đều sai và không phải là vấn đề của kênh alpha, ít nhất là không phải từ bên ngoài. Thực tế đơn giản là, trích dẫn @alanv,

AppCompat chỉ làm mờ các biểu tượng của riêng nó. Hiện tại, bạn cần phải tự tay tô màu bất kỳ biểu tượng nào bạn đang cung cấp riêng biệt với AppCompat.

Điều này có thể thay đổi trong tương lai nhưng cũng có thể không thay đổi. Từ this answer bạn cũng có thể xem danh sách các biểu tượng (tất cả đều thuộc về thư mục tài nguyên nội bộ của appcompat, vì vậy bạn không thể thay đổi chúng) được tô màu tự động và có màu nào.

Cá nhân tôi sử dụng colorControlNormal màu đen hoặc trắng (hoặc các tông màu tương tự) và nhập các biểu tượng có màu cụ thể đó. Biểu tượng màu trên nền có màu hơi xấu. Tuy nhiên, một giải pháp tôi thấy dễ chịu là this class trên github. Bạn chỉ cần gọi MenuColorizer.colorMenu() khi bạn tạo menu.

+0

Tôi nghĩ bạn nên xem câu trả lời của tôi ở trên ... –

19

Đây là giải pháp mà tôi sử dụng. Gọi tintAllIcons sau onPrepareOptionsMenu hoặc vị trí tương đương. Lý do cho mutate() là nếu bạn tình cờ sử dụng các biểu tượng ở nhiều vị trí; mà không có đột biến, tất cả chúng sẽ có cùng màu.

public class MenuTintUtils { 
    public static void tintAllIcons(Menu menu, final int color) { 
     for (int i = 0; i < menu.size(); ++i) { 
      final MenuItem item = menu.getItem(i); 
      tintMenuItemIcon(color, item); 
      tintShareIconIfPresent(color, item); 
     } 
    } 

    private static void tintMenuItemIcon(int color, MenuItem item) { 
     final Drawable drawable = item.getIcon(); 
     if (drawable != null) { 
      final Drawable wrapped = DrawableCompat.wrap(drawable); 
      drawable.mutate(); 
      DrawableCompat.setTint(wrapped, color); 
      item.setIcon(drawable); 
     } 
    } 

    private static void tintShareIconIfPresent(int color, MenuItem item) { 
     if (item.getActionView() != null) { 
      final View actionView = item.getActionView(); 
      final View expandActivitiesButton = actionView.findViewById(R.id.expand_activities_button); 
      if (expandActivitiesButton != null) { 
       final ImageView image = (ImageView) expandActivitiesButton.findViewById(R.id.image); 
       if (image != null) { 
        final Drawable drawable = image.getDrawable(); 
        final Drawable wrapped = DrawableCompat.wrap(drawable); 
        drawable.mutate(); 
        DrawableCompat.setTint(wrapped, color); 
        image.setImageDrawable(drawable); 
       } 
      } 
     } 
    } 
} 

này sẽ không chăm sóc tràn, nhưng vì điều đó, bạn có thể làm điều này:

Layout:

<android.support.v7.widget.Toolbar 
    ... 
    android:theme="@style/myToolbarTheme" /> 

Styles:

<style name="myToolbarTheme"> 
     <item name="colorControlNormal">#FF0000</item> 
</style> 

tác phẩm này như của appcompat v23.1.0.

4

Bạn chỉ có thể tạo Thanh công cụ tùy chỉnh sử dụng màu tô màu của bạn khi tăng cường menu.

public class MyToolbar extends Toolbar { 
    ... some constructors, extracting mAccentColor from AttrSet, etc 

    @Override 
    public void inflateMenu(@MenuRes int resId) { 
     super.inflateMenu(resId); 
     Menu menu = getMenu(); 
     for (int i = 0; i < menu.size(); i++) { 
      MenuItem item = menu.getItem(i); 
      Drawable icon = item.getIcon(); 
      if (icon != null) { 
       item.setIcon(applyTint(icon)); 
      } 
     } 
    } 
    void applyTint(Drawable icon){ 
     icon.setColorFilter(
      new PorterDuffColorFilter(mAccentColor, PorterDuff.Mode.SRC_IN) 
     ); 
    } 

} 

Chỉ cần chắc chắn bạn gọi trong Hoạt động mã/Fragment của bạn:

toolbar.inflateMenu(R.menu.some_menu); 
toolbar.setOnMenuItemClickListener(someListener); 

Không phản ánh, không có tra cứu xem, và không quá nhiều mã, huh?

Và đừng sử dụng onCreateOptionsMenu/onOptionsItemSelected, nếu bạn sử dụng phương pháp này

18

Một lựa chọn khác là sử dụng các hỗ trợ mới cho drawables vector trong thư viện hỗ trợ.

Xem res/xml/ic_search.xml trong bài đăng blog AppCompat — Age of the vectors

Thông báo tham chiếu đến ?attr/colorControlNormal

<vector xmlns:android="..." 
    android:width="24dp" 
    android:height="24dp" 
    android:viewportWidth="24.0" 
    android:viewportHeight="24.0" 
    android:tint="?attr/colorControlNormal"> 
    <path 
     android:pathData="..." 
     android:fillColor="@android:color/white"/> 
</vector> 
+0

Sự khác nhau giữa việc sử dụng '? Attr/colorControlNormal' ở thuộc tính 'android: tint' vs' android: fillColor' là gì? Cảm ơn! –

+0

@SuperThomasLab Ví dụ này là từ blog của Chris Banes, nơi nó minh họa việc thay thế một hình ảnh có màu với một vectơ màu. Lưu ý rằng fillColor đã được mã hóa một cách hiệu quả trong hình ảnh nguồn. Tôi không biết liệu các biểu diễn màu khác hiện có được hỗ trợ trong AppCompat hay không. –

11

tôi thực sự đã có thể làm điều này trên API 10 (Gingerbread) và nó làm việc rất tốt.

Sửa: Nó làm việc trên API 22 cũng ...

Dưới đây là kết quả cuối cùng.

enter image description here

Lưu ý: Biểu tượng là một nguồn lực drawable trong thư mục drawable (s).

Bây giờ dưới đây là cách thực hiện của nó:

@Override 
public void onPrepareOptionsMenu(Menu menu) { 
    super.onPrepareOptionsMenu(menu); 

    MenuItem item = menu.findItem(R.id.action_refresh); 
    Drawable icon = getResources().getDrawable(R.drawable.ic_refresh_white_24dp); 
    icon.setColorFilter(getResources().getColor(R.color.colorAccent), PorterDuff.Mode.SRC_IN); 

    item.setIcon(icon); 
} 

Tại thời điểm này bạn có thể thay đổi nó thành bất kỳ màu nào bạn muốn!

0
@NonNull 
public static Drawable setTintDrawable(@NonNull Drawable drawable, @ColorInt int color) { 
    drawable.clearColorFilter(); 
    drawable.setColorFilter(color, PorterDuff.Mode.SRC_IN); 
    drawable.invalidateSelf(); 
    Drawable wrapDrawable = DrawableCompat.wrap(drawable).mutate(); 
    DrawableCompat.setTint(wrapDrawable, color); 
    return wrapDrawable; 
} 

và gọi theo cách này:

MenuItem location = menu.findItem(R.id.action_location); 
DrawableUtils.setTintDrawable(location.getIcon(), Color.WHITE); 

enter image description here

Các vấn đề liên quan