前语
在本章中,你将学会运用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)
}
上述代码中,咱们声明了三个存储变量logoImage
、logoColor
、bgColor
,分别可以调整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()
}
上述代码中,咱们声明了两个变量segmentTitle
、selectedSegment
。
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
在主视图展现看看作用:
交互部分,当咱们点击布景色彩色块时,上面logo展现区域的logo也同时需求更改其布景色彩,咱们来完结下。示例:
.onTapGesture {
bgColor = Color.Hex(item.cardBGColor)
}
咱们给布景色彩部分的色卡添加一个点击事情,点击布景色彩色块时,将色彩赋予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
的变量,就完结了切换图标的作用。
咱们来运行下看看作用:
同理,图标填充色咱们就把布景色彩那块内容仿制一份过来,然后当点击色彩的时分,赋值给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填充色来看看作用。
功用进阶
完结上述内容后,总觉得好像还差点东西,思来想去总算发现一个问题。
当时咱们的色彩和Logo图标都是内置的,没有办法自定义。布景色彩和填充色还好,可是Logo图片不能自定义,就…….不行高雅。
接下来,咱们来完结自定义Logo图标的办法,最简略的便是本地上传图片。
咱们想象下通用的交互,当咱们点击图标时,它弹出一个弹窗,让咱们挑选修正的来历。常用的图片来历有2种:相册、拍照,这儿咱们只完结相册的部分,究竟应该很少人会直接拍照作为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 })
挑选本地图片
咱们已经成功调用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()
}
}
}
上述代码中,创立了一个揭露的结构体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
绑定了翻开本地图片弹窗的条件,咱们把这个触发条件放在咱们点击“相册”选项的操作。示例:
图标图片替换
上述代码中,咱们已经经过调用本地相册的办法,获得了选中的图片,这时咱们需求替换当时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()
}
}
上述代码中,咱们创立了一个新的视图ShowImageView
,Image
图片的内容换成了交换本地图库中选中回调的image
。
图标图片部分,运用clipShape
修饰符切成圆形比较漂亮,布景色彩可调理,图标由所以图标就无需进行填充色调整了。
咱们在LogoView
视图中依据image
的有无,展现不同的视图。作用如下:
项目预览
祝贺你,完结了本章的一切内容!
快来着手试试吧!
如果本专栏对你有协助,不妨点赞、评论、关注~
我正在参加技术社区创作者签约方案招募活动,点击链接报名投稿。