关于自定义View:

好了,吐槽时间到.自定义view是Android开发知识体系中的重点,也是难点.好多小伙伴(也包括我)之前对自定义view也是似懂非懂.那种感觉老难受了.因此作为社会主义好青年,怎么能够不加钻研呢?那可不是你我的风格哦.因此,我将通过几篇博文来展示自定义view的基本流程.另外,我说一下,关于自定义view的学习呢,我们还是得动手敲代码,实践出真知!因此,我强烈建议同志们先从最基本,最简单的自定义view画起,这样在自定义view的过程中,才能了解其原理,从而为以后画出各种各样炫酷的view,打下基础. OK,本片博文将通过自定义圆环,带你去探索自定义view的奥妙…

俗话说无规矩不成方圆,无图全是扯淡!

实现的效果图:

自定义圆环流程:

上图就是自定义圆环的指导图(非常重要).下面就根据这个神图,来向大家介绍下如何自定义圆环?
 
Step 1:画里面的白色小圆
事实上,里面的白色圆圈如果不画的话,我们也可以画圆环,但是,但是,但是,重要的事情说三遍.强烈建议不要遗漏.因为在画圆时候,我们能对半径等参数有更加清晰,便于后续圆环的绘制.再说了,画个圆又咋了,无非几行代码的事.

Step 2:画矩形(正方形)
这个正方形是画圆环的最核心的步骤.如果想要画出图中绿色的圆环,这个正方形是必须的.注意看正方形是红边圆圈的外接圆.而这个所谓的红色圆圈正好处在圆环中间位置.图中一目了然,不在瞎啰嗦了.

Step 3:画圆环
其实到了这一步,我们的圆环就已经出来了.此处我们可以做的是圆环的属性的调节,比如,你可以调节圆环的颜色啥的
###关于自定义view的基本知识储备
如果你对自定义view的基本流程已经有了一个基本的认知的话,可以跳过次步骤.如果你不是很熟悉的话,推荐你先阅读下Android自定义View的官方套路 ,里面介绍的还可以.

自定义圆环步骤:

Step 1: 继承View

对Android有一些了解的朋友都知道,android为我们提供的很多View都是继承与View的。所以我们自定义的View当然也是继承于View,当然如果你要自定义的View拥有某些android已经提供的控件的功能,你可以直接继承于已经提供的控件。

public class SuperCircleView extends View {public SuperCircleView(Context context) {this(context, null);}public SuperCircleView(Context context, AttributeSet attrs) {this(context, attrs, 0);}public SuperCircleView(Context context, AttributeSet attrs) {this(context, attrs, 0);}public SuperCircleView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);..........}
}

Step 2:定义自定义属性

大部分情况我们的自定义View需要有更多的灵活性,比如我们在xml中指定了颜色大小等属性,在程序运行时候控件就能展示出相应的颜色和大小。所以我们需要自定义属性自定义属性通常写在资源文件res/values/attrs.xml文件中.

贴出attr_super_circle.xml属性文件

<?xml version="1.0" encoding="utf-8"?>
<resources><declare-styleable name="SuperCircleView"><!-- 圆的半径 --><attr name="min_circle_radio" format="integer"/><!-- 圆环的宽度 --><attr name="ring_width" format="float"/><!-- 内圆的颜色 --><attr name="circle_color" format="color"/><!-- 外圆的颜色 --><attr name="max_circle_color" format="color"/><!-- 圆环的默认颜色 --><attr name="ring_normal_color" format="color"/><!-- 圆环要显示的彩色的区域(随着数值的改变,显示不同大小的彩色区域)--><attr name="ring_color_select" format="integer"/><!-- 绘制内容的数值 --><attr name="maxValue" format="integer" /><attr name="value" format="integer" /></declare-styleable></resources>

Step 3:在xml中引用自定义的圆环控件

其实这一步,正常情况下是应该放在自定义圆环完成之后.但是为了演示Step4中获取自定义属性的逻辑,暂时放在这一步了.由于通常我们需要拿到属性做一些事情,因此就需要在xml中设置了控件自定义属性。否则定义自定义属性就没有意义了。
直接上布局文件activity_main.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=".MainActivity"><FrameLayoutandroid:layout_width="300dp"android:layout_height="300dp"android:layout_gravity="center"><com.example.zq.drawcircledemo.SuperCircleViewandroid:id="@+id/superview"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center"app:maxValue="100"app:value="20"app:ring_width="60" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center"android:layout_marginBottom="60dp"android:text="信息完成度"android:textColor="#CFD5DE"android:textSize="18sp" /><LinearLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center"android:layout_marginTop="10dp"android:orientation="horizontal"><TextViewandroid:id="@+id/tv"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="0"android:textColor="#506946"android:textSize="80sp" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="%"android:textSize="28sp" /></LinearLayout></FrameLayout></LinearLayout>

