美文网首页Android控件
模仿好省APP的分类实现

模仿好省APP的分类实现

作者: Peakmain | 来源:发表于2018-12-12 00:52 被阅读35次

首先看下效果图

效果图.gif

实现思路呢,就是左右各一个recylerview,左右进行联动,这里使用到了一个SnapHelper这个类,关于SnapHelper大家可以自行搜索,我们都知道系统提供的LinearSnapHelper是中间对齐,所以呢,我们需要自己去实现一个SnapHelper去实现顶部对齐

public class StartSnapHelper extends LinearSnapHelper {

    private OrientationHelper mHorizontalHelper, mVerticalHelper;

    @Nullable
    @Override
    public int[] calculateDistanceToFinalSnap(RecyclerView.LayoutManager layoutManager, View targetView) {
        int[] out = new int[2];
        if (layoutManager.canScrollHorizontally()) {
            out[0] = distanceToStart(targetView, getHorizontalHelper(layoutManager));
        } else {
            out[0] = 0;
        }
        if (layoutManager.canScrollVertically()) {
            out[1] = distanceToStart(targetView, getVerticalHelper(layoutManager));
        } else {
            out[1] = 0;
        }
        return out;
    }

    private int distanceToStart(View targetView, OrientationHelper helper) {
        return helper.getDecoratedStart(targetView) - helper.getStartAfterPadding();
    }

    @Nullable
    @Override
    public View findSnapView(RecyclerView.LayoutManager layoutManager) {
        if (layoutManager instanceof LinearLayoutManager) {

            if (layoutManager.canScrollHorizontally()) {
                return findStartView(layoutManager, getHorizontalHelper(layoutManager));
            } else {
                return findStartView(layoutManager, getVerticalHelper(layoutManager));
            }
        }

        return super.findSnapView(layoutManager);
    }



    private View findStartView(RecyclerView.LayoutManager layoutManager,
                               OrientationHelper helper) {
        if (layoutManager instanceof LinearLayoutManager) {
            int firstChild = ((LinearLayoutManager) layoutManager).findFirstVisibleItemPosition();
            //需要判断是否是最后一个Item,如果是最后一个则不让对齐,以免出现最后一个显示不完全。
            boolean isLastItem = ((LinearLayoutManager) layoutManager)
                    .findLastCompletelyVisibleItemPosition()
                    == layoutManager.getItemCount() - 1;

            if (firstChild == RecyclerView.NO_POSITION || isLastItem) {
                return null;
            }

            View child = layoutManager.findViewByPosition(firstChild);

            if (helper.getDecoratedEnd(child) >= helper.getDecoratedMeasurement(child) / 2
                    && helper.getDecoratedEnd(child) > 0) {
                return child;
            } else {
                if (((LinearLayoutManager) layoutManager).findLastCompletelyVisibleItemPosition()
                        == layoutManager.getItemCount() - 1) {
                    return null;
                } else {
                    return layoutManager.findViewByPosition(firstChild + 1);
                }
            }
        }

        return super.findSnapView(layoutManager);
    }


    private OrientationHelper getHorizontalHelper(
            @NonNull RecyclerView.LayoutManager layoutManager) {
        if (mHorizontalHelper == null) {
            mHorizontalHelper = OrientationHelper.createHorizontalHelper(layoutManager);
        }
        return mHorizontalHelper;
    }

    private OrientationHelper getVerticalHelper(RecyclerView.LayoutManager layoutManager) {
        if (mVerticalHelper == null) {
            mVerticalHelper = OrientationHelper.createVerticalHelper(layoutManager);
        }
        return mVerticalHelper;

    }
}

使用很简单:mRvHome是我们右边的recylerview

   StartSnapHelper helper = new StartSnapHelper();
   helper.attachToRecyclerView(mRvHome);

我们点击左边的recylerview,实现与右边的recylerview 进行联动

        menuAdapter.setOnItemClickListener(new OnItemClickListener() {
            @Override
            public void onItemClick(int position) {
                mRvHome.smoothScrollToPosition(position + 1);
                menuAdapter.setSelectItem(position);
                menuAdapter.notifyDataSetChanged();

            }
        });

再接下来,我们滑动右边的recylerview实现与左边的recylerview进行联动

mRvHome.addOnScrollListener(new RecyclerView.OnScrollListener() {
            private int scrollState;

            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);
                this.scrollState = newState;

            }

            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);

                if (scrollState == RecyclerView.SCROLL_STATE_IDLE) {
                    return;
                }
                LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
                int current = layoutManager
                        .findFirstVisibleItemPosition();
                if (currentItem != current && current >= 0) {
                    currentItem = current;
                    menuAdapter.setSelectItem(currentItem - 1);
                    menuAdapter.notifyDataSetChanged();
                }
                //-1代表顶部,返回true表示没到顶,还可以滑
                //1代表底部,返回true表示没到底部,还可以滑
                if (!recyclerView.canScrollVertically(1)) {
            
                    int position = currentItem;
                    menuAdapter.setSelectItem(position);
                    menuAdapter.notifyDataSetChanged();
                }
            }
        });

其实我们使用好省APP的时候,我们会发现,右边的最后一条数据的底部实际是个全屏的,我们可以这么做,在左边点击的时候判断是否是最后一条数据,然后利用layoutManager.findViewByPosition的方法获取view,然后设置高度为MATCH_PARENT。在右边滑动的时候利用recyclerView.canScrollVertically(1)判断是否到了底部,如果到了底部就获取view并设置高度为全屏,但是,会有个小bug,就是在第一次点击最后一条数据的时候,右边的数据显示的是这样


image.png

而不是这样的


image.png
具体尚未想出非常好的解决方法,希望有道友提供我思路,非常感谢

最后,源码GitHub:https://github.com/Peakmain/save,大家直接看分类ClassificationFragment即可

相关文章

网友评论

    本文标题:模仿好省APP的分类实现

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