SwiftUI知识点(三)

Stepper

import SwiftUI

struct StepperBootcamp: View {
    
    @State var stepperValue: Int = 10
    @State var widthValue: CGFloat = 0
    
    var body: some View {
        VStack{
            ///步长为1
            Stepper("Stepper:\(stepperValue)", value: $stepperValue)
            
            Rectangle()
                .frame(width: 100 + widthValue, height: 100)
                .cornerRadius(20)
            
            Stepper("Stepper:\(stepperValue)") {
                incrementWidth(amount: 10)
            } onDecrement: {
                incrementWidth(amount: -10)
            }

        }
        .padding()
    }
    
    func incrementWidth(amount: CGFloat){
        withAnimation {
            widthValue += amount
        }
    }
}

#Preview {
    StepperBootcamp()
}

在这里插入图片描述

Slider

可以将滑块线做成随着滑动距离而现实不同的颜色,超级炫酷~


import SwiftUI

struct SliderBootcamp: View {
    
    @State var sliderValue1: CGFloat = 0.0
    @State var sliderValue2: CGFloat = 0.0
    @State var sliderValue3: CGFloat = 50.0
    @State var sliderValue4: CGFloat = 50.0
    
    @State var myColor: Color = .red
    
    var body: some View {
        VStack {
            Text("value: \(sliderValue1)")
            Slider(value: $sliderValue1) {
                Text("\(sliderValue1)")
            }
            
            
            Text("value: \(sliderValue2)")
            //给个步长step
            Slider(value: $sliderValue2, in: 0...10, step: 2)
            
            
            Text("value: \(sliderValue3)")
            Slider(value: $sliderValue3, in: 0...100) {
                //改变的过程
                Text("123")
                
            } minimumValueLabel: {
                Text("0")
            } maximumValueLabel: {
                Text("100")
            } onEditingChanged: { (_) in
                myColor = .green
                myColor = .green.opacity(sliderValue3/100)
            }
            
            // 使用颜色插值从黑色到白色
            Text("滑动控制颜色变化")
            Color(white: sliderValue1)
                .frame(width: 100, height: 100)
                .cornerRadius(20)
            
            //滑动控制颜色变化
            Text("滑动控制颜色变化")
            Rectangle()
                .fill(Color(hue: sliderValue1, saturation: 1.0, brightness: 1.0))
                .frame(width: 100, height: 100)
                .cornerRadius(20)
            
            Slider(value: $sliderValue1, in: 0...1)
                .padding()
                .accentColor(Color(hue: sliderValue1, saturation: 1.0, brightness: 1.0))//颜色渐变
            Spacer()
            
            //自动变化颜色
            Text("自动颜色变化")
            Rectangle()
                .fill(Color(hue: sliderValue4, saturation: 1.0, brightness: 1.0))
                .frame(width: 100, height: 100)
                .cornerRadius(20)
            
        }
        
        .onAppear {
            Timer.scheduledTimer(withTimeInterval: 0.08, repeats: true) { _ in // 你也可以调节时间间隔
                withAnimation(Animation.linear(duration: 0.01)) { //确保颜色变化动画是线性的
                    self.sliderValue4 += 0.01
                    if self.sliderValue4 > 1.0 {
                        self.sliderValue4 = 0.0 // 重置以继续循环
                    }
                }
            }
        }
    }
}

#Preview {
    SliderBootcamp()
}


在这里插入图片描述

超级炫酷~

TabView

import SwiftUI

struct TabViewBootcamp: View {
    @State var selectedTabIndex: Int = 2
    
    var body: some View {
        
        TabView (selection: $selectedTabIndex){
            HomeView(selectedTabIndex: $selectedTabIndex)
                .tabItem {
                    Text("首页")
                    Image(systemName: "house.fill")
                }
                .tag(0)
            
            Text("浏览内容")
                .tabItem {
                    Text("浏览")
                    Image(systemName: "globe.asia.australia")
                }
                .tag(1)
            
            PersonView()
                .tabItem {
                    Text("我的")
                    Image(systemName: "person.fill")
                }
                .tag(2)
        }
        .tint(.orange)
        
    }
}

#Preview {
    TabViewBootcamp()
}

struct HomeView: View {
     
    @Binding var selectedTabIndex: Int
    
