In diesem Kapitel lernen Sie , eine Farbkarte zu verwenden URLSession
und zu erstellen .ContextMenu
ColourAtla
App
Hintergrund des Projekts
Für traditionelle chinesische Farben gibt es seit langem eine besondere Gunst .
Beim Durchsuchen einiger Informationen sah ich einige von Bloggern veröffentlichte Inhalte zur Farbanpassung, die über das Konzept der Farbkarte sprachen . Nach einigem Verstehen und Lernen wollte ich eine Farbanpassungs-App erstellen .
Obwohl es App
noch nicht vollständig entwickelt ist, werde ich hier einige der abgeschlossenen funktionalen Konstruktionsmethoden vorstellen, in der Hoffnung, SwiftUI
Entwicklern zu helfen.
Also, ohne weitere Umschweife, fangen wir an.
Projektaufbau
Erstellen Sie zunächst ein neues SwiftUI
Projekt mit dem Namen ColourAtla
.
Seitenaufbau
Lassen Sie uns kurz die Zusammensetzung der Seite analysieren. Sie besteht aus einem Title
Titel und einer Farbkartenliste List
. Drücken Sie dann in der Farbkartenliste lange auf eine einzelne Farbkarte, um den schwebenden Fenstereffekt zu erhalten .
Nachdem wir die grundlegenden Komponenten verstanden haben, bauen wir den Inhalt Stück für Stück auf.
Titelkonstruktion
Der erste ist der Header-Abschnitt, den wir OpaqueTypes
mit der Opaque-Type-Methode erstellen View
. Beispiel:
//MARK: 标题
private var CardTitleView: some View {
Text("世界最高级的颜色")
.font(.system(size: 17))
.fontWeight(.bold)
}
Im obigen Code deklarieren wir eine private Ansicht CardTitleView
, konstruieren dann den Titel, den wir darin benötigen Text
, und verwenden einige Modifikatoren, damit der Inhalt harmonisch aussieht.
Farberweiterung
Nachdem der Titel erstellt wurde, erstellen wir die Farbkartenliste. Bevor wir die Farbkarte erstellen, erweitern wir die vorhandene Farbkonstruktionsmethode, um den hexadezimalen Farbwert zu verwenden . Beispiel:Color
Extension
我们创建一个新的Swift
文件,命名为ColorHexString
。
import SwiftUI
extension Color {
static func rgb(_ red: CGFloat, green: CGFloat, blue: CGFloat) -> Color {
return Color(red: red / 255, green: green / 255, blue: blue / 255)
}
static func Hex(_ hex: UInt) -> Color {
let r: CGFloat = CGFloat((hex & 0xFF0000) >> 16)
let g: CGFloat = CGFloat((hex & 0x00FF00) >> 8)
let b: CGFloat = CGFloat(hex & 0x0000FF)
return rgb(r, green: g, blue: b)
}
}
上述代码中,我们给Color
进行了Extension
扩展。
我们通过接收一个UInt
十六进制颜色值,然后把它转换成RGB
颜色值,这样我们只需要输入十六进制颜色值,Color
就可以转换为可以使用的RGB
颜色值了。
单张色卡
接下来,我们回到ContentView
文件,先来构建单张色卡。示例:
// MARK: 卡片视图
struct CardViewExamples: View {
var body: some View {
ZStack(alignment: Alignment(horizontal: .center, vertical: .center), content: {
// 背景卡片
Rectangle()
.fill(Color.Hex(0xFF0000))
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: 110)
.cornerRadius(8)
HStack {
VStack(alignment: .leading, spacing: 10) {
//颜色名称
Text("中国红")
.fontWeight(.bold)
.foregroundColor(Color.white)
.font(.system(size: 17))
// 颜色值
Text("#FF0000")
.fontWeight(.bold)
.foregroundColor(Color.white)
.font(.system(size: 14))
}
Spacer()
}.padding()
})
}
}
上述代码中,我们使用Struct
构造体创建视图的方式构建了单张色卡的内容。
在单张色卡,我们构建了一个Rectangle
矩形作为背景,然后填充了一个“中国红”,顺便调整了它的大小和圆角。
依此再构建了两个Text
,作为颜色名称和颜色值,最后使用ZStack
将三个元素组成一个整体。
为什么需要使用Struct
构造体的方式,而不使用OpaqueTypes
不透明类型的方法,这是因为我们构建的色卡之后需要提取参数出来,然后在ContentView
视图中遍历多张色卡,因此使用Struct
构造体的方式创建视图。
参数抽离
接下拉,为了更加方便地遍历出多张色卡,我们将相同的参数进行抽离替换。
在色卡列表中,我们抽离色卡背景色、色卡颜色名称、色卡颜色值3个参数,示例:
var cardBGColor: Color
var cardColorName: String
var cardColorRBG: String
抽离出参数后,由于我们没有给CardViewExamples
构造体中的参数赋值,因此我们在ContentView
视图调用时需要补充参数对应的参数值。
CardViewExamples(cardBGColor: Color.Hex(0xFF0000), cardColorName: "中国红", cardColorRBG: "#FF0000")
悬浮窗口
单张色卡完成后,我们来尝试完成长按色卡唤起悬浮窗口并实现复制颜色值。
在之前的章节中,我们学习过ContextMenu
上下文菜单的使用,在这里我们依旧使用的是ContextMenu
上下文菜单构建悬浮窗口。示例:
// 长按复制颜色值
.contextMenu {
Button(action: {
UIPasteboard.general.string = cardColorName
}, label: {
Text("复制颜色值")
})
}
.padding(.horizontal)
上述代码中,我们使用ContextMenu
上下文菜单创建了悬浮窗口。
当我们长按单张色卡时,我们就把cardColorName
卡片颜色值的内容复制到剪切板中,这样我们就实现了通过长按复制色卡颜色值的交互。
数据模型
模型创建
完成单张色卡创建后,我们需要根据单张色卡的内容遍历多张色卡,通用的方式是创建模型数组,再根据模型数组结合网络请求,获得放在服务端的Json数据,然后再在本地渲染。
我们创建一个Swift
文件,命名为Model.swift
。
import SwiftUI
struct CardModel:Decodable {
var cardBGColor: UIn
var cardColorName: String
var cardColorRBG: String
}
上述代码中,我们创建了一个结构体CardModel
,遵循Decodable
协议。
Decodable
协议,用于将JSON
对象解析为结构体或类,这样我们就可以通过网络请求获得JSON对象
,然后通过Decodable
协议解析在本地。
由于我们的色卡背景颜色是十六进制的颜色值,因此cardBGColor
参数需要声明为UInt
类型,其他cardColorName
、cardColorRBG
都是String
字符串类型。
我们回到ContentView
文件中,首先我们先获得定义好的CardModel
结构体。
@State var cardItems: [CardModel] = []
然后,我们使用OpaqueTypes
不透明类型的方法创建一个卡片视图,我们将CardListView
视图展示在ContentView
中展示。
// MARK: 色卡列表视图
private var CardListView: some View {
ScrollView(.vertical, showsIndicators: false, content: {
ForEach(cardItems, id: \.cardColorRBG) { item in
VStack(spacing: 20) {
CardViewExamples(cardBGColor: Color.Hex(item.cardBGColor), cardColorName: item.cardColorName, cardColorRBG: item.cardColorRBG)
}
}
})
}
这样,色卡列表视图的框架就创建好了。
但是我们在预览时没有看到色卡,这是因为我们的色卡列表视图只是搭建了框架,但是没有数据,下面我们来完成数据部分。
Json数据
色卡框架搭建好后,我们在云端创建好Json
数据。
[
{"cardBGColor":16711680,"cardColorRBG":"#FF0000","cardColorName":"中国红"},
{"cardBGColor":15226919,"cardColorRBG":"#E85827","cardColorName":"爱马仕橙"},
{"cardBGColor":16439902,"cardColorRBG":"#FADA5E","cardColorName":"拿破里黄"},
{"cardBGColor":35980,"cardColorRBG":"#008C8C","cardColorName":"马尔斯绿"},
{"cardBGColor":3175035,"cardColorRBG":"#30727B","cardColorName":"不来梅蓝"},
{"cardBGColor":6901074,"cardColorRBG":"#694D52","cardColorName":"莫兰迪色"},
{"cardBGColor":5338771,"cardColorRBG":"#517693","cardColorName":"马耳他蓝"},
{"cardBGColor":12199,"cardColorRBG":"#002FA7","cardColorName":"克菜因蓝"}
]
上述代码中,我们在某平台创建了Json
数据,并且获得了可以访问Json
数据的API
接口。
我们将API接口地址复制,并在ContentView
中声明一个常量存储它。
let JsonURL = "https://api.npoint.io/dc5a1718e0e958613ade"
网络请求
Mit der API-Schnittstelle wird auch das lokale Farbkarten-Listenansichts- Framework eingerichtet, und der nächste Schritt besteht darin, den Netzwerkanforderungsteil abzuschließen .
// MARK: 网络请求
func getColors() {
let session = URLSession(configuration: .default)
session.dataTask(with: URL(string: JsonURL)!) { data, _, _ in
guard let jsonData = data else { return }
do {
let colors = try JSONDecoder().decode([CardModel].self, from: jsonData)
self.cardItems = colors
} catch {
print(error)
}
}
.resume()
}
Im obigen Code erstellen wir eine Netzwerkanforderungsmethode getColors
. Wir verwenden das offizielle URLSession
Netzwerkanforderungs-Framework und erhalten dann die Daten der URL
Adresse und gleichen die Daten mit den Parametern im Array ab JsonURL
, indem JSONDecoder
wir die Daten analysieren. Nach dem Abgleich speichern wir die Daten in .json
CardModel
cardItems
Wir rufen die Methode auf, ContentView
wenn die Ansicht angezeigt wird .getColors
.onAppear(perform: {
getColors()
})
Wir klicken auf den Ausführungsvorgang im Simulator, um eine Vorschau des Effekts anzuzeigen.
Wird geladen
Da die Netzwerkanforderung einige Zeit in Anspruch nimmt , können wir zur Verbesserung unseres ColourAtla
Farbkartenerlebnisses eine Ansicht als Standardanzeige hinzufügen , wenn die ListenansichtApp
der Farbkarte nicht geladen wurde . Beispiel:Loading
if cardItems.isEmpty {
Spacer()
ProgressView()
Spacer()
} else {
CardListView
}
Sehen wir uns abschließend den Gesamteffekt an .
Das ist alles für dieses Kapitel.
Kommen Sie und probieren Sie es aus!
Wenn diese Spalte für Sie hilfreich ist, liken, kommentieren und folgen Sie ~
Ich nehme an der Rekrutierung des Signierprogramms für Ersteller der Nuggets Technology Community teil. Klicken Sie auf den Link, um sich zu registrieren und einzureichen .