Android Menu菜单

来源:互联网 发布:ug星空自动编程教程 编辑:程序博客网 时间:2024/05/22 12:06
public class MainActivity extends AppCompatActivity {    private static final String TAG = "jojo";    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        //不带菜单的TestActivity 和 MainActivity作比较        Intent intent = new Intent(this, TestActivity.class);        startActivity(intent);    }    @Override    public boolean onCreateOptionsMenu(Menu menu) {        //1 添加菜单的第一种方式  需要在res下创建menu文件夹包含main.xml,main.xml格式<menu><item></item><menu>//        getMenuInflater().inflate(R.menu.main, menu);        //2 通过代码的方式添加        menu.add(0, 1, 0, "前进");        menu.add(0, 2, 0, "后退");        menu.add(0, 3, 0, "首页");        return true;    }    // 当我们想知道具体点击的是哪个菜单条目,重写下面这个方法(固定流程)    @Override    public boolean onOptionsItemSelected(MenuItem item) {        // 具体点击的是哪个菜单条目        switch (item.getItemId()) {            case 1:                Log.d(TAG, "onOptionsItemSelected: 前进");                break;            case 2:                Log.d(TAG, "onOptionsItemSelected: 后退");                break;            case 3:                Log.d(TAG, "onOptionsItemSelected: 首页");                break;        }        return super.onOptionsItemSelected(item);    }    // 当菜单打开之前调用这个方法    @Override    public boolean onMenuOpened(int featureId,Menu menu) {        Log.d(TAG, "onMenuOpened: ");        //弹出一个对话框        AlertDialog.Builder builder = new AlertDialog.Builder(this);        builder.setTitle("警告");        builder.setPositiveButton("确定", new OnClickListener() {            @Override            public void onClick(DialogInterface dialog, int which) {            }        });        builder.setNegativeButton("取消", new OnClickListener() {            @Override            public void onClick(DialogInterface dialog, int which) {            }        });        // 最后一步 记得show出来,和Toast一样        builder.show();        return super.onPrepareOptionsMenu(menu);    }}

待解决:public boolean onMenuOpened(int featureId,Menu menu);

会在点击菜单时被调用两次。

-------------------------------------------------------------------------------------------------------------------------------------------------------------

快捷键:设置了快捷键后,在选项菜单已经弹出的情况下,可以通过按快捷键的方式直接选择需要的菜单项。下面的3个方法都可以设定快捷键:
  1)设置数字快捷键:setNumericShortcut(char numericChar)
  2)设置数字和字符快捷键:setShortcut(char numericChar,char alphaChar);
  3)设置字符快捷键:setAlphabeticShortcut(char alphachar)
短标题:当标题太长有可能显示不全时,可以用短标题代替,用MenuItem调用setTitleCondensed(CharSequence title)就可设置

在第一次初始化了选项菜单之后,我们我们需要动态更改选项菜单的话,则需要重新实现onPrepareOptionMenu()回调方法,他会在每次显示选项菜单之前调用。你可以在此回调方法里根据程序运行的情况即时地更新菜单项的内容,如标题、是否可用等。

 

 

//=======================================

1,菜单的基本用法:

1.1 OptionsMenu 选项菜单(按Menu键弹出的菜单)
Activity的onCreateOptionsMenu事件方法创建选项菜单
通过menu.add添加选项菜单项,返回一个MenuItem。
public MenuItem add(int groupId,int itemId,int order,CharSequence title);
如果groupId、itemId、order省略,默认都是0,显示顺序按添加顺序显示。

1.2 带图像的选项菜单
通过add方法返回的MenuItem的方法setIcon()设置图片

1.3 管理Activity
MenuItem的setItent()方法
注意:如果设置了菜单项的单击事件,并且单击事件返回true,则setIntent方法失效。

1.4 响应菜单的单击动作
通过调用MenuItem的setOnMenuItemClickListener方法可以设置菜单项的单击事件。
还可以使用Activity类的onOptionsItemSelected和onMenuItemSelected方法来响应菜单项的单击事件。这两个方法都有一个MenuItem参数,可以使用其getTitle和getItemId方法来判断单击的是哪个菜单项。
既 然有3种方法响应菜单项单击事件的方法,就会产生一个问题?如果同时使用这3种方法,他们都会起作用吗?如果都起作用那调用顺序又是如何呢?实际上,当 onMenuItemClick方法返回true时,另两种单击事件的响应方式都会失效;如果没有设置onMenuItemClickListener, 系统会根据在onMenuItemSelected方法中调用父类的onMenuItemSelected方法的位置来决定先调用 onOptionsItemSelected方法还是先调用onMenuItemSelected方法。

也就是说super.onMenuItemSelected(featureId,item);调用了onOptionsItemSelected方法

