VoiceOver

since 2023-03-21

最悪の実装をなんとかする

以下 ChatGPT (GPT-4) の書いたコードを参考のためにメモしています。

  • iOS Objective-C で OpenGL ES の View を使いたい
  • このViewにVoiceOverで操作できる透明なViewを重ねたい
  • VoiceOverが有効の場合だけtransparentViewを出したい
  • これを Swift で書くと?
import UIKit
import GLKit
 
class ViewController: GLKViewController {
 
    var transparentView: UIView?
 
    override func viewDidLoad() {
        super.viewDidLoad()
 
        setupGL()
 
        updateTransparentViewForVoiceOver()
 
        // VoiceOverの状態変更を監視する
        NotificationCenter.default.addObserver(self,
                                               selector: #selector(voiceOverStatusDidChange),
                                               name: UIAccessibility.voiceOverStatusDidChangeNotification,
                                               object: nil)
    }
 
    func setupGL() {
        // OpenGL ESの設定と描画の準備を行う
    }
 
    func updateTransparentViewForVoiceOver() {
        if UIAccessibility.isVoiceOverRunning {
            if transparentView == nil {
                transparentView = UIView(frame: view.bounds)
                transparentView?.backgroundColor = .clear
                transparentView?.isAccessibilityElement = false
 
                // ここに透明なUIViewに追加するUI要素を設定します(例:UIButton)
 
                view.addSubview(transparentView!)
            }
        } else {
            if let transparentView = transparentView {
                transparentView.removeFromSuperview()
                self.transparentView = nil
            }
        }
    }
 
    @objc func voiceOverStatusDidChange() {
        updateTransparentViewForVoiceOver()
    }
 
    deinit {
        NotificationCenter.default.removeObserver(self)
    }
}

途中の Objective-C のコード

// 既存のコードに続けて以下のコードを追加します
- (void)viewDidLoad {
    [super viewDidLoad];
    // ...
 
    // 透明なUIViewを作成
    UIView *transparentView = [[UIView alloc] initWithFrame:self.view.bounds];
    transparentView.backgroundColor = [UIColor clearColor];
    transparentView.isAccessibilityElement = NO;
 
    // UIButtonを追加(例として)
    UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
    button.frame = CGRectMake(50, 50, 200, 40);
    button.isAccessibilityElement = YES;
    button.accessibilityLabel = @"ボタン";
    button.accessibilityHint = @"ボタンをタップして機能を実行します。";
    button.backgroundColor = [UIColor clearColor];
    [button addTarget:self action:@selector(buttonTapped) forControlEvents:UIControlEventTouchUpInside];
    [transparentView addSubview:button];
 
    // 透明なUIViewをメインViewに追加
    [self.view addSubview:transparentView];
}
 
// ボタンがタップされたときに実行されるメソッド
- (void)buttonTapped {
    NSLog(@"ボタンがタップされました。");
}
// クラスの拡張部分
@interface ViewController () {
    // ...
    UIView *transparentView;  // 透明なUIViewをインスタンス変数として宣言
}
 
// viewDidLoadメソッド内で通知を登録
- (void)viewDidLoad {
    [super viewDidLoad];
    // ...
 
    // VoiceOverの状態に応じて透明なUIViewを追加または削除するメソッドを呼び出す
    [self updateTransparentViewForVoiceOver];
 
    // VoiceOverの状態変更を監視する
    [[ NSNotificationCenter defaultCenter ] addObserver:self
                                             selector:@selector(voiceOverStatusDidChange)
                                                 name:UIAccessibilityVoiceOverStatusDidChangeNotification
                                               object:nil];
}
 
// 透明なUIViewを作成し、VoiceOverが有効な場合のみ追加するメソッド
- (void)updateTransparentViewForVoiceOver {
    if (UIAccessibilityIsVoiceOverRunning()) {
        if (!transparentView) {
            transparentView = [[UIView alloc] initWithFrame:self.view.bounds];
            transparentView.backgroundColor = [UIColor clearColor];
            transparentView.isAccessibilityElement = NO;
 
            // ここに透明なUIViewに追加するUI要素を設定します(例:UIButton)
 
            [self.view addSubview:transparentView];
        }
    } else {
        if (transparentView) {
            [transparentView removeFromSuperview];
            transparentView = nil;
        }
    }
}
 
// VoiceOverの状態が変更されたときに呼び出されるメソッド
- (void)voiceOverStatusDidChange {
    [self updateTransparentViewForVoiceOver];
}
 
// インスタンスが解放される際に通知を解除
- (void)dealloc {
    [[ NSNotificationCenter defaultCenter ] removeObserver:self];
}

アクセシビリティ カスタムアクション

ChatGPT の情報をすこし修正。

https://developer.apple.com/videos/play/wwdc2019/250/

アクセシビリティカスタムアクションは、アプリ内のUI要素に対してVoiceOverユーザーが簡単にアクセスできるカスタム操作を提供する機能です。これにより、アクセシビリティ対応のアプリでスワイプジェスチャーやダブルタップなどの標準的なVoiceOver操作だけでなく、特定のUI要素に関連する独自の操作を提供できます。

カスタムアクションを実装するには、以下の手順に従います。

UI要素にUIAccessibilityCustomActionオブジェクトを追加します。このオブジェクトには、アクションの名前(VoiceOverが読み上げる)と、アクションが実行されたときに呼び出されるメソッドが指定されます。

UI要素のaccessibilityCustomActionsプロパティに、作成したUIAccessibilityCustomActionオブジェクトを追加します。

以下に、Swiftでカスタムアクションを実装した例を示します。

import UIKit
 
class ViewController: UIViewController {
 
    override func viewDidLoad() {
        super.viewDidLoad()
 
        let customButton = UIButton(type: .system)
        customButton.frame = CGRect(x: 100, y: 100, width: 200, height: 40)
        customButton.setTitle("カスタムアクションの例", for: .normal)
        customButton.addTarget(self, action: #selector(buttonTapped), for: .touchUpInside)
        view.addSubview(customButton)
 
        // カスタムアクションの作成
        let customAction = UIAccessibilityCustomAction(name: "特別な操作", target: self, selector: #selector(performCustomAction))
        customButton.accessibilityCustomActions = [customAction]
    }
 
    @objc func buttonTapped() {
        print("通常のボタンタップが実行されました。")
    }
 
    @objc func performCustomAction() -> Bool {
        print("カスタムアクションが実行されました。")
        return true
    }
}
voiceover.txt · 最終更新: 2023/03/21 18:40 by Takuya Nishimoto
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0