Skip to content

Commit

Permalink
Merge pull request #2 from fermoya/feat/vertical-pagintation
Browse files Browse the repository at this point in the history
Feat/vertical pagintation
  • Loading branch information
fermoya authored Jan 22, 2020
2 parents 38273cd + eb4ebf8 commit 1689bf1
Show file tree
Hide file tree
Showing 10 changed files with 70 additions and 31 deletions.
11 changes: 10 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

<img src="resources/example-of-usage.gif" alt="Example of usage"/>

Expand Down Expand Up @@ -63,6 +63,15 @@ whereas a value greater than one will make it look like a box:

<img src="resources/page_aspect_ratio_greater_than_1.png" alt="PageAspectRatio greater than 1" height="640"/>

By default, `Pager` will create a horizontal container. Use `vertical` to create a vertical pager:

```swift
Pager(...)
.vertical()
```

<img src="resources/vertical-pager.gif" alt="PageAspectRatio greater than 1" height="640"/>

### 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:
Expand Down
18 changes: 9 additions & 9 deletions Sample.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand All @@ -32,7 +32,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
6B3489B923D764D5002601D8 /* SwiftUIPager in Frameworks */,
6B3489BC23D85D46002601D8 /* SwiftUIPager in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -94,7 +94,7 @@
);
name = Sample;
packageProductDependencies = (
6B3489B823D764D5002601D8 /* SwiftUIPager */,
6B3489BB23D85D46002601D8 /* SwiftUIPager */,
);
productName = SwiftUIPager;
productReference = 17D9E0F023D4CF6700C5AE93 /* Sample.app */;
Expand Down Expand Up @@ -125,7 +125,7 @@
);
mainGroup = 17D9E0E723D4CF6700C5AE93;
packageReferences = (
6B3489B723D764D5002601D8 /* XCRemoteSwiftPackageReference "SwiftUIPager" */,
6B3489BA23D85D46002601D8 /* XCRemoteSwiftPackageReference "SwiftUIPager" */,
);
productRefGroup = 17D9E0F123D4CF6700C5AE93 /* Products */;
projectDirPath = "";
Expand Down Expand Up @@ -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 */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}
Expand Down
3 changes: 2 additions & 1 deletion Sample/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
4 changes: 3 additions & 1 deletion Sources/SwiftUIPager/Helpers/SizeViewModifier.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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()
}
}

Expand Down
25 changes: 20 additions & 5 deletions Sources/SwiftUIPager/Pager+Buildable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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.
Expand All @@ -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)
}

}
13 changes: 10 additions & 3 deletions Sources/SwiftUIPager/Pager+Helper.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
Expand Down Expand Up @@ -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)
Expand Down
13 changes: 9 additions & 4 deletions Sources/SwiftUIPager/Pager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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.
///
Expand Down Expand Up @@ -53,7 +53,7 @@ public struct Pager<Data, Content>: 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 ***/

Expand All @@ -65,6 +65,8 @@ public struct Pager<Data, Content>: 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

Expand All @@ -75,7 +77,7 @@ public struct Pager<Data, Content>: 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
Expand Down Expand Up @@ -121,6 +123,8 @@ public struct Pager<Data, Content>: 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: {
Expand All @@ -131,8 +135,9 @@ public struct Pager<Data, Content>: 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)
}
}
Expand Down
8 changes: 4 additions & 4 deletions SwiftUIPager.podspec
Original file line number Diff line number Diff line change
@@ -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"
Expand All @@ -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
end
Binary file added resources/vertical-pager.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 1689bf1

Please sign in to comment.