在macOS上使用SwiftUI,如何在Button上使用自定义图片符号?

时间:2020-04-17 12:28:46

标签: swift macos swiftui

请仔细阅读问题,这是一个MAC应用程序,在Mac OS上无法使用systemName

我试图在macOS上使用swiftUI构建一个简单的应用程序,但是在显示一些图标时遇到了一些麻烦。

我现在到处都有阅读,您需要下载SF Symbols应用程序并自己导出符号才能使用它们,所以我做到了,然后将导出的符号添加到.xcassets中,现在我我试图用图像创建按钮,所以代码如下:

import SwiftUI

struct ActionBar: View {

    var body: some View {
        HStack {
            Spacer()
            Button(action: {

            }) {
                Image("Plus")
                    .font(Font.system(size: 24, weight: .light))
                    .foregroundColor(Color.red)
                Text("Test")
            }
        }
        .frame(maxWidth: .infinity)
        .padding()
        .background(Color.init(red: 0.8, green: 0.8, blue: 0.8))
    }
}

struct ActionBar_Previews: PreviewProvider {
    static var previews: some View {
        ActionBar()
    }
}

我尝试了许多变体,例如:

Image(nsImage: NSImage(name: "Plus"))

,但那里的所有信息,包括苹果自己的documentation都只谈论UIImage,据我所知,UIImage是UIKit的一部分,UIKit是UI框架的iOS版本,有人可以在macOS上使用?

非常感谢!

编辑:资产以Image Symbol Set的形式导入,Xcode不会引发任何错误,因为我只是将SF Symbols应用程序生成的svg放在了资产上。

编辑2:我刚遇到post,它表示对SVG的支持很奇怪...我尝试将SVG转换为PNG,但是xcode不接受png作为Symbols集合...此功能只是普通破解?真烂...

3 个答案:

答案 0 :(得分:5)

在MacOS中,没有可用的systemImages。但是NSImage.Name提供了替代选项。该link显示了大多数MacOS系统默认图标。

这是NSImage.Name的示例:

Icon(NSImage.refreshTemplateName)

以下是Icon视图定义:

struct Icon: View {
    var image: NSImage.Name
    var body: some View {
        Image(nsImage: NSImage(named: image)!)
            .renderingMode(.original)
            .resizable()
            .scaledToFit()
    }
    init(_ image: NSImage.Name){
        self.image = image
    }
}

P.S。 Image视图没有名为.font()的修饰符。请检查其文档以获取正确的语法。

编辑:您可以按照以下格式跳过额外的视图。

Image(nsImage: NSImage(name: NSImage.addTemplateName))

NSImage的列表。名称为here

答案 1 :(得分:1)

这是我的解决方案,但这在很大程度上是一个hack,我不知道Apple是否会批准。因此,我猜想这个答案是出于“教育目的”。

概念

主要思想是修改SF Symbols应用程序导出的SVG文件,使其仅包含所选符号的一个实例而不是完整模板,并使用SVGKit框架通过{{1 }}对象。

导出

在Mac上使用SF Symbols应用程序,然后选择要使用的符号,然后执行“导出自定义符号模板”。

修改

在文本编辑器(例如Sublime Text或CotEditor)中打开导出的SVG文件。

删除文件中除标题和“ Symbols”字段以外的所有内容,这些字段应仅包含要使用的符号变体。然后更改渲染的画布的大小,并正确对齐符号。

例如,如果要使用“ plus”符号的“ Regular-L”版本,则最终的“ plus.svg”文件应如下所示:

NSViewRepresentable

总结:

  • 保留标题
  • 保留<?xml version="1.0" encoding="UTF-8"?> <!--Generator: Apple Native CoreSVG 123--> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"> <!--glyph: "uni10017C.medium", point size: 100.000000, font version: "Version 15.0d7e11", template writer version: "5"--> <g id="Symbols"> <g id="Regular-L" transform="matrix(1 0 0 1 0 100)"> <path d="M 67.4316 17.3828 C 70.0684 17.3828 72.2168 15.2832 72.2168 12.7441 L 72.2168 -30.3711 L 114.062 -30.3711 C 116.65 -30.3711 118.848 -32.5684 118.848 -35.1562 C 118.848 -37.793 116.65 -39.9414 114.062 -39.9414 L 72.2168 -39.9414 L 72.2168 -83.1055 C 72.2168 -85.6445 70.0684 -87.7441 67.4316 -87.7441 C 64.8438 -87.7441 62.6953 -85.6445 62.6953 -83.1055 L 62.6953 -39.9414 L 20.8496 -39.9414 C 18.2617 -39.9414 16.0645 -37.793 16.0645 -35.1562 C 16.0645 -32.5684 18.2617 -30.3711 20.8496 -30.3711 L 62.6953 -30.3711 L 62.6953 12.7441 C 62.6953 15.2832 64.8438 17.3828 67.4316 17.3828 Z"/> </g> </g> </svg> 字段
  • 在“符号”字段中,仅保留一个类别,在我的示例中为id="Symbols"
  • 在示例中,更改标题的大小id="Regular-L"
  • 通过更改变换字段的最后两个参数来对齐符号,在我的示例中为width="128" height="128"(x 0和y 100)

安装SVGKit

发表看法

将修改后的transform="matrix(1 0 0 1 0 100)"文件添加到您的项目中(不在资产目录中,仅在项目本身中)

制作一个plus.svg结构,如下所示:

NSViewRepresentable

使用视图

然后在ContentView中使用它(给它一个框架,使其不会填满整个窗口),例如:

import SVGKit

struct IconView: NSViewRepresentable {

    let name: String

    func makeNSView(context: Context) -> SVGKFastImageView {
        let img = SVGKImage(named: name)!
        return SVGKFastImageView(svgkImage: img)!
    }

    func updateNSView(_ nsView: SVGKFastImageView, context: Context) {
        // not implemented
    }

}

答案 2 :(得分:0)

您不需要自己下载或导出符号,只需执行此操作,它就可以在ios和mac催化剂中运行:

import SwiftUI

struct ContentView: View {
var body: some View {
    HStack {
        Spacer()
        Button(action: {

        }) {
            Image(systemName: "plus")
                .font(Font.system(size: 24, weight: .light))
                .foregroundColor(Color.red)
            Text("Test")
        }
    }
    .frame(maxWidth: .infinity)
    .padding()
    .background(Color.init(red: 0.8, green: 0.8, blue: 0.8))
}
}