Android 列表或网格形式展示大量数据:RecyclerView

news2024/12/23 6:56:12

目录

  1. RecyclerView是什么
  2. 如何使用
  3. RecyclerView 涉及到的类
  4. LayoutManager
  5. 为Item设置不同的布局样式
  6. 制作拖动的RecyclerView

一、RecyclerView是什么

RecyclerView是Android支持库中的一个控件,用于在列表或网格形式展示大量数据。它是ListView的升级版,提供了更灵活、可定制化的方式来展示和管理数据。

二、如何使用

RecyclerView的使用步骤:

  1. 创建RecyclerView控件对象
  2. 设置适配器 : 一般是使用自定义的适配器 , 设置给 RecyclerView 对象 ;
  3. 创建适配器的布局文件
  4. 创建并设置布局管理器 : 可以使用预置的布局管理器 , 也可以自定义布局管理器 ;

(1)创建控件


    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/home_rv_product"
        android:layout_width="1500dp"
        android:layout_height="800dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>

(2)创建适配器

class HomeProductAdapter(var productList:ArrayList<HomeProductBean>): RecyclerView.Adapter<HomeProductAdapter.MyViewHolder>() {

    inner class MyViewHolder(view: View): RecyclerView.ViewHolder(view){
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
       val view = LayoutInflater.from(parent.context).inflate(R.layout.home_item_home_product,parent,false)
        return MyViewHolder(view)
    }

    override fun getItemCount(): Int {
        return productList.size
    }

    override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
    }
}
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="200dp"
    android:layout_height="270dp"
    android:layout_marginRight="20dp"
    android:layout_marginBottom="20dp"
    android:background="@drawable/dingdian_imge_price_bg">


    <ImageView
        android:id="@+id/iv_sugar"
        android:layout_width="150dp"
        android:layout_height="150dp"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="28dp"
        android:src="@drawable/icon_coin"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />


    <TextView
        android:id="@+id/tv_name1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:text="蓝色棉花"
        android:textColor="#fa7698"
        android:textSize="22sp"
        android:textStyle="bold"
        android:layout_marginTop="10dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/iv_sugar" />

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        android:gravity="center"
        android:layout_marginTop="10dp"
        app:layout_constraintTop_toBottomOf="@+id/tv_name1">

        <ImageView
            android:id="@+id/home_imageview"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginRight="5dp"
            android:src="@drawable/icon_coin" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerHorizontal="true"
            android:text="0.0"
            android:textColor="#fa7698"
            android:textSize="30sp"
            android:textStyle="bold"/>

    </LinearLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

(3)进行使用

class HomeFragment : BaseFragment<HomeFragmentHomeBinding, HomeFragmentVM>() {

    private val productList  = ArrayList<HomeProductBean>()
    private var homeProductAdapter:HomeProductAdapter? = null


    override fun HomeFragmentHomeBinding.initView() {

        //设置布局排列方式,默认垂直排列
        val gridLayoutManager: GridLayoutManager =
            GridLayoutManager(this@HomeFragment.context, 6, GridLayoutManager.VERTICAL, false)
        homeRvProduct.layoutManager = gridLayoutManager

        //设置adapter
        productList.add(HomeProductBean(1,"asdf"))
        productList.add(HomeProductBean(1,"asdf"))
        productList.add(HomeProductBean(1,"asdf"))
        productList.add(HomeProductBean(1,"asdf"))
        productList.add(HomeProductBean(1,"asdf"))
        productList.add(HomeProductBean(1,"asdf"))
        productList.add(HomeProductBean(1,"asdf"))
        ....
        homeProductAdapter = HomeProductAdapter(productList)
        homeRvProduct.adapter = homeProductAdapter

        tvTime.setOnLongClickListener {
            val findNavController = findNavController()
            findNavController.navigate(R.id.home_action_home_homefragment_to_home_userloginfragment)
            return@setOnLongClickListener true
        }
    }


}

运行结果:
在这里插入图片描述

