为什么这个自定义形状会占据整个垂直空间?

问题描述

我想知道为什么这个自定义形状,它只是一个字母模板,占据了整个视图空间??我从来没有画过一条需要那么多垂直空间的线,所以我想知道发生了什么。

这是它的外观示例。

enter image description here

您可以看到图像在垂直方向上几乎翻了一番。

这是形状及其父视图的代码

 import SwiftUI
    
    struct ParentView: View {
       var body: some View {
       vstack {
           Spacer()
           LetterPreviewShape()
       }
    }

}


    struct LetterPreviewShape: Shape {
        func path(in rect: CGRect) -> Path {
            let startingPoint = CGPoint(x: rect.minX,y: rect.minY)
            let paragraphStartingPoint = CGPoint(x: rect.maxX * 0.1,y: rect.maxY * 0.1)
            
            var path = Path()
            
            //Letter outline
            path.move(to: startingPoint)
            path.addLine(to: CGPoint(x: rect.maxX,y: rect.minY))
            path.addLine(to: CGPoint(x: rect.maxX,y: rect.midY))
            path.addLine(to: CGPoint(x: rect.minX,y: rect.midY))
            path.closeSubpath()
            
            //Greeting Line
            path.move(to: CGPoint(x: rect.maxX * 0.1,y: rect.maxY * 0.07))
            path.addLine(to: CGPoint(x: rect.maxX * 0.3,y: rect.maxY * 0.07))
            
            
            //Body strokes
            path.move(to: paragraphStartingPoint)
            path.addLine(to: CGPoint(x: rect.maxX * 0.9,y: rect.maxY * 0.1))
            
            path.move(to: CGPoint(x: rect.maxX * 0.1,y: rect.maxY * 0.11))
            path.addLine(to: CGPoint(x: rect.maxX * 0.9,y: rect.maxY * 0.11))
            
            path.move(to: CGPoint(x: rect.maxX * 0.1,y: rect.maxY * 0.12))
            path.addLine(to: CGPoint(x: rect.maxX * 0.9,y: rect.maxY * 0.12))
            
            path.move(to: CGPoint(x: rect.maxX * 0.1,y: rect.maxY * 0.13))
            path.addLine(to: CGPoint(x: rect.maxX * 0.9,y: rect.maxY * 0.13))
            
            path.move(to: CGPoint(x: rect.maxX * 0.1,y: rect.maxY * 0.14))
            path.addLine(to: CGPoint(x: rect.maxX * 0.9,y: rect.maxY * 0.14))
            
            path.move(to: CGPoint(x: rect.maxX * 0.1,y: rect.maxY * 0.15))
            path.addLine(to: CGPoint(x: rect.maxX * 0.9,y: rect.maxY * 0.15))
            
            path.move(to: CGPoint(x: rect.maxX * 0.1,y: rect.maxY * 0.16))
            path.addLine(to: CGPoint(x: rect.maxX * 0.9,y: rect.maxY * 0.16))
            
           //Signature Line
            path.move(to: CGPoint(x: rect.maxX * 0.7,y: rect.maxY * 0.18))
            path.addLine(to: CGPoint(x: rect.maxX * 0.9,y: rect.maxY * 0.18))
            
            path.move(to: CGPoint(x: rect.maxX * 0.7,y: rect.maxY * 0.19))
            path.addLine(to: CGPoint(x: rect.maxX * 0.9,y: rect.maxY * 0.19))
            
            return path
        }
    }

解决方法

SwiftUI 中的

Shape 总是填充可用空间。它与您绘制内容的位置没有任何关系。

您也可以看到非自定义系统形状也复制了这种行为——如果您只使用 RectangleCircle,它们也会填充可用空间。

要限制它,给它一个 frame -- 如果您需要基于可用大小,可以将它与 GeometryReader 结合使用。

例如:

struct ContentView : View {
    var body: some View {
        GeometryReader { geometry in
            VStack {
                Spacer().frame(height: geometry.size.height / 2)
                Rectangle().fill(Color.red).frame(height: geometry.size.height / 2)
            }
        }
    }
}

,

Shape 没有自己的框架,所以你必须在外部给它一个(或者它填充所有可用的东西),比如

struct ParentView: View {
    var body: some View {
       VStack {
           Spacer()
           LetterPreviewShape()
              .frame(height: 200)   // << this goes in `func path(in rect: CGRect) -> Path`
       }
    }
}