-“爹,我要吃糖”

-“好哒儿子”

-“爹,我要吃包包”

- “好哒儿子”

- “爹,我要吃串串”

- “好哒儿子”

- “爹,我要大保健”

- (啪啪啪,三耳光)

儿子是一定要听爹话的,那么在Android世界里,是不是这样呢? 今天就来和大家讨论一下 View 父子之间的琐事。

大家都知道,儿子肯定有自己想做的事情,也就是有自己的思想。那么转换到Android的View上面呢,就是测量啦。View自己会测量自己,告诉父布局他自身有多大,要占多大空间。可儿子就能胆大妄为,想怎么样就怎么样吗,答案是否定的。

View的最终大小不是由自己决定的,而是由layout决定。

这里我们来做一个实验。

比如,新写一个矩形自定义view:

public class RectView extends View {
private Paint mPaint;
private int mWidth;
private int mHeight; public RectView(Context context) {
this(context, null);
} public RectView(Context context, AttributeSet attrs) {
this(context, attrs, 0); } public RectView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mPaint = new Paint();
} @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec); if(widthMode == MeasureSpec.AT_MOST){
mWidth = 200;
} if(heightMode == MeasureSpec.AT_MOST){
mHeight = 200; }
setMeasuredDimension(mWidth,mHeight);
} @Override
protected void onDraw(Canvas canvas) {
canvas.drawRect(0,0,mWidth,mHeight,mPaint);
super.onDraw(canvas);
}
}

这里简单处理了一下 这个view的wrap_content时候的大小,写死为200px(注意是px不是dp)。

放到一个linearLayout下,看看效果

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:orientation="vertical"
tools:context="com.wingsofts.father.MainActivity"> <com.wingsofts.father.RectView
android:layout_width="wrap_content"
android:layout_height="wrap_content" /> <Button
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<com.wingsofts.father.RectView android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>



可以看到,在wrap_content的情况下,两个view的大小跟自己预期的一样。(这种情况就是:“老爹,我想吃包子” “好哒儿子”)。

其实这篇文章的起源来与一个layout函数,大家都知道layout函数决定了一个view在什么位置。但是大家有没有想过,既然是先测量再layout的,为什么layout函数需要四个参数?既然测量知道view的大小了,那么只需要左上角x,y两个坐标不就好了吗?

layout(int l,int t,int r,int b);

难道测量的大小并不能真正决定view自己的大小吗?测量出来的值只是一个期望值,而不是最终的值吗,最终还是要听老爹话吗?我们来实验一下就知道了。(“老爹,我要大保健”)

自己新建一个viewgroup,继承自LinearLayout

public class MyLinear extends LinearLayout {
public MyLinear(Context context) {
this(context, null);
} public MyLinear(Context context, AttributeSet attrs) {
this(context, attrs, 0);
} public MyLinear(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
} @Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
//调用父类方法
super.onLayout(changed, l, t, r, b);
//将第一个view布局到0,0,50,50位置
View v = getChildAt(0);
v.layout(0,0,50,50);
}
}

这时候布局只是把LinearLayout改成MyLinear。



(儿贼,听说你要大保健,先来尝尝爹的大宝剑!咔咔咔嚓,给削小了)

呃呃呃。。。看来在android世界中,儿子也是要听老子的啊。一般的要求绝对满足,有非分之想,过不了老子那关啊。

  • 再来个彩蛋吧。。

话说,大家一定有过一个拿空白View(其实用Space标签比较好)去占一定大小的经历(损招,但是有时候很好用)。。

比如通常希望一个空白view占据50dp的宽度,高度写为wrap_content 。

<LinearLayout 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:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.wingsofts.father.MainActivity"> <Button
android:layout_width="wrap_content"
android:layout_height="wrap_content" /> <View
android:layout_width="50dp"
android:layout_height="wrap_content" /> <Button
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>

那么你就会发现。。

WTF??? 为毛是全屏的高度。我写的是wrap_content啊。。难道View的wrap_content就是全屏??

不要急。。我们来read the fxxking source code ..

直接定位到view的onMeasure方法

   protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
}

额。。没啥东西呀,继续跳到getDefaultSize()

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:
result = size;
break;
case MeasureSpec.AT_MOST:
case MeasureSpec.EXACTLY:
result = specSize;
break;
}
return result;
}

呃呃。。 问:小白为什么长得像他哥哥。

这下真像大白了:原来,在View自身wrap_content(也就是AT_MOST模式),switch的case下面是没有break的,也就是说,

如果View没有处理AT_MOST模式,那么wrap_content自动当成match_parent处理。

呃呃。。跑题了。。。 好吧,没啥说的了,写这篇文章就是告诉大家一个道理。儿子就得听爹的话。。。 拜拜。如果你喜欢我的博客,记得关注我。

