Skip to content

Commit

Permalink
Adjusted demo application to include all configuration options
Browse files Browse the repository at this point in the history
  • Loading branch information
benedom committed Apr 16, 2024
1 parent be22624 commit 5e45542
Show file tree
Hide file tree
Showing 7 changed files with 118 additions and 77 deletions.
18 changes: 13 additions & 5 deletions Demo/SwiftyCropDemo.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand All @@ -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 */
Expand Down Expand Up @@ -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 */,
Expand All @@ -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 */
Expand Down Expand Up @@ -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 */,
);
Expand Down
115 changes: 80 additions & 35 deletions Demo/SwiftyCropDemo/ContentView.swift
Original file line number Diff line number Diff line change
@@ -1,23 +1,28 @@
//
// ContentView.swift
// SwiftyCropDemo
//
// Created by Leonid Zolotarev on 1/23/24.
//

import SwiftUI
import SwiftyCrop

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)
Expand All @@ -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()
Expand All @@ -71,6 +114,8 @@ struct ContentView: View {
imageToCrop: selectedImage,
maskShape: selectedShape,
configuration: SwiftyCropConfiguration(
maxMagnificationScale: maxMagnificationScale,
maskRadius: maskRadius,
cropImageCircular: cropImageCircular,
rotateImage: rotateImage
)
Expand All @@ -81,21 +126,21 @@ 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"
guard let url = URL(string: urlString),
let (data, _) = try? await URLSession.shared.data(from: url),
let image = UIImage(data: data)
else { return nil }

return image
}
}
Expand Down
32 changes: 0 additions & 32 deletions Demo/SwiftyCropDemo/ShapeButton.swift

This file was deleted.

20 changes: 20 additions & 0 deletions Demo/SwiftyCropDemo/UIElements/DecimalTextField.swift
Original file line number Diff line number Diff line change
@@ -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)
}
}
File renamed without changes.
2 changes: 1 addition & 1 deletion Sources/SwiftyCrop/Models/MaskShape.swift
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
public enum MaskShape {
public enum MaskShape: CaseIterable {
case circle, square
}
8 changes: 4 additions & 4 deletions Sources/SwiftyCrop/Models/SwiftyCropConfiguration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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`.
///
Expand Down

0 comments on commit 5e45542

Please sign in to comment.