Android – 底部菜單架構設計及封裝實現

來源:互聯網
上載者:User

引言

在Android的應用中,經常會見到底部菜單,例如的底部菜單如下所示:

 

而在企業級的Android應用中,也存在同樣的需求,但與這些福士軟體的區別在於企業級的Android應用由於UI頁面很多,每個頁面都需要有底部菜單,而且每個頁面的底部功能表按鈕還可能完全不一樣,所以,為了使每個頁面保持一致性並為UI頁面製作時提供便利,針對底部菜單進行專門的設計封裝,就顯得特別重要。

 

設計選型

在設計底部菜單時,有下面兩種思路:

一、單獨定製底部菜單塊,並將菜單塊代碼引入到每一個需要使用到底部菜單的layout.xml檔案中,然後再在代碼中定義需要使用的按鈕。

 

此方法符合正常思維邏輯,缺點在於每個頁面都要重複去引入,其實這個是可以省掉的。

 

二、Android中,可以將某塊自訂的UI從layout.xml中執行個體化出來使用,使用的是LayoutInflater,基於該技術,我們可以換一種思路來解決這個問題:寫頁面layout檔案的時候不用關心底部菜單。然後在展示的代碼中,定義一個大的視圖頁面將頁面的layout檔案以及底部菜單的layout包含進來,過程如所示:

 

詳細設計

1.      設計大的視圖頁面layout:bottom_menu_layout.xml,該頁面用來包含以後自訂的業務頁面,以及底部菜單。

 

 <?xml version="1.0"encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

    android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical">

   

    <LinearLayout  android:orientation="horizontal"android:layout_width="fill_parent"  android:gravity="bottom"

       android:layout_height="wrap_content" android:id="@+id/bottom_menu_button_group_id">

    </LinearLayout>  

</LinearLayout>

 

 

2.      設計底部功能表按鈕layout:bottom_menu_button_frame.xml,該頁面用來定義每一個按鈕的樣式,一般需要包含一個位於上方的圖片以及一個位於下方的按鈕文字。

 

 

<?xml version="1.0"encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

    android:orientation="vertical" android:layout_width="64px"

    android:layout_height="wrap_content" android:id="@+id/bottom_menu_template_button_id"

    android:background="@drawable/tab_one_normal">

    <ImageView android:id="@+id/bottom_menu_template_img_id"   android:paddingTop="5px"android:layout_gravity="center"

    android:layout_width="wrap_content" android:layout_height="wrap_content"android:src="@drawable/image" />

    <TextView android:layout_width="wrap_content"android:id="@+id/bottom_menu_template_text_id"

       android:layout_height="wrap_content" android:layout_gravity="center"

       android:gravity="center" android:textSize="11sp"android:paddingBottom="5px"  />

</LinearLayout>

 

 

 

3.      自訂封裝按鈕的JAVA類:BottomButton,封裝底部功能表按鈕的基本資料:圖片、文字、按鈕事件、是否當前被選中的按鈕等。

 

 

public class BottomButton

{

     // 按鈕菜單文字

    private String text;

   

     // 按鈕菜單圖片

    private int backgroundResource;

   

     // 點擊事件。

    private View.OnClickListener clickListener;

   

    // 是否當前已經選中的按鈕,如果是則高亮,並且忽略點擊事件。

    private boolean isCurrent = false;

 

 

4.      自訂底部菜單Layout 類:BottomMenuLayout,該類繼承自LinearLayout,用來處理按鈕的展示,該類負責以下三件事情:

a)  將底部菜單layout加入到整個大視圖頁面中。

b)  綁定每一個功能表按鈕。

c)  重新計算整個布局的大小,將菜單固定在底部。

 

 

 

public class BottomMenuLayout extends LinearLayout {

 

    //執行個體化layout使用的類   

    private LayoutInflater mInflater;    

 

    //儲存功能表按鈕的集合,每一個集合元素代表一個按鈕,包含了按鈕所需要的資訊:圖片,文字,按鍵處理事件。

    private List<BottomButton> bottomButtons;   

   

    //封裝功能表按鈕的布局。

    private View bottomMenuLayout;  

 

    public void processInitButton()

    {

       //初始化布局,將底部菜單layout加入到視圖中。

       initLayout(this.getContext());   

      

       //綁定每一個功能表按鈕

       bindingButton();                 

 

       //重新計算整個布局的大小,使用整個螢幕的高度減去底部菜單的高度,

       //得出並設定中間頁面部分的高度,就能夠將菜單固定在底部。

       resizeLayout();                  

    } 

註:這裡屏蔽了實現細節,具體參考附件代碼。

 

 

5.      當以上每一個零散的部分都完成以後,就需要一個組裝者,來負責將各個部分組裝在一起,使之能夠正常運作起來,這裡定義一個繼承自Activity的類:BaseBottomMenuActivity ,用來充當組裝者的角色,開發業務時需要更改方式,原來直接繼承自Activity的類改為繼承該類。該類主要完成以下工作:

a) 建立出整個大視圖頁面。

