首先看效果
调用方式也非常的简单如下:
//操作需要用到的图片icon final int itemIconIds[] = new int[] { R.drawable.p_trends_comment, R.drawable.p_trends_forward, R.drawable.p_trends_share, R.drawable.p_trends_delete }; final String itemDescs[] = new String[] { "评 论", "转 发", "共 享", "删 除" }; //获得屏幕的高度,设置ListView的最大高度,动态设置ListView的高度 WindowManager windowManager = this.getWindowManager(); Display display = windowManager.getDefaultDisplay(); int screenHeight = display.getHeight(); showBtn = (Button) this.findViewById(R.id.show); new PathPopupWindowDialog(this, screenHeight, showBtn).create(itemIconIds, itemDescs, new ResponseListener());
PathPopupWindowDialog的参数说明:
构造函数中第一个参数“this”是Context,第二个"screenHeight"是屏幕的高度,本来是要根据内容的增加,来不断调整dialog的高度的,暂时看来是不需要了,第三个参数"showBtn"是用来触发此dialog的一个按钮,其实是PopupWindow的showAtLocation需要的parentView
create方法中的参数分别是dialog中每一个item需要的图标和对应的文字,以及单击每一个条目需要触发的事件,内容形式示例如下:
private class ResponseListener implements AdapterView.OnItemClickListener { @Override public void onItemClick(AdapterView<?> adapter, View view, int id, long position) { System.out.println(view + "----"); @SuppressWarnings("unchecked") HashMap<String, Object> map = (HashMap<String, Object>) adapter.getItemAtPosition((int) position); Toast.makeText(Android_test_02Activity.this, map.get("text").toString(), 1000).show(); } }
package com.king.demo; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import android.content.Context; import android.view.Gravity; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager.LayoutParams; import android.widget.AdapterView; import android.widget.ListAdapter; import android.widget.ListView; import android.widget.PopupWindow; import android.widget.SimpleAdapter; /** * path dialog组件 <br/> * <br/> * <b>示例:<br/> * new PathPopupWindowDialog(Context context, int screenHeight, View showBtn)<br/> * .create(int itemIconIds[],String itemDescs[], * AdapterView.OnItemClickListener listener);<br/> * <br/> * 参数说明:<br/> * context ---- 一般是activity<br/> * screenHeight ---- 屏幕高度<br/> * showBtn ---- 用来PopupWindow展示,例如Button,点击此button会显示dialog<br/> * itemIconIds ---- ListView中每一个item的图标<br/> * itemDescs ---- ListView中每一个item的图标对应的说明<br/> * listener ---- ListView中每一个item需要响应的操作,需要用户自己实现。<br/> * 关于ListView中的值是通过SimpleAdapter设置的,其中SimpleAdapter接收的List<HashMap<String, * Object>><br/> * map中存放的key是图标是"icon"[ITEM_ICON]和文本是"text"[ITEM_TEXT],用户在实现listener的时候可能需要用到 * </b> * * @author kingzhang * */ public class PathPopupWindowDialog { public static final String ITEM_ICON = "icon"; public static final String ITEM_TEXT = "text"; /** * popupWindow */ private PopupWindow popupWindow; /** * 确定dialog需要的context */ private Context context; /** * 手机屏幕的高度 */ private int screenHeight; /** * 确定触发该dialog的view组件,也是创建popupwindow必须的参数 */ private View parentView; public PathPopupWindowDialog(Context context, int screenHeight, View parentView) { this.context = context; this.screenHeight = screenHeight; this.parentView = parentView; } /** * 创建PopupWindow * * @param itemIconIds * ListView中的图标 * @param itemDescs * ListView中图标对应的描述 * @param responseListener * 响应listview中的item click listener 事件 */ public void create(int itemIconIds[], String itemDescs[], AdapterView.OnItemClickListener responseListener) { LayoutInflater inflater = LayoutInflater.from(context); View popupView = inflater.inflate(R.layout.p_trends_option_popup, null); //popupView.se //从popu.xml中获得其中的组件 ListView listView = (ListView) popupView.findViewById(R.id.path_popupwindow_listview); //获得popup中最外层的layout //LinearLayout linearLayout = (LinearLayout) popupView.findViewById(R.id.p_dynamic_popup_layout); //设置ListView中的参数属性 this.setListViewParamters(listView, itemIconIds, itemDescs, responseListener); //获得屏幕的高度,设置ListView的最大高度,动态设置ListView的高度 //this.setListViewHeightBasedOnChildren(listView, screenHeight); //生成PopupWindow对象 popupWindow = new PopupWindow(popupView, LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT, true); //设置PopupWindow对象需要属性参数 popupWindow.setAnimationStyle(R.style.path_popwindow_anim_enterorout_window); popupWindow.setFocusable(true); popupWindow.setTouchable(true); //设置popupwindow以外的区域是否可以触摸 popupWindow.setOutsideTouchable(true); //显示popupwindow parentView.setOnClickListener(new ShowPopupWindowListener()); // 设置android返回事件,用来隐藏popupwindow // 不给LinearLayout设置的原因是因为给其加上后,ListView不能获得焦点 this.setBackListener(listView); } /** * 设置ListView里面的参数属性 * * @param listView * @param itemIconIds * ListView中的图标 * @param itemDescs * ListView中图标对应的描述 * @param responseListener * 响应listview中的item click listener 事件 */ private void setListViewParamters(ListView listView, int itemIconIds[], String itemDescs[], AdapterView.OnItemClickListener responseListener) { // 给popu.xml中ListView设置值 List<HashMap<String, Object>> itemList = new ArrayList<HashMap<String, Object>>(); for (int i = 0; i < itemDescs.length; i++) { HashMap<String, Object> map = new HashMap<String, Object>(); map.put(ITEM_ICON, itemIconIds[i]); map.put(ITEM_TEXT, itemDescs[i]); itemList.add(map); } SimpleAdapter simpleAdapter = new SimpleAdapter(context, itemList, R.layout.p_trends_option_popup_item, new String[] { "icon", "text" }, new int[] { R.id.path_dynamic_popu_item_icon, R.id.path_dynamic_popu_item_textView }); listView.setFocusable(true); listView.requestFocus(); listView.setAdapter(simpleAdapter); listView.setItemsCanFocus(true); listView.setDividerHeight(0); //设置ListView中的item点击事件 listView.setOnItemClickListener(responseListener); } /** * 给parentView设置onclicklistener事件,用于显示popupwindow * * @author kingzhang * */ private class ShowPopupWindowListener implements View.OnClickListener { @Override public void onClick(View v) { popupWindow.showAtLocation(parentView, Gravity.BOTTOM, 0, 0); popupWindow.update(); } } /** * 为PopupWindow中的最外层的布局设置onkeylistener事件 用来隐藏弹出的popupwindow * * @param layout * 为PopupWindow中的最外层的布局 * @param pw * PopupWindow */ private void setBackListener(View view) { view.setOnKeyListener(new View.OnKeyListener() { @Override public boolean onKey(View v, int keyCode, KeyEvent event) { if (event.getAction() == KeyEvent.ACTION_DOWN && keyCode == KeyEvent.KEYCODE_BACK) { popupWindow.dismiss(); } return false; } }); } /** * 动态设置listview的高度 * * @param listView * 需要配置的ListView * @param screenHeight * 屏幕的高度 * @param imageHeight * imageHeight * @param viewHeight * viewHeight */ private void setListViewHeightBasedOnChildren(ListView listView, int screenHeigh) { //获取ListView对应的Adapter ListAdapter listAdapter = listView.getAdapter(); if (listAdapter == null) { return; } int totalHeight = 0; for (int i = 0, len = listAdapter.getCount(); i < len; i++) { //listAdapter.getCount()返回数据项的数目 View listItem = listAdapter.getView(i, null, listView); //计算子项View 的宽高 listItem.measure(0, 0); //统计所有子项的总高度 totalHeight += listItem.getMeasuredHeight(); } ViewGroup.LayoutParams params = listView.getLayoutParams(); //listView.getDividerHeight()获取子项间分隔符占用的高度 int listViewHeight = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1)); //如果总体高度大于屏幕高度,则用屏幕高度 if (listViewHeight > screenHeight) { //此处的30是实验所得出的结果 params.height = screenHeight - 75; } //否则设置为计算出来的高度 else { params.height = listViewHeight; } listView.setLayoutParams(params); } }
<?xml version="1.0" encoding="utf-8"?> <!-- author king --> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/p_dynamic_popup_layout" android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="vertical" android:paddingTop="30dip"> <!-- 显示的高度跟这个LinearLayout的background的大小有关,以及和item里面的backgroud有关 --> <!-- 用来显示popupwindow中的列表项 --> <ImageView android:id="@+id/title_bg" android:layout_width="fill_parent" android:layout_height="wrap_content" android:src="@drawable/top" android:scaleType="fitXY"/> <ListView android:id="@+id/path_popupwindow_listview" android:layout_width="fill_parent" android:layout_height="fill_parent" android:paddingLeft="10dip" android:paddingRight="10dip" android:background="@drawable/bg" android:cacheColorHint="#00000000"/> <ImageView android:id="@+id/bottom_bg" android:src="@drawable/bottom" android:layout_width="fill_parent" android:layout_height="wrap_content" android:scaleType="fitXY"/> </LinearLayout>
<?xml version="1.0" encoding="utf-8"?> <!-- author king --> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="60dip" android:gravity="center" android:orientation="horizontal" > <ImageView android:id="@+id/path_dynamic_popu_item_icon" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:scaleType="centerInside"/> <TextView android:id="@+id/path_dynamic_popu_item_textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:layout_marginLeft="10dip" android:gravity="center" android:textColor="@android:color/white" android:textSize="22sp"/> </LinearLayout>
剩下的就是所用的图片背景如下:
用到的动画效果的xml文件如下:
enter window
<?xml version="1.0" encoding="utf-8"?> <!-- author king --> <set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@android:anim/decelerate_interpolator" > <translate android:duration="300" android:fromXDelta="0.0" android:fromYDelta="100%" android:toXDelta="0.0" android:toYDelta="0.0" /> </set>
<?xml version="1.0" encoding="utf-8"?> <!-- author king --> <set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@android:anim/decelerate_interpolator"> <translate android:duration="400" android:fromXDelta="0.0" android:fromYDelta="0.0" android:toXDelta="0.0" android:toYDelta="100%" /> </set>
style文件外为:
<?xml version="1.0" encoding="utf-8"?> <!-- author king --> <resources> <style name="path_popwindow_anim_enterorout_window"> <item name="android:windowEnterAnimation">@anim/p_trends_enter_window</item> <!-- 指定显示的动画xml --> <item name="android:windowExitAnimation">@anim/p_trends_out_window</item> <!-- 指定消失的动画xml --> </style> </resources>