布局文件中的

   app:maxValue="100"app:ring_width="60" 

设置的属性就是我们在attr.xml中定义的.至于如何获取这些自定义属性的数值,后面会展示.

Step 4:自定义圆环初始化操作

有三个构造方法(一个参数、两个参数、三个参数),其中两个参数的构造方法必须有。

在 public SuperCircleView(Context context, AttributeSet attrs, int defStyleAttr){…}中进行初始化的操作.基本是一些获取自定义属性的操作

public class SuperCircleView extends View {private final String TAG = "SuperCircleView";private ValueAnimator valueAnimator;private int mViewCenterX;   //view宽的中心点(可以暂时理解为圆心)private int mViewCenterY;   //view高的中心点(可以暂时理解为圆心)private int mMinRadio; //最里面白色圆的半径private float mRingWidth; //圆环的宽度private int mMinCircleColor;    //最里面圆的颜色private int mRingNormalColor;    //默认圆环的颜色private Paint mPaint;private int color[] = new int[3];   //渐变颜色private RectF mRectF; //圆环的矩形区域private int mSelectRing = 0; //要显示的彩色区域(岁数值变化)private int mMaxValue;public SuperCircleView(Context context) {this(context, null);}public SuperCircleView(Context context, AttributeSet attrs) {this(context, attrs, 0);}public SuperCircleView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SuperCircleView);//最里面白色圆的半径mMinRadio = a.getInteger(R.styleable.SuperCircleView_min_circle_radio, 300);//圆环宽度mRingWidth = a.getFloat(R.styleable.SuperCircleView_ring_width, 40);//最里面的圆的颜色(绿色)mMinCircleColor = a.getColor(R.styleable.SuperCircleView_circle_color, context.getResources().getColor(R.color.green));//圆环的默认颜色(圆环占据的是里面的圆的空间)mRingNormalColor = a.getColor(R.styleable.SuperCircleView_ring_normal_color, context.getResources().getColor(R.color.gray));//圆环要显示的彩色的区域mSelectRing = a.getInt(R.styleable.SuperCircleView_ring_color_select, 0);mMaxValue = a.getInt(R.styleable.SuperCircleView_maxValue, 100);a.recycle();//抗锯齿画笔mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);//防止边缘锯齿mPaint.setAntiAlias(true);//需要重写onDraw就得调用此this.setWillNotDraw(false);//圆环渐变的颜色color[0] = Color.parseColor("#FFD300");color[1] = Color.parseColor("#FF0084");color[2] = Color.parseColor("#16FF00");}
}

Step 5:画圆环

首先说一些,自定义view的话一般会重写一下三个方法:
onDraw(): 是用来绘制View图像,这个方法必须有.
onMeasure(): 用于改变View 的大小。
onLayout(): 用于改变View在父控件中的位置

Ok,继续.
(1).确定待画里面圆形以及矩形的位置

    @Overrideprotected void onLayout(boolean changed, int left, int top, int right, int bottom) {super.onLayout(changed, left, top, right, bottom);//view的宽和高,相对于父布局(用于确定圆心)int viewWidth = getMeasuredWidth();int viewHeight = getMeasuredHeight();mViewCenterX = viewWidth / 2;mViewCenterY = viewHeight / 2;//画矩形mRectF = new RectF(mViewCenterX - mMinRadio - mRingWidth / 2, mViewCenterY - mMinRadio - mRingWidth / 2, mViewCenterX + mMinRadio + mRingWidth / 2, mViewCenterY + mMinRadio + mRingWidth / 2);}

(2).绘制圆环

@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);mPaint.setColor(mMinCircleColor);canvas.drawCircle(mViewCenterX, mViewCenterY, mMinRadio, mPaint);//画默认圆环drawNormalRing(canvas);//画彩色圆环drawColorRing(canvas);}/*** 画默认圆环** @param canvas*/private void drawNormalRing(Canvas canvas) {Paint ringNormalPaint = new Paint(mPaint);ringNormalPaint.setStyle(Paint.Style.STROKE);ringNormalPaint.setStrokeWidth(mRingWidth);ringNormalPaint.setColor(mRingNormalColor);//圆环默认颜色为灰色canvas.drawArc(mRectF, 360, 360, false, ringNormalPaint);}/*** 画彩色圆环** @param canvas*/private void drawColorRing(Canvas canvas) {Paint ringColorPaint = new Paint(mPaint);ringColorPaint.setStyle(Paint.Style.STROKE);ringColorPaint.setStrokeWidth(mRingWidth);ringColorPaint.setShader(new SweepGradient(mViewCenterX, mViewCenterX, color, null));//逆时针旋转90度canvas.rotate(-90, mViewCenterX, mViewCenterY);canvas.drawArc(mRectF, 360, mSelectRing, false, ringColorPaint);ringColorPaint.setShader(null);}

