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

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

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

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

<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="ProgressView">
<!--circleColor 设置圆形边框的颜色 sweepColor设置扇形变换的颜色
startAngle 设置起始角度 sweepStep 设置变换的步长-->
<attr name="circleColor" format="color|reference"></attr>
<attr name="sweepColor" format="color|reference"></attr>
<attr name="startAngle" format="integer"></attr>
<attr name="sweepStep" format="integer"></attr>
<attr name="padding" format="integer"></attr>
</declare-styleable>
</resources>

可以看到,<declare-styleable>标签中的name属性是为了方便我们获取AttributeSet时候使用,而<attr>标签中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 ? 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_width="warp_content"
//获取屏幕像素
float density = getResources().getDisplayMetrics().density;
wSize = (int) (DEFAULT_WIDTH * density);
hSize = (int) (DEFAULT_HEIGHT * density);
break;
//当在xml中指定控件的宽高为match_parent或者指定数值的宽高时,回调以下代码
case MeasureSpec.EXACTLY://android:layout_width="match_parent" android:layout_width="40dp"
wSize = hSize = Math.min(wSize, hSize);
break;
}
//只要重写onMeasure()方法,一定要调用以下方法,不然会报错
setMeasuredDimension(wSize, hSize);
}
}

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

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

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.yztc.customprogressview.MainActivity">
<com.yztc.customprogressview.ProgressView
android:id="@+id/pv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#0000ff"
app:padding="20"
app:circleColor="#aa0000"
app:sweepColor="#00aa00"
app:sweepStep="1"
app:startAngle="180"
/>
</RelativeLayout>

需要注意的是我们需要在布局的跟标签下面加上这么一段代码: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效果,希望对大家有所帮助,如果大家有任何疑问欢迎给我留言,小编会及时回复大家的!

(0)

