安卓下拉列表样式筛选组件(仿美团,popwindow实现方式)

需求:做一个查询页面,要求点击item的时候能对底下数据进行筛选

安卓下拉列表样式筛选组件(仿美团,popwindow实现方式)_第1张图片

安卓下拉列表样式筛选组件(仿美团,popwindow实现方式)_第2张图片



先看效果图:(顺便送大家一个视频转gif的在线网站https://cloudconvert.com/)

安卓下拉列表样式筛选组件(仿美团,popwindow实现方式)_第3张图片

这节先不说关于toolbar的处理,只说下拉菜单popwindow的封装。

1、首先需要一个包含listview的页面pup_selectlist.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="fill_parent"
    android:orientation="vertical"
    android:id="@+id/popupwindow"
    >

    <FrameLayout
        android:background="#ffffff"
        android:id="@+id/employeesquery_popupwindow"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        >

        <ListView
            android:id="@+id/listview"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:divider="#efefef"
            android:dividerHeight="0.5dp"
            >
        ListView>
    FrameLayout>

    
    <LinearLayout
        android:id="@+id/dissmiss"
        android:layout_width="match_parent"
        android:layout_height="1200dp"
        android:background="#50000000"
        android:orientation="horizontal">LinearLayout>

LinearLayout>

还需要一个ListView的item页面,item_listview.xml,由于我做的只是一个很简单的列表,所以就包含name和code(code不要也行,可以用tag替代)两部分,name是list展示时所用,code的用来当作前后台交互的查询条件。注:在本例子中,id='code'的TextView并没有用到。

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="match_parent"
    android:orientation="vertical"
    android:id="@+id/employeesquery"
    android:background="#ffffff">


    <TextView
        android:gravity="center_vertical"
        android:layout_marginLeft="20dp"
        android:id="@+id/name"
        android:layout_width="wrap_content"
        android:layout_height="40dp"
        >TextView>


    <TextView
        android:visibility="gone"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/code"
        />

LinearLayout>

2、定义一个listview的适配器抽象类(后面会用到)

abstract class Madapter extends BaseAdapter {
    public abstract List getItems();  //返回ListView的数据集
    public abstract void setSelectColor(int color);    //修改选中后item的颜色
    public abstract void setSelectedPosition(int selectedPosition); //设置选中项
    public abstract String getShowKey(int position , String key);//获取选中值,必须有这个方法。
}

在建立自己的适配器时要实现这个接口,当然,这个接口除了本人写的这几个以外,还可以继续添加其他方法。

下面贴上例子中我所写的适配器类

package com.imp.dropdownmenu;

import android.content.Context;
import android.graphics.Color;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;

import java.util.List;

/**
 * Created by import 2017/12/28.
 */

public class SearchAdapter extends Madapter {

    private Context context;
    private int selectColor = Color.GRAY; //被选中后item的颜色,为了方便,所以在添加set方法
    private LayoutInflater inflater;
    private List items;
    private int selectedPosition = -1;

    public List getItems() {
        return items;
    }

    @Override
    public String getShowKey(int position , String key){
        if (key.equals("name")){
            return  items.get(position).getName();
        }else {
            return  items.get(position).getCode();
        }

    }





    public void setSelectedPosition(int selectedPosition) {
        this.selectedPosition = selectedPosition;
    }


    public SearchAdapter(Context context){
        this.context = context;
        inflater = LayoutInflater.from(context);
    }



    public void setItems(List items) {
        this.items = items;
    }



    @Override
    public int getCount() {
        // TODO Auto-generated method stub
        return items.size();
    }

    @Override
    public Object getItem(int i) {
        return null;
    }

    @Override
    public long getItemId(int position) {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        // TODO Auto-generated method stub

        SearchAdapter.ViewHolder holder;
        if(convertView == null){

            holder = new SearchAdapter.ViewHolder();
            convertView = (View)inflater.inflate(R.layout.item_listview, parent , false);
            holder.name =(TextView) convertView.findViewById(R.id.name);
            holder.code = (TextView)convertView.findViewById(R.id.code);
            holder.employeesquery = (LinearLayout)convertView.findViewById(R.id.employeesquery);
            convertView.setTag(holder);
        }else{
            holder = (SearchAdapter.ViewHolder)convertView.getTag();
        }

        /**
         * 该项被选中时改变背景色
         */
        if(selectedPosition == position){
            holder.employeesquery.setBackgroundColor(selectColor);
        }else{
            holder.employeesquery.setBackgroundColor(Color.TRANSPARENT);
        }
        holder.name.setText(items.get(position).getName());
        holder.code.setText(items.get(position).getCode());  //也可在ITTM里去掉这一项,写在Tag里


        return convertView;
    }

    class ViewHolder{
        TextView name;
        TextView code;
        LinearLayout employeesquery;
    }

    @Override
    public void setSelectColor(int selectColor) {
        this.selectColor = selectColor;
    }
}

3、开始编写通用下拉选择列表(DropDownMenu.java)

先上源码

import android.content.Context;
import android.graphics.drawable.BitmapDrawable;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.FrameLayout;
import android.widget.ListView;
import android.widget.PopupWindow;
import android.widget.TextView;

/**
 * Created by import on 2018/1/31.
 */

public class DropDownMenu {

    private final OnListCkickListence mListener;  //item单击事件接口
    private static DropDownMenu instance;
    private static Context sContext;
    private PopupWindow popupWindow;
    private View dissmiss;                          //点击展开后的半透明挡板
    private Boolean showShadow = true;             //是否需要半透明挡板
    private String showName;                        //适配器中所需要显示内容的名字,仅在modifyText中有值时使用
    private String selectName;                      //搜索用的key
    private int itemNum = 6;
    private int indexColor;                         //设置外部所点击的View的颜色
    private static int viewColor;                    //外部所点击的View本来的颜色


    public static DropDownMenu getInstance(Context context, OnListCkickListence mListener) {
        instance = new DropDownMenu(context,mListener);
        return instance;
    }


    private DropDownMenu(Context context,OnListCkickListence mListener) {
        sContext = context;
        this.mListener = mListener;
    }

    /***
     *
     * @param screenWidth  屏幕宽度
     * @param screenHeight  屏幕高度
     * @param searchAdapter 设配器
     * @param item            listView的item
     * @param layout   含有ListView的布局文件
     * @param dropview  菜单弹出后在哪个View下
     * @param modifyText    点击后需要修改的TextView
     * @param type          点击了哪一个标签
     * @param menuSize           是否需要限制弹出菜单大小,若需要,则传true,默认为6个item高,通过setItemNum方法进行设定
     */
    public void showSelectList(int screenWidth, final int screenHeight, final Madapter searchAdapter, View layout,View item, final View dropview, final TextView modifyText, final String type, final boolean menuSize) {

        ListView listview = (ListView) layout.findViewById(R.id.listview);

        viewColor = dropview.getDrawingCacheBackgroundColor();

        if (menuSize && searchAdapter!=null && searchAdapter.getCount()!=0) {
            ViewGroup.LayoutParams para = listview.getLayoutParams();
            int width = View.MeasureSpec.makeMeasureSpec(0,
                    View.MeasureSpec.UNSPECIFIED);
            int height = View.MeasureSpec.makeMeasureSpec(0,
                    View.MeasureSpec.UNSPECIFIED);
            item.measure(width, height);
            item.getMeasuredWidth(); // 获取宽度
            item.getMeasuredHeight(); // 获取高度
            para.height = itemNum * (item.getMeasuredHeight()) + 14;
            listview.setLayoutParams(para);
        }else {
            listview.setLayoutParams( new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                    FrameLayout.LayoutParams.WRAP_CONTENT));
        }

        if (showShadow) {
            dissmiss = (View) layout.findViewById(R.id.dissmiss);
            if (dissmiss != null) {
                dissmiss.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        popupWindow.dismiss();
                        dropview.setBackgroundColor(viewColor);
                    }
                });
            }
        } else {
            dissmiss = (View) layout.findViewById(R.id.dissmiss);
            dissmiss.setVisibility(View.GONE);
        }


        listview.setAdapter(searchAdapter);

        popupWindow = new PopupWindow(layout, screenWidth,
                FrameLayout.LayoutParams.WRAP_CONTENT, true);
        /**
         * 有了mPopupWindow.setBackgroundDrawable(new BitmapDrawable());
         * 这句可以使点击popupwindow以外的区域时popupwindow自动消失 但这句必须放在showAsDropDown之前
         */
        popupWindow.setBackgroundDrawable(new BitmapDrawable());
        /**
         * popupwindow的位置,第一个参数表示位于哪个控件之下 第二个参数表示向左右方向的偏移量,正数表示向左偏移,负数表示向右偏移
         * 第三个参数表示向上下方向的偏移量,正数表示向下偏移,负数表示向上偏移
         *
         */

        if (indexColor != 0){
            dropview.setBackgroundColor(indexColor);
        }else {
            dropview.setBackgroundColor(viewColor);
        }
        popupWindow.showAsDropDown(dropview, -5, 3);// 在控件下方显示popwindow
        popupWindow.setFocusable(true);
        popupWindow.setOutsideTouchable(true);
        popupWindow.setOnDismissListener(new PopupWindow.OnDismissListener() {
            @Override
            public void onDismiss() {
                dropview.setBackgroundColor(viewColor);
            }
        });
        popupWindow.update();


        listview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                                            @Override
                                            public void onItemClick(AdapterView listView, View view, int position, long id) {
                                                searchAdapter.setSelectedPosition(position);
                                                searchAdapter.notifyDataSetInvalidated();
                                                if(modifyText != null){
                                                    modifyText.setText(searchAdapter.getShowKey(position,showName));
                                                }
                                                mListener.search(searchAdapter.getShowKey(position,selectName), type);
                                                mListener.changeSelectPanel(searchAdapter,dropview);
                                                popupWindow.dismiss();
                                                dropview.setBackgroundColor(viewColor);
                                            }
                                        }
        );
    }

    public void setShowShadow(Boolean showShadow) {
        this.showShadow = showShadow;
    }

    public void setItemNum(int itemNum) {
        this.itemNum = itemNum;
    }

    public void setShowName(String showName) {
        this.showName = showName;
    }

    public void setSelectName(String selectName) {
        this.selectName = selectName;
    }

    public void setIndexColor(int color){
        indexColor = sContext.getResources().getColor(color);
    }

    public interface OnListCkickListence {
        void search(String code, String type);  //根据选择的数据进行查询
        void changeSelectPanel(Madapter madapter,View view); //修改选中后item的颜色,以及点击后对View进行一些修改
    }
}

