Android開發技巧:我的菜單我做主

來源:互聯網
上載者:User

本文截選自《Android開發權威指南》

     Android SDK本身提供了一種預設建立菜單的機制。但通過這種機制建立的菜單雖然從功能上很完備,但在介面效果上實在是有點“土”。對於一個擁有絢麗介面的程式配上一個有點“土”的菜單,會使使用者感覺很怪,甚至會使絢麗的介面大打折扣。實際上,對於如此靈活和強大的Android系統,修改菜單的樣式只是小菜一碟。為程式加入漂亮菜單的方法很多。在本節先介紹一種比較常用的方法,就是通過onKeyDown事件方法和PopupWindow實現自訂的菜單。至於通過這種技術能否設計出絢麗的菜單效果,那就要看我們的設 計、美學、心理學功底了。

     通過6.1.1節介紹的選項菜單可以知道。通過按手機的“Menu”鍵(是手機上的硬按鍵,不同手機“Menu”鍵所在的位置會不同),可以彈出選項菜單,再按“Back”鍵,選項菜單會關閉。那麼要想類比選項菜單的彈出和關閉效果,只需要監聽這兩個鍵的按下事件即可。並且在“Menu”鍵按下時使用PopupWindow彈出一個視窗作為類比的選項菜單。下面先來看看6.9所示的類比選項菜單的效果。

從圖6.9可以看出,在介面的下方顯示了3個功能表項目:“首頁”、“我的”和“更多”。其中“我的”功能表項目的文字和映像是左右水平排列,而另兩個功能表項目上的文字和映像是上下垂直排列。實際上,這種效果由一個普通的布局檔案(menu_layout.xml)完成的,代碼如下:

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

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

   android:orientation="horizontal"android:layout_width="fill_parent"

   android:layout_height="wrap_content"android:gravity="bottom">

   <!--  第一個功能表項目:“首頁”  -->

   <LinearLayout android:id="@+id/home"android:orientation="vertical"

        android:layout_width="fill_parent"android:layout_height="wrap_content"

       android:background="@drawable/button_normal_translucent"

       android:layout_weight="1">

       <ImageView android:layout_width="fill_parent"

           android:layout_height="wrap_content"android:src="@drawable/home"

           android:paddingTop="5dp" />

       <TextView android:layout_width="fill_parent"

            android:layout_height="wrap_content"android:text="首頁"

           android:gravity="center" />

   </LinearLayout>

   <!--  第二個功能表項目:“我的”  -->

   <LinearLayout android:orientation="horizontal"

       android:layout_width="fill_parent" android:layout_height="wrap_content"

       android:background="@drawable/button_normal"android:layout_weight="1"

       android:gravity="center">

       <ImageView android:layout_width="wrap_content"

           android:layout_height="wrap_content" android:src="@drawable/mine"/>

       <TextView android:layout_width="wrap_content"

           android:layout_height="wrap_content" android:text="我的" />

   </LinearLayout>

   <!--  第三個功能表項目

   <LinearLayout android:orientation="vertical"

       android:layout_width="fill_parent"

       android:layout_height="wrap_content" android:background="@drawable/button_normal"

       android:layout_weight="1">

       <ImageView android:layout_width="fill_parent"

           android:layout_height="wrap_content"android:src="@drawable/more"

           android:paddingTop="18dp" />

       <TextView android:layout_width="fill_parent"

           android:layout_height="wrap_content" android:text="更多"

           android:gravity="center"android:paddingTop="5dp"/>

   </LinearLayout>

</LinearLayout>

在編寫上面代碼之前,別忘了準備幾個相關的映像,例如,本例使用了5個映像。其中button_normal_translucent.png用於“首頁”功能表項目的背景(半透明效果),button_normal.png用於“我的”和[其他] 功能表項的背景。home.png、mine.png和more.png分別用於這三個功能表項目的映像。

下面來編寫監聽“menu”和“back”鍵按下動作的代碼。按下“back”鍵要處理的任務有如下兩個。

  • 如果選項菜單已經彈出,關閉選項菜單。
  • 如果選項菜單未彈出,或已經被關閉,直接關閉當前的Activity,也就是調用finish方法。

為了區分上面兩個任務,在程式中設定了一個int類型狀態變數(state),當state為1時表示選項菜單已彈出,state為2時表示選項菜單未彈出。下面我們看一下完整的實現代碼。

