我对 vlayout 里的 stickyLayoutHelper 吸顶效果比较满意,想做原理拆解分析,但目前也是一知半解,本文只是在对其大概了解之后做的一个实践小结,后续有新的理解会再跟进。
吸顶效果一种比较简单的实现就是在列表滑动到指定位置时,列表上层展示一个事先布局好的相同的布局,用作吸顶。这种方式基本可以满足简单展示,但如果涉及到点击响应就不太合理了。
另一种我认为的就是像 stickyLayoutHelper 这样,做到了比较合理的吸顶效果。滑动到指定位置后,会从列表中脱离,浮到上层,下拉时又会吸附到列表中去。
1.确定在哪个位置吸顶。
考虑到我需要做吸顶效果的 item 位置永远是在列表的最后一个,所以我可以知道其位置坐标,通过判断其距离顶边的距离来确定吸顶位置。例如我想在其滑动到距离顶部 80 dp 的时候就吸住,那我就去判断这个 item 的 getY() <= 80dp。
//给 RecyclerView 添加 OnScrollListener
@Override
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
int stickyPosition = adapter.getItemCount() - 1;
LayoutManager layoutManager = recyclerView.getLayoutManager();
if(layoutManager != null) {
View item = layoutManager.findViewByPosition(stickyPosition);
//这里做了一个距离顶部的偏移
if(item != null && item.getY() <= 80dp) {
//这里需要做一个判断,如果已经做了上浮吸顶,就不要再做了
if(item.getChildCount() > 2) {
View partView = item.getChildAt(0);
if(partView != null) {
item.removeViewAt(0);
//这里的 padding 可能要根据实际 item 的布局来设置,不一定 padding 都有效
item.setPadding(0, partView.getHeight(), 0, 0);
attachmentLayout.addView(partView);
}
}
} else if(item != null && item.getY() > 80dp) {
//同上浮判断一样,这里做了下沉依附判断,避免多次操作
if(attachmentLayout.getChildCount() > 0) {
View partView = attachmentLayout.getChildAt(0);
item.setPadding(0,0,0,0);
attachmentLayout.removeViewAt(0);
item.addView(partView, 0);
}
}
}
}
2.取出相应的要做上浮的 View。
基于步骤 1,如果 item 是一个复杂布局,而需要上浮吸顶的部分只是其中一部分的话,那么要做遍历取出相应布局,并从 item 从移除,移除后为了避免 item 会填充空位使得发生布局位移变化,需要 item 做一个 padding 设置。如果上浮吸顶部分就是整个 item,那就做简单的移动(从列表中移上来)
3.将吸顶布局添加到上层布局中。
为了有地方可以添加,我在页面布局上覆盖了一层,用来添加吸顶布局。这里要注意在步骤 1 里设置的顶部距离偏移。
完成上述 3 步后就可以实现向上滑动吸顶的效果了,并且你会看到吸顶布局有种从下层浮上来的效果,和 stickyLayoutHelper 就比较像了。
向下滑动时,只要触发脱离位置点,就把吸顶布局从上层移除,并重新添加回 item 就可以了。
网友评论