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 android.support.v7.widget; 18 19import android.content.res.ColorStateList; 20import android.content.res.TypedArray; 21import android.graphics.PorterDuff; 22import android.graphics.drawable.Drawable; 23import android.os.Build; 24import android.support.annotation.Nullable; 25import android.support.v4.graphics.drawable.DrawableCompat; 26import android.support.v4.widget.CompoundButtonCompat; 27import android.support.v7.appcompat.R; 28import android.support.v7.content.res.AppCompatResources; 29import android.util.AttributeSet; 30import android.widget.CompoundButton; 31 32class AppCompatCompoundButtonHelper { 33 34 private final CompoundButton mView; 35 36 private ColorStateList mButtonTintList = null; 37 private PorterDuff.Mode mButtonTintMode = null; 38 private boolean mHasButtonTint = false; 39 private boolean mHasButtonTintMode = false; 40 41 private boolean mSkipNextApply; 42 43 /** 44 * Interface which allows us to directly set a button, bypass any calls back to ourselves. 45 */ 46 interface DirectSetButtonDrawableInterface { 47 void setButtonDrawable(Drawable buttonDrawable); 48 } 49 50 AppCompatCompoundButtonHelper(CompoundButton view) { 51 mView = view; 52 } 53 54 void loadFromAttributes(AttributeSet attrs, int defStyleAttr) { 55 TypedArray a = mView.getContext().obtainStyledAttributes(attrs, R.styleable.CompoundButton, 56 defStyleAttr, 0); 57 try { 58 if (a.hasValue(R.styleable.CompoundButton_android_button)) { 59 final int resourceId = a.getResourceId( 60 R.styleable.CompoundButton_android_button, 0); 61 if (resourceId != 0) { 62 mView.setButtonDrawable( 63 AppCompatResources.getDrawable(mView.getContext(), resourceId)); 64 } 65 } 66 if (a.hasValue(R.styleable.CompoundButton_buttonTint)) { 67 CompoundButtonCompat.setButtonTintList(mView, 68 a.getColorStateList(R.styleable.CompoundButton_buttonTint)); 69 } 70 if (a.hasValue(R.styleable.CompoundButton_buttonTintMode)) { 71 CompoundButtonCompat.setButtonTintMode(mView, 72 DrawableUtils.parseTintMode( 73 a.getInt(R.styleable.CompoundButton_buttonTintMode, -1), 74 null)); 75 } 76 } finally { 77 a.recycle(); 78 } 79 } 80 81 void setSupportButtonTintList(ColorStateList tint) { 82 mButtonTintList = tint; 83 mHasButtonTint = true; 84 85 applyButtonTint(); 86 } 87 88 ColorStateList getSupportButtonTintList() { 89 return mButtonTintList; 90 } 91 92 void setSupportButtonTintMode(@Nullable PorterDuff.Mode tintMode) { 93 mButtonTintMode = tintMode; 94 mHasButtonTintMode = true; 95 96 applyButtonTint(); 97 } 98 99 PorterDuff.Mode getSupportButtonTintMode() { 100 return mButtonTintMode; 101 } 102 103 void onSetButtonDrawable() { 104 if (mSkipNextApply) { 105 mSkipNextApply = false; 106 return; 107 } 108 109 mSkipNextApply = true; 110 applyButtonTint(); 111 } 112 113 void applyButtonTint() { 114 Drawable buttonDrawable = CompoundButtonCompat.getButtonDrawable(mView); 115 116 if (buttonDrawable != null && (mHasButtonTint || mHasButtonTintMode)) { 117 buttonDrawable = DrawableCompat.wrap(buttonDrawable); 118 buttonDrawable = buttonDrawable.mutate(); 119 if (mHasButtonTint) { 120 DrawableCompat.setTintList(buttonDrawable, mButtonTintList); 121 } 122 if (mHasButtonTintMode) { 123 DrawableCompat.setTintMode(buttonDrawable, mButtonTintMode); 124 } 125 // The drawable (or one of its children) may not have been 126 // stateful before applying the tint, so let's try again. 127 if (buttonDrawable.isStateful()) { 128 buttonDrawable.setState(mView.getDrawableState()); 129 } 130 mView.setButtonDrawable(buttonDrawable); 131 } 132 } 133 134 int getCompoundPaddingLeft(int superValue) { 135 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) { 136 // Before JB-MR1 the button drawable wasn't taken into account for padding. We'll 137 // workaround that here 138 Drawable buttonDrawable = CompoundButtonCompat.getButtonDrawable(mView); 139 if (buttonDrawable != null) { 140 superValue += buttonDrawable.getIntrinsicWidth(); 141 } 142 } 143 return superValue; 144 } 145} 146