├── .gitignore ├── .swift-version ├── BFPaperTableViewCell.podspec ├── BFPaperTableViewCell.xcodeproj └── project.pbxproj ├── BFPaperTableViewCell.xcworkspace ├── contents.xcworkspacedata └── xcshareddata │ └── BFPaperTableViewCell.xccheckout ├── BFPaperTableViewCell ├── BFPaperAppDelegate.h ├── BFPaperAppDelegate.m ├── BFPaperTableViewCell-Info.plist ├── BFPaperTableViewCell-Prefix.pch ├── BFPaperViewController.h ├── BFPaperViewController.m ├── Base.lproj │ └── Main.storyboard ├── Images.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ ├── LaunchImage.launchimage │ │ └── Contents.json │ └── bg-blue-white-arrow.imageset │ │ ├── Contents.json │ │ └── bg-blue-white-arrow.png ├── Launch Screen.storyboard ├── SubclassOfPaperTableViewCell.h ├── SubclassOfPaperTableViewCell.m ├── en.lproj │ └── InfoPlist.strings └── main.m ├── BFPaperTableViewCellDemoGif.gif ├── BFPaperTableViewCellTests ├── BFPaperTableViewCellTests-Info.plist ├── BFPaperTableViewCellTests.m └── en.lproj │ └── InfoPlist.strings ├── CHANGELOG.md ├── Classes ├── BFPaperTableViewCell.h └── BFPaperTableViewCell.m ├── LICENSE.md ├── README.md ├── frame1.png ├── frame2.png ├── frame3.png ├── frame4.png └── frame5.png /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | build/ 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | xcuserdata 13 | *.xccheckout 14 | *.moved-aside 15 | DerivedData 16 | *.hmap 17 | *.ipa 18 | *.xcuserstate -------------------------------------------------------------------------------- /.swift-version: -------------------------------------------------------------------------------- 1 | 2.3 2 | -------------------------------------------------------------------------------- /BFPaperTableViewCell.podspec: -------------------------------------------------------------------------------- 1 | 2 | Pod::Spec.new do |s| 3 | s.name = "BFPaperTableViewCell" 4 | s.version = "2.3.10" 5 | s.summary = "A flat button inspired by Google Material Design's Paper theme." 6 | s.homepage = "https://github.com/bfeher/BFPaperTableViewCell" 7 | s.license = { :type => 'MIT', :file => 'LICENSE.md' } 8 | s.author = { "Bence Feher" => "ben.feher@gmail.com" } 9 | s.source = { :git => "https://github.com/bfeher/BFPaperTableViewCell.git", :tag => "2.3.10" } 10 | s.platform = :ios, '8.0' 11 | 12 | 13 | s.source_files = 'Classes/*.{h,m}' 14 | s.requires_arc = true 15 | 16 | end 17 | -------------------------------------------------------------------------------- /BFPaperTableViewCell.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 505849211D530E8100FEE8FE /* Launch Screen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 505849201D530E8100FEE8FE /* Launch Screen.storyboard */; }; 11 | F42B5BA91978DD0000D6F4B5 /* BFPaperTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = F42B5BA81978DD0000D6F4B5 /* BFPaperTableViewCell.m */; }; 12 | F4533CD81A157DA500DF9E50 /* SubclassOfPaperTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = F4533CD71A157DA500DF9E50 /* SubclassOfPaperTableViewCell.m */; }; 13 | F48E73AE1977B45700982A46 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F48E73AD1977B45700982A46 /* Foundation.framework */; }; 14 | F48E73B01977B45700982A46 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F48E73AF1977B45700982A46 /* CoreGraphics.framework */; }; 15 | F48E73B21977B45700982A46 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F48E73B11977B45700982A46 /* UIKit.framework */; }; 16 | F48E73B81977B45700982A46 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = F48E73B61977B45700982A46 /* InfoPlist.strings */; }; 17 | F48E73BA1977B45700982A46 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = F48E73B91977B45700982A46 /* main.m */; }; 18 | F48E73BE1977B45700982A46 /* BFPaperAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = F48E73BD1977B45700982A46 /* BFPaperAppDelegate.m */; }; 19 | F48E73C11977B45700982A46 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F48E73BF1977B45700982A46 /* Main.storyboard */; }; 20 | F48E73C41977B45700982A46 /* BFPaperViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F48E73C31977B45700982A46 /* BFPaperViewController.m */; }; 21 | F48E73C61977B45700982A46 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F48E73C51977B45700982A46 /* Images.xcassets */; }; 22 | F48E73CD1977B45700982A46 /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F48E73CC1977B45700982A46 /* XCTest.framework */; }; 23 | F48E73CE1977B45700982A46 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F48E73AD1977B45700982A46 /* Foundation.framework */; }; 24 | F48E73CF1977B45700982A46 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F48E73B11977B45700982A46 /* UIKit.framework */; }; 25 | F48E73D71977B45700982A46 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = F48E73D51977B45700982A46 /* InfoPlist.strings */; }; 26 | F48E73D91977B45700982A46 /* BFPaperTableViewCellTests.m in Sources */ = {isa = PBXBuildFile; fileRef = F48E73D81977B45700982A46 /* BFPaperTableViewCellTests.m */; }; 27 | /* End PBXBuildFile section */ 28 | 29 | /* Begin PBXContainerItemProxy section */ 30 | F48E73D01977B45700982A46 /* PBXContainerItemProxy */ = { 31 | isa = PBXContainerItemProxy; 32 | containerPortal = F48E73A21977B45700982A46 /* Project object */; 33 | proxyType = 1; 34 | remoteGlobalIDString = F48E73A91977B45700982A46; 35 | remoteInfo = BFPaperTableViewCell; 36 | }; 37 | /* End PBXContainerItemProxy section */ 38 | 39 | /* Begin PBXFileReference section */ 40 | 505849201D530E8100FEE8FE /* Launch Screen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = "Launch Screen.storyboard"; sourceTree = ""; }; 41 | F42B5BA71978DD0000D6F4B5 /* BFPaperTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BFPaperTableViewCell.h; path = ../Classes/BFPaperTableViewCell.h; sourceTree = ""; }; 42 | F42B5BA81978DD0000D6F4B5 /* BFPaperTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BFPaperTableViewCell.m; path = ../Classes/BFPaperTableViewCell.m; sourceTree = ""; }; 43 | F4533CD61A157DA500DF9E50 /* SubclassOfPaperTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SubclassOfPaperTableViewCell.h; sourceTree = ""; }; 44 | F4533CD71A157DA500DF9E50 /* SubclassOfPaperTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SubclassOfPaperTableViewCell.m; sourceTree = ""; }; 45 | F48E73AA1977B45700982A46 /* BFPaperTableViewCell.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = BFPaperTableViewCell.app; sourceTree = BUILT_PRODUCTS_DIR; }; 46 | F48E73AD1977B45700982A46 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 47 | F48E73AF1977B45700982A46 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 48 | F48E73B11977B45700982A46 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 49 | F48E73B51977B45700982A46 /* BFPaperTableViewCell-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "BFPaperTableViewCell-Info.plist"; sourceTree = ""; }; 50 | F48E73B71977B45700982A46 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 51 | F48E73B91977B45700982A46 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 52 | F48E73BB1977B45700982A46 /* BFPaperTableViewCell-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "BFPaperTableViewCell-Prefix.pch"; sourceTree = ""; }; 53 | F48E73BC1977B45700982A46 /* BFPaperAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BFPaperAppDelegate.h; sourceTree = ""; }; 54 | F48E73BD1977B45700982A46 /* BFPaperAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BFPaperAppDelegate.m; sourceTree = ""; }; 55 | F48E73C01977B45700982A46 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 56 | F48E73C21977B45700982A46 /* BFPaperViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BFPaperViewController.h; sourceTree = ""; }; 57 | F48E73C31977B45700982A46 /* BFPaperViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BFPaperViewController.m; sourceTree = ""; }; 58 | F48E73C51977B45700982A46 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 59 | F48E73CB1977B45700982A46 /* BFPaperTableViewCellTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = BFPaperTableViewCellTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 60 | F48E73CC1977B45700982A46 /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; 61 | F48E73D41977B45700982A46 /* BFPaperTableViewCellTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "BFPaperTableViewCellTests-Info.plist"; sourceTree = ""; }; 62 | F48E73D61977B45700982A46 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 63 | F48E73D81977B45700982A46 /* BFPaperTableViewCellTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BFPaperTableViewCellTests.m; sourceTree = ""; }; 64 | /* End PBXFileReference section */ 65 | 66 | /* Begin PBXFrameworksBuildPhase section */ 67 | F48E73A71977B45700982A46 /* Frameworks */ = { 68 | isa = PBXFrameworksBuildPhase; 69 | buildActionMask = 2147483647; 70 | files = ( 71 | F48E73B01977B45700982A46 /* CoreGraphics.framework in Frameworks */, 72 | F48E73B21977B45700982A46 /* UIKit.framework in Frameworks */, 73 | F48E73AE1977B45700982A46 /* Foundation.framework in Frameworks */, 74 | ); 75 | runOnlyForDeploymentPostprocessing = 0; 76 | }; 77 | F48E73C81977B45700982A46 /* Frameworks */ = { 78 | isa = PBXFrameworksBuildPhase; 79 | buildActionMask = 2147483647; 80 | files = ( 81 | F48E73CD1977B45700982A46 /* XCTest.framework in Frameworks */, 82 | F48E73CF1977B45700982A46 /* UIKit.framework in Frameworks */, 83 | F48E73CE1977B45700982A46 /* Foundation.framework in Frameworks */, 84 | ); 85 | runOnlyForDeploymentPostprocessing = 0; 86 | }; 87 | /* End PBXFrameworksBuildPhase section */ 88 | 89 | /* Begin PBXGroup section */ 90 | F48E73A11977B45700982A46 = { 91 | isa = PBXGroup; 92 | children = ( 93 | F48E73E21977BAF000982A46 /* Classes */, 94 | F48E73B31977B45700982A46 /* BFPaperTableViewCell */, 95 | F48E73D21977B45700982A46 /* BFPaperTableViewCellTests */, 96 | F48E73AC1977B45700982A46 /* Frameworks */, 97 | F48E73AB1977B45700982A46 /* Products */, 98 | ); 99 | sourceTree = ""; 100 | }; 101 | F48E73AB1977B45700982A46 /* Products */ = { 102 | isa = PBXGroup; 103 | children = ( 104 | F48E73AA1977B45700982A46 /* BFPaperTableViewCell.app */, 105 | F48E73CB1977B45700982A46 /* BFPaperTableViewCellTests.xctest */, 106 | ); 107 | name = Products; 108 | sourceTree = ""; 109 | }; 110 | F48E73AC1977B45700982A46 /* Frameworks */ = { 111 | isa = PBXGroup; 112 | children = ( 113 | F48E73AD1977B45700982A46 /* Foundation.framework */, 114 | F48E73AF1977B45700982A46 /* CoreGraphics.framework */, 115 | F48E73B11977B45700982A46 /* UIKit.framework */, 116 | F48E73CC1977B45700982A46 /* XCTest.framework */, 117 | ); 118 | name = Frameworks; 119 | sourceTree = ""; 120 | }; 121 | F48E73B31977B45700982A46 /* BFPaperTableViewCell */ = { 122 | isa = PBXGroup; 123 | children = ( 124 | F4533CD61A157DA500DF9E50 /* SubclassOfPaperTableViewCell.h */, 125 | F4533CD71A157DA500DF9E50 /* SubclassOfPaperTableViewCell.m */, 126 | F48E73BC1977B45700982A46 /* BFPaperAppDelegate.h */, 127 | F48E73BD1977B45700982A46 /* BFPaperAppDelegate.m */, 128 | F48E73BF1977B45700982A46 /* Main.storyboard */, 129 | F48E73C21977B45700982A46 /* BFPaperViewController.h */, 130 | F48E73C31977B45700982A46 /* BFPaperViewController.m */, 131 | F48E73C51977B45700982A46 /* Images.xcassets */, 132 | F48E73B41977B45700982A46 /* Supporting Files */, 133 | ); 134 | path = BFPaperTableViewCell; 135 | sourceTree = ""; 136 | }; 137 | F48E73B41977B45700982A46 /* Supporting Files */ = { 138 | isa = PBXGroup; 139 | children = ( 140 | F48E73B51977B45700982A46 /* BFPaperTableViewCell-Info.plist */, 141 | F48E73B61977B45700982A46 /* InfoPlist.strings */, 142 | F48E73B91977B45700982A46 /* main.m */, 143 | F48E73BB1977B45700982A46 /* BFPaperTableViewCell-Prefix.pch */, 144 | 505849201D530E8100FEE8FE /* Launch Screen.storyboard */, 145 | ); 146 | name = "Supporting Files"; 147 | sourceTree = ""; 148 | }; 149 | F48E73D21977B45700982A46 /* BFPaperTableViewCellTests */ = { 150 | isa = PBXGroup; 151 | children = ( 152 | F48E73D81977B45700982A46 /* BFPaperTableViewCellTests.m */, 153 | F48E73D31977B45700982A46 /* Supporting Files */, 154 | ); 155 | path = BFPaperTableViewCellTests; 156 | sourceTree = ""; 157 | }; 158 | F48E73D31977B45700982A46 /* Supporting Files */ = { 159 | isa = PBXGroup; 160 | children = ( 161 | F48E73D41977B45700982A46 /* BFPaperTableViewCellTests-Info.plist */, 162 | F48E73D51977B45700982A46 /* InfoPlist.strings */, 163 | ); 164 | name = "Supporting Files"; 165 | sourceTree = ""; 166 | }; 167 | F48E73E21977BAF000982A46 /* Classes */ = { 168 | isa = PBXGroup; 169 | children = ( 170 | F42B5BA71978DD0000D6F4B5 /* BFPaperTableViewCell.h */, 171 | F42B5BA81978DD0000D6F4B5 /* BFPaperTableViewCell.m */, 172 | ); 173 | name = Classes; 174 | path = BFPaperTableViewCell; 175 | sourceTree = ""; 176 | }; 177 | /* End PBXGroup section */ 178 | 179 | /* Begin PBXNativeTarget section */ 180 | F48E73A91977B45700982A46 /* BFPaperTableViewCell */ = { 181 | isa = PBXNativeTarget; 182 | buildConfigurationList = F48E73DC1977B45700982A46 /* Build configuration list for PBXNativeTarget "BFPaperTableViewCell" */; 183 | buildPhases = ( 184 | F48E73A61977B45700982A46 /* Sources */, 185 | F48E73A71977B45700982A46 /* Frameworks */, 186 | F40049CF1A68FF6E0042C309 /* ShellScript */, 187 | F48E73A81977B45700982A46 /* Resources */, 188 | ); 189 | buildRules = ( 190 | ); 191 | dependencies = ( 192 | ); 193 | name = BFPaperTableViewCell; 194 | productName = BFPaperTableViewCell; 195 | productReference = F48E73AA1977B45700982A46 /* BFPaperTableViewCell.app */; 196 | productType = "com.apple.product-type.application"; 197 | }; 198 | F48E73CA1977B45700982A46 /* BFPaperTableViewCellTests */ = { 199 | isa = PBXNativeTarget; 200 | buildConfigurationList = F48E73DF1977B45700982A46 /* Build configuration list for PBXNativeTarget "BFPaperTableViewCellTests" */; 201 | buildPhases = ( 202 | F48E73C71977B45700982A46 /* Sources */, 203 | F48E73C81977B45700982A46 /* Frameworks */, 204 | F48E73C91977B45700982A46 /* Resources */, 205 | ); 206 | buildRules = ( 207 | ); 208 | dependencies = ( 209 | F48E73D11977B45700982A46 /* PBXTargetDependency */, 210 | ); 211 | name = BFPaperTableViewCellTests; 212 | productName = BFPaperTableViewCellTests; 213 | productReference = F48E73CB1977B45700982A46 /* BFPaperTableViewCellTests.xctest */; 214 | productType = "com.apple.product-type.bundle.unit-test"; 215 | }; 216 | /* End PBXNativeTarget section */ 217 | 218 | /* Begin PBXProject section */ 219 | F48E73A21977B45700982A46 /* Project object */ = { 220 | isa = PBXProject; 221 | attributes = { 222 | CLASSPREFIX = BFPaper; 223 | LastUpgradeCheck = 0820; 224 | ORGANIZATIONNAME = "Bence Feher"; 225 | TargetAttributes = { 226 | F48E73CA1977B45700982A46 = { 227 | TestTargetID = F48E73A91977B45700982A46; 228 | }; 229 | }; 230 | }; 231 | buildConfigurationList = F48E73A51977B45700982A46 /* Build configuration list for PBXProject "BFPaperTableViewCell" */; 232 | compatibilityVersion = "Xcode 3.2"; 233 | developmentRegion = English; 234 | hasScannedForEncodings = 0; 235 | knownRegions = ( 236 | en, 237 | Base, 238 | ); 239 | mainGroup = F48E73A11977B45700982A46; 240 | productRefGroup = F48E73AB1977B45700982A46 /* Products */; 241 | projectDirPath = ""; 242 | projectRoot = ""; 243 | targets = ( 244 | F48E73A91977B45700982A46 /* BFPaperTableViewCell */, 245 | F48E73CA1977B45700982A46 /* BFPaperTableViewCellTests */, 246 | ); 247 | }; 248 | /* End PBXProject section */ 249 | 250 | /* Begin PBXResourcesBuildPhase section */ 251 | F48E73A81977B45700982A46 /* Resources */ = { 252 | isa = PBXResourcesBuildPhase; 253 | buildActionMask = 2147483647; 254 | files = ( 255 | F48E73C61977B45700982A46 /* Images.xcassets in Resources */, 256 | F48E73B81977B45700982A46 /* InfoPlist.strings in Resources */, 257 | 505849211D530E8100FEE8FE /* Launch Screen.storyboard in Resources */, 258 | F48E73C11977B45700982A46 /* Main.storyboard in Resources */, 259 | ); 260 | runOnlyForDeploymentPostprocessing = 0; 261 | }; 262 | F48E73C91977B45700982A46 /* Resources */ = { 263 | isa = PBXResourcesBuildPhase; 264 | buildActionMask = 2147483647; 265 | files = ( 266 | F48E73D71977B45700982A46 /* InfoPlist.strings in Resources */, 267 | ); 268 | runOnlyForDeploymentPostprocessing = 0; 269 | }; 270 | /* End PBXResourcesBuildPhase section */ 271 | 272 | /* Begin PBXShellScriptBuildPhase section */ 273 | F40049CF1A68FF6E0042C309 /* ShellScript */ = { 274 | isa = PBXShellScriptBuildPhase; 275 | buildActionMask = 2147483647; 276 | files = ( 277 | ); 278 | inputPaths = ( 279 | ); 280 | outputPaths = ( 281 | ); 282 | runOnlyForDeploymentPostprocessing = 0; 283 | shellPath = /bin/bash; 284 | shellScript = "echo \"Running Build Number bash script.\"\nbuildNumber=$(/usr/libexec/PlistBuddy -c \"Print CFBundleVersion\" \"$INFOPLIST_FILE\")\nbuildNumber=$(($buildNumber + 1))\n/usr/libexec/PlistBuddy -c \"Set :CFBundleVersion $buildNumber\" \"$INFOPLIST_FILE\"\nupdatedBuildNumber=$(/usr/libexec/PlistBuddy -c \"Print CFBundleVersion\" \"$INFOPLIST_FILE\")\necho \"Updated Build Number $updatedBuildNumber\""; 285 | }; 286 | /* End PBXShellScriptBuildPhase section */ 287 | 288 | /* Begin PBXSourcesBuildPhase section */ 289 | F48E73A61977B45700982A46 /* Sources */ = { 290 | isa = PBXSourcesBuildPhase; 291 | buildActionMask = 2147483647; 292 | files = ( 293 | F4533CD81A157DA500DF9E50 /* SubclassOfPaperTableViewCell.m in Sources */, 294 | F42B5BA91978DD0000D6F4B5 /* BFPaperTableViewCell.m in Sources */, 295 | F48E73C41977B45700982A46 /* BFPaperViewController.m in Sources */, 296 | F48E73BA1977B45700982A46 /* main.m in Sources */, 297 | F48E73BE1977B45700982A46 /* BFPaperAppDelegate.m in Sources */, 298 | ); 299 | runOnlyForDeploymentPostprocessing = 0; 300 | }; 301 | F48E73C71977B45700982A46 /* Sources */ = { 302 | isa = PBXSourcesBuildPhase; 303 | buildActionMask = 2147483647; 304 | files = ( 305 | F48E73D91977B45700982A46 /* BFPaperTableViewCellTests.m in Sources */, 306 | ); 307 | runOnlyForDeploymentPostprocessing = 0; 308 | }; 309 | /* End PBXSourcesBuildPhase section */ 310 | 311 | /* Begin PBXTargetDependency section */ 312 | F48E73D11977B45700982A46 /* PBXTargetDependency */ = { 313 | isa = PBXTargetDependency; 314 | target = F48E73A91977B45700982A46 /* BFPaperTableViewCell */; 315 | targetProxy = F48E73D01977B45700982A46 /* PBXContainerItemProxy */; 316 | }; 317 | /* End PBXTargetDependency section */ 318 | 319 | /* Begin PBXVariantGroup section */ 320 | F48E73B61977B45700982A46 /* InfoPlist.strings */ = { 321 | isa = PBXVariantGroup; 322 | children = ( 323 | F48E73B71977B45700982A46 /* en */, 324 | ); 325 | name = InfoPlist.strings; 326 | sourceTree = ""; 327 | }; 328 | F48E73BF1977B45700982A46 /* Main.storyboard */ = { 329 | isa = PBXVariantGroup; 330 | children = ( 331 | F48E73C01977B45700982A46 /* Base */, 332 | ); 333 | name = Main.storyboard; 334 | sourceTree = ""; 335 | }; 336 | F48E73D51977B45700982A46 /* InfoPlist.strings */ = { 337 | isa = PBXVariantGroup; 338 | children = ( 339 | F48E73D61977B45700982A46 /* en */, 340 | ); 341 | name = InfoPlist.strings; 342 | sourceTree = ""; 343 | }; 344 | /* End PBXVariantGroup section */ 345 | 346 | /* Begin XCBuildConfiguration section */ 347 | F48E73DA1977B45700982A46 /* Debug */ = { 348 | isa = XCBuildConfiguration; 349 | buildSettings = { 350 | ALWAYS_SEARCH_USER_PATHS = NO; 351 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 352 | CLANG_CXX_LIBRARY = "libc++"; 353 | CLANG_ENABLE_MODULES = YES; 354 | CLANG_ENABLE_OBJC_ARC = YES; 355 | CLANG_WARN_BOOL_CONVERSION = YES; 356 | CLANG_WARN_CONSTANT_CONVERSION = YES; 357 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 358 | CLANG_WARN_EMPTY_BODY = YES; 359 | CLANG_WARN_ENUM_CONVERSION = YES; 360 | CLANG_WARN_INFINITE_RECURSION = YES; 361 | CLANG_WARN_INT_CONVERSION = YES; 362 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 363 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 364 | CLANG_WARN_UNREACHABLE_CODE = YES; 365 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 366 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 367 | COPY_PHASE_STRIP = NO; 368 | ENABLE_STRICT_OBJC_MSGSEND = YES; 369 | ENABLE_TESTABILITY = YES; 370 | GCC_C_LANGUAGE_STANDARD = gnu99; 371 | GCC_DYNAMIC_NO_PIC = NO; 372 | GCC_NO_COMMON_BLOCKS = YES; 373 | GCC_OPTIMIZATION_LEVEL = 0; 374 | GCC_PREPROCESSOR_DEFINITIONS = ( 375 | "DEBUG=1", 376 | "$(inherited)", 377 | ); 378 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 379 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 380 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 381 | GCC_WARN_UNDECLARED_SELECTOR = YES; 382 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 383 | GCC_WARN_UNUSED_FUNCTION = YES; 384 | GCC_WARN_UNUSED_VARIABLE = YES; 385 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 386 | ONLY_ACTIVE_ARCH = YES; 387 | SDKROOT = iphoneos; 388 | }; 389 | name = Debug; 390 | }; 391 | F48E73DB1977B45700982A46 /* Release */ = { 392 | isa = XCBuildConfiguration; 393 | buildSettings = { 394 | ALWAYS_SEARCH_USER_PATHS = NO; 395 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 396 | CLANG_CXX_LIBRARY = "libc++"; 397 | CLANG_ENABLE_MODULES = YES; 398 | CLANG_ENABLE_OBJC_ARC = YES; 399 | CLANG_WARN_BOOL_CONVERSION = YES; 400 | CLANG_WARN_CONSTANT_CONVERSION = YES; 401 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 402 | CLANG_WARN_EMPTY_BODY = YES; 403 | CLANG_WARN_ENUM_CONVERSION = YES; 404 | CLANG_WARN_INFINITE_RECURSION = YES; 405 | CLANG_WARN_INT_CONVERSION = YES; 406 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 407 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 408 | CLANG_WARN_UNREACHABLE_CODE = YES; 409 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 410 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 411 | COPY_PHASE_STRIP = YES; 412 | ENABLE_NS_ASSERTIONS = NO; 413 | ENABLE_STRICT_OBJC_MSGSEND = YES; 414 | GCC_C_LANGUAGE_STANDARD = gnu99; 415 | GCC_NO_COMMON_BLOCKS = YES; 416 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 417 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 418 | GCC_WARN_UNDECLARED_SELECTOR = YES; 419 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 420 | GCC_WARN_UNUSED_FUNCTION = YES; 421 | GCC_WARN_UNUSED_VARIABLE = YES; 422 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 423 | SDKROOT = iphoneos; 424 | VALIDATE_PRODUCT = YES; 425 | }; 426 | name = Release; 427 | }; 428 | F48E73DD1977B45700982A46 /* Debug */ = { 429 | isa = XCBuildConfiguration; 430 | buildSettings = { 431 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 432 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 433 | GCC_PREFIX_HEADER = "BFPaperTableViewCell/BFPaperTableViewCell-Prefix.pch"; 434 | INFOPLIST_FILE = "BFPaperTableViewCell/BFPaperTableViewCell-Info.plist"; 435 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 436 | PRODUCT_BUNDLE_IDENTIFIER = "com.bencefeher.${PRODUCT_NAME:rfc1034identifier}"; 437 | PRODUCT_NAME = "$(TARGET_NAME)"; 438 | WRAPPER_EXTENSION = app; 439 | }; 440 | name = Debug; 441 | }; 442 | F48E73DE1977B45700982A46 /* Release */ = { 443 | isa = XCBuildConfiguration; 444 | buildSettings = { 445 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 446 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 447 | GCC_PREFIX_HEADER = "BFPaperTableViewCell/BFPaperTableViewCell-Prefix.pch"; 448 | INFOPLIST_FILE = "BFPaperTableViewCell/BFPaperTableViewCell-Info.plist"; 449 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 450 | PRODUCT_BUNDLE_IDENTIFIER = "com.bencefeher.${PRODUCT_NAME:rfc1034identifier}"; 451 | PRODUCT_NAME = "$(TARGET_NAME)"; 452 | WRAPPER_EXTENSION = app; 453 | }; 454 | name = Release; 455 | }; 456 | F48E73E01977B45700982A46 /* Debug */ = { 457 | isa = XCBuildConfiguration; 458 | buildSettings = { 459 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/BFPaperTableViewCell.app/BFPaperTableViewCell"; 460 | FRAMEWORK_SEARCH_PATHS = ( 461 | "$(SDKROOT)/Developer/Library/Frameworks", 462 | "$(inherited)", 463 | "$(DEVELOPER_FRAMEWORKS_DIR)", 464 | ); 465 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 466 | GCC_PREFIX_HEADER = "BFPaperTableViewCell/BFPaperTableViewCell-Prefix.pch"; 467 | GCC_PREPROCESSOR_DEFINITIONS = ( 468 | "DEBUG=1", 469 | "$(inherited)", 470 | ); 471 | INFOPLIST_FILE = "BFPaperTableViewCellTests/BFPaperTableViewCellTests-Info.plist"; 472 | PRODUCT_BUNDLE_IDENTIFIER = "com.bencefeher.${PRODUCT_NAME:rfc1034identifier}"; 473 | PRODUCT_NAME = "$(TARGET_NAME)"; 474 | TEST_HOST = "$(BUNDLE_LOADER)"; 475 | WRAPPER_EXTENSION = xctest; 476 | }; 477 | name = Debug; 478 | }; 479 | F48E73E11977B45700982A46 /* Release */ = { 480 | isa = XCBuildConfiguration; 481 | buildSettings = { 482 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/BFPaperTableViewCell.app/BFPaperTableViewCell"; 483 | FRAMEWORK_SEARCH_PATHS = ( 484 | "$(SDKROOT)/Developer/Library/Frameworks", 485 | "$(inherited)", 486 | "$(DEVELOPER_FRAMEWORKS_DIR)", 487 | ); 488 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 489 | GCC_PREFIX_HEADER = "BFPaperTableViewCell/BFPaperTableViewCell-Prefix.pch"; 490 | INFOPLIST_FILE = "BFPaperTableViewCellTests/BFPaperTableViewCellTests-Info.plist"; 491 | PRODUCT_BUNDLE_IDENTIFIER = "com.bencefeher.${PRODUCT_NAME:rfc1034identifier}"; 492 | PRODUCT_NAME = "$(TARGET_NAME)"; 493 | TEST_HOST = "$(BUNDLE_LOADER)"; 494 | WRAPPER_EXTENSION = xctest; 495 | }; 496 | name = Release; 497 | }; 498 | /* End XCBuildConfiguration section */ 499 | 500 | /* Begin XCConfigurationList section */ 501 | F48E73A51977B45700982A46 /* Build configuration list for PBXProject "BFPaperTableViewCell" */ = { 502 | isa = XCConfigurationList; 503 | buildConfigurations = ( 504 | F48E73DA1977B45700982A46 /* Debug */, 505 | F48E73DB1977B45700982A46 /* Release */, 506 | ); 507 | defaultConfigurationIsVisible = 0; 508 | defaultConfigurationName = Release; 509 | }; 510 | F48E73DC1977B45700982A46 /* Build configuration list for PBXNativeTarget "BFPaperTableViewCell" */ = { 511 | isa = XCConfigurationList; 512 | buildConfigurations = ( 513 | F48E73DD1977B45700982A46 /* Debug */, 514 | F48E73DE1977B45700982A46 /* Release */, 515 | ); 516 | defaultConfigurationIsVisible = 0; 517 | defaultConfigurationName = Release; 518 | }; 519 | F48E73DF1977B45700982A46 /* Build configuration list for PBXNativeTarget "BFPaperTableViewCellTests" */ = { 520 | isa = XCConfigurationList; 521 | buildConfigurations = ( 522 | F48E73E01977B45700982A46 /* Debug */, 523 | F48E73E11977B45700982A46 /* Release */, 524 | ); 525 | defaultConfigurationIsVisible = 0; 526 | defaultConfigurationName = Release; 527 | }; 528 | /* End XCConfigurationList section */ 529 | }; 530 | rootObject = F48E73A21977B45700982A46 /* Project object */; 531 | } 532 | -------------------------------------------------------------------------------- /BFPaperTableViewCell.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /BFPaperTableViewCell.xcworkspace/xcshareddata/BFPaperTableViewCell.xccheckout: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDESourceControlProjectFavoriteDictionaryKey 6 | 7 | IDESourceControlProjectIdentifier 8 | BA557DB3-B1E9-46B3-A44A-11B6C9C101A7 9 | IDESourceControlProjectName 10 | BFPaperTableViewCell 11 | IDESourceControlProjectOriginsDictionary 12 | 13 | 6863916DC1512129899DB08D80974F762F949807 14 | https://github.com/bfeher/BFPaperTableViewCell.git 15 | 16 | IDESourceControlProjectPath 17 | BFPaperTableViewCell.xcworkspace 18 | IDESourceControlProjectRelativeInstallPathDictionary 19 | 20 | 6863916DC1512129899DB08D80974F762F949807 21 | .. 22 | 23 | IDESourceControlProjectURL 24 | https://github.com/bfeher/BFPaperTableViewCell.git 25 | IDESourceControlProjectVersion 26 | 111 27 | IDESourceControlProjectWCCIdentifier 28 | 6863916DC1512129899DB08D80974F762F949807 29 | IDESourceControlProjectWCConfigurations 30 | 31 | 32 | IDESourceControlRepositoryExtensionIdentifierKey 33 | public.vcs.git 34 | IDESourceControlWCCIdentifierKey 35 | 6863916DC1512129899DB08D80974F762F949807 36 | IDESourceControlWCCName 37 | BFPaperTableViewCell 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /BFPaperTableViewCell/BFPaperAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // BFPaperAppDelegate.h 3 | // BFPaperTableViewCell 4 | // 5 | // Created by Bence Feher on 7/17/14. 6 | // Copyright (c) 2014 Bence Feher. All rights reserved. 7 | // 8 | // The MIT License (MIT) 9 | // 10 | // Copyright (c) 2014 Bence Feher 11 | // 12 | // Permission is hereby granted, free of charge, to any person obtaining a copy 13 | // of this software and associated documentation files (the "Software"), to deal 14 | // in the Software without restriction, including without limitation the rights 15 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 | // copies of the Software, and to permit persons to whom the Software is 17 | // furnished to do so, subject to the following conditions: 18 | // 19 | // The above copyright notice and this permission notice shall be included in all 20 | // copies or substantial portions of the Software. 21 | // 22 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 28 | // SOFTWARE. 29 | 30 | 31 | #import 32 | 33 | @interface BFPaperAppDelegate : UIResponder 34 | 35 | @property (strong, nonatomic) UIWindow *window; 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /BFPaperTableViewCell/BFPaperAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // BFPaperAppDelegate.m 3 | // BFPaperTableViewCell 4 | // 5 | // Created by Bence Feher on 7/17/14. 6 | // Copyright (c) 2014 Bence Feher. All rights reserved. 7 | // 8 | // The MIT License (MIT) 9 | // 10 | // Copyright (c) 2014 Bence Feher 11 | // 12 | // Permission is hereby granted, free of charge, to any person obtaining a copy 13 | // of this software and associated documentation files (the "Software"), to deal 14 | // in the Software without restriction, including without limitation the rights 15 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 | // copies of the Software, and to permit persons to whom the Software is 17 | // furnished to do so, subject to the following conditions: 18 | // 19 | // The above copyright notice and this permission notice shall be included in all 20 | // copies or substantial portions of the Software. 21 | // 22 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 28 | // SOFTWARE. 29 | 30 | 31 | #import "BFPaperAppDelegate.h" 32 | 33 | @implementation BFPaperAppDelegate 34 | 35 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 36 | { 37 | // Override point for customization after application launch. 38 | return YES; 39 | } 40 | 41 | - (void)applicationWillResignActive:(UIApplication *)application 42 | { 43 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 44 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 45 | } 46 | 47 | - (void)applicationDidEnterBackground:(UIApplication *)application 48 | { 49 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 50 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 51 | } 52 | 53 | - (void)applicationWillEnterForeground:(UIApplication *)application 54 | { 55 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 56 | } 57 | 58 | - (void)applicationDidBecomeActive:(UIApplication *)application 59 | { 60 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 61 | } 62 | 63 | - (void)applicationWillTerminate:(UIApplication *)application 64 | { 65 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 66 | } 67 | 68 | @end 69 | -------------------------------------------------------------------------------- /BFPaperTableViewCell/BFPaperTableViewCell-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 2.3 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 10 25 | LSRequiresIPhoneOS 26 | 27 | UILaunchStoryboardName 28 | Launch Screen 29 | UIMainStoryboardFile 30 | Main 31 | UIRequiredDeviceCapabilities 32 | 33 | armv7 34 | 35 | UISupportedInterfaceOrientations 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationLandscapeLeft 39 | UIInterfaceOrientationLandscapeRight 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /BFPaperTableViewCell/BFPaperTableViewCell-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header 3 | // 4 | // The contents of this file are implicitly included at the beginning of every source file. 5 | // 6 | 7 | #import 8 | 9 | #ifndef __IPHONE_5_0 10 | #warning "This project uses features only available in iOS SDK 5.0 and later." 11 | #endif 12 | 13 | #ifdef __OBJC__ 14 | #import 15 | #import 16 | #endif 17 | -------------------------------------------------------------------------------- /BFPaperTableViewCell/BFPaperViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // BFPaperViewController.h 3 | // BFPaperTableViewCell 4 | // 5 | // Created by Bence Feher on 7/17/14. 6 | // Copyright (c) 2014 Bence Feher. All rights reserved. 7 | // 8 | // The MIT License (MIT) 9 | // 10 | // Copyright (c) 2014 Bence Feher 11 | // 12 | // Permission is hereby granted, free of charge, to any person obtaining a copy 13 | // of this software and associated documentation files (the "Software"), to deal 14 | // in the Software without restriction, including without limitation the rights 15 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 | // copies of the Software, and to permit persons to whom the Software is 17 | // furnished to do so, subject to the following conditions: 18 | // 19 | // The above copyright notice and this permission notice shall be included in all 20 | // copies or substantial portions of the Software. 21 | // 22 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 28 | // SOFTWARE. 29 | 30 | 31 | #import 32 | 33 | @interface BFPaperViewController : UITableViewController 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /BFPaperTableViewCell/BFPaperViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // BFPaperViewController.m 3 | // BFPaperTableViewCell 4 | // 5 | // Created by Bence Feher on 7/17/14. 6 | // Copyright (c) 2014 Bence Feher. All rights reserved. 7 | // 8 | // The MIT License (MIT) 9 | // 10 | // Copyright (c) 2014 Bence Feher 11 | // 12 | // Permission is hereby granted, free of charge, to any person obtaining a copy 13 | // of this software and associated documentation files (the "Software"), to deal 14 | // in the Software without restriction, including without limitation the rights 15 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 | // copies of the Software, and to permit persons to whom the Software is 17 | // furnished to do so, subject to the following conditions: 18 | // 19 | // The above copyright notice and this permission notice shall be included in all 20 | // copies or substantial portions of the Software. 21 | // 22 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 28 | // SOFTWARE. 29 | 30 | 31 | #import "BFPaperViewController.h" 32 | // Classes: 33 | #import "SubclassOfPaperTableViewCell.h" 34 | 35 | 36 | @interface BFPaperViewController () 37 | @property NSArray *colors; 38 | @end 39 | 40 | @implementation BFPaperViewController 41 | 42 | - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil 43 | { 44 | self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; 45 | if (self) { 46 | // Custom initialization 47 | } 48 | return self; 49 | } 50 | 51 | - (void)viewDidLoad 52 | { 53 | [super viewDidLoad]; 54 | // Do any additional setup after loading the view. 55 | self.title = @"BFPaperTableViewCell"; 56 | 57 | // Register BFPaperTableViewCell for our tableView: 58 | [self.tableView registerClass:[SubclassOfPaperTableViewCell class] forCellReuseIdentifier:@"BFPaperCell"]; // NOTE: This is not required if we declared a prototype cell in our storyboard (which this example project does). This is here purely for information purposes. 59 | 60 | // Fill up an array with all the basic BFPaperColors: 61 | self.colors = @[[UIColor colorWithRed:244.f/255.f green:67.f/255.f blue:54.f/255.f alpha:1], 62 | [UIColor colorWithRed:233.f/255.f green:30.f/255.f blue:99.f/255.f alpha:1], 63 | [UIColor colorWithRed:156.f/255.f green:39.f/255.f blue:176.f/255.f alpha:1], 64 | [UIColor colorWithRed:103.f/255.f green:58.f/255.f blue:183.f/255.f alpha:1], 65 | [UIColor colorWithRed:63.f/255.f green:81.f/255.f blue:181.f/255.f alpha:1], 66 | [UIColor colorWithRed:33.f/255.f green:150.f/255.f blue:243.f/255.f alpha:1], 67 | [UIColor colorWithRed:3.f/255.f green:169.f/255.f blue:244.f/255.f alpha:1], 68 | [UIColor colorWithRed:0.f/255.f green:188.f/255.f blue:212.f/255.f alpha:1], 69 | [UIColor colorWithRed:0.f/255.f green:150.f/255.f blue:136.f/255.f alpha:1], 70 | [UIColor colorWithRed:76.f/255.f green:175.f/255.f blue:80.f/255.f alpha:1], 71 | [UIColor colorWithRed:139.f/255.f green:195.f/255.f blue:74.f/255.f alpha:1], 72 | [UIColor colorWithRed:205.f/255.f green:220.f/255.f blue:57.f/255.f alpha:1], 73 | [UIColor colorWithRed:255.f/255.f green:235.f/255.f blue:59.f/255.f alpha:1], 74 | [UIColor colorWithRed:255.f/255.f green:193.f/255.f blue:7.f/255.f alpha:1], 75 | [UIColor colorWithRed:255.f/255.f green:152.f/255.f blue:0.f/255.f alpha:1], 76 | [UIColor colorWithRed:255.f/255.f green:87.f/255.f blue:34.f/255.f alpha:1], 77 | [UIColor colorWithRed:121.f/255.f green:85.f/255.f blue:72.f/255.f alpha:1], 78 | [UIColor colorWithRed:158.f/255.f green:158.f/255.f blue:158.f/255.f alpha:1], 79 | [UIColor colorWithRed:96.f/255.f green:125.f/255.f blue:139.f/255.f alpha:1], 80 | [UIColor colorWithRed:97.f/255.f green:97.f/255.f blue:97.f/255.f alpha:1], 81 | [UIColor colorWithRed:97.f/255.f green:97.f/255.f blue:97.f/255.f alpha:1]]; 82 | 83 | self.tableView.dataSource = self; 84 | self.tableView.delegate = self; 85 | 86 | self.tableView.backgroundColor = [UIColor colorWithRed:0.7 green:0.98 blue:0.7 alpha:1]; 87 | self.tableView.delaysContentTouches = NO; 88 | } 89 | 90 | - (void)viewWillAppear:(BOOL)animated 91 | { 92 | [super viewWillAppear:animated]; 93 | 94 | UIImageView *bgIV = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"bg-blue-white-arrow"]]; 95 | bgIV.contentMode = UIViewContentModeScaleAspectFill; 96 | bgIV.frame = self.tableView.frame; 97 | self.tableView.backgroundView = bgIV; 98 | } 99 | 100 | - (void)didReceiveMemoryWarning 101 | { 102 | [super didReceiveMemoryWarning]; 103 | // Dispose of any resources that can be recreated. 104 | } 105 | 106 | /* 107 | #pragma mark - Navigation 108 | 109 | // In a storyboard-based application, you will often want to do a little preparation before navigation 110 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 111 | { 112 | // Get the new view controller using [segue destinationViewController]. 113 | // Pass the selected object to the new view controller. 114 | } 115 | */ 116 | 117 | #pragma mark - Table view delegate 118 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 119 | { 120 | // Every 5th cell gets to push: 121 | if (indexPath.row % 5 == 0) { 122 | [self performSegueWithIdentifier:@"push" sender:self]; 123 | } 124 | } 125 | 126 | 127 | #pragma mark - Table view data source 128 | - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath 129 | { 130 | return 64; 131 | } 132 | 133 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 134 | { 135 | // Return the number of sections. 136 | return 1; 137 | } 138 | 139 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 140 | { 141 | // Return the number of rows in the section. 142 | return self.colors.count * 2; // We will have one set of cells with a white background and colored text, and one set with a colored background and white text. 143 | } 144 | 145 | 146 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 147 | { 148 | SubclassOfPaperTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"BFPaperCell" forIndexPath:indexPath]; 149 | 150 | if (!cell) { 151 | cell = [[SubclassOfPaperTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"BFPaperCell"]; 152 | } 153 | 154 | // Configure the cell... 155 | 156 | // This is a whole bunch of really BAD ways to customize cells that I'm, just doing for the demo. 157 | // I hope you won't attempt to customize your cells in such a way and would rather sub-class BFPaperTableViewCell and do your customizations in said subclass. 158 | // Or at least just don't do it like this ;p 159 | 160 | // Every 5th cell gets to push, so give it a disclosure indicator: 161 | if (indexPath.row % 5 == 0) { 162 | cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; 163 | } 164 | else { 165 | cell.accessoryType = UITableViewCellAccessoryNone; 166 | } 167 | 168 | // Even indexed cells will ripple from the center while odd ones will ripple from tap location: 169 | if (indexPath.row % 2 == 0) { 170 | cell.rippleFromTapLocation = NO; 171 | cell.textLabel.text = @"Ripple from Center"; 172 | } 173 | else { 174 | cell.rippleFromTapLocation = YES; 175 | cell.textLabel.text = @"Ripple from tap location"; 176 | } 177 | 178 | // Demo 2 clear cells: 179 | if (indexPath.row == 0) { 180 | cell.backgroundColor = [UIColor clearColor]; 181 | cell.textLabel.textColor = [UIColor colorWithRed:198.f/255.f green:255.f/255.f blue:0.f/255.f alpha:1]; 182 | cell.usesSmartColor = YES; 183 | cell.textLabel.text = @"Clear, Smart Color"; 184 | cell.tapCircleDiameter = bfPaperTableViewCell_tapCircleDiameterFull; 185 | } 186 | else if (indexPath.row == 1) { 187 | cell.backgroundColor = [UIColor clearColor]; 188 | cell.textLabel.textColor = [UIColor colorWithRed:198.f/255.f green:255.f/255.f blue:0.f/255.f alpha:1]; 189 | cell.usesSmartColor = NO; 190 | cell.textLabel.text = @"Clear, !Smart Color"; 191 | cell.tapCircleDiameter = bfPaperTableViewCell_tapCircleDiameterFull; 192 | } 193 | // The rest of the first half should be white with colored text: 194 | else if (indexPath.row < self.colors.count){ 195 | cell.backgroundColor = [UIColor whiteColor]; 196 | cell.textLabel.textColor = [self.colors objectAtIndex:indexPath.row]; 197 | cell.usesSmartColor = YES; 198 | cell.tapCircleDiameter = bfPaperTableViewCell_tapCircleDiameterFull; 199 | } 200 | // After that, just color their background and give them white text: 201 | else if (!(indexPath.row > (self.colors.count * 2) - 3)) { 202 | cell.backgroundColor = [self.colors objectAtIndex:indexPath.row % self.colors.count]; 203 | cell.textLabel.textColor = [UIColor whiteColor]; 204 | cell.usesSmartColor = YES; 205 | cell.tapCircleDiameter = bfPaperTableViewCell_tapCircleDiameterFull; 206 | } 207 | // Customize last two cells: 208 | else {//if (indexPath.row > (self.colors.count * 2) - 3) { 209 | cell.textLabel.text = @"Customized!"; 210 | cell.backgroundColor = [UIColor colorWithRed:103.f/255.f green:58.f/255.f blue:183.f/255.f alpha:1]; 211 | cell.textLabel.textColor = [UIColor colorWithRed:3.f/255.f green:169.f/255.f blue:244.f/255.f alpha:1]; 212 | cell.tapCircleDiameter = bfPaperTableViewCell_tapCircleDiameterSmall; 213 | cell.tapCircleColor = [UIColor colorWithRed:198.f/255.f green:255.f/255.f blue:0.f/255.f alpha:0.7f]; 214 | cell.backgroundFadeColor = [UIColor whiteColor]; 215 | cell.letBackgroundLinger = NO; 216 | } 217 | 218 | cell.textLabel.backgroundColor = [UIColor clearColor]; // If it's not clear, the tap circles and fade layers are occluded by this label's background. 219 | 220 | return cell; 221 | } 222 | 223 | - (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section 224 | { 225 | return [UIView new]; 226 | } 227 | 228 | - (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section 229 | { 230 | return 0; 231 | } 232 | 233 | @end 234 | -------------------------------------------------------------------------------- /BFPaperTableViewCell/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /BFPaperTableViewCell/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "40x40", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "60x60", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "60x60", 21 | "scale" : "3x" 22 | } 23 | ], 24 | "info" : { 25 | "version" : 1, 26 | "author" : "xcode" 27 | } 28 | } -------------------------------------------------------------------------------- /BFPaperTableViewCell/Images.xcassets/LaunchImage.launchimage/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "orientation" : "portrait", 5 | "idiom" : "iphone", 6 | "extent" : "full-screen", 7 | "minimum-system-version" : "7.0", 8 | "scale" : "2x" 9 | }, 10 | { 11 | "orientation" : "portrait", 12 | "idiom" : "iphone", 13 | "subtype" : "retina4", 14 | "extent" : "full-screen", 15 | "minimum-system-version" : "7.0", 16 | "scale" : "2x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /BFPaperTableViewCell/Images.xcassets/bg-blue-white-arrow.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "bg-blue-white-arrow.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /BFPaperTableViewCell/Images.xcassets/bg-blue-white-arrow.imageset/bg-blue-white-arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bfeher/BFPaperTableViewCell/e0c20f95b44d6a1690e9c5ad99bb6500e07f0385/BFPaperTableViewCell/Images.xcassets/bg-blue-white-arrow.imageset/bg-blue-white-arrow.png -------------------------------------------------------------------------------- /BFPaperTableViewCell/Launch Screen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 27 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /BFPaperTableViewCell/SubclassOfPaperTableViewCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // SubclassOfPaperTableViewCell.h 3 | // BFPaperTableViewCell 4 | // 5 | // This is an example of how to subclass BFPaperTableViewCell. 6 | // Note that you MUST call [super awakeFromNib] from within awakeFromNib! 7 | // 8 | // Created by Bence Feher on 11/14/14. 9 | // Copyright (c) 2014 Bence Feher. All rights reserved. 10 | // 11 | 12 | #import 13 | #import "BFPaperTableViewCell.h" 14 | 15 | @interface SubclassOfPaperTableViewCell : BFPaperTableViewCell 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /BFPaperTableViewCell/SubclassOfPaperTableViewCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // SubclassOfPaperTableViewCell.m 3 | // BFPaperTableViewCell 4 | // 5 | // This is an example of how to subclass BFPaperTableViewCell. 6 | // Note that you MUST call [super awakeFromNib] from within awakeFromNib! 7 | // 8 | // Created by Bence Feher on 11/14/14. 9 | // Copyright (c) 2014 Bence Feher. All rights reserved. 10 | // 11 | 12 | #import "SubclassOfPaperTableViewCell.h" 13 | 14 | 15 | @implementation SubclassOfPaperTableViewCell 16 | 17 | - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier 18 | { 19 | self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; 20 | if (self) { 21 | [self customSetup]; 22 | } 23 | return self; 24 | } 25 | 26 | - (void)awakeFromNib 27 | { 28 | // Initialization code 29 | [super awakeFromNib]; // THIS IS NECESSARY! 30 | [self customSetup]; 31 | } 32 | 33 | - (void)prepareForReuse 34 | { 35 | [super prepareForReuse]; 36 | 37 | // This is a good place to call your custom setup function. 38 | [self customSetup]; 39 | } 40 | 41 | - (void)customSetup 42 | { 43 | // Even though defaults values are cool, I'm setting all of the customizable options here as an example: 44 | self.usesSmartColor = NO; 45 | self.tapCircleColor = [UIColor colorWithRed:198.f/255.f green:255.f/255.f blue:0/255.f alpha:0.6]; 46 | self.tapCircleDiameter = bfPaperTableViewCell_tapCircleDiameterSmall; 47 | self.rippleFromTapLocation = YES; 48 | self.backgroundFadeColor = [UIColor colorWithWhite:1 alpha:0.2f]; 49 | self.letBackgroundLinger = YES; 50 | self.tapDelay = 0.f; 51 | 52 | // CGRect maskRect = CGRectMake(0, 0, 100, 100); 53 | // self.maskPath = [UIBezierPath bezierPathWithRoundedRect:maskRect cornerRadius:25.f]; // Just to show this property exists. 54 | // Other setup (eg. text labels, image views, etc.): 55 | } 56 | 57 | 58 | - (void)setSelected:(BOOL)selected animated:(BOOL)animated 59 | { 60 | [super setSelected:selected animated:animated]; // Be sure to call super! 61 | } 62 | 63 | @end 64 | -------------------------------------------------------------------------------- /BFPaperTableViewCell/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /BFPaperTableViewCell/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // BFPaperTableViewCell 4 | // 5 | // Created by Bence Feher on 7/17/14. 6 | // Copyright (c) 2014 Bence Feher. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "BFPaperAppDelegate.h" 12 | 13 | int main(int argc, char * argv[]) 14 | { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([BFPaperAppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /BFPaperTableViewCellDemoGif.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bfeher/BFPaperTableViewCell/e0c20f95b44d6a1690e9c5ad99bb6500e07f0385/BFPaperTableViewCellDemoGif.gif -------------------------------------------------------------------------------- /BFPaperTableViewCellTests/BFPaperTableViewCellTests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /BFPaperTableViewCellTests/BFPaperTableViewCellTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // BFPaperTableViewCellTests.m 3 | // BFPaperTableViewCellTests 4 | // 5 | // Created by Bence Feher on 7/17/14. 6 | // Copyright (c) 2014 Bence Feher. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface BFPaperTableViewCellTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation BFPaperTableViewCellTests 16 | 17 | - (void)setUp 18 | { 19 | [super setUp]; 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | } 22 | 23 | - (void)tearDown 24 | { 25 | // Put teardown code here. This method is called after the invocation of each test method in the class. 26 | [super tearDown]; 27 | } 28 | 29 | - (void)testExample 30 | { 31 | XCTFail(@"No implementation for \"%s\"", __PRETTY_FUNCTION__); 32 | } 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /BFPaperTableViewCellTests/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | BFPaperTableViewCell 2 | ==================== 3 | [![CocoaPods](https://img.shields.io/cocoapods/v/BFPaperTableViewCell.svg?style=flat)](https://github.com/bfeher/BFPaperTableViewCell) 4 | 5 | > Note that this changelog was started very late, at roughly the time between version 2.1.17 and 2.2.1. Non consecutive jumps in changelog mean that there were incremental builds that weren't released as a pod, typically while solving a problem. 6 | 7 | 8 | 2.3.10 9 | --------- 10 | * (+) Added CAAnimationDelegate for iOS10+. 11 | * (^) Updated project to recommended settings (Xcode) which changed the minimum iOS requirement from 7 to 8! 12 | 13 | 14 | 15 | 2.3.9 16 | --------- 17 | * (^) Fixed a small bug where [super awakeFromNib] wasn't being called in BFPaperTableViewCell.m's 'awakeFromNib'. 18 | 19 | 20 | 2.3.8 21 | --------- 22 | * (-) Removed all BFPaperColor dependency and code. 23 | * (^) Properties now appear in Interface Builder (IBInspectable)! 24 | * (+) Added launch screen to example project. 25 | 26 | 27 | 2.3.4 28 | --------- 29 | * (^) Migrated to CocoaPods 1.0. 30 | 31 | 32 | 2.3.3 33 | --------- 34 | * (^) Updated pods. 35 | 36 | 37 | 2.3.2 38 | --------- 39 | * (^) Fixed bug where .maskPath was not being applied to the .backgroundFadeLayer. 40 | 41 | 42 | 2.3.1 43 | --------- 44 | * (+) Added new property, 'UIBezierPath *maskPath'. 45 | 46 | 47 | 2.2.2 48 | --------- 49 | * (+) Merged a branch from github user @eithanshavit, bringing back support for a tapDelay of 0. 50 | 51 | 52 | 2.2.1 53 | --------- 54 | * (+) Added a changelog! 55 | * (+) Added public property `tapDelay` to allow control over whether or not to spawn a tap circle. If the touch ends or is cancelled before the tap-delay is complete, no circles will be spawned. Default is `0.1f`. 56 | * (-) Removed vestigial private property `letGo`. 57 | * (-) Removed vestigial private property `beganHighlight`. 58 | * (-) Removed vestigial private property `beganSelection`. 59 | * (-) Removed vestigial private property `bAlreadyFadedBackgroundIn`. 60 | * (-) Removed vestigial private property `bAlreadyFadedBackgroundOut`. 61 | -------------------------------------------------------------------------------- /Classes/BFPaperTableViewCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // BFPaperTableViewCell.h 3 | // BFPaperKit 4 | // 5 | // Created by Bence Feher on 7/11/14. 6 | // Copyright (c) 2014 Bence Feher. All rights reserved. 7 | // 8 | // The MIT License (MIT) 9 | // 10 | // Copyright (c) 2014 Bence Feher 11 | // 12 | // Permission is hereby granted, free of charge, to any person obtaining a copy 13 | // of this software and associated documentation files (the "Software"), to deal 14 | // in the Software without restriction, including without limitation the rights 15 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 | // copies of the Software, and to permit persons to whom the Software is 17 | // furnished to do so, subject to the following conditions: 18 | // 19 | // The above copyright notice and this permission notice shall be included in all 20 | // copies or substantial portions of the Software. 21 | // 22 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 28 | // SOFTWARE. 29 | 30 | 31 | #import 32 | 33 | // Nice circle diameter constants: 34 | extern const CGFloat bfPaperTableViewCell_tapCircleDiameterMedium; 35 | extern const CGFloat bfPaperTableViewCell_tapCircleDiameterLarge; 36 | extern const CGFloat bfPaperTableViewCell_tapCircleDiameterSmall; 37 | extern const CGFloat bfPaperTableViewCell_tapCircleDiameterFull; 38 | extern const CGFloat bfPaperTableViewCell_tapCircleDiameterDefault; 39 | 40 | IB_DESIGNABLE 41 | #if __IPHONE_OS_VERSION_MAX_ALLOWED < 100000 42 | // CAAnimationDelegate is not available before iOS 10 SDK 43 | @interface BFPaperTableViewCell : UITableViewCell 44 | #else 45 | @interface BFPaperTableViewCell : UITableViewCell 46 | #endif 47 | 48 | 49 | #pragma mark - Properties 50 | #pragma mark Animation 51 | /** A CGFLoat representing the duration of the animations which take place on touch DOWN! Default is 0.25f seconds. (Go Steelers) */ 52 | @property IBInspectable CGFloat touchDownAnimationDuration; 53 | /** A CGFLoat representing the duration of the animations which take place on touch UP! Default is 2 * touchDownAnimationDuration seconds. */ 54 | @property IBInspectable CGFloat touchUpAnimationDuration; 55 | 56 | 57 | #pragma mark Prettyness and Behaviour 58 | /** A flag to set YES to use Smart Color, or NO to use a custom color scheme. While Smart Color is recommended, customization is cool too. */ 59 | @property (nonatomic) IBInspectable BOOL usesSmartColor; 60 | 61 | /** A CGFLoat representing the diameter of the tap-circle as soon as it spawns, before it grows. Default is 5.f. */ 62 | @property IBInspectable CGFloat tapCircleDiameterStartValue; 63 | 64 | /** The CGFloat value representing the Diameter of the tap-circle. By default it will be the result of MAX(self.frame.width, self.frame.height). tapCircleDiameterFull will calculate a circle that always fills the entire view. Any value less than or equal to tapCircleDiameterFull will result in default being used. The constants: tapCircleDiameterLarge, tapCircleDiameterMedium, and tapCircleDiameterSmall are also available for use. */ 65 | @property IBInspectable CGFloat tapCircleDiameter; 66 | 67 | /** The CGFloat value representing how much we should increase the diameter of the tap-circle by when we burst it. Default is 100.f. */ 68 | @property IBInspectable CGFloat tapCircleBurstAmount; 69 | 70 | /** The UIColor to use for the circle which appears where you tap. NOTE: Setting this defeats the "Smart Color" ability of the tap circle. Alpha values less than 1 are recommended. */ 71 | @property IBInspectable UIColor *tapCircleColor; 72 | 73 | /** The UIColor to fade clear backgrounds to. NOTE: Setting this defeats the "Smart Color" ability of the background fade. Alpha values less than 1 are recommended. */ 74 | @property IBInspectable UIColor *backgroundFadeColor; 75 | 76 | /** A flag to set to YES to have the tap-circle ripple from point of touch. If this is set to NO, the tap-circle will always ripple from the center of the tab. Default is YES. */ 77 | @property (nonatomic) IBInspectable BOOL rippleFromTapLocation; 78 | 79 | /** A BOOL flag that determines whether or not to keep the background around after a tap, essentially "highlighting/selecting" the cell. Note that this does not trigger setSelected:! It is purely aesthetic. Also this kinda clashes with cell.selectionStyle, so by defualt the constructor sets that to UITableViewCellSelectionStyleNone. 80 | Default is YES. */ 81 | @property IBInspectable BOOL letBackgroundLinger; 82 | 83 | /** A BOOL flag indicating whether or not to always complete a full animation cycle (bg fade in, tap-circle grow and burst, bg fade out) before starting another one. NO will behave just like the other BFPaper controls, tapping rapidly spawns many circles which all fade out in turn. Default is YES. */ 84 | @property IBInspectable BOOL alwaysCompleteFullAnimation; 85 | 86 | /** A CGFLoat to set the amount of time in seconds to delay the tap event / trigger to spawn circles. For example, if the tapDelay is set to 1.f, you need to press and hold the cell for 1.f seconds to trigger spawning a circle. Default is 0.1f. */ 87 | @property IBInspectable CGFloat tapDelay; 88 | 89 | /** A UIBezierPath you can set to override the mask path of the ripples and background fade. Set this if you have a custom path for your cell. If this is nil, BFPaperTableViewCell will try its best to provide a correct mask. Default is nil. */ 90 | @property IBInspectable UIBezierPath *maskPath; 91 | @end 92 | -------------------------------------------------------------------------------- /Classes/BFPaperTableViewCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // BFPaperTableViewCell.m 3 | // BFPaperKit 4 | // 5 | // Created by Bence Feher on 7/11/14. 6 | // Copyright (c) 2014 Bence Feher. All rights reserved. 7 | // 8 | // The MIT License (MIT) 9 | // 10 | // Copyright (c) 2014 Bence Feher 11 | // 12 | // Permission is hereby granted, free of charge, to any person obtaining a copy 13 | // of this software and associated documentation files (the "Software"), to deal 14 | // in the Software without restriction, including without limitation the rights 15 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 | // copies of the Software, and to permit persons to whom the Software is 17 | // furnished to do so, subject to the following conditions: 18 | // 19 | // The above copyright notice and this permission notice shall be included in all 20 | // copies or substantial portions of the Software. 21 | // 22 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 28 | // SOFTWARE. 29 | 30 | 31 | #import "BFPaperTableViewCell.h" 32 | 33 | @interface BFPaperTableViewCell () 34 | @property CGRect fadeAndClippingMaskRect; 35 | @property CGPoint tapPoint; 36 | @property CALayer *backgroundColorFadeLayer; 37 | @property BOOL growthFinished; 38 | @property BOOL touchCancelledOrEnded; 39 | @property NSMutableArray *rippleAnimationQueue; 40 | @property NSMutableArray *deathRowForCircleLayers; // This is where old circle layers go to be killed :( 41 | @property UIColor *dumbTapCircleFillColor; 42 | @property UIColor *dumbBackgroundFadeColor; 43 | @property (nonatomic, copy) void (^removeEffectsQueue)(); 44 | @end 45 | 46 | @implementation BFPaperTableViewCell 47 | // Public consts: 48 | CGFloat const bfPaperTableViewCell_tapCircleDiameterMedium = 462.f; 49 | CGFloat const bfPaperTableViewCell_tapCircleDiameterLarge = bfPaperTableViewCell_tapCircleDiameterMedium * 1.4f; 50 | CGFloat const bfPaperTableViewCell_tapCircleDiameterSmall = bfPaperTableViewCell_tapCircleDiameterMedium / 2.f; 51 | CGFloat const bfPaperTableViewCell_tapCircleDiameterFull = -1.f; 52 | CGFloat const bfPaperTableViewCell_tapCircleDiameterDefault = -2.f; 53 | 54 | 55 | #pragma mark - Default Initializers 56 | - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier 57 | { 58 | self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; 59 | if (self) { 60 | // Initialization code 61 | [self setupBFPaperTableViewCell]; 62 | } 63 | return self; 64 | } 65 | 66 | - (void)awakeFromNib 67 | { 68 | [super awakeFromNib]; 69 | // Initialization code 70 | [self setupBFPaperTableViewCell]; 71 | } 72 | 73 | 74 | #pragma mark - Setup 75 | - (void)setupBFPaperTableViewCell 76 | { 77 | // Defaults: 78 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 79 | // Defaults for visual properties: // 80 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 81 | // Animation: 82 | self.touchDownAnimationDuration = 0.3f; 83 | self.touchUpAnimationDuration = self.touchDownAnimationDuration * 2.5f; 84 | // Prettyness and Behaviour: 85 | self.usesSmartColor = YES; 86 | self.tapCircleColor = nil; 87 | self.backgroundFadeColor = nil; 88 | self.rippleFromTapLocation = YES; 89 | self.tapCircleDiameterStartValue = 5.f; 90 | self.tapCircleDiameter = bfPaperTableViewCell_tapCircleDiameterDefault; 91 | self.tapCircleBurstAmount = 100.f; 92 | self.dumbTapCircleFillColor = [UIColor colorWithWhite:0.3 alpha:0.25f]; 93 | self.dumbBackgroundFadeColor = [UIColor colorWithWhite:0.3 alpha:0.15f]; 94 | self.letBackgroundLinger = YES; 95 | self.alwaysCompleteFullAnimation = YES; 96 | self.tapDelay = 0.1f; 97 | self.maskPath = nil; 98 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 99 | 100 | 101 | self.rippleAnimationQueue = [NSMutableArray array]; 102 | self.deathRowForCircleLayers = [NSMutableArray array]; 103 | 104 | self.selectionStyle = UITableViewCellSelectionStyleNone; 105 | 106 | self.layer.masksToBounds = YES; 107 | self.clipsToBounds = YES; 108 | 109 | self.fadeAndClippingMaskRect = CGRectMake(self.bounds.origin.x, self.bounds.origin.y, self.bounds.size.width, self.bounds.size.height); 110 | // Setup background fade layer: 111 | self.backgroundColorFadeLayer = [[CALayer alloc] init]; 112 | self.backgroundColorFadeLayer.frame = self.fadeAndClippingMaskRect; 113 | self.backgroundColorFadeLayer.backgroundColor = [UIColor clearColor].CGColor; 114 | self.backgroundColorFadeLayer.opacity = 0; 115 | [self.contentView.layer insertSublayer:self.backgroundColorFadeLayer atIndex:0]; 116 | 117 | self.textLabel.backgroundColor = [UIColor clearColor]; // We don't want the text label to occlude our tap circles! 118 | 119 | UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:nil]; 120 | tapGestureRecognizer.delegate = self; 121 | [self addGestureRecognizer:tapGestureRecognizer]; 122 | } 123 | 124 | 125 | #pragma Parent Overides 126 | - (void)setSelected:(BOOL)selected animated:(BOOL)animated 127 | { 128 | [super setSelected:selected animated:animated]; 129 | //NSLog(@"setSelected:\'%@\' animated:\'%@\'", selected ? @"YES" : @"NO", animated ? @"YES" : @"NO"); 130 | 131 | if (!self.letBackgroundLinger) { 132 | return; // If we are not letting the background linger, just return as we have nothing more to do here. 133 | } 134 | 135 | if (!selected) { 136 | [self removeBackground]; 137 | } 138 | else { 139 | [self fadeBackgroundIn]; 140 | } 141 | } 142 | 143 | /*- (void)prepareForReuse 144 | { 145 | [super prepareForReuse]; 146 | 147 | // Lets go ahead and "reset" our cell: 148 | // In your subclass, this is where you would call your custom setup. 149 | // [self setupBFPaperTableViewCell]; 150 | // [self fadeBGOut]; 151 | }*/ 152 | 153 | - (void)layoutSubviews 154 | { 155 | [super layoutSubviews]; 156 | 157 | self.fadeAndClippingMaskRect = CGRectMake(self.bounds.origin.x, self.bounds.origin.y , self.bounds.size.width, self.bounds.size.height); 158 | self.backgroundColorFadeLayer.frame = self.fadeAndClippingMaskRect; 159 | 160 | [self setNeedsDisplay]; 161 | [self.layer setNeedsDisplay]; 162 | } 163 | 164 | - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 165 | { 166 | [super touchesBegan:touches withEvent:event]; 167 | 168 | self.touchCancelledOrEnded = NO; 169 | self.growthFinished = NO; 170 | 171 | if (self.tapDelay > 0) { 172 | // Dispatch on main thread to delay animations 173 | dispatch_main_after(self.tapDelay, ^{ 174 | if (!self.touchCancelledOrEnded) { 175 | [self fadeBackgroundIn]; 176 | [self growTapCircle]; 177 | } 178 | else { 179 | [self setSelected:NO]; 180 | [self fadeBGOut]; 181 | } 182 | }); 183 | } 184 | else { 185 | // Avoid dispatching if there's no delay 186 | [self fadeBackgroundIn]; 187 | [self growTapCircle]; 188 | } 189 | } 190 | 191 | - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event 192 | { 193 | [super touchesEnded:touches withEvent:event]; 194 | 195 | self.touchCancelledOrEnded = YES; 196 | 197 | [self removeCircle]; 198 | if (!self.letBackgroundLinger) { 199 | [self removeBackground]; 200 | } 201 | } 202 | 203 | - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event 204 | { 205 | [super touchesCancelled:touches withEvent:event]; 206 | 207 | self.touchCancelledOrEnded = YES; 208 | 209 | [self removeCircle]; 210 | [self removeBackground]; 211 | } 212 | 213 | 214 | #pragma mark - Setters and Getters 215 | - (void)setUsesSmartColor:(BOOL)usesSmartColor 216 | { 217 | _usesSmartColor = usesSmartColor; 218 | self.tapCircleColor = nil; 219 | self.backgroundFadeColor = nil; 220 | } 221 | 222 | #pragma mark - Gesture Recognizer Delegate 223 | - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch { 224 | 225 | CGPoint location = [touch locationInView:self]; 226 | //NSLog(@"location: x = %0.2f, y = %0.2f", location.x, location.y); 227 | self.tapPoint = location; 228 | 229 | return NO; // Disallow recognition of tap gestures. We just needed this to grab that tasty tap location. 230 | } 231 | 232 | 233 | #pragma mark - Animation: 234 | - (void)animationDidStop:(CAAnimation *)animation finished:(BOOL)flag 235 | { 236 | // NSLog(@"animation ENDED"); 237 | self.growthFinished = YES; 238 | 239 | if ([[animation valueForKey:@"id"] isEqualToString:@"fadeCircleOut"]) { 240 | [[self.deathRowForCircleLayers objectAtIndex:0] removeFromSuperlayer]; 241 | if (self.deathRowForCircleLayers.count > 0) { 242 | [self.deathRowForCircleLayers removeObjectAtIndex:0]; 243 | } 244 | } 245 | 246 | if (self.alwaysCompleteFullAnimation) { 247 | if (self.removeEffectsQueue) { 248 | self.removeEffectsQueue(); 249 | self.removeEffectsQueue = nil; 250 | } 251 | } 252 | } 253 | 254 | - (void)removeCircle 255 | { 256 | if (!self.alwaysCompleteFullAnimation) { 257 | [self burstTapCircle]; 258 | } 259 | else { 260 | ////////////////////////////////////////////////////////////////////////////// 261 | // Special thanks to github user @ThePantsThief for providing this code! // 262 | ////////////////////////////////////////////////////////////////////////////// 263 | if (self.growthFinished) { 264 | [self burstTapCircle]; 265 | } else { 266 | void (^oldCompletion)() = self.removeEffectsQueue; 267 | __weak typeof(self) weakSelf = self; 268 | 269 | self.removeEffectsQueue = ^void() { 270 | if (oldCompletion) 271 | oldCompletion(); 272 | [weakSelf burstTapCircle]; 273 | }; 274 | } 275 | } 276 | } 277 | 278 | - (void)removeBackground 279 | { 280 | if (!self.alwaysCompleteFullAnimation) { 281 | [self fadeBGOut]; 282 | } 283 | else { 284 | ////////////////////////////////////////////////////////////////////////////// 285 | // Special thanks to github user @ThePantsThief for providing this code! // 286 | ////////////////////////////////////////////////////////////////////////////// 287 | if (self.growthFinished) { 288 | [self fadeBGOut]; 289 | } else { 290 | void (^oldCompletion)() = self.removeEffectsQueue; 291 | __weak typeof(self) weakSelf = self; 292 | self.removeEffectsQueue = ^void() { 293 | if (oldCompletion) 294 | oldCompletion(); 295 | [weakSelf fadeBGOut]; 296 | }; 297 | } 298 | } 299 | } 300 | 301 | - (void)fadeBackgroundIn 302 | { 303 | if (!self.backgroundFadeColor) { 304 | self.backgroundFadeColor = self.usesSmartColor ? [self.textLabel.textColor colorWithAlphaComponent:CGColorGetAlpha(self.dumbBackgroundFadeColor.CGColor)] : self.dumbBackgroundFadeColor; 305 | } 306 | 307 | if (nil != self.maskPath) { 308 | CAShapeLayer *mask = [CAShapeLayer layer]; 309 | mask.path = self.maskPath.CGPath; 310 | mask.fillColor = [UIColor blackColor].CGColor; 311 | mask.strokeColor = [UIColor clearColor].CGColor; 312 | mask.borderColor = [UIColor clearColor].CGColor; 313 | mask.borderWidth = 0; 314 | self.backgroundColorFadeLayer.mask = mask; 315 | } 316 | 317 | // Setup background fade layer: 318 | self.backgroundColorFadeLayer.backgroundColor = self.backgroundFadeColor.CGColor; 319 | 320 | CGFloat startingOpacity = self.backgroundColorFadeLayer.opacity; 321 | 322 | if ([[self.backgroundColorFadeLayer animationKeys] count] > 0) { 323 | startingOpacity = [[self.backgroundColorFadeLayer presentationLayer] opacity]; 324 | } 325 | 326 | // Fade the background color a bit darker: 327 | CABasicAnimation *fadeBackgroundDarker = [CABasicAnimation animationWithKeyPath:@"opacity"]; 328 | fadeBackgroundDarker.duration = self.touchDownAnimationDuration; 329 | fadeBackgroundDarker.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]; 330 | fadeBackgroundDarker.fromValue = [NSNumber numberWithFloat:startingOpacity]; 331 | fadeBackgroundDarker.toValue = [NSNumber numberWithFloat:1]; 332 | fadeBackgroundDarker.fillMode = kCAFillModeForwards; 333 | fadeBackgroundDarker.removedOnCompletion = !NO; 334 | self.backgroundColorFadeLayer.opacity = 1; 335 | 336 | [self.backgroundColorFadeLayer addAnimation:fadeBackgroundDarker forKey:@"animateOpacity"]; 337 | } 338 | 339 | - (void)growTapCircle 340 | { 341 | //NSLog(@"expanding a tap circle"); 342 | // Spawn a growing circle that "ripples" through the button: 343 | 344 | // Set the fill color for the tap circle (self.animationLayer's fill color): 345 | if (!self.tapCircleColor) { 346 | self.tapCircleColor = self.usesSmartColor ? [self.textLabel.textColor colorWithAlphaComponent:CGColorGetAlpha(self.dumbTapCircleFillColor.CGColor)] : self.dumbTapCircleFillColor; 347 | } 348 | 349 | // Calculate the tap circle's ending diameter: 350 | CGFloat tapCircleFinalDiameter = [self calculateTapCircleFinalDiameter]; 351 | 352 | // Create a UIView which we can modify for its frame value later (specifically, the ability to use .center): 353 | UIView *tapCircleLayerSizerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, tapCircleFinalDiameter, tapCircleFinalDiameter)]; 354 | tapCircleLayerSizerView.center = self.rippleFromTapLocation ? self.tapPoint : CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds)); 355 | 356 | // Calculate starting path: 357 | UIView *startingRectSizerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.tapCircleDiameterStartValue, self.tapCircleDiameterStartValue)]; 358 | startingRectSizerView.center = tapCircleLayerSizerView.center; 359 | 360 | // Create starting circle path: 361 | UIBezierPath *startingCirclePath = [UIBezierPath bezierPathWithRoundedRect:startingRectSizerView.frame cornerRadius:self.tapCircleDiameterStartValue / 2.f]; 362 | 363 | // Calculate ending path: 364 | UIView *endingRectSizerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, tapCircleFinalDiameter, tapCircleFinalDiameter)]; 365 | endingRectSizerView.center = tapCircleLayerSizerView.center; 366 | 367 | // Create ending circle path: 368 | UIBezierPath *endingCirclePath = [UIBezierPath bezierPathWithRoundedRect:endingRectSizerView.frame cornerRadius:tapCircleFinalDiameter / 2.f]; 369 | 370 | // Create tap circle: 371 | CAShapeLayer *tapCircle = [CAShapeLayer layer]; 372 | tapCircle.fillColor = self.tapCircleColor.CGColor; 373 | tapCircle.strokeColor = [UIColor clearColor].CGColor; 374 | tapCircle.borderColor = [UIColor clearColor].CGColor; 375 | tapCircle.borderWidth = 0; 376 | tapCircle.path = startingCirclePath.CGPath; 377 | 378 | // Create a mask if we are not going to ripple over bounds: 379 | CAShapeLayer *mask = [CAShapeLayer layer]; 380 | mask.path = (nil == self.maskPath) ? [UIBezierPath bezierPathWithRoundedRect:self.fadeAndClippingMaskRect cornerRadius:self.layer.cornerRadius].CGPath : self.maskPath.CGPath; 381 | mask.fillColor = [UIColor blackColor].CGColor; 382 | mask.strokeColor = [UIColor clearColor].CGColor; 383 | mask.borderColor = [UIColor clearColor].CGColor; 384 | mask.borderWidth = 0; 385 | 386 | // Set tap circle layer's mask to the mask: 387 | tapCircle.mask = mask; 388 | 389 | // Add tap circle to array and view: 390 | [self.rippleAnimationQueue addObject:tapCircle]; 391 | [self.contentView.layer insertSublayer:tapCircle above:self.backgroundColorFadeLayer]; 392 | 393 | 394 | // Grow tap-circle animation (performed on mask layer): 395 | CABasicAnimation *tapCircleGrowthAnimation = [CABasicAnimation animationWithKeyPath:@"path"]; 396 | tapCircleGrowthAnimation.delegate = self; 397 | tapCircleGrowthAnimation.duration = self.touchDownAnimationDuration; 398 | tapCircleGrowthAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]; 399 | tapCircleGrowthAnimation.fromValue = (__bridge id)startingCirclePath.CGPath; 400 | tapCircleGrowthAnimation.toValue = (__bridge id)endingCirclePath.CGPath; 401 | tapCircleGrowthAnimation.fillMode = kCAFillModeForwards; 402 | tapCircleGrowthAnimation.removedOnCompletion = NO; 403 | 404 | // Fade in self.animationLayer: 405 | CABasicAnimation *fadeIn = [CABasicAnimation animationWithKeyPath:@"opacity"]; 406 | fadeIn.duration = self.touchDownAnimationDuration; 407 | fadeIn.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]; 408 | fadeIn.fromValue = [NSNumber numberWithFloat:0.f]; 409 | fadeIn.toValue = [NSNumber numberWithFloat:1.f]; 410 | fadeIn.fillMode = kCAFillModeForwards; 411 | fadeIn.removedOnCompletion = NO; 412 | 413 | // Add the animations to the layers: 414 | [tapCircle addAnimation:tapCircleGrowthAnimation forKey:@"animatePath"]; 415 | [tapCircle addAnimation:fadeIn forKey:@"opacityAnimation"]; 416 | } 417 | 418 | - (void)fadeBGOut 419 | { 420 | //NSLog(@"fading bg"); 421 | 422 | CGFloat startingOpacity = self.backgroundColorFadeLayer.opacity; 423 | 424 | // Grab the current value if we are currently animating: 425 | if ([[self.backgroundColorFadeLayer animationKeys] count] > 0) { 426 | startingOpacity = [[self.backgroundColorFadeLayer presentationLayer] opacity]; 427 | } 428 | 429 | CABasicAnimation *removeFadeBackgroundDarker = [CABasicAnimation animationWithKeyPath:@"opacity"]; 430 | removeFadeBackgroundDarker.duration = self.touchUpAnimationDuration; 431 | removeFadeBackgroundDarker.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]; 432 | removeFadeBackgroundDarker.fromValue = [NSNumber numberWithFloat:startingOpacity]; 433 | removeFadeBackgroundDarker.toValue = [NSNumber numberWithFloat:0]; 434 | removeFadeBackgroundDarker.fillMode = kCAFillModeForwards; 435 | removeFadeBackgroundDarker.removedOnCompletion = !NO; 436 | self.backgroundColorFadeLayer.opacity = 0; 437 | 438 | [self.backgroundColorFadeLayer addAnimation:removeFadeBackgroundDarker forKey:@"animateOpacity"]; 439 | } 440 | 441 | - (void)burstTapCircle 442 | { 443 | //NSLog(@"expanding a bit more"); 444 | 445 | if (1 > self.rippleAnimationQueue.count) { 446 | return; // We don't have any circles to burst, we can just leave and ponder how and why we got here in this state. 447 | } 448 | 449 | // Get the next tap circle to expand: 450 | CAShapeLayer *tapCircle = [self.rippleAnimationQueue firstObject]; 451 | if (self.rippleAnimationQueue.count > 0) { 452 | [self.rippleAnimationQueue removeObjectAtIndex:0]; 453 | } 454 | [self.deathRowForCircleLayers addObject:tapCircle]; 455 | 456 | 457 | // Calculate the tap circle's ending diameter: 458 | CGFloat tapCircleFinalDiameter = [self calculateTapCircleFinalDiameter]; 459 | tapCircleFinalDiameter += self.tapCircleBurstAmount; 460 | 461 | UIView *endingRectSizerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, tapCircleFinalDiameter, tapCircleFinalDiameter)]; 462 | endingRectSizerView.center = self.rippleFromTapLocation ? self.tapPoint : CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds)); 463 | 464 | // Create ending circle path for mask: 465 | UIBezierPath *endingCirclePath = [UIBezierPath bezierPathWithRoundedRect:endingRectSizerView.frame cornerRadius:tapCircleFinalDiameter / 2.f]; 466 | 467 | 468 | CGPathRef startingPath = tapCircle.path; 469 | CGFloat startingOpacity = tapCircle.opacity; 470 | 471 | if ([[tapCircle animationKeys] count] > 0) { 472 | startingPath = [[tapCircle presentationLayer] path]; 473 | startingOpacity = [[tapCircle presentationLayer] opacity]; 474 | } 475 | 476 | // Burst tap-circle: 477 | CABasicAnimation *tapCircleGrowthAnimation = [CABasicAnimation animationWithKeyPath:@"path"]; 478 | tapCircleGrowthAnimation.duration = self.touchUpAnimationDuration; 479 | tapCircleGrowthAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]; 480 | tapCircleGrowthAnimation.fromValue = (__bridge id)startingPath; 481 | tapCircleGrowthAnimation.toValue = (__bridge id)endingCirclePath.CGPath; 482 | tapCircleGrowthAnimation.fillMode = kCAFillModeForwards; 483 | tapCircleGrowthAnimation.removedOnCompletion = NO; 484 | 485 | // Fade tap-circle out: 486 | CABasicAnimation *fadeOut = [CABasicAnimation animationWithKeyPath:@"opacity"]; 487 | [fadeOut setValue:@"fadeCircleOut" forKey:@"id"]; 488 | fadeOut.delegate = self; 489 | fadeOut.fromValue = [NSNumber numberWithFloat:startingOpacity]; 490 | fadeOut.toValue = [NSNumber numberWithFloat:0.f]; 491 | fadeOut.duration = self.touchUpAnimationDuration; 492 | fadeOut.fillMode = kCAFillModeForwards; 493 | fadeOut.removedOnCompletion = NO; 494 | 495 | [tapCircle addAnimation:tapCircleGrowthAnimation forKey:@"animatePath"]; 496 | [tapCircle addAnimation:fadeOut forKey:@"opacityAnimation"]; 497 | } 498 | 499 | - (CGFloat)calculateTapCircleFinalDiameter 500 | { 501 | CGFloat finalDiameter = self.tapCircleDiameter; 502 | if (self.tapCircleDiameter == bfPaperTableViewCell_tapCircleDiameterFull) { 503 | // Calulate a diameter that will always cover the entire button: 504 | ////////////////////////////////////////////////////////////////////////////// 505 | // Special thanks to github user @ThePantsThief for providing this code! // 506 | ////////////////////////////////////////////////////////////////////////////// 507 | CGFloat centerWidth = self.frame.size.width; 508 | CGFloat centerHeight = self.frame.size.height; 509 | CGFloat tapWidth = 2 * MAX(self.tapPoint.x, centerWidth - self.tapPoint.x); 510 | CGFloat tapHeight = 2 * MAX(self.tapPoint.y, centerHeight - self.tapPoint.y); 511 | CGFloat desiredWidth = self.rippleFromTapLocation ? tapWidth : centerWidth; 512 | CGFloat desiredHeight = self.rippleFromTapLocation ? tapHeight : centerHeight; 513 | CGFloat diameter = sqrt(pow(desiredWidth, 2) + pow(desiredHeight, 2)); 514 | finalDiameter = diameter; 515 | } 516 | else if (self.tapCircleDiameter < bfPaperTableViewCell_tapCircleDiameterFull) { // default 517 | finalDiameter = MAX(self.frame.size.width, self.frame.size.height); 518 | } 519 | return finalDiameter; 520 | } 521 | 522 | 523 | #pragma mark - Helpers 524 | static void dispatch_main_after(NSTimeInterval delay, void (^block)(void)) 525 | { 526 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 527 | block(); 528 | }); 529 | } 530 | #pragma mark - 531 | 532 | 533 | @end 534 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright © (c) 2017 Bence Feher 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | BFPaperTableViewCell 2 | ==================== 3 | [![CocoaPods](https://img.shields.io/cocoapods/v/BFPaperTableViewCell.svg?style=flat)](https://github.com/bfeher/BFPaperTableViewCell) 4 | 5 | > A subclass of UITableViewCell inspired by Google's Material Design: Paper Elements. 6 | 7 | ![Animated Screenshot](https://raw.githubusercontent.com/bfeher/BFPaperTableViewCell/master/BFPaperTableViewCellDemoGif.gif "Animated Screenshot") 8 | 9 | Changes 10 | -------- 11 | > Please see included [CHANGELOG file](https://github.com/bfeher/BFPaperTableViewCell/blob/master/CHANGELOG.md). 12 | 13 | 14 | About 15 | --------- 16 | ### Now with smoother animations and more public properties for even easier customization! 17 | 18 | _BFPaperTableViewCell_ is a subclass of UITableViewCell that behaves much like the new paper table cells from Google's Material Design Labs. 19 | All animation are asynchronous and are performed on sublayers. 20 | _BFPaperTableViewCells_ work right away with pleasing default behaviors, however they can be easily customized! The tap-circle color, background fade color, background fade alpha, background highlight (linger or fade away), tap-circle ripple locaiton, and tap-circle diameter are all readily customizable via public properties. 21 | 22 | By default, _BFPaperTableViewCells_ use "Smart Color" which will match the tap-circle and background fade colors to the color of the `textLabel`. 23 | You can turn off Smart Color by setting the property, `.usesSmartColor` to `NO`. If you disable Smart Color, a gray color will be used by default for both the tap-circle and the background color fade. 24 | You can set your own colors via: `.tapCircleColor` and `.backgroundFadeColor`. Note that setting these disables Smart Color. 25 | 26 | ## Properties 27 | `BOOL usesSmartColor` 28 | > A flag to set YES to use Smart Color, or NO to use a custom color scheme. While Smart Color is the default (usesSmartColor = YES), customization is cool too. 29 | 30 | `CGFloat touchDownAnimationDuration` 31 | > A CGFLoat representing the duration of the animations which take place on touch DOWN! Default is `0.25f` seconds. (Go Steelers) 32 | 33 | `CGFloat touchUpAnimationDuration` 34 | > A CGFLoat representing the duration of the animations which take place on touch UP! Default is `2 * touchDownAnimationDuration` seconds. 35 | 36 | `CGFloat tapCircleDiameterStartValue` 37 | > A CGFLoat representing the diameter of the tap-circle as soon as it spawns, before it grows. Default is `5.f`. 38 | 39 | `CGFloat tapCircleDiameter` 40 | > The CGFloat value representing the Diameter of the tap-circle. By default it will be the result of `MAX(self.frame.width, self.frame.height)`. `tapCircleDiameterFull` will calculate a circle that always fills the entire view. Any value less than or equal to `tapCircleDiameterFull` will result in default being used. The constants: `tapCircleDiameterLarge`, `tapCircleDiameterMedium`, and `tapCircleDiameterSmall` are also available for use. 41 | 42 | `CGFloat tapCircleBurstAmount` 43 | > The CGFloat value representing how much we should increase the diameter of the tap-circle by when we burst it. Default is `100.f`. 44 | 45 | `UIColor *tapCircleColor` 46 | > The UIColor to use for the circle which appears where you tap. NOTE: Setting this defeats the "Smart Color" ability of the tap circle. Alpha values less than `1` are recommended. 47 | 48 | `UIColor *backgroundFadeColor` 49 | > The UIColor to fade clear backgrounds to. NOTE: Setting this defeats the "Smart Color" ability of the background fade. Alpha values less than `1` are recommended. 50 | 51 | `BOOL rippleFromTapLocation` 52 | > A flag to set to `YES` to have the tap-circle ripple from point of touch. If this is set to `NO`, the tap-circle will always ripple from the center of the view. Default is `YES`. 53 | 54 | `BOOL letBackgroundLinger` 55 | > A BOOL flag that determines whether or not to keep the background around after a tap, essentially "highlighting/selecting" the cell. Note that this does not trigger `setSelected:`! It is purely aesthetic. Also this kinda clashes with `cell.selectionStyle`, so by defualt the constructor sets that to `UITableViewCellSelectionStyleNone`. Default is YES. 56 | 57 | `BOOL alwaysCompleteFullAnimation` 58 | > A BOOL flag indicating whether or not to always complete a full animation cycle (bg fade in, tap-circle grow and burst, bg fade out) before starting another one. NO will behave just like the other BFPaper controls, tapping rapidly spawns many circles which all fade out in turn. Default is `YES`. 59 | 60 | `CGFloat tapDelay` 61 | > A CGFLoat to set the amount of time in seconds to delay the tap event / trigger to spawn circles. For example, if the tapDelay is set to `1.f`, you need to press and hold the cell for 1 second to trigger spawning a circle. Default is `0.1f`. 62 | 63 | `UIBezierPath *maskPath` 64 | > A UIBezierPath you can set to override the mask path of the ripples and background fade. Set this if you have a custom path for your cell. If this is `nil`, BFPaperTableViewCell will try its best to provide a correct mask. Default is `nil`. 65 | 66 | 67 | Usage 68 | --------- 69 | Add the _BFPaperTableViewCell_ header and implementation file to your project. (.h & .m) 70 | 71 | After that, you can use it just like any other `UITableViewCell`. 72 | 73 | If you use storyboards with prototype cells, be sure to change the prototype cell's class to _BFPaperTableViewCell_! 74 | 75 | ### Example 76 | ```objective-c 77 | // Register BFPaperTableViewCell for our tableView in viewDidLoad: 78 | - (void)viewDidLoad 79 | { 80 | ... 81 | [self.tableView registerClass:[BFPaperTableViewCell class] forCellReuseIdentifier:@"BFPaperCell"]; // NOTE: This is not required if we declared a prototype cell in our storyboard (which this example project does). This is here purely for information purposes. 82 | ... 83 | } 84 | 85 | 86 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 87 | { 88 | BFPaperTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"BFPaperCell" forIndexPath:indexPath]; 89 | if (!cell) { 90 | cell = [[BFPaperTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"BFPaperCell"]; 91 | } 92 | cell.rippleFromTapLocation = NO; // Will always ripple from center if NO. 93 | cell.tapCircleColor = [[UIColor paperColorDeepPurple] colorWithAlphaComponent:0.3f]; // Paper Colors can be found in my BFPaperColors library :) 94 | cell.backgroundFadeColor = [UIColor paperColorBlue]; // Paper Colors can be found in my BFPaperColors library :) 95 | cell.backgroundFadeAlpha = 0.7f; 96 | cell.letBackgroundLinger = NO; 97 | cell.tapCircleDiameter = bfPaperTableViewCell_tapCircleDiameterSmall; 98 | return cell; 99 | } 100 | ``` 101 | 102 | 103 | CocoaPods 104 | ------- 105 | 106 | CocoaPods are the best way to manage library dependencies in Objective-C projects. 107 | Learn more at http://cocoapods.org 108 | 109 | Add this to your podfile to add _BFPaperTableViewCell_ to your project. 110 | ```ruby 111 | platform :ios, '8.0' 112 | pod 'BFPaperTableViewCell' 113 | ``` 114 | 115 | 116 | License 117 | -------- 118 | _BFPaperTableViewCell_ uses the MIT License: 119 | 120 | > Please see included [LICENSE file](https://raw.githubusercontent.com/bfeher/BFPaperTableViewCell/master/LICENSE.md). 121 | -------------------------------------------------------------------------------- /frame1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bfeher/BFPaperTableViewCell/e0c20f95b44d6a1690e9c5ad99bb6500e07f0385/frame1.png -------------------------------------------------------------------------------- /frame2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bfeher/BFPaperTableViewCell/e0c20f95b44d6a1690e9c5ad99bb6500e07f0385/frame2.png -------------------------------------------------------------------------------- /frame3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bfeher/BFPaperTableViewCell/e0c20f95b44d6a1690e9c5ad99bb6500e07f0385/frame3.png -------------------------------------------------------------------------------- /frame4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bfeher/BFPaperTableViewCell/e0c20f95b44d6a1690e9c5ad99bb6500e07f0385/frame4.png -------------------------------------------------------------------------------- /frame5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bfeher/BFPaperTableViewCell/e0c20f95b44d6a1690e9c5ad99bb6500e07f0385/frame5.png --------------------------------------------------------------------------------