1.1 Menu 菜单
【
Menu 菜单
1. OptionsMenu 选项菜单
特点: 当通过点击menu键或者3.0以上的手机上,点击右上方的三个点,出现的列表,都是有OptionMenu对象进行控制
2. ContextMenu上下文菜单
特点:当长按指定控件后,在屏幕中心弹出列表对话框
3. PopupMenu 浮动菜单
特点:通过指定控件指定监听,触发显示,可以让菜单列表显示在指定控件的下方
】
1.1.1 概述
【
菜单是一种非常常见的与用户交互的一种用户界面组件
从Android 3.0开始,Android不要求手机设备上必须提供MENU按键。因此Android推荐使用ActionBar来代替Menu
】
1.1.2 菜单的创建
【1、通过代码创建
2、使用xml资源文件创建菜单(res/menu目录下)(建议使用,重点掌握)】
1.1.3 菜单的分类
【
Options Menu 选项菜单
Context Menu 上下文菜单
Popup Menu 浮动菜单
】
1.1.4 在XML中定义Menu文件
【
位置:res/menu目录下
<menu>:代表菜单资源
<item>:菜单项
android:id // 菜单项的id
android:icon // 菜单项的图标
android:title // 菜单项的标题
android:orderInCategory // 排序
android:showAsAction // 在ActionBar上的显示参数(API 11)
never:不将MenuItem显示在ActionBar上(是默认值)
always:总是将该MenuItem显示在ActionBar上
ifRoom:当AcitonBar上有空间时将该MenuItem显示在ActionBar上,没有空间就放入溢出菜单中
withText:将该MenuItem显示在ActionBar上,并显示该菜单项的文本
显示自定义ActionBar的View,需要和actionViewClass这组参数结合使用(API14)
<group>:菜单组
二级菜单(子菜单的创建)
概念:在menu Item中嵌套menu元素,可以实现多级菜单,嵌套的菜单叫做子菜单,一般只会使用二级菜单,如果菜单层次太深,会严重影响用户体验。
二级可选菜单
android:checkableBehavior
有三个属性值可选
all(多选)
single(单选)
none(不可选)
】
1.1.5 选项菜单
【
使用步骤
初始化选项菜单:onCreateOptionsMenu(Menu menu)
为菜单项设置监听器:onOptionsItemSelected(MenuItem item)
OptionsMenu的使用方式:
方式一:纯代码处理(官方并不是特别推荐)
方式二:xml文件+代码(官方推荐方式)
通过xml文件+代码实现Options Menu的显示
Xml文件:负责设置菜单列表中总共要显示哪些数据选项,以及这些选项的显示特点
代码: 负责处理加载xml文件,并处理点击事件
关于xml文件的处理:
1. 在res文件夹内容准备一个menu文件夹,所有控制菜单显示的xml文件均被存于此处
2. 在menu文件夹中创建一个xml文件,让该文件以menu标签作为根标签
3. 在menu标签之间添加item标签,每一个item标签代表一个菜单选项
4. 处理item标签中的属性
代码实现:
<?xml version="1.0"encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<!--
android:id 用于设置item的id,即唯一标识,用于稍后的点击判断
android:title 用于设置标题
android:orderInCategory 用于设置item选项在菜单列表中的排列顺序
属性值越小,排列顺序越靠前,
如果属性值相同,哪个item的代码在前面,哪个item就排名靠前
android:icon 用于设置图标。注意:如果item是显示在菜单列表中,那么
图标永远不显示
android:showAsAction android3.0 以后才出的属性
用于设置item在标题栏上的显示特点
可选属性值:
never 该选项永远显示在菜单列表中
ifRoom 如果标题栏上有剩余空间,就显示在标题栏上,如果没有,就显示在菜单列表中
always 该选项永远直接显示在标题栏上
withText 让图标和文字同时显示
-->
<item
android:id="@+id/item1"
android:title="菜单项一"
android:orderInCategory="3000"
android:showAsAction="always|withText"
android:icon="@drawable/ic_launcher"/>
<item
android:id="@+id/item2"
android:title="菜单项二"
android:orderInCategory="10"
android:showAsAction="ifRoom"
android:icon="@drawable/ic_launcher"/>
<item
android:id="@+id/item3"
android:orderInCategory="20"
android:title="菜单项三"
android:icon="@drawable/ic_launcher"/>
</menu>
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
/*
* 重写onCreateOptionsMenu方法,在此方法中加载xml文件参数:代表要显示的菜单对象
*
* 返回值:true 显示菜单, false 不显示菜单
*/
@Override
public boolean onCreateOptionsMenu(Menu menu){
// TODOAuto-generated method stub
/*
* 将my.xml文件中的所有item菜单选项添加到参数二指定的menu对象中显示
*/
getMenuInflater().inflate(R.menu.my_menu, menu);
//通过代码添加菜单选项
/*
* 1. 该菜单选项所在组的groupId
* 2. 该菜单的唯一标识,id属性的值
* 3. 控制排列顺序,作用等同于orderInCategory属性
* 4:选项上要显示的文字标题
* */
menu.add(0, 1, 20, "代码添加menu");
return true;
}
//重写此方法,获取菜单项的点击事件,参数代表被点击的菜单选项
@Override
public boolean onOptionsItemSelected(MenuItemitem) {
// TODOAuto-generated method stub
Toast.makeText(this,item.getTitle()+String.valueOf(item.getItemId()), Toast.LENGTH_SHORT).show();
//区分被点击的item
switch (item.getItemId()){
caseR.id.item1:
break;
caseR.id.item2:
break;
caseR.id.item3:
break;
}
return super.onOptionsItemSelected(item);
}
}
】
1.1.5.1 示例代码
【
<?xml version="1.0"encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/menu1"
android:orderInCategory="100"
android:showAsAction="never"
android:title="选项菜单1"/>
<item
android:id="@+id/menu2"
android:orderInCategory="100"
android:showAsAction="never"
android:title="选项菜单2"/>
<item
android:id="@+id/menu3"
android:orderInCategory="100"
android:showAsAction="never"
android:title="选项菜单3"/>
<!--选项菜单可分组 -->
<group android:id="@+id/menu_group1">
<item
android:id="@+id/menu4"
android:orderInCategory="100"
android:showAsAction="never"
android:title="组1选项菜单1"/>
<item
android:id="@+id/menu5"
android:orderInCategory="100"
android:showAsAction="never"
android:title="组1选项菜单2"/>
</group>
<!--在XML添加具有子选项的菜单 -->
<item
android:id="@+id/con_son_menu"
android:title="点击出子菜单">
<menu>
<!-- 样式出现选择样式 -->
<group android:checkableBehavior="all" >
<item
android:checked="true"
android:id="@+id/con_son_menu_1"
android:title="子菜单1"/>
<item
android:id="@+id/con_son_menu_2"
android:title="子菜单2"/>
</group>
</menu>
</item>
</menu>
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// TODOAuto-generated method stub
//布局xml配置加载
getMenuInflater().inflate(R.menu.my_menu, menu);
//代码添加菜单项
"组2代码项1");
"组2代码项2");
/**
* 可以根据组ID决定组中的菜单项是否可见或可操作
*/
menu.setGroupEnabled(2,false);
/**
* 通过代码添加有子菜单项的菜单
*/
"代码子菜单");
"子1");
"子2").setOnMenuItemClickListener(new OnMenuItemClickListener() {
@Override//boolean监听:代表处理完监听,是否还要进行额外操作
publicboolean onMenuItemClick(MenuItemitem) {
// TODOAuto-generated method stub
Toast.makeText(MainActivity.this, "=====+"+item.getTitle()+"设置单个子菜单事件", Toast.LENGTH_SHORT).show();
returnfalse;
}
});
return true;
}
//菜单列表item的点击事件,参数代表被点击的item菜单选项
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// TODOAuto-generated method stub
switch(item.getItemId()) {
case 34:
Toast.makeText(MainActivity.this, "点击了子菜单中的子选项1", Toast.LENGTH_SHORT).show();
break;
case 35:
Toast.makeText(MainActivity.this, "点击了子菜单中的子选项2", Toast.LENGTH_SHORT).show();
break;
}
return super.onOptionsItemSelected(item);
}
}
】
1.1.6 上下文菜单
【
使用步骤
初始化上下文菜单:onCreateContextMenu(ContextMenu menu, View v,ContextMenuInfo menuInfo)
为指定控件注册上下文菜单:registerForContextMenu(Viewview)
为菜单项设置监听器:onContextItemSelected(MenuItemitem)
特点:当长按指定控件的时候显示的菜单列表
位置固定显示与屏幕中心
使用步骤:
大体步骤与OptionsMenu 基本一致
1. 通过menu文件夹中的xml文件定义菜单列表中要显示的内容
2. 重写onCreateContextMenu方法,在该方法中通过
3. 重写onContextItemSelected方法获取菜单选项被点击的监听事件
4. 在页面的onCreate方法中通过registerForContextMenu方法的参数指定长按哪个控件对象显示菜单
当registerForContextMenu方法中传递的是一个listview对象时,ContextMenu是针对列表中每个item进行设置
在onContextItemSelected方法中可以通过以下方式获取别长按的item在listview中对应的position位置
//获取被点击的菜单选项对应的菜单信息封装对象
aci = (AdapterContextMenuInfo) item.getMenuInfo();
//通过菜单信息封装对象获取被点击的item的位置
int position = aci.position;
】
1.1.6.1 示例代码
【
<?xml version="1.0"encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/list_item1"
android:title="复制"/>
<item
android:id="@+id/list_item2"
android:title="删除"/>
<item
android:id="@+id/list_item3"
android:title="重命名"/>
</menu>
public class MainActivity extends Activity {
private TextView tv;
@Override
protected voidonCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv=(TextView) this.findViewById(R.id.tv);
tv);
}
@Override
public voidonCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfomenuInfo) {
// TODO Auto-generated method stub
super.onCreateContextMenu(menu, v, menuInfo);
getMenuInflater().inflate(R.menu.main, menu);
}
}
public class TwoActivity extends Activity {
private ListView lv;
list = newArrayList<String>();
adapter;
@Override
protected voidonCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_two);
lv=(ListView) this.findViewById(R.id.listview1);
for(inti=0;i<10;i++){
list.add("item"+i);
}
adapter = newArrayAdapter<>(this,android.R.layout.simple_list_item_1, list);
lv.setAdapter(adapter);
lv);
}
@Override
public voidonCreateContextMenu(ContextMenu menu, View v, //此v是传递过来的对象
ContextMenuInfomenuInfo) {
// TODO Auto-generated method stub
super.onCreateContextMenu(menu, v, menuInfo);
getMenuInflater().inflate(R.menu.list_menu, menu);
v.setBackgroundColor(Color.RED);
}
@Override
public booleanonContextItemSelected(MenuItem item) {
// TODO Auto-generated method stub
AdapterContextMenuInfoaci=(AdapterContextMenuInfo)item.getMenuInfo();
final intposition = aci.position;
switch (item.getItemId()) {
case R.id.list_item1: //复制
list.add(list.get(position));
adapter.notifyDataSetChanged();
break;
case R.id.list_item2: //删除
list.remove(position);
adapter.notifyDataSetChanged();
break;
case R.id.list_item3: //重命名
Viewv = View.inflate(this,R.layout.custom, null);
final AlertDialog dialog = new AlertDialog.Builder(this)
.setView(v)
.show();
final EditText ed_name =(EditText)v.findViewById(R.id.ed_name);
Buttonbtn_ok = (Button) v.findViewById(R.id.btn_ok);
btn_ok.setOnClickListener(new OnClickListener() {
@Override
public voidonClick(View v) {
// TODO Auto-generated method stub
list.set(position, ed_name.getText().toString());
adapter.notifyDataSetChanged();
dialog.dismiss();
}
});
break;
}
return super.onContextItemSelected(item);
}
@Override
public voidonContextMenuClosed(Menu menu) {
// TODO Auto-generated method stub
super.onContextMenuClosed(menu);
lv.setBackgroundColor(Color.WHITE);
}
}
】
1.1.7 浮动菜单
【
使用步骤
创建浮动菜单对象:PopupMenu popupMenu = newPopupMenu(this, btn_show_popupmenu);
参数1:上下文环境
参数2:需要绑定浮动菜单的控件id
将菜单文件加载到内存中:getMenuInflater().inflate(R.menu.popup_menu,popupMenu.getMenu());
为菜单项设置监听器:popupMenu.setOnMenuItemClickListener(OnMenuItemClickListener)
显示菜单:popupMenu.show();
PopupMenu浮动菜单
特点:
1. 可以指定任意控件通过任意方式触发浮动菜单的显示
2. 可以显示在指定控件的下方
使用方式:
1. 获取控件对象,设置任意的监听,如设置tv的点击事件
代表是要在tv被点击时显示Popup Menu
//1.初始化popupmenu对象
/*
* 参数2:默认情况下是让pm稍后再显示的时候,可以显示在该控件的下方
* 但是当该控件下方没有足够的控件的时候,就让pm显示在该控件的上方
* */
PopupMenu pm = newPopupMenu(PopupMenuActivity.this,tv);
/*
* 3参的构造方法的参数3:用于指定pm与控件的对齐方式
* 此方法必须确保在 19版本,即4.4.2版本以上才能生效
* */
// PopupMenupm = new PopupMenu(PopupMenuActivity.this, tv, Gravity.RIGHT);
2. 向popupmenu对象中添加要显示的菜单选项
//添加方式一:
// getMenuInflater().inflate(R.menu.popup_menu,pm.getMenu());
//添加方式二
pm.inflate(R.menu.popup_menu);
3. 通过show方法显示popupmenu对象
pm.show();
设置popupmenu中菜单选项的点击事件:
//获取pm菜单选项的点击事件
pm.setOnMenuItemClickListener(new OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
// TODO Auto-generated method stub
Toast.makeText(PopupMenuActivity.this, item.getTitle(), Toast.LENGTH_SHORT).show();
return false;
}
});
PopupWindow的使用:
浮动窗口, 特点:效果上是一个可以自定义显示及显示位置的对话框
使用方式:
//1.初始化对象
/*
* 1. 用于指定pw中要显示View对象
* 2,3. 用于指定pw显示时的宽高
* */
vv= View.inflate(PopupWindowActivity.this, R.layout.custom, null);
pw = new PopupWindow(vv, 400, 400);
//设置pw中的控件能够获取焦点
pw.setFocusable(true);
//设置可以通过点击pw外部关闭pw,但是生效的前提
//是必须给pw设置了背景才行
//设置pw的默认背景,即如果custom布局中没有指定背景的话,就显示此背景
pw.setBackgroundDrawable(getResources().getDrawable(R.drawable.ic_launcher));
pw.setOutsideTouchable(true);
//3.通过show**方法显示
// pw.showAsDropDown(tv,50, 50);
/*
* 1. 通过参数一指定的控件寻找该控件的父控件
* 以父控件的范围为基准
* 2. gravity 居中,右下等位置
* 3,4. 水平和垂直方向的偏移量
*
* */
pw.showAtLocation(tv, Gravity.CENTER, 0, 0);
】
1.1.8 扩展:PopupWindow(浮动窗口)
【
基本使用步骤
构造方法:PopupWindow(View contentView, intwidth, int height)
参数1:contentView,浮动窗口中显示的内容
参数2:width,浮动窗口的宽度
参数3:height,浮动窗口的高度
显示浮动窗口:showAsDropDown(Viewanchor, int xoff, int yoff)
参数1:anchor,浮动窗口出现在指定控件的下方
参数2:xoff,在X轴上的偏移量
参数3:yoff,在Y轴上的偏移量
隐藏浮动窗口:dismiss()
显示带列表的浮动窗口
创建ListView对象
setAdapter(ListAdapter):设置列表适配器,用于填充列表数据
setOnItemClickListener(OnItemClickListener):设置列表项的监听事件
setFocusable(true):使浮动窗口可以获取焦点
setBackgroundDrawable(newColorDrawable()):为解决焦点问题,这行代码必须执行
PopupWindow 补充:
当初始化PopupWindow对象时,需要通过构造方法传递PopupWindow要显示的宽高,除了直接指定宽高对应的数字之外,能不能设置成wrap_content或者match_parent??
解决方式:在需要指定宽高的位置,通过ViewGroup包内的LayoutParams的类中的静态常量即可调用FILL_PARENT,MATCH_PARENT和WRAP_CONTENT 属性设置了
】
1.1.8.1 示例代码
【
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:context="com.example.day13popupmenu.popupwindow.MainActivity">
<item
android:id="@+id/pu_menu1"
android:title="pm菜单1"/>
<item
android:id="@+id/pu_menu2"
android:title="pm菜单2"/>
<item
android:id="@+id/pu_menu3"
android:title="pm菜单3"/>
<item
android:id="@+id/pu_menu4"
android:title="pm菜单4"/>
</menu>
public class MainActivity extends Activity {
private TextView tv;
@Override
protected voidonCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv =(TextView) this.findViewById(R.id.tv);
tv.setOnClickListener(newOnClickListener() {
@Override
public voidonClick(View v) {
// TODO Auto-generated method stub
PopupMenu pm = new PopupMenu(MainActivity.this, tv);
getMenuInflater().inflate(R.menu.main,pm.getMenu());
//pm.inflate(R.menu.main);
pm.show();
pm.setOnMenuItemClickListener(new OnMenuItemClickListener() {
@Override
public booleanonMenuItemClick(MenuItem item) {
// TODO Auto-generated method stub
Toast.makeText(MainActivity.this, item.getTitle(), Toast.LENGTH_SHORT).show();
return false;
}
});
pm.setOnDismissListener(new OnDismissListener() {
@Override
public voidonDismiss(PopupMenu menu) {
// TODO Auto-generated method stub
Toast.makeText(MainActivity.this, "close",Toast.LENGTH_SHORT).show();
}
});
}
});
}
}
public class TwoActivity extends Activity {
private TextView tv;
@Override
protected voidonCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = (TextView) this.findViewById(R.id.tv);
tv.setOnClickListener(newOnClickListener() {
@Override
public voidonClick(View v) {
View vv = View.inflate(TwoActivity.this, R.layout.custom,null);
final PopupWindow pw = newPopupWindow(vv, 300, 300);
// pw.showAsDropDown(vv,50,50);
// 设置pw能够获得焦点
pw.setFocusable(true);
// 设置浮动窗体,点击旁白能够自动消失,但是必须要设置setBackgroundDrawable才能生效
pw.setBackgroundDrawable(getResources().getDrawable(
R.drawable.ic_launcher));
pw.setOutsideTouchable(true);
pw.showAtLocation(vv,Gravity.CENTER, 0, 0);
Buttonbtn_ok = (Button) vv.findViewById(R.id.btn_ok);
final EditText ed_edit = (EditText) vv
.findViewById(R.id.ed_name);
btn_ok.setOnClickListener(new OnClickListener() {
@Override
public voidonClick(View v) {
// TODO Auto-generated method stub
Toast.makeText(TwoActivity.this,
ed_edit.getText().toString(),
Toast.LENGTH_SHORT).show();
pw.dismiss();
}
});
}
});
}
}