背景

在网上看到一个效果,虽然很简单,但是做的很漂亮我很喜欢,正好在学习自定义View,于是拿来练练手。来看下效果,直接用的人家的效果图,后面给出连接,不过我做的是个简化版的,毕竟是拿来练手的。

分析View中的元素

  • 背景圆
  • 进度条弧线
  • 进度条头部的圆
  • 中间的进度文字

实现

  • 画一个空心的背景圆,需要圆心坐标、半径和宽度,这个很简单;
  • 绘制进度,需要计算出弧的圆心角度数、起始点、宽度(不能小于背景圆的宽度吧);
  • 进度头的圆是2个,内圆和外圆,圆心位置是关键,需要用到三角函数,也很简单;
  • 中间的文字绘制关键点是确定文字的起始位置;

确定需要的属性

新建res/values/attr.xml,定义如下属性

<declare-styleable name="CircleProgressView"><attr name="background_circle_width" format="dimension" /><attr name="background_circle_color" format="color" /><attr name="progress_width" format="dimension" /><attr name="progress_color" format="color" /><attr name="progress_percent" format="integer" /><attr name="progress_text_size" format="dimension" /><attr name="progress_text_color" format="color" /><attr name="progress_circle_width" format="dimension"/>
</declare-styleable>
复制代码

在构造方法中获取定义的属性

private void initAttrs(Context context, AttributeSet attributeSet) {TypedArray ta = context.obtainStyledAttributes(attributeSet, R.styleable.CircleProgressView);mBackgroundCircleWidth = ta.getDimension(R.styleable.CircleProgressView_background_circle_width, mBackgroundCircleWidth);mBackgroundCircleColor = ta.getColor(R.styleable.CircleProgressView_background_circle_color, mBackgroundCircleColor);mProgressWidth = ta.getDimension(R.styleable.CircleProgressView_progress_width, mProgressWidth);mProgressColor = ta.getColor(R.styleable.CircleProgressView_progress_color, mProgressColor);mProgressWidth = Math.max(mBackgroundCircleWidth, mProgressWidth);mProgressPercent = ta.getInt(R.styleable.CircleProgressView_progress_percent, 0);mProgressTextSize = ta.getDimension(R.styleable.CircleProgressView_progress_text_size, mProgressTextSize);mProgressTextColor = ta.getColor(R.styleable.CircleProgressView_progress_text_color, mProgressColor);mProgressCircleWidth = ta.getDimension(R.styleable.CircleProgressView_progress_circle_width, mProgressCircleWidth);ta.recycle();
}
复制代码

绘制自然需要画笔,初始化需要的画笔

private void initPaint() {mBackgroundCirclePaint = new Paint();mBackgroundCirclePaint.setAntiAlias(true);mBackgroundCirclePaint.setStyle(Paint.Style.STROKE);mBackgroundCirclePaint.setStrokeWidth(mBackgroundCircleWidth);mBackgroundCirclePaint.setColor(mBackgroundCircleColor);mRect = new RectF();mProgressPaint = new Paint();mProgressPaint.setAntiAlias(true);mProgressPaint.setStyle(Paint.Style.STROKE);mProgressPaint.setStrokeCap(Paint.Cap.ROUND);mProgressPaint.setStrokeWidth(mProgressWidth);mProgressPaint.setColor(mProgressColor);///mProgressCirclePaint = new Paint();mProgressCirclePaint.setAntiAlias(true);mProgressCirclePaint.setStyle(Paint.Style.STROKE);mProgressCirclePaint.setColor(mProgressColor);mProgressCirclePaint.setStrokeWidth(mProgressCircleWidth);//mProgressTextPaint = new Paint();mProgressTextPaint.setAntiAlias(true);mProgressTextPaint.setFakeBoldText(true);mProgressTextPaint.setTextSize(mProgressTextSize);mProgressTextPaint.setColor(mProgressTextColor);mTextRect = new Rect();
}
复制代码

确定位置

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);int widthMode = MeasureSpec.getMode(widthMeasureSpec);int heightMode = MeasureSpec.getMode(heightMeasureSpec);if (MeasureSpec.AT_MOST == widthMode || MeasureSpec.AT_MOST == heightMode) {ViewGroup.LayoutParams layoutParams = getLayoutParams();layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT;layoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT;setLayoutParams(layoutParams);}
}
复制代码

