iOS/macOS - 绘制准备好由系统着色的 image/icon 的最佳方法

iOS/macOS - best way to draw an image/icon ready to be tinted by system

创建一组受操作系统影响的图标以显示彩色/重音版本的最佳方法是什么?

与;

我有大约 10 个黑色版本,但想用选定的或系统选择的强调色对它们进行调整。我应该如何处理我的图标才能让它们被 OS

着色

有路线图吗?

This code shows you how to add set an alternative icon based on iOS theme, and your settings bundle. I've also added accent1Icon and accent2Icon as examples.

在您的 Settings.bundle 中,您需要添加一个 Multi Value - App 项目到 Preference Items(Apple 要求用户可以更改主题,即使您根据他们的 iOS 自动设置它设置):

<dict>
    <key>Type</key>
    <string>PSMultiValueSpecifier</string>
    <key>Values</key>
    <array>
        <string>0</string>
        <string>1</string>
        <string>2</string>
        <string>3</string>
        <string>4</string>
    </array>
    <key>Title</key>
    <string>App Icon Theme</string>
    <key>Key</key>
    <string>app_icon_theme</string>
    <key>DefaultValue</key>
    <string>0</string>
    <key>Titles</key>
    <array>
        <string>Use iOS Theme</string>
        <string>Dark Theme</string>
        <string>Light Theme</string>
        <string>Accent1 Theme</string>
        <string>Accent2 Theme</string>
    </array>
</dict>

创建一个至少具有您的 app_icon_theme 设置的 class:

class SettingsBundleHelper {
    struct SettingsBundleKeys {
        static let AppIconThemeKey = "app_icon_theme"
    }
}

将此添加到您的 info.plist:

<dict>
    <key>CFBundleAlternateIcons</key>
    <dict>
        <key>darkIcon</key>
        <dict>
            <key>CFBundleIconFiles</key>
            <array>
                <string>name-of-dark-icon</string>
            </array>
            <key>UIPrerenderedIcon</key>
            <false/>
        </dict>
        <key>accent1Icon</key>
        <dict>
            <key>CFBundleIconFiles</key>
            <array>
                <string>name-of-accent1-icon</string>
            </array>
            <key>UIPrerenderedIcon</key>
            <false/>
        </dict>  
        <key>accent2Icon</key>
        <dict>
            <key>CFBundleIconFiles</key>
            <array>
                <string>name-of-accent2-icon</string>
            </array>
            <key>UIPrerenderedIcon</key>
            <false/>
        </dict>     
    </dict>
    <key>CFBundlePrimaryIcon</key>
    <dict>
        <key>CFBundleIconFiles</key>
        <array>
            <string>AppIcon</string>
        </array>
        <key>UIPrerenderedIcon</key>
        <false/>
    </dict>
</dict>

在您的项目中创建一个名为 Alternate Icons 的文件夹,并在其中保存 name-of-dark-icon@2x.png 和 name-of-dark-icon@3x.png。

YourProject 
|
+-- Alternate Icons (folder)
   |
   +-- name-of-dark-icon@2x.png
   +-- name-of-dark-icon@3x.png
   +-- name-of-accent1-icon@2x.png
   +-- name-of-accent1-icon@3x.png
   +-- name-of-accent2-icon@2x.png
   +-- name-of-accent2-icon@3x.png

您可以 运行 AppDelegate applicationDidBecomeActive(或其他地方)中的 changeIcon 代码。如果您选择 运行 它在那里,您需要将其添加到您的 AppDelegate 文件中:

enum AppIconTheme: String {
   case UseiOSTheme = "0"
   case DarkTheme = "1"
   case LightTheme = "2"
   case Accent1Theme = "3"
   case Accent2Theme = "4"
}

func applicationDidBecomeActive(_ application: UIApplication) {
// update icon if dark mode
if #available(iOS 12.0, *) {
    var theme = AppIconTheme.UseiOSTheme
    if let iconTheme = UserDefaults.standard.string(forKey: SettingsBundleHelper.SettingsBundleKeys.AppIconThemeKey) {
        if let themeSettings = AppIconTheme(rawValue: iconTheme) {
            theme = themeSettings
        }
    }
    print(theme as Any)
    switch (theme) {
        case .UseiOSTheme:
            if UIApplication.shared.windows[0].rootViewController?.traitCollection.userInterfaceStyle == .dark {
                self.changeIcon(to: "darkIcon")
            } else {
                self.changeIcon(to: nil)
            }
        case .LightTheme:
            self.changeIcon(to: nil)
        case .DarkTheme:
            self.changeIcon(to: "darkIcon")
        case .Accent1Theme:
            self.changeIcon(to: "accent1Icon")
        case .Accent2Theme:
            self.changeIcon(to: "accent2Icon")
        }
    } else {
        // Fallback on earlier versions
        var theme = AppIconTheme.UseiOSTheme
        if let iconTheme = UserDefaults.standard.string(forKey: SettingsBundleHelper.SettingsBundleKeys.AppIconThemeKey) {
            theme = AppIconTheme(rawValue: iconTheme)!
        }
        print(theme as Any)
        switch (theme) {
        case .UseiOSTheme:
            self.changeIcon(to: nil)
        case .LightTheme:
            self.changeIcon(to: nil)
        case .DarkTheme:
            self.changeIcon(to: "darkIcon")
        case .Accent1Theme:
            self.changeIcon(to: "accent1Icon")
        case .Accent2Theme:
            self.changeIcon(to: "accent2Icon")
        }
    }
}

func changeIcon(to name: String?) {
    //Check if the app supports alternating icons
    guard UIApplication.shared.supportsAlternateIcons else {
        return;
    }

    if UIApplication.shared.alternateIconName != name {
        //Change the icon to a specific image with given name
        // if name is nil, the app icon will be the default app icon
        UIApplication.shared.setAlternateIconName(name) { (error) in
             //After app icon changed, print our error or success message
             if let error = error {
                 print("App icon failed to due to \(error.localizedDescription)")
             } else {
                 print("App icon changed successfully.")
             }
        }
    }
}

Here is the documentation from Apple on setAlternativeIcon: https://developer.apple.com/documentation/uikit/uiapplication/2806818-setalternateiconname