RecyclerView添加分割线
RecyclerView没有默认的分割线 需要自己去绘制,实现rv的分割线需要继承ITEMDecoration,先看两张效果图
两种实现的方法,一种是实现了 水平或垂直的分割线,一种是实现了网格的分割线。
我把实现两种方式的代码放在下面了 根据实际需要进行使用。
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<android.support.v7.widget.RecyclerView
android:id="@+id/rv_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="item">
</android.support.v7.widget.RecyclerView>
</android.support.constraint.ConstraintLayout>
recycler_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/tv_text"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="item"/>
</LinearLayout>
drawable下的item_divder.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/tv_text"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="item"/>
</LinearLayout>
RecyclerViewAdapter
public class RecylerViewAdapter extends RecyclerView.Adapter<RecylerViewAdapter.MyAdapterHolder> {
private List<String> stringList;
private onClickListener onItemListener;
private List<Integer> heights;
public RecylerViewAdapter(List stringList){
this.stringList=stringList;
heights = new ArrayList<>();
for (int i = 0; i < stringList.size(); i++) {
heights.add((int)(200+Math.random()*50));
}
}
class MyAdapterHolder extends RecyclerView.ViewHolder{
public TextView textView;
public MyAdapterHolder(@NonNull View itemView) {
super(itemView);
textView=itemView.findViewById(R.id.tv_text);
}
}
@NonNull
@Override
public MyAdapterHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
MyAdapterHolder holder=new MyAdapterHolder(View.inflate(viewGroup.getContext(),R.layout.recycler_item,null));
return holder;
}
@Override
public void onBindViewHolder(@NonNull final MyAdapterHolder viewHolder, int i) {
//绑定数据
final ViewGroup.LayoutParams params = viewHolder.textView.getLayoutParams();
params.height = heights.get(i);
viewHolder.textView.setBackgroundColor(Color.rgb(100, (int)(Math.random()*255), (int)(Math.random()*255)));
viewHolder.textView.setLayoutParams(params);
viewHolder.textView.setText(stringList.get(i));
if(onItemListener!=null){
viewHolder.textView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onItemListener.itemclick(v,viewHolder.getLayoutPosition());
}
});
}
}
@Override
public int getItemCount() {
return stringList.size();
}
public interface onClickListener{
void itemclick(View view,int position);
}
public void setOnItemClick(onClickListener listener){
onItemListener =listener;
}
}
绘制水平和垂直的ItemDecoration
public class RecyclerItemDecoration extends RecyclerView.ItemDecoration {
private int mOrientation=LinearLayoutManager.VERTICAL;
private Drawable mDivider;
private int[] attrs=new int[]{
android.R.attr.listDivider
};
public RecyclerItemDecoration(Context context,int orientation){
TypedArray typedArray=context.obtainStyledAttributes(attrs);
mDivider=typedArray.getDrawable(0);
typedArray.recycle();
setOrientation(orientation);
}
public void setOrientation(int orientation){
if (orientation!= LinearLayoutManager.HORIZONTAL && orientation!=LinearLayoutManager.VERTICAL){
throw new IllegalArgumentException("来了老弟");
}
this.mOrientation=orientation;
}
/**
* recyclerView 会回调该方法 需要自己去绘制间隔线
* @param c
* @param parent
* @param state
*/
@Override
public void onDraw(@NonNull Canvas c, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
if (mOrientation==LinearLayoutManager.VERTICAL){
draVertical(c,parent);
}else {
draHorizontal(c,parent);
}
super.onDraw(c, parent, state);
}
/**
* 垂直分割线
* @param c
* @param parent
*/
private void draHorizontal(Canvas c, RecyclerView parent) {
int top = parent.getPaddingTop();
int bottom = parent.getHeight() - parent.getPaddingBottom();
int childCount = parent.getChildCount();
for (int i = 0; i < childCount ; i++) {
View child = parent.getChildAt(i);
RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
int left = child.getRight() + params.rightMargin + Math.round(ViewCompat.getTranslationX(child));
int right = left + mDivider.getIntrinsicHeight();
mDivider.setBounds(left, top , right, bottom);
mDivider.draw(c);
}
}
/**
* 水平分割线
* @param c
* @param parent
*/
private void draVertical(Canvas c, RecyclerView parent) {
int left=parent.getPaddingLeft();
int right=parent.getWidth() -parent.getPaddingRight();
int childCount=parent.getChildCount();
for (int i = 0; i < childCount; i++) {
View child=parent.getChildAt(i);
RecyclerView.LayoutParams params= (RecyclerView.LayoutParams) child.getLayoutParams();
int top=child.getTop()+params.topMargin+ Math.round(ViewCompat.getTranslationY(child));
int bottom=top+mDivider.getIntrinsicHeight();
mDivider.setBounds(left,top,right,bottom);
mDivider.draw(c);
}
}
/**
*1、调用此方法获取条目偏移量(首先会先获取条目之间的间隙宽度---》通过rect来提现 矩形区域)
* 2、获取条目的偏移量 (所有条目都会调用该方法)
* @param outRect 矩形区域 left、top、bottom、right
* @param view
* @param parent
* @param state
*/
@Override
public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
// super.getItemOffsets(outRect, view, parent, state);
if (mOrientation==LinearLayoutManager.VERTICAL){
outRect.set(0,0,0,mDivider.getIntrinsicHeight());
}else {
outRect.set(0,0,mDivider.getIntrinsicWidth(),0);
}
}
}
绘制网格布局的ItemDecoration
public class DividerGirdViewItemDecoration extends RecyclerView.ItemDecoration {
private Drawable mDivider;
private int[] attrs= new int[]{
android.R.attr.listDivider
};
public DividerGirdViewItemDecoration(Context context) {
TypedArray typedArray = context.obtainStyledAttributes(attrs);
mDivider = typedArray.getDrawable(0);
typedArray.recycle();
}
@Override
public void onDraw(@NonNull Canvas c, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
drawVertical(c,parent);
drawHorizontal(c,parent);
}
/**
* 绘制水平间隔线
* @param c
* @param parent
*/
private void drawHorizontal(Canvas c, RecyclerView parent) {
int childCount=parent.getChildCount();
for (int i = 0; i < childCount; i++) {
View child=parent.getChildAt(i);
RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
int left=child.getLeft()-params.leftMargin;
int right=child.getRight()+ params.rightMargin;
int top=child.getBottom()+params.bottomMargin;
int bottom=top+mDivider.getIntrinsicHeight();
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
}
}
/**
* 绘制垂直间隔线
* @param c
* @param parent
*/
private void drawVertical(Canvas c, RecyclerView parent) {
int childCount=parent.getChildCount();
for (int i = 0; i < childCount; i++) {
View child=parent.getChildAt(i);
RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
int left = child.getRight() + params.rightMargin;
int right = left + mDivider.getIntrinsicWidth();
int top = child.getTop() - params.topMargin;
int bottom = child.getBottom() + params.bottomMargin;
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
}
}
@Override
public void getItemOffsets(@NonNull Rect outRect, int itemPosition, @NonNull RecyclerView parent) {
// super.getItemOffsets(outRect, itemPosition, parent);
int right = mDivider.getIntrinsicWidth();
int bottom = mDivider.getIntrinsicHeight();
//代表四个方向的偏移值
if (isLastColumn(itemPosition,parent)){
Log.d("DividerGirdViewItemDeco", "右");
right=0;
} else if (isLastRow(itemPosition,parent)){
Log.d("DividerGirdViewItemDeco", "下");
bottom=0;
}
outRect.set(0,0,right,bottom);
}
/**
* 是否最后一行
* @param itemPosition
* @return
*/
private boolean isLastRow(int itemPosition,RecyclerView parent) {
int spanCount = getSpanCount(parent);
RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
//有多少列
if(layoutManager instanceof GridLayoutManager){
int childCount = parent.getAdapter().getItemCount();
int lastRowCount = childCount%spanCount;
//最后一行的数量小于spanCount
if(lastRowCount==0||lastRowCount<spanCount){
return true;
}
}
return false;
}
/**
* 是否是最后一列
* @param itemPosition
* @return
*/
private boolean isLastColumn(int itemPosition,RecyclerView parent) {
RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
//有多少列
if(layoutManager instanceof GridLayoutManager){
int spanCount = getSpanCount(parent);
if((itemPosition+1)%spanCount==0){
return true;
}
}
return false;
}
private int getSpanCount(RecyclerView parent){
RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
if(layoutManager instanceof GridLayoutManager){
GridLayoutManager lm = (GridLayoutManager)layoutManager;
int spanCount = lm.getSpanCount();
return spanCount;
}
return 0;
}
}
主页面调用MainActivity
public class MainActivity extends AppCompatActivity {
private RecyclerView rvView;
private List stringLists;
private RecylerViewAdapter adapterHolder;
private DividerGirdViewItemDecoration itemDecoration;
private RecyclerItemDecoration decoration;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
rvView = (RecyclerView) findViewById(R.id.rv_view);
stringLists=new ArrayList();
for (int i=0;i<100;i++){
stringLists.add("条目"+i);
}
/* //垂直或者水平效果
decoration=new RecyclerItemDecoration(this, LinearLayoutManager.VERTICAL);
rvView.setLayoutManager(new LinearLayoutManager(this));
rvView.addItemDecoration(decoration);*/
//瀑布流效果
itemDecoration=new DividerGirdViewItemDecoration(this);
rvView.setLayoutManager(new StaggeredGridLayoutManager(3,LinearLayoutManager.VERTICAL));
rvView.addItemDecoration(itemDecoration);
adapterHolder = new RecylerViewAdapter(stringLists);
adapterHolder.setOnItemClick(new RecylerViewAdapter.onClickListener() {
@Override
public void itemclick(View view, int position) {
Toast.makeText(MainActivity.this, "position:" + position, Toast.LENGTH_SHORT).show();
}
});
rvView.setAdapter(adapterHolder);
}
}