Android仿IOS封装通用的弹出框Dialog和底部弹出列表选择框 仿美团顶部条件筛选框 附自定义ViewGroup

背景

鉴于Android提供的默认弹出框很一般,IOS的弹出框样式还不错,同时使用弹出框dialog的需求还是蛮高的,于是就想仿照ios弹出框封装一个通用的dialog,解决操作询问,提示信息,列表选择等需求;同时在搜索数据的时候,需要选择条件,也是使用弹出框解决,类似于美团的顶部筛选框,今天就来封装下

提示与询问弹出框

为了解决确认、取消这种询问性的需求,还有提示性的需求,我们使用Dialog来仿一个ios式的弹出框,样式简洁大方,效果如图:

在这里插入图片描述
在这里插入图片描述

实现

主要还是自定义一个类继承Dialog,实现比较简单,如下

package com.mango.dialog;


import android.app.Dialog;
import android.content.Context;
import android.graphics.drawable.ColorDrawable;
import android.text.TextUtils;
import android.view.Gravity;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.mango.dialog.listener.OnOptionListener;
import com.mango.dialog.utils.DisplayUtil;


/**
 * @ClassName mango
 * @Description TODO(操作询问框 提示框)
 * @author cxy
 * @Date 2019/6/27 15:19
 */
public class OptionAskDialog extends Dialog implements View.OnClickListener {

    private String TAG = "OptionAskDialog";

    private Context mContext;

    private TextView tv_title;
    private TextView tv_content;
    private Button btn_sure;
    private Button btn_cancle;
    private LinearLayout ll_title;
    private View line;

    private OnOptionListener livingSure;
    private String typeResult;

    private OptionAskDialog(Context context) {
        super(context);
        mContext = context;
        View view = View.inflate(context, R.layout.dialog_ask,null);
        setContentView(view);
        findViewId(view);
        initWindow();
    }

    private OptionAskDialog(Context context, int themeResId) {
        super(context, themeResId);
        mContext = context;
        View view = View.inflate(context, R.layout.dialog_ask,null);
        setContentView(view);
        findViewId(view);
        initWindow();
        initClick();
    }

    private void initClick() {
        btn_sure.setOnClickListener(this);
        btn_cancle.setOnClickListener(this);
    }

    private void findViewId(View view) {
        tv_title = (TextView) view.findViewById(R.id.tv_title);
        tv_content = (TextView) view.findViewById(R.id.tv_content);
        btn_sure = (Button) view.findViewById(R.id.btn_sure);
        btn_cancle = (Button) view.findViewById(R.id.btn_cancle);
        ll_title = (LinearLayout) view.findViewById(R.id.ll_title);
        line = view.findViewById(R.id.line);
    }

    private void initView(String title_dialog,String content_dialog,String btn_left,String btn_right) {
        if (!TextUtils.isEmpty(title_dialog)) {
            tv_title.setText(title_dialog);
        }
        if (!TextUtils.isEmpty(content_dialog)) {
            tv_content.setText(content_dialog);
        }
        if (!TextUtils.isEmpty(btn_left)) {
            btn_sure.setText(btn_left);
        }
        if (!TextUtils.isEmpty(btn_right)) {
            btn_cancle.setText(btn_right);
        }
    }

    /**
     * 设置dialog的背景、宽度、位置
     */
    private void initWindow() {
        Window dialogWindow = getWindow();
        dialogWindow.setBackgroundDrawable(new ColorDrawable(0));
        dialogWindow.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN
                | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
        WindowManager.LayoutParams lp = dialogWindow.getAttributes();
        lp.width = (int) (DisplayUtil.getScreenWidth(mContext) * 0.8);
        lp.gravity = Gravity.CENTER;
        dialogWindow.setAttributes(lp);
    }

    /**
     * 是否隐藏标题
     * @param isShow
     */
    private void setTitleVisible(boolean isShow) {
        if (isShow) {
            ll_title.setVisibility(View.VISIBLE);
            line.setVisibility(View.VISIBLE);
            btn_cancle.setVisibility(View.VISIBLE);
            btn_sure.setText(R.string.ok);
            btn_sure.setBackgroundResource(R.drawable.selector_askdialog_ok);
        } else {
            ll_title.setVisibility(View.GONE);
            line.setVisibility(View.GONE);
            btn_cancle.setVisibility(View.GONE);
            btn_sure.setText(R.string.i_know);
            btn_sure.setBackgroundResource(R.drawable.selector_askdialog_fullok);
        }
    }

