利用PopupWindow制作顶部下拉菜单

利用PopupWindow制作顶部下拉菜单

顶部最常见的筛选下拉菜单,每个菜单view可以自定义,进出动画等都可以自定义。效果如图.
完整的例子demo见GitHub: https://github.com/yinghuihou/PopupWindow

利用PopupWindow制作顶部下拉菜单_第1张图片

开始撸代码

  • 首先我们使用的控件是PopupWindow
  • 筛选栏就是一个自定义layout,一个LinearLayout包着三个TextView,很简单没什么可说的,xml如下
  • 最外层用标签是因为使用了DataBinding,可以省去findViewById这个操作,Java代码直接用 binding.xxx来获取控件



    

        

            

            
        

        

            

            

        

        

            

            
        
    


  • 开始写Java文件HotCreditCardSelectLayout.java
  • 首先就是对三个筛选item设置点击事件
  • 在这里有三个筛选项,所以我用了三个PopupWindow来操作,互不影响操作灵活一些
mBinding.allBank.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (mBankPopupwindow != null && mBankPopupwindow.isShowing()) {
                    dismissPopWindow(mBankPopupwindow);
                } else {
                    if (mBankPopupwindow == null) {
                        mBankPopupwindow = initmPopupWindowView(mData.bank, TYPE_BANK);
                    }
                    showPopWindow(TYPE_BANK, v);
                }
            }
        });
        mBinding.allTopic.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (mTopicPopupwindow != null && mTopicPopupwindow.isShowing()) {
                    dismissPopWindow(mTopicPopupwindow);
                } else {
                    if (mTopicPopupwindow == null) {
                        mTopicPopupwindow = initmPopupWindowView(mData.topic, TYPE_TOPIC);
                    }
                    showPopWindow(TYPE_TOPIC, v);
                }
            }
        });

        mBinding.more.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(final View v) {
                if (mMorePopupwindow != null && mMorePopupwindow.isShowing()) {
                    dismissPopWindow(mMorePopupwindow);
                } else {
                    if (mMorePopupwindow == null) {
                        mMorePopupwindow = initmPopupWindowView(mData);
                    }
                    showPopWindow(TYPE_MORE, v);
                }
            }
        });
  • 这里主要就是三个方法,dismissPopWindow,initmPopupWindowView,showPopWindow。这三个都是我封装过后的方法,很简单也很好理解
  • showPopWindow方法中的常量参数是为了根据不同的筛选项做不同的操作的,因为每个筛选项下拉出来的菜单view可能不一样

1. 生成下拉菜单 initmPopupWindowView

这里我写了两个一样的方法,因为前两个菜单是listview下拉菜单,最后一个是自定义RadioButton单选菜单

  • 先看生成listview的下拉菜单方法
 private PopupWindow initmPopupWindowView(final List list, final int type) {
        // 获取popwindow布局文件的视图
        View customView = LayoutInflater.from(getContext()).inflate(R.layout.layout_popwindow_list_view,
                null, false);
        MaxHeightListView listView = customView.findViewById(R.id.list_view);
        //填充数据
        if (type == TYPE_BANK) {
            mBankAdapter = new CardSelectAdapter(getContext());
            mBankAdapter.setList(list);
            listView.setAdapter(mBankAdapter);
        } else if (type == TYPE_TOPIC) {
            mTopicAdapter = new CardSelectAdapter(getContext());
            mTopicAdapter.setList(list);
            listView.setAdapter(mTopicAdapter);
        }

        final PopupWindow popupwindow = generatePopupWindow(customView);
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView parent, View view, int position, long id) {
                if (mListener == null) {
                    return;
                }
                if (type == TYPE_BANK) {
                    mParams.put("bank_id", String.valueOf(list.get(position).id));
                    mBinding.allBank.setText(list.get(position).value);
                    mListener.onItemClick(mParams);
                } else if (type == TYPE_TOPIC) {
                    mParams.put("topic_id", String.valueOf(list.get(position).id));
                    mBinding.allTopic.setText(list.get(position).value);
                    mListener.onItemClick(mParams);
                }
                if (popupwindow != null && popupwindow.isShowing()) {
                    dismissPopWindow(popupwindow);
                }
            }
        });
        return popupwindow;
    }

这里向listview中填充数据就不用多说,最基本的。listview的点击事件,选中时将对应选中的id加入map,请求页面数据使用

2.生成更多页面的popupWindow方法

这里的view可以自己定义,数据填充方法都不相同,页面效果图是这样的

利用PopupWindow制作顶部下拉菜单_第2张图片

代码如下

