2016-05-03 6 views
0

Ich versuche, eine benutzerdefinierte UIView/Scrollview namens MyScrollView, die ein paar Etiketten (UILabel) enthält, und diese Etiketten erhalten tippen Gesten/Ereignisse, um auf Benutzer zu reagieren Auswahlen See the below screen shot for the custom UIView.Tippen Gesture Recognizer nicht in benutzerdefinierten UIView in super Ansicht

Um die Antippereignis Arbeiten an den UILabels zu machen, ich sicherstellen, dass sie alle haben userIteractionEnabled = true und ich erstellt, wie unten einen Delegierten:

protocol MyScrollViewDelegate { 
    func labelClicked(recognizer: UITapGestureRecognizer) 
} 

Die benutzerdefinierte UIView in ScrollViewController verwendet wird, die ich erstellt, Dies implementiert die ScrollViewController Delegatmethode auch:

import UIKit 
import Neon 
class ScrollViewController: UIViewController, MyScrollViewDelegate { 

var curQuestion: IPQuestion? 
var type: QuestionViewType? 
var lastClickedLabelTag: Int = 0 // 

init(type: QuestionViewType, question: IPQuestion) { 
    super.init(nibName: nil, bundle: nil) 
    self.curQuestion = question 
    self.type = type 
} 

required init?(coder aDecoder: NSCoder) { 
    fatalError("init(coder:) has not been implemented") 
} 

override func viewDidLoad() { 
    super.viewDidLoad() 
    self.automaticallyAdjustsScrollViewInsets = false 
} 

override func didReceiveMemoryWarning() { 
    super.didReceiveMemoryWarning() 
} 

override func loadView() { 
    view = MyScrollView(delegate: self, q: curQuestion!) 
    view.userInteractionEnabled = true 
} 
} 

// implementations for MyScrollViewDelegate 
extension ScrollViewController { 

func labelTitleArray() -> [String]? { 
    print("labelTitleArray called in implemented delegate") 

    return ["Comments", "Answers"] 
} 

func labelClicked(recognizer: UITapGestureRecognizer) { 
    print("labelClicked called in implemented delegate") 
    let controller = parentViewController as? ParentViewController 
    controller?.labelClicked(recognizer) 
    lastClickedLabelTag = recognizer.view!.tag 
    } 
} 

// MARK: - handle parent's ViewController event 
extension QuestionDetailViewController { 
    func updateActiveLabelsColor(index: Int) { 
     print("updating active labels color: \(index)") 
     if let view = view as? MyScrollView { 
      for label in (view.titleScroll.subviews[0].subviews as? [UILabel])! { 
       if label.tag == index { 
        label.transform = CGAffineTransformMakeScale(1.1,1.1) 
        label.textColor = UIColor.purpleColor() 
       } 
       else { 
        label.transform = CGAffineTransformMakeScale(1,1) 
        label.textColor = UIColor.blackColor() 
       } 
      } 
     } 
    } 
} 

das oben ScrollViewController hinzugefügt wird, als ein Kind-view-Controller zu der übergeordneten Ansicht Controller und mit dem oberen Teil des Mutter positioniert‘ Ansicht:

override func viewDidLoad() { 
     super.viewDidLoad() 
     self.automaticallyAdjustsScrollViewInsets = false 
     self.view.backgroundColor = UIColor.whiteColor() 
     addChildViewController(scrollViewController) // added as a child view controller here 
     view.addSubview(scrollViewController.view) // here .view is MyScrollView 
     scrollViewController.view.userInteractionEnabled = true 
     scrollViewController.view.anchorToEdge(.Top, padding: 0, width: view.frame.size.width, height: 100) 
    } 

Die App alles oben in der Ansicht laden, aber die Tippgeste/Ereignisse sind nicht auf die Etiketten in den benutzerdefinierten MyScrollView weitergegeben. Dafür habe ich eine Google-Suche durchgeführt und habe Event Delivery: Responder Chain auf der Apple Developer-Website gelesen und einen Hit-Test gemacht.

