安卓开发:自定义PopupWindow,实现模仿iOS底部弹出菜单

来源:互联网 发布:coc狂暴法术数据 编辑:程序博客网 时间:2024/05/16 01:09

先贴上效果图这里写图片描述
如图,从下面弹出菜单,菜单上面的item是可以扩展的。

先说一下思路,具体布局没啥难点,上面是一个可以扩展的布局,使用ListView和 RecyclerView都可以,我就用RecyclerView做例子了,下面的“取消”就是一个可以点击的按钮或者文字。。。

菜单的子项都是其中的一个item,当然我写的比较简单,满足项目需求,使用的时候还可以加上小图标。。。

先写item的布局,就一个文字,还有一条横线,最下面的item没有横线,所以也需要命名,最后一条要隐藏掉,代码贴上:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="46dp"    android:background="@drawable/selector_btn">    <TextView        android:id="@+id/item_popup_tv"        android:layout_width="match_parent"        android:layout_height="46dp"        android:gravity="center"        android:textColor="@color/blue"        android:textSize="16dp" />    <View        android:id="@+id/item_popup_line"        android:layout_width="match_parent"        android:layout_height="1px"        android:background="#c8c8c8"        android:layout_alignParentBottom="true" /></RelativeLayout>

很简单,就一个textview,一条线。

接下来开始写自定义PopupWindow的布局文件:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:gravity="bottom">    <View        android:id="@+id/popup_btm_bg"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_above="@+id/popup_btm_rv"        android:background="#60000000" />    <android.support.v7.widget.RecyclerView        android:id="@+id/popup_btm_rv"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_above="@+id/popup_btm_line"        android:background="@color/white" />    <View        android:id="@+id/popup_btm_line"        android:layout_width="match_parent"        android:layout_height="6dp"        android:layout_above="@+id/popup_btm_cancel_tv"        android:background="@color/tm_huise" />    <TextView        android:id="@+id/popup_btm_cancel_tv"        android:layout_width="match_parent"        android:layout_height="46dp"        android:layout_alignParentBottom="true"        android:background="@drawable/tm_selector_btn_anxia"        android:gravity="center"        android:text="取消"        android:textColor="@color/tm_blue"        android:textSize="16dp" /></RelativeLayout>

也很简单,上面半透明的view是为了实现半透明效果,点击此处也可以实现关闭PopupWindow,中间是一个RecyclerView,用来放我们定义的菜单项,下面的就是一条分割线和取消按钮了,点击“取消”就可以关闭PopupWindow了;

然后再来写RecyclerView的Adapter;自从用了RecyclerView,就迷上他了,不知道是不是心里作用,感觉RecyclerView比ListView效率高一些(好多大牛也这么说),话不多说,贴上Adapter代码

private class RvAdapter extends RecyclerView.Adapter<RvAdapter.ViewHolder> {        @Override        public int getItemCount() {            return datas.size();        }        @Override        public void onBindViewHolder(ViewHolder holder, final int position) {            holder.itemPopupTv.setText(datas.get(position));            //最后一条要隐藏分割线            holder.itemPopupLine.setVisibility(position + 1 == datas.size() ? View.GONE : View.VISIBLE);            //实现item的点击事件            holder.itemView.setOnClickListener(new View.OnClickListener() {                @Override                public void onClick(View v) {                    dismiss();                    itemClickListener.onItemClick(v, position);                }            });        }        @Override        public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {            View view = LayoutInflater.from(context).inflate(R.layout.item_custom_popup, parent, false);            ViewHolder viewHolder = new ViewHolder(view);            return viewHolder;        }        public class ViewHolder extends RecyclerView.ViewHolder {            private TextView itemPopupTv;            private View itemPopupLine;            public ViewHolder(View itemView) {                super(itemView);                itemPopupTv = (TextView) itemView.findViewById(R.id.item_popup_tv);                itemPopupLine = itemView.findViewById(R.id.item_popup_line);            }        }    }

最后,重头戏来了,万事俱备,就差PopupWindow代码了:

public class BottomPopupWindow extends PopupWindow {    private String TAG = "BottomPopupWindow";    private FragmentActivity context;    //RecyclerView的数据源    private List<String> datas;    //RecyclerView的item点击回调    private OnItemClickListener itemClickListener;    public BottomPopupWindow(FragmentActivity context, List<String> datas, OnItemClickListener itemClickListener) {        this.context = context;        this.datas = datas;        this.itemClickListener = itemClickListener;        foundPopup();    }    private void foundPopup() {        View contentView = View.inflate(context, R.layout.popup_custom_btm, null);        View popupBtmBg = contentView.findViewById(R.id.popup_btm_bg);        RecyclerView popupBtmRv = (RecyclerView) contentView.findViewById(R.id.popup_btm_rv);        TextView popupBtmCancelTv = (TextView) contentView.findViewById(R.id.popup_btm_cancel_tv);        LinearLayoutManager layoutManager = new LinearLayoutManager(context);        layoutManager.setAutoMeasureEnabled(true);        popupBtmRv.setLayoutManager(layoutManager);        setContentView(contentView);        setWidth(ViewGroup.LayoutParams.MATCH_PARENT);        setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);        //设置弹出动画        setAnimationStyle(R.style.popWindow_animation_anim);        //使其聚集 ,要想监听菜单里控件的事件就必须要调用此方法        setFocusable(true);        //设置允许在外点击消失        setOutsideTouchable(true);        //设置背景,点击back可消失        setBackgroundDrawable(new BitmapDrawable());        //PopupWindow的显示及位置设置        showAtLocation(contentView, Gravity.BOTTOM, 0, 0);        popupBtmRv.setAdapter(new RvAdapter());        //取消按钮-点击关闭        popupBtmCancelTv.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                dismiss();            }        });        //上部半透明背景-点击关闭        popupBtmBg.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                dismiss();            }        });    }}

RecyclerView的点击回调

public interface OnItemClickListener {    void onItemClick(View view, int position);}

这样,我们的可扩展的PopupWindow已经完工了,接下来说一下使用方法;
相信各位大牛已经看懂怎么是用了吧,初始化的时候把需要显示的item数据传递过来就可以了,然后做RecyclerView的Item点击事件就ok了。

使用如下:
首先需要初始化数据:

List<String> items = new ArrayList<>();                items.add("拍摄照片/视频");                items.add("从手机相册选择");                items.add("网页分享");

然后就可以调用了,因为我们在BottomPopupWindow里已经实现了各种情况下的关闭事件,所以,就不需要写show(),dismiss()方法了,

new BottomPopupWindow(context, items, new OnItemClickListener() {                    @Override                    public void onItemClick(View view, int position) {                            //position是从0开始的                        if (position == 0) {                           //这里处理点击第一个item的事件                        } else if (position == 1) {                           //这里处理点击第二个item的事件                        } else {                          //这里处理点击第n个item的事件,可以继续往下写,items有几个就可以实现几个                        }                        finish();                    }                });

就这样,拜拜,等会把代码传上去

原创粉丝点击