自定义RecyclerView.LayoutManager实现类实现卡片层叠布局的列表效果

news2024/11/19 2:39:31

一.前言

  • 先看效果(大佬们请忽略水印):
    在这里插入图片描述

  • 卡片层叠列表的实现效果已经发布成插件,集成地址:implementation ‘com.github.MrFishC:YcrCardLayoutHepler:v1.1’;

  • 先讲解如何快速实现,然后再来讲解插件[支持加载固定数量的数据,无限循环,加载更多]中的实现细节;

二.使用方式

  • 先看代码
import android.annotation.SuppressLint
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.RecyclerView
import cn.jack.library_arouter.manager.constants.RouterPathActivity
import com.alibaba.android.arouter.facade.annotation.Route
import com.jack.lib_base.base.view.BaseSimpleActivity
import com.jack.simple_recycleview.databinding.ActivitySimpleRecycleviewBinding
import com.jack.ycr_rv_cardlayout.ConfigManager
import com.jack.ycr_rv_cardlayout.CustomItemTouchHelperCallBackImp
import com.jack.ycr_rv_cardlayout.CustomLayoutManager
import com.jack.ycr_rv_cardlayout.OnItemSwipeListener
import java.util.*
@Route(path = RouterPathActivity.SimpleRv.PAGER_SIMPLE_RV)
class SimpleRecycleViewActivity :
    BaseSimpleActivity<ActivitySimpleRecycleviewBinding>(ActivitySimpleRecycleviewBinding::inflate) {

    override fun prepareData() {
        super.prepareData()

        val adapter = MyAdapter()
        mBinding.recyclerView.adapter = adapter
        val manager = ConfigManager()
        val callBackImp = CustomItemTouchHelperCallBackImp(adapter, list, manager)
        callBackImp.setOnSwipedListener(object : OnItemSwipeListener<Int> {
            override fun onItemSwiping(
                viewHolder: RecyclerView.ViewHolder,
                ratio: Float,
                direction: Int
            ) {
                when (direction) {
                    manager.SWIPING_LEFT -> {
                        println("向左侧滑动")
                    }

                    manager.SWIPING_RIGHT -> {
                        println("向右侧滑动")
                    }

                    else -> {
                        println("向未知方向滑动")
                    }
                }
            }

            override fun onItemSwiped(viewHolder: RecyclerView.ViewHolder, t: Int, direction: Int) {
                when (direction) {
                    manager.SWIPED_UP -> {
                        println("从上方滑出")
                    }

                    manager.SWIPED_DOWN -> {
                        println("从下方滑出")
                    }

                    manager.SWIPED_LEFT -> {
                        println("从左侧滑出")
                    }

                    manager.SWIPED_RIGHT -> {
                        println("从右侧滑出")
                    }

                    else -> {
                        println("从未知方向滑出")
                    }
                }
            }

            @SuppressLint("NotifyDataSetChanged")
            override fun onSwipedAllItem() {
                println("卡片全部滑出")
                //根据实际业务来实现 加载更多
                mBinding.recyclerView.postDelayed({
                    initData()
                    Objects.requireNonNull(mBinding.recyclerView.adapter).notifyDataSetChanged()
                }, 1500L)
            }
        })
        val touchHelper = ItemTouchHelper(callBackImp)
        val cardLayoutManager = CustomLayoutManager(mBinding.recyclerView, touchHelper, manager)
        mBinding.recyclerView.layoutManager = cardLayoutManager
        touchHelper.attachToRecyclerView(mBinding.recyclerView)
        initData()
    }

    private fun initData() {
        list.add(R.drawable.icon_common_bg)
        list.add(R.drawable.icon_common_bg)
        list.add(R.drawable.icon_common_bg)
        list.add(R.drawable.icon_common_bg)
        list.add(R.drawable.icon_common_bg)
        list.add(R.drawable.icon_common_bg)
        list.add(R.drawable.icon_common_bg)
        list.add(R.drawable.icon_common_bg)
        list.add(R.drawable.icon_common_bg)
    }

    private val list: MutableList<Int> = ArrayList()

    private inner class MyAdapter : RecyclerView.Adapter<MyAdapter.MyViewHolder>() {
        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
            val view =
                LayoutInflater.from(parent.context).inflate(R.layout.simple_rv_item, parent, false)
            return MyViewHolder(view)
        }

        override fun onBindViewHolder(holder: MyViewHolder, position: Int) {}
        override fun getItemCount(): Int {
            return list.size
        }

        inner class MyViewHolder(itemView: View?) : RecyclerView.ViewHolder(
            itemView!!
        )
    }
}
  • 插件集成之后,只需要按照prepareData方法中的代码做一下配置便可以实现卡片层叠的列表;

