Android使用PopupWindow创建一个简单的菜单

PopupWindow是一个弹出式窗口,它可以展示任意View。他会浮在当前窗口的上方展示。

下面看代码:

publicclassMyActivityextendsActivity
{
privatePopupWindow menu;
privateLayoutInflater inflater;
privateView layout;
@Override
publicvoidonCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//实例化PopupWindow创建菜单
initMenu();
}
//判断按键 菜单的显示与隐藏
@Override
publicbooleanonKeyDown(intkeyCode, KeyEvent event) {
if(!menu.isShowing()&&keyCode == KeyEvent.KEYCODE_MENU){
show();
}else{
menu.dismiss();
}
if(keyCode == KeyEvent.KEYCODE_BACK&&menu.isShowing()){
menu.dismiss();
}
returntrue;
}
//实例化PopupWindow创建菜单
privatevoidinitMenu(){
//获取LayoutInflater实例
inflater = (LayoutInflater)this.getSystemService(LAYOUT_INFLATER_SERVICE);
//获取弹出菜单的布局
layout = inflater.inflate(R.layout.menu,null);
//设置popupWindow的布局
menu =newPopupWindow(layout, WindowManager.LayoutParams.WRAP_CONTENT,WindowManager.LayoutParams.WRAP_CONTENT);
}
//显示菜单
privatevoidshow(){
//设置位置
menu.showAtLocation(this.findViewById(R.id.main), Gravity.BOTTOM|Gravity.CENTER_HORIZONTAL,0,0);//设置在屏幕中的显示位置
}
}

单的布局文件:


<?xmlversion="1.0"encoding="utf-8"?>
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal"
>
<ImageView
android:id="@+id/icon_1"
android:background="@drawable/icon_1"
android:layout_width="40dp"
android:layout_height="40dp"/>
<ImageView
android:id="@+id/icon_2"
android:background="@drawable/icon_2"
android:layout_width="40dp"
android:layout_height="40dp"/>
<ImageView
android:id="@+id/icon_3"
android:background="@drawable/icon3"
android:layout_width="40dp"
android:layout_height="40dp"/>
<ImageView
android:id="@+id/icon_4"
android:background="@drawable/icon4"
android:layout_width="40dp"
android:layout_height="40dp"/>
</LinearLayout>

半透明弹出框PopUpWindow

http://www.apkbus.com/android-2474-1-1.html

PopUpWindow实现半透明弹出框关键点:

  • 布局文件 最外层设置为全屏 背景颜色为半透明

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"

android:layout_width="fill_parent"

android:layout_height="fill_parent"

android:background="@color/translucent"

android:gravity="center"

android:orientation="vertical"

>

.......

<ListView

android:id="@+id/qianghaoqi_diary_pop_list"

android:divider="@null"

android:scrollingCache="false"

android:fadingEdge="none"

android:scrollbarThumbVertical="@drawable/game_blade_qianghaoqi_listview_scrollbar"

android:layout_marginBottom="@dimen/dip5"

android:layout_marginLeft="@dimen/dip5"

android:layout_marginRight="@dimen/dip10"

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:layout_gravity="center"

android:listSelector="@null"

android:paddingLeft="15.0dip"

/>

.........

</RelativeLayout>

  • new一个全屏的PopUpWindow

//必须为true,可以获取焦点

mPopWin = new PopupWindow(aPopView, LayoutParams.FILL_PARENT,LayoutParams.FILL_PARENT,true);

//mPopWin.setHeight(450);//设置PopupWindow高度

//必须设置。改变弹出窗口的背景,当然也可以设置为NULL。

mPopWin.setBackgroundDrawable(mActivity.getResources().getDrawable(R.drawable.game_blade_qianghaoqi_transparent_bg));

mPopWin.showAtLocation(aParentView,Gravity.CENTER, 0, 0);

//如果窗口已经显示过,更改此值只能在下一次显示时起作用,或者调用update()

mPopWin.update();

  • 如果PopUpWindow内的布局会夺取焦点(如示例ListView),注意代码

mListView.requestFocus();

// 焦点到了listView上,所以需要监听此处的键盘事件。否则会出现不响应键盘事件的情况

mListView.setOnKeyListener(new OnKeyListener() {

@Override

public boolean onKey(View v, int keyCode, KeyEvent event) {

if (keyCode == KeyEvent.KEYCODE_BACK) {

closePopWin();

}

return true;

}

});

  • 关闭PopUpWindow

private void closePopWin(){

if (mPopWin != null && mPopWin.isShowing()) {

mPopWin.dismiss();

}

}

  • PopUpWindow一般应用

mPopWin = new PopupWindow(mPopView, LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);

