Android 使用PopupWindow实现弹出更多的菜单

最近想要做一个弹出更多的菜单,而原生的弹出菜单却不是我们想要的效果,所以必然要自定义菜单咯。本人也是借鉴网上的资料进行封装的,感觉还蛮不错的。

原生的菜单如下图:

自定义之后的效果图:

是不是看到这里之后,对比可知,原生的效果不太理想,所以还是再自己定义吧!

源码下载

1、PopupWindow可以说是一个浮动在Activity之上的容器,通常用来显示自定义的视图。弹出菜单的封装PopMenuMore

 

[java] view plain copy

  1. /** 
  2.  * 对弹出菜单的封装. 
  3.  * http://blog.youkuaiyun.com/maosidiaoxian/article/details/39178167 
  4.  * Author: msdx (645079761@qq.com) 
  5.  * Time: 14-6-13 下午1:51 
  6.  */  
  7. public class PopMenuMore {  
  8.     /** 
  9.      * 上下文. 
  10.      */  
  11.     private Context mContext;  
  12.     /** 
  13.      * 菜单项 
  14.      */  
  15.     private ArrayList<PopMenuMoreItem> mItemList;  
  16.     /** 
  17.      * 列表适配器. 
  18.      */  
  19.     private BaseAdapter mAdapter;  
  20.     /** 
  21.      * 菜单选择监听. 
  22.      */  
  23.     private OnItemSelectedListener mListener;  
  24.     /** 
  25.      * 下角图标 
  26.      */  
  27.     private ImageView cornerIcon;  
  28.     /** 
  29.      * 列表. 
  30.      */  
  31.     private ListView mListView;  
  32.     /** 
  33.      * 弹出窗口. 
  34.      */  
  35.     private PopupWindow mPopupWindow;  
  36.   
  37.     public PopMenuMore(Context context) {  
  38.         mContext = context;  
  39.         mItemList = new ArrayList<>();  
  40.         View view = onCreateView(context);  
  41.         view.setFocusableInTouchMode(true);  
  42.         mAdapter = onCreateAdapter(context, mItemList);  
  43.         cornerIcon = findCornerView(view);  
  44.         mListView = findListView(view);  
  45.         mListView.setAdapter(mAdapter);  
  46.         mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {  
  47.             @Override  
  48.             public void onItemClick(AdapterView<?> parent, View view, int position, long id) {  
  49.                 PopMenuMoreItem item = (PopMenuMoreItem) mAdapter.getItem(position);  
  50.                 if (mListener != null) {  
  51.                     mListener.selected(view, item, position);  
  52.                 }  
  53.                 mPopupWindow.dismiss();  
  54.             }  
  55.         });  
  56.         view.setOnKeyListener(new View.OnKeyListener() {  
  57.             @Override  
  58.             public boolean onKey(View v, int keyCode, KeyEvent event) {  
  59.                 if (keyCode == KeyEvent.KEYCODE_MENU && mPopupWindow.isShowing()) {  
  60.                     mPopupWindow.dismiss();  
  61.                     return true;  
  62.                 }  
  63.                 return false;  
  64.             }  
  65.         });  
  66.         mPopupWindow = new PopupWindow(view, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, true);  
  67.         mPopupWindow.setBackgroundDrawable(new ColorDrawable(0x00000000));  
  68.         setBackgroundColor(Color.parseColor("#000000"));  
  69.         setCorner(R.mipmap.triangle);  
  70.     }  
  71.   
  72.     /** 
  73.      * 设置ListView背景 
  74.      * 
  75.      * @param argb Color.parseColor("..") 
  76.      */  
  77.     public void setBackgroundColor(int argb) {  
  78. //        int strokeWidth = 5; // 3dp 边框宽度  
  79.         int roundRadius = 5; // 8dp 圆角半径  
  80. //        int strokeColor = Color.parseColor("#2E3135");//边框颜色  
  81. //        int fillColor = Color.parseColor("#DFDFE0");//内部填充颜色  
  82.         GradientDrawable gd = new GradientDrawable();//创建drawable  
  83.         gd.setColor(argb);  
  84.         gd.setCornerRadius(roundRadius);  
  85. //        gd.setStroke(strokeWidth, strokeColor);  
  86.         mListView.setBackgroundDrawable(gd);  
  87.     }  
  88.   
  89.     /** 
  90.      * 设置下角图标 
  91.      * 
  92.      * @param resId 
  93.      */  
  94.     public void setCorner(int resId) {  
  95.         cornerIcon.setBackgroundResource(resId);  
  96.     }  
  97.   
  98.     protected View onCreateView(Context context) {  
  99.         return LayoutInflater.from(context).inflate(R.layout.layout_popmenu_more, null);  
  100.     }  
  101.   
  102.     protected ImageView findCornerView(View view) {  
  103.         return (ImageView) view.findViewById(R.id.corner_iv);  
  104.     }  
  105.   
  106.     protected ListView findListView(View view) {  
  107.         return (ListView) view.findViewById(R.id.menu_listview);  
  108.     }  
  109.   
  110.     /** 
  111.      * 菜单列表中的适配器. 
  112.      * 
  113.      * @param context 
  114.      * @param items   表示所有菜单项. 
  115.      * @return 
  116.      */  
  117.     protected BaseAdapter onCreateAdapter(Context context, ArrayList<PopMenuMoreItem> items) {  
  118.         return new PopMenuMoreAdapter(context, items);  
  119.     }  
  120.   
  121.     /** 
  122.      * 添加菜单项 
  123.      * 
  124.      * @param item 
  125.      */  
  126.     public void addItem(PopMenuMoreItem item) {  
  127.         mItemList.add(item);  
  128.         mAdapter.notifyDataSetChanged();  
  129.     }  
  130.   
  131.     public void addItems(List<PopMenuMoreItem> items) {  
  132.         if (items != null) {  
  133.             mItemList.clear();  
  134.         }  
  135.         for (PopMenuMoreItem item : items) {  
  136.             mItemList.add(item);  
  137.         }  
  138.         mAdapter.notifyDataSetChanged();  
  139.     }  
  140.   
  141.   
  142.     /** 
  143.      * 作为指定View的下拉控制显示. 
  144.      * 
  145.      * @param parent 所指定的View 
  146.      */  
  147.     public void showAsDropDown(View parent) {  
  148.         mPopupWindow.showAsDropDown(parent);  
  149.     }  
  150.   
  151.     /** 
  152.      * 隐藏菜单. 
  153.      */  
  154.     public void dismiss() {  
  155.         mPopupWindow.dismiss();  
  156.     }  
  157.   
  158.     /** 
  159.      * 设置菜单选择监听. 
  160.      * 
  161.      * @param listener 监听器. 
  162.      */  
  163.     public void setOnItemSelectedListener(OnItemSelectedListener listener) {  
  164.         mListener = listener;  
  165.     }  
  166.   
  167.     /** 
  168.      * 当前菜单是否正在显示. 
  169.      * 
  170.      * @return 
  171.      */  
  172.     public boolean isShowing() {  
  173.         return mPopupWindow.isShowing();  
  174.     }  
  175.   
  176.     /** 
  177.      * 菜单项选择监听接口. 
  178.      */  
  179.     public interface OnItemSelectedListener {  
  180.         /** 
  181.          * 菜单被选择时的回调接口. 
  182.          * 
  183.          * @param view     被选择的内容的View. 
  184.          * @param item     被选择的菜单项. 
  185.          * @param position 被选择的位置. 
  186.          */  
  187.         void selected(View view, PopMenuMoreItem item, int position);  
  188.     }  
  189. }  

