2017-06-06 1 views
0

Ich benutze Swipe-Gesten zum Navigieren zwischen Tabs mit einem gefälschten UITabBarController, der 4 UIViewController-Unterklassen innerhalb eines UIScrollView hostet, mit UIPanGestureRecognizers auf jedem von ihnen, um Swipes zu erkennen und entsprechend Tabs zu wechseln. Der daraus resultierende Effekt ist die Kernnavigation, wie Sie sie auf Snapchat sehen. Einer dieser Bildschirme enthält jedoch eine Kartenansicht (Mapbox-Map), in die eigene Gestenerkenner integriert sind.Wie verwende ich 2 Gestenerkenner, um Ereignisse gleichzeitig zu empfangen?

Ich möchte, dass der Benutzer in der Lage ist, auf der Karte selbst zu wischen, um zu einem anderen Tab zu navigieren, indem er einen Streifzug vom rechten Rand des Bildschirms erkennt. Ich habe versucht, einen UIPanGestureRecognizer zu einem unsichtbaren UIView in diesem Bereich auf der rechten Seite hinzuzufügen, aber dies bietet einen ruckligen, nicht übereinstimmenden Tab-Schalter, und es fängt Berührungsereignisse von der Karte unten ab.

Wie kann ich beiden Gestenerkennern erlauben, Ereignisse gleichzeitig zu empfangen, oder einige Ereignisse filtern, die nur auf der Startposition des Swipe und seiner Entfernung und Richtung basieren?

-Code für swiping View-Controller:

class KUSwipeViewController: EZSwipeController { 

    fileprivate var fakeTabBar: UIView! 

    fileprivate var tabBarHeight: CGFloat = 50 

    override func viewDidLoad() { 
     initUI() 
    } 

    override func setupView() { 
     super.setupView() 
     datasource = self 
     navigationBarShouldNotExist = true 
    } 

