作者:Noblel
链接:http://www.jianshu.com/p/a21730618ca9
请尊重原创,谢谢!
需求来源
来自某一版本的QQ的运动记步
实现思路
1.分析元素和效果:有两个不同色圆弧,一个为进度一个为背景
一个步数字体
2.确定自定义属性:背景色,进度色,圆弧大小,字体大小和颜色,其余自己可以再加。
3.编写QQStepView
-
获取自定义属性
TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.QQStepView); mOuterColor = array.getColor(R.styleable.QQStepView_outerColor, mOuterColor); mInnerColor = array.getColor(R.styleable.QQStepView_innerColor, mInnerColor); mBorderWidth = (int) array.getDimension(R.styleable.QQStepView_borderWidth, mBorderWidth); mStepTextSize = (int) array.getDimension(R.styleable.QQStepView_stepTextSize, mStepTextSize); mStepTextColor = array.getColor(R.styleable.QQStepView_stepTextColor, mStepTextColor); array.recycle();
-
初始化画笔
//外圆弧画笔 mOutPaint = new Paint(); //设置抗锯齿 mOutPaint.setAntiAlias(true); //设置弧宽 mOutPaint.setStrokeWidth(mBorderWidth); mOutPaint.setColor(mOuterColor); //设置画笔实心 mOutPaint.setStyle(Paint.Style.STROKE); //设置画笔线冒也就是弧的头样式 mOutPaint.setStrokeCap(Paint.Cap.ROUND); //内圆弧画笔 mInnerPaint = new Paint(); mInnerPaint.setAntiAlias(true); mInnerPaint.setStrokeWidth(mBorderWidth); mInnerPaint.setColor(mInnerColor); mInnerPaint.setStyle(Paint.Style.STROKE); mInnerPaint.setStrokeCap(Paint.Cap.ROUND); mTextPaint = new Paint(); mTextPaint.setAntiAlias(true); mTextPaint.setColor(mStepTextColor); mTextPaint.setTextSize(mStepTextSize);
-
画外圆弧
//圆心,这里要注意我们的视图要保证为正方形。所以要在onMeasure中重写 int center = getWidth() / 2; int radius = getWidth() / 2 - mBorderWidth / 2; mRectF.left = center - radius; mRectF.top = center - radius; mRectF.right = center + radius; mRectF.bottom = center + radius; //画弧,RectF和Rect的区别后面讲 canvas.drawArc(mRectF, 135, 270, false, mOutPaint);
-
画内圆弧
//mCurrentStep为当前步数,mStepMax最大步数可以设置为属性也可以直接设置 float sweepAngle = (float) mCurrentStep / mStepMax; canvas.drawArc(mRectF, 135, sweepAngle * 270, false, mInnerPaint);
-
画文字
//在自定义View之变色文字讲解过 String str = mCurrentStep + "步"; mTextPaint.getTextBounds(str, 0, str.length(), mTextBounds); int dx = center - mTextBounds.width() / 2; Paint.FontMetricsInt fontMetricsInt = mTextPaint.getFontMetricsInt(); int dy = (fontMetricsInt.bottom - fontMetricsInt.top) / 2 - fontMetricsInt.bottom; int baseLine = center + dy; canvas.drawText(str, dx, baseLine, mTextPaint);
-
原理图
原理图
测试使用:
final QQStepView qqStepView = findViewById(R.id.step_view);
qqStepView.setStepMax(3000);
//属性动画
ValueAnimator animator = ObjectAnimator.ofFloat(0, 3000);
animator.setInterpolator(new AccelerateInterpolator());
animator.setDuration(3000);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float currentStep = (float) animation.getAnimatedValue();
qqStepView.setCurrentStep((int) currentStep);
}
});
animator.start();
RectF和Rect的区别
Rect是“Rectangle”简写的英文单词,中文意思“矩形或长方形”,Rect对象持有一个矩形的四个int坐标值,RectF对象持有一个矩形的四个float坐标值,这是两者最大的区别。从实现的方式上看,Rect是一个final类实现Parcelable接口,RectF是一个普通类实现Parcelable接口,Rect和RectF除了记录的坐标数据类型不一样外,其他没什么太大差别。
网友评论