博观而约取,厚积而薄发。这篇文章主要讲述SwiftUI - 一起来仿写微信APP之一首页列表视图相关的知识,希望能为你提供帮助。
最近在学习 SwiftUI ,我一般都是先去学习界面布局,所以就想着仿写一下经常使用的软件的界面,所以先拿微信开刀。因为不想一次性发太多的内容,所以只好将主题分解,一部分一部分地去讲,接下来我们一起来学习吧。简介最近在学习 SwiftUI ,我一般都是先去学习界面布局,所以就想着仿写一下经常使用的软件的界面,所以先拿微信开刀。因为不想一次性发太多的内容,所以只好将主题分解,一部分一部分地去讲,接下来我们一起来学习吧。
如果你尝试过使用 SwiftUI 编写界面,你会发现是如此地舒心,我已深深地爱上了它。当然它的坑并不少,毕竟才刚出来,最低支持系统是 ios13,估计还得等个几年才会慢慢在公司里使用上吧。但是这并不妨碍我们的学习。
在这篇文章里,我会一步一步编写微信的首页列表视图,一步一步将代码呈现上来,并仔细地讲解,我相信你们都可以看懂的,先来看看效果图。
文章图片
很简单吧?是很简单,但是在编写的时候还是有些技巧在里面,毕竟,简单才不容易劝退嘛。在开始前先讲一下这篇文章将会用到的一些布局与组件,先给大家一个印象,方便后面的阅读理解。
HStack - 水平布局
VStack - 垂直布局
Text - 文本控件
Spacer - 扩展空间,使容器填满布局空间
Image - 图像控件
List - 列表控件
Divider - 分隔线控件
工作环境Xcode - Version 11.3.1 (11C504)
Swift - version 5.1.3 (swiftlang-1100.0.282.1 clang-1100.0.33.15)
开始编写代码 编写列表行
我们来先把头像添加进来。
Image("1")
.resizable() // 1
.frame(width: 46, height: 46) // 2
.cornerRadius(6)// 3
【SwiftUI - 一起来仿写微信APP之一首页列表视图】1 - 在 SwiftUI 中,如果需要控制图像的大小,则必须先调用resizable修饰因为布局是横向的,所以我们在外层使用
2- 设置图像大小
3 - 设置圆角大小,四个角的大小都相同
HStack
包裹起来,然后添加联系人名字和最后发消息时间。HStack {
// 头像HStack {
Text("女神")
.font(.body) // 1Spacer()Text("下午 2:55")
.font(.caption)
.foregroundColor(Color.gray.opacity(0.5)) // 2
}
}
1 - 使用 font 修饰字体,这里使用了苹果提供的标准字体,苹果还提供了 largeTitle, title, headline, subheadline, body, callout, footnote, caption。名字下方显示的是是最后发送或接收的消息内容,因此我们在外层使用 VStack 包裹起来。
2 - 使用 foregroundColor 修饰字体颜色,因为 gray 的灰色还是太黑了,所以这里又使用了 opacity 去修饰透明度为50%,使它显得更淡一点。
VStack(alignment: .leading, spacing: 6) { // 1
// 名称和时间Text("对不起,你是个好人")
.font(.callout)
.foregroundColor(Color.gray)
}
// 1 - 设定现在样子已经出来了,我们先预览下效果。VStack
里子控件居左对齐,默认是居中对齐。再设定子控件的间隙为 6 个像素,这样比较符合微信上面的设计。
文章图片
我们给最外层的
HStack
增加padding
,使它更美观一些,参数填写.all
代表四周都需要边框。经过我的眼力观察,它的默认是 16px 的样子。HStack {
// 头像、名称、时间、消息内容
}
.padding(.all)
有了间距,好看多了。
文章图片
接下来创建一个视图,它负责装载行视图,起名为
GCMainRow
。struct GCMainRow: View {
var body: some View {
HStack {
Image("1")
.resizable()
.frame(width: 46, height: 46)
.cornerRadius(6)VStack(alignment: .leading, spacing: 6) {
HStack {
Text("女神")
.font(.body)Spacer()Text("下午 2:55")
.font(.caption)
.foregroundColor(Color.gray.opacity(0.5))
}
Text("对不起,你是个好人")
.font(.callout)
.foregroundColor(Color.gray)
}
}
.padding(.all)
}
}
然后在
ContentView
改为调用GCMainRow()
,这样代码就好看很多了。struct ContentView: View {
var body: some View {
GCMainRow()
}
}
编写列表 List
好了,现在让我们来编写列表视图吧。我们在最外层使用
List
包裹GCMainRow
,循环 20 个视图,数据多点才可以让我们滚动。List(0 ..<
20) { _ in // 1
GCMainRow()
}
1 - 因为我们不需要用到循环的一些数据,所以我们使用 _ 去忽略它。
List
控件默认的都会有边距,下图黄色是GCMainRow
的大小,可以看得出来旁边有空白的填充,这对我们当前的设计来说不太友好,因此我们需要想办法去掉这些边距填充。文章图片
List
提供了listRowInsets
来控制行的边距(上下左右),我们来试着使用一下。List(0 ..<
20) { item in
GCMainRow()
.listRowInsets(EdgeInsets())
}
我们发现,这样写是没有作用的,
listRowInsets
的生效条件是“不能直接在List
中使用,需要配合For Each
语句才能生效”,我们再修改一下代码。List {
ForEach(0 ..<
20) { item in
GCMainRow()
.listRowInsets(EdgeInsets())
}
}
好了,这次生效了,这就是我们要的结果。
文章图片
自定义分隔线
我们仔细观察一下分隔线,在微信里分隔线是左对齐在名称和消息内容的,所以我们需要把现有的分隔线隐藏掉,然后再实现它。
在这里讲解一下,
List
是基于UITableView
去实现的,这意味着我们可以通过appearance
全局修改它的所有属性,正如我们现在需要取消它默认的分隔线,将separatorStyle
设置为.none
即可。init() {
UITableView.appearance().separatorStyle = .none
}
因为分隔线是贴着右边缘的,所以我们需要在包裹着名称、时间、消息内容的
VStack
外层再包裹一层VStack
,在其中再添加分隔线Divider
,并将里层的VStack
设定右边距,最后将最外层的HStack
的padding
改为上和左边距。是不是听得有点懵?没关系,看看代码就很容易理解了。HStack(alignment: .top) { // edit
// 头像
VStack { // new
VStack(alignment: .leading, spacing: 6) {
// 名称、时间、消息内容
}
.padding(.trailing) // new
Divider() // new
}
}
.padding(.top) // edit
.padding(.leading) // edit
我们现在来看一下效果。
文章图片
未读消息小红点
未读消息在头像的右上方,小红点的中心点是位于头像的右上顶端。我们可以使用
overlay
叠加一个视图,来制作小红点吧。Image("1")
// ...
.overlay(
Color.red // 1
.frame(width: 16, height: 16)
.cornerRadius(8)
.offset(x: 23, y: -23) // 2
)
// 1 - Color 本身也是一个视图组件,这是官方的定义 @available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *) extension Color : View { }接下来是未读数量,和上面的相似,在
// 2 - 设定视图的偏移量,那么23是怎样得出来的呢?很简单,因为默认的overlay
视图是位于父视图的中心,那么我们要将它放置在右上角,那么只需要宽高都除以2就可以了,那么这里的结果就是,x轴增加23px,y轴减少23px
Color
视图上利用overlay
叠加Text
视图就可以了。Color.red
.overlay( // 1
Text("1")
.font(.caption)
.foregroundColor(.white)
)
.frame(width: 16, height: 16)
.cornerRadius(8)
.offset(x: 23, y: -23)
// 1- 值得注意的是,因为文本也是需要偏移到右上角的,所以必须放在前面,不然它默认就是居中的至此,代码演示结束,预览一下静态图,文章开头有 gif 动态图效果。
文章图片
总结好了,这篇文章就到这里,篇幅有点长了。不过没关系,我们来总结一下关键点:
List
默认是有行边距的,要取消或修改它的行边距,我们必须通过For Each
再配合上listRowInsets
才能实现。List
是基于UITableView
去实现的,这意味着我们可以通过appearance
全局修改它的所有属性。- 使用
overlay
可以给视图叠加一个视图。
GCWechatList
,有需要的朋友可以去下载运行一下,当然你也可以跟着文章去做一遍,这样更有利于你掌握此方面的知识。文章篇幅有点长,虽然教的东西也挺简单,但概述得比较详细。任何东西都是先从简单入手的,才不会造成劝退不是吗?哈哈,此文章针对于新手而言还是很友好的,对于已经会的人来讲就可能废话有点多了,如果必须要喷,请轻喷,我比较玻璃心。
如果本文章对你有帮助,请关注我,你的关注就是我后续写文章的动力,下期会更精彩噢!
关于作者博文作者:GarveyCalvin
微博:https://weibo.com/feiyueharia
博客园:https://www.cnblogs.com/GarveyCalvin
本文版权归作者,欢迎转载,但必须保留此段声明,并给出原文链接,谢谢合作!
公众号
作者第一次运营公众号,请你们一定要关注我的公众号,给我点动力,后期主要运营公众号为主。这是第二篇发布的文章,需要你们的支持,谢谢你们!
文章图片
QQ群
一起讨论 SwiftUI,群主喜欢看热闹,当吃瓜人员。进来时填写你在哪里看到此文章的,并介绍下自己,一句话就行。
文章图片
推荐阅读
- H5活动全屏滚动页面在安卓智能电视TV调试
- ESA2GJK1DH1K基础篇: APP使用SmartConfig绑定Wi-Fi 设备并通过MQTT控制设备(V1.0)(AT+TCP非透传指令)
- 踩坑之uni打包APP后全局注册组件 的样式未生效
- NETAPP 基本操作
- Power Apps课件写作历程
- 合约交易系统开发技术,交易所系统开发app
- Failed to load ApplicationContext
- APP内嵌腾讯X5内核webview测试方法
- Overlapped Model