前语

在本章中,你将学会运用Segment分段器、LazyVGrid垂直网格、ImagePicker图片挑选器构建一个Logo生成器

在上一章中,咱们完善了SearchBar搜索栏、TabView底部导航,还有做了一个Loading加载动作。最近忽然有个想法,如果把色卡图片进行组合,这不便是一个简略的Logo了吗?我能不能做个Logo生成器

说干就干,咱们持续完结App的相关内容。

款式部分

Logo展现区域

首要,咱们创立一个新的SwiftUI文件,命名为LogoView

然后,咱们运用Image作为logo展现的区域,示例:

// MARK: Logo展现区域
private var ShowLogoView: some View {
 Image(systemName: logoImage)
  .font(.system(size: 68))
  .foregroundColor(logoColor)
  .frame(minWidth: 80, maxWidth: 120, minHeight: 80, maxHeight: 120)
  .background(bgColor)
  .cornerRadius(8)
}

SwiftUI极简教程41:使用Segment、LazyVGrid和ImagePicker构建一个Logo生成器

上述代码中,咱们声明了三个存储变量logoImagelogoColorbgColor,分别可以调整logo图片填充色布景色

在主要展现页面,咱们运用Image构建logo视图,并经过修饰符调整logo的图片大小、logo色彩、全体大小布景填充色彩圆角

Segment分段挑选

下面咱们来完结切换挑选调整logo各项参数的区域,咱们经过Segment分段挑选来区分开,示例:

// MARK: 分选挑选
private var SegmentView: some View {
 Picker("分段挑选", selection: $selectedSegment) {
  ForEach(0 ..< 3) {
   Text(self.segmentTitle[$0]).tag($0)
 }
 }
 .pickerStyle(SegmentedPickerStyle())
 .padding()
}

SwiftUI极简教程41:使用Segment、LazyVGrid和ImagePicker构建一个Logo生成器

上述代码中,咱们声明了两个变量segmentTitleselectedSegment

segmentTitle用来存储分段器的标题selectedSegment来记录当时咱们选中的是分段器的哪一项。然后咱们运用Picker完结了分段器的款式,运用ForEach遍历分段器选项和内容,这儿分段器的款式需求挑选SegmentedPickerStyle

然后咱们在LogoView视图中展现,看起来还不错。

功用交互

布景色彩切换

布景色彩咱们运用网格布局来完结,首要咱们先声明了网格的列数为4列,然后色彩部分,咱们取回之前色卡部分的色彩。

private var gridItemLayout = [GridItem(.flexible()), GridItem(.flexible()), GridItem(.flexible()), GridItem(.flexible())]
@State var cardItems: [CardModel] = []

然后构建布景色彩挑选的页面,示例:

//MARK: 布景色彩
private var BGColorView: some View {
ScrollView {
LazyVGrid(columns: gridItemLayout, spacing: 20) {
ForEach(cardItems, id: \.cardColorRBG) { item in
Rectangle()
.fill(Color.Hex(item.cardBGColor))
.frame(width: 80, height: 80)
.cornerRadius(8)
}
}
}.padding()
}

上述代码中,咱们构建了一个纵向网格视图,spacing距离为20,然后经过遍历cardItems色卡数组中的数据,然后遍历出一个个色块

咱们把网络恳求弥补上,然后将BGColorView在主视图展现看看作用:

SwiftUI极简教程41:使用Segment、LazyVGrid和ImagePicker构建一个Logo生成器

交互部分,当咱们点击布景色彩色块时,上面logo展现区域的logo也同时需求更改布景色彩,咱们来完结下。示例:

.onTapGesture {
 bgColor = Color.Hex(item.cardBGColor)
}

SwiftUI极简教程41:使用Segment、LazyVGrid和ImagePicker构建一个Logo生成器

咱们给布景色彩部分的色卡添加一个点击事情,点击布景色彩色块时,将色彩赋予logo布景色彩。

这样,咱们就完结了布景色彩的设置。

图标图片切换

图标部分切换的原理相似,咱们这儿换成本地的数据做一下演示,先预备一些Apple的系统图标作为示例:

