当前位置: 首页 > news >正文

Android笔记(十):结合Navigation组件实现Compose界面的导航

在Android笔记(七)搭建Android JetPack Compose组件中Scaffold脚手架 一文中通过定义一个导航的函数来实现不同界面的切换。如果没有传递任何参数,这样的导航处理也是可以接受的,处理方式也非常简单。但是,如果考虑到不同Compose界面的切换且传递参数,或者有更复杂地处理情况,就可以考虑使用导航组件Navigation来实现。

一、导航组件的配置

新建一个项目模块,在模块对应的build.gradle.kt中中增加依赖:

implementation(“androidx.navigation:navigation-compose:2.7.4”)

注意:采用2.7.4版本,必须设置android的目标SDK和编译SDK为34版本

在本笔记中通过一个展示机器人相关信息来说明导航组件的实现。为此,分别定义实体类和不同的界面。

二、定义机器人实体类

@Parcelize
data class Robot(val name:String,val description:String,val icon:Int):Parcelable

三、定义要显示的主要界面

1.定义机器人列表界面

在这里插入图片描述
图1 显示机器人列表
(1)定义单独一行机器人卡片
注意:
因为使用了ConstraintLayout布局,需要在项目模块的build.gradle.kt中增加依赖:

implementation(“androidx.constraintlayout:constraintlayout-compose:1.0.1”)

具体的代码如下:

//定义单独的机器人单独一行的卡片
@Composable
fun RobotCard(robot:Robot){Card(modifier = Modifier.fillMaxWidth().wrapContentHeight().padding(5.dp),colors = CardDefaults.elevatedCardColors(contentColor = Color.Green, containerColor = Color.Blue),elevation = CardDefaults.elevatedCardElevation(defaultElevation = 3.dp)){ConstraintLayout(modifier= Modifier.fillMaxWidth()) {val (imageRef,nameRef,descRef) = remember{createRefs()}val vguideLine = createGuidelineFromStart(0.3f)val hguideLine = createGuidelineFromTop(0.4f)Image(modifier= Modifier.constrainAs(imageRef) {top.linkTo(parent.top)bottom.linkTo(parent.bottom)start.linkTo(parent.start)end.linkTo(vguideLine)}.clickable {},painter = painterResource(id = robot.icon), contentDescription = robot.name )Text(modifier = Modifier.constrainAs(nameRef){top.linkTo(parent.top)bottom.linkTo(hguideLine)start.linkTo(vguideLine)end.linkTo(parent.end)},text = robot.name,fontSize = 18.sp)Text(modifier = Modifier.constrainAs(descRef){top.linkTo(hguideLine)bottom.linkTo(parent.bottom)start.linkTo(vguideLine)end.linkTo(parent.end)},text = robot.description,fontSize = 20.sp)}}
}

(2)定义组合多个机器人卡片生成机器人列表界面

@Preview
@Composable
fun RobotListScreen(){val robots = mutableListOf<Robot>()for(i in 1..10)robots.add(Robot("机器人${i}号","机器人${i}号的世界",android.R.mipmap.sym_def_app_icon))LazyColumn{items(robots){robot:Robot->RobotCard(robot)}}
}

2.定义机器人单独显示界面

在这里插入图片描述
图2

@Composable
fun RobotDetailScreen(){val robot = Robot("机器人测试","机器人世界",android.R.mipmap.sym_def_app_icon)Box(contentAlignment = Alignment.Center,modifier= Modifier.fillMaxSize()){Column(horizontalAlignment = Alignment.CenterHorizontally){Text(robot.name,fontSize = 28.sp)Image(modifier = Modifier.size(100.dp,100.dp),painter = painterResource(id = robot.icon),contentDescription = robot.name)Text(robot.description,fontSize=24.sp,maxLines = 5)Button(onClick = {}){Text("跳转APP说明")}}}
}

3.定义应用介绍界面

在这里插入图片描述
图3

@Composable
fun RobotAppScreen(){Box(contentAlignment = Alignment.Center,modifier = Modifier.fillMaxSize()){Column(modifier = Modifier.fillMaxWidth(),horizontalAlignment = Alignment.CenterHorizontally){Text("RobotApp是一个简单显示机器人信息的应用",fontSize = 28.sp, maxLines = 5)Button(modifier = Modifier.wrapContentSize(),onClick = {}){Text("返回",fontSize = 20.sp)}}}
}

四.定义界面的密封类