    var body: some View {
        ZStack{
            Color.red.ignoresSafeArea(.all, edges: .top)
            
            VStack{
                Text("首页")
                    .font(.largeTitle)
                    .foregroundStyle(.white)
                
                Button {
                    self.selectedTabIndex = 2
                } label: {
                    Text("跳转到我的页")
                        .foregroundStyle(.white)
                        .font(.title)
                }
                .padding()
                .background(.blue)
                .cornerRadius(10.0)

            }
        }
        
    }
}

struct PersonView: View {
    
    let icons: [String] = [
        "heart.fill", "globe", "house.fill", "person.fill"
    ]
    
    var body: some View {
        //必须加VStack,不然就凭空都了一个“我的”
        VStack{
            Text("我的内容")
            
            TabView {
                ForEach(icons, id: \.self) { item in
                    Image(systemName: item)
                        //可调节大小的
                        .resizable()
                        .foregroundStyle(.blue).opacity(0.8)
                        .padding(30)
                }
                
                Rectangle()
                    .foregroundStyle(.red)
                Rectangle()
                    .foregroundStyle(.green)
                Rectangle()
                    .foregroundStyle(.yellow)
            }
            //分页样式
            .tabViewStyle(PageTabViewStyle())
            .frame(maxWidth: .infinity, maxHeight: 400)
            .cornerRadius(10)
            
            //背景色
            .background(
                ///渐变色
                ///gradient:渐变的颜色
                ///center: 位置
                ///startRadius开始的长度,endRadius结束的长度
                RadialGradient(gradient: Gradient(colors: [.red, .green, .yellow]), center: .topLeading, startRadius: 0.0, endRadius: 500.0)
            )
        }
    }
}

在这里插入图片描述

DarkModel

深色模式适配

黑白是不适应的,即黑色在暗黑模式下黑色背景下不显示、白色在正常模式白色背景下不显示
其他颜色,比如红、黄、绿,在这两种模式下都可以显示

可以在Assets文件夹下,建立自定义颜色(两种模式下都有颜色),从而达到一种颜色值,两种不同的显示

也可以在本地做判断,利用@Environment(\.colorScheme) var colorScheme,然后判断当前模式是.light还是.dark,来设置颜色


import SwiftUI

struct DarkModeBootcamp: View {
    
    @Environment(\.colorScheme) var colorScheme
    
    var body: some View {
        NavigationView{
            ScrollView{
                VStack{
                    Text("这个颜色是Primary")
                        .foregroundStyle(.primary)
                    Text("这个颜色是secondary")
                        .foregroundStyle(.secondary)
                    Text("这个颜色是black")
                        .foregroundStyle(.black)
                    Text("这个颜色是white")
                        .foregroundStyle(.white)
                    Text("这个颜色是red")
                        .foregroundStyle(.red)
                    Text("这个颜色是yellow")
                        .foregroundStyle(.yellow)
                    Text("这个颜色是green")
                        .foregroundStyle(.green)
                    Text("这个颜色是全局的自适应颜色(globally adaptive)")
                        .foregroundStyle(.adaptive)
                    Text("本地设置颜色")
                        .foregroundStyle(colorScheme == .light ? .black : .white)
                }
            }
            .navigationTitle("Dark Mode Bootcamp")
        }
        
        
    }
}

#Preview {
    DarkModeBootcamp()
}

在这里插入图片描述在这里插入图片描述

OnAppear

import SwiftUI

struct OnAppearBootcamp: View {
    
    @State var textString: String = "这是一个初始的字符串"
    @State var count: Int = 0
    var body: some View {
        
        
        NavigationView{
            ScrollView{
                Text(textString)
                
                LazyVStack{
                    ForEach(0..<50) { _ in
                        Rectangle()
                            .cornerRadius(30.0)
                            .frame(height: 300)
                            .padding()
                            .onAppear(perform: {
                                count += 1
                            })
                    }
                }
            }
            
            .onAppear(perform: {
                
                DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 5) {
                    textString = "这是onAppear后的字符串"
                }
            })
            
            .onDisappear(perform: {
                //view不显示的时候调用
            })
            
            .navigationTitle("On Appear \(count)")
        }
    }
}

#Preview {
    OnAppearBootcamp()
}

在这里插入图片描述

明明显示两个,count应该是2或者3,怎么是4呢???
没事,运行起来显示的就是2

TapGesture

import SwiftUI

struct TapGestureBootcamp: View {
    @State var isSelected: Bool = false
    
