SwiftUI实现在子视图中改变父视图的背景色

PHOTO EMBED

Tue Feb 07 2023 12:09:14 GMT+0000 (Coordinated Universal Time)

Saved by @zelda #swift #swiftui

//
//  SelectBackgroundColorView.swift
//  ApiBox
//
//  Created by shiyanjun on 2023/2/6.
//

import SwiftUI

// 视图模型类
class SelectColorViewModel: ObservableObject {
    // 记录当前用户选中的颜色,默认值白色
    @Published var selectColor: Color = .white
}

struct SelectBackgroundColorView: View {
    // 是否显示滑窗,默认不显示
    @State var showSheet: Bool = false
    // 注入视图模型实例
    @EnvironmentObject var vm: SelectColorViewModel
    
    var body: some View {
        ZStack {
            // 用户设置的背景色
            vm.selectColor
            VStack {
                Spacer()
                Button {
                    // 点击按钮展示滑窗让用户选择颜色
                    showSheet.toggle()
                } label: {
                    Text("设置背景色")
                        .frame(maxWidth: .infinity)
                        .frame(height: 45)
                        .foregroundColor(.white)
                        .background(.black)
                        .cornerRadius(10)
                }
                .sheet(isPresented: $showSheet) {
                    SheetView()
                }
                Spacer()
            }
            .padding()
        }
        .edgesIgnoringSafeArea(.all)
    }
}

// 底部滑窗
struct SheetView: View {
    // 注入视图模型实例
    @EnvironmentObject var vm: SelectColorViewModel
    // 用于关闭滑窗
    @Environment(\.presentationMode) private var presentationMode
    
    // 可供用户选择的颜色数组
    private let colors: [Color] = [.red, .green, .blue, .purple, .orange, .pink, .brown, .cyan, .teal]
    
    var body: some View {
        VStack {
            Text("请选择一种颜色")
                .font(.headline)
                .foregroundColor(.white)
                .frame(maxWidth: .infinity)
                .frame(height: 100)
            HStack {
                // 循环展示所有颜色供用户选择
                ForEach(colors, id: \.self) { color in
                    Button {
                        // 记住用户选中的颜色
                        vm.selectColor = color
                        // 关闭滑窗
                        presentationMode.wrappedValue.dismiss()
                    } label: {
                        Circle()
                            .frame(width: 30, height: 30)
                            .foregroundColor(color)
                            .overlay {
                                Circle()
                                // 用描边标识用户选中了该颜色
                                .stroke(.white, lineWidth: vm.selectColor == color ? 1 : 0)
                                // 用放大效果突出用户选的颜色
                                    .scaleEffect(vm.selectColor == color ? 1.2 : 1)
                            }
                    }
                }
            }
            Spacer()
        }
        .background(.black)
    }
}

struct SelectBackgroundColorView_Previews: PreviewProvider {
    static var previews: some View {
        SelectBackgroundColorView()
            .environmentObject(SelectColorViewModel())
    }
}
content_copyCOPY