1.5 动态添加、修改和删除选项菜单
实现这个功能的关键是获得描述选项菜单的Menu对象。
Activity类中的很多方法都可以获得Menu对象。例如,onCreateOptionsMenu方法的menu参数,我们要做的就是在onCreateOptionMenu方法中将Menu对象保存在类变量中。

1.6 带复选框和选项按钮的子菜单
Menu.addSubMenu方法用来添加子菜单。该方法有4种重载形式:
SubMenu addSubMenu(final int gourpId,final int itemId,int order,final CharSequence title);

SubMenu是Menu的子接口,添加SubMenu后,可以通过SubMenu.add方法添加其子菜单项。在子菜单项上不能显示图像,但可以在子菜单的头部显示图像,不过子菜单项可以带复选框和选项按钮。

例如:
SubMenu fileSubMenu=menu.addSubMenu(1,1,2,"文件"); //添加SubMenu
fileSubMenu.setIcon(R.drawable.file); //设置在选项菜单中显示的图像
fileSubMenu.setHeaderIcon(R.drawable.headerfile); //设置子菜单头的图像
MenuItem newMenuItem=fileSubMenu.add(1,2,2,"新建");
newMenuItem.setCheckable(true); //将第一个子菜单项设置成复选框类型
newMenuItem.setChecked(true); //选中第一个子菜单项中的复选框
MenuItem openMenuItem=fileSubMenu.add(2,3,3,"打开");
MenuItem exitMenuItem=fileSubMenu.add(2,4,4,"退出");
exitMenuItem.setChecked(true); //将第3个子菜单项的选项按钮设置为选中状态
fileSubMenu.setGroupCheckable(2,true,true);//将后两个子菜单项设置成选项按钮类型

在编写上面代码时应注意以下几点:
1)添加子菜单并不是直接在MenuItem下添加菜单项,而需要使用addSubMenu方法创建一个SubMenu对象。
2) 将子菜单项设置成复选框类型,需要使用MenuItem.setCheckable方法。但设置成选项按钮类型,不需要使用setCheckable方 法,而要将同一组的选项按钮的groupI的设置成相同的值,同时使用setGroupCheckable方法来设置这个groupId。该方法的第1个 参数是指定子菜单项的groupId,第2个参数必须为true。如果第3个参数为true,相同groupId的子菜单项会被设置成选项按钮效果;如果 为false,相同groupId的子菜单项会被设置成复选框效果。根据相同groupId设置的选项按钮和复选框除了显示效果,并没有什么其他的不同。 其代表的含义完全由开发人员决定。
3)使用setChecked方法可以将复选框或选项按钮设置成选中状态。
4)选项菜单不支持嵌套子菜单。否则将抛出异常。

1.7 上下文菜单
上下文菜单有些和子菜单类似,也分为菜单头和菜单项。
通过onCreateContextMenu方法创建上下文菜单。
可以使用ContextMenu.setHeaderTitle和ContextMenu.setHeaderIcon方法设置上下文菜单头的标题和图像。上下文菜单项也是不能显示图像,但可以带复选框和选项按钮。也不支持嵌套。

上下文菜单必须注册到指定的View上才能显示。注册上下文菜单可以使用Activity.registerForContextMenu方法。
例如:registerForContextMenu(button);

上下文菜单项的单击事件也可以使用单击事件类和onMenuItemSelected方法来响应,还有覆盖
Activity.onContextItemSelected方法

1.8 菜单事件
Activity类还有一些与菜单相关的事件方法,这些方法的定义如下:
public boolean onPrepareOptionsMenu(Menu menu);
public void onOptionsMenuClosed(Menu menu);
public void onContextMenuClosed(Menu menu);
public boolean onMenuOpened(int featureId,Menu menu);

这些方法的含义如下:
1)onPrepareOptionsMenu:在显示选项菜单之前调用。一般用来修改即将显示的选项菜单。
2)onOptionsMenuClosed:在关闭选项菜单时被调用。
3)onContextMenuClosed:在关闭上下文菜单时被调用。
4)onMenuOpened:在显示选项菜单之前被调用。该方法在onPrepareOptionsMenu方法之后调用。

6.1.9 从菜单资源中装载菜单
在res\menu目录中的文件才菜单资源文件。
<menu xmlns:android="...">
 <item ...
 <item ..
</menu>

使用 getMenuInflater().inflate(R.menu.file_menu,menu); 加载


2 菜单特效

2.1 自定义菜单
系统提供的菜单看起来有些“土”,通过onKeyDown和PopupWindow实现自定义的菜单。
首先写一个布局文件准备给PopupWindow使用。
然后监听“menu”键和“back”键按下动作。
1)按下back键时,如果选项菜单已经弹出,则关闭选项菜单。
2)如果选项菜单未弹出,则执行super.onKeyDown

