ScrollViewReader/定位滚动视图, GeometryReader/获取视图更新参数, MultipleSheets/多个工作视图, Mask/五星评价视图 的使用

1. ScrollViewReader 定位滚动视图位置

  1.1 实现

/// 定位滚动视图
struct ScrollViewReaderBootcamp: View {
    @State var scrollToIndex: Int = 0
    @State var textFiledText: String  = ""
    
    var body: some View {
        VStack {
            TextField("Enter a # here...", text: $textFiledText)
                .padding(.horizontal)
                .frame(height: 55)
                .border(Color.gray)
                .padding(.horizontal)
                .keyboardType(.numberPad)
            
            Button("Scroll now") {
                // 添加动画
                if let index = Int(textFiledText){
                    scrollToIndex = index
                }
            }
            
            ScrollView {
                ScrollViewReader { proxy in
                    /// 循环
                    ForEach(0..<50) { index in
                        Text("This is item #\(index)")
                            .font(.headline)
                            .frame(height: 200)
                            .frame(maxWidth: .infinity)
                            .background(Color.white)
                            .cornerRadius(10)
                            .shadow(radius: 10)
                            .padding()
                            .id(index)
                    }
                    .onChange(of: scrollToIndex) { value in
                        withAnimation(.spring()){
                            // anchor 锚点 .top/.center
                            proxy.scrollTo(value, anchor: .top)
                        }
                    }
                }
            }
        }
    }
}

  1.2 效果图:

ScrollViewReader/定位滚动视图, GeometryReader/获取视图更新参数, MultipleSheets/多个工作视图, Mask/五星评价视图 的使用_第1张图片

2. GeometryReader 几何布局获取视图更新参数

  2.1 实现

/// 几何布局
struct GeometryReaderBootcamp: View {
    var body: some View {
        //geometryReader1
        geometryReader2
    }
    
    /// 获取百分比
    func getPercentage(geometry: GeometryProxy) -> Double{
        // 最大距离
        let maxDistance = UIScreen.main.bounds.size.width / 2
        print("maxDistance: \(maxDistance)")
        // 当前 X 点 .global: 全局坐标的位置
        let currentX = geometry.frame(in: .global).midX
        return Double(1 - (currentX / maxDistance))
    }
    
    /// 示例二
    var geometryReader2: some View{
        ScrollView(.horizontal, showsIndicators: false) {
            HStack{
                ForEach(0..<20) { index in
                    GeometryReader { geometry in
                        RoundedRectangle(cornerRadius: 20)
                            .rotation3DEffect(
                                Angle(degrees: getPercentage(geometry: geometry) * 40),
                                axis: (x: 0.0, y: 1.0, z: 0.0))
                    }
                    .frame(width: 300, height: 250)
                    .padding()
                }
            }
        }
    }
    
    /// 示例一
    var geometryReader1: some View{
        // 几何阅读器 解决横竖屏时,更新屏幕的宽度
        GeometryReader { geometry in
            HStack(spacing: 0) {
                Rectangle().fill(Color.red)
                //UIScreen.main.bounds.width
                    .frame(width: geometry.size.width * 0.66666)
                Rectangle().fill(Color.blue)
            }
            .ignoresSafeArea()
        }
    }
}

  2.2 效果图:

ScrollViewReader/定位滚动视图, GeometryReader/获取视图更新参数, MultipleSheets/多个工作视图, Mask/五星评价视图 的使用_第2张图片      ScrollViewReader/定位滚动视图, GeometryReader/获取视图更新参数, MultipleSheets/多个工作视图, Mask/五星评价视图 的使用_第3张图片

3. MultipleSheets 多个工作表单视图使用

  3.1 实现

// 模型
struct RandomModel: Identifiable{
    var id  = UUID().uuidString
    let title: String
}
// 1 - use a binding
// 2 - use multiple .sheets
// 3 - use $item

/// 多个工作表单视图传递 Model
struct MultipleSheetsBootcamp: View {
    //@State var selectedModel: RandomModel = RandomModel(title: "Starting Title")
    @State var selectedModel: RandomModel? = nil
    @State var showSheet:Bool = false
    @State var showSheet2: Bool = false
    