    private void initListener(OnOptionListener livingSure, String typeResult){
        this.livingSure = livingSure;
        this.typeResult = typeResult;
    }

    /**
     * 点击确定按钮
     */
    public void clickSure(){
        if (livingSure != null) {
            livingSure.onOptionSure(typeResult);
        }
        dismiss();
    }

    /**
     * 点击取消按钮
     */
    public void clickCancle(){
        if (livingSure != null) {
            livingSure.onOptionCancle(typeResult);
        }
        dismiss();
    }

    @Override
    public void onClick(View v) {
        if (v.getId() == R.id.btn_cancle) {
            clickCancle();
        } else {
            clickSure();
        }
    }

    public static class Bulid{

        private Context mContext;
        private String title_dialog;
        private String content_dialog;
        private String btn_left;
        private String btn_right;
        private String typeResult;
        private OnOptionListener optionListener;
        private int themeResId;
        private boolean isShowTitle = true;

        public Bulid(Context context, int themeResId) {
            mContext = context;
            this.themeResId = themeResId;
        }

        public Bulid setShowTitle(boolean showTitle) {
            isShowTitle = showTitle;
            return this;
        }

        public Bulid setTitle_dialog(int title_dialog) {
            this.title_dialog = mContext.getResources().getString(title_dialog);
            return this;
        }

        public Bulid setTitle_dialog(String title_dialog) {
            this.title_dialog = title_dialog;
            return this;
        }

        public Bulid setContent_dialog(int content_dialog) {
            this.content_dialog = mContext.getResources().getString(content_dialog);
            return this;
        }

        public Bulid setContent_dialog(String content_dialog) {
            this.content_dialog = content_dialog;
            return this;
        }

        public Bulid setBtn_left(int btn_left) {
            this.btn_left = mContext.getResources().getString(btn_left);
            return this;
        }

        public Bulid setBtn_right(int btn_right) {
            this.btn_right = mContext.getResources().getString(btn_right);
            return this;
        }

        public Bulid setOptionListener(OnOptionListener optionListener, String typeResult) {
            this.optionListener = optionListener;
            this.typeResult = typeResult;
            return this;
        }

        public OptionAskDialog create(){

            OptionAskDialog ackDialog;
            if (themeResId == 0) {
                ackDialog = new OptionAskDialog(mContext);
            } else {
                ackDialog = new OptionAskDialog(mContext,themeResId);
            }
            ackDialog.initView(title_dialog,content_dialog,btn_left,btn_right);
            ackDialog.setTitleVisible(isShowTitle);
            ackDialog.initListener(optionListener,typeResult);
            return ackDialog;
        }

    }

}

使用

    public void showTitle(View v) {
        new OptionAskDialog
                .Bulid(this,R.style.Dialog)
                .setOptionListener(this,"1")
                .setTitle_dialog(R.string.dialog_title)
                .setContent_dialog(R.string.dialog_content)
                .create()
                .show();

    }

    public void showNoTitle(View v){
        new OptionAskDialog
                .Bulid(this,R.style.Dialog)
                .setShowTitle(false)
                .setOptionListener(this,"2")
                .setTitle_dialog(R.string.dialog_title)
                .setContent_dialog(R.string.dialog_content_sure)
                .create()
                .show();
    }

列表选择框

有时候你需要向用户提供一些选项,让用户从列表中选择,如果还是像上面这种就比较丑了;可以设计成从底部弹出,如图:
在这里插入图片描述

实现

第一步:定义Dialog

public class OptionSheetDialog implements AdapterView.OnItemClickListener {

    private WeakReference<Context> mContext;
    private Dialog dialog;

    private RelativeLayout rl_content;
    private TextView txt_title;
    private TextView txt_cancel;

    private ListView mListview;
    private BaseAdapter adapter;
    private float scale;

    private OnItemClickListener onItemClickListener;

