先看一组加载效果图,有点粉粉的加载圈:

自定义这样的圆形加载圈还是比较简单的,主要是用到Canvans的绘制文本,绘制圆和绘制圆弧的api:
/**
* 绘制圆
* @param cx 圆心x坐标
* @param cy 圆心y坐标
* @param radius 圆的半径
* @param paint 画笔
*/
public void drawCircle(float cx, float cy, float radius, @NonNull Paint paint) {
...
}
/**
* 绘制圆弧
* @param oval 决定圆弧范围的矩形区域
* @param startAngle 开始角度
* @param sweepAngle 绘制的角度
* @param useCenter 是否需要连接圆心,true连接,false不连接
* @param paint 画笔
*/
public void drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter,Paint paint) {
...
}
/**
* 绘制文本
* @param text 需要绘制的字符串
* @param x 绘制文本起点x坐标,注意文本比较特殊,它的起点是左下角的x坐标
* @param y 绘制文本起点y坐标,同样是左下角的y坐标
* @param paint 画笔
*/
public void drawText(String text, float x, float y, Paint paint) {
...
}
开始绘图前需要考虑的以下几点:
1.获取控件的宽和高,这个是决定圆的半径大小的,半径大小等于宽高的最小值的1/2,为什么是最小值呢?因为这样就不会受布局文件中宽高属性不一样的影响,当然我们自己在使用的时候肯定是宽高都是会写成一样的,这样就刚好是一个正方形,绘制出来的圆就刚好在该正方形区域内.做了这样的处理,其他人在用的时候就不用当心圆会不会超出控件范围的情况了.
2.确定圆心的坐标,有了半径和圆心坐标就可以确定一个圆了,布局中的控件区域其实都是一个矩形区域,如果想要绘制出来的圆刚好处于控件的矩形区域内并且和矩形的最短的那条边相切,那么圆心坐标的就是该矩形宽高的1/2,即刚好位于矩形区域的中心点.
3.绘制圆弧,注意这里的圆弧指的是进度圈,看上面的示例图是有2种样式,分别是实心的加载圈和空心加载圈,这个其实就是paint的样式决定,如果是实心圆,paint设置为Paint.Style.FILL(填充模式),同时drawArc的useCenter设置为true;如果是空心圆则paint设置为Paint.Style.STROKE(线性模式),同时drawArc的useCenter设置为false即可.值得一提的是绘制空心圆的时候还需要考虑圆弧的宽度,宽度有多大将决定进度圈的厚度.因此在定义空心圆的矩形区域的时候需要减去进度圈的厚度,否则画出来的进度圈会超出控件的区域.
4.绘制文本,需要定位起始点,文本的起始点比较特殊,它是以左下角为起始点的,起点x坐标=圆心x坐标-文本宽度1/2;起始点y坐标=圆心y坐标+文本高度1/2;至于文本的宽高获取可以通过paint的getTextBounds()方法获取,具体等下看代码.
ok,直接上代码,注释已经很详细了.
圆形加载圈
public class CircleProgressView extends View {
private int width;//控件宽度
private int height;//控件高
private float radius;//半径
private float pointX;//圆心x坐标
private float pointY;//圆心y坐标
private int circleBackgroundColor;//背景颜色
private int circleBackgroundAlpha; //背景透明度
private int circleRingColor;//进度颜色
private int progressTextColor;//进度文本的颜色
private int progressTextSize;//进度文本的字体大小
private int circleRingWidth; //进度的宽度
private Paint mPaint;
private int progress;//进度值
private boolean isRingStyle;//是否是空心的圆环进度样式
public CircleProgressView(Context context) {
this(context, null);
}
public CircleProgressView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CircleProgressView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
circleBackgroundColor = Color.WHITE;
circleRingColor = Color.parseColor("#3A91FF");
progressTextColor = Color.BLACK;
circleBackgroundAlpha = 128;
progressTextSize = 32;
circleRingWidth = 10;
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setStyle(Paint.Style.FILL);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
width = getMeasuredWidth();
height = getMeasuredHeight();
radius = Math.min(width, height) / 2.0f;
pointX = width / 2.0f;
pointY = height / 2.0f;
}
@Override
protected void onDraw(Canvas canvas) {
drawBackground(canvas);
drawCircleRing(canvas);
drawProgressText(canvas);
}
/**
* 绘制背景色
*
* @param canvas
*/
private void drawBackground(Canvas canvas) {
mPaint.setColor(circleBackgroundColor);
mPaint.setAlpha(circleBackgroundAlpha);
canvas.drawCircle(pointX, pointY, radius, mPaint);
}
/**
* 绘制圆环
*
* @param canvas
*/
private void drawCircleRing(Canvas canvas) {
mPaint.setColor(circleRingColor);
RectF oval = new RectF();
if (isRingStyle) {
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(circleRingWidth);
mPaint.setStrokeCap(Paint.Cap.ROUND);
//注意:定义圆环的矩形区域是需要考虑圆环的宽度
oval.left = circleRingWidth / 2.0f;
oval.top = height / 2.0f - radius + circleRingWidth / 2.0f;
oval.right = 2 * radius - circleRingWidth / 2.0f;
oval.bottom = height / 2.0f + radius - circleRingWidth / 2.0f;
canvas.drawArc(oval, 0, 360 * progress / 100, false, mPaint);
} else {
mPaint.setStyle(Paint.Style.FILL);
oval.left = 0;
oval.top = height / 2.0f - radius;
oval.right = 2 * radius;
oval.bottom = height / 2.0f + radius;
canvas.drawArc(oval, 0, 360 * progress / 100, true, mPaint);
}
}
/**
* 绘制进度文本
*
* @param canvas
*/
private void drawProgressText(Canvas canvas) {
mPaint.setColor(progressTextColor);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setTextSize(progressTextSize);
Rect textBound = new Rect();
String text = progress + "%";
//获取文本的矩形区域到textBound中
mPaint.getTextBounds(text, 0, text.length(), textBound);
int textWidth = textBound.width();
int textHeight = textBound.height();
float x = pointX - textWidth / 2.0f;
float y = pointY + textHeight / 2.0f;
canvas.drawText(text, x, y, mPaint);
}
/**
* 更新进度
*
* @param progress
*/
public void setValue(int progress) {
this.progress = progress;
invalidate();
}
/**
* 设置进度圆环的样式
*
* @param isRing true是空心的圆环,false表示实心的圆环
*/
public void setCircleRingStyle(boolean isRing) {
this.isRingStyle = isRing;
}
/**
* 设置背景透明度
*
* @param alpha 0~255
*/
public void setCircleBackgroundAlpha(int alpha) {
this.circleBackgroundAlpha = alpha;
}
/**
* 设置进度文本的大小
* @param progressTextSize
*/
public void setProgressTextSize(int progressTextSize) {
this.progressTextSize = progressTextSize;
}
/**
* 设置进度文本的颜色
* @param progressTextColor
*/
public void setProgressTextColor(int progressTextColor) {
this.progressTextColor = progressTextColor;
}
}
测试类
public class MainActivity extends AppCompatActivity {
private CircleProgressView mCircleProgressView;
private int progress;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mCircleProgressView = (CircleProgressView) findViewById(R.id.progressView);
mCircleProgressView.setCircleRingStyle(false);//实心圆
HandlerThread thread = new HandlerThread("draw-thread");
thread.start();
Handler tHandler = new Handler(thread.getLooper()) {
@Override
public void handleMessage(Message msg) {
runOnUiThread(new Runnable() {
@Override
public void run() {
mCircleProgressView.setValue(progress++);
}
});
if (progress <100) {
sendEmptyMessageDelayed(0, 100);
}
}
};
tHandler.sendEmptyMessage(0);
}
}
XML使用方式
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/colorAccent" tools:context="mchenys.net.csdn.blog.progressview.MainActivity"> <mchenys.net.csdn.blog.progressview.CircleProgressView android:id="@+id/progressView" android:layout_width="100dp" android:layout_height="200dp" android:layout_centerInParent="true" /> </RelativeLayout>
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
# android百分比加载圈
# android百分比加载
# android加载圈
# Android实现加载圈
# Android实现仿iOS菊花加载圈动画效果
# Android自定义加载圈动画效果
# Android自定义加载圈的方法
# 加载
# 设置为
# 都是
# 起始点
# 的是
# 是一个
# 最小值
# 是有
# 中心点
# 会不会
# 有多
# 可以通过
# 自定义
# 还需要
# 几点
# 那条
# 一提
# 指的是
# 最短
# 画出
相关文章:
如何通过虚拟主机空间快速建站?
如何快速查询网站的真实建站时间?
在线ppt制作网站有哪些软件,如何把网页的内容做成ppt?
北京网页设计制作网站有哪些,继续教育自动播放怎么设置?
简历在线制作网站免费,免费下载个人简历的网站是哪些?
c++ stringstream用法详解_c++字符串与数字转换利器
无锡营销型网站制作公司,无锡网选车牌流程?
如何快速选择适合个人网站的云服务器配置?
哪家制作企业网站好,开办像阿里巴巴那样的网络公司和网站要怎么做?
Swift开发中switch语句值绑定模式
北京的网站制作公司有哪些,哪个视频网站最好?
nginx修改上传文件大小限制的方法
,柠檬视频怎样兑换vip?
建站之星后台管理:高效配置与模板优化提升用户体验
电商网站制作公司有哪些,1688网是什么意思?
历史网站制作软件,华为如何找回被删除的网站?
详解ASP.NET 生成二维码实例(采用ThoughtWorks.QRCode和QrCode.Net两种方式)
建站一年半SEO优化实战指南:核心词挖掘与长尾流量提升策略
制作电商网页,电商供应链怎么做?
清除minerd进程的简单方法
详解免费开源的DotNet二维码操作组件ThoughtWorks.QRCode(.NET组件介绍之四)
建站主机选购指南:核心配置优化与品牌推荐方案
微信小程序 五星评分(包括半颗星评分)实例代码
网站网页制作电话怎么打,怎样安装和使用钉钉软件免费打电话?
代刷网站制作软件,别人代刷火车票靠谱吗?
国美网站制作流程,国美电器蒸汽鍋怎么用官方网站?
宝塔建站助手安装配置与建站模板使用全流程解析
潍坊网站制作公司有哪些,潍坊哪家招聘网站好?
建站主机助手选型指南:2025年热门推荐与高效部署技巧
较简单的网站制作软件有哪些,手机版网页制作用什么软件?
深圳 网站制作,深圳招聘网站哪个比较好一点啊?
长沙企业网站制作哪家好,长沙水业集团官方网站?
C++如何将C风格字符串(char*)转换为std::string?(代码示例)
建站之星如何实现五合一智能建站与营销推广?
孙琪峥织梦建站教程如何优化数据库安全?
黑客入侵网站服务器的常见手法有哪些?
建站org新手必看:2024最新搭建流程与模板选择技巧
零服务器AI建站解决方案:快速部署与云端平台低成本实践
C#怎么创建控制台应用 C# Console App项目创建方法
武汉网站如何制作,黄黄高铁武穴北站途经哪些村庄?
如何通过二级域名建站提升品牌影响力?
大连网站制作费用,大连新青年网站,五年四班里的视频怎样下载啊?
如何通过老薛主机一键快速建站?
如何快速搭建高效WAP手机网站吸引移动用户?
广平建站公司哪家专业可靠?如何选择?
Avalonia如何实现跨窗口通信 Avalonia窗口间数据传递
如何在景安服务器上快速搭建个人网站?
如何快速完成中国万网建站详细流程?
建站为何优先选择香港服务器?
天河区网站制作公司,广州天河区如何办理身份证?需要什么资料有预约的网站吗?
*请认真填写需求信息,我们会在24小时内与您取得联系。