欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android Recyclerview 网格布局分割线

程序员文章站 2022-08-05 20:05:55
1上一篇仿微信图片选择器的时候分割线出了点bug,其实是我把一块关键代码删掉了,不过无关紧要,这次单独写一篇 2csdn上hongyang大神已经写过了,但是按照他写的方法我自己试了一下网格布局的有点问题,具体是什么问题已经记不清了(没有质疑大神代码的意思,貌似是他的代码有一个方法过期了),我这个是 ......

1上一篇仿微信图片选择器的时候分割线出了点bug,其实是我把一块关键代码删掉了,不过无关紧要,这次单独写一篇

2csdn上hongyang大神已经写过了,但是按照他写的方法我自己试了一下网格布局的有点问题,具体是什么问题已经记不清了(没有质疑大神代码的意思,貌似是他的代码有一个方法过期了),我这个是自己亲测没问题的

3步骤,新建一个DiciderGridItemDecoration

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.support.annotation.IntDef;
import android.support.v4.view.ViewCompat;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;
import android.util.SparseArray;
import android.util.SparseIntArray;
import android.view.View;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

/**
 * Created by MAC on 2018/2/5.
 */

public class DividerGridItemDecoration extends RecyclerView.ItemDecoration {
    private static final int[] ATTRS = new int[]{android.R.attr.listDivider}; //这个就是设置样式的地方(颜色,宽度等等)
    public static final int GRID_DIVIDER_HORIZONTAL = GridLayoutManager.HORIZONTAL;
    public static final int GRID_DIVIDER_VERTICAL = GridLayoutManager.VERTICAL;

    private final SparseIntArray mHorizontalDividerOffsets = new SparseIntArray();
    private final SparseIntArray mVerticalDividerOffsets = new SparseIntArray();

    private final SparseArray<DrawableCreator> mTypeDrawableFactories = new SparseArray<>();

    @IntDef({
            GRID_DIVIDER_HORIZONTAL,
            GRID_DIVIDER_VERTICAL
    })
    @Retention(RetentionPolicy.SOURCE)
    private @interface Orientation {
    }

    @Orientation
    private int mOrientation;
    private Drawable mHorizontalDivider;
    private Drawable mVerticalDivider;

    public DividerGridItemDecoration(Context context, @Orientation int orientation) {
        resolveDivider(context);
        setOrientation(orientation);
    }

    private void resolveDivider(Context context) {
        final TypedArray a = context.obtainStyledAttributes(ATTRS);
        mVerticalDivider = mHorizontalDivider = a.getDrawable(0);
        a.recycle();
    }

    public void setOrientation(int orientation) {
        this.mOrientation = orientation;
    }

    public void setVerticalDivider(Drawable verticalDivider) {
        this.mVerticalDivider = verticalDivider;
    }

    public void setHorizontalDivider(Drawable horizontalDivider) {
        this.mHorizontalDivider = horizontalDivider;
    }

    @Override
    public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
        drawHorizontalDividers(c, parent);
        drawVerticalDividers(c, parent);
    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        final int spanCount = getSpanCount(parent);
        final int childCount = parent.getAdapter().getItemCount();
        final int adapterPosition = parent.getChildAdapterPosition(view);

        if (mHorizontalDividerOffsets.indexOfKey(adapterPosition) < 0) {
            mHorizontalDividerOffsets.put(adapterPosition, getHorizontalDivider(parent, adapterPosition).getIntrinsicHeight());
        }

        if (mVerticalDividerOffsets.indexOfKey(adapterPosition) < 0) {
            mVerticalDividerOffsets.put(adapterPosition, getVerticalDivider(parent, adapterPosition).getIntrinsicHeight());
        }

        outRect.set(0, 0, mHorizontalDividerOffsets.get(adapterPosition), mVerticalDividerOffsets.get(adapterPosition));

        if (isLastRow(adapterPosition, spanCount, childCount)) {
            outRect.bottom = 0;
        }

