Swiftui on MACos, How to Use Custom Image Symbol on Button

SwiftUI on macOS, how to use custom image symbol on Button?

Here's my solution, but this is very much of a hack, and I don't know if Apple would approve it. So consider this answer for "educational purposes", I guess.

Concept

The main idea is to modify the SVG file exported by the SF Symbols app so that it only contains one instance of the selected symbol instead of the full template, and to use the SVGKit framework to display it, via an NSViewRepresentable object.

Export

Use the SF Symbols app on your Mac and select the symbol you want to use, then do "Export Custom Symbol Template".

Modify

Open the exported SVG file in a text editor, such as Sublime Text or CotEditor.

Delete everything in the file except the header and the "Symbols" field, which should only contain the symbol variation you want to use. Then change the size of the rendered canvas and also align the symbol properly.

For example, if you want to use the "Regular-L" version of the "plus" symbol, your final "plus.svg" file should be like this:

<?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>

To sum up:

  • Keep the header
  • Keep the id="Symbols" field
  • In the Symbols field, keep only one category, in my example id="Regular-L"
  • Change the size in the header, in my example width="128" height="128"
  • Align the symbol by changing the last two parameters of the transform field, in my example transform="matrix(1 0 0 1 0 100)" (x 0 and y 100)

Install SVGKit

  • Close Xcode
  • Install SVGKit (https://github.com/SVGKit/SVGKit) using the Cocoapods version
  • Open the .xcworkspace file made by Cocoapods

Make a view

Add the modified plus.svg file to your project (not in the assets catalog, just in the project itself)

Make an NSViewRepresentable struct like this:

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
}

}

Use the view

Then use it in your ContentView (give it a frame so that it doesn't fill up the whole window), for example:

struct ContentView: View {
var body: some View {
VStack {
IconView(name: "plus")
.frame(width: 200, height: 200, alignment: .center)
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
}
}

How to use Symbol Image with Image on macOS 15.15

Seems Symbol Image is not supported on macOS 15.15. The workaround I end up with is converting SF Symbol into SVG and then make them PDF before drag-and-drop in Assets.xcassets.

Sample Image

Use system icon in SwiftUI with macOS as button

Here it is

Image(nsImage: NSImage(named: NSImage.pathTemplateName)!)

How to increase the icon button of Menu in MacOS App SwiftUI?

Use ImageinText.

struct DetailView: View {
var body: some View {
Text("hello")
.contextMenu {
Button(action: { }) {
Text(Image(systemName: "gear"))
.font(.largeTitle)
}

Button(action: { }) {
Image(systemName: "gear")
}
}
}
}

SwiftUI: Correct syntax to add a custom Symbol image/SVG to a view?

You can create an Image from the traditional UIImage(named syntax

Image(uiImage: UIImage(named: "sausages")!)


Related Topics



Leave a reply



Submit