安卓下拉列表样式筛选组件(仿美团,popwindow实现方式)
需求:做一个查询页面,要求点击item的时候能对底下数据进行筛选
先看效果图:(顺便送大家一个视频转gif的在线网站https://cloudconvert.com/)
这节先不说关于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<Dic> items; private int selectedPosition = -1; public List<Dic> 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<Dic> 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<Dic> 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.****.net/download/w1085541827/10249330