通常而言,Android界面佈局使用聚合的方式比較多,這種方式要求首先構建一批可以複用的組件,而後在Activity的佈局文件中進行聚合。儘管這種方式可以完成組件的複用,但若是這些組件在不一樣Activity中的佈局有不少相同點的時候,也仍是會帶來很大程度的冗餘(代碼)。本文介紹一種比聚合更加有效的界面佈局方式——繼承式佈局。java
對於類的繼承和對象的聚合之間有哪些相同點和不一樣點,分別適用於哪一種場景,相信你們已經深有體會。在此就很少講了。其實類比過來,Android的界面佈局也是如此。假設咱們須要實現以下的三種佈局:android
每個佈局都是在前一個佈局的基礎上增長本身的元素。這種形式多麼像類的繼承呀!下面列出實現文件:網絡
page_three_parts.xmlapp
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/page_three_parts_root_layout"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="96dp"
android:layout_alignParentTop="true"
android:background="@color/main_blue" >
<ImageView
android:id="@+id/image_logo"
android:layout_width="120dp"
android:layout_height="80dp"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_margin="10dp"
android:gravity="center"
android:src="@drawable/logo" />
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="96dp"
android:layout_alignParentBottom="true"
android:background="@color/main_blue" >
</RelativeLayout>
</RelativeLayout>ide
page_base_setting.xml佈局
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<include
android:layout_width="match_parent"
android:layout_height="match_parent"
layout="@layout/page_three_parts" />
<Button
android:id="@+id/baseSettingButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_marginBottom="32dp"
android:text="page_base_setting.xml" />
</RelativeLayout>性能
page_net_settting.xmlui
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<include
android:layout_width="match_parent"
android:layout_height="match_parent"
layout="@layout/page_base_setting" />
<Button
android:id="@+id/netSettingButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_marginBottom="32dp"
android:text="page_net_settting.xml" />
</RelativeLayout>this
繼承式佈局在第一個節點處包含父佈局文件,而後實現子佈局。繼承式佈局要求父佈局和子佈局的根佈局大小必須一致。至於爲何這麼要求,很簡單,想想類繼承的特色——子類必須實現父類的全部內容,或者說子類必須可以代替父類。這樣的繼承方式與咱們在C++、C#、Java中實現的繼承很不同,而與GObject、Lua等實現繼承的方式很類似。spa
這種佈局方式可以比聚合實現更簡單的設計,並且可以更大程度的完成代碼和佈局的解耦合。這裏指的是有不少人會在聚合式佈局中留出擴展點,而後在程序運行的時候將內容填充到保留點。這種方式有一個很大的問題,就是隻有當程序運行起來以後才能看到頁面的完整信息。繼承式佈局就不存在這樣的問題。並且,這種繼承關係也徹底能夠映射到代碼類的繼承。下面是代碼中關於佈局的繼承關係:
ThreePartsActivity.java
package com.testui;
import android.app.Activity;
import android.os.Bundle;
import android.widget.ImageView;
/**
* 該類和 page_three_parts.xml 佈局文件對應
*/
public class ThreePartsActivity extends Activity {
/**
* 佈局文件
*/
protected int layoutRes;
/**
* LOGO圖片
*/
protected ImageView imageLogo;
protected ThreePartsActivity(int layoutRes) {
this.layoutRes = layoutRes;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 設置視圖內容
setContentView(layoutRes);
imageLogo = (ImageView) findViewById(R.id.image_logo);
}
}
BaseSettingActivity.java
package com.testui;
import android.os.Bundle;
import android.widget.Button;
/**
* 該類和 page_base_setting.xml 佈局文件對應
*/
public class BaseSettingActivity extends ThreePartsActivity {
/**
* 基本配置按鈕
*/
Button baseSettingButton;
protected BaseSettingActivity(int layoutRes) {
super(layoutRes);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
baseSettingButton = (Button) findViewById(R.id.baseSettingButton);
}
}
NetSettingActivity.java
package com.testui;
import android.os.Bundle;
import android.widget.Button;
/**
* 該類和 page_net_settting.xml 佈局文件對應
*/
public class NetSettingActivity extends BaseSettingActivity {
/**
* 網絡設置按鈕
*/
Button netSettingButton;
public NetSettingActivity() {
super(R.layout.page_net_settting);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
netSettingButton = (Button) findViewById(R.id.netSettingButton);
}
}
繼承式佈局其實是經過佈局的層層疊加實現的,但這種疊加是邏輯上的,而不是渲染層次的。因此在實際運行中不會帶來太大的性能問題。下面這張圖應該可以將繼承式佈局形象的展現出來: