第五章 用戶界面基礎(chǔ)(菜單)

參考資料:
《Android應(yīng)用程序開發(fā)》ISBN 9787302283164
參考軟件:
Android Studio、Eclipse+ADT、Android SDK、JDK
菜單
?應(yīng)用程序中非常重要的組成部分
在不占用界面空間的前提下,為應(yīng)用程序提供了統(tǒng)一的功能和設(shè)置界面
為程序開發(fā)人員提供了易于使用的編程接口
Android系統(tǒng)支持三種菜單
選項(xiàng)菜單(OptionMenu)
?子菜單(Submenu)
快捷菜單(ContextMenu)
1、Android Studio下創(chuàng)建menu布局文件
http://www.cnblogs.com/ssqqhh/p/5213331.html
一、問題:
android studio項(xiàng)目中沒有看到menu文件夾:

在android studio項(xiàng)目中想要添加menu布局文件,一開始我的做法是:直接在res文件夾右鍵選擇xml文件來添加,如下圖:

但是會發(fā)現(xiàn)新建的布局文件好像很奇怪,不能添加menu以及item,如下圖:

?
二、解決辦法:
經(jīng)過百度才知道m(xù)enu布局文件要在menu文件夾地下創(chuàng)建才行,正確的做法如下:
(1)先在res文件夾右鍵,然后如下圖選擇:

然后會出現(xiàn)下面的頁面,在Resource type下拉欄選擇menu,如下圖:

最后點(diǎn)擊OK就行了,這時候可以看到menu文件夾已經(jīng)出來了;
?
(2)接著在menu文件夾下右鍵,選擇如下:

輸入文件名點(diǎn)擊OK即可:

這樣就可以了:

2、選項(xiàng)菜單
http://blog.csdn.net/jdsjlzx/article/details/36433441
http://blog.csdn.net/wwj_748/article/details/44588649
http://www.sjsjw.com/kf_mobile/article/039009ABA009108.asp
(1)強(qiáng)制ActionBar顯示OverFlow按鈕(三個點(diǎn))
關(guān)于ActionBar最右這三個點(diǎn)按鈕:?

正式的名稱應(yīng)該是overflow menu,在android4.2.2以上的設(shè)備是默認(rèn)出現(xiàn)的,但是android4.1.2的設(shè)備不顯示,似乎android也沒有提供顯示的API,所以網(wǎng)上搜索到這個強(qiáng)制顯示的方案(親測可用)。
關(guān)鍵代碼如下:?
private void getOverflowMenu() {
???????????????? ViewConfiguration viewConfig =ViewConfiguration.get(this);
???????????????? try {
????????????????????????? FieldoverflowMenuField =ViewConfiguration.class.getDeclaredField("sHasPermanentMenuKey");
????????????????????????? if(null !=overflowMenuField){
?????????????????????????????????? overflowMenuField.setAccessible(true);
?????????????????????????????????? overflowMenuField.setBoolean(viewConfig,false);
????????????????????????? }
???????????????? } catch (NoSuchFieldExceptione) {
????????????????????????? // TODO Auto-generatedcatch block
????????????????????????? e.printStackTrace();
???????????????? } catch(IllegalArgumentException e) {
????????????????????????? // TODO Auto-generatedcatch block
????????????????????????? e.printStackTrace();
???????????????? } catch (IllegalAccessExceptione) {
????????????????????????? // TODO Auto-generatedcatch block
????????????????????????? e.printStackTrace();
???????????????? }
???????? }
在onCreate()的方法中直接調(diào)用就可以:?
protected void onCreate(Bundle savedInstanceState) {
???????????????? // TODO Auto-generated methodstub
???????????????? super.onCreate(savedInstanceState);
???????????????? setContentView(R.layout.activity_home_page);
? ? ? ? ? ? ? ? ……
???????????????? //force to display overflowmenu in action bar
???????????????? getOverflowMenu();
???????? }
原作者有補(bǔ)充到即時應(yīng)用于android4.4以上的設(shè)備應(yīng)該也不會有問題:因?yàn)榧词沟玫降膐verflowMenuField為null,代碼也做了判空處理,所以沒什么影響。?
我實(shí)際在調(diào)用時加入版本兼容條件,如下:?
//forceto display overflow menu in action bar when sdk version less than 21
???????????????? if((Build.VERSION.SDK_INT >=10) & (Build.VERSION.SDK_INT < 21)) {
????????????????????????? getOverflowMenu();
???????????????? }
(2)代碼實(shí)現(xiàn)

在代碼中之間實(shí)現(xiàn)菜單

