SwiftUI-自定义与扩展

介绍

在SwiftUI中,尽管Apple提供了大量现成的UI组件和样式,但在实际开发中,我们经常需要进行更灵活的控制和个性化设计。SwiftUI鼓励开发者通过"协议+组合"的方式自定义视图行为和样式,从而构建更加丰富和高度可复用的用户界面。本文将通过多个示例,介绍SwiftUI中几种常见的自定义方式,包括样式(Style)、视图修改器(ViewModifier)、自定义视图(Custom View)与视图扩展(View Extension),帮助你构建出更具辨识度的UI组件。

自定义Style

SwiftUI中的Style协议(例如LabelStyle、ButtonStyle、ToggleStyle等)允许我们为组件定义全新的外观表现方式。通过实现makeBody方法,我们可以指定组件中内容(如图标与文本)的布局逻辑,实现不同于系统默认样式的个性化效果。这种方式特别适用于需要统一风格但不想逐一设置的场景。

案例

swift 复制代码
import SwiftUI

struct VLabelStyle: LabelStyle {
    // 在makeBody中实现自定义样式
    func makeBody(configuration: Configuration) -> some View {
        // 垂直排列,图片在上,文本在下
        VStack {
            configuration.icon
            configuration.title
        }
    }
}

struct ContentView: View {
    var body: some View {
        VStack(spacing: 20) {
            Label("Hello, World!", systemImage: "star.fill")

            Label("Hello, World!", systemImage: "star.fill")
                .labelStyle(VLabelStyle())
        }
    }
}

效果

自定义ViewModifier

ViewModifier是SwiftUI中一种非常强大的机制,允许我们将某些视图样式、行为封装成可复用的模块。它可以像"视图的装饰器"一样,在不改变原始视图定义的前提下,为其添加边框、阴影、背景、圆角等效果。通过组合使用多个ViewModifier,我们可以实现复杂且整洁的界面设计。

案例

swift 复制代码
import SwiftUI

struct CustomViewModifier: ViewModifier {
    let color: Color
    let cornerRadius: CGFloat

    // 在body中实现自定义ViewModifier
    func body(content: Content) -> some View {
        content
            .padding()
            .background(color)
            .clipShape(RoundedRectangle(cornerRadius: cornerRadius))
    }
}

struct ContentView: View {
    var body: some View {
        VStack(spacing: 20) {
            Text("Hello, World!")
                .frame(width: 100, height: 100)
                .modifier(CustomViewModifier(color: .red, cornerRadius: 10))
            
            Image(systemName: "star.fill")
                .frame(width: 100, height: 100)
                .modifier(CustomViewModifier(color: .blue, cornerRadius: 30))
        }
    }
}

效果

自定义View

当你发现系统提供的视图组件无法满足需求,或者你希望封装一块结构复杂、功能清晰的视图区域时,定义一个自定义的View是最佳选择。自定义视图不仅提升了代码复用率,还使得界面层级更加清晰。SwiftUI中的自定义View支持通过泛型与@ViewBuilder灵活嵌套不同内容,构建结构化的UI布局。

案例

swift 复制代码
import SwiftUI

// 自定义Card
struct Card<Content: View>: View {
    let color: Color
    let image: String
    let title: LocalizedStringKey
    let content: Content

    init(color: Color, image: String, title: LocalizedStringKey, @ViewBuilder content: () -> Content) {
        self.color = color
        self.image = image
        self.title = title
        self.content = content()
    }

    var body: some View {
        VStack(alignment: .leading, spacing: 12) {
            HStack(alignment: .center, spacing: 8) {
                Image(systemName: image)
                    .foregroundColor(color)

                Text(title)

                Spacer()
            }

            content
        }
        .padding(20)
        .overlay(
            RoundedRectangle(cornerRadius: 16)
                .stroke(color, lineWidth: 2)
        )
    }
}

struct ContentView: View {
    var body: some View {
        Card(color: .green, image: "leaf.fill", title: "环保提醒") {
            VStack(alignment: .leading, spacing: 8) {
                Text("今日减碳")
                    .font(.caption)
                    .foregroundColor(.secondary)

                Text("2.3 kg")
                    .font(.title2)
                    .fontWeight(.bold)
                    .foregroundColor(.green)
            }
        }
        .padding()
    }
}

效果

扩展View

SwiftUI中的View是一个协议,因此我们可以通过扩展(extension View)的方式,为所有视图添加新的功能方法。这是一种极其方便的方式,可以为项目引入统一风格的封装样式,比如边框风格、卡片风格等。通过链式调用这些扩展方法,我们可以使视图代码更加简洁、优雅、富有语义。

案例

swift 复制代码
import SwiftUI

extension View {
    // 添加带颜色的边框
    func borderedStyle(color: Color = .blue, width: CGFloat = 2, cornerRadius: CGFloat = 8) -> some View {
        padding()
            .overlay(
                RoundedRectangle(cornerRadius: cornerRadius)
                    .stroke(color, lineWidth: width)
            )
    }

    // 添加卡片样式
    func cardStyle(backgroundColor: Color = .white, shadowRadius: CGFloat = 5) -> some View {
        padding()
            .background(backgroundColor)
            .cornerRadius(12)
            .shadow(color: .gray.opacity(0.3), radius: shadowRadius, x: 0, y: 2)
    }
}

struct ContentView: View {
    var body: some View {
        VStack(spacing: 30) {
            Text("带颜色边框的文本")
                .font(.headline)
                .borderedStyle(color: .red, width: 3, cornerRadius: 15)

            VStack {
                Text("这是一个卡片")
                    .font(.title2)
                    .fontWeight(.semibold)

                Text("使用了cardStyle扩展")
                    .font(.subheadline)
                    .foregroundColor(.secondary)
            }
            .cardStyle(backgroundColor: .blue.opacity(0.1), shadowRadius: 8)
        }
    }
}

效果

相关推荐
大熊猫侯佩8 小时前
iOS 18 中全新 SwiftData 重装升级,其中一个功能保证你们“爱不释手”
数据库·ios·swift
大熊猫侯佩8 小时前
SwiftUI 6.0(iOS 18)新容器视图修改器漫谈
ios·swiftui·wwdc
SoaringHeart1 天前
SwiftUI组件封装:仿 Flutter 原生组件 Wrap实现
ios·swiftui
东坡肘子1 天前
WWDC 2025 开发者特辑 | 肘子的 Swift 周报 #088
swiftui·swift·wwdc
大熊猫侯佩1 天前
Swift 中强大的 Key Paths(键路径)机制趣谈(下)
swift·编程语言·apple