    func initUI() { 
     fakeTabBar = UIView(frame: CGRect(x: 0, y: Screen.height - tabBarHeight, width: Screen.width, height: tabBarHeight)) 
     fakeTabBar.backgroundColor = .black 

     let tab0 = UIButton(frame: CGRect(x: Screen.width * 0.08, y: 9, width: 32, height: 32)) 
     tab0.setBackgroundImage(#imageLiteral(resourceName: "tab-events"), for: .normal) 
     tab0.addTarget(self, action: #selector(tapped0), for: .touchUpInside) 
     fakeTabBar.addSubview(tab0) 

     let tab1 = UIButton(frame: CGRect(x: Screen.width * 0.32, y: 9, width: 32, height: 32)) 
     tab1.setBackgroundImage(#imageLiteral(resourceName: "tab-feat"), for: .normal) 
     tab1.addTarget(self, action: #selector(tapped1), for: .touchUpInside) 
     fakeTabBar.addSubview(tab1) 

     let tab2 = UIButton(frame: CGRect(x: Screen.width * 0.58, y: 9, width: 32, height: 32)) 
     tab2.setBackgroundImage(#imageLiteral(resourceName: "tab-chat"), for: .normal) 
     tab2.addTarget(self, action: #selector(tapped2), for: .touchUpInside) 
     fakeTabBar.addSubview(tab2) 

     let tab3 = UIButton(frame: CGRect(x: Screen.width * 0.82, y: 9, width: 32, height: 32)) 
     tab3.setBackgroundImage(#imageLiteral(resourceName: "tab-profile"), for: .normal) 
     tab3.addTarget(self, action: #selector(tapped3), for: .touchUpInside) 
     fakeTabBar.addSubview(tab3) 

     view.addSubview(fakeTabBar) 
    } 


    func tapped0() { 
     self.moveToPage(0, animated: true) 
    } 

    func tapped1() { 
     self.moveToPage(1, animated: true) 
    } 

    func tapped2() { 
     self.moveToPage(2, animated: true) 
    } 

    func tapped3() { 
     self.moveToPage(3, animated: true) 
    } 
} 

extension KUSwipeViewController: EZSwipeControllerDataSource { 
    func viewControllerData() -> [UIViewController] { 

     let nav0 = UINavigationController() 
     let nav3 = UINavigationController() 

     let mapVC = EventMapViewController() 
     let featuredVC = FeaturedEventsViewController() 
     let chatVC = MessagesViewController() 
     let profileVC = ProfileViewController() 

     nav0.viewControllers = [mapVC] 
     nav3.viewControllers = [profileVC] 

     return [nav0, featuredVC, chatVC, nav3] 
    } 

    func titlesForPages() -> [String] { 
     return ["", "", "", ""] 
    } 

    func indexOfStartingPage() -> Int { 
     return 0 
    } 

    func changedToPageIndex(_ index: Int) { 
     Haptic.selection.generate() 
    } 
} 

-Code für Kartenansicht Controller:

class EventMapViewController: CommonViewController { 

    fileprivate var mapView: MGLMapView! 
    fileprivate var statusBarView: UIView! 
    fileprivate var searchBar: FloatingSearchBar! 
    fileprivate var searchButton: UIButton! 
    fileprivate var filterButton: UIButton! 
    fileprivate var peekView: UIView! 
    fileprivate var architectView: UIView! 
    fileprivate var panArchitectView: UIView! 
    fileprivate var peekArchitectView: UIView! 
    fileprivate var peekLabel: UILabel! 
    fileprivate var panView: UIPanGestureRecognizer! 

    fileprivate let peekViewHeight: CGFloat = 140 

    fileprivate var selectedEvent: Event? 

    fileprivate var cardShowing: Bool = false 
    fileprivate var peekShowing: Bool = false 

    /* 
    override func statusBarStyle() -> UIStatusBarStyle { 
     return cardShowing ? .lightContent : .default 
    } 
    */ 

    override func navigationBarHidden() -> Bool { 
     return true 
    } 

    override func viewDidLoad() { 
     super.viewDidLoad() 
     initUI() 
    } 

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) { 
     if segue.identifier == "eventSegue" { 
      let dvc = segue.destination as! EventViewController 
      dvc.event = selectedEvent! 
     } 
    } 

    func initUI() { 
     mapView = MGLMapView(frame: view.bounds) 
     mapView.styleURL = (UIColor.theme == .light) ? URL(string: mbThemeLight)! : URL(string: mbThemeDark)! 
     mapView.showsUserLocation = true 
     mapView.userTrackingMode = .none 
     mapView.delegate = self 
     mapView.setCenter(CLLocationCoordinate2D(latitude: 34, longitude: -118), zoomLevel: 5, animated: false) 
     view.addSubview(mapView) 
     mapView.snp.makeConstraints { (make) in 
      make.edges.equalTo(view) 
     } 

     //architect view (for intercepting touch) 
     architectView = UIView(frame: self.view.bounds) 
     let gestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(EventMapViewController.handleTap(gestureRecognizer:))) 
     gestureRecognizer.delegate = self 
     architectView.addGestureRecognizer(gestureRecognizer) 
     architectView.isHidden = true 
     view.addSubview(architectView) 

     statusBarView = UIView() 
     statusBarView.backgroundColor = UIColor.clear 
     view.addSubview(statusBarView) 
     statusBarView.snp.makeConstraints { (make) in 
      make.left.right.top.equalTo(0) 
      make.height.equalTo(20) 
     } 

     searchButton = UIButton() 
     searchButton.backgroundColor = UIColor.kuLightBackground 
     searchButton.tintColor = (UIColor.theme == .light) ? UIColor.kuPrimary : UIColor.kuDeselected 
     searchButton.setImage(#imageLiteral(resourceName: "icon_search_white").withRenderingMode(.alwaysTemplate), for: .normal) 
     searchButton.layer.cornerRadius = 25 
     searchButton.layer.borderColor = UIColor.kuExtraLightBackground.cgColor 
     searchButton.layer.borderWidth = 1 
     searchButton.addTarget(self, action: #selector(searchButtonTapped(_:)), for: .touchUpInside) 
     view.addSubview(searchButton) 
     searchButton.snp.makeConstraints { (make) in 
      make.width.height.equalTo(50) 
      make.left.equalTo(24) 
      make.top.equalTo(34) 
     } 

     filterButton = UIButton() 
     filterButton.backgroundColor = UIColor.kuLightBackground 
     filterButton.tintColor = (UIColor.theme == .light) ? UIColor.kuPrimary : UIColor.kuDeselected 
     filterButton.setImage(#imageLiteral(resourceName: "icon_filter_white").withRenderingMode(.alwaysTemplate), for: .normal) 
     filterButton.layer.cornerRadius = 20 
     filterButton.layer.borderColor = UIColor.kuExtraLightBackground.cgColor 
     filterButton.layer.borderWidth = 1 
     filterButton.addTarget(self, action: #selector(filterButtonTapped(_:)), for: .touchUpInside) 
     view.addSubview(filterButton) 
     filterButton.snp.makeConstraints { (make) in 
      make.width.height.equalTo(40) 
      make.left.equalTo(80) 
      make.top.equalTo(40) 
     } 

     //peek view 
     peekView = UIView(frame: CGRect(x: 0, y: UIScreen.main.bounds.height, width: UIScreen.main.bounds.width, height: peekViewHeight)) 
     peekView.backgroundColor = UIColor(white: 1, alpha: 0.5) 
     peekView.layer.cornerRadius = 10 
     view.addSubview(peekView) 

     //peek label 
     peekLabel = UILabel(frame: CGRect(x: 0, y: 12, width: UIScreen.main.bounds.width, height: 68)) 
     peekLabel.font = UIFont.kuBoldFont(ofSize: 38) 
     peekLabel.textColor = .black 
     peekLabel.textAlignment = .center 
     peekView.addSubview(peekLabel) 

     //peek architect 
     peekArchitectView = UIView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: peekViewHeight)) 
     let peekGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(EventMapViewController.peekSelected(gestureRecognizer:))) 
     peekGestureRecognizer.delegate = self 
     peekArchitectView.addGestureRecognizer(peekGestureRecognizer) 
     peekView.addSubview(peekArchitectView) 

     loadEventAnnotations() 
    } 

    func enterPeekView() { 
     guard !peekShowing else { return } 

     architectView.isHidden = false 
     peekLabel.text = "\(selectedEvent!.title!) >" 

     peekView.cheetah 
      .move(0, peekViewHeight * -1) 
      .duration(0.18) 
      .easeOutExpo 
      .run() 

     peekShowing = true 
    } 

    func exitPeekView() { 
     guard peekShowing else { return } 

     architectView.isHidden = true 
     peekView.cheetah 
      .move(0, peekViewHeight) 
      .duration(0.18) 
      .easeInExpo 
      .run() 

     peekShowing = false 
    } 

    func loadEventAnnotations() { 
     RealmManager.shared.defaultRealm.objects(Event.self).forEach { (event) in 

      let annotation = EventAnnotation() 
      annotation.event = event 
      mapView.addAnnotation(annotation) 
     } 
    } 

    func searchButtonTapped(_ sender: UIButton) { 
     let eventSearchCardViewController = EventSearchCardViewController() 
     eventSearchCardViewController.delegate = self 
     UIApplication.rootViewController()?.presentCardViewController(eventSearchCardViewController) 
    } 

    func filterButtonTapped(_ sender: UIButton) { 
     let eventFilterCardViewController = EventFilterCardViewController() 
     eventFilterCardViewController.delegate = self 
     UIApplication.rootViewController()?.presentCardViewController(eventFilterCardViewController) 
    } 
} 

extension EventMapViewController: CardViewControllerDelegate { 

    func cardViewControllerWillAppear(cardViewController: CardViewController) { 
     cardShowing = true 
     setNeedsStatusBarAppearanceUpdate() 
    } 

    func cardViewControllerWillDisappear(cardViewController: CardViewController) { 
     cardShowing = false 
     setNeedsStatusBarAppearanceUpdate() 
    } 
} 

extension EventMapViewController: MGLMapViewDelegate { 

    func mapView(_ mapView: MGLMapView, didSelect annotation: MGLAnnotation) { 

     guard let eventAnnotation = annotation as? EventAnnotation else { 
      return 
     } 

     selectedEvent = eventAnnotation.event 

     enterPeekView() 
    } 

    func mapView(_ mapView: MGLMapView, annotationCanShowCallout annotation: MGLAnnotation) -> Bool { 
     return false 
    } 

    func mapView(_ mapView: MGLMapView, imageFor annotation: MGLAnnotation) -> MGLAnnotationImage? { 
     var annotationImage = mapView.dequeueReusableAnnotationImage(withIdentifier: UIColor.kuMarkerName) 

     if annotationImage == nil { 
      var image = UIImage(named: UIColor.kuMarkerName)! 
      image = image.withAlignmentRectInsets(UIEdgeInsets(top: 0, left: 0, bottom: image.size.height/2, right: 0)) 
      annotationImage = MGLAnnotationImage(image: image, reuseIdentifier: UIColor.kuMarkerName) 
     } 

     return annotationImage 
    } 
} 

extension EventMapViewController: UIGestureRecognizerDelegate { 

    func handleTap(gestureRecognizer: UIGestureRecognizer) { 
     //close peek and keyboard on tap 
     view.endEditing(true) 

     if peekShowing { 
      exitPeekView() 
     } 
    } 

    func peekSelected(gestureRecognizer: UIGestureRecognizer) { 
//  performSegue(withIdentifier: "eventSegue", sender: nil) 

     let eventController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "EventViewController") as! EventViewController 
     self.navigationController?.pushViewController(eventController, animated: true) 
    } 
} 

Antwort

0

mehrere Gesten verwenden machen Sie Ihre Klasse ein GestureRecognizer delegieren UIGestureRecoginizerDelegate dann diese Funktion verwenden:

func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool { 
     if (gestureRecognizer is UIPanGestureRecognizer || gestureRecognizer is UITapGestureRecognizer) { 
      return true 
     } else { 
      return false 
     } 
    } 
Verwandte Themen