b) 建立出中間內容部分頁面,也就是由開發人員定義的實際layout內容。並加到整個大視圖的頁面中來。

c) 建立出底部菜單,並將底部菜單加入到整個大視圖的頁面中來。

d) 需要得知子類繼承該類後,具體使用的layout頁面的ID,定義抽象方法由子類實現以提供該ID。

e) 需要得知子類繼承該類後,具體需要哪些功能表按鈕,定義抽象方法由子類實現以提供按鈕的列表。

f) 需要得知子類繼承該類後,還需要做哪些頁面初始化的工作,定義抽象方法由子類實現以便在頁面初始過程中調用。

 

 

public abstract class BaseBottomMenuActivity extends Activity

{

    private LayoutInflater mInflater;   //執行個體化layout使用的類   

    protected BottomMenuLayout bottomMenuLayout;   //底部菜單UI部分

    protected View contentView;                   //頁面中間UI部分

   

    final protected void onCreate(Bundle savedInstanceState)

    {

       //a) 建立出整個大視圖頁面。

       //b) 建立出中間內容部分頁面,也就是由開發人員定義的實際layout內容。並加到整個大視圖的頁面中來。

        //c) 建立出底部菜單,並將底部菜單加入到整個大視圖的頁面中來。

    }

   

    /**

     * 子類實現後,在原來的onCreate方法中內容移到這裡來操作。

     * @paramsavedInstanceState

     */

    protected abstract void onCreatOverride(Bundle savedInstanceState);

   

    /**

     * 返回layout xml的ID

     * 原本在Activity的onCreate方法中調用的setContentView(R.layout.xxxxLayoutId); 現在從該方法返回。

     * @return

     */

    public abstract int getContentViewLayoutResId();

   

 

    /**

     * 建立底部菜單,需要子類實現,在此方法中,

     * 建立多個BottomButton對象並放置到List中返回即可。

     * 如果需要哪一個按鈕當前被選中,則設定BottomButton的isCurrent屬性為ture.

     * @param bottomButtons

     * @param bottomMenuLayout

     * @return

     */

    public abstractList<BottomButton> getButtonList(); 

註:這裡屏蔽了實現細節,具體參考附件代碼。

 

 

實現及使用

具體實現代碼見附件。

在上述設計的各部分都實現後,就可以進行使用了,使用時,與平常開發正常頁面的步驟一樣,首先畫layout.xml,然後定義activity,進行綁定並配置AndroidManifest.xml檔案,不同的地方在於定義的Activity需要繼承BaseBottomMenuActivity。並且根據以下步驟開發該Activity:

 

 1. 在子類中繼承實現getButtonList方法,在方法中封裝BottomButton對象返回,每一個BottomButton代表一個功能表項目,具體屬性見BottomButton定義。

2. 在子類中繼承實現getContentViewLayoutResId方法,返回layout xml的ID。

3. 在子類中繼承實現onCreatOverride方法,原先在onCreat方法中完成的事情挪到這裡,super.onCreate(savedInstanceState);和setContentView就不需要調用了。 

 

 

測試

讓我們來寫一個簡單的Demo來進行測試,該Demo中,除了底部菜單,只有一個TextView文本,該類繼承了BaseBottomMenuActivity:

 

 

public class Demo extends BaseBottomMenuActivity {

 

    public List<BottomButton> getButtonList() {

       Map<String,String> buttonMaps =  new HashMap<String,String>();

       buttonMaps.put("Menu1", String.valueOf(R.drawable.home));

     buttonMaps.put("Menu2", String.valueOf(R.drawable.home));

     buttonMaps.put("Menu3", String.valueOf(R.drawable.home));

     buttonMaps.put("Menu4", String.valueOf(R.drawable.home));

     buttonMaps.put("主菜單", String.valueOf(R.drawable.home));

 

 

     List<BottomButton>buttons = new ArrayList<BottomButton>();

        Iterator<String> itKey =buttonMaps.keySet().iterator();

        while(itKey.hasNext())

        {

         Stringkey = itKey.next();

         StringvalueRes = buttonMaps.get(key);

         BottomButtononeBottomButton = new BottomButton();

         oneBottomButton.setText(key);

         oneBottomButton.setBackgroundResource(Integer.parseInt(valueRes));

         buttons.add(oneBottomButton);

        }

        return buttons;

    }

 

    public int getContentViewLayoutResId() { return R.layout.main; }

 

    protected void onCreatOverride(Bundle savedInstanceState) { }

在返回按鈕的getButtonList方法中,返回了5個按鈕。

 

其布局檔案如下:

 

 <?xml version="1.0"encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

    android:orientation="vertical"

    android:layout_width="fill_parent"  android:layout_height="fill_parent"  >

<TextView    android:layout_width="fill_parent"

    android:layout_height="wrap_content"   android:text="@string/hello"  />

</LinearLayout> 

 

 

結果程式效果如所示:

源碼:http://download.csdn.net/detail/linghu_java/5023136

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.