49961

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

<h3>Question</h3>

READ THE QUESTION CAREFULLY, THIS IS A MAC APP, systemName is not available on mac os

I'm trying to build a simple application using swiftUI on macOS, however I'm having some trouble displaying some icons.

I have now read everywhere that you need to download the SF Symbols app and export the symbols yourself in order to use them, so I did that, then I added the exported symbol to the .xcassets and now I'm trying to create a button with an image, so here is the code:

<pre class="lang-swift prettyprint-override">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() } }

I have tried many variations, for example:

<pre class="lang-swift prettyprint-override">Image(nsImage: NSImage(name: "Plus"))

but all the information out there, including apples own documentation only talk about UIImage which as far as I understood is part of UIKit which is the iOS version of the UI framework, has anybody gotten this to work on macOS?

Thanks a lot!

Edit: the asset was imported as a Image Symbol Set, Xcode doesn't throw any errors as I just took the svg generated by the SF Symbols app and put it directly on the assets.

Edit 2: I just run into this post which states SVG support is wonky... I tried converting the SVG into a PNG, but xcode does not accept pngs as Symbol sets... so, I guess this feature is just plain broken? which sucks...


<h3>Answer1:</h3>

<em>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.</em>

<h2>Concept</h2>

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.

<h2>Export</h2>

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

<h2>Modify</h2>

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:

<ul><li>Keep the header</li> <li>Keep the id="Symbols" field</li> <li>In the Symbols field, keep only one category, in my example id="Regular-L"</li> <li>Change the size in the header, in my example width="128" height="128"</li> <li>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)</li> </ul><h2>Install SVGKit</h2> <ul><li>Close Xcode</li> <li>Install SVGKit (https://github.com/SVGKit/SVGKit) using the Cocoapods version</li> <li>Open the .xcworkspace file made by Cocoapods</li> </ul><h2>Make a view</h2>

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 } } <h2>Use the view</h2>

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) } }
<h3>Answer2:</h3>

In MacOS, there are no systemImages available. But NSImage.Name prov ides the alternative option. This link show most of the MacOS system default icons.

This is an example of NSImage.Name :

Icon(NSImage.refreshTemplateName)

Following is the Icon view definition :

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 view does not have a modifier called .font(). Please check its documentation for proper syntax.

Edit: You can skip the extra view by following format.

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

The list of NSImage.Names are here


<h3>Answer3:</h3>

you don't need to download or export the symbols yourself, just do this, and it will work in ios and mac catalyst as well:

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)) } }

来源:https://stackoverflow.com/questions/61271693/swiftui-on-macos-how-to-use-custom-image-symbol-on-button

Recommend

  • How do I make an “empty” anonymous function in MATLAB?
  • Unable to load jqGrid using json in struts2
  • Added String to ArrayList not shown / not updated [duplicate]
  • adding a script tag dynamically with document.write
  • Could copy unsigned int bit values as float but float value not returned to the caller function corr
  • Sending/receiving text data from remote server in android [closed]
  • Azure classic cloud service cannot RDP
  • Does Firebase provide us all queries like Parse Database for Android?
  • How to extract details from the xml files using java?
  • Chaining Requests using BlueBird/ Request-Promise
  • How to receive GCM message when app is closed or in background?
  • System.IO.IOException: Too many open files
  • Caching of Google Cloud Endpoints?
  • How to set image in custom rounded corner image view in android
  • gmail does not render html in email
  • How to create 2 svg's on one page?
  • WooCommerce get order quantity in thank you page and redirect
  • Get max bookings count in range
  • Google Compute instance receiving email
  • VB.net Service Programming and using TCP Sockets
  • Smarter Removing Unnecessary WhiteSpace CSV
  • Pandas time series data Index from a string to float [duplicate]
  • Boolean filter using a timestamp value on a dataframe in Python
  • Fortran function variable length string return
  • AWS RDS Parameter Group not changing MySQL encoding
  • .Net core Hosted Services guaranteed to complete
  • Does hibernate load two seprate copies of same instance if they are loaded twice from database?
  • How to use Typescript with libraries like Ampersand.js that parse configs to build prototypes
  • Autocomplete source from project settings
  • 'Edit' function for forum posts and such
  • Stop an element moving with padding on hover
  • Add font awesome icon to custom add to cart button in Woocommerce 3
  • how to read to huge file into buffer
  • I am consuming a WCF service that requires headers from a .NET 2 website. How can I programmatically
  • How to specify generic type when the type is only known at runtime?
  • How to handle div that is created dynamically in a table
  • Did not understand process of initialize in swift programming
  • Google App Engine backend servlet not responding
  • How to encrypt Connectionstring written in web.config from codebehind?
  • Time Complexity of Fibonacci Algorithm [duplicate]