参考网址:android recycleView 简单使用二---分割线 - FeelRose - 博客园
app下的build.gradle中
dependencies {
...
implementation 'com.android.support:recyclerview-v7:+'
}
xml布局文件使用
说明:RecyclerView中不能直接设置分隔线,所以设置divider没用
<android.support.v7.widget.RecyclerView
android:id="@+id/lv_data"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
Activity中使用
List dataList = new ArrayList();//数据集合
RecyclerView lv_data = findViewById(R.id.lv_data);
LinearLayoutManager manager = new LinearLayoutManager(this);
lv_data.setLayoutManager(manager);//不设置这个数据不显示
//适配器
RecyclerViewAdapter adapter = new RecyclerViewAdapter(this,list);
lv_data.setAapter(adapter);
//设置分隔线
int dividerHeight = 15; // 分割线高度
int dividerColor = Color.RED; // 分割线颜色
DividerItemDecoration divider = new DividerItemDecoration(dividerHeight, dividerColor);
//addItemDecoration这个方法可以叠加使用
lv_data.addItemDecoration(divider);
lv_data.addItemDecoration(new DividerItemDecoration(this));
适配器
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ItemViewHolder> {
Context context;
List<String> list;
public RecyclerViewAdapter(Context context, List<String> list) {
this.context = context;
this.list = list;
}
@Override
public int getItemCount() {
return list == null ? 0 : list.size();
}
@NonNull
@Override
public ItemViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(context).inflate(R.layout.recyclerview_item, viewGroup, false);
return new ItemViewHolder(view);//初始化item布局
}
@Override
public void onBindViewHolder(@NonNull ItemViewHolder viewHolder, int i) {
viewHolder.tv_item_data.setText(list.get(i));
}
class ItemViewHolder extends RecyclerView.ViewHolder {
TextView tv_item_data,
public ItemViewHolder(View view) {
super(view);
//初始化item控件
tv_item_data = (TextView) view.findViewById(R.id.tv_item_data);
}
}
}
padding
public class DividerItemDecoration extends RecyclerView.ItemDecoration {
public DividerItemDecoration() {
}
@Override
public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
//outRect.bottom、left,right,top设置为int值
outRect.bottom =100 ;
outRect.left =50 ;
}
}
分隔线
public class DividerItemDecoration extends RecyclerView.ItemDecoration {
private Paint paint;
private int dividerHeight;
public DividerItemDecoration(int height, int color) {
this.dividerHeight = height;
paint = new Paint();
paint.setColor(color);
}
@Override
public void onDraw(@NonNull Canvas c, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
int left = parent.getPaddingLeft();
int right = parent.getWidth() - parent.getPaddingRight();
for (int i = 0; i < parent.getChildCount() - 1; i++) {
View child = parent.getChildAt(i);
RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
int top = child.getBottom() + params.bottomMargin;
int bottom = top + dividerHeight;
c.drawRect(left, top, right, bottom, paint);
}
}
@Override
public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
//outRect.bottom、left,right,top设置为int值,设置每一项的padding
outRect.bottom =dividerHeight ;
}
}
标签
public class DividerItemDecoration extends RecyclerView.ItemDecoration {
private int tagWidth; //标签的宽度
private Paint leftPaint; //左边的画笔
private Paint rightPaint; //右边的画笔
public DividerItemDecoration(Context context){
leftPaint =new Paint();
leftPaint.setColor(context.getResources().getColor(R.color.colorPrimary));
rightPaint = new Paint();
rightPaint.setColor(context.getResources().getColor(R.color.colorOrange));//上面是画笔的初始化,和设置颜色,下面是标签宽度的获取
tagWidth = context.getResources().getDimensionPixelSize(R.dimen.tag_width);
}
//绘制标签
@Override
public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
super.onDrawOver(c, parent, state);
int childCount = parent.getChildCount();
for(int i=0;i<childCount;i++){
View child = parent.getChildAt(i);
int pos = parent.getChildAdapterPosition(child);
boolean isLeft = pos%2==0;
if(isLeft){
float left = child.getLeft();
float right = left+tagWidth;
float top = child.getTop();
float bottom =child.getBottom();
c.drawRect(left,top,right,bottom,leftPaint);
}else{
float right = child.getRight();
float left = right-tagWidth;
float top = child.getTop();
float bottom =child.getBottom();
c.drawRect(left,top,right,bottom,rightPaint);
}
}
}
}
section
手机上面的通讯录联系人,不是所有的item都需要分割线,只有同组的第一个需要。
public interface DecorationCallback {
long getGroupId(int position);
String getGroupFirstLine(int position);
}
public class SectionDecoration extends RecyclerView.ItemDecoration {
private DecorationCallback callback;
private TextPaint textPaint; //文字画笔
private Paint paint; //普通画笔
private int topGap; //padding_top
private Paint.FontMetrics fontMetrics;
//自定义构造函数
public SectionDecoration(Context context, DecorationCallback decorationCallback) {
Resources res = context.getResources();
this.callback = decorationCallback;
//画笔
paint = new Paint();
paint.setColor(res.getColor(R.color.colorPrimary));
//文字画笔,样式设置
textPaint = new TextPaint();
textPaint.setTypeface(Typeface.DEFAULT_BOLD); //加粗
textPaint.setAntiAlias(true);
textPaint.setTextSize(70); //字体大小
textPaint.setColor(Color.BLACK); //字体颜色
textPaint.getFontMetrics(fontMetrics); //字体的材质
textPaint.setTextAlign(Paint.Align.LEFT); //字体的向左对齐
fontMetrics = new Paint.FontMetrics();
topGap = res.getDimensionPixelSize(R.dimen.sectioned_top);//32dp Padding——top的值
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
//视图的位置
int pos = parent.getChildAdapterPosition(view);
long groupId = callback.getGroupId(pos);
if (groupId < 0) return;
if (pos == 0 || isFirstInGroup(pos)) {//同组的第一个才添加padding
outRect.top = topGap;
} else {
outRect.top = 0;
}
}
@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
super.onDraw(c, parent, state);
int left = parent.getPaddingLeft();
int right = parent.getWidth() - parent.getPaddingRight();
int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
View view = parent.getChildAt(i);
int position = parent.getChildAdapterPosition(view);
long groupId = callback.getGroupId(position);
if (groupId < 0) return;
//分组的文本
String textLine = callback.getGroupFirstLine(position).toUpperCase();
if (position == 0 || isFirstInGroup(position)) {
float top = view.getTop() - topGap;
float bottom = view.getTop();
c.drawRect(left, top, right, bottom, paint);//绘制矩形
c.drawText(textLine, left, bottom, textPaint);//绘制文本
}
}
}
//是否是一个组
private boolean isFirstInGroup(int pos) {
if (pos == 0) {
return true;
} else {
long prevGroupId = callback.getGroupId(pos - 1);
long groupId = callback.getGroupId(pos);
return prevGroupId != groupId;
}
}
//接口实现分组的依据
public interface DecorationCallback {
long getGroupId(int position);
String getGroupFirstLine(int position);
}
}
在Activity中使用
mRecycleView.addItemDecoration(new SectionDecoration(this,
new SectionDecoration.DecorationCallback() {
@Override
public long getGroupId(int position) {
return Character.toUpperCase(homeAdapter.mTitles[position].charAt(0));
}
@Override
public String getGroupFirstLine(int position) {
return homeAdapter.mTitles[position].substring(0, 1).toUpperCase();
}
}
));
StickyHeader
手机联系人固定头部
public class PinnedSectionDecoration extends RecyclerView.ItemDecoration {
private static final String TAG = "PinnedSectionDecoration";
private DecorationCallback callback;
private TextPaint textPaint;
private Paint paint;
private int topGap;
private Paint.FontMetrics fontMetrics;
public PinnedSectionDecoration(Context context, DecorationCallback decorationCallback) {
Resources res = context.getResources();
this.callback = decorationCallback;
paint = new Paint();
paint.setColor(res.getColor(R.color.colorAccent));
textPaint = new TextPaint();
textPaint.setTypeface(Typeface.DEFAULT_BOLD);
textPaint.setAntiAlias(true);
textPaint.setTextSize(80);
textPaint.setColor(Color.BLACK);
textPaint.getFontMetrics(fontMetrics);
textPaint.setTextAlign(Paint.Align.LEFT);
fontMetrics = new Paint.FontMetrics();
topGap = res.getDimensionPixelSize(R.dimen.sectioned_top);
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
int pos = parent.getChildAdapterPosition(view);
long groupId = callback.getGroupId(pos);
if (groupId < 0) return;
if (pos == 0 || isFirstInGroup(pos)) {
outRect.top = topGap;
} else {
outRect.top = 0;
}
}
@Override
public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
super.onDrawOver(c, parent, state);
int itemCount = state.getItemCount();
int childCount = parent.getChildCount();
int left = parent.getPaddingLeft();
int right = parent.getWidth() - parent.getPaddingRight();
float lineHeight = textPaint.getTextSize() + fontMetrics.descent;
long preGroupId, groupId = -1;
for (int i = 0; i < childCount; i++) {
View view = parent.getChildAt(i);
int position = parent.getChildAdapterPosition(view);
preGroupId = groupId;
groupId = callback.getGroupId(position);
if (groupId < 0 || groupId == preGroupId) continue;
String textLine = callback.getGroupFirstLine(position).toUpperCase();
if (TextUtils.isEmpty(textLine)) continue;
int viewBottom = view.getBottom();
float textY = Math.max(topGap, view.getTop());
if (position + 1 < itemCount) { //下一个和当前不一样移动当前
long nextGroupId = callback.getGroupId(position + 1);
if (nextGroupId != groupId && viewBottom < textY ) {//组内最后一个view进入了header
textY = viewBottom;
}
}
c.drawRect(left, textY - topGap, right, textY, paint);
c.drawText(textLine, left, textY, textPaint);
}
}
}