三.插件实现细节

1.ConfigManager

  • 这里是一些配置信息,列表item的缩放比例,显示列表的item数量,item支持滑出的方向,item层叠的方式等等;

2.CustomLayoutManager

  • 这个是层叠布局实现的关键,通过自定义RecyclerView.LayoutManager的实现类可以实现很多炫酷的UI,其核心在于onLayoutChildren方法,绘制RecycleView的子View:
override fun onLayoutChildren(recycler: Recycler, state: RecyclerView.State) {
        // 先移除所有view
        removeAllViews()
        // 在布局之前,将所有的子 View 先 Detach 掉,放入到 Scrap 缓存中
        detachAndScrapAttachedViews(recycler)
        val itemCount = itemCount

        // 当数据源个数大于最大显示数时
        if (itemCount > mCManager.DEFAULT_SHOW_ITEM) {
            // 把数据源倒着循环,这样,第0个数据就在屏幕最上面了            为什么倒序就可以让第0个数据在屏幕最上面  原理是什么 待研究
            for (position in mCManager.DEFAULT_SHOW_ITEM downTo 0) {
                //从缓冲池中获取到itemView
                val view = recycler.getViewForPosition(position)
                // 将 Item View 加入到 RecyclerView 中
                addView(view)
                // 测量 Item View
                measureChildWithMargins(view, 0, 0)
                // getDecoratedMeasuredWidth(view) 可以得到 Item View 的宽度
                // 所以 widthSpace 就是除了 Item View 剩余的值
                val widthSpace = width - getDecoratedMeasuredWidth(view)
                // 同理
                val heightSpace = height - getDecoratedMeasuredHeight(view)

                // recyclerview布局:在这里默认布局是放在 RecyclerView 中心
                // layoutDecoratedWithMargins: 将child显示在RecyclerView上面,left,top,right,bottom规定了显示的区域
                layoutDecoratedWithMargins(
                    view, widthSpace / 2, heightSpace / 2,
                    widthSpace / 2 + getDecoratedMeasuredWidth(view),
                    heightSpace / 2 + getDecoratedMeasuredHeight(view)
                )

                // 其实屏幕上有 mCManager.DEFAULT_SHOW_ITEM + 1 张卡片,但是我们把第 mCManager.DEFAULT_SHOW_ITEM 张和
                // 第 mCManager.DEFAULT_SHOW_ITEM + 1 张卡片重叠在一起,这样看上去就只有 mCManager.DEFAULT_SHOW_ITEM  张
                // 第CardConfig.DEFAULT_SHOW_ITEM + 1张卡片主要是为了保持动画的连贯性
                if (position == mCManager.DEFAULT_SHOW_ITEM) {
                    view.scaleX = 1 - (position - 1) * mCManager.DEFAULT_SCALE
                    view.scaleY = 1 - (position - 1) * mCManager.DEFAULT_SCALE
                    when (mCManager.getStackDirection()) {
                        //从下往上层叠
                        mCManager.UP ->
                            view.translationY =
                                ((position - 1) * view.measuredHeight / mCManager.DEFAULT_TRANSLATE_Y).toFloat()

                        //从上往下层叠
                        mCManager.DOWN ->
                            view.translationY =
                                (-(position - 1) * view.measuredHeight / mCManager.DEFAULT_TRANSLATE_Y).toFloat()

                        else -> view.translationY =
                            (-(position - 1) * view.measuredHeight / mCManager.DEFAULT_TRANSLATE_Y).toFloat()
                    }
                } else if (position > 0) {
                    view.scaleX = 1 - position * mCManager.DEFAULT_SCALE
                    view.scaleY = 1 - position * mCManager.DEFAULT_SCALE
                    when (mCManager.getStackDirection()) {
                        //从下往上层叠
                        mCManager.UP ->
                            view.translationY =
                                (position * view.measuredHeight / mCManager.DEFAULT_TRANSLATE_Y).toFloat()

                        //从上往下层叠
                        mCManager.DOWN ->
                            view.translationY =
                                (-position * view.measuredHeight / mCManager.DEFAULT_TRANSLATE_Y).toFloat()

                        else -> view.translationY =
                            (-position * view.measuredHeight / mCManager.DEFAULT_TRANSLATE_Y).toFloat()
                    }
                } else {
                    //只有顶层的卡片才能滑动
                    view.setOnTouchListener(mOnTouchListener)
                }
            }
        } else {
            // 当数据源个数小于或等于最大显示数时
            for (position in itemCount - 1 downTo 0) {
                val view = recycler.getViewForPosition(position)
                addView(view)
                measureChildWithMargins(view, 0, 0)
                val widthSpace = width - getDecoratedMeasuredWidth(view)
                val heightSpace = height - getDecoratedMeasuredHeight(view)
                // recyclerview 布局
                layoutDecoratedWithMargins(
                    view, widthSpace / 2, heightSpace / 2,
                    widthSpace / 2 + getDecoratedMeasuredWidth(view),
                    heightSpace / 2 + getDecoratedMeasuredHeight(view)
                )
                if (position > 0) {
                    view.scaleX = 1 - position * mCManager.DEFAULT_SCALE
                    view.scaleY = 1 - position * mCManager.DEFAULT_SCALE
                    when (mCManager.getStackDirection()) {
                        //从下往上层叠
                        mCManager.UP ->
                            view.translationY =
                                (position * view.measuredHeight / mCManager.DEFAULT_TRANSLATE_Y).toFloat()

                        //从上往下层叠
                        mCManager.DOWN ->
                            view.translationY =
                                (-position * view.measuredHeight / mCManager.DEFAULT_TRANSLATE_Y).toFloat()

                        else -> view.translationY =
                            (-position * view.measuredHeight / mCManager.DEFAULT_TRANSLATE_Y).toFloat()
                    }
                } else {
                    view.setOnTouchListener(mOnTouchListener)
                }
            }
        }
    }

