此控件是一个开关组件
一个三项开关
可以滑动
可以点击
可以自定义背景颜色
费话少说
接下来是使用说明,(源码放在文章最后)
从布局开始
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@color/blue"
android:padding="20dp">
<com.z.proxy.androidtest.SwitchZ
android:id="@+id/switchz"
android:layout_width="120dp"
android:layout_height="40dp"
app:radian="25sp"
app:viewBgColor="#ffffff"
app:defaultCircleColor="#999999"
app:leftCircleColor="#Ea4a4a"
app:midCircleColor="#ffc600"
app:rightCircleColor="#239a1c"/>
</LinearLayout>
app:viewBgColor="#ffffff" app:defaultCircleColor="#999999" app:leftCircleColor="#Ea4a4a" app:midCircleColor="#ffc600" app:rightCircleColor="#239a1c"从上到下依次代表的意思:背景边角弧度,圆的默认颜色,左边圆选中的颜色,中间圆选中的颜色,右边圆选中的颜色
组件包含一个attrs文件,直接上传attrs的内容
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="switch_style">
<attr name="radian" format="dimension"/>
<attr name="viewBgColor" format="color"/>
<attr name="defaultCircleColor" format="color"/>
<attr name="leftCircleColor" format="color"/>
<attr name="midCircleColor" format="color"/>
<attr name="rightCircleColor" format="color"/>
</declare-styleable>
</resources>
然后就是牛逼的java代码了,(只是指java牛逼,我写的依然只能代表我是)/**
* 三项开关
* Created by zhangxiaohui on 2017/3/17.
*/
public class SwitchZ extends View {
private float viewWidth, viewHeight;
private Paint bgPaint;//背景画笔
private Paint circlePaint;//中间圆画笔
private Paint textPaint;//写文字画笔
private Paint imagePaint;//中间图片画笔
private Paint moveCirclePaint;//移动效果画笔
private Paint arrowPaint;//箭头画笔
private int bgColor = Color.parseColor("#ffffff");//背景颜色
private int textColor = Color.parseColor("#ffffff");//字体颜色
private String arrowColor = "#e0e0e0";//默认箭头颜色
private int normalColor = Color.parseColor("#999999");//未选中颜色
private int leftSelectColor = Color.parseColor("#Ea4a4a");//左边选中颜色
private int rightSelectColor = Color.parseColor("#239a1c");//右边选中颜色
private int midSelectColor = Color.parseColor("#ffc600");//中间选中颜色
private int circleColor = normalColor;//记录颜色
private float circleRadian = 0f;//背景的弧度
private float showCircleX = 0f;//当前界面显示的圆坐标X
private float showCircleY = 0f;//当前界面显示的圆坐标Y
private float showCircleRadian = 0f;//当前界面显示的圆的半径
private float moveCircleX = 0f;
private float moveCircleY = 0f;
private float moveCircleRadian = 0f;
private boolean isMove = false;
private SWITCHBG switchbg = SWITCHBG.RIGHT;
public SwitchZ(Context context) {
this(context, null);
}
public SwitchZ(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.switch_style);
circleRadian = a.getDimension(R.styleable.switch_style_radian, 70f);
bgColor = a.getColor(R.styleable.switch_style_viewBgColor,Color.parseColor("#ffffff"));
normalColor = a.getColor(R.styleable.switch_style_defaultCircleColor, Color.parseColor("#999999"));
leftSelectColor = a.getColor(R.styleable.switch_style_leftCircleColor, Color.parseColor("#Ea4a4a"));
midSelectColor = a.getColor(R.styleable.switch_style_midCircleColor, Color.parseColor("#ffc600"));
rightSelectColor = a.getColor(R.styleable.switch_style_rightCircleColor, Color.parseColor("#239a1c"));
a.recycle();
init();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Log.e("onDraw", "onDraw");
RectF rectF = new RectF(0, 0, viewWidth, viewHeight);
canvas.drawRoundRect(rectF, circleRadian, circleRadian, bgPaint);
setDefaultCircleBackgroundColor(SWITCHBG.MID, canvas);
setDefaultCircleBackgroundColor(SWITCHBG.LEFT, canvas);
setDefaultCircleBackgroundColor(SWITCHBG.RIGHT, canvas);
setCircleColor(switchbg);
canvas.drawCircle(showCircleX, showCircleY, showCircleRadian, circlePaint);//默认选中圆上色
float leftArrowX = (float) (viewWidth / 2.0 - (viewWidth / 2.0 * 2.0 / 6.0));
float leftArrowY = viewHeight / 2 + circlePaint.getTextSize();
float rightArrowX = (float) (viewWidth / 2.0 + (viewWidth / 2.0 / 5.0));
float rightArrowY = leftArrowY;
arrowPaint.setTextSize(viewHeight / 3);//arrowColor
if(switchbg == SWITCHBG.LEFT){
arrowPaint.setColor(leftSelectColor);
canvas.drawText("<", leftArrowX, leftArrowY, arrowPaint);
arrowPaint.setColor(Color.parseColor(arrowColor));
canvas.drawText(">", rightArrowX, rightArrowY, arrowPaint);
}else if(switchbg == SWITCHBG.RIGHT){
arrowPaint.setColor(rightSelectColor);
canvas.drawText(">", rightArrowX, rightArrowY, arrowPaint);
arrowPaint.setColor(Color.parseColor(arrowColor));
canvas.drawText("<", leftArrowX, leftArrowY, arrowPaint);
}else {
arrowPaint.setColor(Color.parseColor(arrowColor));
canvas.drawText("<", leftArrowX, leftArrowY, arrowPaint);
canvas.drawText(">", rightArrowX, rightArrowY, arrowPaint);
}
if (isMove) {
canvas.drawCircle(moveCircleX, moveCircleY, moveCircleRadian, moveCirclePaint);//移动的圆
}
textPaint.setTextSize(viewHeight / 3);
float leftTextX = viewWidth / 3 / 2 - textPaint.getTextSize() / 2;
float leftTextY = viewHeight / 2 + textPaint.getTextSize() / 3;
float rightTextX = viewWidth / 3 * 2 + (viewWidth - viewWidth / 3 * 2) / 2 - textPaint.getTextSize() / 2;
float rightTextY = leftTextY;
canvas.drawText("左", leftTextX, leftTextY, textPaint);
canvas.drawText("右", rightTextX, rightTextY, textPaint);
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.point_switch_m);
float imgX = viewWidth / 2 - bitmap.getWidth() / 2;// imagePaint.getTextSize() / 2
float imgY = viewHeight / 2 - bitmap.getHeight() / 2;
// int width = viewHeight / 3 * 2 / 3;
canvas.drawBitmap(bitmap, imgX, imgY, imagePaint);//zoomImg(bitmap, width, width)
}
public static Bitmap zoomImg(Bitmap bm, int newWidth, int newHeight) {
// 获得图片的宽高
int width = bm.getWidth();
int height = bm.getHeight();
// 计算缩放比例
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
// 取得想要缩放的matrix参数
Matrix matrix = new Matrix();
matrix.postScale(scaleWidth, scaleHeight);
// 得到新的图片
Bitmap newbm = Bitmap.createBitmap(bm, 0, 0, width, height, matrix, true);
return newbm;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
Log.e("onMeasure", "onMeasure");
viewWidth = getMeasuredWidth();
viewHeight = getMeasuredHeight();
/**画圆初始赋值*/
setCircleColor(SWITCHBG.MID);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
/**
* 设置非选中圆的默认背景
*
* @param switchbg
* @param canvas
*/
private void setDefaultCircleBackgroundColor(SWITCHBG switchbg, Canvas canvas) {
if (this.switchbg == switchbg) {
return;
}
circleColor = normalColor;
circlePaint.setColor(circleColor);
switch (switchbg) {
case LEFT:
setCircleSize(SWITCHBG.LEFT);
break;
case MID:
setCircleSize(SWITCHBG.MID);
break;
case RIGHT:
setCircleSize(SWITCHBG.RIGHT);
break;
}
canvas.drawCircle(showCircleX, showCircleY, showCircleRadian, circlePaint);//中间圆
}
private void setCircleColor(SWITCHBG switchbg) {
switch (switchbg) {
case LEFT:
setCircleSize(SWITCHBG.LEFT);
circleColor = leftSelectColor;
break;
case MID:
setCircleSize(SWITCHBG.MID);
circleColor = midSelectColor;
break;
case RIGHT:
setCircleSize(SWITCHBG.RIGHT);
circleColor = rightSelectColor;
break;
}
circlePaint.setColor(circleColor);
moveCirclePaint.setColor(circleColor);
}
/**
* 设置圆大小及位置
*
* @param switchbg
*/
private void setCircleSize(SWITCHBG switchbg) {
switch (switchbg) {
case LEFT:
showCircleX = viewWidth / 3 / 2;
showCircleY = viewHeight / 2;
showCircleRadian = viewHeight / 3;
break;
case MID:
float sideCircleCenter = viewHeight / 3;
float midCircleCenter = sideCircleCenter * 2 / 3;
showCircleX = viewWidth / 2;
showCircleY = viewHeight / 2;
showCircleRadian = midCircleCenter;
break;
case RIGHT:
showCircleX = viewWidth / 3 * 2 + (viewWidth - (viewWidth / 3 * 2)) / 2;
showCircleY = viewHeight / 2;
showCircleRadian = viewHeight / 3;
break;
}
}
float downX;
float downY;
float upX;
float upY;
boolean outsideStart = false;
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
isMove = false;
outsideStart = false;
downX = event.getX();
downY = event.getY();
moveCircleY = viewHeight / 2;
if (upX <= viewWidth / 3 && upX > 0 && upY <= viewHeight && upY > 0) {
// moveCircleX = viewWidth / 3 / 2;
moveCircleRadian = viewHeight / 3;
} else if (upX > viewWidth / 3 && upX < viewWidth * 2 / 3 && upY > 0 && upY < viewHeight) {
// moveCircleX = viewWidth / 2;
moveCircleRadian = viewHeight / 3 * 2 / 3;
} else if (upX > viewWidth * 2 / 3 && upX < viewWidth && upY > 0 && upY < viewHeight) {
// moveCircleX = viewWidth - viewHeight / 2;
moveCircleRadian = viewHeight / 3;
}
break;
case MotionEvent.ACTION_MOVE:
isMove = true;
outsideStart = false;
upX = event.getX();
upY = event.getY();
if (downX < (showCircleX - showCircleRadian) || downX > (showCircleX + showCircleRadian)) {
outsideStart = true;
return true;
}
moveCircleX = event.getX();
invalidate();
break;
case MotionEvent.ACTION_UP:
isMove = false;
if (outsideStart) {
return true;
}
upX = event.getX();
upY = event.getY();
outsideStart = false;
if (upX <= viewWidth / 3 && upY <= viewHeight && upY > 0) {//左
showCircleX = viewWidth / 3 / 2;
showCircleY = viewHeight / 2;
showCircleRadian = viewHeight / 3;
switchbg = SWITCHBG.LEFT;
if (switchScrollListner != null) {
switchScrollListner.leftListner();
}
} else if (upX > viewWidth / 3 && upX < viewWidth * 2 / 3 && upY > 0 && upY < viewHeight) {//中
showCircleX = viewWidth / 2;
showCircleY = viewHeight / 2;
showCircleRadian = viewHeight / 3 * 2 / 3;
switchbg = SWITCHBG.MID;
if (switchScrollListner != null) {
switchScrollListner.midListner();
}
} else if (upX > viewWidth * 2 / 3 && upX < viewWidth * 2 && upY > 0 && upY < viewHeight) {//右
showCircleX = viewWidth / 3 * 2 + (viewWidth - (viewWidth / 3 * 2)) / 2;
showCircleY = viewHeight / 2;
showCircleRadian = viewHeight / 3;
switchbg = SWITCHBG.RIGHT;
if (switchScrollListner != null) {
switchScrollListner.rightListner();
}
}
invalidate();
break;
}
return true;
}
private void init() {
bgPaint = new Paint();
bgPaint.setColor(bgColor);
bgPaint.setStyle(Paint.Style.FILL);
bgPaint.setAntiAlias(true);
circlePaint = new Paint();
circlePaint.setColor(circleColor);
circlePaint.setAntiAlias(true);
moveCirclePaint = new Paint();
moveCirclePaint.setColor(circleColor);
moveCirclePaint.setStyle(Paint.Style.FILL);
moveCirclePaint.setAntiAlias(true);
arrowPaint = new Paint();
arrowPaint.setColor(circleColor);
arrowPaint.setStyle(Paint.Style.FILL);
Typeface font = Typeface.create(Typeface.SANS_SERIF, Typeface.BOLD);
arrowPaint.setTypeface(font);
arrowPaint.setAntiAlias(true);
textPaint = new Paint();
textPaint.setColor(textColor);
textPaint.setStyle(Paint.Style.FILL);
textPaint.setStrokeWidth(1f);
textPaint.setAntiAlias(true);
imagePaint = new Paint();
imagePaint.setStyle(Paint.Style.FILL);
imagePaint.setStrokeWidth(1f);
imagePaint.setAntiAlias(true);
}
/**
* 设置默认选中值
* @param switchbg
*/
public void switchLeftOn(SWITCHBG switchbg) {
this.switchbg = switchbg;
}
/**
* 更新开关状态
* @param switchbg
*/
public void updateSwitchState(SWITCHBG switchbg){
this.switchbg = switchbg;
invalidate();
}
public enum SWITCHBG {
LEFT, MID, RIGHT
}
/**
* 三个点击事件回调
*/
public interface SwitchScrollListner {
void leftListner();
void midListner();
void rightListner();
}
SwitchScrollListner switchScrollListner;
public void setSwitchScrollListner(SwitchScrollListner switchScrollListner) {
this.switchScrollListner = switchScrollListner;
}
}
在外部调用的时候可以用SwitchScrollListner
来进行自定义操作欢迎各位童鞋提出宝贵意见