android中的layoutparams参数使用的简单总结
定义:
我们可以在Android的framework中的ViewGroup类里找到定义的类:
public static class LayoutParams{...}
此类有如下注释:
LayoutParams are used by views to tell their parents how they want to be laid out.
View对象使用LayoutParams对象来告知其上层控件自己需要多少空间。
The base LayoutParams class just describes how big the view wants to be for both width and height.
基础LayoutParams类只是定义了这个view需要占用的宽度和高度。
For each dimension, it can specify one of:
FILL_PARENT (renamed MATCH_PARENT in API Level 8 and higher), which means that the view wants to be as big as its parent (minus padding)
WRAP_CONTENT, which means that the view wants to be just big enough to enclose its content (plus padding)
an exact number
There are subclasses of LayoutParams for different subclasses of ViewGroup. For example, AbsoluteLayout has its own subclass of LayoutParams which adds an X and Y value.
对于每一个维度,也就是对于宽度和高度,LayoutParams对象均可以使用以下参数:
FILL_PARENT(api level 8及以上版本被更名为MATCH_PARENT),它表示这个view想要和包含它的控件在此维度上采用同样大小的尺寸
WRAP_CONTENT,它表示这个view在此维度上采用可以包含它的内容的尺寸
精确尺寸
有多个类继承于ViewGroup.LayoutParams类,比如,AbsoluteLayout类中定义了LayoutParams,它继承于ViewGroup.LayoutParams类
Android中,直接继承于ViewGroup.LayoutParams类的有:ViewGroup.MarginLayoutParams,间接继承的类有:Linearlayout.LayoutParams,RelativeLayout.LayoutParams,FrameLayout.LayoutParams等等。
使用1:
在代码中动态添加view可以采用如下方式:
TextView tv = new TextView(this);
tv.setText("hello world");
linearlayout.addView(tv);
此时就将tv按照默认的布局方式添加进viewgroup中了,这里的viewgroup具体就是linearlayout了。
那么这里只是采用了一句addview(view),没有传入任何的布局参数,那么默认的布局参数是什么呢?
代码跟踪:
在ViewGroup类中函数的定义以及注释:
/*Adds a child view. If no layout parameters are already set on the child, the default parameters for this ViewGroup are set on the child.
添加一个view。如果这个view没有layout parameters参数定义,那么就采取默认参数。
*/
public void addView(View child) {
addView(child, -1);
}
解读:addView(View child)函数直接调用了addView(View child, int index)。
public void addView(View child, int index) {
LayoutParams params = child.getLayoutParams();
if (params == null) {
params = generateDefaultLayoutParams();
if (params == null) {
throw new IllegalArgumentException("generateDefaultLayoutParams() cannot return null");
}
}
addView(child, index, params);
}
解读:使用view.getLayoutParams()的方式获取set在此view对象中的参数,如果此参数是空值,就通过generateDefaultLayoutParams()的方式产生一个LayoutParams。查看generateDefaultLayoutParams()函数的定义:
ViewGroup中定义如下:
protected LayoutParams generateDefaultLayoutParams() {
return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
}
仅仅返回一个固定形式的LayoutParam,文章开始时说了,LayoutParams有多个间接子类,那么进入LinearLayout中,看看是否override了此generateDefaultLayoutParams()函数。
LinearLayout中定义如下:
@Override
protected LayoutParams generateDefaultLayoutParams() {
if (mOrientation == HORIZONTAL) {
return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
} else if (mOrientation == VERTICAL) {
return new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
}
return null;
}
解读:根据LinearLayout的不同方向返回不同的LayoutParams对象,注意这里的LayoutParams对象的类型为LinearLayout.LayoutParams。
我们返回addView(View child, int index)函数继续跟踪:
public void addView(View child, int index, LayoutParams params) {
if (DBG) {
System.out.println(this + " addView");
}
// addViewInner() will call child.requestLayout() when setting the new LayoutParams
// therefore, we call requestLayout() on ourselves before, so that the child's request
// will be blocked at our level
requestLayout();
invalidate(true);
addViewInner(child, index, params, false);
}
//解释说明见:
http://stackoverflow.com/questions/21863631/calling-viewgroupaddview-or-viewgroupremoveview-from-viewdraw
requestLayout()函数的作用是,强制此view向上一直requestLayout,使得view调用measure和layout
(参考:
http://blog.csdn.net/djun100/article/details/11917777)
invalidate(true)函数的作用是,重新draw此view。
再看addViewInner()函数:
private void addViewInner(View child, int index, LayoutParams params,
boolean preventRequestLayout) {
//当ViewGroup中的object改变时,mTransition用以处理动画效果,此对象的类是LayoutTransition
if (mTransition != null) {
// Don't prevent other add transitions from completing, but cancel remove
// transitions to let them complete the process before we add to the container
mTransition.cancel(LayoutTransition.DISAPPEARING);
}
//addView(view)时会检查view是不是具有ViewParent,如果有,就会抛出下面的异常,一个view只能有一个ViewParent。注:ViewParent是一个接口,ViewGroup实现了此接口。
if (child.getParent() != null) {
throw new IllegalStateException("The specified child already has a parent. " +
"You must call removeView() on the child's parent first.");
}
//这里的addChild并非是将view添加至ViewGroup中,这里是在处理动画效果
if (mTransition != null) {
mTransition.addChild(this, child);
}
//检查params是否为空
if (!checkLayoutParams(params)) {
params = generateLayoutParams(params);
}
//preventRequestLayout参数的含义是:是否禁止这个child去requestLayout(),原因是当使用直接赋值的时候,不会触发任何方法,但是当使用setLayoutParams()方法时,此方法中会去调用requestLayout()。不过View中的mLayoutParams参数被注解成了hide,无法在我们自定义的类中直接赋值。
if (preventRequestLayout) {
child.mLayoutParams = params;
} else {
child.setLayoutParams(params);
} if (index < 0) {
index = mChildrenCount;
}
//addInArray()方法是将child添加到ViewGroup的mChildren对象中,mChildren是一个View[]类对象。
addInArray(child, index);
//assignParent()函数给child分配指定parent,并进行requestLayout(),采用preventRequestLayout进行判断,与上边的setLayoutParams()结合,可以保证child只调用一个requestLayout()
// tell our children
if (preventRequestLayout) {
child.assignParent(this);
} else {
child.mParent = this;
}
//焦点
if (child.hasFocus()) {
requestChildFocus(child, child.findFocus());
}
//和view所处环境相关的参数的设置
AttachInfo ai = mAttachInfo;
if (ai != null && (mGroupFlags & FLAG_PREVENT_DISPATCH_ATTACHED_TO_WINDOW) == 0) {
boolean lastKeepOn = ai.mKeepScreenOn;
ai.mKeepScreenOn = false;
child.dispatchAttachedToWindow(mAttachInfo, (mViewFlags&VISIBILITY_MASK));
if (ai.mKeepScreenOn) {
needGlobalAttributesUpdate(true);
}
ai.mKeepScreenOn = lastKeepOn;
} if (child.isLayoutDirectionInherited()) {
child.resetRtlProperties();
}
//回调
onViewAdded(child); if ((child.mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE) {
mGroupFlags |= FLAG_NOTIFY_CHILDREN_ON_DRAWABLE_STATE_CHANGE;
} if (child.hasTransientState()) {
childHasTransientStateChanged(child, true);
} if (child.isImportantForAccessibility() && child.getVisibility() != View.GONE) {
notifySubtreeAccessibilityStateChangedIfNeeded();
}
} //addViewInner()函数中涉及到的setLayoutParams()的具体实现,可以看到view调用了requestLayout()。在我们分析的这个addView()方法中,由于view的parent是null,因此mParent instanceof ViewGroup 返回的是false。
public void setLayoutParams(ViewGroup.LayoutParams params) {
if (params == null) {
throw new NullPointerException("Layout parameters cannot be null");
}
mLayoutParams = params;
resolveLayoutParams();
if (mParent instanceof ViewGroup) {
((ViewGroup) mParent).onSetLayoutParams(this, params);
}
requestLayout();
}
回过头来再看一下addView()的实现:
public void addView(View child, int index, LayoutParams params) {
// addViewInner() will call child.requestLayout() when setting the new LayoutParams
// therefore, we call requestLayout() on ourselves before, so that the child's request
// will be blocked at our level
requestLayout();
invalidate(true);
addViewInner(child, index, params, false);
}
android中的layoutparams参数使用的简单总结的更多相关文章
- Android中调用C++函数的一个简单Demo
这里我不想多解释什么,对于什么JNI和NDK的相关内容大家自己去百度或谷歌.我对Android的学习也只是个新手.废话少说直接进入正题. 一.在Eclipse中创建一个Android Applicat ...
- Android中的AsyncTask异步任务的简单实例
在 Android中的AsyncTask异步任务的简介 一文中.已经对 安卓 异步任务操作做了简单的介绍.这里,直接将上文中的异步任务做了一个实例.实现异步操作更新UI线程,相比开启子线程更新来说逻辑 ...
- Android中pull解析XML文件的简单使用
首先,android中解析XML文件有三种方式,dom,sax,pull 这里先讲pull,稍候会说SAX和DOM pull是一种事件驱动的xml解析方式,不需要解析整个文档,返回的值是数值型,是推荐 ...
- Android中android-async-http开源网络框架的简单使用
android-async-http开源网络框架是专门针对Android在Apache的基础上构建的异步且基于回调的http client.所有的请求全在UI线程之外发生,而callback发生在创建 ...
- android中OnItemClickListener的参数解释
@Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) {} ...
- 关于android中两种service的编写简单总结
1.startservice (两种方法,继承service类或者继承intentservice 类) 继承service类,在onstartcommend重载方法中实现业务逻辑的处理,如果耗时过长最 ...
- Android中直播视频技术探究之---摄像头Camera视频源数据采集解析
一.前言 在视频直播中一般都是两种视频数据源,一个是摄像头数据,一个是录制桌面数据,而一般来说美女妹子直播都是来自于摄像头数据,游戏直播都是录制桌面数据的,那么今天就来看看第一个数据源数据采集分析,A ...
- 一个demo让你彻底理解Android中触摸事件的分发
注:本文涉及的demo的地址:https://github.com/absfree/TouchDispatch 1. 触摸动作及事件序列 (1)触摸事件的动作 触摸动作一共有三种:ACTION_DOW ...
- mono for android中使用dapper或petapoco对sqlite进行数据操作
在mono for android中使用dapper或petapoco,很简单,新建android 类库项目,直接把原来的文件复制过来,对Connection连接报错部分进行注释和修改就可以运行了.( ...
随机推荐
- C#下搭建文件格式转换服务器
文件格式转换,相信很多涉及到office文档在线观看的都会需要,因为浏览器还不能完全支持直接打开office文档,所以很多情况下我们都需要将这些文档转换成flash能够播放的格式,但是另一个问题又来了 ...
- 曲演杂坛--EXISTS语句
通常在我写EXISTS语句时,我会写成IF EXISTS(SELECT TOP(1) 1 FROM XXX),也没细细考究过为什么要这么写,只是隐约认为这样写没有啥问题,那今天就深究下吧! 首先准备测 ...
- Intellij IDEA13无法使用SVN
症状:在公司里面idea13工作正常,到了家里后idea的svn就是无法正常工作,单独使用tortoisesvn一切正常,后来在网上看到有网友解决了这个问题,看了之后明白了为啥公司的正常,家里的不行, ...
- C#——Dictionary<TKey, TValue> 计算向量的余弦值
说明:三角函数的余弦值Cos我想,每个学计算机的理工人都知道,但是真的明白它的用途,我也是刚明白.每个人在初中或者高中的时候,都有这么个疑惑,学三角函数干什么用的?很直白的答案就是考试用的.而且当时的 ...
- lucene字典实现原理
http://www.cnblogs.com/LBSer/p/4119841.html 1 lucene字典 使用lucene进行查询不可避免都会使用到其提供的字典功能,即根据给定的term找到该te ...
- atitit.团队建设总结o6o fix
atitit.团队建设o6o fix #----- 无限放大梦想 2 要有自己的方向...主动添加自己的东东.. 3 有几个tech site,能晓得最新的的知识.. 3 有问题多交流, 3 失败的造 ...
- 更新日志 - BugHD Android 客户端上线
当我们讨论 Bug 的时候,总是一脸愁容.尤其是移动应用的开发者,要应对用户可能在各种场景下使用 App 时产生的莫名崩溃. 为了更好地解决开发者的焦虑,BugHD Android 客户端上线了,高效 ...
- Web端测试和移动端测试的区别
1.记录bug 在Web端可以通过系统自带的截图和QQ截图等方式来截取bug的图片,对于错误的地方可以用工具自带的标识来重点标记. 对于移动端设备可以用手机自带的截图工具来截图然后传到电脑上,个人一般 ...
- Swift 中范围和区间如何使用?
虽然现在swift语言已经发展到了2.0版了,但是相信很多学习iOS开发的童鞋仍对swift语言存在各种各样的疑问,今天小编将为大家详细介绍swift中的范围和区间,下面我们一起来看看吧. Range ...
- 聊天IM的时间戳显示规则
====================================================== 以下规则是在体验微信操作后,推测出来的规则,可能存在一些不准确的表述 ========== ...