Я рисую несколько MKAnnotations
на MKMapView
. Я бы хотел, чтобы пользователи VoiceOver могли продолжать панорамирование/масштабирование карты, как обычно, но я также хотел бы, чтобы они могли быстро и легко перемещаться по моему MKAnnotations
, если они захотят. Я чувствую, что пользовательский ротор - идеальное решение для этого.Создайте собственный ротор VoiceOver для навигации по MKAnnotationViews?
ответ
Автоответчик здесь, потому что я потратил безумное количество времени на правильное решение, и подумал, что кому-то может понадобиться это. В то время, когда мне нужно было это разработать, вряд ли были примеры онлайн, которые подробно рассказывают о создании пользовательских роторов, а документация Apple очень скудна. Я, наконец, понял это, после просмотра и последующего (и паузы на экранах кода) WWDC Session 202 (начинается в 24:17).
Самое сложное, что мне нужно было выяснить, - как надежно вернуть UIAccessibilityCustomRotorItemResult
. Для MKMapView
вы хотите вернуть MKAnnotationView
s, но аннотация не гарантирует наличие связанного представления (они переработаны, а если аннотация включена вне экрана, есть хороший шанс, что ее просмотр был повторно использован), поэтому мои первые попытки продолжал оставлять некоторые или большинство моих аннотаций.
Магия в создании анимированного: свойство ложно:
self.mapView.setCenter(requestedAnnotation.coordinate, animated: false)
Вы не можете использовать вид (для: MKAnnotation) по причинам, указанным выше, так что линия выше делает перемещает карту поэтому ваш контакт находится в центре. Поскольку это не анимация, аннотация имеет вид, созданный сразу, а в следующей строке кода, в моем тестировании, гарантированно возвращается MKAnnotationView
.
YVVM, но, пожалуйста, не стесняйтесь добавлять предложения для улучшения, так как я считаю, что навигационная карта таким образом имеет решающее значение для пользователей VoiceOver.
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]
}
- 1. Как добавить ротор iOS VoiceOver для пользовательского представления?
- 2. Включить ссылки в доступность Ротор VoiceOver на UIView
- 3. Заголовок с ссылкой, не указанной в заголовке VoiceOver, ротор
- 4. Заказать массив MKAnnotationViews по широте?
- 5. Создайте собственный инсталлятор для игры
- 6. Создайте собственный собственный многопользовательский iPhone?
- 7. Как настроить язык VoiceOver на панели навигации?
- 8. Создайте свой собственный браузер
- 9. активировать VoiceOver по коду
- 10. SSCLI (ротор) для v4.0 clr?
- 11. Создайте свой собственный стиль
- 12. Создайте правильный путь для навигации
- 13. Создайте собственный OnItemClickListener
- 14. Создайте собственный переключатель SwitchCompat
- 15. Z-порядок MKAnnotationViews
- 16. Создайте свой собственный API
- 17. Создайте собственный собственный список содержимого веб-сайта
- 18. Создайте собственный видеоплеер
- 19. Создайте собственный открытый график
- 20. Создайте URL-адрес для навигации по карте Uber
- 21. Создайте собственный редактор модели Ecore
- 22. перевести ротор в cfx_http5
- 23. Заменить ротор с file_get_content
- 24. Создайте свой собственный слайдер для приложения multitouch
- 25. SideWaffle - создайте свой собственный шаблон для обмена
- 26. Создайте собственный набор данных для отчета
- 27. Создайте собственный обработчик для подвижек в GWT
- 28. Создайте собственный файл FILTER_VALIDATE_XY для filter_input_array
- 29. Создайте свой собственный диск для эмулятора Android
- 30. Создайте собственный порт для печати в .NET