最近一直在接触自定义控件的知识,自己就尝试着写了一个小的demo,算是对自定义知识点进行下总结

今天先来看下自定义控件需要重写的三个重要方法

看代码

package com.example.testcode;

import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View; public class DrawView extends View { public DrawView(Context context) {
super(context);
Log.e("123", "drawview_1");
// TODO Auto-generated constructor stub
} public DrawView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
Log.e("123", "drawview_3");
// TODO Auto-generated constructor stub
} public DrawView(Context context, AttributeSet attrs) {
super(context, attrs);
Log.e("123", "drawview_2");
// TODO Auto-generated constructor stub
} @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// TODO Auto-generated method stub
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
Log.e("123", "MeasureSpec.UNSPECIFIED==" + MeasureSpec.UNSPECIFIED);
Log.e("123", "MeasureSpec.AT_MOST==" + MeasureSpec.AT_MOST);
Log.e("123", "MeasureSpec.EXACTLY==" + MeasureSpec.EXACTLY);
Log.e("123", "widthMeasureSpec===" + widthMeasureSpec);
Log.e("123", "heightMeasureSpec===" + heightMeasureSpec);
Log.e("123", "widthMode==" + widthMode + " widthSize===" + widthSize);
Log.e("123", "heightMode==" + heightMode + " heightSize==="
+ heightSize);
//这两个方法必须有一个,否则会报错
//super.onMeasure(widthMeasureSpec, heightMeasureSpec);
setMeasuredDimension(75, 75);
} @Override
protected void onLayout(boolean changed, int left, int top, int right,
int bottom) {
// TODO Auto-generated method stub
Log.e("123", "change===" + changed + " left===" + left + " top==="
+ top + " right===" + right + " bottom===" + bottom);
super.onLayout(changed, left, top, right, bottom);
} @Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
Log.e("123", "onDraw");
super.onDraw(canvas);
}
}

xml中使用

<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"
tools:context="com.example.testcode.MainActivity" > <com.example.testcode.DrawView
android:layout_width="100dp"
android:layout_height="100dp"
android:background="#ff0000" /> </RelativeLayout>

先看下我们的打印结果

   - ::26.901: E/(): drawview_2
- ::26.959: E/(): MeasureSpec.UNSPECIFIED==
- ::26.959: E/(): MeasureSpec.AT_MOST==-
- ::26.959: E/(): MeasureSpec.EXACTLY==
- ::26.959: E/(): widthMeasureSpec===
- ::26.960: E/(): heightMeasureSpec===-
- ::26.960: E/(): widthMode== widthSize===
- ::26.960: E/(): heightMode==- heightSize===
- ::26.960: E/(): MeasureSpec.UNSPECIFIED==
- ::26.960: E/(): MeasureSpec.AT_MOST==-
- ::26.961: E/(): MeasureSpec.EXACTLY==
- ::26.961: E/(): widthMeasureSpec===
- ::26.961: E/(): heightMeasureSpec===
- ::26.961: E/(): widthMode== widthSize===
- ::26.961: E/(): heightMode== heightSize===
- ::27.001: E/(): change===true left=== top=== right=== bottom===
- ::27.030: E/(): MeasureSpec.UNSPECIFIED==
- ::27.031: E/(): MeasureSpec.AT_MOST==-
- ::27.031: E/(): MeasureSpec.EXACTLY==
- ::27.031: E/(): widthMeasureSpec===
- ::27.031: E/(): heightMeasureSpec===-
- ::27.031: E/(): widthMode== widthSize===
- ::27.031: E/(): heightMode==- heightSize===
- ::27.031: E/(): MeasureSpec.UNSPECIFIED==
- ::27.031: E/(): MeasureSpec.AT_MOST==-
- ::27.031: E/(): MeasureSpec.EXACTLY==
- ::27.032: E/(): widthMeasureSpec===
- ::27.032: E/(): heightMeasureSpec===
- ::27.032: E/(): widthMode== widthSize===
- ::27.032: E/(): heightMode== heightSize===
- ::27.033: E/(): change===false left=== top=== right=== bottom===
- ::27.045: E/(): onDraw

从上面的结果我们可以知道xml中控件加载过程

1.xml中使用的控件,加载的时候,调用的是控件两个参数的方法

public DrawView(Context context, AttributeSet attrs) {
}

一个是上下文,一个是属性

2.解析来会调用

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
}

方法,这个方法是用来确定控件的宽高的,这个值是从控件的width、height中读出来的。但是我们发现,这两个值的打印结果很奇怪,甚至还有负数。网上对此的解释是

onMeasure传入的widthMeasureSpec和heightMeasureSpec不是一般的尺寸数值,而是将模式和尺寸组合在一起的数值。

具体什么我也不清楚,不过,它其实是包含了很多信息在里面的。一个就是,从这个数值,我们可以获得这个控件宽跟高的形式

使用如下方法

int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);

这个mode的取值,可以有一下三种

MeasureSpec.EXACTLY-是精确尺寸,当我们将控件的layout_width或layout_height指定为具体数值时如andorid:layout_width="50dip",或者为FILL_PARENT是,都是控件大小已经确定的情况,都是精确尺寸。

MeasureSpec.AT_MOST 是最大尺寸,当控件的layout_width或layout_height指定为WRAP_CONTENT时,控件大小一般随着控件的子空间或内容进行 变化,此时控件尺寸只要不超过父控件允许的最大尺寸即可。因此,此时的mode是AT_MOST,size给出了父控件允许的最大尺寸。

