Android轶事之View要去大保健?View大小自己决定?
-“爹,我要吃糖”
-“好哒儿子”
-“爹,我要吃包包”
- “好哒儿子”
- “爹,我要吃串串”
- “好哒儿子”
- “爹,我要大保健”
- (啪啪啪,三耳光)
儿子是一定要听爹话的,那么在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大小自己决定?的更多相关文章
- 【转】Android绘制View的过程研究——计算View的大小
Android绘制View的过程研究——计算View的大小 转自:http://liujianqiao398.blog.163.com/blog/static/18182725720121023218 ...
- android 自定义控件——(二)圆形按钮,圆形View
----------------------------------↓↓圆形按钮,圆形View(源代码下有属性解释)↓↓---------------------------------------- ...
- android Gui系统之WMS(1)----window flags & view flags
SurfaceFlinger 前面说的,就是一个surface的合成.SurfaceFlinger就是一个默默的记录着,它不会对surface的内容有什么改动. WMS(WindowsManagerS ...
- Android中View绘制优化之三---- 优化View
本文原创, 转载请注明出处:http://blog.csdn.net/qinjuning 译三: 优化视图 关于如何设计自定义View以及响应触摸时间等,请看Android developer : 地 ...
- Android音频处理——通过AudioRecord去保存PCM文件进行录制,播放,停止,删除功能
Android音频处理--通过AudioRecord去保存PCM文件进行录制,播放,停止,删除功能 音频这方面很博大精深,我这里肯定讲不了什么高级的东西,最多也只是一些基础类知识,首先,我们要介绍一下 ...
- Android的进阶学习(六)--理解View事件分发
http://www.jianshu.com/p/34cb396104a7 有些无奈,期末考试抱佛脚,还好没有挂,现在继续进阶. 好久以前就看到了View的事件分发,但是当时功底不够,源码也不敢深究, ...
- Android事件分发机制二:viewGroup与view对事件的处理
前言 很高兴遇见你~ 在上一篇文章 Android事件分发机制一:事件是如何到达activity的? 中,我们讨论了触摸信息从屏幕产生到发送给具体 的view处理的整体流程,这里先来简单回顾一下: 触 ...
- 在Android中将子View的坐标转换为父View的坐标
在Android中,我们有时候可能会将子View的坐标转换为父View中的坐标.感觉很有用,分享给大家. 在Launcher中有这么一段代码可以完成这项工作. public float getDes ...
- Xamarin Android开发实战(上册)大学霸内部资料
Xamarin Android开发实战(上册)大学霸内部资料 试读文档下载地址:http://pan.baidu.com/s/1jGEHhhO 密码:vcfm 介绍: 本教程是国内唯一的Xamar ...
随机推荐
- jQuery 效果 – 停止动画
jQuery stop() 方法用于在动画或效果完成前对它们进行停止. 点击这里,向上/向下滑动面板 实例 jQuery stop() 滑动 演示 jQuery stop() 方法. jQuery s ...
- Docker 编辑网络配置文件
Docker 1.2.0 开始支持在运行中的容器里编辑 /etc/hosts, /etc/hostname 和 /etc/resolve.conf 文件. 但是这些修改是临时的,只在运行的容器中保留, ...
- JAVA处理Blob大对象
Blob对象是SQL Blob的Java语言映射.SQL Blob是一个内置类型,它可以将一个二进制大对象保存在数据库中.接口ResultSet.CallableStatement和PreparedS ...
- Mybatis源码分析--关联表查询及延迟加载原理(二)
在上一篇博客Mybatis源码分析--关联表查询及延迟加载(一)中我们简单介绍了Mybatis的延迟加载的编程,接下来我们通过分析源码来分析一下Mybatis延迟加载的实现原理. 其实简单来说Myba ...
- Lucene 6.0下使用IK分词器
Lucene 6.0使用IK分词器需要修改修改IKAnalyzer和IKTokenizer. 使用时先新建一个MyIKTokenizer类,一个MyIkAnalyzer类: MyIKTokenizer ...
- log file sync 等侍值高的一般通用解决办法
log file sync等待时间发生在redo log从log buffer写入到log file期间. 下面对log file sync做个详细的解释. 何时发生日志写入: 1.commit或者r ...
- [CSDN_Markdown] 使用LaTeX写矩阵
简介 LaTeX 的公式功能非常强大,一次性讲全不是件容易的事情.将LaTeX 的这些功能分成较小的相互独立的部分来讲,一方面方便大家单独查阅:另一方面,所有[CSDN_Markdown]相关的文章都 ...
- ant编译mysql驱动
修改驱动源码后需要重新编译构建,由于mysql编译需要两个jdk版本且还需要hibernate4和junit,这里记录下. 安装ant. 配置两个jdk,5和8.并修改build.xml配置,如下: ...
- Android图表库MPAndroidChart(四)——条形图的绘制过程过程,隐隐约约我看到了套路
Android图表库MPAndroidChart(四)--条形图的绘制过程过程,隐隐约约我看到了套路 在学习本课程之前我建议先把我之前的博客看完,这样对整体的流程有一个大致的了解 Android图表库 ...
- JAVA面向对象-----内部类的概述
JAVA面向对象-–内部类的概述s 将类定义在另一个类的内部则成为内部类.其实就是类定义的位置发生了变化. 在一个类中,定义在类中的叫成员变量,定义在函数中的叫成员函数,那么根据类定义的位置也可以分为 ...