效果如下

gif图展示效果不好,实际体验无卡顿

1.自定义属性

早Values目录下New-values resource file,命名为attrs.xml(命名随意,但规范命名为attrs.xml)
自定义属性如下,注意format不要与Android自带的命名重复。

<?xml version="1.0" encoding="utf-8"?>
<resources><declare-styleable name="QQStepView"><attr name="outerColor" format="color" /><attr name="innerColor" format="color" /><attr name="borderWidth" format="dimension" /><attr name="stepTextSize" format="dimension" /><attr name="stepTextColor" format="color" /></declare-styleable><declare-styleable name="MyProgressBar"><attr name="leftColor" format="color" /><attr name="rightColor" format="color" /><attr name="progressTextColor" format="color" /><attr name="progressTextSize" format="dimension" /><attr name="progressBounds" format="dimension" /></declare-styleable>
</resources>
2.编写自定义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.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;import com.cyq.customview2.R;
import com.cyq.customview2.utils.MeasureUtils;@SuppressWarnings("all")
public class QQStepView extends View {private int mOuterColor = Color.parseColor("#2196F3");private int mInnerColor = Color.parseColor("#F44336");private int mStepTextColor = Color.parseColor("#EC407A");private int mBorderWidth = 20;//pxprivate int mStepTextSize = 18;//pxprivate int mSeptMax = 10000;private int mSeptCurrent = 0;private Paint mOutPaint;private Paint mInnerPaint;private Paint mTextPaint;public QQStepView(Context context) {this(context, null);}public QQStepView(Context context, @Nullable AttributeSet attrs) {this(context, attrs, 0);}public QQStepView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.QQStepView);mOuterColor = array.getColor(R.styleable.QQStepView_outerColor, mOuterColor);mInnerColor = array.getColor(R.styleable.QQStepView_innerColor, mInnerColor);mStepTextColor = array.getColor(R.styleable.QQStepView_stepTextColor, mStepTextColor);mBorderWidth = (int) array.getDimension(R.styleable.QQStepView_borderWidth, MeasureUtils.dp2px(mBorderWidth, this));mStepTextSize = array.getDimensionPixelSize(R.styleable.QQStepView_stepTextSize, MeasureUtils.sp2px(mStepTextSize, this));array.recycle();mOutPaint = new Paint();mOutPaint.setAntiAlias(true);mOutPaint.setStrokeWidth(mBorderWidth);mOutPaint.setColor(mOuterColor);mOutPaint.setStyle(Paint.Style.STROKE);mOutPaint.setStrokeCap(Paint.Cap.ROUND);//圆角mInnerPaint = new Paint();mInnerPaint.setAntiAlias(true);mInnerPaint.setStrokeWidth(mBorderWidth);mInnerPaint.setColor(mInnerColor);mInnerPaint.setStyle(Paint.Style.STROKE);//实心mInnerPaint.setStrokeCap(Paint.Cap.ROUND);//圆角mTextPaint = new Paint();mTextPaint.setAntiAlias(true);mTextPaint.setStyle(Paint.Style.STROKE);mTextPaint.setColor(mStepTextColor);mTextPaint.setTextSize(mStepTextSize);}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);int width = MeasureSpec.getSize(widthMeasureSpec);int height = MeasureSpec.getSize(heightMeasureSpec);int widthMode = MeasureSpec.getMode(widthMeasureSpec);int heightMode = MeasureSpec.getMode(heightMeasureSpec);if (widthMode == MeasureSpec.AT_MOST && heightMode == MeasureSpec.AT_MOST) {//用户设置的是wrap_content,此时设置一个默认宽高100width = height = MeasureUtils.dp2px(200, this);}setMeasuredDimension(width > height ? height : width, width > height ? height : width);}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);int center = getWidth() / 2;int radius = getWidth() / 2 - mBorderWidth;RectF rectF = new RectF(mBorderWidth, mBorderWidth, center + radius, center + radius);canvas.drawArc(rectF, 135, 270, false, mOutPaint);if (mSeptMax == 0) return;float sweepAngle = (float) mSeptCurrent / mSeptMax;canvas.drawArc(rectF, 135, 270 * sweepAngle, false, mInnerPaint);String stepText = mSeptCurrent + "";Rect textBounds = new Rect();mTextPaint.getTextBounds(stepText, 0, stepText.length(), textBounds);int dx = getWidth() / 2 - textBounds.width() / 2;int baseLine = MeasureUtils.measureBaseLine(mTextPaint, stepText, this);canvas.drawText(stepText, dx, baseLine, mTextPaint);}public void setmSeptMax(int mSeptMax) {this.mSeptMax = mSeptMax;}public synchronized void setmSeptCurrent(int mSeptCurrent) {this.mSeptCurrent = mSeptCurrent;//重绘invalidate();}
}
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.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;import com.cyq.customview2.R;
import com.cyq.customview2.utils.MeasureUtils;@SuppressWarnings("all")
public class MyProgressBar extends View {private int mLiftColor = Color.parseColor("#F44336");private int mRightColor = Color.parseColor("#E0E0E0");private int mProgressTextColor = Color.parseColor("#616161");private int mProgressTextSize = 12;//px 后续再考虑需不需要转换成spprivate int mProgressBounds = 1;//pxprivate int mCurrentProgress, mMaxProgress = 100;//默认最大刻度为100private Paint mLeftPaint, mRightPaint, mTextPaint;public MyProgressBar(Context context) {this(context, null);}public MyProgressBar(Context context, @Nullable AttributeSet attrs) {this(context, attrs, 0);}public MyProgressBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.MyProgressBar);mLiftColor = array.getColor(R.styleable.MyProgressBar_leftColor, mLiftColor);mRightColor = array.getColor(R.styleable.MyProgressBar_rightColor, mRightColor);mProgressTextColor = array.getColor(R.styleable.MyProgressBar_progressTextColor, mProgressTextColor);mProgressTextSize = array.getDimensionPixelSize(R.styleable.MyProgressBar_progressTextSize, mProgressTextSize);array.recycle();mLeftPaint = new Paint();mLeftPaint.setAntiAlias(true);mLeftPaint.setColor(mLiftColor);mRightPaint = new Paint();mRightPaint.setAntiAlias(true);mRightPaint.setColor(mRightColor);mTextPaint = new Paint();mTextPaint.setAntiAlias(true);mTextPaint.setStyle(Paint.Style.STROKE);mTextPaint.setColor(mProgressTextColor);mTextPaint.setTextSize(mProgressTextSize);}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);int widht = MeasureSpec.getSize(widthMeasureSpec);int height = MeasureSpec.getSize(heightMeasureSpec);setMeasuredDimension(widht, height);}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);mRightPaint.setStrokeWidth(getHeight());RectF rightRect = new RectF(0, 0, getWidth(), getHeight());canvas.drawRoundRect(rightRect, getHeight() / 2, getHeight() / 2, mRightPaint);mLeftPaint.setStrokeWidth(getHeight());float progress = (float) mCurrentProgress / (mMaxProgress * 10);int radius = getHeight() / 2;RectF rectF = new RectF(0, 0, progress * getWidth(), getHeight());canvas.drawRoundRect(rectF, radius, radius, mLeftPaint);//画文字随着进度条右移String text = (float) mCurrentProgress / 10 + "%";int dx = getHeight() / 2;Rect textBounds = new Rect();mTextPaint.getTextBounds(text, 0, text.length(), textBounds);int baseLine = MeasureUtils.measureBaseLine(mTextPaint, text, this);canvas.drawText(text, progress * getWidth() + 10, baseLine, mTextPaint);}public void setProgress(int mCurrentProgress) {this.mCurrentProgress = mCurrentProgress;//重绘invalidate();}public void setMaxProgress(int mMaxProgress) {this.mMaxProgress = mMaxProgress;}public int getProgress() {return mCurrentProgress;}
}
3.为自定义View添加动画

