Home > Net >  UISegmentedControl accessibility mode styling
UISegmentedControl accessibility mode styling

Time:10-11

I'm setting colors for my segmented control like this:

segmentedControl.backgroundColor = .gray
segmentedControl.selectedSegmentTintColor = .red

let textAttrs: [NSAttributedString.Key : Any] = [
    .foregroundColor: UIColor.white
]
segmentedControl.setTitleTextAttributes(textAttrs, for: .normal)

It works well, but when user long taps on it (with large fonts enabled in Settings), I get the following: enter image description here

As you can see, the text is unreadable. Is there any way to set background/tint colors for the accessibility view?

The best solution I found is to set a background color for the text in title attributes like this:

let textAttrs: [NSAttributedString.Key : Any] = [
    .foregroundColor: UIColor.white,
    .backgroundColor: segmentedControl.backgroundColor!
]
segmentedControl.setTitleTextAttributes(textAttrs, for: .normal)

let textAttrsSelected: [NSAttributedString.Key : Any] = [
    .foregroundColor: UIColor.white,
    .backgroundColor: segmentedControl.selectedSegmentTintColor!
]
segmentedControl.setTitleTextAttributes(textAttrsSelected, for: .selected)

The result is better (at least the text is readable), but still it doesn't look good:

enter image description here

Ideally I'd like the accessibility mode view to have the same background color and tint color for selected item as in the main view.

CodePudding user response:

There doesn't appear to be any public API to help you with this. You should open a feedback request with Apple.

In the meantime, if you are interested in somewhat hacky workaround, you can override your controller's presentViewController:animated:completion: and "touch" the view hierarchy a little.

- (void)presentViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)flag completion:(void (^)(void))completion
{
    NSString* controllerClassName = NSStringFromClass(viewControllerToPresent.class);
    
    if([controllerClassName hasPrefix:@"UIAccessibility"] && [controllerClassName containsString:@"Segmented"])
    {
        [[viewControllerToPresent valueForKey:@"segmentButtons"] enumerateObjectsUsingBlock:^(UIButton* _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
            [obj setValue:nil forKeyPath:@"segment.appearanceStorage"];
        }];
    }
    
    [super presentViewController:viewControllerToPresent animated:flag completion:completion];
}

This will make the popover appear as it would, if you hadn't customized the segmented control:

Popover

As you can see, there is some private API usage there, so you will need to hide it.

If you'd like to customize the popover to appear like your segmented control, it will be more difficult. The white selection rectangle is an image, so you'd need to modify that, but also take into account changing appearance (light/dark mode):

Selection Image

I'd suggest not going that route. The default-appearance popover should be good enough.

  • Related