Skip to content

布局案例

水果列表切换

swift
import SwiftUI

func myFood() -> String {
    return ["🍓", "🍒", "🍇", "🍉", "🍊", "🍐", "🍎", "🍌"].randomElement()!
}

struct ContentView: View {
    @State private var todat = myFood()

    var body: some View {
        VStack {
            Spacer() // 撑开
            Text("\(todat)") // html 框架
                .font(.system(size: 100)) // css 样式
                .padding()
            Spacer() // 撑开
            Button("今天吃啥?") {
                // 脚本
                todat = myFood()
            }
            .padding()
            .background(.teal)
            .foregroundColor(.white)
            .cornerRadius(30)
            Spacer() // 撑开
        }
        .padding()
    }
}

#Preview {
    ContentView()
}

增加心跳数量

swift
import SwiftUI

struct ContentView: View {
    @State var num = 12

    var body: some View {
        VStack {
            Spacer()

            Image(systemName: "heart")
                .font(.largeTitle)
                .padding()
                .foregroundColor(.white)
                .bold()
                // 设置背景
                .background {
                    Circle()
                        .fill(.pink)
                }
                .shadow(radius: 5)
                // 设置前景
                .overlay(alignment: .bottomTrailing) {
                    Circle()
                        .fill(.green)
                        .frame(width: 25, height: 25)
                }
                // 设置前景
                .overlay(alignment: .bottomTrailing) {
                    Text("\(num)")
                        .foregroundStyle(.white)
                        .frame(width: 25, height: 25)
                }

            Spacer()

            Button("增加数量") {
                num = num + 1
            }

            Spacer()
        }
    }
}

#Preview {
    ContentView()
}

水平垂直滚动

swift
import SwiftUI

struct ContentView: View {
    var body: some View {
        ScrollView(.vertical) {
            ScrollView(.horizontal) {
                HStack {
                    ForEach(1..<20) { index in
                        Text("\(index)")
                            .font(.largeTitle)
                            .padding()
                            .background(.orange)
                    }
                }
            }
            .scrollIndicators(.hidden) // 是否显示滚动指示器

            VStack {
                ForEach(1..<40) { index in
                    HStack {
                        Circle()
                            .fill(.red)
                            .frame(width: 20, height: 20)
                        Text("这是一个标题\(index)")
                    }
                }
            }
        }
        .defaultScrollAnchor(.top) // 模式开始滚动的位置
        .scrollIndicators(.hidden) // 是否显示滚动指示器
        .scrollContentBackground(.visible) // 滚动的时候是否显示键盘
    }
}

#Preview {
    ContentView()
}

Button 组件

swift
import SwiftUI

struct CustomButton: View {
    var title: String
    var color: Color
    var action: () -> Void

    var body: some View {
        Button(action: action) {
            Text(title)
                .foregroundColor(.white)
                .padding()
                .padding(.horizontal, 20)
                .background(color)
                .cornerRadius(8)
        }
    }
}

struct ContentView: View {
    var body: some View {
        VStack {
            CustomButton(title: "主要按钮", color: .blue) {
                print("主要按钮 点击了")
            }
            CustomButton(title: "成功按钮", color: .green) {
                print("成功按钮 点击了")
            }
            CustomButton(title: "危险按钮", color: .red) {
                print("危险按钮 点击了")
            }
        }
    }
}

#Preview {
    ContentView()
}
swift
import SwiftUI

struct ContentView: View {
    var body: some View {
        Spacer()
        Image(systemName: "swift")
            .font(.system(size: 300))
            .foregroundStyle(
                LinearGradient(
                    colors: [.yellow, .red],
                    startPoint: .topLeading,
                    endPoint: .bottomTrailing
                )
            )
            .shadow(radius: 15)
        Spacer()
    }
}

#Preview {
    ContentView()
}

筛选食物完整案例

包括筛选、添加喜欢、查看喜欢、滑动操作、我的页面、页面跳转、头像加载等功能

swift
import SwiftUI

let foods: [String] = ["🍒", "🍉", "🥒", "🌽", "🥬", "🥕", "🍅", "🍎", "🍐", "🍇", "🐗", "🍍", "🍈", "🍊", "🍃", "🥥", "🫘", "🎃", "🍳", "🥚", "🌳", "🍔", "🍕", "🥩", "🐮", "🐑", "🐷", "🐔", "🦆", "🍜", "🍚"]

var likeList: [String] = []

class LikeListViewModel: ObservableObject {
    @Published var likes: [String] = []

    func addLike(_ food: String) {
        likes.append(food)
    }

    func removeLike(at index: Int) {
        likes.remove(at: index)
    }
}

// 获取随机食物
func getFoods() -> String {
    return foods.randomElement() ?? "未找到"
}

// 首页
struct HomePage: View {
    @State var activeFood = getFoods()
    @State private var showAlert = false
    @ObservedObject var likeListViewModel: LikeListViewModel

    var body: some View {
        VStack {
            Spacer()
            Text(activeFood)
                .font(.system(size: 150))

            Spacer()

            Button("筛选食物") {
                activeFood = getFoods()
            }
            .padding()
            .padding(.horizontal)
            .background(.blue)
            .foregroundColor(.white)
            .bold()
            .cornerRadius(16)

            Button("喜欢") {
                likeListViewModel.addLike(activeFood)
                showAlert = true
            }
            .alert(isPresented: $showAlert, content: {
                Alert(title: Text("提示"), message: Text("喜欢成功"), dismissButton: .default(Text("确定")))
            })
            .foregroundColor(.blue)
            .padding(.top, 20)

            Spacer()
        }
    }
}

