Swipe left or right to load the view controller with the highlight of the collection cell.

I have 3 view controllers called firstvc, secondvc, thirdvc . And I have one view of the collection that will scroll horizontally. If I select my first cell my firstvc wil in my mainviewcontroller on my mainviewcontroller . The same goes for 2, 3rd cell . Perfectly.

Now I need one functionality, for example, if I spent my subview , which will have all my view controllers when I select any cell. I need to add swipe left or right.

For instance:

if i am in firstvc then my first cell will be selected . Now, if I secondvc my subview to the right, my secondvc should appear, while my second collection view cell should also be highlight

I do not know how to use.

my code is:

  @IBOutlet weak var collectionview: UICollectionView! @IBOutlet weak var contentSubView: UIView! func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return self.items.count } // make a cell for each cell index path func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { // get a reference to our storyboard cell let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath as IndexPath) as! MyCollectionViewCell // Use the outlet in our custom class to get a reference to the UILabel in the cell cell.myLabel.text = self.items[indexPath.item] // cell.backgroundColor = UIColor.cyan // make cell more visible in our example project var borderColor: UIColor! = UIColor.clear //var borderWidth: CGFloat = 0 if indexPath == selectedIndexPath{ borderColor = UIColor.red //borderWidth = 1 //or whatever you please }else{ borderColor = UIColor.white // borderWidth = 0 } cell.myview.backgroundColor = borderColor // cell.myview.layer.borderWidth = borderColor return cell } // MARK: - UICollectionViewDelegate protocol func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { print("You selected cell #\(indexPath.item)!") //based on your comment remove the subviews before add on your myview //let cell = collectionView.cellForItemAtIndexPath(indexPath) as! MyCollectionViewCell selectedIndexPath = indexPath for subview in contentSubView.subviews { subview.removeFromSuperview() } let alertStoryBoard = UIStoryboard(name: "Main", bundle: nil) var controller: UIViewController! if indexPath.item == 0 { if let allCollectionViewController = alertStoryBoard.instantiateViewController(withIdentifier:"firstvc") as? firstvc { controller = allCollectionViewController } } else if indexPath.item == 1 { if let allCollec = alertStoryBoard.instantiateViewController(withIdentifier:"secondvc") as? secondvc { controller = allCollec } }else if indexPath.item == 2 { if let wController = alertStoryBoard.instantiateViewController(withIdentifier:"Thirdvc") as? Thirdvc { controller = wController } } addChildViewController(controller) // Add the child View as a subview contentSubView.addSubview(controller.view) controller.view.frame = contentSubView.bounds controller.view.autoresizingMask = [.flexibleWidth, .flexibleHeight] // tell the childviewcontroller it contained in it parent controller.didMove(toParentViewController: self) } 

My complete zip project: https://www.dropbox.com/s/fwj745kdgqvgjxa/Collection%20view%20example.zip?dl=0

0
source share
1 answer

You just need to add the UISwipeGestureRecognizer to the main controller view. The master view controller will be responsible for managing gesture calls.

Mostly in code:

in viewDidLoad :

 let swipeToLeft = UISwipeGestureRecognizer(target: self, action: #selector(changePageOnSwipe(_:))) let swipeToRight = UISwipeGestureRecognizer(target: self, action: #selector(changePageOnSwipe(_:))) swipeToLeft.direction = .right swipeToRight.direction = .left self.contentSubView.addGestureRecognizer(swipeToLeft) // Gesture are added to the top view that should handle them self.contentSubView.addGestureRecognizer(swipeToRight) 

Since you will need to move from VC by index to another index, you may need a property to track the currently selected view controller:

 var currentIndexPath: IndexPath? 

And you can change its value every time a new VC is selected. So:

 func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { print("You selected cell #\(indexPath.item)!") self.currentIndexPath = indexPath // ... Other settings } 

add the changePageOnSwipe(_ gesture: UISwipeGestureRecognizer) to your main ViewController. Since this is the "main" view controller that collectionView has, it will handle swipes and tell its children:

 func changePageOnSwipe(_ gesture: UISwipeGestureRecognizer) { guard let indexPath = self.currentIndexPath else { // When the page loads and there is no current selected VC, the swipe will not work // unless you set an initial value for self.currentIndexPath return } var newIndex = indexPath // if self.collectionview.indexPathsForSelectedItems is not empty, you can also use it instead of having a self.currentIndexPath property // move in the opposite direction for the movement to be intuitive // So swiping " <-- " should show index on the right (row + 1) if gesture.direction == .left { newIndex = IndexPath(row: newIndex.row+1, section: newIndex.section) } else { newIndex = IndexPath(row: newIndex.row-1, section: self.currentIndexPath!.section) } if canPresentPageAt(indexPath: newIndex) { // Programmatically select the item and make the collectionView scroll to the correct number self.collectionview.selectItem(at: newIndex, animated: true, scrollPosition: UICollectionViewScrollPosition.centeredHorizontally) // The delegate method is not automatically called when you select programmatically self.collectionView(self.collectionview, didSelectItemAt: newIndex!) } else { // Do something when the landing page is invalid (like if the swipe would got to page at index -1 ...) // You could choose to direct the user to the opposite side of the collection view (like the VC at index self.items.count-1 print("You are tying to navigate to an invalid page") } } 

and since you are scrolling programmatically, you need to make sure that the swipe is valid before trying to move. You must add security checks :

 /** You can use an helper method for those checks */ func canPresentPageAt(indexPath: IndexPath) -> Bool { // Do necessary checks to ensure that the user can indeed go to the desired page // Like: check if you have a non-nil ViewController at the given index. (If you haven't implemented index 3,4,5,... it should return false) // // This method can be called either from a swipe // or another way when you need it if indexPath.row < 0 || indexPath.row >= self.items.count { print("You are trying to go to a non existing page") return false } else { print("If you haven't implemented a VC for page 4 it will crash here") return true; } } 

Finally, you can set the default indexPath index for self.currentIndexPath to viewDidLoad so that the user can already viewDidLoad when it lands on your main VC without selecting another VC in the collection.


Note. If you have gesture recognizers in sub-ViewControllers, some gestures may conflict, and you will need to learn how to resolve such conflicts using delegate methods such as gestureRecognizer(_:shouldRequireFailureOf:) .

+1
source

Source: https://habr.com/ru/post/1239994/


All Articles