-
読書アプリのアクセシビリティの向上
VoiceOverや画面の読み上げなどを活用して、充実した読書体験を生み出す方法を学びましょう。直感的なテキスト選択、行間や段落間の分かりやすいナビゲーション、個々の要素や複数ページにわたるスムーズな読書体験を提供する方法を紹介します。
関連する章
- 0:01 - Introduction
- 1:26 - Characteristics
- 3:45 - Standard views
- 14:05 - Custom text
リソース
- accessibilityNextTextNavigationElement
- editCategory
- accessibilityLinkedGroup(id:in:)
- causesPageTurn
- UITextInput
- Accessibility for UIKit
関連ビデオ
WWDC19
-
このビデオを検索
-
-
7:29 - Link text elements together with navigation APIs
// Link text elements together with navigation APIs import UIKit class TravelGuidePageController: UIViewController { var paragraphs: [TravelGuideParagraph] func configureNavigationElements() { for (index, paragraph) in paragraphs.enumerated() { if index + 1 < paragraphs.count { paragraph.accessibilityNextTextNavigationElement = paragraphs[index + 1] } if index - 1 >= 0 { paragraph.accessibilityPreviousTextNavigationElement = paragraphs[index - 1] } } } } -
7:59 - Link text elements together with a linked group
// Link text elements together with a linked group import SwiftUI struct PageView : View { @Namespace private var pageNamespace var paragraphs: [String var pageNumber: Int var body: some View { Text(paragraphs[0]) .textSelection(.enabled) .accessibilityLinkedGroup(id: pageNumber, in: pageNamespace) Text(paragraphs[1]) .textSelection(.enabled) .accessibilityLinkedGroup(id: pageNumber, in: pageNamespace) } } -
9:50 - Turn pages automatically after reading
// Turn pages automatically after reading import UIKit class TravelGuidePageController: UIViewController { override func viewDidLoad() { super.viewDidLoad() self.lastParagraphView.accessibilityTraits.insert(.causesPageTurn) } override func accessibilityScroll(_ direction: UIAccessibilityScrollDirection) -> Bool { moveToPage(direction) var scrollString = "Page \(currentPage) of \(pages.count)" UIAccessibility.post(notification: .pageScrolled, argument: scrollString) return true } } -
11:45 - Add actions to the editor rotor
// Add actions to the editor rotor import UIKit class TravelGuideParagraph: UITextView { override var accessibilityCustomActions: [UIAccessibilityCustomAction]? { get { let saveAction = UIAccessibilityCustomAction(name: "Save Recommendation") { _ in self.saveRecommendation() } saveAction.category = UIAccessibilityCustomAction.editCategory return (super.accessibilityCustomActions ?? []) + [saveAction] } set { } } private func saveRecommendation() -> Bool { ... return true } } -
16:10 - Adopt UITextInput
// Adopt UITextInput import UIKit class ScannedPage: UIView, UITextInput { override init(frame: CGRect) { super.init(frame: frame) let interaction = UITextInteraction(for: .nonEditable) interaction.textInput = self addInteraction(interaction) } func selectionRects(for range: UITextRange) -> [UITextSelectionRect] { var rects: [UITextSelectionRect] = [] let startLine = lineIndex(for: range.start) let endLine = lineIndex(for: range.end) for line in startLine...endLine { let rect = selectionRectFromImage(for: range, in: line) rects.append(rect) } return rects } func text(in range: UITextRange) -> String? { let nsRange = nsRange(from: range) guard let range = Range(nsRange, in: scannedText) else { return nil } return String(scannedText[range]) } var tokenizer: any UITextInputTokenizer { CustomHandwritingTokenizer(textInput: self) } weak var inputDelegate: UITextInputDelegate? var selectedTextRange: UITextRange? { // Update visuals when assistive technologies change selection willSet { inputDelegate?.selectionWillChange(self) } didSet { inputDelegate?.selectionDidChange(self) } } }
-
-
- 0:01 - Introduction
What makes reading apps an accessibility challenge distinct from UI navigation, and what the session covers — the characteristics of a great reading experience, extending UIKit and SwiftUI text views, and making custom text accessible.
- 1:26 - Characteristics
Reading apps present unique accessibility challenges distinct from standard UI navigation, requiring fluid movement through text for technologies like VoiceOver and Speak Screen. This session covers three goals — granular navigation, continuous reading, and text selection — using UIKit, SwiftUI, and AppKit APIs.
- 3:45 - Standard views
UITextView, SwiftUI's TextEditor and selectable Text, and NSTextView on macOS all adopt UITextInput automatically, providing line, word, and character navigation and accessible text selection. The accessibilityNextTextNavigationElement and accessibilityPreviousTextNavigationElement APIs (and the new accessibilityLinkedGroup for SwiftUI) connect separate text elements so VoiceOver can move between them seamlessly, while the causesPageTurn trait provides page turning automatically during read-all gestures.
- 14:05 - Custom text
When using custom or custom-rendered text — such as scanned images — adopting the full UITextInput protocol gives VoiceOver and Speak Screen the same granular navigation and selection capabilities as native text views. This requires implementing text geometry methods like selectionRects(for:), a tokenizer, and text range methods, and can be paired with UITextInteraction for visible selection handles.