1. ScrollViewReader positions the scroll view
1.1 Implementation
/// Position the scroll view 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") { // add animation if let index = Int(textFiledText){ scrollToIndex = index } } ScrollView { ScrollViewReader { proxy in /// Loop 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 anchor point .top/.center proxy.scrollTo(value, anchor: .top) } } } } } } }
1.2 Rendering:
2. GeometryReader geometry layout obtains view update parameters
2.1 Implementation
/// Geometric layout struct GeometryReaderBootcamp: View { var body: some View { //geometryReader1 geometryReader2 } /// Get the percentage func getPercentage(geometry: GeometryProxy) -> Double{ //maximum distance let maxDistance = UIScreen.main.bounds.size.width / 2 print("maxDistance: \(maxDistance)") //Current X point .global: the position of global coordinates let currentX = geometry.frame(in: .global).midX return Double(1 - (currentX / maxDistance)) } /// Example 2 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() } } } } /// Example 1 var geometryReader1: some View{ //Geometry reader updates the width of the screen when solving horizontal and vertical screens 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 Rendering:
3. Use of MultipleSheets multiple worksheet views
3.1 Implementation
//Model struct RandomModel: Identifiable{ var id = UUID().uuidString let title: String } // 1 - use a binding // 2 - use multiple .sheets // 3 - use $item /// Multiple work form views pass 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 } /// Method 3: Use 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) } } } // Method 2 Use multiple form views 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")) } } } // Method 1 Use @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) } } } // next view struct NextScreen: View{ // Use Binding to simply fix the problem of passing values // @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 Rendering:
4. Mask creates a five-star review view
4.1 Implementation
//Five-star evaluation production mask modifier/mask component struct MaskBootcamp: View { @State var rating: Int = 2 var body: some View { ZStack{ satrtView .overlay(overlayView.mask(satrtView)) } } // Overwrite View private var overlayView: some View{ // Use geometry reader to get width 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) } } // User cannot click on overlay/remove user click ability .allowsHitTesting(false) } //Start 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 } } } } } }