100字范文,内容丰富有趣,生活中的好帮手!
100字范文 > oracle number型步数 Android自定义View仿QQ计步器

oracle number型步数 Android自定义View仿QQ计步器

时间:2019-04-25 10:23:30

相关推荐

oracle number型步数 Android自定义View仿QQ计步器

自定义计步器

Android自定义View是Android开发中比较重要的一项,也是很多开发者比较怕的一个东西。其实只要认真去学习,自定义View其实没有那么可怕;相反的,我们还能从自定义View中找到很多乐趣。

自定义一个计步器分析:

1、首先需要画一个固定不动的大圆弧

2、其次需要画一个跟着步数变化的小圆弧

3、最后画圆弧中间的步数显示的文字

实现效果图

自定义属性

首先我们在values目录下新建attrs.xml文件;

然后在里面自定义属性:

创建StepView

创建我们的StepView,继承自View并重写构造方法。

public class StepView extends View {

public StepView(Context context) {

this(context, null);

}

public StepView(Context context, @Nullable AttributeSet attrs) {

this(context, attrs, 0);

}

public StepView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {

super(context, attrs, defStyleAttr);

}

}

这里在前两个构造方法中调this,保证使用每个构造方法初始化都能走到第三个构造方法。

在View中获取属性

创建好View,重写构造方法以后就要在View中获取我们的自定义属性:

//获取自定义属性

TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.StepView);

mOutColor = array.getColor(R.styleable.StepView_outColor, Color.GREEN);

mInnerColor = array.getColor(R.styleable.StepView_innerColor, Color.BLUE);

mBorderWidth = (int) array.getDimension(R.styleable.StepView_borderWidth, 10);

mStepTextSize = array.getDimensionPixelSize(R.styleable.StepView_stepTextSize, 20);

mStepTextColor = array.getColor(R.styleable.StepView_stepTextColor, Color.RED);

array.recycle();

重写onMeasure()方法

然后需要重写我们的onMeasure方法,这个方法是测量并设置View的宽高,因为我们这个View比较简单,只需要保证是宽高一致,所以只需要获取我们的宽高,然后设置就行。

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

super.onMeasure(widthMeasureSpec, heightMeasureSpec);

int width = MeasureSpec.getSize(widthMeasureSpec);

int height = MeasureSpec.getSize(heightMeasureSpec);

setMeasuredDimension(Math.min(width, height), Math.min(width, height));

}

重写onDraw()方法

onDraw方法就是绘制View的内容,这里我们要分三步:

1、绘制大圆弧

首先绘制固定的大圆弧:

//画外圆弧

int center = getWidth() / 2;

int radius = getWidth() / 2 - mBorderWidth;

int left = center - radius;

int top = center - radius;

int right = center + radius;

int bottom = center + radius;

mRectF.set(left, top, right, bottom);

canvas.drawArc(mRectF, START_ANGLE, TOTAL_ANGLE, false, mPaintOuter);

首先要定义一个矩形区域mRectF,然后设置四个边界值。center就是圆心位置,radius就是半径,这里要减去圆弧的宽度。

然后调用drawArc(),这个方法主要有四个参数:

oval : 生成椭圆的矩形

startAngle : 弧开始的角度 (X轴正方向为0度,顺时针弧度增大)

sweepAngle : 绘制多少弧度 (注意不是结束弧度)

useCenter : 是否有弧的两边 true有两边 false无两边

2、绘制小圆弧

小圆弧是会跟着当前的步数动态变化的,所以我们要根据步数计算:

//画内圆弧

float sweepAngle = (float) mCurrentStepCount / mMaxStepCount;

canvas.drawArc(mRectF, START_ANGLE, sweepAngle * TOTAL_ANGLE, false, mPaintInner);

计算完成同样是调用drawArc()绘制圆弧。

3、绘制文字

接下来就是绘制显示在圆弧中心的文字就是我们的当前步数:

//画文字

if (mCurrentStepCount == 0) {

return;

}

String currentStepText = String.valueOf(mCurrentStepCount);

mPaintText.getTextBounds(currentStepText, 0, currentStepText.length(), mBounds);

int startX = getWidth() / 2 - mBounds.width() / 2;

Paint.FontMetricsInt fm = mPaintText.getFontMetricsInt();

int dy = (fm.bottom - fm.top) / 2 - fm.descent;

int baseline = getHeight() / 2 + dy;

canvas.drawText(currentStepText, startX, baseline, mPaintText);

首先根据画笔去测量文字的边界,然后计算开始的x坐标和baseline,最后调用drawText()绘制;

这里不知道怎么计算的可以转到另一篇博客,怎么绘制真正的居中文本,里面有详细介绍计算推理过程。

在xml中使用

最后就是在xml中使用我们的自定义View,要让它动起来,还需要借助我们的属性动画,动态去改变当前的步数值,然后去重绘。

这里贴一下xml中使用代码:

xmlns:app="/apk/res-auto"

xmlns:tools="/tools"

android:layout_width="match_parent"

android:layout_height="match_parent"

tools:context=".MainActivity">

android:id="@+id/stepView"

android:layout_width="120dp"

android:layout_height="120dp"

app:outColor="@color/design_default_color_secondary"

