我们知道自定义控件是最直接的方式,但是我想要的其实就是原生的switch的功能,仅仅是样式不同,所以去造一个哪怕是简易的仿造都显得麻烦。
下面这个就是我们想要的样式,on的时候track是绿色,thumb是白色;off的时候track是白色,thumb是绿色。
常见的switch长成这个样子
简单地修改一下, 你会发现宽高的修改完全与switch无关,改的是整个控件的大小。
再修改一下,加上android:switchMinWidth, 把背景换一换,让白色的thumb明显一点
好,到这里你就开始发现所有的switch的attr中设置的可变的参数都影响不了thumb的宽度或者track的高度了,各种padding都是浮云, 内心撕裂[流泪]。
几乎就要放弃的时候去自己写控件的时候,突然想到这个图片本身带点空白不就好了吗?然而,我没有切图工具也不会切图。所以我自己画一个吧
顺便把字也加上
对于这个字怎么加也想了一会,要求textOn、textOff显示的内容是不一样的,原生的控件是有textOn和textOff属性,但是它们是在thumb上
@Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (mShowText) {
if (mOnLayout == null) {
mOnLayout = makeLayout(mTextOn);
}
if (mOffLayout == null) {
mOffLayout = makeLayout(mTextOff);
}
}
...
private Layout makeLayout(CharSequence text) {
final CharSequence transformed = (mSwitchTransformationMethod != null)
? mSwitchTransformationMethod.getTransformation(text, this)
: text;
int width = (int) Math.ceil(Layout.getDesiredWidth(transformed, 0,
transformed.length(), mTextPaint, getTextDirectionHeuristic()));
return new StaticLayout(transformed, mTextPaint, width,
Layout.Alignment.ALIGN_NORMAL, 1.f, 0, true);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
...
if (thumbDrawable != null) {
thumbDrawable.draw(canvas);
}
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 cX;
if (thumbDrawable != null) {
final Rect bounds = thumbDrawable.getBounds();
cX = bounds.left + bounds.right;
} else {
cX = getWidth();
}
final int left = cX / 2 - switchText.getWidth() / 2;
final int top = (switchInnerTop + switchInnerBottom) / 2 - switchText.getHeight() / 2;
canvas.translate(left, top);
switchText.draw(canvas);
}
canvas.restoreToCount(saveCount);
}
原生的switchText是在thumb上的呢,所以自食其力吧,写两textView。
最简单的实现
CompoundButton.OnCheckedChangeListener mSwitchTutorListener = new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
mTvSwitchOff.setVisibility(View.GONE);
mTvSwitchOn.setVisibility(View.VISIBLE);
} else {
mTvSwitchOff.setVisibility(View.VISIBLE);
mTvSwitchOn.setVisibility(View.GONE);
}
}
};
这个是最简单的实现,然后你会发现,这个字唰一下出现唰一下没有真是一点也不美好,加点渐变动画吧。
你肯定会想到alpha动画的fadein和fadeout吧,要写个animation?不用不用,可以用view的crossfade animation:https://developer.android.com/training/animation/reveal-or-hide-view
使用起来非常简单:
CompoundButton.OnCheckedChangeListener mSwitchTutorListener = new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
mTvSwitchOff.setVisibility(View.VISIBLE);
mTvSwitchOn.setVisibility(View.VISIBLE);
if (isChecked) {
mTvSwitchOff.animate().alpha(0f).setDuration(50).setListener(null);
mTvSwitchOn.animate().alpha(1f).setDuration(250).setListener(null);
} else {
mTvSwitchOff.animate().alpha(1f).setDuration(250).setListener(null);
mTvSwitchOn.animate().alpha(0f).setDuration(50).setListener(null);
}
}
};
这样我们就实现了渐变退出和进入啦,世界美好许多。
这个有个事情要注意的是,动画的终态如果是alpha等于0,下次你要再显示它记得把alpha值给设回来。我一开始就忘记了,Visibility半天没改回来一脸懵。