1.因为头部不是我想要的,所以直接下载代码后进行修改,代码:
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.util.Log;
import android.util.SparseArray;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import java.util.HashMap;
import java.util.Map;
public abstract class RecycleViewDecoration extends RecyclerView.ItemDecoration {
protected String TAG = "RecycleViewDecoration";
private Paint mHeaderTxtPaint;//文字
private Paint mHeaderContentPaint;//背景
private Paint mBottomLinePaint;//底部线条
private Paint mBitmapPaint;//右边箭头
protected int headerHeight = 136;//头部高度
private int textPaddingLeft = 30;//头部文字左边距
private int textPaddingRght=40;//右边文字边距
protected int bottomLineHeight=1;
private int textSize = 50;
private int textColor = Color.BLACK;
private int headerContentColor = 0xffeeeeee;
private int bottomLineColor=0xffeeeeee;
private Bitmap bitmap;
private int bitmapPadding=30;//箭头右边边距
private final float txtYAxis;
private RecyclerView mRecyclerView;
public RecycleViewDecoration() {
mHeaderTxtPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mHeaderTxtPaint.setColor(textColor);
mHeaderTxtPaint.setTextSize(textSize);
mHeaderTxtPaint.setTextAlign(Paint.Align.LEFT);
mHeaderContentPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mHeaderContentPaint.setColor(headerContentColor);
Paint.FontMetrics fontMetrics = mHeaderTxtPaint.getFontMetrics();
float total = -fontMetrics.ascent + fontMetrics.descent;
txtYAxis = total / 2 - fontMetrics.descent;
mBitmapPaint=new Paint(Paint.ANTI_ALIAS_FLAG);
bitmap= BitmapFactory.decodeResource(BaseApplication.getContext().getResources(),
R.mipmap.ic_arrow_right);
mBottomLinePaint=new Paint(Paint.ANTI_ALIAS_FLAG);
mBottomLinePaint.setColor(bottomLineColor);
}
private boolean isInitHeight = false;
/**
* 先调用getItemOffsets再调用onDraw
*/
@Override
public void getItemOffsets(Rect outRect, View itemView, RecyclerView parent, RecyclerView.State state) {
super.getItemOffsets(outRect, itemView, parent, state);
if (mRecyclerView == null) {
mRecyclerView = parent;
}
if (headerDrawEvent != null && !isInitHeight) {
View headerView = headerDrawEvent.getHeaderView(0);
headerView
.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
headerHeight = headerView.getMeasuredHeight();
isInitHeight = true;
}
/*我们为每个不同头部名称的第一个item设置头部高度*/
int pos = parent.getChildAdapterPosition(itemView); //获取当前itemView的位置
String curHeaderName = getHeaderName(pos); //根据pos获取要悬浮的头部名
if (curHeaderName == null) {
return;
}
if (pos == 0 || !curHeaderName.equals(getHeaderName(pos - 1))) {//如果当前位置为0,或者与上一个item头部名不同的,都腾出头部空间
outRect.top = headerHeight; //设置itemView PaddingTop的距离
}
}
public abstract String getHeaderName(int pos);
public abstract String getHeaderRightText(int pos);
private SparseArray stickyHeaderPosArray = new SparseArray<>();//记录每个头部和悬浮头部的坐标信息【用于点击事件】
private GestureDetector gestureDetector;
@Override
public void onDrawOver(Canvas canvas, RecyclerView recyclerView, RecyclerView.State state) {
super.onDrawOver(canvas, recyclerView, state);
if (mRecyclerView == null) {
mRecyclerView = recyclerView;
}
if (gestureDetector == null) {
gestureDetector = new GestureDetector(recyclerView.getContext(), gestureListener);
recyclerView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return gestureDetector.onTouchEvent(event);
}
});
}
stickyHeaderPosArray.clear();
int childCount = recyclerView.getChildCount();//获取屏幕上可见的item数量
int left = recyclerView.getLeft() + recyclerView.getPaddingLeft();
int right = recyclerView.getRight() - recyclerView.getPaddingRight();
String firstHeaderName = null;
String headerRirhtText=null;
int firstPos = 0;
int translateTop = 0;//绘制悬浮头部的偏移量
/*for循环里面绘制每个分组的头部*/
for (int i = 0; i < childCount; i++) {
View childView = recyclerView.getChildAt(i);
int pos = recyclerView.getChildAdapterPosition(childView); //获取当前view在Adapter里的pos
String curHeaderName = getHeaderName(pos); //根据pos获取要悬浮的头部名
String curHeaderRightText=getHeaderRightText(pos);
if (i == 0) {
firstHeaderName = curHeaderName;
headerRirhtText=curHeaderRightText;
firstPos = pos;
}
if (curHeaderName == null)
continue;//如果headerName为空,跳过此次循环
int viewTop = childView.getTop() + recyclerView.getPaddingTop();
if (pos == 0 || !curHeaderName.equals(getHeaderName(pos - 1))) {//如果当前位置为0,或者与上一个item头部名不同的,都腾出头部空间
if (headerDrawEvent != null) {
View headerView;
if (headViewMap.get(pos) == null) {
headerView = headerDrawEvent.getHeaderView(pos);
headerView
.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
headerView.setDrawingCacheEnabled(true);
headerView.layout(0, 0, right, headerHeight);//布局layout
headViewMap.put(pos, headerView);
canvas.drawBitmap(headerView.getDrawingCache(), left, viewTop - headerHeight, null);
} else {
headerView = headViewMap.get(pos);
canvas.drawBitmap(headerView.getDrawingCache(), left, viewTop - headerHeight, null);
}
} else {
canvas.drawRect(left, viewTop - headerHeight, right, viewTop, mHeaderContentPaint);
canvas.drawText(curHeaderName, left + textPaddingLeft, viewTop - headerHeight / 2 + txtYAxis, mHeaderTxtPaint);
if (!TextUtils.isEmpty(headerRirhtText)){
Rect mBounds = new Rect();
mHeaderTxtPaint.getTextBounds(headerRirhtText,0,headerRirhtText.length(),mBounds);
float rightTextWidth=mBounds.width();
canvas.drawText(headerRirhtText, right-rightTextWidth-bitmap.getWidth()-textPaddingRght, viewTop - headerHeight / 2 + txtYAxis, mHeaderTxtPaint);
}
canvas.drawBitmap(bitmap,right-bitmap.getWidth()-bitmapPadding,viewTop -headerHeight / 2 - bitmap.getHeight()/2,mBitmapPaint);
canvas.drawRect(left, viewTop, right, viewTop+bottomLineHeight, mBottomLinePaint);
}
if (headerHeight < viewTop && viewTop <= 2 * headerHeight) { //此判断是刚好2个头部碰撞,悬浮头部就要偏移
translateTop = viewTop - 2 * headerHeight;
}
stickyHeaderPosArray.put(pos, viewTop);//将头部信息放进array
Log.i(TAG, "绘制各个头部" + pos);
}
}
if (firstHeaderName == null)
return;
canvas.save();
canvas.translate(0, translateTop);
if (headerDrawEvent != null) {//inflater
View headerView;
if (headViewMap.get(firstPos) == null) {
headerView = headerDrawEvent.getHeaderView(firstPos);
headerView.measure(
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
headerView.setDrawingCacheEnabled(true);
headerView.layout(0, 0, right, headerHeight);//布局layout
headViewMap.put(firstPos, headerView);
canvas.drawBitmap(headerView.getDrawingCache(), left, 0, null);
} else {
headerView = headViewMap.get(firstPos);
canvas.drawBitmap(headerView.getDrawingCache(), left, 0, null);
}
} else {
/*绘制悬浮的头部*/
canvas.drawRect(left, 0, right, headerHeight, mHeaderContentPaint);
canvas.drawText(firstHeaderName, left + textPaddingLeft, headerHeight / 2 + txtYAxis, mHeaderTxtPaint);
if (!TextUtils.isEmpty(headerRirhtText)){
Rect mBounds = new Rect();
mHeaderTxtPaint.getTextBounds(headerRirhtText,0,headerRirhtText.length(),mBounds);
float rightTextWidth=mBounds.width();
canvas.drawText(headerRirhtText, right-rightTextWidth-bitmap.getWidth()-textPaddingRght, headerHeight / 2 + txtYAxis, mHeaderTxtPaint);
}
canvas.drawBitmap(bitmap,right-bitmap.getWidth()-bitmapPadding,headerHeight / 2 - bitmap.getHeight()/2,mBitmapPaint);
canvas.drawRect(left, headerHeight, right, headerHeight+bottomLineHeight, mBottomLinePaint);
}
canvas.restore();
Log.i(TAG, "绘制悬浮头部");
}
private Map headViewMap = new HashMap<>();
public interface OnHeaderClickListener {
void headerClick(int pos);
}
private OnHeaderClickListener headerClickEvent;
public void setOnHeaderClickListener(OnHeaderClickListener headerClickListener) {
this.headerClickEvent = headerClickListener;
}
private GestureDetector.OnGestureListener gestureListener = new GestureDetector.OnGestureListener() {
@Override
public boolean onDown(MotionEvent e) {
return false;
}
@Override
public void onShowPress(MotionEvent e) {
}
@Override
public boolean onSingleTapUp(MotionEvent e) {
for (int i = 0; i < stickyHeaderPosArray.size(); i++) {
int value = stickyHeaderPosArray.valueAt(i);
LogUtil.e("value"+value);
float y = e.getY();
if (value - headerHeight <= y && y <= value) {//如果点击到分组头
if (headerClickEvent != null) {
headerClickEvent.headerClick(stickyHeaderPosArray.keyAt(i));
LogUtil.e("stickyHeaderPosArray.keyAt(i)"+stickyHeaderPosArray.keyAt(i));
}
return true;
}
}
return false;
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
return false;
}
@Override
public void onLongPress(MotionEvent e) {
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
return false;
}
};
private OnDecorationHeadDraw headerDrawEvent;
public interface OnDecorationHeadDraw {
View getHeaderView(int pos);
}
/**
* 只是用来绘制,不能做其他处理/点击事件等
*/
public void setOnDecorationHeadDraw(OnDecorationHeadDraw decorationHeadDraw) {
this.headerDrawEvent = decorationHeadDraw;
}
private Map imgDrawableMap = new HashMap<>();
private Drawable getImg(String url) {
return imgDrawableMap.get(url);
}
public void onDestory() {
headViewMap.clear();
imgDrawableMap.clear();
stickyHeaderPosArray.clear();
mRecyclerView = null;
setOnHeaderClickListener(null);
setOnDecorationHeadDraw(null);
}
public void setHeaderHeight(int headerHeight) {
this.headerHeight = headerHeight;
}
public void setTextPaddingLeft(int textPaddingLeft) {
this.textPaddingLeft = textPaddingLeft;
}
public void setTextSize(int textSize) {
this.textSize = textSize;
this.mHeaderTxtPaint.setTextSize(textSize);
}
public void setTextColor(int textColor) {
this.textColor = textColor;
this.mHeaderTxtPaint.setColor(textColor);
}
public void setHeaderContentColor(int headerContentColor) {
this.headerContentColor = headerContentColor;
this.mHeaderContentPaint.setColor(headerContentColor);
}
public void setBottomLineHeight(int bottomLineHeight) {
this.bottomLineHeight = bottomLineHeight;
}
public void setBottomLineColor(int bottomLineColor) {
this.bottomLineColor = bottomLineColor;
this.mBottomLinePaint.setColor(bottomLineColor);
}
}
2.使用和原来的一样,但是滑动后头部点击没反应
这个很方便,悬浮头部也可点击,但是点击返回不对,解决办法:直接判断position是否等于0,等于0就返回recycleView的当前显示的第一个item的位置,这样就可以正确获取位置了
StickyRecyclerHeadersTouchListener touchListener =
new StickyRecyclerHeadersTouchListener(recyclerView, headersDecor);
touchListener.setOnHeaderClickListener(
new StickyRecyclerHeadersTouchListener.OnHeaderClickListener() {
@Override
public void onHeaderClick(View header, int position, long headerId) {
int itemPosition;
if (position==0){
itemPosition=manager.findFirstVisibleItemPosition();
}else {
itemPosition=position;
}
}
});
recyclerView.addOnItemTouchListener(touchListener);