match_parent、wrap_parent、具体值 和 MeasureSpec 类中 mode 的对应关系

测试结果如下:

* wrap_parent -> MeasureSpec.AT_MOST

* match_parent -> MeasureSpec.EXACTLY

* 具体值 -> MeasureSpec.EXACTLY

一个 view 的 onMeasure 方法最终得到的测量规格值(测量约束值)中包含的测量模式和上面不一定对的上,这是因为 onMeasure 方法中得到的测量规格值(测量约束值)是 measure 方法传过来的,父 view 在调用 measure 方法的时候可以根据自己的情况不使用 ViewGroup 提供的 measureChildren 方法,而改变上面的映射关系,比如 RelativeLayout 中就结合其他 Layout 属性综合确定 MeasureSpec 中的模式。上面的映射关系可以直接查看
ViewGroup 类的 measureChildren 方法,这是最简单的 measure 方式.

ViewGroup 中 measureChild 方法如下:

    protected void measureChild(View child, int parentWidthMeasureSpec,
            int parentHeightMeasureSpec) {
        final LayoutParams lp = child.getLayoutParams();

        final int childWidthMeasureSpec = getChildMeasureSpec(parentWidthMeasureSpec,
                mPaddingLeft + mPaddingRight, lp.width);
        final int childHeightMeasureSpec = getChildMeasureSpec(parentHeightMeasureSpec,
                mPaddingTop + mPaddingBottom, lp.height);

        child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
    }

测试代码如下

TestView.java

/**
 * 测试 match_parent、wrap_parent、具体值 和 MeasureSpec 中  mode 的对应关系
 */
package com.example.testmeasurespec;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;

public class TestView extends View {

    private static final String TAG = "TestView";

    public TestView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    public TestView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public TestView(Context context) {
        super(context);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        Log.i(TAG, "onMeasure:" + getTag());
        setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
                getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
    }

    public static int getDefaultSize(int size, int measureSpec) {
        int result = size;
        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize = MeasureSpec.getSize(measureSpec);

        switch (specMode) {
            case MeasureSpec.UNSPECIFIED:
                Log.i(TAG, "specMode:MeasureSpec.UNSPECIFIED");
                result = size;
                break;
            case MeasureSpec.AT_MOST:
                Log.i(TAG, "specMode:MeasureSpec.AT_MOST");
            case MeasureSpec.EXACTLY:
                Log.i(TAG, "specMode:MeasureSpec.EXACTLY");
                result = specSize;
                break;
        }
        return result;
    }
}

TestLayout.java

public class TestLayout extends ViewGroup {

    public TestLayout(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public TestLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public TestLayout(Context context) {
        super(context);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {

    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        measureChildren(widthMeasureSpec, heightMeasureSpec);
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
}

main_activity.xml

<com.example.testmeasurespec.TestLayout 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" >

    <com.example.testmeasurespec.TestView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@drawable/ic_launcher"
        android:tag="test1" />

    <com.example.testmeasurespec.TestView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@drawable/ic_launcher"
        android:tag="test2" />

    <com.example.testmeasurespec.TestView
        android:layout_width="20dp"
        android:layout_height="20dp"
        android:background="@drawable/ic_launcher"
        android:tag="test3" />

</com.example.testmeasurespec.TestLayout>
时间: 2024-08-04 15:31:38

match_parent、wrap_parent、具体值 和 MeasureSpec 类中 mode 的对应关系的相关文章

python第三十六天-----类中的特殊成员方法

__doc__ 查看尖的描述信息 __module__表示当前操作的对象所在的模块 __class__表示当前操作的对象所属的类 __init__构造方法 通过类创建对象自动执行 __del__析构方法,当前对象在内存中被释放自动斩妖执行 __call__对象后面加括号触发执行 __dict__查看类或对象中的成员 __str__如果一个类中定义了此方法,那么打印此类对象时,输出此方法的返回值 __getitem__当类中定义了一个字典的属性成员,可以获取 __setitem__设置修改类中字典

尽量理解xml 中LayoutParams的wrap_content, match_parent, 和具体值

概述:本文试图分析理解view 的measure 的过程,在分析过程中重点分析了LayoutParams 中MATCH_PARENT和MATCH_PARENT 的对应关系:onMeasure 默认值的计算过程:解释了onMeasure 接口中的注释中的问题,并提出一个问题:ViewRootImpl 是怎么创建的? 留作下篇引子.最后,讨论如何重写onMeasure()方法. LayoutParams 中MATCH_PARENT和MATCH_PARENT  的对应关系 为什么从perform 开始

NSMutableDictionary 类中增加键值对方法分析

在iOS中可变字典增加一个键值对的方法有setObject: forKey: 和setValue : forKey: .为了方便我们把这两个方法简称为方法A和方法B. B这个方法中其中的value值是不能为nil,否则程序会出项崩溃.而A方法中的这个value可以为nil,但是当这个value位nil时,系统会自动调用removeObjectforKey:这个方法.这样就把这个键值对删除掉了.B方法中的key值可以是任意类型的,但是这个类型必须要实现NSCopying协议.而A方法中它的key值

继承类中static数据值

1 class A{ 2 static int num = 1; 3 public static void Display(){ 4 System.out.println( num ); 5 } 6 } 7 8 class B extends A{ 9 static int num = 2; 10 public static void Display(){ 11 System.out.println( num ); 12 } 13 } 14 15 class C extends A{ 16 st

ascii#ascii,对象类中找__repr__,获取其返回值

1 #!/usr/bin/env python 2 #ascii,对象类中找__repr__,获取其返回值 3 class Foo : 4 def __repr__(self): 5 return "hello" 6 7 obj = Foo() 8 r = ascii(obj) 9 print(r )

java自定义Annotation,得到注解类中Annotation设定的注解值

java注解机制在各大框架中应用普遍,注解中可以设置一些值,如何得到呢. 要得到注解类中Annotation设定的注解值 即:遍历自定义Annotation中的方法,反射执行方法,结果就是 对应的注解值. java代码例子: package com.doctor.spring.core; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotat

Java通过反射机制修改类中的私有属性的值

首先创建一个类包含一个私有属性: class PrivateField{ private String username = "Jason"; } 通过反射机制修改username的值: //创建一个类的对象 PrivateField privateField = new PrivateField(); //获取对象的Class Class<?> classType = privateField.getClass(); //获取指定名字的私有域 Field field =

使用在类中定义的有返回值的函数,如何得到执行结果反馈?

我们做开发时,程序执行完后最好会有个反馈结果,尤其是在庞大的程序中,如果有bug可以及时发现,不然很浪费时间...最近做sde的二次开发,创建数据集时要用到带有返回值的函数,因为在数据集上创建要素类需要用到这个数据集,声明一个全局变量,可以直接用这个返回值.但是在捕获错误方面受到了限制,因为有返回值的函数每一个节点都要有返回值,想直接得到反馈是不行的,想在方法执行后写结果反馈的代码是检测不到的. 只能向师傅求救,给我提供了两种方法解决,感觉很巧妙. 原来的代码: Form1中的代码: priva

将source类中的属性值赋给target类中对应的属性

/** * 对象的属性值拷贝 * <p> * 将source对象中的属性值赋值到target对象中的属性,属性名一样,类型一样 * <p> * example: * <p> * source: * <p> * String name; * String address; * Integer age; * Date birthday; * <p> * target: * String name; * String address; * String