首先在xml中使用我们的自定义布局和自定义属性

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context=".page3.QQSportActivity"><com.cyq.customview2.page3.QQStepViewandroid:id="@+id/custom_QQ_step"android:layout_width="200dp"android:layout_height="200dp"android:layout_gravity="center_horizontal"android:layout_marginTop="50dp"app:borderWidth="6dp"app:innerColor="@color/innerColor"app:outerColor="@color/outerColor"app:stepTextSize="30sp"android:layout_marginBottom="100dp"/><com.cyq.customview2.page3.MyProgressBarandroid:id="@+id/custom_progressbar"android:layout_width="match_parent"android:layout_height="20dp"android:layout_margin="50dp"app:leftColor="@color/innerColor"app:progressTextColor="@color/stepTextColor"app:progressTextSize="16sp"app:rightColor="@color/greyColor" />
</LinearLayout>

通过属性动画动态增加进度


import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.animation.DecelerateInterpolator;import com.cyq.customview2.R;import butterknife.BindView;
import butterknife.ButterKnife;public class QQSportActivity extends AppCompatActivity {@BindView(R.id.custom_QQ_step)QQStepView customQQStep;@BindView(R.id.custom_progressbar)MyProgressBar customProgressbar;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_qqsport);ButterKnife.bind(this);customQQStep.setmSeptMax(10000);//属性动画ValueAnimator valueAnimator = ObjectAnimator.ofFloat(0, 8765);valueAnimator.setDuration(2000);valueAnimator.setInterpolator(new DecelerateInterpolator());//插值器valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator animation) {float currentStep = (Float) animation.getAnimatedValue();customQQStep.setmSeptCurrent((int) currentStep);}});valueAnimator.start();//属性动画ValueAnimator valueAnimator2 = ObjectAnimator.ofFloat(0, 780);valueAnimator2.setDuration(2000);valueAnimator2.setInterpolator(new DecelerateInterpolator());//插值器valueAnimator2.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator animation) {float currentStep = (Float) animation.getAnimatedValue();customProgressbar.setProgress((int) currentStep);}});valueAnimator2.start();}
}

