View的测量

关于几点说明

  1. Android中每个Activity包含一个Window对象,这个Window对象就是PhoneWindow
  2. PhoneWindow将DecorView设为根View
  3. 所有View的监听事件都是通过WindowManagerService来进行接收的
  4. 在显示上屏幕是分两部分的,TitleView和ContentView
  5. setContentView就是设置ContentView,requestWindowFeature(Window.FEAUTRE_NO_TITLE)就是来设置全屏

View的测量

  1. View的测量是通过MeasureSpec类,测量模式有三种:EXACTLY精准模式、AT_MOST最大模式(控件属性指定为wrap_content)、UNSPECIFIED默认模式想多大多大,一般自定义View时才使用
  2. View类默认的onMeasure()方法只支持EXACTLY模式,自定义控件如果不重写onMeasure()方法时,只能使用EXACTLY模式。指定具体值或match_parent属性,要View支持wrap_content属性就必须重写该方法

测量示例

1、当指定具体值或者match_parent属性时显示对应的大小,当指定wrap_content时不显示全屏,显示一个我们定义的大小

因为是在Android Studio中测试的,所以自定义View就变得相对比Eclipse中药简单些。
步骤:

  1. 在AS中新建一个自定义View,右键->UI Component->Custom View。
  2. 重写onMeasure方法,Code->Override Methods,输入onMeasure就可以了。

重写的内容:

public class MyView extends View {
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        // super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        setMeasuredDimension(
                measureWidth(widthMeasureSpec),
                measureHeight(heightMeasureSpec));
    }

    private int measureWidth(int measureSpec){
        int result = 0;
        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize = MeasureSpec.getSize(measureSpec);

        if(specMode == MeasureSpec.EXACTLY){
            result = specSize;
        }else {
            result = 200;
            if (specMode == MeasureSpec.AT_MOST) {
                result =Math.min(result,specSize);
            }
        }
        return result;
    }

    private int measureHeight(int measureSpec){
        int result = 0;
        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize = MeasureSpec.getSize(measureSpec);

        if(specMode == MeasureSpec.EXACTLY){
            result = specSize;
        }else {
            result = 200;
            if (specMode == MeasureSpec.AT_MOST) {
                result =Math.min(result,specSize);
            }
        }
        return result;
    }
}

content_main.xml文件内容(此处只写了wrap_content一种情况):

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context="com.example.yzx.mytest_book.MainActivity"
    tools:showIn="@layout/activity_main">

    <com.example.yzx.mytest_book.UI.MyView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="#ccc"
    app:exampleColor="#33b5e5"
    app:exampleDimension="12sp"
    app:exampleString="Hello, MyView" />
</RelativeLayout>

说明:exampleColor、exampleDimension、exampleString是定义在values文件下的attrs.xml文件中的。

<resources>
    <declare-styleable name="MyView">
        <attr name="exampleString" format="string" />
        <attr name="exampleDimension" format="dimension" />
        <attr name="exampleColor" format="color" />
        <attr name="exampleDrawable" format="color|reference" />
    </declare-styleable>
</resources>

指定宽高值为300dp时:

这里写图片描述

宽高值为match_parent:

这里写图片描述

宽高值为wrap_content:

这里写图片描述

可以发现,当指定wrap_content属性时,View就获得了一个默认200px,而不是再填充父布局了。如果不重写onMeasure()方法,那么系统就不知道该使用默认多大的尺寸。因此,它就会默认填充整个父布局,所以重写onMeasure()方法的目的,就是为了给View一个wrap_content属性下的默认大小。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值