nur in der Ansicht
override func hitTest(point: CGPoint, withEvent event: UIEvent?) -> UIView? { 
     print("hit test started, point: \(point), event: \(event)") 
     return self 
    } 

Meine Beobachtungen mit den hitTest ist, dass die touchesBegan() und touchesEnded() Methoden werden ausgelöst, wenn die hitTest Funktion gibt es: Die hitTest Funktion unten in den MyScrollView ausgelöst werden. Ohne hitTest werden beide Funktionen nicht mit Taps aufgerufen.

aber kein Glück bekommen die UILabel auf Tap Gesten reagieren. Ich bin hier also an Experten für SO interessiert. Danke fürs Helfen!

+1

Versuchen Sie, diese in den relevanten Berührungsmethoden des übergeordneten Elements an den nächsten Responder weiterzuleiten. Zum Beispiel versuchen Sie innerhalb von 'touchesBegan' innerhalb des Elternteils 'self.nextResponder.touchesEnged' aufzurufen. –

+0

Haben Sie die Eigenschaft userInteractionEnabled = true für Ihre Labels festgelegt?Der Standardwert für UILabel ist falsch, Sie sollten ihn also ändern, wenn Sie Gesten erhalten möchten. –

+0

@VladimirK, ja, ich habe 'userIteractionEnabled' auf allen Labels auf 'true' gesetzt. Danke – TonyGW

Antwort

3

Ich glaube, ich den Grund herausgefunden, warum die UILabel nicht nach viel Kampf auf Klopfen reagierte: die .addGestureRecognizer() Methode auf das Etikett in der Komponente init() Methode meiner benutzerdefinierten UIView ausgeführt wurde, die falsch ist, weil die view/label wurde möglicherweise noch nicht gerendert. Stattdessen zog ich diesen Code mit dem Lebenszyklus Methode layoutSubviews(), und alles begann gut zu funktionieren:

var lastLabel: UILabel? = nil 

     for i in 0..<scrollTitleArr.count { 
      let label = UILabel() 
      label.text = scrollTitleArr[i] ?? "nothing" 
      print("label: \(label.text)") 
      label.font = UIFont(name: "System", size: 15) 
      label.textColor = (i == 0) ? MaterialColor.grey.lighten2 : MaterialColor.grey.darken2 
      label.transform = (i == 0) ? CGAffineTransformMakeScale(1.1, 1.1) : CGAffineTransformMakeScale(0.9, 0.9) 
      label.sizeToFit() 
      label.tag = i // for tracking the label by tag number 
      label.userInteractionEnabled = true 
      label.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.labelClicked(_:)))) 

      titleContainer.addSubview(label) 

      if lastLabel == nil { 
       label.anchorInCorner(.TopLeft, xPad: 0, yPad: 0, width: 85, height: 40) 
     //   label.anchorToEdge(.Left, padding: 2, width: 85, height: 40) 
      } else { 
       label.align(.ToTheRightMatchingTop, relativeTo: lastLabel!, padding: labelHorizontalGap, width: 85, height: 40) 
      } 

      lastLabel = label 

     } 

Außerdem brauche ich keine der UIGestureRecognizer Delegatmethoden zu implementieren und ich brauche nicht zu machen die Containeransicht oder die Bildlaufansicht userInteractionEnabled. Noch wichtiger ist, dass ich beim Einbetten der benutzerdefinierten UIView in eine Superview ihre Größe konfigurierte und clipsToBounds = true festlegte.

Ich denke, ich hätte mehr UIView Dokumentation auf der Apple Developer Website gelesen. Hoffe, das wird jemandem wie mir in der Zukunft helfen! Dank an alle!

0

Sie müssen die Eigenschaft userInteractionEnabled = YES festlegen.