Android的RecyclerView不规则Grid显示

前言

前面我们有介绍RecyclerView的使用,详见《Android中RecyclerView嵌套RecyclerView》,这一篇我们来讲讲RecyclerView的不规则Grid显示。

先上图看看效果

从上图里面我们可以看到,我们在单元模块中有标题栏和功能项,其实这个都昌在一个RecyclerView中实现的,下面我们就来介绍一下实现的方法。

代码演示

首先我们先建一个类,用于加载这些功能和标题的

CMenu

package sum.prm.pkgsys.main.mod;


/**
 * 作者:Vaccae
 * 邮箱:3657447@qq.com
 * 创建时间:2019-02-26 14:14
 * 功能模块说明:功能菜单类
 */
public class CMenu {
    public CMenu() {
        menuname = "";
        menubmp = 0;
        menuclass = null;
        istitle = true;
    }


    //菜单名称
    public String menuname;
    //菜单图标
    public int menubmp;
    //菜单模块
    public Class<?> menuclass;
    //是否标题
    public boolean istitle;
}



然后再写一个方法,创建我们开始上图中所需要显示的标题及功能

menuopt

package sum.prm.pkgsys.main.bll;


import java.util.ArrayList;
import java.util.List;


import sum.prm.pkgsys.R;
import sum.prm.pkgsys.cfg.CfgActivity;
import sum.prm.pkgsys.main.mod.CMenu;
import sum.prm.pkgwh.whin.WhInActivity;
import sum.prm.pkgwh.whout.WhOutActivity;


/**
 * 作者:Vaccae
 * 邮箱:3657447@qq.com
 * 创建时间:2019-02-26 14:51
 * 功能模块说明:
 */
public class menuopt {


    public static List<CMenu> GetMenuList() {
        List<CMenu> menus = new ArrayList<>();


        //出入库业务
        CreateWh(menus);
        //报表查询
        CreateRpt(menus);
        //系统菜单增加
        CreateSys(menus);




        return menus;
    }


    /**
     * 出入库业务
     * @param menus
     */
    private static void CreateWh(List<CMenu> menus) {
        //出入库业务标题
        CMenu menuwh = new CMenu();
        menuwh.menuname = "出入库业务";
        menuwh.menubmp = 0;
        menuwh.menuclass = null;
        menuwh.istitle = true;
        menus.add(menuwh);


        //组托入库
        menuwh = new CMenu();
        menuwh.menuname = "组托入库";
        menuwh.menubmp = R.drawable.menu_whin;
        menuwh.menuclass=WhInActivity.class;
        menuwh.istitle = false;
        menus.add(menuwh);


        //扫描出库
        menuwh=new CMenu();
        menuwh.menuname="扫描出库";
        menuwh.menubmp = R.drawable.menu_whout;
        menuwh.menuclass=WhOutActivity.class;
        menuwh.istitle = false;
        menus.add(menuwh);


        //托盘管理
        menuwh=new CMenu();
        menuwh.menuname="托盘管理";
        menuwh.menubmp=R.drawable.menu_pallet;
        menuwh.menuclass=WhInActivity.class;
        menuwh.istitle=false;
        menus.add(menuwh);
    }


    private static void CreateRpt(List<CMenu> menus) {
        //报表查询标题
        CMenu menurpt=new CMenu();
        menurpt.menuname="报表查询";
        menurpt.menubmp=0;
        menurpt.menuclass=null;
        menurpt.istitle=true;
        menus.add(menurpt);


        //库存查询
        menurpt=new CMenu();
        menurpt.menuname="库存查询";
        menurpt.menubmp=R.drawable.menu_qry;
        menurpt.menuclass=null;
        menurpt.istitle=false;
        menus.add(menurpt);
    }


    /**
     * 系统菜单增加
     * @param menus
     */
    private static void CreateSys(List<CMenu> menus) {
        //系统参数
        CMenu menusys = new CMenu();
        menusys.menuname = "系统参数";
        menusys.menubmp = 0;
        menusys.menuclass = null;
        menusys.istitle = true;
        menus.add(menusys);




        //参数设置
        menusys = new CMenu();
        menusys.menuname = "参数设置";
        menusys.menubmp = R.drawable.menu_cfg;
        menusys.menuclass=CfgActivity.class;
        menusys.istitle = false;
        menus.add(menusys);
    }
}



接下来我们看一下activity_main的布局文件

activity_main.xml、

然后我们看一下RecyclerView的布局

rcl_menu.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="wrap_content"
    android:weightSum="10"
    android:orientation="vertical">
    
    <view.XCRoundImageView
        android:layout_width="70dp"
        android:layout_height="70dp"
        android:layout_margin="10dp"
        android:background="@drawable/shape"
        android:scaleType="centerInside"
        android:layout_gravity="center_horizontal"
        android:id="@+id/rcl_menu_img"
        android:layout_weight="8" />




    <TextView
        android:text="TextView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:gravity="center"
        android:id="@+id/rcl_menu_tv"
        android:textSize="9pt"
        android:layout_weight="2" />


</LinearLayout>

显示的效果就是一个图片下面加一个文本

