通過定義BaseActivity來實現項目中代碼重用,重寫setContentView實現多個Activity部分UI佈局相同

安卓應用中不同的activity一般都具有相同的地方,最典型的是標題欄(titlebar),我們只需在每個activity中調用setTitle就可以得到一個除了標題文字不同,其他完全相同的標題欄。

系統已經爲我們引進了titlebar這樣的功能,但是如果我們還需要一個類似titlebar這樣容易copy外形的bottombar呢?

當然是否需要一個bottombar是個問題,我要說的其實是如果我們想讓activity共享一部分UI的情況下該怎麼做。

很直觀的我們會寫一個activity的子類,然後將公共部分的UI在這個子類activity中實現,命名爲BaseActivity,最後所有要共享此部分UI的activity都繼承這個BaseActivity。

思路是這樣,但是究竟該如何寫這個BaseActivity呢,注意上面藍色那句話,公共部分的UI如果是通過setContentView來渲染的話那該如果處理BaseActivity子類中其獨有的UI呢,合理的情況是在BaseActivity子類中調用setContentView來顯示自己獨有的界面,但是兩次調用setContentView總有一次是會被覆蓋的。

現在的情況是,我們想得到公共的UI,但沒辦法把公共部分和獨有部分的UI分開來處理。解決問題的辦法是瞭解activity的佈局到底是如何組成的,setContentView做了些什麼。

一、DecorView爲整個Window界面的最頂層View。

二、DecorView只有一個子元素爲LinearLayout。代表整個Window界面,包含通知欄,標題欄,內容顯示欄三塊區域。

三、LinearLayout裏有兩個FrameLayout子元素。

(20)爲標題欄顯示界面。只有一個TextView顯示應用的名稱。也可以自定義標題欄,載入後的自定義標題欄View將加入FrameLayout中。

(21)爲內容欄顯示界面。就是setContentView()方法載入的佈局界面,加入其中。

所以要實現activity具有公共部分的UI,重寫setContentView()方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
import android.app.Activity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.view.ViewGroup.LayoutParams;
import android.widget.LinearLayout;
import android.widget.TextView;
public class BaseActivity extends Activity {
private TextView mTitleTx;
private View mBack;
private LinearLayout contentLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initContentView();
initTitleBar();
}
public void initTitleBar(){
mTitleTx = (TextView)findViewById(R.id.titlebar_title);
mBack = findViewById(R.id.titlebar_left);
mBack.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View view){
finish();
}
});
}
private void initContentView() {
ViewGroup content = (ViewGroup) findViewById(android.R.id.content);
content.removeAllViews();
contentLayout=new LinearLayout(this);
contentLayout.setOrientation(LinearLayout.VERTICAL);
content.addView(contentLayout);
LayoutInflater.from(this).inflate(R.layout.common_title_bar, contentLayout, true);
}
@Override
public void setContentView(int layoutResID) {
//View customContentView = LayoutInflater.from(this).inflate(layoutResID,null);
/*this is the same result with
View customContentView = LayoutInflater.from(this).inflate(layoutResID,contentLayout, false);
*/
//contentLayout.addView(customContentView,LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
LayoutInflater.from(this).inflate(layoutResID, contentLayout, true);
}
@Override
public void setContentView(View customContentView) {
contentLayout.addView(customContentView);
}
@Override
public void setTitle(CharSequence title) {
mTitleTx.setText(title);
}
}

(ViewGroup) findViewById(android.R.id.content)可以獲得掛在一個activity內容部分LinearLayout。在這個LinearLayout中添加一個LinearLayout

1
contentLayout=new LinearLayout(this);
1
2
contentLayout.setOrientation(LinearLayout.VERTICAL);
content.addView(contentLayout);

作爲新的內容區域。

接下來將公共部分的UI添加進新的內容區域。

1
LayoutInflater.from(this).inflate(R.layout.common_title_bar, contentLayout, true);

我這裏是自定義了一個標題欄作爲公共部分,其實如果是標題欄可以不如此麻煩直接用原生的titlebar就行了。

然後重寫setContentView,將子類的內容區域從原本該直接掛在到android.R.id.content上面改爲掛在到這個新的內容區域。代碼如下:

1
2
3
4
5
6
@Override
public void setContentView(int layoutResID) {
LayoutInflater.from(this).inflate(layoutResID, contentLayout, true);
發佈了51 篇原創文章 · 獲贊 2 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章