【iOS】同サイズのWidgetをWidget Galley に並べる方法


WidgetBundle

WidgetBundleを利用することで、同サイズのWidgetや異なる種類のWidgetをWidgetGallery上に並べることができます。

通常のWidget表示

通常は下記のようにWidgetクラスを継承した構造体に対してmain属性を指定し、以下で言うTestWidgetをエントリーポイントに指定します。この方法ではIntentConfigurationのコンテントに指定したViewのみをWidgetGalleryに表示することしかできません。またsystemSmall、systemMedium、systemLargeのサイズごとにしかWidgetGalleryに表示できず、同サイズのWidgetを並べることはできません。

@main
struct TestWidget: Widget {
    var body: some WidgetConfiguration {
        IntentConfiguration(kind: "Test", intent: ConfigurationIntent.self, provider: Provider()) { entry in
            TestWidgetEntryView(entry: TestEntry(date: Date(), testHeader: entry.testHeader , testTitle: "", configuration: ConfigurationIntent()))
        }.configurationDisplayName("DisplayName")
        .description("Description")
        .supportedFamilies([.systemSmall,.systemMedium,systemLarge])
    }
}

WidgetBundleの利用

異なるWidgetや同サイズのWidgetをGalleryに表示するには、下記のようにWidgetBundleクラスを継承した構造体をmain属性でエントリーポイントに指定します。その構造体のbody内で別で定義したWidgetクラスを継承した構造体をインスタンス化することでWidgetGalleryに表示することができます。
異なるWidgetを表示したい場合は、表示したい順でインスタンス化します。
同サイズのWidgetを表示したい場合は、対象のWidgetのsupportedFamiliesを一つだけ選び、複数回そのWidgetをインスタンス化したらその分同サイズのWidgetが表示されます。

@main
struct TestWidgetBundle: WidgetBundle {
    var body: some Widget {
        // 異なるWidget
        test1Widget()
        test2Widget()

        // 同サイズのWidget(systemSmallが二つ表示される)
        test2Widget()
        test2Widget()
    }
}

struct test1Widget: Widget {
    var body: some WidgetConfiguration {
        IntentConfiguration(kind: "Test1", intent: ConfigurationIntent.self, provider: Provider()) { entry in
            TestWidgetEntryView(entry: TestEntry(date: Date(), testHeader: entry.testHeader , testTitle: "", configuration: ConfigurationIntent()))
        }.configurationDisplayName("DisplayName")
        .description("Description")
        .supportedFamilies([.systemSmall,.systemMedium,systemLarge])
    }
}

struct test2Widget: Widget {
    var body: some WidgetConfiguration {
        IntentConfiguration(kind: "Test2", intent: ConfigurationIntent.self, provider: Provider()) { entry in
            TestWidgetEntryView(entry: TestEntry(date: Date(), testHeader: entry.testHeader , testTitle: "", configuration: ConfigurationIntent()))
        }.configurationDisplayName("DisplayName")
        .description("Description")
        .supportedFamilies([.systemSmall])
    }
}