三、RecyclerView 涉及到的类

  1. RecyclerView:是RecyclerView控件的核心类,用于展示和管理数据。它负责协调LayoutManager、Adapter和ItemAnimator之间的交互,并处理用户交互事件。

  2. RecyclerView.Adapter:是RecyclerView的适配器类,负责将数据绑定到RecyclerView上。开发者需要继承该类并实现必要的方法,如创建ViewHolder、绑定数据等。

  3. RecyclerView.ViewHolder:是RecyclerView中每个列表项或网格项的持有者类。它包含了对应项的视图以及与之相关的操作。通过重写Adapter的 onCreateViewHolder() 方法来创建ViewHolder。RecyclerView.Adapter 适配器 的 onBindViewHolder 方法中为其关联数据 ;

  4. RecyclerView.LayoutManager:是RecyclerView的布局管理器类,负责决定子项的排列方式。Android提了一些默认的LayoutManager,如LinearLayoutManager(线性布局)、GridLayoutManager(网格布局)和StaggeredGridLayoutManager(瀑布流布局),也可以自定义LayoutManager。

  5. RecyclerView.ItemDecoration:是RecyclerView的装饰器类,用于为列表项添加分割线或其他样式。开发者可以继承该类并实现相应的方法,然后通过RecyclerView的addItemDecoration方法添加装饰器。
    【binding.rvX.addItemDecoration(new CustomDecoration(mContext, LinearLayoutManager.VERTICAL, 2));】这句代码的作用是在RecyclerView中添加一个自定义的装饰器,用于给列表项之间添加分割线,并指定分割线的宽度和方向。

  6. RecyclerView.ItemAnimator:是RecyclerView的动画类,用于在插入、删除和移动列表项时添加过渡动画效果。Android提供了一些默认的ItemAnimator,如DefaultItemAnimator和SimpleItemAnimator,也可以自定义ItemAnimator。

四、LayoutManager

4.1 线性布局 LinearLayoutManager

使用代码创建 线性布局管理器 LinearLayoutManager

LinearLayoutManager(Context context, @RecyclerView.Orientation int orientation, boolean reverseLayout)

context:表示上下文对象,通常是Activity或Fragment的引用。
orientation:表示布局的方向,可以是RecyclerView.HORIZONTAL(水平方向)或RecyclerView.VERTICAL(垂直方向)。
reverseLayout:表示是否将布局进行反转。如果设置为true,则列表项会从尾部开始排列;如果设置为false,则列表项会从头部开始排列。

reverseLayout这个参数在某些情况下很有用,比如当需要实现类似聊天界面的消息列表时,可以将reverseLayout设置为true,使得新的消息始终显示在列表的底部。


 LinearLayoutManager layoutManagerFirst = new LinearLayoutManager(mContext,RecyclerView.HORIZONTAL,true);
 
 advancedNewBinding.rvAdvancedFirst.setLayoutManager(layoutManagerFirst);

4.2 GridLayoutManager

使用代码创建 线性布局管理器 GridLayoutManager

GridLayoutManager (Context context, int spanCount, @RecyclerView.Orientation int orientation, boolean reverseLayout)

参数同LinearLayoutManager一样。

int spanCount : 网格布局行或列的个数.

 GridLayoutManager layoutManager = new GridLayoutManager(mContext, 8, GridLayoutManager.HORIZONTAL, false);
        
 advancedBinding.rvPara.setLayoutManager(layoutManager);

五、为Item设置不同的布局样式

比如,有的item需要的是:
布局一:文本+输入框+按钮
布局二:按钮
在这里插入图片描述

 @Override
    public int getItemViewType(int position) {
    		//这里为不同位置的组件设置不同的布局类型 ;
        if (position > 27) return TYPE_OTHER;
        return TYPE_NORMAL;
    }
 @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
        View inflate;
        //根据布局类型加载不同的布局文件
        if (viewType == TYPE_NORMAL) {
            inflate = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item_parameter_new, viewGroup, false);
            return new ViewHolder(inflate);
        } else {
            inflate = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item_manual_advanced, viewGroup, false);
            return new ViewHolderOther(inflate);
        }


    }

六、制作拖动的RecyclerView

比如我们想通过拖动item来调整位置,应该如何操作呢?
ItemTouchHelper 可以为 RecyclerView 添加拖动效果 ;

