Dragging Fixes and Velocity
Twitter Slide Out Menu
In 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.
HELP & SUPPORT