相关推荐

  • Android使用Dialog风格弹出框的Activity

    在Android中经常会遇到需要使用Dialog风格弹出框的activity,首先我们可能会首先想到的是在XML布局文件中设置android:layout_height="wrap_content"属性,让activity的高度自适应,显然这还不行,我们还需要为其DialogActivity设置自定义一个样式 <style name="dialogstyle"> <!--设置dialog的背景--> <item name="a

  • Android利用Theme自定义Activity间的切换动画

    大多Android系统默认Activity间的动画切换效果为,右边滑入,左边滑出:有时候我们的需求可能是要求所有Activity的切换为淡入淡出的效果,这时候就可能需要改变一下默认的切换风格. 下面开始实现: 首先在res文件夹下建立anim文件夹,然后在里面建立fade_in.xml和fade_out.xml两个动画资源 fade_in.xml <?xml version="1.0" encoding="utf-8"?> <alpha xmlns

  • Android带清除功能的输入框控件EditTextWithDel

    记录下一个很实用的小控件EditTextWithDel,就是在Android系统的输入框右边加入一个小图标,点击小图标可以清除输入框里面的内容,由于Android原生EditText不具备此功能,所以要想实现这一功能我们需要重写EditText. 效果图如下: 主要的思路就是为右边的图片设置监听,点击右边的图片清除输入框的内容并隐藏删除图标,因为我们不能直接给EditText设置点击事件,所以我们用记住我们按下的位置来模拟点击事件,用输入框的的onTouchEvent()方法来模拟. packa

  • Android和iOS 测试五个最好的开源自动化工具

    自动化测试在产品测试上有着非常重要的作用.实现测试自动化有多种积极的方式,包括最大限度地减少测试执行时间:在关键的发布阶段,用更少的时间确保更大的覆盖范围:在产品开发阶段,可靠又重复性地运行以确保没有引进回归问题.最大限度地减少重复性回归测试循环时的人为错误和疏忽的风险. 在市场上有很多可用的工具,开源的或要付费的.虽然付费和开源工具各有利弊,但是后者在自动化测试社区得到了广泛的应用.根据项目需求来选择合适的自动化工具是非常棘手的. 下面介绍5个最佳的iOS和Android开源自动化工具. 1.

  • 解决Android Studio导入项目非常慢的办法

    前言 大家都知道Android Studio目前已经更新到2.0 Preview 6了,作为Google大力推崇的开发工具,相对于Eclipse ADT有着不可比拟的优势.然而在实际使用时,依然有不少不爽的地方.Android Studio原生支持使用Gradle来构建项目本是个不错的想法,使用动态语言Groovy定义项目构建过程,避免了build.xml文件的繁琐定义.但是Gradle的二进制包体积较大,而且用户可能按照了不同的Gradle版本,构建时可能会出现各种问题.因此又提出了Gradl

  • Android使用自定义View绘制渐隐渐现动画

    实现了一个有趣的小东西:使用自定义View绘图,一边画线,画出的线条渐渐变淡,直到消失.效果如下图所示: 用属性动画或者渐变填充(Shader)可以做到一笔一笔的变化,但要想一笔渐变(手指不抬起边画边渐隐),没在Android中找到现成的API可用.所以,自己做了一个. 基本的想法是这样的: 在View的onTouchEvent中记录触摸点,生成一条一条的线LineElement,放在一个List中.给每个LineElement配置一个Paint实例. 在onDraw中绘制线段. 变换LineE

  • Android自定义View绘制随机生成图片验证码

    本篇文章讲的是Android自定义View之随机生成图片验证码,开发中我们会经常需要随机生成图片验证码,但是这个是其次,主要还是想总结一些自定义View的开发过程以及一些需要注意的地方. 按照惯例先看看效果图: 一.先总结下自定义View的步骤: 1.自定义View的属性 2.在View的构造方法中获得我们自定义的属性 3.重写onMesure 4.重写onDraw 其中onMesure方法不一定要重写,但大部分情况下还是需要重写的 二.View 的几个构造函数 1.public CustomV

  • Android实现游戏中的渐隐和渐现动画效果

    1实现渐隐的动画 在程序中实现可以通过如下方式 View view = new View(context);//执行动画的View AlphaAnimation aa = new AlphaAnimation(1.0f, 0.0f);//创建一个AlphaAnimation 对象,渐变从1->0 aa.setDuration(1500);//设置持续时间 aa.setFillAfter(true);//设置这个View最后的状态,由于是从1->0,所以最后的是消失状态(最后是看不到见这个Vie

  • Android QQ新用户注册界面绘制

    先看看效果图: 问题: 1.下拉列表(因为还没看到这里...) 2.标题栏显示问题 3.按钮的 Enable 设置 .......... 以下是代码: 布局 fragment_main(问题1) <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layo

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

    先给大家展示下效果图,如果感觉不错,请参考实现思路: 我们要实现一个自定义的再一个圆形中绘制一个弧形的自定义View,思路是这样的: 先要创建一个类ProgressView,继承自View类,然后重写其中的两个构造方法,一个是一个参数的,一个是两个参数的,因为我们要在xml文件中使用该自定义控件,所以必须要定义这个两个参数的构造函数.创建完了这个类后,我们先不去管它,先考虑我们实现的这个自定义View,我们想让它的哪些部分可以由使用者自己指定,比如说这个Demo中我们让他的外面圆的外边框颜色和宽

  • Android自定义View实现APP启动页倒计时效果

    Android自定义View实现APP启动页倒计时效果,供大家参考,具体内容如下 之前也是做过APP启动页的倒计时效果,但是只有文字变化,没有动画效果,这次通过使用自定义View控件来制作一个带有动画效果的倒计时. 倒计时效果的基本思路如下: Canvas提供了绘制弧形的方法,drawArc(),使用这个方法通过定时刷新计算当前弧形的角度,就可以模拟出倒计时的动画效果,同时借助drawText()方法可以实现倒计时文字.(1)继承View(2)使用canvas的drawArc()来绘制弧形,模拟

  • Android 自定义view实现进度条加载效果实例代码

    这个其实很简单,思路是这样的,就是拿view的宽度,除以点的点的宽度+二个点 之间的间距,就可以算出大概能画出几个点出来,然后就通过canvas画出点,再然后就是每隔多少时间把上面移动的点不断的去改变它的坐标就可以, 效果如下: 分析图: 代码如下: package com.example.dotloadview; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Bit

  • Android 自定义View之边缘凹凸的优惠券效果的开发过程

    本篇文章讲的是自定义View之边缘凹凸的优惠券效果,之前有见过很多优惠券的效果都是使用了边缘凹凸的样式.和往常一样,主要总结一下在自定义View的开发过程中需要注意的一些地方. 按照惯例,我们先来看看效果图 一.写代码之前,我们先弄清楚view的启动过程: 之所以想要弄清楚这个问题是因为代码里面用到了onSizeChanged()方法,一开始我有点犹豫onSizeChanged是在什么时候启动的呢,所以看看View的启动流程吧 package per.lijuan.coupondisplayvi

  • Android自定义View实现loading动画加载效果

    项目开发中对Loading的处理是比较常见的,安卓系统提供的不太美观,引入第三发又太麻烦,这时候自己定义View来实现这个效果,并且进行封装抽取给项目提供统一的loading样式是最好的解决方式了. 先自定义一个View,继承自LinearLayout,在Layout中,添加布局控件 /** * Created by xiedong on 2017/3/7. */ public class Loading_view extends LinearLayout { private Context m

  • Android 自定义View实现任意布局的RadioGroup效果

    前言 RadioGroup是继承LinearLayout,只支持横向或者竖向两种布局.所以在某些情况,比如多行多列布局,RadioGroup就并不适用 . 本篇文章通过继承RelativeLayout实现自定义RadioGroup,实现RadioButton的任意布局.效果图如下: 代码(RelativeRadioGroup) /** * Author : BlackHao * Time : 2018/10/26 10:46 * Description : 自定义 RadioGroup */ p

  • Android自定义view实现仿抖音点赞效果

    前言 学习自定义view,想找点东西耍一下,刚好看到抖音的点赞效果不错,尝试一下. 抖音效果: 话不多说,先上代码: public class Love extends RelativeLayout { private Context mContext; float[] num = {-30, -20, 0, 20, 30};//随机心形图片角度 public Love(Context context) { super(context); initView(context); } public

  • Android自定义View实现抖音飘动红心效果

    本文实例为大家分享了Android自定义View实现抖音飘动红心效果的具体代码,供大家参考,具体内容如下 自定义View--抖音飘动红心 效果展示 动画效果 使用自定义view完成红心飘动效果 View实现 动画:属性动画(位移+缩放+透明度+旋转) + 随机数:(属性动画参数+颜色选取) View /** * 飘心效果 * 1.创建ImageView * 2.ImageView执行组合动画 * 3.动画执行完成后销毁View */ public class FlyHeartView exten

  • Android自定义View模仿即刻点赞数字切换效果实例

    目录 即刻点赞展示 自己如何实现这种数字切换呢? 效果展示 源码 总结 即刻点赞展示 点赞的数字增加和减少并不是整个替换,而是差异化替换.再加上动画效果就看的很舒服. 自己如何实现这种数字切换呢? 下面用一张图来展示我的思路: 现在只需要根据这张图,写出对应的动画即可. 分为2种场景: 数字+1: 差异化的数字从3号区域由渐变动画(透明度 0- 255) + 偏移动画 (3号区域绘制文字的基线,2号区域绘制文字的基线),将数字移动到2号位置处 差异化的数字从2号区域由渐变动画(透明度 255-

  • Android自定义View实现简单水波纹效果

    本文实例为大家分享了Android自定义View实现水波纹效果的具体代码,供大家参考,具体内容如下 效果如下: 原理 控制代码 //这里用的kotlin //主线程刷新控件  val mHandler = object : Handler() {         override fun handleMessage(msg: Message?) {             waterRippleView.refreshView()         }      //开启动画,开线程,延时刷新pe

随机推荐