如何仅在地图视图中为注释设置辅助功能?

时间:2015-08-07 13:04:41

标签: ios mkmapview uiaccessibility

我正在尝试使我的mapview可访问,但我有一个非常好的做法:

如果我尝试使mapView可访问,请执行以下操作:

   self.mapView.isAccessibilityElement=YES; 

然后,语音不会读取地图视图。

如果我这样设置:

  self.mapView.isAccessibilityElement=NO;

然后,配音正在读取地图,街道,建筑物,当前位置和我的注释中的所有内容。

我已经为我的注释提供了辅助功能标签和提示,但我还没有为mapview提供任何其他值。

我还试过设置地图视图的辅助功能元素:

  [self.mapView setAccessibilityElements:@[self.mapView.annotations,self.mapView.userLocation]];

但仍然没有运气。

无论如何,只有通过阅读注释而忽略了街道,建筑物等剩余元素?

1 个答案:

答案 0 :(得分:2)

我认为您遇到了困难,因为MKMapView是UIAccessibilityContainer,所以isAccessibilityElement默认为false

您应该考虑制作自定义语音转换器,允许用户仅通过您的注释来浏览您的应用。

这是一种很好的方法,因为它为用户提供了一种自定义的应用专用方式来导航地图,同时也没有从MKMapView的内置辅助功能中获取任何内容。

网上几乎没有任何关于创建自定义转子的详细信息,但我只是成功创建了一个完全按照您的需要去做的事情。我跟着WWDC Session 202(从24:17开始)。

这是我的代码:

func configureCustomRotors() {
  let favoritesRotor = UIAccessibilityCustomRotor(name: "Bridges") { predicate in
    let forward = (predicate.searchDirection == .next)

    // which element is currently highlighted
    let currentAnnotationView = predicate.currentItem.targetElement as? MKPinAnnotationView
    let currentAnnotation = (currentAnnotationView?.annotation as? BridgeAnnotation)

    // easy reference to all possible annotations
    let allAnnotations = self.mapView.annotations.filter { $0 is BridgeAnnotation }

    // we'll start our index either 1 less or 1 more, so we enter at either 0 or last element
    var currentIndex = forward ? -1 : allAnnotations.count

    // set our index to currentAnnotation's index if we can find it in allAnnotations
    if let currentAnnotation = currentAnnotation {
      if let index = allAnnotations.index(where: { (annotation) -> Bool in
        return (annotation.coordinate.latitude == currentAnnotation.coordinate.latitude) &&
    (annotation.coordinate.longitude == currentAnnotation.coordinate.longitude)
        }) {
          currentIndex = index
      }
    }

    // now that we have our currentIndex, here's a helper to give us the next element
    // the user is requesting
    let nextIndex = {(index:Int) -> Int in forward ? index + 1 : index - 1}

    currentIndex = nextIndex(currentIndex)

    while currentIndex >= 0 && currentIndex < allAnnotations.count {
      let requestedAnnotation = allAnnotations[currentIndex]

      // i can't stress how important it is to have animated set to false. save yourself the 10 hours i burnt, and just go with it. if you set it to true, the map starts moving to the annotation, but there's no guarantee the annotation has an associated view yet, because it could still be animating. in which case the line below this one will be nil, and you'll have a whole bunch of annotations that can't be navigated to
      self.mapView.setCenter(requestedAnnotation.coordinate, animated: false)
      if let annotationView = self.mapView.view(for: requestedAnnotation) {
        return UIAccessibilityCustomRotorItemResult(targetElement: annotationView, targetRange: nil)
      }

      currentIndex = nextIndex(currentIndex)
    }

    return nil
  }

  self.accessibilityCustomRotors = [favoritesRotor]
}
相关问题