向左或向右滑动以加载具有集合视图单元格高亮显示的视图控制器

我有3个视图控制器称为firstvc, secondvc, thirdvc 。 我有一个水平滚动的集合视图。 如果我select我的first cell我的firstvc在我的子视图显示在我的mainviewcontroller 。 它同样也是2, 3rd cell 。 没关系 。

现在我需要一个function,如果我滑动我的subview ,将有我所有的视图控制器时,我select任何单元格。 我需要添加左右滑动。

例如 :

如果我在firstvc那么我的first cell将被选中 。 现在,如果我滑动我的subview ,我的secondvc必须来意味着,而我的第二个集合视图单元格也必须highlight

我不知道如何涂抹。

我的代码:

  @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's View as a subview contentSubView.addSubview(controller.view) controller.view.frame = contentSubView.bounds controller.view.autoresizingMask = [.flexibleWidth, .flexibleHeight] // tell the childviewcontroller it's contained in it's parent controller.didMove(toParentViewController: self) } 

我的完整项目zip: https : //www.dropbox.com/s/fwj745kdgqvgjxa/Collection%20view%20example.zip? dl =0

您只需将UISwipeGestureRecognizer添加到主视图控制器的视图。 主视图控制器将负责pipe理手势的呼叫

基本上在代码中:

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) 

由于您将不得不从VC索引移动到另一个索引,您可能需要一个属性来跟踪当前选定的视图控制器:

 var currentIndexPath: IndexPath? 

每次select一个新的VC,您都可以更改它的值。 所以:

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

在主ViewController中添加changePageOnSwipe(_ gesture: UISwipeGestureRecognizer)方法。 由于它是拥有collectionView的“首席”视图控制器,它将处理滑动并告诉其子显示:

 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") } } 

而且由于您是以编程方式进行滑动操作,因此在尝试实际移动之前,必须确保滑动操作是有效的 。 你必须添加安全检查

 /** 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; } } 

最后,你可以在viewDidLoadself.currentIndexPath设置一个默认的indexPath,这样当用户登陆你的主VC时,用户就可以不用在collectionView中select另一个VC了。


注意:如果您在子ViewControllers中碰巧拥有手势识别器,则某些手势可能会发生冲突,您将不得不学习如何使用诸如gestureRecognizer(_:shouldRequireFailureOf:)类的委托方法来解决此类冲突。