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 之外的地方此或者 back PopuWindow 會消失); 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:我上面的代碼是部分源碼,如果直接復制是無法運行的


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2026 CODEPRJ.COM