《SwiftUI 高级特性第1章:自定义视图》

0 阅读4分钟

Snip20260419_12.png

1.1 自定义视图概述

在 SwiftUI 中,自定义视图是构建复杂用户界面的基础。通过创建可重用的自定义视图组件,我们可以:

  • 提高代码的可维护性和可重用性
  • 封装复杂的 UI 逻辑
  • 保持主视图代码的简洁性
  • 实现统一的设计风格

1.2 自定义视图的创建方法

1.2.1 基本结构

创建自定义视图的基本步骤:

  1. 定义一个遵循 View 协议的结构体
  2. 实现 body 计算属性,返回一个视图
  3. 为视图添加必要的属性和初始化方法

1.2.2 示例代码结构

// 自定义视图结构体
struct CustomView: View {
    // 属性定义
    let title: String
    let subtitle: String
    
    // 初始化方法
    init(title: String, subtitle: String) {
        self.title = title
        self.subtitle = subtitle
    }
    
    // 视图体
    var body: some View {
        VStack {
            Text(title)
            Text(subtitle)
        }
    }
}

1.3 自定义组件示例

1.3.1 自定义按钮

功能说明:创建一个具有不同样式的自定义按钮组件。

代码实现

// 自定义按钮组件
struct CustomButton: View {
    let title: String
    let style: ButtonStyle
    let action: () -> Void
    
    // 按钮样式枚举
    enum ButtonStyle {
        case primary
        case secondary
    }
    
    // 初始化方法
    init(title: String, style: ButtonStyle = .primary, action: @escaping () -> Void) {
        self.title = title
        self.style = style
        self.action = action
    }
    
    var body: some View {
        Button(action: action) {
            Text(title)
                .padding()
                .background(style == .primary ? .blue : .gray)
                .foregroundColor(.white)
                .cornerRadius(10)
                .font(.headline)
        }
    }
}

使用示例

CustomButton(title: "点击我") {
    print("自定义按钮被点击")
}

CustomButton(title: "次要按钮", style: .secondary) {
    print("次要按钮被点击")
}

1.3.2 自定义卡片

功能说明:创建一个带有标题、副标题和图标的卡片组件。

代码实现

// 自定义卡片组件
struct CustomCard: View {
    let title: String
    let subtitle: String
    let imageName: String
    
    var body: some View {
        VStack(alignment: .leading, spacing: 10) {
            HStack {
                Image(systemName: imageName)
                    .font(.largeTitle)
                    .foregroundColor(.blue)
                Spacer()
            }
            Text(title)
                .font(.headline)
                .fontWeight(.bold)
            Text(subtitle)
                .font(.subheadline)
                .foregroundColor(.gray)
        }
        .padding()
        .background(.white)
        .cornerRadius(10)
        .shadow(radius: 5)
        .padding(.horizontal)
    }
}

使用示例

CustomCard(
    title: "欢迎使用 SwiftUI",
    subtitle: "这是一个自定义卡片视图",
    imageName: "star.fill"
)

CustomCard(
    title: "学习 SwiftUI",
    subtitle: "从基础到高级",
    imageName: "book.fill"
)

1.3.3 自定义进度条

功能说明:创建一个可自定义颜色和进度的进度条组件。

代码实现

// 自定义进度条组件
struct CustomProgressBar: View {
    let progress: Double
    let color: Color
    
    init(progress: Double, color: Color = .red) {
        self.progress = min(max(progress, 0), 1) // 确保进度在0-1之间
        self.color = color
    }
    
    var body: some View {
        GeometryReader { geometry in
            ZStack(alignment: .leading) {
                // 背景
                Rectangle()
                    .fill(.gray.opacity(0.3))
                    .cornerRadius(5)
                
                // 进度条
                Rectangle()
                    .fill(color)
                    .frame(width: geometry.size.width * CGFloat(progress))
                    .cornerRadius(5)
            }
            .frame(height: 20)
        }
        .padding(.horizontal)
    }
}

使用示例

CustomProgressBar(progress: 0.3)
CustomProgressBar(progress: 0.7, color: .green)
CustomProgressBar(progress: 1.0, color: .blue)

1.3.4 自定义徽章

功能说明:创建一个可自定义颜色的徽章组件。

代码实现

// 自定义徽章组件
struct CustomBadge: View {
    let text: String
    let color: Color
    
    init(text: String, color: Color = .blue) {
        self.text = text
        self.color = color
    }
    
    var body: some View {
        Text(text)
            .padding(.horizontal, 12)
            .padding(.vertical, 6)
            .background(color)
            .foregroundColor(.white)
            .cornerRadius(15)
            .font(.subheadline)
            .fontWeight(.bold)
    }
}

使用示例

CustomBadge(text: "新")
CustomBadge(text: "热门", color: .red)
CustomBadge(text: "优惠", color: .green)

1.3.5 自定义开关

功能说明:创建一个带有动画效果的自定义开关组件。

代码实现

// 自定义开关组件
struct CustomToggle: View {
    @Binding var isOn: Bool
    
