Android RecyclerView实现九宫格效果

RecyclerView更加优化的复用机制和方便实现UI效果,几乎替代Listview和GridView的使用。但是分割线的实现,需要自己继承ItemDecoration来绘制。

效果图

item的布局文件

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"     android:orientation="vertical"     android:gravity="center"     android:layout_width="match_parent"     android:layout_height="wrap_content">     <LinearLayout         android:layout_width="match_parent"         android:layout_height="wrap_content"         android:orientation="horizontal"         android:gravity="center_vertical"         android:layout_marginTop="25dp"         android:layout_marginLeft="15dp"         android:layout_marginRight="15dp">         <TextView             android:layout_width="match_parent"             android:layout_height="wrap_content"             android:layout_weight="1"             android:text="餐饮"             android:id="@+id/txt_title"             android:textSize="16sp"             android:textStyle="bold"             android:textColor="#555555"/>         <ImageView             android:layout_width="36dp"             android:layout_height="36dp"             android:id="@+id/img_title"             android:src="@mipmap/luggage_blue"/>     </LinearLayout>     <LinearLayout         android:layout_width="match_parent"         android:layout_height="20dp"         android:orientation="vertical"         android:layout_marginBottom="25dp"         android:layout_marginLeft="15dp"         android:layout_marginRight="15dp">         <TextView             android:layout_width="match_parent"             android:layout_height="match_parent"             android:text="提供航空 餐饮美食"             android:id="@+id/txt_info"             android:textSize="14sp"             android:textColor="#999999"/>     </LinearLayout> </LinearLayout>

activity_main.xml布局文件

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"     xmlns:tools="http://schemas.android.com/tools"     android:orientation="vertical"     android:layout_width="match_parent"     android:layout_height="match_parent"     android:background="#f1f1f1"     tools:context=".MainActivity">     <TextView         android:layout_width="match_parent"         android:layout_height="50dp"         android:textColor="#ffffff"         android:textSize="18sp"         android:gravity="center"         android:text="RecyclerView实现九宫格"         android:background="#30B8E3"/>     <ScrollView         android:layout_width="match_parent"         android:layout_height="match_parent">         <LinearLayout             android:layout_width="match_parent"             android:layout_height="wrap_content"             android:orientation="vertical">             <LinearLayout                 android:layout_width="match_parent"                 android:layout_height="50dp"                 android:gravity="center_vertical"                 android:layout_marginLeft="15dp"                 android:layout_marginRight="15dp"                 android:orientation="horizontal">                 <ImageView                     android:layout_width="20dp"                     android:layout_height="20dp"                     android:src="@mipmap/air_gray"                     android:layout_marginRight="8dp"/>                 <TextView                     android:layout_width="match_parent"                     android:layout_height="wrap_content"                     android:text="航行助手"                     android:textStyle="bold"                     android:textSize="18sp"/>             </LinearLayout>             <android.support.v7.widget.RecyclerView                 android:id="@+id/main_recycleview"                 android:divider="#00000000"                 android:layout_width="match_parent"                 android:layout_height="wrap_content"                 android:background="@drawable/shape_bg"                 android:layout_marginLeft="15dp"                 android:layout_marginRight="15dp"                 android:layout_marginBottom="15dp">             </android.support.v7.widget.RecyclerView>         </LinearLayout>     </ScrollView> </LinearLayout>

MainActivity.java代码

package com.davis.recyclerviewdemo; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.RecyclerView; import com.davis.recyclerviewdemo.adapter.CommonDecoration; import com.davis.recyclerviewdemo.adapter.RecyclerViewAdapter; import com.davis.recyclerviewdemo.bean.MenuBean; import java.util.ArrayList; import java.util.List; public class MainActivity extends AppCompatActivity {     private RecyclerView recyclerView;     private RecyclerViewAdapter adapter;     private List<MenuBean> listDatas = new ArrayList<MenuBean>();     @Override     protected void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState);         setContentView(R.layout.activity_main);         init();     }     private void init(){         recyclerView = (RecyclerView)findViewById(R.id.main_recycleview);         loadMenuData();         recyclerView.setLayoutManager(new GridLayoutManager(this, 2));         recyclerView.addItemDecoration(new CommonDecoration(this));         adapter = new RecyclerViewAdapter(this, listDatas);         recyclerView.setAdapter(adapter);     }     private void loadMenuData(){         listDatas.add(new MenuBean("安检", "快速安检", R.mipmap.check_blue));         listDatas.add(new MenuBean("行李", "提醒行李动态", R.mipmap.luggage_blue));         listDatas.add(new MenuBean("餐饮", "提供航空 餐饮美食", R.mipmap.food_blue));         listDatas.add(new MenuBean("VIP休息", "机场休息室", R.mipmap.vip_blue));         listDatas.add(new MenuBean("机舱服务", "机舱上网 游戏娱乐", R.mipmap.service_blue));         listDatas.add(new MenuBean("更多", "更多信息", R.mipmap.more_blue));     } }

其中GridLayoutManager用来设置显示列数,CommonDecoration用来绘制分隔线。

CommonDecoration.java代码

package com.davis.recyclerviewdemo.adapter; 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.v7.widget.GridLayoutManager; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.StaggeredGridLayoutManager; import android.view.View; /**  * Created by Administrator on 2019/4/14.  */ public class CommonDecoration extends RecyclerView.ItemDecoration {     private static final int[] ATTRS = new int[]{android.R.attr.listDivider};     private Drawable mDivider;     public CommonDecoration(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 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) {             int last = childCount % spanCount;             if (last == 0) {                 last = spanCount;             }             childCount = childCount - last;             if (pos >= childCount) {// 如果是最后一行,则不需要绘制底部                 return true;             }         } else if (layoutManager instanceof StaggeredGridLayoutManager) {             int orientation = ((StaggeredGridLayoutManager) layoutManager)                     .getOrientation();             // StaggeredGridLayoutManager 且纵向滚动             if (orientation == StaggeredGridLayoutManager.VERTICAL) {                 int last = childCount % spanCount;                 if (last == 0) {                     last = spanCount;                 }                 childCount = childCount - last;                 // 如果是最后一行,则不需要绘制底部                 if (pos >= childCount) {                     return true;                 }             } else {// StaggeredGridLayoutManager 且横向滚动                 // 如果是最后一行,则不需要绘制底部                 if ((pos + 1) % spanCount == 0) {                     return true;                 }             }         }         return false;     }     @Override     public void getItemOffsets(Rect outRect, int itemPosition,                                RecyclerView parent) {         int spanCount = getSpanCount(parent);         int childCount = parent.getAdapter().getItemCount();         if (isLastColum(parent, itemPosition, spanCount, childCount)) {// 如果是最后一列,则不需要绘制右边             if (itemPosition == (childCount - 1)) {                 outRect.set(0, 0, 0, 0);             } else {                 outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());             }         } else if (isLastRaw(parent, itemPosition, spanCount, childCount)) {// 如果是最后一行,则不需要绘制底部             outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);         } else {             outRect.set(0, 0, mDivider.getIntrinsicWidth(),                     mDivider.getIntrinsicHeight());         }     } }

推荐阅读