private var appleSymbols = ["house.circle", "person.circle", "bag.circle", "location.circle", "bookmark.circle", "gift.circle", "globe.asia.australia.fill", "lock.circle", "pencil.circle", "link.circle"]

然后也经过LazyVGrid纵向网格和ForEach循环的方式遍历appleSymbols图片数组的数据,示例:

// MARK: 图标切换
private var SwitchIconView: some View {
ScrollView {
LazyVGrid(columns: gridItemLayout, spacing: 20) {
ForEach(appleSymbols.indices, id: \.self) { item in
Image(systemName: appleSymbols[item])
.font(.system(size: 30))
.frame(width: 80, height: 80)
.background(bgColor)
.cornerRadius(8)
.onTapGesture {
logoImage = appleSymbols[item]
}
}
}
}.padding()
}

上述代码中,当咱们创立了一个图标网格,然后遍历appleSymbols图片数组的数据,在点击每个图片时,咱们把点击的图片赋值到logo区域中logoImage的变量,就完结了切换图标的作用。

咱们来运行下看看作用:

SwiftUI极简教程41:使用Segment、LazyVGrid和ImagePicker构建一个Logo生成器

同理,图标填充色咱们就把布景色彩那块内容仿制一份过来,然后当点击色彩的时分,赋值给logoColor变量就完结了,这儿就不做演示了。

分段选项切换

最后是分段器的切换,咱们可以依据selectedSegment变量作为切换状态值,当selectedSegment处于不同的值时,咱们切换不同的视图。示例:

VStack(spacing: 60) {
Spacer()
ShowLogoView
Spacer()
VStack(spacing: -10) {
SegmentView
if selectedSegment == 0 {
BGColorView
} else if selectedSegment == 1 {
SwitchIconView
} else {
LogoColorView
}
}
}

完结后,咱们测验更改Logo布景色彩、Logo图标、Logo填充色来看看作用。

SwiftUI极简教程41:使用Segment、LazyVGrid和ImagePicker构建一个Logo生成器

功用进阶

完结上述内容后,总觉得好像还差点东西,思来想去总算发现一个问题。

当时咱们的色彩和Logo图标都是内置的,没有办法自定义。布景色彩和填充色还好,可是Logo图片不能自定义,就…….不行高雅

接下来,咱们来完结自定义Logo图标的办法,最简略的便是本地上传图片

咱们想象下通用的交互,当咱们点击图标时,它弹出一个弹窗,让咱们挑选修正的来历。常用的图片来历有2种:相册、拍照,这儿咱们只完结相册的部分,究竟应该很少人会直接拍照作为Logo图标。

SwiftUI极简教程41:使用Segment、LazyVGrid和ImagePicker构建一个Logo生成器

翻开Sheet弹窗

咱们运用官方提供的Sheet弹窗来完结来历挑选交互,示例:

// MARK: - 挑选来历弹窗
private var chooseImageSheet: ActionSheet {
let action = ActionSheet(title: Text("挑选来历"), buttons: [.default(Text("相册"), action: {
// 翻开相册
}), .cancel(Text("取消"), action: {
})])
return action
}

上述代码中,咱们构建了一个翻开Sheet弹窗的视图chooseImageSheet,它的类型是ActionSheet,即触发Sheet弹窗

然后咱们完善了Sheet弹窗里的相关内容,标题、操作(相册、取消)。

然后咱们需求声明一个变量,判断是否翻开Sheet弹窗,示例:

@State var showChooseImageSheet: Bool = false

完结后,咱们在LogoView中运用.actionSheet修饰符完结翻开Sheet弹窗的交互。示例:

// 挑选来历
.actionSheet(isPresented: $showChooseImageSheet, content: {chooseImageSheet })

SwiftUI极简教程41:使用Segment、LazyVGrid和ImagePicker构建一个Logo生成器

挑选本地图片

咱们已经成功调用Sheet弹窗了,可选项为相册取消,取消即主动收起Sheet弹窗,而当咱们点击相册的时分,需求调用本地相册

接下来,咱们来完结唤起本地相册的功用。

咱们新建一个Swift文件,命名为ImagePickerView,然后完结以下办法:

