diff --git a/PuraceDemo/PuraceDemo/Examples/Complex/ImageViewerExample.swift b/PuraceDemo/PuraceDemo/Examples/Complex/ImageViewerExample.swift
index ce44bf4..65d9b82 100644
--- a/PuraceDemo/PuraceDemo/Examples/Complex/ImageViewerExample.swift
+++ b/PuraceDemo/PuraceDemo/Examples/Complex/ImageViewerExample.swift
@@ -12,6 +12,12 @@ import Purace
struct ImageViewerExample: View {
@State var isVisible = false
+ let urls: [URL?] = [
+ URL(string: "https://payan-dev-images.s3.us-east-2.amazonaws.com/santo-domingo.jpg"),
+ URL(string: "https://payan-dev-images.s3.us-east-2.amazonaws.com/santo-domingo.jpg"),
+ URL(string: "https://payan-places.s3.us-east-2.amazonaws.com/001/001.jpg")
+ ]
+
var body: some View {
VStack {
PuraceButtonView("Mostrar imagen") {
@@ -19,8 +25,10 @@ struct ImageViewerExample: View {
}
Spacer()
}.imageViewer(
- url: URL(string: "https://payan-dev-images.s3.us-east-2.amazonaws.com/santo-domingo.jpg"),
- isVisible: $isVisible
+ urls: urls,
+ isVisible: $isVisible,
+ selectedIndex: 1
)
+ .navigationBarHidden(true)
}
}
diff --git a/Sources/Purace/Resources/Media.xcassets/arrow_back.imageset/Contents.json b/Sources/Purace/Resources/Media.xcassets/arrow_back.imageset/Contents.json
new file mode 100644
index 0000000..7c6179f
--- /dev/null
+++ b/Sources/Purace/Resources/Media.xcassets/arrow_back.imageset/Contents.json
@@ -0,0 +1,12 @@
+{
+ "images" : [
+ {
+ "filename" : "arrow_back.svg",
+ "idiom" : "universal"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/Sources/Purace/Resources/Media.xcassets/arrow_back.imageset/arrow_back.svg b/Sources/Purace/Resources/Media.xcassets/arrow_back.imageset/arrow_back.svg
new file mode 100644
index 0000000..1d069ae
--- /dev/null
+++ b/Sources/Purace/Resources/Media.xcassets/arrow_back.imageset/arrow_back.svg
@@ -0,0 +1,8 @@
+
diff --git a/Sources/Purace/Views/Complex/Image Viewer/PuraceImageViewer.swift b/Sources/Purace/Views/Complex/Image Viewer/PuraceImageViewer.swift
index aacd169..6d2838a 100644
--- a/Sources/Purace/Views/Complex/Image Viewer/PuraceImageViewer.swift
+++ b/Sources/Purace/Views/Complex/Image Viewer/PuraceImageViewer.swift
@@ -11,117 +11,117 @@ import Kingfisher
public struct PuraceImageViewer: View {
@Binding var isVisible: Bool
- let backgroundColor: Color
- let url: URL?
- @State var opacity: Double = 0
- @State var dragOffset: CGSize = .zero
- @State var backgroundOpacity: Double = 1
- @State var hasDraggedTheImage = false
- @State var dragInitialTime: Date?
-
+ let urls: [URL?]
+ @State var currentIndex: Int
@GestureState var scale: CGFloat = 1
+ @State var dragOffset: CGFloat = .zero
+ @State var backgroundOpacity = 1.0
+
+ private let numberOfImages: Int
private let maximumImageHeight = UIScreen.main.bounds.height * 0.65
- public init(url: URL?, isVisible: Binding) {
- let colors: [Color] = [
- PuraceStyle.Color.X1,
- PuraceStyle.Color.X2,
- PuraceStyle.Color.X3,
- PuraceStyle.Color.X4
- ]
- backgroundColor = colors.randomElement()!
- self.url = url
+ public init(urls: [URL?], isVisible: Binding, index: Int = 0) {
+ self.urls = urls
self._isVisible = isVisible
+ self._currentIndex = .init(initialValue: index)
+ self.numberOfImages = urls.count
}
- private func differenceBeetwenInitialDragTime(and date: Date) -> Double {
- guard let dragInitialTime = dragInitialTime else {
- return .zero
+ var indicator: some View {
+ HStack {
+ if numberOfImages > 1 {
+ PuraceTextView("\(currentIndex + 1)/\(numberOfImages)", fontSize: 14, textColor: .white, weight: .medium)
+ .padding(.trailing)
+ }
}
- return date.timeIntervalSince(dragInitialTime) * 1000
}
- var draggableArea: some View {
- Color.black
- .animation(.none)
- .opacity(0.001)
- .gesture(
+ var backButton: some View {
+ Image(systemName: "chevron.left")
+ .foregroundColor(.white)
+ .scaleEffect(1.2)
+ .padding()
+ .highPriorityGesture(
+ TapGesture()
+ .onEnded {
+ withAnimation {
+ isVisible = false
+ }
+ }
+ )
+ }
+
+ var topBar: some View {
+ VStack {
+ HStack(alignment: .center) {
+ backButton
+
+ Spacer()
+
+ indicator
+ }.frame(height: 60)
+ .opacity((abs(dragOffset) >= .zero && abs(dragOffset) <= 5) ? 1 : 0.0002)
+ }
+ }
+
+ var viewer: some View {
+ VStack(spacing: 0) {
+ topBar
+
+ TabView(selection: $currentIndex) {
+ ForEach(0..= 0.9 {
+ scale = value
+ }
+ }
+ )
+ }
+ }
+ .tabViewStyle(PageTabViewStyle(indexDisplayMode: .never))
+ .simultaneousGesture(
DragGesture()
.onChanged { value in
- hasDraggedTheImage = true
- if scale == 1 {
- if dragInitialTime == nil {
- dragInitialTime = Date()
- }
- let translation = value.translation.height
- dragOffset.height = translation
- backgroundOpacity = 1 - abs(translation) * 0.001
+ dragOffset = value.translation.height
+ let screenHeight = UIScreen.main.bounds.height
+ let progress = abs(dragOffset) / screenHeight / 2
+ withAnimation {
+ backgroundOpacity = 1 - progress
}
}
- .onEnded { value in
- if scale == 1 {
- let diff = differenceBeetwenInitialDragTime(and: Date())
- if diff <= 150 || abs(dragOffset.height) >= UIScreen.main.bounds.height * 0.4 {
- hideView()
- } else {
- withAnimation {
- backgroundOpacity = 1
- }
- dragOffset = .zero
+ .onEnded { _ in
+ if abs(dragOffset) < 200 {
+ withAnimation {
+ dragOffset = 0
+ backgroundOpacity = 1
+ }
+ } else {
+ withAnimation {
+ isVisible = false
}
- dragInitialTime = nil
}
}
)
- .simultaneousGesture(
- MagnificationGesture()
- .updating($scale, body: { value, state, _ in
- guard value > 0.7 else { return }
- state = value
- })
- )
- }
-
- var image: some View {
- PuraceImageView(url: url)
- .scaledToFit()
- .offset(x: dragOffset.width, y: dragOffset.height)
- .animation(hasDraggedTheImage ? .easeOut(duration: 0.35) : .none)
- .scaleEffect(scale)
- .frame(maxHeight: maximumImageHeight)
- }
-
- public var body: some View {
- ZStack {
- backgroundColor
+ .onChange(of: currentIndex) { _ in
+ dragOffset = .zero
+ }
+
+ }.background(
+ PuraceStyle.Color.X1
+ .edgesIgnoringSafeArea(.all)
.opacity(backgroundOpacity)
- image
- draggableArea
- }
- .edgesIgnoringSafeArea(.all)
- .transition(.opacity.animation(.linear))
- }
-}
-
-extension PuraceImageViewer {
- private func hideImage() {
- withAnimation {
- if dragOffset.height > 0 {
- dragOffset.height = UIScreen.main.bounds.height
- } else {
- dragOffset.height = -UIScreen.main.bounds.height
- }
- }
+ )
}
- private func hideView() {
- hideImage()
- withAnimation {
- backgroundOpacity = 0
- }
- DispatchQueue.main.asyncAfter(deadline: .now() + 0.25) {
- isVisible = false
- }
+ public var body: some View {
+ viewer
}
}
diff --git a/Sources/Purace/Views/Complex/Image Viewer/PuraceImageViewerModifier.swift b/Sources/Purace/Views/Complex/Image Viewer/PuraceImageViewerModifier.swift
index 0c69e29..257d8c3 100644
--- a/Sources/Purace/Views/Complex/Image Viewer/PuraceImageViewerModifier.swift
+++ b/Sources/Purace/Views/Complex/Image Viewer/PuraceImageViewerModifier.swift
@@ -9,26 +9,28 @@ import Foundation
import SwiftUI
public struct PuraceImageViewerModifier: ViewModifier {
- let url: URL?
+ let urls: [URL?]
@Binding var isVisible: Bool
+ let selectedIndex: Int
- public init(url: URL?, isVisible: Binding) {
- self.url = url
+ public init(urls: [URL?], isVisible: Binding, selectedIndex: Int) {
+ self.urls = urls
self._isVisible = isVisible
+ self.selectedIndex = selectedIndex
}
public func body(content: Content) -> some View {
ZStack {
content
if isVisible {
- PuraceImageViewer(url: url, isVisible: $isVisible)
+ PuraceImageViewer(urls: urls, isVisible: $isVisible, index: selectedIndex)
}
}
}
}
public extension View {
- func imageViewer(url: URL?, isVisible: Binding) -> some View {
- modifier(PuraceImageViewerModifier(url: url, isVisible: isVisible))
+ func imageViewer(urls: [URL?], isVisible: Binding, selectedIndex: Int = 0) -> some View {
+ modifier(PuraceImageViewerModifier(urls: urls, isVisible: isVisible, selectedIndex: selectedIndex))
}
}