-
Notifications
You must be signed in to change notification settings - Fork 411
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
465 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
42 changes: 42 additions & 0 deletions
42
SwiftPamphletApp/Resource/Guide/SwiftUI/布局组件/布局进阶/AnyLayout(ap).md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
|
||
使用 AnyLayout 包装布局组件,可以在布局之间进行切换,同时保持动画效果。 | ||
|
||
```swift | ||
struct WeatherLayout: View { | ||
@State private var changeLayout = false | ||
|
||
var body: some View { | ||
let layout = changeLayout ? AnyLayout(HStackLayout()) : AnyLayout(VStackLayout()) | ||
|
||
layout { | ||
WeatherView(icon: "sun.max.fill", temperature: 25, color: .yellow) | ||
WeatherView(icon: "cloud.rain.fill", temperature: 18, color: .blue) | ||
WeatherView(icon: "snow", temperature: -5, color: .white) | ||
} | ||
.animation(.default, value: changeLayout) | ||
.onTapGesture { | ||
changeLayout.toggle() | ||
} | ||
} | ||
} | ||
|
||
struct WeatherView: View { | ||
let icon: String | ||
let temperature: Int | ||
let color: Color | ||
|
||
var body: some View { | ||
VStack { | ||
Image(systemName: icon) | ||
.font(.system(size: 80)) | ||
.foregroundColor(color) | ||
Text("\(temperature)°") | ||
.font(.system(size: 50)) | ||
.foregroundColor(color) | ||
} | ||
.frame(width: 120, height: 120) | ||
} | ||
} | ||
``` | ||
|
||
代码中,我们创建了一个 WeatherView 视图,它包含一个天气图标和一个温度标签。然后,我们在 WeatherLayout 视图中使用 AnyLayout 来动态改变布局。用户可以通过点击视图来在水平布局和垂直布局之间切换。 |
71 changes: 71 additions & 0 deletions
71
SwiftPamphletApp/Resource/Guide/SwiftUI/布局组件/布局进阶/GeometryReader(ap).md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
|
||
|
||
在 SwiftUI 中,有多种方法可以获取和控制视图的尺寸: | ||
|
||
- `frame(width:60, height:60)`:这个方法会为子视图提供一个建议的尺寸,这里是 60 x 60。 | ||
- `fixedSize()`:这个方法会为子视图提供一个未指定模式的建议尺寸,这意味着视图会尽可能地大以适应其内容。 | ||
- `frame(minWidth: 120, maxWidth: 360)`:这个方法会将子视图的需求尺寸控制在指定的范围中,这里是宽度在 120 到 360 之间。 | ||
- `frame(idealWidth: 120, idealHeight: 120)`:这个方法会返回一个需求尺寸,如果当前视图收到为未指定模式的建议尺寸,那么它会返回 120 x 120 的尺寸。 | ||
- `GeometryReader`:`GeometryReader` 会将建议尺寸作为需求尺寸直接返回,这意味着它会充满全部可用区域。你可以使用 `GeometryReader` 来获取其内容的尺寸和位置。 | ||
|
||
|
||
`GeometryReader` 可以获取其内容的尺寸和位置。在这个例子中,我们使用 `GeometryReader` 来获取视图的尺寸,然后打印出来。这对于理解 SwiftUI 的布局系统和调试布局问题非常有用。 | ||
|
||
```swift | ||
extension View { | ||
func logSizeInfo(_ label: String = "") -> some View { | ||
background( | ||
GeometryReader { proxy in | ||
Color.clear | ||
.onAppear(perform: { | ||
debugPrint("\(label) Size: \(proxy.size)") | ||
}) | ||
} | ||
) | ||
} | ||
} | ||
|
||
struct ContentView: View { | ||
var body: some View { | ||
VStack { | ||
Text("大标题") | ||
.font(.largeTitle) | ||
.logSizeInfo("大标题视图") // 打印视图尺寸 | ||
Text("正文") | ||
.logSizeInfo("正文视图") | ||
} | ||
} | ||
} | ||
``` | ||
|
||
这段代码首先定义了一个 `View` 的扩展,添加了一个 `logSizeInfo(_:)` 方法。这个方法接受一个标签字符串作为参数,然后返回一个新的视图。这个新的视图在背景中使用 `GeometryReader` 来获取并打印视图的尺寸。 | ||
|
||
然后,我们创建了一个 `VStack` 视图,其中包含一个 `Text` 视图。我们为 `Text` 视图调用了 `logSizeInfo(_:)` 方法,以打印其尺寸。 | ||
|
||
|
||
如何利用 `GeometryReader` 来绘制一个圆形? | ||
|
||
```swift | ||
struct CircleView: View { | ||
var body: some View { | ||
GeometryReader { proxy in | ||
Path { path in | ||
let radius = min(proxy.size.width, proxy.size.height) / 2 | ||
let center = CGPoint(x: proxy.size.width / 2, y: proxy.size.height / 2) | ||
path.addArc(center: center, radius: radius, startAngle: .zero, endAngle: .init(degrees: 360), clockwise: false) | ||
} | ||
.fill(Color.blue) | ||
} | ||
} | ||
} | ||
``` | ||
|
||
在这个例子中,我们首先获取 `GeometryReader` 的尺寸,然后计算出半径和中心点的位置。然后,我们使用 `Path` 的 `addArc(center:radius:startAngle:endAngle:clockwise:)` 方法来添加一个圆形路径。最后,我们使用 `fill(_:)` 方法来填充路径,颜色为蓝色。 | ||
|
||
关于 GeometryReader 性能问题 | ||
|
||
GeometryReader 是 SwiftUI 中的一个工具,它可以帮助我们获取视图的大小和位置。但是,它在获取这些信息时,需要等待视图被评估、布局和渲染完成。这就好比你在装修房子时,需要等待墙壁砌好、油漆干燥后,才能测量墙壁的尺寸。这个过程可能需要等待一段时间,而且可能需要多次重复,因为每次墙壁的尺寸改变,都需要重新测量。 | ||
|
||
这就是 GeometryReader 可能会影响性能的原因。它需要等待视图完成一轮的评估、布局和渲染,然后才能获取到尺寸数据,然后可能需要根据这些数据重新调整布局,这就需要再次进行评估、布局和渲染。这个过程可能需要重复多次,导致视图被多次重新评估和布局。 | ||
|
||
但是,随着 SwiftUI 的更新,这个问题已经有所改善。现在,我们可以创建自定义的布局容器,这些容器可以在布局阶段就获取到父视图的建议尺寸和所有子视图的需求尺寸,这样就可以避免反复传递尺寸数据,减少了视图的反复更新。 |
Oops, something went wrong.