在继承ViewGroup类时,需要重写两个方法,分别是onMeasure和onLayout。



1,在方法onMeasure中调用setMeasuredDimension方法



void android.view.View.setMeasuredDimension(int measuredWidth, int measuredHeight)



在onMeasure(int, int)中,必须调用setMeasuredDimension(int width, int height)来存储测量得到的宽度和高度值,如果没有这么去做会触发异常IllegalStateException。



2,在方法onMeasure中调用孩子的measure方法



void android.view.View.measure(int widthMeasureSpec, int heightMeasureSpec)



这个方法用来测量出view的大小。父view使用width参数和height参数来提供constraint信息。实际上,view的测量工作在onMeasure(int, int)方法中完成。因此,只有onMeasure(int, int)方法可以且必须被重写。参数widthMeasureSpec提供view的水平空间的规格说明,参数heightMeasureSpec提供view的垂直空间的规格说明。



3,解析onMeasure(int, int)方法



void android.view.View.onMeasure(int widthMeasureSpec, int heightMeasureSpec)



测量view及其内容来确定view的宽度和高度。这个方法在measure(int, int)中被调用,必须被重写来精确和有效的测量view的内容。



在重写这个方法时,必须调用setMeasuredDimension(int, int)来存储测量得到的宽度和高度值。执行失败会触发一个IllegalStateException异常。调用父view的onMeasure(int, int)是合法有效的用法。



view的基本测量数据默认取其背景尺寸,除非允许更大的尺寸。子view必须重写onMeasure(int, int)来提供其内容更加准确的测量数值。如果被重写,子类确保测量的height和width至少是view的最小高度和宽度(通过getSuggestedMinimumHeight()和getSuggestedMinimumWidth()获取)。



4,解析onLayout(boolean, int, int, int, int)方法



void android.view.ViewGroup.onLayout(boolean changed, int l, int t, int r, int b)



调用场景:在view给其孩子设置尺寸和位置时被调用。子view,包括孩子在内,必须重写onLayout(boolean, int, int, int, int)方法,并且调用各自的layout(int, int, int, int)方法。



参数说明:参数changed表示view有新的尺寸或位置;参数l表示相对于父view的Left位置;参数t表示相对于父view的Top位置;参数r表示相对于父view的Right位置;参数b表示相对于父view的Bottom位置。.



5,解析View.MeasureSpec类



android.view.View.MeasureSpec



MeasureSpec对象,封装了layout规格说明,并且从父view传递给子view。每个MeasureSpec对象代表了width或height的规格。



MeasureSpec对象包含一个size和一个mode,其中mode可以取以下三个数值之一:



    UNSPECIFIED,1073741824 [0x40000000],未加规定的,表示没有给子view添加任何规定。

    EXACTLY,0 [0x0],精确的,表示父view为子view确定精确的尺寸。

AT_MOST,-2147483648 [0x80000000],子view可以在指定的尺寸内尽量大。

在这里给大家举一个例子demo:

第一步:自定义一个View实现ViewGroup接口,即自定义ViewGroup:

package net.loonggg.viewgroup;

import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup; public class MyViewGroup extends ViewGroup { public MyViewGroup(Context context) {
super(context);
} public MyViewGroup(Context context, AttributeSet attrs) {
super(context, attrs);
} public MyViewGroup(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
} /**
* 计算控件的大小
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int measureWidth = measureWidth(widthMeasureSpec);
int measureHeight = measureHeight(heightMeasureSpec);
// 计算自定义的ViewGroup中所有子控件的大小
measureChildren(widthMeasureSpec, heightMeasureSpec);
// 设置自定义的控件MyViewGroup的大小
setMeasuredDimension(measureWidth, measureHeight);
} private int measureWidth(int pWidthMeasureSpec) {
int result = 0;
int widthMode = MeasureSpec.getMode(pWidthMeasureSpec);// 得到模式
int widthSize = MeasureSpec.getSize(pWidthMeasureSpec);// 得到尺寸 switch (widthMode) {
/**
* mode共有三种情况,取值分别为MeasureSpec.UNSPECIFIED, MeasureSpec.EXACTLY,
* MeasureSpec.AT_MOST。
*
*
* 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方法传入的模式。
*/
case MeasureSpec.AT_MOST:
case MeasureSpec.EXACTLY:
result = widthSize;
break;
}
return result;
} private int measureHeight(int pHeightMeasureSpec) {
int result = 0; int heightMode = MeasureSpec.getMode(pHeightMeasureSpec);
int heightSize = MeasureSpec.getSize(pHeightMeasureSpec); switch (heightMode) {
case MeasureSpec.AT_MOST:
case MeasureSpec.EXACTLY:
result = heightSize;
break;
}
return result;
} /**
* 覆写onLayout,其目的是为了指定视图的显示位置,方法执行的前后顺序是在onMeasure之后,因为视图肯定是只有知道大小的情况下,
* 才能确定怎么摆放
*/
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
// 记录总高度
int mTotalHeight = 0;
// 遍历所有子视图
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
View childView = getChildAt(i); // 获取在onMeasure中计算的视图尺寸
int measureHeight = childView.getMeasuredHeight();
int measuredWidth = childView.getMeasuredWidth(); childView.layout(l, mTotalHeight, measuredWidth, mTotalHeight
+ measureHeight); mTotalHeight += measureHeight; }
} }

第二步,布局文件:

