Native exports
One command turns glyphfox icons into real vector assets for Android, Jetpack Compose, iOS, SwiftUI and Flutter. Weight, corners, duotone, modifiers and fusions export as plain paths, and strokes stay strokes.
Overview
npx glyphfox export android home search file+check --out app/src/main/res npx glyphfox export compose --from icons.txt --package com.acme.icons --out app/src/main/java npx glyphfox export ios home search --out MyApp/Assets.xcassets npx glyphfox export swiftui home search --out MyApp npx glyphfox export flutter home search --out . npx glyphfox export android --all --weight 1.5 --corners sharp --out app/src/main/res
Pass icon names or any spec of the name syntax, a list file with --from (one name per line, # starts a comment) or --all for the whole set. The geometry is the one the web packages draw, so the same specs look the same everywhere:
| Target | Writes under --out | Use it as |
|---|---|---|
android | drawable/gf_NAME.xml | @drawable/gf_home, R.drawable.gf_home |
compose | PACKAGE/GlyphFox.kt and PACKAGE/NAME.kt | Icon(GlyphFox.Home, null) |
ios | GlyphFox.xcassets/gf-NAME.imageset | UIImage(named: "gf-home") |
swiftui | GlyphFox.swift and the catalog | Image(glyphfox: .home) |
flutter | assets/glyphfox/NAME.svg and lib/glyphfox.dart | GlyphFoxIcon(GlyphFoxIcons.home) |
Android
One VectorDrawable per icon in drawable/, so point --out at app/src/main/res. Strokes keep their width in viewport units, their round or square caps and joins, and never get a fill, so they scale with the drawable exactly like the SVG. The color is a tint: ?attr/colorControlNormal by default, so the icons follow the theme like the Material icons do.
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:pathData="M12,19.89 L4.41,12.3 A4.8,4.8,0,1,1,12,6.58 A4.8,4.8,0,1,1,19.59,12.3 Z"
android:strokeColor="@android:color/white"
android:strokeWidth="2"
android:strokeLineCap="round"
android:strokeLineJoin="round" />
</vector><ImageView
android:layout_width="24dp"
android:layout_height="24dp"
android:src="@drawable/gf_heart"
android:contentDescription="@string/favorite" />Pass a theme attribute or a color resource as --color (?attr/colorPrimary, @color/brand) to tint with it, or a hex color (#ff7a1a) to bake the color into the paths without a tint. Duotone layers are filled paths with fillAlpha, --mirror-rtl sets android:autoMirrored, and rotate and flips become a group around the center.
Jetpack Compose
GlyphFox.kt declares the GlyphFox object and every icon is an ImageVector extension property on it, built on first use and cached, in its own file. The files go to the package folder under --out, so point it at the Kotlin source root.
package com.acme.icons
val GlyphFox.Heart: ImageVector
get() {
if (_heart != null) {
return _heart!!
}
_heart = ImageVector.Builder(
name = "GlyphFox.Heart",
defaultWidth = 24.dp,
defaultHeight = 24.dp,
viewportWidth = 24f,
viewportHeight = 24f,
).apply {
path(
stroke = SolidColor(Color.Black),
strokeLineWidth = 2f,
strokeLineCap = StrokeCap.Round,
strokeLineJoin = StrokeJoin.Round,
) {
moveTo(12f, 19.89f)
lineTo(4.41f, 12.3f)
arcTo(4.8f, 4.8f, 0f, true, true, 12f, 6.58f)
arcTo(4.8f, 4.8f, 0f, true, true, 19.59f, 12.3f)
close()
}
}.build()
return _heart!!
}
private var _heart: ImageVector? = nullimport com.acme.icons.GlyphFox
import com.acme.icons.Heart
Icon(GlyphFox.Heart, contentDescription = "Favorite")
Icon(GlyphFox.Heart, contentDescription = null, tint = MaterialTheme.colorScheme.primary)
Image(GlyphFox.Heart, contentDescription = null) // keeps the exported color
GlyphFox.all.forEach { (name, vector) -> Icon(vector, contentDescription = name) }Each property is imported by name, like the Material icons. GlyphFox.all maps every exported name to its vector for pickers and previews. With code shrinking on, R8 removes the icons an app never uses, unless it reads GlyphFox.all.
iOS asset catalog
One image set per icon with the SVG, Preserve Vector Data and Render As Template Image, so the icons stay sharp at any size and take the tint color. Point --out at an existing catalog such as MyApp/Assets.xcassets to add the image sets to it (its own Contents.json is kept), or at a folder to get GlyphFox.xcassets.
{
"images" : [
{
"filename" : "gf-heart.svg",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"preserves-vector-representation" : true,
"template-rendering-intent" : "template"
}
}let heart = UIImageView(image: UIImage(named: "gf-heart")) heart.tintColor = .systemOrange
The SVG files carry concrete colors (black by default), which template rendering replaces with the tint. With a hex --color the catalog switches to original rendering so the color shows; --rendering template or original picks one explicitly, and --mirror-rtl marks the image sets to flip in right to left layouts.
SwiftUI
glyphfox export swiftui writes the same asset catalog plus GlyphFox.swift: an enum with one case per image set, Image(glyphfox:) and UIImage.glyphfox(_:) for UIKit.
public enum GlyphFox: String, CaseIterable, Sendable {
case heart = "gf-heart"
case `repeat` = "gf-repeat"
}
public extension Image {
init(glyphfox icon: GlyphFox, bundle: Bundle? = nil) {
self = Image(icon.rawValue, bundle: bundle).renderingMode(.template)
}
}Label { Text("Favorites") } icon: { Image(glyphfox: .heart) }
Image(glyphfox: .heart)
.resizable()
.frame(width: 32, height: 32)
.foregroundStyle(.orange)
.accessibilityLabel("Favorite")
ForEach(GlyphFox.allCases, id: \.self) { Image(glyphfox: $0) }Pass bundle: .module when the catalog lives in a Swift package.
Flutter
SVG files in assets/glyphfox/ and lib/glyphfox.dart with one constant per icon and a small GlyphFoxIcon widget on top of flutter_svg. Point --out at the app folder, then add the package and the assets to pubspec.yaml:
dependencies:
flutter_svg: ^2.0.0
flutter:
assets:
- assets/glyphfox/import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'glyphfox.dart'; Row(children: [ const GlyphFoxIcon(GlyphFoxIcons.heart), GlyphFoxIcon(GlyphFoxIcons.heart, size: 32, color: Colors.orange, semanticLabel: 'Favorite'), SvgPicture.asset(GlyphFoxIcons.heart), // the exported colors, no tint ])
GlyphFoxIcon follows the surrounding IconTheme for size and color like Icon does, tints the whole drawing (the duotone layer keeps its opacity) and is decorative unless it gets a semanticLabel. GlyphFoxIcons.values lists every exported path, and --assets moves the SVG folder.
Options
| Option | Targets | Default | Description |
|---|---|---|---|
specs | all | Names or specs such as file+check@tr, cloud&lock:side or heart/duotone. | |
--from | all | A list file: one name per line or separated by commas, # starts a comment. | |
--all | all | Every icon of the set. | |
--out | all | . | The project folder: res for android, the Kotlin source root for compose, a folder or an .xcassets catalog for ios and swiftui, the app folder for flutter. |
--size | all | 24 | Size in dp, points or logical pixels. Below 24 the stroke is optically compensated, as on the web. |
--weight | all | 2 | Stroke width from 1 to 3 on the 24 grid. |
--absolute-weight | all | Keeps the stroke at weight units at the export size. | |
--corners | all | round | round or sharp (square caps and miter joins). |
--variant | all | outline | outline or duotone. The solid style cuts lines out with masks, which VectorDrawable and ImageVector cannot draw, so it is refused. |
--color | all | tint | A hex color baked into the files. Android also takes a theme attribute or a color resource, used as the tint. |
--secondary-color, --secondary-opacity | all | color, 0.3 | Color and opacity of the duotone layer. |
--rotate, --flip-x, --flip-y | all | A transform around the center of the grid. | |
--mirror-rtl | all | Flips the icon in right to left layouts (autoMirrored, autoMirror, the image set direction). | |
--modifier, --modifier-corner | all | The same badge on every icon, like file+check. | |
--prefix | android, ios, swiftui | gf_, gf- | Prefix of the drawable or image set names. |
--package | compose | glyphfox | Kotlin package, also the folder under --out. |
--rendering | ios, swiftui | template | template or original; original is the default with a hex --color. |
--assets | flutter | assets/glyphfox | Folder of the SVG files and of the paths in the constants. |
Names and colors
A spec becomes a name on each platform: file+check@tr is gf_file_check_tr on Android, GlyphFox.FileCheckTr in Compose, gf-file-check-tr in the catalog and fileCheckTr in Swift and Dart. Two specs that end up with the same name are refused, and keywords are escaped (repeat becomes `repeat` in Swift).
Without --color every target follows the platform tint: colorControlNormal, LocalContentColor, the SwiftUI foreground style or IconTheme. With a hex color the color is baked in and stays: Android drops the tint, the catalog renders the original and GlyphFoxIcon keeps the exported colors unless it gets a color. Compose Icon() always tints, so use Image() or tint = Color.Unspecified to see the baked color.