// 喜欢页面
struct LovePage: View {
    // @Binding var fruits: [String]
    // @ObservedObject var likeListViewModel = LikeListViewModel()
    @ObservedObject var likeListViewModel: LikeListViewModel

    var body: some View {
        if !likeListViewModel.likes.isEmpty {
            List {
                ForEach(likeListViewModel.likes, id: \.self) { item in
                    Text("我喜欢的食物:\(item)")
                        .swipeActions(edge: .trailing, allowsFullSwipe: true) {
                            Button("删除") {
                                // Delete action
                                // LikeListViewModel.removeLike()
                            }
                            .tint(.red)
                            Button("置顶") {
                                // Top action
                            }
                            .tint(.orange)
                            Button("不显示") {
                                // Hide action
                            }
                            .tint(.blue)
                        }
                        .swipeActions(edge: .leading, allowsFullSwipe: false) {
                            Button("已完成") {
                                // Completed action
                            }
                            .tint(.black)
                        }
                        .badge("食物")
                }
                // .onDelete(perform: delete)
            }
        } else {
            Text("暂无喜欢内容")
        }
    }
}

struct MyDetail: View {
    @State var sttingItem: String

    var body: some View {
        NavigationView {
            VStack {
                Text(sttingItem)
            }
        }
        .navigationTitle(sttingItem)
    }
}

// 我的
struct MyPage: View {
    @State var infoOptions = ["账号设置", "联系客服", "通用设置"]

    var body: some View {
        // let imgSrc = URL(string: "https://picsum.photos/200")
        let imgSrc = URL(string: "https://finecare-fxk.fxkang.com/rich-text/image/2023-12-22/1187678699633860608.jpg")

        NavigationView {
            VStack {
                // AsyncImage(url: imgSrc) // 直接显示图片
                AsyncImage(url: imgSrc) { returnedImage in
                    returnedImage
                        .resizable()
                        // .scaledToFit()
                        .frame(width: 100, height: 100)
                        .cornerRadius(70)
                } placeholder: {
                    ProgressView() // loading 动画
                    Text("头像加载中")
                }

                Text("我的昵称")
                    .textSelection(.enabled) // 分享或复制

                List {
                    ForEach(infoOptions, id: \.self) { item in
                        NavigationLink(
                            destination: MyDetail(sttingItem: item), label: {
                                Text(item)
                            }
                        )
                    }
                }
                // .listStyle(GroupedListStyle())
                .navigationTitle("我的信息")
            }
        }
    }
}

struct ContentView: View {
    @StateObject var likeListViewModel = LikeListViewModel()

    var body: some View {
        TabView {
            HomePage(likeListViewModel: likeListViewModel)
                .tabItem {
                    Image(systemName: "house")
                    Text("首页")
                }

            LovePage(likeListViewModel: likeListViewModel)
                .tabItem {
                    Image(systemName: "heart.fill")
                    Text("喜欢")
                }

            MyPage()
                .tabItem {
                    Image(systemName: "person")
                    Text("我的")
                }
        }
    }

    func delete(indexSet: IndexSet) {
        print(indexSet)
    }
}

#Preview {
    ContentView()
}

TabView 标签页面切换 ß

swift
import SwiftUI

struct TabDemoView: View {
    @State var active = 0

    var body: some View {
        NavigationView {
            VStack {
                TabView(selection: $active) {
                    ScrollView {
                        Text("第0页")
                    }.tag(0)

                    ScrollView {
                        Text("第1页")
                    }.tag(1)

                    ScrollView {
                        Text("第2页")
                    }.tag(2)
                }
                .tabViewStyle(.page)
            }
        }
    }
}

#Preview {
    TabDemoView()
}

调用接口拿到数据展示

swift
import Alamofire
import SwiftUI

// Step 1: 创建一个 Model 来表示数据结构
struct CatImage: Identifiable, Decodable {
    let id: String
    let url: URL
    let width: Int
    let height: Int
}

struct Api {
    private let baseURL = "https://api.thecatapi.com/v1"

    private func http(url: String, callback: @escaping ([CatImage]) -> Void) {
        AF.request("https://api.thecatapi.com/v1\(url)")
            .responseDecodable(of: [CatImage].self) { response in
                if let images = response.value {
                    // 成功获取到响应数据
                    callback(images)
                } else if let error = response.error {
                    // 请求失败
                    print("Error fetching images: \(error)")
                    callback([])
                }
            }
    }

    func getList(callback: @escaping ([CatImage]) -> Void) {
        http(url: "/images/search?limit=10&page=1", callback: callback)
    }
}

struct DemoView: View {
    @State private var catImages: [CatImage] = []
    let API = Api()

    var body: some View {
        List(catImages) { catImage in
            VStack(alignment: .leading) {
                Text("ID: \(catImage.id)")
                    .aspectRatio(contentMode: .fit)
                Text("Width: \(catImage.width), Height: \(catImage.height)")
            }
        }
        .onAppear {
            API.getList { images in
                catImages = images
            }
        }
    }
}

#Preview {
    DemoView()
}