博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android 使用PopupWindow实现弹出菜单
阅读量:6082 次
发布时间:2019-06-20

本文共 8863 字,大约阅读时间需要 29 分钟。

在本文当中,我将会与大家分享一个封装了PopupWindow实现弹出菜单的类,并说明它的实现与使用。

因对界面的需求,android原生的弹出菜单已不能满足我们的需求,自定义菜单成了我们的唯一选择,在本文当中,我将与大家分享如何使用PopupWindow实现弹出菜单

1.弹出菜单的封装PopMenu

PopupWindow可以说是一个浮动在Activity之上的容器,通常用来显示自定义的视图。比如像自动完成输入框AutoCompleteTextView,它的提示列表就是使用PopupWindow来实现的。下面的抽象类PopMenu封装了使用PopupWindow实现弹出菜单的UI逻辑,但不包括界面布局的设定。

/* * Date: 14-6-13 * Project: Parking Lay-by */package cn.irains.access.v2.common;import android.content.Context;import android.graphics.drawable.ColorDrawable;import android.view.KeyEvent;import android.view.View;import android.view.ViewGroup;import android.widget.AdapterView;import android.widget.ArrayAdapter;import android.widget.ListView;import android.widget.PopupWindow;import java.util.ArrayList;/** * 对弹出菜单的封装. * Author: msdx (645079761@qq.com) * Time: 14-6-13 下午1:51 */public abstract class PopMenu {    /**     * 上下文.     */    private Context mContext;    /**     * 菜单项     */    private ArrayList
mItemList; /** * 列表适配器. */ private ArrayAdapter
mAdapter; /** * 菜单选择监听. */ private OnItemSelectedListener mListener; /** * 列表. */ private ListView mListView; /** * 弹出窗口. */ private PopupWindow mPopupWindow; public PopMenu(Context context) { mContext = context; mItemList = new ArrayList
(2); View view = onCreateView(context); view.setFocusableInTouchMode(true); mAdapter = onCreateAdapter(context, mItemList); mListView = findListView(view); mListView.setAdapter(mAdapter); mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView
parent, View view, int position, long id) { Item item = mAdapter.getItem(position); if (mListener != null) { mListener.selected(view, item, position); } mPopupWindow.dismiss(); } }); view.setOnKeyListener(new View.OnKeyListener() { @Override public boolean onKey(View v, int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_MENU && mPopupWindow.isShowing()) { mPopupWindow.dismiss(); return true; } return false; } }); mPopupWindow = new PopupWindow(view, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, true); mPopupWindow.setBackgroundDrawable(new ColorDrawable(0x00000000)); } /** * 菜单的界面视图. * * @param context * @return */ protected abstract View onCreateView(Context context); /** * 菜单界面视图中的列表. * * @param view * @return */ protected abstract ListView findListView(View view); /** * 菜单列表中的适配器. * * @param context * @param itemList 表示所有菜单项. * @return */ protected abstract ArrayAdapter
onCreateAdapter(Context context, ArrayList
itemList); /** * 添加菜单项. * * @param text 菜单项文字内容. * @param id 菜单项的ID */ public void addItem(String text, int id) { mItemList.add(new Item(text, id)); mAdapter.notifyDataSetChanged(); } /** * 添加菜单项. * * @param resId 菜单项文字内容的资源ID * @param id 菜单项的ID. */ public void addItem(int resId, int id) { addItem(mContext.getString(resId), id); } /** * 作为指定View的下拉控制显示. * * @param parent 所指定的View */ public void showAsDropDown(View parent) { mPopupWindow.showAsDropDown(parent); } /** * 隐藏菜单. */ public void dismiss() { mPopupWindow.dismiss(); } /** * 设置菜单选择监听. * * @param listener 监听器. */ public void setOnItemSelectedListener(OnItemSelectedListener listener) { mListener = listener; } /** * 当前菜单是否正在显示. * * @return */ public boolean isShowing() { return mPopupWindow.isShowing(); } /** * 菜单项. */ public static class Item { public String text; public int id; public Item(String text, int id) { this.text = text; this.id = id; } @Override public String toString() { return text; } } /** * 菜单项选择监听接口. */ public static interface OnItemSelectedListener { /** * 菜单被选择时的回调接口. * * @param view 被选择的内容的View. * @param item 被选择的菜单项. * @param position 被选择的位置. */ public void selected(View view, Item item, int position); }}

这里面有三个抽象方法,第一个是onCreateView(Context context),在这里需要实现并返回我们的弹出菜单的这个view,然后才能装载到PopupWindow当中并显示出来。

第二个方法是findListView(View view)。这是因为我们的菜单通常是一个列表,然后点击去选择列表的某一项,所以这里需要返回一个ListView对象,用来装载我们的菜单项。

第三个方法是onCreateAdapter,即listview的适配器。

在这个类中,还封装了一个内部类Item:

/**     * 菜单项.     */    public static class Item {        public String text;        public int id;        public Item(String text, int id) {            this.text = text;            this.id = id;        }        @Override        public String toString() {            return text;        }    }