    public OptionSheetDialog(Context context) {
        this.mContext = new WeakReference<>(context);
        scale = DisplayUtil.getDensity(mContext.get());
    }

    public OptionSheetDialog builder() {
        // 获取Dialog布局
        View view = LayoutInflater.from(mContext.get()).inflate(R.layout.dialog_sheet, null);

        // 获取自定义Dialog布局中的控件
        rl_content = (RelativeLayout) view.findViewById(R.id.rl_content);
        mListview = (ListView) view.findViewById(R.id.lv);
        mListview.setOnItemClickListener(this);
        txt_title = (TextView) view.findViewById(R.id.txt_title);
        txt_cancel = (TextView) view.findViewById(R.id.txt_cancel);
        txt_cancel.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                dialog.dismiss();
            }
        });

        // 定义Dialog布局和参数
        dialog = new Dialog(mContext.get(), R.style.ActionSheetDialogStyle);
        dialog.setContentView(view);

        //设置显示坐标、位置、宽度
        Window dialogWindow = dialog.getWindow();
        dialogWindow.setGravity(Gravity.BOTTOM);
        WindowManager.LayoutParams lp = dialogWindow.getAttributes();
        lp.x = 0;
        lp.y = 0;
        lp.width = DisplayUtil.getScreenWidth(mContext.get()) - (int)(16*scale + 0.5f);
        dialogWindow.setAttributes(lp);

        return this;
    }
}

第二步:既然有LitView,那肯定需要adapter

    public OptionSheetDialog setAdapter(BaseAdapter adapter) {
        this.adapter = adapter;
        return this;
    }

第三步:现在需要考虑这个弹出框的高度问题了,既然是ListView,那它的item数量可能只有一个,两个…100个,所以肯定不能有多少个item,dialog就有多高,需要进行动态设置

    /**
     * 根据item数量动态设置listview的高度
     * item数量在5个以下,高度由item个数决定
     * item数量在5个及以上,高度固定是5个item高度总和
     */
    private void setSheetItems() {

        int height = (int) (LISTVIEW_ITEM_HEIGHT * scale + 0.5f);
        int totalHeight;
        RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) mListview.getLayoutParams();

        if (adapter.getCount() >= MAX_ITEM_HEIGHT) {
            params.height = height * MAX_ITEM_HEIGHT;
            totalHeight = height * MAX_ITEM_HEIGHT;
            mListview.setLayoutParams(params);
        } else {
            params.height = height * adapter.getCount();
            totalHeight = height * adapter.getCount();
            mListview.setLayoutParams(params);
        }

        ViewGroup.LayoutParams vl =  rl_content.getLayoutParams();
        vl.height = (int) (DIALOG_TITLE_HEIGHT * scale + 0.5f) + totalHeight + (int) (DIALOG_CANCLE_HEIGHT * scale + 0.5f);
        rl_content.setLayoutParams(vl);

        mListview.setAdapter(adapter);
    }

第四步:就是显示弹出框了,不过在show之前,调用下setSheetItems方法

    public void show() {
        setSheetItems();
        dialog.show();
    }

使用

    private List<SheetItem> itemList = new ArrayList<>();
    private List<SheetItem> moreItemList = new ArrayList<>();
    private SheetAdapter sheetAdapter;
    
    itemList.add(new SheetItem("清空消息列表",R.color.sheet_red));
    
    moreItemList.add(new SheetItem("发送给好友",R.color.sheet_blue));
    moreItemList.add(new SheetItem("转载到空间相册",R.color.sheet_blue));
    moreItemList.add(new SheetItem("上传到群相册",R.color.sheet_blue));
    moreItemList.add(new SheetItem("保存到手机",R.color.sheet_blue));
    moreItemList.add(new SheetItem("发送到朋友圈",R.color.sheet_blue));
    moreItemList.add(new SheetItem("查看聊天图片",R.color.sheet_blue));
    
    sheetAdapter = new SheetAdapter(this);
    
    
    public void showSheet(View v){

        sheetAdapter.setItemList(itemList);
        new OptionSheetDialog(MainActivity.this)
                .builder()
                .setTitle("清空消息列表后,聊天记录依然保留,确定要清空消息列表?")
                .setCancelable(true)
                .setCanceledOnTouchOutside(true)
                .setAdapter(sheetAdapter)
                .setOnItemClickListener(this)
                .show();
    }

    public void showMoreSheet(View v){

        sheetAdapter.setItemList(moreItemList);
        new OptionSheetDialog(MainActivity.this)
                .builder()
                .setTitle("请选择操作")
                .setCancelable(true)
                .setCanceledOnTouchOutside(true)
                .setAdapter(sheetAdapter)
                .setOnItemClickListener(this)
                .show();
    }

