PopupWindow有点类似于Dialog,相同点在于都是弹出窗口,并且都可以对其进行自定义显示,并且里面的监听组件,进行相应的操作,但它与Dialog又有很大的区别,PopupWindow只是弹出窗口,不会使宿主Activity组件失去焦点,也就是说PopupWindow弹出后,你仍可以与宿主Activity进行交互,Dialog却不能做到这一点。
参考:http://blog.csdn.net/hlyjunhe/article/details/6572159   
http://www.cnblogs.com/noTice520/archive/2011/08/16/2140356.html
http://www.2cto.com/kf/201108/100378.html
http://www.cnblogs.com/noTice520/archive/2011/02/15/1955541.html

 
使用PopupWindow可实现弹出窗口效果,,其实和AlertDialog一样,也是一种对话框,两者也经常混用,但是也各有特点。下面就看看使用方法。
首先初始化一个PopupWindow,指定窗口大小参数。


PopupWindow mPop = new PopupWindow(getLayoutInflater().inflate(R.layout.window, null),
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
也可以分开写:
LayoutInflater mLayoutInflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
//自定义布局
ViewGroup menuView = (ViewGroup) mLayoutInflater.inflate(
                    R.layout.window, null, true);
PopupWindow mPop = new PopupWindow(menuView, LayoutParams.WRAP_CONTENT,
                    LayoutParams.WRAP_CONTENT, true);
当然也可以手动设置PopupWindow大小。
mPop.setContentView(menuView );//设置包含视图
mPop.setWidth(int )
mPop.setHeight(int )//设置弹出框大小

设置进场动画:
mPop.setAnimationStyle(R.style.AnimationPreview);//设置动画样式

 

mPop.setOutsideTouchable(true);//这里设置显示PopuWindow之后在外面点击是否有效。如果为false的话,那么点击PopuWindow外面并不会关闭PopuWindow。当然这里很明显只能在Touchable下才能使用。

当有mPop.setFocusable(false);的时候,说明PopuWindow不能获得焦点,即使设置设置了背景不为空也不能点击外面消失,只能由dismiss()消失,但是外面的View的事件还是可以触发,back键也可以顺利dismiss掉。当设置为popuWindow.setFocusable(true);的时候,加上下面两行设置背景代码,点击外面和Back键才会消失。

mPop.setFocusable(true);
需要顺利让PopUpWindow dimiss(即点击PopuWindow之外的地方此或者backPopuWindow会消失);PopUpWindow的背景不能为空。必须在popuWindow.showAsDropDown(v);或者其它的显示PopuWindow方法之前设置它的背景不为空:

mPop.setBackgroundDrawable(new ColorDrawable(0));



mPop.showAsDropDown(anchor, 0, 0);//设置显示PopupWindow的位置位于View的左下方,x,y表示坐标偏移量

mPop.showAtLocation(findViewById(R.id.parent), Gravity.LEFT, 0, -90);(以某个View为参考),表示弹出窗口以parent组件为参考,位于左侧,偏移-90。

mPop.setOnDismissListenerd(new PopupWindow.OnDismissListener(){})//设置窗口消失事件

注:window.xml为布局文件

总结:

1PopupWindowview布局,通过LayoutInflator获取布局的view.:

LayoutInflater inflater =(LayoutInflater)            

this.anchor.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);

View textEntryView =  inflater.inflate(R.layout.paopao_alert_dialog, null);

       

2、显示位置,可以有很多方式设置显示方式

pop.showAtLocation(findViewById(R.id.ll2), Gravity.LEFT, 0, -90);

或者

pop.showAsDropDown(View anchor, int xoff, int yoff)

 

3、进出场动画

pop.setAnimationStyle(R.style.PopupAnimation);

 

4、点击PopupWindow区域外部,PopupWindow消失

   this.window = new PopupWindow(anchor.getContext());

 

this.window.setTouchInterceptor(new OnTouchListener() {

@Override

public boolean onTouch(View v, MotionEvent event) {

if(event.getAction() ==MotionEvent.ACTION_OUTSIDE) {              

BetterPopupWindow.this.window.dismiss();

return true;

}

return false;

}

});

例子

例一:

效果:

图一:原来

点击下拉列表中的项,例如郑州大学南校门

效果图2:

点击图片,图片消失,重新回到图1

代码

private PopupWindow popupWindow;

。。。。。。

。。。。。。

list.setOnItemClickListener(new OnItemClickListener() {   
            @Override  
            public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,   
                    long arg3) {   
             openPopupwin(arg2);
            }   
        });

。。。。。。

。。。。。。

