android自定义view获取控件,Android 自定义View onMeasure方法的实现

发觉自己在进行Android开发的时候发觉自己开发的APP的UI几乎是由第三方View库(比如 android-pulltorefresh,ActionBar-PullToRefresh)等等堆砌出来的,发觉自己居然没有自定义过一个控件。心好痛:)

本文是一篇对于Android自定义View时继承View 并实现 onMeasure() 方法的理解。

为什么要写这篇文章为了避免以后自定义View的时候掉坑。

我在国内搜了相关文章(=_=!英语实在拙计),居然发觉理解起来非常生硬,相同的文章也特别多(没错我就是在吐槽天朝的技术贴,尼玛一搜前几篇帖子都是一模一样)

帮助自己理解以及游客们0.0

问题为什麼要实现onMeasure()。

什么情况下需要实现onMeasure()。

实现onMeasure()有什么作用。

调用父类onMeasure()

首先定义一个类继承View,重写onMeasure(),并调用父类onMeasure()方法。public class MeasureExampleView extends View {

public MeasureExampleView(Context context) {

super(context);

}

public MeasureExampleView(Context context, AttributeSet attrs) {

super(context, attrs);

}

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

super.onMeasure(widthMeasureSpec, heightMeasureSpec);

}

}

再定义layout文件,使用MeasureExampleView并设置background,margin与父容器区分。<?xml version="1.0" encoding="utf-8"?>

android:layout_width="match_parent"

android:layout_height="match_parent">

android:background="@android:color/holo_blue_dark"

android:layout_margin="10dp"

android:layout_width="match_parent"

android:layout_height="match_parent" />

产生效果如下,不难发现MeasureExampleView充满了父控件

73d729ad59dacb97d81249e6eb9dd38d.png

修改layout文件中的MeasureExampleView layout_width以及layout_height属性修改成wrap_content,结果仍然是一样的,就不贴图了。

修改layout文件中LinearLayout(父容器) layout_width以及layout_height属性修改成固定的值比如50dp,产生效果如下。发现 MeasureExampleView 跟随了LinearLayout(父容器)设置的固定大小(50dpx50dp)。

dc873588b80b3903a0a7b0e38943fb36.png

修改layout文件中MeasureExampleView layout_width以及layout_height属性修改成固定的值比如50dp,产生效果如下,发现 MeasureExampleView 的大小为设定的值 50dp x 50dp

dc873588b80b3903a0a7b0e38943fb36.png

结论

重写onMeasure(),并调用父类onMeasure()时MeasureExampleView的layout_width以及layout_height属性值 match_parent 或者 wrap_content显示大小由其父容器控件决定。

MeasureExampleView设置为固定的值,就显示该设定的值

怎样重写onMeasure()

示例//widthMeasureSpec 和 heightMeasureSpec的值 由父容器决定

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

int width = measureDimension(DEFAULT_WIDTH, widthMeasureSpec);

int height = measureDimension(DEFAULT_HEIGHT, heightMeasureSpec);

setMeasuredDimension(width, height);

}

定义一个方法处理  widthMeasureSpec,heightMeasureSpec的值private int measureHanlder(int measureSpec){

int result = defaultSize;

int specMode = MeasureSpec.getMode(measureSpec);

int specSize = MeasureSpec.getSize(measureSpec);

if (specMode == MeasureSpec.EXACTLY) {

result = specSize;

} else if (specMode == MeasureSpec.AT_MOST) {

result = Math.min(defaultSize, specSize);

} else {

result = defaultSize;

}

return result;

}

说明

MeasureSpec.getSize()会解析MeasureSpec值得到父容器width或者height。

MeasureSpec.getMode()会得到三个int类型的值分别为:MeasureSpec.EXACTLY MeasureSpec.AT_MOST,MeasureSpec.UNSPECIFIED。

MeasureSpec.UNSPECIFIED 未指定,所以可以设置任意大小。

MeasureSpec.AT_MOST  MeasureExampleView可以为任意大小,但是有一个上限。比如这种情况<?xml version="1.0" encoding="utf-8"?>

android:layout_width="match_parent"

android:layout_height="match_parent">

android:background="@android:color/holo_blue_dark"

android:layout_margin="10dp"

android:layout_width="wrap_content"

android:layout_height="wrap_content" />

MeasureSpec.EXACTLY 父容器为MeasureExampleView决定了一个大小,MeasureExampleView大小只能在这个父容器限制的范围之内。

比如这种情况:<?xml version="1.0" encoding="utf-8"?>

android:layout_width="50dp"

android:layout_height="50dp">

android:background="@android:color/holo_blue_dark"

android:layout_margin="10dp"

android:layout_width="wrap_content"

android:layout_height="wrap_content" />

又或者是这种情况:<?xml version="1.0" encoding="utf-8"?>

android:layout_width="match_parent"

android:layout_height="match_parent">

android:background="@android:color/holo_blue_dark"

android:layout_margin="10dp"

android:layout_width="50dp"

android:layout_height="50dp" />

这样当你使用 android:layout_width|android:layout_height属性为:wrap_content时,MeasureView的大小为默认值 100dpx100dp,你也可以根据自己的规则去重写onMeasure()方法。

小结重写onMeasure()方法是为了自定义View尺寸的规则

如果你的自定义View的尺寸是根据父控件行为一致,就不需要重写onMeasure()方法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值