顶部条件筛选框

这种弹出框比较适合选择条件搜索的需求,而且是分类别的条件,比如你在美团上搜外卖,按条件搜商家;在淘宝京东上按条件搜商品等;如图:
在这里插入图片描述

具体实现前分析下实现思路:

首先可以确定使用PopupWindow来作为弹出框的载体,易于显示位置的确定

弹出框内容分为两部分:第一部分是条件展示,可以使用ListView来显示条件列表;第二部分是按钮操作,处于弹出框底部,用两个Button或者Textview就行了

其中第二部分很简单,主要是第一部分,条件是分类别的,然后类别下又分很多子选项,所以把类别和子选项一起作为Item;其中子选项可以是一个自定义ViewGroup,显示众多子选项

其实第一部分也可以是一个ScrollView,然后开发者可以往里动态添加自己编写的各式各样的Item,这样扩展性更强,更灵活;我这里是从通用性和简易型角度考虑选择了上面使用ListView的方案

实现

先封装 搜索条件对象,这个对象主要包括类型及包括的条件

/**
 * @Description TODO(搜索条件对象)
 * @author cxy
 * @Date 2019/6/28 11:51
 */
public class FilterTypeBean {

    /**
     * 筛选条件所属的类型
     */
    private String typeName;
    /**
     * 包含的条件
     */
    private List<Condition> children;

    public String getTypeName() {
        return typeName;
    }

    public void setTypeName(String typeName) {
        this.typeName = typeName;
    }

    public List<Condition> getChildren() {
        return children;
    }

    public void setChildren(List<Condition> children) {
        this.children = children;
    }

    public static class Condition {
        //条件名称
        private String value;
        //是否选中
        private boolean isSelected = false;

        public String getValue() {
            return value;
        }

        public void setValue(String value) {
            this.value = value;
        }

        public boolean isSelected() {
            return isSelected;
        }

        public void setSelected(boolean selected) {
            isSelected = selected;
        }
    }

}

接下来需要重新定义下ListView,因为它的高度决定了弹出框的高度,我给它指定高度

/**
 * @Description TODO()
 * @author cxy
 * @Date 2019/6/28 10:52
 */
public class FixedHeightListView extends ListView {

    private Context mContext;

    public FixedHeightListView(Context context) {
        this(context, null);
    }

    public FixedHeightListView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public FixedHeightListView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    private void init(Context context) {
        mContext = context;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        try {
            /**
             * 设置ListView高度不能超过屏幕高度一半
             * 因为下面有按钮,所以使用屏幕一半高度减去100
             */
            heightMeasureSpec = MeasureSpec.makeMeasureSpec(DisplayUtil.getScreenHeight(mContext) / 2 - 100, MeasureSpec.AT_MOST);
        } catch (Exception e) {
            e.printStackTrace();
        }
        //重新计算控件高、宽
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
}

自定义ViewGroup

到这一步就需要自定义ViewGroup了,摆放搜索条件;自定义ViewGroup主要有两件事:第一就是重写onMeasure方法测量子控件的宽高和自己的宽高,第二就是重写onLayout方法摆放子控件的位置

先重写onMeasure方法,这里需要考虑viewGroup的宽度,同时高度需要考虑使用多少行来展示子view

    /**
     * 测量子view大小 和自己大小
     * @param widthMeasureSpec
     * @param heightMeasureSpec
     */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        //从约束规范中获取尺寸
        int sizeWidth = MeasureSpec.getSize(widthMeasureSpec);
        //获取测量规格
        int modeWidth = MeasureSpec.getMode(widthMeasureSpec);
        int sizeHeight = MeasureSpec.getSize(heightMeasureSpec);
        int modeHeight = MeasureSpec.getMode(heightMeasureSpec);

