鍍金池/ 教程/ Android/ 第二十二章-PopupWindow浮動(dòng)窗
第十八章-ViewPager+FragmentStatePagerAdapter實(shí)現(xiàn)仿微信Tab
第十五章-GridView實(shí)現(xiàn)動(dòng)態(tài)添加和刪除子項(xiàng)
第九章-進(jìn)度條ProgressBar
第十二章-經(jīng)典的ListView
第十四章-GridView控件
第八章-時(shí)間相關(guān)控件
第七章-下拉框Spinner控件
第二章-EditText探秘
第二十章-Android菜單之上下文菜單
第十一章-各種對(duì)話框Dialog集錦
第二十一章-Android菜單之子菜單
第六章-切換類TextSwitcher和ImageSwitcher
第十七章-ViewPager切換界面
第五章-開關(guān)按鈕ToggleButton和Switch
第二十二章-PopupWindow浮動(dòng)窗
第十六章-幻燈片ViewFlipper
第二十四章-RecyclerView動(dòng)態(tài)添加、刪除及點(diǎn)擊事件
第三章-交互之王Button控件
第二十三章-全新控件RecyclerView
第一章-好玩的TextView
第十三章-ListView擴(kuò)展(多選、全選、反選)
第四章-玩轉(zhuǎn)單選和多選按鈕
第十章-可以拖動(dòng)的ProgressBar-SeekBar
第十九章-Android菜單之選項(xiàng)菜單

第二十二章-PopupWindow浮動(dòng)窗

PopupWindow的官方定義如下:

A popup window that can be used to display an arbitrary view. The popup window is a floating container that appears on top of the current activity.

也就是說它是一個(gè)浮動(dòng)在當(dāng)前界面上方并且可以顯示在任意位置的View,前面的章節(jié)我們學(xué)習(xí)了彈出框,各式各樣的,那么PopupWindow應(yīng)該有兩點(diǎn)和彈出框不同,一是PopupWindow必須指定寬高屬性,而彈出框則不是必須指定;二是PopupWindow必須指定其布局文件。下面總結(jié)一下常用方法:

http://wiki.jikexueyuan.com/project/twenty-four-Scriptures/images/22-1.png" alt="這里寫圖片描述" />

由上面方法可以看出,PopupWindow共有兩種彈出方式,一種在某控件的下方,一種在父控件的任意方向,彈出位置可以任意設(shè)定,十分靈活。 首先通過一個(gè)實(shí)例熟悉一下PopupWindow的用法,這里采用showAtLocation方法彈出PopupWindow。 主布局文件代碼(activity_main.xml)

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:textSize="20sp"
        android:onClick="test"
        android:layout_centerInParent="true"
        android:text="PopupWindowTest" />
</RelativeLayout>

定義了一個(gè)Button控件,設(shè)置了其onClick屬性用于單擊事件監(jiān)聽。 PopupWindow布局文件代碼(popupwindow_layout.xml)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="#ffffff"
    android:orientation="vertical"
    android:paddingBottom="1dp">
    <View
        android:layout_width="match_parent"
        android:layout_height="2dp"
        android:background="#10a324"
        android:layout_alignParentTop="true"/>
    <TextView
        android:id="@+id/tv_exit"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        style="@style/text_style"
        android:text="退出"/>
    <View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="#d4d2d2"/>
    <TextView
        android:id="@+id/tv_set"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        style="@style/text_style"
        android:text="設(shè)置"/>
    <View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="#d4d2d2"/>
    <TextView
        android:id="@+id/tv_cancel"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        style="@style/text_style"
        android:text="取消"/>
</LinearLayout>

這里TextView引入了樣式,樣式表如下:

<style name="text_style">
    <item name="android:paddingTop">5dp</item>
    <item name="android:paddingBottom">5dp</item>
    <item name="android:gravity">center</item>
    <item name="android:textColor">#10a324</item>
</style>

一些共用的屬性可以提取出來做成樣式表,方便后期維護(hù),每一個(gè)屬性由一個(gè)item標(biāo)簽包裹。

MainActivity代碼(MainActivity.java)