<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"
android:background="#00f0f0"
tools:context=".MainActivity" > <net.loonggg.viewgroup.MyViewGroup
android:id="@+id/myViewGroup"
android:layout_width="480dp"
android:layout_height="300dp"
android:background="#0f0f0f" > <TextView
android:layout_width="200dp"
android:layout_height="100dp"
android:background="#000000"
android:gravity="center"
android:text="第一个TextView" /> <TextView
android:layout_width="100dp"
android:layout_height="200dp"
android:background="#ffffff"
android:gravity="center"
android:text="第二个TextView" />
</net.loonggg.viewgroup.MyViewGroup> </RelativeLayout>

第三步,MainActivity.java:

package net.loonggg.viewgroup;

import android.os.Bundle;
import android.app.Activity; public class MainActivity extends Activity { @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
} }

ok,你们大家懂了吗?有问题请留言。

通过重写ViewGroup学习onMeasure()和onLayout()方法的更多相关文章

  1. 继承ViewGroup学习onMeasure()和onLayout()方法

    在继承ViewGroup类时,需要重写两个方法,分别是onMeasure和onLayout. 1,在方法onMeasure中调用setMeasuredDimension方法void android.v ...

  2. 【转】ViewGroup的onMeasure和onLayout分析

    ViewGroup的onMeasure和onLayout分析 一个Viewgroup基本的继承类格式如下: 1 import android.content.Context; 2 import and ...

  3. Android的onMeasure和onLayout And MeasureSpec揭秘

    Android中自定义ViewGroup最重要的就是onMeasure和onLayout方法,都需要重写这两个方法,ViewGroup绘制 的过程是这样的:onMeasure → onLayout → ...

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

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

  5. 自定义ViewGroup基础巩固1---理解onLayout()方法

    自定义ViewGroup这个是在android中自定义控件中不可获缺的很重要的一部分,关于它的意义这里就不过多阐述了,为了在未来深入上继续走下去,所以先把基础给打牢. 这篇主要是理解ViewGroup ...

  6. java===java基础学习(12)---方法的重写和重载

    覆盖 / 重写(Override) 重写是子类对父类的允许访问的方法的实现过程进行重新编写, 返回值和形参都不能改变.即外壳不变,核心重写! 重写的好处在于子类可以根据需要,定义特定于自己的行为. 也 ...

  7. C#基础知识学习(1)方法的重写和隐藏

    做了1年多了C#,发现些项目过程中很多基础东西都不是很清晰,基础不够牢固.现在开始复习基础知识并做重点记录 方法需要被重写的时候,可以在方法前加入virtual使方法变成虚方法. 这样我们可以重新写个 ...

  8. Android开发之View重写相关API-onLayout,onMeasure,MeasureSpec

     1.onLayout android.view.ViewGroup protected void onLayout(boolean changed, int l, int t, int r, int ...

  9. 对于view的深入理解,续篇(一)重写ViewGroup的onDraw

    在上一篇文章中,不仅熟悉了动态设定布局的方法,而且也对view的绘制流程有所了解.于是我继续做了下面几个实验,发现了一个问题.如果对view的绘制流程不是很明白,可以看看我的上一篇文章的介绍,点击下面 ...

随机推荐

  1. 显示、更改ubuntu linux主机名(计算机名)

    在bash中输入hostname可以显示计算机名.Linux和windows都可以使用这条指令. 主机名保存在/etc/hostname文件中 需要进入Root权限才可以修改该文件. sudo ged ...

  2. CSS:响应式下的折叠菜单(条纹式)

    原文:CSS: Responsive Navigation Menu 译文:CSS:响应式导航菜单 译者:dwqs 写在之前,关于如何制作响应式的下拉菜单:响应式下的下拉菜单 之前,我写了一篇关于怎么 ...

  3. 2019.03.09 ZJOI2019模拟赛 解题报告

    得分: \(20+0+40=60\)(\(T1\)大暴力,\(T2\)分类讨论写挂,\(T3\)分类讨论\(40\)分) \(T1\):天空碎片 一道神仙数学题,貌似需要两次使用中国剩余定理. 反正不 ...

  4. 计算最大矩形面积,POJ(2082)

    题目链接:http://poj.org/problem?id=2082 把矩形按照高度一次递增的循序排列,当违反这一规则的时候,更新ans,用新的data替换之前的矩形.然后最后扫一遍. #inclu ...

  5. 今天 小小收获, 看了 sam Xiao 的好帖子 明白了 泛型委托 的 意思。

    Func<int,int,int> cAdd1 = (int x, int y) => { return x + y; }; int result= aAdd1(1,2); cons ...

  6. python3 安装turtle tkitnter 报错

    导入tkinter模块后,运行出现No module named _tkinter, please install the python-tk package ubuntu运行tkinter错误   ...

  7. vue 城市搜索组件

    1.实现大致是如下效果 2.搜索组件的页面结构 <template>    <div>     <div class="search">     ...

  8. 实现一个clone函数,对javascript中的5种数据类型进行值复制

    <!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  9. shell编程中的vim命令说明

    vim命令模式:  1.一般命令模式 2.编辑模式 3.底行命令行命令模式 一般命令模式 直接用字符操作编辑模式 可以写文档(跟txt有点像)底行命令模式 先按'ESC',在按下“:”,之后在输出命令 ...

  10. 【学时总结】◆学时·VI◆ SPLAY伸展树

    ◆学时·VI◆ SPLAY伸展树 平衡树之多,学之不尽也…… ◇算法概述 二叉排序树的一种,自动平衡,由 Tarjan 提出并实现.得名于特有的 Splay 操作. Splay操作:将节点u通过单旋. ...