Dragging Fixes and Velocity

Twitter Slide Out MenuIn today's video, we'll look at applying some various fixes to bugs that we were experiencing in the last lesson. Once we take care of a couple of issues, we'll also add a new feature. This feature will allow users to swipe open and close our menu based on the velocity of our pan gesture. It's a great feature to include in an application so let's find out exactly how to implement it.

Comments (6)

PreachOnBerto

4 years ago

If checks looking pretty long in handleEnded. Perfect time for ternary operators haha. Looking forward to the next lesson.

Brian Voong

4 years ago

Dennisvm82

4 years ago

I changed the same function into two types of ternary operators, but one of them looks like it came straight from The Matrix.
The first version only changes the "translation.x" part to a ternary (easy to maintain in my opinion), and the second one is a single line of code with several if statements (unreadable, but kind of cool).
# Version #1
if isMenuOpened {
if abs(velocity.x) > velocityOpenTreshold {
handleHide()
return
}
abs(translation.x) < menuWidth / 2 ? handleOpen() : handleHide() // Ternary operation
} else {
if velocity.x > velocityOpenTreshold {
handleOpen()
return
}
translation.x < menuWidth / 2 ? handleHide() : handleOpen() // Ternary operation
}
}
# Version 2
isMenuOpened ? (abs(translation.x) < menuWidth / 2 && velocity.x > velocityOpenTreshold ? handleOpen() : handleHide()) : (translation.x < menuWidth / 2 ? handleHide() : handleOpen())

Adam El-Kadi

4 years ago

Hey Brian, how did you get the leftBarItem Button to look like a complete circle? I tried using the width/2 but no luck.
Thanks,

Adam El-Kadi

4 years ago

It doesn't look round:
I created a "profileButton", and then set the frame and contraints inside it
then I added
navigationItem?.leftBarItem = UIBarItem(custom: profileButton)

Brian Voong

4 years ago

Adam El-Kadi

4 years ago

Its very scary code, but it is very easy to implment. Thank you very much! I'll try to look over the code and analyse it.
Thank you again,

Brian Voong

4 years ago

Adam El-Kadi

4 years ago

Interesting, I think I may have missed the
.scaleAspectFit part
clips to bounds
setNeedsLayout()
Thanks again!

Brian Voong

4 years ago

Adam El-Kadi

4 years ago

Yep I saw it this morning when I was watching the videos, thanks Brian greatly appreciated!

YuraChudnick

4 years ago

Hi! I have TableView with swipe to delete row, but it did not work when I added pan gesture to open menu. How I can to fix this bug without using 'shouldRecognizeSimultaneouslyWith otherGestureRecognizer' method in pan gesture delegate? because when I used this method, everything work, but TableView scroll with menu.
Thanks.

chevi99

4 years ago

Nice. I never knew the print function can take more than on arguments. Tnx Brian.

darren100

4 years ago

damn. cool maths.

darren100

4 years ago

did you come up with this yourself or you got some help online? i don't think my mind would be that creative...idk

Brian Voong

4 years ago

TWei

4 years ago

niubi

LucienChu

4 years ago

Regarding the logic of 8:33 in this video, I have some details, hopefully it would help someone out one day.
@objc func handlePanGuesture(guesture: UIPanGestureRecognizer){
let translation = guesture.translation(in: self.view)
var x = translation.x
//if menueIsShown {
//x += self.menueWidth
//}
x = min(self.menueWidth, x) // moving left x increate
x = max(0, x) // moving right x decrease
if guesture.state == .changed {
let transform = CGAffineTransform(translationX: x, y: 0)
// self.showAnimation(transform: transform, onComplete: nil)
self.menuViewController.view.transform = transform
self.navigationController?.view.transform = transform
}
else if guesture.state == .ended{
handleGuestureEnd(guesture: guesture)
}
}
Let say the if menueIsShown is commented out
Assume slide from left to right, one slide 100px horizontally, so x = 100, menueWidth = 300
So x = min (300, 100) -> x = 100
x = max (0, ,100) --> x = 100
So the slide from left to right is smooth in .changed state
Let’s consider from right to left
Assume one slide 100px horizontally from right to left, so x = -100, menueWidth = 300
So x = min(300, -100) —> x = -100
x = max(0, -100) --> x = 0
Here problem comes.
In .changed state,
let transform = CGAffineTransform (translationX: 0, y: 0)
All the sudden the transform of both menueViewController and self.view are translate from current position to 0, that’s why the animation is so abrupt
With the menueIsShown is active, see what’s gonna happen
Assume slide from left to right, one slide 100px horizontally, so x = 100, menueWidth = 300
If statement is not executed
So x = min (300, 100) -> x = 100
x = max (0, ,100) -> x == 100
So the slide from left to right is smooth in .changed state
Let’s consider from right to left
Assume one slide 100px horizontally from right to left, so x = -100, menueWidth = 300
in if statement
x += menueWdith -> -100 + 300 => 200
So x = min(300, 200) —> x = 200
x = max(0, ,200) --> x = 200
let transform = CGAffineTransform (translationX: 200, y: 0)
Both menueViewController and self.view are translate from current position to x = 200, that keeps both animation smooth and nature.
The if statement is more like to offer some offset for x. Instead of decrease from 0, it decreases from 300(menueWidth)
So when min and max function is executed, we still have a very nice (positive) x for menViewController and self.view's transform.
Hope it is clear a bit.
Spent an hour to figure out what’s wrong since I was absent minded why Brian was talking about that part.
Back to his video and spend 10 minutes to figure out why that if statement works, physically.

Please contact **support@letsbuildthatapp.com** if you have any issues.