110e2dbc1ad1c01d2824d921a8b0f070859d6f146Chris Banes/* 210e2dbc1ad1c01d2824d921a8b0f070859d6f146Chris Banes * Copyright (C) 2015 The Android Open Source Project 310e2dbc1ad1c01d2824d921a8b0f070859d6f146Chris Banes * 410e2dbc1ad1c01d2824d921a8b0f070859d6f146Chris Banes * Licensed under the Apache License, Version 2.0 (the "License"); 510e2dbc1ad1c01d2824d921a8b0f070859d6f146Chris Banes * you may not use this file except in compliance with the License. 610e2dbc1ad1c01d2824d921a8b0f070859d6f146Chris Banes * You may obtain a copy of the License at 710e2dbc1ad1c01d2824d921a8b0f070859d6f146Chris Banes * 810e2dbc1ad1c01d2824d921a8b0f070859d6f146Chris Banes * http://www.apache.org/licenses/LICENSE-2.0 910e2dbc1ad1c01d2824d921a8b0f070859d6f146Chris Banes * 1010e2dbc1ad1c01d2824d921a8b0f070859d6f146Chris Banes * Unless required by applicable law or agreed to in writing, software 1110e2dbc1ad1c01d2824d921a8b0f070859d6f146Chris Banes * distributed under the License is distributed on an "AS IS" BASIS, 1210e2dbc1ad1c01d2824d921a8b0f070859d6f146Chris Banes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1310e2dbc1ad1c01d2824d921a8b0f070859d6f146Chris Banes * See the License for the specific language governing permissions and 1410e2dbc1ad1c01d2824d921a8b0f070859d6f146Chris Banes * limitations under the License. 1510e2dbc1ad1c01d2824d921a8b0f070859d6f146Chris Banes */ 1610e2dbc1ad1c01d2824d921a8b0f070859d6f146Chris Banes 1710e2dbc1ad1c01d2824d921a8b0f070859d6f146Chris Banespackage android.support.v7.widget; 1810e2dbc1ad1c01d2824d921a8b0f070859d6f146Chris Banes 19b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banesimport android.content.res.ColorStateList; 20b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banesimport android.graphics.Canvas; 21b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banesimport android.graphics.PorterDuff; 2210e2dbc1ad1c01d2824d921a8b0f070859d6f146Chris Banesimport android.graphics.drawable.Drawable; 23b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banesimport android.support.annotation.Nullable; 24b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banesimport android.support.v4.graphics.drawable.DrawableCompat; 25b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banesimport android.support.v4.view.ViewCompat; 26b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banesimport android.support.v7.appcompat.R; 2710e2dbc1ad1c01d2824d921a8b0f070859d6f146Chris Banesimport android.util.AttributeSet; 2810e2dbc1ad1c01d2824d921a8b0f070859d6f146Chris Banesimport android.widget.SeekBar; 2910e2dbc1ad1c01d2824d921a8b0f070859d6f146Chris Banes 3010e2dbc1ad1c01d2824d921a8b0f070859d6f146Chris Banesclass AppCompatSeekBarHelper extends AppCompatProgressBarHelper { 3110e2dbc1ad1c01d2824d921a8b0f070859d6f146Chris Banes 3210e2dbc1ad1c01d2824d921a8b0f070859d6f146Chris Banes private final SeekBar mView; 3310e2dbc1ad1c01d2824d921a8b0f070859d6f146Chris Banes 34b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes private Drawable mTickMark; 35b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes private ColorStateList mTickMarkTintList = null; 36b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes private PorterDuff.Mode mTickMarkTintMode = null; 37b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes private boolean mHasTickMarkTint = false; 38b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes private boolean mHasTickMarkTintMode = false; 39b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes 404c99f0e29b0926d8e5de44b7e3980d47f052f04cChris Banes AppCompatSeekBarHelper(SeekBar view) { 414c99f0e29b0926d8e5de44b7e3980d47f052f04cChris Banes super(view); 4210e2dbc1ad1c01d2824d921a8b0f070859d6f146Chris Banes mView = view; 4310e2dbc1ad1c01d2824d921a8b0f070859d6f146Chris Banes } 4410e2dbc1ad1c01d2824d921a8b0f070859d6f146Chris Banes 45dc8e099ed130434c0238f558277c5bcb6a533121Aurimas Liutikas @Override 4610e2dbc1ad1c01d2824d921a8b0f070859d6f146Chris Banes void loadFromAttributes(AttributeSet attrs, int defStyleAttr) { 4710e2dbc1ad1c01d2824d921a8b0f070859d6f146Chris Banes super.loadFromAttributes(attrs, defStyleAttr); 4810e2dbc1ad1c01d2824d921a8b0f070859d6f146Chris Banes 4910e2dbc1ad1c01d2824d921a8b0f070859d6f146Chris Banes TintTypedArray a = TintTypedArray.obtainStyledAttributes(mView.getContext(), attrs, 50b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes R.styleable.AppCompatSeekBar, defStyleAttr, 0); 51b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes final Drawable drawable = a.getDrawableIfKnown(R.styleable.AppCompatSeekBar_android_thumb); 5210e2dbc1ad1c01d2824d921a8b0f070859d6f146Chris Banes if (drawable != null) { 5310e2dbc1ad1c01d2824d921a8b0f070859d6f146Chris Banes mView.setThumb(drawable); 5410e2dbc1ad1c01d2824d921a8b0f070859d6f146Chris Banes } 55b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes 56b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes final Drawable tickMark = a.getDrawable(R.styleable.AppCompatSeekBar_tickMark); 57b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes setTickMark(tickMark); 58b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes 59b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes if (a.hasValue(R.styleable.AppCompatSeekBar_tickMarkTintMode)) { 60b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes mTickMarkTintMode = DrawableUtils.parseTintMode(a.getInt( 61b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes R.styleable.AppCompatSeekBar_tickMarkTintMode, -1), mTickMarkTintMode); 62b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes mHasTickMarkTintMode = true; 63b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes } 64b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes 65b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes if (a.hasValue(R.styleable.AppCompatSeekBar_tickMarkTint)) { 66b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes mTickMarkTintList = a.getColorStateList(R.styleable.AppCompatSeekBar_tickMarkTint); 67b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes mHasTickMarkTint = true; 68b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes } 69b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes 7010e2dbc1ad1c01d2824d921a8b0f070859d6f146Chris Banes a.recycle(); 71b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes 72b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes applyTickMarkTint(); 73b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes } 74b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes 75b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes void setTickMark(@Nullable Drawable tickMark) { 76b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes if (mTickMark != null) { 77b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes mTickMark.setCallback(null); 78b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes } 79b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes 80b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes mTickMark = tickMark; 81b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes 82b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes if (tickMark != null) { 83b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes tickMark.setCallback(mView); 84b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes DrawableCompat.setLayoutDirection(tickMark, ViewCompat.getLayoutDirection(mView)); 85b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes if (tickMark.isStateful()) { 86b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes tickMark.setState(mView.getDrawableState()); 87b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes } 88b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes applyTickMarkTint(); 89b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes } 90b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes 91b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes mView.invalidate(); 92b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes } 93b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes 94b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes @Nullable 95b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes Drawable getTickMark() { 96b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes return mTickMark; 97b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes } 98b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes 99b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes void setTickMarkTintList(@Nullable ColorStateList tint) { 100b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes mTickMarkTintList = tint; 101b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes mHasTickMarkTint = true; 102b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes 103b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes applyTickMarkTint(); 104b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes } 105b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes 106b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes @Nullable 107b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes ColorStateList getTickMarkTintList() { 108b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes return mTickMarkTintList; 10910e2dbc1ad1c01d2824d921a8b0f070859d6f146Chris Banes } 110b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes 111b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes void setTickMarkTintMode(@Nullable PorterDuff.Mode tintMode) { 112b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes mTickMarkTintMode = tintMode; 113b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes mHasTickMarkTintMode = true; 114b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes 115b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes applyTickMarkTint(); 116b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes } 117b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes 118b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes @Nullable 119b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes PorterDuff.Mode getTickMarkTintMode() { 120b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes return mTickMarkTintMode; 121b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes } 122b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes 123b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes private void applyTickMarkTint() { 124b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes if (mTickMark != null && (mHasTickMarkTint || mHasTickMarkTintMode)) { 125168fbe2c9b213338bce447c8825303c86b5b9281Chris Banes mTickMark = DrawableCompat.wrap(mTickMark.mutate()); 126b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes 127b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes if (mHasTickMarkTint) { 128168fbe2c9b213338bce447c8825303c86b5b9281Chris Banes DrawableCompat.setTintList(mTickMark, mTickMarkTintList); 129b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes } 130b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes 131b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes if (mHasTickMarkTintMode) { 132168fbe2c9b213338bce447c8825303c86b5b9281Chris Banes DrawableCompat.setTintMode(mTickMark, mTickMarkTintMode); 133b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes } 134b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes 135b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes // The drawable (or one of its children) may not have been 136b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes // stateful before applying the tint, so let's try again. 137b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes if (mTickMark.isStateful()) { 138b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes mTickMark.setState(mView.getDrawableState()); 139b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes } 140b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes } 141b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes } 142b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes 143b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes void jumpDrawablesToCurrentState() { 144b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes if (mTickMark != null) { 145b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes mTickMark.jumpToCurrentState(); 146b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes } 147b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes } 148b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes 149b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes void drawableStateChanged() { 150b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes final Drawable tickMark = mTickMark; 151b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes if (tickMark != null && tickMark.isStateful() 152b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes && tickMark.setState(mView.getDrawableState())) { 153b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes mView.invalidateDrawable(tickMark); 154b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes } 155b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes } 156b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes 157b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes /** 158b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes * Draw the tick marks. 159b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes */ 160b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes void drawTickMarks(Canvas canvas) { 161b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes if (mTickMark != null) { 162b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes final int count = mView.getMax(); 163b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes if (count > 1) { 164b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes final int w = mTickMark.getIntrinsicWidth(); 165b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes final int h = mTickMark.getIntrinsicHeight(); 166b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes final int halfW = w >= 0 ? w / 2 : 1; 167b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes final int halfH = h >= 0 ? h / 2 : 1; 168b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes mTickMark.setBounds(-halfW, -halfH, halfW, halfH); 169b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes 170b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes final float spacing = (mView.getWidth() - mView.getPaddingLeft() 171b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes - mView.getPaddingRight()) / (float) count; 172b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes final int saveCount = canvas.save(); 173b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes canvas.translate(mView.getPaddingLeft(), mView.getHeight() / 2); 174b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes for (int i = 0; i <= count; i++) { 175b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes mTickMark.draw(canvas); 176b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes canvas.translate(spacing, 0); 177b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes } 178b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes canvas.restoreToCount(saveCount); 179b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes } 180b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes } 181b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes } 182b19cba1c83a68efb5c18ef74e4e5d376fa166625Chris Banes 18310e2dbc1ad1c01d2824d921a8b0f070859d6f146Chris Banes} 184