在本章中,你将学会如何使用代码分组和代码复用的方式创建ScrollView滚动视图。
当然,也顺便复习下前面所学的Text、Image、Stack的用法。
以微信公众号文章为例,我们试试完成下面的UI设计图。
首先,先创建一个新项目,命名为SwiftUIScrollView。
预览后,我们可以看到模拟器效果。
我们准备一些图片,作为展示的素材。
在Assets.xcassets文件中,将本地的图片拖入到素材库中。
回到Content.swift文件中。
我们看到公众号文章是由图片Image和文字Text组成,而且是纵向排列。
我们先完成基础的单个卡片的代码。
首先是图片Image部分。
修饰符 | 名称 | 描述 |
.resizable() | 调节大小 | 调整图片显示的大小 |
aspectRatio() | 宽高比 | .aspectRatio(contentMode: .fit)让图片适应屏幕,并保持原有的宽高比 |
//图片 Image("book1") .resizable() .aspectRatio(contentMode: .fit)
在增加文字前,需要确定页面布局。
我们在Image上添加VStack纵向排列布局。
鼠标移动到Image的位置,键盘按住command键,单击鼠标,选择Embed in VStack。
在VStack内,我们给两部分代码写上注释,并把它们分隔开。
写注释的好处时,可以帮助我们快速定位代码块位置。
然后,我们补充上文字的代码。
当然,Text也要用修饰符美化样式。
修饰符 | 名称 | 描述 |
.font() | 字体 | .font(.system(size: 17)),系统17号字 |
.fontWeight() | 字重 | .fontWeight(.bold),加粗 |
.foregroundColor() | 字体颜色 | .foregroundColor(.black),系统黑色 |
.padding() | 边距 | 四周留开边距 |
// 文字 Text("你的能力是否能在全世界通用,如果不能,那么需求重新评估你的能力。") .font(.system(size: 17)) .fontWeight(.bold) .foregroundColor(.black) .padding()
看看还缺少什么?是的,圆角边框。
还记得我们的加边框用的什么方法吗?
没错,用的修饰符是.overlay(),我们需要给整个纵向视图加覆盖边框。
但由于.overlay()修饰符是“覆盖”上去的,而UI稿里,图片上面也是圆角的。
我们需要先给个圆角给VStack,再用.overlay(),不然图片上边的直角会突出。
VStack { // 图片 Image("book1") .resizable() .aspectRatio(contentMode: .fit) // 文字 Text("你的能力是否能在全世界通用,如果不能,那么需求重新评估你的能力。") .font(.system(size: 17)) .fontWeight(.bold) .foregroundColor(.black) .padding() } .cornerRadius(10) .overlay(RoundedRectangle(cornerRadius: 10) .stroke(Color(red: 150/255, green: 150/
简单说明下覆盖的内容。
修饰符 | 名称 | 描述 |
.overlay() | 覆盖 | 将内容覆盖在指定View上 |
RoundedRectangle | 圆角矩形 | 没啥好说的 |
cornerRadius | 圆角 | cornerRadius:10,10度的圆角 |
.stroke() | 描边 | 描边修饰 |
Color | 颜色 | 支持RGB定义颜色值 |
opacity | 透明度 | opacity: 0.1,透明度为10% |
lineWidth | 线宽 | lineWidth: 1,边框宽度为1 |
还是蛮多的,不过基本常用到的也就这几种。
那最后,我们还需要让整个VStack整体两边留些边距。
这里我们用到了.padding()边距修饰符,而且是它的高级用法。
.padding([.top, .horizontal]),顶部,水平居中,我们可以用“[]”将两个参数组合在一起。
这是边距的组合修饰规则,给顶部、左右都留了边距。
VStack { // 图片 Image("book1") .resizable() .aspectRatio(contentMode: .fit) // 文字 Text("你的能力是否能在全世界通用,如果不能,那么需求重新评估你的能力。") .font(.system(size: 17)) .fontWeight(.bold) .foregroundColor(.black) .padding() } .cornerRadius(10) .overlay(RoundedRectangle(cornerRadius: 10) .stroke(Color(red: 150/255, green: 150/255, blue: 150/255, opacity: 0.1), lineWidth: 1)) .padding([.top, .horizontal])
接下来,我们需要复制多几个样式一样的卡片。
我们注意到卡片都是纵向排列的,那么我们需要把原来的VStack外再包裹一层VStack。
记得要写注释哦。
然后再把卡片视图抽离出来变成子视图。
这样我们就不用复制那么多的代码。
之后,我们给子视图重命名,便于我们区分。
这里,我们命名为cardView。
接下来,我们在cardView定义好需要变动的变量。
我们看到图片Image,以及文字Text是不同的,其他都是一样的。
那么可以定义2个变量,分别为image,title。
然后把原来固定的内容替换成变量。
//卡片子视图 struct cardView: View { //定义变量 var image: String var title: String var body: some View { VStack { // 图片 Image(image) .resizable() .aspectRatio(contentMode: .fit) // 文字 Text(title) .font(.system(size: 17)) .fontWeight(.bold) .foregroundColor(.black) .padding() } .cornerRadius(10) .overlay(RoundedRectangle(cornerRadius: 10) .stroke(Color(red: 150/255, green: 150/255, blue: 150/255, opacity: 0.1), lineWidth: 1)) .padding([.top, .horizontal]) } }
报错了?
不用担心,是因为我们在子视图定义了变量,在主视图引用时,主视图不知道变量具体值是啥。
我们点击小红点,点击“Fix”,补充缺失的变量值。
补充好内容,我们再复制多几个卡片看看效果。
VStack { //卡片 cardView(image: "book1", title: "你的能力是否能在全世界通用,如果不能,那么需求重新评估你的能力。") cardView(image: "book2", title: "当你判断你的想法是正确的,那么就在今天完成吧。") }
那我们大功告成了吗?
不不不,再复制几个卡片看看效果。
因为VStack是固定的纵向排列,所有的内容都会在整个屏幕范围内。
如果我们想让整个视图滚动起来,SwiftUI提供了一个名为ScrollView的视图。
当主视图的VStack内容嵌入到ScrollView中时,它就变成了可滚动的。
由于滚动是动态加载的,需要点击模拟器顶部的“Preview”预览效果。
ScrollView { VStack { // 卡片 cardView(image: "book1", title: "你的能力是否能在全世界通用,如果不能,那么需求重新评估你的能力。") cardView(image: "book2", title: "当你判断你的想法是正确的,那么就在今天完成吧。") cardView(image: "book3", title: "将自身所学回馈社会,,不也是一件幸福的事么。") cardView(image: "book4", title: "成功的秘诀是,绝对不要和别人做同样的事情。" } }
恭喜你,我们完成了使用ScrollView实现微信公众号文章的项目!
ScrollView默认是纵向的,我们可以通过ScrollView(.horizontal)变成水平横向。
那我们是不是可以做到横向滚动呢?
留一个作业,请试试看。