CheckBox

简介: 写一个带动画化效果的CheckBox,先看效果,我觉得这个尺寸是最好看的,画图板画出来的,有点丑啊。。003.png000.

写一个带动画化效果的CheckBox,先看效果,我觉得这个尺寸是最好看的,画图板画出来的,有点丑啊。。

003.png
000.gif

怎么用

<pre>
<org.alex.checkbox.CheckBox
xmlns:CheckBox="http://schemas.android.com/apk/res-auto"
android:id="@+id/cb"
android:layout_width="16dp"
android:layout_height="24dp"
android:layout_centerVertical="true"
android:layout_marginBottom="16dp"
android:layout_marginLeft="22dp"
android:paddingTop="12dp"
CheckBox:cb_canAnim="true"
CheckBox:cb_checkMarkWidth="2dp"
CheckBox:cb_checkMarkerDuration="200"
CheckBox:cb_innerCheckedColor="#FFFFFF"
CheckBox:cb_innerNormalColor="#FFFFFF"
CheckBox:cb_outBorderRadius="2dp"
CheckBox:cb_outBorderWidth="1.5dp"/>
</pre>

核心代码

<pre>
/**
* 作者:Alex
* 时间:2016/9/8 12:57
* 简述:
*/
public class CheckBox extends View {
/**
* 复选框 默认 大小
*/
private int defaultSize = 40;
/**
* 控件的 尺寸
*/
private int size;
/**
* 最外层的圆角矩形
*/
private RectF outBorderRectF;
/**
* 最外层的圆角矩形
*/
private Paint outBorderPaint;
/**
* 最外层 边框的 宽度
*/
private float outBorderWidth;
/**
* 最外层 边框的 颜色
*/
private int outBorderColor;
/**
* 外边框 圆角化 半径
*/
private float outBorderRadius;
/**
* 内置矩形框
*/
private RectF innerCheckedRectF;
/**
* 内置矩形框
*/
private Paint innerCheckedPaint;
/**
* 内置矩形框 颜色
*/
private int innerCheckedColor;
//
/**
* 内置矩形框
*/
private RectF innerNormalRectF;
/**
* 内置矩形框
*/
private Paint innerNormalPaint;
/**
* 内置矩形框 颜色
*/
private int innerNormalColor;
/**
* 对勾
*/
private Paint checkMarkPaint;
/**
* 对号的4个点的坐标
*/
private float[] pointArray;
/**
* 对勾的宽度
*/
private float checkMarkWidth;
/**
* 对勾的 颜色
*/
private int checkMarkColor;
private float checkMarkerProgress;
/**
* 选中
*/
private boolean isChecked;
/**
* 使用过渡动画
*/
private boolean canAnim;
/**
* 展示 对勾 需要的时间长度
*/
private int checkMarkerDuration;
private ObjectAnimator checkMarkerShowAnimator;
private ObjectAnimator checkMarkerDismissAnimator;
private OnCheckChangeListener onCheckChangeListener;
private static final String KEY_IS_CHECKED = "IS_CHECKED";
public CheckBox(Context context, AttributeSet attrs) {
super(context, attrs);
initView(attrs);
}
private void initView(AttributeSet attrs) {
/*外边框*/
outBorderRectF = new RectF();
outBorderPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
outBorderPaint.setFlags(Paint.ANTI_ALIAS_FLAG);
outBorderPaint.setColor(outBorderColor);
outBorderPaint.setStrokeWidth(outBorderWidth);
outBorderPaint.setStyle(Paint.Style.STROKE);
/*内置 矩形框*/
innerCheckedRectF = new RectF();
innerCheckedPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
innerCheckedPaint.setFlags(Paint.ANTI_ALIAS_FLAG);
innerCheckedPaint.setColor(innerCheckedColor);
innerCheckedPaint.setStrokeWidth(outBorderWidth);
innerCheckedPaint.setStyle(Paint.Style.FILL);
innerNormalRectF = new RectF();
innerNormalPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
innerNormalPaint.setFlags(Paint.ANTI_ALIAS_FLAG);
innerNormalPaint.setColor(innerNormalColor);
innerNormalPaint.setStrokeWidth(outBorderWidth);
innerNormalPaint.setStyle(Paint.Style.FILL);
/*对勾*/
checkMarkPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
checkMarkPaint.setFlags(Paint.ANTI_ALIAS_FLAG);
checkMarkPaint.setColor(checkMarkColor);
checkMarkPaint.setStrokeWidth(checkMarkWidth);
checkMarkPaint.setStrokeCap(Paint.Cap.ROUND);
checkMarkPaint.setStyle(Paint.Style.STROKE);
pointArray = new float[8];
checkMarkerProgress = (isChecked) ? 1F : 0F;
/*动画*/
checkMarkerShowAnimator = ObjectAnimator.ofFloat(this, "checkMarkerProgress", 0F, 1F);
checkMarkerShowAnimator.setDuration(checkMarkerDuration);
checkMarkerShowAnimator.addListener(new MySimpleAnimatorListener("checkMarkerShowAnimator"));
checkMarkerDismissAnimator = ObjectAnimator.ofFloat(this, "checkMarkerProgress", 1F, 0F);
checkMarkerDismissAnimator.setDuration(checkMarkerDuration);
checkMarkerDismissAnimator.addListener(new MySimpleAnimatorListener("checkMarkerDismissAnimator"));
setOnClickListener(new MyOnClickListener());
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.setDrawFilter(new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG));
drawInnerNormalRect(canvas);
drawInnerCheckedRect(canvas);
canvas.drawRoundRect(outBorderRectF, outBorderRadius, outBorderRadius, outBorderPaint);
drawCheckMarker(canvas);
}
/**
* 画 内置矩形
*/
private void drawInnerNormalRect(Canvas canvas) {
float width = outBorderWidth * 0.5F;
float checkMarkerProgress = this.checkMarkerProgress;
innerNormalRectF.left = size * 0.5F * (checkMarkerProgress) + width;
innerNormalRectF.right = size * (1 - checkMarkerProgress) - width;
innerNormalRectF.top = size * 0.5F * (checkMarkerProgress) + width;
innerNormalRectF.bottom = size * (1 - checkMarkerProgress) - width;
canvas.drawRoundRect(innerNormalRectF, outBorderRadius, outBorderRadius, innerNormalPaint);
}
/**
* 画 内置矩形
*/
private void drawInnerCheckedRect(Canvas canvas) {
/*内置矩形*/
float width = outBorderWidth * 0.5F;
float checkMarkerProgress = this.checkMarkerProgress;
if (isChecked) {
//checkMarkerProgress += 0.5;
}
if (checkMarkerProgress >= 1) {
checkMarkerProgress = 1F;
}
innerCheckedRectF.left = size * 0.5F * (1 - checkMarkerProgress) + width;
innerCheckedRectF.right = size * 0.5F * (1 + checkMarkerProgress) - width;
innerCheckedRectF.top = size * 0.5F * (1 - checkMarkerProgress) + width;
innerCheckedRectF.bottom = size * 0.5F * (1 + checkMarkerProgress) - width;
canvas.drawRoundRect(innerCheckedRectF, outBorderRadius, outBorderRadius, innerCheckedPaint);
}
/**
* 画 对勾
*/
private void drawCheckMarker(Canvas canvas) {
if (checkMarkerProgress < 1 / 2f) {
float x = pointArray[0] + (pointArray[2] - pointArray[0]) * checkMarkerProgress;
float y = pointArray[1] + (pointArray[3] - pointArray[1]) * checkMarkerProgress;
canvas.drawLine(pointArray[0], pointArray[1], x, y, checkMarkPaint);
} else {
float x = pointArray[4] + (pointArray[6] - pointArray[4]) * checkMarkerProgress;
float y = pointArray[5] + (pointArray[7] - pointArray[5]) * checkMarkerProgress;
canvas.drawLine(pointArray[0], pointArray[1], pointArray[2], pointArray[3], checkMarkPaint);
canvas.drawLine(pointArray[4], pointArray[5], x, y, checkMarkPaint);
}
}
private final class MySimpleAnimatorListener extends SimpleAnimatorListener {
private String type;
public MySimpleAnimatorListener(String type) {
this.type = type;
}
@Override
public void onAnimationStart(Animator animation) {
super.onAnimationStart(animation);
if ("checkMarkerShowAnimator".equals(type)) {
isChecked = true;
} else if ("checkMarkerDismissAnimator".equals(type)) {
isChecked = false;
}
}
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
if ("checkMarkerShowAnimator".equals(type)) {
isChecked(true);
} else if ("checkMarkerDismissAnimator".equals(type)) {
isChecked(false);
}
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
if (MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.AT_MOST && MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.AT_MOST) {
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) getLayoutParams();
width = height = (int) Math.min(dp2px(defaultSize) - params.leftMargin - params.rightMargin, dp2px(defaultSize) - params.bottomMargin - params.topMargin);
}
int size = Math.min(width, height);
setMeasuredDimension(size, size);
this.size = size;
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
float halfOutBorderWidth = outBorderWidth * 0.5F;
outBorderRectF.left = 0 + halfOutBorderWidth;
outBorderRectF.right = size - halfOutBorderWidth;
outBorderRectF.top = 0 + halfOutBorderWidth;
outBorderRectF.bottom = size - halfOutBorderWidth;
/*对号左边细线 起点 - x */
pointArray[0] = 121 / 600F * size;
/*对号左边线 起点 - y */
pointArray[1] = 309 / 600F * size;
/*对号左边细线 终点 - x */
pointArray[2] = 241 / 600F * size;
/*对号左边细线 终点 - y */
pointArray[3] = 408 / 600F * size;
/*对号右边细线 起点 - x */
pointArray[4] = pointArray[2];
/*对号右边细线 起点 - y */
pointArray[5] = pointArray[3];
/*对号右边细线 终点 - x */
pointArray[6] = 476 / 600F * size;
/*对号右边细线 终点 - y */
pointArray[7] = 181 / 600F * size;
}
}

