美文网首页
cs193p_2021_笔记[2]

cs193p_2021_笔记[2]

作者: walkerwzy | 来源:发表于2021-11-06 02:29 被阅读0次

    cs193p_2021_笔记_1
    cs193p_2021_笔记_2
    cs193p_2021_笔记_3_Animation_Transition
    cs193p_2021_笔记_4_Color_Image_Gesture
    cs193p_2021_笔记_5_Property Wrapper
    cs193p_2021_笔记_6_Persistence
    cs193p_2021_笔记_7_Document Architecture
    cs193p_2021_笔记_8

    本文涉及内容:ViewModifier, Property Observers, Layout


    ViewModifier

    .aspectRatio(2/3) is likely something like .modifier(AspectModifier(2/3)) AspectModifier can be anything that conforms to the ViewModifier protocol ...

    它只有一个body方法:

    protocol ViewModifier {
        associatedtype Content // this is a protocol’s version of a“don’t care” 
        func body(content: Content) -> some View {
            return some View that represents a modification of content }
    }
    
    • 对一个view调用.modifier就是把这个view传成了上述body方法的content
    • 而从.modifer变成.cardify,不过是用了extension
    extension View {
        func cardify(isFaceUp: Bool) -> some View {
            return self.modifier(Cardify(isFaceUp: isFaceUp))
        }
    }
    

    Property Observers

    • 语法长得像computed var, 但完全不是一回事 (get, set之于willSet, didSet)
    • willSet, didSet,对应newValue, oldValue

    @State

    your view is Read Only,

    为什么?

    因为view的生命周期足够短,基本上是不断地生成和销毁,根本不需要”被改变“

    • 所以永远用let
    • 所以是stateles

    这样的结构很简单,任何view的变化其实就是重绘。

    仍然有些时候需要状态:

    • 编辑表单
    • 模态窗口或通知窗口等临时窗口
    • 动画需要追踪动画进度

    声明:

    @State private var somethingTemporary: SomeType // this can be of any type
    
    • private 表示别人访问不到
    • @State的的变化会在必要时引起重绘 (相当于一个@ObservedObject
    • view会不断销毁和重建 -> 指针会永远指向新的内存地址
    • 而state是在堆上分配的空间
    • 所以销毁和重建view并不会丢失state
    • 后文property wrapper详述

    Layout

    1. Container提供空间
    2. Views确定自身的大小
    3. Container提供View的位置
    4. Container确定自身大小(等同于#2)

    HStack and VStack

    横/纵向排列元素(View),并提供“尽可能小”的空间,根据元素性质,有三种场景:

    1. inflexble view: Image,fixed size
    2. slightly more flexible view: Text,适应文字的合适大小
    3. very flexible view: RoundedRectangle: 占满空间 -> 基本上Shape都会有多少空间占多少
    • 一旦元素确定了size,多余的空间就会给下一个元素,最后very flexible view平均分配剩下的空间
    • 所有元素大小确定,容器大小也就确定了,如果有very flexible的,那么容易本身也是very flexible

    remark:

    • Spacer(minLength: CGFloat) 空格, draw nothing, 占尽可能多的空间
    • Divider() 画条分隔线,占尽可能小的空间
    • .layoutPriority(100) 用优先级来表示分配空间的顺序,默认值为0。后分配者如果没有空间了会用省略号表示
    • HStack(alignment: .leading)用来控制元素的对齐

    List, Form, OutlineGroup 其实就是 really smart VStacks,即本质上就是一个纵向排列的布局。

    LazyHStack and LazyVStack

    • Lazy的意思是如果元素对应的位置没有出现在屏幕上,就不会构建View.
    • they also size themselves to fit their views
    • 前两条加一起,得出这个容器不会尽可能多的占用空间,即使含有very flexible的view -> 尽可能小的空间
    • 显然,它最多出现在ScrollView里(只有在有限窗口里滚动,才有可见不可见的差别)

    Scrollview

    • 给多少空间占多少空间

    LazyHGrid and LazyVGrid

    • 一个方向view数量固定,另一个方向动态增减(scroll)的H/V stack,以竖向的LazyVGrid为例:
    • 确定每行元素个数,多少行由元素总数决定
    • 或者确定元素大小,在行方向铺满后,再往下一行铺
    • HGrid方向则是先纵向铺满,再水平铺

    ZStack

    • sizes itself to fit its children
    • can be very flexible (if one children is)

    两个modifier其实也是用的ZStack:

    • .background,插入一个view在底层,stack起来: Text("hello").background(Rectangle().foregroundColor(.red))
    • .overlay,覆盖到表层的zstack: Circle().overlay(Text("hello"), alignment:.center)

    More:

    • 一个view是可以选择任意size的,哪怕比给它的空间更大(产生裁剪)
    • .aspectRatio(2/3, contentMode: .fit)如果是在HStack里,
      • 则是把元素横向排列后得到宽度,根据宽度计算出高度,得到元素大小
      • .fit表示完整显示图片(就长边),短边部分补成黑色,.fill应该是就短边,长边部分就裁剪了
    HStack {
        ForEach(cards) { card in
            CardView(card).aspectRatio(2/3, contentMode: .fit)
        }
    }
        .foregroundColor(.orange)
        .padding(10)
    
    1. 在能够分配的空间里,四边各减10 -> padding(10)
    2. 减10后的空间里,根据aspectRation确定一个size
    3. 这个size应用给CardView
    4. 组合成HStack的size

    总大小就是HStack的size四边各加10

    而View们如何知道能占多少空间?-> GeometryReader

    GeometryReader

    var body: View {
        GeometryReader { geometry in
            ...
        }
    }
    

    参数geometry是一个GeometryProxy:

    struct GeometryProxy {
        var size: CGSize
        var safeAreaInsets: EdgeInsets
        func frame(in: CoordinateSpace) -> CGRect
    }
    
    • size表示被提供了多少的空间(by its container)
    • 并且不包含safe area(如刘海)
    • 如果需要绘制到safe area里去: ZStack{...}.edgesIgnoringSafeArea([.top])
    image.png

    图中演示的是设置卡片字体的大小,希望尽可能地填充卡片,geometry.size能给出运行时数据,而无需硬编码。

    相关文章

      网友评论

          本文标题:cs193p_2021_笔记[2]

          本文链接:https://www.haomeiwen.com/subject/zjbdzltx.html