确定圆心和半径

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {super.onSizeChanged(w, h, oldw, oldh);mCenterX = w / 2;mCenterY = h / 2;mRadius = Math.min(w, h) / 3;mRect.set(mCenterX - mRadius, mCenterY - mRadius, mCenterX + mRadius, mCenterY + mRadius);
}
复制代码

onDraw中进行绘制,注释都写的很清楚了

@Override
protected void onDraw(Canvas canvas) {super.onDraw(canvas);//1.绘制底部的圆canvas.drawCircle(mCenterX, mCenterY, mRadius, mBackgroundCirclePaint);//2.绘制进度,-180度为起始点float mProgressAngel = 360 * mProgressPercent / 100;canvas.drawArc(mRect, -180, mProgressAngel, false, mProgressPaint);//3.绘制进度圆圈if (mProgressPercent > 0 && mProgressPercent < 100) {canvas.drawCircle((float) (mCenterX + mRadius * Math.cos((mProgressAngel - 180) / 360 * (2 * Math.PI))), (float) (mCenterY + mRadius * Math.sin((mProgressAngel - 180) / 360 * (2 * Math.PI))), mBackgroundCircleWidth, mProgressCirclePaint);canvas.drawCircle((float) (mCenterX + mRadius * Math.cos((mProgressAngel - 180) / 360 * (2 * Math.PI))), (float) (mCenterY + mRadius * Math.sin((mProgressAngel - 180) / 360 * (2 * Math.PI))), mBackgroundCircleWidth / 3, mBackgroundCirclePaint);}//4.绘制中间的文字String mText = mProgressPercent + "%";mProgressTextPaint.getTextBounds(mText, 0, mText.length(), mTextRect);canvas.drawText(mText, mCenterX - mTextRect.width() / 2, mCenterY + mTextRect.height() / 2, mProgressTextPaint);
}
复制代码

绘制没有动画,很生硬怎么办?

private void startAnimation() {if (mValueAnimator == null) {mValueAnimator = new ValueAnimator();mValueAnimator.setDuration(400);mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator animation) {mProgressPercent = (int) animation.getAnimatedValue();invalidate();}});}mValueAnimator.setIntValues(0, mProgressPercent);mValueAnimator.start();
}
复制代码

什么时候调用动画呢?我是在onAttachedToWindow中调用的动画,在onDetachedFromWindow中取消动画

@Override
protected void onDetachedFromWindow() {super.onDetachedFromWindow();if (mValueAnimator != null) {mValueAnimator.cancel();mValueAnimator = null;}
}
复制代码

只能在xml中设置进度数据怎么可以?提供个方法吧

public void setProgress(int progress) {mProgressPercent = progress;startAnimation();
}
复制代码

怎么使用呢?直接XML中

<com.example.administrator.circleprogressdemo.CircleProgressViewandroid:id="@+id/circle_progress_view"android:layout_width="200dp"android:layout_height="200dp"app:background_circle_width="6dp"app:progress_circle_width="6dp"app:progress_color="#FC7F03"app:progress_percent="28"app:progress_text_size="16sp"app:progress_width="2dp" />private int progress=0;@Override
protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);final CircleProgressView mCircleProgressView = (CircleProgressView) findViewById(R.id.circle_progress_view);SeekBar seekBar=(SeekBar) findViewById(R.id.seekBar);seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {@Overridepublic void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {MainActivity.this.progress=progress;}@Overridepublic void onStartTrackingTouch(SeekBar seekBar) {}@Overridepublic void onStopTrackingTouch(SeekBar seekBar) {mCircleProgressView.setProgress(progress);}});
}
复制代码

效果

代码和apk下载连接

gitee.com/Android_Wan…

原文连接

www.jianshu.com/p/bfe74a862…