</pre>

详见源码apk

目录
相关文章
|
JavaScript
Element el-radio 单选框详解
本文目录 1. 用途 2. 单选框 3. 单选框样式 4. 单选框组 4. 单选框组样式 5. 尺寸调节 6. 绑定值变化事件 7. 小结
1354 0
Element el-radio 单选框详解
|
3月前
|
容器
Qt6学习笔记七(ToolButton、RadioButton、GroupBox、CheckBox、ListWidget、TreeWidget、TableWidget)
Qt6学习笔记七(ToolButton、RadioButton、GroupBox、CheckBox、ListWidget、TreeWidget、TableWidget)
44 0
|
8月前
|
JavaScript 前端开发
一行jQuery代码搞定checkbox 全选和全不选
一行jQuery代码搞定checkbox 全选和全不选
input checkbox 复选框大小修改
有的时候,需要使用复选框,但是复选框有时候默认的太小,这时候就需要加大复选框。 解决方法: 其实就是zoom属性,这个是放大的意思,可以设置为180%,这样就会比之前大很多。
1377 0
|
前端开发
Bootstrap系列 -- 17. 复选框checkbox和单选择按钮radio
  Bootstrap框架中checkbox和radio有点特殊,Bootstrap针对他们做了一些特殊化处理,主要是checkbox和radio与label标签配合使用会出现一些小问题(最头痛的是对齐问题)。
1240 0
自定义Checkbox和Radiobox
在线演示 本地下载
856 0
input[type="radio"]自定义样式
input为radio时,虽然会有默认选中的样式,但是并不符合大多数项目的需求,我们的目标是可以随心所欲自定义它的样式。怎么做呢?其实很简单,只要抓住3点。分别是1.label 2.隐藏自带样式 3.绘制我们的样式。
1141 0
|
JavaScript 前端开发 Windows
|
JavaScript 前端开发 Java