3.CustomItemTouchHelperCallBackImp

  • ItemTouchHelper.Callback的实现类,两个核心方法:
    • onChildDraw:这个方法被触发的条件之一是,item滑动的时候,在该方法内部对所有可见的item进行缩放,对最上层的item进行旋转角度的设置,如此,用户体验效果更佳;
override fun onChildDraw(
        c: Canvas, recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder,
        dX: Float, dY: Float, actionState: Int, isCurrentlyActive: Boolean
    ) {
        super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive)
        val itemView = viewHolder.itemView
        if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE) {
            //滑动的比例
            var ratio: Float = dX / mCManager.getThreshold(recyclerView)

            // ratio 最大为 1 或 -1
            if (ratio > 1) {
                ratio = 1f
            } else if (ratio < -1) {
                ratio = -1f
            }

            //旋转的角度
            itemView.rotation = ratio * mCManager.DEFAULT_ROTATE_DEGREE
            val childCount = recyclerView.childCount

            //卡片滑动过程中   对view进行缩放处理  [这里的逻辑需要跟自定义的RecyclerView.LayoutManager实现类onLayoutChildren方法对应]        具体的缩放效果可以自行通过计算来尝试
            // 当数据源个数大于最大显示数时
            if (childCount > mCManager.DEFAULT_SHOW_ITEM) {
                //position:从1开始       for循环中定义position的初始值以及其边界,目的是为了让第一张不做处理
                for (position in 1 until childCount - 1) {
                    val index = childCount - position - 1
                    val view = recyclerView.getChildAt(position)
                    //通过调用setScaleX()和setScaleY()方法,可以实现View的缩放
                    view.scaleX =
                        1 - index * mCManager.DEFAULT_SCALE + abs(ratio) * mCManager.DEFAULT_SCALE
                    view.scaleY =
                        1 - index * mCManager.DEFAULT_SCALE + abs(ratio) * mCManager.DEFAULT_SCALE
                    when (mCManager.getStackDirection()) {
                        //从下往上层叠
                        mCManager.UP -> view.translationY =
                            (index - abs(ratio)) * itemView.measuredHeight / mCManager.DEFAULT_TRANSLATE_Y
                        //从上往下层叠
                        mCManager.DOWN -> view.translationY =
                            -(index - abs(ratio)) * itemView.measuredHeight / mCManager.DEFAULT_TRANSLATE_Y

                        else -> view.translationY =
                            -(index - abs(ratio)) * itemView.measuredHeight / mCManager.DEFAULT_TRANSLATE_Y
                    }
                }
            } else {
                // 当数据源个数小于或等于最大显示数时      for循环中定义position的初始值以及其边界,目的是为了让最后一张不做处理
                for (position in 0 until childCount - 1) {
                    val index = childCount - position - 1
                    val view = recyclerView.getChildAt(position)
                    view.scaleX =
                        1 - index * mCManager.DEFAULT_SCALE + abs(ratio) * mCManager.DEFAULT_SCALE
                    view.scaleY =
                        1 - index * mCManager.DEFAULT_SCALE + abs(ratio) * mCManager.DEFAULT_SCALE
                    when (mCManager.getStackDirection()) {
                        //从下往上层叠
                        mCManager.UP ->
                            view.translationY =
                                (index - abs(ratio)) * itemView.measuredHeight / mCManager.DEFAULT_TRANSLATE_Y

                        //从上往下层叠
                        mCManager.DOWN ->
                            view.translationY =
                                -(index - abs(ratio)) * itemView.measuredHeight / mCManager.DEFAULT_TRANSLATE_Y

                        else -> view.translationY =
                            -(index - abs(ratio)) * itemView.measuredHeight / mCManager.DEFAULT_TRANSLATE_Y
                    }
                }
            }
            //由于增加了上下方向 这里 可以按需添加业务逻辑
            if (ratio != 0f) {
                if (mListener != null) {
                    mListener!!.onItemSwiping(
                        viewHolder,
                        ratio,
                        if (ratio < 0) mCManager.SWIPING_LEFT else mCManager.SWIPING_RIGHT
                    )
                }
            } else {
                if (mListener != null) {
                    mListener!!.onItemSwiping(viewHolder, ratio, mCManager.SWIPING_NONE)
                }
            }
        }
    }

  • onSwiped:当item滑动的时候触发,这个方法内部做设置回调,设置支持无限循环的情况下集合需要添加顶层被移除的item,同时需要调用适配器的notifyDataSetChanged方法,对所有item“一视同仁”;
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
        // 移除onTouchListener,防止触摸 滑动之间冲突
        viewHolder.itemView.setOnTouchListener(null)

        val layoutPosition = viewHolder.layoutPosition
        val remove: T = mDataList.removeAt(layoutPosition)

        if (mCManager.isLoopCard()) {
            mDataList.add(remove)
        }

        //主动调用刷新,否则会出现只有顶层卡片才能滑动
        mAdapter.notifyDataSetChanged()

        //使用接口回调进行拓展1
        if (mListener != null) {
            when (direction) {
                ItemTouchHelper.UP -> mListener!!.onItemSwiped(
                    viewHolder,
                    remove,
                    mCManager.SWIPED_UP
                )

                ItemTouchHelper.DOWN -> mListener!!.onItemSwiped(
                    viewHolder,
                    remove,
                    mCManager.SWIPED_DOWN
                )

                ItemTouchHelper.LEFT -> mListener!!.onItemSwiped(
                    viewHolder,
                    remove,
                    mCManager.SWIPED_LEFT
                )

                ItemTouchHelper.RIGHT -> mListener!!.onItemSwiped(
                    viewHolder,
                    remove,
                    mCManager.SWIPED_RIGHT
                )

                else -> mListener!!.onItemSwiped(viewHolder, remove, mCManager.SWIPED_NONE)
            }
        }

        //使用接口回调进行拓展2
        // 当没有数据时回调 mListener
        if (mAdapter.itemCount == 0 && mListener != null && !mCManager.isLoopCard()) {
            mListener!!.onSwipedAllItem()
        }
    }