    var body: some View {
        
        VStack {
            Rectangle()
                .foregroundStyle(isSelected ? .red : .green)
                .cornerRadius(30)
                .frame(height: 200)
                .padding(.bottom, 20)
            
            Button(action: {
                isSelected.toggle()
            }, label: {
                Text("Button")
                    .foregroundStyle(.white)
                    .frame(height: 60)
                    .frame(maxWidth: .infinity)
                    .background(.blue)
                    .cornerRadius(5)
            })
            .padding(.bottom, 20)
            
            Text("Tap Gesture")
                .foregroundStyle(.white)
                .frame(height: 60)
                .frame(maxWidth: .infinity)
                .background(.blue)
                .cornerRadius(5)
                //添加tapGesture
                .onTapGesture {
                    isSelected.toggle()
                }
        }
        .padding(50)
        
        Spacer()
    }
}

#Preview {
    TapGestureBootcamp()
}

在这里插入图片描述

Model

import SwiftUI

struct UserModel: Identifiable {
    let id: String = UUID().uuidString
    let name: String
    let subName: String
    let isAuthentication: Bool
    let followCount: Int
}

struct ModelBootcamp: View {
    
    var userArray = [
        UserModel(name: "张三", subName: "zhangsan", isAuthentication: true, followCount: 100),
        UserModel(name: "李四", subName: "lisi", isAuthentication: false, followCount: 55),
        UserModel(name: "王五", subName: "wangwu", isAuthentication: false, followCount: 355),
        UserModel(name: "赵六", subName: "zhaoliu", isAuthentication: true, followCount: 88),
    ]
    
    var body: some View {
        NavigationView{
            List{
                ForEach(0..<userArray.count) { index in
                    HStack {
                        Circle()
                            .frame(width: 40, height: 40)
                            .foregroundColor(.yellow)
                        
                        VStack{
                            Text(userArray[index].name)
                                .font(.title2)
                            Text("@\(userArray[index].subName)")
                                .font(.caption)
                                .foregroundStyle(.gray)
                        }
                        
                        Spacer()
                        
                        if userArray[index].isAuthentication {
                            Image(systemName: "checkmark.seal.fill")
                                .foregroundColor(.blue)
                        }
                        
                        VStack{
                            Text("\(userArray[index].followCount)")
                                .font(.title2)
                            Text("Followers")
                                .font(.caption)
                                .foregroundStyle(.gray)
                        }
                    }
                    .padding(.vertical, 10)
                }
            }
            .navigationTitle("Users")
        }
    }
}

#Preview {
    ModelBootcamp()
}

在这里插入图片描述

ViewModel

@StateObject

监听对象的改变,并且在view刷新的时候,不会改变
在本view里面创建或者初始化

@ObservedObject

监听对象的改变,并且在view刷新的时候也会改变
传递到下一个view使用,则使用ObservedObject

import SwiftUI

struct FruitModel : Hashable, Identifiable{
    let id = UUID()
    let name: String
    let color: String
    let count: Int
}


class FruitViewModel: ObservableObject {
    @Published var fruitArray:[FruitModel] = []
    @Published var isLoading: Bool = false
    
    func getFruits(){
        let fruit1 = FruitModel(name: "apple", color: "green", count: 2)
        let fruit2 = FruitModel(name: "banana", color: "yellow", count: 1)
        let fruit3 = FruitModel(name: "grape", color: "purple", count: 100)
        let fruit4 = FruitModel(name: "orange", color: "orange", count: 5)
        
        isLoading = true
        DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 3.0) {
            self.fruitArray.append(fruit1)
            self.fruitArray.append(fruit2)
            self.fruitArray.append(fruit3)
            self.fruitArray.append(fruit4)
            self.isLoading = false
        }
    }
    
    func deleteFruit(index: IndexSet){
        fruitArray.remove(atOffsets: index)
    }
}

struct ViewModelBootcamp: View {
    
    //监听对象的改变,并且在view刷新的时候,不会改变
    //在本view里面创建或者初始化
    @StateObject var fruitViewModel: FruitViewModel = FruitViewModel()
    //监听对象的改变,并且在view刷新的时候也会改变
    //传递到下一个view使用,则使用ObservedObject
    //@ObservedObject var fruitViewModel: FruitViewModel = FruitViewModel()
    
    var body: some View {
        NavigationView{
            List{
                if fruitViewModel.isLoading{
                    ProgressView()
                }else{
                    ForEach(fruitViewModel.fruitArray) { item in
                        HStack {
                            
                            NavigationLink {
                                //下一个View的内容
                                SecondScreen(fruitViewModel: fruitViewModel, selectedFruitModel: item)
                            } label: {
                                Text("\(item.count)个")
                                    .foregroundStyle(.red)
                                
                                Text(item.name)
                                    .foregroundStyle(Color(wordName: item.color) ?? .black)
                            }
                        }
                        .font(.title)
                        
                        
                     }
                    .onDelete(perform: { indexSet in
                        fruitViewModel.deleteFruit(index: indexSet)
                    })
                }
            }
            
            .navigationTitle("Fruit List")
        }
        
        .onAppear{
            fruitViewModel.getFruits()
        }
        
//        .onAppear(perform: {
//            fruitViewModel.getFruits()
//        })
    }
}

struct SecondScreen: View {
    
    @Environment(\.presentationMode) var presentationModel
    //@Environment(\.isPresented) var isPresented
    
    @ObservedObject var fruitViewModel: FruitViewModel
    //不需要监听状态的改变,只是传值
    var selectedFruitModel: FruitModel
    
    var body: some View {
        ZStack {
            Color.blue.opacity(0.5).ignoresSafeArea()
            
            VStack{
                Text(selectedFruitModel.name)
                    .font(.largeTitle)
                    .foregroundStyle(Color(wordName: selectedFruitModel.color) ?? .white)
                
                
                Button(action: {
                    //返回
    //                isPresented = true
                    presentationModel.wrappedValue.dismiss()
                }, label: {
                    Text("Back")
                        .foregroundStyle(.black)
                        .font(.largeTitle)
                })
            }
        }
    }
}

#Preview {
    ViewModelBootcamp()
}

在这里插入图片描述在这里插入图片描述

Environment

import SwiftUI

class EnvironmentObjectViewModel: ObservableObject{
    @Published var dataArray: [String] = []
    
    init() {
        getData()
    }
    
    func getData(){
        self.dataArray.append(contentsOf: ["iPhone", "iPad", "iMac", "Apple Watch"])
    }
}

struct EnvironmentObjectBootcamp: View {
    @StateObject var viewMolde: EnvironmentObjectViewModel = EnvironmentObjectViewModel()
    
    var body: some View {
        NavigationView{
            List{
                
                ForEach(viewMolde.dataArray, id: \.self) { item in
                    NavigationLink {
                        SecondView(selectedItem: item)
                    } label: {
                        Text(item)
                    }
                }
            }
            .navigationTitle("iOS Devices")
        }
        ///在这写上后,后面所有的NavigationView的子view都有这个属性
        .environmentObject(viewMolde)
    }
}

struct SecondView: View {
    var selectedItem: String
    var body: some View{
        ZStack{
            Color.orange.ignoresSafeArea()
            NavigationLink {
                ThirdView()
            } label: {
                Text(selectedItem)
                    .font(.largeTitle)
                    .foregroundStyle(.orange)
                    .padding()
                    .background(.white)
                    .cornerRadius(30)
            }
        }
    }
}

struct ThirdView: View {
    //@EnvironmentObject 接收上面已经定义的属性
    @EnvironmentObject var viewModel: EnvironmentObjectViewModel
    var body: some View{
        ZStack {
            LinearGradient(gradient: Gradient(colors: [.red, .yellow, .green]),
                           startPoint: .leading,
                           endPoint: .trailing)
            .ignoresSafeArea()
            
            ScrollView{
                VStack(spacing: 20){
                    
                    ForEach(viewModel.dataArray, id: \.self) { item in
                        Text(item)
                    }
                }
                .foregroundColor(.white)
                .font(.largeTitle)
            }
        }
    }
}

#Preview {
    EnvironmentObjectBootcamp()
}

在这里插入图片描述在这里插入图片描述在这里插入图片描述

AppStorage

@AppStorage("age") var currentUserAge: Int?

import SwiftUI

struct AppStorageBootcamp: View {
    //方法一:使用UserDefaults.standard
    @State var currentUserName: String?
    
    //方法二:使用AppStorage
    @AppStorage("age") var currentUserAge: Int?
    
