Дизайн и прототипирование
Дизайн-система в SwiftUI
В двух словах, дизай-система нужна нам для того, чтобы обеспечить единый внешний вид и восприятие различных продуктов на разных платформах, обеспечивая бесшовный пользовательский опыт.
Что такое дизайн-система?
Система дизайна (Design System) — это комплексный набор рекомендаций, компонентов и инструментов, которые используются для создания последовательных и целостных пользовательских интерфейсов на разных платформах и в разных продуктах. Она служит единым источником истины для дизайна и разработки, помогая командам поддерживать единый внешний вид и ощущение от своих продуктов.
В двух словах, дизай-система нужна нам для того, чтобы обеспечить единый внешний вид и восприятие различных продуктов на разных платформах, обеспечивая бесшовный пользовательский опыт.
Благодаря согласованности мы можем получить эффективность, которая ускоряет процесс проектирования и разработки за счет предоставления многократно используемых компонентов и шаблонов.
Улучшение сотрудничества между дизайнерами и разработчиками получается за счет предоставления общего языка и набора инструментов, уменьшения недопонимания и обеспечения согласованности.
OK, нам нужно внедрить систему проектирования в наш проект. Сделаем это на примере. Шаблон дизайна я взял из Figma Free Mobile App Template. Для этого проекта я выбрал приложение Podcast.
Для создания системы дизайна нам нужно создать такие основы, как цвет, типографика и интервалы.
Дизайн-система
Цвета
Для цвета я использую Ассеты, в которых объявляю все цвета, которые мне нужны, как на картинке ниже:
Цвета
Затем мы создаем расширение для работы с цветовыми маркерами:
import SwiftUI
public extension Color {
static let accent1 = Color("Accent 1", bundle: .module)
static let accent2 = Color("Accent 2", bundle: .module)
static let accent3 = Color("Accent 3", bundle: .module)
static let grayScale1 = Color("Grayscale 1", bundle: .module)
static let grayScale2 = Color("Grayscale 2", bundle: .module)
static let grayScale3 = Color("Grayscale 3", bundle: .module)
static let grayScale4 = Color("Grayscale 4", bundle: .module)
static let grayScale5 = Color("Grayscale 5", bundle: .module)
}
Я знаю, что названия цветов все еще могут путаться, но пока мы просто создадим подобие Podcast App Guidelines. Мы можем использовать его следующим образом:
xxxxxxxxxx
Color.accent1
Типографика
Для типографики нам нужно импортировать наш пользовательский шрифт в менеджер пакетов или проект:
Шрифты
После того как мы импортировали шрифт в наш проект, нам нужно создать класс и метод для регистрации пользовательского шрифта в приложении, это очень просто:
xxxxxxxxxx
import SwiftUI
public enum NotoSans: String, CaseIterable {
case thin = "NotoSans-Thin"
case bold = "NotoSans-Bold"
case light = "NotoSans-Light"
case black = "NotoSans-Black"
case medium = "NotoSans-Medium"
case regular = "NotoSans-Regular"
case semiBold = "NotoSans-SemiBold"
case extraBold = "NotoSans-ExtraBold"
case extraLight = "NotoSans-ExtraLight"
}
public struct NotoSansFont {
public static func registerFonts() {
NotoSans.allCases.forEach {
registerFont(bundle: .module, fontName: $0.rawValue, fontExtension: "ttf")
}
}
fileprivate static func registerFont(bundle: Bundle, fontName: String, fontExtension: String) {
guard let fontURL = bundle.url(forResource: fontName, withExtension: fontExtension),
let fontDataProvider = CGDataProvider(url: fontURL as CFURL),
let font = CGFont(fontDataProvider) else {
fatalError("Couldn't ceate font from filename: \(fontName) with extension \(fontExtension)")
}
var error: Unmanaged<CFError>?
CTFontManagerRegisterGraphicsFont(font, &error)
}
}
Объявите здесь все типы вашего шрифта, после чего создайте расширение для шрифта следующим образом:
xxxxxxxxxx
import SwiftUI
extension Font {
public static var h1: Font = {
return notoSans(.bold, size: 36)
}()
public static var h2: Font = {
return notoSans(.semiBold, size: 24)
}()
public static var h3: Font = {
return notoSans(.medium, size: 18)
}()
public static var h4: Font = {
return notoSans(.medium, size: 14)
}()
public static var h5: Font = {
return notoSans(.medium, size: 12)
}()
public static var h6: Font = {
return notoSans(.regular, size: 12)
}()
public static func notoSans(_ font: NotoSans, size: CGFloat) -> Font {
return .custom(font.rawValue, size: size)
}
}
Чтобы использовать шрифт, мы можем просто сделать так:
xxxxxxxxxx
Text("Listen to the best Podcast")
.font(.h1)
.foregroundColor(.grayScale1)
Но мы можем еще больше упростить задачу с помощью ViewModifier:
xxxxxxxxxx
struct TitleStyle: ViewModifier {
func body(content: Content) -> some View {
content.font(.h1)
}
}
extension View {
public func titleStyle() -> some View {
modifier(TitleStyle())
}
}
Тогда мы можем применить шрифт следующим образом:
xxxxxxxxxx
Text("Listen to the best Podcast")
.foregroundColor(.grayScale1)
.titleStyle()
Интервалы
Для интервалов мы просто добавим следующее:
xxxxxxxxxx
public enum Spacing {
public static let small: CGFloat = 8
public static let medium: CGFloat = 16
public static let large: CGFloat = 32
public static let extrLarge: CGFloat = 64
}
Основание готово!
Далее мы перейдем к компонентам и просто создадим компонент кнопки.
Кнопка
В SwiftUI мы можем создать ButtonStyle, который может быть использован для всех кнопок.
Так как же его использовать?
На самом деле все очень просто, вы можете просто скопировать из моего кода:
xxxxxxxxxx
import SwiftUI
public struct PrimaryButtonStyle: ButtonStyle {
public init() {}
public func makeBody(configuration: Configuration) -> some View {
configuration.label
.font(.h4)
.padding(Spacing.medium)
.background(Capsule().fill(Color.accent1))
.foregroundColor(.white)
.scaleEffect(configuration.isPressed ? 0.95 : 1.0)
}
}
А как это использовать? Следующим образом:
xxxxxxxxxx
Button {
} label: {
Text("Create new account")
}
.buttonStyle(PrimaryButtonStyle())
Но мы можем сделать все более красивым, просто добавив такой код:
xxxxxxxxxx
extension ButtonStyle where Self == PrimaryButtonStyle {
public static var primary: Self { Self() }
}
Поэтому всякий раз, когда вы регистрируете ButtonStyle, вы просто вызываете его следующим образом:
xxxxxxxxxx
Button {
} label: {
Text("Create new account")
}
.buttonStyle(.primary)
Дайте мне 6 часов, чтобы срубить дерево, и первые 4 часа я потрачу на заточку топора.
Так и с дизайн-системой. Мы потратим 4 часа на заточку топора, это заняло больше половины времени, но это того стоило.
-
Видео и подкасты для разработчиков4 недели назад
Как устроена мобильная архитектура. Интервью с тех. лидером юнита «Mobile Architecture» из AvitoTech
-
Новости4 недели назад
Видео и подкасты о мобильной разработке 2025.10
-
Новости3 недели назад
Видео и подкасты о мобильной разработке 2025.11
-
Видео и подкасты для разработчиков2 недели назад
Javascript для бэкенда – отличная идея: Node.js, NPM, Typescript