app:innerColor="@color/design_default_color_primary"

app:stepTextColor="@color/black"

app:stepTextSize="16sp"

app:borderWidth="6dp"

app:layout_constraintBottom_toBottomOf="parent"

app:layout_constraintLeft_toLeftOf="parent"

app:layout_constraintRight_toRightOf="parent"

app:layout_constraintTop_toTopOf="parent" />

然后是在activity使用:

public class MainActivity extends AppCompatActivity {

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

StepView stepView = findViewById(R.id.stepView);

stepView.setMaxStep(3000);

ValueAnimator valueAnimator = ObjectAnimator.ofFloat(0,1800);

valueAnimator.setDuration(2000);

valueAnimator.setInterpolator(new DecelerateInterpolator());

valueAnimator.addUpdateListener(animation -> {

float animatedValue = (float) animation.getAnimatedValue();

stepView.setStep((int) animatedValue);

});

valueAnimator.start();

}

}

StepView类全部代码

package com.px.test.view;

import android.content.Context;

import android.content.res.TypedArray;

import android.graphics.Canvas;

import android.graphics.Color;

import android.graphics.Paint;

import android.graphics.Rect;

import android.graphics.RectF;

import android.util.AttributeSet;

import android.view.View;

import com.px.test.R;

import androidx.annotation.Nullable;

public class StepView extends View {

private static final String TAG = "StepView";

private static final int START_ANGLE = 135;

private static final int TOTAL_ANGLE = 270;

private int mOutColor;

private int mInnerColor;

private int mBorderWidth;

private int mStepTextSize;

private int mStepTextColor;

private Paint mPaintOuter;

private RectF mRectF;

private Paint mPaintInner;

private Paint mPaintText;

private Rect mBounds;

private int mMaxStepCount;

private int mCurrentStepCount;

public StepView(Context context) {

this(context, null);

}

public StepView(Context context, @Nullable AttributeSet attrs) {

this(context, attrs, 0);

}

public StepView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {

super(context, attrs, defStyleAttr);

//获取自定义属性

TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.StepView);

mOutColor = array.getColor(R.styleable.StepView_outColor, Color.GREEN);

mInnerColor = array.getColor(R.styleable.StepView_innerColor, Color.BLUE);

mBorderWidth = (int) array.getDimension(R.styleable.StepView_borderWidth, 10);

mStepTextSize = array.getDimensionPixelSize(R.styleable.StepView_stepTextSize, 20);

mStepTextColor = array.getColor(R.styleable.StepView_stepTextColor, Color.RED);

array.recycle();

mPaintOuter = new Paint();

mPaintOuter.setAntiAlias(true);

mPaintOuter.setColor(mOutColor);

mPaintOuter.setStrokeWidth(mBorderWidth);

mPaintOuter.setStrokeCap(Paint.Cap.ROUND);

mPaintOuter.setStyle(Paint.Style.STROKE);

mPaintInner = new Paint();

mPaintInner.setAntiAlias(true);

mPaintInner.setColor(mInnerColor);

mPaintInner.setStrokeWidth(mBorderWidth);

mPaintInner.setStrokeCap(Paint.Cap.ROUND);

mPaintInner.setStyle(Paint.Style.STROKE);

mPaintText = new Paint();

mPaintText.setAntiAlias(true);

mPaintText.setColor(mStepTextColor);

mPaintText.setTextSize(mStepTextSize);

mBounds = new Rect();

mRectF = new RectF();

}

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

super.onMeasure(widthMeasureSpec, heightMeasureSpec);

int width = MeasureSpec.getSize(widthMeasureSpec);

int height = MeasureSpec.getSize(heightMeasureSpec);

setMeasuredDimension(Math.min(width, height), Math.min(width, height));

}

@Override

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

//画外圆弧

int center = getWidth() / 2;

int radius = getWidth() / 2 - mBorderWidth;

int left = center - radius;

int top = center - radius;

int right = center + radius;

int bottom = center + radius;

mRectF.set(left, top, right, bottom);

canvas.drawArc(mRectF, START_ANGLE, TOTAL_ANGLE, false, mPaintOuter);

//画内圆弧

float sweepAngle = (float) mCurrentStepCount / mMaxStepCount;

canvas.drawArc(mRectF, START_ANGLE, sweepAngle * TOTAL_ANGLE, false, mPaintInner);

//画文字

if (mCurrentStepCount == 0) {

return;

}

String currentStepText = String.valueOf(mCurrentStepCount);

mPaintText.getTextBounds(currentStepText, 0, currentStepText.length(), mBounds);

int startX = getWidth() / 2 - mBounds.width() / 2;

Paint.FontMetricsInt fm = mPaintText.getFontMetricsInt();

int dy = (fm.bottom - fm.top) / 2 - fm.descent;

int baseline = getHeight() / 2 + dy;

canvas.drawText(currentStepText, startX, baseline, mPaintText);

}

public void setMaxStep(int maxStepCount) {

mMaxStepCount = maxStepCount;

}

public void setStep(int currentStepCount) {

mCurrentStepCount = currentStepCount;

invalidate();

}

}

整个实现过程并不复杂,有时候有些事情并没有我们想的那么难,只要我们去做了,就会发现其实就那样。

完整工程文件下载

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。