public class MainActivity extends Activity implements View.OnClickListener {
    private PopupWindow popupWindow;
    private TextView tvExit,tvSet,tvCancel;
    private View rootView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
    private void showPopup() {
        View view = LayoutInflater.from(this).inflate(R.layout.popupwindow_layout,null);//PopupWindow對(duì)象
        popupWindow=new PopupWindow(this);//初始化PopupWindow對(duì)象
        popupWindow.setContentView(view);//設(shè)置PopupWindow布局文件
        popupWindow.setWidth(ViewGroup.LayoutParams.MATCH_PARENT);//設(shè)置PopupWindow寬
        popupWindow.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);//設(shè)置PopupWindow高
        rootView =LayoutInflater.from(this).inflate(R.layout.activity_main, null);//父布局
        popupWindow.showAtLocation(rootView, Gravity.BOTTOM,0,0);
        popupWindow.setOutsideTouchable(true);
        tvSet=(TextView)view.findViewById(R.id.tv_set);
        tvCancel=(TextView)view.findViewById(R.id.tv_cancel);
        tvExit=(TextView)view.findViewById(R.id.tv_exit);//在view對(duì)象中通過findViewById找到TextView控件
        tvSet.setOnClickListener(this);//注冊(cè)點(diǎn)擊監(jiān)聽
        tvCancel.setOnClickListener(this);//注冊(cè)點(diǎn)擊監(jiān)聽
        tvExit.setOnClickListener(this);//注冊(cè)點(diǎn)擊監(jiān)聽
        popupWindow.setOnDismissListener(new PopupWindow.OnDismissListener() {
            @Override
            public void onDismiss() {
                Toast.makeText(MainActivity.this,"PupWindow消失了!",Toast.LENGTH_SHORT).show();
            }
        });
    }
    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.tv_cancel:
                popupWindow.dismiss();//關(guān)閉PopupWindow
                break;
            case R.id.tv_exit:
                finish();//調(diào)用Activity的finish方法退出應(yīng)用程序
                break;
            case R.id.tv_set:
                Toast.makeText(this,"設(shè)置",Toast.LENGTH_SHORT).show();
                popupWindow.dismiss();
                break;
        }
    }
    public void test(View view){
        if(popupWindow==null) {
            showPopup();
        }else{
            popupWindow.showAtLocation(rootView, Gravity.BOTTOM,0,0);//設(shè)置PopupWindow的彈出位置。
        }
    }
}

在按鈕的單擊響應(yīng)事件test中判斷在沒有初始化時(shí)調(diào)用showPopup方法, 否則調(diào)用showAtLocation彈出PopupWindow,這個(gè)方法需要傳入四個(gè)參數(shù),第一個(gè)是父布局對(duì)象,第二個(gè)是彈出位置,第三個(gè)是關(guān)于x軸偏移量,第四個(gè)是關(guān)于y軸偏移量。

ShowPopup方法首先獲取到了PopupWindow的布局文件,初始化了一個(gè)PopupWindow對(duì)象,使用該對(duì)象調(diào)用setWidth方法設(shè)置寬度,調(diào)用setHeight方法設(shè)置高度。然后調(diào)用showAtLocation方法顯示出PopupWindow,通過findViewById的方法獲取PopupWindow中的每個(gè)控件,方便注冊(cè)單擊監(jiān)聽,進(jìn)行邏輯事件的處理。

最后設(shè)置了使用setOnDismissListener方法對(duì)PopupWindow 進(jìn)行了消失事件監(jiān)聽。 運(yùn)行實(shí)例如下:

http://wiki.jikexueyuan.com/project/twenty-four-Scriptures/images/22-2.png" alt="這里寫圖片描述" /> http://wiki.jikexueyuan.com/project/twenty-four-Scriptures/images/22-3.png" alt="這里寫圖片描述" />

點(diǎn)擊按鈕會(huì)在主界面正下方彈出popupWindow,點(diǎn)擊設(shè)置按鈕popupWindow消失,并觸發(fā)消失事件監(jiān)聽。

用過微信的朋友都會(huì)熟悉如下的界面,這個(gè)效果同樣也可以用popupWindow模擬實(shí)現(xiàn)。

http://wiki.jikexueyuan.com/project/twenty-four-Scriptures/images/22-4.png" alt="這里寫圖片描述" />

主布局文件代碼(activity_main.xml)

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <ImageView
        android:id="@+id/iv_add"
        android:layout_width="40dp"
        android:layout_height="40dp"
        android:layout_alignParentRight="true"
        android:padding="10dp"
        android:src="@drawable/add" />
</RelativeLayout>

主布局文件引入了一個(gè)ImageView,設(shè)置了layout_alignParentRight屬性為true,將控件顯示在主布局右方,設(shè)置src屬性選擇圖片源。 popupWindow布局文件代碼(pop_layout.xml)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#24a943"
    android:orientation="vertical">

    <LinearLayout
        android:id="@+id/ll_pic"
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:orientation="horizontal">
        <ImageView
            android:layout_width="35dp"
            android:layout_height="35dp"
            android:padding="5dp"
            android:src="@drawable/pic" />
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="35dp"
            android:gravity="center"
            android:paddingLeft="20dp"
            android:paddingRight="40dp"
            android:text="圖片" />
    </LinearLayout>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:orientation="horizontal">
        <ImageView
            android:layout_width="35dp"
            android:layout_height="35dp"
            android:padding="5dp"
            android:src="@drawable/location" />
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="35dp"
            android:gravity="center"
            android:paddingLeft="20dp"
            android:paddingRight="40dp"
            android:text="GPS" />
    </LinearLayout>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:orientation="horizontal">
        <ImageView
            android:layout_width="35dp"
            android:layout_height="35dp"
            android:padding="5dp"
            android:src="@drawable/music" />
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="35dp"
            android:gravity="center"
            android:paddingLeft="20dp"
            android:paddingRight="40dp"
            android:text="音樂" />
    </LinearLayout>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:orientation="horizontal">
        <ImageView
            android:layout_width="35dp"
            android:layout_height="35dp"
            android:padding="5dp"
            android:src="@drawable/wifi" />
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="35dp"
            android:gravity="center"
            android:paddingLeft="20dp"
            android:paddingRight="40dp"
            android:text="WIFI" />
    </LinearLayout>
