前言
Android中提供的菜单有如下几种:
- 选项菜单OptionsMenu
- 上下文菜单ContextMenu
- 弹出菜单PopupMenu
- 创建子菜单的步骤:
- 重写Activity类的onCreateOptionsMenu()方法
- 调用Menu的addSubMenu()方法添加子菜单
- 调用SubMenu的add()方法为子菜单添加菜单项
- 重写Activity类的onOptionsItemSelected ()方法
测试样例代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
| package com.gallifrey.todayapplication.menu;
import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.view.SubMenu; import android.widget.Toast;
import com.gallifrey.todayapplication.R;
public class OptionsMenuActivity extends AppCompatActivity {
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_options_menu); }
@Override public boolean onCreateOptionsMenu(Menu menu) {
menu.add("options1"); menu.add(0,1,1,"options2"); menu.add(0,2,2,"options3"); menu.add(1,2,4,"options4"); menu.add(1,1,3,"options5");
SubMenu f=menu.addSubMenu("sub_options"); f.add("sub1"); SubMenu f2=f.addSubMenu("sub1-2"); f2.add("sub2");
return super.onCreateOptionsMenu(menu); }
@Override public boolean onPrepareOptionsMenu(Menu menu) { menu.clear(); getMenuInflater().inflate(R.menu.options_menu,menu); return super.onPrepareOptionsMenu(menu); }
@Override public boolean onOptionsItemSelected(@NonNull MenuItem item) { String str=""; switch (item.getItemId()){ case R.id.menu_open: str="menu_open"; break; case R.id.menu_close: str="menu_close"; break; default: str="NULL"; break; } Toast.makeText(this,str+" Click",Toast.LENGTH_LONG).show();
return super.onOptionsItemSelected(item); } }
|
- 在res文件夹下创建menu目录,然后建立options_meu.xml文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| <?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="File" android:icon="@mipmap/file" app:showAsAction="ifRoom"> <menu> <item android:id="@+id/menu_open" android:icon="@mipmap/open" android:title="open"/> <item android:id="@+id/menu_close" android:icon="@mipmap/close" android:title="close"/> <item android:icon="@mipmap/edit" android:title="Edit"> <menu> <item android:id="@+id/menu_cut" android:icon="@mipmap/cut" android:title="Cut"/> <item android:id="@+id/menu_copy" android:icon="@mipmap/copy" android:title="Copy"/> </menu> </item> </menu> </item> </menu>
|
- 上下文菜单是通过调用ContextMenu接口中的方法来实现
- onCreateContextMenu()方法来生成ContextMenu对象
1
| onCreateContextMenu(ContextMenu menu, View v,ContextMenu.ContextMenuInfo menuInfo)
|
- 创建上下文菜单的步骤:
- 通过registerForContextMenu()方法为ContextMenu分配一个View对象
- 通过onCreateContextMenu()创建一个上下文对象
使用XML资源生成菜单项的步骤:
- 在res目录中创建menu子目录
- 在menu子目录中创建一个Menu Resource file(XML文件)
- 使用XML文件的资源ID,在Activity中将XML文件中所定义的菜单元素添加到menu对象中
- 判断资源ID,实现相应事件处理
测试样例代码
- 上下文菜单基于View,长按显示
- 上下文菜单中,一级菜单不显示icon图标,二级菜单才显示icon图标。(一级菜单设置了图标也没有用)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| package com.gallifrey.todayapplication.menu;
import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle; import android.view.ContextMenu; import android.view.MenuItem; import android.view.SubMenu; import android.view.View; import android.widget.TextView; import android.widget.Toast;
import com.gallifrey.todayapplication.R;
public class ContextMenuActivity extends AppCompatActivity { private TextView mTvContext1,mTvContext2; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_context_menu); mTvContext1=findViewById(R.id.tv_context_menu1); mTvContext2=findViewById(R.id.tv_context_menu2);
registerForContextMenu(mTvContext1); registerForContextMenu(mTvContext2); }
@Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { super.onCreateContextMenu(menu, v, menuInfo); if(v.equals(mTvContext1)){ menu.add("context java 1"); SubMenu f=menu.addSubMenu("context java 2"); f.add("context java 21"); }else{ getMenuInflater().inflate(R.menu.context_menu,menu); } }
@Override public boolean onContextItemSelected(@NonNull MenuItem item) { String str=" "; switch (item.getItemId()){ case R.id.context_menu_cut: str="context_menu_cut"; break; case R.id.context_menu_paste: str="context_menu_paste"; break; default: return super.onContextItemSelected(item); } Toast.makeText(this,str,Toast.LENGTH_LONG).show(); return true; } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| <?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout 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=".menu.ContextMenuActivity"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" app:layout_constraintTop_toTopOf="parent" android:id="@+id/tv_context_menu1" android:text="Context1" android:gravity="center" android:textSize="30sp"/> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" app:layout_constraintTop_toBottomOf="@id/tv_context_menu1" android:id="@+id/tv_context_menu2" android:text="Context2" android:layout_marginTop="39dp" android:gravity="center" android:textSize="30sp"/> </androidx.constraintlayout.widget.ConstraintLayout>
|
- 在res文件夹下创建menu目录,然后建立context_meu.xml文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| <?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:icon="@mipmap/file" android:title="File"> </item> <item android:icon="@mipmap/edit" android:title="Edit"> <menu> <item android:id="@+id/context_menu_cut" android:title="context_cut" android:icon="@mipmap/cut"/> <item android:id="@+id/context_menu_paste" android:title="context_paste" android:icon="@mipmap/paste"/> </menu> </item> </menu>
|
PopupMenu弹出菜单
- 创建PopupMenu的实例
- 填充实例
- 设置监听
- 展示弹出菜单
测试样例代码
- 一级菜单不显示icon图标,二级菜单才显示icon图标。(一级菜单设置了图标也没有用)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| package com.gallifrey.todayapplication.menu;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle; import android.view.MenuItem; import android.view.View; import android.widget.Button; import android.widget.PopupMenu; import android.widget.Toast;
import com.gallifrey.todayapplication.R;
public class PopupMenuActivity extends AppCompatActivity { private Button mBtnPopup0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_popup_menu);
mBtnPopup0 =findViewById(R.id.btn_popup); mBtnPopup0.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { PopupMenu popupMenu=new PopupMenu(PopupMenuActivity.this,view); popupMenu.getMenuInflater().inflate(R.menu.popupo_menu,popupMenu.getMenu()); popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem menuItem) { String str=""; switch (menuItem.getItemId()){ case R.id.popup_file: str="popup_file"; break; case R.id.popup_save: str="popup_save"; break; case R.id.popup_search: str="popup_search"; break; default: return false; } Toast.makeText(PopupMenuActivity.this,str,Toast.LENGTH_LONG).show(); return true; } }); popupMenu.show(); } });
} }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| <?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout 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=".menu.PopupMenuActivity"> <Button android:layout_width="match_parent" android:layout_height="wrap_content" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent" android:id="@+id/btn_popup" android:textSize="30sp" android:text="弹出菜单" /> </androidx.constraintlayout.widget.ConstraintLayout>
|
- 在res文件夹下创建menu目录,然后建立popup_meu.xml文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| <?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/popup_file" android:icon="@mipmap/file" android:title="File"/> <item android:title="Edit" android:icon="@mipmap/edit"> <menu> <item android:id="@+id/popup_search" android:title="Search" android:icon="@mipmap/search"/> <item android:id="@+id/popup_save" android:title="Save" android:icon="@mipmap/save"/> </menu> </item> </menu>
|
- Material Design风格的导航组件
- 取代Actionbar(Toolbar可以出现屏幕任意位置,允许开发者更多定制,Actionbar只能出现在屏幕最上方且开发有限)
- 为开发者预留许多可定制修改的余地:
- 支持添加一个或多个的自定义组件
- 设置App的Logo图标
- 支持设置标题和子标题
- 设置导航栏图标
- 支持Action Menu
方法 |
功能描述 |
setTitle(int resId) |
设置标题 |
setSubtitle(int resId) |
设置子标题 |
setTitleTextColor(int color) |
设置标题字体颜色 |
setSubtitleTextColor(int color) |
设置子标题字体颜色 |
setNavigationIcon(Drawable icon) |
设置导航栏的图标 |
setLogo(Drawable drawable) |
设置Toolbar的Logo图标 |
Toolbar的使用步骤:
- 在styles.xml文件中对原主题进行修改(使用Toolbar,必须设置不支持Actionbar)
1
| <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar/>
|
1 2 3 4 5
| <androidx.appcompat.widget.Toolbar android:id="@+id/my_toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" >
|
ToolBar可以包含导航按钮、应用的Logo、标题和子标题、若干个自定义View以及动作菜单等元素
ps:Toolbar的setTitle()方法需要在setSupportActionBar()方法之前调用,否则无效
测试样例代码