Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RTL Support #14

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Example/liquid-swipe/ViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ class ViewController: LiquidSwipeContainerController, LiquidSwipeContainerDataSo
}()

override func viewDidLoad() {
// Uncomment for testing RTL
// view.semanticContentAttribute = .forceRightToLeft
super.viewDidLoad()
datasource = self
}
Expand Down
91 changes: 66 additions & 25 deletions liquid-swipe/Classes/LiquidSwipeContainerController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@ open class LiquidSwipeContainerController: UIViewController {
private var animating: Bool = false
private var duration: CFTimeInterval = 0.8

private var rightEdgeGesture = UIScreenEdgePanGestureRecognizer()
private var leftEdgeGesture = UIScreenEdgePanGestureRecognizer()
private var trailingEdgeGesture = UIScreenEdgePanGestureRecognizer()
private var leadingEdgeGesture = UIScreenEdgePanGestureRecognizer()

private var csBtnNextLeading: NSLayoutConstraint?
private var csBtnNextCenterY: NSLayoutConstraint?
Expand All @@ -91,14 +91,14 @@ open class LiquidSwipeContainerController: UIViewController {
}

private func configureGestures() {
rightEdgeGesture.addTarget(self, action: #selector(rightEdgePan))
rightEdgeGesture.edges = .right
view.addGestureRecognizer(rightEdgeGesture)
trailingEdgeGesture.addTarget(self, action: #selector(trailingEdgePan))
trailingEdgeGesture.edges = view.trailingEdge
view.addGestureRecognizer(trailingEdgeGesture)

leftEdgeGesture.addTarget(self, action: #selector(leftEdgePan))
leftEdgeGesture.edges = .left
view.addGestureRecognizer(leftEdgeGesture)
leftEdgeGesture.isEnabled = false
leadingEdgeGesture.addTarget(self, action: #selector(leadingEdgePan))
leadingEdgeGesture.edges = view.leadingEdge
view.addGestureRecognizer(leadingEdgeGesture)
leadingEdgeGesture.isEnabled = false
}

private func animate(view: UIView, forProgress progress: CGFloat, waveCenterY: CGFloat? = nil) {
Expand Down Expand Up @@ -137,7 +137,7 @@ open class LiquidSwipeContainerController: UIViewController {
private var shouldFinish: Bool = false
private var shouldCancel: Bool = false
private var animationProgress: CGFloat = 0.0
@objc private func rightEdgePan(_ sender: UIPanGestureRecognizer) {
@objc private func trailingEdgePan(_ sender: UIPanGestureRecognizer) {
guard !animating else {
return
}
Expand All @@ -162,7 +162,7 @@ open class LiquidSwipeContainerController: UIViewController {
let direction: CGFloat = (gesture.location(in: view).y - mask.waveCenterY).sign == .plus ? 1 : -1
let distance = min(CGFloat(time) * speed, abs(mask.waveCenterY - gesture.location(in: view).y))
let centerY = mask.waveCenterY + distance * direction
let change = -gesture.translation(in: view).x
let change = -gesture.translation(in: view).x.flipped(for: self.view)
let maxChange: CGFloat = self.view.bounds.width * (1.0/0.45)
if !(self.shouldFinish || self.shouldCancel) {
let progress: CGFloat = min(1.0, max(0, change / maxChange))
Expand Down Expand Up @@ -219,7 +219,7 @@ open class LiquidSwipeContainerController: UIViewController {
}
}

@objc private func leftEdgePan(_ sender: UIPanGestureRecognizer) {
@objc private func leadingEdgePan(_ sender: UIPanGestureRecognizer) {
guard !animating else {
return
}
Expand All @@ -245,7 +245,7 @@ open class LiquidSwipeContainerController: UIViewController {
let direction: CGFloat = (gesture.location(in: view).y - mask.waveCenterY).sign == .plus ? 1 : -1
let distance = min(CGFloat(time) * speed, abs(mask.waveCenterY - gesture.location(in: view).y))
let centerY = mask.waveCenterY + distance * direction
let change = gesture.translation(in: view).x
let change = gesture.translation(in: view).x.flipped(for: self.view)
let maxChange: CGFloat = self.view.bounds.width
if !(self.shouldFinish || self.shouldCancel) {
let progress: CGFloat = min(1.0, max(0, 1 - change / maxChange))
Expand Down Expand Up @@ -389,7 +389,13 @@ open class LiquidSwipeContainerController: UIViewController {
layoutPageView(firstPage)

if pagesCount > 1 {
let maskLayer = WaveLayer(waveCenterY: initialWaveCenter, waveHorRadius: initialHorRadius, waveVertRadius: initialVertRadius, sideWidth: initialSideWidth)
let maskLayer = WaveLayer(
waveCenterY: initialWaveCenter,
waveHorRadius: initialHorRadius,
waveVertRadius: initialVertRadius,
sideWidth: initialSideWidth,
isRTL: self.view.isRTL
)
apply(mask: maskLayer, on: firstPage)
}
currentViewController = firstVC
Expand All @@ -403,19 +409,21 @@ open class LiquidSwipeContainerController: UIViewController {
previousViewController = currentViewController
currentViewController = nextViewController
currentPageIndex += 1
leftEdgeGesture.isEnabled = true
leadingEdgeGesture.isEnabled = true
let maskLayer = WaveLayer(waveCenterY: initialWaveCenter,
waveHorRadius: 0,
waveVertRadius: initialVertRadius,
sideWidth: 0)
sideWidth: 0,
isRTL: self.view.isRTL
)
if let currentPage = currentPage {
apply(mask: maskLayer, on: currentPage)
}
configureNextPage()
setNeedsStatusBarAppearanceUpdate()
guard nextViewController != nil else {
btnNext.isHidden = true
rightEdgeGesture.isEnabled = false
trailingEdgeGesture.isEnabled = false
if let viewController = currentViewController {
delegate?.liquidSwipeContainer(self, didFinishTransitionTo: viewController, transitionCompleted: true)
}
Expand Down Expand Up @@ -457,17 +465,19 @@ open class LiquidSwipeContainerController: UIViewController {
currentViewController = previousViewController
currentPageIndex -= 1
btnNext.isHidden = false
rightEdgeGesture.isEnabled = true
trailingEdgeGesture.isEnabled = true
let maskLayer = WaveLayer(waveCenterY: initialWaveCenter,
waveHorRadius: 0,
waveVertRadius: maxVertRadius,
sideWidth: view.bounds.width)
sideWidth: view.bounds.width,
isRTL: self.view.isRTL
)
configurePreviousPage()
setNeedsStatusBarAppearanceUpdate()
if let prevPage = previousViewController?.view {
apply(mask: maskLayer, on: prevPage)
} else {
leftEdgeGesture.isEnabled = false
leadingEdgeGesture.isEnabled = false
}
let startTime = CACurrentMediaTime()
let duration: CFTimeInterval = 0.3
Expand Down Expand Up @@ -502,7 +512,7 @@ open class LiquidSwipeContainerController: UIViewController {
let pagesCount = datasource.numberOfControllersInLiquidSwipeContainer(self)
guard pagesCount > currentPageIndex + 1 else {
nextViewController = nil
rightEdgeGesture.isEnabled = false
trailingEdgeGesture.isEnabled = false
return
}
let nextVC = datasource.liquidSwipeContainer(self, viewControllerAtIndex: currentPageIndex + 1)
Expand All @@ -529,7 +539,7 @@ open class LiquidSwipeContainerController: UIViewController {
let pagesCount = datasource.numberOfControllersInLiquidSwipeContainer(self)
guard currentPageIndex > 0 && pagesCount > 0 else {
previousViewController = nil
leftEdgeGesture.isEnabled = false
leadingEdgeGesture.isEnabled = false
return
}
let previousVC = datasource.liquidSwipeContainer(self, viewControllerAtIndex: currentPageIndex - 1)
Expand Down Expand Up @@ -608,15 +618,25 @@ open class LiquidSwipeContainerController: UIViewController {
let hasNextPage = self.nextViewController != nil
let maskLayer = WaveLayer(waveCenterY: self.initialWaveCenter,
waveHorRadius: hasNextPage ? self.initialHorRadius : 0,
waveVertRadius: self.initialVertRadius, sideWidth: hasNextPage ?self.initialSideWidth : 0)
waveVertRadius: self.initialVertRadius, sideWidth: hasNextPage ? self.initialSideWidth : 0,
isRTL: self.view.isRTL
)
self.apply(mask: maskLayer, on: currentPage)
}
if let nextPage = self.nextViewController?.view {
let maskLayer = WaveLayer(waveCenterY: self.initialWaveCenter, waveHorRadius: 0, waveVertRadius: self.initialVertRadius, sideWidth: 0)
let maskLayer = WaveLayer(waveCenterY: self.initialWaveCenter, waveHorRadius: 0, waveVertRadius: self.initialVertRadius, sideWidth: 0,
isRTL: self.view.isRTL
)
self.apply(mask: maskLayer, on: nextPage)
}
if let prevPage = self.previousViewController?.view {
let maskLayer = WaveLayer(waveCenterY: self.initialWaveCenter, waveHorRadius: 0, waveVertRadius: self.initialVertRadius, sideWidth: prevPage.bounds.height)
let maskLayer = WaveLayer(
waveCenterY: self.initialWaveCenter,
waveHorRadius: 0,
waveVertRadius: self.initialVertRadius,
sideWidth: prevPage.bounds.height,
isRTL: self.view.isRTL
)
self.apply(mask: maskLayer, on: prevPage)
}
self.csBtnNextCenterY?.constant = self.initialWaveCenter
Expand Down Expand Up @@ -713,3 +733,24 @@ private extension LiquidSwipeContainerController {
return initialSideWidth + (view.bounds.width - initialSideWidth) * (progress - p1)/(p2 - p1)
}
}

private extension UIView {
var leadingEdge: UIRectEdge {
isRTL ? .right : .left
}
var trailingEdge: UIRectEdge {
isRTL ? .left : .right
}
var isRTL: Bool {
if #available(iOS 10.0, *) {
return effectiveUserInterfaceLayoutDirection == .rightToLeft
} else {
return false
}}
}

private extension FloatingPoint {
func flipped(for view: UIView) -> Self {
view.isRTL ? -self : self
}
}
11 changes: 10 additions & 1 deletion liquid-swipe/Classes/WaveLayer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,21 @@ internal class WaveLayer: CAShapeLayer {
super.init(layer: layer)
}

init(waveCenterY: CGFloat, waveHorRadius: CGFloat, waveVertRadius: CGFloat, sideWidth: CGFloat) {
init(
waveCenterY: CGFloat,
waveHorRadius: CGFloat,
waveVertRadius: CGFloat,
sideWidth: CGFloat,
isRTL: Bool
) {
self.waveCenterY = waveCenterY
self.waveHorRadius = waveHorRadius
self.waveVertRadius = waveVertRadius
self.sideWidth = sideWidth
super.init()
if isRTL {
setAffineTransform(.init(scaleX: -1, y: 1))
}
}

func updatePath() {
Expand Down