ItemTouchHelper 需要与 RecyclerView 和 ItemTouchHelper.Callback 结合起来使用 ;

 ItemTouchHelper helper = new ItemTouchHelper(new ItemTouchHelper.Callback() {
        //线性布局和网格布局都可以使用
        @Override
        public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
            int dragFrlg = 0;
            if (recyclerView.getLayoutManager() instanceof GridLayoutManager) {
                dragFrlg = ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
            } else if (recyclerView.getLayoutManager() instanceof LinearLayoutManager) {
                dragFrlg = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
            }
            return makeMovementFlags(dragFrlg, 0);
        }

        @Override
        public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
            //滑动事件  下面注释的代码,滑动后数据和条目错乱,被舍弃
//            Collections.swap(datas,viewHolder.getAdapterPosition(),target.getAdapterPosition());
//            ap.notifyItemMoved(viewHolder.getAdapterPosition(),target.getAdapterPosition());

            //得到当拖拽的viewHolder的Position
            int fromPosition = viewHolder.getAdapterPosition();
            //拿到当前拖拽到的item的viewHolder
            int toPosition = target.getAdapterPosition();
            if (fromPosition < toPosition) {
                for (int i = fromPosition; i < toPosition; i++) {
                    Collections.swap(showAdapter.getGoodsBeans(), i, i + 1);
                }
            } else {
                for (int i = fromPosition; i > toPosition; i--) {
                    Collections.swap(showAdapter.getGoodsBeans(), i, i - 1);
                }
            }
            showAdapter.notifyItemMoved(fromPosition, toPosition);
            return true;
        }

        @Override
        public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
            //侧滑删除可以使用;
        }

        @Override
        public boolean isLongPressDragEnabled() {
        //启用长按拖动功能
            return true;
        }

        /**
         * 长按选中Item的时候开始调用
         * 长按高亮
         *
         * @param viewHolder
         * @param actionState
         */
        @SuppressLint("MissingPermission")
        @Override
        public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
            super.onSelectedChanged(viewHolder, actionState);
            if (actionState == ItemTouchHelper.ACTION_STATE_DRAG) {
                viewHolder.itemView.setScaleX(1.1f);
                viewHolder.itemView.setScaleY(1.1f);
            }
        }

        /**
         * 手指松开的时候还原高亮
         *
         * @param recyclerView
         * @param viewHolder
         */
        @Override
        public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
            super.clearView(recyclerView, viewHolder);
            viewHolder.itemView.setBackgroundColor(0);
            showAdapter.notifyDataSetChanged();  //完成拖动后刷新适配器,这样拖动后删除就不会错乱
        }
    });

		//为rv设置helper
        helper.attachToRecyclerView(binding.rvShow);

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1948810.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Mybatis(三) 查询不同数据封装的方式

实体类&#xff1a; 数据库&#xff1a; 1、查询一个实体类对象 /** * 根据用户id查询用户信息* param id * return */User getUserById(Param("id") int id);<select id"getUserById" resultType"User">select * from t_user where id …

乐尚代驾六订单执行一

加载当前订单 需求 无论是司机端&#xff0c;还是乘客端&#xff0c;遇到页面切换&#xff0c;重新登录小程序等&#xff0c;只要回到首页面&#xff0c;查看当前是否有正在执行订单&#xff0c;如果有跳转到当前订单执行页面 之前这个接口已经开发&#xff0c;为了测试&…

MySQL练习(5)

作业要求&#xff1a; 实现过程&#xff1a; 一、触发器 &#xff08;1&#xff09;建立两个表&#xff1a;goods&#xff08;商品表&#xff09;、orders&#xff08;订单表&#xff09; &#xff08;2&#xff09;在商品表中导入商品记录 &#xff08;3&#xff09;建立触发…

Nuxt3:ERROR [nitro] [unhandledRejection] connect ECONNREFUSED ::1:80

Nuxt3对接接口时报错 &#xff1a;ERROR [nitro] [unhandledRejection] connect ECONNREFUSED ::1:80 排查了很久配置&#xff0c;端口等都是没问题的&#xff0c;但是如果直接将访问地址修改完整访问是没有问题但是我们会遇到跨域问题可以参考Nuxt3&#xff1a;跨域-CSDN博客…

Java连接Redis和SpringBoot整合Redis

1. Java连接Redis 思考&#xff1a;我们之前操作redis都是通过命令行的客户端来操作。在开发时都是通过java项目操作redis java提高连接redis的方式为jedis。我们需要遵循jedis协议。 java提供连接mysql的方式为jdbc。 1.1 单机模式 引入依赖 <!--引入java连接redis的驱动…

Linux---01---安装VMware

一. 什么时Linux Linux 是一个开源的类 Unix 操作系统,Linux 是许多计算机硬件的底层操作系统&#xff0c;特别是服务器、嵌入式系统和个人电脑。它支持多种架构&#xff0c;包括 x86、x64、ARM 和 MIPS 等。Linux 因其稳定性、安全性、开源性以及广泛的社区支持而广受欢迎。 …

《人工智能大语言模型技术发展研究报告(2024)》【下载】

《人工智能大语言模型技术发展研究报告&#xff08;2024&#xff09;》下载 自2023年起&#xff0c;大模型技术产品的快速迭代和升级&#xff0c;已经成为全球科技竞争的关键因素。由中国软件评测中心发布的《人工智能大语言模型技术发展研究报告&#xff08;2024&#xff09;》…

安卓开机启动性能优化之-bootchart相关工具使用及查看

背景&#xff1a; 开机启动相关的详细信息&#xff0c;一般都是可以通过logcat中查看boot_progress相关查看&#xff0c;这种方式查看相对不那么方便&#xff0c;毕竟开机过程中涉及的进程较多&#xff0c;要查看也较多&#xff0c;而且还经常需要查看代码才可以对应起来&…

Vue3时间选择器datetimerange在数据库存开始时间和结束时间

♥️作者&#xff1a;小宋1021 &#x1f935;‍♂️个人主页&#xff1a;小宋1021主页 ♥️坚持分析平时学习到的项目以及学习到的软件开发知识&#xff0c;和大家一起努力呀&#xff01;&#xff01;&#xff01; &#x1f388;&#x1f388;加油&#xff01; 加油&#xff01…

