web-dev-qa-db-fra.com

SwiftUI sur macOS, comment utiliser le symbole d'image personnalisé sur Button?

LISEZ ATTENTIVEMENT LA QUESTION, CECI IS UNE APP MAC, systemName n'est pas disponible sur mac os

J'essaie de créer une application simple en utilisant swiftUI sur macOS, mais j'ai du mal à afficher certaines icônes.

J'ai maintenant lu partout où vous devez télécharger l'application SF Symbols et exporter vous-même les symboles afin de les utiliser, alors je l'ai fait, puis j'ai ajouté le symbole exporté au .xcassets et maintenant j'essaye de créer un bouton avec une image, voici donc le code:

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

J'ai essayé de nombreuses variantes, par exemple:

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

mais toutes les informations là-bas, y compris les pommes propres documentation ne parlent que de UIImage qui, pour autant que je sache, fait partie de UIKit qui est la version iOS du framework UI, est-ce que quelqu'un a réussi à faire fonctionner cela sur macOS ?

Merci beaucoup!

Modifier: l'élément a été importé en tant que Image Symbol Set, Xcode ne lance aucune erreur car je viens de prendre le svg généré par l'application SF Symbols et de le mettre directement sur les actifs.

Edit 2: Je viens de rencontrer ceci post qui indique que le support SVG est bancal ... J'ai essayé de convertir le SVG en PNG, mais xcode n'accepte pas les png comme jeux de symboles ... donc, je suppose cette fonctionnalité est tout simplement cassée? qui craint ...

3
Oscar

Voici ma solution, mais c'est vraiment un hack, et je ne sais pas si Apple l'approuverait. Alors considérez cette réponse pour "éducatif fins ", je suppose.

Concept

L'idée principale est de modifier le fichier SVG exporté par l'application SF Symbols afin qu'il ne contienne qu'une seule instance du symbole sélectionné au lieu du modèle complet, et d'utiliser le framework SVGKit pour l'afficher, via un NSViewRepresentable objet.

Exportation

Utilisez l'application SF Symbols sur votre Mac et sélectionnez le symbole que vous souhaitez utiliser, puis faites "Exporter le modèle de symbole personnalisé".

Modifier

Ouvrez le fichier SVG exporté dans un éditeur de texte, tel que Sublime Text ou CotEditor.

Supprimez tout ce qui se trouve dans le fichier sauf l'en-tête et le champ "Symboles", qui ne doivent contenir que la variante de symbole que vous souhaitez utiliser. Modifiez ensuite la taille du canevas rendu et alignez correctement le symbole.

Par exemple, si vous souhaitez utiliser la version "Regular-L" du symbole "plus", votre fichier final "plus.svg" devrait ressembler à ceci:

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

Pour résumer:

  • Gardez l'en-tête
  • Conservez le champ id="Symbols"
  • Dans le champ Symboles, ne gardez qu'une seule catégorie, dans mon exemple id="Regular-L"
  • Changer la taille dans l'en-tête, dans mon exemple width="128" height="128"
  • Alignez le symbole en modifiant les deux derniers paramètres du champ de transformation, dans mon exemple transform="matrix(1 0 0 1 0 100)" (x 0 et y 100)

Installez SVGKit

Faire une vue

Ajoutez le fichier plus.svg Modifié à votre projet (pas dans le catalogue des ressources, juste dans le projet lui-même)

Créez une structure NSViewRepresentable comme ceci:

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
    }

}

Utilisez la vue

Ensuite, utilisez-le dans votre ContentView (donnez-lui un cadre pour qu'il ne remplisse pas toute la fenêtre), par exemple:

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

vous n'avez pas besoin de télécharger ou d'exporter les symboles vous-même, faites simplement ceci, et cela fonctionnera également dans iOS et Mac Catalyst:

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