一、 OptionMenu
1、首先在项目目录下的res资源目录下,新建一个资源文件夹menu
(1)res目录的位置如下
(2)新建名称为menu的包
2、然后在menu的包下新建Menu Resource File资源文件
(1)文件名字自己任意填写即可,我这里写的是optionmenu
(2)然后点击ok即可,资源文件新建完成之后会出现以下xml界面
(3)此时的界面是最初的界面,然后我们开始书写菜单的界面,这里就简单的写一下菜单的选项,仅做测试学习,修改optionmenu.xml文件如下所示:
<?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"
app:showAsAction="always"/>
<item android:title="设置"
android:id="@+id/setting"/>
<item
android:title="更多" >
<menu >
<item android:title="退出"
android:id="@+id/back"/>
<item android:title="子菜单2" />
</menu>
</item>
</menu>
里面的属性我就不一一介绍了,都是一些比较基础的属性,不懂的可以自行查阅
3、将menu资源文件引入到你想要引入的Activity中,在这里我就默认引入到MainActivity中了
(1)首先将布局文件引入到MainActivity中,需要重写如下函数onCreateOptionsMenu,相信大家从英文单词也能看出来这是创建OptionMenu的意思,这里需要做的操作是利用getMenuInflater().inflate()函数将相关的menu资源引入到当前的view中,最后记得要返回true,代表我们已经完成对menu资源的引入
@Override
public boolean onCreateOptionsMenu(Menu menu) {
//将菜单资源加载到当前的菜单资源
getMenuInflater().inflate(R.menu.optionmenu,menu);
return true;
}
其实这是我们运行程序的话,我们已经能够看到菜单效果了,如下图:
但是此时并没有设置点击事件,所以我们点击菜单选项的话也不会发生响应,接下来我们就开始设置菜单选项的响应,由于是测试,这里简单使用Toast来进行测试,实际开发中只需要把Toast替换成响应的操作即可
(2)给菜单选项设置点击事件,这里我们只需要重写响应的方法即可
//菜单的点击事件
@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.back:
Toast.makeText(this, "退出", Toast.LENGTH_SHORT).show();
finish();
break;
default:super.onOptionsItemSelected(item);
}
return true;
}
这里使用item.getItemId()方法来获取当前的选项实例,然后进行相应的响应操作,最后返回true即可,这样点击事件就已经设置完成了,点击保存选项时,会出现如下效果:
其他的菜单选项的效果是一样的,这里就不展示了,到此OptionMenu的基础知识就已经讲解完毕了,下面是另外两种的菜单了,一种叫上下文菜单(ContextMenu),一种叫弹出式菜单(PopupMenu)。在开始讲解这两个菜单之前,我需要在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"
android:orientation="vertical"
tools:context=".MainActivity">
<Button
android:id="@+id/ctx_btn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="上下文菜单"/>
<Button
android:id="@+id/popup_btn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="弹出式菜单"/>
</LinearLayout>
二、ContextMenu
1、同上,先创建menu的资源文件
我这里就取名为context了,你们自行取名即可,建立资源文件的过程如上,这里就不详细讲了,建立好文件之后,将文件内容修改为如下(可自行修改,这里仅仅是作为案例讲解):
<?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>
<item android:title="返回"/>
<item android:title="退出" android:id="@+id/back"/>
</menu>
</item>
</menu>
2、在MainActivity中去加载menu资源文件以及创建点击事件
(1)首先加载menu资源文件,这里会和OptionMenu的操作不太相同,这里需要创建一个内部类,如下图:
ActionMode.Callback cb = new ActionMode.Callback() {
//处理绑定菜单
@Override
public boolean onCreateActionMode(ActionMode actionMode, Menu menu) {
getMenuInflater().inflate(R.menu.context,menu);
return true;
}
@Override
public boolean onPrepareActionMode(ActionMode actionMode, Menu menu) {
return false;
}
//处理点击事件
@Override
public boolean onActionItemClicked(ActionMode actionMode, MenuItem menuItem) {
switch (menuItem.getItemId()){
case R.id.delete:
Toast.makeText(MainActivity.this, "delete", Toast.LENGTH_SHORT).show();
break;
case R.id.back:
Toast.makeText(MainActivity.this, "back", Toast.LENGTH_SHORT).show();
break;
case R.id.rename:
Toast.makeText(MainActivity.this, "rename", Toast.LENGTH_SHORT).show();
break;
}
return true;
}
当我们在new ActionMode.Callback()对象的时候,回车,下面对应的函数就会自动生成了,并不需要我们自己书写,这里面我们主要关注的就是onCreateActionMode和onActionItemClicked这两个重载的方法,其实从他们的名字来看,相信你也能看出来它们分别是创建菜单和处理菜单的点击事件,上图中的代码,我简单处理了一下,做了几个简单的点击事件的响应,其实我们会发现,这里的加载资源文件以及处理选项的点击事件基本和OptionMenu是一样的,只不过是在不同的方法下执行的,基本的执行逻辑是一致的,或者可以说就是一样的。
3、在view的长按事件中启动上下文操作菜单模式
在这里需要说明的一点是,ContextMenu是需要长按来触发的,所以在这里绑定长按点击事件即可,代码如下:
findViewById(R.id.ctx_btn).setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View view) {
startActionMode(cb);
return false;
}
});
和我们平时使用的按钮的点击事件基本是一样的,只不过函数名多了个Long,应该是很好理解的,也是需要我们长按才能触发,接下来我们长按上下文菜单按钮,会出现如下图的效果:
可见最上部出现了我们定义的删除和重命名两个选项,同时还有一个返回的箭头,点击返回的箭头就代表取消操作,这个返回按钮是ContextMenu自动为我们生成的,我们只需知道它的作用就行了,无需过多了解,另外的就是我们自己定义的选项按钮了,因为我们已经设置了点击事件,所以当我点击删除时,会出现以下效果:
即会Toast当前的操作,这就是ContextMenu的基本内容了,我们会发现实现的逻辑和前面的OptionMenu差不多,对你们来说应该不难。
三、弹出式菜单
1、同上新建menu资源文件
这里我为了节约时间,就不新建资源文件了,直接使用ContextMenu的资源文件了,因为其实menu资源文件是可以在任意的menu中引入的,当然这个要看具体的需求,那我这里为了测试,就不在新建新的menu资源文件了,大家可以自行选择新建和使用原来的文件,这个不会影响到功能的实现。
2、加载资源文件以及处理点击事件
这个菜单的加载menu资源文件和建立点击事件比较集中在一起,所以我就一并说了,这个菜单和前两个有点区别,他是直接在按钮的点击事件中处理的
代码如下图:
//首先获取到PopupMenu按钮的实例,然后进行处理点击事件
Button popup = findViewById(R.id.popup_btn);
popup.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//实例化一个PopupMenu对象,传两个参数(Context,当前按钮的实例)
PopupMenu menu = new PopupMenu(MainActivity.this,popup);
//加载菜单资源
menu.getMenuInflater().inflate(R.menu.context, menu.getMenu());
//设置点击事件的响应
menu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem menuItem) {
switch (menuItem.getItemId()){
case R.id.delete:
Toast.makeText(MainActivity.this, "delete", Toast.LENGTH_SHORT).show();
break;
case R.id.back:
Toast.makeText(MainActivity.this, "back", Toast.LENGTH_SHORT).show();
break;
case R.id.rename:
Toast.makeText(MainActivity.this, "rename", Toast.LENGTH_SHORT).show();
break;
}
return true;
}
});
//一定要调用show()来显示弹出式菜单
menu.show();
}
});
相关的描述以及处理的步骤我已经写在代码的注释里面了,相信大家都能够看得明白,其实,这三种菜单的原理以及处理的逻辑都是基本相同的,只不过是实现方式不同而已,你只要掌握好第一个OptionMenu的话,相信下面的两个菜单也是很容易掌握的。
四、给出完整代码
1、MainActivity
package com.example.menudemo;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.ActionMode;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.PopupMenu;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//一、ContextMenu菜单:上下文菜单
//1.ContextMenu的注册
registerForContextMenu(findViewById(R.id.ctx_btn));
//2.创建
//就是重写onCreateContextMenu方法
//3.菜单项的操作:点击事件的处理
//重写onCreateOptionsMenu即可
//4.为按钮设置上下文操作模式(创建了这个模式的话,前面的几步都可以省略)
//实现ActionMode CallBack
//新建如下内部类
//在view的长按事件中启动上下文操作模式
findViewById(R.id.ctx_btn).setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View view) {
startActionMode(cb);
return false;
}
});
//二、弹出式菜单
//首先获取到PopupMenu按钮的实例,然后进行处理点击事件
Button popup = findViewById(R.id.popup_btn);
popup.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//实例化一个PopupMenu对象,传两个参数(Context,当前按钮的实例)
PopupMenu menu = new PopupMenu(MainActivity.this,popup);
//加载菜单资源
menu.getMenuInflater().inflate(R.menu.context, menu.getMenu());
//设置点击事件的响应
menu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem menuItem) {
switch (menuItem.getItemId()){
case R.id.delete:
Toast.makeText(MainActivity.this, "delete", Toast.LENGTH_SHORT).show();
break;
case R.id.back:
Toast.makeText(MainActivity.this, "back", Toast.LENGTH_SHORT).show();
break;
case R.id.rename:
Toast.makeText(MainActivity.this, "rename", Toast.LENGTH_SHORT).show();
break;
}
return true;
}
});
//一定要调用show()来显示弹出式菜单
menu.show();
}
});
}
ActionMode.Callback cb = new ActionMode.Callback() {
//处理绑定菜单
@Override
public boolean onCreateActionMode(ActionMode actionMode, Menu menu) {
getMenuInflater().inflate(R.menu.context,menu);
return true;
}
@Override
public boolean onPrepareActionMode(ActionMode actionMode, Menu menu) {
return false;
}
//处理点击事件
@Override
public boolean onActionItemClicked(ActionMode actionMode, MenuItem menuItem) {
switch (menuItem.getItemId()){
case R.id.delete:
Toast.makeText(MainActivity.this, "delete", Toast.LENGTH_SHORT).show();
break;
case R.id.back:
Toast.makeText(MainActivity.this, "back", Toast.LENGTH_SHORT).show();
break;
case R.id.rename:
Toast.makeText(MainActivity.this, "rename", Toast.LENGTH_SHORT).show();
break;
}
return true;
}
//在操作结束时被调用
@Override
public void onDestroyActionMode(ActionMode actionMode) {
Log.e("TAG", "结束!" );
}
};
// @Override
// public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
// getMenuInflater().inflate(R.menu.context,menu);
// super.onCreateContextMenu(menu, v, menuInfo);
// }
//
// @Override
// public boolean onContextItemSelected(@NonNull MenuItem item) {
// switch (item.getItemId()){
// case R.id.delete:
// Toast.makeText(this, "delete", Toast.LENGTH_SHORT).show();
// break;
// case R.id.back:
// Toast.makeText(this, "back", Toast.LENGTH_SHORT).show();
// break;
// case R.id.rename:
// Toast.makeText(this, "rename", Toast.LENGTH_SHORT).show();
// break;
// }
// return super.onContextItemSelected(item);
// }
@Override
public boolean onCreateOptionsMenu(Menu menu) {
//将菜单资源加载到当前的菜单资源
getMenuInflater().inflate(R.menu.optionmenu,menu);
return true;
}
//菜单的点击事件
@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.back:
Toast.makeText(this, "退出", Toast.LENGTH_SHORT).show();
finish();
break;
default:super.onOptionsItemSelected(item);
}
return true;
}
}
2、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"
android:orientation="vertical"
tools:context=".MainActivity">
<Button
android:id="@+id/ctx_btn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="上下文菜单"/>
<Button
android:id="@+id/popup_btn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="弹出式菜单"/>
</LinearLayout>
3、optionmenu.xml文章来源:https://www.toymoban.com/news/detail-409791.html
<?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"
app:showAsAction="always"/>
<item android:title="设置"
android:id="@+id/setting"/>
<item
android:title="更多" >
<menu >
<item android:title="退出"
android:id="@+id/back"/>
<item android:title="子菜单2" />
</menu>
</item>
</menu>
4、context.xml文章来源地址https://www.toymoban.com/news/detail-409791.html
<?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>
<item android:title="返回"/>
<item android:title="退出" android:id="@+id/back"/>
</menu>
</item>
</menu>
以上只是我个人在学习中学习到了的内容,可能我的理解会有错误和偏差,还希望各位大佬能够不吝指出我的问题所在,后面我会再次完善我的知识体系,以后也会不断分享我个人对于Android知识的理解和体会,谢谢大家!
创作不易,希望留个赞再走吧。
到了这里,关于Android三种常用菜单Menu(OptionMenu,ContextMenu,PopupMenu)的详细讲解使用(全网最详细)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!