核心方法是showSelectList,定义接口为了方便在外部调用时根据不用的需求写不同的实现。

4、实例调用

4.1、初始化dropDownMenu


dropDownMenu = DropDownMenu.getInstance(this, new DropDownMenu.OnListCkickListence() {
    @Override
    public void search(String code, String type) {
        System.out.println("======"+code+"========="+type);
    //写一些你自己的需求和方法,比如:点击某个item我们可以得到你点的是哪个列表和item的code,根据code查询后台并刷新页面
 }

    @Override
    public void changeSelectPanel(Madapter madapter, View view) {
    //提供了对适配器方法调用以及返回第一次点击的view的回调(本例中为:性别、民族、国家...)
    }
});
dropDownMenu.setIndexColor(R.color.colorAccent);//用来设置点击(性别、民族、国家...)后的颜色
dropDownMenu.setShowShadow(true);//要不要在popwindow展示的时候背景变为半透明
dropDownMenu.setShowName("name");//listView适配器中返回数据的名字(比如:我在适配器中传入List list,在这个list中有n个Dic类,我要在性别、民族...View中显示的值在Dic这个类中的名字’)
dropDownMenu.setSelectName("code");//listView适配器中返回数据的名字(返回用来查询的)

4.2、调用dropDownMenu
先定义好需要调用的layout布局
@Overrid
public void onClick(View view) {
    switch (view.getId()) {
        case R.id.sex:
            dropDownMenu.showSelectList(ScreenUtils.getScreenWidth(this),
                    ScreenUtils.getScreenHeight(this), sexAdapter,
                    listView, listItem,sex, sex_text, "cyry.xbdm", false);
            break;
        case R.id.nation:
            dropDownMenu.showSelectList(ScreenUtils.getScreenWidth(this),
                    ScreenUtils.getScreenHeight(this), nationAdapter,
                    listView, listItem,nation,nation_text,"cyry.mzdm",true);
            break;
        case R.id.country:
            dropDownMenu.showSelectList(ScreenUtils.getScreenWidth(this),
                    ScreenUtils.getScreenHeight(this), countryAdapter,
                    listView, listItem,country,country_text,"cyry.gjdm",true);

            break;
        case R.id.culture:
            dropDownMenu.showSelectList(ScreenUtils.getScreenWidth(this),
                    ScreenUtils.getScreenHeight(this), cultureAdapter,
                    listView, listItem,culture,culture_text,"cyry.whcd",true);
            break;
        default:
            break;
    }
}

5、小结

由于这个例子为前期测试例子,所以命名不是很规范,各位看官有啥不明白的可以再下面留言,共同进步。


demo传送门:http://download.csdn.net/download/w1085541827/10249330




你可能感兴趣的:(Android)