Sitemap
Better Programming

Advice for programmers.

How to Create a Draggable Floating View in Swift

5 min readDec 9, 2020

--

Man swimming underwater
Photo by will terra on Unsplash.

Long story short, on our latest project, our team has to implement a floating view that can be dragged freely on the screen. For those who have an Android development background, think of it as a floating action button lookalike, but instead of staying still on certain parts of the screen, it can be dragged freely!

For those who don’t, have a look at these images :

Draggable floating view
Draggable floating view

The floating view is circled in red, as shown in the two images above.

After conducting some research, we found out that it was not that hard to implement it from scratch on an iOS app. This tutorial will cover every single thing you need to create one.

Note: Since I have not found the official name for this component on Apple’s HIG, I will just continue to call it a draggable view in this article.

Preparation

Create an iOS project on Xcode, choose storyboard as the project’s interface and UIKit App Delegate as its life cycle. Then we end up with the usual Xcode starter code that you love so much:

Preparing the project

Then, go to Main.storyboard, add a UIView, and place it somewhere on the screen. You are free to decide where to put the view. For example, mine would be:

Placing the UIView
I made a red UIView with a 70pt width and height, aligning its trailing to a safe area by 16pt constraint and 300pt to the safe area’s bottom.

For simplicity’s sake, our draggable view will just be a circular view with some background colour on it. You could always go further by customizing it (e.g. by adding an image or something else).

What we have to do next is to connect our newly made view to the ViewController:

Connecting view to ViewController

If we run our application right now, we will see a little red box on the screen.

Let’s Get Started

In order to make our view draggable, we have to add a gesture recognizer called UIPanGestureRecognizer.

Apple’s explanation of UIPanGestureRecognizer is quite straightforward:

“A discrete gesture recognizer that interprets panning gestures.

Clients of this class can, in their action methods, query the UIPanGestureRecognizer object for the current translation of the gesture (translation(in:)) and the velocity of the translation (velocity(in:)).”

In simpler terms, this gesture can detect any translation that happens on the view, even enabling you to acquire its attributes such as velocity, final location, etc.

Let’s try to implement it on our ViewController:

Here’s the play-by-play :

  1. On line 16, we set a UIPanGestureRecognizer to our draggable view, where we also made a callback function for our recognizer (which is called every time the panning event is emitted).
  2. On the handler function, we simply print the gesture’s current location.

Try to run the application, then drag the view freely. Notice that although our view is not moving anywhere, we can see some kind of tuple on the debugging console, which is the current gesture location given in a coordinate. We’re on track to achieve our goal!

Now What?

Now that we have set a gesture recognizer, all we have to do is to update our view’s location. And since we already have our final location from the handler function, let’s just reuse that.

Add this code to our ViewController:

In the code above:

  1. On line 20, we get the gesture’s current location.
  2. On line 21, we assign the gesture view that sent the panning event (our draggable view) to a variable.
  3. We then update the view’s center with the current location retrieved before.

If you try to run the app again, our view is eventually draggable. Yay!

GIF of draggable view
Successfully made the view draggable

But something is not right: Although we successfully made our view draggable, we can drag it beyond the screen, which is not a normal behaviour.

Besides that, the normal draggable view has the ability to drag itself to the nearest side of the screen when the user stops dragging, while ours does not.

So what can we do about it?

Actually, to achieve this behaviour, we only need to do a little workaround. We can apply some logic when the user stops dragging. Add this code to our ViewController:

Here’s the logic :

  1. Starting on line 24, we add some logic to our handler to make the view have the behaviour we expect.
  2. We check whether the user has stopped dragging, then we do a comparison between the current view’s midX position and its superview’s width divided by half. We do the comparison to determine whether the current view is closer to its superview’s left or right side.
  3. If the view’s midX is greater than or equal to half the width of its superview (closer to the right side of the screen), we then update its X position as its superview width minus 40. This means that our view’s final location will be located at 40pt from its superview’s trailing.
  4. If it is closer to the left screen, we then update its X position to 40. This means that our view’s final location will be located 40pt away from its superview trailing.

Try to run the app. Voila! Our view now behaves as expected:

GIF of draggable view in action
Our draggable view in action

Conclusion

As you can see, creating a draggable view on iOS is not as hard as it seems. We only need to implement some logic regarding the final position of the view.

Happy coding!

--

--

Arya Surya
Arya Surya

Written by Arya Surya

Mostly writes about frontend, including but not limited to iOS and web development. Go follow @agustinustheoo for other stuff

Responses (1)