首页 > 代码库 > Android 使用PopupWindow实现弹出更多的菜单

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

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

原生的菜单如下图:

技术分享

自定义之后的效果图:

技术分享技术分享技术分享

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

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

/**
 * 对弹出菜单的封装.
 * http://blog.csdn.net/maosidiaoxian/article/details/39178167
 * Author: msdx (645079761@qq.com)
 * Time: 14-6-13 下午1:51
 */
public class PopMenuMore {
    /**
     * 上下文.
     */
    private Context mContext;
    /**
     * 菜单项
     */
    private ArrayList<PopMenuMoreItem> mItemList;
    /**
     * 列表适配器.
     */
    private BaseAdapter mAdapter;
    /**
     * 菜单选择监听.
     */
    private OnItemSelectedListener mListener;
    /**
     * 下角图标
     */
    private ImageView cornerIcon;
    /**
     * 列表.
     */
    private ListView mListView;
    /**
     * 弹出窗口.
     */
    private PopupWindow mPopupWindow;

    public PopMenuMore(Context context) {
        mContext = context;
        mItemList = new ArrayList<>();
        View view = onCreateView(context);
        view.setFocusableInTouchMode(true);
        mAdapter = onCreateAdapter(context, mItemList);
        cornerIcon = findCornerView(view);
        mListView = findListView(view);
        mListView.setAdapter(mAdapter);
        mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                PopMenuMoreItem item = (PopMenuMoreItem) 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));
        setBackgroundColor(Color.parseColor("#000000"));
        setCorner(R.mipmap.triangle);
    }

    /**
     * 设置ListView背景
     *
     * @param argb Color.parseColor("..")
     */
    public void setBackgroundColor(int argb) {
//        int strokeWidth = 5; // 3dp 边框宽度
        int roundRadius = 5; // 8dp 圆角半径
//        int strokeColor = Color.parseColor("#2E3135");//边框颜色
//        int fillColor = Color.parseColor("#DFDFE0");//内部填充颜色
        GradientDrawable gd = new GradientDrawable();//创建drawable
        gd.setColor(argb);
        gd.setCornerRadius(roundRadius);
//        gd.setStroke(strokeWidth, strokeColor);
        mListView.setBackgroundDrawable(gd);
    }

    /**
     * 设置下角图标
     *
     * @param resId
     */
    public void setCorner(int resId) {
        cornerIcon.setBackgroundResource(resId);
    }

    protected View onCreateView(Context context) {
        return LayoutInflater.from(context).inflate(R.layout.layout_popmenu_more, null);
    }

    protected ImageView findCornerView(View view) {
        return (ImageView) view.findViewById(R.id.corner_iv);
    }

    protected ListView findListView(View view) {
        return (ListView) view.findViewById(R.id.menu_listview);
    }

    /**
     * 菜单列表中的适配器.
     *
     * @param context
     * @param items   表示所有菜单项.
     * @return
     */
    protected BaseAdapter onCreateAdapter(Context context, ArrayList<PopMenuMoreItem> items) {
        return new PopMenuMoreAdapter(context, items);
    }

    /**
     * 添加菜单项
     *
     * @param item
     */
    public void addItem(PopMenuMoreItem item) {
        mItemList.add(item);
        mAdapter.notifyDataSetChanged();
    }

    public void addItems(List<PopMenuMoreItem> items) {
        if (items != null) {
            mItemList.clear();
        }
        for (PopMenuMoreItem item : items) {
            mItemList.add(item);
        }
        mAdapter.notifyDataSetChanged();
    }


    /**
     * 作为指定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 interface OnItemSelectedListener {
        /**
         * 菜单被选择时的回调接口.
         *
         * @param view     被选择的内容的View.
         * @param item     被选择的菜单项.
         * @param position 被选择的位置.
         */
        void selected(View view, PopMenuMoreItem item, int position);
    }
}
2、菜单中ListView的适配器:PopMenuMoreAdapter

/**
 * @author SoBan
 * @create 2017/4/12 10:29.
 */

public class PopMenuMoreAdapter extends BaseAdapter {

    private ArrayList<PopMenuMoreItem> items;
    private Context context;

    public PopMenuMoreAdapter(Context context, ArrayList<PopMenuMoreItem> items) {
        this.context = context;
        this.items = items;
    }

    @Override
    public int getCount() {
        return items.size();
    }

    @Override
    public PopMenuMoreItem getItem(int position) {
        return items.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View view, ViewGroup parent) {
        if (view == null) {
            view = LayoutInflater.from(context).inflate(R.layout.item_popmenu_more, null);
            ViewHolder holder = new ViewHolder();
            holder.icon = (ImageView) view.findViewById(R.id.menu_icon);
            holder.text = (TextView) view.findViewById(R.id.menu_text);
            view.setTag(holder);
        } else if (view.getParent() != null) {
            ((ViewGroup) view.getParent()).removeView(view);
        }
        ViewHolder holder = (ViewHolder) view.getTag();
        PopMenuMoreItem item = items.get(position);
        if (item.getResId() == 0) {
            holder.icon.setVisibility(View.GONE);
        }
        holder.text.setText(item.getText());
        return view;
    }

