热门标签 | HotTags
当前位置:  开发笔记 > 运维 > 正文

Android自定义View实现简单的圆形Progress效果

这篇文章主要介绍了Android自定义View实现简单的圆形Progress效果的相关资料,非常不错,具有参考借鉴价值,需要的朋友可以参考下

先给大家展示下效果图,如果感觉不错,请参考实现思路:

我们要实现一个自定义的再一个圆形中绘制一个弧形的自定义View,思路是这样的:

  先要创建一个类ProgressView,继承自View类,然后重写其中的两个构造方法,一个是一个参数的,一个是两个参数的,因为我们要在xml文件中使用该自定义控件,所以必须要定义这个两个参数的构造函数。创建完了这个类后,我们先不去管它,先考虑我们实现的这个自定义View,我们想让它的哪些部分可以由使用者自己指定,比如说这个Demo中我们让他的外面圆的外边框颜色和宽度,还有扇形部分的颜色,扇形增长的速度等等属性,这时候我们要在项目工程目录的res/values目录下创建一个资源文件命名为attrs(注意,名字随意,只是大多数情况下都这么叫而已),然后我们在这个资源文件中添加我们想要的属性,如下:

<&#63;xml version="1.0" encoding="utf-8"&#63;>









可以看到,标签中的name属性是为了方便我们获取AttributeSet时候使用,而标签中name,则是我们希望控件可以自定义的属性部分,类似于xml文件中的android:name=""等标签的使用。format属性是设置该属性可以接受什么类型的参数。

定义好了自定义资源类,我们开始写ProgressView中的主要代码:

package com.yztc.customprogressview;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;
/**
* 自定义的
*/
public class ProgressView extends View {
private int sweepStep = 10;//扇形变换的步长(就是角度)
private int padding = 40;//外边框距离扇形的距离 填充
private int circleColor = Color.GRAY;//边框的颜色
private int sweepColor = Color.BLUE;//扇形颜色
private int startAngle = 90;//起始角度
//设置外边框圆的边框粗细
private int storke = 20;
private int sweepAngle = 0;//扫过的角度
private static final int DEFAULT_WIDTH = 200;
private static final int DEFAULT_HEIGHT = 200;
public ProgressView(Context context) {
super(context);
}
//如果要在xml文件中使用该自定义控件,则必须重写两个参数的构造函数
//因为我们使用自定义的属性的时候,会默认传递过来一个AttributeSet集合
public ProgressView(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.ProgressView);
if (array != null) {
//获取我们在xml中设置的各个自定义属性
sweepStep = array.getInteger(R.styleable.ProgressView_sweepStep, sweepStep);
padding = array.getInteger(R.styleable.ProgressView_padding, padding);
circleColor = array.getColor(R.styleable.ProgressView_circleColor, circleColor);
sweepColor = array.getColor(R.styleable.ProgressView_sweepColor, sweepColor);
startAngle = array.getInteger(R.styleable.ProgressView_startAngle, startAngle);
//回收TypeArray资源
array.recycle();
}
}
/**
* 先绘制外边框 --内部扇形
*
* @param canvas
*/
@Override
protected void onDraw(Canvas canvas) {
Paint mPaint = new Paint();
mPaint.setAntiAlias(true); //设置抗锯齿
//绘制外层的圆框
mPaint.setColor(circleColor);
mPaint.setStrokeWidth(storke);
mPaint.setStyle(Paint.Style.STROKE);//设置圆形为空心的圆
//这里我们得到控件的Height和Width,根据Heigh和Width来确定圆心的位置,来绘制外层圆
canvas.drawCircle(getWidth() / 2, getWidth() / 2, getWidth() / 2 - storke / 2, mPaint);
// Log.d("tag", "onDraw: "+getWidth());
invalidate();//请求重新绘制view
//绘制内部的扇形
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
mPaint.setColor(sweepColor);
/*
drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter,Paint paint)
RectF oval 指定扇形的矩形容器对象 指定圆弧的外轮廓的矩形
float startAngle 表示圆弧的起始角度
float sweepAngle 表示圆弧走过扫过的角度 顺时针方向
boolean useCenter 如果设置为true 在绘制圆弧时将圆心包括在内,是指以一个固定的圆心来绘制弧形(扇形),
如果指定为false,则不规则绘制扇形
Paint paint 画笔 颜色 填充
public RectF(float left, float top, float right, float bottom)
float left 矩形的左边点(左切点)的x坐标
float top 矩形上边点(上切点)的y轴坐标
float right, 矩形的右边点(右切点)的x坐标
float bottom 矩形的下边点(下切点)的y坐标
*/
//RectF中的四个参数,分别对应其内切圆的四个切点的坐标
RectF rectF = new RectF(padding + storke, padding + storke, getWidth() - padding - storke, getWidth() - padding - storke);
canvas.drawArc(rectF, startAngle, sweepAngle, true, mPaint);
sweepAngle += sweepStep;//根据步长更新扫过的角度
sweepAngle = sweepAngle > 360 &#63; 0 : sweepAngle;
invalidate();//重绘view
}
//因为我们是继承的View来自定义的View,所以onMeasure()方法要重写
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int wMode = MeasureSpec.getMode(widthMeasureSpec);
int hMode = MeasureSpec.getMode(heightMeasureSpec);
int wSize = MeasureSpec.getSize(widthMeasureSpec);
int hSize = MeasureSpec.getSize(heightMeasureSpec);
//因为绘制的是圆,所以判断一下高度或者宽度中的一个就可以。
switch (wMode) {
case MeasureSpec.AT_MOST://android:layout_
//获取屏幕像素
float density = getResources().getDisplayMetrics().density;
wSize = (int) (DEFAULT_WIDTH * density);
hSize = (int) (DEFAULT_HEIGHT * density);
break;
//当在xml中指定控件的宽高为match_parent或者指定数值的宽高时,回调以下代码
case MeasureSpec.EXACTLY://android:layout_ android:layout_
wSize = hSize = Math.min(wSize, hSize);
break;
}
//只要重写onMeasure()方法,一定要调用以下方法,不然会报错
setMeasuredDimension(wSize, hSize);
}
}

