最近一直在接触自定义控件的知识,自己就尝试着写了一个小的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. POJ 1274 二分图匹配

    匈牙利算法 裸题 //By SiriusRen #include <cstdio> #include <cstring> #include <algorithm> ...

  2. SSRS 报表 递归列表

    SSRS 报表 递归列表 .需要数据集合中两个必备字段 ID PID 1.添加数据集合,在图上标记的地方点击右键添加数据集合,根据需求自己编写 2.点击插入选项卡 中的 矩阵  有两种方式 一种是 矩 ...

  3. <Sicily> Longest Common Subsequence

    一.题目描述 Given a sequence A = < a1, a2, -, am >, let sequence B = < b1, b2, -, bk > be a s ...

  4. HDU 2515 Yanghee 的算术【找规律】

    题意:中文的题目 找规律可以发现 sum[1]=a[1]+a[2] sum[2]=a[1]+a[3] sum[n]=a[2]+a[3] 解出a[1],就可以求出其他的了 #include<ios ...

  5. 51Nod 蜥蜴和地下室(搜索)

    哈利喜欢玩角色扮演的电脑游戏<蜥蜴和地下室>.此时,他正在扮演一个魔术师.在最后一关,他必须和一排的弓箭手战斗.他唯一能消灭他们的办法是一个火球咒语.如果哈利用他的火球咒语攻击第i个弓箭手 ...

  6. 51Nod 活动安排问题(排序+优先队列)

    有若干个活动,第i个开始时间和结束时间是[Si,fi),同一个教室安排的活动之间不能交叠,求要安排所有活动,最少需要几个教室? Input 第一行一个正整数n (n <= 10000)代表活动的 ...

  7. CentOS 7.4 ifconfig, ip/ss, nmcli, nmtui, 配置文件 修改ip信息用法

    CentOS 7.4 ifconfig, ip/ss, nmcli, nmtui, 配置文件 修改ip信息用法 CentOS 7.4 中, 网卡命名方式发生改变, 可预测功能命名: 网卡简要名称组成格 ...

  8. vue-router路由配置

    转自http://www.cnblogs.com/padding1015/ 两种配置方法:在main.js中 || 在src/router文件夹下的index.js中 src/router/index ...

  9. 题解 CF327C 【Magic Five】

    这道题带坑,假如没有发现肯定会爆. 首先先搜索一遍0和5,储存在数组a里面. 那么应当有2 ^ a1 +2 ^ a2 +...+ 2 ^ an. 然而这道题没那么简单,数串还可以重复k次. 因此,需要 ...

  10. 二叉树、B树、B+树、B*树、LSM树

      HBase 对于数据产品,底层存储架构直接决定了数据库的特性和使用场景.RDBMS(关系型数据库)使用 B树 及 B+树 作为数据存储结构. HBase 使用 LSM树. .     二叉树    ...