您的位置:首页 > 其它

自定义一个圆形运动步数de计步效果

2017-08-30 19:32 162 查看
今天来分享一个自定义圆形计步器的效果,通过这个demo,一起来熟悉下Paint画笔的使用,先上一波效果图:



首先,按照原先的自定义View的套路:

分析自定义View的效果的需求

在attrs.xml中自定义View的属性

在布局文件中引用自定义属性

在自定义View的类中获取自定义View的属性并设置相应的属性

在onMeasure()方法中去测量自定义View

在onDraw()方法中绘制效果

根据上面的步骤,下面来具体撸一把代码

1:分析自定义需求

从动画中,我们可以看到,需要外圈圆弧的颜色,内圈圆弧的颜色,圆弧的宽度,字体的颜色,字体的大小

2:在attrs.xml中自定义这些属性

<declare-styleable name="CustomStepView">
<!-- 外圆弧颜色 -->
<attr name="outerColor" format="color"/>

<!-- 内圆弧颜色 -->
<attr name="innerColor" format="color"/>

<!-- 圆弧宽度 -->
<attr name="borderWidth" format="dimension"/>

<!-- 字体大小 -->
<attr name="textSize" format="dimension"/>

<!-- 字体颜色 -->
<attr name="textColor" format="color"/>
</declare-styleable>


3:在布局文件中引用自定义属性(注意,需要定义命名空间)

<com.justh.dell.customqqstepview.CustomStepView
android:id="@+id/customview"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:outerColor="@color/colorPrimary"
app:innerColor="@color/colorAccent"
app:borderWidth="12dp"
app:textColor="@color/colorAccent"
app:textSize="90dp"/>


4: 在自定义View的类中获取自定义View的属性并设置相应的属性

5: 在onMeasure()方法中去测量自定义View

6:在onDraw()方法中绘制效果

//定义属性并设置默认值
private int mOuterColor = Color.RED;
private int mInnerColor = Color.BLUE;
private int mTextSize = 30;
private int mBorderWidth = 10;
private int mTextColor = Color.RED;

//画外圆弧 内圆弧  字体的画笔
private Paint mOuterPaint;
private Paint mInnerPaint;
private Paint mTextPaint;

//设置最大的步数
private int maxStep;
//当前步数
private int currentStep;

private Rect bounds;

public CustomStepView(Context context) {
this(context,null);
}

public CustomStepView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs,0);
}

public CustomStepView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);

/**
*1:自定义属性
*2:布局中使用
*3:在自定义view中获取属性
*4:onMeasure
*5:onDraw
*/
//获取自定义属性
TypedArray array = context.obtainStyledAttributes(attrs,R.styleable.CustomStepView);

mOuterColor = array.getColor(R.styleable.CustomStepView_outerColor,mOuterColor);
mInnerColor = array.getColor(R.styleable.CustomStepView_innerColor,mInnerColor);
mTextColor = array.getColor(R.styleable.CustomStepView_textColor,mTextColor);
mBorderWidth = (int) array.getDimension(R.styleable.CustomStepView_borderWidth,mBorderWidth);
mTextSize = array.getDimensionPixelSize(R.styleable.CustomStepView_textSize,mTextSize);
//回收
array.recycle();

//设置三个画笔的属性
mOuterPaint = new Paint();
mOuterPaint.setAntiAlias(true);
mOuterPaint.setColor(mOuterColor);
mOuterPaint.setStrokeWidth(mBorderWidth);
//画圆弧的帽子
mOuterPaint.setStrokeCap(Paint.Cap.ROUND);
mOuterPaint.setStyle(Paint.Style.STROKE);

mInnerPaint = new Paint();
mInnerPaint.setAntiAlias(true);
mInnerPaint.setColor(mInnerColor);
mInnerPaint.setStrokeWidth(mBorderWidth);
mInnerPaint.setStrokeCap(Paint.Cap.ROUND);
mInnerPaint.setStyle(Paint.Style.STROKE);

mTextPaint = new Paint();
mTextPaint.setColor(mTextColor);
mTextPaint.setTextSize(mTextSize);

4000
mTextPaint.setAntiAlias(true);
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//当MeasureMode == AT_MOST的时候  指定其宽度和高度为250dp
//EXACTLY   为宽高的最小值 保证其为一个正方形
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int width = 0,height=0;
if(widthMode == MeasureSpec.AT_MOST){
width = dp2px(250);
}else{
width = MeasureSpec.getSize(widthMeasureSpec);
}
if(heightMode == MeasureSpec.AT_MOST){
height = dp2px(250);
}else{
height = MeasureSpec.getSize(heightMeasureSpec);
}

setMeasuredDimension(width>height?height:width,width>height?height:width);

}

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//画外圆 画笔的粗细占了圆内和圆外的一半的   所以要预留出一定的空间
int width = mBorderWidth/2;
RectF oval = new RectF(width,width,getWidth()-width,getHeight()-width);
canvas.drawArc(oval,135,270,false,mOuterPaint);

if(maxStep <= 0){
return;
}
float sweepAngle = (float) (currentStep*1.0/maxStep);
canvas.drawArc(oval,135,sweepAngle*270,false,mInnerPaint);

//画字
String textStep = currentStep+"";
//计算字体的宽
if(bounds == null){
bounds = new Rect();
}
mTextPaint.getTextBounds(textStep,0,textStep.length(),bounds);
int textWidth = bounds.width();

//计算文字基线值
Paint.FontMetricsInt fontMetricsInt = mTextPaint.getFontMetricsInt();
int dy = (fontMetricsInt.bottom - fontMetricsInt.top)/2-fontMetricsInt.bottom;
canvas.drawText(textStep,getWidth()/2-textWidth/2,getHeight()/2+dy,mTextPaint);
}

private int dp2px(int dp){
return (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,dp,
getResources().getDisplayMetrics());
}

//设置最大步数
public void setMaxStep(int maxStep){
this.maxStep = maxStep;
}

//设置当前步数
public synchronized void setCurrentStep(int currentStep){
if(currentStep>maxStep){
this.currentStep = maxStep;
}else{
this.currentStep = currentStep;
}
//更新
invalidate();
}


第4,5,6步的具体实现,在代买中已经做了注释,相信大家都能看得懂!

到这里,自定义计步器的动作就完成了,下面就需要在Activity或其他使用的地方设置他,并让她实现动画效果,这里使用了属性动画来做处理,当然,有其他好的方法,欢迎推荐:

mCustomStepView = (CustomStepView) findViewById(R.id.customview);
mCustomStepView.setMaxStep(5000);

ValueAnimator animator = ObjectAnimator.ofFloat(0,3729);
animator.setDuration(3000);
animator.setInterpolator(new DecelerateInterpolator());
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float currentStep = (float) animation.getAnimatedValue();
mCustomStepView.setCurrentStep((int) currentStep);
}
});
animator.start();


好了,今天到这里就结束了!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  自定义view