        //viewgroup的宽度
        int width = 0;
        //viewgroup的高度
        int height = 0;

        //一行子view的宽度之和
        int lineWidth = 0;
        //一行子view的高
        int lineHeight = 0;

        //获取子view数量
        int count = getChildCount();

        for (int i = 0; i < count; i++) {
            View child = getChildAt(i);
            //如果子View设置了GONE属性,就跳过
            if (child.getVisibility() == View.GONE) {
                //计算viewgroup宽高
                if (i == count - 1) {
                    width = Math.max(lineWidth, width);
                    height += lineHeight;
                }
                continue;
            }
            //计算这个子view的大小
            measureChild(child, widthMeasureSpec, heightMeasureSpec);
            MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
            //设置子view的margin
            lp.leftMargin = 10;
            lp.rightMargin = 10;
            lp.topMargin = 10;
            lp.bottomMargin = 10;

            //计算子view的宽高
            int childWidth = child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin;
            int childHeight = child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin;

            /**
             * 1.如果算出来的子view宽度和 > ViewGroup能使用的宽度值,那就说明需要重启一行显示了,就需要重新计算ViewGroup的宽高及每行的宽高
             *   那就取width和lineWidth最大值并赋值给width,即一行的宽度或者说ViewGroup的宽度
             *   新的一行的宽度lineWidth就重置为子view宽度childWidth,下一行第一个子view
             *   ViewGroup的高度height等于与每行高度lineHeight之和
             *   同时新的一行的高度lineHeight重置为子view的高度
             *
             * 2.如果算出来的子view宽度和 <= ViewGroup能使用的宽度值,说明这些子view可以摆在同一行
             *   那么一行宽度lineWidth等于子view宽度之和
             *   一行lineHeight取子view高度和上一行高度lineHeight最大值
             */
            if (lineWidth + childWidth > sizeWidth - getPaddingLeft() - getPaddingRight()) {
                width = Math.max(width, lineWidth);
                lineWidth = childWidth;
                height += lineHeight;
                lineHeight = childHeight;
            } else {
                lineWidth += childWidth;
                lineHeight = Math.max(lineHeight, childHeight);
            }

            /**
             * 当最后一个子view计算完了
             * viewGroup的宽度取lineWidth和width最大值
             * viewGroup的高度取前面N行高度+最后一行高度
             */
            if (i == count - 1) {
                width = Math.max(lineWidth, width);
                height += lineHeight;
            }
        }
        /**
         * 保存测量后的宽高
         * 如果指定了ViewGroup的宽高,那就用指定的宽高
         * 否则使用测量出来的宽高值
         */
        setMeasuredDimension(
                modeWidth == MeasureSpec.EXACTLY ? sizeWidth : width + getPaddingLeft() + getPaddingRight(),
                modeHeight == MeasureSpec.EXACTLY ? sizeHeight : height + getPaddingTop() + getPaddingBottom()
        );

    }

