├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── RMShapedImageView.podspec ├── RMShapedImageView.xcodeproj ├── project.pbxproj └── xcshareddata │ └── xcschemes │ ├── RMShapedImageView.xcscheme │ └── RMShapedImageViewDemo.xcscheme ├── RMShapedImageView ├── RMShapedImageView-Prefix.pch ├── RMShapedImageView.h └── RMShapedImageView.m ├── RMShapedImageViewDemo ├── RMAppDelegate.h ├── RMAppDelegate.m ├── RMShapedImageViewDemo-Info.plist ├── RMShapedImageViewDemo-Prefix.pch ├── RMViewController.h ├── RMViewController.m ├── en.lproj │ ├── InfoPlist.strings │ └── RMViewController.xib ├── flower-no-retina.png ├── flower.png ├── flower@2x.png └── main.m └── RMShapedImageViewTests ├── RMShapedImageViewTests-Info.plist ├── RMShapedImageViewTests.m └── en.lproj └── InfoPlist.strings /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | .DS_Store 3 | build/ 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | *.xcworkspace 13 | !default.xcworkspace 14 | xcuserdata 15 | profile 16 | *.moved-aside 17 | DerivedData 18 | .idea/ 19 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: objective-c 2 | script: 3 | - xctool -project RMShapedImageView.xcodeproj -scheme 'RMShapedImageView' -configuration Release -sdk iphonesimulator test 4 | - xctool -project RMShapedImageView.xcodeproj -scheme 'RMShapedImageViewDemo' -configuration Release -sdk iphonesimulator 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2013 Robot Media SL 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at 4 | 5 | http://www.apache.org/licenses/LICENSE-2.0 6 | 7 | Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | RMShapedImageView 2 | ================= 3 | [![Build Status](https://travis-ci.org/robotmedia/RMShapedImageView.png)](https://travis-ci.org/robotmedia/RMShapedImageView) 4 | 5 | A `UIImageView` subclass that ignores touches on transparent pixels, based on [OBShapedButton](https://github.com/ole/OBShapedButton) by Ole Begemann. 6 | 7 | `RMShapedImageView` does it magic by overriding `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`). 8 | 9 | Usage 10 | ----- 11 | 12 | 1. Add [`RMShapedImageView.h`](https://github.com/robotmedia/RMShapedImageView/blob/master/RMShapedImageView/RMShapedImageView.h) and [`RMShapedImageView.m`](https://github.com/robotmedia/RMShapedImageView/blob/master/RMShapedImageView/RMShapedImageView.m) to your project. 13 | 2. Replace your `UIImageView` with `RMShapedImageView` either in code or Interface Builder (by setting the Class of your `UIImageView` to `RMShapedImageView`). 14 | 3. Profit! 15 | 16 | Configuration 17 | ------------- 18 | 19 | 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: 20 | 21 | * `shapedTransparentMaxAlpha`: maximum alpha value that will be considered transparent. 0 by default. 22 | * `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. 23 | 24 | License 25 | ------- 26 | 27 | Copyright 2013 [Robot Media SL](http://www.robotmedia.net) 28 | 29 | Licensed under the Apache License, Version 2.0 (the "License"); 30 | you may not use this file except in compliance with the License. 31 | You may obtain a copy of the License at 32 | 33 | http://www.apache.org/licenses/LICENSE-2.0 34 | 35 | Unless required by applicable law or agreed to in writing, software 36 | distributed under the License is distributed on an "AS IS" BASIS, 37 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 38 | See the License for the specific language governing permissions and 39 | limitations under the License. 40 | -------------------------------------------------------------------------------- /RMShapedImageView.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = "RMShapedImageView" 3 | s.version = "0.2" 4 | s.license = "Apache 2.0" 5 | s.summary = "A UIImageView subclass that ignores touches on transparent pixels." 6 | s.homepage = "https://github.com/robotmedia/RMShapedImageView" 7 | s.author = 'Hermes Pique' 8 | s.source = { :git => "https://github.com/robotmedia/RMShapedImageView.git", :tag => "0.2" } 9 | s.platform = :ios, '5.0' 10 | s.source_files = 'RMShapedImageView' 11 | s.frameworks = 'CoreGraphics', 'UIKit' 12 | s.requires_arc = true 13 | end 14 | -------------------------------------------------------------------------------- /RMShapedImageView.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | A0359CA617037537007DA6D3 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A07269B116D7ACA9001D35C4 /* UIKit.framework */; }; 11 | A0359CA717037546007DA6D3 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A07269B116D7ACA9001D35C4 /* UIKit.framework */; }; 12 | A07269B216D7ACA9001D35C4 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A07269B116D7ACA9001D35C4 /* UIKit.framework */; }; 13 | A07269B316D7ACC8001D35C4 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A0CED62416D6805800135D8B /* CoreGraphics.framework */; }; 14 | A07269B416D7ACD5001D35C4 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A0CED62416D6805800135D8B /* CoreGraphics.framework */; }; 15 | A07269B616D7ACFE001D35C4 /* flower@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = A07269B516D7ACFE001D35C4 /* flower@2x.png */; }; 16 | A07269B816D7AD1F001D35C4 /* flower-no-retina.png in Resources */ = {isa = PBXBuildFile; fileRef = A07269B716D7AD1F001D35C4 /* flower-no-retina.png */; }; 17 | A0CED5F616D66F2300135D8B /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A0CED5F516D66F2300135D8B /* Foundation.framework */; }; 18 | A0CED5FB16D66F2300135D8B /* RMShapedImageView.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = A0CED5FA16D66F2300135D8B /* RMShapedImageView.h */; }; 19 | A0CED5FD16D66F2300135D8B /* RMShapedImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = A0CED5FC16D66F2300135D8B /* RMShapedImageView.m */; }; 20 | A0CED60516D66F2300135D8B /* SenTestingKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A0CED60416D66F2300135D8B /* SenTestingKit.framework */; }; 21 | A0CED60816D66F2300135D8B /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A0CED5F516D66F2300135D8B /* Foundation.framework */; }; 22 | A0CED60B16D66F2300135D8B /* libRMShapedImageView.a in Frameworks */ = {isa = PBXBuildFile; fileRef = A0CED5F216D66F2300135D8B /* libRMShapedImageView.a */; }; 23 | A0CED61116D66F2300135D8B /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = A0CED60F16D66F2300135D8B /* InfoPlist.strings */; }; 24 | A0CED61416D66F2300135D8B /* RMShapedImageViewTests.m in Sources */ = {isa = PBXBuildFile; fileRef = A0CED61316D66F2300135D8B /* RMShapedImageViewTests.m */; }; 25 | A0CED62316D6805800135D8B /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A0CED5F516D66F2300135D8B /* Foundation.framework */; }; 26 | A0CED62516D6805800135D8B /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A0CED62416D6805800135D8B /* CoreGraphics.framework */; }; 27 | A0CED62B16D6805800135D8B /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = A0CED62916D6805800135D8B /* InfoPlist.strings */; }; 28 | A0CED62D16D6805800135D8B /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = A0CED62C16D6805800135D8B /* main.m */; }; 29 | A0CED63116D6805800135D8B /* RMAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = A0CED63016D6805800135D8B /* RMAppDelegate.m */; }; 30 | A0CED63A16D6805800135D8B /* RMViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = A0CED63916D6805800135D8B /* RMViewController.m */; }; 31 | A0CED63D16D6805800135D8B /* RMViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = A0CED63B16D6805800135D8B /* RMViewController.xib */; }; 32 | A0CED64316D680B200135D8B /* flower.png in Resources */ = {isa = PBXBuildFile; fileRef = A0CED64216D680B200135D8B /* flower.png */; }; 33 | A0CED64416D6842300135D8B /* RMShapedImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = A0CED5FC16D66F2300135D8B /* RMShapedImageView.m */; }; 34 | /* End PBXBuildFile section */ 35 | 36 | /* Begin PBXContainerItemProxy section */ 37 | A0CED60916D66F2300135D8B /* PBXContainerItemProxy */ = { 38 | isa = PBXContainerItemProxy; 39 | containerPortal = A0CED5EA16D66F2300135D8B /* Project object */; 40 | proxyType = 1; 41 | remoteGlobalIDString = A0CED5F116D66F2300135D8B; 42 | remoteInfo = RMShapedImageView; 43 | }; 44 | /* End PBXContainerItemProxy section */ 45 | 46 | /* Begin PBXCopyFilesBuildPhase section */ 47 | A0CED5F016D66F2300135D8B /* CopyFiles */ = { 48 | isa = PBXCopyFilesBuildPhase; 49 | buildActionMask = 2147483647; 50 | dstPath = "include/${PRODUCT_NAME}"; 51 | dstSubfolderSpec = 16; 52 | files = ( 53 | A0CED5FB16D66F2300135D8B /* RMShapedImageView.h in CopyFiles */, 54 | ); 55 | runOnlyForDeploymentPostprocessing = 0; 56 | }; 57 | /* End PBXCopyFilesBuildPhase section */ 58 | 59 | /* Begin PBXFileReference section */ 60 | A07269B116D7ACA9001D35C4 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 61 | A07269B516D7ACFE001D35C4 /* flower@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "flower@2x.png"; sourceTree = ""; }; 62 | A07269B716D7AD1F001D35C4 /* flower-no-retina.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "flower-no-retina.png"; sourceTree = ""; }; 63 | A0CED5F216D66F2300135D8B /* libRMShapedImageView.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRMShapedImageView.a; sourceTree = BUILT_PRODUCTS_DIR; }; 64 | A0CED5F516D66F2300135D8B /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 65 | A0CED5F916D66F2300135D8B /* RMShapedImageView-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "RMShapedImageView-Prefix.pch"; sourceTree = ""; }; 66 | A0CED5FA16D66F2300135D8B /* RMShapedImageView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RMShapedImageView.h; sourceTree = ""; }; 67 | A0CED5FC16D66F2300135D8B /* RMShapedImageView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RMShapedImageView.m; sourceTree = ""; }; 68 | A0CED60316D66F2300135D8B /* RMShapedImageViewTests.octest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RMShapedImageViewTests.octest; sourceTree = BUILT_PRODUCTS_DIR; }; 69 | A0CED60416D66F2300135D8B /* SenTestingKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SenTestingKit.framework; path = Library/Frameworks/SenTestingKit.framework; sourceTree = DEVELOPER_DIR; }; 70 | A0CED60E16D66F2300135D8B /* RMShapedImageViewTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "RMShapedImageViewTests-Info.plist"; sourceTree = ""; }; 71 | A0CED61016D66F2300135D8B /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 72 | A0CED61316D66F2300135D8B /* RMShapedImageViewTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RMShapedImageViewTests.m; sourceTree = ""; }; 73 | A0CED62116D6805700135D8B /* RMShapedImageViewDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = RMShapedImageViewDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 74 | A0CED62416D6805800135D8B /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 75 | A0CED62816D6805800135D8B /* RMShapedImageViewDemo-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "RMShapedImageViewDemo-Info.plist"; sourceTree = ""; }; 76 | A0CED62A16D6805800135D8B /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 77 | A0CED62C16D6805800135D8B /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 78 | A0CED62E16D6805800135D8B /* RMShapedImageViewDemo-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "RMShapedImageViewDemo-Prefix.pch"; sourceTree = ""; }; 79 | A0CED62F16D6805800135D8B /* RMAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RMAppDelegate.h; sourceTree = ""; }; 80 | A0CED63016D6805800135D8B /* RMAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RMAppDelegate.m; sourceTree = ""; }; 81 | A0CED63816D6805800135D8B /* RMViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RMViewController.h; sourceTree = ""; }; 82 | A0CED63916D6805800135D8B /* RMViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RMViewController.m; sourceTree = ""; }; 83 | A0CED63C16D6805800135D8B /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/RMViewController.xib; sourceTree = ""; }; 84 | A0CED64216D680B200135D8B /* flower.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = flower.png; sourceTree = ""; }; 85 | /* End PBXFileReference section */ 86 | 87 | /* Begin PBXFrameworksBuildPhase section */ 88 | A0CED5EF16D66F2300135D8B /* Frameworks */ = { 89 | isa = PBXFrameworksBuildPhase; 90 | buildActionMask = 2147483647; 91 | files = ( 92 | A07269B316D7ACC8001D35C4 /* CoreGraphics.framework in Frameworks */, 93 | A07269B216D7ACA9001D35C4 /* UIKit.framework in Frameworks */, 94 | A0CED5F616D66F2300135D8B /* Foundation.framework in Frameworks */, 95 | ); 96 | runOnlyForDeploymentPostprocessing = 0; 97 | }; 98 | A0CED5FF16D66F2300135D8B /* Frameworks */ = { 99 | isa = PBXFrameworksBuildPhase; 100 | buildActionMask = 2147483647; 101 | files = ( 102 | A0359CA717037546007DA6D3 /* UIKit.framework in Frameworks */, 103 | A07269B416D7ACD5001D35C4 /* CoreGraphics.framework in Frameworks */, 104 | A0CED60516D66F2300135D8B /* SenTestingKit.framework in Frameworks */, 105 | A0CED60816D66F2300135D8B /* Foundation.framework in Frameworks */, 106 | A0CED60B16D66F2300135D8B /* libRMShapedImageView.a in Frameworks */, 107 | ); 108 | runOnlyForDeploymentPostprocessing = 0; 109 | }; 110 | A0CED61E16D6805700135D8B /* Frameworks */ = { 111 | isa = PBXFrameworksBuildPhase; 112 | buildActionMask = 2147483647; 113 | files = ( 114 | A0359CA617037537007DA6D3 /* UIKit.framework in Frameworks */, 115 | A0CED62316D6805800135D8B /* Foundation.framework in Frameworks */, 116 | A0CED62516D6805800135D8B /* CoreGraphics.framework in Frameworks */, 117 | ); 118 | runOnlyForDeploymentPostprocessing = 0; 119 | }; 120 | /* End PBXFrameworksBuildPhase section */ 121 | 122 | /* Begin PBXGroup section */ 123 | A0CED5E916D66F2300135D8B = { 124 | isa = PBXGroup; 125 | children = ( 126 | A0CED5F716D66F2300135D8B /* RMShapedImageView */, 127 | A0CED60C16D66F2300135D8B /* RMShapedImageViewTests */, 128 | A0CED62616D6805800135D8B /* RMShapedImageViewDemo */, 129 | A0CED5F416D66F2300135D8B /* Frameworks */, 130 | A0CED5F316D66F2300135D8B /* Products */, 131 | ); 132 | sourceTree = ""; 133 | }; 134 | A0CED5F316D66F2300135D8B /* Products */ = { 135 | isa = PBXGroup; 136 | children = ( 137 | A0CED5F216D66F2300135D8B /* libRMShapedImageView.a */, 138 | A0CED60316D66F2300135D8B /* RMShapedImageViewTests.octest */, 139 | A0CED62116D6805700135D8B /* RMShapedImageViewDemo.app */, 140 | ); 141 | name = Products; 142 | sourceTree = ""; 143 | }; 144 | A0CED5F416D66F2300135D8B /* Frameworks */ = { 145 | isa = PBXGroup; 146 | children = ( 147 | A0CED62416D6805800135D8B /* CoreGraphics.framework */, 148 | A0CED5F516D66F2300135D8B /* Foundation.framework */, 149 | A0CED60416D66F2300135D8B /* SenTestingKit.framework */, 150 | A07269B116D7ACA9001D35C4 /* UIKit.framework */, 151 | ); 152 | name = Frameworks; 153 | sourceTree = ""; 154 | }; 155 | A0CED5F716D66F2300135D8B /* RMShapedImageView */ = { 156 | isa = PBXGroup; 157 | children = ( 158 | A0CED5FA16D66F2300135D8B /* RMShapedImageView.h */, 159 | A0CED5FC16D66F2300135D8B /* RMShapedImageView.m */, 160 | A0CED5F816D66F2300135D8B /* Supporting Files */, 161 | ); 162 | path = RMShapedImageView; 163 | sourceTree = ""; 164 | }; 165 | A0CED5F816D66F2300135D8B /* Supporting Files */ = { 166 | isa = PBXGroup; 167 | children = ( 168 | A0CED5F916D66F2300135D8B /* RMShapedImageView-Prefix.pch */, 169 | ); 170 | name = "Supporting Files"; 171 | sourceTree = ""; 172 | }; 173 | A0CED60C16D66F2300135D8B /* RMShapedImageViewTests */ = { 174 | isa = PBXGroup; 175 | children = ( 176 | A0CED61316D66F2300135D8B /* RMShapedImageViewTests.m */, 177 | A0CED60D16D66F2300135D8B /* Supporting Files */, 178 | ); 179 | path = RMShapedImageViewTests; 180 | sourceTree = ""; 181 | }; 182 | A0CED60D16D66F2300135D8B /* Supporting Files */ = { 183 | isa = PBXGroup; 184 | children = ( 185 | A0CED60E16D66F2300135D8B /* RMShapedImageViewTests-Info.plist */, 186 | A0CED60F16D66F2300135D8B /* InfoPlist.strings */, 187 | ); 188 | name = "Supporting Files"; 189 | sourceTree = ""; 190 | }; 191 | A0CED62616D6805800135D8B /* RMShapedImageViewDemo */ = { 192 | isa = PBXGroup; 193 | children = ( 194 | A07269B716D7AD1F001D35C4 /* flower-no-retina.png */, 195 | A07269B516D7ACFE001D35C4 /* flower@2x.png */, 196 | A0CED64216D680B200135D8B /* flower.png */, 197 | A0CED62F16D6805800135D8B /* RMAppDelegate.h */, 198 | A0CED63016D6805800135D8B /* RMAppDelegate.m */, 199 | A0CED63816D6805800135D8B /* RMViewController.h */, 200 | A0CED63916D6805800135D8B /* RMViewController.m */, 201 | A0CED63B16D6805800135D8B /* RMViewController.xib */, 202 | A0CED62716D6805800135D8B /* Supporting Files */, 203 | ); 204 | path = RMShapedImageViewDemo; 205 | sourceTree = ""; 206 | }; 207 | A0CED62716D6805800135D8B /* Supporting Files */ = { 208 | isa = PBXGroup; 209 | children = ( 210 | A0CED62816D6805800135D8B /* RMShapedImageViewDemo-Info.plist */, 211 | A0CED62916D6805800135D8B /* InfoPlist.strings */, 212 | A0CED62C16D6805800135D8B /* main.m */, 213 | A0CED62E16D6805800135D8B /* RMShapedImageViewDemo-Prefix.pch */, 214 | ); 215 | name = "Supporting Files"; 216 | sourceTree = ""; 217 | }; 218 | /* End PBXGroup section */ 219 | 220 | /* Begin PBXNativeTarget section */ 221 | A0CED5F116D66F2300135D8B /* RMShapedImageView */ = { 222 | isa = PBXNativeTarget; 223 | buildConfigurationList = A0CED61716D66F2300135D8B /* Build configuration list for PBXNativeTarget "RMShapedImageView" */; 224 | buildPhases = ( 225 | A0CED5EE16D66F2300135D8B /* Sources */, 226 | A0CED5EF16D66F2300135D8B /* Frameworks */, 227 | A0CED5F016D66F2300135D8B /* CopyFiles */, 228 | ); 229 | buildRules = ( 230 | ); 231 | dependencies = ( 232 | ); 233 | name = RMShapedImageView; 234 | productName = RMShapedImageView; 235 | productReference = A0CED5F216D66F2300135D8B /* libRMShapedImageView.a */; 236 | productType = "com.apple.product-type.library.static"; 237 | }; 238 | A0CED60216D66F2300135D8B /* RMShapedImageViewTests */ = { 239 | isa = PBXNativeTarget; 240 | buildConfigurationList = A0CED61A16D66F2300135D8B /* Build configuration list for PBXNativeTarget "RMShapedImageViewTests" */; 241 | buildPhases = ( 242 | A0CED5FE16D66F2300135D8B /* Sources */, 243 | A0CED5FF16D66F2300135D8B /* Frameworks */, 244 | A0CED60016D66F2300135D8B /* Resources */, 245 | A0CED60116D66F2300135D8B /* ShellScript */, 246 | ); 247 | buildRules = ( 248 | ); 249 | dependencies = ( 250 | A0CED60A16D66F2300135D8B /* PBXTargetDependency */, 251 | ); 252 | name = RMShapedImageViewTests; 253 | productName = RMShapedImageViewTests; 254 | productReference = A0CED60316D66F2300135D8B /* RMShapedImageViewTests.octest */; 255 | productType = "com.apple.product-type.bundle"; 256 | }; 257 | A0CED62016D6805700135D8B /* RMShapedImageViewDemo */ = { 258 | isa = PBXNativeTarget; 259 | buildConfigurationList = A0CED63E16D6805800135D8B /* Build configuration list for PBXNativeTarget "RMShapedImageViewDemo" */; 260 | buildPhases = ( 261 | A0CED61D16D6805700135D8B /* Sources */, 262 | A0CED61E16D6805700135D8B /* Frameworks */, 263 | A0CED61F16D6805700135D8B /* Resources */, 264 | ); 265 | buildRules = ( 266 | ); 267 | dependencies = ( 268 | ); 269 | name = RMShapedImageViewDemo; 270 | productName = RMShapedImageViewDemo; 271 | productReference = A0CED62116D6805700135D8B /* RMShapedImageViewDemo.app */; 272 | productType = "com.apple.product-type.application"; 273 | }; 274 | /* End PBXNativeTarget section */ 275 | 276 | /* Begin PBXProject section */ 277 | A0CED5EA16D66F2300135D8B /* Project object */ = { 278 | isa = PBXProject; 279 | attributes = { 280 | LastUpgradeCheck = 0460; 281 | ORGANIZATIONNAME = "Robot Media"; 282 | }; 283 | buildConfigurationList = A0CED5ED16D66F2300135D8B /* Build configuration list for PBXProject "RMShapedImageView" */; 284 | compatibilityVersion = "Xcode 3.2"; 285 | developmentRegion = English; 286 | hasScannedForEncodings = 0; 287 | knownRegions = ( 288 | en, 289 | ); 290 | mainGroup = A0CED5E916D66F2300135D8B; 291 | productRefGroup = A0CED5F316D66F2300135D8B /* Products */; 292 | projectDirPath = ""; 293 | projectRoot = ""; 294 | targets = ( 295 | A0CED5F116D66F2300135D8B /* RMShapedImageView */, 296 | A0CED60216D66F2300135D8B /* RMShapedImageViewTests */, 297 | A0CED62016D6805700135D8B /* RMShapedImageViewDemo */, 298 | ); 299 | }; 300 | /* End PBXProject section */ 301 | 302 | /* Begin PBXResourcesBuildPhase section */ 303 | A0CED60016D66F2300135D8B /* Resources */ = { 304 | isa = PBXResourcesBuildPhase; 305 | buildActionMask = 2147483647; 306 | files = ( 307 | A0CED61116D66F2300135D8B /* InfoPlist.strings in Resources */, 308 | ); 309 | runOnlyForDeploymentPostprocessing = 0; 310 | }; 311 | A0CED61F16D6805700135D8B /* Resources */ = { 312 | isa = PBXResourcesBuildPhase; 313 | buildActionMask = 2147483647; 314 | files = ( 315 | A0CED62B16D6805800135D8B /* InfoPlist.strings in Resources */, 316 | A0CED63D16D6805800135D8B /* RMViewController.xib in Resources */, 317 | A0CED64316D680B200135D8B /* flower.png in Resources */, 318 | A07269B616D7ACFE001D35C4 /* flower@2x.png in Resources */, 319 | A07269B816D7AD1F001D35C4 /* flower-no-retina.png in Resources */, 320 | ); 321 | runOnlyForDeploymentPostprocessing = 0; 322 | }; 323 | /* End PBXResourcesBuildPhase section */ 324 | 325 | /* Begin PBXShellScriptBuildPhase section */ 326 | A0CED60116D66F2300135D8B /* ShellScript */ = { 327 | isa = PBXShellScriptBuildPhase; 328 | buildActionMask = 2147483647; 329 | files = ( 330 | ); 331 | inputPaths = ( 332 | ); 333 | outputPaths = ( 334 | ); 335 | runOnlyForDeploymentPostprocessing = 0; 336 | shellPath = /bin/sh; 337 | shellScript = "# Run the unit tests in this test bundle.\n\"${SYSTEM_DEVELOPER_DIR}/Tools/RunUnitTests\"\n"; 338 | }; 339 | /* End PBXShellScriptBuildPhase section */ 340 | 341 | /* Begin PBXSourcesBuildPhase section */ 342 | A0CED5EE16D66F2300135D8B /* Sources */ = { 343 | isa = PBXSourcesBuildPhase; 344 | buildActionMask = 2147483647; 345 | files = ( 346 | A0CED5FD16D66F2300135D8B /* RMShapedImageView.m in Sources */, 347 | ); 348 | runOnlyForDeploymentPostprocessing = 0; 349 | }; 350 | A0CED5FE16D66F2300135D8B /* Sources */ = { 351 | isa = PBXSourcesBuildPhase; 352 | buildActionMask = 2147483647; 353 | files = ( 354 | A0CED61416D66F2300135D8B /* RMShapedImageViewTests.m in Sources */, 355 | ); 356 | runOnlyForDeploymentPostprocessing = 0; 357 | }; 358 | A0CED61D16D6805700135D8B /* Sources */ = { 359 | isa = PBXSourcesBuildPhase; 360 | buildActionMask = 2147483647; 361 | files = ( 362 | A0CED62D16D6805800135D8B /* main.m in Sources */, 363 | A0CED63116D6805800135D8B /* RMAppDelegate.m in Sources */, 364 | A0CED63A16D6805800135D8B /* RMViewController.m in Sources */, 365 | A0CED64416D6842300135D8B /* RMShapedImageView.m in Sources */, 366 | ); 367 | runOnlyForDeploymentPostprocessing = 0; 368 | }; 369 | /* End PBXSourcesBuildPhase section */ 370 | 371 | /* Begin PBXTargetDependency section */ 372 | A0CED60A16D66F2300135D8B /* PBXTargetDependency */ = { 373 | isa = PBXTargetDependency; 374 | target = A0CED5F116D66F2300135D8B /* RMShapedImageView */; 375 | targetProxy = A0CED60916D66F2300135D8B /* PBXContainerItemProxy */; 376 | }; 377 | /* End PBXTargetDependency section */ 378 | 379 | /* Begin PBXVariantGroup section */ 380 | A0CED60F16D66F2300135D8B /* InfoPlist.strings */ = { 381 | isa = PBXVariantGroup; 382 | children = ( 383 | A0CED61016D66F2300135D8B /* en */, 384 | ); 385 | name = InfoPlist.strings; 386 | sourceTree = ""; 387 | }; 388 | A0CED62916D6805800135D8B /* InfoPlist.strings */ = { 389 | isa = PBXVariantGroup; 390 | children = ( 391 | A0CED62A16D6805800135D8B /* en */, 392 | ); 393 | name = InfoPlist.strings; 394 | sourceTree = ""; 395 | }; 396 | A0CED63B16D6805800135D8B /* RMViewController.xib */ = { 397 | isa = PBXVariantGroup; 398 | children = ( 399 | A0CED63C16D6805800135D8B /* en */, 400 | ); 401 | name = RMViewController.xib; 402 | sourceTree = ""; 403 | }; 404 | /* End PBXVariantGroup section */ 405 | 406 | /* Begin XCBuildConfiguration section */ 407 | A0CED61516D66F2300135D8B /* Debug */ = { 408 | isa = XCBuildConfiguration; 409 | buildSettings = { 410 | ALWAYS_SEARCH_USER_PATHS = NO; 411 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 412 | CLANG_CXX_LIBRARY = "libc++"; 413 | CLANG_ENABLE_OBJC_ARC = YES; 414 | CLANG_WARN_CONSTANT_CONVERSION = YES; 415 | CLANG_WARN_EMPTY_BODY = YES; 416 | CLANG_WARN_ENUM_CONVERSION = YES; 417 | CLANG_WARN_INT_CONVERSION = YES; 418 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 419 | COPY_PHASE_STRIP = NO; 420 | GCC_C_LANGUAGE_STANDARD = gnu99; 421 | GCC_DYNAMIC_NO_PIC = NO; 422 | GCC_OPTIMIZATION_LEVEL = 0; 423 | GCC_PREPROCESSOR_DEFINITIONS = ( 424 | "DEBUG=1", 425 | "$(inherited)", 426 | ); 427 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 428 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 429 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 430 | GCC_WARN_UNUSED_VARIABLE = YES; 431 | IPHONEOS_DEPLOYMENT_TARGET = 6.1; 432 | ONLY_ACTIVE_ARCH = YES; 433 | SDKROOT = iphoneos; 434 | }; 435 | name = Debug; 436 | }; 437 | A0CED61616D66F2300135D8B /* Release */ = { 438 | isa = XCBuildConfiguration; 439 | buildSettings = { 440 | ALWAYS_SEARCH_USER_PATHS = NO; 441 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 442 | CLANG_CXX_LIBRARY = "libc++"; 443 | CLANG_ENABLE_OBJC_ARC = YES; 444 | CLANG_WARN_CONSTANT_CONVERSION = YES; 445 | CLANG_WARN_EMPTY_BODY = YES; 446 | CLANG_WARN_ENUM_CONVERSION = YES; 447 | CLANG_WARN_INT_CONVERSION = YES; 448 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 449 | COPY_PHASE_STRIP = YES; 450 | GCC_C_LANGUAGE_STANDARD = gnu99; 451 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 452 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 453 | GCC_WARN_UNUSED_VARIABLE = YES; 454 | IPHONEOS_DEPLOYMENT_TARGET = 6.1; 455 | SDKROOT = iphoneos; 456 | VALIDATE_PRODUCT = YES; 457 | }; 458 | name = Release; 459 | }; 460 | A0CED61816D66F2300135D8B /* Debug */ = { 461 | isa = XCBuildConfiguration; 462 | buildSettings = { 463 | DSTROOT = /tmp/RMShapedImageView.dst; 464 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 465 | GCC_PREFIX_HEADER = "RMShapedImageView/RMShapedImageView-Prefix.pch"; 466 | OTHER_LDFLAGS = "-ObjC"; 467 | PRODUCT_NAME = "$(TARGET_NAME)"; 468 | SKIP_INSTALL = YES; 469 | }; 470 | name = Debug; 471 | }; 472 | A0CED61916D66F2300135D8B /* Release */ = { 473 | isa = XCBuildConfiguration; 474 | buildSettings = { 475 | DSTROOT = /tmp/RMShapedImageView.dst; 476 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 477 | GCC_PREFIX_HEADER = "RMShapedImageView/RMShapedImageView-Prefix.pch"; 478 | OTHER_LDFLAGS = "-ObjC"; 479 | PRODUCT_NAME = "$(TARGET_NAME)"; 480 | SKIP_INSTALL = YES; 481 | }; 482 | name = Release; 483 | }; 484 | A0CED61B16D66F2300135D8B /* Debug */ = { 485 | isa = XCBuildConfiguration; 486 | buildSettings = { 487 | FRAMEWORK_SEARCH_PATHS = ( 488 | "\"$(SDKROOT)/Developer/Library/Frameworks\"", 489 | "\"$(DEVELOPER_LIBRARY_DIR)/Frameworks\"", 490 | ); 491 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 492 | GCC_PREFIX_HEADER = "RMShapedImageView/RMShapedImageView-Prefix.pch"; 493 | INFOPLIST_FILE = "RMShapedImageViewTests/RMShapedImageViewTests-Info.plist"; 494 | PRODUCT_NAME = "$(TARGET_NAME)"; 495 | WRAPPER_EXTENSION = octest; 496 | }; 497 | name = Debug; 498 | }; 499 | A0CED61C16D66F2300135D8B /* Release */ = { 500 | isa = XCBuildConfiguration; 501 | buildSettings = { 502 | FRAMEWORK_SEARCH_PATHS = ( 503 | "\"$(SDKROOT)/Developer/Library/Frameworks\"", 504 | "\"$(DEVELOPER_LIBRARY_DIR)/Frameworks\"", 505 | ); 506 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 507 | GCC_PREFIX_HEADER = "RMShapedImageView/RMShapedImageView-Prefix.pch"; 508 | INFOPLIST_FILE = "RMShapedImageViewTests/RMShapedImageViewTests-Info.plist"; 509 | PRODUCT_NAME = "$(TARGET_NAME)"; 510 | WRAPPER_EXTENSION = octest; 511 | }; 512 | name = Release; 513 | }; 514 | A0CED63F16D6805800135D8B /* Debug */ = { 515 | isa = XCBuildConfiguration; 516 | buildSettings = { 517 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 518 | FRAMEWORK_SEARCH_PATHS = ( 519 | "$(inherited)", 520 | "\"$(SYSTEM_APPS_DIR)/Xcode.app/Contents/Developer/Library/Frameworks\"", 521 | ); 522 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 523 | GCC_PREFIX_HEADER = "RMShapedImageViewDemo/RMShapedImageViewDemo-Prefix.pch"; 524 | INFOPLIST_FILE = "RMShapedImageViewDemo/RMShapedImageViewDemo-Info.plist"; 525 | PRODUCT_NAME = "$(TARGET_NAME)"; 526 | WRAPPER_EXTENSION = app; 527 | }; 528 | name = Debug; 529 | }; 530 | A0CED64016D6805800135D8B /* Release */ = { 531 | isa = XCBuildConfiguration; 532 | buildSettings = { 533 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 534 | FRAMEWORK_SEARCH_PATHS = ( 535 | "$(inherited)", 536 | "\"$(SYSTEM_APPS_DIR)/Xcode.app/Contents/Developer/Library/Frameworks\"", 537 | ); 538 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 539 | GCC_PREFIX_HEADER = "RMShapedImageViewDemo/RMShapedImageViewDemo-Prefix.pch"; 540 | INFOPLIST_FILE = "RMShapedImageViewDemo/RMShapedImageViewDemo-Info.plist"; 541 | OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; 542 | PRODUCT_NAME = "$(TARGET_NAME)"; 543 | WRAPPER_EXTENSION = app; 544 | }; 545 | name = Release; 546 | }; 547 | /* End XCBuildConfiguration section */ 548 | 549 | /* Begin XCConfigurationList section */ 550 | A0CED5ED16D66F2300135D8B /* Build configuration list for PBXProject "RMShapedImageView" */ = { 551 | isa = XCConfigurationList; 552 | buildConfigurations = ( 553 | A0CED61516D66F2300135D8B /* Debug */, 554 | A0CED61616D66F2300135D8B /* Release */, 555 | ); 556 | defaultConfigurationIsVisible = 0; 557 | defaultConfigurationName = Release; 558 | }; 559 | A0CED61716D66F2300135D8B /* Build configuration list for PBXNativeTarget "RMShapedImageView" */ = { 560 | isa = XCConfigurationList; 561 | buildConfigurations = ( 562 | A0CED61816D66F2300135D8B /* Debug */, 563 | A0CED61916D66F2300135D8B /* Release */, 564 | ); 565 | defaultConfigurationIsVisible = 0; 566 | defaultConfigurationName = Release; 567 | }; 568 | A0CED61A16D66F2300135D8B /* Build configuration list for PBXNativeTarget "RMShapedImageViewTests" */ = { 569 | isa = XCConfigurationList; 570 | buildConfigurations = ( 571 | A0CED61B16D66F2300135D8B /* Debug */, 572 | A0CED61C16D66F2300135D8B /* Release */, 573 | ); 574 | defaultConfigurationIsVisible = 0; 575 | defaultConfigurationName = Release; 576 | }; 577 | A0CED63E16D6805800135D8B /* Build configuration list for PBXNativeTarget "RMShapedImageViewDemo" */ = { 578 | isa = XCConfigurationList; 579 | buildConfigurations = ( 580 | A0CED63F16D6805800135D8B /* Debug */, 581 | A0CED64016D6805800135D8B /* Release */, 582 | ); 583 | defaultConfigurationIsVisible = 0; 584 | defaultConfigurationName = Release; 585 | }; 586 | /* End XCConfigurationList section */ 587 | }; 588 | rootObject = A0CED5EA16D66F2300135D8B /* Project object */; 589 | } 590 | -------------------------------------------------------------------------------- /RMShapedImageView.xcodeproj/xcshareddata/xcschemes/RMShapedImageView.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 52 | 53 | 54 | 55 | 61 | 62 | 64 | 65 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /RMShapedImageView.xcodeproj/xcshareddata/xcschemes/RMShapedImageViewDemo.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 51 | 52 | 58 | 59 | 60 | 61 | 62 | 63 | 69 | 70 | 76 | 77 | 78 | 79 | 81 | 82 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /RMShapedImageView/RMShapedImageView-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'RMShapedImageView' target in the 'RMShapedImageView' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #endif 8 | -------------------------------------------------------------------------------- /RMShapedImageView/RMShapedImageView.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013 Robot Media SL (http://www.robotmedia.net) 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | // 17 | // RMShapedImageView.h 18 | // RMShapedImageView 19 | // 20 | // Created by Hermes Pique on 2/21/13. 21 | // Copyright (c) 2013 Robot Media. All rights reserved. 22 | // 23 | 24 | #import 25 | 26 | /** A UIImageView subclass that ignores touches on transparent pixels, based on OBShapedButton by Ole Begemann. 27 | 28 | RMShapedImageView does it magic by overriding 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. 29 | */ 30 | @interface RMShapedImageView : UIImageView 31 | 32 | /** 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. 33 | */ 34 | @property (nonatomic, assign) NSUInteger shapedPixelTolerance; 35 | 36 | /** Maximum alpha value that will be considered transparent. 0 by default. 37 | */ 38 | @property (nonatomic, assign) CGFloat shapedTransparentMaxAlpha; 39 | 40 | /** Returns YES if shape is supported, NO otherwise. If shape is not supported pointInside:withEvent: will return the same than super. 41 | */ 42 | @property (nonatomic, readonly) BOOL shapedSupported; 43 | 44 | @end 45 | -------------------------------------------------------------------------------- /RMShapedImageView/RMShapedImageView.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013 Robot Media SL (http://www.robotmedia.net) 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | // 17 | // RMShapedImageView.m 18 | // RMShapedImageView 19 | // 20 | // Created by Hermes Pique on 2/21/13. 21 | // Copyright (c) 2013 Robot Media. All rights reserved. 22 | // 23 | 24 | #import "RMShapedImageView.h" 25 | 26 | @implementation RMShapedImageView { 27 | CGPoint _previousPoint; 28 | BOOL _previousPointInsideResult; 29 | } 30 | 31 | #pragma mark - UIView 32 | 33 | - (id)initWithFrame:(CGRect)frame 34 | { 35 | self = [super initWithFrame:frame]; 36 | if (self) { 37 | [self initHelper]; 38 | } 39 | return self; 40 | } 41 | - (id)initWithCoder:(NSCoder *)decoder 42 | { 43 | self = [super initWithCoder:decoder]; 44 | if (self) { 45 | [self initHelper]; 46 | } 47 | return self; 48 | } 49 | 50 | - (void) initHelper 51 | { 52 | _previousPoint = CGPointMake(CGFLOAT_MIN, CGFLOAT_MIN); 53 | } 54 | 55 | - (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event 56 | { 57 | BOOL superResult = [super pointInside:point withEvent:event]; 58 | if (!superResult) return NO; 59 | if (!self.shapedSupported) return YES; 60 | if (!self.image) return NO; 61 | if (CGPointEqualToPoint(point, _previousPoint)) return _previousPointInsideResult; 62 | 63 | _previousPoint = point; 64 | 65 | // Image might be scaled or translated due to contentMode. We want to convert the view point into an image point first. 66 | CGPoint imagePoint = [self imagePointFromViewPoint:point]; 67 | 68 | BOOL result = [self isAlphaVisibleAtImagePoint:imagePoint]; 69 | _previousPointInsideResult = result; 70 | return result; 71 | } 72 | 73 | #pragma mark - UIImageView 74 | 75 | - (void)setImage:(UIImage *)image 76 | { 77 | [super setImage:image]; 78 | [self resetPointInsideCache]; 79 | } 80 | 81 | #pragma mark - RMShapedImageView 82 | 83 | - (BOOL) shapedSupported 84 | { 85 | if (!self.image) return YES; 86 | switch (self.contentMode) 87 | { 88 | case UIViewContentModeScaleToFill: 89 | case UIViewContentModeTopLeft: 90 | return YES; 91 | default: 92 | return NO; 93 | } 94 | } 95 | 96 | #pragma mark - Private 97 | 98 | - (CGPoint)imagePointFromViewPoint:(CGPoint)viewPoint 99 | { 100 | switch (self.contentMode) { 101 | case UIViewContentModeScaleToFill: 102 | { 103 | CGSize imageSize = self.image.size; 104 | CGSize boundsSize = self.bounds.size; 105 | viewPoint.x *= (boundsSize.width != 0) ? (imageSize.width / boundsSize.width) : 1; 106 | viewPoint.y *= (boundsSize.height != 0) ? (imageSize.height / boundsSize.height) : 1; 107 | return viewPoint; 108 | } 109 | break; 110 | case UIViewContentModeTopLeft: 111 | return viewPoint; 112 | default: // TODO: Handle the rest of contentMode values 113 | return viewPoint; 114 | } 115 | } 116 | 117 | - (BOOL)isAlphaVisibleAtImagePoint:(CGPoint)point 118 | { 119 | CGRect queryRect; 120 | { 121 | CGRect imageRect = CGRectMake(0, 0, self.image.size.width, self.image.size.height); 122 | NSInteger pointRectWidth = self.shapedPixelTolerance * 2 + 1; 123 | CGRect pointRect = CGRectMake(point.x - self.shapedPixelTolerance, point.y - self.shapedPixelTolerance, pointRectWidth, pointRectWidth); 124 | queryRect = CGRectIntersection(imageRect, pointRect); 125 | if (CGRectIsNull(queryRect)) return NO; 126 | } 127 | 128 | CGContextRef context; 129 | unsigned char *data; 130 | NSUInteger pixelCount; 131 | { 132 | // TODO: Wouldn't it be better to use drawInRect:. See: http://stackoverflow.com/questions/15008270/get-alpha-channel-from-uiimage-rectangle 133 | CGSize querySize = queryRect.size; 134 | NSUInteger bytesPerPixel = sizeof(unsigned char); 135 | const NSUInteger bitsPerComponent = 8; 136 | pixelCount = querySize.width * querySize.height; 137 | data = (unsigned char*) calloc(pixelCount, bytesPerPixel); 138 | context = CGBitmapContextCreate(data, 139 | querySize.width, 140 | querySize.height, 141 | bitsPerComponent, 142 | bytesPerPixel * querySize.width, 143 | NULL, // colorspace can be NULL when using kCGImageAlphaOnly. See: http://developer.apple.com/library/mac/#qa/qa1037/_index.html 144 | kCGImageAlphaOnly); 145 | } 146 | 147 | CGContextSetBlendMode(context, kCGBlendModeCopy); 148 | CGContextTranslateCTM(context, -queryRect.origin.x, queryRect.origin.y-(CGFloat)self.image.size.height); 149 | CGContextDrawImage(context, CGRectMake(0.0f, 0.0f, (CGFloat)self.image.size.width, (CGFloat)self.image.size.height), self.image.CGImage); 150 | 151 | for (int i = 0; i < pixelCount; i++) 152 | { 153 | unsigned char alphaChar = data[i]; 154 | CGFloat alpha = alphaChar / 255.0; 155 | if (alpha > self.shapedTransparentMaxAlpha) 156 | { 157 | CGContextRelease(context); 158 | free(data); 159 | return YES; 160 | } 161 | } 162 | CGContextRelease(context); 163 | free(data); 164 | return NO; 165 | } 166 | 167 | - (void)resetPointInsideCache 168 | { 169 | _previousPoint = CGPointMake(CGFLOAT_MIN, CGFLOAT_MIN); 170 | _previousPointInsideResult = NO; 171 | } 172 | 173 | @end 174 | -------------------------------------------------------------------------------- /RMShapedImageViewDemo/RMAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // RMAppDelegate.h 3 | // RMShapedImageViewDemo 4 | // 5 | // Created by Hermes Pique on 2/21/13. 6 | // Copyright (c) 2013 Robot Media. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class RMViewController; 12 | 13 | @interface RMAppDelegate : UIResponder 14 | 15 | @property (strong, nonatomic) UIWindow *window; 16 | 17 | @property (strong, nonatomic) RMViewController *viewController; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /RMShapedImageViewDemo/RMAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // RMAppDelegate.m 3 | // RMShapedImageViewDemo 4 | // 5 | // Created by Hermes Pique on 2/21/13. 6 | // Copyright (c) 2013 Robot Media. All rights reserved. 7 | // 8 | 9 | #import "RMAppDelegate.h" 10 | 11 | #import "RMViewController.h" 12 | 13 | @implementation RMAppDelegate 14 | 15 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 16 | { 17 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 18 | self.viewController = [[RMViewController alloc] initWithNibName:@"RMViewController" bundle:nil]; 19 | self.window.rootViewController = self.viewController; 20 | [self.window makeKeyAndVisible]; 21 | return YES; 22 | } 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /RMShapedImageViewDemo/RMShapedImageViewDemo-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | net.robotmedia.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.0 25 | LSRequiresIPhoneOS 26 | 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /RMShapedImageViewDemo/RMShapedImageViewDemo-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'RMShapedImageViewDemo' target in the 'RMShapedImageViewDemo' project 3 | // 4 | 5 | #import 6 | 7 | #ifndef __IPHONE_4_0 8 | #warning "This project uses features only available in iOS SDK 4.0 and later." 9 | #endif 10 | 11 | #ifdef __OBJC__ 12 | #import 13 | #import 14 | #endif 15 | -------------------------------------------------------------------------------- /RMShapedImageViewDemo/RMViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // RMViewController.h 3 | // RMShapedImageViewDemo 4 | // 5 | // Created by Hermes Pique on 2/21/13. 6 | // Copyright (c) 2013 Robot Media. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "RMShapedImageView.h" 11 | 12 | @interface RMViewController : UIViewController 13 | 14 | @property (weak, nonatomic) IBOutlet RMShapedImageView *transformedImageView; 15 | 16 | - (IBAction)onGestureRecognized:(id)sender; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /RMShapedImageViewDemo/RMViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // RMViewController.m 3 | // RMShapedImageViewDemo 4 | // 5 | // Created by Hermes Pique on 2/21/13. 6 | // Copyright (c) 2013 Robot Media. All rights reserved. 7 | // 8 | 9 | #import "RMViewController.h" 10 | 11 | @implementation RMViewController 12 | 13 | - (void) viewDidLoad 14 | { 15 | [super viewDidLoad]; 16 | self.transformedImageView.transform = CGAffineTransformMakeScale(200, 1); 17 | } 18 | 19 | - (IBAction)onGestureRecognized:(id)sender 20 | { 21 | NSLog(@"Hit"); 22 | } 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /RMShapedImageViewDemo/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /RMShapedImageViewDemo/en.lproj/RMViewController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 1552 5 | 12C60 6 | 3084 7 | 1187.34 8 | 625.00 9 | 10 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 11 | 2083 12 | 13 | 14 | IBNSLayoutConstraint 15 | IBProxyObject 16 | IBUIImageView 17 | IBUILabel 18 | IBUITapGestureRecognizer 19 | IBUIView 20 | 21 | 22 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 23 | 24 | 25 | PluginDependencyRecalculationVersion 26 | 27 | 28 | 29 | 30 | IBFilesOwner 31 | IBCocoaTouchFramework 32 | 33 | 34 | IBFirstResponder 35 | IBCocoaTouchFramework 36 | 37 | 38 | 39 | 274 40 | 41 | 42 | 43 | 274 44 | {{180, 49}, {120, 120}} 45 | 46 | 47 | 48 | _NS:9 49 | 50 | 1 51 | MC45ODAzOTIxNTggMC43ODgyMzUzMDY3IDAuODYyNzQ1MTA2MgA 52 | 53 | 54 | IBCocoaTouchFramework 55 | 56 | NSImage 57 | flower.png 58 | 59 | 60 | 61 | 62 | 292 63 | {{20, 49}, {120, 120}} 64 | 65 | 66 | 67 | _NS:9 68 | 69 | 1 70 | MC45ODAzOTIxNTggMC43ODgyMzUzMDY3IDAuODYyNzQ1MTA2MgA 71 | 72 | 73 | IBCocoaTouchFramework 74 | 75 | 76 | 77 | 78 | 292 79 | {{20, 20}, {120, 21}} 80 | 81 | 82 | 83 | _NS:9 84 | NO 85 | YES 86 | 7 87 | NO 88 | IBCocoaTouchFramework 89 | UIImageView 90 | 91 | 1 92 | MCAwIDAAA 93 | darkTextColor 94 | 95 | 96 | 0 97 | 1 98 | 99 | 1 100 | 12 101 | 102 | 103 | Helvetica 104 | 12 105 | 16 106 | 107 | NO 108 | 109 | 110 | 111 | 292 112 | {{20, 177}, {120, 21}} 113 | 114 | 115 | 116 | _NS:9 117 | NO 118 | YES 119 | 7 120 | NO 121 | IBCocoaTouchFramework 122 | Non-retina 123 | 124 | 125 | 0 126 | 1 127 | 128 | 129 | NO 130 | 131 | 132 | 133 | 292 134 | {{180, 177}, {120, 21}} 135 | 136 | 137 | 138 | _NS:9 139 | NO 140 | YES 141 | 7 142 | NO 143 | IBCocoaTouchFramework 144 | Transform 145 | 146 | 147 | 0 148 | 1 149 | 150 | 151 | NO 152 | 153 | 154 | 155 | 292 156 | {{180, 20}, {120, 21}} 157 | 158 | 159 | 160 | _NS:9 161 | NO 162 | YES 163 | 7 164 | NO 165 | IBCocoaTouchFramework 166 | RMShapedImageView 167 | 168 | 169 | 0 170 | 1 171 | 172 | 173 | NO 174 | 175 | 176 | 177 | 292 178 | {{20, 334}, {280, 21}} 179 | 180 | 181 | 182 | _NS:9 183 | NO 184 | YES 185 | 7 186 | NO 187 | IBCocoaTouchFramework 188 | UIViewContentModeTopLeft 189 | 190 | 191 | 0 192 | 1 193 | 194 | 195 | NO 196 | 197 | 198 | 199 | 292 200 | {{20, 363}, {280, 60}} 201 | 202 | 203 | 204 | _NS:9 205 | 206 | 1 207 | MC45ODAzOTIxNTggMC43ODgyMzUzMDY3IDAuODYyNzQ1MTA2MgA 208 | 209 | 9 210 | 211 | IBCocoaTouchFramework 212 | 213 | 214 | 215 | 216 | 292 217 | {{20, 206}, {120, 120}} 218 | 219 | 220 | 221 | _NS:9 222 | 223 | 1 224 | MC45ODAzOTIxNTggMC43ODgyMzUzMDY3IDAuODYyNzQ1MTA2MgA 225 | 226 | 227 | IBCocoaTouchFramework 228 | 229 | NSImage 230 | flower-no-retina.png 231 | 232 | 233 | 234 | 235 | 292 236 | {{180, 206}, {120, 120}} 237 | 238 | 239 | 240 | _NS:9 241 | 242 | 1 243 | MC45ODAzOTIxNTggMC43ODgyMzUzMDY3IDAuODYyNzQ1MTA2MgA 244 | 245 | 246 | IBCocoaTouchFramework 247 | 248 | 249 | 250 | {{0, 20}, {320, 548}} 251 | 252 | 253 | 254 | 255 | 3 256 | MC43NQA 257 | 258 | 2 259 | 260 | 261 | NO 262 | 263 | 264 | IBUIScreenMetrics 265 | 266 | YES 267 | 268 | 269 | 270 | 271 | 272 | {320, 568} 273 | {568, 320} 274 | 275 | 276 | IBCocoaTouchFramework 277 | Retina 4 Full Screen 278 | 2 279 | 280 | IBCocoaTouchFramework 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | view 293 | 294 | 295 | 296 | 7 297 | 298 | 299 | 300 | transformedImageView 301 | 302 | 303 | 304 | 209 305 | 306 | 307 | 308 | gestureRecognizers 309 | 310 | 311 | NSArray 312 | YES 313 | 314 | 31 315 | 316 | 317 | 318 | onGestureRecognized: 319 | 320 | 321 | 322 | 32 323 | 324 | 325 | 326 | gestureRecognizers 327 | 328 | 329 | NSArray 330 | YES 331 | 332 | 57 333 | 334 | 335 | 336 | onGestureRecognized: 337 | 338 | 339 | 340 | 58 341 | 342 | 343 | 344 | gestureRecognizers 345 | 346 | 347 | NSArray 348 | YES 349 | 350 | 147 351 | 352 | 353 | 354 | gestureRecognizers 355 | 356 | 357 | NSArray 358 | YES 359 | 360 | 144 361 | 362 | 363 | 364 | onGestureRecognized: 365 | 366 | 367 | 368 | 145 369 | 370 | 371 | 372 | onGestureRecognized: 373 | 374 | 375 | 376 | 148 377 | 378 | 379 | 380 | gestureRecognizers 381 | 382 | 383 | NSArray 384 | YES 385 | 386 | 207 387 | 388 | 389 | 390 | onGestureRecognized: 391 | 392 | 393 | 394 | 208 395 | 396 | 397 | 398 | 399 | 400 | 0 401 | 402 | 403 | 404 | 405 | 406 | -1 407 | 408 | 409 | File's Owner 410 | 411 | 412 | -2 413 | 414 | 415 | 416 | 417 | 6 418 | 419 | 420 | 421 | 422 | 6 423 | 0 424 | 425 | 6 426 | 1 427 | 428 | 20 429 | 430 | 1000 431 | 432 | 8 433 | 29 434 | 3 435 | 436 | 437 | 438 | 5 439 | 0 440 | 441 | 5 442 | 1 443 | 444 | 20 445 | 446 | 1000 447 | 448 | 8 449 | 29 450 | 3 451 | 452 | 453 | 454 | 3 455 | 0 456 | 457 | 4 458 | 1 459 | 460 | 8 461 | 462 | 1000 463 | 464 | 6 465 | 24 466 | 3 467 | 468 | 469 | 470 | 5 471 | 0 472 | 473 | 5 474 | 1 475 | 476 | 20 477 | 478 | 1000 479 | 480 | 8 481 | 29 482 | 3 483 | 484 | 485 | 486 | 6 487 | 0 488 | 489 | 6 490 | 1 491 | 492 | 20 493 | 494 | 1000 495 | 496 | 8 497 | 29 498 | 3 499 | 500 | 501 | 502 | 3 503 | 0 504 | 505 | 4 506 | 1 507 | 508 | 8 509 | 510 | 1000 511 | 512 | 6 513 | 24 514 | 3 515 | 516 | 517 | 518 | 3 519 | 0 520 | 521 | 4 522 | 1 523 | 524 | 8 525 | 526 | 1000 527 | 528 | 6 529 | 24 530 | 3 531 | 532 | 533 | 534 | 3 535 | 0 536 | 537 | 4 538 | 1 539 | 540 | 8 541 | 542 | 1000 543 | 544 | 6 545 | 24 546 | 3 547 | 548 | 549 | 550 | 6 551 | 0 552 | 553 | 6 554 | 1 555 | 556 | 20 557 | 558 | 1000 559 | 560 | 8 561 | 29 562 | 3 563 | 564 | 565 | 566 | 3 567 | 0 568 | 569 | 4 570 | 1 571 | 572 | 8 573 | 574 | 1000 575 | 576 | 6 577 | 24 578 | 3 579 | 580 | 581 | 582 | 11 583 | 0 584 | 585 | 11 586 | 1 587 | 588 | 0.0 589 | 590 | 1000 591 | 592 | 6 593 | 24 594 | 2 595 | 596 | 597 | 598 | 3 599 | 0 600 | 601 | 3 602 | 1 603 | 604 | 0.0 605 | 606 | 1000 607 | 608 | 6 609 | 24 610 | 2 611 | 612 | 613 | 614 | 6 615 | 0 616 | 617 | 6 618 | 1 619 | 620 | 20 621 | 622 | 1000 623 | 624 | 8 625 | 29 626 | 3 627 | 628 | 629 | 630 | 5 631 | 0 632 | 633 | 5 634 | 1 635 | 636 | 0.0 637 | 638 | 1000 639 | 640 | 6 641 | 24 642 | 2 643 | 644 | 645 | 646 | 5 647 | 0 648 | 649 | 5 650 | 1 651 | 652 | 0.0 653 | 654 | 1000 655 | 656 | 6 657 | 24 658 | 2 659 | 660 | 661 | 662 | 5 663 | 0 664 | 665 | 5 666 | 1 667 | 668 | 20 669 | 670 | 1000 671 | 672 | 8 673 | 29 674 | 3 675 | 676 | 677 | 678 | 3 679 | 0 680 | 681 | 4 682 | 1 683 | 684 | 8 685 | 686 | 1000 687 | 688 | 6 689 | 24 690 | 3 691 | 692 | 693 | 694 | 3 695 | 0 696 | 697 | 4 698 | 1 699 | 700 | 8 701 | 702 | 1000 703 | 704 | 9 705 | 40 706 | 3 707 | 708 | 709 | 710 | 6 711 | 0 712 | 713 | 6 714 | 1 715 | 716 | 20 717 | 718 | 1000 719 | 720 | 8 721 | 29 722 | 3 723 | 724 | 725 | 726 | 6 727 | 0 728 | 729 | 6 730 | 1 731 | 732 | 20 733 | 734 | 1000 735 | 736 | 8 737 | 29 738 | 3 739 | 740 | 741 | 742 | 3 743 | 0 744 | 745 | 3 746 | 1 747 | 748 | 20 749 | 750 | 1000 751 | 752 | 8 753 | 29 754 | 3 755 | 756 | 757 | 758 | 5 759 | 0 760 | 761 | 5 762 | 1 763 | 764 | 0.0 765 | 766 | 1000 767 | 768 | 6 769 | 24 770 | 2 771 | 772 | 773 | 774 | 3 775 | 0 776 | 777 | 4 778 | 1 779 | 780 | 8 781 | 782 | 1000 783 | 784 | 6 785 | 24 786 | 3 787 | 788 | 789 | 790 | 6 791 | 0 792 | 793 | 6 794 | 1 795 | 796 | 0.0 797 | 798 | 1000 799 | 800 | 6 801 | 24 802 | 2 803 | 804 | 805 | 806 | 5 807 | 0 808 | 809 | 5 810 | 1 811 | 812 | 20 813 | 814 | 1000 815 | 816 | 8 817 | 29 818 | 3 819 | 820 | 821 | 822 | 6 823 | 0 824 | 825 | 6 826 | 1 827 | 828 | 0.0 829 | 830 | 1000 831 | 832 | 6 833 | 24 834 | 2 835 | 836 | 837 | 838 | 3 839 | 0 840 | 841 | 4 842 | 1 843 | 844 | 8 845 | 846 | 1000 847 | 848 | 6 849 | 24 850 | 3 851 | 852 | 853 | 854 | 6 855 | 0 856 | 857 | 6 858 | 1 859 | 860 | 0.0 861 | 862 | 1000 863 | 864 | 6 865 | 24 866 | 2 867 | 868 | 869 | 870 | 5 871 | 0 872 | 873 | 5 874 | 1 875 | 876 | 20 877 | 878 | 1000 879 | 880 | 8 881 | 29 882 | 3 883 | 884 | 885 | 886 | 11 887 | 0 888 | 889 | 11 890 | 1 891 | 892 | 0.0 893 | 894 | 1000 895 | 896 | 6 897 | 24 898 | 2 899 | 900 | 901 | 902 | 3 903 | 0 904 | 905 | 3 906 | 1 907 | 908 | 20 909 | 910 | 1000 911 | 912 | 8 913 | 29 914 | 3 915 | 916 | 917 | 918 | 5 919 | 0 920 | 921 | 5 922 | 1 923 | 924 | 20 925 | 926 | 1000 927 | 928 | 8 929 | 29 930 | 3 931 | 932 | 933 | 934 | 935 | 936 | 937 | 938 | 939 | 940 | 941 | 942 | 943 | 944 | 945 | 946 | 8 947 | 948 | 949 | 950 | 951 | 952 | 30 953 | 954 | 955 | 956 | 957 | 45 958 | 959 | 960 | 961 | 962 | 46 963 | 964 | 965 | 966 | 967 | 8 968 | 0 969 | 970 | 0 971 | 1 972 | 973 | 120 974 | 975 | 1000 976 | 977 | 3 978 | 9 979 | 1 980 | 981 | 982 | 983 | 984 | 985 | 52 986 | 987 | 988 | 989 | 990 | 56 991 | 992 | 993 | 994 | 995 | 64 996 | 997 | 998 | 999 | 1000 | 8 1001 | 0 1002 | 1003 | 0 1004 | 1 1005 | 1006 | 21 1007 | 1008 | 1000 1009 | 1010 | 3 1011 | 9 1012 | 1 1013 | 1014 | 1015 | 1016 | 7 1017 | 0 1018 | 1019 | 0 1020 | 1 1021 | 1022 | 120 1023 | 1024 | 1000 1025 | 1026 | 3 1027 | 9 1028 | 1 1029 | 1030 | 1031 | 1032 | 1033 | 1034 | 67 1035 | 1036 | 1037 | 1038 | 1039 | 7 1040 | 0 1041 | 1042 | 0 1043 | 1 1044 | 1045 | 120 1046 | 1047 | 1000 1048 | 1049 | 3 1050 | 9 1051 | 1 1052 | 1053 | 1054 | 1055 | 1056 | 1057 | 68 1058 | 1059 | 1060 | 1061 | 1062 | 69 1063 | 1064 | 1065 | 1066 | 1067 | 72 1068 | 1069 | 1070 | 1071 | 1072 | 73 1073 | 1074 | 1075 | 1076 | 1077 | 74 1078 | 1079 | 1080 | 1081 | 1082 | 75 1083 | 1084 | 1085 | 1086 | 1087 | 76 1088 | 1089 | 1090 | 1091 | 1092 | 86 1093 | 1094 | 1095 | 1096 | 1097 | 70 1098 | 1099 | 1100 | 1101 | 1102 | 93 1103 | 1104 | 1105 | 1106 | 1107 | 8 1108 | 0 1109 | 1110 | 0 1111 | 1 1112 | 1113 | 60 1114 | 1115 | 1000 1116 | 1117 | 3 1118 | 9 1119 | 1 1120 | 1121 | 1122 | 1123 | 1124 | 1125 | 100 1126 | 1127 | 1128 | 1129 | 1130 | 101 1131 | 1132 | 1133 | 1134 | 1135 | 114 1136 | 1137 | 1138 | 1139 | 1140 | 8 1141 | 0 1142 | 1143 | 0 1144 | 1 1145 | 1146 | 21 1147 | 1148 | 1000 1149 | 1150 | 3 1151 | 9 1152 | 1 1153 | 1154 | 1155 | 1156 | 1157 | 1158 | 118 1159 | 1160 | 1161 | 1162 | 1163 | 122 1164 | 1165 | 1166 | 1167 | 1168 | 8 1169 | 0 1170 | 1171 | 0 1172 | 1 1173 | 1174 | 21 1175 | 1176 | 1000 1177 | 1178 | 3 1179 | 9 1180 | 1 1181 | 1182 | 1183 | 1184 | 1185 | 1186 | 124 1187 | 1188 | 1189 | 1190 | 1191 | 128 1192 | 1193 | 1194 | 1195 | 1196 | 129 1197 | 1198 | 1199 | 1200 | 1201 | 132 1202 | 1203 | 1204 | 1205 | 1206 | 8 1207 | 0 1208 | 1209 | 0 1210 | 1 1211 | 1212 | 120 1213 | 1214 | 1000 1215 | 1216 | 3 1217 | 9 1218 | 1 1219 | 1220 | 1221 | 1222 | 1223 | 1224 | 137 1225 | 1226 | 1227 | 1228 | 1229 | 138 1230 | 1231 | 1232 | 1233 | 1234 | 139 1235 | 1236 | 1237 | 1238 | 1239 | 140 1240 | 1241 | 1242 | 1243 | 1244 | 143 1245 | 1246 | 1247 | 1248 | 1249 | 146 1250 | 1251 | 1252 | 1253 | 1254 | 157 1255 | 1256 | 1257 | 1258 | 1259 | 163 1260 | 1261 | 1262 | 1263 | 1264 | 1265 | 173 1266 | 1267 | 1268 | 1269 | 1270 | 179 1271 | 1272 | 1273 | 1274 | 1275 | 1276 | 184 1277 | 1278 | 1279 | 1280 | 1281 | 185 1282 | 1283 | 1284 | 1285 | 1286 | 186 1287 | 1288 | 1289 | 1290 | 1291 | 187 1292 | 1293 | 1294 | 1295 | 1296 | 188 1297 | 1298 | 1299 | 1300 | 1301 | 189 1302 | 1303 | 1304 | 1305 | 1306 | 191 1307 | 1308 | 1309 | 1310 | 1311 | 192 1312 | 1313 | 1314 | 1315 | 1316 | 196 1317 | 1318 | 1319 | 1320 | 1321 | 197 1322 | 1323 | 1324 | 1325 | 1326 | 198 1327 | 1328 | 1329 | 1330 | 1331 | 199 1332 | 1333 | 1334 | 1335 | 1336 | 200 1337 | 1338 | 1339 | 1340 | 1341 | 202 1342 | 1343 | 1344 | 1345 | 1346 | 203 1347 | 1348 | 1349 | 1350 | 1351 | 204 1352 | 1353 | 1354 | 1355 | 1356 | 205 1357 | 1358 | 1359 | 1360 | 1361 | 206 1362 | 1363 | 1364 | 1365 | 1366 | 1367 | 1368 | RMViewController 1369 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1370 | UIResponder 1371 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1372 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1373 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1374 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1375 | 1376 | 1377 | 1378 | 1379 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1380 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1381 | 1382 | 1383 | 1384 | 1385 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1386 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1387 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1388 | RMShapedImageView 1389 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1390 | 1391 | 1392 | 1393 | 1394 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1395 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1396 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1397 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1398 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1399 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1400 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1401 | RMShapedImageView 1402 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1403 | 1404 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1405 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1406 | 1407 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1408 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1409 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1410 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1411 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1412 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1413 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1414 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1415 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1416 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1417 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1418 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1419 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1420 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1421 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1422 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1423 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1424 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1425 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1426 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1427 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1428 | 1429 | 1430 | 1431 | 1432 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1433 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1434 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1435 | 1436 | 1437 | 1438 | 1439 | 1440 | 1441 | 1442 | 1443 | 1444 | 1445 | 1446 | 1447 | 1448 | 1449 | 1450 | 1451 | 1452 | 1453 | 1454 | 1455 | 1456 | 1457 | 1458 | 1459 | 1460 | 1461 | 1462 | 1463 | 1464 | 1465 | 1466 | 1467 | 1468 | 1469 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1470 | 1471 | 1472 | 1473 | 1474 | 1475 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1476 | 1477 | 1478 | 1479 | 1480 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1481 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1482 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1483 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1484 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1485 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1486 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1487 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1488 | RMShapedImageView 1489 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1490 | 1491 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1492 | RMShapedImageView 1493 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1494 | 1495 | 1496 | 1497 | 1498 | 1499 | 1500 | 1501 | 1502 | 1503 | 209 1504 | 1505 | 1506 | 1507 | 1508 | NSLayoutConstraint 1509 | NSObject 1510 | 1511 | IBProjectSource 1512 | ./Classes/NSLayoutConstraint.h 1513 | 1514 | 1515 | 1516 | RMShapedImageView 1517 | UIImageView 1518 | 1519 | IBProjectSource 1520 | ./Classes/RMShapedImageView.h 1521 | 1522 | 1523 | 1524 | RMViewController 1525 | UIViewController 1526 | 1527 | onGestureRecognized: 1528 | id 1529 | 1530 | 1531 | onGestureRecognized: 1532 | 1533 | onGestureRecognized: 1534 | id 1535 | 1536 | 1537 | 1538 | transformedImageView 1539 | RMShapedImageView 1540 | 1541 | 1542 | transformedImageView 1543 | 1544 | transformedImageView 1545 | RMShapedImageView 1546 | 1547 | 1548 | 1549 | IBProjectSource 1550 | ./Classes/RMViewController.h 1551 | 1552 | 1553 | 1554 | 1555 | 0 1556 | IBCocoaTouchFramework 1557 | YES 1558 | 3 1559 | 1560 | {300, 300} 1561 | {300, 300} 1562 | 1563 | YES 1564 | 2083 1565 | 1566 | 1567 | -------------------------------------------------------------------------------- /RMShapedImageViewDemo/flower-no-retina.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotmedia/RMShapedImageView/7c686b31b4250d00ffba1df5b6535f9149d907e7/RMShapedImageViewDemo/flower-no-retina.png -------------------------------------------------------------------------------- /RMShapedImageViewDemo/flower.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotmedia/RMShapedImageView/7c686b31b4250d00ffba1df5b6535f9149d907e7/RMShapedImageViewDemo/flower.png -------------------------------------------------------------------------------- /RMShapedImageViewDemo/flower@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotmedia/RMShapedImageView/7c686b31b4250d00ffba1df5b6535f9149d907e7/RMShapedImageViewDemo/flower@2x.png -------------------------------------------------------------------------------- /RMShapedImageViewDemo/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // RMShapedImageViewDemo 4 | // 5 | // Created by Hermes Pique on 2/21/13. 6 | // Copyright (c) 2013 Robot Media. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "RMAppDelegate.h" 12 | 13 | int main(int argc, char *argv[]) 14 | { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([RMAppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /RMShapedImageViewTests/RMShapedImageViewTests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | net.robotmedia.${PRODUCT_NAME:rfc1034identifier} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /RMShapedImageViewTests/RMShapedImageViewTests.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013 Robot Media SL (http://www.robotmedia.net) 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | // 17 | // RMShapedImageViewTests.m 18 | // RMShapedImageViewTests 19 | // 20 | // Created by Hermes Pique on 2/21/13. 21 | // Copyright (c) 2013 Robot Media. All rights reserved. 22 | // 23 | 24 | #import 25 | #import "RMShapedImageView.h" 26 | 27 | @interface RMShapedImageViewTests : SenTestCase 28 | 29 | @end 30 | 31 | @implementation RMShapedImageViewTests { 32 | RMShapedImageView *_view; 33 | } 34 | 35 | - (void) testInitWithFrame 36 | { 37 | _view = [[RMShapedImageView alloc] initWithFrame:CGRectMake(0, 0, 50, 50)]; 38 | STAssertNotNil(_view, @""); 39 | } 40 | 41 | - (void) testInitWithCoder 42 | { 43 | _view = [[RMShapedImageView alloc] initWithCoder:nil]; 44 | STAssertNotNil(_view, @""); 45 | } 46 | 47 | - (void)testPointInsideImageNil 48 | { 49 | _view = [[RMShapedImageView alloc] initWithFrame:CGRectMake(0, 0, 50, 50)]; 50 | BOOL result = [_view pointInside:CGPointMake(0, 0) withEvent:nil]; 51 | STAssertFalse(result, @""); 52 | } 53 | 54 | - (void)testPointInsideOutside 55 | { 56 | _view = [[RMShapedImageView alloc] initWithFrame:CGRectMake(0, 0, 50, 50)]; 57 | BOOL result = [_view pointInside:CGPointMake(-50, -50) withEvent:nil]; 58 | STAssertFalse(result, @""); 59 | } 60 | 61 | - (void)testPointInsideYES 62 | { 63 | CGRect imageRect = CGRectMake(0, 0, 50, 50); 64 | _view = [[RMShapedImageView alloc] initWithFrame:imageRect]; 65 | CGRect opaqueRect = CGRectMake(10, 10, 10, 10); 66 | _view.image = [self transparentImageWithSize:imageRect.size withOpaqueRect:opaqueRect]; 67 | CGPoint point = CGPointMake(CGRectGetMidX(opaqueRect), CGRectGetMidY(opaqueRect)); 68 | BOOL result = [_view pointInside:point withEvent:nil]; 69 | STAssertTrue(result, @""); 70 | } 71 | 72 | - (void)testPointInsideNO 73 | { 74 | CGRect imageRect = CGRectMake(0, 0, 50, 50); 75 | _view = [[RMShapedImageView alloc] initWithFrame:imageRect]; 76 | _view.image = [self transparentImageWithSize:imageRect.size withOpaqueRect:CGRectZero]; 77 | CGPoint point = CGPointMake(CGRectGetMidX(imageRect), CGRectGetMidY(imageRect)); 78 | BOOL result = [_view pointInside:point withEvent:nil]; 79 | STAssertFalse(result, @""); 80 | } 81 | 82 | - (void)testPointInsideTwice 83 | { 84 | CGRect imageRect = CGRectMake(0, 0, 50, 50); 85 | _view = [[RMShapedImageView alloc] initWithFrame:imageRect]; 86 | CGRect opaqueRect = CGRectMake(10, 10, 10, 10); 87 | _view.image = [self transparentImageWithSize:imageRect.size withOpaqueRect:opaqueRect]; 88 | CGPoint point = CGPointMake(CGRectGetMidX(opaqueRect), CGRectGetMidY(opaqueRect)); 89 | [_view pointInside:point withEvent:nil]; 90 | BOOL result = [_view pointInside:point withEvent:nil]; 91 | STAssertTrue(result, @""); 92 | } 93 | 94 | - (void)testSetImage 95 | { 96 | CGRect imageRect = CGRectMake(0, 0, 50, 50); 97 | _view = [[RMShapedImageView alloc] initWithFrame:imageRect]; 98 | _view.image = [self transparentImageWithSize:imageRect.size withOpaqueRect:CGRectZero]; 99 | } 100 | 101 | - (void)testSetImageNil 102 | { 103 | CGRect imageRect = CGRectMake(0, 0, 50, 50); 104 | _view = [[RMShapedImageView alloc] initWithFrame:imageRect]; 105 | _view.image = nil; 106 | } 107 | 108 | - (void)testShapedSupportedImageNil 109 | { 110 | _view = [[RMShapedImageView alloc] init]; 111 | STAssertTrue(_view.shapedSupported, @""); 112 | } 113 | 114 | - (void)testShapedSupportedImageNotNil 115 | { 116 | CGRect imageRect = CGRectMake(0, 0, 50, 50); 117 | _view = [[RMShapedImageView alloc] initWithFrame:imageRect]; 118 | _view.image = [self transparentImageWithSize:imageRect.size withOpaqueRect:CGRectZero]; 119 | 120 | [self _testShapedSupportedWithContentMode:UIViewContentModeScaleToFill expected:YES]; 121 | [self _testShapedSupportedWithContentMode:UIViewContentModeScaleAspectFit expected:NO]; 122 | [self _testShapedSupportedWithContentMode:UIViewContentModeScaleAspectFill expected:NO]; 123 | [self _testShapedSupportedWithContentMode:UIViewContentModeRedraw expected:NO]; 124 | [self _testShapedSupportedWithContentMode:UIViewContentModeCenter expected:NO]; 125 | [self _testShapedSupportedWithContentMode:UIViewContentModeTop expected:NO]; 126 | [self _testShapedSupportedWithContentMode:UIViewContentModeBottom expected:NO]; 127 | [self _testShapedSupportedWithContentMode:UIViewContentModeLeft expected:NO]; 128 | [self _testShapedSupportedWithContentMode:UIViewContentModeTopLeft expected:YES]; 129 | [self _testShapedSupportedWithContentMode:UIViewContentModeTopRight expected:NO]; 130 | [self _testShapedSupportedWithContentMode:UIViewContentModeBottomLeft expected:NO]; 131 | [self _testShapedSupportedWithContentMode:UIViewContentModeBottomRight expected:NO]; 132 | } 133 | 134 | #pragma mark - Helpers 135 | 136 | - (UIImage*) transparentImageWithSize:(CGSize)size withOpaqueRect:(CGRect)opaqueRect 137 | { 138 | CGRect rect = CGRectMake(0, 0, size.width, size.width); 139 | UIGraphicsBeginImageContext(rect.size); 140 | CGContextRef context = UIGraphicsGetCurrentContext(); 141 | CGContextSetFillColorWithColor(context, [UIColor clearColor].CGColor); 142 | CGContextFillRect(context, rect); 143 | CGContextSetFillColorWithColor(context, [UIColor blackColor].CGColor); 144 | CGContextFillRect(context, opaqueRect); 145 | UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); 146 | UIGraphicsEndImageContext(); 147 | return image; 148 | } 149 | 150 | - (void)_testShapedSupportedWithContentMode:(UIViewContentMode)contentMode expected:(BOOL)expected 151 | { 152 | _view.contentMode = contentMode; 153 | BOOL result = _view.shapedSupported; 154 | STAssertEquals(expected, result, @"%d", contentMode); 155 | } 156 | 157 | @end 158 | -------------------------------------------------------------------------------- /RMShapedImageViewTests/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | --------------------------------------------------------------------------------