iOS Widget開發(fā)1:創(chuàng)建一個(gè)Widget Extension

了解Widget

官方學(xué)習(xí)WidgetKit Demo
Widgets顯示相關(guān)的、可瀏覽的內(nèi)容,允許用戶快速訪問你的App以獲取更多詳細(xì)信息。你的App可以提供多種小組件,讓用戶專注于對(duì)他們最重要的信息。
向你的應(yīng)用添加一個(gè)小組件需要少量的設(shè)置,以及一些關(guān)于你的用戶界面的配置和風(fēng)格的決定。小組件使用SwiftUI視圖顯示其內(nèi)容。有關(guān)詳細(xì)信息,請(qǐng)參見SwiftUI

添加一個(gè)Widget到你的App

Widget Extension模板為創(chuàng)建小組件提供了一個(gè)起點(diǎn)。一個(gè)Widget Extension可以包含多種類型的小組件。例如,一個(gè)體育應(yīng)用程序可能有一個(gè)小組件顯示團(tuán)隊(duì)信息,另一個(gè)小組件顯示比賽日程,這個(gè)例子一個(gè)Widget Extension包含了兩個(gè)組件。建議在一個(gè)Widget Extension中包含你的App所有小組件。
添加步驟如下:

  1. 在Xcode中打開你的項(xiàng)目,然后選擇 File > New > Target 。
  2. 從“Application Extension”組中,選擇“Widget Extension”,然后單擊“Next”。如下圖:


    1.png
  3. 然后,給小組件命令,如下:


    2.png
  4. 如果小組件提供用戶可配置的屬性,請(qǐng)選中include configuration intent復(fù)選框。
  5. 點(diǎn)擊Finish,會(huì)生成你們組件文件,如:AppWidget.swift、AppWidget.intentdefinition、Assets.xcassets、Info.plist 。如下圖:


    3.png

然后你可以運(yùn)行到iOS14的設(shè)備上看效果,會(huì)看到默認(rèn)的小時(shí)鐘組件。


IMG_0039.PNG

配置描述

widget extension模板提供了一個(gè)符合widget協(xié)議的初始widget實(shí)現(xiàn)。此小組件的body屬性決定小組件是否具有用戶可配置的屬性。有兩種配置:

  • StaticConfiguration:對(duì)于沒有用戶可配置屬性的小組件。例如,顯示一般市場(chǎng)信息的股市小組件,或顯示趨勢(shì)標(biāo)題的新聞小組件。
  • IntentConfiguration:對(duì)于具有用戶可配置屬性的小組件。你可以使用SiriKit自定義內(nèi)容來定義屬性。例如,需要一個(gè)城市的郵政編碼的天氣小組件,或者需要跟蹤號(hào)碼的包裹跟蹤小組件。
    要初始化配置,請(qǐng)?zhí)峁┮韵滦畔ⅲ?/li>
  1. Kind: 標(biāo)識(shí)小部件的字符串。這是一個(gè)你選擇的標(biāo)識(shí)符,應(yīng)該描述小部件所代表的內(nèi)容。
  2. Provider:一個(gè)符合TimelineProvider的對(duì)象,它生成一個(gè)時(shí)間軸,告訴WidgetKit何時(shí)呈現(xiàn)小組件。時(shí)間線包含您定義的自定義TimelineEntry類型。時(shí)間線條目標(biāo)識(shí)您希望WidgetKit更新小組件內(nèi)容的日期。包括小組件視圖需要在自定義類型中呈現(xiàn)的屬性。
  3. Placeholder View: WidgetKit第一次使用SwiftUI視圖呈現(xiàn)小組件。占位符是小組件的通用表示,沒有特定的配置或數(shù)據(jù)。
  4. Content Closure: 包含SwiftUI視圖的閉包。WidgetKit調(diào)用它來呈現(xiàn)小組件的內(nèi)容,從提供者傳遞一個(gè)TimelineEntry參數(shù)。
  5. Custom Intent: 定義用戶可配置屬性的自定義意圖。有關(guān)添加自定義更多信息,請(qǐng)參閱 Making a Configurable Widget。
    例如下面代碼顯示IntentConfiguration類型的組件:
@main
struct AppWidget: Widget {
    private let kind: String = "AppWidget" //小組件的標(biāo)識(shí)

    public var body: some WidgetConfiguration {
        IntentConfiguration(kind: kind, intent: ConfigurationIntent.self, provider: Provider(), placeholder: PlaceholderView()) { entry in
            AppWidgetEntryView(entry: entry)
        }
        .configurationDisplayName("My Widget") //小組件的名稱
        .description("This is an example widget.") //小組件的描述
        .supportedFamilies([.systemSmall, .systemMedium, .systemLarge]) //用戶選擇小部件、中版本或大版本的組件
    }
}

在上面代碼中,小組件使用PlaceholderView()作為占位符視圖,并在內(nèi)容閉包中使用AppWidgetEntryView。占位符視圖顯示小組件的通用表示,讓用戶大致了解小部件顯示的內(nèi)容。不要在占位符視圖中包含實(shí)際數(shù)據(jù)。例如,使用灰色框表示文本行,或使用灰色圓表示圖像。
Provider為小組件生成一個(gè)時(shí)間軸,當(dāng)每個(gè)時(shí)間軸條目的日期到達(dá)時(shí),WidgetKit調(diào)用content閉包來更新顯示小組件的內(nèi)容。
注意這個(gè)小組件上@main屬性的用法。此屬性指示AppWidget是小組件擴(kuò)展的入口點(diǎn),表示該擴(kuò)展包含一個(gè)小組件。

TimelineProvider

TimelineEntry為TimelineProvider提供數(shù)據(jù)信息來源,如下所示:

struct SimpleEntry: TimelineEntry {
    public let date: Date
    public let configuration: ConfigurationIntent
}

為了在窗口小組件庫中顯示小組件,WidgetKit要求提供者提供預(yù)覽快照。你可以通過檢查此 snapshot(for:with:completion:)方法中context的isPreview屬性來判斷小組件顯示情況。當(dāng)isPreview為true時(shí),WidgetKit會(huì)在widget庫中顯示你的widget。對(duì)于有網(wǎng)絡(luò)數(shù)據(jù)的話,你需要先提供一個(gè)默認(rèn)數(shù)據(jù)顯示快照。如下示例代碼:

struct Provider: IntentTimelineProvider {
    public func snapshot(for configuration: ConfigurationIntent, with context: Context, completion: @escaping (SimpleEntry) -> ()) {
        print(context.isPreview) //顯示widget的顯示情況
        let entry = SimpleEntry(date: Date(), configuration: configuration)
        completion(entry)
    }
}

WidgetKit框架要求我們用timeline(for:with:completion:)來控制刷新小組件的時(shí)間。

struct Provider: IntentTimelineProvider {
    public func snapshot(for configuration: ConfigurationIntent, with context: Context, completion: @escaping (SimpleEntry) -> ()) {
        print(context.isPreview) //顯示widget的顯示情況
        let entry = SimpleEntry(date: Date(), configuration: configuration)
        completion(entry)
    }

    public func timeline(for configuration: ConfigurationIntent, with context: Context, completion: @escaping (Timeline<Entry>) -> ()) {
        var entries: [SimpleEntry] = []

        // Generate a timeline consisting of five entries an hour apart, starting from the current date.
        let currentDate = Date()
        for hourOffset in 0 ..< 5 {
            let entryDate = Calendar.current.date(byAdding: .hour, value: hourOffset, to: currentDate)!
            let entry = SimpleEntry(date: entryDate, configuration: configuration)
            entries.append(entry)
        }

        // Create the timeline with the entry and a reload policy with the date
        // for the next update.
        let timeline = Timeline(entries: entries, policy: .atEnd)
        // Call the completion to pass the timeline to WidgetKit.
        completion(timeline)
    }
}

小組件的顯示內(nèi)容

小組件UI使用SwiftUI來編寫的,當(dāng)用戶從widget庫中添加你的widget時(shí),他們會(huì)從widget支持的組件中選擇特定的組件(小型、中型或大型),widget的內(nèi)容閉包必須能夠呈現(xiàn)widget支持的每個(gè)組件。根據(jù)組件類型可以不同的實(shí)現(xiàn),代碼示例如下:

struct AppWidgetEntryView : View {
    @Environment(\.widgetFamily) var family: WidgetFamily
    var entry: Provider.Entry
    
    //view使用@ViewBuilder聲明,因?yàn)樗褂玫膙iew類型不同。
    @ViewBuilder
    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)
        default:
            Text(entry.date, style: .time)
        }
    }
}

小組件顯示只讀信息,不支持交互元素,如滾動(dòng)元素或開關(guān)。

在一個(gè)Widget Extension創(chuàng)建多個(gè)小組件

要支持多個(gè)小組件,需要聲明一個(gè)符合WidgetBundle的結(jié)構(gòu),WidgetBundle在其body屬性中將多個(gè)小組件組合在一起。在這個(gè)Widget bundle結(jié)構(gòu)上添加@main屬性,告訴WidgetKit你的擴(kuò)展支持多個(gè)widget。代碼示例:

@main
struct AppWidgets: WidgetBundle {
    @WidgetBundleBuilder
    var body: some Widget {
        AppWidget()
        //可以繼續(xù)添加其它Widget
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容