然后重写onLayout方法,摆放每一个子view,具体要算出每个子view的上下左右四个值,换行时要重新计算left值和top值

    /**
     * 摆放子view的位置
     * @param changed
     * @param l
     * @param t
     * @param r
     * @param b
     */
    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        mAllViews.clear();
        mLineHeight.clear();
        mLineWidth.clear();
        lineViews.clear();

        //viewgroup宽度
        int width = getWidth();
        //一行宽度
        int lineWidth = 0;
        //一行高度
        int lineHeight = 0;
        //子view数量
        int count = getChildCount();

        for (int i = 0; i < count; i++) {
            View child = getChildAt(i);
            if (child.getVisibility() == View.GONE) {
                continue;
            }
            MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();

            int childWidth = child.getMeasuredWidth();
            int childHeight = child.getMeasuredHeight();

            /**
             * 如果已经计算的一行宽度+当前子view的宽度+leftMargin+rightMargin 大于 一行实际能显示的宽度
             * 这就需要折行显示了
             * 那就保存已经算出来的一行高度、宽度、这一行所包含的view
             * 然后重置下一行宽度为0,高度为当前子view的高度加topMargin,bottomMargin,并实例化保存新一行子view的list
             */
            if (lineWidth + childWidth + lp.leftMargin + lp.rightMargin > width - getPaddingLeft() - getPaddingRight()) {
                mLineHeight.add(lineHeight);
                mLineWidth.add(lineWidth);
                mAllViews.add(lineViews);

                lineWidth = 0;
                lineHeight = childHeight + lp.topMargin + lp.bottomMargin;
                lineViews = new ArrayList<>();
            }
            //计算一行的宽度=前面计算的一行宽度+当前子view的宽度及leftMargin和rightMargin
            lineWidth += childWidth + lp.leftMargin + lp.rightMargin;
            //计算一行的高度取lineHeight和子view的实际高度最大值
            lineHeight = Math.max(lineHeight, childHeight + lp.topMargin + lp.bottomMargin);
            //保存子view
            lineViews.add(child);
        }
        //保存每行的高度、宽度、子view
        mLineHeight.add(lineHeight);
        mLineWidth.add(lineWidth);
        mAllViews.add(lineViews);


        int left = getPaddingLeft();
        int top = getPaddingTop();

        //viewgroup的行数
        int lineNum = mAllViews.size();

        for (int i = 0; i < lineNum; i++) {
            //一行的子view
            lineViews = mAllViews.get(i);
            //这一行需要的高度
            lineHeight = mLineHeight.get(i);
            //这一行需要的宽度
            int currentLineWidth = mLineWidth.get(i);
            //每次换行重新计算left值,getPaddingLeft获取viewgroup的PaddingLeft
            switch (this.mGravity) {
                case LEFT:
                    left = getPaddingLeft();
                    break;
                case CENTER:
                    left = getPaddingLeft();
                    break;
                case RIGHT:
                    left = width - currentLineWidth + getPaddingLeft();
                    break;
            }

            //遍历每行子view
            for (int j = 0; j < lineViews.size(); j++) {
                View child = lineViews.get(j);
                if (child.getVisibility() == View.GONE) {
                    continue;
                }

                MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
                //计算子view 的left值=当前left+子view自身的leftMargin
                int lc = left + lp.leftMargin;
                //计算子view 的top值=当前top+子view 的topMargin
                int tc = top + lp.topMargin;
                int rc = lc + child.getMeasuredWidth();
                int bc = tc + child.getMeasuredHeight();
                //摆放子view
                child.layout(lc, tc, rc, bc);
                //下一个子view 的left=当前left+当前子view的宽度+当前子view的leftMargin与rightMargin
                left += child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin;
            }
            //计算下一行的top=当前top+一行高度
            top += lineHeight;
        }

    }

最后重写下generateLayoutParams方法,返回布局参数类LayoutParams

    @Override
    public LayoutParams generateLayoutParams(AttributeSet attrs) {
        return new MarginLayoutParams(getContext(), attrs);
    }

    @Override
    protected LayoutParams generateDefaultLayoutParams() {
        return new MarginLayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
    }

    @Override
    protected LayoutParams generateLayoutParams(LayoutParams p) {
        return new MarginLayoutParams(p);
    }

最后就是实现PopupWindow

public class MangoPopWindow extends PopupWindow {

    private final Activity context;
    private final List<FilterTypeBean> dictList;
    private FixedHeightListView mListView;
    private TextView tvReset, tvConfirm;
    private View nullView;
    private PopAdapter adapter;
    private OnConfirmClickListener onConfirmClickListener;

    public MangoPopWindow(Activity context, List<FilterTypeBean> dictList ) {
        this.context = context;
        this.dictList=dictList;
        initPop();
    }


