首先看下效果图

实现思路呢,就是左右各一个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,就是在第一次点击最后一条数据的时候,右边的数据显示的是这样

而不是这样的

具体尚未想出非常好的解决方法,希望有道友提供我思路,非常感谢
最后,源码GitHub:https://github.com/Peakmain/save,大家直接看分类ClassificationFragment即可
网友评论