aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbenedom <>2024-04-16 10:51:16 +0200
committerbenedom <>2024-04-16 11:00:59 +0200
commit5e4554272f1262120a643efb39ccdb890ae592fe (patch)
treeb41eb7a0c5517a03d6937bb7c58cbb61ddb12920
parentbe22624ac4e3d15091aa4556f4f7bdf1ff2b65ad (diff)
Adjusted demo application to include all configuration options
-rw-r--r--Demo/SwiftyCropDemo.xcodeproj/project.pbxproj18
-rw-r--r--Demo/SwiftyCropDemo/ContentView.swift115
-rw-r--r--Demo/SwiftyCropDemo/ShapeButton.swift32
-rw-r--r--Demo/SwiftyCropDemo/UIElements/DecimalTextField.swift20
-rw-r--r--Demo/SwiftyCropDemo/UIElements/LongText.swift (renamed from Demo/SwiftyCropDemo/LongText.swift)0
-rw-r--r--Sources/SwiftyCrop/Models/MaskShape.swift2
-rw-r--r--Sources/SwiftyCrop/Models/SwiftyCropConfiguration.swift8
7 files changed, 118 insertions, 77 deletions
diff --git a/Demo/SwiftyCropDemo.xcodeproj/project.pbxproj b/Demo/SwiftyCropDemo.xcodeproj/project.pbxproj
index de1f6b6..5609787 100644
--- a/Demo/SwiftyCropDemo.xcodeproj/project.pbxproj
+++ b/Demo/SwiftyCropDemo.xcodeproj/project.pbxproj
@@ -12,8 +12,8 @@
7D05339D2B60AE9D001056D4 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7D05339C2B60AE9D001056D4 /* Assets.xcassets */; };
7D0533A02B60AE9D001056D4 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7D05339F2B60AE9D001056D4 /* Preview Assets.xcassets */; };
7D0533A82B60AFE0001056D4 /* SwiftyCrop in Frameworks */ = {isa = PBXBuildFile; productRef = 7D0533A72B60AFE0001056D4 /* SwiftyCrop */; };
- 7D3848F02B618832009AF289 /* ShapeButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7D3848EF2B618832009AF289 /* ShapeButton.swift */; };
7D3848F22B61888F009AF289 /* LongText.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7D3848F12B61888F009AF289 /* LongText.swift */; };
+ BA4737712BCE6ED500DC696D /* DecimalTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA4737702BCE6ED500DC696D /* DecimalTextField.swift */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
@@ -23,8 +23,8 @@
7D05339C2B60AE9D001056D4 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
7D05339F2B60AE9D001056D4 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
7D0C5DFA2B63F03F004BD980 /* SwiftyCropDemo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = SwiftyCropDemo.xcconfig; sourceTree = "<group>"; };
- 7D3848EF2B618832009AF289 /* ShapeButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShapeButton.swift; sourceTree = "<group>"; };
7D3848F12B61888F009AF289 /* LongText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LongText.swift; sourceTree = "<group>"; };
+ BA4737702BCE6ED500DC696D /* DecimalTextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DecimalTextField.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -58,8 +58,7 @@
7D0533972B60AE9C001056D4 /* SwiftyCropDemo */ = {
isa = PBXGroup;
children = (
- 7D3848F12B61888F009AF289 /* LongText.swift */,
- 7D3848EF2B618832009AF289 /* ShapeButton.swift */,
+ BA47376F2BCE6EBE00DC696D /* UIElements */,
7D05339A2B60AE9C001056D4 /* ContentView.swift */,
7D0533982B60AE9C001056D4 /* SwiftyCropDemoApp.swift */,
7D05339C2B60AE9D001056D4 /* Assets.xcassets */,
@@ -77,6 +76,15 @@
path = "Preview Content";
sourceTree = "<group>";
};
+ BA47376F2BCE6EBE00DC696D /* UIElements */ = {
+ isa = PBXGroup;
+ children = (
+ 7D3848F12B61888F009AF289 /* LongText.swift */,
+ BA4737702BCE6ED500DC696D /* DecimalTextField.swift */,
+ );
+ path = UIElements;
+ sourceTree = "<group>";
+ };
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
@@ -154,7 +162,7 @@
buildActionMask = 2147483647;
files = (
7D05339B2B60AE9C001056D4 /* ContentView.swift in Sources */,
- 7D3848F02B618832009AF289 /* ShapeButton.swift in Sources */,
+ BA4737712BCE6ED500DC696D /* DecimalTextField.swift in Sources */,
7D3848F22B61888F009AF289 /* LongText.swift in Sources */,
7D0533992B60AE9C001056D4 /* SwiftyCropDemoApp.swift in Sources */,
);
diff --git a/Demo/SwiftyCropDemo/ContentView.swift b/Demo/SwiftyCropDemo/ContentView.swift
index cfb1f01..f4e90ee 100644
--- a/Demo/SwiftyCropDemo/ContentView.swift
+++ b/Demo/SwiftyCropDemo/ContentView.swift
@@ -1,10 +1,3 @@
-//
-// ContentView.swift
-// SwiftyCropDemo
-//
-// Created by Leonid Zolotarev on 1/23/24.
-//
-
import SwiftUI
import SwiftyCrop
@@ -12,12 +5,24 @@ struct ContentView: View {
@State private var showImageCropper: Bool = false
@State private var selectedImage: UIImage?
@State private var selectedShape: MaskShape = .square
- @State private var cropImageCircular: Bool = false
- @State private var rotateImage: Bool = true
-
+ @State private var cropImageCircular: Bool
+ @State private var rotateImage: Bool
+ @State private var maxMagnificationScale: CGFloat
+ @State private var maskRadius: CGFloat
+ @FocusState private var textFieldFocused: Bool
+
+ init() {
+ let defaultConfiguration = SwiftyCropConfiguration()
+ _cropImageCircular = State(initialValue: defaultConfiguration.cropImageCircular)
+ _rotateImage = State(initialValue: defaultConfiguration.rotateImage)
+ _maxMagnificationScale = State(initialValue: defaultConfiguration.maxMagnificationScale)
+ _maskRadius = State(initialValue: defaultConfiguration.maskRadius)
+ }
+
var body: some View {
VStack {
Spacer()
+
Group {
if let selectedImage = selectedImage {
Image(uiImage: selectedImage)
@@ -30,34 +35,72 @@ struct ContentView: View {
}
.scaledToFit()
.padding()
+
Spacer()
+
GroupBox {
- HStack {
- Button {
- loadImage()
- } label: {
- LongText(title: "Load image")
+ VStack(spacing: 15) {
+ HStack {
+ Button {
+ loadImage()
+ } label: {
+ LongText(title: "Load image")
+ }
+ Button {
+ showImageCropper.toggle()
+ } label: {
+ LongText(title: "Crop image")
+ }
}
- Button {
- showImageCropper.toggle()
- } label: {
- LongText(title: "Crop image")
+
+ HStack {
+ Text("Mask shape")
+ .frame(maxWidth: .infinity, alignment: .leading)
+
+ Picker("maskShape", selection: $selectedShape) {
+ ForEach(MaskShape.allCases, id: \.self) { mask in
+ Text(String(describing: mask))
+ }
+ }
+ .pickerStyle(.segmented)
+ }
+
+ Toggle("Crop image to circle", isOn: $cropImageCircular)
+
+ Toggle("Rotate image", isOn: $rotateImage)
+
+ HStack {
+ Text("Max magnification")
+ .frame(maxWidth: .infinity, alignment: .leading)
+
+ DecimalTextField(value: $maxMagnificationScale)
+ .focused($textFieldFocused)
+ }
+
+ HStack {
+ Text("Mask radius")
+ .frame(maxWidth: .infinity, alignment: .leading)
+
+ Button {
+ maskRadius = UIScreen.main.bounds.width / 2
+ } label: {
+ Image(systemName: "arrow.up.left.and.arrow.down.right")
+ .font(.footnote)
+ }
+
+ DecimalTextField(value: $maskRadius)
+ .focused($textFieldFocused)
}
}
- HStack {
- ShapeButton(
- title: "Use square crop",
- shape: .square,
- selection: $selectedShape
- )
- ShapeButton(
- title: "Use circle crop",
- shape: .circle,
- selection: $selectedShape
- )
+ }
+ .toolbar {
+ ToolbarItemGroup(placement: .keyboard) {
+ Spacer()
+
+ Button("Done") {
+ textFieldFocused = false
+ }
}
- Toggle("Crop image to circle", isOn: $cropImageCircular)
- Toggle("Rotate image", isOn: $rotateImage)
}
.buttonStyle(.bordered)
.padding()
@@ -71,6 +114,8 @@ struct ContentView: View {
imageToCrop: selectedImage,
maskShape: selectedShape,
configuration: SwiftyCropConfiguration(
+ maxMagnificationScale: maxMagnificationScale,
+ maskRadius: maskRadius,
cropImageCircular: cropImageCircular,
rotateImage: rotateImage
)
@@ -81,13 +126,13 @@ struct ContentView: View {
}
}
}
-
+
private func loadImage() {
Task {
selectedImage = await downloadExampleImage()
}
}
-
+
// Example function for downloading an image
private func downloadExampleImage() async -> UIImage? {
let urlString = "https://picsum.photos/1000/1200"
@@ -95,7 +140,7 @@ struct ContentView: View {
let (data, _) = try? await URLSession.shared.data(from: url),
let image = UIImage(data: data)
else { return nil }
-
+
return image
}
}
diff --git a/Demo/SwiftyCropDemo/ShapeButton.swift b/Demo/SwiftyCropDemo/ShapeButton.swift
deleted file mode 100644
index c7aae9f..0000000
--- a/Demo/SwiftyCropDemo/ShapeButton.swift
+++ /dev/null
@@ -1,32 +0,0 @@
-//
-// ShapeButton.swift
-// SwiftyCropDemo
-//
-// Created by Leonid Zolotarev on 1/24/24.
-//
-
-import SwiftUI
-import SwiftyCrop
-
-struct ShapeButton: View {
- let title: String
- let shape: MaskShape
- @Binding var selection: MaskShape
-
- var body: some View {
- Button {
- selection = shape
- } label: {
- LongText(title: title)
- }
- .foregroundColor(selection == shape ? .accentColor : .secondary)
- }
-}
-
-#Preview {
- ShapeButton(
- title: "title",
- shape: .circle,
- selection: .constant(.circle)
- )
-}
diff --git a/Demo/SwiftyCropDemo/UIElements/DecimalTextField.swift b/Demo/SwiftyCropDemo/UIElements/DecimalTextField.swift
new file mode 100644
index 0000000..f616413
--- /dev/null
+++ b/Demo/SwiftyCropDemo/UIElements/DecimalTextField.swift
@@ -0,0 +1,20 @@
+import SwiftUI
+
+struct DecimalTextField: View {
+ @Binding var value: CGFloat
+ private let decimalFormatter: NumberFormatter = {
+ let formatter = NumberFormatter()
+ formatter.numberStyle = .decimal
+ formatter.allowsFloats = true
+ formatter.minimumFractionDigits = 1
+ formatter.decimalSeparator = "."
+ return formatter
+ }()
+
+ var body: some View {
+ TextField("maxMagnification", value: $value, formatter: decimalFormatter)
+ .textFieldStyle(RoundedBorderTextFieldStyle())
+ .multilineTextAlignment(.trailing)
+ .keyboardType(.decimalPad)
+ }
+}
diff --git a/Demo/SwiftyCropDemo/LongText.swift b/Demo/SwiftyCropDemo/UIElements/LongText.swift
index 77e211a..77e211a 100644
--- a/Demo/SwiftyCropDemo/LongText.swift
+++ b/Demo/SwiftyCropDemo/UIElements/LongText.swift
diff --git a/Sources/SwiftyCrop/Models/MaskShape.swift b/Sources/SwiftyCrop/Models/MaskShape.swift
index d20e722..38e5f20 100644
--- a/Sources/SwiftyCrop/Models/MaskShape.swift
+++ b/Sources/SwiftyCrop/Models/MaskShape.swift
@@ -1,3 +1,3 @@
-public enum MaskShape {
+public enum MaskShape: CaseIterable {
case circle, square
}
diff --git a/Sources/SwiftyCrop/Models/SwiftyCropConfiguration.swift b/Sources/SwiftyCrop/Models/SwiftyCropConfiguration.swift
index b41ea53..8cda96c 100644
--- a/Sources/SwiftyCrop/Models/SwiftyCropConfiguration.swift
+++ b/Sources/SwiftyCrop/Models/SwiftyCropConfiguration.swift
@@ -2,10 +2,10 @@ import CoreGraphics
/// `SwiftyCropConfiguration` is a struct that defines the configuration for cropping behavior.
public struct SwiftyCropConfiguration {
- let maxMagnificationScale: CGFloat
- let maskRadius: CGFloat
- let cropImageCircular: Bool
- let rotateImage: Bool
+ public let maxMagnificationScale: CGFloat
+ public let maskRadius: CGFloat
+ public let cropImageCircular: Bool
+ public let rotateImage: Bool
/// Creates a new instance of `SwiftyCropConfiguration`.
///