四.总结

  • 核心在于两点,其一:自定义RecyclerView.LayoutManager实现类,重写onLayoutChildren方法,对子item进行“绘制”;其二:自定义ItemTouchHelper.Callback实现类,重写onChildDraw和onSwiped方法;快速实现只需要按照前言中的方式进行配置即可,若想要了解细节,可以看插件代码中的注释(写的还是比较详细);

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

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

相关文章

小程序开发费用估算:如何控制项目成本?

在当今数字化的时代&#xff0c;小程序已经成为了很多企业和个人开展业务的重要手段。小程序的开发需要耗费时间和资源&#xff0c;因此在项目初期&#xff0c;了解预计的开发费用是非常重要的。本文将详细介绍如何估算小程序开发费用以及如何控制项目成本。 小程序开发费用 …

2023年重庆经济发展研究报告

第一章 发展概况 1.1 地理和人口发展概况 重庆&#xff08;简称“渝”&#xff09;位于中国西南地区&#xff0c;是中国四个直辖市之一&#xff0c;地处长江中上游&#xff0c;横跨东经10517到11011&#xff0c;北纬2810到3213之间。重庆市地势复杂&#xff0c;地形多山&…

风光场景削减及源荷不确定性的虚拟电厂随机优化调度研究(Matlab代码实现)

