您的位置:首页 > 移动开发 > Android开发

Android自定义View实现仿QQ实现运动步数效果

2017-07-26 13:19 507 查看
效果图:



1、attrs.xml中

<declare-styleable name="QQStepView">
<attr name="outerColor" format="color"/>
<attr name="innerColor" format="color"/>
<attr name="borderWidth" format="dimension"/>
<attr name="stepViewTextSize" format="dimension"/>
<attr name="stepViewTextColor" format="color"/>
</declare-styleable>


2、QQStepView

public class QQStepView extends View {
private int mOuterColor = Color.GRAY;
private int mInnerColor = Color.RED;
private float mBorderWidth = 20.0f;//20代表的20px
private float mStepViewTextSize = 12.0f;
private int mStepViewTextColor = Color.BLACK;
private Paint mOutPaint;

private int mStepMax;//最大的数值
private int mCurrentStep;//当前的数值
private Paint mInnerPaint;

private Paint mTextPaint;

public QQStepView(Context context) {
this(context, null);

}

public QQStepView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}

public QQStepView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
//1分析效果
//2确定自定义属性,编写attr.xml
//3在布局中使用
//4在自定义View中获取自定义属性
//5onMeasure
//6onDraw
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 = array.getDimension(R.styleable.QQStepView_borderWidth, mBorderWidth);
mStepViewTextColor = array.getColor(R.styleable.QQStepView_stepViewTextColor, mStepViewTextColor);
mStepViewTextSize = array.getDimension(R.styleable.QQStepView_stepViewTextSize, mStepViewTextSize);
array.recycle();
//外层圆弧画笔
mOutPaint = new Paint();
mOutPaint.setAntiAlias(true);
mOutPaint.setStrokeWidth(mBorderWidth);
mOutPaint.setColor(mOuterColor);
mOutPaint.setStrokeCap(Paint.Cap.ROUND);//两端变圆弧
//        mOutPaint.setStyle(Paint.Style.FILL);
mOutPaint.setStyle(Paint.Style.STROKE);
//内层圆弧画笔
mInnerPaint = new Paint();
mInnerPaint.setAntiAlias(true);
mInnerPaint.setStrokeWidth(mBorderWidth);
mInnerPaint.setColor(mInnerColor);
mInnerPaint.setStrokeCap(Paint.Cap.ROUND);//两端变圆弧
//        mOutPaint.setStyle(Paint.Style.FILL);
mInnerPaint.setStyle(Paint.Style.STROKE);
//文字画笔
mTextPaint = new Paint();
mInnerPaint.setAntiAlias(true);
mInnerPaint.setColor(mStepViewTextColor);
mTextPaint.setTextSize(mStepViewTextSize);
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//在布局文件中,可能wrap_content,可能高宽不一致
//获取模式 AT_MOST
//宽度高度不一致时取最小值,保持是个正方形
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
setMeasuredDimension(width > height ? height : width, width > height ? height : width);
}

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//画外圆弧:
//        int center = getWidth() / 2;
//        int radius= (int) (getWidth()/2-mBorderWidth/2);
//        RectF rectF = new RectF(center-radius, center-radius, center+radius, center+radius);
//        int radius = (int) (getWidth() / 2 - mBorderWidth / 2);
RectF rectF = new RectF(mBorderWidth / 2, mBorderWidth / 2, getWidth() - mBorderWidth / 2,
getWidth() - mBorderWidth / 2);
canvas.drawArc(rectF, 135, 270, false, mOutPaint);
//画内圆弧:百分比,由用户设置的
if (mStepMax == 0) {
return;//防止第一次进入时为0,引起错误
}
float sweepAngle = (float) mCurrentStep / mStepMax;
canvas.drawArc(rectF, 135, sweepAngle * 270, false, mInnerPaint);

//画文字
String stepText = mCurrentStep + "";
Rect textBounds = new Rect();
mTextPaint.getTextBounds(stepText, 0, stepText.length(), textBounds);
int dx = getWidth() / 2 - textBounds.width() / 2;//文字的起始位置
//基线
Paint.FontMetricsInt fontMetricsInt = mTextPaint.getFontMetricsInt();
int dy = (fontMetricsInt.bottom = fontMetricsInt.top) - fontMetricsInt.bottom;
int baseLine = getHeight() / 2 + dy;
canvas.drawText(stepText, dx, baseLine, mTextPaint);
}

//其他,动画效果等
public synchronized void setStepMax(int stepMax) {
this.mStepMax = stepMax;
}

//    synchronized,防止多线程操作出错
public synchronized void setCurrentStep(int currentStep) {
this.mCurrentStep = currentStep;
//不断绘制
invalidate();
}
}


3、在Activity布局中

<com.siberiadante.view.QQStepView
android:id="@+id/step_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerInParent="true"
app:borderWidth="10dp"
app:innerColor="@color/blue"
app:outerColor="@color/colorAccent"
app:stepViewTextColor="@color/blue"
app:stepViewTextSize="28sp" />


4、在Activity中

mTvStart = (TextView) findViewById(R.id.tv_start);
stepView = (QQStepView) findViewById(R.id.step_view);
stepView.setStepMax(10000);
//        stepView.setCurrentStep(5000);
//属性动画
final ValueAnimator valueAnimator = ObjectAnimator.ofFloat(0, 9000);
valueAnimator.setDuration(3000);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
float value = (float) valueAnimator.getAnimatedValue();
stepView.setCurrentStep((int)value);
}
});
mTvStart.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
valueAnimator.start();

}
});
}


我的微信公众号:tstongxiao



github地址:https://github.com/SiberiaDante/SiberiaDanteLib/blob/master/siberiadante/src/main/java/com/siberiadante/view/QQStepView.java

参考文章:http://www.jianshu.com/p/4e0eb9bb09ab
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: