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连接报错部分进行注释和修改就可以运行了.( ...
随机推荐
- day8---多线程socket 编程,tcp粘包处理
复习下socket 编程的步骤: 服务端: 1 声明socket 实例 server = socket.socket() #括号里不写 默认地址簇使用AF_INET 即 IPv4 ...
- 【基础知识】.Net基础加强11天
一. 扩展方法 1. 声明扩展方法的步骤: 1> 类必须是static,方法是static ,第一个参数是被扩展的对象,前面标注(this 数据类型参数名). 2> 使用扩展方法的时候必须 ...
- 读《你必须知道的.NET》继承本质论 Bird bird=new Chicken()
我们创建如下的三层继承层次类. public abstract class Animal { public abstract void ShowType(); } public class Bird ...
- SVN中Branch的创建与合并
在使用源代码版本控制工具时,最佳实践是一直保持一个主干版本.但是为了应付实际开发中的各种情况,适时的开辟一些分支也是很有必要的.比如在持续开发新功能的同时,需要发布一个新版本,那么就需要从开发主干中建 ...
- Minifying Angular应用时产生的问题
一.产生的问题 如果你正在进行AngularJS的项目开发,生产时Minified JS文件有没有遇到下面问题: angular.module("myApp", []) .cont ...
- atitit.查看预编译sql问号 本质and原理and查看原生sql语句
atitit.查看预编译sql问号 本质and原理and查看原生sql语句 1. 预编译原理. 1 2. preparedStatement 有三大优点: 1 3. How to look gene ...
- paip.截取字符串byLastDot方法总结uapi python java php c# 总结
paip.截取字符串byLastDot方法总结uapi python java php c# 总结 ========uapi left_byLastDot right_byLastDot 目前 ...
- Leetcode 219 Contains Duplicate II STL
找出是否存在nums[i]==nums[j],使得 j - i <=k 这是map的一个应用 class Solution { public: bool containsNearbyDuplic ...
- mac系统安装php redis扩展
安装步骤如下: 1.下载redis扩展 下载地址:https://nodeload.github.com/nicolasff/phpredis/zip/master 2.下载下来是zip包 手动解压 ...
- Winform TreeView 查找下一个节点
转载:http://www.cnblogs.com/Ruiky/archive/2013/02/01/2888674.html public static class TreeViewHelper { ...