求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Modeler   Code  
会员   
 
  
 
 
     
   
分享到
Android开发技巧:我的菜单我做主
 

作者:nokiaguy ,发布于2012-9-17,来源:博客

 

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,表示不发生偏移。因此,弹出窗口会在屏幕的最底部显示,也就是显示选项菜单的位置。

相关文章

深度解析:清理烂代码
如何编写出拥抱变化的代码
重构-使代码更简洁优美
团队项目开发"编码规范"系列文章
相关文档

重构-改善既有代码的设计
软件重构v2
代码整洁之道
高质量编程规范
相关课程

基于HTML5客户端、Web端的应用开发
HTML 5+CSS 开发
嵌入式C高质量编程
C++高级编程

 
分享到
 
 
     


android人机界面指南
Android手机开发(一)
Android手机开发(二)
Android手机开发(三)
Android手机开发(四)
iPhone消息推送机制实现探讨
手机软件测试用例设计实践
手机客户端UI测试分析
手机软件自动化测试研究报告
更多...   


Android高级移动应用程序
Android应用开发
Android系统开发
手机软件测试
嵌入式软件测试
Android软、硬、云整合


领先IT公司 android开发平台最佳实践
北京 Android开发技术进阶
某新能源领域企业 Android开发技术
某航天公司 Android、IOS应用软件开发
阿尔卡特 Linux内核驱动
艾默生 嵌入式软件架构设计
西门子 嵌入式架构设计
更多...