前置资源GitHub: SwiftUI-WeChatDemo 第零章:用 SwiftUI 5天组装一个微信 第二章:剖析:如何用 SwiftUI 5天组装一个微信 —— 通讯录发现我篇 ![]() 整体结构![]() UI 部分的代码分布如上图所示,App 的主入口类为 WeChatDemoApp。 该类在创建新的 SwiftUI 项目时会自动生成,这里只需要将其展示内容的部分变更为第一级容器:TabContainer,该容器包括微信的四个页面,分别为 聊天界面部分、通讯录、发现、我,这四个部分的主 UI 视图分布如上图标示,由各自的分级文件夹装载,并统合到主目录 UI 下面。 与 UI 目录同级目录有:
UI 层级示意图谱:
第一级容器:TabContainerApp 所引入的第一级视图容器,使用的是 TabView,通过自定义结构体 TabContainer 将其包裹封装,实现代码分离: ![]() TabView 需要提供一个参数 selection,类型可随意自定义,用于告诉 TabView 在初始化后应该展示哪个 Tab,以及当用户选择其他 Tab 时,将其反馈、存储到该变量中。 此处用于 selection 的类型为自定义枚举: 传递给 selection 的变量需要声明为
其他如 Picker 等可提供用户 选择 能力的 UI,也都需要与一个 selection 变量进行绑定。 在 TabView 下面按序放置 4 个 View 视图,代表提供了 4 个 Tab 的界面,每个 Tab 视图的结构如下:
为了实现 Tab 按钮在激活・非激活状态下展示不同的图标(实心与空心),此处通过一个函数动态返回对应图标素材名字,传递到 Image 中,该函数接受一个指向当前正在选择的 Tab 的 selecting 参数,当
最后通过对 TabView 整体添加 Tab 1:聊天列表![]() 整一个 Tab 视图的根容器是一个 NavigationView,该部件提供了标准的 Toolbar、子页面跳转、返回等功能。 在 NavigationView 之中包裹的是真正的视图布局。 视图布局三剑客
(※ 这三个容器默认带有元素间距,可使用参数 在界面上,排除由 NavigationView 提供的 Toolbar 部分,视图由一个自定义的搜索栏 SearchBar,以及一个列表组成,通过 VStack 纵向排列布局。 列表部分可使用 SwitchUI 中专用的循环体 ForEach,实现一个根据数据数组元素数量、内容,不断添加 UI 元素的循环结构。(也可以考虑使用 List,但 List 带有比较强烈的样式倾向,不如 ForEach 容易控制) ※ 不能使用普通的 for 语法 ForEach 要求提供的数据类型遵循 Hashable 协议,同样 id 也要求遵循 Hashable,以便其识别、追踪每次循环所生成的 View,在数据发生变化时能够在正确位置插入、删除、修改对应的 UI。
此处 上述代码中,ForEach 根据 Chat 数组,生成聊天列表中每一个聊天记录项的 View,该 View 由 NavigationLink 所包裹,当用户点击该 View 时,将自动通过外层的 NavigationView 进行页面导航,跳转至此处指定的 destination 指向的 View(作为子页布局展示)。 同时,NavigationView 会为该子页面添加一个 Toolbar,以及一个用于返回的箭头按钮。 而 这些部分描述当前界面的顶部的 Title 展示形式、标题文本、Toolbar构成等。 需要注意的是这部分描述需要在 NavigationView 内的 View 上书写,而不是附加在 NavigationView 自身上。 聊天列表记录 ItemView![]() 聊天列表上的记录 Item View: ![]() Spacer 是一个可以依据剩余可用空间自动填充扩展的结构,用于自动撑开两个 View 或将容器撑满整个屏幕等。 头像部分,显示一个图片素材,指定其可缩放至指定 frame 大小,并追加圆角角度:
最后的 ![]() 该函数通过为 View 添加一个圆形的 overlay,指定放置在右上角并偏移一半尺寸到 View 外侧,来实现信息红点功能。 函数返回类型指定为
![]() 分割线可使用 Divider() 实现。 聊天窗口![]() 数据部分
界面主体由两大部分组成:
ChatFlowView 根据由 ViewModel 所托管的消息记录 messageFlow 数组数据,使用 ForEach 生成每一条对话消息: ![]() ScrollViewReader 用于提供对 ScrollView 的滑动控制能力,在不需要程序自动控制 ScrollView 滑动时,则不需要使用该部件。 ChatMessageView 表示头像+信息组成的一条聊天信息,使用一个 ChatMessage 类型的数据进行初始化,数据包含聊天信息内容的 String,以及发送方向、头像。 ![]() 其中的 MessageText 基本上是一个普通 Text,展示 ChatMessage 中的信息内容,并根据其中的发送方向(左侧或是右侧)决定 Text 的底色。 在外层 HStack 上通过改写局部环境变量 layoutDirection,来实现布局排序方向变化。 免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |