Make The Swipe gesture Animated - ios

i have swipe gesture that switch between tab bars when I swipe in the screen right or left its change the tab bar im in it
How would I make it so it looks like it is sliding to the right or left tab bar rather than just instantly changing the tab bar
class SwipeGesture: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let left = UISwipeGestureRecognizer(target: self, action: #selector(swipeLeft))
left.direction = .left
self.view.addGestureRecognizer(left)
let right = UISwipeGestureRecognizer(target: self, action: #selector(swipeRight))
right.direction = .right
self.view.addGestureRecognizer(right)
}
#objc func swipeLeft() {
let total = self.tabBarController!.viewControllers!.count - 1
tabBarController!.selectedIndex = min(total, tabBarController!.selectedIndex + 1)
}
#objc func swipeRight() {
tabBarController!.selectedIndex = max(0, tabBarController!.selectedIndex - 1)
}
}

You can achieve this effect using this pod
If you want to build it from scratch, you need to subclass containerView. Then put the view controllers (childVCs) inside a scrollView (scrolls only in horizontal direction).

Related

UIScreenEdgePanGestureRecognizer

I'm trying to implement screen edge pan gesture for my view controller. But the problem is, if trying to add edge pan gesture for two edges (UIRectEdge.left, UIRectEdge.right) as
let screenEdgePanGesture = UIScreenEdgePanGestureRecognizer.init(target: self, action: #selector(self.didPanningScreen))
screenEdgePanGesture.edges = [.right, .left]
screenEdgePanGesture.delegate = self
self.view.addGestureRecognizer(screenEdgePanGesture)
the selector method not calling. But the edge pan gesture is working for one edge i.e.,
let screenEdgePanGesture = UIScreenEdgePanGestureRecognizer.init(target: self, action: #selector(self.didPanningScreen))
screenEdgePanGesture.edges = .right
screenEdgePanGesture.delegate = self
self.view.addGestureRecognizer(screenEdgePanGesture)
Yes, you are right, UIScreenEdgePanGestureRecognizer edges is accept/working only with one value, So you need to create two different functions for left and right edge panning.
Swift 4
let screenEdgePanGestureRight = UIScreenEdgePanGestureRecognizer.init(target: self, action: #selector(self.didPanningScreenRight(_:)))
screenEdgePanGestureRight.edges = .right
screenEdgePanGestureRight.delegate = self
self.view.addGestureRecognizer(screenEdgePanGestureRight)
let screenEdgePanGestureLeft = UIScreenEdgePanGestureRecognizer.init(target: self, action: #selector(self.didPanningScreenLeft(_:)))
screenEdgePanGestureLeft.edges = .left
screenEdgePanGestureLeft.delegate = self
self.view.addGestureRecognizer(screenEdgePanGestureLeft)
#objc func didPanningScreenRight(_ recognizer: UIScreenEdgePanGestureRecognizer) {
print("Right edge penning")
}
#objc func didPanningScreenLeft(_ recognizer: UIScreenEdgePanGestureRecognizer) {
print("Left edge penning")
}

UIView with label + button - Tap gesture not recognized

I added a label and an image to the navigation item title view, like this - https://stackoverflow.com/a/38548905/1373592
And I added these three lines of code, to make the title clickable.
....
let recognizer = UITapGestureRecognizer(target: self, action: #selector(MyViewController.titleTapped(_:)))
navView.isUserInteractionEnabled = true
navView.addGestureRecognizer(recognizer)
And this titleTapped function.
#objc func titleTapped(_ tapGestureRecognizer: UITapGestureRecognizer) {
print("Tapped")
}
What am I doing wrong?
I tried adding gesture recognizer to the label, and to the image (separately). That didn't work either.
Thanks.
Your NavView has no frame, so there is nothing "there" to tap.
Add this line:
// Create a navView to add to the navigation bar
let navView = UIView()
// new line
navView.frame = CGRect(x: 0, y: 0, width: 200, height: 40)
// Create the label
let label = UILabel()
and you should be on your way.
100% sure working in my app and well tested.
var tapGesture = UITapGestureRecognizer()
take your view and set IBOutlet like:
#IBOutlet weak var viewTap: UIView!
Write pretty code on viewDidLoad() like:
tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.myviewTapped(_:)))
tapGesture.numberOfTapsRequired = 1
tapGesture.numberOfTouchesRequired = 1
viewTap.addGestureRecognizer(tapGesture)
viewTap.isUserInteractionEnabled = true
this method is calling when tap gesture recognized
#objc func myviewTapped(_ sender: UITapGestureRecognizer) {
if self.viewTap.backgroundColor == UIColor.yellow {
self.viewTap.backgroundColor = UIColor.green
}else{
self.viewTap.backgroundColor = UIColor.yellow
}
}
Note: In your case you have to sure for view which view infront like UILabel or UIView that is nav and then assign the gesture to it.If your label cover the whole view then let's try to give gesture to label only.