import SwiftUI
public struct ImagePickerView: UIViewControllerRepresentable {
private let sourceType: UIImagePickerController.SourceType
private let onImagePicked: (UIImage) -> Void
@Environment(\.presentationMode) private var presentationMode
public init(sourceType: UIImagePickerController.SourceType, onImagePicked: @escaping (UIImage) -> Void) {
self.sourceType = sourceType
self.onImagePicked = onImagePicked
}
public func makeUIViewController(context: Context) -> UIImagePickerController {
let picker = UIImagePickerController()
picker.sourceType = self.sourceType
picker.delegate = context.coordinator
return picker
}
public func updateUIViewController(_ uiViewController: UIImagePickerController, context: Context) {}
public func makeCoordinator() -> Coordinator {
Coordinator(
onDismiss: { self.presentationMode.wrappedValue.dismiss() },
onImagePicked: self.onImagePicked
)
}
final public class Coordinator: NSObject, UINavigationControllerDelegate, UIImagePickerControllerDelegate {
private let onDismiss: () -> Void
private let onImagePicked: (UIImage) -> Void
init(onDismiss: @escaping () -> Void, onImagePicked: @escaping (UIImage) -> Void) {
self.onDismiss = onDismiss
self.onImagePicked = onImagePicked
}
public func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) {
if let image = info[.originalImage] as? UIImage {
self.onImagePicked(image)
}
self.onDismiss()
}
public func imagePickerControllerDidCancel(_: UIImagePickerController) {
self.onDismiss()
}
}
}

SwiftUI极简教程41:使用Segment、LazyVGrid和ImagePicker构建一个Logo生成器

上述代码中,创立了一个揭露的结构体ImagePickerView,遵循UIViewControllerRepresentable协议。

然后调用系统的UIImagePickerController挑选图片办法,调用成功后关闭弹窗而且返回选中的图片

代码中大部分内容为完结挑选图片的相关协议和返回UIImage类型图片的办法,在这儿就不赘述了。

咱们回到LogoView文件中,咱们先声明必要的参数。示例:

@State var showImagePicker: Bool = false
@State var image: UIImage?

上述代码中,showImagePicker是咱们是否翻开挑选图片的弹窗,而image则用来接收咱们相册中挑选的图片。

咱们运用.sheet调用翻开本地相册的办法。示例:

// 本地图片挑选弹窗
.sheet(isPresented: $showImagePicker) {
 ImagePickerView(sourceType: .photoLibrary) { image in
  self.image = image
 }
}

咱们运用showImagePicker绑定了翻开本地图片弹窗的条件,咱们把这个触发条件放在咱们点击“相册”选项的操作。示例:

SwiftUI极简教程41:使用Segment、LazyVGrid和ImagePicker构建一个Logo生成器

图标图片替换

上述代码中,咱们已经经过调用本地相册的办法,获得了选中的图片,这时咱们需求替换当时Logo的图标。

咱们创立多一个视图来展现选中图片后回调的内容。示例:

// MARK: 本地图片
private var ShowImageView: some View {
Image(uiImage: image!)
.resizable()
.frame(width: 68, height: 68, alignment: .center)
.clipShape(Circle())
.padding(20)
.background(bgColor)
.cornerRadius(8)
.onTapGesture {
self.showChooseImageSheet.toggle()
}
}

上述代码中,咱们创立了一个新的视图ShowImageViewImage图片的内容换成了交换本地图库中选中回调的image

图标图片部分,运用clipShape修饰符切成圆形比较漂亮,布景色彩可调理,图标由所以图标就无需进行填充色调整了。

咱们在LogoView视图中依据image的有无,展现不同的视图。作用如下:

SwiftUI极简教程41:使用Segment、LazyVGrid和ImagePicker构建一个Logo生成器

项目预览

SwiftUI极简教程41:使用Segment、LazyVGrid和ImagePicker构建一个Logo生成器

祝贺你,完结了本章的一切内容!

快来着手试试吧!

如果本专栏对你有协助,不妨点赞、评论、关注~

我正在参加技术社区创作者签约方案招募活动,点击链接报名投稿。