ok,代码中的注释已经很详细了,我就不再细说了.

我只想说一下,代码中在绘制彩色圆环的时canvas.rotate(-90, mViewCenterX, mViewCenterY);注释中已经说了左边旋转90度.那么问题来了为什么要逆时针旋转90度呢?
这个是因为在后面画渐变色的圆弧时,drawArc和SweepGradient这两个类的起始点0度不是在我们习惯的圆环最上面那个点,而是从圆环最右边那个点开始,所以逆时针旋转90度就能让它从最上面的点开始.

盗图演示:

这下明白了吧.如果你还体会不深刻的话,就让你看一下,假如不逆时针旋转90度的话,是什么样的效果吧.

看到需要逆时针旋转90度的区别了吧.

Step 6:设置自定义view的部分监听事件

通过上述步骤我们所需的圆环基本完成了.但是,要知道,画圆环不是目的,目的是让圆环去传表达或者描述一些信息,常用的场景,比如用来显示计步器的步数,显示文件下载的完成度等等.因此我们可以适当的添加点监听事件.

 //***************************************用于更新圆环表示的数值*****************************************************/*** 设置当前值** @param value*/public void setValue(int value,TextView textView) {if (value > mMaxValue) {value = mMaxValue;}int start = 0;int end = value;startAnimator(start, end, 2000,textView);}private void startAnimator(int start, int end, long animTime, final TextView textView) {valueAnimator = ValueAnimator.ofInt(start, end);valueAnimator.setDuration(animTime);valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator animation) {Log.i(TAG, "onAnimationUpdate: animation.getAnimatedValue()::"+animation.getAnimatedValue());int i = Integer.valueOf(String.valueOf(animation.getAnimatedValue()));textView.setText(i + "");//每个单位长度占多少度mSelectRing=(int) (360 * (i / 100f));Log.i(TAG, "onAnimationUpdate: mSelectRing::"+mSelectRing);invalidate();}});valueAnimator.start();}

主程序 MainActivity.java:

  public class MainActivity extends AppCompatActivity {private static final String TAG = "MainActivity";SuperCircleView mSuperCircleView;TextView textView;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);textView = findViewById(R.id.tv);mSuperCircleView = findViewById(R.id.superview);mSuperCircleView.setValue(100, textView);mSuperCircleView.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {//随机设定圆环大小int i = new Random().nextInt(100) + 1;Log.i(TAG, "onClick: i::" + i);mSuperCircleView.setValue(i, textView);}});}
}

上述代码中设计属性动画ValueAnimator的相关知识,有兴趣的同学自己学习下.
好了,至此,自定义圆环结束.如果有疑问的话,请留言.诺诺的说一句,如果你感觉这篇文章写的还行的话,请给个赞.我感觉我需要被鼓励,哈哈,开玩笑的…

附上示例:
https://download.csdn.net/download/zhangqunshuai/10486568

参考文章:
一步步做Android自定义圆环百分比控件
Android自定义View的官方套路
Android 自定义view实现圆环

