From 03a145f7d9240b98940765c761023d4ec2f1977f Mon Sep 17 00:00:00 2001 From: v504 Date: Mon, 25 Aug 2025 18:51:10 +0800 Subject: [PATCH] Add tab type selection and content organization in QRCodeStyleView for improved user experience. Introduced TabType enum for managing styles, and refactored content areas for colors, dots, eyes, and logos, enhancing the overall layout and interaction. --- MyQrCode/Views/QRCodeStyleView.swift | 291 ++++++++++++++++++--------- 1 file changed, 191 insertions(+), 100 deletions(-) diff --git a/MyQrCode/Views/QRCodeStyleView.swift b/MyQrCode/Views/QRCodeStyleView.swift index 7f02d80..b1104dd 100644 --- a/MyQrCode/Views/QRCodeStyleView.swift +++ b/MyQrCode/Views/QRCodeStyleView.swift @@ -2,6 +2,32 @@ import SwiftUI import QRCode import CoreData +// MARK: - 标签类型枚举 +enum TabType: String, CaseIterable { + case colors = "colors" + case dots = "dots" + case eyes = "eyes" + case logos = "logos" + + var displayName: String { + switch self { + case .colors: return "颜色" + case .dots: return "点类型" + case .eyes: return "眼睛" + case .logos: return "Logo" + } + } + + var iconName: String { + switch self { + case .colors: return "paintpalette" + case .dots: return "circle.grid.3x3" + case .eyes: return "eye" + case .logos: return "photo" + } + } +} + // MARK: - 自定义二维码样式界面 struct QRCodeStyleView: View { let qrCodeContent: String @@ -25,6 +51,9 @@ struct QRCodeStyleView: View { @State private var qrCodeImage: UIImage? @State private var isLoading = false + // 选中的标签类型 + @State private var selectedTabType: TabType = .colors + // 创建QRCode文档 private func createQRCodeDocument() -> QRCode.Document { let d = try! QRCode.Document(engine: QRCodeEngineExternal()) @@ -95,6 +124,69 @@ struct QRCodeStyleView: View { // MARK: - 样式选择区域 private var styleSelectionSection: some View { + VStack(spacing: 0) { + // 标签类型选择 + tabTypeSelection + + // 内容区域 + contentArea + } + .background(Color(.systemGroupedBackground)) + } + + // MARK: - 标签类型选择 + private var tabTypeSelection: some View { + HStack(spacing: 0) { + ForEach(TabType.allCases, id: \.self) { tabType in + Button(action: { + selectedTabType = tabType + }) { + VStack(spacing: 4) { + Image(systemName: tabType.iconName) + .font(.system(size: 20)) + .foregroundColor(selectedTabType == tabType ? .blue : .gray) + + Text(tabType.displayName) + .font(.caption) + .foregroundColor(selectedTabType == tabType ? .blue : .gray) + } + .frame(maxWidth: .infinity) + .padding(.vertical, 12) + .background( + Rectangle() + .fill(selectedTabType == tabType ? Color.blue.opacity(0.1) : Color.clear) + ) + } + } + } + .background(Color(.systemBackground)) + .overlay( + Rectangle() + .frame(height: 1) + .foregroundColor(Color(.separator)), + alignment: .bottom + ) + } + + // MARK: - 内容区域 + private var contentArea: some View { + Group { + switch selectedTabType { + case .colors: + colorsContent + case .dots: + dotsContent + case .eyes: + eyesContent + case .logos: + logosContent + } + } + .frame(maxHeight: 400) + } + + // MARK: - 颜色内容 + private var colorsContent: some View { ScrollView { VStack(spacing: 24) { // 前景色选择 @@ -110,59 +202,21 @@ struct QRCodeStyleView: View { colors: QRCodeColor.backgroundColors, selectedColor: $selectedBackgroundColor ) - - // 点类型选择 - dotTypeSelectionSection - - // 眼睛类型选择 - eyeTypeSelectionSection - - // Logo选择 - logoSelectionSection } .padding() } - .background(Color(.systemGroupedBackground)) - } - - // MARK: - 颜色选择区域 - private func colorSelectionSection( - title: String, - colors: [QRCodeColor], - selectedColor: Binding - ) -> some View { - VStack(alignment: .leading, spacing: 12) { - Text(title) - .font(.headline) - .foregroundColor(.primary) - - LazyVGrid(columns: Array(repeating: GridItem(.flexible()), count: 6), spacing: 12) { - ForEach(colors, id: \.self) { color in - Button(action: { - selectedColor.wrappedValue = color - }) { - RoundedRectangle(cornerRadius: 8) - .fill(color.color) - .frame(height: 40) - .overlay( - RoundedRectangle(cornerRadius: 8) - .stroke(selectedColor.wrappedValue == color ? Color.blue : Color.clear, lineWidth: 3) - ) - } - } - } - } } - // MARK: - 点类型选择区域 - private var dotTypeSelectionSection: some View { - VStack(alignment: .leading, spacing: 12) { - Text("点类型") - .font(.headline) - .foregroundColor(.primary) - - ScrollView(.horizontal, showsIndicators: false) { - HStack(spacing: 12) { + // MARK: - 点类型内容 + private var dotsContent: some View { + ScrollView { + VStack(spacing: 16) { + Text("选择点类型") + .font(.title2) + .fontWeight(.bold) + .padding(.top) + + LazyVGrid(columns: Array(repeating: GridItem(.flexible()), count: 3), spacing: 16) { ForEach(QRCodeDotType.allCases, id: \.self) { dotType in Button(action: { selectedDotType = dotType @@ -172,16 +226,16 @@ struct QRCodeStyleView: View { Image(uiImage: image) .resizable() .aspectRatio(contentMode: .fit) - .frame(width: 40, height: 40) + .frame(width: 60, height: 60) .background(Color.white) - .cornerRadius(8) + .cornerRadius(12) } else { - RoundedRectangle(cornerRadius: 8) + RoundedRectangle(cornerRadius: 12) .fill(Color.gray.opacity(0.3)) - .frame(width: 40, height: 40) + .frame(width: 60, height: 60) .overlay( Text("?") - .font(.caption) + .font(.title2) .foregroundColor(.secondary) ) } @@ -189,14 +243,15 @@ struct QRCodeStyleView: View { Text(dotType.displayName) .font(.caption) .foregroundColor(.primary) + .multilineTextAlignment(.center) } - .padding(8) + .padding(12) .background( - RoundedRectangle(cornerRadius: 12) + RoundedRectangle(cornerRadius: 16) .fill(selectedDotType == dotType ? Color.blue.opacity(0.1) : Color.clear) .overlay( - RoundedRectangle(cornerRadius: 12) - .stroke(selectedDotType == dotType ? Color.blue : Color.clear, lineWidth: 2) + RoundedRectangle(cornerRadius: 16) + .stroke(selectedDotType == dotType ? Color.blue : Color.clear, lineWidth: 3) ) ) } @@ -207,15 +262,16 @@ struct QRCodeStyleView: View { } } - // MARK: - 眼睛类型选择区域 - private var eyeTypeSelectionSection: some View { - VStack(alignment: .leading, spacing: 12) { - Text("眼睛类型") - .font(.headline) - .foregroundColor(.primary) - - ScrollView(.horizontal, showsIndicators: false) { - HStack(spacing: 12) { + // MARK: - 眼睛类型内容 + private var eyesContent: some View { + ScrollView { + VStack(spacing: 16) { + Text("选择眼睛类型") + .font(.title2) + .fontWeight(.bold) + .padding(.top) + + LazyVGrid(columns: Array(repeating: GridItem(.flexible()), count: 3), spacing: 16) { ForEach(QRCodeEyeType.allCases, id: \.self) { eyeType in Button(action: { selectedEyeType = eyeType @@ -225,16 +281,16 @@ struct QRCodeStyleView: View { Image(uiImage: image) .resizable() .aspectRatio(contentMode: .fit) - .frame(width: 40, height: 40) + .frame(width: 60, height: 60) .background(Color.white) - .cornerRadius(8) + .cornerRadius(12) } else { - RoundedRectangle(cornerRadius: 8) + RoundedRectangle(cornerRadius: 12) .fill(Color.gray.opacity(0.3)) - .frame(width: 40, height: 40) + .frame(width: 60, height: 60) .overlay( Text("?") - .font(.caption) + .font(.title2) .foregroundColor(.secondary) ) } @@ -242,14 +298,15 @@ struct QRCodeStyleView: View { Text(eyeType.displayName) .font(.caption) .foregroundColor(.primary) + .multilineTextAlignment(.center) } - .padding(8) + .padding(12) .background( - RoundedRectangle(cornerRadius: 12) + RoundedRectangle(cornerRadius: 16) .fill(selectedEyeType == eyeType ? Color.blue.opacity(0.1) : Color.clear) .overlay( - RoundedRectangle(cornerRadius: 12) - .stroke(selectedEyeType == eyeType ? Color.blue : Color.clear, lineWidth: 2) + RoundedRectangle(cornerRadius: 16) + .stroke(selectedEyeType == eyeType ? Color.blue : Color.clear, lineWidth: 3) ) ) } @@ -260,40 +317,42 @@ struct QRCodeStyleView: View { } } - // MARK: - Logo选择区域 - private var logoSelectionSection: some View { - VStack(alignment: .leading, spacing: 12) { - Text("Logo") - .font(.headline) - .foregroundColor(.primary) - - ScrollView(.horizontal, showsIndicators: false) { - HStack(spacing: 12) { + // MARK: - Logo内容 + private var logosContent: some View { + ScrollView { + VStack(spacing: 16) { + Text("选择Logo") + .font(.title2) + .fontWeight(.bold) + .padding(.top) + + LazyVGrid(columns: Array(repeating: GridItem(.flexible()), count: 3), spacing: 16) { // 无Logo选项 Button(action: { selectedLogo = nil }) { VStack(spacing: 8) { - RoundedRectangle(cornerRadius: 8) + RoundedRectangle(cornerRadius: 12) .fill(Color.gray.opacity(0.3)) - .frame(width: 40, height: 40) + .frame(width: 60, height: 60) .overlay( Text("无") - .font(.caption) + .font(.title2) .foregroundColor(.secondary) ) Text("无Logo") .font(.caption) .foregroundColor(.primary) + .multilineTextAlignment(.center) } - .padding(8) + .padding(12) .background( - RoundedRectangle(cornerRadius: 12) + RoundedRectangle(cornerRadius: 16) .fill(selectedLogo == nil ? Color.blue.opacity(0.1) : Color.clear) .overlay( - RoundedRectangle(cornerRadius: 12) - .stroke(selectedLogo == nil ? Color.blue : Color.clear, lineWidth: 2) + RoundedRectangle(cornerRadius: 16) + .stroke(selectedLogo == nil ? Color.blue : Color.clear, lineWidth: 3) ) ) } @@ -308,16 +367,16 @@ struct QRCodeStyleView: View { Image(uiImage: image) .resizable() .aspectRatio(contentMode: .fit) - .frame(width: 40, height: 40) + .frame(width: 60, height: 60) .background(Color.white) - .cornerRadius(8) + .cornerRadius(12) } else { - RoundedRectangle(cornerRadius: 8) + RoundedRectangle(cornerRadius: 12) .fill(Color.gray.opacity(0.3)) - .frame(width: 40, height: 40) + .frame(width: 60, height: 60) .overlay( Text("?") - .font(.caption) + .font(.title2) .foregroundColor(.secondary) ) } @@ -325,14 +384,15 @@ struct QRCodeStyleView: View { Text(logo.displayName) .font(.caption) .foregroundColor(.primary) + .multilineTextAlignment(.center) } - .padding(8) + .padding(12) .background( - RoundedRectangle(cornerRadius: 12) + RoundedRectangle(cornerRadius: 16) .fill(selectedLogo == logo ? Color.blue.opacity(0.1) : Color.clear) .overlay( - RoundedRectangle(cornerRadius: 12) - .stroke(selectedLogo == logo ? Color.blue : Color.clear, lineWidth: 2) + RoundedRectangle(cornerRadius: 16) + .stroke(selectedLogo == logo ? Color.blue : Color.clear, lineWidth: 3) ) ) } @@ -343,6 +403,37 @@ struct QRCodeStyleView: View { } } + // MARK: - 颜色选择区域 + private func colorSelectionSection( + title: String, + colors: [QRCodeColor], + selectedColor: Binding + ) -> some View { + VStack(alignment: .leading, spacing: 12) { + Text(title) + .font(.headline) + .foregroundColor(.primary) + + LazyVGrid(columns: Array(repeating: GridItem(.flexible()), count: 6), spacing: 12) { + ForEach(colors, id: \.self) { color in + Button(action: { + selectedColor.wrappedValue = color + }) { + RoundedRectangle(cornerRadius: 8) + .fill(color.color) + .frame(height: 40) + .overlay( + RoundedRectangle(cornerRadius: 8) + .stroke(selectedColor.wrappedValue == color ? Color.blue : Color.clear, lineWidth: 3) + ) + } + } + } + } + } + + + // MARK: - 保存二维码 private func saveQRCode() { guard let qrCodeImage = qrCodeImage else { return }