我们先画一个外部的圆,也就是都用drawCircle()方法,这里我们调用getWidth(),getHeight()表示得到布局中设置的控件的尺寸,因为是圆,所以可以使用getWidth()/2来表示圆心位置。而画内部弧形的时候,确定其圆心位置,左部点的坐标是外面圆的边框加上弧形与原的间距padding来确定,右侧点的x坐标则是getWidth()得到总长度,减去边框宽度,再减去padding得到,上边距和下边距同样,不明白的画一个图立马明白。大部分不好理解的地方都有注释,只要认真看不会看不明白的~

然后就是在布局中引入我们的自定义View了:

<&#63;xml version="1.0" encoding="utf-8"&#63;>


需要注意的是我们需要在布局的跟标签下面加上这么一段代码:xmlns:app="http://schemas.android.com/apk/res-auto"

用来指定我们可以使用自己再attrs中自定义的属性啦~,使用的形式就是app:你定义的属性。当然,这个app也不是固定的写法,只要跟上面你加的那段代码的xmlns后面的字段一致就可以了~

还有需要注意的是:

默认使用Canvas类的drawCircle()方法来画圆的时候,圆的半径是你指定的半径,再加上一半的边长,比如你的边框size=10,radius=50,则实际空心部分的半径为55.注意这点,否则画出来的圆的四个切点位置会与其他位置有些不一样,类似出现锯齿的效果。具体请看drawCircle()的Rect边框问题。

以上所述是小编给大家介绍的Android自定义View实现简单的圆形Progress效果,希望对大家有所帮助,如果大家有任何疑问欢迎给我留言,小编会及时回复大家的!


