SwiftUI极简教程04:VStack, HStack, ZStack视图排列的使用(下)

简介: SwiftUI极简教程04:VStack, HStack, ZStack视图排列的使用(下)

image.png


承接上一章节的内容。

我们看到3个定价方案是横向排列的,最简单的编程方式将定价方案包裹在HStack里,然后再在里面按照第一个定价方案复制2个。

鼠标移动到定价方案VStack的位置,键盘按住command键,单击鼠标,选择Embed in HStack,那么我们在之前VStack外面会再包裹一层HStack。

image.png

在HStack里面,我们复制多2个定价方案,修改文字、颜色。

备注:记得要写注释哦~


// 定价方案
HStack {
    //连续包月
    VStack {
        Text("连续包月")
            .fontWeight(.bold)
            .font(.system(size: 17))
            .foregroundColor(Color(red: 190 / 255, green: 188 / 255, blue: 184 / 255))
        Text("¥18")
            .fontWeight(.bold)
            .font(.system(size: 30))
            .foregroundColor(Color(red: 239 / 255, green: 129 / 255, blue: 112 / 255))
        }
        .padding(20)
        .background(Color("faf7f3"))
        .overlay(RoundedRectangle(cornerRadius: 6)
        .stroke(Color(red: 202 / 255, green: 169 / 255, blue: 106 / 255), lineWidth: 2))
    //1个月
    VStack {
        Text("1个月")
            .fontWeight(.bold)
            .font(.system(size: 17))
            .foregroundColor(Color(red: 190 / 255, green: 188 / 255, blue: 184 / 255))
        Text("¥30")
            .fontWeight(.bold)
            .font(.system(size: 30))
            .foregroundColor(Color(red: 239 / 255, green: 129 / 255, blue: 112 / 255))
        }
        .padding(20)
        .background(Color(red: 244 / 255, green: 244 / 255, blue: 245 / 255))
        .cornerRadius(10)
    //12个月
    VStack {
        Text("12个月")
            .fontWeight(.bold)
            .font(.system(size: 17))
            .foregroundColor(Color(red: 190 / 255, green: 188 / 255, blue: 184 / 255))
        Text("¥228")
            .fontWeight(.bold)
            .font(.system(size: 30))
            .foregroundColor(Color(red: 239 / 255, green: 129 / 255, blue: 112 / 255))
        Text("¥19.00/月")
            .fontWeight(.bold)
            .font(.system(size: 17))
            .foregroundColor(Color(red: 190 / 255, green: 188 / 255, blue: 184 / 255))
        }
        .padding(20)
        .background(Color(red: 244 / 255, green: 244 / 255, blue: 245 / 255))
        .cornerRadius(10)
    }


image.png

编程后可以发现,三个定价方案的大小都不一样。

这是因为我们的View取决于我们内部元素,视图的大小会自定义内部的内容。

如果我们需要让三个定价方案同样的大小,我们需要引入.frame()修饰符。

.frame()修饰符允许用户定义视图的大小,无论内部元素怎么变化,视图都可以维持固定的大小。


// 定价方案
HStack {
    //连续包月
    VStack {
        Text("连续包月")
            .fontWeight(.bold)
            .font(.system(size: 17))
            .foregroundColor(Color(red: 190 / 255, green: 188 / 255, blue: 184 / 255))
        Text("¥18")
            .fontWeight(.bold)
            .font(.system(size: 30))
            .foregroundColor(Color(red: 239 / 255, green: 129 / 255, blue: 112 / 255))
        }
        .frame(minWidth: 0, maxWidth: .infinity, minHeight: 90)
        .padding(20)
        .background(Color("faf7f3"))
        .overlay(RoundedRectangle(cornerRadius: 6)
        .stroke(Color(red: 202 / 255, green: 169 / 255, blue: 106 / 255), lineWidth: 2))
    //1个月
    VStack {
        Text("1个月")
            .fontWeight(.bold)
            .font(.system(size: 17))
            .foregroundColor(Color(red: 190 / 255, green: 188 / 255, blue: 184 / 255))
        Text("¥30")
            .fontWeight(.bold)
            .font(.system(size: 30))
            .foregroundColor(Color(red: 239 / 255, green: 129 / 255, blue: 112 / 255))
        }
        .frame(minWidth: 0, maxWidth: .infinity, minHeight: 90)
        .padding(20)
        .background(Color(red: 244 / 255, green: 244 / 255, blue: 245 / 255))
        .cornerRadius(10)
    //12个月
    VStack {
        Text("12个月")
            .fontWeight(.bold)
            .font(.system(size: 17))
            .foregroundColor(Color(red: 190 / 255, green: 188 / 255, blue: 184 / 255))
        Text("¥228")
            .fontWeight(.bold)
            .font(.system(size: 30))
            .foregroundColor(Color(red: 239 / 255, green: 129 / 255, blue: 112 / 255))
        Text("¥19.00/月")
            .fontWeight(.bold)
            .font(.system(size: 17))
            .foregroundColor(Color(red: 190 / 255, green: 188 / 255, blue: 184 / 255))
        }
        .frame(minWidth: 0, maxWidth: .infinity, minHeight: 90)
        .padding(20)
        .background(Color(red: 244 / 255, green: 244 / 255, blue: 245 / 255))
        .cornerRadius(10)
    }


