UIBarButtonItem的accessibilityElementDidBecomeFocused回调未触发问题
问题描述
需要监听UIBarButtonItem获取/失去无障碍焦点的事件,实现了UIAccessibilityFocus非正式协议的方法,但回调始终未触发。
尝试的实现方案
方案1:Swift扩展UIBarButtonItem
extension UIBarButtonItem { override open func accessibilityElementDidBecomeFocused() { if self.accessibilityElementIsFocused() { print("My element has become focused.") } } override open func accessibilityElementDidLoseFocus() { if self.accessibilityElementIsFocused() { print("My element has lost focus.") } } override open func accessibilityElementIsFocused() -> Bool { return self.accessibilityIdentifier == "hamburger" } }
在Objective-C的ViewController中导入Swift桥接文件:
#import "Sample-Swift.h"
方案2:子类化UIBarButtonItem(HamburgerButton)
.h文件
#import <UIKit/UIKit.h> #import <UIKit/UIAccessibility.h> NS_ASSUME_NONNULL_BEGIN @interface HamburgerButton : UIBarButtonItem @end NS_ASSUME_NONNULL_END
.m文件
@implementation HamburgerButton - (BOOL)isAccessibilityElement { return YES; } - (void)accessibilityElementDidBecomeFocused { if ([self accessibilityElementIsFocused]) { NSLog(@"My element has become focused."); } } - (void)accessibilityElementDidLoseFocus { if ([self accessibilityElementIsFocused]) { NSLog(@"My element has lost focus."); } } - (BOOL)accessibilityElementIsFocused { return [self.accessibilityIdentifier isEqualToString:@"hamburger"]; } @end
ViewController中使用子类实例
HamburgerButton *leftButton = [[HamburgerButton alloc] initWithTitle:@"Hamburger" style:UIBarButtonItemStylePlain target:self action:@selector(flipView:)]; leftButton.accessibilityIdentifier=@"Hamburger"; leftButton.tag = 88; leftButton.isAccessibilityElement = YES; HamburgerButton *rightButton = [[HamburgerButton alloc] initWithTitle:@"Chat" style:UIBarButtonItemStylePlain target:self action:@selector(flipView:)]; rightButton.accessibilityIdentifier=@"Chat"; rightButton.tag = 89; rightButton.isAccessibilityElement = YES; self.navigationItem.leftBarButtonItem = leftButton; self.navigationItem.rightBarButtonItem = rightButton;
实际测试中,焦点确实在两个BarButton间切换,但
accessibilityElementDidBecomeFocused和accessibilityElementDidLoseFocus始终未触发。
后续尝试与疑问
更新1:通过通知监听,但无法区分具体按钮
注册无障碍焦点通知:
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(hamburgerGotFocus:) name:UIAccessibilityElementFocusedNotification object:nil];
回调方法:
-(void)hamburgerGotFocus:(NSNotification *) notification{ NSLog(@"Focus:%@",notification); UIView *receiver = notification.userInfo[@"UIAccessibilityFocusedElementKey"]; if(receiver!=nil){ NSString *strElement = [[NSString alloc]initWithFormat:@"%@",notification.userInfo[@"UIAccessibilityFocusedElementKey"]]; if([strElement containsString:@"UIButtonBarButton"]){ // 无法判断具体是哪个BarButtonItem } } }
通知日志示例:
2022-10-12 18:57:03.992859+0530 Sample[32427:1579550] Focus:NSConcreteNotification 0x280ac9980 {name = UIAccessibilityElementFocusedNotification; userInfo = { UIAccessibilityAssistiveTechnologyKey = UIAccessibilityNotificationVoiceOverIdentifier; UIAccessibilityFocusedElementKey = "<_UIButtonBarButton: 0x10690fce0; frame = (0 0; 49 44); tintColor = UIExtendedSRGBColorSpace 0 1 0 1; gestureRecognizers = <NSArray: 0x2804262e0>; layer = <CALayer: 0x280afa9e0>>"; }}
更新2:UILabel测试正常,怀疑兼容性问题
对UILabel使用分类和子类化的方式实现UIAccessibilityFocus协议方法,均能正常触发焦点回调。由此怀疑UIBarButtonItem是否与UIAccessibilityFocus非正式协议存在兼容性问题。
参考教程内容(翻译)
iOS无障碍开发:聚焦元素
- 当VoiceOver等辅助技术聚焦到某个元素时,系统会调用
accessibilityElementDidBecomeFocused方法;当元素失去焦点时,会调用accessibilityElementDidLoseFocus方法。 - 这两个方法属于
UIAccessibilityFocus非正式协议,主要针对继承自UIView的元素,用于在焦点变化时执行自定义逻辑。
内容的提问来源于stack exchange,提问作者Durai Amuthan.H
相关产品推荐
相关产品推荐

