RecyclerView 简单实现章节列表

作者: 区区一只yamada | 来源:发表于2017-03-01 14:58 被阅读219次
    Animation.gif

    在开发项目的时候,很多时候都需要用到上图这种功能, 章节列表。 但坑爹的是,这种控件在ios中原生自带, 但android却没有自带。这时候又不免去github里面去找一些开源库。所以说, 开发android的同学需要做各种ios的特效。

    ![H$RK3[L)N}]%$RX5HK)HTG.gif

    github这种开源库灰常多,但开源库毕竟是别人的,能自己弄出来当然是最好的。下面我就分享下我的实现思路。

    功能需求:
    1.章节标题栏需要固定在顶部。
    2.固定的章节标题栏可以随着列表的章节标题栏进行相应的移动。

    实现:
    1.固定章节栏: 采用famelayout布局, 在RecyclerView 外层添加一个章节栏标题,一直固定在顶部。
    2.固定章节栏随列表章节栏移动:当判断下个进入顶部是列表章节标题的时候 ,对固定章节栏进行相应的布局调整。

    主要的实现代码:

    public class SectionRecyclerActivity extends AppCompatActivity {
    
        ..........
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
          ..........
    
            mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
                @Override
                public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                    super.onScrollStateChanged(recyclerView, newState);
                }
    
                @Override
                public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                    super.onScrolled(recyclerView, dx, dy);
                    int position = (mLayoutManager.findFirstVisibleItemPosition() < 0) ? 0 : mLayoutManager.findFirstVisibleItemPosition();
                    int totalSize = mLayoutManager.getItemCount();
                    if (mAdapter.getItemViewType(position) == TITLE_TYPE) {
                        mTopTitle.setText(mDatas.get(position).content);
                    }
                    int nextPosition = position + 1;
                    if (nextPosition < totalSize) {
                        //获取下个章节标题的位置, 如果小于0说明后面没有章节标题。 如果下个章节标题位置还未显示出来,也不用做改变。
                        int sectionPosition = findNextSection(nextPosition, totalSize);
                        if (sectionPosition < 0 || sectionPosition > (position + mRecyclerView.getChildCount() - 1)) {
                            refreshTopTitle();
                            return;
                        }
    
                        //获取下一个章节标题的top, 如果top 大于 展示label的高度, 无须做改动。
                        int nextTopMargin = mLayoutManager.findViewByPosition(sectionPosition).getTop();
                        if (nextTopMargin < mMaxHeight) {
                            mTopTitleLayoutParams.topMargin = -(mMaxHeight - nextTopMargin);
                            mTopTitle.setLayoutParams(mTopTitleLayoutParams);
                            //如果当前第一个显示的不是章节标题, 需要显示上一个章节标题
                            if (mAdapter.getItemViewType(position) != TITLE_TYPE) {
                                mTopTitle.setText(findPreSectionText(position));
                            }
                        } else {
                            refreshTopTitle();
                        }
                    }
                }
            });
        }
    
        private void refreshTopTitle() {
            if (mTopTitleLayoutParams.topMargin == 0) return;
            mTopTitleLayoutParams.topMargin = 0;
            mTopTitle.setLayoutParams(mTopTitleLayoutParams);
        }
    
        private int findNextSection(int position, int size) {
            for (; position < size; position++) {
                if (mAdapter.getItemViewType(position) == TITLE_TYPE) return position;
            }
            return -1;
        }
    
        private String findPreSectionText(int position) {
            for (; position > -1; position--) {
                if (mAdapter.getItemViewType(position) == TITLE_TYPE) return mDatas.get(position).content;
            }
            return "";
        }
    
        private boolean isInit = false;
    
        @Override
        public void onWindowFocusChanged(boolean hasFocus) {
            super.onWindowFocusChanged(hasFocus);
            //当activity可以获取焦点的时候,获取固定标题栏的高度
            if (hasFocus && !isInit) {
                isInit = true;
                mMaxHeight = mTopTitle.getHeight();
            }
        }
    ..........
    }
    

    这里是主要实现逻辑的代码,主要是监听recyclerView的滚动事件对固定标题栏做相应的操作。
    这里暂且只支持recylerView的垂直的线性布局。像瀑布和网格布局现在还没有支持。
    完整的代码:https://github.com/hu5080126/SimpleExample/tree/master/sectionRecyclerView/src

    各位同学如果还有什么更好的实现方式,欢迎留言!

    相关文章

      网友评论

      • 沈敏杰:大神的文章,不错,学习了

      本文标题:RecyclerView 简单实现章节列表

      本文链接:https://www.haomeiwen.com/subject/ksqfgttx.html