    var body: some View {
        //useBinding
        //useMultipleSheets
        useItem
    }
    
    /// 方式三 使用 Item
    private var useItem: some View{
        ScrollView {
            VStack(spacing: 20){
                ForEach(0..<50) { index in
                    Button(action: {
                        selectedModel = RandomModel(title: "\(index)")
                    }, label: {
                        Text("Button \(index)")
                            .frame(height: 150)
                            .frame(maxWidth: .infinity)
                            .background(Color.white.cornerRadius(10))
                            .padding(.horizontal)
                            .shadow(radius: 10)
                            .padding(.horizontal)
                    })
                }
            }
            .sheet(item: $selectedModel) { model in
                NextScreen(selectedModel: model)
            }
        }
    }
    
    // 方式二 使用多个表单视图
    private var useMultipleSheets: some View{
        VStack(spacing: 20){
            Button("Button 1") {
                showSheet.toggle()
            }
            .sheet(isPresented: $showSheet) {
                NextScreen(selectedModel: RandomModel(title: "One1"))
            }
            Button("Button 2") {
                showSheet2.toggle()
            }
            .sheet(isPresented: $showSheet2) {
                NextScreen(selectedModel: RandomModel(title: "Two2"))
            }
        }
    }
    
    // 方式一 使用 @Binding
    private var useBinding: some View{
        VStack(spacing: 20){
            Button("Button 1") {
                selectedModel = RandomModel(title: "One")
                showSheet.toggle()
            }
            Button("Button 2") {
                selectedModel = RandomModel(title: "Two")
                showSheet.toggle()
            }
        }
        .sheet(isPresented: $showSheet) {
            //NextScreen(selectedModel: $selectedModel)
        }
    }
}

// 下一个视图
struct NextScreen: View{
    // 使用 Binding 简单修复传递值问题
    // @Binding var selectedModel: RandomModel
    @State var selectedModel: RandomModel
    
    init(selectedModel: RandomModel) {
        self.selectedModel = selectedModel
        print(selectedModel.title)
    }
    
    var body: some View{
        Text("\(selectedModel.title)")
            .font(.largeTitle)
    }
}

  3.2 效果图:

ScrollViewReader/定位滚动视图, GeometryReader/获取视图更新参数, MultipleSheets/多个工作视图, Mask/五星评价视图 的使用_第4张图片

4. Mask 制作五星评价视图

  4.1 实现

// 五星评价制作遮盖修改器/蒙版组件
struct MaskBootcamp: View {
    @State var rating: Int = 2
    
    var body: some View {
        ZStack{
            satrtView
               .overlay(overlayView.mask(satrtView))
        }
    }
    
    // 覆盖 View
    private var overlayView: some View{
        // 使用几何读取器 获取宽度
        GeometryReader{ geometryProxy in
            ZStack(alignment: .leading) {
                Rectangle()
                    //.foregroundColor(.yellow)
                    .fill(LinearGradient(gradient: Gradient(colors: [Color.red, Color.blue]), startPoint: .leading, endPoint: .trailing))
                    .frame(width: CGFloat(rating) / 5 * geometryProxy.size.width)
            }
        }
        // 用户无法点击覆盖层/删除用户点击能力
        .allowsHitTesting(false)
    }
    
    // 开始的View
    private var satrtView : some View{
        HStack{
            ForEach(1 ..< 6) { index in
                Image(systemName: "star.fill")
                    .font(.largeTitle)
                    .foregroundColor(Color.gray)
                    .onTapGesture {
                        withAnimation(.easeInOut){
                            rating = index
                        }
                    }
            }
        }
    }
}

  4.2 效果图:

ScrollViewReader/定位滚动视图, GeometryReader/获取视图更新参数, MultipleSheets/多个工作视图, Mask/五星评价视图 的使用_第5张图片

你可能感兴趣的:(SwiftUI,Continued,Learning,iOS,Swift,UI)