mPopWin.setBackgroundDrawable(mActivity.getResources().getDrawable(R.drawable.game_blade_qianghaoqi_transparent_bg));

mPopWin.setOutsideTouchable(true);

mPopWin.setFocusable(true);

mPopWin.showAsDropDown(aParentView,0,-15);

mPopWin.update();


0 热度 | 全文链接 #PopWin #半透明

Android之PopWindow

1.设置半透明主题
2.设置window的alpha值

  1. // WindowManager.LayoutParams lp =getWindow().getAttributes();
  2. // lp.alpha =0.5f; //0.0-1.0
  3. // getWindow().setAttributes(lp);

发现这两种都不能满足要求,起码的颜色就不太对。想做好点,做成类似alertDialog的样子,带边框,弹出窗口带动画效果,之后背景置灰,那多帅。
看到那个仿uc浏览器的源码,是用alertdialog做的,达到那种效果,加点动画就行了。下图是从那个ucweb源码里面弄出来的。



上面的代码就不贴了,我上传的项目文件里面也有。
下面是弹出popupwindow的图片,第一张是动画中,第二张是完全弹出的:






弹出popwindow的代码如下,比较乱,多包涵:

popupWindow = new PopupWindow(menuView,LayoutParams.FILL_PARENT

LayoutParams.FILL_PARENT,true);

popupWindow.showAtLocation(findViewById(R.id.parent),Gravity.CENTER

|Gravity.CENTER, 0, 0);

popupWindow.setAnimationStyle(R.style.PopupAnimation);

//加上下面两行可以用back键关闭popupwindow,否则必须调用dismiss();

ColorDrawable dw = new ColorDrawable(-00000);

popupWindow.setBackgroundDrawable(dw);

popupWindow.update();


下面是实现步骤:
1。背景置灰:
popupWindow =new PopupWindow(menuView,LayoutParams.FILL_PARENT,LayoutParams.FILL_PARENT, true);
第二三个参数必须是LayoutParams.FILL_PARENT,这样才能填充整个屏幕,达到背景置灰的目的。
整个popupwindow里面是一个GridView,图片什么的也是用的那个仿UC浏览器界面项目的,在此谢谢了。
关键的东西都在xml里面。

<?xml version="1.0"encoding="utf-8"?>

<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"

android:orientation="vertical"android:layout_width="fill_parent"

android:gravity="center"android:layout_height="fill_parent"

android:layout_gravity="center"android:background="#b0000000" >

<LinearLayoutandroid:orientation="vertical"

android:layout_width="wrap_content"android:gravity="center"

android:layout_height="wrap_content"android:layout_gravity="center"

android:background="@drawable/downbutton_corner">

<GridViewandroid:id="@+id/gridview"android:layout_width="wrap_content"

android:layout_height="wrap_content"android:numColumns="4"

android:verticalSpacing="5dip"android:horizontalSpacing="5dip"

android:stretchMode="columnWidth"android:gravity="center"

android:layout_gravity="center"/></LinearLayout></LinearLayout>


第一个linearlayout里面的android:background="#b0000000",就是全屏背景,网上搜的好多半透明都是“#e0000000”,我觉得那颜色太深,“#b0000000”更合适。
第二个linearlayout是popupwind的背景,里面的android:background="@drawable/downbutton_corner"是关键,边框,圆角都是里面定义的。

2。popupwindow的边框,圆角背景。downbutton_corne.xml

<shapexmlns:android="http://schemas.android.com/apk/res/android"

android:shape="rectangle">

<gradientandroid:startColor="#c0000000"android:endColor="#c0000000"

android:angle="90" /><!--背景颜色渐变-->

<strokeandroid:dashWidth="2dp" android:dashGap="2dp"

android:width="2dp"android:color="#FF00ff00"></stroke>

<!--描边-->

<cornersandroid:bottomRightRadius="5dp"

android:bottomLeftRadius="5dp"android:topLeftRadius="5dp"

android:topRightRadius="5dp"/><!--设置圆角-->

</shape>


这个涉及到shape画图,要是不懂的话。网上很多资料,搜一下就是了。我博客里面也有,http://blog.csdn.net/ymdcr/archive/2010/12/01/6048256.aspx
<gradient android:startColor="#c0000000"android:endColor="#c0000000" android:angle="90"/><!--背景颜色渐变 -->
我就设置了一个固定的颜色"#c0000000"。android:angle="90"这个是设置颜色渐变方向,从上到下啊,从左到右啊,貌似只能90的倍数,也只有四个方向嘛。
<stroke></stroke>,边框就是这个实现的。
dashWidth指的是边线的宽度 dashGap 指的是每条线之间的间距,(因为是边线是很多小横线组成的)。