image.png

我们在每个视图后都加上了.frame(minWidth: 0, maxWidth: .infinity, minHeight: 90)修饰符。


我们解释下这句代码的意思,最小宽度为0,最大宽度为自适应,最小高度为90。

如果我们设置了最小的高度,那么它的最小高度是固定的,而最大宽度会跟随系统自适应。


像我们有三个定价方案,最小高度固定都是90,最小宽度为0,最大宽度就按照屏幕宽度平均分了。


我们看到三个定价方案两边紧贴着屏幕,需要留点空间,那么需要对整个HStack设置.padding。


// 定价方案
HStack {
    //连续包月
    VStack {
        Text("连续包月")
            .fontWeight(.bold)
            .font(.system(size: 17))
            .foregroundColor(Color(red: 190 / 255, green: 188 / 255, blue: 184 / 255))
        Text("¥18")
            .fontWeight(.bold)
            .font(.system(size: 30))
            .foregroundColor(Color(red: 239 / 255, green: 129 / 255, blue: 112 / 255))
        }
        .frame(minWidth: 0, maxWidth: .infinity, minHeight: 90)
        .padding(20)
        .background(Color("faf7f3"))
        .overlay(RoundedRectangle(cornerRadius: 6)
        .stroke(Color(red: 202 / 255, green: 169 / 255, blue: 106 / 255), lineWidth: 2))
    //1个月
    VStack {
        Text("1个月")
            .fontWeight(.bold)
            .font(.system(size: 17))
            .foregroundColor(Color(red: 190 / 255, green: 188 / 255, blue: 184 / 255))
        Text("¥30")
            .fontWeight(.bold)
            .font(.system(size: 30))
            .foregroundColor(Color(red: 239 / 255, green: 129 / 255, blue: 112 / 255))
        }
        .frame(minWidth: 0, maxWidth: .infinity, minHeight: 90)
        .padding(20)
        .background(Color(red: 244 / 255, green: 244 / 255, blue: 245 / 255))
        .cornerRadius(10)
    //12个月
    VStack {
        Text("12个月")
            .fontWeight(.bold)
            .font(.system(size: 17))
            .foregroundColor(Color(red: 190 / 255, green: 188 / 255, blue: 184 / 255))
        Text("¥228")
            .fontWeight(.bold)
            .font(.system(size: 30))
            .foregroundColor(Color(red: 239 / 255, green: 129 / 255, blue: 112 / 255))
        Text("¥19.00/月")
            .fontWeight(.bold)
            .font(.system(size: 17))
            .foregroundColor(Color(red: 190 / 255, green: 188 / 255, blue: 184 / 255))
        }
        .frame(minWidth: 0, maxWidth: .infinity, minHeight: 90)
        .padding(20)
        .background(Color(red: 244 / 255, green: 244 / 255, blue: 245 / 255))
        .cornerRadius(10)
    }
    .padding(.horizontal)

image.png


根据上面内容,我们学习了VStack、HStack,我们看一个第一个定价方案。

第一个定价方案的顶部有个“首月特惠”,它是覆盖在视图上面的,而且是覆盖了一半。

这时候我们就需要用到ZStack。


image.png


我们先找到第一个定价方案的视图。

鼠标移动到定价方案VStack的位置,键盘按住command键,单击鼠标,选择Embed in ZStack,那么我们在之前VStack外面会再包裹一层ZStack。

image.png


我们在两个视图分割点写上注释,便于我们区分代码内容。

