【问题标题】:Why accessibilityElementDidBecomeFocused is not firing for UIBarButtonItem为什么 accessibilityElementDidBecomeFocused 没有为 UIBarButtonItem 触发
【发布时间】:2022-11-16 22:46:59
【问题描述】:

我想知道 BarButton 项何时获得可访问性焦点或失去可访问性焦点,因此我实现了非正式协议方法UIAccessibilityFocus但它还没有开火。

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 {
    
   if (self.accessibilityIdentifier == "hamburger") {
        return true
    } else {
        return false
    }
}

我也将 swift 文件导入了 viewcontroller

#import "Sample-Swift.h"

然后我尝试子类化并实现了同样无效的方法

.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 {
    
     if ([self.accessibilityIdentifier isEqualToString:@"hamburger"]) {
        return YES;
   } else {
       return NO;
   }
}
@end

这是视图控制器中的实现

 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;

即使焦点从 bar button 来来去去,我也没有接到电话accessibilityElementDidBecomeFocused

任何想法可以做什么来获得accessibilityElementDidBecomeFocused射击?

更新 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"]){
                
        }
    }
}

这是通知日志

 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 进行此操作都有效

@interface SampleLabel : UILabel

@end

@implementation SampleLabel

- (void)accessibilityElementDidBecomeFocused {
        NSLog(@"accessibilityIdentifier:%@",self.accessibilityIdentifier);
        UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification, @"sample label from subclass");
}

- (void)accessibilityElementDidLoseFocus {
    
    if ([self accessibilityElementIsFocused]) {
        NSLog(@"My element has lost focus.subclass");
    }
}

- (BOOL)accessibilityElementIsFocused {
        return YES;
}
@end

通过类别

@interface UILabel (SampleLabel1)

@end

@implementation UILabel (SampleLabel1)

- (void)accessibilityElementDidBecomeFocused {
        NSLog(@"accessibilityIdentifier:%@",self.accessibilityIdentifier);
        UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification, @"sample label from category");
}

- (void)accessibilityElementDidLoseFocus {
    
    if ([self accessibilityElementIsFocused]) {
        NSLog(@"My element has lost focus.Category");
    }
}

- (BOOL)accessibilityElementIsFocused {
        return YES;
}
@end

我想知道 accessibilityElementDidBecomeFocused 是否不兼容UIBarButtonItem

供参考: 我正在关注这个tutorial来实现accessibilityElementDidLoseFocus.

【问题讨论】:

    标签: ios uibarbuttonitem uiaccessibility uiaccessibility-notification


    【解决方案1】:
    accessibilityElementDidBecomeFocused 
    

    不是为条形按钮触发,而是为 UIButton 触发。所以我只是像下面这样使用 UIButton 创建了一个条形按钮,问题就解决了

    // Image
    UIImage *img1 = [UIImage imageNamed:@"img1"];
    
    // Button 
    UIButton *btn1 = [UIButton buttonWithType:UIButtonTypeCustom];
    [btn1 setImage:img1 forState:UIControlStateNormal];
    btn1.frame = CGRectMake(0.0, 0.0, img1.size.width, img1.size.height);
    btn1.tintColor = [UIColor greenColor];
    [btn1 addTarget:self action:@selector(barButtonClicked:) forControlEvents:UIControlEventTouchUpInside];
    
    // Bar button
    UIBarButtonItem *barButton1 = [[UIBarButtonItem alloc]initWithCustomView:btn1];
    
    // Accessibility element
    btn1.isAccessibilityElement = true;
    img1.isAccessibilityElement = false;
    btn1.accessibilityLabel = @"some accessibility text";
    btn1.accessibilityTraits = UIAccessibilityTraitNone;
    
    self.navigationItem.rightBarButtonItem = barButton1;
    

    【讨论】: