IOS小組件(3):SwiftUI開發小組件布局入門


引言

  經過上一篇文章,我們已經可以在桌面上展示出一個小組件出來了,你肯定想小試牛刀,動手改一改,那我們就從改小組件的布局做起吧。本文不會講解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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM