この章では、カラーカードの使用方法URLSession
とContextMenu
作成方法を学習します。ColourAtla
App
プロジェクトの背景
長い間、繁体字中国語の色には特別な支持がありました。
いくつかの情報を閲覧していると、ブロガーがリリースしたカラーカードの概念について話しているカラーマッチングコンテンツをいくつか見ました。ある程度の理解と学習の後、カラーマッチングアプリを作成したいと思いました。
まだApp
完全には開発されていませんが、開発者の助けになることを願って、完成した機能構築方法のいくつかをここで共有しますSwiftUI
。
それで、それ以上の苦労なしに、始めましょう。
プロジェクト建設
まず、という名前の新しいSwiftUI
プロジェクトを作成しますColourAtla
。
ページビルド
ページの構成を簡単に分析してみましょう。Title
タイトルとカラーカードList
リストで構成されています。次に、カラーカードリストで1枚のカラーカードを長押しすると、フローティングウィンドウ効果が得られます。
基本的なコンポーネントを理解した後、コンテンツを1つずつ作成していきましょう。
タイトル構成
OpaqueTypes
1つ目は、不透明(OPAQUE)型の方法を使用して作成したヘッダーセクションView
です。例:
//MARK: 标题
private var CardTitleView: some View {
Text("世界最高级的颜色")
.font(.system(size: 17))
.fontWeight(.bold)
}
上記のコードでは、プライベートビューを宣言してから、CardTitleView
必要なタイトルをText
作成し、いくつかの修飾子を使用してコンテンツを調和させています。
カラーエクステンション
タイトルを作成したら、カラーカードリストを作成しましょう。カラーカードを作成する前に、16進数のカラー値を使用するために、既存の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"
网络请求
APIインターフェースを使用して、ローカルカラーカードリストビューフレームワークも確立されます。次のステップは、ネットワーク要求部分を完了することです。
// 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()
}
上記のコードでは、ネットワークリクエストメソッドを作成しますgetColors
。公式のURLSession
ネットワークリクエストフレームワークを使用して、URL
アドレスのデータを取得し、データJsonURL
をJSONDecoder
解析して配列内のパラメータとjson
データを照合します。CardModel
照合後、データを保存します。cardItems
の 。
ContentView
ビューが表示されたときにgetColors
メソッドを呼び出します。
.onAppear(perform: {
getColors()
})
シミュレータで実行操作をクリックして、効果をプレビューします。
読み込み中
ネットワークリクエストには時間がかかるColourAtla
ため、カラーカードのエクスペリエンスを向上させるためにApp
、カラーカードリストビューがロードされていない場合のデフォルトの表示としてビューを追加できます。例:Loading
if cardItems.isEmpty {
Spacer()
ProgressView()
Spacer()
} else {
CardListView
}
最後に全体的な効果をプレビューします。
この章は以上です。
是非、お試しください!
このコラムがお役に立てば、いいね、コメント、フォローしてください〜
ナゲッツテクノロジーコミュニティのクリエイター署名プログラムの募集に参加しています。リンクをクリックして登録し、送信してください。