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 ...
随机推荐
- ngx.ctx
https://github.com/openresty/lua-nginx-module#ngxctx 要点 生命周期和请求一致 每个请求的ngx.ctx是相互独立的,包括ngx.location. ...
- DrawerLayout案例
布局文件: <?xml version="1.0" encoding="utf-8"?> <android.support.v4.widget ...
- Xcode 中的断言
转自:http://weibo.com/p/100808885591f113cdedc3301794e5e7d7e9f0/home?from=page_100808&mod=TAB#_rnd1 ...
- ICL Auto Vectorization
简介 此文简单介绍如何使用intel c++编译器实现向量化加速. 全文如下安排: base : 待优化的源代码. vectorization : 第一个向量化版本. aligned : 内存对其对向 ...
- Freeline--Android平台上的秒级编译方案
Freeline 技术揭秘 Freeline是什么? Freeline是蚂蚁金服旗下一站式理财平台蚂蚁聚宝团队15年10月在Android平台上的量身定做的一个基于动态替换的编译方案,5月阿里集团内部 ...
- 高性能的Redis代理TwemProxy
TwemProxy是一个Redis的中间件代理,具有很多有用的功能,可以暂时替代一部分Redis Cluster的功能: ² 支持和6479.之后相应地,配置好两个Redis实例并启动.现在就可以启 ...
- java之IO流详解(一)
IO流的分类: A:流向 输入流 读取数据 输出流 写出数据 B:数据类型 字节流 字节输入流 InputStream 字节输出流 OutputStream 字符流 字符输入流 Reader 字 ...
- 如何在苹果手机上安装自制的AD证书
写这篇博文的契机是有人已经实现了CRM在用自制证书部署IFD后,在手机安装上自制证书后即可登录官方移动端APP,因为之前很多人都尝试过只要是自制证书部署的IFD就无法使用官网手机APP,而本人实验下来 ...
- iOS开发之Xcode常用调试(Debug)技巧总结
一.Xcode调试技巧之:NSLog 上面也提到了,在我们日常的开发过程中最常见的Debug方式就是打Log.而在OC语言中,打Log是采用NSLog方法.但是NSLog效率低下,具体原因可以看这篇博 ...
- 【shell点滴】参数变量
参数变量故名思议就是用来操作输入参数的变量,知道用户输入了哪些参数,才可以进行相应的处理. 参数变量 作用 $1,$2- 取第几个参数的意思 $* 取出所有的参数,解析参数的分割符环境变量 IFS 来 ...