3。淡入淡出动画
popupWindow.setAnimationStyle(R.style.PopupAnimation);

这条代码是设置style的,动画文件就是在style文件里面引入的。下面是淡入的动画,动画教程网上也很多。淡出的动画就这些参数值交换位置就是了。android:duration这个是持续时间,为了截图,我把它弄成5秒了。

<setxmlns:android="http://schemas.android.com/apk/res/android">

<scaleandroid:fromXScale="0.6" android:toXScale="1.0"

android:fromYScale="0.6" android:toYScale="1.0"android:pivotX="50%"

android:pivotY="50%" android:duration="5000"/>

<alphaandroid:interpolator="@android:anim/decelerate_interpolator"

android:fromAlpha="0.0" android:toAlpha="1.0"android:duration="5000" />

</set>



大概就是这些了。

还有一个关键的问题。弹出pop之后,back键无效了,必须在pop里面设置事件dismiss掉。下面是问题的描述,哪位解决了,告诉我一下,谢谢。我的邮箱:
问题解决了,是因为没设置背景的原因。
popupWindow.setBackgroundDrawable(new BitmapDrawable());
//把这一行放在showAtLocation前面就行了,以前是放在后面的,粗心了。
popupWindow.showAtLocation(findViewById(R.id.parent),Gravity.CENTER
|Gravity.CENTER, 0,0);
网上也有很多人说,弹出pop之后,不响应键盘事件了,这个其实是焦点在pop里面的view去了。
以这个为例,焦点就在gridview上面去了。28楼的兄弟提示的,谢了。

在gridview加上setOnKeyListener,就能解决。

menuGrid.setOnKeyListener(newOnKeyListener() {

@Override

publicboolean onKey(View v, int keyCode, KeyEvent event){

switch(keyCode) {

caseKeyEvent.KEYCODE_MENU:

if(popupWindow != null &&popupwindows.isShowing()) {

popupWindow.dismiss();

System.out.println("menuGridfdsfdsfdfd");

}

break;

}

returntrue;

}

});



---------------------------------------------------------------------------------

使用PopupWindow来做自定义menu,往PopupWindow增加一个子View,子View的布局就是menu的布局。

出现和退出的动画:可以给PopUpWindow或它的子view添加。

网上所有用PopupWindow做的menu有个共同特点:就是点击menu键出现PopupWindow,然后再点击menu键无法使PopupWindow退出/dismiss()。

当给PopupWindow设置了setFocusable(true),menu显示后,点击menu其他任何地方,menu都会消失,但是这时候按钮的点击事件其实是不响应的。同时只响应键盘的返回键,其他按键均不响应,比如点击menu键,没有任何反应。

要解决这个问题很简单,就是给PopupWindow的子View设置下面的代码:

[java] view plain copy
  1. //sub_view是PopupWindow的子View
  2. sub_view.setFocusableInTouchMode(true);
  3. sub_view.setOnKeyListener(newOnKeyListener(){
  4. @Override
  5. publicbooleanonKey(Viewv,intkeyCode,KeyEventevent){
  6. //TODOAuto-generatedmethodstub
  7. if((keyCode==KeyEvent.KEYCODE_MENU)&&(mPopupWindow.isShowing())){
  8. mPopupWindow.dismiss();//这里写明模拟menu的PopupWindow退出就行
  9. returntrue;
  10. }
  11. returnfalse;
  12. }
  13. });


记住,一定要给PopupWindow设置setFocusable(true),要不然点击menu其他地方以及返回键,menu都不会退出。且这时候是响应PopupWindow的parent的menu事件的。

下面阐述为什么这么写之后,当PopupWindow显示后,点击menu键PopupWindow会退出的原因:

首先得明白为什么给PopupWindow setFocusable(true)后,点击menu出现PopupWindow后再点击menu没反应的原因。

PopupWindow初始化的时候一般都指定了在哪个View上出现,我们称这个View为parent。parent里面写了点击menu出现PopupWindow的事件,如果给PopupWindow setFocusable(true),此时屏幕的焦点在PopupWindow上面,肯定是不会响应parent的按键事件的,它只会响应PopupWindow的按键事件。

但是PopupWindow的本质是Window,没有继承View类,自己没有onkeyDown或onkey或dispatchKey这些事件的。我刚开始试着实现这些接口,但是按键依然不响应,不知原因。因现在对按键的原理还不熟,无法阐述其原因。

然后我想绕道而行,就是给PopupWindow的子View注册按键事件,setKeyListener,刚开始我在子View的xml设置了android:focusable=”true” 但按键事件依然不响应。。。。纠结啊纠结。。。然后没得办法,我google了所有关于PopupWindow的文章。。。最后终于被我发现。。。需要给PopupWindow的子View 设置setFocusableInTouchMode(true)。这时候按键事件就响应了。。。

