該備忘單提(ti)供了使用 的標(biao)簽的一些示例等
提供用于聲明應用程(cheng)序用戶界面(mian)的視圖、控件和布局(ju)結構
import SwiftUI
struct AlbumDetail: View {
var album: Album
var body: some View {
List(album.songs) { song in
HStack {
Image(album.cover)
VStack(alignment: .leading) {
Text(song.title)
}
}
}
}
}
要在(zai)UI中(zhong)顯(xian)示文本,只需編寫:
Text("Hello World")
添加樣式
Text("Hello World")
.font(.largeTitle)
.foregroundColor(Color.green)
.lineSpacing(50)
.lineLimit(nil)
.padding()
static let dateFormatter: DateFormatter = {
let formatter = DateFormatter()
formatter.dateStyle = .long
return formatter
}()
var now = Date()
var body: some View {
Text("Task due date: \(now, formatter: Self.dateFormatter)")
}
可以使用以下(xia)代碼行在文本(ben)旁(pang)邊(bian)設(she)置圖標。
Label("SwiftUI CheatSheet", systemImage: "up.icloud")
文檔 -
可(ke)以(yi)設置(zhi)URL,單(dan)擊后將重定向到瀏(liu)覽器。
Link("Click me", destination: URL(string: "your_url")!)
文檔 -
顯示與環境相關的圖(tu)像的視圖(tu)。
Image("foo") // 圖像名稱是foo
我們可以使用新的 SF Symbols
Image(systemName: "clock.fill")
您(nin)可以向系統(tong)圖標集添加樣式(shi)以匹(pi)配您(nin)使用的字體
Image(systemName: "cloud.heavyrain.fill")
.foregroundColor(.red)
.font(.title)
Image(systemName: "clock")
.foregroundColor(.red)
.font(Font.system(.largeTitle).bold())
為圖像添加樣式
Image("foo")
.resizable() // 調整大(da)小以(yi)便填充所有可用空間
.aspectRatio(contentMode: .fit)
文檔 -
創建矩形的步驟
Rectangle()
.fill(Color.red)
.frame(width: 200, height: 200)
創建圓的步驟
Circle()
.fill(Color.blue)
.frame(width: 50, height: 50)
文檔 -
顯示任務完(wan)成進度的視圖。
@State private var progress = 0.5
VStack {
ProgressView(value: progress)
Button("More", action: { progress += 0.05 })
}
通過應用 CircularProgressViewStyle
,可以將其用作 UIActivityIndicatorView
。
ProgressView(value: progress)
.progressViewStyle(CircularProgressViewStyle())
文檔 -
顯示指定區域的地圖
import MapKit
@State var region = MKCoordinateRegion(center: .init(latitude: 37.334722, longitude: -122.008889), latitudinalMeters: 300, longitudinalMeters: 300)
Map(coordinateRegion: $region)
您可以通過指定 interactionModes
(使用[]
禁(jin)用(yong)所有交互(hu))來控制(zhi)地(di)圖的交互(hu)。
struct PinItem: Identifiable {
let id = UUID()
let coordinate: CLLocationCoordinate2D
}
Map(coordinateRegion: $region,
interactionModes: [],
showsUserLocation: true,
userTrackingMode: nil,
annotationItems: [PinItem(coordinate: .init(latitude: 37.334722, longitude: -122.008889))]) { item in
MapMarker(coordinate: item.coordinate)
}
文檔 -
將圖像用作背景
Text("Hello World")
.font(.largeTitle)
.background(
Image("hello_world")
.resizable()
.frame(width: 100, height: 100)
)
以(yi)垂(chui)直(zhi)線排列其(qi)子(zi)項的視圖
VStack (alignment: .center, spacing: 20){
Text("Hello")
Divider()
Text("World")
}
創建靜(jing)態(tai)可滾動列表。文檔 -
將其子級排列在一條水平線上的視圖。
創建靜態可滾動列表
HStack (alignment: .center, spacing: 20){
Text("Hello")
Divider()
Text("World")
}
文檔 -
iOS 14
一種視圖(tu),將其子級排列在(zai)垂直增長的線中,僅在(zai)需要時創建項。
ScrollView {
LazyVStack(alignment: .leading) {
ForEach(1...100, id: \.self) {
Text("Row \($0)")
}
}
}
文檔 -
將子(zi)項排列在(zai)水平增長的線中的視圖,僅在(zai)需要時(shi)創建(jian)項。
ScrollView(.horizontal) {
LazyHStack(alignment: .center, spacing: 20) {
ForEach(1...100, id: \.self) {
Text("Column \($0)")
}
}
}
文檔 -
覆蓋(gai)其(qi)子項的視圖(tu),使子項在兩個軸上對齊。
ZStack {
Text("Hello")
.padding(10)
.background(Color.red)
.opacity(0.8)
Text("World")
.padding(20)
.background(Color.red)
.offset(x: 0, y: 40)
}
文檔 -
容器視(shi)圖,將其子視(shi)圖排列在垂直增(zeng)長(chang)的網格中,僅(jin)在需要時創建項目(mu)。
var columns: [GridItem] = Array(repeating: .init(.fixed(20)), count: 5)
ScrollView {
LazyVGrid(columns: columns) {
ForEach((0...100), id: \.self) {
Text("\($0)").background(Color.pink)
}
}
}
文檔 -
一種容器視(shi)圖,將其子視(shi)圖排列在水平增長的(de)網格中,僅在需要時創建項目。
var rows: [GridItem] =
Array(
repeating: .init(.fixed(20)), count: 2
)
ScrollView(.horizontal) {
LazyHGrid(rows: rows, alignment: .top) {
ForEach((0...100), id: \.self) {
Text("\($0)").background(Color.pink)
}
}
}
文檔 -
沿(yan)其(qi)包(bao)含的(de)堆棧布局(ju)的(de)主軸(zhou)或(huo)如(ru)果(guo)不包(bao)含在堆棧中的(de)兩個軸(zhou)上(shang)擴展的(de)靈活空間。
HStack {
Image(systemName: "clock")
Spacer()
Text("Time")
}
文檔 -
可用(yong)于分隔其他內容的視(shi)覺元素。
HStack {
Image(systemName: "clock")
Divider()
Text("Time")
}.fixedSize()
文檔 -
在打開(kai)和關閉狀態(tai)之(zhi)間(jian)切換(huan)的(de)控件。
@State var isShowing = true // toggle state
Toggle(isOn: $isShowing) {
Text("Hello World")
}
如果您的 Toggle
的標簽只有 Text
,則可以(yi)使用此更簡(jian)單的簽名進行初始化。
Toggle("Hello World", isOn: $isShowing)
文檔 -
在觸(chu)發時執行(xing)操(cao)作的控件。
Button(
action: {
print("did tap")
},
label: { Text("Click Me") }
)
如果 Button
的標簽僅為 Text
,則可以使用(yong)此(ci)更簡單的(de)簽名進(jin)行初始(shi)化(hua)。
Button("Click Me") {
print("did tap")
}
您可以通過此按鈕了解一下
Button(action: {
// 退出應用(yong)
NSApplication.shared.terminate(self)
}, label: {
Image(systemName: "clock")
Text("Click Me")
Text("Subtitle")
})
.foregroundColor(Color.white)
.padding()
.background(Color.blue)
.cornerRadius(5)
文檔 -
顯示可(ke)編輯(ji)文本界面(mian)的(de)控件。
@State var name: String = "John"
var body: some View {
TextField("Name's placeholder", text: $name)
.textFieldStyle(RoundedBorderTextFieldStyle())
.padding()
}
取消編輯框焦點樣(yang)式(shi)。
extension NSTextField { // << workaround !!!
open override var focusRingType: NSFocusRingType {
get { .none }
set { }
}
}
如何居中放置 TextField
的文本
struct ContentView: View {
@State var text: String = "TextField Text"
var body: some View {
TextField("Placeholder Text", text: $text)
.padding(.all, 20)
.multilineTextAlignment(.center)
}
}
文檔 -
用戶安全地輸入私人文本的(de)控件(jian)。
@State var password: String = "1234"
var body: some View {
SecureField($password)
.textFieldStyle(RoundedBorderTextFieldStyle())
.padding()
}
文檔 -
可(ke)以顯(xian)示(shi)和編輯長格式文(wen)本的視圖(tu)。
@State private var fullText: String = "這是一(yi)些(xie)可編輯的文(wen)本..."
var body: some View {
TextEditor(text: $fullText)
}
設置 TextEditor
背景顏色
extension NSTextView {
open override var frame: CGRect {
didSet {
backgroundColor = .clear
// drawsBackground = true
}
}
}
struct DetailContent: View {
@State private var profileText: String = "輸入您(nin)的簡歷"
var body: some View {
VSplitView(){
TextEditor(text: $profileText)
.background(Color.red)
}
}
}
文檔 -
日期選擇器(DatePicker)的樣式也會根據其祖先而改變。 在 Form
或 List
下,它顯(xian)示為單(dan)個列表(biao)行,您可以點擊以展(zhan)開(kai)到日(ri)期(qi)選擇(ze)器(qi)(就像日(ri)歷應用程序一樣)。
@State var selectedDate = Date()
var dateClosedRange: ClosedRange<Date> {
let min = Calendar.current.date(byAdding: .day, value: -1, to: Date())!
let max = Calendar.current.date(byAdding: .day, value: 1, to: Date())!
return min...max
}
NavigationView {
Form {
Section {
DatePicker(
selection: $selectedDate,
in: dateClosedRange,
displayedComponents: .date,
label: { Text("Due Date") }
)
}
}
}
在表格和列表的外部,它顯示為(wei)普通(tong)的輪(lun)式拾取器
@State var selectedDate = Date()
var dateClosedRange: ClosedRange<Date> {
let min = Calendar.current.date(byAdding: .day, value: -1, to: Date())!
let max = Calendar.current.date(byAdding: .day, value: 1, to: Date())!
return min...max
}
DatePicker(selection: $selectedDate, in: dateClosedRange,
displayedComponents: [.hourAndMinute, .date],
label: { Text("Due Date") }
)
如果 DatePicker
的標簽(qian)僅是(shi)純文本,則可以使用(yong)此更簡單的簽(qian)名進行(xing)初始(shi)化。
DatePicker("Due Date", selection: $selectedDate, in: dateClosedRange,
displayedComponents: [.hourAndMinute, .date])
可以使用 ClosedRange
,PartialRangeThrough
和 PartialRangeFrom
來設置 minimumDate
和 maximumDate
。
DatePicker("Minimum Date", selection: $selectedDate,
in: Date()...,
displayedComponents: [.date])
DatePicker("Maximum Date", selection: $selectedDate,
in: ...Date(),
displayedComponents: [.date])
文檔 -
用于(yu)從值(zhi)的(de)有(you)界線性范(fan)圍(wei)中選擇一(yi)個值(zhi)的(de)控件。
@State var progress: Float = 0
Slider(value: $progress,
from: 0.0,
through: 100.0,
by: 5.0)
滑塊缺少 minimumValueImage
和 maximumValueImage
,但是我們可以通過 HStack
輕松地復制它
@State var progress: Float = 0
HStack {
Image(systemName: "sun.min")
Slider(value: $progress,
from: 0.0,
through: 100.0,
by: 5.0)
Image(systemName: "sun.max.fill")
}.padding()
文檔 -
用(yong)于從一組互斥值(zhi)中進行選擇的(de)控件。
選擇器樣式的更改基于其祖先,在 Form
或 List
下,它顯示為單(dan)個列(lie)表(biao)行(xing),您可(ke)以點擊以進入(ru)一個顯示所(suo)有可(ke)能(neng)選項(xiang)的(de)新屏幕。
NavigationView {
Form {
Section {
Picker(selection: $selection,
label: Text("Picker Name"),
content: {
Text("Value 1").tag(0)
Text("Value 2").tag(1)
Text("Value 3").tag(2)
Text("Value 4").tag(3)
})
}
}
}
您可以使用 .pickerStyle(WheelPickerStyle())
覆蓋樣式。
@State var mapChoioce = 0
var settings = ["Map", "Transit", "Satellite"]
Picker("Options", selection: $mapChoioce) {
ForEach(0 ..< settings.count) { index in
Text(self.settings[index])
.tag(index)
}
}.pickerStyle(SegmentedPickerStyle())
在 SwiftUI
中,UISegmentedControl
只是 Picker
的另一種樣式。分段控制(SegmentedControl)在 iOS 13
中也煥(huan)然一新(xin)。文檔 -
用于執行語義遞增和(he)遞減操作的控件。
@State var quantity: Int = 0
Stepper(
value: $quantity,
in: 0...10,
label: { Text("Quantity \(quantity)")}
)
如果 Stepper
的標簽只有 Text
,則可(ke)以使用此更簡單的簽名進行初始化。
Stepper(
"Quantity \(quantity)",
value: $quantity,
in: 0...10
)
如果要完全控制,他們可以提供裸機步進器,您可以在其(qi)中管理(li)自己的數據源(yuan)。
@State var quantity: Int = 0
Stepper(onIncrement: {
self.quantity += 1
}, onDecrement: {
self.quantity -= 1
}, label: { Text("Quantity \(quantity)") })
如果您還為帶有 step
的(de)初始化(hua)程序的(de)每個步驟指定了(le)一個值的(de)數(shu)量。
Stepper(
value: $quantity, in: 0...10, step: 2
) {
Text("Quantity \(quantity)")
}
文檔 -
對于單次敲擊
Text("Tap me!").onTapGesture {
print("Tapped!")
}
用于雙擊
Text("Tap me!").onTapGesture(count: 2) {
print("Tapped!")
}
手勢如輕(qing)敲手勢、長按手勢、拖拉手勢
Text("Tap")
.gesture(
TapGesture()
.onEnded { _ in
// do something
}
)
Text("Drag Me")
.gesture(
DragGesture(minimumDistance: 50)
.onEnded { _ in
// do something
}
)
Text("Long Press")
.gesture(
LongPressGesture(minimumDuration: 2)
.onEnded { _ in
// do something
}
)
onChange 是一(yi)個新的視(shi)(shi)圖修改器,可用于(yu)所有 SwiftUI 視(shi)(shi)圖。它允許您偵聽狀態更(geng)改并相應地對視(shi)(shi)圖執(zhi)行操作
TextEditor(text: $currentText)
.onChange(of: clearText) { value in
if clearText{
currentText = ""
}
}
一個容器,用于顯示(shi)排(pai)列在(zai)單(dan)列中的數據行。創建靜態可滾動列表
List {
Text("Hello world")
Text("Hello world")
Text("Hello world")
}
let names = ["John", "Apple", "Seed"]
List(names) { name in
Text(name)
}
添加 Section
List {
Section(header: Text("UIKit"), footer: Text("We will miss you")) {
Text("UITableView")
}
Section(header: Text("SwiftUI"), footer: Text("A lot to learn")) {
Text("List")
}
}
List {
Text("Hello world")
Image(systemName: "clock")
}
添加 .listStyle(GroupedListStyle())
List {
Section(header: Text("UIKit"),
footer: Text("我們會想念你的")) {
Text("UITableView")
}
Section(header: Text("SwiftUI"),
footer: Text("要學的(de)東西很多")) {
Text("List")
}
}.listStyle(GroupedListStyle())
要使其插入分組(.insetGrouped
),請添加 .listStyle(GroupedListStyle())
并強制使用常規水平尺寸類 .environment(\.horizontalSizeClass, .regular)
。
List {
Section(header: Text("UIKit"), footer: Text("We will miss you")) {
Text("UITableView")
}
Section(header: Text("SwiftUI"), footer: Text("A lot to learn")) {
Text("List")
}
}.listStyle(GroupedListStyle())
.environment(\.horizontalSizeClass, .regular)
插圖分組已添加到
iOS 13.2
中的SwiftUI
在 iOS 14
中,我們(men)為此設置了(le)專(zhuan)用樣式。
.listStyle(InsetGroupedListStyle())
文檔 -
滾動視圖。
ScrollView(alwaysBounceVertical: true) {
Image("foo")
Text("Hello World")
}
文檔 -
NavigationView
或多或少類似于 UINavigationController
,它處(chu)理視圖之間(jian)的導航(hang),顯示標題,將導航(hang)欄放在頂部(bu)。
NavigationView {
Text("Hello")
.navigationBarTitle(Text("World"), displayMode: .inline)
}
大標題使用 .large
將條形圖項添加到導(dao)航視(shi)圖
NavigationView {
Text("Hello")
.navigationBarTitle(Text("World"), displayMode: .inline)
.navigationBarItems(
trailing:
Button(
action: { print("Going to Setting") },
label: { Text("Setting") }
)
)
}
按下時觸發導航演示的按鈕。這是 pushViewController
的替代品
NavigationView {
NavigationLink(destination:
Text("Detail")
.navigationBarTitle(Text("Detail"))
) {
Text("Push")
}.navigationBarTitle(Text("Master"))
}
或者通過將組目標添加到自己的視圖 DetailView
中,使其更具可讀性(xing)
NavigationView {
NavigationLink(destination: DetailView()) {
Text("Push")
}.navigationBarTitle(Text("Master"))
}
Group 創建多個(ge)視(shi)圖作為一個(ge)視(shi)圖,同時也避免了 Stack 的(de)10視(shi)圖最(zui)大(da)限制
VStack {
Group {
Text("Hello")
Text("Hello")
Text("Hello")
}
Group {
Text("Hello")
Text("Hello")
}
}
一個(ge)(ge)視圖(tu),允許使用可交互的用戶界面元素在多(duo)個(ge)(ge)子視圖(tu)之(zhi)間進行切換。
TabView {
Text("First View")
.font(.title)
.tabItem({ Text("First") })
.tag(0)
Text("Second View")
.font(.title)
.tabItem({ Text("Second") })
.tag(1)
}
圖像和文本在一起。 您可以在此處使用 SF Symbol
。
TabView {
Text("First View")
.font(.title)
.tabItem({
Image(systemName: "circle")
Text("First")
})
.tag(0)
Text("Second View")
.font(.title)
.tabItem(VStack {
Image("second")
Text("Second")
})
.tag(1)
}
或者您可以省略 VStack
TabView {
Text("First View")
.font(.title)
.tabItem({
Image(systemName: "circle")
Text("First")
})
.tag(0)
Text("Second View")
.font(.title)
.tabItem({
Image("second")
Text("Second")
})
.tag(1)
}
用于對用于數據輸入的(de)控件(jian)(例(li)如(ru)在(zai)設置或檢查器(qi)中)進行(xing)分組的(de)容器(qi)。
NavigationView {
Form {
Section {
Text("Plain Text")
Stepper(value: $quantity, in: 0...10, label: { Text("Quantity") })
}
Section {
DatePicker($date, label: { Text("Due Date") })
Picker(selection: $selection, label:
Text("Picker Name")
, content: {
Text("Value 1").tag(0)
Text("Value 2").tag(1)
Text("Value 3").tag(2)
Text("Value 4").tag(3)
})
}
}
}
您幾乎可以在此(ci)表單(dan)中(zhong)放(fang)入任何內(nei)容(rong),它(ta)將為表單(dan)呈現(xian)適當的樣式。文檔 -
Modal 過渡。我們可以(yi)顯示基于布(bu)爾的 Modal。
@State var isModal: Bool = false
var modal: some View {
Text("Modal")
}
Button("Modal") {
self.isModal = true
}.sheet(isPresented: $isModal, content: {
self.modal
})
文檔 -
警(jing)報演示的(de)容器。我們可(ke)以(yi)根據布爾值顯(xian)示Alert。
@State var isError: Bool = false
Button("Alert") {
self.isError = true
}.alert(isPresented: $isError, content: {
Alert(title: Text("Error"),
message: Text("Error Reason"),
dismissButton: .default(Text("OK"))
)
})
@State var error: AlertError?
var body: some View {
Button("Alert Error") {
self.error = AlertError(reason: "Reason")
}.alert(item: $error, content: { error in
alert(reason: error.reason)
})
}
func alert(reason: String) -> Alert {
Alert(title: Text("Error"),
message: Text(reason),
dismissButton: .default(Text("OK"))
)
}
struct AlertError: Identifiable {
var id: String {
return reason
}
let reason: String
}
文檔 -
操作表演示文稿的存儲類型。我們可以顯示基于布爾值的 ActionSheet
@State var isSheet: Bool = false
var actionSheet: ActionSheet {
ActionSheet(title: Text("Action"),
message: Text("Description"),
buttons: [
.default(Text("OK"), action: {
}),
.destructive(Text("Delete"), action: {
})
]
)
}
Button("Action Sheet") {
self.isSheet = true
}.actionSheet(isPresented: $isSheet,
content: {
self.actionSheet
})
@State var sheetDetail: SheetDetail?
var body: some View {
Button("Action Sheet") {
self.sheetDetail = ModSheetDetail(body: "Detail")
}.actionSheet(item: $sheetDetail, content: { detail in
self.sheet(detail: detail.body)
})
}
func sheet(detail: String) -> ActionSheet {
ActionSheet(title: Text("Action"),
message: Text(detail),
buttons: [
.default(Text("OK"), action: {
}),
.destructive(Text("Delete"), action: {
})
]
)
}
struct SheetDetail: Identifiable {
var id: String {
return body
}
let body: String
}
文檔 -