android中的layoutparams参数使用的简单总结

时间:2022-09-22 10:42:23

定义:

我们可以在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://*.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&plus;&plus;函数的一个简单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. UOJ79 一般图最大匹配

    题目描述 从前一个和谐的班级,所有人都是搞OI的.有 nn 个是男生,有 00 个是女生.男生编号分别为 1,-,n1,-,n. 现在老师想把他们分成若干个两人小组写动态仙人掌,一个人负责搬砖另一个人 ...

  2. Chocolat&period;js – 响应式的 jQuery Lightbox 插件

    Chocolat.js 使您能够显示一个或多个图像在同一页面上.给用户展示一组图片缩略图,可以显示全页或块.Chocolat.js 可以很好地处理所有主要的浏览器.它在下面这些浏览器测试通过:IE7+ ...

  3. 转:java&period;sql&period;SQLException&colon; &lbrack;Microsoft&rsqb;&lbrack;ODBC 驱动程序管理器&rsqb; 未发现数据源名称并且未指定默认驱动程序

    在Win7 64位系统下,使用Java+Access数据库编程,用Java连数据库时,出现错误提示,如下: Java java.sql.SQLException: [Microsoft][ODBC 驱 ...

  4. Ubuntu下Eclipse中文乱码问题解决(转)

    Ubuntu下Eclipse中文乱码问题解决 把Windows下的工程导入到了Linux下Eclipse中,由于以前的工程代码,都是GBK编码的(Windows下的Eclipse 默认会去读取系统的编 ...

  5. RCF

    1. RCF: 纯c++的RPC, 不引入IDL, 大量用到boost,比较强大.2. casocklib:  protobuf + asio 较完善实现3. eventrpc: protobuf + ...

  6. XSS解决方案系列之四:关于编码

    本文准备说明以下几个问题: 1. 关于重复编码的问题 2. 关于编码的多种形式的问题 3. 关于编码的几个常见问题 [说明] 本文所述编码是指encode,可以理解为转义,而不是编程序写代码. 编码或 ...

  7. &period;net好好地利用Conditional属性

    Conditional是.net提供关于编译的属性描述,其作用是添加到方法或属上,通过定义编译符的方式告指示编译器应忽略方法调用或属性.在.NET中Debug 和 Trace 类中的方法都添加了这属性 ...

  8. &lbrack;20190213&rsqb;测试服务端打开那些端口&period;txt

    [20190213]测试服务端打开那些端口.txt --//前几天测试使用发送信息到/dev/tcp/ip_address/port,测试端口是否打开.写简单写一个脚本验证看看. $ seq 1 65 ...

  9. Sql入门学习——基本语法函数

    --------使用工具navicat 快捷键操作 --------基本操作DML &DDL --------运算比较 --------数据类型 --------常用函数 --------常用 ...

  10. cin中函数的作用

    cin是istream类的对象,它是从标准输入设备(键盘)获取数据,程序中的变量通过流提取符">>"从流中提取数据.流提取符">>"从流 ...