在连续包月的VStack下补充“首月特惠”的代码,其实就是简单的Text("首月特惠”),再加上一些修饰符美化。

编码完可以看到Text视图将覆盖在定价视图上面。


// 连续包月
ZStack {
    VStack {
        Text("连续包月")
            .fontWeight(.bold)
            .font(.system(size: 17))
            .foregroundColor(Color(red: 190 / 255, green: 188 / 255, blue: 184 / 255))
        Text("¥18")
            .fontWeight(.bold)
            .font(.system(size: 30))
            .foregroundColor(Color(red: 239 / 255, green: 129 / 255, blue: 112 / 255))
        }
        .frame(minWidth: 0, maxWidth: .infinity, minHeight: 90)
        .padding(20)
        .background(Color("faf7f3"))
        .overlay(RoundedRectangle(cornerRadius: 6).stroke(Color(red: 202 / 255, green: 169 / 255, blue: 106 / 255), lineWidth: 2))
    // 首月特惠
    Text("首月特惠")
        .font(.system(size: 14))
        .fontWeight(.bold)
        .foregroundColor(.white)
        .padding(5)
        .background(Color(red: 202 / 255, green: 169 / 255, blue: 106 / 255))
        .cornerRadius(4)
    }

image.png

要调整文本的位置,我们可以使用.offset修饰符,它是设置偏移量的。

简单来说,就是修饰被选定的视图,应该移动到哪里。

X,Y分别对应坐标轴位置,X轴正数为右移,负数为左移,Y轴正数下移,负数上移。


// 首月特惠
    Text("首月特惠")
        .font(.system(size: 14))
        .fontWeight(.bold)
        .foregroundColor(.white)
        .padding(5)
        .background(Color(red: 202 / 255, green: 169 / 255, blue: 106 / 255))
        .cornerRadius(4)
        .offset(x: 0, y: -65)


image.png

恭喜你!页面完成度有80%啦!

我们看到标题“会员套餐”和“解锁高级功能”是左对齐,但标题和定价方案目前是还是居中对齐。

我们希望整个文字和定价方案是左对齐,这时候我们引入一个新的参数,叫做Spacer()。

Spacer()相当于空白视图,什么都没有,但可以在Stack中充当“挤开”其他视图的作用。


image.png

我们可以看到标题部分和Spacer()是横向分布的关系,那么我们先把整个标题包裹在一个HStack里。

鼠标移动到定价方案VStack的位置,键盘按住command键,单击鼠标,选择Embed in HStack,那么我们在之前标题VStack外面会再包裹一层HStack。


image.png

我们在标题HStack内,标题VStack内增加Spacer(),得到的效果就是标题被挤开到左边了。


// 标题
    HStack {
        VStack(alignment: .leading, spacing: 10) {
            Text("会员套餐")
                .fontWeight(.bold)
                .font(.system(.title))
            Text("解锁高级功能")
                .fontWeight(.bold)
                .font(.system(.title))
            }
            //间隔符
            Spacer()
        }


image.png

最后,我们再在整个标题HStack外增加一个.padding,保持屏幕两边的边距,就得到了我们想要的效果。


// 标题
    HStack {
        VStack(alignment: .leading, spacing: 10) {
            Text("会员套餐")
                .fontWeight(.bold)
                .font(.system(.title))
            Text("解锁高级功能")
                .fontWeight(.bold)
                .font(.system(.title))
            }
            //间隔符
            Spacer()
        }
        .padding


image.png

如果最后我们还想把整个视图“挤”到上面一点的位置。

不妨把标题和定价的组合外面再包裹一个VStack,再用Spacer()试试吧!

相关文章
|
9月前
|
前端开发
Web前端---图层嵌套与层叠&&三行三列效果
Web前端---图层嵌套与层叠&&三行三列效果
137 0
|
5月前
|
前端开发 容器
前端基础(十五)_多栏布局(两列自适应布局、圣杯布局---三列布局、双飞翼布局--三列布局、等高布局)
本文介绍了前端开发中的多种自适应布局技术,包括两列自适应布局、圣杯布局(三列布局)、双飞翼布局(三列布局)和等高布局。文章通过代码示例展示了如何使用HTML和CSS实现这些布局,以及如何通过flex布局简化实现过程。
204 2
|
程序员 索引
SwiftUI极简教程18:SwipeCard卡片滑动效果的使用(上)
SwiftUI极简教程18:SwipeCard卡片滑动效果的使用(上)
1140 0
SwiftUI极简教程18:SwipeCard卡片滑动效果的使用(上)
|
自然语言处理 iOS开发
SwiftUI极简教程03:VStack, HStack, ZStack视图排列的使用(上)
SwiftUI极简教程03:VStack, HStack, ZStack视图排列的使用(上)
1529 0
SwiftUI极简教程03:VStack, HStack, ZStack视图排列的使用(上)
|
开发者 索引
SwiftUI极简教程27:DisclosureGroup拓展折叠视图的使用
SwiftUI极简教程27:DisclosureGroup拓展折叠视图的使用
657 0
SwiftUI极简教程27:DisclosureGroup拓展折叠视图的使用
SwiftUI—使用ZStack在深度方向排列视图
SwiftUI—使用ZStack在深度方向排列视图
218 0
SwiftUI—使用ZStack在深度方向排列视图
|
定位技术
SwiftUI—使用MapKit里的地图视图
SwiftUI—使用MapKit里的地图视图
478 0
SwiftUI—使用MapKit里的地图视图
SwiftUI—如何在PreviewProvider中使用导航视图
SwiftUI—如何在PreviewProvider中使用导航视图
417 0
SwiftUI—如何在PreviewProvider中使用导航视图
SwiftUI—将子视图作为属性以使布局代码更简洁
SwiftUI—将子视图作为属性以使布局代码更简洁
204 0
SwiftUI—将子视图作为属性以使布局代码更简洁
SwiftUI—创建两层嵌套的滚动视图
SwiftUI—创建两层嵌套的滚动视图
593 0
SwiftUI—创建两层嵌套的滚动视图