由于开发中经常会用到滑动开关,但是Android自带的滑动开发滑动效果太难看,所以这里模仿了IOS的滑动效果自制了一个滑动开关.
"SwitchButton">
"sb_shadow_radius" format="reference|dimension" />
"sb_shadow_offset" format="reference|dimension" />
"sb_shadow_color" format="reference|color" />
"sb_uncheck_color" format="reference|color" />
"sb_checked_color" format="reference|color" />
"sb_border_width" format="reference|dimension" />
"sb_checkline_color" format="reference|color" />
"sb_checkline_width" format="reference|dimension" />
"sb_uncheckcircle_color" format="reference|color" />
"sb_uncheckcircle_width" format="reference|dimension" />
"sb_uncheckcircle_radius" format="reference|dimension" />
"sb_checked" format="reference|boolean" />
"sb_shadow_effect" format="reference|boolean" />
"sb_effect_duration" format="reference|integer" />
"sb_button_color" format="reference|color" />
"sb_show_indicator" format="reference|boolean" />
"sb_background" format="reference|color" />
"sb_enable_effect" format="reference|boolean" />
<per.stramchen.switchbuttondemo.SwitchButton
android:id="@+id/btn_voice_switch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
app:sb_background="#E8E9EB"
app:sb_checked_color="#65C065"
app:sb_show_indicator="false" />
switchButton.setOnCheckedChangeListener(
new SwitchButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(SwitchButton view, final boolean isChecked) {
}
});
实现思路其实很简单,我们可以将按钮的状态变换分为两种情况.
1.手动拖拽改变按钮位置.
2.点击使按钮自动滑动到另一端.
对于第一种情况的实现其实很容易,我们只需要用手指移动的距离来改变滑块的位置,以及背景色的深浅即可.当然这需要我们手动拦截View的touch事件.以下贴出关键代码.
fraction我们可以理解为变化率,就是手指划过的距离占整个控件的百分比,接下来我们利用fraction来计算出button的X坐标,下面的buttonMaxX-buttonMinX我们可以理解为SwitchButton的真实长度.然后我们利用argbEvaluator这样一个颜色估值器来拿到不同时刻的变化率的颜色值,将它赋给背景色.最后调用postInvalidate();来刷新UI,我们就可以达到用手滑的时候,颜色随之改变的效果了.
//……………………………………部分代码省略
case MotionEvent.ACTION_MOVE:{
//拖动按钮位置,同时改变对应的背景颜色
float fraction = eventX / getWidth();
//变化率
fraction = Math.max(0f, Math.min(1f, fraction));
//滑块的位置
viewState.buttonX = buttonMinX
+ (buttonMaxX - buttonMinX)
* fraction;
//背景色
viewState.checkStateColor = (int) argbEvaluator.evaluate(
fraction,
uncheckColor,
checkedColor);
postInvalidate();
}
//……………………………………部分代码省略
这个实现起来其实也很方便,我们只需要利用一个属性动画,即可解决问题.
那么第一步我们需要判断它是否是一个点击时间,由于我们拦截了整个touch事件,那么点击事件的判断需要我们自己来完成,我们可以用一次按下抬起的时间小于300ms来判断它是否是一次点击事件
if(System.currentTimeMillis() - touchDownTime <= 300){
//点击时间小于300ms,认为是点击操作
toggle();
}
如果是点击事件,我们就可以开启动画来让滑块自己滑动来.这里我们并没有使用ObjectAnimator,而是使用的是ValueAnimator,因为这样可以让我们在每一帧改变多个属性.下面展示关键代码.
实现方式,其实与上面也很类似,只不过这时候我们改变属性的时刻不是在touch的时候了,而且在ValueAnimator每一帧的回调里.同样是计算button的X坐标,背景色,以及变化半径.
@Override
//……………………………………部分代码省略
public void onAnimationUpdate(ValueAnimator animation) {
//……………………………………部分代码省略
viewState.buttonX = beforeState.buttonX
+ (afterState.buttonX - beforeState.buttonX) * value;
float fraction = (viewState.buttonX - buttonMinX) / (buttonMaxX - buttonMinX);
viewState.checkStateColor = (int) argbEvaluator.evaluate(
fraction,
uncheckColor,
checkedColor
);
viewState.radius = fraction * viewRadius;
);
postInvalidate();
//……………………………………部分代码省略
}
当然,真实场景要比理论稍微复杂一些,我们需要考虑一些特殊的情况,比如在自动滑动的时候,我们突然点击了滑块,我们该怎么处理.等等.这里就不详细展开了.读者可以阅读源码自行探索.
下面贴出源码以及demo地址,
https://github.com/stramChen/SwitchButton
如果任何疑问,请联系邮箱:[email protected]