SwiftUI极简教程39:构建一个ColourAtla色卡App

简介: 在本章中,你将学会使用URLSession和ContextMenu构建一个ColourAtla色卡App。

image.png

项目背景


一直以来,对于中国传统颜色有种特别的青睐。

而在浏览一些资讯时看到博主发布的一些色彩搭配的内容,其中就谈到了色卡的概念,经过一些了解和学习,就想着打造一款色彩搭配App

虽然App尚未完全开发完成,但在此分享一下其中一些已经完成的功能构建方式,希望能够帮助到SwiftUI开发者们。

那么,废话少说,让我们开始吧。


首先,创建一个新的SwiftUI项目,命名为ColourAtla

image.png

页面搭建


我们简单分析下页面的组成结构,它是由一个Title标题和一个色卡List列表构成,然后在色卡列表中,长按单张色卡,就可以获得悬浮窗口效果。

理解完基本组成后,我们一块一块来构建内容。

标题搭建


首先是标题部分,我们使用OpaqueTypes不透明类型的方法构建View。示例:

//MARK: 标题
private var CardTitleView: some View {
    Text("世界最高级的颜色")
        .font(.system(size: 17))
        .fontWeight(.bold)
}

image.png

上述代码中,我们声明了一个私有的视图CardTitleView,然后在里面构建了我们需要的标题Text,并使用一些修饰符让内容看起来协调一些。

颜色扩展


标题创建完成后,我们来构建色卡列表,在构建色卡之前,为了能使用十六进制颜色值,我们给现有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)
    }
}

image.png

上述代码中,我们给Color进行了Extension扩展。

我们通过接收一个UInt十六进制颜色值,然后把它转换成RGB颜色值,这样我们只需要输入十六进制颜色值,Color就可以转换为可以使用的RGB颜色值了。

单张色卡


接下来,我们回到ContentView文件,先来构建单张色卡。示例:


上述代码中,我们给Color进行了Extension扩展。
我们通过接收一个UInt十六进制颜色值,然后把它转换成RGB颜色值,这样我们只需要输入十六进制颜色值,Color就可以转换为可以使用的RGB颜色值了。
单张色卡
接下来,我们回到ContentView文件,先来构建单张色卡。示例:

image.png

上述代码中,我们使用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")

image.png

浮窗口


单张色卡完成后,我们来尝试完成长按色卡唤起悬浮窗口并实现复制颜色值

在之前的章节中,我们学习过ContextMenu上下文菜单的使用,在这里我们依旧使用的是ContextMenu

// 长按复制颜色值
    .contextMenu {
        Button(action: {
            UIPasteboard.general.string = cardColorName
            }, label: {
                Text("复制颜色值")
                })
            }
            .padding(.horizontal)

image.png

上述代码中,我们使用ContextMenu上下文菜单创建了悬浮窗口。

当我们长按单张色卡时,我们就把cardColorName卡片颜色值的内容复制到剪切板中,这样我们就实现了通过长按复制色卡颜色值的交互。

数据模型


模型创建

完成单张色卡创建后,我们需要根据单张色卡的内容遍历多张色卡,通用的方式是创建模型数组,再根据模型数组结合网络请求,获得放在服务端的Json数据,然后再在本地渲染

我们创建一个Swift文件,命名为Model.swift

import SwiftUI
struct CardModel:Decodable {
    var cardBGColor: UIn
    var cardColorName: String
    var cardColorRBG: String
}

image.png

上述代码中,我们创建了一个结构体CardModel,遵循Decodable协议。

Decodable协议,用于将JSON对象解析为结构体或类,这样我们就可以通过网络请求获得JSON对象,然后通过Decodable协议解析在本地。

由于我们的色卡背景颜色是十六进制的颜色值,因此cardBGColor参数需要声明为UInt类型,其他cardColorNamecardColorRBG都是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)
            }
        }
    })
}

image.png

这样,色卡列表视图的框架就创建好了。

但是我们在预览时没有看到色卡,这是因为我们的色卡列表视图只是搭建了框架,但是没有数据,下面我们来完成数据部分

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":"克菜因蓝"}]

image.png

上述代码中,我们在某平台创建了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()
}

image.png

上述代码中,我们创建了一个网络请求的方法getColors,我们使用官方提供的URLSession网络请求框架,然后获得URL地址JsonURL的数据,并通过JSONDecoder解析json数据与CardModel数组中的参数做匹配,匹配上后将数据存储到cardItems中。

我们在ContentView视图展示的时候调用getColors方法。

.onAppear(perform: {
    getColors()
})

我们点击模拟器上的运行操作,预览下效果。

image.png

Loading加载


由于网络请求需要时间,为了让我们ColourAtla色卡App体验更好,在色卡列表视图还没有加载完成时,我们可以增加一个Loading视图作为缺省展示。示例:

if cardItems.isEmpty {
    Spacer()
    ProgressView()
    Spacer()
} else {
    CardListView
}

image.png

我们最后预览下整体效果

image.png

以上就是本章全部内容。

相关文章
|
1月前
|
监控 安全 数据可视化
【教程】为什么要为 App 应用加固 ?如何为 App 应用加固 ?
【教程】为什么要为 App 应用加固 ?如何为 App 应用加固 ?
|
1月前
|
iOS开发 开发者
一键制作 iOS 上架 App Store 描述文件教程
一键制作 iOS 上架 App Store 描述文件教程
|
1月前
|
开发者 iOS开发
【教程】无法验证 app 需要互联网连接以验证是否信任开发者
【教程】无法验证 app 需要互联网连接以验证是否信任开发者
|
1月前
|
开发工具 数据安全/隐私保护 Android开发
【教程】APP 开发后如何上架?
【教程】APP 开发后如何上架?
|
1月前
|
开发者 iOS开发
UniApp打包教程:使用HBuilder X和AppUploader完成原生App云打包和上架指南“
UniApp打包教程:使用HBuilder X和AppUploader完成原生App云打包和上架指南“
47 3
|
2月前
|
机器学习/深度学习 算法 数据可视化
基于Google Earth Engine云平台构建的多源遥感数据森林地上生物量AGB估算模型含生物量模型应用APP
基于Google Earth Engine云平台构建的多源遥感数据森林地上生物量AGB估算模型含生物量模型应用APP
103 0
|
1月前
|
iOS开发 开发者
【教程】uni-app iOS 打包解决 profile 文件与私钥证书不匹配问题
【教程】uni-app iOS 打包解决 profile 文件与私钥证书不匹配问题
|
1月前
|
移动开发 安全 数据安全/隐私保护
【教程】APP 加固的那些小事情
【教程】APP 加固的那些小事情
|
2月前
|
移动开发 开发工具 数据安全/隐私保护
iOS APP 版本更新升级教程:如何打包上架新的 APP 版本?
iOS APP 版本更新升级教程:如何打包上架新的 APP 版本?
iOS APP 版本更新升级教程:如何打包上架新的 APP 版本?
|
3月前
|
存储 前端开发 Go
flutter+go构建的即时通讯app,ChatCraft
社交应用程序在世界各地都很流行,例如 Facebook、Line、Whatsapp。如果您渴望打造一款独具个性的社交平台,Chat-Craft项目将是您不可或缺的理想之选。Chat-Craft是一款跨平台移动应用,采用了Golang作为后端服务端技术,以及Flutter作为前端客户端技术。该应用旨在提供高效、稳定且跨平台的用户体验,将现代的移动应用开发技术和高性能的后端服务端技术相结合。在Chat-Craft项目中,作者精心雕琢了客户端UI,灵感汲取于各大即时通讯应用及最新的应用设计规范。