//生成更多页面的Window
    private PopupWindow initmPopupWindowView(HotCreditCardPageData.Select data) {
        // 获取自定义布局文件pop.xml的视图
        moreItemBinding = DataBindingUtil.inflate(LayoutInflater.from(getContext()), R.layout.layout_popwindow_custom_view,
                null, false);
        //填充数据
        moreItemBinding.cardLevel.setText(data.level_title);
        moreItemBinding.cardAnnualFee.setText(data.annual_fee_title);
        setMoreViewData(data.level, moreItemBinding.cardLevelContent, TYPE_LEVEL);
        setMoreViewData(data.annual_fee, moreItemBinding.cardAnnualFeeContent, TYPE_FEE);
        final PopupWindow popupwindow = generatePopupWindow(moreItemBinding.getRoot());
        moreItemBinding.confirm.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                int levelId = moreItemBinding.cardLevelContent.getCheckedRadioButtonId();
                int annualFeeId = moreItemBinding.cardAnnualFeeContent.getCheckedRadioButtonId();
                if (levelId == -1) {
                    mParams.put("level_id", "0");
                } else {
                    mParams.put("level_id", String.valueOf(levelId));
                }
                if (annualFeeId == -1) {
                    mParams.put("annual_fee", "0");
                } else {
                    mParams.put("annual_fee", String.valueOf(annualFeeId));
                }
                if (mListener != null) {
                    mListener.onItemClick(mParams);
                }
                if (popupwindow != null && popupwindow.isShowing()) {
                    dismissPopWindow(popupwindow);
                }
            }
        });
        return popupwindow;
    }

这里不要在乎填充数据的方法,可以自行扩展。这里和上个一样都有一个共同的方法generatePopupWindow。这个方法是生成Window的核心方法

代码如下

//根据view初始化popupWindow
    public PopupWindow generatePopupWindow(View customView) {
        final PopupWindow popupwindow = new PopupWindow(customView,
                LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
        popupwindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
        popupwindow.setOutsideTouchable(false);
        popupwindow.setAnimationStyle(R.style.popup_animation);
        popupwindow.setFocusable(false);
        //弹出框消失,筛选条颜色和箭头归位
        popupwindow.setOnDismissListener(new PopupWindow.OnDismissListener() {
            @Override
            public void onDismiss() {
                resetSelectView();
            }
        });
        return popupwindow;
    }
  • 这里一定要注意,setOutsideTouchable一定要置为false,是为了点击Window外部区域自身不消失,因为这样我们可以很灵活的控制Window的消失时机
  • 同时,setFocusable(false)也很重要,因为如果设置为true,在三个item之间切换时候,Window会点击一下先消失,再次点击才弹出
  • resetSelectView()这个方法是让Window消失时候标题颜色设置为黑色,并且小箭头归位用的,可以无视

3.showPopWindow方法

在点击筛选item时候,如果当前对应的Window在显示,则收起自己的Window,如果别的item对应的Window在显示,则先收起所有Window,在显示自己的Window

public void showPopWindow(int type, View view) {
        //取消所有在显示的Window
        dismissAllPopWindow();
        String selectItemText = "";
        switch (type) {
            case TYPE_BANK:
                selectItemText = mBinding.allBank.getText().toString();
                mBankPopupwindow.showAsDropDown(view);
                setOpenState(mBinding.allBank, mBinding.bankImg);
                mBankAdapter.setSelectItem(selectItemText);
                break;
            case TYPE_TOPIC:
                selectItemText = mBinding.allTopic.getText().toString();
                mTopicPopupwindow.showAsDropDown(view);
                setOpenState(mBinding.allTopic, mBinding.topicImg);
                mTopicAdapter.setSelectItem(selectItemText);
                break;
            case TYPE_MORE:
                setOpenState(mBinding.more, mBinding.moreImg);
                mMorePopupwindow.showAsDropDown(view);
                break;
            default:
                break;
        }
        if (mListener != null) {
            mListener.onSelectTitleClick();
        }
    }
  • setOpenState方法就是对应的Window展开时候筛选item颜色变为蓝色,箭头变换方向的动作

4.dismissPopWindow这个就很简单了

//关闭单个popWindow
    public void dismissPopWindow(PopupWindow popupWindow) {
        popupWindow.dismiss();
        if (mListener != null) {
            mListener.closeBackground();
        }
    }

    public void dismissAllPopWindow() {
        if (mBankPopupwindow != null && mBankPopupwindow.isShowing()) {
            mBankPopupwindow.dismiss();
        }
        if (mTopicPopupwindow != null && mTopicPopupwindow.isShowing()) {
            mTopicPopupwindow.dismiss();
        }
        if (mMorePopupwindow != null && mMorePopupwindow.isShowing()) {
            mMorePopupwindow.dismiss();
        }
    }

最后附加上下拉菜单进出的动画,需要的直接复制即可

设置展开收起动画是在初始化PopupWindow时候直接设置的xml文件,这样设置setAnimationStyle:

popupwindow.setOutsideTouchable(false);
popupwindow.setAnimationStyle(R.style.popup_animation);
popupwindow.setFocusable(false);

然后在style.xml里定义进出动画:

    

最后在res下的anim文件夹里自定义你的进出动画文件即可:
dialog_in.xml




    
    

    

dialog_out.xml:




    
    

    


完整的demo例子在GitHub

https://github.com/yinghuihou/PopupWindow

刚开始写博客写的不好大家将就着看看吧,有疑问或者意见可留言

你可能感兴趣的:(Android,Android,下拉菜单,PopupWindow)