MeasureSpec.UNSPECIFIED是未指定尺寸,这种情况不多,一般都是父控件是AdapterView,通过measure方法传入的模式。

自定义控件之onMeasure的更多相关文章

  1. Android View的绘制过程

    首先是view的绘制过程~最主要的分三部分 measure layout draw 看字面意思,计算,布局,画~ android中控件相当于是画在一个无限大的画布上的,那就产生了几个问题 画布无限大, ...

  2. 【Android 界面效果15】Android UI 之一步步教你自定义控件(自定义属性、合理设计onMeasure、合理设计onDraw等)

        Android开发做到了一定程度,多少都会用到自定义控件,一方面是更加灵活,另一方面在大数据量的情况下自定义控件的效率比写布局文件更高.     一个相对完善的自定义控件在布局文件中和java ...

  3. Android UI 之一步步教你自定义控件(自定义属性、合理设计onMeasure、合理设计onDraw等)

        Android开发做到了一定程度,多少都会用到自定义控件,一方面是更加灵活,另一方面在大数据量的情况下自定义控件的效率比写布局文件更高.     一个相对完善的自定义控件在布局文件中和java ...

  4. android自定义控件 onMeasure() 测量尺寸

    上次讲的自定义控件刷新点屏幕的任意地方都会刷新,而且在xml里自定义控件下面放一个textview的话,这个TextView是显示不出来的,不只这个,以前的几个自定义控件都是 为什么呢?今天来讲下on ...

  5. 自定义控件详解(五):onMeasure()、onLayout()

    前言: 自定义控件的三大方法: 测量: onMeasure(): 测量自己的大小,为正式布局提供建议 布局: onLayout(): 使用layout()函数对所有子控件布局 绘制: onDraw() ...

  6. android自定义控件onMeasure方法

    1.自定义控件首先定义一个类继承View 有时,Android系统控件无法满足我们的需求,因此有必要自定义View.具体方法参见官方开发文档:http://developer.android.com/ ...

  7. android自定义控件(8)-利用onMeasure测量使图片拉伸永不变形,解决屏幕适配问题

    使用ImageView会遇到的问题 在Android应用中,都少不了图片的显示,ImageView,轮播图,ViewPager等等,很多都是来显示图片的,很多时候,我们都希望图片能够在宽度上填充父窗体 ...

  8. android自定义控件(6)-详解在onMeasure()方法中如何测量一个控件尺寸

    今天的任务就是详细研究一下protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)方法.如果只是说要重写什么方法有什么 ...

  9. Android 自定义控件高度设置onMeasure方法

    最近使用hellocharts需要表格横向显示,而activity需要竖屏显示,在旋转以后,默认宽度为不超过屏幕宽度,则一直无法显示全控件. 此时需要修改onMeasure方法,这个方法是用来控制控件 ...

随机推荐

  1. Metasploit的三种启动方式

    不多说,直接上干货! 注意:博主我用的是Kali linux 2016.2(Rolling).  msfcli 的启动 root@kali:~# msfcli -h bash: msfcli: 未找到 ...

  2. Idea的一些调试技巧及设置todo

    程序员的工作内容,除了大部分时间写代码之外,因为有不少的时间是用在调试代码上.甚至说不是在调试代码,就是即将调试代码. :) 今天我们来谈谈调试代码的一些技巧,在使用IDE提供的debugger时一些 ...

  3. ASP.NET Identity 角色管理(Roles)

    当我们使用ASP.NET 4.5创建模板项目时,会发现模板只提供了ApplicationUserManager用于用户的登录注册.修改.设置等,而没有提供与用户角色相关的代码,对此就需要我们自己手动的 ...

  4. IHttpHandler的学习(0-2)

    这个IHttpHandler,要想到asp.net生命周期 ,想到哪个从你发起请求开始,这个请求通过HttpModule------>IHttpHandler的: 执行HttpModule的一系 ...

  5. HYSBZ1061题解

  6. 题解 P3521 【[POI2011]ROT-Tree Rotations】

    这道题采用权值线段树合并的解法. 首先讲一下解法中出现的两个概念:权值线段树与线段树合并. 所谓权值线段树,可以理解为维护的信息反过来的普通线段树,我个人认为值域线段树这个名字其实要准确一些. 举个例 ...

  7. ECNUOJ 2613 Gamma 函数

    Gamma 函数 Time Limit:1000MS Memory Limit:65536KBTotal Submit:237 Accepted:138 Description  Pollux最近在复 ...

  8. svn 的使用(二)

    这篇主要介绍下 svn 钩子的使用,svn 的安装以及配置等能够查看svn 的使用(一) 我们能够在svn创建的仓库目录下看到 hooks 目录. 这里面就存放这个各种svn操作同一时候会运行的脚本文 ...

  9. 新一代企业即时通信系统 -- 傲瑞通(OrayTalk)

    傲瑞通(OrayTalk)是我们为企业专门打造的新一代企业即时通讯平台,功能强大丰富.像组织结构.文字/语音/视频会话.文件传送.远程协助.消息记录等功能都有,而且留有接口可与企业遗留系统进行集成. ...

  10. libvirt 部分API 介绍

    感谢朋友支持本博客.欢迎共同探讨交流,因为能力和时间有限,错误之处在所难免,欢迎指正! 假设转载,请保留作者信息. 博客地址:http://blog.csdn.net/qq_21398167 原博文地 ...