Android 自定义菜单示例
转自:http://huolangge.blog.163.com/blog/static/226510048201410995533991/注:为什么我不直接在csdn上写博客,而是先在网易上写了再转载过来:
因为我是用为知笔记/wps记录实验过程的,写好之后直接就可以发到博客了,优快云 xxx的居然禁用第三方博客客户端,而复制到csdn的网页上,它不能识别图片,直接在网页上的时候又没有在本地那样快捷。但是毕竟技术文章发在csdn上比发在网易上有更多的人可以交流,所以才这么麻烦,真心希望csdn更够更人性化!!!!!
创建Android application project;
创建menu_layout.xml文件;注意必须在此文件中的根linearLayout下添加
android:gravity="bottom" 标签才能显示出来popwindow
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="bottom"
android:orientation="horizontal" >
<!-- 第一个菜单项:首页 上面是图片,下面是文字 -->
<LinearLayout
android:id="@+id/home"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:src="@drawable/home" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="首页" />
</LinearLayout>
<!-- 第二个菜单项:我的 左边是图片,右边是文字 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
</LinearLayout>
<!-- 第一个菜单项:更多 上面是图片,下面是文字 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
</LinearLayout>
</LinearLayout>
在主Activity类里监听“menu”按键的按下事件,然后动态装载menu_layout.xml文件;
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_MENU:// 按下“menu”按键的动作
Log.d("tag", "菜单按钮按下");
// 装载菜单布局文件,没有父窗口,所以第二个参数为null
layout = getLayoutInflater().inflate(R.layout.menu_layout1, null);
//创建PopupWindow对象,并指定其布局文件和其弹出的位置
popwindow =new PopupWindow(layout,getWindowManager().getDefaultDisplay().getWidth(),getWindowManager().getDefaultDisplay().getHeight());
//设置弹出窗口的位置
popwindow.showAtLocation(layout, Gravity.BOTTOM, 0,0);
return false;// 如果不返回true/false,则会继续执行super的方法
case KeyEvent.KEYCODE_BACK:// 按下“back”按键的动作
return false;// 如果不返回true/false,则会继续执行super的方法
}
// 必须调用此方法,以响应其他按键的按下事件
return super.onKeyDown(keyCode, event);
显示效果如下:

初步完成雏形,进行优化
menu_layout.xml文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="bottom"
android:orientation="horizontal" >
<!-- 第一个菜单项:首页 上面是图片,下面是文字 -->
<LinearLayout
android:id="@+id/home"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@drawable/button_normal_translucent"
android:orientation="vertical" >
<ImageView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingTop="5dp"
android:src="@drawable/home" />
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="首页" />
</LinearLayout>
<!-- 第二个菜单项:我的 左边是图片,右边是文字 -->
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@drawable/button_normal"
android:gravity="center"
android:orientation="horizontal" >
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/mine" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="我的" />
</LinearLayout>
<!-- 第一个菜单项:更多 上面是图片,下面是文字 -->
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@drawable/button_normal"
android:orientation="vertical" >
<ImageView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingTop="18dp"
android:src="@drawable/more" />
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:paddingTop="5dp"
android:text="更多" />
</LinearLayout>
</LinearLayout>
最后的效果:

这时还没有给选项添加点击事件,作为示例,给“首页”选项添加一个点击事件
// 设置弹出窗口的位置
popwindow.showAtLocation(layout, Gravity.BOTTOM, 0, 0);
// "首页"按钮的点击事件,用onClickListerner模拟
View home = layout.findViewById(R.id.home);
home.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(getApplicationContext(), "恭喜,自定义菜单点击成功", 0)
.show();
popwindow.dismiss();// 关闭弹出菜单
}
});
效果如下:点击选项之后弹出菜单就消失了

还有一个问题就是,弹出菜单之后,如果不点击选项,怎么退出弹出菜单,答案是监听back按键,这时,需要一个状态变量标志菜单是否弹出。
最后的完整代码如下:
package com.tops.custommenudemo;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.PopupWindow;
import android.widget.Toast;
public class MainActivity extends ActionBarActivity {
private View layout;
private PopupWindow popwindow;
private int state = 0;// 标志菜单是否弹出,0为没有弹出,1为弹出
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_MENU:// 按下“menu”按键的动作
// Log.d("tag", "菜单按钮按下");
if (state == 1)
return false;// 菜单已弹出,不处理
// 装载菜单布局文件,没有父窗口,所以第二个参数为null
layout = getLayoutInflater().inflate(R.layout.menu_layout1, null);
// 创建PopupWindow对象,并指定其布局文件和其弹出的位置
popwindow = new PopupWindow(layout, getWindowManager()
.getDefaultDisplay().getWidth(), getWindowManager()
.getDefaultDisplay().getHeight());
// 设置弹出窗口的位置
popwindow.showAtLocation(layout, Gravity.BOTTOM, 0, 0);
// "首页"按钮的点击事件,用onClickListerner模拟
View home = layout.findViewById(R.id.home);
home.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(getApplicationContext(), "恭喜,自定义菜单点击成功", 0)
.show();
popwindow.dismiss();// 关闭弹出菜单
state = 0;// 更改标志为未弹出菜单
}
});
state = 1;// 更改标志为已弹出菜单
return false;// 如果不返回true/false,则会继续执行super的方法
case KeyEvent.KEYCODE_BACK:// 按下“back”按键的动作
if (state == 1) {
popwindow.dismiss();
state = 0;// 更改标志为未弹出菜单
} else if (state == 0) {// 这里不能直接写else就finish(),如果有其他情况还要交给后面的系统去处理
finish();
}
return false;// 如果不返回true/false,则会继续执行super的方法
}
// 必须调用此方法,以响应其他按键的按下事件
return super.onKeyDown(keyCode, event);
}
// @Override
// public boolean onCreateOptionsMenu(Menu menu) {
// // Inflate the menu; this adds items to the action bar if it is present.
// getMenuInflater().inflate(R.menu.main, menu);
// return true;
// }
//
// @Override
// public boolean onOptionsItemSelected(MenuItem item) {
// // Handle action bar item clicks here. The action bar will
// // automatically handle clicks on the Home/Up button, so long
// // as you specify a parent activity in AndroidManifest.xml.
// int id = item.getItemId();
// if (id == R.id.action_settings) {
// return true;
// }
// return super.onOptionsItemSelected(item);
// }
}