//创建  弹出窗口
 private void openPopupwin(int arg) {
  LayoutInflater mLayoutInflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
  View menuView = (View) mLayoutInflater.inflate(
    R.layout.pop_popwindow, null, true);
  imgview = (ImageView) menuView.findViewById(R.id.pop_popwindowimage);
  switch(arg)
  {
  case 0:
   imgview.setBackgroundResource(R.drawable.p_overview_pop_image1);
   break;
  case 1:
   imgview.setBackgroundResource(R.drawable.p_overview_pop_image2);
   break;
  case 2:
   imgview.setBackgroundResource(R.drawable.p_overview_pop_image3);
   break;
  case 3:
   imgview.setBackgroundResource(R.drawable.p_overview_pop_image4);
   break;
  case 4:
   imgview.setBackgroundResource(R.drawable.p_overview_pop_image5);
   break;
  case 5:
   imgview.setBackgroundResource(R.drawable.p_overview_pop_image6);
   break;
  }
  imgview.requestFocus();
  imgview.setOnClickListener(new View.OnClickListener() {
   @Override
   public void onClick(View v) {// 焦点到了gridview上,所以需要监听此处的键盘事件。否则会出现不响应键盘事件的情况
    if (popupWindow != null && popupWindow.isShowing()) {
     popupWindow.dismiss();
    }
   }
  });
  popupWindow = new PopupWindow(menuView, LayoutParams.FILL_PARENT,  
                LayoutParams.FILL_PARENT, true);
  popupWindow.setBackgroundDrawable(new BitmapDrawable());
  popupWindow.setAnimationStyle(R.style.PopupAnimation);
  popupWindow.showAtLocation(menuView, Gravity.CENTER
    | Gravity.CENTER, 0, 0);
  popupWindow.update();
 }

 pop_popwindow.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns: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="#b5555555" >
    <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@drawable/logo"
            android:id="@+id/pop_popwindowimage"
            />
</LinearLayout>

 

 

 

例子:

 

先上图

用的豌豆荚截图,本来是个动画的,每个过程都有几张,大概就是要实现这个效果,初始状态只有一个Button,当点击show的时候,另外一个页面从底部慢慢升起来,直到覆盖到上一个页面,注意这里不是启用另一个Activity,是用的PopupWindow,当点击dismiss的时候,又慢慢消失。。。这种效果看上去不错,PopupWindow上面可以添加想要添加的控件,比如ListView(注意,如果添加ListView的话,当它弹出来之后,按back键不起作用,它获取不了监听,其余的非ListView控件可以,这里添加了个Button ),下面贴出代码

这是主类MainActivity.java

package com.test.popupwindow;






import android.app.Activity;
import android.os.Bundle;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.LinearLayout.LayoutParams;
import android.widget.PopupWindow;

publicclass MainActivity extends Activity {
/** Called when the activity is first created. */

boolean flag =false;
PopupWindow popupWindow;

@Override
publicvoid onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

init();
}

publicvoid init() {
Button btn_show
= (Button) findViewById(R.id.btn_show);
LayoutInflater inflater
= LayoutInflater.from(this);
View layout
= inflater.inflate(R.layout.popup, null);
popupWindow
=new PopupWindow(layout, LayoutParams.FILL_PARENT,
LayoutParams.FILL_PARENT);
Button btn_dismiss
= (Button) layout.findViewById(R.id.btn_dismiss);
btn_dismiss.setOnClickListener(
new OnClickListener() {

@Override
publicvoid onClick(View v) {
// TODO Auto-generated method stub
openMenu();
}
});
btn_show.setOnClickListener(
new OnClickListener() {

@Override
publicvoid onClick(View v) {
// TODO Auto-generated method stub
openMenu();
}
});
}

publicvoid btn_showOnClicked() {
openMenu();
}

publicvoid btn_dismissOnClicked() {
openMenu();
}

publicvoid openMenu() {
if (!flag) {
popupWindow.setAnimationStyle(R.style.PopupAnimation);
popupWindow.showAtLocation(findViewById(R.id.btn_show), Gravity.NO_GRAVITY,
0, 0);
popupWindow.setFocusable(
true);
popupWindow.update();
flag
=true;
}
else {
popupWindow.dismiss();
popupWindow.setFocusable(
false);
flag
=false;
}
}
}

  布局文件main.xml

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





<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation
="vertical"
android:layout_width
="fill_parent"
android:layout_height
="fill_parent"
android:id
="@+id/layout"
>
<Button
android:id="@+id/btn_show"
android:layout_width
="fill_parent"
android:layout_height
="wrap_content"
android:text
="show"
/>
</RelativeLayout>

  布局文件popup.xml

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





<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation
="vertical"
android:layout_width
="fill_parent"
android:layout_height
="fill_parent"
android:background
="#cccccc"
>
<Button
android:id="@+id/btn_dismiss"
android:layout_width
="fill_parent"
android:layout_height
="wrap_content"
android:text
="dismiss"/>
</LinearLayout>

  工程结构

注意看在res文件夹下面新建了一个anim文件夹,里面要实现的动画页面,比如从哪个坐标移动到哪个坐标之类的,当然还可以定义其它的,这里只实现了Y坐标的移动

在anim文件夹下面建两个文件,一个是in.xml,另外一个是out.xml,意思一看就明白

in.xml

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






<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator
="@android:anim/decelerate_interpolator">
<translate
android:fromYDelta="854"
android:toYDelta
="0"
android:duration
="1000"/>
</set>

  它表示Y的坐标从854移动到0,时间为1秒

out.xml

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






<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:interpolator="@android:anim/decelerate_interpolator"
android:fromYDelta
="0"
android:toYDelta
="854"
android:duration
="10000"
/>
</set>

  这个不解释了。。。

另一个例子: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:我上面的代码是部分源码,如果直接复制是无法运行的

posted on 2012-08-09 15:54  清沁  阅读(14822)  评论(0编辑  收藏  举报