推荐阅读
  • Android 九宫格布局详解及实现:人人网应用示例
    本文深入探讨了人人网Android应用中独特的九宫格布局设计,解析其背后的GridView实现原理,并提供详细的代码示例。这种布局方式不仅美观大方,而且在现代Android应用中较为少见,值得开发者借鉴。 ... [详细]
  • 深入解析Android自定义View面试题
    本文探讨了Android Launcher开发中自定义View的重要性,并通过一道经典的面试题,帮助开发者更好地理解自定义View的实现细节。文章不仅涵盖了基础知识,还提供了实际操作建议。 ... [详细]
  • 优化ListView性能
    本文深入探讨了如何通过多种技术手段优化ListView的性能,包括视图复用、ViewHolder模式、分批加载数据、图片优化及内存管理等。这些方法能够显著提升应用的响应速度和用户体验。 ... [详细]
  • 本文详细介绍了如何使用Spring Boot进行高效开发,涵盖了配置、实例化容器以及核心注解的使用方法。 ... [详细]
  • Android LED 数字字体的应用与实现
    本文介绍了一种适用于 Android 应用的 LED 数字字体(digital font),并详细描述了其在 UI 设计中的应用场景及其实现方法。这种字体常用于视频、广告倒计时等场景,能够增强视觉效果。 ... [详细]
  • RecyclerView初步学习(一)
    RecyclerView初步学习(一)ReCyclerView提供了一种插件式的编程模式,除了提供ViewHolder缓存模式,还可以自定义动画,分割符,布局样式,相比于传统的ListVi ... [详细]
  • 2023年京东Android面试真题解析与经验分享
    本文由一位拥有6年Android开发经验的工程师撰写,详细解析了京东面试中常见的技术问题。涵盖引用传递、Handler机制、ListView优化、多线程控制及ANR处理等核心知识点。 ... [详细]
  • 本文介绍如何在 Unity 的 XML 配置文件中,将参数传递给自定义生命周期管理器的构造函数。我们将详细探讨 CustomLifetimeManager 类的实现及其配置方法。 ... [详细]
  • 解决JAX-WS动态客户端工厂弃用问题并迁移到XFire
    在处理Java项目中的JAR包冲突时,我们遇到了JaxWsDynamicClientFactory被弃用的问题,并成功将其迁移到org.codehaus.xfire.client。本文详细介绍了这一过程及解决方案。 ... [详细]
  • 本文详细介绍了W3C标准盒模型和IE传统盒模型的区别,探讨了CSS3中box-sizing属性的使用方法及其在布局中的重要性。通过实例分析,帮助读者更好地理解和应用这一关键概念。 ... [详细]
  • 360SRC安全应急响应:从漏洞提交到修复的全过程
    本文详细介绍了360SRC平台处理一起关键安全事件的过程,涵盖从漏洞提交、验证、排查到最终修复的各个环节。通过这一案例,展示了360在安全应急响应方面的专业能力和严谨态度。 ... [详细]
  • 题库来源:安全生产模拟考试一点通公众号小程序G3锅炉水处理报名考试是安全生产模拟考试一点通生成的,G3锅炉水处理证模拟考试题库是根据G3锅炉水处理最新 ... [详细]
  • 本文介绍如何通过Windows批处理脚本定期检查并重启Java应用程序,确保其持续稳定运行。脚本每30分钟检查一次,并在需要时重启Java程序。同时,它会将任务结果发送到Redis。 ... [详细]
  • MySQL中枚举类型的所有可能值获取方法
    本文介绍了一种在MySQL数据库中查询枚举(ENUM)类型字段所有可能取值的方法,帮助开发者更好地理解和利用这一数据类型。 ... [详细]
  • 本文详细探讨了Netty中Future及其子类的设计与实现,包括其在并发编程中的作用和具体应用场景。我们将介绍Future的继承体系、关键方法的实现细节,并讨论如何通过监听器和回调机制来处理异步任务的结果。 ... [详细]
author-avatar
手机用户2502863701
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有