事件實(shí)現(xiàn)

@Override
??public?boolean?onCreateOptionsMenu(Menu menu) {
?????// ?getMenuInflater().inflate(R.menu.activity_main, menu);
?????//?使用java代碼實(shí)現(xiàn)菜單
???? MenuItem menuItem = menu.add(1001, 100, ?1,?"系統(tǒng)菜單");
?????// ?menuItem.setIcon(R.drawable.ic_launcher);
???? menuItem.setTitle("菜單一");
???? MenuItem menuItem2 = menu.add(1001, 101, ?2,?"用戶菜單");
???? menuItem2.setTitle("菜單二");//?最多可以顯示6個子菜單
???? MenuItem menuItem3 = menu.add(1001, 102, ?2,?"客戶菜單");
???? menuItem3.setTitle("菜單三");//?最多可以顯示6個子菜單
???? menuItem3.setShortcut('c',?'c');//?給指定的菜單設(shè)置快捷鍵
?????return?true;
? }
??@Override
??public?boolean?onOptionsItemSelected(MenuItem item) {
?????//?TODO?Auto-generated ?method stub
?????switch?(item.getItemId()) {
?????case?100:
?????? Intent intent =?new?Intent(MainActivity.this, NextActivity.class);
?????? item.setIntent(intent);
???????// item.setIntent(intent);
???????// Toast.makeText(MainActivity.this, "選擇了菜單一", 1).show();
???????break;
?????case?101:
?????? Toast.makeText(MainActivity.this,?"選擇了菜單二", 1).show();
???????break;
?????case?102:
?????? Toast.makeText(MainActivity.this,?"選擇了菜單三", 1).show();
???????break;
???? }
?????return?super.onOptionsItemSelected(item);
? }
(3)資源文件實(shí)現(xiàn)


建立菜單的資源文件

<menu?xmlns:android="http://schemas.android.com/apk/res/android"??>
????<item
????????android:id="@+id/menu_settings"
????????android:icon="@drawable/sys"
????????android:orderInCategory="100"
????????android:showAsAction="ifRoom|withText"
????????android:title="@string/menu_settings">
????????<menu>
????????????<item
????????????????android:id="@+id/create_new"
????????????????android:title="新建文件">
????????????</item>
????????????<item
????????????????android:id="@+id/open"
????????????????android:title="打開文件"/>
????????</menu>
????</item>
????<item
????????android:id="@+id/sys"
????????android:icon="@drawable/sys"
????????android:orderInCategory="101"
????????android:showAsAction="never"
????????android:title="用戶菜單">
????????<menu>
????????????<group?android:id="@+id/group1"?>
????????????????<item
????????????????????android:id="@+id/load"
????????????????????android:title="加載文件">
????????????????</item>
????????????</group>
????????????<group?android:id="@+id/group2"?>
????????????????<item
?????????????????? ?android:id="@+id/save"
????????????????????android:title="保存文件">
????????????????</item>
????????????</group>?
????????</menu>
????</item>
</menu>
代碼中的實(shí)現(xiàn)

@Override
??public?boolean?onCreateOptionsMenu(Menu menu) {
? ? getMenuInflater().inflate(R.menu.activity_main, menu);
?????return?true;
? }

??@Override
??public?boolean?onMenuItemSelected(int?featureId, MenuItem item) {
?????//?TODO?Auto-generated ?method stub
?????switch?(item.getItemId()) {
?????case?R.id.create_new:
?????? Intent intent =?new?Intent(MainActivity.this, SystemMenu.class);
?????? item.setIntent(intent);
???????break;
?????case?R.id.open:
?????? Toast.makeText(MainActivity.this,?"打開菜單", 1).show();
???????break;
?????case?R.id.load:
?????? Toast.makeText(MainActivity.this,?"加載菜單", 1).show();
???????break;
?????case?R.id.save:
?????? Toast.makeText(MainActivity.this,?"保存菜單", 1).show();
???????break;
???? }
?????return?super.onMenuItemSelected(featureId, ?item);
? }
?
(4)?android:showAsAction

3、子菜單
子菜單就是二級菜單,點(diǎn)擊選項(xiàng)菜單或快捷菜單中的菜單項(xiàng),就可以打開子菜單
Android系統(tǒng)使用浮動窗體的形式顯示菜單子項(xiàng),可以更好適應(yīng)小屏幕的顯示方式

(1)資源文件實(shí)現(xiàn)

?

