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)畫。