package mobile.android.ch06.custom.menu;

 

import android.app.Activity;

import android.os.Bundle;

import android.view.Gravity;

import android.view.KeyEvent;

import android.view.View;

import android.view.View.OnClickListener;

import android.widget.PopupWindow;

import android.widget.Toast;

 

public class Main extends Activity

{

    privatePopupWindow pop;

    privateView layout;

    private int state = 2;                          //狀態變數,1:選項菜單已彈出,2:選項菜單未彈出

 

    @Override

    publicvoid onCreate(Bundle savedInstanceState)

    {

       super.onCreate(savedInstanceState);

       setContentView(R.layout.main);

    }

    @Override

    publicboolean onKeyDown(int keyCode, KeyEvent event)

    {

       switch (keyCode)

        {

           case KeyEvent.KEYCODE_MENU:    //  按下“menu”鍵的動作

               //  選項菜單已彈出,不再彈出新的視窗

               if (state == 1)

                   return false;

               //  裝載選項菜單布局檔案

                layout =getLayoutInflater().inflate(R.layout.menu_layout, null);

               //  建立PopupWindow對象,並在指定位置彈出用於顯示菜單的視窗

                pop = new PopupWindow(layout,getWindowManager()

                       .getDefaultDisplay().getWidth(), getWindowManager()

                       .getDefaultDisplay().getHeight());

                //  設定快顯視窗的位置

                pop.showAtLocation(layout,Gravity.BOTTOM, 0, 0);

               View home = layout.findViewById(R.id.home);

               //  為“首頁”功能表項目添加單擊事件

               home.setOnClickListener(new OnClickListener()

                {

                   @Override

                   public void onClick(View view)

                   {

                       Toast.makeText(Main.this, "單擊定製菜單.", Toast.LENGTH_LONG).show();

                        //  單擊“首頁”功能表項目後,關閉選項菜單

                        pop.dismiss();

                        //  重新設定狀態變數

                        state = 2;

                   }

               });

               //  彈出選項菜單後,將狀態變數設為1,表示選項菜單已彈出

                state = 1;

               return false;

            case KeyEvent.KEYCODE_BACK:                   //  按下“back”鍵的動作

               if (state == 1)

               {

                   //  如果選項菜單已彈出,關閉它

                    pop.dismiss();

                   //  將狀態變數設為選項菜單已關閉

                    state = 2;

                }

               else if (state == 2)

               {

                   //  如果選項菜單還沒有顯示,或已經關閉,則直接關閉當前的Activity

                    finish();

               }

               return false;

        }

      //  除“menu”和“back”按下事件外,仍需調用Activity類的onKeyDown方法來響應其他鍵的按下事件

       return super.onKeyDown(keyCode, event);

    }

}

在編寫上面代碼時應注意如下幾點。

  • 對於選項菜單來說,一般單擊某個功能表項目後,會執行一些動作,並且選項菜單會自動關閉。為了類比這一過程。為“首頁”功能表項目添加了一個單擊事件。當單擊“首頁”功能表項目時,會彈出一個Toast提示資訊,並且選項菜單會關閉。
  •  當執行完按下“menu”或“back”鍵的動作後,onKeyDown方法應返回一個常量(false或true都可以),不能再調用super.onKeyDown方法,否則在執行完定製的功能表項目動作後,又會執行系統的預設動作。例如,當按下“back”鍵後,關閉快顯功能表後,連當前的Activity也一起關了。當然,如果是除了“menu”和“back”的其他鍵按下時還是需要調用Activity類的onKeyDown方法的(也就是super.onKeyDown方法),這樣在程式中還可以響應其他的按鍵事件,否則程式除了“menu”和“back”鍵外,其他的鍵幾乎都不好使了。
  • showAtLocation方法用於控制項快顯視窗的位置。該方法的第1個參數是一個View對象。實際上,showAtLocation方法內部只是需要調用View.getWindowToken方法來獲得一個IBinder對象。showAtLocation方法的第2個參數表示快顯視窗的位置。本例中設定了快顯視窗在螢幕底部顯示。最後兩個參數分別表示水平和垂直位移量。本例都設為0,表示不發生位移。因此,快顯視窗會在螢幕的最底部顯示,也就是顯示選項菜單的位置。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.