一个简单的自定义view
2017-10-25 本文已影响163人
ChangQin
参考自http://www.jianshu.com/p/1b2cdba03d23
public class CheckView extends View {
private Context mContext;
//圆环画笔
private Paint mPaintRing;
//对号画笔
private Paint mPaintTick;
//圆的画笔
private Paint mPaintCircle;
private int unCheckBaseColor;
private int checkBaseColor;
private int checkTickColor;
private RectF mRectF = new RectF();
private float centerX, centerY;
private float[] mPoints = new float[8];
private boolean mIsChecked;
private int radius;
private float tickRadius;
private float tickRadiusOffset;
private int ringProgress = 0;
private int circleProgress = 0;
private int rightAlpha = 0;
private boolean IsAnimeRuning;
private boolean ringAnimeEnd;
private OnCheckChangeListener mCheckChangeListener;
public CheckView(Context context) {
this(context, null);
}
public CheckView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public CheckView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mContext = context;
init(attrs);
initPaint();
setClickEvent();
}
private void initPaint() {
mPaintRing = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaintRing.setStyle(Paint.Style.STROKE);
mPaintRing.setColor(mIsChecked ? checkBaseColor : unCheckBaseColor);
mPaintRing.setStrokeWidth(dp2px(mContext, 2.5f));
mPaintRing.setStrokeCap(Paint.Cap.ROUND);
mPaintCircle = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaintCircle.setColor(checkTickColor);
mPaintCircle.setStrokeWidth(dp2px(mContext, 1));
mPaintTick = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaintTick.setColor(mIsChecked ? checkTickColor : unCheckBaseColor);
mPaintTick.setStyle(Paint.Style.STROKE);
mPaintTick.setStrokeCap(Paint.Cap.ROUND);
mPaintTick.setStrokeWidth(dp2px(mContext, 2.5f));
}
private void init(AttributeSet attrs) {
TypedArray a = mContext.obtainStyledAttributes(attrs, R.styleable.CheckView);
unCheckBaseColor = a.getColor(R.styleable.CheckView_uncheck_color, getResources().getColor(R.color.tick_gray));
checkBaseColor = a.getColor(R.styleable.CheckView_check_color, getResources().getColor(R.color.tick_yellow));
checkTickColor = a.getColor(R.styleable.CheckView_check_right_color, getResources().getColor(R.color.tick_white));
a.recycle();
radius = dp2px(mContext, 30);
tickRadius = dp2px(mContext, 12);
tickRadiusOffset = dp2px(mContext, 4);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = getMySize(radius * 2, widthMeasureSpec);
int height = getMySize(radius * 2, heightMeasureSpec);
int res = Math.max(width, height);
setMeasuredDimension(res, res);
centerX = getMeasuredWidth() / 2;
centerY = getMeasuredHeight() / 2;
mRectF.set(centerX - radius, centerY - radius, centerX + radius, centerY + radius);
//设置打钩的几个点坐标
mPoints[0] = centerX - tickRadius + tickRadiusOffset;
mPoints[1] = (float) centerY;
mPoints[2] = centerX - tickRadius / 2 + tickRadiusOffset;
mPoints[3] = centerY + tickRadius / 2;
mPoints[4] = centerX - tickRadius / 2 + tickRadiusOffset;
mPoints[5] = centerY + tickRadius / 2;
mPoints[6] = centerX + tickRadius * 2 / 4 + tickRadiusOffset;
mPoints[7] = centerY - tickRadius * 2 / 4;
}
@Override
protected void onDraw(final Canvas canvas) {
super.onDraw(canvas);
if (!mIsChecked) {
canvas.drawArc(mRectF, 90, 360, false, mPaintRing);
canvas.drawLines(mPoints, mPaintTick);
return;
}
if (ringAnimeEnd){
mPaintCircle.setColor(checkBaseColor);
//画满黄色的圆
canvas.drawCircle(centerX,centerY,radius,mPaintCircle);
mPaintCircle.setColor(checkTickColor);
}
//画圆环
canvas.drawArc(mRectF, 90, ringProgress, false, mPaintRing);
//画逐渐缩小的白圆
canvas.drawCircle(centerX,centerY,radius-circleProgress,mPaintCircle);
//画对号
mPaintTick.setAlpha(rightAlpha);
canvas.drawLines(mPoints,mPaintTick);
if (!IsAnimeRuning) {
IsAnimeRuning = true;
ObjectAnimator ringAnimator = ObjectAnimator.ofInt(this,"ringProgress",0,360);
ObjectAnimator circleAnimator = ObjectAnimator.ofInt(this,"circleProgress",0,radius);
ObjectAnimator rightAnimator = ObjectAnimator.ofInt(this,"rightAlpha",0,255);
ringAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
ringAnimeEnd = true;
}
});
PropertyValuesHolder holder1 = PropertyValuesHolder.ofFloat("scaleX", 1f,1.2f,1f);
PropertyValuesHolder holder2 = PropertyValuesHolder.ofFloat("scaleY", 1f,1.2f,1f);
ObjectAnimator scaleAnimator = ObjectAnimator.ofPropertyValuesHolder(this, holder1, holder2);
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.playSequentially(ringAnimator,circleAnimator,rightAnimator,scaleAnimator);
animatorSet.start();
}
}
private void reset() {
initPaint();
ringProgress = 0;
circleProgress = 0;
rightAlpha = 0;
IsAnimeRuning = false;
ringAnimeEnd = false;
mRectF.set(centerX - radius, centerY - radius, centerX + radius, centerY + radius);
invalidate();
}
private void setClickEvent() {
this.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mIsChecked = !mIsChecked;
reset();
if (mCheckChangeListener!=null){
mCheckChangeListener.onCheckChange((TestTickView)v,mIsChecked);
}
}
});
}
//用于属性动画的getter和setter
public int getRingProgress() {
return ringProgress;
}
public void setRingProgress(int ringProgress) {
this.ringProgress = ringProgress;
invalidate();
}
public int getCircleProgress() {
return circleProgress;
}
public void setCircleProgress(int circleProgress) {
this.circleProgress = circleProgress;
invalidate();
}
public int getRightAlpha() {
return rightAlpha;
}
public void setRightAlpha(int rightAlpha) {
this.rightAlpha = rightAlpha;
invalidate();
}
private int getMySize(int defSize, int measureSpec) {
int result;
int mode = MeasureSpec.getMode(measureSpec);
int size = MeasureSpec.getSize(measureSpec);
if (mode == MeasureSpec.UNSPECIFIED || mode == MeasureSpec.AT_MOST) {
result = defSize;
} else {
result = size;
}
return result;
}
private static int dp2px(Context context, float dpValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
public void setCheckChangeListener(OnCheckChangeListener checkChangeListener) {
mCheckChangeListener = checkChangeListener;
}
public interface OnCheckChangeListener{
void onCheckChange(TestTickView testTickView,boolean checked);
}
}
<declare-styleable name="CheckView">
<attr name="uncheck_color" format="color" />
<!--选中后的基调颜色-->
<attr name="check_color" format="color" />
<!--选中后钩的颜色-->
<attr name="check_right_color" format="color" />
<!--圆的半径-->
<attr name="radius_size" format="dimension" />
</declare-styleable>