├── .gitignore ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── Examples ├── Examples.xcodeproj │ ├── project.pbxproj │ └── xcshareddata │ │ └── xcschemes │ │ └── Logo-iOS.xcscheme ├── LICENSE └── Logo-iOS │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── Base.lproj │ ├── Main_iPad.storyboard │ └── Main_iPhone.storyboard │ ├── Images.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ ├── LaunchImage.launchimage │ │ └── Contents.json │ └── Wallpaper.imageset │ │ ├── 1800126_10152272440319357_261758585_o.png │ │ └── Contents.json │ ├── Logo-iOS-Info.plist │ ├── Logo-iOS-Prefix.pch │ ├── ViewController.h │ ├── ViewController.m │ ├── en.lproj │ └── InfoPlist.strings │ └── main.m ├── FBShimmering.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ └── contents.xcworkspacedata └── xcshareddata │ └── xcschemes │ ├── FBShimmering.xcscheme │ └── Framework.xcscheme ├── FBShimmering.xcworkspace ├── contents.xcworkspacedata └── xcshareddata │ └── IDEWorkspaceChecks.plist ├── FBShimmering ├── FBShimmering-Prefix.pch ├── FBShimmering.h ├── FBShimmeringLayer.h ├── FBShimmeringLayer.m ├── FBShimmeringView.h └── FBShimmeringView.m ├── Framework ├── Info.plist └── Shimmer.h ├── LICENSE ├── README.md ├── Shimmer.podspec └── shimmer.gif /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | 3 | *.pbxuser 4 | *.perspective 5 | *.perspectivev3 6 | 7 | *.mode1v3 8 | *.mode2v3 9 | 10 | *.xcodeproj/xcuserdata/*.xcuserdatad 11 | 12 | *.xccheckout 13 | *.xcuserdatad 14 | 15 | build/ 16 | 17 | Pods 18 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Code of Conduct 2 | Facebook has adopted a Code of Conduct that we expect project participants to adhere to. Please [read the full text](https://code.fb.com/codeofconduct) so that you can understand what actions will and will not be tolerated. -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | We want to make contributing to Shimmer as easy and transparent as 3 | possible. If you run into problems, please open an issue. We also actively welcome pull requests. 4 | 5 | ## Pull Requests 6 | 1. Fork the repo and create your branch from `master`. 7 | 2. If you've added code that should be tested, add tests 8 | 3. If you've changed APIs, update the documentation. 9 | 4. Ensure the test suite passes. 10 | 5. Make sure your code lints. 11 | 6. If you haven't already, complete the Contributor License Agreement ("CLA"). 12 | 13 | ## Contributor License Agreement ("CLA") 14 | In order to accept your pull request, we need you to submit a CLA. You only need 15 | to do this once to work on any of Facebook's open source projects. 16 | 17 | Complete your CLA here: 18 | 19 | ## Issues 20 | We use GitHub issues to track public bugs. Please ensure your description is 21 | clear and has sufficient instructions to be able to reproduce the issue. 22 | 23 | ## Coding Style 24 | * 2 spaces for indentation rather than tabs 25 | 26 | ## License 27 | By contributing to Shimmer you agree that your contributions will be licensed 28 | under its BSD license. 29 | -------------------------------------------------------------------------------- /Examples/Examples.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 077ACA6E1CBD6B7200B3A708 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 077ACA6D1CBD6B7200B3A708 /* UIKit.framework */; }; 11 | EC45CACE18ADC7CE0063DD11 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EC45CACD18ADC7CE0063DD11 /* Foundation.framework */; }; 12 | EC45CAD018ADC7CE0063DD11 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EC45CACF18ADC7CE0063DD11 /* CoreGraphics.framework */; }; 13 | EC45CAD818ADC7CE0063DD11 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = EC45CAD618ADC7CE0063DD11 /* InfoPlist.strings */; }; 14 | EC45CADA18ADC7CE0063DD11 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = EC45CAD918ADC7CE0063DD11 /* main.m */; }; 15 | EC45CADE18ADC7CE0063DD11 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = EC45CADD18ADC7CE0063DD11 /* AppDelegate.m */; }; 16 | EC45CAE118ADC7CE0063DD11 /* Main_iPhone.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = EC45CADF18ADC7CE0063DD11 /* Main_iPhone.storyboard */; }; 17 | EC45CAE418ADC7CE0063DD11 /* Main_iPad.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = EC45CAE218ADC7CE0063DD11 /* Main_iPad.storyboard */; }; 18 | EC45CAE718ADC7CE0063DD11 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = EC45CAE618ADC7CE0063DD11 /* ViewController.m */; }; 19 | EC45CAE918ADC7CE0063DD11 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = EC45CAE818ADC7CE0063DD11 /* Images.xcassets */; }; 20 | EC45CB0418ADC7E80063DD11 /* libFBShimmering.a in Frameworks */ = {isa = PBXBuildFile; fileRef = EC45CB0318ADC7E80063DD11 /* libFBShimmering.a */; }; 21 | /* End PBXBuildFile section */ 22 | 23 | /* Begin PBXFileReference section */ 24 | 077ACA6D1CBD6B7200B3A708 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 25 | EC45CACA18ADC7CE0063DD11 /* Logo-iOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Logo-iOS.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 26 | EC45CACD18ADC7CE0063DD11 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 27 | EC45CACF18ADC7CE0063DD11 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 28 | EC45CAD518ADC7CE0063DD11 /* Logo-iOS-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Logo-iOS-Info.plist"; sourceTree = ""; }; 29 | EC45CAD718ADC7CE0063DD11 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 30 | EC45CAD918ADC7CE0063DD11 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 31 | EC45CADB18ADC7CE0063DD11 /* Logo-iOS-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Logo-iOS-Prefix.pch"; sourceTree = ""; }; 32 | EC45CADC18ADC7CE0063DD11 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 33 | EC45CADD18ADC7CE0063DD11 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 34 | EC45CAE018ADC7CE0063DD11 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main_iPhone.storyboard; sourceTree = ""; }; 35 | EC45CAE318ADC7CE0063DD11 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main_iPad.storyboard; sourceTree = ""; }; 36 | EC45CAE518ADC7CE0063DD11 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 37 | EC45CAE618ADC7CE0063DD11 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 38 | EC45CAE818ADC7CE0063DD11 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 39 | EC45CB0318ADC7E80063DD11 /* libFBShimmering.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libFBShimmering.a; path = "../../../Library/Developer/Xcode/DerivedData/FBShimmering-amnevtoymcgzwwazjmzbwvbeduoi/Build/Products/Debug-iphoneos/libFBShimmering.a"; sourceTree = ""; }; 40 | /* End PBXFileReference section */ 41 | 42 | /* Begin PBXFrameworksBuildPhase section */ 43 | EC45CAC718ADC7CE0063DD11 /* Frameworks */ = { 44 | isa = PBXFrameworksBuildPhase; 45 | buildActionMask = 2147483647; 46 | files = ( 47 | 077ACA6E1CBD6B7200B3A708 /* UIKit.framework in Frameworks */, 48 | EC45CB0418ADC7E80063DD11 /* libFBShimmering.a in Frameworks */, 49 | EC45CAD018ADC7CE0063DD11 /* CoreGraphics.framework in Frameworks */, 50 | EC45CACE18ADC7CE0063DD11 /* Foundation.framework in Frameworks */, 51 | ); 52 | runOnlyForDeploymentPostprocessing = 0; 53 | }; 54 | /* End PBXFrameworksBuildPhase section */ 55 | 56 | /* Begin PBXGroup section */ 57 | EC45CABF18ADC7920063DD11 = { 58 | isa = PBXGroup; 59 | children = ( 60 | ECC5761518ADEDFC00C2BFB8 /* Logo */, 61 | EC45CACC18ADC7CE0063DD11 /* Frameworks */, 62 | EC45CACB18ADC7CE0063DD11 /* Products */, 63 | ); 64 | indentWidth = 2; 65 | sourceTree = ""; 66 | tabWidth = 2; 67 | }; 68 | EC45CACB18ADC7CE0063DD11 /* Products */ = { 69 | isa = PBXGroup; 70 | children = ( 71 | EC45CACA18ADC7CE0063DD11 /* Logo-iOS.app */, 72 | ); 73 | name = Products; 74 | sourceTree = ""; 75 | }; 76 | EC45CACC18ADC7CE0063DD11 /* Frameworks */ = { 77 | isa = PBXGroup; 78 | children = ( 79 | EC45CB0318ADC7E80063DD11 /* libFBShimmering.a */, 80 | EC45CACD18ADC7CE0063DD11 /* Foundation.framework */, 81 | EC45CACF18ADC7CE0063DD11 /* CoreGraphics.framework */, 82 | 077ACA6D1CBD6B7200B3A708 /* UIKit.framework */, 83 | ); 84 | name = Frameworks; 85 | sourceTree = ""; 86 | }; 87 | EC45CAD318ADC7CE0063DD11 /* Logo-iOS */ = { 88 | isa = PBXGroup; 89 | children = ( 90 | EC45CADC18ADC7CE0063DD11 /* AppDelegate.h */, 91 | EC45CADD18ADC7CE0063DD11 /* AppDelegate.m */, 92 | EC45CADF18ADC7CE0063DD11 /* Main_iPhone.storyboard */, 93 | EC45CAE218ADC7CE0063DD11 /* Main_iPad.storyboard */, 94 | EC45CAE518ADC7CE0063DD11 /* ViewController.h */, 95 | EC45CAE618ADC7CE0063DD11 /* ViewController.m */, 96 | EC45CAE818ADC7CE0063DD11 /* Images.xcassets */, 97 | EC45CAD418ADC7CE0063DD11 /* Supporting Files */, 98 | ); 99 | path = "Logo-iOS"; 100 | sourceTree = ""; 101 | }; 102 | EC45CAD418ADC7CE0063DD11 /* Supporting Files */ = { 103 | isa = PBXGroup; 104 | children = ( 105 | EC45CAD518ADC7CE0063DD11 /* Logo-iOS-Info.plist */, 106 | EC45CAD618ADC7CE0063DD11 /* InfoPlist.strings */, 107 | EC45CAD918ADC7CE0063DD11 /* main.m */, 108 | EC45CADB18ADC7CE0063DD11 /* Logo-iOS-Prefix.pch */, 109 | ); 110 | name = "Supporting Files"; 111 | sourceTree = ""; 112 | }; 113 | ECC5761518ADEDFC00C2BFB8 /* Logo */ = { 114 | isa = PBXGroup; 115 | children = ( 116 | EC45CAD318ADC7CE0063DD11 /* Logo-iOS */, 117 | ); 118 | name = Logo; 119 | sourceTree = ""; 120 | }; 121 | /* End PBXGroup section */ 122 | 123 | /* Begin PBXNativeTarget section */ 124 | EC45CAC918ADC7CE0063DD11 /* Logo-iOS */ = { 125 | isa = PBXNativeTarget; 126 | buildConfigurationList = EC45CAFD18ADC7CE0063DD11 /* Build configuration list for PBXNativeTarget "Logo-iOS" */; 127 | buildPhases = ( 128 | EC45CAC618ADC7CE0063DD11 /* Sources */, 129 | EC45CAC718ADC7CE0063DD11 /* Frameworks */, 130 | EC45CAC818ADC7CE0063DD11 /* Resources */, 131 | ); 132 | buildRules = ( 133 | ); 134 | dependencies = ( 135 | ); 136 | name = "Logo-iOS"; 137 | productName = "Logo-iOS"; 138 | productReference = EC45CACA18ADC7CE0063DD11 /* Logo-iOS.app */; 139 | productType = "com.apple.product-type.application"; 140 | }; 141 | /* End PBXNativeTarget section */ 142 | 143 | /* Begin PBXProject section */ 144 | EC45CAC018ADC7920063DD11 /* Project object */ = { 145 | isa = PBXProject; 146 | attributes = { 147 | LastUpgradeCheck = 0510; 148 | }; 149 | buildConfigurationList = EC45CAC318ADC7920063DD11 /* Build configuration list for PBXProject "Examples" */; 150 | compatibilityVersion = "Xcode 3.2"; 151 | developmentRegion = English; 152 | hasScannedForEncodings = 0; 153 | knownRegions = ( 154 | en, 155 | Base, 156 | ); 157 | mainGroup = EC45CABF18ADC7920063DD11; 158 | productRefGroup = EC45CACB18ADC7CE0063DD11 /* Products */; 159 | projectDirPath = ""; 160 | projectRoot = ""; 161 | targets = ( 162 | EC45CAC918ADC7CE0063DD11 /* Logo-iOS */, 163 | ); 164 | }; 165 | /* End PBXProject section */ 166 | 167 | /* Begin PBXResourcesBuildPhase section */ 168 | EC45CAC818ADC7CE0063DD11 /* Resources */ = { 169 | isa = PBXResourcesBuildPhase; 170 | buildActionMask = 2147483647; 171 | files = ( 172 | EC45CAE418ADC7CE0063DD11 /* Main_iPad.storyboard in Resources */, 173 | EC45CAE918ADC7CE0063DD11 /* Images.xcassets in Resources */, 174 | EC45CAE118ADC7CE0063DD11 /* Main_iPhone.storyboard in Resources */, 175 | EC45CAD818ADC7CE0063DD11 /* InfoPlist.strings in Resources */, 176 | ); 177 | runOnlyForDeploymentPostprocessing = 0; 178 | }; 179 | /* End PBXResourcesBuildPhase section */ 180 | 181 | /* Begin PBXSourcesBuildPhase section */ 182 | EC45CAC618ADC7CE0063DD11 /* Sources */ = { 183 | isa = PBXSourcesBuildPhase; 184 | buildActionMask = 2147483647; 185 | files = ( 186 | EC45CAE718ADC7CE0063DD11 /* ViewController.m in Sources */, 187 | EC45CADE18ADC7CE0063DD11 /* AppDelegate.m in Sources */, 188 | EC45CADA18ADC7CE0063DD11 /* main.m in Sources */, 189 | ); 190 | runOnlyForDeploymentPostprocessing = 0; 191 | }; 192 | /* End PBXSourcesBuildPhase section */ 193 | 194 | /* Begin PBXVariantGroup section */ 195 | EC45CAD618ADC7CE0063DD11 /* InfoPlist.strings */ = { 196 | isa = PBXVariantGroup; 197 | children = ( 198 | EC45CAD718ADC7CE0063DD11 /* en */, 199 | ); 200 | name = InfoPlist.strings; 201 | sourceTree = ""; 202 | }; 203 | EC45CADF18ADC7CE0063DD11 /* Main_iPhone.storyboard */ = { 204 | isa = PBXVariantGroup; 205 | children = ( 206 | EC45CAE018ADC7CE0063DD11 /* Base */, 207 | ); 208 | name = Main_iPhone.storyboard; 209 | sourceTree = ""; 210 | }; 211 | EC45CAE218ADC7CE0063DD11 /* Main_iPad.storyboard */ = { 212 | isa = PBXVariantGroup; 213 | children = ( 214 | EC45CAE318ADC7CE0063DD11 /* Base */, 215 | ); 216 | name = Main_iPad.storyboard; 217 | sourceTree = ""; 218 | }; 219 | /* End PBXVariantGroup section */ 220 | 221 | /* Begin XCBuildConfiguration section */ 222 | EC45CAC418ADC7920063DD11 /* Debug */ = { 223 | isa = XCBuildConfiguration; 224 | buildSettings = { 225 | IPHONEOS_DEPLOYMENT_TARGET = 6.0; 226 | ONLY_ACTIVE_ARCH = YES; 227 | SDKROOT = iphoneos; 228 | }; 229 | name = Debug; 230 | }; 231 | EC45CAC518ADC7920063DD11 /* Release */ = { 232 | isa = XCBuildConfiguration; 233 | buildSettings = { 234 | IPHONEOS_DEPLOYMENT_TARGET = 6.0; 235 | SDKROOT = iphoneos; 236 | }; 237 | name = Release; 238 | }; 239 | EC45CAFE18ADC7CE0063DD11 /* Debug */ = { 240 | isa = XCBuildConfiguration; 241 | buildSettings = { 242 | ALWAYS_SEARCH_USER_PATHS = NO; 243 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 244 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 245 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 246 | CLANG_CXX_LIBRARY = "libc++"; 247 | CLANG_ENABLE_MODULES = YES; 248 | CLANG_ENABLE_OBJC_ARC = YES; 249 | CLANG_WARN_BOOL_CONVERSION = YES; 250 | CLANG_WARN_CONSTANT_CONVERSION = YES; 251 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 252 | CLANG_WARN_EMPTY_BODY = YES; 253 | CLANG_WARN_ENUM_CONVERSION = YES; 254 | CLANG_WARN_INT_CONVERSION = YES; 255 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 256 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 257 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 258 | COPY_PHASE_STRIP = NO; 259 | FRAMEWORK_SEARCH_PATHS = ( 260 | "$(inherited)", 261 | "$(DEVELOPER_FRAMEWORKS_DIR)", 262 | ); 263 | GCC_C_LANGUAGE_STANDARD = gnu99; 264 | GCC_DYNAMIC_NO_PIC = NO; 265 | GCC_OPTIMIZATION_LEVEL = 0; 266 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 267 | GCC_PREFIX_HEADER = "Logo-iOS/Logo-iOS-Prefix.pch"; 268 | GCC_PREPROCESSOR_DEFINITIONS = ( 269 | "DEBUG=1", 270 | "$(inherited)", 271 | ); 272 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 273 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 274 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 275 | GCC_WARN_UNDECLARED_SELECTOR = YES; 276 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 277 | GCC_WARN_UNUSED_FUNCTION = YES; 278 | GCC_WARN_UNUSED_VARIABLE = YES; 279 | INFOPLIST_FILE = "Logo-iOS/Logo-iOS-Info.plist"; 280 | IPHONEOS_DEPLOYMENT_TARGET = 6.0; 281 | LIBRARY_SEARCH_PATHS = ( 282 | "$(inherited)", 283 | "$(USER_LIBRARY_DIR)/Developer/Xcode/DerivedData/FBShimmering-amnevtoymcgzwwazjmzbwvbeduoi/Build/Products/Debug-iphoneos", 284 | ); 285 | ONLY_ACTIVE_ARCH = YES; 286 | PRODUCT_NAME = "$(TARGET_NAME)"; 287 | SDKROOT = iphoneos; 288 | TARGETED_DEVICE_FAMILY = "1,2"; 289 | WRAPPER_EXTENSION = app; 290 | }; 291 | name = Debug; 292 | }; 293 | EC45CAFF18ADC7CE0063DD11 /* Release */ = { 294 | isa = XCBuildConfiguration; 295 | buildSettings = { 296 | ALWAYS_SEARCH_USER_PATHS = NO; 297 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 298 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 299 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 300 | CLANG_CXX_LIBRARY = "libc++"; 301 | CLANG_ENABLE_MODULES = YES; 302 | CLANG_ENABLE_OBJC_ARC = YES; 303 | CLANG_WARN_BOOL_CONVERSION = YES; 304 | CLANG_WARN_CONSTANT_CONVERSION = YES; 305 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 306 | CLANG_WARN_EMPTY_BODY = YES; 307 | CLANG_WARN_ENUM_CONVERSION = YES; 308 | CLANG_WARN_INT_CONVERSION = YES; 309 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 310 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 311 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 312 | COPY_PHASE_STRIP = YES; 313 | ENABLE_NS_ASSERTIONS = NO; 314 | FRAMEWORK_SEARCH_PATHS = ( 315 | "$(inherited)", 316 | "$(DEVELOPER_FRAMEWORKS_DIR)", 317 | ); 318 | GCC_C_LANGUAGE_STANDARD = gnu99; 319 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 320 | GCC_PREFIX_HEADER = "Logo-iOS/Logo-iOS-Prefix.pch"; 321 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 322 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 323 | GCC_WARN_UNDECLARED_SELECTOR = YES; 324 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 325 | GCC_WARN_UNUSED_FUNCTION = YES; 326 | GCC_WARN_UNUSED_VARIABLE = YES; 327 | INFOPLIST_FILE = "Logo-iOS/Logo-iOS-Info.plist"; 328 | IPHONEOS_DEPLOYMENT_TARGET = 6.0; 329 | LIBRARY_SEARCH_PATHS = ( 330 | "$(inherited)", 331 | "$(USER_LIBRARY_DIR)/Developer/Xcode/DerivedData/FBShimmering-amnevtoymcgzwwazjmzbwvbeduoi/Build/Products/Debug-iphoneos", 332 | ); 333 | PRODUCT_NAME = "$(TARGET_NAME)"; 334 | SDKROOT = iphoneos; 335 | TARGETED_DEVICE_FAMILY = "1,2"; 336 | VALIDATE_PRODUCT = YES; 337 | WRAPPER_EXTENSION = app; 338 | }; 339 | name = Release; 340 | }; 341 | /* End XCBuildConfiguration section */ 342 | 343 | /* Begin XCConfigurationList section */ 344 | EC45CAC318ADC7920063DD11 /* Build configuration list for PBXProject "Examples" */ = { 345 | isa = XCConfigurationList; 346 | buildConfigurations = ( 347 | EC45CAC418ADC7920063DD11 /* Debug */, 348 | EC45CAC518ADC7920063DD11 /* Release */, 349 | ); 350 | defaultConfigurationIsVisible = 0; 351 | defaultConfigurationName = Release; 352 | }; 353 | EC45CAFD18ADC7CE0063DD11 /* Build configuration list for PBXNativeTarget "Logo-iOS" */ = { 354 | isa = XCConfigurationList; 355 | buildConfigurations = ( 356 | EC45CAFE18ADC7CE0063DD11 /* Debug */, 357 | EC45CAFF18ADC7CE0063DD11 /* Release */, 358 | ); 359 | defaultConfigurationIsVisible = 0; 360 | defaultConfigurationName = Release; 361 | }; 362 | /* End XCConfigurationList section */ 363 | }; 364 | rootObject = EC45CAC018ADC7920063DD11 /* Project object */; 365 | } 366 | -------------------------------------------------------------------------------- /Examples/Examples.xcodeproj/xcshareddata/xcschemes/Logo-iOS.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 43 | 45 | 51 | 52 | 53 | 54 | 60 | 62 | 68 | 69 | 70 | 71 | 73 | 74 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /Examples/LICENSE: -------------------------------------------------------------------------------- 1 | This file provided by Facebook is for non-commercial testing and evaluation 2 | purposes only. Facebook reserves all rights not expressly granted. 3 | 4 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 5 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 6 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 7 | FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 8 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 9 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | -------------------------------------------------------------------------------- /Examples/Logo-iOS/AppDelegate.h: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2014-present, Facebook, Inc. 3 | All rights reserved. 4 | 5 | This source code is licensed under the BSD-style license found in the 6 | LICENSE file in the root directory of this source tree. An additional grant 7 | of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #import 11 | 12 | @interface AppDelegate : UIResponder 13 | 14 | @property (strong, nonatomic) UIWindow *window; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /Examples/Logo-iOS/AppDelegate.m: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2014-present, Facebook, Inc. 3 | All rights reserved. 4 | 5 | This source code is licensed under the BSD-style license found in the 6 | LICENSE file in the root directory of this source tree. An additional grant 7 | of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #import "AppDelegate.h" 11 | 12 | @implementation AppDelegate 13 | 14 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 15 | { 16 | return YES; 17 | } 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /Examples/Logo-iOS/Base.lproj/Main_iPad.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 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /Examples/Logo-iOS/Base.lproj/Main_iPhone.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 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /Examples/Logo-iOS/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" : "ipad", 20 | "size" : "29x29", 21 | "scale" : "1x" 22 | }, 23 | { 24 | "idiom" : "ipad", 25 | "size" : "29x29", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "ipad", 30 | "size" : "40x40", 31 | "scale" : "1x" 32 | }, 33 | { 34 | "idiom" : "ipad", 35 | "size" : "40x40", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "76x76", 41 | "scale" : "1x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "76x76", 46 | "scale" : "2x" 47 | } 48 | ], 49 | "info" : { 50 | "version" : 1, 51 | "author" : "xcode" 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Examples/Logo-iOS/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 | "orientation" : "portrait", 20 | "idiom" : "ipad", 21 | "extent" : "full-screen", 22 | "minimum-system-version" : "7.0", 23 | "scale" : "1x" 24 | }, 25 | { 26 | "orientation" : "landscape", 27 | "idiom" : "ipad", 28 | "extent" : "full-screen", 29 | "minimum-system-version" : "7.0", 30 | "scale" : "1x" 31 | }, 32 | { 33 | "orientation" : "portrait", 34 | "idiom" : "ipad", 35 | "extent" : "full-screen", 36 | "minimum-system-version" : "7.0", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "orientation" : "landscape", 41 | "idiom" : "ipad", 42 | "extent" : "full-screen", 43 | "minimum-system-version" : "7.0", 44 | "scale" : "2x" 45 | } 46 | ], 47 | "info" : { 48 | "version" : 1, 49 | "author" : "xcode" 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Examples/Logo-iOS/Images.xcassets/Wallpaper.imageset/1800126_10152272440319357_261758585_o.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookarchive/Shimmer/a7eba17652638ef894407ce13a4bc5ca347ba488/Examples/Logo-iOS/Images.xcassets/Wallpaper.imageset/1800126_10152272440319357_261758585_o.png -------------------------------------------------------------------------------- /Examples/Logo-iOS/Images.xcassets/Wallpaper.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "1800126_10152272440319357_261758585_o.png" 7 | } 8 | ], 9 | "info" : { 10 | "version" : 1, 11 | "author" : "xcode" 12 | } 13 | } -------------------------------------------------------------------------------- /Examples/Logo-iOS/Logo-iOS-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | com.facebook.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.0 25 | LSRequiresIPhoneOS 26 | 27 | UIMainStoryboardFile 28 | Main_iPhone 29 | UIMainStoryboardFile~ipad 30 | Main_iPad 31 | UIRequiredDeviceCapabilities 32 | 33 | armv7 34 | 35 | UISupportedInterfaceOrientations 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationLandscapeLeft 39 | UIInterfaceOrientationLandscapeRight 40 | 41 | UIStatusBarHidden 42 | 43 | UIStatusBarStyle 44 | 45 | UISupportedInterfaceOrientations~ipad 46 | 47 | UIInterfaceOrientationPortrait 48 | UIInterfaceOrientationPortraitUpsideDown 49 | UIInterfaceOrientationLandscapeLeft 50 | UIInterfaceOrientationLandscapeRight 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /Examples/Logo-iOS/Logo-iOS-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 | -------------------------------------------------------------------------------- /Examples/Logo-iOS/ViewController.h: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2014-present, Facebook, Inc. 3 | All rights reserved. 4 | 5 | This source code is licensed under the BSD-style license found in the 6 | LICENSE file in the root directory of this source tree. An additional grant 7 | of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #import 11 | 12 | @interface ViewController : UIViewController 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /Examples/Logo-iOS/ViewController.m: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2014-present, Facebook, Inc. 3 | All rights reserved. 4 | 5 | This source code is licensed under the BSD-style license found in the 6 | LICENSE file in the root directory of this source tree. An additional grant 7 | of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #import "ViewController.h" 11 | 12 | #import 13 | 14 | @interface ViewController () 15 | 16 | @end 17 | 18 | @implementation ViewController 19 | { 20 | UIImageView *_wallpaperView; 21 | FBShimmeringView *_shimmeringView; 22 | UILabel *_logoLabel; 23 | 24 | UILabel *_valueLabel; 25 | 26 | CGFloat _panStartValue; 27 | BOOL _panVertical; 28 | } 29 | 30 | - (BOOL)prefersStatusBarHidden 31 | { 32 | return YES; 33 | } 34 | 35 | - (void)viewDidLoad 36 | { 37 | [super viewDidLoad]; 38 | self.view.backgroundColor = [UIColor blackColor]; 39 | 40 | _wallpaperView = [[UIImageView alloc] initWithFrame:self.view.bounds]; 41 | _wallpaperView.image = [UIImage imageNamed:@"Wallpaper"]; 42 | _wallpaperView.contentMode = UIViewContentModeScaleAspectFill; 43 | [self.view addSubview:_wallpaperView]; 44 | 45 | CGRect valueFrame = self.view.bounds; 46 | valueFrame.size.height = valueFrame.size.height * 0.25; 47 | 48 | _valueLabel = [[UILabel alloc] initWithFrame:valueFrame]; 49 | _valueLabel.font = [UIFont fontWithName:@"HelveticaNeue-UltraLight" size:32.0]; 50 | _valueLabel.textColor = [UIColor whiteColor]; 51 | _valueLabel.textAlignment = NSTextAlignmentCenter; 52 | _valueLabel.numberOfLines = 0; 53 | _valueLabel.alpha = 0.0; 54 | _valueLabel.backgroundColor = [UIColor clearColor]; 55 | [self.view addSubview:_valueLabel]; 56 | 57 | _shimmeringView = [[FBShimmeringView alloc] init]; 58 | _shimmeringView.shimmering = YES; 59 | _shimmeringView.shimmeringBeginFadeDuration = 0.3; 60 | _shimmeringView.shimmeringOpacity = 0.3; 61 | [self.view addSubview:_shimmeringView]; 62 | 63 | _logoLabel = [[UILabel alloc] initWithFrame:_shimmeringView.bounds]; 64 | _logoLabel.text = @"Shimmer"; 65 | _logoLabel.font = [UIFont fontWithName:@"HelveticaNeue-UltraLight" size:60.0]; 66 | _logoLabel.textColor = [UIColor whiteColor]; 67 | _logoLabel.textAlignment = NSTextAlignmentCenter; 68 | _logoLabel.backgroundColor = [UIColor clearColor]; 69 | _shimmeringView.contentView = _logoLabel; 70 | 71 | UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(_tapped:)]; 72 | [self.view addGestureRecognizer:tapRecognizer]; 73 | 74 | UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(_panned:)]; 75 | [self.view addGestureRecognizer:panRecognizer]; 76 | } 77 | 78 | - (void)viewWillLayoutSubviews 79 | { 80 | [super viewWillLayoutSubviews]; 81 | 82 | CGRect shimmeringFrame = self.view.bounds; 83 | shimmeringFrame.origin.y = shimmeringFrame.size.height * 0.68; 84 | shimmeringFrame.size.height = shimmeringFrame.size.height * 0.32; 85 | _shimmeringView.frame = shimmeringFrame; 86 | } 87 | 88 | - (void)_tapped:(UITapGestureRecognizer *)tapRecognizer 89 | { 90 | _shimmeringView.shimmering = !_shimmeringView.shimmering; 91 | } 92 | 93 | - (void)_panned:(UIPanGestureRecognizer *)panRecognizer 94 | { 95 | CGPoint translation = [panRecognizer translationInView:self.view]; 96 | CGPoint velocity = [panRecognizer velocityInView:self.view]; 97 | 98 | if (panRecognizer.state == UIGestureRecognizerStateBegan) { 99 | #if CGFLOAT_IS_DOUBLE 100 | _panVertical = (fabs(velocity.y) > fabs(velocity.x)); 101 | #else 102 | _panVertical = (fabsf(velocity.y) > fabsf(velocity.x)); 103 | #endif 104 | 105 | if (_panVertical) { 106 | _panStartValue = _shimmeringView.shimmeringSpeed; 107 | } else { 108 | _panStartValue = _shimmeringView.shimmeringOpacity; 109 | } 110 | 111 | [self _animateValueLabelVisible:YES]; 112 | } else if (panRecognizer.state == UIGestureRecognizerStateChanged) { 113 | CGFloat directional = (_panVertical ? translation.y : translation.x); 114 | CGFloat possible = (_panVertical ? self.view.bounds.size.height : self.view.bounds.size.width); 115 | 116 | CGFloat progress = (directional / possible); 117 | 118 | if (_panVertical) { 119 | _shimmeringView.shimmeringSpeed = fmaxf(0.0, fminf(1000.0, _panStartValue + progress * 200.0)); 120 | _valueLabel.text = [NSString stringWithFormat:@"Speed\n%.1f", _shimmeringView.shimmeringSpeed]; 121 | } else { 122 | _shimmeringView.shimmeringOpacity = fmaxf(0.0, fminf(1.0, _panStartValue + progress * 0.5)); 123 | _valueLabel.text = [NSString stringWithFormat:@"Opacity\n%.2f", _shimmeringView.shimmeringOpacity]; 124 | } 125 | } else if (panRecognizer.state == UIGestureRecognizerStateEnded || 126 | panRecognizer.state == UIGestureRecognizerStateCancelled) { 127 | [self _animateValueLabelVisible:NO]; 128 | } 129 | } 130 | 131 | - (void)_animateValueLabelVisible:(BOOL)visible 132 | { 133 | UIViewAnimationOptions options = UIViewAnimationOptionBeginFromCurrentState; 134 | void (^animations)() = ^{ 135 | _valueLabel.alpha = (visible ? 1.0 : 0.0); 136 | }; 137 | [UIView animateWithDuration:0.5 delay:0.0 options:options animations:animations completion:NULL]; 138 | } 139 | 140 | @end 141 | -------------------------------------------------------------------------------- /Examples/Logo-iOS/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Examples/Logo-iOS/main.m: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2014-present, Facebook, Inc. 3 | All rights reserved. 4 | 5 | This source code is licensed under the BSD-style license found in the 6 | LICENSE file in the root directory of this source tree. An additional grant 7 | of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #import 11 | 12 | #import "AppDelegate.h" 13 | 14 | int main(int argc, char * argv[]) 15 | { 16 | @autoreleasepool { 17 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /FBShimmering.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 077ACA6A1CBD6B4300B3A708 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 077ACA691CBD6B4300B3A708 /* UIKit.framework */; }; 11 | 077ACA6C1CBD6B5800B3A708 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 077ACA6B1CBD6B5800B3A708 /* CoreGraphics.framework */; }; 12 | 1899D26B18BD1CFB0035A1B0 /* FBShimmeringView.m in Sources */ = {isa = PBXBuildFile; fileRef = 1899D26718BD1CFB0035A1B0 /* FBShimmeringView.m */; }; 13 | 1899D26C18BD1CFB0035A1B0 /* FBShimmeringLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 1899D26918BD1CFB0035A1B0 /* FBShimmeringLayer.m */; }; 14 | 1899D27418BD201B0035A1B0 /* FBShimmering.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 1899D26D18BD1D070035A1B0 /* FBShimmering.h */; }; 15 | 1899D27518BD201B0035A1B0 /* FBShimmeringView.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 1899D26818BD1CFB0035A1B0 /* FBShimmeringView.h */; }; 16 | 1899D27618BD201B0035A1B0 /* FBShimmeringLayer.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 1899D26A18BD1CFB0035A1B0 /* FBShimmeringLayer.h */; }; 17 | A1C8E0BF1E13C0C9002D6069 /* Shimmer.h in Headers */ = {isa = PBXBuildFile; fileRef = A1C8E0BD1E13C0C9002D6069 /* Shimmer.h */; settings = {ATTRIBUTES = (Public, ); }; }; 18 | A1C8E0C31E13C0D3002D6069 /* FBShimmering.h in Headers */ = {isa = PBXBuildFile; fileRef = 1899D26D18BD1D070035A1B0 /* FBShimmering.h */; settings = {ATTRIBUTES = (Public, ); }; }; 19 | A1C8E0C41E13C0D3002D6069 /* FBShimmeringView.h in Headers */ = {isa = PBXBuildFile; fileRef = 1899D26818BD1CFB0035A1B0 /* FBShimmeringView.h */; settings = {ATTRIBUTES = (Public, ); }; }; 20 | A1C8E0C51E13C0D3002D6069 /* FBShimmeringLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 1899D26A18BD1CFB0035A1B0 /* FBShimmeringLayer.h */; settings = {ATTRIBUTES = (Public, ); }; }; 21 | A1C8E0C61E13C0D8002D6069 /* FBShimmeringView.m in Sources */ = {isa = PBXBuildFile; fileRef = 1899D26718BD1CFB0035A1B0 /* FBShimmeringView.m */; }; 22 | A1C8E0C71E13C0D8002D6069 /* FBShimmeringLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 1899D26918BD1CFB0035A1B0 /* FBShimmeringLayer.m */; }; 23 | ECEA610218A49C620064AFF4 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ECEA610118A49C620064AFF4 /* Foundation.framework */; }; 24 | /* End PBXBuildFile section */ 25 | 26 | /* Begin PBXCopyFilesBuildPhase section */ 27 | ECEA60FC18A49C620064AFF4 /* CopyFiles */ = { 28 | isa = PBXCopyFilesBuildPhase; 29 | buildActionMask = 2147483647; 30 | dstPath = "$(PRODUCT_NAME)Headers"; 31 | dstSubfolderSpec = 16; 32 | files = ( 33 | 1899D27418BD201B0035A1B0 /* FBShimmering.h in CopyFiles */, 34 | 1899D27518BD201B0035A1B0 /* FBShimmeringView.h in CopyFiles */, 35 | 1899D27618BD201B0035A1B0 /* FBShimmeringLayer.h in CopyFiles */, 36 | ); 37 | runOnlyForDeploymentPostprocessing = 0; 38 | }; 39 | /* End PBXCopyFilesBuildPhase section */ 40 | 41 | /* Begin PBXFileReference section */ 42 | 077ACA691CBD6B4300B3A708 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 43 | 077ACA6B1CBD6B5800B3A708 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 44 | 1899D26718BD1CFB0035A1B0 /* FBShimmeringView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBShimmeringView.m; sourceTree = ""; }; 45 | 1899D26818BD1CFB0035A1B0 /* FBShimmeringView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBShimmeringView.h; sourceTree = ""; }; 46 | 1899D26918BD1CFB0035A1B0 /* FBShimmeringLayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBShimmeringLayer.m; sourceTree = ""; }; 47 | 1899D26A18BD1CFB0035A1B0 /* FBShimmeringLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBShimmeringLayer.h; sourceTree = ""; }; 48 | 1899D26D18BD1D070035A1B0 /* FBShimmering.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBShimmering.h; sourceTree = ""; }; 49 | A1C8E0BB1E13C0C9002D6069 /* Shimmer.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Shimmer.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 50 | A1C8E0BD1E13C0C9002D6069 /* Shimmer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Shimmer.h; sourceTree = ""; }; 51 | A1C8E0BE1E13C0C9002D6069 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 52 | EC8BB5B318A5A1EE00EB2793 /* LICENSE */ = {isa = PBXFileReference; lastKnownFileType = text; path = LICENSE; sourceTree = ""; }; 53 | EC8BB5B418A5A1F500EB2793 /* PATENTS */ = {isa = PBXFileReference; lastKnownFileType = text; path = PATENTS; sourceTree = ""; }; 54 | EC8BB5B518A5A30700EB2793 /* CONTRIBUTING.md */ = {isa = PBXFileReference; lastKnownFileType = text; path = CONTRIBUTING.md; sourceTree = ""; }; 55 | EC8BB5B618A5A30F00EB2793 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = text; path = README.md; sourceTree = ""; }; 56 | ECEA60FE18A49C620064AFF4 /* libFBShimmering.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libFBShimmering.a; sourceTree = BUILT_PRODUCTS_DIR; }; 57 | ECEA610118A49C620064AFF4 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 58 | ECEA610518A49C620064AFF4 /* FBShimmering-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "FBShimmering-Prefix.pch"; sourceTree = ""; }; 59 | /* End PBXFileReference section */ 60 | 61 | /* Begin PBXFrameworksBuildPhase section */ 62 | A1C8E0B71E13C0C9002D6069 /* Frameworks */ = { 63 | isa = PBXFrameworksBuildPhase; 64 | buildActionMask = 2147483647; 65 | files = ( 66 | ); 67 | runOnlyForDeploymentPostprocessing = 0; 68 | }; 69 | ECEA60FB18A49C620064AFF4 /* Frameworks */ = { 70 | isa = PBXFrameworksBuildPhase; 71 | buildActionMask = 2147483647; 72 | files = ( 73 | 077ACA6C1CBD6B5800B3A708 /* CoreGraphics.framework in Frameworks */, 74 | 077ACA6A1CBD6B4300B3A708 /* UIKit.framework in Frameworks */, 75 | ECEA610218A49C620064AFF4 /* Foundation.framework in Frameworks */, 76 | ); 77 | runOnlyForDeploymentPostprocessing = 0; 78 | }; 79 | /* End PBXFrameworksBuildPhase section */ 80 | 81 | /* Begin PBXGroup section */ 82 | A1C8E0BC1E13C0C9002D6069 /* Framework */ = { 83 | isa = PBXGroup; 84 | children = ( 85 | A1C8E0BD1E13C0C9002D6069 /* Shimmer.h */, 86 | A1C8E0BE1E13C0C9002D6069 /* Info.plist */, 87 | ); 88 | path = Framework; 89 | sourceTree = ""; 90 | }; 91 | ECEA60F518A49C620064AFF4 = { 92 | isa = PBXGroup; 93 | children = ( 94 | EC8BB5B618A5A30F00EB2793 /* README.md */, 95 | EC8BB5B518A5A30700EB2793 /* CONTRIBUTING.md */, 96 | EC8BB5B318A5A1EE00EB2793 /* LICENSE */, 97 | EC8BB5B418A5A1F500EB2793 /* PATENTS */, 98 | ECEA610318A49C620064AFF4 /* FBShimmering */, 99 | A1C8E0BC1E13C0C9002D6069 /* Framework */, 100 | ECEA610018A49C620064AFF4 /* Frameworks */, 101 | ECEA60FF18A49C620064AFF4 /* Products */, 102 | ); 103 | indentWidth = 2; 104 | sourceTree = ""; 105 | tabWidth = 2; 106 | }; 107 | ECEA60FF18A49C620064AFF4 /* Products */ = { 108 | isa = PBXGroup; 109 | children = ( 110 | ECEA60FE18A49C620064AFF4 /* libFBShimmering.a */, 111 | A1C8E0BB1E13C0C9002D6069 /* Shimmer.framework */, 112 | ); 113 | name = Products; 114 | sourceTree = ""; 115 | }; 116 | ECEA610018A49C620064AFF4 /* Frameworks */ = { 117 | isa = PBXGroup; 118 | children = ( 119 | 077ACA6B1CBD6B5800B3A708 /* CoreGraphics.framework */, 120 | 077ACA691CBD6B4300B3A708 /* UIKit.framework */, 121 | ECEA610118A49C620064AFF4 /* Foundation.framework */, 122 | ); 123 | name = Frameworks; 124 | sourceTree = ""; 125 | }; 126 | ECEA610318A49C620064AFF4 /* FBShimmering */ = { 127 | isa = PBXGroup; 128 | children = ( 129 | 1899D26D18BD1D070035A1B0 /* FBShimmering.h */, 130 | 1899D26818BD1CFB0035A1B0 /* FBShimmeringView.h */, 131 | 1899D26718BD1CFB0035A1B0 /* FBShimmeringView.m */, 132 | 1899D26A18BD1CFB0035A1B0 /* FBShimmeringLayer.h */, 133 | 1899D26918BD1CFB0035A1B0 /* FBShimmeringLayer.m */, 134 | ECEA610418A49C620064AFF4 /* Supporting Files */, 135 | ); 136 | path = FBShimmering; 137 | sourceTree = ""; 138 | }; 139 | ECEA610418A49C620064AFF4 /* Supporting Files */ = { 140 | isa = PBXGroup; 141 | children = ( 142 | ECEA610518A49C620064AFF4 /* FBShimmering-Prefix.pch */, 143 | ); 144 | name = "Supporting Files"; 145 | sourceTree = ""; 146 | }; 147 | /* End PBXGroup section */ 148 | 149 | /* Begin PBXHeadersBuildPhase section */ 150 | A1C8E0B81E13C0C9002D6069 /* Headers */ = { 151 | isa = PBXHeadersBuildPhase; 152 | buildActionMask = 2147483647; 153 | files = ( 154 | A1C8E0BF1E13C0C9002D6069 /* Shimmer.h in Headers */, 155 | A1C8E0C31E13C0D3002D6069 /* FBShimmering.h in Headers */, 156 | A1C8E0C41E13C0D3002D6069 /* FBShimmeringView.h in Headers */, 157 | A1C8E0C51E13C0D3002D6069 /* FBShimmeringLayer.h in Headers */, 158 | ); 159 | runOnlyForDeploymentPostprocessing = 0; 160 | }; 161 | /* End PBXHeadersBuildPhase section */ 162 | 163 | /* Begin PBXNativeTarget section */ 164 | A1C8E0BA1E13C0C9002D6069 /* Shimmer */ = { 165 | isa = PBXNativeTarget; 166 | buildConfigurationList = A1C8E0C01E13C0C9002D6069 /* Build configuration list for PBXNativeTarget "Shimmer" */; 167 | buildPhases = ( 168 | A1C8E0B61E13C0C9002D6069 /* Sources */, 169 | A1C8E0B71E13C0C9002D6069 /* Frameworks */, 170 | A1C8E0B81E13C0C9002D6069 /* Headers */, 171 | A1C8E0B91E13C0C9002D6069 /* Resources */, 172 | ); 173 | buildRules = ( 174 | ); 175 | dependencies = ( 176 | ); 177 | name = Shimmer; 178 | productName = Shimmer; 179 | productReference = A1C8E0BB1E13C0C9002D6069 /* Shimmer.framework */; 180 | productType = "com.apple.product-type.framework"; 181 | }; 182 | ECEA60FD18A49C620064AFF4 /* FBShimmering */ = { 183 | isa = PBXNativeTarget; 184 | buildConfigurationList = ECEA612118A49C620064AFF4 /* Build configuration list for PBXNativeTarget "FBShimmering" */; 185 | buildPhases = ( 186 | ECEA60FA18A49C620064AFF4 /* Sources */, 187 | ECEA60FB18A49C620064AFF4 /* Frameworks */, 188 | ECEA60FC18A49C620064AFF4 /* CopyFiles */, 189 | ECEA612718A49DDD0064AFF4 /* ShellScript */, 190 | ); 191 | buildRules = ( 192 | ); 193 | dependencies = ( 194 | ); 195 | name = FBShimmering; 196 | productName = FBShimmering; 197 | productReference = ECEA60FE18A49C620064AFF4 /* libFBShimmering.a */; 198 | productType = "com.apple.product-type.library.static"; 199 | }; 200 | /* End PBXNativeTarget section */ 201 | 202 | /* Begin PBXProject section */ 203 | ECEA60F618A49C620064AFF4 /* Project object */ = { 204 | isa = PBXProject; 205 | attributes = { 206 | CLASSPREFIX = FB; 207 | LastUpgradeCheck = 0510; 208 | ORGANIZATIONNAME = Facebook; 209 | }; 210 | buildConfigurationList = ECEA60F918A49C620064AFF4 /* Build configuration list for PBXProject "FBShimmering" */; 211 | compatibilityVersion = "Xcode 3.2"; 212 | developmentRegion = English; 213 | hasScannedForEncodings = 0; 214 | knownRegions = ( 215 | en, 216 | ); 217 | mainGroup = ECEA60F518A49C620064AFF4; 218 | productRefGroup = ECEA60FF18A49C620064AFF4 /* Products */; 219 | projectDirPath = ""; 220 | projectRoot = ""; 221 | targets = ( 222 | ECEA60FD18A49C620064AFF4 /* FBShimmering */, 223 | A1C8E0BA1E13C0C9002D6069 /* Shimmer */, 224 | ); 225 | }; 226 | /* End PBXProject section */ 227 | 228 | /* Begin PBXResourcesBuildPhase section */ 229 | A1C8E0B91E13C0C9002D6069 /* Resources */ = { 230 | isa = PBXResourcesBuildPhase; 231 | buildActionMask = 2147483647; 232 | files = ( 233 | ); 234 | runOnlyForDeploymentPostprocessing = 0; 235 | }; 236 | /* End PBXResourcesBuildPhase section */ 237 | 238 | /* Begin PBXShellScriptBuildPhase section */ 239 | ECEA612718A49DDD0064AFF4 /* ShellScript */ = { 240 | isa = PBXShellScriptBuildPhase; 241 | buildActionMask = 2147483647; 242 | files = ( 243 | ); 244 | inputPaths = ( 245 | ); 246 | outputPaths = ( 247 | ); 248 | runOnlyForDeploymentPostprocessing = 0; 249 | shellPath = /bin/sh; 250 | shellScript = "set -e\n\nmkdir -p \"${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.framework/Versions/A/Headers\"\n\n# Link the \"Current\" version to \"A\"\n/bin/ln -sfh A \"${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.framework/Versions/Current\"\n/bin/ln -sfh Versions/Current/Headers \"${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.framework/Headers\"\n/bin/ln -sfh \"Versions/Current/${PRODUCT_NAME}\" \"${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.framework/${PRODUCT_NAME}\"\n\n# The -a ensures that the headers maintain the source modification date so that we don't constantly\n# cause propagating rebuilds of files that import these headers.\n/bin/cp -a \"${TARGET_BUILD_DIR}/${PUBLIC_HEADERS_FOLDER_PATH}/\" \"${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.framework/Versions/A/Headers\""; 251 | }; 252 | /* End PBXShellScriptBuildPhase section */ 253 | 254 | /* Begin PBXSourcesBuildPhase section */ 255 | A1C8E0B61E13C0C9002D6069 /* Sources */ = { 256 | isa = PBXSourcesBuildPhase; 257 | buildActionMask = 2147483647; 258 | files = ( 259 | A1C8E0C71E13C0D8002D6069 /* FBShimmeringLayer.m in Sources */, 260 | A1C8E0C61E13C0D8002D6069 /* FBShimmeringView.m in Sources */, 261 | ); 262 | runOnlyForDeploymentPostprocessing = 0; 263 | }; 264 | ECEA60FA18A49C620064AFF4 /* Sources */ = { 265 | isa = PBXSourcesBuildPhase; 266 | buildActionMask = 2147483647; 267 | files = ( 268 | 1899D26C18BD1CFB0035A1B0 /* FBShimmeringLayer.m in Sources */, 269 | 1899D26B18BD1CFB0035A1B0 /* FBShimmeringView.m in Sources */, 270 | ); 271 | runOnlyForDeploymentPostprocessing = 0; 272 | }; 273 | /* End PBXSourcesBuildPhase section */ 274 | 275 | /* Begin XCBuildConfiguration section */ 276 | A1C8E0C11E13C0C9002D6069 /* Debug */ = { 277 | isa = XCBuildConfiguration; 278 | buildSettings = { 279 | CLANG_ANALYZER_NONNULL = YES; 280 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 281 | CLANG_WARN_INFINITE_RECURSION = YES; 282 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 283 | CLANG_WARN_UNREACHABLE_CODE = YES; 284 | CODE_SIGN_IDENTITY = ""; 285 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 286 | CURRENT_PROJECT_VERSION = 1; 287 | DEBUG_INFORMATION_FORMAT = dwarf; 288 | DEFINES_MODULE = YES; 289 | DYLIB_COMPATIBILITY_VERSION = 1; 290 | DYLIB_CURRENT_VERSION = 1; 291 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 292 | ENABLE_STRICT_OBJC_MSGSEND = YES; 293 | ENABLE_TESTABILITY = YES; 294 | GCC_NO_COMMON_BLOCKS = YES; 295 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 296 | INFOPLIST_FILE = Framework/Info.plist; 297 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 298 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 299 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 300 | PRODUCT_BUNDLE_IDENTIFIER = com.facebook.Shimmer; 301 | PRODUCT_NAME = "$(TARGET_NAME)"; 302 | SKIP_INSTALL = YES; 303 | TARGETED_DEVICE_FAMILY = "1,2"; 304 | VERSIONING_SYSTEM = "apple-generic"; 305 | VERSION_INFO_PREFIX = ""; 306 | }; 307 | name = Debug; 308 | }; 309 | A1C8E0C21E13C0C9002D6069 /* Release */ = { 310 | isa = XCBuildConfiguration; 311 | buildSettings = { 312 | CLANG_ANALYZER_NONNULL = YES; 313 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 314 | CLANG_WARN_INFINITE_RECURSION = YES; 315 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 316 | CLANG_WARN_UNREACHABLE_CODE = YES; 317 | CODE_SIGN_IDENTITY = ""; 318 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 319 | COPY_PHASE_STRIP = NO; 320 | CURRENT_PROJECT_VERSION = 1; 321 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 322 | DEFINES_MODULE = YES; 323 | DYLIB_COMPATIBILITY_VERSION = 1; 324 | DYLIB_CURRENT_VERSION = 1; 325 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 326 | ENABLE_STRICT_OBJC_MSGSEND = YES; 327 | GCC_NO_COMMON_BLOCKS = YES; 328 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 329 | INFOPLIST_FILE = Framework/Info.plist; 330 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 331 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 332 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 333 | PRODUCT_BUNDLE_IDENTIFIER = com.facebook.Shimmer; 334 | PRODUCT_NAME = "$(TARGET_NAME)"; 335 | TARGETED_DEVICE_FAMILY = "1,2"; 336 | VERSIONING_SYSTEM = "apple-generic"; 337 | VERSION_INFO_PREFIX = ""; 338 | }; 339 | name = Release; 340 | }; 341 | ECEA611F18A49C620064AFF4 /* Debug */ = { 342 | isa = XCBuildConfiguration; 343 | buildSettings = { 344 | ALWAYS_SEARCH_USER_PATHS = NO; 345 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 346 | CLANG_CXX_LIBRARY = "libc++"; 347 | CLANG_ENABLE_MODULES = YES; 348 | CLANG_ENABLE_OBJC_ARC = YES; 349 | CLANG_WARN_BOOL_CONVERSION = YES; 350 | CLANG_WARN_CONSTANT_CONVERSION = YES; 351 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 352 | CLANG_WARN_EMPTY_BODY = YES; 353 | CLANG_WARN_ENUM_CONVERSION = YES; 354 | CLANG_WARN_INT_CONVERSION = YES; 355 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 356 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 357 | COPY_PHASE_STRIP = NO; 358 | GCC_C_LANGUAGE_STANDARD = gnu99; 359 | GCC_DYNAMIC_NO_PIC = NO; 360 | GCC_OPTIMIZATION_LEVEL = 0; 361 | GCC_PREPROCESSOR_DEFINITIONS = ( 362 | "DEBUG=1", 363 | "$(inherited)", 364 | ); 365 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 366 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 367 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 368 | GCC_WARN_UNDECLARED_SELECTOR = YES; 369 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 370 | GCC_WARN_UNUSED_FUNCTION = YES; 371 | GCC_WARN_UNUSED_VARIABLE = YES; 372 | IPHONEOS_DEPLOYMENT_TARGET = 6.0; 373 | ONLY_ACTIVE_ARCH = YES; 374 | SDKROOT = iphoneos; 375 | }; 376 | name = Debug; 377 | }; 378 | ECEA612018A49C620064AFF4 /* Release */ = { 379 | isa = XCBuildConfiguration; 380 | buildSettings = { 381 | ALWAYS_SEARCH_USER_PATHS = NO; 382 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 383 | CLANG_CXX_LIBRARY = "libc++"; 384 | CLANG_ENABLE_MODULES = YES; 385 | CLANG_ENABLE_OBJC_ARC = YES; 386 | CLANG_WARN_BOOL_CONVERSION = YES; 387 | CLANG_WARN_CONSTANT_CONVERSION = YES; 388 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 389 | CLANG_WARN_EMPTY_BODY = YES; 390 | CLANG_WARN_ENUM_CONVERSION = YES; 391 | CLANG_WARN_INT_CONVERSION = YES; 392 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 393 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 394 | COPY_PHASE_STRIP = YES; 395 | ENABLE_NS_ASSERTIONS = NO; 396 | GCC_C_LANGUAGE_STANDARD = gnu99; 397 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 398 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 399 | GCC_WARN_UNDECLARED_SELECTOR = YES; 400 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 401 | GCC_WARN_UNUSED_FUNCTION = YES; 402 | GCC_WARN_UNUSED_VARIABLE = YES; 403 | IPHONEOS_DEPLOYMENT_TARGET = 6.0; 404 | SDKROOT = iphoneos; 405 | VALIDATE_PRODUCT = YES; 406 | }; 407 | name = Release; 408 | }; 409 | ECEA612218A49C620064AFF4 /* Debug */ = { 410 | isa = XCBuildConfiguration; 411 | buildSettings = { 412 | COPY_PHASE_STRIP = NO; 413 | DEAD_CODE_STRIPPING = NO; 414 | DSTROOT = /tmp/FBShimmering.dst; 415 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 416 | GCC_PREFIX_HEADER = "FBShimmering/FBShimmering-Prefix.pch"; 417 | OTHER_LDFLAGS = "-ObjC"; 418 | PRODUCT_NAME = "$(TARGET_NAME)"; 419 | PUBLIC_HEADERS_FOLDER_PATH = "$(PROJECT_NAME)Headers"; 420 | SKIP_INSTALL = YES; 421 | STRIP_STYLE = "non-global"; 422 | }; 423 | name = Debug; 424 | }; 425 | ECEA612318A49C620064AFF4 /* Release */ = { 426 | isa = XCBuildConfiguration; 427 | buildSettings = { 428 | COPY_PHASE_STRIP = NO; 429 | DEAD_CODE_STRIPPING = NO; 430 | DSTROOT = /tmp/FBShimmering.dst; 431 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 432 | GCC_PREFIX_HEADER = "FBShimmering/FBShimmering-Prefix.pch"; 433 | OTHER_LDFLAGS = "-ObjC"; 434 | PRODUCT_NAME = "$(TARGET_NAME)"; 435 | PUBLIC_HEADERS_FOLDER_PATH = "$(PROJECT_NAME)Headers"; 436 | SKIP_INSTALL = YES; 437 | STRIP_STYLE = "non-global"; 438 | }; 439 | name = Release; 440 | }; 441 | /* End XCBuildConfiguration section */ 442 | 443 | /* Begin XCConfigurationList section */ 444 | A1C8E0C01E13C0C9002D6069 /* Build configuration list for PBXNativeTarget "Shimmer" */ = { 445 | isa = XCConfigurationList; 446 | buildConfigurations = ( 447 | A1C8E0C11E13C0C9002D6069 /* Debug */, 448 | A1C8E0C21E13C0C9002D6069 /* Release */, 449 | ); 450 | defaultConfigurationIsVisible = 0; 451 | defaultConfigurationName = Release; 452 | }; 453 | ECEA60F918A49C620064AFF4 /* Build configuration list for PBXProject "FBShimmering" */ = { 454 | isa = XCConfigurationList; 455 | buildConfigurations = ( 456 | ECEA611F18A49C620064AFF4 /* Debug */, 457 | ECEA612018A49C620064AFF4 /* Release */, 458 | ); 459 | defaultConfigurationIsVisible = 0; 460 | defaultConfigurationName = Release; 461 | }; 462 | ECEA612118A49C620064AFF4 /* Build configuration list for PBXNativeTarget "FBShimmering" */ = { 463 | isa = XCConfigurationList; 464 | buildConfigurations = ( 465 | ECEA612218A49C620064AFF4 /* Debug */, 466 | ECEA612318A49C620064AFF4 /* Release */, 467 | ); 468 | defaultConfigurationIsVisible = 0; 469 | defaultConfigurationName = Release; 470 | }; 471 | /* End XCConfigurationList section */ 472 | }; 473 | rootObject = ECEA60F618A49C620064AFF4 /* Project object */; 474 | } 475 | -------------------------------------------------------------------------------- /FBShimmering.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /FBShimmering.xcodeproj/xcshareddata/xcschemes/FBShimmering.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 43 | 44 | 50 | 51 | 57 | 58 | 59 | 60 | 62 | 63 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /FBShimmering.xcodeproj/xcshareddata/xcschemes/Framework.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 43 | 44 | 50 | 51 | 52 | 53 | 59 | 60 | 66 | 67 | 68 | 69 | 71 | 72 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /FBShimmering.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /FBShimmering.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /FBShimmering/FBShimmering-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 | #ifdef __OBJC__ 8 | #import 9 | #endif 10 | -------------------------------------------------------------------------------- /FBShimmering/FBShimmering.h: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2014-present, Facebook, Inc. 3 | All rights reserved. 4 | 5 | This source code is licensed under the BSD-style license found in the 6 | LICENSE file in the root directory of this source tree. An additional grant 7 | of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #import 11 | #import 12 | 13 | typedef NS_ENUM(NSInteger, FBShimmerDirection) { 14 | //! Shimmer animation goes from left to right 15 | FBShimmerDirectionRight, 16 | //! Shimmer animation goes from right to left 17 | FBShimmerDirectionLeft, 18 | //! Shimmer animation goes from below to above 19 | FBShimmerDirectionUp, 20 | //! Shimmer animation goes from above to below 21 | FBShimmerDirectionDown, 22 | }; 23 | 24 | static const float FBShimmerDefaultBeginTime = CGFLOAT_MAX; 25 | 26 | @protocol FBShimmering 27 | 28 | //! @abstract Set this to YES to start shimming and NO to stop. Defaults to NO. 29 | @property (assign, nonatomic, readwrite, getter = isShimmering) BOOL shimmering; 30 | 31 | //! @abstract The time interval between shimmerings in seconds. Defaults to 0.4. 32 | @property (assign, nonatomic, readwrite) CFTimeInterval shimmeringPauseDuration; 33 | 34 | //! @abstract The opacity of the content while it is shimmering. Defaults to 0.5. 35 | @property (assign, nonatomic, readwrite) CGFloat shimmeringAnimationOpacity; 36 | 37 | //! @abstract The opacity of the content before it is shimmering. Defaults to 1.0. 38 | @property (assign, nonatomic, readwrite) CGFloat shimmeringOpacity; 39 | 40 | //! @abstract The speed of shimmering, in points per second. Defaults to 230. 41 | @property (assign, nonatomic, readwrite) CGFloat shimmeringSpeed; 42 | 43 | //! @abstract The highlight length of shimmering. Range of [0,1], defaults to 1.0. 44 | @property (assign, nonatomic, readwrite) CGFloat shimmeringHighlightLength; 45 | 46 | //! @abstract Same as "shimmeringHighlightLength", just for downward compatibility. @deprecated 47 | @property (assign, nonatomic, readwrite, getter = shimmeringHighlightLength, setter = setShimmeringHighlightLength:) CGFloat shimmeringHighlightWidth DEPRECATED_MSG_ATTRIBUTE("Use shimmeringHighlightLength"); 48 | 49 | //! @abstract The direction of shimmering animation. Defaults to FBShimmerDirectionRight. 50 | @property (assign, nonatomic, readwrite) FBShimmerDirection shimmeringDirection; 51 | 52 | //! @abstract The duration of the fade used when shimmer begins. Defaults to 0.1. 53 | @property (assign, nonatomic, readwrite) CFTimeInterval shimmeringBeginFadeDuration; 54 | 55 | //! @abstract The duration of the fade used when shimmer ends. Defaults to 0.3. 56 | @property (assign, nonatomic, readwrite) CFTimeInterval shimmeringEndFadeDuration; 57 | 58 | /** 59 | @abstract The absolute CoreAnimation media time when the shimmer will fade in. 60 | @discussion Only valid after setting {@ref shimmering} to NO. 61 | */ 62 | @property (assign, nonatomic, readonly) CFTimeInterval shimmeringFadeTime; 63 | 64 | /** 65 | @abstract The absolute CoreAnimation media time when the shimmer will begin. 66 | @discussion Only valid after setting {@ref shimmering} to YES. 67 | */ 68 | @property (assign, nonatomic) CFTimeInterval shimmeringBeginTime; 69 | 70 | @end 71 | 72 | -------------------------------------------------------------------------------- /FBShimmering/FBShimmeringLayer.h: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2014-present, Facebook, Inc. 3 | All rights reserved. 4 | 5 | This source code is licensed under the BSD-style license found in the 6 | LICENSE file in the root directory of this source tree. An additional grant 7 | of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #import 11 | 12 | #import "FBShimmering.h" 13 | 14 | /** 15 | @abstract Lightweight, generic shimmering layer. 16 | */ 17 | @interface FBShimmeringLayer : CALayer 18 | 19 | //! @abstract The content layer to be shimmered. 20 | @property (strong, nonatomic) CALayer *contentLayer; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /FBShimmering/FBShimmeringLayer.m: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2014-present, Facebook, Inc. 3 | All rights reserved. 4 | 5 | This source code is licensed under the BSD-style license found in the 6 | LICENSE file in the root directory of this source tree. An additional grant 7 | of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #import "FBShimmeringLayer.h" 11 | 12 | #import 13 | #import 14 | #import 15 | 16 | #import 17 | #import 18 | 19 | #if !__has_feature(objc_arc) 20 | #error This file must be compiled with ARC. Convert your project to ARC or specify the -fobjc-arc flag. 21 | #endif 22 | 23 | #if TARGET_IPHONE_SIMULATOR 24 | UIKIT_EXTERN float UIAnimationDragCoefficient(void); // UIKit private drag coeffient, use judiciously 25 | #endif 26 | 27 | static CGFloat FBShimmeringLayerDragCoefficient(void) 28 | { 29 | #if TARGET_IPHONE_SIMULATOR 30 | return UIAnimationDragCoefficient(); 31 | #else 32 | return 1.0; 33 | #endif 34 | } 35 | 36 | static void FBShimmeringLayerAnimationApplyDragCoefficient(CAAnimation *animation) 37 | { 38 | CGFloat k = FBShimmeringLayerDragCoefficient(); 39 | 40 | if (k != 0 && k != 1) { 41 | animation.speed = 1 / k; 42 | } 43 | } 44 | 45 | // animations keys 46 | static NSString *const kFBShimmerSlideAnimationKey = @"slide"; 47 | static NSString *const kFBFadeAnimationKey = @"fade"; 48 | static NSString *const kFBEndFadeAnimationKey = @"fade-end"; 49 | 50 | static CABasicAnimation *fade_animation(CALayer *layer, CGFloat opacity, CFTimeInterval duration) 51 | { 52 | CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"opacity"]; 53 | animation.fromValue = @([(layer.presentationLayer ?: layer) opacity]); 54 | animation.toValue = @(opacity); 55 | animation.fillMode = kCAFillModeBoth; 56 | animation.removedOnCompletion = NO; 57 | animation.duration = duration; 58 | FBShimmeringLayerAnimationApplyDragCoefficient(animation); 59 | return animation; 60 | } 61 | 62 | static CABasicAnimation *shimmer_slide_animation(CFTimeInterval duration, FBShimmerDirection direction) 63 | { 64 | CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position"]; 65 | animation.toValue = [NSValue valueWithCGPoint:CGPointZero]; 66 | animation.duration = duration; 67 | animation.repeatCount = HUGE_VALF; 68 | FBShimmeringLayerAnimationApplyDragCoefficient(animation); 69 | if (direction == FBShimmerDirectionLeft || 70 | direction == FBShimmerDirectionUp) { 71 | animation.speed = -fabsf(animation.speed); 72 | } 73 | return animation; 74 | } 75 | 76 | // take a shimmer slide animation and turns into repeating 77 | static CAAnimation *shimmer_slide_repeat(CAAnimation *a, CFTimeInterval duration, FBShimmerDirection direction) 78 | { 79 | CAAnimation *anim = [a copy]; 80 | anim.repeatCount = HUGE_VALF; 81 | anim.duration = duration; 82 | anim.speed = (direction == FBShimmerDirectionRight || direction == FBShimmerDirectionDown) ? fabsf(anim.speed) : -fabsf(anim.speed); 83 | return anim; 84 | } 85 | 86 | // take a shimmer slide animation and turns into finish 87 | static CAAnimation *shimmer_slide_finish(CAAnimation *a) 88 | { 89 | CAAnimation *anim = [a copy]; 90 | anim.repeatCount = 0; 91 | return anim; 92 | } 93 | 94 | @interface FBShimmeringMaskLayer : CAGradientLayer 95 | @property (readonly, nonatomic) CALayer *fadeLayer; 96 | @end 97 | 98 | @implementation FBShimmeringMaskLayer 99 | 100 | - (instancetype)init 101 | { 102 | self = [super init]; 103 | if (nil != self) { 104 | _fadeLayer = [[CALayer alloc] init]; 105 | _fadeLayer.backgroundColor = [UIColor whiteColor].CGColor; 106 | [self addSublayer:_fadeLayer]; 107 | } 108 | return self; 109 | } 110 | 111 | - (void)layoutSublayers 112 | { 113 | [super layoutSublayers]; 114 | CGRect r = self.bounds; 115 | _fadeLayer.bounds = r; 116 | _fadeLayer.position = CGPointMake(CGRectGetMidX(r), CGRectGetMidY(r)); 117 | } 118 | 119 | @end 120 | 121 | @interface FBShimmeringLayer () 122 | #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 100000 123 | // iOS 10 SDK has CALayerDelegate and CAAnimationDelegate as proper protocols. 124 | 125 | #endif 126 | 127 | @property (strong, nonatomic) FBShimmeringMaskLayer *maskLayer; 128 | @end 129 | 130 | @implementation FBShimmeringLayer 131 | { 132 | CALayer *_contentLayer; 133 | FBShimmeringMaskLayer *_maskLayer; 134 | } 135 | 136 | #pragma mark - Lifecycle 137 | 138 | @synthesize shimmering = _shimmering; 139 | @synthesize shimmeringPauseDuration = _shimmeringPauseDuration; 140 | @synthesize shimmeringAnimationOpacity = _shimmeringAnimationOpacity; 141 | @synthesize shimmeringOpacity = _shimmeringOpacity; 142 | @synthesize shimmeringSpeed = _shimmeringSpeed; 143 | @synthesize shimmeringHighlightLength = _shimmeringHighlightLength; 144 | @synthesize shimmeringDirection = _shimmeringDirection; 145 | @synthesize shimmeringFadeTime = _shimmeringFadeTime; 146 | @synthesize shimmeringBeginFadeDuration = _shimmeringBeginFadeDuration; 147 | @synthesize shimmeringEndFadeDuration = _shimmeringEndFadeDuration; 148 | @synthesize shimmeringBeginTime = _shimmeringBeginTime; 149 | @dynamic shimmeringHighlightWidth; 150 | 151 | - (instancetype)init 152 | { 153 | self = [super init]; 154 | if (nil != self) { 155 | // default configuration 156 | _shimmeringPauseDuration = 0.4; 157 | _shimmeringSpeed = 230.0; 158 | _shimmeringHighlightLength = 1.0; 159 | _shimmeringAnimationOpacity = 0.5; 160 | _shimmeringOpacity = 1.0; 161 | _shimmeringDirection = FBShimmerDirectionRight; 162 | _shimmeringBeginFadeDuration = 0.1; 163 | _shimmeringEndFadeDuration = 0.3; 164 | _shimmeringBeginTime = FBShimmerDefaultBeginTime; 165 | } 166 | return self; 167 | } 168 | 169 | #pragma mark - Properties 170 | 171 | - (void)setContentLayer:(CALayer *)contentLayer 172 | { 173 | // reset mask 174 | self.maskLayer = nil; 175 | 176 | // note content layer and add for display 177 | _contentLayer = contentLayer; 178 | self.sublayers = contentLayer ? @[contentLayer] : nil; 179 | 180 | // update shimmering animation 181 | [self _updateShimmering]; 182 | } 183 | 184 | - (void)setShimmering:(BOOL)shimmering 185 | { 186 | if (shimmering != _shimmering) { 187 | _shimmering = shimmering; 188 | [self _updateShimmering]; 189 | } 190 | } 191 | 192 | - (void)setShimmeringSpeed:(CGFloat)speed 193 | { 194 | if (speed != _shimmeringSpeed) { 195 | _shimmeringSpeed = speed; 196 | [self _updateShimmering]; 197 | } 198 | } 199 | 200 | - (void)setShimmeringHighlightLength:(CGFloat)length 201 | { 202 | if (length != _shimmeringHighlightLength) { 203 | _shimmeringHighlightLength = length; 204 | [self _updateShimmering]; 205 | } 206 | } 207 | 208 | - (void)setShimmeringDirection:(FBShimmerDirection)direction 209 | { 210 | if (direction != _shimmeringDirection) { 211 | _shimmeringDirection = direction; 212 | [self _updateShimmering]; 213 | } 214 | } 215 | 216 | - (void)setShimmeringPauseDuration:(CFTimeInterval)duration 217 | { 218 | if (duration != _shimmeringPauseDuration) { 219 | _shimmeringPauseDuration = duration; 220 | [self _updateShimmering]; 221 | } 222 | } 223 | 224 | - (void)setShimmeringAnimationOpacity:(CGFloat)shimmeringAnimationOpacity 225 | { 226 | if (shimmeringAnimationOpacity != _shimmeringAnimationOpacity) { 227 | _shimmeringAnimationOpacity = shimmeringAnimationOpacity; 228 | [self _updateMaskColors]; 229 | } 230 | } 231 | 232 | - (void)setShimmeringOpacity:(CGFloat)shimmeringOpacity 233 | { 234 | if (shimmeringOpacity != _shimmeringOpacity) { 235 | _shimmeringOpacity = shimmeringOpacity; 236 | [self _updateMaskColors]; 237 | } 238 | } 239 | 240 | - (void)setShimmeringBeginTime:(CFTimeInterval)beginTime 241 | { 242 | if (beginTime != _shimmeringBeginTime) { 243 | _shimmeringBeginTime = beginTime; 244 | [self _updateShimmering]; 245 | } 246 | } 247 | 248 | - (void)layoutSublayers 249 | { 250 | [super layoutSublayers]; 251 | CGRect r = self.bounds; 252 | _contentLayer.anchorPoint = CGPointMake(0.5, 0.5); 253 | _contentLayer.bounds = r; 254 | _contentLayer.position = CGPointMake(CGRectGetMidX(r), CGRectGetMidY(r)); 255 | 256 | if (nil != _maskLayer) { 257 | [self _updateMaskLayout]; 258 | } 259 | } 260 | 261 | - (void)setBounds:(CGRect)bounds 262 | { 263 | CGRect oldBounds = self.bounds; 264 | [super setBounds:bounds]; 265 | 266 | if (!CGRectEqualToRect(oldBounds, bounds)) { 267 | [self _updateShimmering]; 268 | } 269 | } 270 | 271 | #pragma mark - Internal 272 | 273 | - (void)_clearMask 274 | { 275 | if (nil == _maskLayer) { 276 | return; 277 | } 278 | 279 | BOOL disableActions = [CATransaction disableActions]; 280 | [CATransaction setDisableActions:YES]; 281 | 282 | self.maskLayer = nil; 283 | _contentLayer.mask = nil; 284 | 285 | [CATransaction setDisableActions:disableActions]; 286 | } 287 | 288 | - (void)_createMaskIfNeeded 289 | { 290 | if (_shimmering && !_maskLayer) { 291 | _maskLayer = [FBShimmeringMaskLayer layer]; 292 | _maskLayer.delegate = self; 293 | _contentLayer.mask = _maskLayer; 294 | [self _updateMaskColors]; 295 | [self _updateMaskLayout]; 296 | } 297 | } 298 | 299 | - (void)_updateMaskColors 300 | { 301 | if (nil == _maskLayer) { 302 | return; 303 | } 304 | 305 | // We create a gradient to be used as a mask. 306 | // In a mask, the colors do not matter, it's the alpha that decides the degree of masking. 307 | UIColor *maskedColor = [UIColor colorWithWhite:1.0 alpha:_shimmeringOpacity]; 308 | UIColor *unmaskedColor = [UIColor colorWithWhite:1.0 alpha:_shimmeringAnimationOpacity]; 309 | 310 | // Create a gradient from masked to unmasked to masked. 311 | _maskLayer.colors = @[(__bridge id)maskedColor.CGColor, (__bridge id)unmaskedColor.CGColor, (__bridge id)maskedColor.CGColor]; 312 | } 313 | 314 | - (void)_updateMaskLayout 315 | { 316 | // Everything outside the mask layer is hidden, so we need to create a mask long enough for the shimmered layer to be always covered by the mask. 317 | CGFloat length = 0.0f; 318 | if (_shimmeringDirection == FBShimmerDirectionDown || 319 | _shimmeringDirection == FBShimmerDirectionUp) { 320 | length = CGRectGetHeight(_contentLayer.bounds); 321 | } else { 322 | length = CGRectGetWidth(_contentLayer.bounds); 323 | } 324 | if (0 == length) { 325 | return; 326 | } 327 | 328 | // extra distance for the gradient to travel during the pause. 329 | CGFloat extraDistance = length + _shimmeringSpeed * _shimmeringPauseDuration; 330 | 331 | // compute how far the shimmering goes 332 | CGFloat fullShimmerLength = length * 3.0f + extraDistance; 333 | CGFloat travelDistance = length * 2.0f + extraDistance; 334 | 335 | // position the gradient for the desired width 336 | CGFloat highlightOutsideLength = (1.0 - _shimmeringHighlightLength) / 2.0; 337 | _maskLayer.locations = @[@(highlightOutsideLength), 338 | @(0.5), 339 | @(1.0 - highlightOutsideLength)]; 340 | 341 | CGFloat startPoint = (length + extraDistance) / fullShimmerLength; 342 | CGFloat endPoint = travelDistance / fullShimmerLength; 343 | 344 | // position for the start of the animation 345 | _maskLayer.anchorPoint = CGPointZero; 346 | if (_shimmeringDirection == FBShimmerDirectionDown || 347 | _shimmeringDirection == FBShimmerDirectionUp) { 348 | _maskLayer.startPoint = CGPointMake(0.0, startPoint); 349 | _maskLayer.endPoint = CGPointMake(0.0, endPoint); 350 | _maskLayer.position = CGPointMake(0.0, -travelDistance); 351 | _maskLayer.bounds = CGRectMake(0.0, 0.0, CGRectGetWidth(_contentLayer.bounds), fullShimmerLength); 352 | } else { 353 | _maskLayer.startPoint = CGPointMake(startPoint, 0.0); 354 | _maskLayer.endPoint = CGPointMake(endPoint, 0.0); 355 | _maskLayer.position = CGPointMake(-travelDistance, 0.0); 356 | _maskLayer.bounds = CGRectMake(0.0, 0.0, fullShimmerLength, CGRectGetHeight(_contentLayer.bounds)); 357 | } 358 | } 359 | 360 | - (void)_updateShimmering 361 | { 362 | // create mask if needed 363 | [self _createMaskIfNeeded]; 364 | 365 | // if not shimmering and no mask, noop 366 | if (!_shimmering && !_maskLayer) { 367 | return; 368 | } 369 | 370 | // ensure layout 371 | [self layoutIfNeeded]; 372 | 373 | BOOL disableActions = [CATransaction disableActions]; 374 | if (!_shimmering) { 375 | if (disableActions) { 376 | // simply remove mask 377 | [self _clearMask]; 378 | } else { 379 | // end slide 380 | CFTimeInterval slideEndTime = 0; 381 | 382 | CAAnimation *slideAnimation = [_maskLayer animationForKey:kFBShimmerSlideAnimationKey]; 383 | if (slideAnimation != nil) { 384 | 385 | // determine total time sliding 386 | CFTimeInterval now = CACurrentMediaTime(); 387 | CFTimeInterval slideTotalDuration = now - slideAnimation.beginTime; 388 | 389 | // determine time offset into current slide 390 | CFTimeInterval slideTimeOffset = fmod(slideTotalDuration, slideAnimation.duration); 391 | 392 | // transition to non-repeating slide 393 | CAAnimation *finishAnimation = shimmer_slide_finish(slideAnimation); 394 | 395 | // adjust begin time to now - offset 396 | finishAnimation.beginTime = now - slideTimeOffset; 397 | 398 | // note slide end time and begin 399 | slideEndTime = finishAnimation.beginTime + slideAnimation.duration; 400 | [_maskLayer addAnimation:finishAnimation forKey:kFBShimmerSlideAnimationKey]; 401 | } 402 | 403 | // fade in text at slideEndTime 404 | CABasicAnimation *fadeInAnimation = fade_animation(_maskLayer.fadeLayer, 1.0, _shimmeringEndFadeDuration); 405 | fadeInAnimation.delegate = self; 406 | [fadeInAnimation setValue:@YES forKey:kFBEndFadeAnimationKey]; 407 | fadeInAnimation.beginTime = slideEndTime; 408 | [_maskLayer.fadeLayer addAnimation:fadeInAnimation forKey:kFBFadeAnimationKey]; 409 | 410 | // expose end time for synchronization 411 | _shimmeringFadeTime = slideEndTime; 412 | } 413 | } else { 414 | // fade out text, optionally animated 415 | CABasicAnimation *fadeOutAnimation = nil; 416 | if (_shimmeringBeginFadeDuration > 0.0 && !disableActions) { 417 | fadeOutAnimation = fade_animation(_maskLayer.fadeLayer, 0.0, _shimmeringBeginFadeDuration); 418 | [_maskLayer.fadeLayer addAnimation:fadeOutAnimation forKey:kFBFadeAnimationKey]; 419 | } else { 420 | BOOL innerDisableActions = [CATransaction disableActions]; 421 | [CATransaction setDisableActions:YES]; 422 | 423 | _maskLayer.fadeLayer.opacity = 0.0; 424 | [_maskLayer.fadeLayer removeAllAnimations]; 425 | 426 | [CATransaction setDisableActions:innerDisableActions]; 427 | } 428 | 429 | // begin slide animation 430 | CAAnimation *slideAnimation = [_maskLayer animationForKey:kFBShimmerSlideAnimationKey]; 431 | 432 | // compute shimmer duration 433 | CGFloat length = 0.0f; 434 | if (_shimmeringDirection == FBShimmerDirectionDown || 435 | _shimmeringDirection == FBShimmerDirectionUp) { 436 | length = CGRectGetHeight(_contentLayer.bounds); 437 | } else { 438 | length = CGRectGetWidth(_contentLayer.bounds); 439 | } 440 | CFTimeInterval animationDuration = (length / _shimmeringSpeed) + _shimmeringPauseDuration; 441 | 442 | if (slideAnimation != nil) { 443 | // ensure existing slide animation repeats 444 | [_maskLayer addAnimation:shimmer_slide_repeat(slideAnimation, animationDuration, _shimmeringDirection) forKey:kFBShimmerSlideAnimationKey]; 445 | } else { 446 | // add slide animation 447 | slideAnimation = shimmer_slide_animation(animationDuration, _shimmeringDirection); 448 | slideAnimation.fillMode = kCAFillModeForwards; 449 | slideAnimation.removedOnCompletion = NO; 450 | if (_shimmeringBeginTime == FBShimmerDefaultBeginTime) { 451 | _shimmeringBeginTime = CACurrentMediaTime() + fadeOutAnimation.duration; 452 | } 453 | slideAnimation.beginTime = _shimmeringBeginTime; 454 | 455 | [_maskLayer addAnimation:slideAnimation forKey:kFBShimmerSlideAnimationKey]; 456 | } 457 | } 458 | } 459 | 460 | #pragma mark - CALayerDelegate 461 | 462 | - (id)actionForLayer:(CALayer *)layer forKey:(NSString *)event 463 | { 464 | // no associated actions 465 | return (id)kCFNull; 466 | } 467 | 468 | #pragma mark - CAAnimationDelegate 469 | 470 | - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag 471 | { 472 | if (flag && [[anim valueForKey:kFBEndFadeAnimationKey] boolValue]) { 473 | [_maskLayer.fadeLayer removeAnimationForKey:kFBFadeAnimationKey]; 474 | 475 | [self _clearMask]; 476 | } 477 | } 478 | 479 | @end 480 | -------------------------------------------------------------------------------- /FBShimmering/FBShimmeringView.h: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2014-present, Facebook, Inc. 3 | All rights reserved. 4 | 5 | This source code is licensed under the BSD-style license found in the 6 | LICENSE file in the root directory of this source tree. An additional grant 7 | of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #import 11 | 12 | #import "FBShimmering.h" 13 | 14 | /** 15 | @abstract Lightweight, generic shimmering view. 16 | */ 17 | @interface FBShimmeringView : UIView 18 | 19 | //! @abstract The content view to be shimmered. 20 | @property (strong, nonatomic) UIView *contentView; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /FBShimmering/FBShimmeringView.m: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2014-present, Facebook, Inc. 3 | All rights reserved. 4 | 5 | This source code is licensed under the BSD-style license found in the 6 | LICENSE file in the root directory of this source tree. An additional grant 7 | of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #import "FBShimmeringView.h" 11 | 12 | #import "FBShimmeringLayer.h" 13 | 14 | #if !__has_feature(objc_arc) 15 | #error This file must be compiled with ARC. Convert your project to ARC or specify the -fobjc-arc flag. 16 | #endif 17 | 18 | @implementation FBShimmeringView 19 | 20 | + (Class)layerClass 21 | { 22 | return [FBShimmeringLayer class]; 23 | } 24 | 25 | #define __layer ((FBShimmeringLayer *)self.layer) 26 | 27 | #define LAYER_ACCESSOR(accessor, ctype) \ 28 | - (ctype)accessor { \ 29 | return [__layer accessor]; \ 30 | } 31 | 32 | #define LAYER_MUTATOR(mutator, ctype) \ 33 | - (void)mutator (ctype)value { \ 34 | [__layer mutator value]; \ 35 | } 36 | 37 | #define LAYER_RW_PROPERTY(accessor, mutator, ctype) \ 38 | LAYER_ACCESSOR (accessor, ctype) \ 39 | LAYER_MUTATOR (mutator, ctype) 40 | 41 | LAYER_RW_PROPERTY(isShimmering, setShimmering:, BOOL) 42 | LAYER_RW_PROPERTY(shimmeringPauseDuration, setShimmeringPauseDuration:, CFTimeInterval) 43 | LAYER_RW_PROPERTY(shimmeringAnimationOpacity, setShimmeringAnimationOpacity:, CGFloat) 44 | LAYER_RW_PROPERTY(shimmeringOpacity, setShimmeringOpacity:, CGFloat) 45 | LAYER_RW_PROPERTY(shimmeringSpeed, setShimmeringSpeed:, CGFloat) 46 | LAYER_RW_PROPERTY(shimmeringHighlightLength, setShimmeringHighlightLength:, CGFloat) 47 | LAYER_RW_PROPERTY(shimmeringDirection, setShimmeringDirection:, FBShimmerDirection) 48 | LAYER_ACCESSOR(shimmeringFadeTime, CFTimeInterval) 49 | LAYER_RW_PROPERTY(shimmeringBeginFadeDuration, setShimmeringBeginFadeDuration:, CFTimeInterval) 50 | LAYER_RW_PROPERTY(shimmeringEndFadeDuration, setShimmeringEndFadeDuration:, CFTimeInterval) 51 | LAYER_RW_PROPERTY(shimmeringBeginTime, setShimmeringBeginTime:, CFTimeInterval) 52 | 53 | - (void)setContentView:(UIView *)contentView 54 | { 55 | if (contentView != _contentView) { 56 | _contentView = contentView; 57 | [self addSubview:contentView]; 58 | __layer.contentLayer = contentView.layer; 59 | } 60 | } 61 | 62 | - (void)layoutSubviews 63 | { 64 | // Autolayout requires these to be set on the UIView, not the CALayer. 65 | // Do this *before* the layer has a chance to set the properties, as the 66 | // setters would be ignored (even for autolayout) if set to the same value. 67 | _contentView.bounds = self.bounds; 68 | _contentView.center = self.center; 69 | 70 | [super layoutSubviews]; 71 | } 72 | 73 | @end 74 | -------------------------------------------------------------------------------- /Framework/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 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | NSPrincipalClass 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /Framework/Shimmer.h: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2014-present, Facebook, Inc. 3 | All rights reserved. 4 | 5 | This source code is licensed under the BSD-style license found in the 6 | LICENSE file in the root directory of this source tree. An additional grant 7 | of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #import 11 | #import 12 | #import 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD License 2 | 3 | For Shimmer software 4 | 5 | Copyright (c) 2014, Facebook, Inc. All rights reserved. 6 | 7 | Redistribution and use in source and binary forms, with or without modification, 8 | are permitted provided that the following conditions are met: 9 | 10 | * Redistributions of source code must retain the above copyright notice, this 11 | list of conditions and the following disclaimer. 12 | 13 | * Redistributions in binary form must reproduce the above copyright notice, 14 | this list of conditions and the following disclaimer in the documentation 15 | and/or other materials provided with the distribution. 16 | 17 | * Neither the name Facebook nor the names of its contributors may be used to 18 | endorse or promote products derived from this software without specific 19 | prior written permission. 20 | 21 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 22 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 25 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 27 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 28 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Shimmer 2 | Shimmer is an easy way to add a shimmering effect to any view in your app. It's useful as an unobtrusive loading indicator. 3 | 4 | Shimmer was originally developed to show loading status in [Paper](http://facebook.com/paper). 5 | 6 | ![Shimmer](https://github.com/facebook/Shimmer/blob/master/shimmer.gif?raw=true) 7 | 8 | ## Usage 9 | To use Shimmer, create a `FBShimmeringView` or `FBShimmeringLayer` and add your content. To start shimmering, set the `shimmering` property to `YES`. 10 | 11 | An example of making a label shimmer: 12 | 13 | ```objective-c 14 | FBShimmeringView *shimmeringView = [[FBShimmeringView alloc] initWithFrame:self.view.bounds]; 15 | [self.view addSubview:shimmeringView]; 16 | 17 | UILabel *loadingLabel = [[UILabel alloc] initWithFrame:shimmeringView.bounds]; 18 | loadingLabel.textAlignment = NSTextAlignmentCenter; 19 | loadingLabel.text = NSLocalizedString(@"Shimmer", nil); 20 | shimmeringView.contentView = loadingLabel; 21 | 22 | // Start shimmering. 23 | shimmeringView.shimmering = YES; 24 | ``` 25 | 26 | There's also an example project. In the example, you can swipe horizontally and vertically to try various shimmering parameters, or tap to start or stop shimmering. (To build the example locally, you'll need to open `FBShimmering.xcworkpace` rather than the `.xcodeproj`.) 27 | 28 | ## Installation 29 | There are two options: 30 | 31 | 1. Shimmer is available as `Shimmer` in [Cocoapods](http://cocoapods.org). 32 | 2. Manually add the files into your Xcode project. Slightly simpler, but updates are also manual. 33 | 34 | Shimmer requires iOS 6 or later. 35 | 36 | ## How it works 37 | Shimmer uses the `-[CALayer mask]` property to enable shimmering, similar to what's described in John Harper's 2009 WWDC talk (unfortunately no longer online). Shimmer uses CoreAnimation's timing features to smoothly transition "on-beat" when starting and stopping the shimmer. 38 | 39 | ## Other Platforms 40 | 41 | We have a version of Shimmer for Android, too! It's [also available on GitHub](https://github.com/facebook/shimmer-android). 42 | 43 | ## Contributing 44 | See the CONTRIBUTING file for how to help out. 45 | 46 | ## License 47 | Shimmer is BSD-licensed. 48 | 49 | -------------------------------------------------------------------------------- /Shimmer.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |spec| 2 | spec.name = 'Shimmer' 3 | spec.version = '1.0.2' 4 | spec.license = { :type => 'BSD' } 5 | spec.homepage = 'https://github.com/facebook/Shimmer' 6 | spec.authors = { 'Grant Paul' => 'shimmer@grantpaul.com', 'Kimon Tsinteris' => 'kimon@mac.com' } 7 | spec.summary = 'Simple shimmering effect.' 8 | spec.source = { :git => 'https://github.com/facebook/Shimmer.git', :tag => '1.0.2' } 9 | spec.source_files = 'FBShimmering/FBShimmering{,View,Layer}.{h,m}' 10 | spec.requires_arc = true 11 | 12 | spec.ios.deployment_target = '6.0' 13 | end 14 | -------------------------------------------------------------------------------- /shimmer.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookarchive/Shimmer/a7eba17652638ef894407ce13a4bc5ca347ba488/shimmer.gif --------------------------------------------------------------------------------