Android UI 之 RecyclerView 九宫格
Posted Kevin_小飞象
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android UI 之 RecyclerView 九宫格相关的知识,希望对你有一定的参考价值。
基础用法
添加依赖
// RecyclerAdapter
implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.30'
// glide
implementation 'com.github.bumptech.glide:glide:4.8.0';
-
效果图
-
布局文件
activity_fruit.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
android:orientation="vertical"
tools:context=".ui.FruitActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_fruit"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
item_fruit
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="80dp"
android:layout_height="wrap_content"
android:background="@color/btn_answer_pressed"
android:orientation="vertical">
<ImageView
android:id="@+id/iv_fruit"
android:layout_width="45dp"
android:layout_height="45dp"
android:layout_gravity="center_horizontal"
android:src="@mipmap/ic_apple"/>
<TextView
android:id="@+id/tv_fruit_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_gravity="center_horizontal"/>
</LinearLayout>
- 分隔线
public class GridDividerItemDecoration extends RecyclerView.ItemDecoration
private static final String TAG = "GridDividerItemDeco";
private Context mContext;
private int mFirstAndLastColumnW; //您所需指定的间隔宽度,主要为第一列和最后一列与父控件的间隔;行间距,列间距将动态分配
private int mFirstRowTopMargin = 0; //第一行顶部是否需要间隔
private int mLastRowBottomMargin = 0;
private int mSpanCount = 0;
private int mScreenW = 0;
private int mItemDistance;
/**
* @param firstAndLastColumnW 间隔宽度
* @param firstRowTopMargin 第一行顶部是否需要间隔
*/
public GridDividerItemDecoration(Context context, int firstAndLastColumnW, int firstRowTopMargin, int lastRowBottomMargin)
mContext = context;
mFirstAndLastColumnW = firstAndLastColumnW;
mFirstRowTopMargin = firstRowTopMargin;
mLastRowBottomMargin = lastRowBottomMargin;
public void setFirstRowTopMargin(int firstRowTopMargin)
mFirstRowTopMargin = firstRowTopMargin;
public void setLastRowBottomMargin(int lastRowBottomMargin)
mLastRowBottomMargin = lastRowBottomMargin;
public void setItemDistance(int itemDistance)
mItemDistance = itemDistance;
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state)
super.getItemOffsets(outRect, view, parent, state);
int top = 0;
int left;
int right;
int bottom;
int itemPosition = ((RecyclerView.LayoutParams) view.getLayoutParams()).getViewLayoutPosition();
mSpanCount = getSpanCount(parent);
int childCount = parent.getAdapter().getItemCount();
// 屏幕宽度-View的宽度*spanCount 得到屏幕剩余空间
int maxDividerWidth = getMaxDividerWidth(view);
int spaceWidth = mFirstAndLastColumnW;//首尾两列与父布局之间的间隔
// 除去首尾两列,item与item之间的距离
int eachItemWidth = maxDividerWidth / mSpanCount;
int dividerItemWidth = (maxDividerWidth - 2 * spaceWidth) / (mSpanCount - 1);//item与item之间的距离
left = itemPosition % mSpanCount * (dividerItemWidth - eachItemWidth) + spaceWidth;
right = eachItemWidth - left;
bottom = dividerItemWidth;
// 首行
if (mFirstRowTopMargin > 0 && isFirstRow(parent, itemPosition, mSpanCount, childCount))
top = mFirstRowTopMargin;
//最后一行
if (isLastRow(parent, itemPosition, mSpanCount, childCount))
if (mLastRowBottomMargin < 0)
bottom = 0;
else
bottom = mLastRowBottomMargin;
Log.i(TAG, "getItemOffsets: dividerItemWidth =" + dividerItemWidth + "eachItemWidth = " + eachItemWidth);
Log.i(TAG, "getItemOffsets: itemPosition =" + itemPosition + " left = " + left + " top = " + top
+ " right = " + right + " bottom = " + bottom);
outRect.set(left, top, right, bottom);
/**
* 获取Item View的大小,若无则自动分配空间
* 并根据 屏ge幕宽度-View的宽度*spanCount 得到屏幕剩余空间
*
* @param view
* @return
*/
private int getMaxDividerWidth(View view)
int itemWidth = view.getLayoutParams().width;
int itemHeight = view.getLayoutParams().height;
Log.i(TAG, "getMaxDividerWidth: itemWidth =" + itemWidth);
int screenWidth = getScreenWidth();
int maxDividerWidth = screenWidth - itemWidth * mSpanCount;
if (itemHeight < 0 || itemWidth < 0 || maxDividerWidth <= (mSpanCount - 1) * mFirstAndLastColumnW)
view.getLayoutParams().width = getAttachCloumnWidth();
view.getLayoutParams().height = getAttachCloumnWidth();
maxDividerWidth = screenWidth - view.getLayoutParams().width * mSpanCount;
return maxDividerWidth;
private int getScreenWidth()
Log.i(TAG, "getScreenWidth: mScreenW =" + mScreenW);
if (mScreenW > 0)
return mScreenW;
mScreenW = mContext.getResources().getDisplayMetrics().widthPixels > mContext.getResources().getDisplayMetrics().heightPixels
? mContext.getResources().getDisplayMetrics().heightPixels : mContext.getResources().getDisplayMetrics().widthPixels;
return mScreenW;
/**
* 根据屏幕宽度和item数量分配 item View的width和height
*
* @return
*/
private int getAttachCloumnWidth()
int itemWidth = 0;
int spaceWidth = 0;
try
int width = getScreenWidth();
spaceWidth = 2 * mFirstAndLastColumnW;
itemWidth = (width - spaceWidth) / mSpanCount - 40;
catch (Exception e)
e.printStackTrace();
return itemWidth;
/**
* 判读是否是第一列
*
* @param parent
* @param pos
* @param spanCount
* @return
*/
private boolean isFirstColumn(RecyclerView parent, int pos, int spanCount)
RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
if (layoutManager instanceof GridLayoutManager)
if (pos % spanCount == 0)
return true;
else if (layoutManager instanceof StaggeredGridLayoutManager)
int orientation = ((StaggeredGridLayoutManager) layoutManager)
.getOrientation();
if (orientation == StaggeredGridLayoutManager.VERTICAL)
if (pos % spanCount == 0) // 第一列
return true;
else
return false;
/**
* 判断是否是最后一列
*
* @param parent
* @param pos
* @param spanCount
* @param childCount
* @return
*/
private boolean isLastColumn(RecyclerView parent, int pos, int spanCount)
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
return false;
/**
* 判读是否是最后一行
*
* @param parent
* @param pos
* @param spanCount
* @param childCount
* @return
*/
private boolean isLastRow(RecyclerView parent, int pos, int spanCount, int childCount)
RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
if (layoutManager instanceof GridLayoutManager)
int lines = childCount % spanCount == 0 ? childCount / spanCount : childCount / spanCount + 1;
return lines == pos / spanCount + 1;
return false;
/**
* 判断是否是第一行
*
* @param parent
* @param pos
* @param spanCount
* @param childCount
* @return
*/
private boolean isFirstRow(RecyclerView parent, int pos, int spanCount, int childCount)
RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
if (layoutManager instanceof GridLayoutManager)
if ((pos / spanCount + 1) == 1)
return true;
else
return false;
return false;
/**
* 获取列数
*
* @param parent
* @return
*/
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 class FruitAdapter extends BaseQuickAdapter<FruitBean, BaseViewHolder>
public FruitAdapter(int layoutResId, @Nullable List<FruitBean> data)
super(layoutResId, data);
@Override
protected void convert(BaseViewHolder helper, FruitBean item)
ImageView image = helper.getView(R.id.iv_fruit);
Glide.with(MyApp.getAppContext())
.load(item.getIconId())
.into(image);
helper.setText(R.id.tv_fruit_name,item.getName());
- 逻辑代码
public class FruitActivity extends BaseActivity
@BindView(R.id.rv_fruit)
RecyclerView mRecyclerView;
private FruitAdapter mAdapter;
@Override
public int getLayoutId()
return R.layout.activity_fruit;
@Override
public void initView()
mAdapter = new FruitAdapter(R.layout.item_fruit,getData());
mAdapter.openLoadAnimation();
int firstAndLastColumnW = DensityUtil.dip2px(this, 15);
int firstRowTopMargin = DensityUtil.dip2px(this, 15);
GridDividerItemDecoration gridDividerItemDecoration =
new GridDividerItemDecoration(this, firstAndLastColumnW, firstRowTopMargin, firstRowTopMargin);
gridDividerItemDecoration.setFirstRowTopMargin(firstRowTopMargin);
gridDividerItemDecoration.setLastRowBottomMargin(firstRowTopMargin);
mRecyclerView.addItemDecoration(gridDividerItemDecoration);
GridLayoutManager layoutManager = new GridLayoutManager(this, 3);
mRecyclerView.setLayoutManager(layoutManager);
mRecyclerView.setAdapter(mAdapter);
private List<FruitBean> getData()
return Arrays.asList(new FruitBean("apple",R.mipmap.ic_apple),
new FruitBean("banana",R.mipmap.ic_banana),
new FruitBean("cherry",R.mipmap.ic_cherry),
new FruitBean("grape",R.mipmap.ic_grape),
new FruitBean("mango",R.mipmap.ic_mango),
new FruitBean("orange",R.mipmap.ic_orange),
new FruitBean("pear",R.mipmap.ic_pear),
new FruitBean("pineapple",R.mipmap.ic_pineapple以上是关于Android UI 之 RecyclerView 九宫格的主要内容,如果未能解决你的问题,请参考以下文章
Android UI 之 RecyclerView 基础用法