RecycleView指定item项置顶效果
由于最近需求需 当滑过列表中的某一项时置顶该item项,网上也搜索了下 大多是通过ItemDecoration 来实现 原理是获指定item的view视图通过分割线去来来绘制出来.但是我的置顶item是一个横向的recycleview 能滑动能点击.而通过分割线的方式只能有点击事件.所以此种方式不适用于我的情况
所以采用滚动监听事件来失效此效果
根据判断第一项可见的position来做逻辑
如果第一项可见的item的位置小于指定item的话隐藏掉置顶布局
其他情况显示置顶布局
采用自定义LayoutManager的方式来实现
package cn.lhj.stickhead;
import android.content.Context;
import android.os.Build;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
import android.view.View;
/**
* Filedescription.
* 指定item项吸顶
* @author lihongjun
* @date 2018/10/8
*/
public class StickLayoutManager extends LinearLayoutManager{
private int mStickPosition = -1; // 吸顶position
private View mStickView; // 吸顶布局
public StickLayoutManager(Context context) {
super(context);
}
public StickLayoutManager(Context context, int orientation, boolean reverseLayout) {
super(context, orientation, reverseLayout);
}
public StickLayoutManager(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
/**
* 设置吸顶的position
*
* @param stickPosition
*/
public void setStickPosition(int stickPosition) {
mStickPosition = stickPosition;
}
/**
* 设置吸顶的布局
*
* @param stickView
*/
public void setStickView(View stickView) {
setStickView(stickView,0);
}
/**
* 设置吸顶的布局
*
* @param stickView
* @param elevation 阴影值 dp
*/
public void setStickView(View stickView,int elevation) {
mStickView = stickView;
if (stickView != null && elevation > 0) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (mStickView.getTag() != null) {
// 已经设置过阴影了
return;
}
mStickView.setTag(true);
mStickView.animate().z(elevation);
}
}
}
@Override
public int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler, RecyclerView.State state) {
int scroll = super.scrollVerticallyBy(dy, recycler, state);
if (Math.abs(scroll) > 0) {
if (mStickPosition == -1) { // 如果列表中不存在二级分则返回
hideStickView();
return scroll;
}
changeFirstVisibilityStatu();
}
return scroll;
}
/**
* 根据位置变化检测吸顶布局的显示状态
*/
private void changeFirstVisibilityStatu() {
if (findFirstVisibleItemPosition() < mStickPosition) {
hideStickView();
} else if (findFirstVisibleItemPosition() == mStickPosition) {
View view = findViewByPosition(mStickPosition);
if (view != null && view.getTop() < 0) {
showStickView();
} else {
hideStickView();
}
} else {
showStickView();
}
}
/**
* 隐藏吸顶布局
*/
private void hideStickView() {
if (mStickView != null && mStickView.getVisibility() != View.GONE) {
mStickView.post(new Runnable() { // 如果父布局是ConstraintLayout会导致吸顶布局状态不对 用主线程队列去更新状态
@Override
public void run() {
mStickView.setVisibility(View.GONE);
}
});
}
}
/**
* 显示吸顶布局
*/
private void showStickView() {
if (mStickView != null && mStickView.getVisibility() != View.VISIBLE) {
mStickView.post(new Runnable() {// 如果父布局是ConstraintLayout会导致吸顶布局状态不对 用主线程队列去更新状态
@Override
public void run() {
mStickView.setVisibility(View.VISIBLE);
}
});
}
}
@Override
public void onLayoutCompleted(RecyclerView.State state) {
super.onLayoutCompleted(state);
changeFirstVisibilityStatu();
}
}
遇到的坑就
1.通过调用RecycleView的scrollToPosition,置顶布局不能正常的显示出来,发现是因为scrollToPosition会使recycleView requestLayout,然后会super.requestLayout;现在采用sitckView.post来避免此问题
2.通过调用recycleView的scrollToPosition方式不会出发scroll回掉
需要在onLayoutCompleted回掉中监测可见的第一项来确定吸顶布局的显示状态