1992 stories
·
34 followers

Avoiding Conflicts with System Gestures at Screen Edges

1 Comment

If you rely on hiding the status bar to avoid conflicting with system gestures at the screen edges you will need to make some changes when updating for iOS 11. Apple no longer assumes your app wants to override system gestures at the edges when you hide the status bar. Instead you need to tell the system directly which edges you want first shot at handling gestures for.

The Problem with Gestures at the Screen Edges

A quick recap on the way this worked pre-iOS 11. Here is my App which shows a count in the center of the screen. You swipe up anywhere in the yellow play area to count up and down to count down.

iPhone 6S

I will skip the details (see the code) but the count works with two swipe gesture recognizers I added to the yellow view. The gestures are only recognized when they happen inside the yellow view which I constrain to half screen width and height.

I also allow a full screen mode which expands the yellow view to fill the screen. Swipes up or down then work anywhere on the screen. The problem is that it is easy for the user to accidentally trigger the control or notification centers when a swipe starts near the edge of the screen. Here is what happens when running on iOS 9 with a swipe up from the bottom edge.

control center

The system sees the swipe up gesture before our app and shows the control center.

Hiding the Status Bar

Before iOS 11 the way you tell the system not to grab gestures at the edge of the screen is to hide the status bar. Apple engineers made the assumption that if you are hiding the status bar you probably want to see gestures at the screen edges before the system.

Suppose we have a property in our view controller that stores the screen mode:

private var fullScreenMode: Bool = false

We set the property when the user changes the switch:

@IBAction func fullScreen(_ sender: UISwitch) {
  fullScreenMode = sender.isOn
}

To hide the status bar programmatically in our view controller I override prefersStatusBarHidden and return the full screen mode:

override var prefersStatusBarHidden: Bool {
  return fullScreenMode || super.prefersStatusBarHidden
}

Note that we also give the superclass (UIViewController) the chance to hide the status bar. This keeps the system default behaviour which hides the status bar for a compact height (iPhone in landscape).

There is one more step we need to do. When the user changes the screen mode we need to update our appearance and let the system know to handle the status bar. We can do that with a setter for our fullScreenMode property:

private var fullScreenMode: Bool = false {
  didSet {
    updateAppearance()
  }
}

The updateAppearance method takes care of updating the constraints to resize the yellow view (see the code for details). The key for the status bar handling is to call setNeedsStatusBarAppearanceUpdate to let the system know we have changed the value of prefersStatusBarHidden.

private func updateAppearance() {
    view.layoutIfNeeded()
    updateConstraints()
    UIView.animate(withDuration: 0.25) {
        self.setNeedsStatusBarAppearanceUpdate()
        self.view.layoutIfNeeded()
    }
}

Here is what it looks like when in full screen mode with the status bar hidden:

iPhone 6S full screen

The system now gives us the chance to handle up and down swipes at the system edges. Our app gets the first swipe up from the bottom edge. The system shows a small indicator to let the user know that they can still reach the control center with a second swipe up from the edge.

swipe up

Deferring System Gestures (iOS 11)

Apple has changed the way they handle gestures at the screen edges in iOS 11. Hiding the status bar in iOS 11 no longer causes the system to guess that you want to defer the system gestures. To keep the same behaviour we need to override preferredScreenEdgesDeferringSystemGestures in our view controller.

Since we are no longer forced to hide the status bar we can go back to the default handling for iOS 11:

override var prefersStatusBarHidden: Bool {
    if #available(iOS 11.0, *) {
        return super.prefersStatusBarHidden
    } else {
        return fullScreenMode || super.prefersStatusBarHidden
    }
}

Instead of hiding the status bar we override preferredScreenEdgesDeferringSystemGestures and return the edges where we want our gestures to fire first:

override func preferredScreenEdgesDeferringSystemGestures() -> UIRectEdge {
  return fullScreenMode ? [.bottom,.top] : UIRectEdge()
}

The return value is an option set of UIRectEdge constants. Possible values are .top, .left, .bottom, .right and .all. If we are in full screen mode we return .top and .bottom else we return the empty option set.