CircleProgressView相关推荐

  1. Android鬼点子 CircleProgressView

    分享一个最近在项目中用到的一个视图,具体的效果如下图: 打包赠送一个带光晕的按钮效果. 但是因为时间比较紧,这两个控件封装的不是很好,使用的时候需要修改一些代码中的参数(代码中有详细的comment, ...

  2. Circle-Progress-View

    https://github.com/jakob-grabner/Circle-Progress-View 转载于:https://www.cnblogs.com/eustoma/p/4507476. ...

  3. 最新最全的 Android 开源项目合集(一)

    原文链接:https://github.com/opendigg/awesome-github-android-ui 抽屉菜单 MaterialDrawer ★7337 - 安卓抽屉效果实现方案 Si ...

  4. 自定义View:测量measure,布局layout,绘制draw

    1. 什么是View 在Android的官方文档中是这样描述的:表示了用户界面的基本构建模块.一个View占用了屏幕上的一个矩形区域并且负责界面绘制和事件处理. 手机屏幕上所有看得见摸得着的都是Vie ...

  5. Android自定义圆形进度条

    Android自定义圆形进度条 github地址:https://github.com/opq1289/CircleProgressView 效果图: 无动画: 有动画: 整圆: 切割圆: 具体步骤: ...

  6. 自定义控件android.r,Android控件架构与自定义控件

    前言 最近在开发的路上越走越远了,每天在看各位大神公众号更新内容是自定义View的时候,一些小的内容有点模具,决定回过头来温习一下过往的内容.此篇也是根据android群英传来总结的一篇文章. 1 A ...

  7. android uber源码,Uber SDK in android

    问题 I am trying to add an Uber 'request a ride' button in my android application. In my gradle build ...

  8. Android开源库

    PagerSlidingTabStrip 配合ViewPager使用的交互式页面指示器控件. leakcanary 它是一个Android和Java的内存泄露检测库,可以大幅度减少了开发中遇到的OOM ...

  9. GitHub 上受欢迎的 Android UI Library 整理(一)

    内容较多,可以用 ctrl+F 来搜索 抽屉菜单 https://github.com/mikepenz/MaterialDrawer ★7337 - 安卓抽屉效果实现方案 https://githu ...

最新文章

  1. 微信小程序 长按图片不出现菜单_微信更新,新功能上了热搜
  2. [Python爬虫] 在Windows下安装PIP+Phantomjs+Selenium
  3. Android RecyclerView 使用完全解析 体验艺术般的控件
  4. Visual Studio 2017 调试 windows server 2016 Docker Container
  5. Zookeeper 使用
  6. 自定义ActiveX组件在设计阶段,切换属性页后出现异常
  7. 信息学奥赛一本通 2019:【例4.4】求阶乘
  8. java毫秒 mysql秒_MySQL和Java时间毫秒之间的转换问题的总结
  9. b站测试岗怎么样_情商测试《大家一起察言观色》,一款适合作为B站测试题的游戏...
  10. 可拖拽的窗口(Vue)
  11. Java用HttpClient爬大学英语四六级考试成绩查询接口
  12. html鼠标悬停闪烁,鼠标悬停闪烁星星插件jQuery-canvas-sparkles
  13. idea怎么进行c语言编程_idea编写c语言
  14. PCM开发板模块实验指导--有刷直流马达正反转实验
  15. kube-controller-manager源码分析(三)之 Informer机制
  16. 12. linux系统管理(1)
  17. 更新 macOS Ventura ssh堡垒机报错:no matching host key type found. Their offer: ssh-rsa,ssh-dss
  18. 使用jquery ajax调用后台方法 有时候不调用回调函数
  19. 网络层:单播unicast 组播multicast 广播broadcast
  20. 干货 | 携程酒店Flutter性能优化实践

热门文章

  1. Dubbo -- 系统学习 笔记 -- 示例 -- 参数验证
  2. rocketmq单机搭建
  3. Orchard模块开发全接触3:分类的实现及内容呈现(Display)
  4. Tomcat 6.0.32 +Spring dbcp datasource关闭Tomcat出现严重异常
  5. OSPF的RID和DR/BDR的选举
  6. spring boot 整合mybatis 无法输出sql的问题
  7. 20180925-7 规格说明书-吉林市2日游
  8. 云计算或将逐步被认可
  9. 20天持续压测,告诉你云存储性能哪家更强?
  10. pdf文档出现乱码如何修改