Skip to main content

Widgets桌面小组件开发

·244 words·2 mins
IOS Widget Extension

系统要求
#

iOS 14及以上

三种显示模式
#

systemSmall(2x2)、systemMedium (4x2)、systemLarge(4x4)

创建Widget
#

官方文档: https://developer.apple.com/documentation/widgetkit/creating-a-widget-extension

创建方式1: Xcode > File > New > Target

创建方式2:Xcode > 选中项目工程 -> Editor > Add Target

信息填写:

  • Product Name : 除了不要直接命名Widget, 其他的任意,一般我们取名Widgets 或者应用名+Widgets, 比如:Widgets, MyAppWidgets , MusicAppWidgets等等
  • Team: 有团队就勾选,不勾选也可以在工程中去设置
  • Organization Identifier: 有就写你自己的组织名称,测试就随意写
  • 勾选:Include Live Activity、Include Control、Include Configuration App Intent

文件结构:

文件名是根据Product Name自动生成带这个前缀的文件名,假设我创建时的Product Name为 Widgets, 那么自动生成的文件名如下:

  • WidgetsBundle.swift : 入口文件
  • AppIntent.swift: 意图文件
  • Widgets.swift: 默认的示例文件,这个作为参考,自己可另外创建相同类型文件来自定义自己的Widget界面元素
  • WidgetsControl.swift :组件控制, 这个系统要求iOS18+才支持
  • WidgetsLiveActivity.swift: 灵动岛活动

示例说明:

我们以音乐播放器为示例,创建了项目

Widget入口文件
#

import WidgetKit
import SwiftUI

@main
struct WidgetsBundle: WidgetBundle {
    var body: some Widget {
        //可以添加最多5个Widget, 每个可以设置3个显示模式
        PlayerStandardWidget()
        //PlayerRichWidget()
        //PlayerOtherWidget()
        //WidgetsLiveActivity()
    }
}

在body中可以创建最多5个Widget, 每个可以设置3个显示模式

AppIntent意图文件
#

定义播放器三个操作意图:PlayerPlayPrevIntent、PlayerPlayPauseIntent、PlayerPlayNextIntent

import WidgetKit
import AppIntents

@available(iOS 17.0, *)
struct ConfigurationAppIntent: WidgetConfigurationIntent {
    static var title: LocalizedStringResource = "Configuration"
    static var description = IntentDescription("This is an example widget.")

    // An example configurable parameter.
    @Parameter(title: "Favorite Emoji", default: "😃")
    var favoriteEmoji: String
}

//以下为播放器的:播放上一首,播放暂停,播放下一首意图操作
@available(iOS 16, *)
struct PlayerPlayPrevIntent: AppIntent {
    static var title: LocalizedStringResource = "PlayerPlayPrevIntent"
    
    func perform() async throws -> some IntentResult {
      //触发移除后会自动调用这个方法,执行自己的操作事件逻辑
        AppGroupsShared.setValue("playPrev", forKey: DataKeys.udKey_control_command)
        return .result()
    }
}

@available(iOS 16.0, *)
struct PlayerPlayPauseIntent: AppIntent {
    static var title: LocalizedStringResource = "PlayerPlayPauseIntent"
    
    func perform() async throws -> some IntentResult {
    
        AppGroupsShared.setValue("togglePlayPause", forKey: DataKeys.udKey_control_command)
        return .result()
    }
}

@available(iOS 16, *)
struct PlayerPlayNextIntent: AppIntent {
    static var title: LocalizedStringResource = "PlayerPlayPauseIntent"
    
    func perform() async throws -> some IntentResult {
    
        AppGroupsShared.setValue("playNext", forKey: DataKeys.udKey_control_command)
        return .result()
    }
}

创建自定义Widget
#

新建一个 PlayerStandardWidget.swift的文件

刷新Widget方式
#

WidgetCenter.shared.reloadTimelines(ofKind:"XXX")
WidgetCenter.shared.reloadAllTimelines()

可以刷新指定widget, 也可以直接刷新所有。

参考资料
#

https://www.jianshu.com/p/40e438b40a0b

https://segmentfault.com/a/1190000037602578?utm_source=sf-related

官方示例下载参考
#

https://developer.apple.com/documentation/widgetkit/emoji-rangers-supporting-live-activities-interactivity-and-animations

https://developer.apple.com/documentation/swiftui/backyard-birds-sample

Pin
Author
Pin
A little bit about you