效果图:

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. [2016北京集训试题14]股神小D-[LCT]

    Description Solution 将(u,v,l,r)换为(1,u,v,l)和(2,u,v,r).进行排序(第4个数为第一关键字,第1个数为第二关键字).用LCT维护联通块的合并和断开.(维护 ...

  2. lxml etree xpath

    from lxml import etree #####################基本用法: ##################### html = ''' <h1 class=&quo ...

  3. 洛咕 P2403 [SDOI2010]所驼门王的宝藏

    简单tarjan. 一行的横天门如果暴力连边会被卡成平方,所以只要相邻两个横天门连双向边,再随便选一个横天门向整行连边即可.纵寰门同理.ziyou门直接map暴力连边. 然后tarjan直接dp. / ...

  4. SSIS 容器

    容器(Container)是控制流的特殊的任务(Task),它为一个或多个Task提供逻辑组合,可以实现工作流的重复执行和顺序执行,还可以把变量和事件处理程序的作用域缩小到容器中.不能在容器内的Tas ...

  5. 树莓派修改VNC分辨率

    1.打开终端输入 sudo raspi-config 2. 选择 Advanced Options  再选择 Resolution 3.选择想要的分辨率,确定 4.重启

  6. jmeter发送http请求(初学者)

    1.jmeter安装配置(百度,这里就不赘述了) 2.添加线程组 测试计划-->添加-->Threads-->线程组 3.线程组配置 线程数:用户数或者并发数,设置为100则有100 ...

  7. Unity优化方向——优化Unity游戏中的图形渲染(译)

    CPU bound:CPU性能边界,是指CPU计算时一直处于占用率很高的情况. GPU bound:GPU性能边界,同样的是指GPU计算时一直处于占用率很高的情况. 原文:https://unity3 ...

  8. Http protocal

        https://tools.ietf.org/html/rfc2616   1. 状态码:status code 1xxx:信息--请求被接收,继续下一步处理   2xxx:成功--请求行为被 ...

  9. Mysql启动失败解决方案 - 个人经验可能不适合所有场景

    以前一直用的Mysql5.5,安装程序是一个exe程序,安装完了相应的服务也给我注册好了,然后直接启动连接即可. 最近升级到了8.0.15,发现和以前不一样了. 8.0.15下载地址 安装解压之后目录 ...

  10. 脚本处理iOS的Crash日志

    背景 当我们打包app时,可以选择生成对应的符号表,其保存 16 进制函数地址映射信息,通过给定的函数起始地址和偏移量,可以对应函数具体信息以供分析. 所以我们拿到测试给的闪退日志(.crash)时, ...