summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Viverette <alanv@google.com>2014-05-12 17:56:56 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2014-05-12 17:56:57 +0000
commit1cb088c1281deec042bdf00e0f2d227f7e5cd718 (patch)
tree786e750c7c6384ccd981cca97a109f661281f645
parent033655636e9b936244f2ee3ae28e1363506007d4 (diff)
parent661e63658da39cccfe49a129e4860455716ff3c9 (diff)
downloadframeworks_base-1cb088c1281deec042bdf00e0f2d227f7e5cd718.zip
frameworks_base-1cb088c1281deec042bdf00e0f2d227f7e5cd718.tar.gz
frameworks_base-1cb088c1281deec042bdf00e0f2d227f7e5cd718.tar.bz2
Merge "Support for hollow switch and seek bar thumbs"
-rw-r--r--api/current.txt5
-rw-r--r--core/java/android/widget/AbsSeekBar.java219
-rw-r--r--core/java/android/widget/ProgressBar.java21
-rw-r--r--core/java/android/widget/Switch.java90
-rw-r--r--core/res/res/drawable-hdpi/scrubber_control_off_qntm_alpha.pngbin341 -> 232 bytes
-rw-r--r--core/res/res/drawable-hdpi/scrubber_control_on_qntm_alpha.pngbin241 -> 184 bytes
-rw-r--r--core/res/res/drawable-hdpi/switch_off_qntm_alpha.9.pngbin546 -> 523 bytes
-rw-r--r--core/res/res/drawable-hdpi/switch_on_qntm_alpha.9.pngbin222 -> 187 bytes
-rw-r--r--core/res/res/drawable-mdpi/scrubber_control_off_qntm_alpha.pngbin230 -> 181 bytes
-rw-r--r--core/res/res/drawable-mdpi/scrubber_control_on_qntm_alpha.pngbin182 -> 154 bytes
-rw-r--r--core/res/res/drawable-mdpi/switch_off_qntm_alpha.9.pngbin390 -> 371 bytes
-rw-r--r--core/res/res/drawable-mdpi/switch_on_qntm_alpha.9.pngbin184 -> 156 bytes
-rw-r--r--core/res/res/drawable-xhdpi/scrubber_control_off_qntm_alpha.pngbin495 -> 314 bytes
-rw-r--r--core/res/res/drawable-xhdpi/scrubber_control_on_qntm_alpha.pngbin304 -> 248 bytes
-rw-r--r--core/res/res/drawable-xhdpi/switch_off_qntm_alpha.9.pngbin827 -> 767 bytes
-rw-r--r--core/res/res/drawable-xhdpi/switch_on_qntm_alpha.9.pngbin279 -> 223 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/scrubber_control_off_qntm_alpha.pngbin1014 -> 388 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/scrubber_control_on_qntm_alpha.pngbin881 -> 294 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/switch_off_qntm_alpha.9.pngbin1153 -> 1089 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/switch_on_qntm_alpha.9.pngbin508 -> 293 bytes
-rw-r--r--core/res/res/drawable/scrubber_progress_horizontal_quantum.xml16
-rw-r--r--core/res/res/values/attrs.xml4
-rw-r--r--core/res/res/values/public.xml1
-rw-r--r--core/res/res/values/styles_quantum.xml6
24 files changed, 244 insertions, 118 deletions
diff --git a/api/current.txt b/api/current.txt
index 9c142d44..40e3ad2 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -1047,6 +1047,7 @@ package android {
field public static final int spinnerStyle = 16842881; // 0x1010081
field public static final int spinnersShown = 16843595; // 0x101034b
field public static final int splitMotionEvents = 16843503; // 0x10102ef
+ field public static final int splitTrack = 16843858; // 0x1010452
field public static final int src = 16843033; // 0x1010119
field public static final int ssp = 16843747; // 0x10103e3
field public static final int sspPattern = 16843749; // 0x10103e5
@@ -34386,9 +34387,11 @@ package android.widget {
ctor public AbsSeekBar(android.content.Context, android.util.AttributeSet, int);
ctor public AbsSeekBar(android.content.Context, android.util.AttributeSet, int, int);
method public int getKeyProgressIncrement();
+ method public boolean getSplitTrack();
method public android.graphics.drawable.Drawable getThumb();
method public int getThumbOffset();
method public void setKeyProgressIncrement(int);
+ method public void setSplitTrack(boolean);
method public void setThumb(android.graphics.drawable.Drawable);
method public void setThumbOffset(int);
}
@@ -36193,6 +36196,7 @@ package android.widget {
ctor public Switch(android.content.Context, android.util.AttributeSet);
ctor public Switch(android.content.Context, android.util.AttributeSet, int);
ctor public Switch(android.content.Context, android.util.AttributeSet, int, int);
+ method public boolean getSplitTrack();
method public int getSwitchMinWidth();
method public int getSwitchPadding();
method public java.lang.CharSequence getTextOff();
@@ -36201,6 +36205,7 @@ package android.widget {
method public int getThumbTextPadding();
method public android.graphics.drawable.Drawable getTrackDrawable();
method public void onMeasure(int, int);
+ method public void setSplitTrack(boolean);
method public void setSwitchMinWidth(int);
method public void setSwitchPadding(int);
method public void setSwitchTextAppearance(android.content.Context, int);
diff --git a/core/java/android/widget/AbsSeekBar.java b/core/java/android/widget/AbsSeekBar.java
index 225cd6d..4f2d9c6 100644
--- a/core/java/android/widget/AbsSeekBar.java
+++ b/core/java/android/widget/AbsSeekBar.java
@@ -19,7 +19,9 @@ package android.widget;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
+import android.graphics.Insets;
import android.graphics.Rect;
+import android.graphics.Region.Op;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.util.AttributeSet;
@@ -32,9 +34,12 @@ import android.view.accessibility.AccessibilityNodeInfo;
import com.android.internal.R;
public abstract class AbsSeekBar extends ProgressBar {
+ private final Rect mTempRect = new Rect();
+
private Drawable mThumb;
private int mThumbOffset;
-
+ private boolean mSplitTrack;
+
/**
* On touch, this offset plus the scaled value from the position of the
* touch will form the progress value. Usually 0.
@@ -51,10 +56,10 @@ public abstract class AbsSeekBar extends ProgressBar {
* progress.
*/
private int mKeyProgressIncrement = 1;
-
+
private static final int NO_ALPHA = 0xFF;
private float mDisabledAlpha;
-
+
private int mScaledTouchSlop;
private float mTouchDownX;
private boolean mIsDragging;
@@ -76,12 +81,16 @@ public abstract class AbsSeekBar extends ProgressBar {
TypedArray a = context.obtainStyledAttributes(
attrs, com.android.internal.R.styleable.SeekBar, defStyleAttr, defStyleRes);
- Drawable thumb = a.getDrawable(com.android.internal.R.styleable.SeekBar_thumb);
- setThumb(thumb); // will guess mThumbOffset if thumb != null...
- // ...but allow layout to override this
- int thumbOffset = a.getDimensionPixelOffset(
+
+ final Drawable thumb = a.getDrawable(com.android.internal.R.styleable.SeekBar_thumb);
+ setThumb(thumb);
+
+ // Guess thumb offset if thumb != null, but allow layout to override.
+ final int thumbOffset = a.getDimensionPixelOffset(
com.android.internal.R.styleable.SeekBar_thumbOffset, getThumbOffset());
setThumbOffset(thumbOffset);
+
+ mSplitTrack = a.getBoolean(com.android.internal.R.styleable.SeekBar_splitTrack, false);
a.recycle();
a = context.obtainStyledAttributes(attrs,
@@ -97,7 +106,7 @@ public abstract class AbsSeekBar extends ProgressBar {
* <p>
* If the thumb is a valid drawable (i.e. not null), half its width will be
* used as the new thumb offset (@see #setThumbOffset(int)).
- *
+ *
* @param thumb Drawable representing the thumb
*/
public void setThumb(Drawable thumb) {
@@ -132,7 +141,7 @@ public abstract class AbsSeekBar extends ProgressBar {
mThumb = thumb;
invalidate();
if (needUpdate) {
- updateThumbPos(getWidth(), getHeight());
+ updateThumbAndTrackPos(getWidth(), getHeight());
if (thumb != null && thumb.isStateful()) {
// Note that if the states are different this won't work.
// For now, let's consider that an app bug.
@@ -162,7 +171,7 @@ public abstract class AbsSeekBar extends ProgressBar {
/**
* Sets the thumb offset that allows the thumb to extend out of the range of
* the track.
- *
+ *
* @param thumbOffset The offset amount in pixels.
*/
public void setThumbOffset(int thumbOffset) {
@@ -171,8 +180,27 @@ public abstract class AbsSeekBar extends ProgressBar {
}
/**
+ * Specifies whether the track should be split by the thumb. When true,
+ * the thumb's optical bounds will be clipped out of the track drawable,
+ * then the thumb will be drawn into the resulting gap.
+ *
+ * @param splitTrack Whether the track should be split by the thumb
+ */
+ public void setSplitTrack(boolean splitTrack) {
+ mSplitTrack = splitTrack;
+ invalidate();
+ }
+
+ /**
+ * Returns whether the track should be split by the thumb.
+ */
+ public boolean getSplitTrack() {
+ return mSplitTrack;
+ }
+
+ /**
* Sets the amount of progress changed via the arrow keys.
- *
+ *
* @param increment The amount to increment or decrement when the user
* presses the arrow keys.
*/
@@ -184,14 +212,14 @@ public abstract class AbsSeekBar extends ProgressBar {
* Returns the amount of progress changed via the arrow keys.
* <p>
* By default, this will be a value that is derived from the max progress.
- *
+ *
* @return The amount to increment or decrement when the user presses the
* arrow keys. This will be positive.
*/
public int getKeyProgressIncrement() {
return mKeyProgressIncrement;
}
-
+
@Override
public synchronized void setMax(int max) {
super.setMax(max);
@@ -217,79 +245,85 @@ public abstract class AbsSeekBar extends ProgressBar {
@Override
protected void drawableStateChanged() {
super.drawableStateChanged();
-
- Drawable progressDrawable = getProgressDrawable();
+
+ final Drawable progressDrawable = getProgressDrawable();
if (progressDrawable != null) {
progressDrawable.setAlpha(isEnabled() ? NO_ALPHA : (int) (NO_ALPHA * mDisabledAlpha));
}
-
- if (mThumb != null && mThumb.isStateful()) {
- int[] state = getDrawableState();
- mThumb.setState(state);
+
+ final Drawable thumb = mThumb;
+ if (thumb != null && thumb.isStateful()) {
+ thumb.setState(getDrawableState());
}
}
-
+
@Override
void onProgressRefresh(float scale, boolean fromUser) {
super.onProgressRefresh(scale, fromUser);
- Drawable thumb = mThumb;
+
+ final Drawable thumb = mThumb;
if (thumb != null) {
setThumbPos(getWidth(), thumb, scale, Integer.MIN_VALUE);
- /*
- * Since we draw translated, the drawable's bounds that it signals
- * for invalidation won't be the actual bounds we want invalidated,
- * so just invalidate this whole view.
- */
+
+ // Since we draw translated, the drawable's bounds that it signals
+ // for invalidation won't be the actual bounds we want invalidated,
+ // so just invalidate this whole view.
invalidate();
}
}
-
-
+
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
- updateThumbPos(w, h);
+
+ updateThumbAndTrackPos(w, h);
}
- private void updateThumbPos(int w, int h) {
- Drawable d = getCurrentDrawable();
- Drawable thumb = mThumb;
- int thumbHeight = thumb == null ? 0 : thumb.getIntrinsicHeight();
+ private void updateThumbAndTrackPos(int w, int h) {
+ final Drawable track = getCurrentDrawable();
+ final Drawable thumb = mThumb;
+
// The max height does not incorporate padding, whereas the height
- // parameter does
- int trackHeight = Math.min(mMaxHeight, h - mPaddingTop - mPaddingBottom);
-
- int max = getMax();
- float scale = max > 0 ? (float) getProgress() / (float) max : 0;
-
+ // parameter does.
+ final int trackHeight = Math.min(mMaxHeight, h - mPaddingTop - mPaddingBottom);
+ final int thumbHeight = thumb == null ? 0 : thumb.getIntrinsicHeight();
+
+ // Apply offset to whichever item is taller.
+ final int trackOffset;
+ final int thumbOffset;
if (thumbHeight > trackHeight) {
- if (thumb != null) {
- setThumbPos(w, thumb, scale, 0);
- }
- int gapForCenteringTrack = (thumbHeight - trackHeight) / 2;
- if (d != null) {
- // Canvas will be translated by the padding, so 0,0 is where we start drawing
- d.setBounds(0, gapForCenteringTrack,
- w - mPaddingRight - mPaddingLeft, h - mPaddingBottom - gapForCenteringTrack
- - mPaddingTop);
- }
+ trackOffset = (thumbHeight - trackHeight) / 2;
+ thumbOffset = 0;
} else {
- if (d != null) {
- // Canvas will be translated by the padding, so 0,0 is where we start drawing
- d.setBounds(0, 0, w - mPaddingRight - mPaddingLeft, h - mPaddingBottom
- - mPaddingTop);
- }
- int gap = (trackHeight - thumbHeight) / 2;
- if (thumb != null) {
- setThumbPos(w, thumb, scale, gap);
- }
+ trackOffset = 0;
+ thumbOffset = (trackHeight - thumbHeight) / 2;
+ }
+
+ if (track != null) {
+ track.setBounds(0, trackOffset, w - mPaddingRight - mPaddingLeft,
+ h - mPaddingBottom - trackOffset - mPaddingTop);
+ }
+
+ if (thumb != null) {
+ setThumbPos(w, thumb, getScale(), thumbOffset);
}
}
+ private float getScale() {
+ final int max = getMax();
+ return max > 0 ? getProgress() / (float) max : 0;
+ }
+
/**
- * @param gap If set to {@link Integer#MIN_VALUE}, this will be ignored and
+ * Updates the thumb drawable bounds.
+ *
+ * @param w Width of the view, including padding
+ * @param thumb Drawable used for the thumb
+ * @param scale Current progress between 0 and 1
+ * @param offset Vertical offset for centering. If set to
+ * {@link Integer#MIN_VALUE}, the current offset will be used.
*/
- private void setThumbPos(int w, Drawable thumb, float scale, int gap) {
+ private void setThumbPos(int w, Drawable thumb, float scale, int offset) {
int available = w - mPaddingLeft - mPaddingRight;
final int thumbWidth = thumb.getIntrinsicWidth();
final int thumbHeight = thumb.getIntrinsicHeight();
@@ -301,13 +335,13 @@ public abstract class AbsSeekBar extends ProgressBar {
final int thumbPos = (int) (scale * available + 0.5f);
final int top, bottom;
- if (gap == Integer.MIN_VALUE) {
+ if (offset == Integer.MIN_VALUE) {
final Rect oldBounds = thumb.getBounds();
top = oldBounds.top;
bottom = oldBounds.bottom;
} else {
- top = gap;
- bottom = gap + thumbHeight;
+ top = offset;
+ bottom = offset + thumbHeight;
}
final int left = (isLayoutRtl() && mMirrorForRtl) ? available - thumbPos : thumbPos;
@@ -342,6 +376,33 @@ public abstract class AbsSeekBar extends ProgressBar {
protected synchronized void onDraw(Canvas canvas) {
super.onDraw(canvas);
+ drawThumb(canvas);
+ }
+
+ @Override
+ void drawTrack(Canvas canvas) {
+ final Drawable thumbDrawable = mThumb;
+ if (thumbDrawable != null && mSplitTrack) {
+ final Insets insets = thumbDrawable.getOpticalInsets();
+ final Rect tempRect = mTempRect;
+ thumbDrawable.copyBounds(tempRect);
+ tempRect.offset(mPaddingLeft - mThumbOffset, mPaddingTop);
+ tempRect.left += insets.left;
+ tempRect.right -= insets.right;
+
+ final int saveCount = canvas.save();
+ canvas.clipRect(tempRect, Op.DIFFERENCE);
+ super.drawTrack(canvas);
+ canvas.restoreToCount(saveCount);
+ } else {
+ super.drawTrack(canvas);
+ }
+ }
+
+ /**
+ * Draw the thumb.
+ */
+ void drawThumb(Canvas canvas) {
if (mThumb != null) {
canvas.save();
// Translate the padding. For the x, we need to allow the thumb to
@@ -366,17 +427,17 @@ public abstract class AbsSeekBar extends ProgressBar {
}
dw += mPaddingLeft + mPaddingRight;
dh += mPaddingTop + mPaddingBottom;
-
+
setMeasuredDimension(resolveSizeAndState(dw, widthMeasureSpec, 0),
resolveSizeAndState(dh, heightMeasureSpec, 0));
}
-
+
@Override
public boolean onTouchEvent(MotionEvent event) {
if (!mIsUserSeekable || !isEnabled()) {
return false;
}
-
+
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
if (isInScrollingContainer()) {
@@ -391,7 +452,7 @@ public abstract class AbsSeekBar extends ProgressBar {
attemptClaimDrag();
}
break;
-
+
case MotionEvent.ACTION_MOVE:
if (mIsDragging) {
trackTouchEvent(event);
@@ -408,7 +469,7 @@ public abstract class AbsSeekBar extends ProgressBar {
}
}
break;
-
+
case MotionEvent.ACTION_UP:
if (mIsDragging) {
trackTouchEvent(event);
@@ -426,7 +487,7 @@ public abstract class AbsSeekBar extends ProgressBar {
// value has not apparently changed)
invalidate();
break;
-
+
case MotionEvent.ACTION_CANCEL:
if (mIsDragging) {
onStopTrackingTouch();
@@ -493,7 +554,7 @@ public abstract class AbsSeekBar extends ProgressBar {
mParent.requestDisallowInterceptTouchEvent(true);
}
}
-
+
/**
* This is called when the user has started touching this widget.
*/
@@ -526,7 +587,7 @@ public abstract class AbsSeekBar extends ProgressBar {
setProgress(progress - mKeyProgressIncrement, true);
onKeyChange();
return true;
-
+
case KeyEvent.KEYCODE_DPAD_RIGHT:
if (progress >= getMax()) break;
setProgress(progress + mKeyProgressIncrement, true);
@@ -595,17 +656,13 @@ public abstract class AbsSeekBar extends ProgressBar {
public void onRtlPropertiesChanged(int layoutDirection) {
super.onRtlPropertiesChanged(layoutDirection);
- int max = getMax();
- float scale = max > 0 ? (float) getProgress() / (float) max : 0;
-
- Drawable thumb = mThumb;
+ final Drawable thumb = mThumb;
if (thumb != null) {
- setThumbPos(getWidth(), thumb, scale, Integer.MIN_VALUE);
- /*
- * Since we draw translated, the drawable's bounds that it signals
- * for invalidation won't be the actual bounds we want invalidated,
- * so just invalidate this whole view.
- */
+ setThumbPos(getWidth(), thumb, getScale(), Integer.MIN_VALUE);
+
+ // Since we draw translated, the drawable's bounds that it signals
+ // for invalidation won't be the actual bounds we want invalidated,
+ // so just invalidate this whole view.
invalidate();
}
}
diff --git a/core/java/android/widget/ProgressBar.java b/core/java/android/widget/ProgressBar.java
index f7e81b8..0c3715d 100644
--- a/core/java/android/widget/ProgressBar.java
+++ b/core/java/android/widget/ProgressBar.java
@@ -1066,21 +1066,30 @@ public class ProgressBar extends View {
protected synchronized void onDraw(Canvas canvas) {
super.onDraw(canvas);
- Drawable d = mCurrentDrawable;
+ drawTrack(canvas);
+ }
+
+ /**
+ * Draws the progress bar track.
+ */
+ void drawTrack(Canvas canvas) {
+ final Drawable d = mCurrentDrawable;
if (d != null) {
// Translate canvas so a indeterminate circular progress bar with padding
// rotates properly in its animation
- canvas.save();
+ final int saveCount = canvas.save();
+
if(isLayoutRtl() && mMirrorForRtl) {
canvas.translate(getWidth() - mPaddingRight, mPaddingTop);
canvas.scale(-1.0f, 1.0f);
} else {
canvas.translate(mPaddingLeft, mPaddingTop);
}
- long time = getDrawingTime();
+
+ final long time = getDrawingTime();
if (mHasAnimation) {
mAnimation.getTransformation(time, mTransformation);
- float scale = mTransformation.getAlpha();
+ final float scale = mTransformation.getAlpha();
try {
mInDrawing = true;
d.setLevel((int) (scale * MAX_LEVEL));
@@ -1089,8 +1098,10 @@ public class ProgressBar extends View {
}
postInvalidateOnAnimation();
}
+
d.draw(canvas);
- canvas.restore();
+ canvas.restoreToCount(saveCount);
+
if (mShouldStartAnimationDrawable && d instanceof Animatable) {
((Animatable) d).start();
mShouldStartAnimationDrawable = false;
diff --git a/core/java/android/widget/Switch.java b/core/java/android/widget/Switch.java
index 08af4de..438e164 100644
--- a/core/java/android/widget/Switch.java
+++ b/core/java/android/widget/Switch.java
@@ -22,9 +22,11 @@ import android.content.res.ColorStateList;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Canvas;
+import android.graphics.Insets;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Typeface;
+import android.graphics.Region.Op;
import android.graphics.drawable.Drawable;
import android.text.Layout;
import android.text.StaticLayout;
@@ -85,6 +87,7 @@ public class Switch extends CompoundButton {
private int mThumbTextPadding;
private int mSwitchMinWidth;
private int mSwitchPadding;
+ private boolean mSplitTrack;
private CharSequence mTextOn;
private CharSequence mTextOff;
@@ -174,13 +177,13 @@ public class Switch extends CompoundButton {
super(context, attrs, defStyleAttr, defStyleRes);
mTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
- Resources res = getResources();
+
+ final Resources res = getResources();
mTextPaint.density = res.getDisplayMetrics().density;
mTextPaint.setCompatibilityScaling(res.getCompatibilityInfo().applicationScale);
final TypedArray a = context.obtainStyledAttributes(
attrs, com.android.internal.R.styleable.Switch, defStyleAttr, defStyleRes);
-
mThumbDrawable = a.getDrawable(com.android.internal.R.styleable.Switch_thumb);
mTrackDrawable = a.getDrawable(com.android.internal.R.styleable.Switch_track);
mTextOn = a.getText(com.android.internal.R.styleable.Switch_textOn);
@@ -191,15 +194,16 @@ public class Switch extends CompoundButton {
com.android.internal.R.styleable.Switch_switchMinWidth, 0);
mSwitchPadding = a.getDimensionPixelSize(
com.android.internal.R.styleable.Switch_switchPadding, 0);
+ mSplitTrack = a.getBoolean(com.android.internal.R.styleable.Switch_splitTrack, false);
- int appearance = a.getResourceId(
+ final int appearance = a.getResourceId(
com.android.internal.R.styleable.Switch_switchTextAppearance, 0);
if (appearance != 0) {
setSwitchTextAppearance(context, appearance);
}
a.recycle();
- ViewConfiguration config = ViewConfiguration.get(context);
+ final ViewConfiguration config = ViewConfiguration.get(context);
mTouchSlop = config.getScaledTouchSlop();
mMinFlingVelocity = config.getScaledMinimumFlingVelocity();
@@ -469,6 +473,29 @@ public class Switch extends CompoundButton {
}
/**
+ * Specifies whether the track should be split by the thumb. When true,
+ * the thumb's optical bounds will be clipped out of the track drawable,
+ * then the thumb will be drawn into the resulting gap.
+ *
+ * @param splitTrack Whether the track should be split by the thumb
+ *
+ * @attr ref android.R.styleable#Switch_splitTrack
+ */
+ public void setSplitTrack(boolean splitTrack) {
+ mSplitTrack = splitTrack;
+ invalidate();
+ }
+
+ /**
+ * Returns whether the track should be split by the thumb.
+ *
+ * @attr ref android.R.styleable#Switch_splitTrack
+ */
+ public boolean getSplitTrack() {
+ return mSplitTrack;
+ }
+
+ /**
* Returns the text displayed when the button is in the checked state.
*
* @attr ref android.R.styleable#Switch_textOn
@@ -518,13 +545,15 @@ public class Switch extends CompoundButton {
mTrackDrawable.getPadding(mTempRect);
- final int maxTextWidth = Math.max(mOnLayout.getWidth(), mOffLayout.getWidth());
+ final int maxTextWidth = Math.max(mOnLayout.getWidth(), mOffLayout.getWidth())
+ + mThumbTextPadding * 2;
+ mThumbWidth = Math.max(maxTextWidth, mThumbDrawable.getIntrinsicWidth());
+
final int switchWidth = Math.max(mSwitchMinWidth,
- maxTextWidth * 2 + mThumbTextPadding * 4 + mTempRect.left + mTempRect.right);
+ 2 * mThumbWidth + mTempRect.left + mTempRect.right);
final int switchHeight = Math.max(mTrackDrawable.getIntrinsicHeight(),
mThumbDrawable.getIntrinsicHeight());
- mThumbWidth = maxTextWidth + mThumbTextPadding * 2;
mSwitchWidth = switchWidth;
mSwitchHeight = switchHeight;
@@ -777,7 +806,7 @@ public class Switch extends CompoundButton {
final Drawable trackDrawable = mTrackDrawable;
final Drawable thumbDrawable = mThumbDrawable;
- // Draw the switch
+ // Layout the track.
final int switchLeft = mSwitchLeft;
final int switchTop = mSwitchTop;
final int switchRight = mSwitchRight;
@@ -793,9 +822,10 @@ public class Switch extends CompoundButton {
// Relies on mTempRect, MUST be called first!
final int thumbPos = getThumbOffset();
+ // Layout the thumb.
thumbDrawable.getPadding(tempRect);
- int thumbLeft = switchInnerLeft - tempRect.left + thumbPos;
- int thumbRight = switchInnerLeft + thumbPos + mThumbWidth + tempRect.right;
+ final int thumbLeft = switchInnerLeft - tempRect.left + thumbPos;
+ final int thumbRight = switchInnerLeft + thumbPos + mThumbWidth + tempRect.right;
thumbDrawable.setBounds(thumbLeft, switchTop, thumbRight, switchBottom);
final Drawable background = getBackground();
@@ -805,20 +835,32 @@ public class Switch extends CompoundButton {
super.onDraw(canvas);
- trackDrawable.draw(canvas);
+ if (mSplitTrack) {
+ final Insets insets = thumbDrawable.getOpticalInsets();
+ thumbDrawable.copyBounds(tempRect);
+ tempRect.left += insets.left;
+ tempRect.right -= insets.right;
+
+ final int saveCount = canvas.save();
+ canvas.clipRect(tempRect, Op.DIFFERENCE);
+ trackDrawable.draw(canvas);
+ canvas.restoreToCount(saveCount);
+ } else {
+ trackDrawable.draw(canvas);
+ }
final int saveCount = canvas.save();
canvas.clipRect(switchInnerLeft, switchTop, switchInnerRight, switchBottom);
thumbDrawable.draw(canvas);
- final int drawableState[] = getDrawableState();
- if (mTextColors != null) {
- mTextPaint.setColor(mTextColors.getColorForState(drawableState, 0));
- }
- mTextPaint.drawableState = drawableState;
-
final Layout switchText = getTargetCheckedState() ? mOnLayout : mOffLayout;
if (switchText != null) {
+ final int drawableState[] = getDrawableState();
+ if (mTextColors != null) {
+ mTextPaint.setColor(mTextColors.getColorForState(drawableState, 0));
+ }
+ mTextPaint.drawableState = drawableState;
+
final int left = (thumbLeft + thumbRight) / 2 - switchText.getWidth() / 2;
final int top = (switchInnerTop + switchInnerBottom) / 2 - switchText.getHeight() / 2;
canvas.translate(left, top);
@@ -889,12 +931,16 @@ public class Switch extends CompoundButton {
protected void drawableStateChanged() {
super.drawableStateChanged();
- int[] myDrawableState = getDrawableState();
+ final int[] myDrawableState = getDrawableState();
+
+ if (mThumbDrawable != null && mThumbDrawable.setState(myDrawableState)) {
+ // Handle changes to thumb width and height.
+ requestLayout();
+ }
- // Set the state of the Drawable
- // Drawable may be null when checked state is set from XML, from super constructor
- if (mThumbDrawable != null) mThumbDrawable.setState(myDrawableState);
- if (mTrackDrawable != null) mTrackDrawable.setState(myDrawableState);
+ if (mTrackDrawable != null) {
+ mTrackDrawable.setState(myDrawableState);
+ }
invalidate();
}
diff --git a/core/res/res/drawable-hdpi/scrubber_control_off_qntm_alpha.png b/core/res/res/drawable-hdpi/scrubber_control_off_qntm_alpha.png
index f1023ea..5a99528 100644
--- a/core/res/res/drawable-hdpi/scrubber_control_off_qntm_alpha.png
+++ b/core/res/res/drawable-hdpi/scrubber_control_off_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/scrubber_control_on_qntm_alpha.png b/core/res/res/drawable-hdpi/scrubber_control_on_qntm_alpha.png
index 15ceeee..79de664 100644
--- a/core/res/res/drawable-hdpi/scrubber_control_on_qntm_alpha.png
+++ b/core/res/res/drawable-hdpi/scrubber_control_on_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/switch_off_qntm_alpha.9.png b/core/res/res/drawable-hdpi/switch_off_qntm_alpha.9.png
index 90b1498..73e8f1c 100644
--- a/core/res/res/drawable-hdpi/switch_off_qntm_alpha.9.png
+++ b/core/res/res/drawable-hdpi/switch_off_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/switch_on_qntm_alpha.9.png b/core/res/res/drawable-hdpi/switch_on_qntm_alpha.9.png
index b535758..ff6affe 100644
--- a/core/res/res/drawable-hdpi/switch_on_qntm_alpha.9.png
+++ b/core/res/res/drawable-hdpi/switch_on_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/scrubber_control_off_qntm_alpha.png b/core/res/res/drawable-mdpi/scrubber_control_off_qntm_alpha.png
index 1833704..e40cba8 100644
--- a/core/res/res/drawable-mdpi/scrubber_control_off_qntm_alpha.png
+++ b/core/res/res/drawable-mdpi/scrubber_control_off_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/scrubber_control_on_qntm_alpha.png b/core/res/res/drawable-mdpi/scrubber_control_on_qntm_alpha.png
index e64d3f2..437a3e3 100644
--- a/core/res/res/drawable-mdpi/scrubber_control_on_qntm_alpha.png
+++ b/core/res/res/drawable-mdpi/scrubber_control_on_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/switch_off_qntm_alpha.9.png b/core/res/res/drawable-mdpi/switch_off_qntm_alpha.9.png
index ffd6c39..8949b52 100644
--- a/core/res/res/drawable-mdpi/switch_off_qntm_alpha.9.png
+++ b/core/res/res/drawable-mdpi/switch_off_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/switch_on_qntm_alpha.9.png b/core/res/res/drawable-mdpi/switch_on_qntm_alpha.9.png
index 15faff0..d727683 100644
--- a/core/res/res/drawable-mdpi/switch_on_qntm_alpha.9.png
+++ b/core/res/res/drawable-mdpi/switch_on_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/scrubber_control_off_qntm_alpha.png b/core/res/res/drawable-xhdpi/scrubber_control_off_qntm_alpha.png
index ad72f06..729e0bf 100644
--- a/core/res/res/drawable-xhdpi/scrubber_control_off_qntm_alpha.png
+++ b/core/res/res/drawable-xhdpi/scrubber_control_off_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/scrubber_control_on_qntm_alpha.png b/core/res/res/drawable-xhdpi/scrubber_control_on_qntm_alpha.png
index 7aceed1..d018a7c 100644
--- a/core/res/res/drawable-xhdpi/scrubber_control_on_qntm_alpha.png
+++ b/core/res/res/drawable-xhdpi/scrubber_control_on_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/switch_off_qntm_alpha.9.png b/core/res/res/drawable-xhdpi/switch_off_qntm_alpha.9.png
index 309b528..a7a972c 100644
--- a/core/res/res/drawable-xhdpi/switch_off_qntm_alpha.9.png
+++ b/core/res/res/drawable-xhdpi/switch_off_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/switch_on_qntm_alpha.9.png b/core/res/res/drawable-xhdpi/switch_on_qntm_alpha.9.png
index 139795e..dd8910b 100644
--- a/core/res/res/drawable-xhdpi/switch_on_qntm_alpha.9.png
+++ b/core/res/res/drawable-xhdpi/switch_on_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/scrubber_control_off_qntm_alpha.png b/core/res/res/drawable-xxhdpi/scrubber_control_off_qntm_alpha.png
index c11b0ae..a2b5716 100644
--- a/core/res/res/drawable-xxhdpi/scrubber_control_off_qntm_alpha.png
+++ b/core/res/res/drawable-xxhdpi/scrubber_control_off_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/scrubber_control_on_qntm_alpha.png b/core/res/res/drawable-xxhdpi/scrubber_control_on_qntm_alpha.png
index cde797e..caabc2c 100644
--- a/core/res/res/drawable-xxhdpi/scrubber_control_on_qntm_alpha.png
+++ b/core/res/res/drawable-xxhdpi/scrubber_control_on_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/switch_off_qntm_alpha.9.png b/core/res/res/drawable-xxhdpi/switch_off_qntm_alpha.9.png
index 9e234af..8d79a13 100644
--- a/core/res/res/drawable-xxhdpi/switch_off_qntm_alpha.9.png
+++ b/core/res/res/drawable-xxhdpi/switch_off_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/switch_on_qntm_alpha.9.png b/core/res/res/drawable-xxhdpi/switch_on_qntm_alpha.9.png
index b371eab..e0e4ef9 100644
--- a/core/res/res/drawable-xxhdpi/switch_on_qntm_alpha.9.png
+++ b/core/res/res/drawable-xxhdpi/switch_on_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable/scrubber_progress_horizontal_quantum.xml b/core/res/res/drawable/scrubber_progress_horizontal_quantum.xml
index d172b05..f82fe7a 100644
--- a/core/res/res/drawable/scrubber_progress_horizontal_quantum.xml
+++ b/core/res/res/drawable/scrubber_progress_horizontal_quantum.xml
@@ -16,22 +16,26 @@
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_enabled="false">
- <bitmap android:src="@drawable/scrubber_track_qntm_alpha"
+ <nine-patch android:src="@drawable/scrubber_track_qntm_alpha"
android:tint="?attr/colorControlNormal" />
</item>
<item>
<layer-list>
<item android:id="@id/background">
- <bitmap android:src="@drawable/scrubber_track_qntm_alpha"
+ <nine-patch android:src="@drawable/scrubber_track_qntm_alpha"
android:tint="?attr/colorControlNormal" />
</item>
<item android:id="@id/secondaryProgress">
- <bitmap android:src="@drawable/scrubber_primary_qntm_alpha"
- android:tint="?attr/colorControlNormal" />
+ <scale android:scaleWidth="100%">
+ <nine-patch android:src="@drawable/scrubber_primary_qntm_alpha"
+ android:tint="?attr/colorControlNormal" />
+ </scale>
</item>
<item android:id="@id/progress">
- <bitmap android:src="@drawable/scrubber_primary_qntm_alpha"
- android:tint="?attr/colorControlActivated" />
+ <scale android:scaleWidth="100%">
+ <nine-patch android:src="@drawable/scrubber_primary_qntm_alpha"
+ android:tint="?attr/colorControlActivated" />
+ </scale>
</item>
</layer-list>
</item>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 7a6832e..cedb92d 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -3343,6 +3343,8 @@
<attr name="thumb" format="reference" />
<!-- An offset for the thumb that allows it to extend out of the range of the track. -->
<attr name="thumbOffset" format="dimension" />
+ <!-- Whether to split the track and leave a gap for the thumb drawable. -->
+ <attr name="splitTrack" format="boolean" />
</declare-styleable>
<declare-styleable name="StackView">
@@ -6393,6 +6395,8 @@
<attr name="switchMinWidth" format="dimension" />
<!-- Minimum space between the switch and caption text -->
<attr name="switchPadding" format="dimension" />
+ <!-- Whether to split the track and leave a gap for the thumb drawable. -->
+ <attr name="splitTrack" />
</declare-styleable>
<declare-styleable name="Pointer">
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index ecb22ae..dc5efea 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2169,6 +2169,7 @@
<public type="attr" name="toId" />
<public type="attr" name="fromId" />
<public type="attr" name="reversible" />
+ <public type="attr" name="splitTrack" />
<public-padding type="dimen" name="l_resource_pad" end="0x01050010" />
diff --git a/core/res/res/values/styles_quantum.xml b/core/res/res/values/styles_quantum.xml
index 88a2a9f..e693673 100644
--- a/core/res/res/values/styles_quantum.xml
+++ b/core/res/res/values/styles_quantum.xml
@@ -455,10 +455,10 @@ please see styles_device_defaults.xml.
<style name="Widget.Quantum.CompoundButton.Switch">
<item name="track">@drawable/switch_track_quantum</item>
<item name="thumb">@drawable/switch_inner_quantum</item>
+ <item name="splitTrack">true</item>
<item name="switchTextAppearance">@style/TextAppearance.Quantum.Widget.Switch</item>
<item name="textOn"></item>
<item name="textOff"></item>
- <item name="thumbTextPadding">12dip</item>
<item name="switchMinWidth">72dip</item>
<item name="switchPadding">16dip</item>
<item name="background">?attr/selectableItemBackground</item>
@@ -572,10 +572,8 @@ please see styles_device_defaults.xml.
<item name="indeterminateOnly">false</item>
<item name="progressDrawable">@drawable/scrubber_progress_horizontal_quantum</item>
<item name="indeterminateDrawable">@drawable/scrubber_progress_horizontal_quantum</item>
- <item name="minHeight">13dip</item>
- <item name="maxHeight">13dip</item>
<item name="thumb">@drawable/scrubber_control_selector_quantum</item>
- <item name="thumbOffset">16dip</item>
+ <item name="splitTrack">true</item>
<item name="focusable">true</item>
<item name="paddingStart">16dip</item>
<item name="paddingEnd">16dip</item>