关于RecycleView的子元素锁定吸顶效果

  最近有一关于列表元素锁定吸顶的需求。处理方案比较简单的,在外层布局添加一个相同的标题栏控件,根据控件在滚动过中的位置来判断显示隐藏,从而达到效果。使用的关键代码是:

     int[] loc = new int[2];
     view.getLocationOnScreen(loc);
     int[] fitLoc = new int[2];
     outView.getLocationOnScreen(fitLoc);
     if (loc[1] <= fitLoc[1]){
          //外部标题栏显示
     }else{
          //外部标题栏隐藏
     }    

 在这个过程中,碰到几个问题:

1、当数据比较多,超过一个屏时,屏下所要固定的标题栏,显示状态时InVisible的状态,且所在屏幕位置坐标为(0, 0),这会导致显示判断的错误,这一情况做过滤处理;
2、当数据量从多到少或从少到多变化时,外层标题栏都要默认隐藏,列表标题栏都要默认显示(在onBindViewHolder()写);

以上如果是针对子项某一元素吸顶就够了,如果是对多个子元素需要吸顶需加如下处理:

1、列表的数据结构使用Map<TitleBean, List<ContentBean>>,的键值对, 重写的adapter的getItemCount()t,用TitleBean+ItemBean作为总数。这时我们可以建立算法(计算Map与List一一对应的对象),如果界面展示的是九宫格布局GridLayoutManager的方式,可以重写onAttachedToRecyclerView进行一维列表化。(关于公有/私有修饰,大家随意 )

   private Map<TitleBean, List<ContentBean<T>>> data = new TreeMap<>();  

   @Override
    public void onAttachedToRecyclerView(@NonNull RecyclerView recyclerView) {
        super.onAttachedToRecyclerView(recyclerView);
        RecyclerView.LayoutManager manager = recyclerView.getLayoutManager();
        if (manager instanceof GridLayoutManager) {
            final GridLayoutManager gridManager = ((GridLayoutManager) manager);
            gridManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
                @Override
                public int getSpanSize(int position) {
                    return getItemViewType(position) != Type.Content ? gridManager.getSpanCount() : 1;
                }
            });
        }
    }


   private BaseTimeBean<T> getItemBean(int pos){
        if(data.isEmpty()) return null;
        int count = 0;
        for(TimeBean titleBean : data.keySet()){
            count++;
            if (count -1 == pos)
                return titleBean;
            else {
                List<ImageBean<T>> contentBeans = data.get(titleBean);
                if (count + contentBeans.size() -1 <= pos){
                    int index = pos-count;
                    return (index >= 0 && index < contentBeans.size()) ? contentBeans.get(pos- count) : null;
                }else {
                    count += contentBeans.size();
                }
            }
        }
        return null;
    }

   public class ItemBean<T>{
     public String id;
     public String name;
        public T t;
   }

   public class TimeBean extends ItemBaen{}

   public class ContentBean<T> extends ItemBean<T>{}            

2、添加列表控件的滑动监听了,如addOnScrollListener,重写onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy)方法,用布局管理器找第一个可是元素位置findFirstVisibleItemPosition,传入getTitleBean方法中,找打对应的数据, 进而赋值到吸顶控件上。

    private TitleBean getTitleBean(int pos){
        if(data.isEmpty()) return null;
        int count = 0;
        for(TitleBean titleBean : data.keySet()){
            count++;
            if (count -1 == pos)
                return titleBean;
            else {
                int size = data.get(titleBean).size();
                if (count + size -1 <= pos){
                    int index = pos-count;
                    return titleBean;
                }else {
                    count += size;
                }
            }
        }
        return null;
   }

 

热门相关:帝少的专属:小甜心,太缠人