Android轶事之View要去大保健?View大小自己决定?的更多相关文章

  1. 【转】Android绘制View的过程研究——计算View的大小

    Android绘制View的过程研究——计算View的大小 转自:http://liujianqiao398.blog.163.com/blog/static/18182725720121023218 ...

  2. android 自定义控件——(二)圆形按钮,圆形View

    ----------------------------------↓↓圆形按钮,圆形View(源代码下有属性解释)↓↓---------------------------------------- ...

  3. android Gui系统之WMS(1)----window flags & view flags

    SurfaceFlinger 前面说的,就是一个surface的合成.SurfaceFlinger就是一个默默的记录着,它不会对surface的内容有什么改动. WMS(WindowsManagerS ...

  4. Android中View绘制优化之三---- 优化View

    本文原创, 转载请注明出处:http://blog.csdn.net/qinjuning 译三: 优化视图 关于如何设计自定义View以及响应触摸时间等,请看Android developer : 地 ...

  5. Android音频处理——通过AudioRecord去保存PCM文件进行录制,播放,停止,删除功能

    Android音频处理--通过AudioRecord去保存PCM文件进行录制,播放,停止,删除功能 音频这方面很博大精深,我这里肯定讲不了什么高级的东西,最多也只是一些基础类知识,首先,我们要介绍一下 ...

  6. Android的进阶学习(六)--理解View事件分发

    http://www.jianshu.com/p/34cb396104a7 有些无奈,期末考试抱佛脚,还好没有挂,现在继续进阶. 好久以前就看到了View的事件分发,但是当时功底不够,源码也不敢深究, ...

  7. Android事件分发机制二:viewGroup与view对事件的处理

    前言 很高兴遇见你~ 在上一篇文章 Android事件分发机制一:事件是如何到达activity的? 中,我们讨论了触摸信息从屏幕产生到发送给具体 的view处理的整体流程,这里先来简单回顾一下: 触 ...

  8. 在Android中将子View的坐标转换为父View的坐标

    在Android中,我们有时候可能会将子View的坐标转换为父View中的坐标.感觉很有用,分享给大家. 在Launcher中有这么一段代码可以完成这项工作.  public float getDes ...

  9. Xamarin Android开发实战(上册)大学霸内部资料

    Xamarin Android开发实战(上册)大学霸内部资料   试读文档下载地址:http://pan.baidu.com/s/1jGEHhhO 密码:vcfm 介绍: 本教程是国内唯一的Xamar ...

随机推荐

  1. jQuery 效果 – 停止动画

    jQuery stop() 方法用于在动画或效果完成前对它们进行停止. 点击这里,向上/向下滑动面板 实例 jQuery stop() 滑动 演示 jQuery stop() 方法. jQuery s ...

  2. Docker 编辑网络配置文件

    Docker 1.2.0 开始支持在运行中的容器里编辑 /etc/hosts, /etc/hostname 和 /etc/resolve.conf 文件. 但是这些修改是临时的,只在运行的容器中保留, ...

  3. JAVA处理Blob大对象

    Blob对象是SQL Blob的Java语言映射.SQL Blob是一个内置类型,它可以将一个二进制大对象保存在数据库中.接口ResultSet.CallableStatement和PreparedS ...

  4. Mybatis源码分析--关联表查询及延迟加载原理(二)

    在上一篇博客Mybatis源码分析--关联表查询及延迟加载(一)中我们简单介绍了Mybatis的延迟加载的编程,接下来我们通过分析源码来分析一下Mybatis延迟加载的实现原理. 其实简单来说Myba ...

  5. Lucene 6.0下使用IK分词器

    Lucene 6.0使用IK分词器需要修改修改IKAnalyzer和IKTokenizer. 使用时先新建一个MyIKTokenizer类,一个MyIkAnalyzer类: MyIKTokenizer ...

  6. log file sync 等侍值高的一般通用解决办法

    log file sync等待时间发生在redo log从log buffer写入到log file期间. 下面对log file sync做个详细的解释. 何时发生日志写入: 1.commit或者r ...

  7. [CSDN_Markdown] 使用LaTeX写矩阵

    简介 LaTeX 的公式功能非常强大,一次性讲全不是件容易的事情.将LaTeX 的这些功能分成较小的相互独立的部分来讲,一方面方便大家单独查阅:另一方面,所有[CSDN_Markdown]相关的文章都 ...

  8. ant编译mysql驱动

    修改驱动源码后需要重新编译构建,由于mysql编译需要两个jdk版本且还需要hibernate4和junit,这里记录下. 安装ant. 配置两个jdk,5和8.并修改build.xml配置,如下: ...

  9. Android图表库MPAndroidChart(四)——条形图的绘制过程过程,隐隐约约我看到了套路

    Android图表库MPAndroidChart(四)--条形图的绘制过程过程,隐隐约约我看到了套路 在学习本课程之前我建议先把我之前的博客看完,这样对整体的流程有一个大致的了解 Android图表库 ...

  10. JAVA面向对象-----内部类的概述

    JAVA面向对象-–内部类的概述s 将类定义在另一个类的内部则成为内部类.其实就是类定义的位置发生了变化. 在一个类中,定义在类中的叫成员变量,定义在函数中的叫成员函数,那么根据类定义的位置也可以分为 ...