View[6] inflate()、addView()removeView() 及 LayoutParams
【参考链接】
LayoutParams
LayoutParams主要是构造于布局文件中的layout_width、layout_height属性,用于后续的measure()过程
以ViewGroup.LayoutParams为例,只提供了width、height成员变量
而各个子ViewGroup,则依据自己的布局特性,继承自ViewGroup.LayoutParams并扩展出自己的LayoutParams
以LinearLayout.LayoutParams为例,增加了我们熟知的layout_weight成员变量
inflate()
LayoutInflater提供了inflate()方法来从xml布局文件创建一个View对象。其内部是通过pull的方式来解析xml的。
publicView inflate(intresource,ViewGroup root, booleanattachToRoot) {
通过源码可知
如果root=null,则读取xml创建View,未设置LayoutParams,此时后面的attachToRoot参数无实际作用
如果root!=null,则读取xml创建View,并设置LayoutParams,(LayoutParams由root.generateLayoutParams(attrs)方法创建)。此时如果attachToRoot=true,则还会将其添加到root中。
以如下代码为例
button.xml
<?xml
version="1.0"encoding="utf-8"?>
<Button xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#00FF00"
android:text="HelloWorld">
</Button>
FrameLayout frame =(FrameLayout) findViewById(R.id.frame);
View inflate =getLayoutInflater().inflate(R.layout.button,frame,
false);
frame.addView(inflate);
//效果同getLayoutInflater().inflate(R.layout.button,frame,
true);
此外View还提供了inflate()方法用于书写方便
X:\android-2.3.3_r1\frameworks\base\core\java\android\view\View.java
X:\android-2.3.3_r1\frameworks\base\core\java\android\view\LayoutInflater.java
addView()/removeView()
ViewGroup提供了addView()方法用于向ViewGroup中添加子View
上面inflate()如果布局文件中存在子View,则会自动调用addView()添加子View。
在某些需求场景下,我们也可以自己调用addView(),此时其内部会调用requestLayout()触发重新布局重绘。
从源码可知
如果传递了LayoutParams,则会将其覆盖子View已有的LayoutParams,
如果没有传递LayoutParams,则会使用子View已有的LayoutParams,如果子View还没有设置LayoutParams,则ViewGroup会为其自动创建一个。
以如下布局文件为例
<?xml
version="1.0"encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="400px"
android:layout_height="400px"
android:background="#FF0000"
android:orientation="vertical"
tools:context="com.example.shadowfaxghh.demo.MainActivity"
android:id="@+id/frame">
</FrameLayout>
如果传递LayoutParams
FrameLayout frame =(FrameLayout) findViewById(R.id.frame);
Button btn=newButton(this);
frame.addView(btn, newFrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT));
因为默认有background,并且有padding。
如果未传递LayoutParams,则FrameLayout会为其创建一个MATCH_PARENT x MATCH_PARENT的
FrameLayout frame =(FrameLayout) findViewById(R.id.frame);
Button btn=newButton(this);
frame.addView(btn);
X:\android-2.3.3_r1\frameworks\base\core\java\android\widget\FrameLayout.java
当我们自己调用addView()\removeView()的时候,其会遵从ViewGroup的布局约束,并且内部重新布局重绘,以此可以达到动态刷新界面的效果。
如下是向LinearLayout中添加子View