C++知识点:类和对象(自用)

类和对象 1. 类和对象的关系2. 对象指针3. 在堆上创建对象4. 成员访问限定符5. 名字编码&#xff08;Name Mangling&#xff09;6.构造函数7.构造函数的重载8.初始化列表8. 成员变量初始化的顺序&#xff08;通过初始化列表&#xff09;9. 初始化 const 成员变量10. 析构函数11…

【Web爬虫逆向】“企业预警通”模糊查询公司信息,逆向案例实战

“企业预警通”模糊查询公司信息&#xff0c;逆向案例实战 功能介绍效果演示思路分析1、先找到模糊查询的接口2、分析headers与params中参数并进行构造3、JS逆向&#xff0c;跟栈&#xff0c;找到js中key和dataCategory的生成方法&#xff0c;并完成js补码构造4、成功还原key后…

嵌入式中什么是三次握手

在开始前刚好我有一些资料&#xff0c;是我根据网友给的问题精心整理了一份「嵌入式的资料从专业入门到高级教程」&#xff0c;点个关注在评论区回复“666”之后私信回复“666”&#xff0c;全部无偿共享给大家&#xff01;&#xff01;&#xff01; 在网络数据传输中&#xf…

Mysql的主从复制(重要)和读写分离(理论重要实验不重要)

一、主从复制&#xff1a;架构一般是一主两从。 1.主从复制的模式&#xff1a; mysql默认模式为异步模式&#xff1a;主库在更新完事务之后会立即把结果返回给从服务器&#xff0c;并不关心从库是否接收到以及从库是否处理成功。缺点&#xff1a;网络问题没有同步、防火墙的等…

论文阅读:Deep_Generic_Dynamic_Object_Detection_Based_on_Dynamic_Grid_Maps

目录 概要 Motivation 整体框架流程 技术细节 小结 不足 论文地址&#xff1a;Deep Generic Dynamic Object Detection Based on Dynamic Grid Maps | IEEE Conference Publication | IEEE Xplore 概要 该文章提出了一种基于动态网格图&#xff08;Dynamic Grid Maps&a…

DevExpress WPF中文教程:如何完成GridControl的列和编辑器配置?

DevExpress WPF拥有120个控件和库&#xff0c;将帮助您交付满足甚至超出企业需求的高性能业务应用程序。通过DevExpress WPF能创建有着强大互动功能的XAML基础应用程序&#xff0c;这些应用程序专注于当代客户的需求和构建未来新一代支持触摸的解决方案。 无论是Office办公软件…

基于微信小程序的校园警务系统/校园安全管理系统/校园出入管理系统

摘要 伴随着社会以及科学技术的发展&#xff0c;小程序已经渗透在人们的身边&#xff0c;小程序慢慢的变成了人们的生活必不可少的一部分&#xff0c;紧接着网络飞速的发展&#xff0c;小程序这一名词已不陌生&#xff0c;越来越多的学校机构等都会定制一款属于自己个性化的小程…

Exponential Moving Average (EMA) in Stable Diffusion

1.Moving Average in Stable Diffusion (SMA&EMA) 1.Moving average 2.移动平均值 3.How We Trained Stable Diffusion for Less than $50k (Part 3) Moving Average 在统计学中&#xff0c;移动平均是通过创建整个数据集中不同选择的一系列平均值来分析数据点的计算。 …

树莓集团——缔造国际领先的数字媒体产业孵化基地

在数字化浪潮席卷全球的背景下&#xff0c;树莓集团以其卓越的创新能力&#xff0c;正在全力打造一个全球领先的数字媒体产业基地。成都国际数字影像产业园不仅是技术和创意的汇聚地&#xff0c;更是数字内容创新与应用的典范&#xff0c;推动数字媒体产业迈向新的高度。 树莓集…

vue.js入门

目录 一. 框架概述 二. vue常用命令 2.1 插值表达式 2.2 v-text 2.3 v-html 2.4 v-on 2.5 v-model 2.6 v-show 2.7 v-if 2.8 v-else 2.9 v-bind 2.10 v-for 三. vue生命周期函数 一. 框架概述 我们之前写的javaScript代码都是原生的,而框架是在基础语言之上,对其进…

pytorch-梯度下降

梯度下降 y x 2 ∗ s i n ( x ) y ′ 2 x s i n x x 2 c o s x x 1 x − Δ y ′ ( x ) 其中 Δ 表示学习率&#xff0c; y ′ ( x ) 代表 y 在 x 点处关于 x 的梯度。 y x^2 * sin(x) \\ y 2xsinxx^2cosx \\ x_1 x - \Delta y(x) \\ 其中 \Delta 表示学习率&#xff0c…