June 22, 2019

How to create a slide-over card using SwiftUI (like in Maps or Stocks)

A common UI pattern in iOS apps is a card of content that slides up over other content, either minimised or at half-screen or full-screen positions. (Take a look at the native Maps and Stocks apps.)

Here’s an example of how to implement that type of floating panel using SwiftUI.

Sliding the card over a mapSliding the card over a map

I’m pretty pumped about SwiftUI because every time I’ve tried making iOS apps before I’ve always ended up completely stuck managing the UI. Half of it was in the Storyboard, half was in long blocks of imperative code, and usually I’d just end up unplugging the computer when it took me two hours to display a list of images with the correct aspect ratios.

Meanwhile in React land I’ve been thinking now here’s how you write UI code”, and finally that declarative code-based pattern comes to iOS. I’m surprised I actually got this example working so quickly because I’ve never worked with animations or touch gestures before, but writing the SwiftUI code felt very natural and intuitive.

Here’s the code

The juicy bits are in SlideOverCard.swift, here are a few highlights:

  1. We declare a property called var content: () -> Content so that users of our view can use SlideOverCard { Text("Hey") } to embed their own custom views in the card. The part in braces is the closure that gets passed in as the content property in our view. This is the same pattern used by the built-in views like List and VStack.
  2. We use a DragGesture on the card to respond to the touch interactions. While the drag is in progress, we update the card’s position to follow the drag. Once the drag is finished, we decide where the card should end up based on its position and the final velocity.
  3. We set the new position for the card and use a spring animation to move the card there with a bit of bounce.

I’m a Swift noob so let me know if there are better ways to do some of this stuff.

SwiftUI iOS

Previous post
Manage your book inventory in Airtable by scanning barcodes and scraping Goodreads
Next post
Turning webpages into EPUBs on iOS using Scriptable, Shortcuts, and EpubPress