自定义view(结合刻度盘学习)
先上效果图
一、View的测量(刻度盘的大小测量)
在现实生活中,我们如果要去画一个图形,那么便要知道它的大小和位置。所以android绘图时需要我们对view进行测量。android为我们提供了onMeasure()方法来帮助我们去测量一个view,我们只需要重写onMeasur()方法,将我们测算长宽设置给setMeasuredDimension()。
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//根据模式测算长宽
... setMeasuredDimension(width,height);
}
我们首先测量我们最开始弧形的大小。即图中的样例。
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//根据模式测算长宽,这里获取的尺寸便是在xml文件中指定的尺寸
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
//以最小值为刻度区域正方形的长
len = Math.min(width, height);
//确定圆弧所在的矩形区域
oval = new RectF(0, 0, len, len);
radius = len/2;
//设置测量高度和宽度
setMeasuredDimension(len,len);
}
二、View的绘制(简单绘制出我们需要的弧形)
测算完成后我们需要将他在画面上显示出来,android为我们提供了onDraw()方法,来绘制view。
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//弧形的绘画查看api
canvas.drawArc(oval,startAngle,sweepAngle,useCenter,paint); }
不了解canvas的可以去看看canvas的绘制API
现在在布局文件中设置后,就可以看见我们最开始的view了。
三、完善我们的绘制,为仪表盘添加刻度。
private void drawViewLine(Canvas canvas) {
canvas.save();
//移动canvas
canvas.translate(radius,radius);
//旋转canvas
canvas.rotate(30);
//普通刻度
Paint linePatin=new Paint();
//设置普通刻度画笔颜色
linePatin.setColor(Color.WHITE);
//线宽
linePatin.setStrokeWidth(2);
//设置画笔抗锯齿
linePatin.setAntiAlias(true);
/* //画一条刻度线
canvas.drawLine(0,radius,0,radius-40,linePatin);*/
//画101条刻度线
//确定每次旋转的角度
float rotateAngle=sweepAngle/99;
//绘制需要有颜色部分的画笔
Paint targetLinePatin=new Paint();
targetLinePatin.setColor(Color.GREEN);
targetLinePatin.setStrokeWidth(2);
targetLinePatin.setAntiAlias(true);
//记录已经绘制过的有色部分范围(角度float)
float hasDraw=0;
for(int i=0;i<100;i++){
if (hasDraw <= targetAngle && targetAngle != 0) {
//计算已经绘制的比例
canvas.drawLine(0, radius, 0, radius - 40, targetLinePatin);
} else {
canvas.drawLine(0,radius,0,radius-40,linePatin);
}
hasDraw += rotateAngle;
canvas.rotate(rotateAngle);
} //操作完成后恢复状态
canvas.restore();
}
如图
四、完善onMeasure()测量
我们先看看在布局中的CircleView
原先
<com.example.tyr.circleviewtest.CircleView
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
如图
改成Button
<Button
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
现在,我么修改CircleView改为wrap_content,如图
可以发现没有改变
对比button的wrap_content可以发现如图,
所以我们需要在onMeasure()方法中,对view的模式进行区别测量。
五、MeasureSpec类
android系统为我们提供了一个短小精悍的类MeasureSpec。它是一个32位的int值,高两位为测量模式,低30位为测量大小。
测量模式分为三种:
1、EXACTLY--系统的默认模式。
精确模式,当我们将width和height指定100dp、200dp等精确值时或是match_parent属性时系统使用EXACTLY模式
2、AT_MOST
最大值模式,当height和width属性指定为wrap_content时,控件大小随子控件或内容的变化而变化,控件大小只要不超过父控件允许的最大尺寸即可。
3、UNSPECIFIED
不指定大小测量模式,view想多大就多大,通常在绘制自定义view时才会用。
将onMeasure()方法进行修改,适应wrap_content
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//根据模式测算长宽
int width = measureSize(widthMeasureSpec);
int height = measureSize(heightMeasureSpec);
//以最小值为刻度区域正方形的长
len = Math.min(width, height);
//确定圆弧所在的矩形区域
oval = new RectF(0, 0, len, len);
radius = len/2;
//设置测量高度和宽度
setMeasuredDimension(len, len);
} private int measureSize(int measureSpec){
//差不多固定的格式
int reslut = 0;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
if (specMode==MeasureSpec.EXACTLY){
reslut = specSize;
}else{
reslut = 200;
if (specMode==MeasureSpec.AT_MOST){
reslut = Math.min(reslut,specSize);
}
} return reslut;
}
六、自定义属性
我们在xml文件中使用的时候往往会使用一些属性类似width和height等等,那么我们便需要为我们的刻度盘添加新的属性。
<resources>
<declare-styleable name="CircleView">
<attr name="pointDisArc" format="dimension"></attr>
<attr name="textSize" format="dimension"></attr>
</declare-styleable>
</resources>
在构造方法中处理
public CircleView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
parseAttr(context, attrs, defStyleAttr);
initPaint();
} private void parseAttr(Context context, AttributeSet attrs, int defStyleAttr) {
TypedArray typedArray = context.obtainStyledAttributes(attrs,R.styleable.CircleView,defStyleAttr,0);
pDisArc = typedArray.getDimensionPixelSize(R.styleable.CircleView_pointDisArc,dp2px(context,20));
textSize = typedArray.getDimensionPixelSize(R.styleable.CircleView_textSize,dp2px(context,20));
typedArray.recycle();
}
<com.example.tyr.circleviewtest.CircleView
android:id="@+id/cicleview"
android:layout_width="match_parent"
android:layout_height="match_parent"
circle:textSize="20sp"
circle:pointDisArc="20dp"
/>
到目前为止view的自定义差不多完成了,也可以将刻度盘设计的更加精巧一些,下一节开始viewgroup的绘制,涉及到新的方法onLayout()。
自定义view(结合刻度盘学习)的更多相关文章
- Android自定义View初步
经过上一篇的介绍,大家对于自定义View一定有了一定的认识,接下来我们就以实现一个图片下显示文字的自定义View来练习一下.废话不多说,下面进入我们的正题,首先看一下我们的思路,1.我们需要通过在va ...
- 通过圆形载入View了解自定义View
这是自定义View的第一篇文章,通过制作简单的自定义View来了解自定义View的流程. 自定义View是Android学习和开发中必不可少的一部分.通过自定义View我们可以制作丰富绚丽的控件,自定 ...
- Android查缺补漏(View篇)--自定义 View 的基本流程
View是Android很重要的一部分,常用的View有Button.TextView.EditView.ListView.GridView.各种layout等等,开发者通过对这些View的各种组合以 ...
- 简单说说Android自定义view学习推荐的方式
这几天比较受关注,挺开心的,嘿嘿. 这里给大家总结一下学习自定义view的一些技巧. 以后写自定义view可能不会写博客了,但是可以开源的我会把源码丢到github上我的地址:https://git ...
- 20170831工作日记--自定义View学习
学习了LayoutInflater的原理分析.视图的绘制流程.视图的状态及重绘等知识,按类型来划分的话,自定义View的实现方式大概可以分为三种,自绘控件.组合控件.以及继承控件.那么下面我们就来依次 ...
- Android之自定义View学习(一)
Android之自定义View学习(一) Canvas常用方法: 图片来源 /** * Created by SiberiaDante on 2017/6/3. */ public class Bas ...
- Android开发之制作圆形头像自定义View,直接引用工具类,加快开发速度。带有源代码学习
作者:程序员小冰,CSDN博客:http://blog.csdn.net/qq_21376985 QQ986945193 博客园主页:http://www.cnblogs.com/mcxiaobing ...
- salesforce 零基础学习(五十)自定义View或者List以及查看系统原来的View或者List
salesforce给我们提供了标准的页面,比如标准的页面包括标准的列表和标准的详细页视图.有的时候我们想要自定义视图,比如做一个项目的时候不希望使用者直接通过ID查看到标准的详细页,而是跳转到指定处 ...
- Android自定义View学习(四)
硬件加速 参考:HenCoder Android 自定义 View 1-8 硬件加速 硬件加速能够让绘制变快,主要有三个原因: 本来由 CPU 自己来做的事,分摊给了 GPU 一部分,自然可以提高效率 ...
随机推荐
- HDU P3341 Lost's revenge 题解+数据生成器
Lost and AekdyCoin are friends. They always play "number game"(A boring game based on numb ...
- JavaWeb学习总结(六):HttpServletRespone对象(二)
一.HttpServletResponse常见应用——生成验证码 1.1.生成随机图片用作验证码 生成图片主要用到了一个BufferedImage类, 生成随机图片范例: package gacl.r ...
- 学习servlet心得
1,关于字符编码问题: // resp.setCharacterEncoding("UTF-8");//这个的作用仅仅只是输出字符,不做格式转换成HTML // resp.setC ...
- Breakpoint debugging
断点调试的作用: A:查看程序的执行流程. B:调试程序. package basic.java; public class DebugTest { public static void main(S ...
- android studio新建项目时出现Error:Execution failed for task ':app:preDebugAndroidTestBuild'.
android studio更新后创建新项目时出现以下错误 可以用Build->Rebuild Project解决,但这个方法只是临时的,重新打开项目还是会报错 所以用另一种方法: 在app下的 ...
- jQuery中index()方法用法实例
本文实例讲述了jQuery中index()方法用法.分享给大家供大家参考.具体分析如下: 此方法可以搜索匹配元素,并返回元素的索引值.索引值是从0开始的. 语法结构一: 当此方法没有参数的时候,返回值 ...
- 字典构造、合并(dict)、排序
使用dict,zip方法将两个list合并为dict keys = ["b", "a", "c", "e", " ...
- ThreadState属性
这个属性代表了线程运行时状态,在不同的情况下有不同的值,我们有时候可以通过对该值的判断来设计程序流程. ThreadState 属性的取值如下: Aborted:线程已停止: AbortRequest ...
- 使用事务和SqlBulkCopy批量插入数据
SqlBulkCopy是.NET Framework 2.0新增的类,位于命名空间System.Data.SqlClient下,主要提供把其他数据源的数据有效批量的加载到SQL Server表中的功能 ...
- yaml 入手
一.变量 YAML使用冒号加缩进的方式代表层级(属性)关系,使用短横杠(-)代表数组元素. YAML中允许表示三种格式,分别是常量值,对象和数组 #即表示url属性值: url: http://www ...