法1:
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
// 获取第一个item
View itemHeader = recyclerView.getChildAt(0);
tvMainHead.setVisibility(View.VISIBLE);
tvMainHead.setText(itemHeader.getContentDescription());
ViewGroup view = (ViewGroup) recyclerView.findChildViewUnder(rlMainHead.getWidth(),rlMainHead.getHeight()+1);
if(view != null){
int deltY = view.getTop()-rlMainHead.getHeight();
if(view.getChildAt(0).getVisibility() == View.VISIBLE) {
if (deltY < 0 && Math.abs(deltY) <= rlMainHead.getHeight()) {
rlMainHead.setTranslationY(deltY);
} else {
rlMainHead.setTranslationY(0);
}
}else {
rlMainHead.setTranslationY(0);
}
}
}
});
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
MyViewHolder myViewHolder = (MyViewHolder)holder;
GroupStr groupStr = list.get(position);
if(position == 0){
myViewHolder.rlHead.setVisibility(View.VISIBLE);
} else {
if(!groupStr.getGroupName().equals(list.get(position-1).getGroupName())){
myViewHolder.rlHead.setVisibility(View.VISIBLE);
} else {
myViewHolder.rlHead.setVisibility(View.GONE);
}
}
myViewHolder.tvHead.setText(groupStr.getGroupName());
myViewHolder.tvContent.setText(groupStr.getText());
myViewHolder.item.setContentDescription(groupStr.getGroupName());
myViewHolder.item.setTag(groupStr.getGroupName()+position);
}
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/account_pull_rv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="300dp"/>
<RelativeLayout
android:id="@+id/rl_main_head"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/color_e1faf7">
<TextView
android:id="@+id/tv_main_head"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="1st head"
android:padding="10dp"
android:textSize="16sp"/>
</RelativeLayout>
</RelativeLayout>
法2:
利用ItemDecoration,当Head的高度大于Item高度时有点小瑕疵,但不影响使用
recyclerView.addItemDecoration(decoration);
public class MyDecoration extends RecyclerView.ItemDecoration {
private Paint mPaint;
private Paint textPaint;
private float offset = 200;
private List<GroupStr> list;
public MyDecoration(List<GroupStr> list ) {
this.list = list;
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setColor(Color.RED);
textPaint = new Paint();
textPaint.setAntiAlias(true);
textPaint.setColor(Color.BLACK);
textPaint.setTextSize(80);
}
//before the item views are drawn,在绘制item之前调用,会被item view盖掉
//getItemOffsets 是针对每一个 ItemView,而 onDraw 方法却是针对 RecyclerView 本身,
// 所以在 onDraw 方法中需要遍历屏幕上可见的 ItemView,分别获取它们的位置信息
// @Override
// public void onDraw(@NonNull Canvas c, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
// super.onDraw(c, parent, state);
//
// for(int i=0;i<parent.getChildCount();i++){
//
// View child = parent.getChildAt(i);
// int index = parent.getChildAdapterPosition(child);
// if(!list.get(index).isHead()){
// continue;
// }
if(parent.getChildAdapterPosition(child) != 0) {
// float topDivide = child.getTop() - offset;
// float bottomDivide = child.getTop();
// float leftDivide = parent.getPaddingLeft();
// float rightDivide = parent.getWidth() - parent.getPaddingRight();
//
// c.drawRect(leftDivide, topDivide, rightDivide, bottomDivide, mPaint);
// c.drawText(list.get(index).getGroupName(),leftDivide+100,bottomDivide-100,textPaint);
c.drawCircle(left/2,(child.getBottom()-child.getTop())/2+child.getTop(),10,mPaint);
}
//
c.drawLine(left/2,child.getTop() - 1,left/2,child.getBottom(),mPaint);
// }
// }
//after the item views are drawn,绘制item之后调用,能盖item view
@Override
public void onDrawOver(@NonNull Canvas c, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
super.onDrawOver(c, parent, state);
for(int i=0;i<parent.getChildCount();i++){
View child = parent.getChildAt(i);
int index = parent.getChildAdapterPosition(child);
float leftDivide = parent.getPaddingLeft();
float rightDivide = parent.getWidth() - parent.getPaddingRight();
//非第一个item但是组内第一个时画头部
if(i!= 0 && list.get(index).isHead()){
float topDivide = child.getTop() - offset;
float bottomDivide = child.getTop();
c.drawRect(leftDivide, topDivide, rightDivide, bottomDivide, mPaint);
c.drawText(list.get(index).getGroupName(),leftDivide+100,bottomDivide-100,textPaint);
}else if(i == 0){
Log.d("zyy","index = 0");
//当child是屏幕上第一个可见的 ItemView 时,画顶部粘性头部
float topDivide,bottomDivide;
topDivide = parent.getPaddingTop();
bottomDivide = topDivide + offset;
//组别里的最后一个
if(!list.get(index).getGroupName().equals(list.get(index+1).getGroupName())){
if(child.getBottom() < bottomDivide){
topDivide = topDivide - (bottomDivide - child.getBottom());
}
}
bottomDivide = topDivide + offset;
c.drawRect(leftDivide, topDivide, rightDivide, bottomDivide, mPaint);
c.drawText(list.get(index).getGroupName(),leftDivide+100,bottomDivide-100,textPaint);
}
}
}
@Override
public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
int index = parent.getChildAdapterPosition(view);
if(list.get(index).isHead()){
outRect.top = (int) offset;
}
}
}