定义关于界面的密封类,在密封类对上述的三个界面基本特征如导航路径route、导航使用的标题title以及导航使用的图表icon进行分别定义,代码如下所示:

sealed class Screen(val route:String,val title:String,val icon: ImageVector){object RobotListPage:Screen(route="robotlist",title="机器人列表",icon= Icons.Filled.List)object RobotPage:Screen(route = "robot",title="机器人",icon = Icons.Filled.Face)object AppPage:Screen(route="aboutApp",title = "APP介绍",icon = Icons.Filled.Info)
}

在此前提的基础上,定义一个列表,将三个核心显示的界面定义在列表中,如下所示:

val screens = listOf(Screen.RobotListPage,Screen.RobotPage,Screen.AppPage)

五、定义导航图

在导航图中需要确定导航图中宿主和要切换的界面。要让定义好的导航图发挥作用

(1)需要在活动中指定导航宿主NavHost,通过指定NavHost表示导航宿主,用于定义用户界面的屏幕目标的预留位置;
(2) 需要利用NavController导航控件实现导航。
val navController = rememberNavController()

值得注意的是:NavController可以调用navigate()函数来实现导航,常见有三种形式:

//在导航到route的目的地之前,要将路径home之前所有的内容退出后退堆栈
navController.navigate(“route”){
popUpTo(“home”)
}

//在导航到route的目的地之前,要将包括路径home之前所有的内容退出后退堆栈
navController.navigate(“route”){
popUpTo(“home”) {inclusive = true}
}

//当没有导航到route时,才导航到route路径后退堆栈只有一个route导航路径
navController.navigate(“route”){
launchSingleTop = true
}

在下列定义了一个简单的导航图,代码如下:

@Composable
fun NavigationGraphScreen(navController:NavHostController,startDestination:String){NavHost(navController = navController,startDestination=Screen.RobotListPage.route){composable(Screen.RobotListPage.route){RobotListScreen()}composable(Screen.RobotPage.route){RobotDetailScreen()}composable(Screen.AppPage.route){RobotAppScreen()}}
}

六、在脚手架结构的底部导航栏中使用导航图

在这里插入图片描述

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun MainScreen(){val currentScreen: MutableState<Screen> = remember{mutableStateOf(Screen.RobotListPage)}val navController = rememberNavController()Scaffold(topBar={TopAppBar(title = {Text(text = currentScreen.value.title )},navigationIcon = {Icon(imageVector = currentScreen.value.icon,contentDescription = null)})},bottomBar = {BottomAppBar {screens.forEach {screen:Screen->NavigationBarItem(selected = screen.route == currentScreen.value.route ,onClick = {currentScreen.value = screennavController.navigate(screen.route){popUpTo(Screen.RobotListPage.route)launchSingleTop}},icon = {Icon(imageVector = screen.icon,contentDescription = screen.title)})}}},content={it:PaddingValues->Box(modifier = Modifier.padding(it)){NavigationGraphScreen(navController = navController,startDestination =Screen.RobotListPage.route )}})
}

注意:
(1)导航navController.navigate(screen.route)中设置popUpTo(Screen.RobotListPage.route),表示导航到screen.route的界面会将Screen.RobotListPage.route之前(不包含)的所有其他界面退出返回堆栈BackStack。可以观察到,通过底部导航栏,如上图依次从左到右访问三个界面,在最后一个界面APP介绍界面时,选择手机模拟器的Back键,会直接返回第一个界面RobotListPage.route路径指向的界面。
(2)在脚手架Scaffold的content属性设置核心显示内容为导航图NavigationGraphScreen

七、实现导航传递参数

在上述的运行效果中,可以发现如下不足:

从机器人列表Screen.RobotListPage.route跳转到单个机器人界面Screen.RobotPage.route路径时,只能固定的显示机器人测试信息,显然不合实际情况;

解决之道:就是在不同导航中设置参数传递。

(1)发送方:
navController.navigate(“route/${参数}”)

