引言
經過上一篇文章,我們已經可以在桌面上展示出一個小元件出來了,你肯定想小試牛刀,動手改一改,那我們就從改小元件的佈局做起吧。本文不會講解Swift語法,如果是熟悉Flutter,Kotlin這種語言的,問題也不大。本文只講解小元件中常用的SwiftUI元件。
本文大綱
- 小元件佈局怎麼區分元件型號:大中小
- 常用基礎元件 Text Image
- 常用容器元件 ZStack VStack HStack
- 常用屬性:充滿父佈局 文字內部居中 等分剩餘空間(Spacer)
小元件佈局怎麼區分元件型號:大中小
struct Widget1EntryView : View {
// 這句程式碼能從上下文環境中取到小元件的型號
@Environment(\.widgetFamily) var family
// 元件資料
var entry: Provider.Entry
// 這個 body 中就是自己需要實現的元件佈局
var body: some View {
switch family {
case .systemSmall: // 小號
Text(entry.date, style: .time)
case .systemMedium: // 中號
Text(entry.date, style: .time)
case .systemLarge: // 大號
Text(entry.date, style: .time)
@unknown default:
Text(entry.date, style: .time)
}
}
}
常用基礎元件Text使用
Text("普通文字")
.font(.system(size: 15)) // 字型
.foregroundColor(Color(hexString: "#FF0000"))
// Text以日期作為引數時可以有以下多種使用方式,參考官網定義
// 重要:其中的.timer比較有用,可以用來做時鐘的重新整理
/// A predefined style used to display a `Date`.
public struct DateStyle {
/// A style displaying only the time component for a date.
///
/// Text(event.startDate, style: .time)
///
/// Example output:
/// 11:23PM
public static let time: Text.DateStyle
/// A style displaying a date.
///
/// Text(event.startDate, style: .date)
///
/// Example output:
/// June 3, 2019
public static let date: Text.DateStyle
/// A style displaying a date as relative to now.
///
/// Text(event.startDate, style: .relative)
///
/// Example output:
/// 2 hours, 23 minutes
/// 1 year, 1 month
public static let relative: Text.DateStyle
/// A style displaying a date as offset from now.
///
/// Text(event.startDate, style: .offset)
///
/// Example output:
/// +2 hours
/// -3 months
public static let offset: Text.DateStyle
/// A style displaying a date as timer counting from now.
///
/// Text(event.startDate, style: .timer)
///
/// Example output:
/// 2:32
/// 36:59:01
public static let timer: Text.DateStyle
}
IOS中的顏色RGB不是安卓的0-255,而是0-1,這裡寫了一個擴充函式支援十六進位制顏色字串
#if (arch(arm64) || arch(x86_64))
import Foundation
import SwiftUI
@available(iOS 13.0, *)
extension Color {
//#ARGB
init?(hexString: String) {
var hex = hexString;
guard hexString.starts(with: "#") else {
return nil
}
hex.remove(at: hexString.startIndex)
var value: UInt64 = 0
Scanner(string: hex).scanHexInt64(&value)
var a = 0xFF / 255.0
if hex.count > 7 {
a = Double(value >> 24) / 255.0
}
let r = Double((value & 0xFF0000) >> 16) / 255.0;
let g = Double((value & 0xFF00) >> 8) / 255.0;
let b = Double(value & 0xFF) / 255.0
self.init(red: Double(r), green: Double(g), blue: Double(b))
_ = self.opacity(Double(a))
}
}
常用基礎元件Image使用
// 訪問bundle中的資源
Image("imageName")
// 通過UIImage載入資料夾中的圖片資源
Image(uiImage: UIImage(contentsOfFile: "picPath") ?? UIImage())
.resizable()
.scaledToFill()
.clipped()
.colorMultiply(Color(hexString: config.textColor) ?? Color.white) // 重要:這個類似安卓中的colorFilter可以修改圖片顏色
.frame(width: 36, height: 36, alignment: .center)
常用容器元件ZStack使用,類似安卓裡面的FrameLayout,可以重疊佈局
ZStack {
Text("普通文字")
.font(.system(size: 15)) // 字型
.foregroundColor(Color(hexString: "#FF0000"))
Text(entry.date, style: .time)
}.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .top)
.background(Color(hexString: "#00FFFF"))
常用容器元件HStack使用,水平方向佈局
HStack {
Text("普通文字")
.font(.system(size: 15)) // 字型
.foregroundColor(Color(hexString: "#FF0000"))
Text(entry.date, style: .time)
}.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .center)
.background(Color(hexString: "#00FFFF"))
常用容器元件VStack使用,垂直方向佈局
VStack {
Text("普通文字")
.font(.system(size: 15)) // 字型
.foregroundColor(Color(hexString: "#FF0000"))
Text(entry.date, style: .time)
}.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .center)
.background(Color(hexString: "#00FFFF"))
充滿父佈局怎麼實現
.frame(maxWidth: .infinity, maxHeight: .infinity)
VStack {
Text("普通文字")
.font(.system(size: 15)) // 字型
.foregroundColor(Color(hexString: "#FF0000"))
Text(entry.date, style: .time)
}
.frame(maxWidth: .infinity, maxHeight: .infinity) // 充滿父佈局
.background(Color(hexString: "#00FFFF"))
文字內部居中(multilineTextAlignment)
.multilineTextAlignment(.center)
VStack {
Text("普通文字")
.font(.system(size: 15)) // 字型
.foregroundColor(Color(hexString: "#FF0000"))
Text(entry.date, style: .timer)
.multilineTextAlignment(.center) // 讓文字在Text內部居中
.background(Color(hexString: "#FFFF00"))
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color(hexString: "#00FFFF"))
等分剩餘空間(Spacer)
VStack {
Spacer()
Text("普通文字")
.font(.system(size: 15)) // 字型
.foregroundColor(Color(hexString: "#FF0000"))
Spacer()
Text(entry.date, style: .timer)
.multilineTextAlignment(.center)
.background(Color(hexString: "#FFFF00"))
Spacer()
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color(hexString: "#00FFFF"))
控制間距(spacing)
VStack(spacing: 10) {
Text("普通文字")
.font(.system(size: 15)) // 字型
.foregroundColor(Color(hexString: "#FF0000"))
Text(entry.date, style: .timer)
.multilineTextAlignment(.center)
.background(Color(hexString: "#FFFF00"))
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color(hexString: "#00FFFF"))
結語
關於小元件SwiftUI佈局就講這麼多,入個門差不多了,另外,小元件並不能使用全部的SwiftUI控制元件,只能使用一些基本的控制元件,更多詳情可以檢視官網 https://developer.apple.com/documentation/widgetkit/swiftui-views