    var body: some View {
        Text(currentUserName ?? "Add Name Here")
        
        if let name = currentUserName{
            Text(name)
        }
        
        Button("Save".uppercased()){
            let name: String = "Nick"
            currentUserName = name
            currentUserAge = 100
            
            UserDefaults.standard.setValue(name, forKey: "name")
        }
        
        .onAppear(){
            currentUserName = UserDefaults.standard.value(forKey: "name") as? String
        }
        
        if let age = currentUserAge {
            Text("age = \(String(describing: age))")
        }
        
        
    }
}

#Preview {
    AppStorageBootcamp()
}

在这里插入图片描述

AsyncImage


import SwiftUI

struct AsyncImageBootcamp: View {
    let url = URL(string: "https://picsum.photos/200")
    
    var body: some View {
        VStack{
            AsyncImage(url: url)
                .frame(width: 100, height: 100)
                
            Spacer()
            AsyncImage(url: url) { Image in
                Image
            } placeholder: {
                ProgressView()
            }
            Spacer()
        }
    }
}

#Preview {
    AsyncImageBootcamp()
}

在这里插入图片描述

BackgroundMaterials

import SwiftUI

struct BackgroundMaterialsBootcamp: View {
    var body: some View {
        
        VStack{
            Spacer()
            
            VStack{
                RoundedRectangle(cornerRadius: 4)
                    .frame(width: 50, height: 4)
                    .padding()
                    
                Spacer()
            }
            .frame(maxWidth: .infinity)
            .frame(height: 300)
            .background(.thinMaterial)//设置磨砂效果
            .cornerRadius(30)
        }
        .ignoresSafeArea()
        .background(Image("dinner"))
    }
}

#Preview {
    BackgroundMaterialsBootcamp()
}

在这里插入图片描述

ButtonStyles

import SwiftUI

struct ButtonStylesBootcamp: View {
    var body: some View {
        VStack{
            Button("Button Title") {
            }
            .frame(height: 55)
            .frame(maxWidth: .infinity)
            .buttonStyle(.plain)
            
            Button("Button Title") {
            }
            .frame(height: 55)
            .frame(maxWidth: .infinity)
            .buttonStyle(.bordered)
            
            Button("Button Title") {
            }
            .frame(height: 55)
            .frame(maxWidth: .infinity)
            .buttonStyle(.borderedProminent)
            
            Button("Button Title") {
            }
            .frame(height: 55)
            .frame(maxWidth: .infinity)
            .buttonStyle(.borderless)
        }
    }
}

#Preview {
    ButtonStylesBootcamp()
}

在这里插入图片描述

ListSwipeActions

import SwiftUI

struct ListSwipeActionsBootcamp: View {
    
    @State var fruits: [String] = [
        "apple", "banana", "orange", "peach"
    ]
    
    var body: some View {
        VStack{
            List{
                
                ForEach(fruits, id: \.self) { item in
                    Text(item)
                        ///allowsFullSwipe:true允许拉很长然后触发按钮
                        .swipeActions(edge: .trailing, allowsFullSwipe: true){
                            Button("Archive"){
                                print("Archive")
                            }
                            .tint(.green)
                            
                            Button("Save"){
                                print("Save")
                            }
                            .tint(.blue)
                            
                            Button("Junk"){
                                print("Junk")
                            }
                            .tint(.black)
                        }
                    
                        .swipeActions(edge: .leading, allowsFullSwipe: true){
                            Button("Share"){
                                print("Share")
                            }
                            .tint(.yellow)
                        }
                    
                }
            }
            
        }
        
        Spacer()
    }
}

#Preview {
    ListSwipeActionsBootcamp()
}

在这里插入图片描述

Badges

import SwiftUI

struct BadgesBootcamp: View {
    var body: some View {
        ZStack{
            Color.yellow.ignoresSafeArea(.all)
            TabView{
                Color.red
                    .tabItem {
                        Image(systemName: "heart.fill")
                        Text("Hello")
                    }
                    .badge("NEW")
                
                Color.yellow
                    .tabItem {
                        Image(systemName: "heart.fill")
                        Text("Hello")
                    }
                    .badge(10)
                
                Color.green
                    .tabItem {
                        Image(systemName: "heart.fill")
                        Text("Hello")
                    }
                    .badge(120)
            }
        }
    }
}

#Preview {
    BadgesBootcamp()
}

在这里插入图片描述

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值