最近一直在接触自定义控件的知识,自己就尝试着写了一个小的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. Classes and functions

    As another example of a user-defined type, we’ll define a class called Time that records the time of ...

  2. Pycharm-连接服务器

  3. 23.STL容器小结

  4. SpringMVC后台使用对象接受参数字符串转日期

    在springMVC配置文件中加入: <bean id="dateConvert" class="com.iomp.util.DateConvert"/& ...

  5. #p-complete原来比np更难

    转载一下豆瓣的一个不知名的朋友的介绍: NP是指多项式时间内验证其解是否正确.比如: 我们给一个0-1背包的解,就可以在多项式时间内验证是否满足条件.至于是否能找到 满足条件的解,这在NP复杂度里没有 ...

  6. caffe(14) python可视化

    首先将caffe的根目录作为当前目录,然后加载caffe程序自带的小猫图片,并显示. 图片大小为360x480,三通道 In [1]: import numpy as np import matplo ...

  7. caffe(13) 数据可视化(python接口)配置

    caffe程序是由c++语言写的,本身是不带数据可视化功能的.只能借助其它的库或接口,如opencv, python或matlab.大部分人使用python接口来进行可视化,因为python出了个比较 ...

  8. HDU-2045 不容易系列之(3)—— LELE的RPG难题 找规律&递推

    题目链接:https://cn.vjudge.net/problem/HDU-2045 找规律 代码 #include <cstdio> long long num[51][2]; int ...

  9. WPS for Linux使用测评

    从去年有WPS for Linux的消息到现在,Linux 版的WPS Office在经过一系列的alpha版本之后终于迎来了Beta版本.笔者也是第一时间下载安装,WPS 文字.WPS 演示和WPS ...

  10. PKU 2288 Islands and Bridges 状态dp

    题意: 给你一张地图,上面有一些岛和桥.你要求出最大的三角哈密顿路径,以及他们的数量. 哈密顿路:一条经过所有岛的路径,每个岛只经过一次. 最大三角哈密顿路:满足价值最大的哈密顿路. 价值计算分为以下 ...