@Override
????public?boolean??onCreateOptionsMenu(Menu menu) {
??????? MenuInflater?inflater?= getMenuInflater();
????????inflater.inflate(R.menu.sub_menu, menu);
????????return?true;
??? }
<?xml?version="1.0"??encoding="utf-8"?>
<menu?xmlns:android="http://schemas.android.com/apk/res/android">
????<item?android:id="@+id/main_menu_0"
??????????android:icon="@drawable/pic0"
??????????android:title="設(shè)置"?>
?????????<menu>
???????<item?android:id="@+id/sub_menu_0_0"
????????? ???android:icon="@drawable/pic4"
????????? ???android:title="打印"?/>
?????????</menu>
?????</item>? ? ? ? ?
?? ??<item?android:id="@+id/main_menu_1"
??????????android:icon="@drawable/pic1"
??????????android:title="新建"?>
?????<menu>
???????<item?android:id="@+id/sub_menu_1_0"
??????? ???android:icon="@drawable/pic2"
????????? ????android:title="郵件"?/>? ??
??? ????<item?android:id="@+id/sub_menu_1_1"
????????? ???android:icon="@drawable/pic3"
????????? ???android:title="訂閱"?/>
????????</menu>
?????</item>? ??
</menu>
(2)代碼實(shí)現(xiàn)
package edu.hrbeu.SubMenu2;
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.SubMenu;
import android.widget.TextView;
public class SubMenu2Activity extends ?Activity {
???????? final ?static int MENU_00 = Menu.FIRST;
???????? final ?static int MENU_01 = Menu.FIRST+1;
???????? final ?static int SUB_MENU_00_01 = Menu.FIRST+2;
???????? final ?static int SUB_MENU_01_00 = Menu.FIRST+3;
???????? final ?static int SUB_MENU_01_01 = Menu.FIRST+4;
??? ?@Override
??? ?public void onCreate(Bundle savedInstanceState) {
?????? ??super.onCreate(savedInstanceState);
??????? ?setContentView(R.layout.main);
??? ?}
??? ?@Override
??? ?public boolean onCreateOptionsMenu(Menu menu) {
? ? ? ? ? ? ? ? SubMenu ?sub1 = (SubMenu) menu.addSubMenu(0,MENU_00,0,"設(shè)置")
???????????????????????????????????? .setHeaderIcon(R.drawable.pic3);
?????????????????? sub1.add(0,SUB_MENU_00_01 ?,0,"打印").setIcon(R.drawable.pic0);
?????????????????? SubMenu ?sub2 = (SubMenu) menu.addSubMenu(0,MENU_01,1,"新建")
???????????????????????????????????? .setHeaderIcon(R.drawable.pic1);
?????????????????? sub2.add(0,SUB_MENU_01_00 ?,0,"郵件").setIcon(R.drawable.pic2);
?????????????????? sub2.add(0,SUB_MENU_01_01 ?,0,"訂閱").setIcon(R.drawable.pic4);
??????? ?return true;
??? ?}
??? ?@Override
??? ?public boolean onOptionsItemSelected(MenuItem item) {
??????? ?TextView label = (TextView)findViewById(R.id.label);
??????? ?switch (item.getItemId()) {
?????? ??case MENU_00:
??????? ????????? label.setText("設(shè)置,菜單ID:" + item.getItemId());
??????????? return true;
??????? ?case MENU_01:
??????? ????????? label.setText("新建,菜單ID:" + item.getItemId());
??????????? return true;
??????? ?case SUB_MENU_00_01:
??????? ????????? label.setText("打印,子菜單ID:" + item.getItemId());
??????????? return true;
??????? ?case SUB_MENU_01_00:
??????? ????????? label.setText("郵件,子菜單ID:" + item.getItemId());
? ? ? ? ? ?return true;
??????? ?case SUB_MENU_01_01:
??????? ????????? label.setText("訂閱,子菜單ID:" + item.getItemId());
????????? ???return true;
??????? ?default:
??????????? return false;
??????? ?}
??? ?}
}
4、上下文菜單(快捷菜單)
?當(dāng)用戶點(diǎn)擊界面元素超過2秒后,將啟動注冊到該界面元素的快捷菜單
類似于計(jì)算機(jī)程序中的“右鍵菜單”
與“選項(xiàng)菜單”的方法非常相似,需要重載:
onCreateContextMenu()函數(shù)
onContextItemSelected()函數(shù)
快捷菜單注冊到界面中的某個控件上
?registerForContextMenu()函數(shù)

例子

(1)資源文件