&#x1f4a5; &#x1f4a5; &#x1f49e; &#x1f49e; 欢迎来到本博客 ❤️ ❤️ &#x1f4a5; &#x1f4a5; &#x1f3c6; 博主优势&#xff1a; &#x1f31e; &#x1f31e; &#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 …

Ubuntu16.04配置使用robosense雷达18版本的rsview软件记录

目录 依赖安装boost安装下载源码解压编译安装更新一下系统的动态链接库 libpng16-16安装 rsview运行下载运行具体操作可以看doc文件夹内的说明文件 参考文章 依赖安装 boost安装 下载源码 boost1.65官方下载地址 解压 进入下载文件所在的文件夹 tar -zxvf boost_1_65_1.t…

托福高频真词List05 // 附托福TPO阅读真题

目录 4月23日单词 生词 熟词 4月24日真题 4月23日单词 生词 sparsethinly distributedadj 稀疏的sparselythinlyadv 稀疏地congestion / kənˈdʒestʃən / overcrowdingn 拥挤continuallyregularlyadv 持续的eradicateeliminatev 消除facilitatemake easiereasev 使..…

M2下通过docker安装sqlserver

背景&#xff1a;要做这一个需求&#xff0c;将txt文件格式化以后&#xff0c;入库到sqlserver中&#xff0c;没有测试环境&#xff0c;只能自己在本地搭建一个sqlserver的服务器 前提&#xff1a;安装好docker 第一步&#xff1a;在终端下查找sqlserver的镜像文件 我们可以选…

S7-1200通过模拟量的方式实现PID控制恒压供水的具体方法示例

S7-1200通过模拟量的方式实现PID控制恒压供水的具体方法示例 具体方法和步骤可参考以下内容: 创建工艺对象,如下图所示,有2种方式: PID_Compact指令需要在OB30中断组织块中调用,如下图所示, 使用 PID 控制器前,需要对其进行组态设置,分为基本设置、过程值设置、高级设…

Stm32开发环境从0搭建(Clion作为开发软件)

环境安装 1. 下载CLion开发软件和安装 https://www.jetbrains.com/zh-cn/clion/2. 安装msys2开发环境 一直下一步 参考文档 安装OpenOCD工具(烧录下载工具) 将压缩包解压到环境安装目录下: 安装Arm-Gcc编译环境 将此目录拷贝到安装目录&#xff0c;并解压 配置环境变量 …

实测有效!手把手带你将 Docker Image 体积减少 90%

Docker Image 体积越大,那部署要花的时间就越长;假如每个版本都有好几 GB,那并不是一个理想的状态;因此笔者开始动手实作,想看看到底能将 Docker Image 的体积缩小多少! 大纲 ㄧ、先初始化一个简易的 Node.js 专案 二、撰写 Dockefile,了解优化前体积有多大 三、使用 No…

嵌入式开发--无刷电机学习1--FOC简介

