RMShapedImageView: A UIImageView subclass that ignores touches on transparent pixels

When using transparent PNG images in iOS development sometimes it’s useful to limit touches to where the image is not transparent.

Artwork from

You don’t want to interact with the bird if you touch the top left or bottom right corners.

For UIButton, there’s the most excellent OBShapedButton by Ole Begemann. At Robot Media we also needed this for UIImageView. After asking about this problem on StackOverflow and studying OBShapedButton, I decided to create RMShapedImageView and open-source it on GitHub.

RMShapedImageView is a UIImage subclass that overrides pointInside:withEvent:. This method is called to determine if a touch is inside the view. In our case, we only want to return YES if the corresponding pixels are not transparent (alpha > 0).

Usage

  1. Add RMShapedImageView.h and RMShapedImageView.m to your project.
  2. Replace your UIImageView with RMShapedImageView either in code or Interface Builder (by setting the Class of your UIImageView to RMShapedImageView).
  3. Profit! 

RMShapedImageView works with retina and non-retina images, as well as transformed views. It’s particularly useful is you’re using gesture recognisers. Currently supports only two content modes: UIViewContentModeScaleToFill and UIViewContentModeTopLeft. More will be added in time.

Configuration

Touches are inexact things and querying the alpha value of a single pixel might be too strict, even more so if the image is scaled down. Furthermore, if the image has shadows you might also want to ignore touches on them. RMShapedImageView has two configuration options to work around these problems:

  • shapedTransparentMaxAlpha: maximum alpha value that will be considered transparent. 0 by default.
  • shapedPixelTolerance: number of pixels around the point that will be examined. If at least one of them has alpha bigger than shapedTransparentMaxAlpha pointInside:withEvent: will return YES. 0 by default.

The project also includes a demo and bare-bones unit tests and is distributed under the Apache License 2.0. You’re more than welcome to fork it and improve.

One thought on “RMShapedImageView: A UIImageView subclass that ignores touches on transparent pixels

  1. David Landy

    Great code! Thanks for sharing it. I have been using this code in a project, and wanted to make one suggestion: in my program, I have about 30 views acting as buttons, and need to check them all very quickly (they are embedded in a scroll view, so users often tap and expect fast responses). I found the code too slow as it was, as was Ole Begemann’s excellent code.

    Fortunately, the happy ending: I easily modified RMShapedImageView to cache the full image data, and calculate just a box to check around the touch, rather than transforming and writing the image on each potential touch. This was a small but bearable memory hit, and drastically improved the responsiveness of the app. Just a suggestion, in case other people run into the same trouble!

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">