LayoutParams
每个 ViewGroup
(例如 LinearLayout
, RelativeLayout
, CoordinatorLayout
等)都需要存储有关其子项属性的信息。关于他们的孩子在这里铺设的方式 5。此信息存储在包装类 ViewGroup.LayoutParams
的对象中。
要包含特定布局类型的参数,ViewGroups
使用 ViewGroup.LayoutParams
类的子类。
例如
LinearLayout
它是LinearLayout.LayoutParams
RelativeLayout
它是RelativeLayout.LayoutParams
CoordinatorLayout
它是CoordinatorLayout.LayoutParams
- …
大多数 ViewGroups
都重新使用了为孩子设置 margins
的能力,因此他们不直接将 ViewGroup.LayoutParams
子类化,但是他们将 ViewGroup.MarginLayoutParams
子类化 (它本身是 ViewGroup.LayoutParams
的子类)。
LayoutParams
in xml
LayoutParams
对象是基于膨胀的布局 xml
文件创建的。
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="50dp"
android:layout_gravity="right"
android:gravity="bottom"
android:text="Example text"
android:textColor="@android:color/holo_green_dark"/>
<ImageView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="@android:color/holo_green_dark"
android:scaleType="centerInside"
android:src="@drawable/example"/>
</LinearLayout>
所有以 layout_
开头的参数都指定了封闭布局应该如何工作。当布局膨胀时,这些参数被包裹在一个合适的 LayoutParams
对象中,Layout
稍后将使用该对象将特定的 View
正确定位在 ViewGroup
内。View
的其他属性直接与 View
相关,并由 View
本身处理。
对于 TextView
:
layout_width
,layout_height
和layout_gravity
将存储在LinearLayout.LayoutParams
对象中并由LinearLayout
使用gravity
,text
和textColor
将由TextView
本身使用
对于 ImageView
:
layout_width
,layout_height
和layout_weight
将存储在LinearLayout.LayoutParams
对象中并由LinearLayout
使用ImageView
,scaleType
和src
将由ImageView
本身使用
获取 LayoutParams
对象
getLayoutParams
是一个 View's
方法,允许检索当前的 LayoutParams
对象。
因为 LayoutParams
对象与封闭的 ViewGroup
直接相关,所以只有当 View
附加到 ViewGroup
时,此方法才会返回非空值。你需要记住,此对象可能始终不存在。特别是你不应该依赖于 View's
构造函数。
public class ExampleView extends View {
public ExampleView(Context context) {
super(context);
setupView(context);
}
public ExampleView(Context context, AttributeSet attrs) {
super(context, attrs);
setupView(context);
}
public ExampleView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setupView(context);
}
private void setupView(Context context) {
if (getLayoutParams().height == 50){ // DO NOT DO THIS!
// This might produce NullPointerException
doSomething();
}
}
//...
}
如果你想依赖 LayoutParams
对象,你应该使用 onAttachedToWindow
方法代替。
public class ExampleView extends View {
public ExampleView(Context context) {
super(context);
}
public ExampleView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ExampleView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
if (getLayoutParams().height == 50) { // getLayoutParams() will NOT return null here
doSomething();
}
}
//...
}
转换 LayoutParams
对象
你可能需要使用特定于 ViewGroup
的功能(例如,你可能希望以编程方式更改 RelativeLayout
的规则)。为此,你需要知道如何正确地投射 ViewGroup.LayoutParams
对象。
当为一个孩子获得一个 LayoutParams
对象时,这可能有点令人困惑,这实际上是另一个 ViewGroup
。
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/outer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<FrameLayout
android:id="@+id/inner_layout"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_gravity="right"/>
</LinearLayout>
重要提示: LayoutParams
对象的类型与 ENCLOSING ViewGroup
的类型直接相关。
***** 转换错误* :
FrameLayout innerLayout = (FrameLayout)findViewById(R.id.inner_layout);
FrameLayout.LayoutParams par = (FrameLayout.LayoutParams) innerLayout.getLayoutParams();
// INCORRECT! This will produce ClassCastException
正确转换 :
FrameLayout innerLayout = (FrameLayout)findViewById(R.id.inner_layout);
LinearLayout.LayoutParams par = (LinearLayout.LayoutParams) innerLayout.getLayoutParams();
// CORRECT! the enclosing layout is a LinearLayout