您的当前位置:首页正文

RecyclerView 简单实现章节列表

来源:图艺博知识网
Animation.gif

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

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();
        }
    }
..........
}

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

Top