<menu?xmlns:android="http://schemas.android.com/apk/res/android"??>
????<item
????????android:id="@+id/edit"
????????android:orderInCategory="100"
????????android:showAsAction="never"
????????android:title="Edit"/>
????<item
????????android:id="@+id/share"
????????android:orderInCategory="100"
????????android:showAsAction="never"
????????android:title="Share"/>
????<item
????????android:id="@+id/delete"
????????android:orderInCategory="100"
????????android:showAsAction="never"
????????android:title="Delete"/>
</menu>
(2)listview內(nèi)容填充

??@Override
??public?void?onCreate(Bundle savedInstanceState) {
?????super.onCreate(savedInstanceState);
???? setContentView(R.layout.activity_main);
?????listView?= (ListView)?this.findViewById(R.id.listView1);
???? ArrayAdapter<String> adapter =?new??ArrayAdapter<String>(this,
???????? android.R.layout.simple_list_item_1, getData());
?????listView.setAdapter(adapter);
?????//給ListView注冊上下文菜單
?????registerForContextMenu(listView);//View類型
? }
??public?List<String> getData() {
???? List<String> list =?new??ArrayList<String>();
?????for?(int?i = 1; i <= 7; i++) {
?????? list.add("jack"?+ i);
???? }
?????return?list;
? }
(3)下文菜單及事件

@Override
??public?boolean?onCreateOptionsMenu(Menu menu) {
? ? getMenuInflater().inflate(R.menu.activity_main, menu);
?????return?true;
? }
??@Override
??public?void?onCreateContextMenu(ContextMenu menu, View v,
?????? ContextMenuInfo menuInfo) {
?????//?加載xml中的上下文菜單
?????super.onCreateContextMenu(menu, v, ?menuInfo);
???? MenuInflater inflater = ?getMenuInflater();
???? inflater.inflate(R.menu.activity_main, menu);
? }
??//響應(yīng)上下文菜單的操作
??@Override
??public?boolean?onContextItemSelected(MenuItem item) {
?????//?TODO?Auto-generated ?method stub
?????switch?(item.getItemId()) {
?????case?R.id.delete:
?????? Toast.makeText(MainActivity.this,?"Delete", 1).show();
???????break;
?????case?R.id.share:
?????? Toast.makeText(MainActivity.this,?"Share", 1).show();
???????break;
?????case?R.id.edit:
?????? Toast.makeText(MainActivity.this,?"Edit", 1).show();
???????break;
???? }
?????return?super.onContextItemSelected(item);
? }
5、ActionModel菜單和PopUp菜單


(1)資源文件

<menu?xmlns:android="http://schemas.android.com/apk/res/android">
????<item?android:id="@+id/edit"
????????android:title="Edit"
????????android:orderInCategory="100"
????????android:showAsAction="never"??/>
??????<item?android:id="@+id/share"
???? ???android:title="Share"
????????android:orderInCategory="100"
????????android:showAsAction="never"??/>
????????<item?android:id="@+id/delete"
????????android:title="Share"
????????android:orderInCategory="100"
????????android:showAsAction="never"??/>
</menu>
(2)界面布局