上面的XCRoundImageView是我自己设计的一个圆角矩形的方法,如果不需要我们直接用ImageView即可。


XCRoundImageView

package view;


import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;


public class XCRoundImageView extends android.support.v7.widget.AppCompatImageView {
    private Paint paint ;


    public XCRoundImageView(Context context) {
        this(context,null);
    }


    public XCRoundImageView(Context context, AttributeSet attrs) {
        this(context, attrs,0);
    }


    public XCRoundImageView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        paint = new Paint();
    }




    /**
     * 绘制圆形图片
     * @author caizhiming
     */
    @Override
    protected void onDraw(Canvas canvas) {


        Drawable drawable = getDrawable();
        if (null != drawable) {
            Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();
            Bitmap b = getCircleBitmap(bitmap, 14);
            final Rect rectSrc = new Rect(0, 0, b.getWidth(), b.getHeight());
            final Rect rectDest = new Rect(0,0,getWidth(),getHeight());
            paint.reset();
            canvas.drawBitmap(b, rectSrc, rectDest, paint);


        } else {
            super.onDraw(canvas);
        }
    }


    /**
     * 获取圆形图片方法
     * @param bitmap
     * @param pixels
     * @return Bitmap
     * @author caizhiming
     */
    private Bitmap getCircleBitmap(Bitmap bitmap, int pixels) {
        Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
                bitmap.getHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(output);


        final int color = 0xff424242;


        final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
        paint.setAntiAlias(true);
        canvas.drawARGB(0, 0, 0, 0);
        paint.setColor(color);
        int x = bitmap.getWidth();


        canvas.drawCircle(x / 2, x / 2, x / 2, paint);
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
        canvas.drawBitmap(bitmap, rect, rect, paint);
        return output;




    }
}





XML已经创建好了,下面我们就要写对应的Adapter了

menuAdapter

package sum.prm.pkgsys.main;


import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Typeface;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.text.TextPaint;
import android.text.style.TextAppearanceSpan;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;


import java.util.List;


import comm.user.CUserInfo;
import sum.prm.pkgsys.R;
import sum.prm.pkgsys.main.mod.CMenu;
import utils.image.imgHelper;
import view.XCRoundImageView;


/**
 * 作者:Vaccae
 * 邮箱:3657447@qq.com
 * 创建时间:2019-02-26 14:07
 * 功能模块说明:
 */
public class menuAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {


    private List<CMenu> mMenulist;
    private CUserInfo userInfo;
    private Context mContext;


    public menuAdapter(Context context,List<CMenu> list,CUserInfo info) {
        mMenulist = list;
        mContext = context;
        userInfo=info;


    }




    public static class menuHolder extends RecyclerView.ViewHolder  {
        private XCRoundImageView img;
        private TextView tv;


        public menuHolder(View itemView) {
            super(itemView);


            img = itemView.findViewById(R.id.rcl_menu_img);
            tv = itemView.findViewById(R.id.rcl_menu_tv);
        }
    }
    @NonNull
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View v = LayoutInflater.from(mContext).inflate(R.layout.rcl_menu, parent, false);
        return new menuHolder(v);
    }


    @Override
    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
        menuHolder mholder = (menuHolder) holder;
        final CMenu item = mMenulist.get(position);


        if (!item.istitle) {
            //图片显示
            Bitmap bmp = imgHelper.readBitMap(mContext, item.menubmp);
            mholder.img.setImageBitmap(bmp);
            mholder.img.setVisibility(View.VISIBLE);


            //点击事件
            mholder.itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Intent intent = new Intent(mContext, item.menuclass);
                    intent.putExtra("menuname", item.menuname);
                    intent.putExtra("userinfo", userInfo.ToJson());
                    mContext.startActivity(intent);
                }
            });
            //设置文本的背景,字体及位置
            mholder.tv.setBackgroundColor(mContext.getResources().getColor(R.color.colortransparent));
            mholder.tv.setTextColor(mContext.getResources().getColor(R.color.seesimilarcolorThistle4));
            mholder.tv.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));
            mholder.tv.setGravity(Gravity.CENTER);
        } else {
            mholder.img.setVisibility(View.GONE);
            //设置文本的背景,字体及位置
            mholder.tv.setBackgroundColor(mContext.getResources().getColor(R.color.seesimilarcolorThistle4));
            mholder.tv.setTextColor(mContext.getResources().getColor(R.color.colorWhite));
            mholder.tv.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));
            mholder.tv.setGravity(Gravity.LEFT);


        }
        //功能名称
        mholder.tv.setText(item.menuname);


    }


    @Override
    public int getItemCount() {
        return mMenulist.size();
    }




}



到这里准备工作基本都做完了,我们看一下怎么样实现显示的核心方法

