Changing ActionBar tabs underline color programmatically

后端 未结 8 1894
误落风尘
误落风尘 2020-12-01 18:28

I have created the action bar by

ActionBar actionbar = getActionBar()

The background of the action bar is changed by

acti         


        
8条回答
  •  再見小時候
    2020-12-01 18:33

    I tried many of the suggestions posted here and other places with no luck. But I think I managed to piece together a (albeit not perfect) solution.

    The TabWidget is using a selector. Essentially it is showing a different 9 patch image depending on the state of the tab (selected, pressed, etc.). I finally figured out that you could generate a selector programmatically. I started with generated 9 patches from http://android-holo-colors.com/ (color: #727272, TabWidget: Yes).

    The biggest issue was setting the color. Setting the color filter did nothing. So, I ended up changing the colors of each of the pixels of the 9 patch image inside a loop.

    ...    
    /**
     * NinePatchDrawableUtility utility class for manipulating nine patch resources.
     * 
     * @author amossman
     *
     */
    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
    public class NinePatchDrawableUtility {
    
        // Matches the colors in the supported drawables
        private static final int TAB_UNDERLINE_HIGHLIGHT_COLOR = 1417247097;
        private static final int TAB_UNDERLINE_COLOR = -8882056;
        private static final int TAB_PRESSED_COLOR = -2122745479;
    
        private Resources resources;
    
        public NinePatchDrawableUtility(Resources resources) {
            this.resources = resources;
        }
    
        /**
         * Create a StateListDrawable that can be used as a background for the {@link android.widget.TabWidget}

    * * * FragmentTabHost tabHost = ...
    * NinePatchUtility ninePatchUtility = new NinePatchUtility(getResources());
    * TabWidget tabWidget = tabHost.getTabWidget();
    * for (int i = 0; i < tabWidget.getChildCount(); i++) {
    *    tabWidget.getChildAt(i).setBackground(ninePatchUtility.getTabStateListDrawable(titleColor));
    * } *
    * * @param tintColor The color to tint the StateListDrawable * @return A new StateListDrawable that has been tinted to the given color */ public StateListDrawable getTabStateListDrawable(int tintColor) { StateListDrawable states = new StateListDrawable(); states.addState(new int[] {android.R.attr.state_pressed}, changeTabNinePatchColor(resources, R.drawable.cc_tab_selected_pressed_holo, tintColor)); states.addState(new int[] {android.R.attr.state_focused}, changeTabNinePatchColor(resources, R.drawable.cc_tab_selected_focused_holo, tintColor)); states.addState(new int[] {android.R.attr.state_selected}, changeTabNinePatchColor(resources, R.drawable.cc_tab_selected_holo, tintColor)); states.addState(new int[] { }, changeTabNinePatchColor(resources, R.drawable.cc_tab_unselected_holo, tintColor)); return states; } /** * Change the color of the tab indicator.

    * * Supports only the following drawables:

    * * R.drawable.cc_tab_selected_pressed_holo
    * R.drawable.cc_tab_selected_focused_holo
    * R.drawable.cc_tab_selected_holo
    * R.drawable.cc_tab_unselected_holo

    * * Note: This method is not efficient for large Drawable sizes. * * @param resources Contains display metrics and image data * @param drawable The nine patch Drawable for the tab * @param tintColor The color to tint the Drawable * @return A new NinePatchDrawable tinted to the given color */ public NinePatchDrawable changeTabNinePatchColor(Resources resources, int drawable, int tintColor) { int a = Color.alpha(tintColor); int r = Color.red(tintColor); int g = Color.green(tintColor); int b = Color.blue(tintColor); BitmapFactory.Options opt = new BitmapFactory.Options(); opt.inMutable = true; Bitmap bitmap = BitmapFactory.decodeResource(resources, drawable, opt); for (int x = 0; x < bitmap.getWidth(); x++) { for (int y = 0; y < bitmap.getHeight(); y++) { int color = bitmap.getPixel(x, y); if (color == TAB_PRESSED_COLOR) { bitmap.setPixel(x, y, Color.argb((int)(a * 0.5), r, g, b)); } else if (color == TAB_UNDERLINE_HIGHLIGHT_COLOR) { bitmap.setPixel(x, y, Color.argb((int)(a * 0.9), r, g, b)); } else if (color == TAB_UNDERLINE_COLOR) { bitmap.setPixel(x, y, tintColor); } } } return new NinePatchDrawable(resources, bitmap, bitmap.getNinePatchChunk(), new Rect(), null); } }

    Example of usage:

    /**
     * Theme the tab widget with the defined background color and title color set
     * in the TabManager
     * @param tabWidget
     */
    @SuppressWarnings("deprecation")
    @SuppressLint("NewApi")
    public void theme(TabWidget tabWidget) {
        ColorDrawable backgroundDrawable = new ColorDrawable(backgroundColor);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
            tabWidget.setBackground(backgroundDrawable);
            tabWidget.setAlpha(0.95f);
        } else {
            backgroundDrawable.setAlpha(242);
            tabWidget.setBackgroundDrawable(backgroundDrawable);
        }
        NinePatchDrawableUtility ninePatchUtility = new NinePatchDrawableUtility(resources);
        for (int i = 0; i < tabWidget.getChildCount(); i++) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                tabWidget.getChildAt(i).setBackground(ninePatchUtility.getTabStateListDrawable(titleColor));
            } else {
                tabWidget.getChildAt(i).setBackgroundDrawable(ninePatchUtility.getTabStateListDrawable(titleColor));
            }
            View tabView = tabWidget.getChildTabViewAt(i);
            tabView.setPadding(0, 0, 0, 0);
            TextView tv = (TextView) tabView.findViewById(android.R.id.title);
            tv.setSingleLine(); // set the texts on the tabs to be single line
            tv.setTextColor(titleColor);
        }
    }
    

提交回复
热议问题