2、菜单中ListView的适配器:PopMenuMoreAdapter

 

 

[java] view plain copy

  1. /** 
  2.  * @author SoBan 
  3.  * @create 2017/4/12 10:29. 
  4.  */  
  5.   
  6. public class PopMenuMoreAdapter extends BaseAdapter {  
  7.   
  8.     private ArrayList<PopMenuMoreItem> items;  
  9.     private Context context;  
  10.   
  11.     public PopMenuMoreAdapter(Context context, ArrayList<PopMenuMoreItem> items) {  
  12.         this.context = context;  
  13.         this.items = items;  
  14.     }  
  15.   
  16.     @Override  
  17.     public int getCount() {  
  18.         return items.size();  
  19.     }  
  20.   
  21.     @Override  
  22.     public PopMenuMoreItem getItem(int position) {  
  23.         return items.get(position);  
  24.     }  
  25.   
  26.     @Override  
  27.     public long getItemId(int position) {  
  28.         return position;  
  29.     }  
  30.   
  31.     @Override  
  32.     public View getView(int position, View view, ViewGroup parent) {  
  33.         if (view == null) {  
  34.             view = LayoutInflater.from(context).inflate(R.layout.item_popmenu_more, null);  
  35.             ViewHolder holder = new ViewHolder();  
  36.             holder.icon = (ImageView) view.findViewById(R.id.menu_icon);  
  37.             holder.text = (TextView) view.findViewById(R.id.menu_text);  
  38.             view.setTag(holder);  
  39.         } else if (view.getParent() != null) {  
  40.             ((ViewGroup) view.getParent()).removeView(view);  
  41.         }  
  42.         ViewHolder holder = (ViewHolder) view.getTag();  
  43.         PopMenuMoreItem item = items.get(position);  
  44.         if (item.getResId() == 0) {  
  45.             holder.icon.setVisibility(View.GONE);  
  46.         }  
  47.         holder.text.setText(item.getText());  
  48.         return view;  
  49.     }  
  50.   
  51.     private class ViewHolder {  
  52.         ImageView icon;  
  53.         TextView text;  
  54.     }  
  55. }  