ShowRecyclerView

    private void ShowRecyclerView(final List<CMenu> list) {
        rcl_menu = findViewById(R.id.main_rcl_menu);
        final menuAdapter adapter = new menuAdapter(this, list, userInfo);
        //设置布局管理器 , 将布局设置成纵向
        final GridLayoutManager layoutManager = new GridLayoutManager(this, 3, GridLayoutManager.VERTICAL, false);
        rcl_menu.setLayoutManager(layoutManager);
        //根据是否标题判断显示几格
        layoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
            @Override
            public int getSpanSize(int position) {
                if (list.get(position).istitle) {
                    return layoutManager.getSpanCount();
                } else {
                    return 1;
                }
            }
        });
        //设置分隔线
//        rcl_menu.addItemDecoration(new DividerItemDecoration(this , DividerItemDecoration.VERTICAL));
        //设置增加或删除条目动画
        rcl_menu.setItemAnimator(new DefaultItemAnimator());
        //填充数据
        rcl_menu.setAdapter(adapter);
        //取消局部更新时闪烁动画
        ((SimpleItemAnimator)rcl_menu.getItemAnimator()).setSupportsChangeAnimations(false);


    }

重点就是上面标红框的地方,判断类里面是不是标题用于显示几列的情况。


MainActivity.java

package sum.prm.pkgsys.main;


import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.DividerItemDecoration;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.SimpleItemAnimator;
import android.util.Log;
import android.view.KeyEvent;
import android.widget.Toast;


import java.util.List;


import comm.user.CUserInfo;
import sum.prm.pkgsys.R;
import sum.prm.pkgsys.main.bll.menuopt;
import sum.prm.pkgsys.main.mod.CMenu;
import view.background;


public class MainActivity extends Activity {


    private List<CMenu> mMenuList;


    private CUserInfo userInfo;


    private background bglayout;


    private RecyclerView rcl_menu;


    // 定义一个变量,计算退出时间,用于按两次退出
    private long exitTime = 0;


    //界面返回按钮事件,用于点击两次退出
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        Log.i("keycode", "" + keyCode);
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            exit();
            return false;
        }
        return super.onKeyDown(keyCode, event);
    }


    //退出事件
    private void exit() {
        //大于两秒时重置
        if (System.currentTimeMillis() - exitTime > 2000) {
            Toast.makeText(getApplicationContext(), "再按一次退出",
                    Toast.LENGTH_SHORT).show();
            exitTime = System.currentTimeMillis();
        } else {
            finish();
            System.exit(0);
        }
    }




    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);


        Intent intent=getIntent();
        userInfo=CUserInfo.fromJson(intent.getStringExtra("userinfo"));


        bglayout = findViewById(R.id.main_bglayout);
        bglayout.SetFunName("功能菜单");
        bglayout.SetUserInfo(userInfo.UserName, "设备号:" + userInfo.DevCode);


        //获取功能列表
        mMenuList = menuopt.GetMenuList();


        //显示列表
        ShowRecyclerView(mMenuList);
    }


    private void ShowRecyclerView(final List<CMenu> list) {
        rcl_menu = findViewById(R.id.main_rcl_menu);
        final menuAdapter adapter = new menuAdapter(this, list, userInfo);
        //设置布局管理器 , 将布局设置成纵向
        final GridLayoutManager layoutManager = new GridLayoutManager(this, 3, GridLayoutManager.VERTICAL, false);
        rcl_menu.setLayoutManager(layoutManager);
        //根据是否标题判断显示几格
        layoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
            @Override
            public int getSpanSize(int position) {
                if (list.get(position).istitle) {
                    return layoutManager.getSpanCount();
                } else {
                    return 1;
                }
            }
        });
        //设置分隔线
//        rcl_menu.addItemDecoration(new DividerItemDecoration(this , DividerItemDecoration.VERTICAL));
        //设置增加或删除条目动画
        rcl_menu.setItemAnimator(new DefaultItemAnimator());
        //填充数据
        rcl_menu.setAdapter(adapter);
        //取消局部更新时闪烁动画
        ((SimpleItemAnimator)rcl_menu.getItemAnimator()).setSupportsChangeAnimations(false);


    }
}


上面代码主要是我自己程序中用到的,直接复制出来使用会报错,我们可以自己修改一下MainActivity,把一些不需要的东西直接删除即可。

-END-

Vaccae的往期经典


OpenCV

《C++ OpenCV案例实战---卡号获取

《C++ OpenCV案例实战---卡片截取(附代码)

《C++ OpenCV透视变换---切换手机正面图片》

《C++ OpenCV实战---获取数量

《C++ OpenCV实战---利用颜色分割获取数量》


Android

《Android利用SurfaceView结合科大讯飞修改语音实别UI

《Android关于语音识别的功能实现分析(一)---结构化思维》

《Android关于语音识别的功能实现分析(二)---语义解析》

《Android根据类生成签名字符串

《Android碎片化布局fragment的实战应用


.Net C#

《C#自定义特性(Attribute)讲解与实际应用

《C#根据类生成签名字符串(附DEMO下载地址)

《C++创建动态库C#调用》

《C#与三菱PLC(型号FX2N)串口通讯类


数据库及其它

《Oracel存储过程写报表实战》

《Delphi轮播视频和图片程序(用于双屏显示程序)

《SQL随机增加销售数据的脚本编写(附脚本下载地址)


长按下方二维码关注微卡智享

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Vaccae

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值