RecyclerView的GridLayout布局前后两列靠边、中间列平分展示
说明:图中的第一个列表及第二个列表
第一个列表(1-5)展示的是GridLayut布局对子项不做任何修饰时,子项平分展示
第二个列表(1-5)展示的是GridLayou布局前后两列靠左右两边,中间列进行平分展示
竖屏展示效果如下:
横屏展示效果如下:
1、列表子项的布局
给布局的背景添加了一个红色的线圈,便于观察如何分割空间
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/item_background">
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/item_tv"
android:layout_width="36dp"
android:layout_height="36dp"
android:visibility="visible"
android:text=""
android:gravity="center"
android:textSize="18sp"
android:textColor="@color/white"
android:layout_margin="1dp"/>
</RelativeLayout>
布局的背景如下:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/white" />
<stroke
android:width="1dp"
android:color="@color/red" />
</shape>
2、GridLayut布局对子项不做任何修饰时,子项平分展示
如上图中的第一个列表所示,每个列表子项所占据的空间是平分当前屏幕的。
仅仅是将RecyclerView的LayoutManger设置为GridLayoutManager,就起到每个子项平分当前屏幕的效果。
mRecyclerView.setLayoutManager(new GridLayoutManager(mContext, 5));
mRecyclerView.setAdapter(adapter);
3、通过实现ItemDecoration,前后两列靠边,中间列平分展示
(1)推导过程
对于图中的第二行列表所示,前后两列靠屏幕的左右两边展示,中间列进行平分空间展示。
通过图中的第一行列表和第二行列表对比能够看出,想要实现上述的效果:
对于第二行列表 相较于 第一行列表而言
-
对于子项1,向右偏移红色框中白色空间的0/4
-
对于子项2,向右偏移红色框中白色空间的1/4
-
对于子项3,向右偏移红色框中白色空间的2/4
-
对于子项4,向右偏移红色框中白色空间的3/4
-
对于子项5,向右偏移红色框中白色空间的4/4
对上面内容进行拆解下
拆解一:
对于子项,可以拿到position,子项1-5对应的position是0 - 4,因此对每一项而言:
向右偏移了position * (红色框中白色空间的1/4)
拆解二:
红色框中白色空间:(当前屏幕 - 每个子项TextView所占空间 * 5 )/ 5
这里的当前屏幕 - 每个子项所占空间 * 5 实际就是当前的剩余空间,用totalRemainSpace变量表示
将拆解一及拆解二合并下:
向右偏移:position * (totalRemainSpace / 5 * 1/4)
(2)计算公式
通过position * (totalRemainSpace / 5 * 1/4) 再进一步推导可得:mSpanCount变量表示5
position * totalRemainSpace / (mSpanCount * (mSpanCount - 1))
或者:
position * (totalRemainSpace / (mSpanCount - 1) - totalRemainSpace / mSpanCount)
说明:这里的5表示的是列数,上面的每个子项所占空间是指布局中的TextView
(3)代码实现
向右偏移: 实际就是指子项布局的矩形的left值
即通过实现继承ItemDecoration,重写getItemOffsets方法来改变每个子项布局中的left值,代码如下
@Override
public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent,
@NonNull RecyclerView.State state) {
// 这里的 mSpanCount 是指:Grid布局的列数,mDp36 是指:item(TextView)的宽度
int position = parent.getChildAdapterPosition(view) % mSpanCount;
// 当前屏幕宽度
int screenWidth = mContext.getResources().getDisplayMetrics().widthPixels;
// 前后item靠左右两边,其余的item平分剩余空间
int totalRemainSpace = screenWidth - mSpanCount * mDp36;
outRect.left = position * (totalRemainSpace / (mSpanCount - 1) - totalRemainSpace / mSpanCount);
}
RecyclerView设置ItemDecoration即可:DivideSpaceItemDecoration 是继承 ItemDecoration 的实现类
mRecyclerView.addItemDecoration(new DivideSpaceItemDecoration(mContext, 5));
mRecyclerView.setLayoutManager(new GridLayoutManager(mContext, 5));
mRecyclerView.setAdapter(adapter);