@Override
public boolean onKeyDown(int keyCode,KeyEvent event)
{
 switch (keyCode)
 {
  case KeyEvent.KEYCODE_MENU: //如果按下“menu”键
    if (state==1) //自定义的state表示状态,1表示选项菜单已弹出
     return false;
   //装载选项菜单布局文件
   layout=getLayoutInflater().inflate(R.layout.menu_layout,null);
   pop=new PopupWindow(layout,getWindowManager().getDefaultDisplay().getWidth(),getWindowManager().getDefaultDisplay().getHeight());
   //设置弹出窗口的位置
   pop.showAcLocation(layout,Gravity.BOTTOM,0,0);
   View home=layout.findViewById(R.id.home);
   home.seonClickListener(...);
   ...
   pop.dismiss();
   ...
   state=2;
   return false;
 case KeyEvent.KEYCODE_BACK:
   if (state==1) ...
   else ...



2.2 模拟UCWeb效果菜单
通过onCreateOptionsMenu和onMenuOpened两个方法相互配合来弹出自定义菜单。
在显示选项菜单之前,系统会调用onMenuOpened方法,如果该方法返回false,则不再显示选项菜单。因此,可以在onMenuOpened方法中弹出用于显示自定义菜单的窗口。

@Override
public boolean onCreateOptionsMenu(Menu menu)
{
  //必须构建一项,否则系统不会调用onMenuOpened方法
 menu.add("menu");
 return super.onCreateOptionsMenu(menu);
}

@Override
public boolean onMenuOpened(int featureId,Menu menu)
{
 if (popup!=null) {
  if (popup.isShowing())
  {
   popup.dismiss();
  }
  else 
  {
    View layout=getLayoutInflater().inflate(R.layout.main,null);
   //popup.showAtLocation(layout,Gravity.CENTER,0,0);
  }
 return false;
}



2.3 QuickContactBadge与联系人菜单
我们在使用Android内置的联系人功能时发现,在单击某个联系人之后,会弹出一个可以选择的图像菜单,其中包括拨打电话、发短信等功能。
这 个功能实际上是由QuickContactBadge控件完成的。QuickContactBadge是ImageView的子类,因 此,QuickContactBadge完全可以作为一个ImageView来使用。但QuickContactBadge还可以查询系统的联系人列表, 并根据联系人的相关信息显示如图6.12所示的快捷菜单。现在我们先在布局文件中放两个QuickContactBadge控件。

<?xml version...>
<LinearLayout ...>
 <QuickContactBadge ... android:src="http://supershll.blog.163.com/blog/@drawable/ic_contact_picture" style="?android:attr/quickContactbadgeStyleWindowSmall" />
 <QuickContactBadge ... style="?android:attr/quickContactbadgeStyleWindowLarge" />
</LinearLayout>

style属性指定了显示图像菜单的风格。如果quickContactBadgeStyleWindowLarge风格可以显示联系人的姓名,quickContactBadgeStyleWindowSmall风格只显示图像菜单。

部分示例代码:

String select="(("+Contacts.DISPLAY_NAME+" NOTNULL) AND ("+Contacts.HAS_PHONE_NUMBER+"=1) AND ("+Contacts.DISPLAY_NAME+" !='' ))";

//查询所有的联系人
Cursor cursor=getContentResolver().query(Contacts.CONTENT_URI,CONTACTS_SUMMARY_PROJECTION,select,null,Contacts.DISPLAY_NAME+" COLLATE LOCALIZED ASC");

//将记录指针移动到第一条记录
cursor.moveToFirst();

//创建第一个QuickContactBadge对象
QuickContactBadge badge1=findViewById(R.id.badge1);
... badge2=...;

//获得联系人的ID
long contactId=cursor.getLong(cursor.getColumnIndex(Contacts._ID));
//获得联系人的Lookup_key
String lookupKey=cursor.getString(cursor.getColumnIndex(Contacts.LOOKUP_KEY));
//将联系人与QuickContactBadge关联
badge1.assignContactUri(Contacts.getLookupUri(contactId,lookupKey));
cursor.moveToNext();
contactId=....;
lookupKey=...
badge2.assignContactUri(...);

注意:QuickContactBadge控件并不会自动显示联系人的图像,要想显示图像,需要像ImageView一样设置src属性、

扩展学习:除了使用QuickContactBadge.assignContactUri方法关联联系人外,还可以使用
QuickContactBadge.assignContactFromEmail(String emailAddress,boolean lazyLookup)关联Email
QuickContactBadge.assignContactFromPhone(String phoneNumber,boolean lazyLookup) 关联电话号码

如 果lazyLookup为true,并不会立即通过Email或Phone查找联系人,直接QuickContactBadge控件被单击。如果有多个联 系人使用了同一个电话或Email,则只显示第一个查到的联系人信息。使用这两个方法与联系人关联,单击QuickContactBadge控件并不会显 示图像菜单,而会直接跳到联系人界面。



2 0
原创粉丝点击