• PopupWindow


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

  • 相关阅读:
    zookeeper学习笔记
    wsl笔记
    SSDB数据库笔记
    spring笔记
    redis笔记
    openresty配置
    openresty安装笔记
    mybatis笔记
    nginx配置
    STM32F373(青风)+CUBEMX快速上手
  • 原文地址:https://www.cnblogs.com/qingblog/p/2630414.html
Copyright © 2020-2023  润新知