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

德州安卓

一起养成写作习惯!

前言:刚开始学习编程的时候,确实太苦了,官网教材例子也做了,但好像也做不出什么实际的东西。后来发现真正干一行是不一样的,每一个有每一行的规则和定律。我们能做的,就是学会它,遵守它,最终变成制定标准的人。
今日职言:遇到困难时,我们要迎难而上,而不是畏畏缩缩。找到一个明确的目标,不在乎别人的眼光,努力去做就好了。

承接上一章节的内容。

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

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

在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)
    }

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

这是因为我们的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)
    }

我们在每个视图后都加上了.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)

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

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

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

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

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

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

在连续包月的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)
    }

要调整文本的位置,我们可以使用.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)

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

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

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

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

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

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

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

// 标题

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

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

// 标题

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

            //间隔符
            Spacer()
        }
        .padding

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

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

阅读量:2019

点赞量:0

收藏量:0