在 SwiftUI 中,stroke()
描述符是一个用于为形状添加边框(Stroke)的修饰符。它可以以多种方式配置边框的颜色、线宽和线条样式,例如虚线或其他自定义样式。
以下是 stroke
修饰符的详细使用说明。
语法概述 #
1. 基本形式 #
.stroke(Color, lineWidth: CGFloat)
Color
:边框的颜色,通常使用系统定义的颜色或自定义的Color
。lineWidth
:边框的宽度(浮点值,单位为点)。
2. 自定义线条样式 #
.stroke(style: StrokeStyle)
StrokeStyle
:用于创建自定义的线条样式(包括虚线、线帽等)。
基础用法示例 #
示例 1:为形状添加简单的边框 #
import SwiftUI
struct ContentView: View {
var body: some View {
Circle()
.stroke(Color.blue, lineWidth: 5) // 蓝色的边框,线宽为 5 点
.frame(width: 100, height: 100)
}
}
效果:
- 一个半径为 50 点的圆形,边框为蓝色,宽度 5 点。
进阶用法:调整线条样式 #
通过 StrokeStyle
可以更详细地定制边框样式,包括:
- 线条宽度(
lineWidth
) - 线条的端点形状(
lineCap
) - 拐角的形状(
lineJoin
) - 虚线样式(
dash
和dashPhase
)
StrokeStyle
常见参数:
StrokeStyle(lineWidth: CGFloat = 1,
lineCap: CGLineCap = .butt,
lineJoin: CGLineJoin = .miter,
miterLimit: CGFloat = 10,
dash: [CGFloat] = [],
dashPhase: CGFloat = 0)
示例 2:自定义线条端点形状和拐角形状 #
import SwiftUI
struct ContentView: View {
var body: some View {
RoundedRectangle(cornerRadius: 20)
.stroke(Color.red, style: StrokeStyle(lineWidth: 5,
lineCap: .round,
lineJoin: .bevel))
.frame(width: 200, height: 100)
}
}
参数解析: #
lineCap
: 表示线条端点的形状,这里设置为.round
,端点变为圆形。- 常用值:
.butt
(默认值):直角结束。.round
:圆形端点。.square
:方形端点。
- 常用值:
lineJoin
: 表示线条拐角的形状,这里设置为.bevel
,拐角变为斜角。- 常用值:
.miter
(默认值):尖角拐角(变尖)。.round
:圆角拐角。.bevel
:切角拐角。
- 常用值:
效果:
- 一个四边形,边缘有斜角 (Bevel),每条边的端点为圆形(Round)。
示例 3:创建虚线样式 #
StrokeStyle
中的 dash
参数用于设置虚线的模式。dash
是一个数组,其中的数值交替表示绘制线段和跳过的长度。
import SwiftUI
struct ContentView: View {
var body: some View {
Circle()
.stroke(Color.green, style: StrokeStyle(lineWidth: 4,
dash: [10, 5],
dashPhase: 0))
.frame(width: 100, height: 100)
}
}
参数解析: #
dash
:一个数组,依次交替表示线段长度和间隔长度。[10, 5]
表示:绘制 10 点长度的线,然后跳过 5 点长度的空白。
dashPhase
:虚线的偏移量,控制虚线的起始部分。如果偏移量不为零,它会“滚动”虚线的绘图位置。
效果:
- 一个绿色的圆形边框,显示有规律的虚线(每段线长为 10 点,间隔为 5 点)。
示例 4:带动态偏移的虚线 #
如果想让虚线不断滚动,可以动态调整 dashPhase
的值,例如借助 Timer
动态更新视图。
import SwiftUI
struct ContentView: View {
@State private var phase: CGFloat = 0
var body: some View {
Circle()
.stroke(Color.orange, style: StrokeStyle(lineWidth: 4,
dash: [10, 5],
dashPhase: phase))
.frame(width: 100, height: 100)
.onAppear {
Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { _ in
phase -= 5 // 动态调整偏移
}
}
}
}
效果:
- 虚线圆边框会不断“滚动”。
示例 5:组合填充和边框 #
在实践中,经常需要为形状同时添加填充颜色(内部)和边框颜色(外部)。可以通过 .stroke()
与 .fill()
的组合实现。
import SwiftUI
struct ContentView: View {
var body: some View {
Circle()
.fill(Color.yellow) // 内部填充为黄色
.overlay(
Circle()
.stroke(Color.blue, lineWidth: 5) // 外部边框为蓝色
)
.frame(width: 100, height: 100)
}
}
效果:
- 一个内部填充为黄色的圆形,外层有蓝色边框。
注意: #
.stroke()
本身只会绘制边框,不能设置填充。若需要同时具备填充,可结合 .fill()
或 .background()
。
完整的 StrokeStyle 参数 #
StrokeStyle
提供了一系列参数,用于高度自定义边框的绘制行为。参数功能如下:
参数名 | 描述 | 示例值 |
---|---|---|
lineWidth | 边框的宽度(单位:点) | 4 , 10 |
lineCap | 定义线条端点的形状,适用于开放路径(CGLineCap )。 | .butt , .round |
lineJoin | 定义线条拐角的形状,适用于路径的拐角(CGLineJoin )。 | .miter , .round |
miterLimit | 定义尖角的限制(仅当 lineJoin = .miter 时生效),限制拐角延伸的长度 | 默认值 10 |
dash | 设置虚线样式的间隔模式(绘制段长度与空白段长度数组)。 | [5, 10] , [2, 4, 6] |
dashPhase | 控制虚线起始偏移量。正值偏移使虚线滚动,可用于动画。 | 0 , 5 , -5 |
常见用途 #
绘制带边框的基本形状: 使用
.stroke()
可以为Circle
、RoundedRectangle
、Capsule
等形状添加边框。创建虚线或其他自定义样式的边框: 使用
StrokeStyle
中的dash
和dashPhase
创建虚线样式,动态更新dashPhase
实现动画。分层图形:
.stroke()
常与.fill()
配合,满足填充和描边的双重需求。
总结 #
stroke()
描述符是 SwiftUI 中一种简单而灵活的方式,用于为形状添加边框。它可以通过简单的参数如颜色和线宽满足基本需求,也可以通过强大的 StrokeStyle
为边框样式提供完整的自定义支持。
常用写法总结: #
修饰符(需求) | 示例 | 效果 |
---|---|---|
简单边框 | .stroke(Color.red, lineWidth: 5) | 固定宽度的彩色边框 |
自定义虚线 | .stroke(style: StrokeStyle(lineWidth: 4, dash: [5, 3])) | 连续虚线 |
动态虚线 | 使用 dashPhase 动态调整 | 虚线滚动动画 |
结合填充和背景 | .fill(Color.green).overlay(Circle().stroke(Color.red, ...)) | 同时具备填充颜色和边框 |
通过合理利用 stroke()
和 StrokeStyle
,你可以在 SwiftUI 中创建多种样式的形状和边框,满足各种视觉设计需求!
strokeBorder 区别 #
在 SwiftUI 中,stroke
和 strokeBorder
都是用于为形状(Shape
)添加边框的修饰符,但它们的绘制方式和布局行为有显著区别。以下是两者的对比和适用场景:
1. stroke
#
作用:沿形状的原始路径(路径的中心线)绘制边框,边框的宽度向内外等距扩展。
布局影响:边框会超出形状的原始边界,导致视图的整体尺寸(布局空间)增大。
示例:
Circle() .stroke(Color.blue, lineWidth: 10) .frame(width: 100, height: 100)
- 效果:边框的宽度会向圆形内外各扩展
5pt
(总宽度10pt
),最终视图的布局尺寸为110x110
(原始100x100
+ 边框10pt
)。
- 效果:边框的宽度会向圆形内外各扩展
适用场景:
- 当需要边框不影响形状内部的绘制区域时。
- 当允许边框超出原始形状的布局空间时。
2. strokeBorder
#
作用:将边框完全绘制在形状的原始边界内部,边框宽度不会超出原始形状的尺寸。
布局影响:视图的整体尺寸保持与原始形状一致,边框的宽度会向内“压缩”内容。
示例:
Circle() .strokeBorder(Color.red, lineWidth: 10) .frame(width: 100, height: 100)
- 效果:边框完全在
100x100
的圆形内部,最终视图的布局尺寸仍为100x100
,但边框会向内占用空间(实际可见的圆形直径为80pt
)。
- 效果:边框完全在
适用场景:
- 当需要严格保持视图的布局尺寸不变时。
- 当边框需要完全包含在形状内部时(如避免覆盖相邻视图)。
3. 关键区别对比 #
特性 | stroke | strokeBorder |
---|---|---|
边框位置 | 向内外扩展,超出原始边界 | 完全在原始边界内部 |
布局尺寸 | 增加(边框宽度影响布局) | 保持原始尺寸不变 |
视觉大小 | 原始形状 + 边框宽度 | 原始形状 - 边框宽度 |
适用场景 | 允许布局扩展的边框 | 严格固定布局尺寸的边框 |
4. 代码验证 #
通过叠加两个形状观察差异:
struct StrokeDemo: View {
var body: some View {
VStack(spacing: 20) {
// stroke:边框超出布局
Circle()
.stroke(Color.blue, lineWidth: 10)
.frame(width: 100, height: 100)
.background(Color.gray.opacity(0.2))
// strokeBorder:边框不超出布局
Circle()
.strokeBorder(Color.red, lineWidth: 10)
.frame(width: 100, height: 100)
.background(Color.gray.opacity(0.2))
}
}
}
- 效果:
stroke
的蓝色边框会导致灰色背景区域变大。strokeBorder
的红色边框保持灰色背景区域为100x100
。
5. 高级用法 #
自定义
StrokeStyle
:两者都支持自定义样式(如虚线、端点样式):Circle() .strokeBorder( Color.green, style: StrokeStyle( lineWidth: 5, dash: [10] ) )
组合形状:当形状需要叠加边框时,
strokeBorder
更适合确保布局稳定:ZStack { Circle() .fill(Color.yellow) Circle() .strokeBorder(Color.black, lineWidth: 2) } .frame(width: 100, height: 100)
总结 #
- 使用
stroke
:当需要边框向外扩展,且不介意视图布局尺寸增大时。 - 使用
strokeBorder
:当需要边框完全在原始形状内部,且严格保持布局尺寸不变时。