    var body: some View {
        Button(action: {
            isOn.toggle()
        }) {
            HStack {
                Text(isOn ? "开启" : "关闭")
                    .font(.headline)
                Spacer()
                RoundedRectangle(cornerRadius: 20)
                    .fill(isOn ? .green : .gray)
                    .frame(width: 50, height: 30)
                    .overlay(
                        Circle()
                            .fill(.white)
                            .frame(width: 24, height: 24)
                            .offset(x: isOn ? 10 : -10)
                            .animation(.spring(), value: isOn)
                    )
            }
            .padding()
            .background(.white)
            .cornerRadius(10)
            .shadow(radius: 2)
        }
    }
}

使用示例

@State private var isEnabled = true

CustomToggle(isOn: $isEnabled)

1.3.6 自定义列表项

功能说明:创建一个带有图标、标题和副标题的列表项组件。

代码实现

// 自定义列表项组件
struct CustomListItem: View {
    let title: String
    let subtitle: String
    let imageName: String
    
    var body: some View {
        HStack(spacing: 15) {
            Image(systemName: imageName)
                .font(.title)
                .foregroundColor(.blue)
            VStack(alignment: .leading, spacing: 5) {
                Text(title)
                    .font(.headline)
                Text(subtitle)
                    .font(.subheadline)
                    .foregroundColor(.gray)
            }
            Spacer()
            Image(systemName: "chevron.right")
                .foregroundColor(.gray)
        }
        .padding()
        .background(.white)
        .cornerRadius(10)
        .shadow(radius: 2)
    }
}

使用示例

CustomListItem(
    title: "项目1",
    subtitle: "这是第一个项目",
    imageName: "circle.fill"
)

CustomListItem(
    title: "项目2",
    subtitle: "这是第二个项目",
    imageName: "square.fill"
)

1.4 自定义视图的最佳实践

  1. 命名规范:使用清晰、描述性的名称
  2. 参数设计:合理设计初始化参数,提供默认值
  3. 布局考虑:使用适当的布局容器和间距
  4. 可访问性:确保视图对所有用户可访问
  5. 性能优化:避免不必要的计算和重绘
  6. 文档注释:为组件添加清晰的文档注释

1.5 综合示例

功能说明:展示所有自定义组件的综合示例。

代码实现

import SwiftUI

struct CustomViewsDemo: View {
    @State private var toggleState = false
    
    var body: some View {
        ScrollView {
            VStack(spacing: 20) {
                // 标题
                Text("自定义视图")
                    .font(.largeTitle)
                    .fontWeight(.bold)
                    .foregroundColor(.blue)
                
                // 1. 自定义按钮
                VStack {
                    Text("1. 自定义按钮")
                        .font(.headline)
                    CustomButton(title: "主要按钮") {
                        print("主要按钮被点击")
                    }
                    CustomButton(title: "次要按钮", style: .secondary) {
                        print("次要按钮被点击")
                    }
                }
                .padding()
                .background(Color.gray.opacity(0.1))
                .cornerRadius(10)
                
                // 2. 自定义卡片
                VStack {
                    Text("2. 自定义卡片")
                        .font(.headline)
                    CustomCard(
                        title: "SwiftUI 教程",
                        subtitle: "学习现代 UI 开发",
                        imageName: "swift"
                    )
                    CustomCard(
                        title: "高级特性",
                        subtitle: "自定义视图与动画",
                        imageName: "star.fill"
                    )
                }
                .padding()
                .background(Color.gray.opacity(0.1))
                .cornerRadius(10)
                
                // 3. 自定义进度条
                VStack {
                    Text("3. 自定义进度条")
                        .font(.headline)
                    CustomProgressBar(progress: 0.3)
                    CustomProgressBar(progress: 0.7, color: .green)
                }
                .padding()
                .background(Color.gray.opacity(0.1))
                .cornerRadius(10)
                
                // 4. 自定义徽章
                VStack {
                    Text("4. 自定义徽章")
                        .font(.headline)
                    HStack {
                        CustomBadge(text: "新")
                        CustomBadge(text: "热门", color: .red)
                        CustomBadge(text: "推荐", color: .green)
                    }
                }
                .padding()
                .background(Color.gray.opacity(0.1))
                .cornerRadius(10)
                
                // 5. 自定义开关
                VStack {
                    Text("5. 自定义开关")
                        .font(.headline)
                    CustomToggle(isOn: $toggleState)
                }
                .padding()
                .background(Color.gray.opacity(0.1))
                .cornerRadius(10)
                
                // 6. 自定义列表项
                VStack {
                    Text("6. 自定义列表项")
                        .font(.headline)
                    CustomListItem(
                        title: "设置",
                        subtitle: "应用偏好设置",
                        imageName: "gear"
                    )
                    CustomListItem(
                        title: "个人资料",
                        subtitle: "查看和编辑个人信息",
                        imageName: "person"
                    )
                }
                .padding()
                .background(Color.gray.opacity(0.1))
                .cornerRadius(10)
            }
            .padding()
        }
    }
}

#Preview {
    CustomViewsDemo()
}

1.6 总结

自定义视图是 SwiftUI 中非常强大的功能,通过创建可重用的组件,我们可以构建更加模块化、可维护的用户界面。在本章节中,我们学习了如何创建各种类型的自定义视图,包括按钮、卡片、进度条、徽章、开关和列表项等。

通过合理的设计和组织,自定义视图可以大大提高开发效率,同时保持代码的清晰性和可维护性。


参考资料


本内容为《SwiftUI 高级特性》第一章,欢迎关注后续更新。