菜单的分类
选项菜单
菜单资源文件
这里有个属性要说一下,app:showAsAction属性值:always:直接在操作栏显示,never:不显示,withText:控制图标和文本一起显示,ifRoom:有空间就显示
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:title="保存"
android:id="@+id/save"
android:icon="@mipmap/ic_launcher"
app:showAsAction="always|withText"/>
<item android:title="设置"
android:id="@+id/setting"/>
<item android:title="更多"
android:id="@+id/more">
<menu>
<item android:title="操作1"/>
<item android:title="操作2"/>
<item android:title="操作3"/>
</menu>
</item>
</menu>
在onCreateOptionsMenu(Menu menu)方法中加载菜单资源文件,显示菜单。
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.save:
break;
case R.id.setting:
break;
case R.id.more:
break;
}
return super.onOptionsItemSelected(item);
}
当选项菜单被选中时会回调onOptionsItemSelected(@NonNull MenuItem item)方法,在此方法里通过判断id可以对不同的选项做不同的操作。
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.save:
Toast.makeText(this,"保存",Toast.LENGTH_SHORT).show();
break;
case R.id.setting:
Toast.makeText(this,"设置",Toast.LENGTH_SHORT).show();
break;
case R.id.more:
Toast.makeText(this,"更多",Toast.LENGTH_SHORT).show();
break;
}
return super.onOptionsItemSelected(item);
}
除了使用菜单资源文件这种方式还可以使用纯代码的方式来添加选项菜单。
@Override
public boolean onCreateOptionsMenu(Menu menu) {
//参数1:组id,参数2:菜单项id,参数3:序号,参数4:选项名称
menu.add(1,1,1,"保存");
menu.add(1,2,2,"设置");
SubMenu subMenu = menu.addSubMenu(1, 3, 3, "更多");
subMenu.add(2,1,1,"操作1");
subMenu.add(2,2,2,"操作2");
return super.onCreateOptionsMenu(menu);
}
弹出菜单
API11以后才可以使用弹出菜单
popmenu.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:title="复制"
android:id="@+id/copy"/>
<item android:title="粘贴"
android:id="@+id/paste"/>
</menu>
代码
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btnMenu = findViewById(R.id.btn_popmenu);
btnMenu.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//初始化弹出式菜单
PopupMenu popupMenu = new PopupMenu(MainActivity.this,btnMenu);
//加载菜单资源文件
getMenuInflater().inflate(R.menu.popmenu,popupMenu.getMenu());
//设置菜单项的监听器
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()) {
case R.id.copy:
Toast.makeText(MainActivity.this,"复制",Toast.LENGTH_SHORT).show();
break;
case R.id.paste:
Toast.makeText(MainActivity.this,"粘贴",Toast.LENGTH_SHORT).show();
break;
}
return false;
}
});
//显示菜单
popupMenu.show();
}
});
}
弹出菜单显示效果:
上下文菜单
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:orientation="vertical">
<Button
android:id="@+id/btn_contextmenu"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="上下文菜单"/>
<Button
android:id="@+id/btn_popmenu"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="弹出式菜单"/>
</LinearLayout>
contextmenu.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:title="删除"
android:id="@+id/delete"/>
<item android:title="重命名"
android:id="@+id/rename"/>
</menu>
创建上下文菜单代码
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//注册上下文菜单
registerForContextMenu(findViewById(R.id.btn_contextmenu));
}
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
//加载上下文菜单资源文件
getMenuInflater().inflate(R.menu.contextmenu,menu);
super.onCreateContextMenu(menu, v, menuInfo);
}
//当上下文菜单选项被选中时调用
@Override
public boolean onContextItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.delete:
Toast.makeText(MainActivity.this,"删除",Toast.LENGTH_SHORT).show();
break;
case R.id.rename:
Toast.makeText(MainActivity.this,"重命名",Toast.LENGTH_SHORT).show();
break;
}
return super.onContextItemSelected(item);
}
}
此时上下文菜单是这样的
上下文操作模式其实就是占用操作栏来显示上下文菜单。
如果我们使用上下文操作模式的话,应该这样写:
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//上下文操作模式
findViewById(R.id.btn_contextmenu).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//启动上下文操作模式
startActionMode(callback);
}
});
}
ActionMode.Callback callback = new ActionMode.Callback() {
/**
* 在创建方法后调用
* @param mode
* @param menu
* @return
*/
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
Log.d(TAG, "onCreateActionMode: 创建");
getMenuInflater().inflate(R.menu.contextmenu,menu);
return true;
}
/**
*在准备上下文操作模式时调用
* @param mode
* @param menu
* @return
*/
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
Log.d(TAG, "onPrepareActionMode: 准备");
return false;
}
/**
*在选项被点击时调用
* @param mode
* @param item
* @return
*/
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
Log.d(TAG, "onActionItemClicked: 点击");
switch (item.getItemId()) {
case R.id.delete:
Toast.makeText(MainActivity.this,"删除",Toast.LENGTH_SHORT).show();
break;
case R.id.rename:
Toast.makeText(MainActivity.this,"重命名",Toast.LENGTH_SHORT).show();
break;
}
return false;
}
/**
*在上下文操作模式结束时调用
* @param mode
*/
@Override
public void onDestroyActionMode(ActionMode mode) {
Log.d(TAG, "onDestroyActionMode: 销毁");
}
};
}
使用上下文模式以后,界面变成了下面这样