Blue Highlighting / Focus Ring on Catalyst App
Asked Answered
H

7

13

I'm currently in the process of porting my iOS app to macOS using Project Catalyst.

All of my text fields, text views and table views have a blue outline when active.

I've noticed it in Apple Catalyst apps (e.g. News) in recent betas so I'm hoping it's just a bug.

Has anyone found any way to remove it otherwise?

Humidifier answered 20/8, 2019 at 15:49 Comment(2)
I have the same issue, asked around on Apple Dev Forum, not much response so far: forums.developer.apple.com/thread/121280 UIKit started to adopt the focusRing APIs that macOS UI elements have by default (see: developer.apple.com/documentation/appkit/nsview/…), but there is no public API yet to change the default behaviour.Storehouse
Please don't remove this ring - this is important for accessibility + keyboard only users.Overcoat
R
21

In swift you can do


extension UITextView {
    #if targetEnvironment(macCatalyst)
    @objc(_focusRingType)
    var focusRingType: UInt {
        return 1 //NSFocusRingTypeNone
    }
    #endif
}

Refuel answered 11/10, 2019 at 17:29 Comment(3)
You could also add this to a subclass if you don't want the behavior to be global etc.Refuel
Thanks - just what I was looking for!Humidifier
Thanks dude. This was driving me crazy! :DElagabalus
U
13

It helps to disable focus ring in all "view" classes in Catalyst

extension UIView {
    #if targetEnvironment(macCatalyst)
    @objc(_focusRingType)
    var focusRingType: UInt {
        return 1 //NSFocusRingTypeNone
    }
    #endif
}
Unreasoning answered 15/5, 2020 at 10:5 Comment(2)
This worked for me - solved a problem of bar buttons having a weird highlight on UIToolbar on CatalystSerotine
Is there an obj c equivalent for this?Poetess
P
2

This can also be done without any code in Interface Builder for specific buttons, if that fits your needs.

In the identity inspector, just set the user-defined run-time attribute to 1 like so:

enter image description here

Pipistrelle answered 23/7, 2020 at 10:13 Comment(0)
S
1

There is a private method _setFocusRingType: that appears to match the NSView API. I was able to use that to eliminate the focus ring, though this may not pass app review.

Use this at your own risk:

SEL selector = NSSelectorFromString(@"_setFocusRingType:");
NSMethodSignature *signature = [self.textView methodSignatureForSelector:selector];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
[invocation setSelector:selector];
NSUInteger arg = 1; // NSFocusRingTypeNone
[invocation setArgument:&arg atIndex:2];
[invocation invokeWithTarget:self.textView];

Hopefully we get a real solution from Apple.

Scrapbook answered 6/9, 2019 at 20:53 Comment(1)
Thanks I’ll take a look at this. It looks like Apple has removed the focus ring for all UI elements apart from UITextViews - including in Apple Catalyst apps.Humidifier
B
1

A slight improvement to Amerino's answer for greater flexibility and use in Storyboards:

@IBDesignable
class UITextViewCS: UITextView {
    @IBInspectable
    public var focusRing: UInt = 1 // 0-default, 1-None, 2-Exterior

    #if targetEnvironment(macCatalyst)
    @objc(_focusRingType)
    var focusRingType: UInt {
        guard [0, 1, 2].contains(focusRing) else { return 0 }
        return focusRing
    }
    #endif
}
Bord answered 16/4, 2020 at 17:34 Comment(0)
O
1

Please don't do this - this is a focus indicator for accessibility and is important for keyboard-only users.

Overcoat answered 19/12, 2020 at 23:13 Comment(1)
It would be nice to be able to change the colour to white instead of bright blue.Stour
A
0

The solution proposed here hasn't worked for me in situations where pressing tab adds a blue rectangle around entire views. I've seen it happen for the whole page of a UIPageViewController, for the cells of a UITableView and more. The only solution I was able to use to fix this is to override the key press.

#if targetEnvironment(macCatalyst)
open override func pressesBegan(_ presses: Set<UIPress>, with event: UIPressesEvent?) {
    guard let key = presses.first?.key else { return }
    switch key.keyCode {
    case .keyboardTab: break
    default: super.pressesBegan(presses, with: event)
    }
}
#endif
Aftereffect answered 19/1, 2023 at 21:42 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.