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