4、菜单项中item:  PopMenuMoreItem

 

 

[java] view plain copy

  1. /** 
  2.  * 菜单项. 
  3.  */  
  4. public class PopMenuMoreItem {  
  5.     public int id; //标识  
  6.     public int resId; //资源图标  
  7.     public String text;//文字  
  8.   
  9.     public PopMenuMoreItem(int id, String text) {  
  10.         this.id = id;  
  11.         this.resId = 0;  
  12.         this.text = text;  
  13.     }  
  14.   
  15.     public PopMenuMoreItem(int id, int resId, String text) {  
  16.         this.id = id;  
  17.         this.resId = resId;  
  18.         this.text = text;  
  19.     }  
  20.   
  21.     public int getId() {  
  22.         return id;  
  23.     }  
  24.   
  25.     public void setId(int id) {  
  26.         this.id = id;  
  27.     }  
  28.   
  29.     public int getResId() {  
  30.         return resId;  
  31.     }  
  32.   
  33.     public void setResId(int resId) {  
  34.         this.resId = resId;  
  35.     }  
  36.   
  37.     public String getText() {  
  38.         return text;  
  39.     }  
  40.   
  41.     public void setText(String text) {  
  42.         this.text = text;  
  43.     }  
  44. }  

4、宽度适配内容、不滚动的ListView:PopMenuMoreListView

 

 

[java] view plain copy

  1. /** 
  2.  * 宽度适配内容的ListView. 
  3.  * Author: msdx (645079761@qq.com) 
  4.  * Time: 14-9-2 下午5:14 
  5.  */  
  6. public class PopMenuMoreListView extends ListView {  
  7.   
  8.     public PopMenuMoreListView(Context context) {  
  9.         super(context);  
  10.     }  
  11.   
  12.     public PopMenuMoreListView(Context context, AttributeSet attrs) {  
  13.         super(context, attrs);  
  14.     }  
  15.   
  16.     public PopMenuMoreListView(Context context, AttributeSet attrs, int defStyle) {  
  17.         super(context, attrs, defStyle);  
  18.     }  
  19.   
  20.     @Override  
  21.     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {  
  22.         int width = 0;  
  23.         for (int i = 0; i < getChildCount(); i++) {  
  24.             View child = getChildAt(i);  
  25.             child.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), heightMeasureSpec);  
  26.             int w = child.getMeasuredWidth();  
  27.             if (w > width) width = w;  
  28.         }  
  29.   
  30.         widthMeasureSpec = MeasureSpec.makeMeasureSpec(width + getPaddingLeft() + getPaddingRight(), MeasureSpec.EXACTLY);  
  31.   
  32.         super.onMeasure(widthMeasureSpec, heightMeasureSpec);  
  33.     }  
  34. }  

 

5、item的布局:item_popmenu_more.xml

 

[html] view plain copy

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="wrap_content"  
  4.     android:layout_height="wrap_content"  
  5.     android:paddingBottom="10dip"  
  6.     android:paddingLeft="20dip"  
  7.     android:paddingRight="20dip"  
  8.     android:paddingTop="10dip">  
  9.   
  10.     <ImageView  
  11.         android:id="@+id/menu_icon"  
  12.         android:layout_width="wrap_content"  
  13.         android:layout_height="wrap_content"  
  14.         android:layout_gravity="center_vertical"  
  15.         android:layout_marginLeft="5dip"  
  16.         android:layout_marginRight="5dip"  
  17.         android:src="@mipmap/demand_icon_location" />  
  18.   
  19.     <TextView  
  20.         android:id="@+id/menu_text"  
  21.         android:layout_width="wrap_content"  
  22.         android:layout_height="wrap_content"  
  23.         android:layout_gravity="center_vertical"  
  24.         android:singleLine="true"  
  25.         android:textColor="#FFFFFF" />  
  26. </LinearLayout>  

6、更多菜单的布局:layout_popmenu_more.xml

 

 

[html] view plain copy

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="wrap_content"  
  5.     android:orientation="vertical"  
  6.     android:paddingRight="5dip">  
  7.   
  8.     <ImageView  
  9.         android:id="@+id/corner_iv"  
  10.         android:layout_width="wrap_content"  
  11.         android:layout_height="wrap_content"  
  12.         android:layout_gravity="right"  
  13.         android:layout_marginRight="15dip"  
  14.         android:contentDescription="@null" />  
  15.   
  16.     <soban.orderscroll.PopMenuMoreListView  
  17.         android:id="@+id/menu_listview"  
  18.         android:layout_width="wrap_content"  
  19.         android:layout_height="wrap_content"  
  20.         android:layout_gravity="right"  
  21.         android:cacheColorHint="@android:color/transparent"  
  22.         android:listSelector="@android:color/transparent"  
  23.         android:divider="#FFFFFF"  
  24.         android:dividerHeight="1px"  
  25.         android:focusable="true" />  
  26. </LinearLayout>  

