1/* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.setupwizardlib.view; 18 19import android.content.Context; 20import android.content.res.ColorStateList; 21import android.graphics.PorterDuff; 22import android.graphics.drawable.Drawable; 23import android.graphics.drawable.LayerDrawable; 24import android.os.Build; 25import android.util.AttributeSet; 26import android.widget.Button; 27 28public class NavigationBarButton extends Button { 29 30 public NavigationBarButton(Context context) { 31 super(context); 32 init(); 33 } 34 35 public NavigationBarButton(Context context, AttributeSet attrs) { 36 super(context, attrs); 37 init(); 38 } 39 40 private void init() { 41 // Unfortunately, drawableStart and drawableEnd set through XML does not call the setter, 42 // so manually getting it and wrapping it in the compat drawable. 43 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { 44 Drawable[] drawables = getCompoundDrawablesRelative(); 45 for (int i = 0; i < drawables.length; i++) { 46 if (drawables[i] != null) { 47 drawables[i] = TintedDrawable.wrap(drawables[i].mutate()); 48 } 49 } 50 setCompoundDrawablesRelativeWithIntrinsicBounds(drawables[0], drawables[1], 51 drawables[2], drawables[3]); 52 } 53 } 54 55 @Override 56 public void setCompoundDrawables(Drawable left, Drawable top, Drawable right, Drawable bottom) { 57 if (left != null) left = TintedDrawable.wrap(left.mutate()); 58 if (top != null) top = TintedDrawable.wrap(top.mutate()); 59 if (right != null) right = TintedDrawable.wrap(right.mutate()); 60 if (bottom != null) bottom = TintedDrawable.wrap(bottom.mutate()); 61 super.setCompoundDrawables(left, top, right, bottom); 62 tintDrawables(); 63 } 64 65 @Override 66 public void setCompoundDrawablesRelative(Drawable start, Drawable top, Drawable end, 67 Drawable bottom) { 68 if (start != null) start = TintedDrawable.wrap(start.mutate()); 69 if (top != null) top = TintedDrawable.wrap(top.mutate()); 70 if (end != null) end = TintedDrawable.wrap(end.mutate()); 71 if (bottom != null) bottom = TintedDrawable.wrap(bottom.mutate()); 72 super.setCompoundDrawablesRelative(start, top, end, bottom); 73 tintDrawables(); 74 } 75 76 @Override 77 public void setTextColor(ColorStateList colors) { 78 super.setTextColor(colors); 79 tintDrawables(); 80 } 81 82 private void tintDrawables() { 83 final ColorStateList textColors = getTextColors(); 84 if (textColors != null) { 85 for (Drawable drawable : getAllCompoundDrawables()) { 86 if (drawable instanceof TintedDrawable) { 87 ((TintedDrawable) drawable).setTintListCompat(textColors); 88 } 89 } 90 invalidate(); 91 } 92 } 93 94 private Drawable[] getAllCompoundDrawables() { 95 Drawable[] drawables = new Drawable[6]; 96 Drawable[] compoundDrawables = getCompoundDrawables(); 97 drawables[0] = compoundDrawables[0]; // left 98 drawables[1] = compoundDrawables[1]; // top 99 drawables[2] = compoundDrawables[2]; // right 100 drawables[3] = compoundDrawables[3]; // bottom 101 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { 102 Drawable[] compoundDrawablesRelative = getCompoundDrawablesRelative(); 103 drawables[4] = compoundDrawablesRelative[0]; // start 104 drawables[5] = compoundDrawablesRelative[2]; // end 105 } 106 return drawables; 107 } 108 109 // TODO: Remove this class and use DrawableCompat.wrap() once we can use support library 22.1.0 110 // or above 111 private static class TintedDrawable extends LayerDrawable { 112 113 public static TintedDrawable wrap(Drawable drawable) { 114 if (drawable instanceof TintedDrawable) { 115 return (TintedDrawable) drawable; 116 } 117 return new TintedDrawable(drawable); 118 } 119 120 private ColorStateList mTintList = null; 121 122 public TintedDrawable(Drawable wrapped) { 123 super(new Drawable[] { wrapped }); 124 } 125 126 @Override 127 public boolean isStateful() { 128 return true; 129 } 130 131 @Override 132 public boolean setState(int[] stateSet) { 133 boolean needsInvalidate = super.setState(stateSet); 134 boolean needsInvalidateForState = updateState(); 135 return needsInvalidate || needsInvalidateForState; 136 } 137 138 public void setTintListCompat(ColorStateList colors) { 139 mTintList = colors; 140 if (updateState()) { 141 invalidateSelf(); 142 } 143 } 144 145 private boolean updateState() { 146 if (mTintList != null) { 147 final int color = mTintList.getColorForState(getState(), 0); 148 setColorFilter(color, PorterDuff.Mode.SRC_IN); 149 return true; // Needs invalidate 150 } 151 return false; 152 } 153 } 154} 155