它用来表示我们的菜单项,text是显示在菜单当中的文本信息,id表示菜单项的ID。

在该抽象类中还定义了一个接口OnItemSelectedListener,是在菜单项被点击时的回调接口。关于它的说明见注释,这是我在这个博客里目前为止注释写得最详细的一个类了。

2.PopMenu的使用

首先继承PopMenu并实现抽象方法:

/* * Date: 14-9-2 * Project: Access-Control-V2 */package cn.irains.access.v2.usermanager;import android.content.Context;import android.view.LayoutInflater;import android.view.View;import android.widget.ArrayAdapter;import android.widget.ListView;import java.util.ArrayList;import cn.irains.access.v2.R;import cn.irains.access.v2.common.PopMenu;/** * Author: msdx (645079761@qq.com) * Time: 14-9-2 上午8:56 */public class UserMenu extends PopMenu {    public UserMenu(Context context) {        super(context);    }    @Override    protected ListView findListView(View view) {        return (ListView) view.findViewById(R.id.menu_listview);    }    @Override    protected View onCreateView(Context context) {        View view = LayoutInflater.from(context).inflate(R.layout.menu_user, null);        return view;    }    @Override    protected ArrayAdapter
onCreateAdapter(Context context, ArrayList
items) { return new ArrayAdapter
(context, R.layout.item_menu_user, items); }}

ListView的宽度,如果不写死的话,默认是宽度填充满父控件的,就像ViewPager默认高度填满父控件一样。如果想让ListView的宽度适配内容,则需要重写一下。参考前面的文章(),代码如下:

/* * Date: 14-9-2 * Project: Access-Control-V2 */package cn.irains.access.v2.common;import android.content.Context;import android.util.AttributeSet;import android.view.View;import android.widget.ListView;/** * 宽度适配内容的ListView. * Author: msdx (645079761@qq.com) * Time: 14-9-2 下午5:14 */public class WrapWidthListView extends ListView {    public WrapWidthListView(Context context) {        super(context);    }    public WrapWidthListView(Context context, AttributeSet attrs) {        super(context, attrs);    }    public WrapWidthListView(Context context, AttributeSet attrs, int defStyle) {        super(context, attrs, defStyle);    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        int width = 0;        for (int i = 0; i < getChildCount(); i++) {            View child = getChildAt(i);            child.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), heightMeasureSpec);            int w = child.getMeasuredWidth();            if (w > width) width = w;        }        widthMeasureSpec = MeasureSpec.makeMeasureSpec(width + getPaddingLeft() + getPaddingRight(), MeasureSpec.EXACTLY);        super.onMeasure(widthMeasureSpec, heightMeasureSpec);    }}

弹出菜单的布局文件如下:

其中的ImageView的照片是一个黑色三角图案。这个等在最后我发一下效果图就明白了。ListView背景是一张黑色图片。

接下来是item的布局,只是一个TextView,代码如下:

使用代码如下:

    private static final int USER_SEARCH = 0;    private static final int USER_ADD = 1;    private UserMenu mMenu;            private void initMenu() {        mMenu = new UserMenu(context);        mMenu.addItem(R.string.user_search, USER_SEARCH);        mMenu.addItem(R.string.user_add, USER_ADD);        mMenu.setOnItemSelectedListener(new PopMenu.OnItemSelectedListener() {            @Override            public void selected(View view, PopMenu.Item item, int position) {                switch (item.id) {                    case USER_SEARCH:                        startActivity(new Intent(getActivity(), UserSearchActivity.class));                        break;                    case USER_ADD:                        startActivity(new Intent(getActivity(), UserAddActivity.class));                        break;                }            }        });    }

在activity的onCreate或fragment中的onCreateView中初始化menu代码,然后需要显示时调用mMenu.showAsDropDown(view);它就作为view的下拉菜单显示了。效果如下:

 

你可能感兴趣的文章
中国足球
查看>>
windows本机域名配置
查看>>
Java编程基础-反射
查看>>
yarn+webpack+react
查看>>
Linux与VMwareTools与hgfs权限问题
查看>>
Database.SQL.join
查看>>
RIA Services Staying Logged In (Ria Service持久登陆,session-cookie,notcookie)
查看>>
最少加多少边成为强连通图
查看>>
[转]html5 Canvas画图4:填充和渐变
查看>>
数组json格式的字符串 转 list<Bean>
查看>>
alert 多语言的处理
查看>>
Ubuntu 最好用的CHM阅读器KchmViewer
查看>>
c# 高效率导出多维表头excel
查看>>
知识积累:CGI,FastCGI,PHP-CGI与PHP-FPM
查看>>
关于PHP定时执行任务的实现(转)
查看>>
PHP定时执行任务的实现(转)
查看>>
magento的一些小技巧(转)
查看>>
C++ 运行时类型识别 知道实例父类类型,显示出子类类型
查看>>
Android获取状态栏高度、标题栏高度、编辑区域高度
查看>>
bzoj1452 二维树状数组
查看>>