2017-06-06 3 views
0

スワイプジェスチャーを使用して、UIScrollView内で4つのUIViewControllerサブクラスをホストする偽のUITabBarControllerを使用してタブ間を移動します。それぞれのUIPanGestureRecognizersでスワイプを検出し、それに従ってタブを切り替えます。結果として得られる効果は、Snapchatで見られるようなコアナビゲーションです。ただし、これらの画面の1つには、独自のジェスチャ認識機能が組み込まれたマップビュー(マップマップマップ)が格納されています。2つのジェスチャ認識器を同時に使用してイベントを受信するにはどうすればよいですか?

画面の右端からスワイプを検出することで、ユーザーが地図上をスワイプして別のタブに移動できるようにしたいと考えています。私はUIPanGestureRecognizerを右側のこの領域にある見えないUIViewに追加しようとしましたが、これは不規則で、アニメートされていないタブスイッチを提供し、下のマップからタッチイベントを傍受します。

どのようにして、両方のジェスチャ認識機能がイベントを同時に受信するか、スワイプの開始位置とその距離と方向のみに基づいていくつかのイベントをフィルタリングすることを許可できますか?マップビューコントローラの

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

コード:ビューコントローラをスワイプため

コードは

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

答えて

0

複数のジェスチャーを使用するにはGestureRecognizerデリゲートUIGestureRecoginizerDelegateあなたのクラスを作成し、この機能を使用します。

func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool { 
     if (gestureRecognizer is UIPanGestureRecognizer || gestureRecognizer is UITapGestureRecognizer) { 
      return true 
     } else { 
      return false 
     } 
    } 
関連する問題