(2)数据接受方:
在导航图中指定接受参数名和参数类型

  composable(route = "route/{参数名}",arguments = listOf(arguments = listOf(navArgument(“参数名"){type =NavType.StringType})){val data = it.arguments?.getString(“参数名”)?:"默认值"}

在传递数据如果是基本数据类型比较容易,但是对于自定义的数据类,则可以采用转换的方式实现数据传递:
(1)数据发送方,把自定义类型的对象通过Gson库转换成字符串;
(2)数据接受方,将接受的数据字符串通过Gson库再转换成自定义类型的对象
为了使用Gson库,需要在模块的build.gradle.kt中增加依赖,如下所示:

implementation(“com.google.code.gson:gson:2.10.1”)

1.数据发送方

将机器人列表界面RobotListScreen作为数据的发送方,每次点击列表的图标,则传递数据到下一个界面RobotDetailScreen;由于点击实际的图标定义在RobotCard组合项中,因此,为RobotCard定义的图片内容增加一个点击处理的功能;因为要实现导航,因此RobotListScreen和RobotCard都需要传递NavController参数,下面是修改的代码:

@Composable
fun RobotCard(navController:NavController,robot:Robot){Card(modifier = Modifier.fillMaxWidth().wrapContentHeight().padding(5.dp),colors = CardDefaults.elevatedCardColors(contentColor = Color.Green, containerColor = Color.Blue),elevation = CardDefaults.elevatedCardElevation(defaultElevation = 3.dp)){ConstraintLayout(modifier= Modifier.fillMaxWidth()) {val (imageRef,nameRef,descRef) = remember{createRefs()}val vguideLine = createGuidelineFromStart(0.3f)val hguideLine = createGuidelineFromTop(0.4f)Image(modifier= Modifier.constrainAs(imageRef) {top.linkTo(parent.top)bottom.linkTo(parent.bottom)start.linkTo(parent.start)end.linkTo(vguideLine)}.clickable {val robotStr = Gson().toJson(robot)navController.navigate(Screen.RobotPage.route+"/${robotStr}")},painter = painterResource(id = robot.icon), contentDescription = robot.name )Text(modifier = Modifier.constrainAs(nameRef){top.linkTo(parent.top)bottom.linkTo(hguideLine)start.linkTo(vguideLine)end.linkTo(parent.end)},text = robot.name,fontSize = 18.sp)Text(modifier = Modifier.constrainAs(descRef){top.linkTo(hguideLine)bottom.linkTo(parent.bottom)start.linkTo(vguideLine)end.linkTo(parent.end)},text = robot.description,fontSize = 20.sp)}}
}
@Composable
fun RobotListScreen(navController: NavController){val robots = mutableListOf<Robot>()for(i in 1..10)robots.add(Robot("机器人${i}号","机器人${i}号的世界",android.R.mipmap.sym_def_app_icon))LazyColumn{items(robots){robot:Robot->RobotCard(navController,robot)}}
}

2.数据接受方

在这个应用中RobotDetailScreen是数据的接受方,因此需要修改导航图,在导航图中增加接受数据的处理,代码如下:

@Composable
fun NavigationGraphScreen(navController:NavHostController,startDestination:String){NavHost(navController = navController,startDestination=Screen.RobotListPage.route){composable(Screen.RobotListPage.route){RobotListScreen(navController = navController)}composable(Screen.RobotPage.route+"/{robot}", arguments = listOf(navArgument("robot"){type = NavType.StringType})){val robotStr = it.arguments?.getString("robot")val robot = Gson().fromJson(robotStr,Robot::class.java)RobotDetailScreen(robot)}composable(Screen.AppPage.route){RobotAppScreen()}}
}

相应的RobotDetailScreen也需要修改,增加一个Robot参数,可以对具体的Robot对象进行显示,代码修改如下:

@Composable
fun RobotDetailScreen(robot:Robot){Box(contentAlignment = Alignment.Center,modifier= Modifier.fillMaxSize()){Column(horizontalAlignment = Alignment.CenterHorizontally){Text(robot.name,fontSize = 28.sp)Image(modifier = Modifier.size(100.dp,100.dp),painter = painterResource(id = robot.icon),contentDescription = robot.name)Text(robot.description,fontSize=24.sp,maxLines = 5)Button(onClick = {}){Text("跳转APP说明")}}}
}

3.调整底部栏导航处理

因为增加了数据发送和接受的处理,相应的针对脚手架的底部栏导航的处理也需要调整,需要增加发送和接受数据的处理:

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun MainScreen(){val currentScreen: MutableState<Screen> = remember{mutableStateOf(Screen.RobotListPage)}val currentRobot:MutableState<Robot> = remember{mutableStateOf(Robot("机器人${1}号","机器人${1}号的世界",android.R.mipmap.sym_def_app_icon))}val navController = rememberNavController()Scaffold(topBar={TopAppBar(title = {Text(text = currentScreen.value.title )},navigationIcon = {Icon(imageVector = currentScreen.value.icon,contentDescription = null)})},bottomBar = {BottomAppBar {screens.forEach {screen:Screen->NavigationBarItem(selected = screen.route == currentScreen.value.route ,onClick = {currentScreen.value = screenif(screen.route == Screen.RobotPage.route){val robotStr = Gson().toJson(currentRobot.value)navController.navigate(Screen.RobotPage.route+"/${robotStr}"){popUpTo(Screen.RobotListPage.route)}}else {navController.navigate(screen.route) {popUpTo(Screen.RobotListPage.route)launchSingleTop}}},icon = {Icon(imageVector = screen.icon,contentDescription = screen.title)})}}},content={it:PaddingValues->Box(modifier = Modifier.padding(it)){NavigationGraphScreen(navController = navController,startDestination =Screen.RobotListPage.route )}})
}

在MainScreen中增加判断是否跳转到RobotDetailScreen界面路径的判断,如果是,就增加参数传递的处理。在上述代码中,增加了一个状态currentRobot来记住当前要显示的机器人对象。这里的处理并不是非常好,因为并没有提供处理修改currentRobot的状态值的操作。最好的方式,是将这个状态值提升,并通过机器人列表界面点击图片达到修改这个状态值的目的。在此处,就不再修改了,由读者自行调整。

相关文章:

Android笔记(十):结合Navigation组件实现Compose界面的导航

在Android笔记&#xff08;七&#xff09;搭建Android JetPack Compose组件中Scaffold脚手架 一文中通过定义一个导航的函数来实现不同界面的切换。如果没有传递任何参数&#xff0c;这样的导航处理也是可以接受的&#xff0c;处理方式也非常简单。但是&#xff0c;如果考虑到不…...

linux内核tcp配置--断网后连接卡住

通过隐藏通信应用程序中的临时网络中断&#xff0c;TCP 可以在偶尔不可靠的网络上提供可靠的通信。在通知发件人任何问题之前&#xff0c;您的操作系统将多次重发丢失的消息。大多数 Linux 发行版默认将任何丢失的数据包重传 15 次。重新传输以指数方式回退&#xff0c;因此这 …...

Apache Pulsar 在腾讯云上的最佳实践

导语 由 StreamNative 主办的 Pulsar Meetup Beijing 2023 在2023年10月14日完美落幕&#xff0c;本次活动大咖云集&#xff0c;来自腾讯、滴滴、华为、智联招聘、RisingWave 和 StreamNative 的行业专家们一起&#xff0c;深入探讨 Pulsar 在生产环境中的最佳应用实践&#x…...

VMware 虚拟机安装 CentOS 7

CentOS 7 1. 下载CentOS 7 iso镜像 Index of /centos/7.9.2009/isos/x86_64/ 2. Vmware安装CentOS 7 安装教程&#xff1a; 超详细VMware CentOS7(最小安装)安装教程_虚拟机最小化安装-CSDN博客 【精选】VMware 安装 Centos7 详细过程_vm虚拟机安装centos7_expectation Fu…...

UnityAI——个体AI角色的操控行为脚本

注&#xff1a;本文用到了前文所用的基类UnityAI——操控行为编程的主要基类-CSDN博客 在一些游戏中&#xff0c;可能会遇到想让AI角色追逐或者避开玩家的情况。 如在飞机模拟游戏中&#xff0c;让导弹跟踪和进攻玩家或玩家的飞行器。这种情况下&#xff0c;可以运用本节介绍…...

ssh登录界面变成vim提示,进不去系统

是ubuntu系统 使用远程连接root&#xff0c;进去后发现界面变成vim编辑器的介绍界面了 使用普通用户登录 查询用户的登录shell是不是有问题 sudo vim /etc/passwd 发现用户shell变成了vim编辑器 修改为/bin/bash就可以正常登录了 重新登录测试就正常了...

虹科示波器 | 汽车免拆检修 | 2012 款上汽大众帕萨特车 发动机偶尔无法起动

一、故障现象 一辆2012款上汽大众帕萨特车&#xff0c;搭载CFB发动机&#xff0c;累计行驶里程约为12万km。车主反映&#xff0c;将点火开关置于起动挡&#xff0c;偶尔只能听到“咔哒”一声&#xff0c;起动机没有反应&#xff0c;类似蓄电池亏电时起动发动机的现象。为此&…...

UE5.0.3版本 像素流送 Pixel Streaming

目录 0 引言1 准备工作1.1 下载Node.js1.2 下载 PixelStreaming&#xff08;非必须&#xff09; 2 快速入门2.1 打包工程2.2 启动信令服务器2.3 启动工程2.4 打开网页 3 总结 &#x1f64b;‍♂️ 作者&#xff1a;海码007&#x1f4dc; 专栏&#xff1a;UE虚幻引擎专栏&#x…...

BetterDisplay Pro v1.4.15(显示器管理管理软件)

BetterDisplay Pro是一款屏幕显示优化工具&#xff0c;可用于Windows和Mac操作系统。它可以帮助用户调整屏幕的亮度、对比度、色彩等参数&#xff0c;以获得更好的视觉体验。此外&#xff0c;BetterDisplay Pro还提供了一些额外的功能&#xff0c;如屏幕分割、窗口管理、快捷键…...

蓝桥等考C++组别四级006

第一部分&#xff1a;选择题 1、C L4 &#xff08;20分&#xff09; 以下选项中&#xff0c;不是逻辑运算符的选项是&#xff08; &#xff09;。 A.! B.|| C.&& D.< 正确答案&#xff1a;D 2、C L4 &#xff08;20分&#xff09; …...

app开发之后需要做什么

在完成app的开发之后&#xff0c;还有一系列的工作需要进行&#xff0c;以确保app的顺利上线和用户的良好体验。下面将从原理和详细介绍两个方面来介绍app开发之后需要做的工作。 一、原理介绍 1. 测试与调试&#xff1a;在app开发完成后&#xff0c;需要进行全面的测试与调试…...

某汽车金融企业:搭建SDLC安全体系,打造智慧金融服务样本

某汽车金融企业是国内头部汽车金融公司&#xff0c;已经为超过数百万名客户提供专业的汽车金融服务。该公司通过近几年的数字化创新&#xff0c;在提升客户体验、提高管理效率、降低经营成本等方面已具备很强的服务能力&#xff0c;让客户获得更方便、更快捷、更灵活的金融服务…...

iOS GCD(Grand Central Dispatch)

iOS 常用有三种线程管理方式&#xff0c;分别是 NSThread、GCD 与 NSOperation&#xff0c;现在我们先来了解一下其中的 GCD 串行与并行针对的是任务队列&#xff0c;而同步与异步&#xff0c;针对的则是线程。 Serial Queue Sync 序列执行同步 Serial Queue Async 序列执…...

Cross-Entropy Loss(多分类损失函数)

文章目录 1. 网络输出output&#xff1a;score2. Cross-Entropy Loss(多分类损失函数) 1. 网络输出output&#xff1a;score 2. Cross-Entropy Loss(多分类损失函数) 先用softmax function把score 变成 probabilities。再用交叉熵损失函数来进行Loss的计算...

TP858 3BSE018138R1 具有高性能CPU的工业PC技术

TP858 3BSE018138R1 具有高性能CPU的工业PC技术 为了充分利用新电脑的扩展图形功能&#xff0c;如DirectX&#xff0c;Beckhoff Automation重新设计了TwinCAT automation软件套件中的Scope工具。这为TwinCAT用户在灵活的软件环境中提供了一系列令人印象深刻的测量技术。改进的…...

Observability:使用 OpenTelemetry 手动检测 .NET 应用程序

作者&#xff1a;David Hope 在快节奏的软件开发领域&#xff0c;尤其是在云原生领域&#xff0c;DevOps 和 SRE 团队日益成为应用程序稳定性和增长的重要合作伙伴。 DevOps 工程师不断优化软件交付&#xff0c;而 SRE 团队则充当应用程序可靠性、可扩展性和顶级性能的管理者。…...

生产事故:redis主从的坑

一、问题 昨天生产redis缩容&#xff0c;3主3从模式&#xff0c;重启了服务器&#xff0c;重启了redis&#xff1b; 结果今天发现生产服务报错了&#xff0c;连接不上redis。 排查发现&#xff0c;由于生产后台只配置了一个redis的ip&#xff0c;本来是主redis的ip的&#x…...

maven本地仓库有依赖包,还会远程下载的问题

maven本地仓库有依赖包&#xff0c;还会远程下载的问题 传送门...

动作捕捉系统处理单点多点丢点问题

在动作捕捉数据采集过程中&#xff0c;丢点是经常容易遇到的问题。NOKOV度量动作捕捉软件可以方便地解决丢点问题。 一、单点丢点的处理 如下图&#xff0c;已经采集了动捕数据。 查看是否有丢点&#xff0c;在形影软件左上角选择“窗口分割”&#xff0c;在下方分割出一个空…...

FIFO 位宽转换

从8位转32位 module tb_fifo();reg clk,rst; initial beginclk0;forever #4.545 clk~clk; end initial beginrst1;#9.09 rst0; endreg [31:0] cnts; always (posedge clk or posedge rst) beginif(rst)begincnts < 32d0;endelsebegincnts < cnts 1b1;end endreg […...

电脑插入多块移动硬盘后经常出现卡顿和蓝屏

当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时&#xff0c;可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案&#xff1a; 1. 检查电源供电问题 问题原因&#xff1a;多块移动硬盘同时运行可能导致USB接口供电不足&#x…...

基于数字孪生的水厂可视化平台建设:架构与实践

分享大纲&#xff1a; 1、数字孪生水厂可视化平台建设背景 2、数字孪生水厂可视化平台建设架构 3、数字孪生水厂可视化平台建设成效 近几年&#xff0c;数字孪生水厂的建设开展的如火如荼。作为提升水厂管理效率、优化资源的调度手段&#xff0c;基于数字孪生的水厂可视化平台的…...

全志A40i android7.1 调试信息打印串口由uart0改为uart3

一&#xff0c;概述 1. 目的 将调试信息打印串口由uart0改为uart3。 2. 版本信息 Uboot版本&#xff1a;2014.07&#xff1b; Kernel版本&#xff1a;Linux-3.10&#xff1b; 二&#xff0c;Uboot 1. sys_config.fex改动 使能uart3(TX:PH00 RX:PH01)&#xff0c;并让boo…...

10-Oracle 23 ai Vector Search 概述和参数

一、Oracle AI Vector Search 概述 企业和个人都在尝试各种AI&#xff0c;使用客户端或是内部自己搭建集成大模型的终端&#xff0c;加速与大型语言模型&#xff08;LLM&#xff09;的结合&#xff0c;同时使用检索增强生成&#xff08;Retrieval Augmented Generation &#…...

Kafka入门-生产者

生产者 生产者发送流程&#xff1a; 延迟时间为0ms时&#xff0c;也就意味着每当有数据就会直接发送 异步发送API 异步发送和同步发送的不同在于&#xff1a;异步发送不需要等待结果&#xff0c;同步发送必须等待结果才能进行下一步发送。 普通异步发送 首先导入所需的k…...

vulnyx Blogger writeup

信息收集 arp-scan nmap 获取userFlag 上web看看 一个默认的页面&#xff0c;gobuster扫一下目录 可以看到扫出的目录中得到了一个有价值的目录/wordpress&#xff0c;说明目标所使用的cms是wordpress&#xff0c;访问http://192.168.43.213/wordpress/然后查看源码能看到 这…...

根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的----NTFS源代码分析--重要

根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的 第一部分&#xff1a; 0: kd> g Breakpoint 9 hit Ntfs!ReadIndexBuffer: f7173886 55 push ebp 0: kd> kc # 00 Ntfs!ReadIndexBuffer 01 Ntfs!FindFirstIndexEntry 02 Ntfs!NtfsUpda…...

什么是VR全景技术

VR全景技术&#xff0c;全称为虚拟现实全景技术&#xff0c;是通过计算机图像模拟生成三维空间中的虚拟世界&#xff0c;使用户能够在该虚拟世界中进行全方位、无死角的观察和交互的技术。VR全景技术模拟人在真实空间中的视觉体验&#xff0c;结合图文、3D、音视频等多媒体元素…...

篇章二 论坛系统——系统设计

目录 2.系统设计 2.1 技术选型 2.2 设计数据库结构 2.2.1 数据库实体 1. 数据库设计 1.1 数据库名: forum db 1.2 表的设计 1.3 编写SQL 2.系统设计 2.1 技术选型 2.2 设计数据库结构 2.2.1 数据库实体 通过需求分析获得概念类并结合业务实现过程中的技术需要&#x…...

uni-app学习笔记三十五--扩展组件的安装和使用

由于内置组件不能满足日常开发需要&#xff0c;uniapp官方也提供了众多的扩展组件供我们使用。由于不是内置组件&#xff0c;需要安装才能使用。 一、安装扩展插件 安装方法&#xff1a; 1.访问uniapp官方文档组件部分&#xff1a;组件使用的入门教程 | uni-app官网 点击左侧…...