As with the status bar handling any time you change the value of preferredScreenEdgesDeferringSystemGestures you should let the system know. So for iOS 11 we call setNeedsUpdateOfScreenEdgesDeferringSystemGestures.

Let’s refactor that into a separate method that does the right thing for iOS 11 and falls back to updating the status bar for earlier versions:

private func updateDeferringSystemGestures() {
  if #available(iOS 11.0, *) {
    setNeedsUpdateOfScreenEdgesDeferringSystemGestures()
  } else {
    setNeedsStatusBarAppearanceUpdate()
  }
}

Our updateAppearance method then becomes:

private func updateAppearance() {
  view.layoutIfNeeded()
  updateConstraints()
  UIView.animate(withDuration: 0.25) {
    self.updateDeferringSystemGestures()
    self.view.layoutIfNeeded()
  }
}

We should now have an iOS 11 full screen mode with the status bar visible in regular size classes that defers system gestures on the top and bottom edges.

full screen with iOS 11

Note: This is a small but significant change in iOS 11. If you rely on hiding the status bar to use gestures at the screen edges you should update your app and override setNeedsUpdateOfScreenEdgesDeferringSystemGestures for iOS 11.

Example Code

If you want the full example Xcode project I used for this post you can find it in my GitHub repository:

More Details


Avoiding Conflicts with System Gestures at Screen Edges was originally posted 31 Jul 2017 on useyourloaf.com.

Want this direct to your inbox? Sign up and get my free iOS Size Classes guide.


Read the whole story
Share this story
Delete
1 public comment
sirshannon
14 hours ago
reply
newsblur search functionality just saved me an hour of googling.

Not a balloon

1 Share
Détour — A very short film by Michel Gondry, shot on an iPhone. In French, with English subtitles. (via Alas, a Blog)

Michael Gondry previously, 1, 2,
Read the whole story
Share this story
Delete

withoneeye: You may be fearless in this world. But there are...

1 Share




















withoneeye:

You may be fearless in this world. But there are other worlds.

Read the whole story
Share this story
Delete

samhumphries: sassyscans: Here it is! You CLAMORED for it and...

1 Share














samhumphries:

sassyscans:

Here it is! You CLAMORED for it and you got it, courtesy of Sassy fan Remyrogue - the Twin Peaks fashion spread from the October 1990 issue of Sassy Magazine.

PLEASE do not remove the Flickr attribution or re-upload this photo set. Remy LeBeau worked very hard to track down this magazine and share these images with us! I know there is very little I can do to stop you from doing these things but heed my words - stealing is not the Sassy Magazine way.

NEVER FORGET

Read the whole story
Share this story
Delete

Remembering Mike Brown and the Ferguson movement

1 Share

Three years ago today, I received a message from a friend in St. Louis who told me something was very wrong in Ferguson. The police had shot an eighteen-year old, and he had been lying on the street for hours. Police response was apparently tentative at best. I looked outside. Clear sunny day. No weather impediments. I quickly surmised that ...

The post Remembering Mike Brown and the Ferguson movement is from Eric Garland

Read the whole story
Share this story
Delete

What she says: I'm fine

1 Share
What she says: I'm fine
What she means: In Legally Blonde, Elle only gets accepted because she's hot and sent a video, but she had a 4.0 and got a 179 (out of 180) on her LSATS. Sure, her major was in Fashion Merchandising but that's a business major, and the fake school she was at was supposed to be UCLA so she had a business degree from a major college, probably went to a great high school, had a 4.0, and a 179 on the LSATS and at that point she would have been automatically accepted so why did they make it sound like she was such a bad risk? She even had leadership experience as president of a major chapter of what is apparently a huge sorority, since Delta Nus are shown as everything from cheerleaders to senators. Harvard should have been desperate to take her. She should have been able to get in if she turned in a cocktail napkin with her name written on it. So why make up the bullshit excuse of "multiculturalism" to justify letting in an extremely qualified and highly driven candidate just for laughs? Elle Woods deserved to go to Harvard and she earned that place with academic excellence and not by being hot.
Read the whole story
Share this story
Delete
Next Page of Stories