SwiftUI 미니멀리스트 튜토리얼 39: ColourAtla 컬러 카드 앱 빌드

이 장에서는 컬러 카드 를 사용 URLSession하고 ContextMenu만드는 방법을 배웁니다 .ColourAtlaApp

프로젝트의 배경

오랫동안 중국 전통 색상 에 대한 특별한 호의 가 있었습니다.

정보를 검색하다가 블로거들이 발표한 컬러 카드 의 개념에 대한 컬러 매칭 콘텐츠를 보았고 이해와 학습을 거쳐 컬러 매칭 앱 을 만들고 싶었습니다 .

App아직 완전히 개발되지는 않았지만 완성된 기능 구성 방법 중 일부를 여기에서 공유하여 개발자에게 도움이 되었으면 SwiftUI합니다.

이제 더 이상 고민하지 않고 시작하겠습니다.

프로젝트 건설

먼저 SwiftUI이라는 새 프로젝트 를 만듭니다 ColourAtla.

1.png

페이지 빌드

페이지의 구성을 간략히 분석하자면 Title제목과 컬러 카드 List목록으로 구성되어 있으며 컬러 카드 목록에서 단일 컬러 카드를 길게 누르면 플로팅 윈도우 효과를 얻을 수 있습니다.

기본 구성 요소를 이해한 후 콘텐츠를 하나씩 구성해 보겠습니다.

타이틀 구성

첫 번째는 OpaqueTypes불투명한 유형 메서드를 사용하여 빌드 하는 헤더 섹션 View입니다. 예시:

//MARK: 标题

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

2.png

위의 코드에서 private view 를 선언한 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)
    }
}

3.png

上述代码中,我们给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()
        })
    }
}

4.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")

5.png

悬浮窗口

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

在之前的章节中,我们学习过ContextMenu上下文菜单的使用,在这里我们依旧使用的是ContextMenu上下文菜单构建悬浮窗口。示例:

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

6.png

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

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

数据模型

模型创建

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

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

import SwiftUI

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

9.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)
            }
        }
    })
}

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

11.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()
}

12.png

위의 코드에서 우리는 네트워크 요청 메소드를 생성 getColors하고 공식 네트워크 요청 프레임워크를 사용하여 주소 의 데이터 URLSession를 얻고 데이터 파싱 하여 배열의 매개변수 와 데이터를 일치시킵니다. 일치 후 데이터를 저장합니다 안에 .URLJsonURLJSONDecoderjsonCardModelcardItems

ContentView뷰가 표시될 때 getColors메서드 를 호출합니다.

.onAppear(perform: {
    getColors()
})

시뮬레이터에서 실행 작업을 클릭하여 효과를 미리 봅니다.

13.png

로딩 중

네트워크 요청 에 시간이 걸리므ColourAtla 로 컬러 카드 경험을 개선 하기 위해 App컬러 카드 목록 보기가 로드되지 않은 경우 보기를 기본 디스플레이 로 추가할 수 있습니다 . 예시:Loading

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

14.png

우리는 마침내 전반적인 효과 를 미리 봅니다.

15.png

이것이 이 장의 전부입니다.

와서 사용해 보세요!

이 칼럼이 도움이 되셨다면 좋아요, 댓글, 팔로우 부탁드립니다~

Nuggets Technology Community의 작성자 서명 프로그램 모집에 참여하고 있습니다. 링크를 클릭하여 등록하고 제출 하십시오.

рекомендация

отjuejin.im/post/7116043069673177118