Android自定义View之画圆环(手把手教你如何一步步画圆环)相关推荐

  1. android 弹出菜单环形,『Android自定义View实战』实现一个小清新的弹出式圆环菜单...

    前言 Android表现快捷菜单的形式有很多种,比如使用PopupWindow弹出来的小弹窗,类似QQ的侧拉功能菜单,以及之前讲过的弧形菜单( Android 自定义弧形旋转菜单栏--卫星菜单),这次 ...

  2. Android自定义View之画圆环(进阶篇:圆形进度条)

    前言: 如果你想读懂或者更好的理解本篇文章关于自定义圆环或圆弧的内容.请你务必提前阅读下Android自定义View之画圆环(手把手教你如何一步步画圆环).在这篇文章中,详细描述了最基本的自定义圆环的 ...

  3. 【朝花夕拾】Android自定义View之(一)手把手教你看懂View绘制流程——向源码要答案

    前言 原文:Android自定义View之(一)手把手教你看懂View绘制流程--向源码要答案 View作为整个app的颜值担当,在Android体系中占有重要的地位.深入理解Android View ...

  4. android xml画圆,Android自定义View画圆功能

    本文实例为大家分享了Android自定义View画圆的具体代码,供大家参考,具体内容如下 引入布局 xmlns:tools="http://schemas.android.com/tools ...

  5. android 圆环温度控件,Android自定义View分享——一个圆形温度显示器

    写在前面 笔者近来在学习Android自定义View,收集了一些不算复杂但又"长得"还可以的自定义View效果实现,之前分享过一个水平的进度条,如果你有兴趣的话可以看看: Andr ...

  6. Android 自定义 圆环,Android自定义view实现圆环效果实例代码

    先上效果图,如果大家感觉不错,请参考实现代码. 重要的是如何实现自定义的view效果 (1)创建类,继承view,重写onDraw和onMesure方法 public class CirclePerc ...

  7. Android 自定义view 图片编辑(画圆,画长方形,手势缩放)

    Android 自定义view 图片编辑(画圆,画长方形,手势缩放) package com.bridgetek.yqm.view; import android.annotation.Suppres ...

  8. android自定义view圆环,Android自定义View实现圆环进度条

    本文实例为大家分享了android自定义view实现圆环进度条的具体代码,供大家参考,具体内容如下 效果展示 动画效果 view实现 1.底层圆环是灰色背景 2.上层圆环是红色背景 3.使用动画画一条 ...

  9. Android 系统(201)---Android 自定义View实战系列 :时间轴

    Android 自定义View实战系列 :时间轴 Android开发中,时间轴的 UI需求非常常见,如下图: 本文将结合 自定义View & RecyclerView的知识,手把手教你实现该常 ...

最新文章

  1. Java--语言基础
  2. .config 和 kconfig以及 makefile的关系
  3. Schedulerx2.0分布式计算原理最佳实践
  4. 三包围结构的字是什么样的_一年级语文重点(字、字母、字词、词语、句子)知识点汇总!...
  5. NPM使用前设置和升级
  6. python批量生成图_利用Python批量生成任意尺寸的图片
  7. SQL笔记-检索出ID为Int或Long中不连续的第一个点
  8. IDEA引MAVEN项目jar包依赖导入问题解决
  9. apache mysql 密码_apache2 – 无法为mysql“root”用户设置密码
  10. Sqoop1 From PostgreSQL to Hdfs
  11. if...else 应用(猜幸运数字)
  12. mysql linux查看配置文件my.cnf位置
  13. 模型预测控制的缺点_模型预测控制(MPC)与最优控制的理论分析 | NeurIPS 2020
  14. 第十六届全国大学生智能车广东赛区高校组合汇总
  15. 森林防火火灾漫延算法 火灾推演算法分析 火灾蔓延范围计算方法 森林火灾边界漫延计算方法
  16. android P adb shell dumpsys battery 使用
  17. html网页制作提交注册信息,利用HTML表单标签编写一个注册页面
  18. Kaggle竞赛:San Francisco Crime Classification(旧金山犯罪分类) 参赛心得
  19. 服务器硬盘如何把硬盘装换到gpt格式化,装GPT硬盘系统的格式转换与diskpart命令使用方法...
  20. 计算机专业基础英语,计算机专业基础英语1.ppt

热门文章

  1. Qt - 奇葩问题 解决方案
  2. 【Get深一度】dB、dBm、dBW和W换分别代表的含义及换算关系
  3. 我的MATLAB学习
  4. 实时系统与嵌入式操作系统
  5. Oracle 字符集从GBK升级到Utf8
  6. AUTOSAR 通信栈配置
  7. python 股票回测书籍推荐_python实现马丁策略回测3000只股票
  8. linux环境下安装pyhdf
  9. php+mysql 留言板系统 学生适用
  10. vs 2019使用Installer Project制作安装包的问题