adamfootdev
adamfootdev

Reputation: 1195

Blue Highlighting / Focus Ring on Catalyst App

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?

Upvotes: 13

Views: 3412

Answers (8)

Tomeu Mascó
Tomeu Mascó

Reputation: 319

This solution is no longer working.

I found an alternative that does not require using private APIs. You just need to set focusEffect = nil.

Example:

extension UIView {

    func preventSetFocusRingForMac() {
    #if targetEnvironment(macCatalyst)
        focusEffect = nil
    #endif
    }
}

Upvotes: 0

CristianMoisei
CristianMoisei

Reputation: 2279

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

Upvotes: 0

user11145365
user11145365

Reputation: 313

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

Upvotes: 1

megastep
megastep

Reputation: 1275

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

Upvotes: 3

Dmitry Frantskevich
Dmitry Frantskevich

Reputation: 131

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
}

Upvotes: 13

Steig
Steig

Reputation: 173

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
}

Upvotes: 1

 Amerino
Amerino

Reputation: 389

In swift you can do


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

Upvotes: 21

Adam
Adam

Reputation: 5145

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.

Upvotes: 1

Related Questions