定义:

我们可以在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参数使用的简单总结的更多相关文章

  1. Android中调用C++函数的一个简单Demo

    这里我不想多解释什么,对于什么JNI和NDK的相关内容大家自己去百度或谷歌.我对Android的学习也只是个新手.废话少说直接进入正题. 一.在Eclipse中创建一个Android Applicat ...

  2. Android中的AsyncTask异步任务的简单实例

    在 Android中的AsyncTask异步任务的简介 一文中.已经对 安卓 异步任务操作做了简单的介绍.这里,直接将上文中的异步任务做了一个实例.实现异步操作更新UI线程,相比开启子线程更新来说逻辑 ...

  3. Android中pull解析XML文件的简单使用

    首先,android中解析XML文件有三种方式,dom,sax,pull 这里先讲pull,稍候会说SAX和DOM pull是一种事件驱动的xml解析方式,不需要解析整个文档,返回的值是数值型,是推荐 ...

  4. Android中android-async-http开源网络框架的简单使用

    android-async-http开源网络框架是专门针对Android在Apache的基础上构建的异步且基于回调的http client.所有的请求全在UI线程之外发生,而callback发生在创建 ...

  5. android中OnItemClickListener的参数解释

    @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) {} ...

  6. 关于android中两种service的编写简单总结

    1.startservice (两种方法,继承service类或者继承intentservice 类) 继承service类,在onstartcommend重载方法中实现业务逻辑的处理,如果耗时过长最 ...

  7. Android中直播视频技术探究之---摄像头Camera视频源数据采集解析

    一.前言 在视频直播中一般都是两种视频数据源,一个是摄像头数据,一个是录制桌面数据,而一般来说美女妹子直播都是来自于摄像头数据,游戏直播都是录制桌面数据的,那么今天就来看看第一个数据源数据采集分析,A ...

  8. 一个demo让你彻底理解Android中触摸事件的分发

    注:本文涉及的demo的地址:https://github.com/absfree/TouchDispatch 1. 触摸动作及事件序列 (1)触摸事件的动作 触摸动作一共有三种:ACTION_DOW ...

  9. mono for android中使用dapper或petapoco对sqlite进行数据操作

    在mono for android中使用dapper或petapoco,很简单,新建android 类库项目,直接把原来的文件复制过来,对Connection连接报错部分进行注释和修改就可以运行了.( ...

随机推荐

  1. 安装python 的 包 paramiko

    安装python 的 包 paramiko 安装 依赖 yum -y install gcc python-devel 获取安装 pycryptowget https://pypi.python.or ...

  2. 平衡树模板 bzoj 3224

    program t3224; var tr:array[-1..1000000,1..2] of int64; num,fa,size,quan:array[-1..1000000] of int64 ...

  3. 125 Valid Palindrome

    public class Solution { public boolean isPalindrome(String s) { if(s==null) return false; s=s.toLowe ...

  4. 大熊君说说JS与设计模式之------状态模式State

    一,总体概要 1,笔者浅谈 状态模式,又称状态对象模式(Pattern of Objects for States),状态模式是对象的行为模式. 状态模式主要解决的是当控制一个对象状态的条件表达式过于 ...

  5. ASP.NET最误导人的错误提示:“未预编译文件,因此不能请求该文件”

    昨天在一个ASP.NET MVC项目中,一个预编译后的视图访问时总是报错: 未预编译文件,因此不能请求该文件(The file has not been pre-compiled, and canno ...

  6. [JS10] 获取时间

    <html> <head> <meta http-equiv="Content-Type" content="text/html; char ...

  7. Atitit. 解压缩zip文件 的实现最佳实践 java c# .net php

    Atitit. 解压缩zip文件 的实现最佳实践 java c# .net php 1. Jdk zip 跟apache ant zip 1 2. Apache Ant包进行ZIP文件压缩,upzip ...

  8. 生成月初月末便于拼接sql

    for ($i=1; $i < 13; $i++) { $date = strtotime(date("2015-$i-01")); $firstday = date(&qu ...

  9. iOS开发-图片高斯模糊效果

    iOS开发的时候有的时候需要将图片设置模糊,或者通过点击下拉方法,去除模糊,一切都是为了应用更受用户欢迎,iOS7之后半透明模糊效果得到大范围使用的比较大,现在也可以看到很多应用局部用到了图片模糊效果 ...

  10. LeakCanary 中文使用说明

    http://www.liaohuqiu.net/cn/posts/leak-canary-read-me/ LeakCanary 中文使用说明 分享到:新浪微博微信 10 May 2015 Leak ...