    private class ViewHolder {
        ImageView icon;
        TextView text;
    }
}
4、菜单项中item:  PopMenuMoreItem

/**
 * 菜单项.
 */
public class PopMenuMoreItem {
    public int id; //标识
    public int resId; //资源图标
    public String text;//文字

    public PopMenuMoreItem(int id, String text) {
        this.id = id;
        this.resId = 0;
        this.text = text;
    }

    public PopMenuMoreItem(int id, int resId, String text) {
        this.id = id;
        this.resId = resId;
        this.text = text;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getResId() {
        return resId;
    }

    public void setResId(int resId) {
        this.resId = resId;
    }

    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
    }
}
4、宽度适配内容、不滚动的ListView:PopMenuMoreListView

/**
 * 宽度适配内容的ListView.
 * Author: msdx (645079761@qq.com)
 * Time: 14-9-2 下午5:14
 */
public class PopMenuMoreListView extends ListView {

    public PopMenuMoreListView(Context context) {
        super(context);
    }

    public PopMenuMoreListView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public PopMenuMoreListView(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);
    }
}

5、item的布局:item_popmenu_more.xml

<?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:paddingBottom="10dip"
    android:paddingLeft="20dip"
    android:paddingRight="20dip"
    android:paddingTop="10dip">

    <ImageView
        android:id="@+id/menu_icon"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical"
        android:layout_marginLeft="5dip"
        android:layout_marginRight="5dip"
        android:src=http://www.mamicode.com/"@mipmap/demand_icon_location" />>6、更多菜单的布局:layout_popmenu_more.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:orientation="vertical"
    android:paddingRight="5dip">

    <ImageView
        android:id="@+id/corner_iv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="right"
        android:layout_marginRight="15dip"
        android:contentDescription="@null" />

    <soban.orderscroll.PopMenuMoreListView
        android:id="@+id/menu_listview"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="right"
        android:cacheColorHint="@android:color/transparent"
        android:listSelector="@android:color/transparent"
        android:divider="#FFFFFF"
        android:dividerHeight="1px"
        android:focusable="true" />
</LinearLayout>
7、例子Activity: MainActivity

public class MainActivity extends Activity {

    private static final int USER_SEARCH = 0;
    private static final int USER_ADD = 1;
    private PopMenuMore mMenu;
    private TextView mTextView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initMenu();
        mTextView = (TextView) findViewById(R.id.hello_tv);
        mTextView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mMenu.showAsDropDown(mTextView);
            }
        });
    }

    private void initMenu() {
        mMenu = new PopMenuMore(this);
       // mMenu.setCorner(R.mipmap.demand_icon_location);
       // mMenu.setBackgroundColor(Color.parseColor("#ff8800"));
        ArrayList<PopMenuMoreItem> items = new ArrayList<>();
        items.add(new PopMenuMoreItem(USER_SEARCH, "搜索"));
        items.add(new PopMenuMoreItem(USER_ADD, "添加"));
        items.add(new PopMenuMoreItem(USER_SEARCH, "搜索"));
        items.add(new PopMenuMoreItem(USER_ADD, "添加"));
        items.add(new PopMenuMoreItem(USER_SEARCH, "搜索"));
        items.add(new PopMenuMoreItem(USER_ADD, "添加"));
        /*items.add(new PopMenuMoreItem(USER_SEARCH, R.mipmap.demand_icon_number, "搜索"));
        items.add(new PopMenuMoreItem(USER_ADD, R.mipmap.demand_icon_location, "添加"));
        items.add(new PopMenuMoreItem(USER_SEARCH, R.mipmap.demand_icon_number, "搜索"));
        items.add(new PopMenuMoreItem(USER_ADD, R.mipmap.demand_icon_location, "添加"));
        items.add(new PopMenuMoreItem(USER_SEARCH, R.mipmap.demand_icon_number, "搜索"));
        items.add(new PopMenuMoreItem(USER_ADD, R.mipmap.demand_icon_location, "添加"));*/

        mMenu.addItems(items);
        mMenu.setOnItemSelectedListener(new PopMenuMore.OnItemSelectedListener() {
            @Override
            public void selected(View view, PopMenuMoreItem item, int position) {
                switch (item.id) {
                    case USER_SEARCH:
//                        startActivity(new Intent(this, UserSearchActivity.class));
                        break;
                    case USER_ADD:
//                        startActivity(new Intent(getActivity(), UserAddActivity.class));
                        break;
                }
            }
        });
    }
}
8、例子布局:activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin">

    <TextView
        android:id="@+id/hello_tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!" />
</RelativeLayout>

9、所需资源文件:

技术分享技术分享技术分享


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


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

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








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