Skip to content

Commit

Permalink
Fixing gesture collisions
Browse files Browse the repository at this point in the history
  • Loading branch information
Fernando Moya de Rivas committed Jan 23, 2020
1 parent 80a5e5b commit 3b05829
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 29 deletions.
13 changes: 0 additions & 13 deletions Sources/SwiftUIPager/Helpers/SizeViewModifier.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,6 @@

import SwiftUI

/// Tracks the size of the view
struct SizePreferenceKey: PreferenceKey {
static var defaultValue: CGSize = .zero

static func reduce(value: inout CGSize, nextValue: () -> CGSize) {
let newValue = nextValue()
guard value != newValue else { return }
value = newValue
}
}

/// This modifier wraps a view into a `GeometryReader` and tracks the available space by using `SizePreferenceKey` on the content
struct SizeViewModifier: ViewModifier {

Expand All @@ -27,8 +16,6 @@ struct SizeViewModifier: ViewModifier {
func body(content: Content) -> some View {
GeometryReader { proxy in
content
.preference(key: SizePreferenceKey.self,
value: proxy.size)
.frame(width: proxy.size.width, height: proxy.size.height)
.onAppear (perform: {
self.size = proxy.size
Expand Down
5 changes: 5 additions & 0 deletions Sources/SwiftUIPager/Pager+Buildable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ import SwiftUI

extension Pager: Buildable {

/// Adds a `TapGesture` to the items to bring them to focus
public func itemTappable(_ value: Bool) -> Self {
mutating(keyPath: \.isItemTappable, value: value)
}

/// Returns a horizontal pager
public func horizontal() -> Self {
mutating(keyPath: \.isHorizontal, value: true)
Expand Down
10 changes: 5 additions & 5 deletions Sources/SwiftUIPager/Pager+Helper.swift
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ extension Pager {
}

/// Data that is being displayed at the moment
var dataDisplayed: [Data] {
var dataDisplayed: [Element] {
Array(data[lowerPageDisplayed..<upperPageDisplayed])
}

Expand All @@ -117,7 +117,7 @@ extension Pager {
}

/// Angle for the 3D rotation effect
func angle(for item: Data) -> Angle {
func angle(for item: Element) -> Angle {
guard shouldRotate else { return .zero }
guard let index = data.firstIndex(of: item) else { return .zero }

Expand All @@ -133,7 +133,7 @@ extension Pager {
}

/// Axis for the rotations effect
func axis(for item: Data) -> (CGFloat, CGFloat, CGFloat) {
func axis(for item: Element) -> (CGFloat, CGFloat, CGFloat) {
guard shouldRotate else { return (0, 0, 0) }
guard let index = data.firstIndex(of: item) else { return (0, 0, 0) }

Expand All @@ -142,7 +142,7 @@ extension Pager {
}

/// Scale that applies to a particular item
func scale(for item: Data) -> CGFloat {
func scale(for item: Element) -> CGFloat {
guard isDragging else { return isFocused(item) ? 1 : interactiveScale }

let totalIncrement = abs(totalOffset / pageDistance)
Expand All @@ -164,7 +164,7 @@ extension Pager {
}

/// Returns true if the item is focused on the screen.
func isFocused(_ item: Data) -> Bool {
func isFocused(_ item: Element) -> Bool {
data.firstIndex(of: item) == currentPage
}

Expand Down
32 changes: 21 additions & 11 deletions Sources/SwiftUIPager/Pager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import SwiftUI
/// - 30 px of vertical insets
/// - 0.6 shrink ratio for items that aren't focused.
///
public struct Pager<Data, Content>: View where Content: View, Data: Identifiable & Equatable {
public struct Pager<Element, PageView>: View where PageView: View, Element: Identifiable & Equatable {

/// `Direction` determines the direction of the swipe gesture
enum Direction {
Expand Down Expand Up @@ -58,13 +58,17 @@ public struct Pager<Data, Content>: View where Content: View, Data: Identifiabl
/*** Dependencies ***/

/// `ViewBuilder` block to create each page
let content: (Data) -> Content
let content: (Element) -> PageView

/// Array of items that will populate each page
var data: [Data]
var data: [Element]

/*** ViewModified properties ***/

/// `true` if items are tapable
var isItemTappable: Bool = false

/// `true` if the pager is horizontal
var isHorizontal: Bool = true

/// Shrink ratio that affects the items that aren't focused
Expand Down Expand Up @@ -111,12 +115,12 @@ public struct Pager<Data, Content>: View where Content: View, Data: Identifiabl
/// - Parameter page: Binding to the index of the focused page
/// - Parameter data: Array of items to populate the content
/// - Parameter content: Factory method to build new pages
public init(page: Binding<Int>, data: [Data], @ViewBuilder content: @escaping (Data) -> Content) {
public init(page: Binding<Int>, data: [Element], @ViewBuilder content: @escaping (Element) -> PageView) {
self._page = page
self.data = data
self.content = content
}

public var body: some View {
HStack(spacing: self.interactiveItemSpacing) {
ForEach(self.dataDisplayed) { item in
Expand All @@ -127,11 +131,8 @@ public struct Pager<Data, Content>: View where Content: View, Data: Identifiabl
axis: (0, 0, 1))
.rotation3DEffect(self.angle(for: item),
axis: self.axis(for: item))
.onTapGesture (perform: {
withAnimation(.spring()) {
self.scrollToItem(item)
}
})
.gesture(self.tapGesture(for: item))
.disabled(self.isFocused(item) || !self.isItemTappable)
}
.offset(x: self.xOffset, y : 0)
}
Expand All @@ -147,11 +148,20 @@ public struct Pager<Data, Content>: View where Content: View, Data: Identifiabl
extension Pager {

/// Helper function to scroll to a specific item.
func scrollToItem(_ item: Data) {
func scrollToItem(_ item: Element) {
guard let index = data.firstIndex(of: item) else { return }
self.page = index
}

func tapGesture(for item: Element) -> some Gesture {
TapGesture(count: 1)
.onEnded({ _ in
withAnimation(.spring()) {
self.scrollToItem(item)
}
})
}

/// `DragGesture` customized to work with `Pager`
var swipeGesture: some Gesture {
DragGesture()
Expand Down

0 comments on commit 3b05829

Please sign in to comment.