2015-05-12 17 views
5

Ich versuche, Unterstützung für Voice Over Zugänglichkeit in einem Puzzle-Spiel, das ein festes Board hat. Allerdings habe ich Probleme, UIAccessibilityElements zu bekommen.Erreichbarkeit (Voice Over) mit Sprite Kit

Im Moment überschreibe ich in meinem SKScene accessibilityElementAtIndex, accessibilityElementCount und indexOfAccessibilityElement.

Sie sind eine Reihe von zugänglichen Elementen als solche zurückkehr:

func loadAccessibleElements() 
{ 
    self.isAccessibilityElement = false 

    let pieces = getAllPieces() 

    accessibleElements.removeAll(keepCapacity: false) 
    for piece in pieces 
    { 
     let element = UIAccessibilityElement(accessibilityContainer: self.usableView!) 

     element.accessibilityFrame = piece.getAccessibilityFrame() 
     element.accessibilityLabel = piece.getText() 
     element.accessibilityTraits = UIAccessibilityTraitButton 
     accessibleElements.append(element) 
    } 
} 

Wo Stück eine Unterklasse von SKSpriteNode und getAccessibilityFrame definiert ist:

func getAccessibilityFrame() -> CGRect 
{ 
    return parentView!.convertRect(frame, toView: nil) 
} 

Gerade jetzt ein (fälschlich Größe) accessibility Element scheint auf dem Bildschirm an der falschen Stelle zu erscheinen.

Könnte mir jemand in die richtige Richtung zeigen?

Vielen Dank

EDIT:
ich einen Hack-ish Arbeit um versucht haben, durch eine UIView über die SKView mit UIButton Elemente in der gleichen Position wie die SKSpriteNodes platzieren. Zugänglichkeit will jedoch immer noch nicht funktionieren. Die Ansicht wird folgendermaßen geladen:

func loadAccessibilityView() 
{ 
    view.isAccessibilityElement = false 
    view.accessibilityElementsHidden = false 
    skView.accessibilityElementsHidden = false 
    let accessibleSubview = UIView(frame: view.frame) 
    accessibleSubview.userInteractionEnabled = true 
    accessibleSubview.isAccessibilityElement = false 
    view.addSubview(accessibleSubview) 
    view.bringSubviewToFront(accessibleSubview) 

    let pieces = (skView.scene! as! GameScene).getAllPieces() 
    for piece in pieces 
    { 
     let pieceButton = UIButton(frame: piece.getAccessibilityFrame()) 
     pieceButton.isAccessibilityElement = true 
     pieceButton.accessibilityElementsHidden = false 
     pieceButton.accessibilityTraits = UIAccessibilityTraitButton 
     pieceButton.setTitle(piece.getText(), forState: UIControlState.Normal) 
     pieceButton.setBackgroundImage(UIImage(named: "blue-button"), forState: UIControlState.Normal) 
     pieceButton.alpha = 0.2 
     pieceButton.accessibilityLabel = piece.getText() 
     pieceButton.accessibilityFrame = pieceButton.frame 
     pieceButton.addTarget(self, action: Selector("didTap:"), forControlEvents: UIControlEvents.TouchUpInside) 
     accessibleSubview.addSubview(pieceButton) 
    } 

    UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, nil) 

} 

Die Schaltflächen sind korrekt platziert, die Zugriffsmöglichkeit funktioniert jedoch nicht. Etwas scheint zu verhindern, dass es funktioniert.

+0

Im Anschluss an diese, ich habe einen anderen Weg versucht - Ich habe eine Subview UIButtons in der exakt gleichen Position wie die skspritenodes überlagert . Ich war überrascht, dass diese Tasten auch nicht von Voice-over zugegriffen werden können. Habe ich einen Fehler gemacht, Eingaben zu blockieren? Die Skscene selbst überschreibt die BerührungenBegun (...) usw. – Mason

Antwort

2

Ich habe vergeblich nach einer Beschreibung gesucht, wie man VoiceOver in Swift mit SpriteKit implementiert, also habe ich endlich herausgefunden, wie es geht. Hier einige Arbeits Code, der eine SKNode zu einem zugänglichen Taster umwandelt, wenn zu einer SKScene Klasse hinzugefügt:

