iOS Share Icon On UIButton

This post provides working examples of how to implement the iOS share icon, more formally known as the Action button icon, on a regular UIButton.

You might have come across the fact that the iOS Action icon is available as an iOS system button, but is only supported on a Navigation Bar or Toolbar.

I’ll walkthrough how to create two variants of a standard UIButton with the Action button icon, so that you can place it wherever you want in your app, and invoke a UIActivityViewController. One variant is a Standalone Button (UIButton) with just the icon, and the other is an Uber Style presentation such as what you see in the Uber app Free Rides screen.

Let’s get started creating the two iOS action or share button examples in a demo app, starting with a Single View Application template, and a project called iOSActionIconUIButton.

To overcome the fact that the Action image is not made available on a UIButton, and to use the exact same image that Apple uses, we can use the Artwork Extractor to extract all the images from iOS. This tool has not been updated in a few years, but as of writing this post, it still did the trick for me. You can find the extractor here on GitHub.

Note: If you are not comfortable using the Artwork Extractor and/or using the image from it, you can find one on the web, buy an icon pack, or create one yourself with a tool like Sketch app, which I’ve used to create a number of icons for various projects.

With the Artwork Extractor, I had to make a couple of obvious changes to remove compile errors when I most recently used this tool, but once everything was extracted into an iPhone 10.3.1 artwork directory, I found an Artwork bundle Assets directory, and in there a file named UIButtonBarAction@3x.png. I did not find the 1x and 2x files, so I simply duplicated the 3x and created the resized version of 1x and 2x, and added these files to the project in an images group.

With those added to the project, I created an Image Set named ActionIcon, being sure to set the Render As value to Template Image, so it can match the tint color of a UIButton.

There is one special note about Render As. When you create a UIButton in Interface Builder, and set it to a Type of Custom, you must have the rendering as Template in order for it to color the image according to the tint color, since Custom means a UIButton that has no style. Alternatively, you can set the type of button to System, and not use the rendering value as Template Image, and it will match the tint color. I just always use Template Image for icons that I want to match the tint color, regardless of whether specifying a System or Custom UIButton.

The next step is to setup the UIViewController to have an image to share via the UIActivityViewController, and create normal buttons before starting to turn them into iOS action buttons.

In the storyboard, I’ll add a UIStackView below the main View, and then inside it a UIImageView, as well as two instances of UIButton. I have an image in the project which I named ios-share-button-social.jpg, and you can see that below.

Although I won’t go into significant detail on the constraints and general setup, there are a few items to highlight.

First, I’ve specified the image for the Uber style button in the storyboard, but placing it in the right spot will be done via a subclass of UIButton, so in the storyboard it will not be right aligned.

Second, the UIImageView has a low content hugging priority and also a low compression resistance priority so that it will grow to take extra space, or shrink if there is not enough space available. I have a previous post dedicated to understanding content hugging and compression resistance if you are interested in a deeper discussion on those topics.

Third, I’ve specified the image name in the storyboard for both buttons, using ActionIcon from the image set.

Finally, I want the button that has only the image to be left aligned, so I’ve put it in a UIStackView along with a spacer view, and set the content hugging priority of the view to be less than that of the button. This means that the view will take all the extra space and the button will stay left aligned.

To achieve the desired functionality, I’ve created a subclass of UIButton that will configure the button to mimic the Uber style button for sharing. Here is the definition of the subclass, which I’ve called AlignedImageButton.

The code is fairly uneventful, with the required initializer for a storyboard, which calls the configure method to setup the button. I’ve added some comments to clarify parts of the configuration.

The text in the button is left aligned in Interface Builder. The key to positioning the action image just inside the right edge is to use imageEdgeInsets, and place the image relative to the left edge.

A border is applied to the button for aesthetics, in a darkGray color since that works well for this demo, and finally, I’ve added padding to the top and bottom of the button using contentEdgeInsets.

For this demo, I’ve triggered the configure method whenever bounds it set, since the placement of the image via imageEdgeInsets is dependent on the bounds of the button. This means that the image will be rendered with the correct placement in portrait or landscape, and with iPhone and iPad. If we didn’t factor in a bounds change, the image would be correct in portrait for iPhone, but would be incorrect for landscape and iPad. You can see this for yourself if you grab the demo app and comment out the configure method call.

With everything in place, you can handle button touches in the usual manner. In this case, the intent is to present a UIActivityViewController. You can also use the same code as I’ve shown, but with a different icon image, to provide support in an app for something other than presenting activities.

To complete this demo, I’ve implemented support for presenting the UIActivityViewController from either of the two buttons. Here is the UIViewController code.

You can see that I have one common share method that takes the button as a parameter. The reason for this is that iPad uses a UIPopoverPresentationController, and I want to anchor the UIActivityViewController screen based on the button location.

Just for illustration purposes, I’ve shown how to exclude some activity types from the UIActivityViewController screen.

There are other ways to accomplish what we’ve done here, and if you have implemented it differently or have suggestions, please leave a comment!

The demo app for this tutorial is here in GitHub.

Leave a Comment: