项目中经常会使用到popupwindow做菜单选项,这个类在使用中有一些经常被遗忘的细节,今天用一个实例来总结一个popupwindow较常用的用法。
效果图:
MainActivity.java:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
| public class MainActivity extends Activity { private ImageButton ibOperationMore; List<Map<String, String>> moreList; private PopupWindow pwMyPopWindow; private ListView lvPopupList; private int NUM_OF_VISIBLE_LIST_ROWS = 3; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); iniData(); iniPopupWindow(); ibOperationMore = (ImageButton) findViewById(R.id.ib_operate_more); ibOperationMore.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if (pwMyPopWindow.isShowing()) { pwMyPopWindow.dismiss(); } else { pwMyPopWindow.showAsDropDown(ibOperationMore); } } }); } private void iniData() { moreList = new ArrayList<Map<String, String>>(); Map<String, String> map; map = new HashMap<String, String>(); map.put("share_key", "复制"); moreList.add(map); map = new HashMap<String, String>(); map.put("share_key", "删除"); moreList.add(map); map = new HashMap<String, String>(); map.put("share_key", "修改"); moreList.add(map); } private void iniPopupWindow() { LayoutInflater inflater = (LayoutInflater) this .getSystemService(LAYOUT_INFLATER_SERVICE); View layout = inflater.inflate(R.layout.task_detail_popupwindow, null); lvPopupList = (ListView) layout.findViewById(R.id.lv_popup_list); pwMyPopWindow = new PopupWindow(layout); pwMyPopWindow.setFocusable(true); lvPopupList.setAdapter(new SimpleAdapter(MainActivity.this, moreList, R.layout.list_item_popupwindow, new String[] { "share_key" }, new int[] { R.id.tv_list_item })); lvPopupList.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Toast.makeText(MainActivity.this, moreList.get(position).get("share_key"), Toast.LENGTH_LONG).show(); } }); lvPopupList.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED); pwMyPopWindow.setWidth(lvPopupList.getMeasuredWidth()); pwMyPopWindow.setHeight((lvPopupList.getMeasuredHeight() + 20) * NUM_OF_VISIBLE_LIST_ROWS); pwMyPopWindow.setBackgroundDrawable(this.getResources().getDrawable( R.drawable.bg_popupwindow)); pwMyPopWindow.setOutsideTouchable(true); } }
|
activity_main.xml:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity" android:background="#ffffff" > <LinearLayout android:id="@+id/ll_head_bar" style="@style/header_linear_layout" android:layout_alignParentTop="true" > <Button android:id="@+id/btn_back" style="@style/header_button_back" android:layout_marginLeft="8dip" /> <TextView style="@style/header_text_view" android:visibility="invisible" /> <ImageButton android:id="@+id/ib_operate_more" style="@style/header_button_operate" android:layout_marginLeft="8dip" android:layout_marginRight="10dip" android:src="@drawable/ico_headbar_more" /> </LinearLayout> </RelativeLayout>
|
list_item_popupwindow.xml:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| <?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:gravity="center" android:orientation="vertical" > <TextView android:id="@+id/tv_list_item" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" android:minHeight="40dp" android:minWidth="120dp" android:textSize="20sp" android:textColor="@color/popupwindow_list_item_text_selector" /> </LinearLayout>
|
task_detail_popupwindow.xml:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" >" <ListView android:id="@+id/lv_popup_list" android:layout_width="wrap_content" android:layout_height="wrap_content" android:listSelector="#00000000" android:divider="@drawable/ico_list_item_line_popupwindow" android:focusableInTouchMode="true" /> </LinearLayout>
|
注意:如果你想让自己的popupwindow在Activity启动的时候就显示的话,不能放在onCreate方法中,因为这个时候,界面组件还未加载好,所以会提示你你的Activity是否已经启动了,你可以放在onAttachedToWindow方法中。
关于显示的位置还有一个方法showAtLocation(parent, gravity, x, y)
这里的参数parent指的是这个popupwindow相对的是哪个父类,比如你想要让这个popupwindow相对于整个屏幕那么你的parent可以是View parent = this.getWindow().getDecorView();
parent.getHeight()
得到的值是你的屏幕的高度(像素)。
这个时候,x,y就是它在这个parent中的相对位置了。Gravity默认是左上Left,Top
例如:下面的代码设置了popupwindow在屏幕的左下角的位置。
1 2
| View parent = this.getWindow().getDecorView(); pwMyPopWindow.showAtLocation(parent, Gravity.NO_GRAVITY, (int)(parent.getWidth()/18), parent.getHeight() - btnAddTask.getHeight() - (int)(parent.getHeight()/9));
|
还有一些style,color之类的属性这里就不贴出来了。
项目地址:
https://github.com/michaelye/PopupwindowDemo.git
PopupWindow的位置按照有无偏移分,可以分为偏移和无偏移两种;按照参照物的不同,可以分为相对于某个控件(Anchor锚)和相对于父控件。具体如下
- showAsDropDown(View anchor):相对某个控件的位置(正左下方),无偏移
- showAsDropDown(View anchor, int xoff, int yoff):相对某个控件的位置,有偏移
- showAtLocation(View parent, int gravity, int x, int y):相对于父控件的位置(例如正中央Gravity.CENTER,下方Gravity.BOTTOM等),可以设置偏移或无偏移
常用方法:
popupWindow.setAnimationStyle(R.style.PopMenuAnimation); //设置popwindow出现和消失动画
popupWindow.setFocusable(true); //获取popwindow焦点
popupWindow.setOutsideTouchable(true); //设置popwindow如果点击外面区域,便关闭。
参考:
Android中的PopupWindow详解
Android-自定义PopupWindow
Android中PopupWindow的用法(位置、动画、焦点)
在Android中有很多级别的Window,不同级别的Window按照z-index方向分布。下面看看Android控件(view)PopupWindow的用法(位置、动画、焦点)。
1、创建PopouWindow及相关参数设置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| private PopupWindow makePopupWindow(Context cx) { PopupWindow window; window = new PopupWindow(cx); TextView contentView = new TextView(cx); contentView.setGravity(Gravity.CENTER); final Resources res = cx.getResources(); contentView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); window.setAnimationStyle(R.style.AnimationFade); window.setWidth(res.getDimensionPixelSize(R.dimen.page_window_width)); window.setHeight(res.getDimensionPixelSize(R.dimen.page_window_height)); window.setContentView(contentView); window.setOutsideTouchable(true); return window; }
|
XML配置代码:
1 2 3 4 5
| <style name="AnimationFade"> <item name="android:windowEnterAnimation">@anim/fade_in</item> <item name="android:windowExitAnimation">@anim/fade_out</item> </style>
|
JAVA代码:
window.setAnimationStyle(R.style.AnimationFade);
1 2 3
| window.setFocusable(true); window.setTouchable(true); window.setOutsideTouchable(true);
|
1 2
| window.showAtLocation(); window.showAsDropDown();
|
下面说说PopupWindow的如何隐藏、显示及显示位置(showAtLocation/showAsDropDown)。
1 2 3 4
| final PopupWindow window = mPageStatWin; if(null != window && window.isShowing()) { win.dismiss(); }
|
window.showAtLocation(parent, Gravity.RIGHT | Gravity.BOTTOM, 10,10);
第一个参数指定PopupWindow的锚点view,即依附在哪个view上。
第二个参数指定起始点为parent的右下角,第三个参数设置以parent的右下角为原点,向左、上各偏移10像素。
1 2 3 4
| //将PopupWindow作为anchor的下拉窗口显示。即在anchor的左下角显示 window.showAsDropDown(anchor); //xoff,yoff基于anchor的左下角进行偏移。 window.showAsDropDown(anchor, xoff, yoff);
|
如果没有充足的空间显示PopupWindow,那么PopupWindow的左下角将位于anchor的左上角来显示。