最近在学习 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
1 - 在 SwiftUI 中,如果需要操控图画的巨细,则有必要先调用resizable润饰
2- 设置图画巨细
3 - 设置圆角巨细,四个角的巨细都相同
由于布局是横向的,所以咱们在外层运用HStack包裹起来,然后增加联系人姓名和最终发音讯时刻。
HStack { // 头像 HStack { Text("女神") .font(.body) // 1 Spacer() Text("下午 2:55") .font(.caption) .foregroundColor(Color.gray.opacity(0.5)) // 2 } }
1 - 运用 font 润饰字体,这儿运用了苹果供给的标准字体,苹果还供给了 largeTitle, title, headline, subheadline, body, callout, footnote, caption。
2 - 运用 foregroundColor 润饰字体色彩,由于 gray 的灰色仍是太黑了,所以这儿又运用了 opacity 去润饰透明度为50%,使它显得更淡一点。
姓名下方显现的是是最终发送或接收的音讯内容,因而咱们在外层运用 VStack 包裹起来。
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包裹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 动态图效果。
好了,这篇文章就到这儿,篇幅有点长了。不过没关系,咱们来总结一下关键点:
本文转载于:https://blog.csdn.net/dafengit/article/details/106073709