Android Menu
一、Opti onMenu选项菜单:
(一)、简介:
1、A ndroi d应用中的菜单默认是隐藏的,只有当用户点击手机上的ME NU 键,系统才会显示菜单。这种菜单叫做选项菜单(Opti on Menu)
2、从3. 0开始,A ndroi d不要求手机设备上必须提供ME NU 按键。因此A ndroi d推荐使用A c ti onB ar来代替Menu
(二)、创建菜单:(A ndroi d提供了两种创建菜单的方式)
1、在j ava代码创建菜单;
2、使用xml 资源文件创建菜单(res/menu目录下)。建议使用后者。
(三)、XML 资源文件中定义菜单:
1、普通菜单:
androi d: showA sA c ti on
a)never: 从来不再导航栏显示,但是如果手机没有menu,这个参数无效
b)i fRoom: 如果导航栏有空间系统进行摆放,没有空间不摆放
c )al ways: 总是在导航栏进行显示
d)wi thText: 在导航栏只显示文字
e)c ol l apseA c ti onV i ew:显示自定义A c ti onB ar的V i ew,他是和ac ti onV i ewCl ass这组参数结合使用的
<i tem
androi d: i d=" @+i d/opti ons_i tem"
androi d: i c on=" @drawabl e/i c on"
androi d: showA sA c ti on=" i fRoom"
androi d: ti tl e=" 内容" />
说明:showA sA c ti on表示在A c ti onB ar位置出现的设定:never(从不,还在原来位置) ,i fRoom(如果有空间就会摆放)
2、二级普通菜单:
<i tem
androi d: i d=" @+i d/opti ons_i tem2"
androi d: i c on=" @drawabl e/i c on_0002"
androi d: ti tl e=" @stri ng/opti ons_i tem2" >
<menu>
<i tem
androi d: i d=" @+i d/opti ons_submenui tem1"
androi d: ti tl e=" @stri ng/opti ons_submenui tem1" />
<i tem
androi d: i d=" @+i d/opti ons_submenui tem2"
androi d: ti tl e=" @stri ng/opti ons_submenui tem2" />
</menu>
</i tem>
说明:菜单的嵌套称为子菜单
3、二级可选项菜单:
<i tem
androi d: i d=" @+i d/menu_group1"
androi d: orderInCategory=" 1"
androi d: showA sA c ti on=" never"
androi d: ti tl e=" 文字尺寸" >
<menu >
<!-- androi d: c hec kabl eB ehavi or 属性有三个可选值:al l 为多选,si ngl e为单选,none为不可选。为none时就是一个普通菜单 -->
<group androi d: c hec kabl eB ehavi or=" si ngl e" >
<i tem androi d: i d=" @+i d/font_10" androi d: ti tl e=" 10sp" ></i tem>
<i tem androi d: i d=" @+i d/font_15" androi d: ti tl e=" 15sp" ></i tem>
<i tem androi d: i d=" @+i d/font_20" androi d: ti tl e=" 20sp" ></i tem>
<i tem androi d: i d=" @+i d/font_25" androi d: ti tl e=" 25sp" ></i tem>
<i tem androi d: i d=" @+i d/font_30" androi d: ti tl e=" 30sp" ></i tem>
</group>
</menu>
</i tem>
(四)、菜单操作:
利用bool ean onOpti onsItemSel ec ted(MenuItem i tem)回调方法。
核心代码如下:利用以上定义的xml 菜单文件,实现通过菜单选项对文字的大小和颜色进行控制。
@Overri de
publ i c bool ean onOpti onsItemSel ec ted(MenuItem i tem) {
swi tc h (i tem. getItemId()) {
c ase R. i d. font_20:
text_mai n_i nfo. setTextSi ze(20);
break;
c ase R. i d. font_30:
text_mai n_i nfo. setTextSi ze(30);
break;
c ase R. i d. font_red:
text_mai n_i nfo. setTextCol or(Col or. RE D);
break;
c ase R. i d. font_green:
text_mai n_i nfo. setTextCol or(Col or. GRE E N);
break;
}
return super. onOpti onsItemSel ec ted(i tem);
}
二、ContextMenu上下文菜单:
(一)、上下文菜单介绍:上下文菜单继承自androi d. vi ew.Menu。
1、上下文菜单与Opti ons Menu最大的不同在于:
Opti ons Menu的拥有者是A c ti vi ty,而上下文菜单的拥有者是A c ti vi ty中的V i ew;
每个A c ti vi ty有且只有一个Opti ons Menu,它为整个A c ti vi ty服务。而一个A c ti vi ty往往有多个V i ew,哪个V i ew需要上下文菜单就通
过regi sterForContextMenu(V i ew vi ew)给这个V i ew注册上下文菜单。
2、生成上下文菜单是通过A c ti vi ty中的onCreateContextMenu()方法:
onCreateContextMenu(ContextMenu menu, V i ew v, ContextMenu. ContextMenuInfo menuInfo)方法很像生成Opti ons Menu的
onCreateOpti onsMenu(Menu menu)方法;
两者的不同在于:onCreateOpti onsMenu只在用户第一次按“Menu”键时被调用,而onCreateContextMenu会在用户每一次长按注册了上
下文菜单的V i ew时被调用。
3、ContextMenu工作原理图:
4、ContextMenuInfo 有什么用呢?
当视图元素需要向上下文菜单传递一些信息,比如该V i ew对应DB 记录的i d等,这就要使用ContextMenuInfo。需要传递额外信息的
V i ew需要重写getContextMenuInfo()方法,返回一个带有数据的ContextMenuInfo实现类对象。
ContextMenuInfo携带了注册上下文菜单控件的一些额外信息。一般用在A daterV i ews(例如:Spi nner 、L i stV i ew或Gri dV i ew)上,可以
在ContextMenuInfo 中获取到适配器V i ew中的posi ti on的信息。
5、如何获取adapter数据源的下标posi ti on
方法一:通过A dapterContextMenuInfo获取ContextMenuInfo的信息,在A dapterContextMenuInfo里可以获取posi ti on的信息,最后在监听
里通过posi ti on进行逻辑的操作了
方法二:通过lis t V iew的s et onI t em L ongC lick获取pos it ion, 然后定义全局的变量pos it ion获取内容,最后在监听里通过posi ti on进行
逻辑的操作了
(二)、开发上下文菜单的步骤:
1、调用A c ti vi ty的regi sterForContextMenu(V i ew vi ew)方法为vi ew组件注册上下文菜单;(注册上下文菜单后,意味着用户长按该控件后显
示上下文菜单)。
2、重写onCreateContextMenu(ContextMenu menu, V i ew v, ContextMenuInfo menuInfo)方法;
3、为菜单项提供响应,重写onContextItemSel ec ted(MenuItem i tem)。
(三)、核心示例代码:
@Overri de
protec ted voi d onCreate(B undl e savedInstanc eState) {
super. onCreate(savedInstanc eState);
setContentV i ew(R. l ayout. ac ti vi ty_mai n);
text_mai n_i nfo = (TextV i ew) fi ndV i ewB yId(R. i d. text_mai n_i nfo);
thi s. regi sterForContextMenu(text_mai n_i nfo);
}
@Overri de
publ i c voi d onCreateContextMenu(ContextMenu menu, V i ew v,
ContextMenuInfo menuInfo) {
super. onCreateContextMenu(menu, v, menuInfo);
getMenuInfl ater(). i nfl ate(R. menu. c ontextmenu_mai n, menu);
}
@Overri de
publ i c bool ean onContextItemSel ec ted(MenuItem i tem) {
swi tc h (i tem. getItemId()) {
c ase R. i d. font_20:
text_mai n_i nfo. setTextSi ze(20);
break;
c ase R. i d. font_30:
text_mai n_i nfo. setTextSi ze(30);
break;
c ase R. i d. font_red:
text_mai n_i nfo. setTextCol or(Col or. RE D);
break;
c ase R. i d. font_green:
text_mai n_i nfo. setTextCol or(Col or. GRE E N);
break;
}
return super. onContextItemSel ec ted(i tem);
}
(四)、上下文菜单和A c ti onB ar模式的结合(Contextual A c ti onMode)
1、 从3. 0开始,可以用这种模式代替原有的ContextMenu形式,这种模式会在列表选项的时候呈现,并且支持多选的功能
(五)、普通V i ew开发Contextual 菜单的步骤:
步骤一:通过V i ew的长按事件开启模式
A c ti onMode mA c ti onMode = nul l ;
vi ew. setOnL ongCl i c kL i stener(new V i ew. OnL ongCl i c kL i stener() {
publ i c bool ean onL ongCl i c k(V i ew vi ew) {
i f (mA c ti onMode != nul l ) { //避免反复开启 A c ti onMode 模式
return fal se;
}
//开启模式
mA c ti onMode = getA c ti vi ty(). startA c ti onMode(mA c ti onModeCal l bac k);
//视图设置为被选中
vi ew. setSel ec ted(true);
return true;
}
});
步骤二:实现A c ti onMode的Cal l bac k接口
pri vate A c ti onMode. Cal l bac k mA c ti onModeCal l bac k = new A c ti onMode. Cal l bac k() {
//模式开启第一个调用的方法
@Overri de
publ i c bool ean onCreateA c ti onMode(A c ti onMode mode, Menu menu) {
//创建上下文菜单
MenuInfl ater i nfl ater = mode. getMenuInfl ater();
i nfl ater. i nfl ate(R. menu. c ontext_menu, menu);
return true;
}
//每次模式显示会被反复调用,在onCreateA c ti onMode方法之后执行,如果模式更新会被多次调用
@Overri de
publ i c bool ean onPrepareA c ti onMode(A c ti onMode mode, Menu menu) {
//不处理任何事
return fal se;
}
// A c ti onMode下上下文菜单被选中
@Overri de
publ i c bool ean onA c ti onItemCl i c ked(A c ti onMode mode, MenuItem i tem) {
swi tc h (i tem. getItemId()) {
c ase R. i d. menu_share:
//自己的逻辑算法
。。。
//关闭开启的A c ti onMode
mode. fi ni sh();
//事件到此为止,不再继续传递
return true;
defaul t:
return fal se;
}
}
// 退出A c ti onMode时候调用
@Overri de
publ i c voi d onDestroyA c ti onMode(A c ti onMode mode) {
mA c ti onMode = nul l ;
}
};
(六)、L i stV i ew/Gri dV i ew开发Contextual 菜单的步骤(比较常用):
步骤一: 设置L i stV i ew的模式为 CH OICE _MODE _MU L TIPL E _MODA L
L i stV i ew l i stV i ew = getL i stV i ew();
l i stV i ew. setChoi c eMode(L i stV i ew. CH OICE _MODE _MU L TIPL E _MODA L );
步骤二:设置多选监听
l i stV i ew. setMul ti Choi c eModeL i stener(new Mul ti Choi c eModeL i stener() {
@Overri de
publ i c voi d onItemChec kedStateChanged(A c ti onMode mode, i nt posi ti on, l ong i d, bool ean c hec ked) {
//多选框选中状态发生改变时调用,可以添加相应的逻辑
}
// A c ti onMode下上下文菜单被选中
@Overri de
publ i c bool ean onA c ti onItemCl i c ked(A c ti onMode mode, MenuItem i tem) {
// Respond to c l i c ks on the ac ti ons i n the CA B
swi tc h (i tem. getItemId()) {
c ase R. i d. menu_del ete:
del eteSel ec tedItems();
mode. fi ni sh(); // A c ti on pi c ked, so c l ose the CA B
return true;
defaul t:
return fal se;
}
}
//A c ti onMode模式启动
@Overri de
publ i c bool ean onCreateA c ti onMode(A c ti onMode mode, Menu menu) {
// 创建上下文菜单
MenuInfl ater i nfl ater = mode. getMenuInfl ater();
i nfl ater. i nfl ate(R. menu. c ontext, menu);
return true;
}
//退出A c ti onMode
@Overri de
publ i c voi d onDestroyA c ti onMode(A c ti onMode mode) {
}
//每次模式显示会被反复调用,在onCreateA c ti onMode方法之后执行,如果模式更新会被多次调用
@Overri de
publ i c bool ean onPrepareA c ti onMode(A c ti onMode mode, Menu menu) {
//什么都不处理
return fal se;
}
});
三、PopU p Menu 浮动菜单:
1.一种经常会使用的浮动式弹出的菜单,点击后会在该视图剩余空白的空间显示菜单,可能在vi ew的上方出现,也有可能在vi ew的下方出现
2.式例代码:
步骤一:注册绑定的流程
//指定的vi ew创建PopU pMenu,第二个参数,实际指定的vi ew,点击它以后就会产生PopupMenu
PopupMenu popupMenu = new PopupMenu(thi s, vi ew);
// 弹出菜单的设置
MenuInfl ater i nfl ater = getMenuInfl ater();
i nfl ater. i nfl ate(R. menu. popupmenu, popupMenu. getMenu());
// A PI 在14之上
可以一步完成上述的两步
//popupMenu. i nfl ate(R. menu. popupmenu);
// 注册监听事件
popupMenu. setOnMenuItemCl i c kL i stener(thi s);
//点击进进行显示
popupMenu. show();
步骤二:菜单监听
@Overri de
publ i c bool ean onMenuItemCl i c k(MenuItem i tem) {
swi tc h (i tem. getItemId()) {
c ase R. i d. i tem1:
return true;
defaul t:
return fal se;
}
}
*四、PopU pWi ndow浮动视图(补充内容):
1.弹出的浮动式窗口,可以放在屏幕的任何位置,灵活项很强
核心代码:
1)创建:
V i ew popV i ew = getL ayoutInfl ater(). i nfl ate(R. l ayout. popupwi ndow_menu, nul l );
popupWi ndow = new PopupWi ndow(popV i ew, L ayoutParams.MA TCH _PA RE NT, L ayoutParams.WRA P_CONTE NT);
2)消失: di smi ss()
3)设置显示位置:showA tL oc ati on(popV i ew, Gravi ty. B ottom, 0, 0) 并且显示;