以前因爲年少無知,以爲自定義ViewGroup時一定要自己安排其中子View的佈局,幻想着要是能直接繼承某個佈局從而不用自己再安排子View的佈局該有多好,今天無意間看了一段源碼之後,才知道這原來不是夢!!!#-#
自定義的Card
public class Card extends LinearLayout {
private TextView mFirstName;
private TextView mLastName;
private TextView mAge;
public Card(Context context) {
this(context, null);
}
public Card(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public Card(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
inflate(context, R.layout.card, this);
setOrientation(VERTICAL);
//因爲Data binding 不支持直接包含 merge 節點,所以這裏只能通過findViewById
mFirstName = (TextView) findViewById(R.id.firstname);
mLastName = (TextView) findViewById(R.id.lastname);
mAge = (TextView) findViewById(R.id.age);
}
// 自動 Setter
public void setObject(User user) {
mFirstName.setText(user.getFirstName());
mLastName.setText(user.getLastName());
mAge.setText(String.valueOf(user.getAge()));
}
}
對應的card佈局:
<merge
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/firstname"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/lastname"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/age"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</merge>
當然這裏還涉及到了Data Binding使得內容,順便提一下(Data Binding 在對應名稱的屬性不存在的時候也能繼續工作。你可以輕而易舉地使用 Data Binding 爲任何 setter “創建” 屬性。):
<路徑名.Card
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:object="@{user}"/>
上述自定義佈局 Card,並沒有添加 declare-styleable,但是可以使用自動 setter 的特性來調用這些函數。