Android进阶之多级列表
遇到一个需求需要显示多级列表,因为界面是在平板上的,所以层级是从左向右往下排的,类似于

我当时的写法是在xml布局里一个个RecyclerView往下排的

当然前提是已经规定好最大的层级我才敢如此去写界面,如果已经明确规定只有两级或者三级,当然如果可以的话,不管多少级都这么写也是没毛病的
作为一名开发者,如果以后也用到类似的需求,并且级数不是固定的话,这么写肯定是有很多瑕疵的,所以想着怎么样去做一个轮子,以后遇到直接拿来用就行,不用每次都去搭界面,写逻辑,当然网络上也有类似的代码,但是感觉和自己的有多少出入,那不如自己来写一套吧
下面是效果图,界面有些丑,没有花时间去做一些美化,只是为了展示不同的效果,毕竟真正用起来界面样式还是多样化没法固定的


首先的问题是如何去分级,一开始想法是把所有数据放进入,自己去解析数据进行分级,但是又可能涉及到部分数据需要网络请求等复杂的环境
问题一: 如何解决一开始就分级还是点击之后逐级显示?
答: 自主触发,不自行解析添加,告诉我添加我再去添加
问题二: 不同条件下如何去分级?
答: 要定义一个自己的规则,可能不完善但是后面可以自己添加,否则出现要写死或者部分要网络请求的时候无法完整判断,而且不同的数据结构可能连参数名字都不一样,所以需要自主分类并且添加数据
思路:
1.一开始传入最大多少级,以及每一级的样式(比如宽度,背景),动态创建对应级数的列表并和适配器存储起来(别忘了关闭界面的时候或者不使用的时候去销毁),这样就不会存在每次点击都重新创建列表的情况,每次点击只是对应的显示隐藏和替换数据而已
2.我需要创建第一级的时候,我将第一级的数据筛选出来,将步骤1存储的第一级适配器拿出来塞数据
3.如果我一开始就要将第一级相关的全部显示出来我只要自己去根据数据筛选出对应的下一级,继续往里面塞
4.如果我要点击之后显示,那我也和第三步骤一样,点击之后我再去筛选,再去塞数据
5.我点之后要将所有下面的级数隐藏,在去显示对应的层级,否则就会出现我已经出现了三级,此时我点击其他的层级没有第三极,但是上次的第三极还在那显示
6.样式问题,不同的需求有不同的样式,这点无能为力,只能自己去修改样式,但是最基础的每一级的宽度,间距,背景,以及每一个条目的字体大小,高度是必须的,我可以统一规定起来
具体实现:
首先导入用到的三方依赖
implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:3.0.4'
其中的适配器里的实体类要根据自己的情况去更改
1.创建多级列表:
xml布局里的主布局要用约束布局
将不同层级样式给Util去创建
//这个集合存储的是每一层级的样式以及信息,会根据该集合的长度去创建最大多少级val mList: ArrayList<GetListUtils.GetListData> = arrayListOf()//第一级样式mList.add(GetListUtils.GetListData(width = 200,itemSize = 16f,itemHeight = 160, bGround = "#CC00FFFF"))//第二级样式mList.add(GetListUtils.GetListData(itemSize = 14f,itemHeight = 140,leftMargin = 60, bDrawable = getDrawable(R.mipmap.ic_launcher)))//第三极样式mList.add(GetListUtils.GetListData(width = 180,itemSize = 12f,itemHeight = 120,leftMargin = 80,bGround = "#CC33ff00"))//第四级样式mList.add(GetListUtils.GetListData(itemSize = 10f,itemHeight = 100,leftMargin = 30,bGround = "#CCFFFF33"))//第五级样式mList.add(GetListUtils.GetListData(itemSize = 8f,itemHeight = 80,leftMargin = 70))//这里是布局里的主布局,要用约束布局!!!val clAll = findViewById<ConstraintLayout>(R.id.cl_all)//层级列表和主布局传进去GetListUtils.find(clAll,context = this,mList)
2.自行分类,将数据塞给对应的层级,这里是筛选出第一级数据,并把数据给第一级
这里的模拟数据集合就需要替换成项目中真正的数据类了(TestData)
//模拟数据 type当前类型 parentType 父级,默认parentType = 0 为一级val mListAll: ArrayList<GetListUtils.TestData> = arrayListOf()mListAll.add(GetListUtils.TestData(name = "美食",type = 1, parentType = 0))mListAll.add(GetListUtils.TestData("饮品",2,0))mListAll.add(GetListUtils.TestData("西瓜",3,1))mListAll.add(GetListUtils.TestData("火龙果",4,1))mListAll.add(GetListUtils.TestData("葡萄",5,1))mListAll.add(GetListUtils.TestData("橘子",6,1))mListAll.add(GetListUtils.TestData("可乐",7,2))mListAll.add(GetListUtils.TestData("雪碧",8,2))mListAll.add(GetListUtils.TestData("美年达",9,2))mListAll.add(GetListUtils.TestData("西瓜汁",10,3))mListAll.add(GetListUtils.TestData("冰镇西瓜",11,3))mListAll.add(GetListUtils.TestData("火龙果块",12,4))mListAll.add(GetListUtils.TestData("冰葡萄",13,5))mListAll.add(GetListUtils.TestData("橘子汁",14,6))mListAll.add(GetListUtils.TestData("无糖可乐",15,7))mListAll.add(GetListUtils.TestData("满糖可乐",16,7))mListAll.add(GetListUtils.TestData("西瓜皮",17,11))mListAll.add(GetListUtils.TestData("西瓜籽",18,11))mListAll.add(GetListUtils.TestData("西瓜瓤",19,11))mListAll.add(GetListUtils.TestData("火龙果籽",20,12))mListAll.add(GetListUtils.TestData("橘子皮",21,14))mListAll.add(GetListUtils.TestData("橘子核",22,14))mListAll.add(GetListUtils.TestData("西瓜子",23,18))//筛选一级目录val mList1: ArrayList<GetListUtils.TestData> = arrayListOf()mListAll.forEach {if (it.parentType == 0){mList1.add(it)}}//设置一级目录GetListUtils.setListData(1,mList1,object :GetListUtils.OnListener{override fun onClick(l: GetListUtils.TestData) {}})
默认显示对应的层级,只需要继续筛选,继续塞数据即可
//筛选二级目录val mList2: ArrayList<GetListUtils.TestData> = arrayListOf()mListAll.forEach {if (it.parentType == 1){mList1.add(it)}}GetListUtils.setListData(2,mList2,object :GetListUtils.OnListener{override fun onClick(l: GetListUtils.TestData) {}})
以上就是使用方式, setListData(当前层级,层级数据,点击事件回调)
以下全部代码,供参考
GetListUtils
/*** 动态添加集合* */
object GetListUtils {private val mRVList: ArrayList<RecyclerView> = arrayListOf()private val mAdapterList: ArrayList<QnZtListAdapter> = arrayListOf()private var mParentView: ConstraintLayout? = nullfun find(view: ConstraintLayout, //父控件context: Context, //上下文gradle: ArrayList<GetListData>, //几级){clearList()mParentView = viewfor (i in 0 until gradle.size){val mGradle = gradle[i]val mRecyclerView = RecyclerView(context)mRecyclerView.id = View.generateViewId()mRVList.add(mRecyclerView)val layoutParams = ConstraintLayout.LayoutParams(mGradle.width,ViewGroup.LayoutParams.WRAP_CONTENT)if (i == 0){layoutParams.startToStart = view.idlayoutParams.topToTop = view.idif (mGradle.leftMargin != 0){layoutParams.leftMargin = mGradle.leftMargin}}else{layoutParams.startToEnd = mRVList[i-1].idlayoutParams.topToTop = mRVList[i-1].idif (mGradle.leftMargin != 0){layoutParams.leftMargin = mGradle.leftMargin}}//背景图优先级高if (mGradle.bDrawable != null){mRecyclerView.background = mGradle.bDrawable}else{if (mGradle.bGround.isNotEmpty()){mRecyclerView.setBackgroundColor(Color.parseColor(mGradle.bGround))}}mRecyclerView.layoutParams = layoutParamsmRecyclerView.layoutManager = LinearLayoutManager(context)mRecyclerView.itemAnimator = DefaultItemAnimator()val mAdapter = QnZtListAdapter(R.layout.item_get_list,mGradle)mRecyclerView.adapter = mAdaptermAdapterList.add(mAdapter)view.addView(mRecyclerView)}}//设置数据fun setListData(i: Int, l: ArrayList<TestData>,k: OnListener){val a = getAdapter(i)if (a != null){a.setList(l)a.setOnItemClickListener { adapter, view, position ->//点击当前层级,隐藏下一层级for (j in 0 until mRVList.size){//这里减一是因为点击的时候是i点击的当前级数,要从下一级开始if (j > i-1){mRVList[j].visibility = View.GONE}}//这里加一是因为i是当前级数,要从下一级开始//下标从零开始为什么还要加一呢?因为获取列表里面减一了if (getList(i+1) != null){getList(i+1)!!.visibility = View.VISIBLE}val mData = adapter.data as ArrayList<TestData>//回调k.onClick(mData[position])//更新选中状态mData.forEach {it.select = false}mData[position].select = trueadapter.notifyDataSetChanged()}}}//获取对应层级的列表private fun getList(i: Int): RecyclerView?{var mL: RecyclerView? = nullif (mRVList.isNotEmpty() && i-1 < mRVList.size){try {mL = mRVList[i - 1]}catch (e: java.lang.Exception){e.printStackTrace()}}return mL}//获取对应层级的适配器private fun getAdapter(i: Int): QnZtListAdapter?{var mAdapter: QnZtListAdapter? = nullif (mAdapterList.isNotEmpty() && i-1 < mAdapterList.size){try {mAdapter = mAdapterList[i - 1]}catch (e: java.lang.Exception){e.printStackTrace()}}return mAdapter}//置空操作fun clearList(){mRVList.clear()mAdapterList.clear()if (mParentView != null){mParentView!!.removeAllViews()}}interface OnListener {fun onClick(l: TestData)}//需要的数据类data class GetListData(var width: Int = ViewGroup.LayoutParams.WRAP_CONTENT, //宽度var leftMargin: Int = 0, //左间距var bGround: String = "", //背景颜色var bDrawable: Drawable? = null, //背景图片var itemSize: Float = 0f, //条目字体大小var itemHeight: Int = ViewGroup.LayoutParams.WRAP_CONTENT, //条目字体高度):java.io.Serializable//模拟数据data class TestData(var name: String? = "", //名称var type: Int? = 0, //分类var parentType: Int? = 0, //父类var select: Boolean = false //是否选中):java.io.Serializableclass QnZtListAdapter : BaseQuickAdapter<GetListUtils.TestData, BaseViewHolder> {constructor(layoutResId: Int) : super(layoutResId) {}private var gradle: GetListUtils.GetListData? = nullconstructor(layoutResId: Int, data: GetListUtils.GetListData) : super(layoutResId) {this.gradle = data}override fun convert(helper: BaseViewHolder, item: GetListUtils.TestData) {//总布局val clGetList = helper.getView<ConstraintLayout>(R.id.cl_get_list)//第一条不显示分割线if (helper.adapterPosition == 0){helper.setGone(R.id.view_line,true)}val tvGetTxt = helper.getView<TextView>(R.id.tv_get_txt)tvGetTxt.text = item.nameif (item.select){tvGetTxt.setTextColor(Color.RED)}else{tvGetTxt.setTextColor(Color.GRAY)}if (gradle != null){//界面高度if (gradle!!.itemHeight != 0){val lp: ViewGroup.LayoutParams = clGetList.layoutParamslp.height = gradle!!.itemHeightclGetList.layoutParams = lp}//字体大小if (gradle!!.itemSize != 0f){tvGetTxt.textSize = gradle!!.itemSize}}}}
}
item_get_list
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayoutandroid:id="@+id/cl_get_list"xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="wrap_content"xmlns:tools="http://schemas.android.com/tools"xmlns:app="http://schemas.android.com/apk/res-auto"><Viewandroid:id="@+id/view_line"android:layout_width="0dp"android:layout_height="1px"android:background="#CC666666"app:layout_constraintStart_toStartOf="parent"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintTop_toTopOf="parent"/><TextViewandroid:id="@+id/tv_get_txt"android:layout_width="wrap_content"android:layout_height="wrap_content"app:layout_constraintTop_toTopOf="parent"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintStart_toStartOf="parent"tools:text = "哈哈哈"/></androidx.constraintlayout.widget.ConstraintLayout>
AddListActivity
/*** 动态创建多级列表*/
class AddListActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_add_list)//这个集合存储的是每一层级的样式以及信息,会根据该集合的长度去创建最大多少级val mList: ArrayList<GetListUtils.GetListData> = arrayListOf()//第一级样式mList.add(GetListUtils.GetListData(width = 200,itemSize = 16f,itemHeight = 160, bGround = "#CC00FFFF"))//第二级样式mList.add(GetListUtils.GetListData(itemSize = 14f,itemHeight = 140,leftMargin = 60, bDrawable = getDrawable(R.mipmap.ic_launcher)))//第三极样式mList.add(GetListUtils.GetListData(width = 180,itemSize = 12f,itemHeight = 120,leftMargin = 80,bGround = "#CC33ff00"))//第四级样式mList.add(GetListUtils.GetListData(itemSize = 10f,itemHeight = 100,leftMargin = 30,bGround = "#CCFFFF33"))//第五级样式mList.add(GetListUtils.GetListData(itemSize = 8f,itemHeight = 80,leftMargin = 70))//这里是布局里的主布局,要用约束布局!!!val clAll = findViewById<ConstraintLayout>(R.id.cl_all)//层级列表和主布局传进去GetListUtils.find(clAll,context = this,mList)//模拟数据 type当前类型 parentType 父级,默认parentType = 0 为一级val mListAll: ArrayList<GetListUtils.TestData> = arrayListOf()mListAll.add(GetListUtils.TestData(name = "美食",type = 1, parentType = 0))mListAll.add(GetListUtils.TestData("饮品",2,0))mListAll.add(GetListUtils.TestData("西瓜",3,1))mListAll.add(GetListUtils.TestData("火龙果",4,1))mListAll.add(GetListUtils.TestData("葡萄",5,1))mListAll.add(GetListUtils.TestData("橘子",6,1))mListAll.add(GetListUtils.TestData("可乐",7,2))mListAll.add(GetListUtils.TestData("雪碧",8,2))mListAll.add(GetListUtils.TestData("美年达",9,2))mListAll.add(GetListUtils.TestData("西瓜汁",10,3))mListAll.add(GetListUtils.TestData("冰镇西瓜",11,3))mListAll.add(GetListUtils.TestData("火龙果块",12,4))mListAll.add(GetListUtils.TestData("冰葡萄",13,5))mListAll.add(GetListUtils.TestData("橘子汁",14,6))mListAll.add(GetListUtils.TestData("无糖可乐",15,7))mListAll.add(GetListUtils.TestData("满糖可乐",16,7))mListAll.add(GetListUtils.TestData("西瓜皮",17,11))mListAll.add(GetListUtils.TestData("西瓜籽",18,11))mListAll.add(GetListUtils.TestData("西瓜瓤",19,11))mListAll.add(GetListUtils.TestData("火龙果籽",20,12))mListAll.add(GetListUtils.TestData("橘子皮",21,14))mListAll.add(GetListUtils.TestData("橘子核",22,14))mListAll.add(GetListUtils.TestData("西瓜子",23,18))//筛选一级目录val mList1: ArrayList<GetListUtils.TestData> = arrayListOf()mListAll.forEach {if (it.parentType == 0){mList1.add(it)}}//设置一级目录GetListUtils.setListData(1,mList1,object :GetListUtils.OnListener{override fun onClick(l: GetListUtils.TestData) {//点击一级目录后筛选二级val mList2: ArrayList<GetListUtils.TestData> = arrayListOf()mListAll.forEach {//还原选中状态,如果默认选中第一个用for循环去设置it.select = falseif (l.type == it.parentType){mList2.add(it)}}//设置二级目录GetListUtils.setListData(2,mList2,object :GetListUtils.OnListener{override fun onClick(l: GetListUtils.TestData) {//点击二级目录后筛选三级val mList3: ArrayList<GetListUtils.TestData> = arrayListOf()mListAll.forEach {//还原选中状态,如果默认选中第一个用for循环去设置it.select = falseif (l.type == it.parentType){mList3.add(it)}}//设置三级目录GetListUtils.setListData(3,mList3,object :GetListUtils.OnListener{override fun onClick(l: GetListUtils.TestData) {//点击三级目录筛选四级目录val mList4: ArrayList<GetListUtils.TestData> = arrayListOf()mListAll.forEach {//还原选中状态,如果默认选中第一个用for循环去设置it.select = falseif (l.type == it.parentType){mList4.add(it)}}//设置四级目录GetListUtils.setListData(4,mList4,object :GetListUtils.OnListener{override fun onClick(l: GetListUtils.TestData) {//点击四级目录筛选五级目录val mList5: ArrayList<GetListUtils.TestData> = arrayListOf()mListAll.forEach {//还原选中状态,如果默认选中第一个用for循环去设置it.select = falseif (l.type == it.parentType){mList5.add(it)}}GetListUtils.setListData(5,mList5,object :GetListUtils.OnListener{override fun onClick(l: GetListUtils.TestData) {Toast.makeText(this@AddListActivity,l.name,Toast.LENGTH_SHORT).show()}})}})}})}})}})}override fun onDestroy() {super.onDestroy()GetListUtils.clearList()}
}
activity_add_list
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayoutandroid:id="@+id/cl_all"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"tools:context=".AddListActivity"></androidx.constraintlayout.widget.ConstraintLayout>
自测效果基本满意~ 就是要修改对应的TestData比较繁琐,后续看看能不能集中处理
相关文章:
Android进阶之多级列表
遇到一个需求需要显示多级列表,因为界面是在平板上的,所以层级是从左向右往下排的,类似于 我当时的写法是在xml布局里一个个RecyclerView往下排的 当然前提是已经规定好最大的层级我才敢如此去写界面,如果已经明确规定只有两级或…...
Stochastic: Distribution-Expectation-Inequalities
见:https://www.math.hkust.edu.hk/~makchen/MATH5411/Chap1Sec2.pdf...
Java算法_ 二叉树的最大深度(LeetCode_Hot100)
题目描述:给定一个二叉树 ,返回其最大深度。root 二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。 获得更多?算法思路:代码文档,算法解析的私得。 运行效果 完整代码 /*** 2 * Author: LJJ* 3 * Date: 2023/…...
行业追踪,2023-08-18
自动复盘 2023-08-18 凡所有相,皆是虚妄。若见诸相非相,即见如来。 k 线图是最好的老师,每天持续发布板块的rps排名,追踪板块,板块来开仓,板块去清仓,丢弃自以为是的想法,板块去留让…...
js将项目中的图片上传到服务器
项目上有时候会有奇怪的需求,比如前端有一些示例,想点击按钮就能上传图片,而这个图片是在前端的项目中的,如果不上传吧,又获取不到一些业务数据的id,但后端又不想为这块功能做特殊的处理,这时想通过前端直接上传到后端,需要file对象才可以。 这个时候我们需要将img转换…...
【C语言】指针的进阶
目录 一、字符指针 二、指针数组 三、数组指针 1.数组指针的定义 2.&数组名和数组名区别 3.数组指针的使用 四、数组参数与指针参数 1.一维数组传参 2.二维数组传参 3.一级指针传参 4.二级指针传参 五、函数指针 六、函数指针数组 七、指向函数指针数组的指针…...
【Windows系统编程】03.远线程注入ShellCode
shellcode:本质上也是一段普通的代码,只不过特殊的编程手法,可以在任意环境下,不依赖于原有的依赖库执行。 远程线程 #include <iostream> #include <windows.h> #include <TlHelp32.h>int main(){HANDLE hPr…...
第1天----验证一个字符串是否是另一个字符串的子串
本文我们将学习如何去验证一个字符串是否是另一个字符串的子串。 一、小试牛刀: 题目描述 输入两个字符串,验证其中一个串是否为另一个串的子串。 输入格式 两行,每行一个字符串。 输出格式 若第一个串 s 1 是第二个串 s 2 的子串,…...
项目实战第四十三讲:使用模版模式优雅实现财务编辑费用
项目实战第四十三讲:财务编辑费用 本文是项目实战第43讲:使用模版模式优雅实现财务编辑费用。支持查看司机填写费用信息,并且附件管理支持展示司机上传费用照片。 文章目录 项目实战第四十三讲:财务编辑费用1、项目背景2、主要技术3、项目职责4、项目实现4.1、表结构4.2、流…...
[JavaWeb]【六】web后端开发-请求响应
前言:请求响应 目录 一 引子 二 请求 2.1 Postman 2.1.1 安装 2.1.2 创建工作空间 2.1.3 添加接口 2.2 简单参数 2.2.1 原始方式(不推荐) 2.2.2 SpringBoot方式-GET(参数名与形参变量名相同) 2.2.3 SpringBoot方式-POST(参数名与形参…...
uniapp websocket机制 心跳 重连
在开发程序过程中通信功能还是比较常用到的,本文主要介绍的是uniapp中websocket的使用 websocket建立连接后,断开、心跳机制重新链接的一个过程。 关于uni.connectSocket可仔细阅读uniapp官网中的uni.connetSocket以及连接socket创建的实例SocketTask …...
labelme安装以及标注自己的目标检测数据集
目录 一、labelme安装指令 二、使用教程 三、 快捷键 一、labelme安装指令 winR之后在弹出的对话框中输入cmd按回车进入终端 conda activate 虚拟环境名称 pip install labelme -i https://pypi.tuna.tsinghua.edu.cn/simple/ 二、使用教程 安装成功之后在终端输入label…...
归并排序JS
当然,下面是使用JavaScript编写的归并排序的示例代码。归并排序是一种分治算法,其基本思想是将数组分成两半进行排序,然后将排序后的结果合并在一起。 function mergeSort(arr) {if (arr.length < 1) {return arr;}const middle Math.fl…...
matlab 计算点云平均密度
目录 一、算法原理二、代码实现三、结果展示四、C++版计算结果本文由CSDN点云侠原创,爬虫自重。如果你不是在点云侠的博客中看到该文章,那么此处便是不要脸的爬虫。 一、算法原理 采样设备不同、设备距离场景远近不同,会使点云密度产生差异。现有的对点云密度的估算方法有基…...
c++ | uint8_t、uint16_t、unint32_t 和size_t
头文件 #include <stdint.h> // for C #include <cstdint> // for Cuint8_t、uint16_t、unint32_t 这三个分别是表示无符号整型,不同点是他们的长度不同,分别是8位机器位、16、32,也就是一个字节、两个字节、四个字节 注意在…...
mysql 超大 sql 文件导入过程
问题 最近遇到 2 个超大 sql 文件导入,好一通折腾 文档在哪里 调优参数太多,文档都看不过来 找到这些参数也费劲, ubuntu 在 /etc/mysql/mysql.conf.d/mysqld.cnf 中找到这个链接 ...... # # The MySQL Server configuration file. # # For explanat…...
【悬挂绝缘子的串效模型】测量每个绝缘子盘之间的电压并测量串效研究(Simulink)
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...
P3957 [NOIP2017 普及组] 跳房子
题目背景 NOIP2017 普及组 T4 题目描述 跳房子,也叫跳飞机,是一种世界性的儿童游戏,也是中国民间传统的体育游戏之一。 跳房子的游戏规则如下: 在地面上确定一个起点,然后在起点右侧画 nn 个格子,这些…...
VR数字工厂多元化展现,打造数字企业工厂名片
5G时代,各种营销都在走数字化的路子,VR数字工厂用VR赋能工厂数字升级,将企业环境、工厂生产、产品研发、质检运输等流程,无死角720度的展示在客户面前,不仅可以提升自身企业的实力,还可以提高客户的信任感。…...
uniapp封装组件,选中后右上角显示对号√样式(通过css实现)
效果: 一、组件封装 1、在项目根目录下创建components文件夹,自定义组件名称,我定义的是xc-button 2、封装组件代码 <template><view class"handle-btn"><view :class"handleIdCode 1 ? select : unSelec…...
【Linux】C语言执行shell指令
在C语言中执行Shell指令 在C语言中,有几种方法可以执行Shell指令: 1. 使用system()函数 这是最简单的方法,包含在stdlib.h头文件中: #include <stdlib.h>int main() {system("ls -l"); // 执行ls -l命令retu…...
Python实现prophet 理论及参数优化
文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候,写过一篇简单实现,后期随着对该模型的深入研究,本次记录涉及到prophet 的公式以及参数调优,从公式可以更直观…...
uniapp微信小程序视频实时流+pc端预览方案
方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度WebSocket图片帧定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐RTMP推流TRTC/即构SDK推流❌ 付费方案 (部分有免费额度&#x…...
C++ 求圆面积的程序(Program to find area of a circle)
给定半径r,求圆的面积。圆的面积应精确到小数点后5位。 例子: 输入:r 5 输出:78.53982 解释:由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982,因为我们只保留小数点后 5 位数字。 输…...
第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词
Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵,其中每行,每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid,其中有多少个 3 3 的 “幻方” 子矩阵&am…...
MySQL账号权限管理指南:安全创建账户与精细授权技巧
在MySQL数据库管理中,合理创建用户账号并分配精确权限是保障数据安全的核心环节。直接使用root账号进行所有操作不仅危险且难以审计操作行为。今天我们来全面解析MySQL账号创建与权限分配的专业方法。 一、为何需要创建独立账号? 最小权限原则…...
服务器--宝塔命令
一、宝塔面板安装命令 ⚠️ 必须使用 root 用户 或 sudo 权限执行! sudo su - 1. CentOS 系统: yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh2. Ubuntu / Debian 系统…...
HDFS分布式存储 zookeeper
hadoop介绍 狭义上hadoop是指apache的一款开源软件 用java语言实现开源框架,允许使用简单的变成模型跨计算机对大型集群进行分布式处理(1.海量的数据存储 2.海量数据的计算)Hadoop核心组件 hdfs(分布式文件存储系统)&a…...
tauri项目,如何在rust端读取电脑环境变量
如果想在前端通过调用来获取环境变量的值,可以通过标准的依赖: std::env::var(name).ok() 想在前端通过调用来获取,可以写一个command函数: #[tauri::command] pub fn get_env_var(name: String) -> Result<String, Stri…...
rknn toolkit2搭建和推理
安装Miniconda Miniconda - Anaconda Miniconda 选择一个 新的 版本 ,不用和RKNN的python版本保持一致 使用 ./xxx.sh进行安装 下面配置一下载源 # 清华大学源(最常用) conda config --add channels https://mirrors.tuna.tsinghua.edu.cn…...
