转自:http://blog.csdn.net/longhushi/article/details/6923001
这几天说是要在Android的平板电脑上(其实不是平板电脑,是中兴的一款超大手机,7寸屏)改一个应用的主界面,原本功能菜单是通过点击手机上的Menu键实现的,但是貌似客户不满意,说是要做成类似于windows系统开始菜单的样子,一点击菜单按钮(一个Button),就弹出一个菜单窗口供选择,上网查了下,发现PopupWindow可以实现该功能。
一开始觉得挺容易,不就是建一个菜单布局文件和item布局文件,然后在程序用引用么,但是真正一做才发现了问题:
起初,我用的是listView实现的菜单
menu_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@drawable/menu">
<ListView
android:id="@+id/menulist"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
</ListView>
</LinearLayout>
menu_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/menuitem"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="15dp"
android:textSize="20sp"
android:textColor="#000000"
/>
</LinearLayout>
然后在MainActivity.java中使用:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
HashMap<String,String> map = new HashMap<String,String>();
map.put("menuItemName", "信息展示");
list.add(map);
HashMap<String,String> map2 = new HashMap<String,String>();
map2.put("menuItemName", "系统设置");
list.add(map2);
HashMap<String,String> map3 = new HashMap<String,String>();
map3.put("menuItemName", "自助更新");
list.add(map3);
HashMap<String,String> map4 = new HashMap<String,String>();
map4.put("menuItemName", "关于");
list.add(map4);
HashMap<String,String> map5 = new HashMap<String,String>();
map5.put("menuItemName", "搜索");
list.add(map5);
HashMap<String,String> map6 = new HashMap<String,String>();
map6.put("menuItemName", "退出");
list.add(map6);
HashMap<String,String> map7 = new HashMap<String,String>();
map7.put("menuItemName", "返回");
list.add(map7);
myButton = (Button)findViewById(R.id.myButton);
myButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(state == 1) {
state = 0;
pop.dismiss();
}
else if(state == 0) {
// 弹出自定义的菜单
layout = getLayoutInflater().inflate(R.layout.menu_layout, null);
menulist = (ListView)layout.findViewById(R.id.menulist);
SimpleAdapter listAdapter = new SimpleAdapter(MainActivity.this,list,R.layout.menu_item,new String[]{"menuItemName"},new int[]{R.id.menuitem});
menulist.setAdapter(listAdapter);
pop = new PopupWindow(layout, myButton.getWidth(),getWindowManager().getDefaultDisplay().getHeight()/3+40);
pop.update();
//pop.setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED);
pop.setTouchable(true);
pop.setOutsideTouchable(true);
pop.setFocusable(true);
pop.showAtLocation(layout, (Gravity.BOTTOM-myButton.getHeight())|Gravity.LEFT, 0, 2*myButton.getHeight());
state = 1;
pop.setTouchInterceptor(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_OUTSIDE) {
pop.dismiss();
return true;
}
return false;
}
});
menulist.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View arg1,
int arg2, long arg3) {
// TODO Auto-generated method stub
switch(arg2) {
case 0:
Toast.makeText(getApplicationContext(), "信息展示", Toast.LENGTH_SHORT).show();
pop.dismiss();
break;
case 1:
Toast.makeText(getApplicationContext(), "系统设置", Toast.LENGTH_SHORT).show();
pop.dismiss();
break;
case 2:
Toast.makeText(getApplicationContext(), "自动更新", Toast.LENGTH_SHORT).show();
pop.dismiss();
break;
case 3:
Toast.makeText(getApplicationContext(), "关于", Toast.LENGTH_SHORT).show();
pop.dismiss();
break;
case 4:
Toast.makeText(getApplicationContext(), "搜索", Toast.LENGTH_SHORT).show();
pop.dismiss();
break;
case 5:
Toast.makeText(getApplicationContext(), "退出", Toast.LENGTH_SHORT).show();
pop.dismiss();
break;
case 6:
Toast.makeText(getApplicationContext(), "返回", Toast.LENGTH_SHORT).show();
pop.dismiss();
break;
}
}
});
}
}
});
}
但是这样就带来一个问题,关键在于pop.setFocusable(true);这句话,一旦设置popupwindow获得了焦点,那么在点击界面中的其它元素都会没有响应,就是手机的按钮也一样(除了那个home按键),也就是说如果点开了这个菜单就关不上了,除非在点击响应Item的时候dismiss掉这个popupwindow,但是如果用户一个按钮都不点击呢?好比我们点击windows的开始菜单后,可能一个菜单项都没选,继续点击下开始按钮,这个菜单又会消失,可是在这里,如果设置popupwindow获得了焦点的话是不可能再响应Button的onclick事件的。之前在网上搜的时候也用朋友说,没必要设置pop.setFocusable(true),popupwindow上的东西本来就可以响应,我实践了发现,这句话对于普通的控件是对的,但是对于listView这种控件,则必须得到焦点才能使用。但是这句话让我想到了,可不可以不用listview来显示呢?我又看了下UCWEB的菜单,人家也是用popupwindow来实现的,可是他们在popupwindow上面排放的都是小图片,由此我想到的第二种方法:直接用TextView
不但简便,而且可以实现菜单功能:
menu_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@drawable/menu1"
android:orientation="vertical">
<TextView
android:id="@+id/information"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="15dp"
android:layout_marginTop="5dp"
android:text="信息展示"
android:textSize="20sp"
android:textColor="#000000"
/>
<TextView
android:id="@+id/system"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="15dp"
android:layout_marginTop="8dp"
android:text="系统设置"
android:textSize="20sp"
android:textColor="#000000"
/>
<TextView
android:id="@+id/autoupdate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="15dp"
android:layout_marginTop="6dp"
android:text="自动更新"
android:textSize="20sp"
android:textColor="#000000"
/>
<TextView
android:id="@+id/about"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="15dp"
android:layout_marginTop="6dp"
android:text="关于 "
android:textSize="20sp"
android:textColor="#000000"
/>
<TextView
android:id="@+id/search"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="15dp"
android:layout_marginTop="6dp"
android:text="搜索 "
android:textSize="20sp"
android:textColor="#000000"
/>
<TextView
android:id="@+id/exit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="15dp"
android:layout_marginTop="6dp"
android:text="退出 "
android:textSize="20sp"
android:textColor="#000000"
/>
</LinearLayout>
MainActivity.java:
myButton = (Button)findViewById(R.id.myButton);
myButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(state == 1) {
state = 0;
pop.dismiss();
}
else if(state == 0) {
// 弹出自定义的菜单
layout = getLayoutInflater().inflate(R.layout.menu_layout, null);
pop = new PopupWindow(layout, myButton.getWidth(),getWindowManager().getDefaultDisplay().getHeight()/3+40);
pop.showAtLocation(layout, (Gravity.BOTTOM-myButton.getHeight())|Gravity.LEFT, 0, 2*myButton.getHeight());
state = 1;
tv1 = (TextView)layout.findViewById(R.id.information);
tv2 = (TextView)layout.findViewById(R.id.system);
tv3 = (TextView)layout.findViewById(R.id.autoupdate);
tv4 = (TextView)layout.findViewById(R.id.about);
tv5 = (TextView)layout.findViewById(R.id.search);
tv6 = (TextView)layout.findViewById(R.id.exit);
tv1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Toast.makeText(getApplicationContext(), "信息展示", Toast.LENGTH_SHORT).show();
state = 0;
pop.dismiss();
}
});
tv2.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Toast.makeText(getApplicationContext(), "系统设置", Toast.LENGTH_SHORT).show();
state = 0;
pop.dismiss();
}
});
tv3.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Toast.makeText(getApplicationContext(), "自动更新", Toast.LENGTH_SHORT).show();
state = 0;
pop.dismiss();
}
});
tv4.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Toast.makeText(getApplicationContext(), "关于", Toast.LENGTH_SHORT).show();
state = 0;
pop.dismiss();
}
});
tv5.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Toast.makeText(getApplicationContext(), "搜索", Toast.LENGTH_SHORT).show();
state = 0;
pop.dismiss();
}
});
tv6.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Toast.makeText(getApplicationContext(), "退出", Toast.LENGTH_SHORT).show();
state = 0;
pop.dismiss();
}
});
}
}
});
不过我这种在布局文件中就设定TextView个数的情况,仅限于菜单项是固定的,如果不固定就不能这么用了(不过貌似手机上的菜单基本就那么几个)
PS:我上面的代码是部分源码,如果直接复制是无法运行的