// Add the following code to a scene where you want to make the SKNode variable named “leave” an accessible button 
// leave must already be initialized and added as a child of the scene, or a child of other SKNodes in the scene 
// screenHeight must already be defined as the height of the device screen, in points 

// Accessibility 

private var accessibleElements: [UIAccessibilityElement] = [] 

private func nodeToDevicePointsFrame(node: SKNode) -> CGRect { 

    // first convert from frame in SKNode to frame in SKScene's coordinates 

    var sceneFrame = node.frame 
    sceneFrame.origin = node.scene!.convertPoint(node.frame.origin, fromNode: node.parent!) 

    // convert frame from SKScene coordinates to device points 
    // sprite kit scene origin is in lower left, accessibility device screen origin is at upper left 
    // assumes scene is initialized using SKSceneScaleMode.Fill using dimensions same as device points 

    var deviceFrame = sceneFrame 
    deviceFrame.origin.y = CGFloat(screenHeight-1) - (sceneFrame.origin.y + sceneFrame.size.height) 
    return deviceFrame 
} 

private func initAccessibility() { 
    if accessibleElements.count == 0 { 
     let accessibleLeave = UIAccessibilityElement(accessibilityContainer: self.view!) 
     accessibleLeave.accessibilityFrame = nodeToDevicePointsFrame(leave) 
     accessibleLeave.accessibilityTraits = UIAccessibilityTraitButton 
     accessibleLeave.accessibilityLabel = “leave” // the accessible name of the button 
     accessibleElements.append(accessibleLeave) 
    } 
} 
override func didMoveToView(view: SKView) { 
    self.isAccessibilityElement = false 
    leave.isAccessibilityElement = true 
} 

override func willMoveFromView(view: SKView) { 
    accessibleElements = [] 
} 

override func accessibilityElementCount() -> Int { 
    initAccessibility() 
    return accessibleElements.count 
} 

override func accessibilityElementAtIndex(index: Int) -> AnyObject? { 
    initAccessibility() 
    if (index < accessibleElements.count) { 
     return accessibleElements[index] as AnyObject 
    } else { 
     return nil 
    } 
} 

override func indexOfAccessibilityElement(element: AnyObject) -> Int { 
    initAccessibility() 
    return accessibleElements.indexOf(element as! UIAccessibilityElement)! 
} 
0

Eingabehilfen Frames sind in den festen physikalischen Bildschirmkoordinaten, nicht UIView Koordinaten definiert, und die Transformation zwischen ihnen ist eine Art schwierig.

Der Geräteursprung befindet sich links unten auf dem Bildschirm, mit X up, wenn sich das Gerät im Landscape-Right-Modus befindet.

Es ist ein Schmerz zu konvertieren, ich habe keine Ahnung, warum Apple es so gemacht hat.

+0

Ja, sie sind ein Problem, ich habe ein paar Variationen der Funktion getAccessibilityFrame ausprobiert, die alle nicht richtig funktionierten. Ich habe es geschafft, UIButtons stattdessen über die Sprite-Elemente zu legen, aber die Barrierefreiheit funktioniert auch nicht für sie. Ich habe das Gefühl, dass die SKScene die Eingaben verwirrte? Wenn Sie auf tippen und ziehen, wird nur ein Geräusch erzeugt, als ob Sie versucht hätten, einen leeren Bereich ohne Zugänglichkeit auszuwählen. Ich werde es in meiner Frage in Kürze erweitern – Mason

+0

Ich hatte Glück, dass die App-Spezifikation will nur Landschaft links und rechts, so dass es einfach war, die Transformation der Hand Code, wenn sie nicht konsequent arbeiten. –

+0

Das Accessibility-Element ist nur ein Fokusbereich für einen Tipp oder eine Geste, also würde alles, was es blockiert, es tatsächlich davon abhalten zu arbeiten. Sind Sie sicher, dass Ihr Accessibility-Container, wenn Sie einen haben, "nein" zurückgibt? –