下面附上完整代码:

[java] view plain copy
  1. /*必须重写,否则点击MENU无反应为了让他不显示,下面onMenuOpened()必须返回false*/
  2. @Override
  3. publicbooleanonCreateOptionsMenu(Menumenu){
  4. menu.add("menu");//必须创建一项
  5. returnsuper.onCreateOptionsMenu(menu);
  6. }
  7. /**
  8. *拦截MENU
  9. */
  10. @Override
  11. publicbooleanonMenuOpened(intfeatureId,Menumenu){
  12. if(mPopupWindow!=null){
  13. if(!mPopupWindow.isShowing()){
  14. /*最重要的一步:弹出显示在指定的位置(parent)最后两个参数是相对于x/y轴的坐标*/
  15. mPopupWindow.showAtLocation(findViewById(R.id.linear_menu_parent),Gravity.BOTTOM,0,0);
  16. }
  17. }
  18. returnfalse;//返回为true则显示系统menu
  19. }
  20. privatevoidinitPopuWindow(intmenuViewID){
  21. LayoutInflatermLayoutInflater=(LayoutInflater)getSystemService(LAYOUT_INFLATER_SERVICE);
  22. /*设置显示menu布局view子VIEW*/
  23. sub_view=mLayoutInflater.inflate(menuViewID,null);
  24. /*第一个参数弹出显示view后两个是窗口大小*/
  25. mPopupWindow=newPopupWindow(sub_view,LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT);
  26. /*设置背景显示*/
  27. mPopupWindow.setBackgroundDrawable(getResources().getDrawable(R.drawable.bg_menu_popup));
  28. /*设置触摸外面时消失*/
  29. mPopupWindow.setOutsideTouchable(true);
  30. /*设置系统动画*/
  31. mPopupWindow.setAnimationStyle(android.R.style.Animation_Dialog);
  32. mPopupWindow.update();
  33. mPopupWindow.setTouchable(true);
  34. /*设置点击menu以外其他地方以及返回键退出*/
  35. mPopupWindow.setFocusable(true);
  36. /**1.解决再次点击MENU键无反应问题
  37. *2.sub_view是PopupWindow的子View
  38. */
  39. sub_view.setFocusableInTouchMode(true);
  40. sub_view.setOnKeyListener(newOnKeyListener(){
  41. @Override
  42. publicbooleanonKey(Viewv,intkeyCode,KeyEventevent){
  43. //TODOAuto-generatedmethodstub
  44. if((keyCode==KeyEvent.KEYCODE_MENU)&&(mPopupWindow.isShowing())){
  45. mPopupWindow.dismiss();//这里写明模拟menu的PopupWindow退出就行
  46. returntrue;
  47. }
  48. returnfalse;
  49. }
  50. });
  51. /*监听MENU事件*/
  52. menu=newView[3];
  53. menu[0]=sub_view.findViewById(R.id.menu_0);
  54. menu[1]=sub_view.findViewById(R.id.menu_1);
  55. menu[2]=sub_view.findViewById(R.id.menu_2);
  56. menu[0].setOnClickListener(newOnClickListener(){
  57. @Override
  58. publicvoidonClick(Viewv){
  59. //doSomething
  60. }
  61. });
  62. menu[1].setOnClickListener(newOnClickListener(){
  63. @Override
  64. publicvoidonClick(Viewv){
  65. //doSomething
  66. }
  67. });
  68. menu[2].setOnClickListener(newOnClickListener(){
  69. @Override
  70. publicvoidonClick(Viewv){
  71. //doSomething
  72. }
  73. });
  74. }

更多相关文章

  1. button imageButton 背景透明
  2. Android(安卓)Studio 时间选择器创建
  3. Android(安卓)升级到android studio 2.2项目死活run不起来
  4. Android中的eventBus传值
  5. android 上层应用如何监听 sdcard的插拔事件
  6. Android(安卓)事件分发机制
  7. android canvas实现在图片上画图
  8. android4.4 Launcher主菜单界面同样采用背景图片的方式
  9. Android(安卓)EditText截获与监听输入事件

随机推荐

  1. android 在google商店里搜索不到的问题
  2. android 计算器(2)
  3. android studio 程序员有福了—从layout
  4. 设置 listview 滚动条样式
  5. android 开发实现静默安装
  6. android 自定义progressbar进度条颜色
  7. Andriod开发必备资料
  8. AndroidShortcuts
  9. Android中的Adapter
  10. Android之 系统启动流程