        if (isLastColumn(adapterPosition, spanCount, childCount)) {
            outRect.right = 0;
        }

    }

    private boolean isLastColumn(int position, int spanCount, int childCount) {
        if (mOrientation == GRID_DIVIDER_VERTICAL) {
            return (position + 1) % spanCount == 0;
        } else {
            int lastColumnCount = childCount % spanCount;
            lastColumnCount = lastColumnCount == 0 ? spanCount : lastColumnCount;
            return position >= childCount - lastColumnCount;
        }
    }

    private boolean isLastRow(int position, int spanCount, int childCount) {
        if (mOrientation == GRID_DIVIDER_VERTICAL) {
            int lastColumnCount = childCount % spanCount;
            lastColumnCount = lastColumnCount == 0 ? spanCount : lastColumnCount;
            return position >= childCount - lastColumnCount;
        } else {
            return (position + 1) % spanCount == 0;
        }
    }

    private int getSpanCount(RecyclerView parent) {
        RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();

        if (layoutManager instanceof GridLayoutManager) {
            return ((GridLayoutManager) layoutManager).getSpanCount();
        } else if (layoutManager instanceof StaggeredGridLayoutManager) {
            return ((StaggeredGridLayoutManager) layoutManager).getSpanCount();
        } else {
            throw new UnsupportedOperationException("the GridDividerItemDecoration can only be used in " +
                    "the RecyclerView which use a GridLayoutManager or StaggeredGridLayoutManager");
        }
    }

    public void drawVerticalDividers(Canvas c, RecyclerView parent) {
        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 Drawable divider = getVerticalDivider(parent, params.getViewAdapterPosition());
            final int top = child.getBottom() + params.bottomMargin + Math.round(ViewCompat.getTranslationY(child));
            final int bottom = top + divider.getIntrinsicHeight();

            mVerticalDividerOffsets.put(params.getViewAdapterPosition(), divider.getIntrinsicHeight());

            divider.setBounds(left, top, right, bottom);
            divider.draw(c);
        }
    }

    public void drawHorizontalDividers(Canvas c, RecyclerView parent) {
        final int top = parent.getPaddingTop();
        final int bottom = parent.getHeight() - parent.getPaddingBottom();

        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 Drawable divider = getHorizontalDivider(parent, params.getViewAdapterPosition());
            final int left = child.getRight() + params.rightMargin + Math.round(ViewCompat.getTranslationX(child));
            final int right = left + divider.getIntrinsicHeight();

            mHorizontalDividerOffsets.put(params.getViewAdapterPosition(), divider.getIntrinsicHeight());

            divider.setBounds(left, top, right, bottom);
            divider.draw(c);
        }
    }

    private Drawable getVerticalDivider(RecyclerView parent, int adapterPosition) {
        RecyclerView.Adapter adapter = parent.getAdapter();
        int itemType = adapter.getItemViewType(adapterPosition);
        DrawableCreator drawableCreator = mTypeDrawableFactories.get(itemType);

        if (drawableCreator != null) {
            return drawableCreator.createVertical(parent, adapterPosition);
        }

        return mVerticalDivider;
    }

    private Drawable getHorizontalDivider(RecyclerView parent, int adapterPosition) {
        RecyclerView.Adapter adapter = parent.getAdapter();
        int itemType = adapter.getItemViewType(adapterPosition);
        DrawableCreator drawableCreator = mTypeDrawableFactories.get(itemType);

        if (drawableCreator != null) {
            return drawableCreator.createHorizontal(parent, adapterPosition);
        }

        return mHorizontalDivider;
    }

    public void registerTypeDrawable(int itemType, DrawableCreator drawableCreator) {
        mTypeDrawableFactories.put(itemType, drawableCreator);
    }

    public interface DrawableCreator {
        Drawable createVertical(RecyclerView parent, int adapterPosition);

        Drawable createHorizontal(RecyclerView parent, int adapterPosition);
    }

}

4下一步 在drawable文件夹下新建分割线样式 ,divider_bg.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle" >

    <gradient //说来惭愧,这个是设置渐变色的,为了省事我直接把三个色改成相同颜色(正常写corners,solid,stroke这些应该也是可以的我自己没试)
        android:centerColor="#F5F6F6"
        android:endColor="#F5F6F6"
        android:startColor="#F5F6F6"
        android:type="linear" />
    <size android:height="4dp"/>

</shape>

5下一步 在manifests 的 application里找到them,点击进入并修改

<style name="PlayerTheme" parent="Theme.AppCompat.NoActionBar">
        <item name="android:windowAnimationStyle">@style/PlayerAnimation</item>
        <item name="android:listDivider">@drawable/divider_bg</item>//主要就是加上这句话,其他的代码跟分割线无关(具体的可以看hongyang大神的博客)
    </style>

6使用

binding.recyclerview.setLayoutManager(new GridLayoutManager(context, 2));
binding.recyclerview.addItemDecoration(new DividerGridItemDecoration(context, DividerGridItemDecoration.GRID_DIVIDER_VERTICAL));//最后这个参数应该就是设置分割线的方向的,如果是不变色的分割线怎么设置无所谓,变色的线就自己决定方向吧

7总结一下,其实非常的简单,把DividerGridItemDecoration复制一下,写一个样式,把样式添加到them里,然后一行代码调用