效果图:

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

Android自定义View实现仿QQ实现运动步数效果的更多相关文章

  1. Android自定义View 画弧形,文字,并增加动画效果

    一个简单的Android自定义View的demo,画弧形,文字,开启一个多线程更新ui界面,在子线程更新ui是不允许的,但是View提供了方法,让我们来了解下吧. 1.封装一个抽象的View类   B ...

  2. android自定义View之仿通讯录侧边栏滑动,实现A-Z字母检索

    我们的手机通讯录一般都有这样的效果,如下图: OK,这种效果大家都见得多了,基本上所有的android手机通讯录都有这样的效果.那我们今天就来看看这个效果该怎么实现. 一.概述 1.页面功能分析 整体 ...

  3. Android 自定义View,仿微信视频播放按钮

    闲着,尝试实现了新版微信视频播放按钮,使用的是自定义View,先来个简单的效果图...真的很简单哈. 由于暂时用不到,加上时间原因,加上实在是没意思,加上……,本控件就没有实现自定义属性,有兴趣的朋友 ...

  4. Android 自定义View修炼-仿QQ5.0 的侧滑菜单效果的实现

    有一段时间没有写博客了,最近比较忙,没什么时间写,刚好今天有点时间, 我就分享下,侧滑菜单的实现原理,一般android侧滑的实现原理和步骤如下:(源码下载在下面最后给出哈) 1.使用ViewGrou ...

  5. Android自定义view之仿微信录制视频按钮

    本文章只写了个类似微信的录制视频的按钮,效果图如下:             一.主要的功能: 1.长按显示进度条,单击事件,录制完成回调 2.最大时间和最小时间控制 3.进度条宽度,颜色设置 二.实 ...

  6. Android 自定义View修炼-仿360手机卫士波浪球进度的实现

    像360卫士的波浪球进度的效果,一般最常用的方法就是 画线的方式,先绘sin线或贝塞尔曲线,然后从左到右绘制竖线,然后再裁剪圆区域. 今天我这用图片bitmap的方式,大概的方法原理是: (1)首先用 ...

  7. android桌面悬浮窗仿QQ手机管家加速效果

    主要还是用到了WindowManager对桌面悬浮进行管理. 需要一个火箭的悬浮窗 一个发射台悬浮窗  ,判断火箭是否放到了发射台,如果放上了,则使用AsyTask 慢慢将火箭的图片往上移.结束后., ...

  8. Android自定义View之ProgressBar出场记

    关于自定义View,我们前面已经有三篇文章在介绍了,如果筒子们还没阅读,建议先看一下,分别是android自定义View之钟表诞生记.android自定义View之仿通讯录侧边栏滑动,实现A-Z字母检 ...

  9. android自定义View之NotePad出鞘记

    现在我们的手机上基本都会有一个记事本,用起来倒也还算方便,记事本这种东东,如果我想要自己实现,该怎么做呢?今天我们就通过自定义View的方式来自定义一个记事本.OK,废话不多说,先来看看效果图. 整个 ...

随机推荐

  1. Markdown编辑器语言——30分钟入门到到精通

    一.简要说明 开篇说明 其实吧这是我人生中写的第一篇博客,我也不知道怎么排版和编辑让博文显示的更加美观,现在正在学Markdown编辑语法,也是刚刚学编程的一个小菜鸟,目前是大二的在校生,我的初衷是把 ...

  2. 【commons】IO工具类——commons-io之IOUtils

    本文转载自xingoo: https://www.cnblogs.com/xing901022/p/5978989.html 一.常用静态变量 public static final char DIR ...

  3. c++ 方框中绘制菜单代码

    绘制静态菜单 getch与getchar 接收光标控制 一.绘制静态菜单 编写函数void mainmenu( void) 二.getch与getchar getch()的作用是从键盘接收一个字 ...

  4. matplotlib绑定到PyQt5(有菜单)

    稍微复杂地实现matplotlib绑定到PyQt5(有菜单) [知识点] import matplotlib matplotlib.use("Qt5Agg") [效果图] [源代码 ...

  5. 3504: [Cqoi2014]危桥

    3504: [Cqoi2014]危桥 链接 分析: 首先往返的可以转化为全是“往”,那么只要将容量除以2即可. 然后S向a1连边容量为an(除以2之前为2*an),S向a2连边容量为an,b1,b2向 ...

  6. 一个简单的nodejs项目(cat-names)分析

    https://github.com/sindresorhus/cat-names 一个非常简单的nodejs项目,用来方便的获取猫猫的名字: 安装: npm install --save cat-n ...

  7. ASP.NET Core Token认证

    翻译:Token Authentication in ASP.NET Core 令牌认证(Token Authentication)已经成为单页应用(SPA)和移动应用事实上的标准.即使是传统的B/S ...

  8. hdu1546Idiomatic Phrases Game(floyd+map)

    传送门 成语接龙,找每个单词都需要一点时间,问最少的时间 把字符串用map处理成数字编号,之后用floyd #include<bits/stdc++.h> using namespace ...

  9. Unity3D之AR开发(一)

    近期研究了下AR技术,下面给大家分享一下. 第一种方法:高通AR(Vuforia) Vuforia插件下载地址(官网): https://developer.vuforia.com/downloads ...

  10. 通过扩展方法简化UnityAPI调用

    通过扩展方法简化UnityAPI调用 扩展方法unity apiapi简化 通过扩展方法简化UnityAPI调用 能省一秒是一秒,时间就是金钱,没人愿意把时间花在冗长的coding上