<Button
????????android:id="@+id/button1"
????????android:layout_width="wrap_content"
????????android:layout_height="wrap_content"
????????android:layout_alignParentTop="true"
????????android:layout_centerHorizontal="true"
????????android:layout_marginTop="50dp"
????????android:text="ActionModel"??/>
????<Button
????????android:id="@+id/button2"
????????android:layout_width="wrap_content"
????????android:layout_height="wrap_content"
????????android:layout_alignLeft="@+id/button1"
????? ??android:layout_below="@+id/button1"
????????android:layout_marginTop="67dp"
????????android:text="Popup"??/>
(3)代碼實(shí)現(xiàn)
package ?com.example.android_menu_action_mode_popup;
import android.app.Activity;
import android.os.Bundle;
import android.view.ActionMode;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import ?android.view.View.OnLongClickListener;
import android.widget.Button;
import android.widget.PopupMenu;
import android.widget.PopupMenu.OnMenuItemClickListener;
import android.widget.Toast;
public class MainActivity extends ?Activity {
???????? private ?Button button;
???????? private ?ActionMode actionMode;//?使用ActionMode完成菜單操作
??? ?private Button button2;
???????? @Override
???????? public ?void onCreate(Bundle savedInstanceState) {
?????????????????? super.onCreate(savedInstanceState);
?????????????????? setContentView(R.layout.activity_main);
?????????????????? button ?= (Button) this.findViewById(R.id.button1);
?????????????????? button.setOnLongClickListener(new ?OnLongClickListener() {
??????????????????????????? @Override
??????????????????????????? public ?boolean onLongClick(View v) {
???????????????????????????????????? // ?TODO Auto-generated method stub
???????????????????????????????????? if ?(actionMode != null) {
?????????????????????????????????????????????? return ?false;
???????????????????????????????????? }
???????????????????????????????????? actionMode ?= startActionMode(actionCallback);
???????????????????????????????????? v.setSelected(true);
???????????????????????????????????? return ?true;
??????????????????????????? }
?????????????????? });
?????????????????? button2 ?= (Button)this.findViewById(R.id.button2);
?????????????????? button2.setOnClickListener(new ?View.OnClickListener() {
??????????????????????????? @Override
??????????????????????????? public ?void onClick(View v) {
???????????????????????????????????? // ?TODO Auto-generated method stub
???????????????????????????????????? PopupMenu ?popupMenu = new PopupMenu(MainActivity.this, v);
???????????????????????????????????? popupMenu.setOnMenuItemClickListener(new ?OnMenuItemClickListener() {
?????????????????????????????????????????????? @Override
?????????????????????????????????????????????? public ?boolean onMenuItemClick(MenuItem item) {
??????????????????????????????????????????????????????? // ?TODO Auto-generated method stub
??????????????????????????????????????????????????????? switch ?(item.getItemId()) {
??????????????????????????????????????????????????????? case ?R.id.edit:
???????????????????????????????????????????????????????????????? edit();
???????????????????????????????????????????????????????????????? break;
??????????????????????????????????????????????????????? case ?R.id.delete:
??????????????????????????????????????????????????????? ???????? Toast.makeText(MainActivity.this, ?"Delete", 1).show();
???????????????????????????????????????????????????????????????? break;
??????????????????????????????????????????????????????? case ?R.id.share:
???????????????????????????????????????????????????????????????? Toast.makeText(MainActivity.this, ?"Share", 1).show();
???????????????????????????????????????????????????????????????? break;
??????????????????????????????????????????????????????? }
??????????????????????????????????????????????????????? return ?false;
?????????????????????????????????????????????? }
???????????????????????????????????? });
???????????????????????????????????? MenuInflater ?inflater = popupMenu.getMenuInflater();
???????????????????????????????????? inflater.inflate(R.menu.activity_main, ?popupMenu.getMenu());
???????????????????????????????????? popupMenu.show();//顯示菜單
??????????????????????????? }
?????????????????? });
???????? }
???????? private ?ActionMode.Callback actionCallback = new ActionMode.Callback() {
?????????????????? @Override
?????????????????? public ?boolean onPrepareActionMode(ActionMode mode, Menu menu) {
??????????????????????????? // ?TODO Auto-generated method stub
??????????????????????????? return ?false;
?????????????????? }
?????????????????? @Override
?????????????????? public ?void onDestroyActionMode(ActionMode mode) {
??????????????????????????? // ?TODO Auto-generated method stub
??????????????????????????? actionMode ?= null;
?????????????????? }
?????????????????? // ?表示我們要加載菜單,從xml中加載
?????????????????? @Override
?????????????????? public ?boolean onCreateActionMode(ActionMode mode, Menu menu) {
??????????????????????????? // ?TODO Auto-generated method stub
??????????????????????????? MenuInflater ?inflater = getMenuInflater();
??????????????????????????? inflater.inflate(R.menu.activity_main, ?menu);
??????????????????????????? return ?true;
?????????????????? }
?????????????????? @Override
?????????????????? public ?boolean onActionItemClicked(ActionMode mode, MenuItem item) {
??????????????????????????? // ?TODO Auto-generated method stub
??????????????????????????? switch ?(item.getItemId()) {
??????????????????????????? case ?R.id.edit:
???????????????????????????????????? edit();
???????????????????????????????????? break;
??????????????????????????? case ?R.id.delete:
???????????????????????????????????? Toast.makeText(MainActivity.this, ?"Delete", 1).show();
???????????????????????????????????? break;
??????????????????????????? case ?R.id.share:
???????????????????????????????????? Toast.makeText(MainActivity.this, ?"Share", 1).show();
???????????????????????????????????? break;
??????????????????????????? }
??????????????????????????? return ?false;
?????????????????? }
???????? };
???????? public ?void edit() {
?????????????????? Toast.makeText(MainActivity.this, ?"Edit", 1).show();
???????? }
???????? @Override
???????? public ?boolean onCreateOptionsMenu(Menu menu) {
?????????????????? getMenuInflater().inflate(R.menu.activity_main, ?menu);
?????????????????? return ?true;
???????? }
}