diff --git a/README.md b/README.md
index c955f92..6adb068 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,7 @@
[![CocoaPods platforms](https://img.shields.io/cocoapods/p/SwiftUIPager.svg)](https://cocoapods.org/pods/SwiftUIPager)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
-SwiftUIPager provides a `Pager` component built with SwiftUI native components. `Pager` is a horizontal view that will create a scrollable container to display a handful of pages. These pages are recycled on scroll, so you don't have to worry about memory issues.
+SwiftUIPager provides a `Pager` component built with SwiftUI native components. `Pager` is a view that renders a scrollable container to display a handful of pages. These pages are recycled on scroll, so you don't have to worry about memory issues.
@@ -63,6 +63,15 @@ whereas a value greater than one will make it look like a box:
+By default, `Pager` will create a horizontal container. Use `vertical` to create a vertical pager:
+
+```swift
+Pager(...)
+ .vertical()
+```
+
+
+
### Animations
Use `interactive` to pass a shrink ratio that will be applied to those components that are not focused, that is, those elements whose index is different from `pageIndex` binding:
diff --git a/Sample.xcodeproj/project.pbxproj b/Sample.xcodeproj/project.pbxproj
index 15390ab..73a2468 100644
--- a/Sample.xcodeproj/project.pbxproj
+++ b/Sample.xcodeproj/project.pbxproj
@@ -13,7 +13,7 @@
17D9E0FA23D4CF6900C5AE93 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 17D9E0F923D4CF6900C5AE93 /* Assets.xcassets */; };
17D9E0FD23D4CF6900C5AE93 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 17D9E0FC23D4CF6900C5AE93 /* Assets.xcassets */; };
17D9E10023D4CF6900C5AE93 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 17D9E0FE23D4CF6900C5AE93 /* LaunchScreen.storyboard */; };
- 6B3489B923D764D5002601D8 /* SwiftUIPager in Frameworks */ = {isa = PBXBuildFile; productRef = 6B3489B823D764D5002601D8 /* SwiftUIPager */; };
+ 6B3489BC23D85D46002601D8 /* SwiftUIPager in Frameworks */ = {isa = PBXBuildFile; productRef = 6B3489BB23D85D46002601D8 /* SwiftUIPager */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
@@ -32,7 +32,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
- 6B3489B923D764D5002601D8 /* SwiftUIPager in Frameworks */,
+ 6B3489BC23D85D46002601D8 /* SwiftUIPager in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -94,7 +94,7 @@
);
name = Sample;
packageProductDependencies = (
- 6B3489B823D764D5002601D8 /* SwiftUIPager */,
+ 6B3489BB23D85D46002601D8 /* SwiftUIPager */,
);
productName = SwiftUIPager;
productReference = 17D9E0F023D4CF6700C5AE93 /* Sample.app */;
@@ -125,7 +125,7 @@
);
mainGroup = 17D9E0E723D4CF6700C5AE93;
packageReferences = (
- 6B3489B723D764D5002601D8 /* XCRemoteSwiftPackageReference "SwiftUIPager" */,
+ 6B3489BA23D85D46002601D8 /* XCRemoteSwiftPackageReference "SwiftUIPager" */,
);
productRefGroup = 17D9E0F123D4CF6700C5AE93 /* Products */;
projectDirPath = "";
@@ -352,20 +352,20 @@
/* End XCConfigurationList section */
/* Begin XCRemoteSwiftPackageReference section */
- 6B3489B723D764D5002601D8 /* XCRemoteSwiftPackageReference "SwiftUIPager" */ = {
+ 6B3489BA23D85D46002601D8 /* XCRemoteSwiftPackageReference "SwiftUIPager" */ = {
isa = XCRemoteSwiftPackageReference;
- repositoryURL = "https://github.com/fermoya/SwiftUIPager.git";
+ repositoryURL = "https://github.com/fermoya/SwiftUIPager";
requirement = {
- branch = master;
+ branch = "feat/vertical-pagintation";
kind = branch;
};
};
/* End XCRemoteSwiftPackageReference section */
/* Begin XCSwiftPackageProductDependency section */
- 6B3489B823D764D5002601D8 /* SwiftUIPager */ = {
+ 6B3489BB23D85D46002601D8 /* SwiftUIPager */ = {
isa = XCSwiftPackageProductDependency;
- package = 6B3489B723D764D5002601D8 /* XCRemoteSwiftPackageReference "SwiftUIPager" */;
+ package = 6B3489BA23D85D46002601D8 /* XCRemoteSwiftPackageReference "SwiftUIPager" */;
productName = SwiftUIPager;
};
/* End XCSwiftPackageProductDependency section */
diff --git a/Sample.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Sample.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
index 0f602bc..fcde048 100644
--- a/Sample.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
+++ b/Sample.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
@@ -3,10 +3,10 @@
"pins": [
{
"package": "SwiftUIPager",
- "repositoryURL": "https://github.com/fermoya/SwiftUIPager.git",
+ "repositoryURL": "https://github.com/fermoya/SwiftUIPager",
"state": {
- "branch": "master",
- "revision": "1d22a5878394697884a4b15215522e04a68f835c",
+ "branch": "feat/vertical-pagintation",
+ "revision": "824efeeaac08717ef7d1aefc5037c3e3f32736e6",
"version": null
}
}
diff --git a/Sample/ContentView.swift b/Sample/ContentView.swift
index 54a1af5..65eec2a 100644
--- a/Sample/ContentView.swift
+++ b/Sample/ContentView.swift
@@ -31,7 +31,8 @@ struct ContentView: View {
.interactive(0.8)
.itemSpacing(10)
.padding(8)
- .itemAspectRatio(0.6)
+ .itemAspectRatio(1.5)
+ .vertical()
.border(Color.red, width: 2)
.frame(width: min(proxy.size.width,
proxy.size.height),
diff --git a/Sources/SwiftUIPager/Helpers/SizeViewModifier.swift b/Sources/SwiftUIPager/Helpers/SizeViewModifier.swift
index 44e30e8..b4a9057 100644
--- a/Sources/SwiftUIPager/Helpers/SizeViewModifier.swift
+++ b/Sources/SwiftUIPager/Helpers/SizeViewModifier.swift
@@ -27,9 +27,11 @@ struct SizeViewModifier: ViewModifier {
content
.preference(key: SizePreferenceKey.self,
value: proxy.size)
- }.onPreferenceChange(SizePreferenceKey.self, perform: { (newSize) in
+ }
+ .onPreferenceChange(SizePreferenceKey.self, perform: { (newSize) in
self.size = newSize
})
+ .clipped()
}
}
diff --git a/Sources/SwiftUIPager/Pager+Buildable.swift b/Sources/SwiftUIPager/Pager+Buildable.swift
index 6c81d2b..5bee404 100644
--- a/Sources/SwiftUIPager/Pager+Buildable.swift
+++ b/Sources/SwiftUIPager/Pager+Buildable.swift
@@ -10,6 +10,16 @@ import SwiftUI
extension Pager: Buildable {
+ /// Returns a horizontal pager
+ public func horizontal() -> Self {
+ mutating(keyPath: \.isHorizontal, value: true)
+ }
+
+ /// Returns a vertical pager
+ public func vertical() -> Self {
+ mutating(keyPath: \.isHorizontal, value: false)
+ }
+
/// Call this method to provide a shrink ratio that will apply to the items that are not focused.
///
/// - Parameter scale: shrink ratio
@@ -43,9 +53,12 @@ extension Pager: Buildable {
/// Configures the aspect ratio of each page. This value is considered to be _width / height_.
///
/// - `value > 1` will make the page spread horizontally and have a width larger than its height.
- /// - `value < 0` will give the page a larger height.
+ /// - `value < 1` will give the page a larger height.
+ ///
+ /// Note: `value` should be greater than 0
public func itemAspectRatio(_ value: CGFloat) -> Self {
- mutating(keyPath: \.itemAspectRatio, value: value)
+ guard value > 0 else { return self }
+ return mutating(keyPath: \.itemAspectRatio, value: value)
}
/// Adds a callback to react to every change on the page index.
@@ -59,12 +72,14 @@ extension Pager: Buildable {
public func padding(_ insets: EdgeInsets) -> Self {
let length = min(insets.top, insets.bottom)
- return padding(.vertical, length)
+ let edges: Edge.Set = isHorizontal ? .vertical : .horizontal
+ return padding(edges, length)
}
public func padding(_ edges: Edge.Set = .all, _ length: CGFloat? = nil) -> Self {
- guard edges == .all || edges == .vertical else { return self }
- return mutating(keyPath: \.verticalInsets, value: length ?? 8)
+ let allowedEdges: Edge.Set = isHorizontal ? .vertical : .horizontal
+ guard edges == .all || edges == allowedEdges else { return self }
+ return mutating(keyPath: \.sideInsets, value: length ?? 8)
}
}
diff --git a/Sources/SwiftUIPager/Pager+Helper.swift b/Sources/SwiftUIPager/Pager+Helper.swift
index 6f52e3b..4731442 100644
--- a/Sources/SwiftUIPager/Pager+Helper.swift
+++ b/Sources/SwiftUIPager/Pager+Helper.swift
@@ -10,11 +10,18 @@ import SwiftUI
extension Pager {
+ /// `true` if `Pager` is vertical
+ var isVertical: Bool {
+ return !isHorizontal
+ }
+
/// Size increment to be applied to a unfocs item when it comes to focus
var scaleIncrement: CGFloat { 1 - interactiveScale }
/// Total space between items. The spacing will be larger when `Pager` is interactive
- var interactiveItemSpacing: CGFloat { itemSpacing - (pageSize.width * scaleIncrement) / 2 }
+ var interactiveItemSpacing: CGFloat {
+ itemSpacing - (pageSize.width * scaleIncrement) / 2 + (isHorizontal ? 0 : (pageSize.height - pageSize.width) * (1 - scaleIncrement / 2))
+ }
/// `True` if the the user is dragging or some event is changing `contentOffset`
var isDragging: Bool { abs(totalOffset) > 0 }
@@ -51,8 +58,8 @@ extension Pager {
/// Size of each item. Takes into account `pageAspectRatio` and `verticalInsets` to fit the page into its container
var pageSize: CGSize {
- let size = CGSize(width: self.size.width - 2 * verticalInsets,
- height: self.size.height - 2 * verticalInsets)
+ let size = CGSize(width: self.size.width - 2 * sideInsets,
+ height: self.size.height - 2 * sideInsets)
let side = min(size.width, size.height)
if itemAspectRatio > 1 {
return CGSize(width: side, height: side / itemAspectRatio)
diff --git a/Sources/SwiftUIPager/Pager.swift b/Sources/SwiftUIPager/Pager.swift
index 9861d92..b2947e9 100644
--- a/Sources/SwiftUIPager/Pager.swift
+++ b/Sources/SwiftUIPager/Pager.swift
@@ -9,7 +9,7 @@
import SwiftUI
///
-/// `Pager` is a horizontal pager built with native SwiftUI components. Given a `ViewBuilder` and some `Identifiable` and `Equatable` data,
+/// `Pager` is a view built on top of native SwiftUI components. Given a `ViewBuilder` and some `Identifiable` and `Equatable` data,
/// this view will create a scrollable container to display a handful of pages. The pages are recycled on scroll. `Pager` is easily customizable through a number
/// of view-modifier functions. You can change the vertical insets, spacing between items, ... You can also make the pages size interactive.
///
@@ -53,7 +53,7 @@ public struct Pager: View where Content: View, Data: Identifiabl
let rotationInteractiveScale: CGFloat = 0.7
/// Axis of rotation when should rotate
- let rotationAxis: (x: CGFloat, y: CGFloat, z: CGFloat) = (0.2, 1, 0)
+ let rotationAxis: (x: CGFloat, y: CGFloat, z: CGFloat) = (0, 1, 0)
/*** Dependencies ***/
@@ -65,6 +65,8 @@ public struct Pager: View where Content: View, Data: Identifiabl
/*** ViewModified properties ***/
+ var isHorizontal: Bool = true
+
/// Shrink ratio that affects the items that aren't focused
var interactiveScale: CGFloat = 1
@@ -75,7 +77,7 @@ public struct Pager: View where Content: View, Data: Identifiabl
var contentOffset: CGFloat = 0
/// Vertical padding
- var verticalInsets: CGFloat = 0
+ var sideInsets: CGFloat = 0
/// Space between pages
var itemSpacing: CGFloat = 0
@@ -121,6 +123,8 @@ public struct Pager: View where Content: View, Data: Identifiabl
self.content(item)
.frame(size: self.pageSize)
.scaleEffect(self.scale(for: item))
+ .rotation3DEffect(self.isHorizontal ? .zero : Angle(degrees: -90),
+ axis: (0, 0, 1))
.rotation3DEffect(self.angle(for: item),
axis: self.axis(for: item))
.onTapGesture (perform: {
@@ -131,8 +135,9 @@ public struct Pager: View where Content: View, Data: Identifiabl
}
.offset(x: self.xOffset, y : 0)
}
- .clipped()
.gesture(self.swipeGesture)
+ .rotation3DEffect(isHorizontal ? .zero : Angle(degrees: 90),
+ axis: (0, 0, 1))
.sizeTrackable($size)
}
}
diff --git a/SwiftUIPager.podspec b/SwiftUIPager.podspec
index 138c987..6c0907f 100644
--- a/SwiftUIPager.podspec
+++ b/SwiftUIPager.podspec
@@ -1,11 +1,11 @@
Pod::Spec.new do |s|
s.name = "SwiftUIPager"
- s.version = "1.0.0"
- s.summary = "Native horizontal pager for SwiftUI. Easily to use, easy to customize."
+ s.version = "1.1.0"
+ s.summary = "Native pager for SwiftUI. Easily to use, easy to customize."
s.description = <<-DESC
- This framework provides a horizontal pager build with native SwiftUI views. Views are recycled, so you do not have to worry about memory issues. It is very easy to use and lets you customize it. For example, you can change the aspect ratio of the page displayed, the spacing between pages or you can make it interactive.
+ This framework provides a pager build on top of SwiftUI native components. Views are recycled, so you do not have to worry about memory issues. It is very easy to use and lets you customize it. For example, you can change the aspect ratio of the page displayed, the spacing between pages or you can make it interactive.
DESC
s.homepage = "https://medium.com/@fmdr.ct"
@@ -21,4 +21,4 @@ Pod::Spec.new do |s|
s.xcconfig = { "SWIFT_VERSION" => "5.1" }
s.documentation_url = "https://github.com/fermoya/SwiftUIPager/blob/master/README.md"
-end
\ No newline at end of file
+end
diff --git a/resources/vertical-pager.gif b/resources/vertical-pager.gif
new file mode 100644
index 0000000..f39b2db
Binary files /dev/null and b/resources/vertical-pager.gif differ