实现诸如 FourSquare 或 Ebay 之类的 Android 搜索过滤器
Posted
技术标签:
【中文标题】实现诸如 FourSquare 或 Ebay 之类的 Android 搜索过滤器【英文标题】:Implement Android Search Filters like FourSquare or Ebay 【发布时间】:2014-12-06 22:17:52 【问题描述】:我的问题是关于 android 中的过滤。 Ebay 和 Foursquare 都有一个看起来像是从右侧滑入的对话框片段。在这个片段中有几个嵌套的列表视图,它们打开并展开以填充片段。打开嵌套列表视图时,顶部也会出现一个后退箭头。
一旦选择过滤器,它们就会显示为***片段中每个类别名称下的列表视图文本。 (参见 ebay 截图中“Disney”和“HTC”的不同颜色文字)
我想知道是否有一个库可以实现这样的嵌套列表视图?这是否被认为是过滤搜索结果的最佳实践?
我已经包含了屏幕截图,希望能显示我在说什么。
【问题讨论】:
【参考方案1】:您可以通过带有自定义单元格的 android Expandable ListView 执行此操作。
这是一个关于Expandable ListView 的示例,带有自定义单元格。
谢谢
【讨论】:
【参考方案2】:可以通过android Recyclerview 和一些逻辑来实现。我曾通过以下方式处理过类似的情况。
FilterViewAdapter - Adapter of Recycler.
FilterListPresenter - class used to separate business logic.
八种不同类型的单元格用于动态生成过滤器列表。
static final int FILTER_HEADER = 0;
static final int FILTER_DROPDOWN_HEADER = 1;
static final int FILTER_DROPDOWN_ITEM_RADIO = 2;
static final int FILTER_DROPDOWN_ITEM_CHECKBOX = 3;
static final int FILTER_DROPDOWN_ITEM_RADIO_LAST = 22;
static final int FILTER_DROPDOWN_ITEM_CHECKBOX_LAST = 33;
static final int FILTER_DUEDATE = 4;
static final int FILTER_PROGRESS = 5;
getItemViewType() 提供基于逻辑的单元格类型。例如,如果打开过滤器,则提供与通常过滤器标题不同类型的单元格。
@Override
public int getItemViewType(int position)
return filterListPresenter.getItemViewType(position);
找到我的适配器类
public class FilterViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements FilterListPresenter.AdapterCallBacks
FilterListPresenter filterListPresenter;
Context context;
public FilterViewAdapter(Context context, FilterListPresenter filterListPresenter)
this.filterListPresenter = filterListPresenter;
this.context = context;
filterListPresenter.setAdapterCallback(this);
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
View view = LayoutInflater.from(parent.getContext())
.inflate(filterListPresenter.getLayoutForView(viewType), parent, false);
return filterListPresenter.getViewHolder(view,viewType);
@Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, int position)
filterListPresenter.onBindCallLogRowViewAtPosition(position,holder,context);
@Override
public int getItemViewType(int position)
return filterListPresenter.getItemViewType(position);
@Override
public int getItemCount()
return filterListPresenter.getRowsCount();
@Override
public void notifyDataSetChanged1()
notifyDataSetChanged();
找到我的 Presenter 类
public class FilterListPresenter<T extends RecyclerView.ViewHolder> implements FilterListener
static final int FILTER_HEADER = 0;
static final int FILTER_DROPDOWN_HEADER = 1;
static final int FILTER_DROPDOWN_ITEM_RADIO = 2;
static final int FILTER_DROPDOWN_ITEM_CHECKBOX = 3;
static final int FILTER_DROPDOWN_ITEM_RADIO_LAST = 22;
static final int FILTER_DROPDOWN_ITEM_CHECKBOX_LAST = 33;
static final int FILTER_DUEDATE = 4;
static final int FILTER_PROGRESS = 5;
Context context;
SessionData sessionData;
int openPosition = -1;
List<FIlterData> fIlterDatas ;
int numberOfRows = 5;
String[] filterNAmes = "Checkin Template", "Employee", "Due Date", "Percentage of progress", "Status"; //Main filters
int[] filterICons = R.drawable.outline_view_agenda_black_24,
R.drawable.outline_person_black_24 ,
R.drawable.outline_calendar_today_black_24,
R.drawable.outline_trending_up_black_24,
R.drawable.outline_check_circle_black_24;
private String checkBoxValue;
public FilterListPresenter(Context context, SessionData sessionData)
this.context = context;
this.sessionData = sessionData;
initilizeData(sessionData);
private void initilizeData(SessionData sessionData)
fIlterDatas = new ArrayList<>();
//add data
public void onBindCallLogRowViewAtPosition(int position, T rowView, Context context)
int itemViewType = getItemViewType(position);
switch (itemViewType)
case FILTER_HEADER:
FilterHeaderHolder filterHeaderHolder = (FilterHeaderHolder) rowView;
filterHeaderHolder.setListener(this);
filterHeaderHolder.setTitle(getFilterTitle(position));
filterHeaderHolder.setImageView(getIcon(position), context);
break;
case FILTER_DROPDOWN_HEADER:
//add logic for each type cell
break;
case FILTER_DROPDOWN_ITEM_CHECKBOX:
case FILTER_DROPDOWN_ITEM_CHECKBOX_LAST:
break;
case FILTER_DROPDOWN_ITEM_RADIO:
case FILTER_DROPDOWN_ITEM_RADIO_LAST:
break;
case FILTER_PROGRESS:
break;
case FILTER_DUEDATE:
break;
private int getIcon(int position)
if((openPosition == -1) || (position<=openPosition))
return filterICons[position];
else
return filterICons[position - getExtraRowCountForFIlter(openPosition)];
private String getFilterTitle(int position)
if((openPosition == -1) || (position<=openPosition))
return filterNAmes[position];
else
return filterNAmes[position - getExtraRowCountForFIlter(openPosition)];
public int getRowsCount()
if(openPosition == -1) return numberOfRows;
else return numberOfRows+ getExtraRowCountForFIlter(openPosition);
private int getExtraRowCountForFIlter(int position)
switch (position) //Additional one for header
case 0: return ((List<CheckinTemplate>) fIlterDatas.get(0).getFilterData()).size()+1;
case 1: tryreturn ((List<Employee>) fIlterDatas.get(1).getFilterData()).size()+1;catch (Exception exc)
return 0;
case 4: return ((List<Status>) fIlterDatas.get(4).getFilterData()).size()+1;
default: return 1;
public int getItemViewType(int position) //Complex logic to determine my cell type
if(openPosition == -1 || (position<=openPosition))
return FILTER_HEADER;
else
int extraRowsForOpenFilter = getExtraRowCountForFIlter(openPosition);
if(position > (openPosition+extraRowsForOpenFilter))
return FILTER_HEADER;
switch (openPosition)
case 0:
if(openPosition+1 == position) return FILTER_DROPDOWN_HEADER;
else if(openPosition+extraRowsForOpenFilter == position) return FILTER_DROPDOWN_ITEM_RADIO_LAST;
else return FILTER_DROPDOWN_ITEM_RADIO;
case 1: if(openPosition+1 == position) return FILTER_DROPDOWN_HEADER;
else if(openPosition+extraRowsForOpenFilter == position) return FILTER_DROPDOWN_ITEM_CHECKBOX_LAST;
else return FILTER_DROPDOWN_ITEM_CHECKBOX;
case 4:
if(openPosition+1 == position) return FILTER_DROPDOWN_HEADER;
else if(openPosition+extraRowsForOpenFilter == position) return FILTER_DROPDOWN_ITEM_CHECKBOX_LAST;
else return FILTER_DROPDOWN_ITEM_CHECKBOX;
case 2:
return FILTER_DUEDATE;
case 3:
return FILTER_PROGRESS;
default: return FILTER_HEADER;
public int getLayoutForView(int viewType)
switch (viewType)
case FILTER_HEADER:
return R.layout.a_filter_list_item_header;
case FILTER_DROPDOWN_HEADER:
return R.layout.a_filter_list_item_dropdown_header;
case FILTER_DROPDOWN_ITEM_RADIO:
return R.layout.a_filter_list_item_dropdown_item_radio;
case FILTER_DROPDOWN_ITEM_RADIO_LAST:
return R.layout.a_filter_list_item_dropdown_item_radio_last;
case FILTER_DROPDOWN_ITEM_CHECKBOX:
return R.layout.a_filter_list_item_dropdown_item_chekbox;
case FILTER_DROPDOWN_ITEM_CHECKBOX_LAST:
return R.layout.a_filter_list_item_dropdown_item_chekbox_last;
case FILTER_DUEDATE:
return R.layout.a_filter_list_item_duedate;
case FILTER_PROGRESS:
return R.layout.a_filter_list_item_progress;
return FILTER_HEADER;
@Override
public void onFilterItemClick(int position, int viewTypeId)
switch (viewTypeId)
case FILTER_HEADER:
if(openPosition!=-1) minimizeFilters();
else
openPosition = position;
adapterCallback.notifyDataSetChanged1();
case FILTER_DROPDOWN_HEADER:
break;
case FILTER_DROPDOWN_ITEM_RADIO:
case FILTER_DROPDOWN_ITEM_RADIO_LAST:
break;
case FILTER_DROPDOWN_ITEM_CHECKBOX:
case FILTER_DROPDOWN_ITEM_CHECKBOX_LAST:
break;
case FILTER_DUEDATE:
break;
case FILTER_PROGRESS:
break;
@Override
public RecyclerView.ViewHolder getViewHolder(View view, int viewType)
switch (viewType)
case FILTER_HEADER:
return new FilterHeaderHolder(view);
case FILTER_DROPDOWN_HEADER:
return new FilterListDropdownHeader(view);
case FILTER_DROPDOWN_ITEM_RADIO:
case FILTER_DROPDOWN_ITEM_RADIO_LAST:
return new FilterListItemRadioButton(view);
case FILTER_DROPDOWN_ITEM_CHECKBOX:
case FILTER_DROPDOWN_ITEM_CHECKBOX_LAST:
return new FilterListItemCheckBox(view);
case FILTER_DUEDATE:
return new FilterListItemDueDate(view);
case FILTER_PROGRESS:
return new FilterListItemProgress(view);
default: return new FilterHeaderHolder(view);
private void minimizeFilters()
openPosition = -1;
adapterCallback.notifyDataSetChanged1();
AdapterCallBacks adapterCallback;
public void setAdapterCallback(FilterViewAdapter adapterCallback)
this.adapterCallback = adapterCallback;
public String getDropdownHeader()
if( ((List<?>) fIlterDatas.get(openPosition).getFilterData()).get(0) instanceof CheckinTemplate)
return "Select Template";
else if( ((List<?>) fIlterDatas.get(openPosition).getFilterData()).get(0) instanceof Employee)
return "Select Employees";
else if( ((List<?>) fIlterDatas.get(openPosition).getFilterData()).get(0) instanceof Status)
return "Select status";
return "";
public String getCheckBoxValue(int pos)
if( ((List<?>) fIlterDatas.get(openPosition).getFilterData()).get(0) instanceof CheckinTemplate)
return ((List<CheckinTemplate>) fIlterDatas.get(openPosition).getFilterData()).get(pos).getName();
else if( ((List<?>) fIlterDatas.get(openPosition).getFilterData()).get(0) instanceof Employee)
return ((List<Employee>) fIlterDatas.get(openPosition).getFilterData()).get(pos).getEmpName();
else if( ((List<?>) fIlterDatas.get(openPosition).getFilterData()).get(0) instanceof Status)
return ((List<Status>) fIlterDatas.get(openPosition).getFilterData()).get(pos).getName();
return "";
public interface AdapterCallBacks
void notifyDataSetChanged1();
构建过滤器的方法类似。添加您的想法。
【讨论】:
以上是关于实现诸如 FourSquare 或 Ebay 之类的 Android 搜索过滤器的主要内容,如果未能解决你的问题,请参考以下文章
为啥jQuery或诸如getElementById之类的DOM方法找不到元素?
为啥jQuery或诸如getElementById之类的DOM方法找不到元素?
为啥jQuery或诸如getElementById之类的DOM方法找不到元素?
为啥jQuery或诸如getElementById之类的DOM方法找不到元素?