    private void initPop() {
        View popView = View.inflate(context, R.layout.listview_popwindow, null);
        //设置view
        this.setContentView(popView);
        //设置宽高(也可设置为LinearLayout.LayoutParams.MATCH_PARENT或者LinearLayout.LayoutParams.MATCH_PARENT)
        this.setWidth(-1);
        this.setHeight(-2);
        //设置PopupWindow的焦点
        this.setFocusable(true);
        //设置窗口以外的地方点击可关闭
        this.setOutsideTouchable(true);
        //设置背景透明
        this.setBackgroundDrawable(new ColorDrawable(0x33000000));

        mListView = (FixedHeightListView) popView.findViewById(R.id.listview);
        tvReset = (TextView) popView.findViewById(R.id.tv_reset);
        tvConfirm = (TextView) popView.findViewById(R.id.tv_confirm);
        nullView = popView.findViewById(R.id.view_null);

        adapter = new PopAdapter(context, dictList);
        mListView.setAdapter(adapter);
        tvReset.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                for (int x = 0; x < dictList.size(); x++) {
                    List<FilterTypeBean.Condition> childrenBeen = dictList.get(x).getChildren();
                    for (int y=0;y<childrenBeen.size();y++){
                        if (childrenBeen.get(y).isSelected()) {
                            childrenBeen.get(y).setSelected(false);
                        }
                    }
                }
                adapter.notifyDataSetChanged();
            }
        });
        tvConfirm.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                onConfirmClickListener.onConfirmClick();
                dismiss();
            }
        });
        nullView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                dismiss();
            }
        });
    }

    public void setOnConfirmClickListener(OnConfirmClickListener onConfirmClickListener){
        this.onConfirmClickListener=onConfirmClickListener;
    }

    public interface OnConfirmClickListener{
        void onConfirmClick();
    }

}

使用

    private void initView() {
        ivBack = (ImageView) findViewById(R.id.iv_back);
        tvFilter = (TextView) findViewById(R.id.tv_flow);
        tvFilter.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                mPopWindow = new MangoPopWindow(MainActivity.this, dictList);
                mPopWindow.showAsDropDown(ivBack);
                mPopWindow.setOnConfirmClickListener(new MangoPopWindow.OnConfirmClickListener() {
                    @Override
                    public void onConfirmClick() {
                        StringBuilder sb = new StringBuilder();
                        for (FilterTypeBean fb : dictList) {
                            List<FilterTypeBean.Condition> cdList = fb.getChildren();
                            for (int x = 0; x < cdList.size(); x++) {
                                FilterTypeBean.Condition children = cdList.get(x);
                                if (children.isSelected()) {
                                    sb.append(fb.getTypeName() + ":" + children.getValue() + ";");
                                }
                            }
                        }
                        if (!TextUtils.isEmpty(sb.toString())) {
                            Toast.makeText(MainActivity.this, sb.toString(), Toast.LENGTH_LONG).show();
                        }
                    }
                });

            }
        });

    }

    private void initParam() {
        String[] send = {"美团专送", "到店自取","骑手配送"};
        String[] feature = {"免配送费", "0元起送", "品牌商家", "点评高分", "跨天预定", "最新商家", "可开发票"};
        String[] activity = {"优惠商家", "首单立减", "满减优惠", "进店领券", "折扣商品", "第二份半价", "提前下单优惠", "满返代金券"};

        FilterTypeBean fb1 = new FilterTypeBean();
        fb1.setTypeName("配送");
        List<FilterTypeBean.Condition> childrenList = new ArrayList<>();
        for (int x = 0; x < send.length; x++) {
            FilterTypeBean.Condition cd = new FilterTypeBean.Condition();
            cd.setValue(send[x]);
            childrenList.add(cd);
        }
        fb1.setChildren(childrenList);

        FilterTypeBean fb2 = new FilterTypeBean();
        fb2.setTypeName("商家特色");
        List<FilterTypeBean.Condition> childrenList2 = new ArrayList<>();
        for (int x = 0; x < feature.length; x++) {
            FilterTypeBean.Condition cd = new FilterTypeBean.Condition();
            cd.setValue(feature[x]);
            childrenList2.add(cd);
        }
        fb2.setChildren(childrenList2);

        FilterTypeBean fb3 = new FilterTypeBean();
        fb3.setTypeName("优惠活动");
        List<FilterTypeBean.Condition> childrenList3 = new ArrayList<>();
        for (int x = 0; x < activity.length; x++) {
            FilterTypeBean.Condition cd = new FilterTypeBean.Condition();
            cd.setValue(activity[x]);
            childrenList3.add(cd);
        }
        fb3.setChildren(childrenList3);

        filterList.add(fb1);
        filterList.add(fb2);
        filterList.add(fb3);
    }

总结

这下不用烦恼在需要弹出框的时候到底该弹个什么样的dialog了,这三种弹出框应该能适应大部分的弹出框需求了

代码托管于MangoDialog

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值