ViewModifier 和 圆角以及渐变色

ViewModifier

是什么

把一组样式或 UI 结构打包成可复用的东西,用 .modifier() 链式调用贴到任意 View 上。

类比 UIKit

UIKit 里你会封装一个函数来复用样式:

swift 复制代码
func styleToolButton(_ button: UIButton) {
    button.titleLabel?.font = .systemFont(ofSize: 25)
    button.setTitleColor(.white, for: .normal)
    button.frame.size = CGSize(width: 30, height: 30)
}

ViewModifier 干的是同一件事,但它不只能改属性,还能在原有 View 外面包一层新的 View 结构,这是普通函数做不到的:

swift 复制代码
struct BadgeModifier: ViewModifier {
    func body(content: Content) -> some View {
        ZStack(alignment: .topTrailing) {
            content  // 原来的 View 原封不动
            Text("99")
                .background(Color.red)
                .clipShape(Circle())
                .offset(x: 10, y: -10)
        }
    }
}

Image(systemName: "bell").modifier(BadgeModifier())
Image(systemName: "message").modifier(BadgeModifier())

本质

本质就是一个语法糖,功能上等价于自定义一个 View 然后把其他 View 塞进去,但它能融入 SwiftUI 的链式调用语法,用起来跟 .font() .foregroundColor() 一模一样。


圆角 + 渐变色 + 描边

是什么

SwiftUI 没有 UIKit 那样直接设置 layer.borderWidth 的属性,填充和描边需要两个图层叠加来实现。

类比 UIKit

UIKit 两行搞定:

swift 复制代码
view.layer.borderWidth = 4
view.layer.borderColor = UIColor.green.cgColor

SwiftUI 必须用 ZStack 叠两个 RoundedRectangle:

swift 复制代码
.background(
    ZStack {
        RoundedRectangle(cornerRadius: 20)
            .stroke(model.color, style: StrokeStyle(lineWidth: 4))
        RoundedRectangle(cornerRadius: 20)
            .fill(gradientStyle)
    }
)

为什么先 stroke 再 fill

stroke(描边)默认居中描边,线宽一半在内一半在外。fill 只填充内部区域,所以 fill 会覆盖 stroke 内侧的那一半。先画 stroke 再盖 fill,能让 stroke 外侧的一半露出来,边框视觉上更完整。反过来的话内侧边框线被盖住,边框显得细一半。

本质

这块 UIKit 确实更直观,SwiftUI 的声明式思路在这个场景下反而绕了一圈


本质

SwiftUI 没有 layer,只有 Shape + 绘制规则


fill 和 stroke 的区别

操作 本质
fill 填充 Shape 内部
stroke 沿路径画边

stroke 的问题

less 复制代码
.stroke(lineWidth: 4)

👉 描边在路径两侧(内 + 外)


推荐方案(更精准)

less 复制代码
.strokeBorder(lineWidth: 4)

👉 描边完全在内部


推荐结构

scss 复制代码
.fill(...)
.overlay(stroke)

👉 语义清晰:先填充,再叠加边框

ViewModifier

本质是 (View) -> View,不是修改 View,而是生成新 View


Modifier 顺序

顺序不是语法问题,而是 View 树结构

描边本质

边框不是属性,而是绘制结果(Shape + stroke)


相关推荐
空中海1 小时前
第二章:SwiftUI 视图基础
ios·swiftui·swift
择势5 小时前
MVVM 本质解构 + RxSwift 与 Combine 深度对决与选型指南
swiftui·swift·rxswift
东坡肘子6 天前
被 Vibe 摧毁的版权壁垒,与开发者的新护城河 -- 肘子的 Swift 周报 #131
人工智能·swiftui·swift
用户79457223954136 天前
【DGCharts】iOS 图表渲染事实标准——8 种图表类型、高度可定制,3 行代码画出一条折线
swiftui·swift
用户794572239541310 天前
【Lottie】让设计稿上的动效直接"活"在 App 里
swiftui·swift
用户794572239541312 天前
【SnapKit】优雅的 Swift Auto Layout DSL 库
swiftui·swift
Mr_Tony12 天前
iOS / SwiftUI 输入法(键盘)布局处理总结(AI版)
ios·swiftui
东坡肘子12 天前
苹果的罕见妥协:当高危漏洞遇上“拒升”潮 -- 肘子的 Swift 周报 #130
人工智能·swiftui·swift
曾经我也有梦想19 天前
SwiftUI 如何使用 UIKit 组件
swiftui
东坡肘子19 天前
一墙之隔,不同的时空 -- 肘子的 Swift 周报 #129
人工智能·swiftui·swift