7、例子Activity: MainActivity

 

 

[java] view plain copy

  1. public class MainActivity extends Activity {  
  2.   
  3.     private static final int USER_SEARCH = 0;  
  4.     private static final int USER_ADD = 1;  
  5.     private PopMenuMore mMenu;  
  6.     private TextView mTextView;  
  7.   
  8.     @Override  
  9.     protected void onCreate(Bundle savedInstanceState) {  
  10.         super.onCreate(savedInstanceState);  
  11.         setContentView(R.layout.activity_main);  
  12.         initMenu();  
  13.         mTextView = (TextView) findViewById(R.id.hello_tv);  
  14.         mTextView.setOnClickListener(new View.OnClickListener() {  
  15.             @Override  
  16.             public void onClick(View view) {  
  17.                 mMenu.showAsDropDown(mTextView);  
  18.             }  
  19.         });  
  20.     }  
  21.   
  22.     private void initMenu() {  
  23.         mMenu = new PopMenuMore(this);  
  24.        // mMenu.setCorner(R.mipmap.demand_icon_location);  
  25.        // mMenu.setBackgroundColor(Color.parseColor("#ff8800"));  
  26.         ArrayList<PopMenuMoreItem> items = new ArrayList<>();  
  27.         items.add(new PopMenuMoreItem(USER_SEARCH, "搜索"));  
  28.         items.add(new PopMenuMoreItem(USER_ADD, "添加"));  
  29.         items.add(new PopMenuMoreItem(USER_SEARCH, "搜索"));  
  30.         items.add(new PopMenuMoreItem(USER_ADD, "添加"));  
  31.         items.add(new PopMenuMoreItem(USER_SEARCH, "搜索"));  
  32.         items.add(new PopMenuMoreItem(USER_ADD, "添加"));  
  33.         /*items.add(new PopMenuMoreItem(USER_SEARCH, R.mipmap.demand_icon_number, "搜索")); 
  34.         items.add(new PopMenuMoreItem(USER_ADD, R.mipmap.demand_icon_location, "添加")); 
  35.         items.add(new PopMenuMoreItem(USER_SEARCH, R.mipmap.demand_icon_number, "搜索")); 
  36.         items.add(new PopMenuMoreItem(USER_ADD, R.mipmap.demand_icon_location, "添加")); 
  37.         items.add(new PopMenuMoreItem(USER_SEARCH, R.mipmap.demand_icon_number, "搜索")); 
  38.         items.add(new PopMenuMoreItem(USER_ADD, R.mipmap.demand_icon_location, "添加"));*/  
  39.   
  40.         mMenu.addItems(items);  
  41.         mMenu.setOnItemSelectedListener(new PopMenuMore.OnItemSelectedListener() {  
  42.             @Override  
  43.             public void selected(View view, PopMenuMoreItem item, int position) {  
  44.                 switch (item.id) {  
  45.                     case USER_SEARCH:  
  46. //                        startActivity(new Intent(this, UserSearchActivity.class));  
  47.                         break;  
  48.                     case USER_ADD:  
  49. //                        startActivity(new Intent(getActivity(), UserAddActivity.class));  
  50.                         break;  
  51.                 }  
  52.             }  
  53.         });  
  54.     }  
  55. }  

8、例子布局:activity_main.xml

 

 

[html] view plain copy

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     xmlns:tools="http://schemas.android.com/tools"  
  4.     android:id="@+id/activity_main"  
  5.     android:layout_width="match_parent"  
  6.     android:layout_height="match_parent"  
  7.     android:paddingBottom="@dimen/activity_vertical_margin"  
  8.     android:paddingLeft="@dimen/activity_horizontal_margin"  
  9.     android:paddingRight="@dimen/activity_horizontal_margin"  
  10.     android:paddingTop="@dimen/activity_vertical_margin">  
  11.   
  12.     <TextView  
  13.         android:id="@+id/hello_tv"  
  14.         android:layout_width="wrap_content"  
  15.         android:layout_height="wrap_content"  
  16.         android:text="Hello World!" />  
  17. </RelativeLayout>  

 

9、所需资源文件:

 

最近项目也蛮急的,这里写的有点匆忙,可能写的就没有那么具体,希望各位朋友看的懂

 

借鉴:http://blog.csdn.NET/maosidiaoxian/article/details/39178167

代码设置背景圆角+边框+圆半径:http://blog.csdn.net/houshunwei/article/details/17392409

转载于:https://my.oschina.net/u/1177694/blog/961894

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值