前言:
Swift知识点,大至看完了,公司项目是Swift语言写的,后续苹果新出的SwiftUI,也需要学习一下
不知觉间,SwiftUI是19年出的,现在24年,5年前的东西了
学习的几个原因:
- 项目工程里面有一部分SwiftUI的代码;
- 跟上脚步,学习新知识,给自己加分;
- Vision AR的开发语言是SwiftUI,以后想开发或者接触这些新东西,语言需要提前准备
这次学习,参考的是:B站SwiftUI Bootcamp (Beginner Level),一个歪果仁的课,讲的很不错~
struct ContentView: View {
//xxx
}
定义一个ContentView,继承View?
不对,联想swift,struct没有继承,难道swiftUI的结构体可以继承???
点击进去,看到View的定义:
public protocol View {
associatedtype Body : View
@ViewBuilder @MainActor var body: Self.Body { get }
}
原来,View被定义为了protocol协议
struct可以遵守协议,因此,上述写法不是继承,而是遵守协议。
UI介绍
Text介绍
import SwiftUI
import SwiftData
struct ContentView: View {
@Environment(\.modelContext) private var modelContext
@Query private var items: [Item]
var body: some View {
VStack {
Image("dinner")
.resizable()
.aspectRatio(contentMode: .fit)
Text("今天吃什么?")
.font(.largeTitle)//字体大小
.fontWeight(.semibold)//字体样式
.bold()//粗体
.underline(true, color: Color.red)//下划线
.italic()//斜线
.strikethrough(true, color: Color.green)//穿过线
.foregroundStyle(.purple)//颜色
//原来那一套,size设置字体大小,weight设置是bold还是什么样式,design设置自己的字体
Text("告诉我!")
.font(.system(size: 40, weight: .bold, design: .default))
Text("NSOperation 需要配合 NSOperationQueue 来实现多线程。因为默认情况下,NSOperation 单独使用时系统同步执行操作,配合 NSOperationQueue 我们能更好的实现异步执行。")
.multilineTextAlignment(.trailing)
.kerning(1)//左右间距调大
// .baselineOffset(20)//行间距调大:每一行,下面留20间距
.baselineOffset(-20)//行间距调大:每一行,上面留20间距
.frame(width: 200, height: 200, alignment: .center)//frame大小
.background(.gray)//背景颜色
}
}
}
#Preview {
ContentView()
.modelContainer(for: Item.self, inMemory: true)
}
形状UI介绍
Color介绍
var body: some View {
RoundedRectangle(cornerRadius: 25.0)
//填充颜色
//.fill(Color.red)
.fill(
//Color(UIColor.blue)
Color("CustomColor")//自定义颜色
)
.frame(width: 250, height: 100)
//阴影
.shadow(color: .gray, radius: 20, x: 0, y: 1)
}
渐变色
Frame
Background 和 OverLay
//
// BackgroundAndOverlayView.swift
// SwiftUI_Bootcamp_Learn_Code
//
// Created by SYZ on 2024/5/30.
//
import SwiftUI
struct BackgroundAndOverlayView: View {
var body: some View {
VStack{
Text("Hello, World!-1")
.background(.red)
Text("Hello, World!-2")
.background(
LinearGradient(gradient: Gradient(colors: [Color.red, Color.blue]), startPoint: .leading, endPoint: .trailing)
)
Text("Hello, World!-3")
.background(
Circle()
.fill(Color.blue)
)
Text("Hello, World!-4")
.frame(width: 120, height: 120)
.background(
Circle()
.fill(Color.blue)
)
.frame(width: 130, height: 130)
.background(){
Circle()
.fill(Color.red)
}
.padding(EdgeInsets(top: 0, leading: 0, bottom: 50, trailing: 0))
Text("Hello, World!-5")
.background(
Circle()
.fill(Color.blue)
.frame(width: 120, height: 120, alignment: .bottom)
)
.background(){
Circle()
.fill(Color.red)
.frame(width: 130, height: 130, alignment: .bottom)
}
.padding(EdgeInsets(top: 0, leading: 0, bottom: 105, trailing: 0))
Text("Hello, World!-6")
.background(
Circle()
.fill(LinearGradient(gradient: Gradient(colors: [Color.red, Color.blue]), startPoint: .leading, endPoint: .trailing))
.frame(width: 120, height: 120)
)
.background(){
Circle()
.fill(Color.red)
.frame(width: 130, height: 130)
}
.padding(EdgeInsets(top: 0, leading: 0, bottom: 60, trailing: 0))
Circle()
.fill(.pink)
.frame(width: 100, height: 100)
.overlay(
Text("1")
.font(.largeTitle)
.foregroundColor(.white)
)
//可以看出,添加的背景色,在后面,而使用overlay的Text在前面
.background(
Circle()
.fill(.purple)
.frame(width: 120, height: 120)
)
.padding(EdgeInsets(top: 0, leading: 0, bottom: 40, trailing: 0))
Image(systemName: "heart.fill")
.font(.system(size: 40))
.foregroundColor(.white)
.background(
Circle()
.fill(
LinearGradient(gradient: Gradient(colors: [Color.red, Color.blue]), startPoint: .leading, endPoint: .trailing)
)
.frame(width: 100, height: 100)
.shadow(color: Color.gray, radius: 10, x: 0.0, y: 10)
.overlay(
Circle()
.fill(.blue)
.frame(width: 35, height: 35)
.overlay(
Text("5")
.font(.headline)
.foregroundStyle(.white)
.shadow(color: .gray, radius: 10, x: 5.0, y: 5.0)
)
, alignment: .bottomTrailing)
)
}
}
}
#Preview {
BackgroundAndOverlayView()
}
Stack
VStack有两种创建方式:
VStack{}
VStack(alignment: .center, spacing: nil, content:{ })
第一种创建的时候,spacing是nil,有个8的大小,如果想不要间距,改为0即可
VStack:垂直方向
HStack:水平方向
ZStack:bottom-top方向
Padding And Spacer
Padding解决两两之间的间隔,或者本身自己预留 的间隔
Spacer主要解决平分等问题
ScrollView
Grid
struct LearnGridView: View {
let columns: [GridItem] = [
//.fixed:固定大小
GridItem(.fixed(50), spacing: nil, alignment: nil),//代表一列
GridItem(.fixed(150), spacing: nil, alignment: nil),
//.flexible:灵活的
//整分屏幕:如果只有一个,则整屏;如果有两个,则半屏;依次类推
//spacing:左右间距,即列间距
GridItem(.flexible(), spacing: nil, alignment: nil),
GridItem(.flexible(), spacing: nil, alignment: nil),
GridItem(.flexible(), spacing: nil, alignment: nil),
//.adaptive:自适应,以最小值为准,尽量多放
GridItem(.adaptive(minimum: 50, maximum: 120), spacing: nil, alignment: nil),
GridItem(.adaptive(minimum: 150, maximum: 120), spacing: nil, alignment: nil),
]
var body: some View {
ScrollView{
//LazyVGrid没有滚动属性,需要滚动的话,外面要包一个ScrollView
LazyVGrid(
columns: columns,
//居中
alignment: .center,
//上下间距,即行间距,默认是6
spacing: 1,
//.sectionHeaders:头,划过去不消失,还在前面显示
pinnedViews: [.sectionHeaders],
content: {
ForEach(0..<70) { index in
Rectangle()
.frame(height: 50)
.foregroundColor(.red)
}
})
.background(.gray)
}
}
}
SafeArea
struct SafeView: View {
var body: some View {
Text(/*@START_MENU_TOKEN@*/"Hello, World!"/*@END_MENU_TOKEN@*/)
.background(.red)
.frame(width: .infinity, height: .infinity)
Rectangle()
.frame(width: .infinity, height: .infinity)
.foregroundColor(.red)
//忽略安全区,本来不到顶,现在忽略顶部的安全区,则直接到顶
.ignoresSafeArea(.all, edges: .bottom)
//忽略所有的安全区
.ignoresSafeArea()
ScrollView{
VStack{
Text("This is title")
.font(.largeTitle)
.frame(maxWidth: .infinity, alignment: .leading)
ForEach(0..<10){ index in
RoundedRectangle(cornerRadius: 25)
.fill(.white)
.frame(height: 150)
.shadow(radius: 10)
.padding()
}
}
}
.background(.red)
}
}
Button
state
只需要在监听的var变量前,加上@state即可。告诉这个属性是可观察的,后面有地方改变,则所有用到的地方,都会被改变
太6了
extractSubView
import SwiftUI
struct LearnExtractSubView2: View {
var body: some View {
ZStack{
Color.blue
.ignoresSafeArea()
contentLay
}
}
var contentLay: some View {
HStack{
MyItem(count: 1, title: "apple", myColor: .red)
MyItem(count: 19, title: "orange", myColor: .orange)
MyItem(count: 33, title: "banana", myColor: .yellow)
}
}
}
struct LearnExtractSubView2_Previews: PreviewProvider {
static var previews: some View {
LearnExtractSubView2()
}
}
struct MyItem: View {
let count: Int
let title: String
let myColor: Color
var body: some View {
VStack{
Text("\(count)")
Text(title)
}
.padding()//增加间距
.background(myColor)
.cornerRadius(10)//加圆角
}
}