Swipe to show additional buttons on UICollectionView

I'm trying to create a feature similar to tableView swipe to show delete button, the only difference is that I show multiple buttons and have it implemented on a collectionView within a collectionViewCell. I want to be able to slide the inner collectionView to the right and have multiple options buttons snap into view on the left.
Something like this:
I understand that I'll probably need to use UIPanGestureRecognizer, the problem for me is that the collectionView to pan is nested within another collectionView, and I'm not certain as to how to use the UIGestureRecognizer correctly so that the cells slide together and the buttons snap into view.
Any suggestions are very much appreciated.
set delegate in collection view for get action
protocol ColumnBookCellDelegate: class {
func deleteBook(_ book: Book)
}
class ColumnBookCell: AZCollectionViewCell{
weak var deleteDelegate: ColumnBookCellDelegate?
var canBeRemove: Bool = false{
didSet{
if self.canBeRemove{
let swipeL = UISwipeGestureRecognizer(target: self, action: #selector(self.showDelete))
swipeL.numberOfTouchesRequired = 1
swipeL.direction = .left
self.addGestureRecognizer(swipeL)
let swipeR = UISwipeGestureRecognizer(target: self, action: #selector(self.hideDelete))
swipeR.numberOfTouchesRequired = 1
swipeR.direction = .right
self.addGestureRecognizer(swipeR)
}
}
}
// Show Delete Button
func showDelete(){
// unhidden button here
// self.button.isHidden = false
UIView.animate(withDuration: 0.2) {
self.layoutIfNeeded()
}
}
// Hide Delete Button
func hideDelete(){
// hidden button here
// self.button.isHidden = true
// self.deleteButton.aZConstraints.width?.constant = 0
UIView.animate(withDuration: 0.2) {
self.layoutIfNeeded()
}
}
// Delete Action
func deleteAction(){
self.deleteDelegate?.deleteBook(self.book)
self.hideDelete()
}
// blob blob blob
}

Tap gesture recognizer added to UILabel not working

I've the following code to add a gesture recognizer to a UILabel. User Interaction Enabled is ticked on for the label in the storyboard, but when I tap on the label the onUserClickingSendToken method is not being called.
class ViewController: UIViewController, MFMailComposeViewControllerDelegate {
#IBOutlet weak var tokenDisplay: UILabel!
var tapGestureRecognizer:UITapGestureRecognizer = UITapGestureRecognizer(target:self, action: #selector(onUserClickingSendToken(_:)))
override func viewDidLoad() {
super.viewDidLoad()
tapGestureRecognizer.numberOfTapsRequired = 1
tokenDisplay.addGestureRecognizer(tapGestureRecognizer)
}
func onUserClickingSendToken(_ sender: Any)
{
....
Initializing the tapRecognizer in viewDidLoad should do it, cause you were targeting self before the view was initialized
class ViewController: UIViewController, MFMailComposeViewControllerDelegate {
#IBOutlet weak var tokenDisplay: UILabel!
var tapGestureRecognizer:UITapGestureRecognizer!
override func viewDidLoad() {
super.viewDidLoad()
tapGestureRecognizer = UITapGestureRecognizer(target:self, action: #selector(onUserClickingSendToken(_:)))
tapGestureRecognizer.numberOfTapsRequired = 1
tokenDisplay.isUserInteractionEnabled = true
tokenDisplay.addGestureRecognizer(tapGestureRecognizer)
}
#objc func onUserClickingSendToken(_ sender: Any)
{
....
In general for UILabel clickable issue:
There are couple of reasons why your UILabel will not work as clickable
Make sure to mark UILabel UserInteraction true and if yourLabel is inside other view than mark that view UserInteraction true too.
yourLabel.isUserInteractionEnabled = true
Assigning self to target before the view initialisation, move your code inside viewDidLoad/awakeFromNib or after view Load
let tap = UITapGestureRecognizer(target: self, action: #selector(onClickLabel(_:)))
self.yourLabel.addGestureRecognizer(tap)
If you are adding UILabel programmatically, than you have to assign it's frame too.
yourLabel.frame = CGRect(x: 0, y: 0, width: 300, height: 20)
Super view in which your UILabel is should be large enough to fit/display label properly, if your label is inside some view than that view's height/weight should assign in a way that it cover the whole UILabel frame.
In my case this was the problem I had, I tried so many thing but at last it turns out that the view in which I had my label had fixed width, the label was displaying properly but onClick event was't working due to out of frame.
It was missing UILabel's trailing constraints, so half of the thing is not clickable.
Using same tab gesture for multiple view, you cannot use one tab gesture for more than one view or labels,use different for each UILabel.
try this:
let tap = UITapGestureRecognizer(target: self, action: #selector(onClickLabel(_:)))
self.yourLabel.isUserInteractionEnabled = true
self.yourLabel.addGestureRecognizer(tap)
let tap2 = UITapGestureRecognizer(target: self, action: #selector(onClickLabel(_:)))
self.someView.isUserInteractionEnabled = true
self.someView.addGestureRecognizer(tap2)
instead of this:
let tap = UITapGestureRecognizer(target: self, action: #selector(onClickLabel(_:)))
self.yourLabel.isUserInteractionEnabled = true
self.yourLabel.addGestureRecognizer(tap)
self.someView.isUserInteractionEnabled = true
self.someView.addGestureRecognizer(tap)
// tapGesture will work on only one element
Try changing your selector setup to:
#selector(ViewController .onUserClickingSendToken(_:).

Why does the swipe gesture recognizer give an error in swift?

I'm trying to add the swipe gesture recognizer to the collection view by using swift. Everytime the user swipe to right or left, I want my collection view reload. However, when I swipe to right or left in collection view on the simulator, it gives me an error and AppDelegate.swift class is automatically opened. The error says " libc++abi.dylib: terminating with uncaught exception of type NSException "
I write this part to the viewDidLoad() in the collectionViewController class
collectionView.userInteractionEnabled = true
collectionView.delegate = self
var left = UISwipeGestureRecognizer(target: collectionView, action: "swipping:")
left.direction = UISwipeGestureRecognizerDirection.Left
collectionView.addGestureRecognizer(left)
var right = UISwipeGestureRecognizer(target: collectionView, action: "swipping:")
right.direction = UISwipeGestureRecognizerDirection.Right
collectionView.addGestureRecognizer(right)
This is the swipping function:
func swipping (gesture : UIGestureRecognizer){
if let swipeGesture = gesture as? UISwipeGestureRecognizer {
switch swipeGesture.direction {
case UISwipeGestureRecognizerDirection.Left:
collectionView.reloadData()
pageControl.currentPage++
case UISwipeGestureRecognizerDirection.Right:
collectionView.reloadData()
pageControl.currentPage--
default:
break
}
}
}
Added UIGestureRecognizerDelegate to the CollectionViewController class and AppDelegate class. What should I do?
Thanks.
When you declare gesture recogniser you specify collectionView as a target:
var left = UISwipeGestureRecognizer(target: collectionView, action: "swipping:")
But I believe the swiping: method is placed in the same file where the declaration is taking place.
You have to change target to self:
var left = UISwipeGestureRecognizer(target: self, action: "swipping:")
var right = UISwipeGestureRecognizer(target: self, action: "swipping:")
//Extended
This is not working because UICollectionView is a subclass of UIScrollView and when you swipe UIScrollView handle the gesture (this is because you can create collection in horizontal direction so collection view needs to know that you are scrolling left/right).
You should consider override UIScrollViewDelegate method:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView;
to find out the swipe and you should handle it instead of adding gesture recogniser.
Try something like that:
//Declare private property
#property (nonatomic, assign) CGFloat prevOffset
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
if (self.prevOffset > scrollView.contentOffset.x)
// You are swiping right
else if (self.prevOffset < scrollView.contentOffset.x)
// You are swiping left
self.prevOffset = scrollView.contentOffset.x;
}

Resources