图片预览
1. 分析
1. 开关按钮这个可以考虑用两个图片来实现
2. 一个背景图片,一个开关图片
3. 通过手势移动切换开关状态 换图
4. 然后做动画处理
5. 当然可以完全自定义 画两个圆角矩形 切换的时候重绘控件
2. 实现原理
1. 需要实现onMeasure处理控件宽高为wrap_content时的宽高
2. 考虑用图片做开关背景还是完全自定义,加一个字段区分
3. 在onTouchEvent中处理开关事件
4. 动画处理
3. 初始化一些东西 初始化一般我放在onSizeChanged方法中
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mViewX = w;
mViewY = h;
//计算开关按钮的偏移量
mToggleOffsetX = -mViewX / 2 + dp2px(1);
if(mToggleType == 1){
Resources resources = getResources();
Drawable closeDrawable = resources.getDrawable(mToggleCloseBackGroundImg);
mCloseBgBitmap = drawableToBitmap(closeDrawable, w, h);
Drawable openDrawable = resources.getDrawable(mToggleOpenBackGroundImg);
mOpenBgBitmap = drawableToBitmap(openDrawable, w, h);
Drawable leftDrawable = resources.getDrawable(mToggleSwitchImg);
mToggleBitmap = drawableToBitmap(leftDrawable, (int) (w * 0.5f), h - dp2px(2));
}
}
4. 绘制开关按钮
方式一:完全自定义 画圆角矩形
private void drawSwitchToggle1(Canvas canvas) {
//画背景圆角矩形
if(mToggleOffsetX == -mViewX / 2 + dp2px(1)){
mBackGroundPaint.setColor(mToggleCloseColor);
}else{
mBackGroundPaint.setColor(mToggleOpenColor);
}
mBgRectF.set(-mViewX / 2,-mViewY / 2,mViewX / 2,mViewY / 2);
canvas.drawRoundRect(mBgRectF,mToggleRoundRadius,mToggleRoundRadius,mBackGroundPaint);
//画开关按钮圆角矩形
mToggleRectF.set(mToggleOffsetX, -mViewY / 2 + dp2px(1), mToggleOffsetX + mViewX / 2, mViewY / 2 - dp2px(1));
canvas.drawRoundRect(mToggleRectF,mToggleRoundRadius,mToggleRoundRadius, mTogglePaint);
}
方式二:通过画背景图和开关图来回切换
private void drawSwitchToggle2(Canvas canvas) {
//画背景图
if(mToggleOffsetX == -mViewX / 2 + dp2px(1)) {
canvas.drawBitmap(mCloseBgBitmap, -mCloseBgBitmap.getWidth() / 2, -mCloseBgBitmap.getHeight() / 2, mTogglePaint);
}else{
canvas.drawBitmap(mOpenBgBitmap, -mCloseBgBitmap.getWidth() / 2, -mCloseBgBitmap.getHeight() / 2, mTogglePaint);
}
//画开关按钮图
canvas.drawBitmap(mToggleBitmap, mToggleOffsetX,-mCloseBgBitmap.getHeight() / 2 + dp2px(1), mTogglePaint);
}
5. 触摸事件onTouchEvent方法处理
@Override
public boolean onTouchEvent(MotionEvent event) {
float distanceY = 0f;
float startY = 0f;
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
mIsToggleMove = false;
mStartX = event.getX();
startY = event.getY();
break;
case MotionEvent.ACTION_MOVE:
float moveX = event.getX();
float moveY = event.getY();
mDistanceX = moveX - startY;
distanceY = moveY - startY;
if(Math.abs(mDistanceX) > Math.abs(distanceY) && Math.abs(mDistanceX) >= mViewX / 2){
mIsToggleMove = true;
}else{
mIsToggleMove = false;
}
mStartX = moveX;
break;
case MotionEvent.ACTION_UP:
if(mIsToggleMove){
if(mDistanceX < 0){
mToggleOffsetX = -mViewX / 2 + dp2px(1);
mLastX = -dp2px(1);
mCurrentX = (int) mToggleOffsetX;
}else{
mToggleOffsetX = 0 - dp2px(1);
mLastX = - mViewX / 2 + dp2px(1);
mCurrentX = (int) mToggleOffsetX;
}
setToggleAnimation();
return true;
}
break;
}
return super.onTouchEvent(event);
}
//点击事件处理
@Override
public void onClick(View view) {
Log.e("startX",mStartX+"");
//点击开关同一侧 不做处理
if((mToggleOffsetX == 0 - dp2px(1) && mStartX >= mViewX / 2)
|| (mToggleOffsetX == -mViewX / 2 + dp2px(1) && mStartX < mViewX / 2)){
return;
}
if(mStartX >= mViewX / 2){
mToggleOffsetX = 0 - dp2px(1);
mLastX = - mViewX / 2 + dp2px(1);
mCurrentX = (int) mToggleOffsetX;
}else {
mToggleOffsetX = -mViewX / 2 + dp2px(1);
mLastX = -dp2px(1);
mCurrentX = (int) mToggleOffsetX;
}
setToggleAnimation();
// invalidate();
}
6. 动画处理
//给按钮添加动画
public void setToggleAnimation(){
ValueAnimator toggleAnimator = ValueAnimator.ofFloat(mLastX, mCurrentX);
toggleAnimator.setDuration(DURATION);
toggleAnimator.setInterpolator(new AccelerateInterpolator());
toggleAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mToggleOffsetX = (float) animation.getAnimatedValue();
invalidate();
}
});
toggleAnimator.start();
}
7. 项目源代码下载
后面统一提供下载地址
8. 联系方式
QQ:1509815887