</LinearLayout>

這里設(shè)置了四個(gè)LinearLayout控件,并設(shè)置其orientation屬性為horizontal,每個(gè)LinearLayout中添加了一個(gè)ImageView和一個(gè)TextView。

因?yàn)檫@里為popupWindow添加了動(dòng)畫,所以下面看一下兩個(gè)動(dòng)畫文件:

popupWindow消失動(dòng)畫(anim_dismiss.xml)

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >
    <translate
        android:duration="@android:integer/config_shortAnimTime"
        android:fromXDelta="0"
        android:fromYDelta="0"
        android:interpolator="@android:anim/accelerate_decelerate_interpolator"
        android:toXDelta="0"
        android:toYDelta="100%p" />
</set>

通過interpolator設(shè)置了內(nèi)置的動(dòng)畫插值器用于動(dòng)畫加速。 popupWindow顯示動(dòng)畫(anim_show.xml)

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:duration="@android:integer/config_shortAnimTime"
        android:fromXDelta="0"
        android:fromYDelta="100%p"
        android:interpolator="@android:anim/accelerate_decelerate_interpolator"
        android:toXDelta="0"
        android:toYDelta="0"/>
</set>

設(shè)置了duration屬性,選擇內(nèi)置的時(shí)間值:config_shortAnimTime=200ms。 PopupWindow設(shè)置動(dòng)畫調(diào)用setAnimationStyle方法需要傳入style樣式,因此定義如下樣式表:

樣式表代碼(styles.xml)

<style name="popupAnim" parent="@android:style/Animation.Activity">
    <item name="android:windowEnterAnimation">@anim/anim_show</item>
    <item name="android:windowExitAnimation">@anim/anim_dismiss</item>
</style>

設(shè)置了windowEnterAnimation(窗口進(jìn)入動(dòng)畫)和windowExitAnimation(窗口消失動(dòng)畫)屬性,其值分別對(duì)應(yīng)顯示和消失動(dòng)畫。

MainActivity.java代碼(MainActivity.java)

public class MainActivity extends AppCompatActivity {
    private ImageView imageView;
    private  PopupWindow popupWindow;
    private LinearLayout linearLayoutPic;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        imageView=(ImageView)findViewById(R.id.iv_add);
        imageView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                addAnimation();
                if(popupWindow==null){
                    showPopupWindow();
                }else if(popupWindow.isShowing()){
                    popupWindow.dismiss();
                }
                else{
                    popupWindow.showAsDropDown(imageView,-300,0);
                }
            }
        });
    }
    private void addAnimation() {//加入了旋轉(zhuǎn)動(dòng)畫
        RotateAnimation rotateAnimation=new RotateAnimation(0,360, Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF,0.5f);
        rotateAnimation.setDuration(500);//設(shè)置動(dòng)畫時(shí)間   
        imageView.setAnimation(rotateAnimation);//設(shè)置動(dòng)畫
        imageView.startAnimation(rotateAnimation);//開始動(dòng)畫
    }
    private void showPopupWindow() {
        View view= LayoutInflater.from(this).inflate(R.layout.pop_layout,null);//獲取popupWindow子布局對(duì)象
        popupWindow =new PopupWindow(view, ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT,false);//初始化
        popupWindow.showAsDropDown(imageView,-300,0);//在ImageView控件下方彈出
        popupWindow.setAnimationStyle(R.style.popupAnim);//設(shè)置動(dòng)畫
        linearLayoutPic=(LinearLayout)view.findViewById(R.id.ll_pic);
        linearLayoutPic.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(MainActivity.this, "單擊了圖片按鈕!", Toast.LENGTH_SHORT).show();
                popupWindow.dismiss();
            }
        });
    }
}

為了提供用戶體驗(yàn),這里對(duì)ImageView圖片也設(shè)置了旋轉(zhuǎn)動(dòng)畫,每次點(diǎn)擊圖片顯示出popupWindow時(shí)同樣ImageView也會(huì)進(jìn)行旋轉(zhuǎn)。調(diào)用showAsDropDown方法在ImageView下方顯示出popupWindow,并調(diào)用了setAnimationStyle為popupWindow設(shè)置了消失和顯示時(shí)的動(dòng)畫,這個(gè)方法需要傳入一個(gè)樣式表。

運(yùn)行項(xiàng)目實(shí)例如下:

http://wiki.jikexueyuan.com/project/twenty-four-Scriptures/images/22-5.png" alt="這里寫圖片描述" /> http://wiki.jikexueyuan.com/project/twenty-four-Scriptures/images/22-6.png" alt="這里寫圖片描述" />

通過快速截圖可以看出,popupWindow通過動(dòng)畫從下方彈出,并且ImgeView也有了旋轉(zhuǎn)動(dòng)畫。