Tips and tricks
A few tips and an example of how to implement the iOS Swipe Back interaction using Edge Swipe.
Setting the first screen
I think you’ve seen these two friends before:
flow = new FlowComponent
flow.showNext screenA
They seem to be inseparable.
- The first line creates a FlowComponent instance …
- … and the second one adds the first screen.
But you can create a FlowComponent and add a screen in one go:
flow = new FlowComponent screenA
Setting size, position, and background color
By default, a FlowComponent will assume the size of the Screen
, but you can give it a desired size and position with the common, well-known properties.
flow = new FlowComponent
width: Screen.width
height: Screen.height - 40
y: 20
A FlowComponent’s background color is what you see when you overdrag (so you’ll only see it on scrollable screens). It’s "black"
by default, but easy to change:
flow = new FlowComponent
backgroundColor: "red"
Several other properties, for instance borderRadius
, will also work.
You can set properties and a start screen at the same time, if you first set the screen (screenA
below), followed by a ,
and then add the other properties.
# A FlowComponent with a first screen, and extra properties
flow = new FlowComponent screenA,
width: Screen.width
height: Screen.height - 40
y: 20
backgroundColor: "red"
borderRadius: 20
(It’s a bit like when creating an animation object: first the layer followed by a comma, and then the other properties.)
Using Edge Swipe events to create the iOS Swipe Back gesture
We have the FlowComponent, with its iOS-inspired showNext()
transition, and Framer has Edge swipe events. So I wanted to see if we can combine them to create the iOS Swipe Back interaction.
It’s doable, but I had to use onEdgeSwipeLeftStart
, and onEdgeSwipeLeft
, and onEdgeSwipeLeftEnd
to have it work as it should.
A bunch of things are happening here:
1. The user started swiping from the left edge
Event: Screen.onEdgeSwipeLeftStart
When the user starts swiping, I flag it by setting a weAreSwiping
variable to yes
.
This will impede taps from triggering a showNext()
when we’re in this ‘edge swiping from the left’ mode. Because otherwise, the FlowComponent would advance to the next screen the moment the user lifts his finger.
# User started swiping from the left edge …
Screen.onEdgeSwipeLeftStart ->
# … so now taps shouldn’t trigger anything
weAreSwiping = yes
2. The user is swiping along happily
Event: Screen.onEdgeSwipeLeft
When the user is busy swiping we let the current
screen follow the movement (by updating its x
with the current event.offset
).
But we only want to do this when not on the start screen, so we first check the length
of our flow.stack
.
# We continuously adjust the x position of the “current” screen
# and of the “previous” screen underneath
Screen.onEdgeSwipeLeft ->
# only when not the first screen
if flow.stack.length > 1
# Current screen
flow.current.x = event.offset.x
# Previous screen, will be hidden at first
flow.previous.visible = yes
# … and only moves at half the speed
flow.previous.x = (event.offset.x/2) - (flow.previous.width/2)
We also move the previous
screen at half the speed. We first make it visible
, though, because any screen not currently in use will be hidden.
3. The user stopped swiping
Event: Screen.onEdgeSwipeLeftEnd
When the user has finished swiping, we take a look at the current event.offset.x
.
If it’s less than Screen.midX
, the user did not pan halfway so we should animate back. The current
screen’s x
is set back to 0
with a spring animation (the same as in the transition). And we do the same with previous
but place it half its width more to the left.
# End of the swipe gesture
Screen.onEdgeSwipeLeftEnd ->
# only when not the first screen
if flow.stack.length > 1
# Panned less than half the screen width?
# -> animate back to the initial position
if event.offset.x < Screen.midX
flow.current.animate
x: 0
options:
curve: "spring(300, 35)"
flow.previous.animate
x: - (flow.previous.width / 2)
options:
curve: "spring(300, 35)"
# Panned more than half the screen?
# -> Trigger transition
else
flow.showPrevious()
# Taps are allowed to happen again
Utils.delay 0.1, ->
weAreSwiping = no
But when the user did swipe far enough, we trigger showPrevious()
to have the transition run until the end.
4. Ready again for tapping action
Taps are allowed to trigger transitions again, so we set weAreSwiping
back to no
. But only after a (minimal) 🛠 Delay, to not have it sneak in a quick showNext()
.
# Taps are allowed to happen again
Utils.delay 0.1, ->
weAreSwiping = no
By the way, this is how that weAreSwiping
variable is used to impede taps:
# Tap on A ? -> Show screen B
Screen_A.onTap ->
if not weAreSwiping
flow.showNext Screen_B
In every onTap
event handler, we first check weAreSwiping
before doing a showNext()
.