Preventing sweeping focus changes

My app has a view that's kept off-screen normally, but slides in from the left when you change focus into it. However, it's pretty easy to accidentally open this pane by making a sweeping slide to the left that overshoots a little. Is there a way to avoid that?


Ideally, I'd like to prevent a focus change if it's part of a gesture that has already caused other focus changes, but I don't see a way to detect that. The best trick I've found so far is to measure the time between focus changes and prevent it if it's too short, but I can't seem to find a sweet spot where a decelerating gesture is always rejected but a series of quick intentional ones isn't:


private let durationBetweenDiscreteFocusChanges = 0.3
<snip>
    private func locationOfView(view: UIView) -> ViewLocation {
        if (slidingViewController?.view).map(view.isDescendantOfView) ?? false {
            return .InSlidingView
        }
        else if (fixedViewController?.view).map(view.isDescendantOfView) ?? false {
            return .InFixedView
        }
  
        return .InNeitherView
    }
<snip>
    override func shouldUpdateFocusInContext(context: UIFocusUpdateContext) -> Bool {
        if NSDate() - dateOfLastFocusChange < durationBetweenDiscreteFocusChanges {
            if let previousFocusLocation = context.previouslyFocusedView.map(locationOfView), nextFocusLocation = context.nextFocusedView.map(locationOfView) {
                if previousFocusLocation != nextFocusLocation && previousFocusLocation != .InNeitherView && nextFocusLocation != .InNeitherView {
                    return false
                }
            }
        }
    
        return super.shouldUpdateFocusInContext(context)
    }


(dateOfLastFocusChange is updated in didUpdateFocus.)


Any better ideas? Should I file a radar?

How about excluding your offscreen element from focus until after, say, a 0.2-second delay from when the last onscreen element gets focused?

That's roughly what I'm doing now—recording the time of the last focus change, and not allowing focus to enter an offscreen element unless enough time has passed. The problem with that is that I can't find a good timespan—0.2 allows too many accidental focus changes, 0.5 locks out too many intentional ones, and numbers in between seem to mess up in both directions.

It sounds to me like all you need to do is a little bit of calibration work, fiddling around with the delay, until you find the right one. I really have no idea if this is possible or not (I'm not an iOS/tvOS expert by far), but you might want to look into trying to observe when the touch on the remote ends and use that to unlock focus for your offscreen element.

Maybe it would be more appropriate to not show your slide out panel just on focus, but to have a control to receive the focus which the user would then click to reveal the panel.

Preventing sweeping focus changes
 
 
Q