重寫setContentView實現多個Activity部分UI布局相同

3u0h1g3r 8年前發布 | 10K 次閱讀 Android開發 移動開發

 安卓應用中不同的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()方法:

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);
} 

}</pre>

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

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

作為新的內容區域。

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

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

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

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

@Override
public void setContentView(int layoutResID) {

LayoutInflater.from(this).inflate(layoutResID, contentLayout, true);

}</pre>

 

 本文由用戶 3u0h1g3r 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!