获取文字基线和sp,dp转xp的工具类如下;

import android.graphics.Paint;
import android.graphics.Rect;
import android.util.TypedValue;
import android.view.View;public class MeasureUtils {/*** drawText获取基线** @param textPaint* @param text* @param view* @return*/public static int measureBaseLine(Paint textPaint, String text, View view) {Rect textBounds = new Rect();textPaint.getTextBounds(text, 0, text.length(), textBounds);Paint.FontMetricsInt fontMetricsInt = textPaint.getFontMetricsInt();int dy = (fontMetricsInt.bottom - fontMetricsInt.top) / 2 - fontMetricsInt.bottom;int baseLine = view.getHeight() / 2 + dy;return baseLine;}public static int sp2px(int sp, View view) {return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp, view.getResources().getDisplayMetrics());}public static int dp2px(int dp, View view) {return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, view.getResources().getDisplayMetrics());}
}

后续待改进

1.sp,dp,xp的转换
2.进度文字接近100%时不向右边移动,并且文字和进度重叠部分动态变色

转载于:https://www.cnblogs.com/chenyangqi/p/9489115.html

QQ运动步数自定义ProgressBar相关推荐

  1. Android自定义View之仿QQ运动步数进度效果

    文章目录 前言 先看效果图 ![在这里插入图片描述](https://img-blog.csdnimg.cn/6e4ddec17933496ea4830fa08d8ffbe5.png?x-oss-pr ...

  2. 自定义View | 仿QQ运动步数进度效果

    项目GitHub地址 思路 固定不动的蓝色大圆弧 动画变动的红色小圆弧 中间的步数文字显示 相关的自定义属性 比如固定不动的大圆弧, 我们不能写死他的蓝色颜色属性, 要提供一个颜色的自定义属性给用户自 ...

  3. 自定义View之仿QQ运动步数进度效果

    前言 今天接着上一篇来写关于自定义View方面的东西,我是近期在学习整理这方面的知识点,所以把相关的笔记都放到这个Android自定义View的专栏里了,方便自己下次忘记的时候能回来翻翻,今天的内容是 ...

  4. android自定义计步器形状,Android自定义View仿QQ运动步数效果

    本文实例为大家分享了Android QQ运动步数的具体代码,供大家参考,具体内容如下 今天我们实现下面这样的效果: 首先自定义属性: 自定义View代码如下: /** * Created by Mic ...

  5. android 自定义view实现仿QQ运动步数进度效果

    最近公司在策划一个新的项目,原型还没出来,再说这公司人都要走没了,估计又要找工作了,所以必须要学习,争取每个写个关于自定义view方面的,这样几个月积累下来,也能学习到东西,今天就带来简单的效果,就是 ...

  6. android 自定义园动画,Android 自定View实现仿QQ运动步数圆弧及动画效果

    在之前的Android超精准计步器开发-Dylan计步中的首页用到了一个自定义控件,和QQ运动的界面有点类似,还有动画效果,下面就来讲一下这个View是如何绘制的. 1.先看效果图 2.效果图分析 功 ...

  7. 利用安卓SQLite修改QQ运动步数方法分享 简单粗暴

    这个方法简单粗暴,比昨天的安卓用户秒刷QQ运动步数教程+软件下载更简单.亲测百分百成功,根据教程图片的步骤找到文件进行编辑保存即可. 1.自行百度搜索"安卓SQLite汉化版"下载 ...

  8. 自定义View 仿QQ运动步数进度效果

    1. 概述   我记得QQ之前是有一个,运动步数的进度效果,今天打开QQ一看发现没有了.具体效果我也不清楚了,我就按照自己大概的印象写一下,这一期我们主要是熟悉Paint画笔的使用:    2. 效果 ...

  9. 【Android自定义View实战】之仿QQ运动步数圆弧及动画,Dylan计步中的控件StepArcView

    转载请注明出处:http://blog.csdn.net/linglongxin24/article/details/52936609 [DylanAndroid的csdn博客] 在之前的Androi ...

最新文章

  1. 盛大文学难逃“垄断”嫌疑,完美文学虎口夺食
  2. java泛型(二)、泛型的内部原理:类型擦除以及类型擦除带来的问题
  3. 第一个vue.js项目
  4. [css] 你有用过sass中的Mixin功能吗?它有哪些作用?
  5. 判断非负整数是否是3的倍数_五年级数学因数与倍数知识点汇总与解题方法技巧...
  6. 一文教你如何用 Python 将 iPhone “玩弄于股掌之中”!
  7. python 中self
  8. Android计算器简单实现及代码分析
  9. Eureka入口之DiscoveryClient
  10. 商品库存清单案例java_JAVA实现简单的商城库存清单
  11. 简单理解NLP中文分词
  12. 产量预测文献读后整理
  13. 用python放烟花咯
  14. 粤嵌开发板ARM电子相册
  15. 上海电机学院计算机类分数,2021年上海电机学院投档线及各省最低录取分数线统计表...
  16. sql注入的原理分析
  17. python入门程序有趣例子_10 个最值得 Python 新人练手的有趣项目
  18. D3.js【学习一】
  19. 中文注释 MariaDB my.cnf 大型服务器配置模板
  20. 【阅读源码系列】ConcurrentHashMap源码分析(JDK1.7和1.8)

热门文章

  1. 如果她的确睡自己床上
  2. 反问题_不适定_正则化
  3. 计算机毕业设计JavaH5乡镇疫情防控系统(源码+系统+mysql数据库+lw文档)
  4. M0001 a和b平方和
  5. 拼多多砍价算法 php
  6. 计算机视听觉机理和方法,【看点】 “视听觉信息的认知计算”重大研究计划 迎接人工智能新时代...
  7. 免费MD5解密网站,轻松破解md5密码,mysql5/mysql323,ntlm,salt密码
  8. 《SCDA:Adapting Object Detectors via Selective Cross-Domain Alignment》论文笔记
  9. Gstreamer推送摄像头数据到RTMP服务器的方法(SRS成功示例)
  10. 计算光线反射的reflect向量