Android自定义上下文菜单

来源:互联网 发布:php 编译 sass 编辑:程序博客网 时间:2024/06/12 23:51

今天自定义了一个简单的Android菜单控件。实现方式是:PopupWindow和ListView。
现在来给大家分享一下源码:

SHContextMenu.java

核心代码部分:主要是对PopupWindow和ListView的初始化,为ListView设置数据源,以及封装了菜单的显示和隐藏的方法。还有提供了菜单的点击回调。

import android.app.Activity;import android.content.Context;import android.graphics.Rect;import android.graphics.drawable.BitmapDrawable;import android.view.Gravity;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.AdapterView;import android.widget.BaseAdapter;import android.widget.ImageView;import android.widget.ListView;import android.widget.PopupWindow;import android.widget.TextView;import com.eroad.ehr.R;import com.eroad.product.bean.ContextMenuItem;import java.util.ArrayList;import java.util.List;/** * 自定义上下文菜单 * Created by MaJian on 16/4/28. */public class SHContextMenu {    private Context mContext;    private List<ContextMenuItem> itemList;    private PopupWindow popupWindow;    private View contentView;    private ListView mLvMenuList;    private MenuAdapter menuAdapter;    private OnItemSelectListener onItemSelectListener;    public interface OnItemSelectListener{        void onItemSelect(int position);    }    public void setOnItemSelectListener(OnItemSelectListener onItemSelectListener){        this.onItemSelectListener = onItemSelectListener;    }    public SHContextMenu(Context mContext){        this.mContext = mContext;        itemList = new ArrayList<>();        initPopWindow();    }    /**     * 初始化popwindow菜单     */    private void initPopWindow(){        contentView = LayoutInflater.from(mContext).inflate(R.layout.popwindow_menu, null);        popupWindow = new PopupWindow(contentView, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);        popupWindow.setFocusable(true);        popupWindow.setOutsideTouchable(true);        // 这个是为了点击“返回Back”也能使其消失,并且并不会影响你的背景        popupWindow.setBackgroundDrawable(new BitmapDrawable());        popupWindow.setAnimationStyle(R.style.PopupAnimation);        mLvMenuList = (ListView) contentView.findViewById(R.id.lv_menu);        menuAdapter = new MenuAdapter();        mLvMenuList.setAdapter(menuAdapter);        mLvMenuList.setOnItemClickListener(new AdapterView.OnItemClickListener() {            @Override            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {                if (onItemSelectListener != null){                    onItemSelectListener.onItemSelect(position);                }                popupWindow.dismiss();            }        });    }    /**     * 设置菜单列表数据源     * @param itemList     */    public void setItemList(List<ContextMenuItem> itemList){        this.itemList = itemList;        menuAdapter.notifyDataSetChanged();    }    public void showMenu(View view){        if (popupWindow == null)            return;        int[] location = new int[2];        view.getLocationInWindow(location);        // 状态栏的高度        Rect frame = new Rect();        ((Activity)mContext).getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);        popupWindow.showAtLocation(((Activity)mContext).getWindow().getDecorView(), Gravity.TOP|Gravity.RIGHT, 0, ((Activity)mContext).getActionBar().getHeight()+frame.top-27);    }    /**     * 上下文菜单列表适配器     */    class MenuAdapter extends BaseAdapter{        /**         * How many items are in the data set represented by this Adapter.         *         * @return Count of items.         */        @Override        public int getCount() {            return itemList == null ? 0 : itemList.size();        }        /**         * Get the data item associated with the specified position in the data set.         *         * @param position Position of the item whose data we want within the adapter's         *                 data set.         * @return The data at the specified position.         */        @Override        public Object getItem(int position) {            return itemList.get(position);        }        /**         * Get the row id associated with the specified position in the list.         *         * @param position The position of the item within the adapter's data set whose row id we want.         * @return The id of the item at the specified position.         */        @Override        public long getItemId(int position) {            return position;        }        /**         * Get a View that displays the data at the specified position in the data set. You can either         * create a View manually or inflate it from an XML layout file. When the View is inflated, the         * parent View (GridView, ListView...) will apply default layout parameters unless you use         * {@link LayoutInflater#inflate(int, ViewGroup, boolean)}         * to specify a root view and to prevent attachment to the root.         *         * @param position    The position of the item within the adapter's data set of the item whose view         *                    we want.         * @param convertView The old view to reuse, if possible. Note: You should check that this view         *                    is non-null and of an appropriate type before using. If it is not possible to convert         *                    this view to display the correct data, this method can create a new view.         *                    Heterogeneous lists can specify their number of view types, so that this View is         *                    always of the right type (see {@link #getViewTypeCount()} and         *                    {@link #getItemViewType(int)}).         * @param parent      The parent that this view will eventually be attached to         * @return A View corresponding to the data at the specified position.         */        @Override        public View getView(int position, View convertView, ViewGroup parent) {            ViewHolder viewHolder = null;            if (convertView == null){                viewHolder = new ViewHolder();                convertView = LayoutInflater.from(mContext).inflate(R.layout.popmenu_item, null);                viewHolder.mIvIcon = (ImageView) convertView.findViewById(R.id.iv_icon);                viewHolder.mTvTitle = (TextView) convertView.findViewById(R.id.tv_title);                viewHolder.mViewDivider = convertView.findViewById(R.id.view_divider);                convertView.setTag(viewHolder);            } else {                viewHolder = (ViewHolder) convertView.getTag();            }            viewHolder.mTvTitle.setText(itemList.get(position).getTitle());            viewHolder.mIvIcon.setImageDrawable(itemList.get(position).getImgDrawable());//            convertView.setBackgroundColor(Color.parseColor(itemList.get(position).getColorString()));            if (position == itemList.size() - 1){                viewHolder.mViewDivider.setVisibility(View.INVISIBLE);            } else {                viewHolder.mViewDivider.setVisibility(View.VISIBLE);            }            return convertView;        }        class ViewHolder{            TextView mTvTitle;            ImageView mIvIcon;            View mViewDivider;        }    }}

popwindow_menu.xml

PopupWindow 的布局文件

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:orientation="vertical"    android:layout_width="wrap_content"    android:layout_height="match_parent">    <ListView        android:layout_width="180dp"        android:layout_height="match_parent"        android:id="@+id/lv_menu"        android:divider="@null"      android:background="@drawable/ic_bg_contextmenu">    </ListView></LinearLayout>

PopupWindow展现样式

<style name="PopupAnimation" parent="android:Animation" mce_bogus="1">        <item name="android:windowEnterAnimation">@anim/anim_popmenu_show</item>        <item name="android:windowExitAnimation">@anim/anim_popmenu_hide</item>    </style>

菜单隐藏的动画anim_popmenu_hide.xml

<?xml version="1.0" encoding="utf-8"?><set xmlns:android="http://schemas.android.com/apk/res/android">    <scale android:fromXScale="1.0" android:toXScale="1.25"        android:fromYScale="1.0" android:toYScale="1.25" android:pivotX="100%"        android:pivotY="0%" android:duration="200" />    <scale android:fromXScale="1.0" android:toXScale="0.48"        android:fromYScale="1.0" android:toYScale="0.48" android:pivotX="100%"        android:pivotY="0%" android:duration="400" android:delay="200" />    <alpha android:interpolator="@android:anim/linear_interpolator"        android:fromAlpha="1.0" android:toAlpha="0.0" android:duration="400" /></set>

菜单显示的动画anim_popmenu_show.xml

<?xml version="1.0" encoding="utf-8"?><set xmlns:android="http://schemas.android.com/apk/res/android">    <scale android:fromXScale="0.6" android:toXScale="1.1"        android:fromYScale="0.6" android:toYScale="1.1" android:pivotX="100%"        android:pivotY="0%" android:duration="200" />    <scale android:fromXScale="1.0" android:toXScale="0.91"        android:fromYScale="1.0" android:toYScale="0.91" android:pivotX="100%"        android:pivotY="0%" android:duration="400" android:delay="200" />    <alpha android:interpolator="@android:anim/linear_interpolator"        android:fromAlpha="0.0" android:toAlpha="1.0" android:duration="400" /></set>

上下文菜单Item的Bean

package com.eroad.product.bean;import android.graphics.drawable.Drawable;/** * 上下文菜单项对象 * Created by MaJian on 16/4/28. */public class ContextMenuItem {    private Drawable imgDrawable;    private String title;    private boolean visible;    private String colorString;    public ContextMenuItem(Drawable imgDrawable, String title, boolean visible, String colorString) {        this.imgDrawable = imgDrawable;        this.title = title;        this.visible = visible;        this.colorString = colorString;    }    public String getColorString() {        return colorString;    }    public void setColorString(String colorString) {        this.colorString = colorString;    }    public boolean isVisible() {        return visible;    }    public void setVisible(boolean visible) {        this.visible = visible;    }    public String getTitle() {        return title;    }    public void setTitle(String title) {        this.title = title;    }    public Drawable getImgDrawable() {        return imgDrawable;    }    public void setImgDrawable(Drawable imgDrawable) {        this.imgDrawable = imgDrawable;    }}

现在和大家说一下菜单的调用方式

SHContextMenu shContextMenu = new SHContextMenu(getActivity());                List<ContextMenuItem> itemList = new ArrayList<>();                itemList.add(new ContextMenuItem(getResources().getDrawable(R.drawable.ic_create_company), "草稿", true, "#FFFFFF"));                itemList.add(new ContextMenuItem(getResources().getDrawable(R.drawable.ic_create_company), "草稿", true, "#FFFFFF"));                itemList.add(new ContextMenuItem(getResources().getDrawable(R.drawable.ic_create_company), "草稿", true, "#FFFFFF"));                itemList.add(new ContextMenuItem(getResources().getDrawable(R.drawable.ic_create_company), "草稿", true, "#FFFFFF"));                itemList.add(new ContextMenuItem(getResources().getDrawable(R.drawable.ic_create_company), "草稿", true, "#FFFFFF"));                shContextMenu.setItemList(itemList);                shContextMenu.setOnItemSelectListener(new SHContextMenu.OnItemSelectListener() {                    @Override                    public void onItemSelect(int position) {                        SHToast.showToast(getActivity(), position + "");                    }                });                shContextMenu.showMenu(et_search);

当然最后是大家最关心的效果图:
这里写图片描述

1 0
原创粉丝点击