自定义View_onDraw,onMeasure方法
来源:互联网 发布:中国电信德国数据漫游 编辑:程序博客网 时间:2024/05/16 08:35
package xena.view;import xena.act.R;import android.content.Context;import android.content.res.Resources;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.util.AttributeSet;import android.view.View;public class MyView extends View {private Context context;private int r = 10;private String str = "小";private final String NS = "http://www.hqyj.com";// 名称空间private boolean flag;public float getR() {return r;}public void setR(int r) {this.r = r;this.invalidate();//触发onDraw方法的执行}public String getStr() {return str;}public void setStr(String str) {this.str = str;this.invalidate();//触发onDraw方法的执行}public boolean isFlag() {return flag;}public void setFlag(boolean flag) {this.flag = flag;this.invalidate();//触发onDraw方法的执行}// 用于自定义View当作标签时用的public MyView(Context context, AttributeSet attrs) {super(context, attrs);this.context = context;// 参数1:名称空间, 参数2:自定义属性名, 取失败时当作默认值返回this.r = attrs.getAttributeIntValue(NS, "r", 20);//this.flag = attrs.getAttributeBooleanValue(NS, "flag", false);// 参数1:我称空间, 参数2: 自定义属性名// this.str = attrs.getAttributeValue(NS, "text");// 如果属性值是资源文件id// int getAttributeResourceValue(String namespace, String attributeName,// int defaultValue);int id = attrs.getAttributeResourceValue(NS, "text", -1);if (id != -1) {// int id = R.string.hello_world;Resources resources = this.context.getResources();this.str = resources.getString(id);}else {this.str = attrs.getAttributeValue(NS, "text");}}// 用于new MyView(...)用的public MyView(Context context) {super(context);}private int getwidth(int widthMeasureSpec) {int width = 10;int width_mode = MeasureSpec.getMode(widthMeasureSpec);if(width_mode==MeasureSpec.EXACTLY) {width = MeasureSpec.getSize(widthMeasureSpec);}else if(width_mode==MeasureSpec.AT_MOST) {width = (int) (2*r);}else if(width_mode==MeasureSpec.UNSPECIFIED) {width = 100;}return width;}// 00 11 10 11private int getheight(int heightMeasureSpec) {int hight = 10;int hight_mode = MeasureSpec.getMode(heightMeasureSpec);if(hight_mode==MeasureSpec.EXACTLY) {hight = MeasureSpec.getSize(heightMeasureSpec);}else if(hight_mode==MeasureSpec.AT_MOST) {hight= (int) (2*r);}else if(hight_mode==MeasureSpec.UNSPECIFIED) {hight = 100;}return hight;}//在onDraw前调用@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {int width=0, hight=0;width = this.getwidth(widthMeasureSpec);hight = this.getheight(heightMeasureSpec);this.setMeasuredDimension(width, hight);}//// 用于绘制界面上的内容,当界面显示时调用@Overrideprotected void onDraw(Canvas canvas) {// canvas画布对象super.onDraw(canvas);// 创建笔 画Paint paint = new Paint();paint.setColor(Color.BLUE);// 画圆canvas.drawCircle(r, r, r, paint);paint.setColor(Color.RED);if (flag) {canvas.drawCircle(r, r, 5, paint);}// 画字// 参数1:被绘制的字符串, 参数2,3:指字符串每一个字符的左下角坐标paint.setTextSize(30);// 设置文字大小canvas.drawText(this.str, r, r, paint);}}
(1)一般情况重写onMeasure()方法作用是为了自定义View尺寸的规则,如果你的自定义View的尺寸是根据父控件行为一致,就不需要重写onMeasure()方法
(3)widthMeasureSpec和heightMeasureSpec这两个值通常情况下都是由父视图经过计算后传递给子视图的,说明父视图会在一定程度上决定子视图的大小。
1.
wrap--AT_MOST
fill--EXACTLY
固定值--EXACTLY
上边是大家都知道的,但是一直很疑惑UNSPECIFIED什么情况发生,今天测了下,发现在使用weigt时会调用,因为此时定义的值为0dp,这不就是UNSPECIFIED嘛!
父 match_parent match_parent match_parent wrap_content wrap_content wrap_content 200px 200px 200px
子 match_parent 100px wrap_content match_parent 100px wrap_content 100px match_parent wrap_content
结果 exactly(fill) exactly(100px) at_most(fill) at_most (fill) exactly(100xp) at_most(fill) exactly(100px) exactly(200px) at_most(200xp)
1.有at_most 适合自定义一个大小,(子的大小超不过父大小)
2.有exactly 则适合测出的大小.
3,有unspecified, 适合任意指定大小,(子的大小可超过父大小)
可以说重载onMeasure(),onLayout(),onDraw()三个函数构建了自定义View的外观形象。再加上onTouchEvent()等重载视图的行为,可以构建任何我们需要的可感知到的自定义View。
不管是自定义View还是系统提供的TextView这些,它们都必须放置在LinearLayout等一些ViewGroup中,因此理论上我们可以很好的理解onMeasure(),onLayout(),onDraw()这三个函数:1.View本身大小多少,这由onMeasure()决定;2.View在ViewGroup中的位置如何,这由onLayout()决定;3.绘制View,onDraw()定义了如何绘制这个View。
widthMeasureSpec, heightMeasureSpec这两个参数是从哪里来的?onMeasure()函数由包含这个View的具体的ViewGroup调用,因此值也是从这个ViewGroup中传入的。这里我直接给出答案:子类View的这两个参数,由ViewGroup中的layout_width,layout_height和padding以及View自身的layout_margin共同决定。权值weight也是尤其需要考虑的因素,有它的存在情况可能会稍微复杂点。
这个值由高32位组成,最高的两位保存的值叫specMode,可以通过如代码中所示的MeasureSpec.getMode()获取;低30位为specSize,同样可以由MeasureSpec.getSize()获取
所有的View的onMeasure()的最后一行都会调用setMeasureDimension()函数的作用——这个函数调用中传进去的值是View最终的视图大小。也就是说onMeasure()中之前所作的所有工作都是为了最后这一句话服务的。
specMode一共有三种可能:
MeasureSpec.EXACTLY:父视图希望子视图的大小应该是specSize中指定的。
MeasureSpec.AT_MOST:子视图的大小最多是specSize中指定的值,也就是说不建议子视图的大小超过specSize中给定的值。
MeasureSpec.UNSPECIFIED:我们可以随意指定视图的大小。
MATCH_PARENT对应于EXACTLY,WRAP_CONTENT对应于AT_MOST,其他情况也对应于EXACTLY,它和MATCH_PARENT的区别在于size值不一样。
0 0
- 自定义View_onDraw,onMeasure方法
- 自定义的onMeasure()方法
- 自定义view 重写onMeasure()方法
- 自定义View-onMeasure()方法
- 自定义控件---OnMeasure()方法分析
- 自定义View之onMeasure方法
- 自定义View之onMeasure()方法
- 自定义View的onMeasure方法理解
- Android 自定义view 和 onMeasure方法介绍
- Android 自定义view 和 onMeasure方法介绍
- Android 自定义控件onMeasure()方法详解
- 自定义控件的onMeasure方法详解
- 自定义view onMeasure方法的重写
- 自定义view,viewgroup的onMeasure 方法
- 自定义View学习笔记之onMeasure()方法
- 自定义View之OnMeasure方法学习
- Android 自定义View onMeasure方法的实现
- 自定义View控件之onMeasure方法详解
- 自定义Dialog android Dialog
- HDU 5037 Frog(2014年北京网络赛 F)
- OpenGL API simple summary
- Java中Class对象详解
- The Tamworth Two_usaco2.4.1_模拟
- 自定义View_onDraw,onMeasure方法
- 【《代码整洁之道》精读与演绎】之五 整洁类的书写准则
- NodeJS VS Tomcat搭建高并发静态文件服务器
- (七)c52学习之旅-中断
- mysql-字段为汉字,须将字符集设定UTF8
- ubuntu12.04卸载软件方法
- 走进计算机世界--计算机科学
- Android 热修复
- Leetcode 14 Longest Common Prefix