写在前面 最近刚学FOC电机控制&#xff0c;文中错误在所难免&#xff0c;欢迎批评指正&#xff0c;也欢迎在评论区留言讨论。 FOC意义 普通直流电机&#xff08;DC MOTOR&#xff09;的驱动是碳刷换向&#xff0c;能看到这篇文章的朋友应该不用我再去复述一遍直流电机的工作…

【论文阅读】You Are What You Do:通过数据来源分析寻找隐蔽的恶意软件

You Are What You Do: Hunting Stealthy Malware via Data Provenance Analysis NDSS-2020 伊利诺伊大学香槟分校、德克萨斯大学达拉斯分校 Wang Q, Hassan W U, Li D, et al. You Are What You Do: Hunting Stealthy Malware via Data Provenance Analysis[C]//NDSS. 2020. 目…

Java每日一练(20230424)

目录 1. 二叉树的中序遍历 &#x1f31f;&#x1f31f; 2. 两两交换链表中的节点 &#x1f31f;&#x1f31f; 3. 不同的子序列 &#x1f31f;&#x1f31f;&#x1f31f; &#x1f31f; 每日一练刷题专栏 &#x1f31f; Golang每日一练 专栏 Python每日一练 专栏 C/…

Python 基础(十一):集合

❤️ 博客主页&#xff1a;水滴技术 &#x1f338; 订阅专栏&#xff1a;Python 入门核心技术 &#x1f680; 支持水滴&#xff1a;点赞&#x1f44d; 收藏⭐ 留言&#x1f4ac; 文章目录 一、声明集合1.1、使用 {} 声明集合1.2、声明空的集合1.3、自动过滤重复元素 二、添加…

Excel中的数据如何导入MySQL

近期工作遇到了excel数据灌入数据库表的任务&#xff0c;无聊整理一下实现方法&#xff1a; System.out.println("分割线");文章目录 1、使用数据库管理工具2、使用SQL3、使用脚本 1、使用数据库管理工具 首先是使用工具来完成&#xff0c;常见的比较成熟的数据库管…

【Unity入门】18.脚本对资源进行访问

【Unity入门】脚本对资源进行访问 大家好&#xff0c;我是Lampard~~ 欢迎来到Unity入门系列博客&#xff0c;所学知识来自B站阿发老师~感谢 &#xff08;一&#xff09;脚本中切换背景音乐 &#xff08;1&#xff09;定义全局变量&#xff0c;引用音频资源 之前的博客中&…

024:Mapbox GL加载image图像文件

第024个 点击查看专栏目录 本示例的目的是介绍演示如何在vuemapbox中加载image图像文件。图像源。 “url”值包含图像位置。“坐标”数组包含按顺时针顺序列出的图像角的 [longitude, latitude] 对&#xff1a;左上角、右上角、右下角、左下角。 直接复制下面的 vuemapbox源代…

Python提取JSON格式数据

文章目录 前言&#xff1a;一、JSON使用1.导入json的包2.常用的方法 二、实战1.json.loads()2.jsonpath 前言&#xff1a; 我们经常会用到json数据&#xff0c;json数据格式主要是用来和不同语言之间进行交互比如你要给java端的提供数据&#xff0c;你需要将自己的数据转换为j…

如何使用OpenGL来绘制一个圆角矩形

iOS系统的流行带来了一阵圆角矩形的热风。许多设计狮与产品汪都对圆角矩形比较感冒&#xff0c;那作为程序猿该如何应付呢&#xff1f; 幸好&#xff0c;当前无论是iOS还是Android系统&#xff0c;系统框架库都带了一些API能让我们比较便利地实现圆角矩形的功能。这里&#xf…

基于TensorRT的yolov5 实例分割部署

yolov5-7.0 github: https://github.com/ultralytics/yolov5/tree/master 1. 代码的使用 1.1 训练yolov5-seg模型 使用的yolov5-7.0的代码,github下载:https://github.com/ultralytics/yolov5/releases/tag/v7.0 训练指令 python segment/train.py --data coco128-seg.y…

案例——数据表的基本操作

目录 案例目的&#xff1a; 创建表&#xff1a; 创建offices&#xff1a; 创建employees表&#xff1a; 修改表&#xff1a; 将 employees 的 mobile 字段移动到 officeCode 字段后&#xff1a; 将 birth 字段名称改为 employee_birth: 修改 sex 字段&#xff0c;数据类…