1,线性布局
列表图片- 1,引入
compile 'com.android.support:recyclerview-v7:27.1.1' - 2,xml布局
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="@+id/rv_linear_list"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</android.support.constraint.ConstraintLayout>
- 3,Activity内容
public class RvLinearActivity extends AppCompatActivity {
private android.support.v7.widget.RecyclerView rvlinearlist;
private ArrayList<String> mData;
private RvLinearAdapter mAdapter;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_linear);
this.rvlinearlist = (RecyclerView) findViewById(R.id.rv_linear_list);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
//设置方向,默认方向(垂直)
linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
rvlinearlist.setLayoutManager(linearLayoutManager);
mData = new ArrayList<>();
for (int i = 0; i < 10; i++) {
mData.add("频道"+i);
}
mAdapter = new RvLinearAdapter(this, mData);
rvlinearlist.setAdapter(mAdapter);
//添加下划线
}
}
- 4,adapter
public class RvLinearAdapter extends RecyclerView.Adapter<RvLinearAdapter.ViewHolder>{
private final LayoutInflater mLayoutInflater;
private Context mContext;
private List<String>mData;
public RvLinearAdapter(Context context, List<String> data) {
mContext = context;
mData = data;
mLayoutInflater = LayoutInflater.from(context);
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View inflate = mLayoutInflater.inflate(R.layout.item_rv_linear, parent, false);
return new ViewHolder(inflate);
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
holder.tvText.setText(mData.get(position));
//点击监听
holder.tvText.setOnClickListener(v->{
Toast.makeText(mContext, mData.get(position), Toast.LENGTH_SHORT).show();
});
}
@Override
public int getItemCount() {
return mData.size();
}
class ViewHolder extends RecyclerView.ViewHolder {
TextView tvText;
public ViewHolder(View itemView) {
super(itemView);
tvText=itemView.findViewById(R.id.tv_item_rv_linear_text);
}
}
}
-
5,添加下划线
1,添加默认分割线
image.png
rvlinearlist.addItemDecoration(new DividerItemDecoration
(this, LinearLayoutManager.VERTICAL));//默认类型的分割线
2,修改默认分割线
image.png
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="android:listDivider">@drawable/recyclerview_decoration</item>
</style>
recyclerview_decoration:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/red"/>
<size android:height="1dp"/>
</shape>
3,头部也带分割线
//自定义
public class ListViewHeadDecoration extends RecyclerView.ItemDecoration {//从头部开始绘制
private Drawable mDrawable;
public ListViewHeadDecoration(Context context, int drawableId) {
mDrawable = ContextCompat.getDrawable(context, drawableId);
}
@Override
public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
final int left = parent.getPaddingLeft();
final int right = parent.getWidth() - parent.getPaddingRight();
final int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
final View child = parent.getChildAt(i);
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
// 以下计算主要用来确定绘制的位置
final int top = child.getTop() -mDrawable.getIntrinsicHeight()+
Math.round(ViewCompat.getTranslationY(child));
final int bottom = top + mDrawable.getIntrinsicHeight();
mDrawable.setBounds(left, top, right, bottom);
mDrawable.draw(c);
}
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
outRect.set(0, mDrawable.getIntrinsicHeight(),0,0);
}
}
//调用
rvlinearlist.addItemDecoration(new ListViewHeadDecoration
(this,R.drawable.listview_decoration));
头部不加分割线:
public class ListViewDecoration extends RecyclerView.ItemDecoration {
private Drawable mDrawable;
public ListViewDecoration(Context context, int drawableId) {
mDrawable = ContextCompat.getDrawable(context, drawableId);
}
@Override
public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
final int left = parent.getPaddingLeft();
final int right = parent.getWidth() - parent.getPaddingRight();
final int childCount = parent.getChildCount();
for (int i = 0; i < childCount-1; i++) {
final View child = parent.getChildAt(i);
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
// 以下计算主要用来确定绘制的位置
final int top = child.getBottom() + params.bottomMargin;
final int bottom = top + mDrawable.getIntrinsicHeight();
mDrawable.setBounds(left, top, right, bottom);
mDrawable.draw(c);
}
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
outRect.set(0, 0, 0, mDrawable.getIntrinsicHeight());
}
}
- 4,地址
源码
2,网格布局添加分割线
image.png- 1,Xml文件
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="@+id/rv_linear_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="20dp"/>
</android.support.constraint.ConstraintLayout>
- 2,Activity文件
public class GridLineActivity extends AppCompatActivity {
private android.support.v7.widget.RecyclerView rvlinearlist;
private ArrayList<String> mData;
private GridAdapter mGridAdapter;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_linear);
this.rvlinearlist = (RecyclerView) findViewById(R.id.rv_linear_list);
initData();
initAdapter();
}
private void initAdapter() {
GridLayoutManager gridLayoutManager = new GridLayoutManager(this, 2);
rvlinearlist.setLayoutManager(gridLayoutManager);
//使用添加头和尾的适配器
mGridAdapter = new GridAdapter(this, mData);
rvlinearlist.setAdapter(mGridAdapter);
//添加分割线
//rvlinearlist.addItemDecoration(new Divider2(this));
//添加分割线
ItemDivider itemDivider = new ItemDivider();
itemDivider.setDividerColor(Color.YELLOW).setDividerWith(5);
rvlinearlist.addItemDecoration(itemDivider);
}
private void initData() {
mData = new ArrayList<>();
for (int i = 0; i < 10; i++) {
mData.add("频道"+i);
}
}
}
- 3,Adapter文件
public class GridAdapter extends RecyclerView.Adapter<GridAdapter.ViewHolder>{
private final LayoutInflater mLayoutInflater;
private Context mContext;
private List<String>mData;
//Type
private int TYPE_NORMAL = 1000;
private int TYPE_HEADER = 1001;
private int TYPE_FOOTER = 1002;
public GridAdapter(Context context, List<String> data) {
mContext = context;
mData = data;
mLayoutInflater = LayoutInflater.from(context);
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View inflate = mLayoutInflater.inflate(R.layout.item_rv_linear, parent, false);
return new ViewHolder(inflate);
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
holder.tvText.setText(mData.get(position));
//点击监听
holder.tvText.setOnClickListener(v->{
Toast.makeText(mContext, mData.get(position), Toast.LENGTH_SHORT).show();
});
}
@Override
public int getItemCount() {
return mData.size();
}
@Override
public int getItemViewType(int position) {
return super.getItemViewType(position);
}
class ViewHolder extends RecyclerView.ViewHolder {
TextView tvText;
public ViewHolder(View itemView) {
super(itemView);
tvText=itemView.findViewById(R.id.tv_item_rv_linear_text);
}
}
}
- 4,用到的添加分割线方法
方法一:(这个也可以用到线性布局中)
public class ItemDivider extends RecyclerView.ItemDecoration {
private int dividerWith = 1;
private Paint paint;
private RecyclerView.LayoutManager layoutManager;
// 构造方法,可以在这里做一些初始化,比如指定画笔颜色什么的
public ItemDivider() {
initPaint();
paint.setColor(0xffff0000);
}
private void initPaint() {
if (paint == null) {
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setStyle(Paint.Style.FILL);
}
}
public ItemDivider setDividerWith(int dividerWith) {
this.dividerWith = dividerWith;
return this;
}
public ItemDivider setDividerColor(int color) {
initPaint();
paint.setColor(color);
return this;
}
/**
* 指定item之间的间距(就是指定分割线的宽度) 回调顺序 1
* @param outRect Rect to receive the output.
* @param view The child view to decorate
* @param parent RecyclerView this ItemDecoration is decorating
* @param state The current state of RecyclerView.
*/
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
if (layoutManager == null) {
layoutManager = parent.getLayoutManager();
}
// 适用 LinearLayoutManager 和 GridLayoutManager
if (layoutManager instanceof LinearLayoutManager) {
int orientation = ((LinearLayoutManager) layoutManager).getOrientation();
if (orientation == LinearLayoutManager.VERTICAL) {
// 水平分割线将绘制在item底部
outRect.bottom = dividerWith;
} else if (orientation == LinearLayoutManager.HORIZONTAL) {
// 垂直分割线将绘制在item右侧
outRect.right = dividerWith;
}
if (layoutManager instanceof GridLayoutManager) {
GridLayoutManager.LayoutParams lp = (GridLayoutManager.LayoutParams) view.getLayoutParams();
// 如果是 GridLayoutManager 则需要绘制另一个方向上的分割线
if (orientation == LinearLayoutManager.VERTICAL && lp != null && lp.getSpanIndex() > 0) {
// 如果列表是垂直方向,则最左边的一列略过
outRect.left = dividerWith;
} else if (orientation == LinearLayoutManager.HORIZONTAL && lp != null && lp.getSpanIndex() > 0) {
// 如果列表是水平方向,则最上边的一列略过
outRect.top = dividerWith;
}
}
}
}
/**
* 在item 绘制之前调用(就是绘制在 item 的底层) 回调顺序 2
* 一般分割线在这里绘制
* 看到canvas,对自定义控件有一定了解的话,就能想到为什么说给RecyclerView设置分割线更灵活了
* @param c Canvas to draw into
* @param parent RecyclerView this ItemDecoration is drawing into
* @param state The current state of RecyclerView
*/
@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
super.onDraw(c, parent, state);
// 这个值是为了补偿横竖方向上分割线交叉处间隙
int offSet = (int) Math.ceil(dividerWith * 1f / 2);
for (int i = 0; i < parent.getChildCount(); i++) {
View child = parent.getChildAt(i);
RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
int left1 = child.getRight() + params.rightMargin;
int right1 = left1 + dividerWith;
int top1 = child.getTop() - offSet - params.topMargin;
int bottom1 = child.getBottom() + offSet + params.bottomMargin;
//绘制分割线(矩形)
c.drawRect(left1, top1, right1, bottom1, paint);
int left2 = child.getLeft() - offSet - params.leftMargin;
int right2 = child.getRight() + offSet + params.rightMargin;
int top2 = child.getBottom() + params.bottomMargin;
int bottom2 = top2 + dividerWith;
//绘制分割线(矩形)
c.drawRect(left2, top2, right2, bottom2, paint);
}
}
/**
* 在item 绘制之后调用(就是绘制在 item 的上层) 回调顺序 3
* 也可以在这里绘制分割线,和上面的方法 二选一
* @param c Canvas to draw into
* @param parent RecyclerView this ItemDecoration is drawing into
* @param state The current state of RecyclerView
*/
@Override
public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
super.onDrawOver(c, parent, state);
}
}
直接调用:
ItemDivider itemDivider = new ItemDivider();
itemDivider.setDividerColor(Color.YELLOW).setDividerWith(5);
rvlinearlist.addItemDecoration(itemDivider);
方法二:
public class Divider2 extends RecyclerView.ItemDecoration
{
private static final int[] ATTRS = new int[] { android.R.attr.listDivider };
private Drawable mDivider;
public Divider2(Context context)
{
final TypedArray a = context.obtainStyledAttributes(ATTRS);
mDivider = a.getDrawable(0);
a.recycle();
}
@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state)
{
drawHorizontal(c, parent);
drawVertical(c, parent);
}
private int getSpanCount(RecyclerView parent)
{
// 列数
int spanCount = -1;
RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
if (layoutManager instanceof GridLayoutManager)
{
spanCount = ((GridLayoutManager) layoutManager).getSpanCount();
} else if (layoutManager instanceof StaggeredGridLayoutManager)
{
spanCount = ((StaggeredGridLayoutManager) layoutManager)
.getSpanCount();
}
return spanCount;
}
public void drawHorizontal(Canvas c, RecyclerView parent)
{
int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++)
{
final View child = parent.getChildAt(i);
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
.getLayoutParams();
final int left = child.getLeft() - params.leftMargin;
// final int right = child.getRight() + params.rightMargin
// + mDivider.getIntrinsicWidth();
final int right = child.getRight() + params.rightMargin
+ mDivider.getIntrinsicWidth();
final int top = child.getBottom() + params.bottomMargin;
final int bottom = top + mDivider.getIntrinsicHeight();
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
}
}
public void drawVertical(Canvas c, RecyclerView parent)
{
final int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++)
{
final View child = parent.getChildAt(i);
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
.getLayoutParams();
final int top = child.getTop() - params.topMargin;
final int bottom = child.getBottom() + params.bottomMargin;
final int left = child.getRight() + params.rightMargin;
final int right = left + mDivider.getIntrinsicWidth();
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
}
}
private boolean isLastColum(RecyclerView parent, int pos, int spanCount,
int childCount)
{
RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
if (layoutManager instanceof GridLayoutManager)
{
if ((pos + 1) % spanCount == 0)// 如果是最后一列,则不需要绘制右边
{
return true;
}
} else if (layoutManager instanceof StaggeredGridLayoutManager)
{
int orientation = ((StaggeredGridLayoutManager) layoutManager)
.getOrientation();
if (orientation == StaggeredGridLayoutManager.VERTICAL)
{
if ((pos + 1) % spanCount == 0)// 如果是最后一列,则不需要绘制右边
{
return true;
}
} else
{
childCount = childCount - childCount % spanCount;
if (pos >= childCount)// 如果是最后一列,则不需要绘制右边
return true;
}
}
return false;
}
private boolean isLastRaw(RecyclerView parent, int pos, int spanCount,
int childCount)
{
RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
if (layoutManager instanceof GridLayoutManager)
{
childCount = childCount - childCount % spanCount;
// if(childCount % spanCount == 0){
// childCount=childCount-spanCount;
// }else{
// childCount = childCount - childCount % spanCount;
// }
if (pos >= childCount)// 如果是最后一行,则不需要绘制底部
return true;
} else if (layoutManager instanceof StaggeredGridLayoutManager)
{
int orientation = ((StaggeredGridLayoutManager) layoutManager)
.getOrientation();
// StaggeredGridLayoutManager 且纵向滚动
if (orientation == StaggeredGridLayoutManager.VERTICAL)
{
childCount = childCount - childCount % spanCount;
// 如果是最后一行,则不需要绘制底部
if (pos >= childCount)
return true;
} else
// StaggeredGridLayoutManager 且横向滚动
{
// 如果是最后一行,则不需要绘制底部
if ((pos + 1) % spanCount == 0)
{
return true;
}
}
}
// if(childCount % spanCount == 0){
// childCount=childCount-spanCount;
// }else{
// childCount = childCount - childCount % spanCount;
// }
// if (pos >= childCount)// 如果是最后一行,则不需要绘制底部
// return true;
return false;
}
private boolean isLastRaw2(RecyclerView parent, int pos, int spanCount,
int childCount)
{
if(childCount % spanCount == 0){
childCount=childCount-spanCount;
}else{
childCount = childCount - childCount % spanCount;
}
if (pos >= childCount){
// 如果是最后一行,则不需要绘制底部
return true;
}
return false;
}
// @Override
// public void getItemOffsets(Rect outRect, int itemPosition,
// RecyclerView parent)
// {
//
//// int left = column * mBuilder.dividerVerSize / spanCount;
//// int right = mBuilder.dividerVerSize - (column + 1) * mBuilder.dividerVerSize / spanCount;
//
//
//
//
//
// int spanCount = getSpanCount(parent);
// int childCount = parent.getAdapter().getItemCount();
//
// int column=itemPosition%spanCount;
// int right= mDivider.getIntrinsicWidth()-(column+1)*mDivider.getIntrinsicWidth()/spanCount;
// int left=column*mDivider.getIntrinsicWidth()/spanCount;
//
// if (isLastRaw(parent, itemPosition, spanCount, childCount))// 如果是最后一行,则不需要绘制底部
// {
// outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
//
// } else if (isLastColum(parent, itemPosition, spanCount, childCount))// 如果是最后一列,则不需要绘制右边
// {
//
// outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
// } else
// {
// outRect.set(left, 0, right,
// mDivider.getIntrinsicHeight());
// //Log.i("MMM", "getItemOffsets: "+mDivider.getIntrinsicWidth()+"||"+ mDivider.getIntrinsicHeight());
// }
// }
@Override
public void getItemOffsets(Rect outRect, int itemPosition,
RecyclerView parent)
{
int spanCount = getSpanCount(parent);
int childCount = parent.getAdapter().getItemCount();
int left,top=0,right,bottom;
int eachWidth = (spanCount - 1) * mDivider.getIntrinsicHeight() / spanCount;
int dl = mDivider.getIntrinsicHeight() - eachWidth;
left = itemPosition % spanCount * dl;
right = eachWidth - left;
bottom = mDivider.getIntrinsicHeight();
if (isLastRaw(parent, itemPosition, spanCount, childCount)) {
bottom = 0;
}
outRect.set(left, top, right, bottom);
// if (isLastRaw(parent, itemPosition, spanCount, childCount))// 如果是最后一行,则不需要绘制底部
// {
// outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
// } else if (isLastColum(parent, itemPosition, spanCount, childCount))// 如果是最后一列,则不需要绘制右边
// {
// outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
// } else
// {
// outRect.set(0, 0, mDivider.getIntrinsicWidth(),
// mDivider.getIntrinsicHeight());
// }
}
}
需要的style文件:
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="android:listDivider">@drawable/listview_decoration</item>
</style>
资源文件:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/red"/>
<size android:height="10dp"
android:width="10dp"/>
</shape>
使用:
rvlinearlist.addItemDecoration(new Divider2(this));
网友评论