实现诸如 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方法找不到元素?

Tomcat 或 Java 中是不是存在诸如 beforeCrash() 或 beforeExit() 之类的函数

是否有可能从 facebook 图形 API 中不是我的页面中的某个帖子中获取诸如反应或喜欢之类的信息?