├── .gitignore ├── .npmignore ├── FLAnimatedImage.android.js ├── FLAnimatedImage.ios.js ├── LICENSE ├── README.md ├── RNFLAnimatedImage ├── RNFLAnimatedImage.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ └── contents.xcworkspacedata └── RNFLAnimatedImage │ ├── RNFLAnimatedImage.h │ ├── RNFLAnimatedImage.m │ ├── RNFLAnimatedImageManager.h │ └── RNFLAnimatedImageManager.m ├── index.js └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Build generated 6 | build/ 7 | DerivedData 8 | 9 | ## Various settings 10 | *.pbxuser 11 | !default.pbxuser 12 | *.mode1v3 13 | !default.mode1v3 14 | *.mode2v3 15 | !default.mode2v3 16 | *.perspectivev3 17 | !default.perspectivev3 18 | xcuserdata 19 | 20 | ## Other 21 | *.xccheckout 22 | *.moved-aside 23 | *.xcuserstate 24 | *.xcscmblueprint 25 | 26 | ## Obj-C/Swift specific 27 | *.hmap 28 | *.ipa 29 | 30 | # CocoaPods 31 | # 32 | # We recommend against adding the Pods directory to your .gitignore. However 33 | # you should judge for yourself, the pros and cons are mentioned at: 34 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 35 | # 36 | # Pods/ 37 | 38 | # Carthage 39 | # 40 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 41 | # Carthage/Checkouts 42 | 43 | Carthage/Build 44 | 45 | # fastlane 46 | # 47 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 48 | # screenshots whenever they are needed. 49 | # For more information about the recommended setup visit: 50 | # https://github.com/fastlane/fastlane/blob/master/docs/Gitignore.md 51 | 52 | fastlane/report.xml 53 | fastlane/screenshots 54 | 55 | #node_modules 56 | node_modules/**/* -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Build generated 6 | build/ 7 | DerivedData 8 | 9 | ## Various settings 10 | *.pbxuser 11 | !default.pbxuser 12 | *.mode1v3 13 | !default.mode1v3 14 | *.mode2v3 15 | !default.mode2v3 16 | *.perspectivev3 17 | !default.perspectivev3 18 | xcuserdata 19 | 20 | ## Other 21 | *.xccheckout 22 | *.moved-aside 23 | *.xcuserstate 24 | *.xcscmblueprint 25 | 26 | ## Obj-C/Swift specific 27 | *.hmap 28 | *.ipa 29 | 30 | # CocoaPods 31 | # 32 | # We recommend against adding the Pods directory to your .gitignore. However 33 | # you should judge for yourself, the pros and cons are mentioned at: 34 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 35 | # 36 | # Pods/ 37 | 38 | # Carthage 39 | # 40 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 41 | # Carthage/Checkouts 42 | 43 | Carthage/Build 44 | 45 | # fastlane 46 | # 47 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 48 | # screenshots whenever they are needed. 49 | # For more information about the recommended setup visit: 50 | # https://github.com/fastlane/fastlane/blob/master/docs/Gitignore.md 51 | 52 | fastlane/report.xml 53 | fastlane/screenshots 54 | 55 | #node_modules 56 | node_modules/**/* -------------------------------------------------------------------------------- /FLAnimatedImage.android.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | 3 | import { StyleSheet, View } from 'react-native' 4 | 5 | class FLAnimatedImage extends Component { 6 | render() { 7 | return 8 | } 9 | } 10 | 11 | const styles = StyleSheet.create({}) 12 | 13 | export default FLAnimatedImage 14 | -------------------------------------------------------------------------------- /FLAnimatedImage.ios.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import PropTypes from 'prop-types' 3 | 4 | import { requireNativeComponent, NativeModules, StyleSheet } from 'react-native' 5 | 6 | import resolveAssetSource from 'react-native/Libraries/Image/resolveAssetSource' 7 | 8 | const { 9 | ScaleToFill, 10 | ScaleAspectFit, 11 | ScaleAspectFill, 12 | } = NativeModules.RNFLAnimatedImageManager 13 | 14 | const MODES = { 15 | stretch: ScaleToFill, 16 | contain: ScaleAspectFit, 17 | cover: ScaleAspectFill, 18 | } 19 | 20 | class FLAnimatedImage extends Component { 21 | static propTypes = { 22 | // native only 23 | contentMode: PropTypes.number, 24 | 25 | source: PropTypes.oneOfType([ 26 | PropTypes.shape({ 27 | uri: PropTypes.string, 28 | width: PropTypes.number, 29 | height: PropTypes.number, 30 | scale: PropTypes.number, 31 | }), 32 | PropTypes.number, 33 | ]), 34 | src: PropTypes.string, 35 | resizeMode: PropTypes.string, 36 | onFrameChange: PropTypes.func, 37 | onLoadEnd: PropTypes.func, 38 | } 39 | static defaultProps = { 40 | resizeMode: 'contain', 41 | } 42 | 43 | render() { 44 | const contentMode = MODES[this.props.resizeMode] 45 | const source = resolveAssetSource(this.props.source) || { 46 | uri: undefined, 47 | width: undefined, 48 | height: undefined, 49 | } 50 | const src = source.uri 51 | return ( 52 | 53 | ) 54 | } 55 | } 56 | 57 | const styles = StyleSheet.create({}) 58 | 59 | const RNFLAnimatedImage = requireNativeComponent( 60 | 'RNFLAnimatedImage', 61 | FLAnimatedImage 62 | ) 63 | export default FLAnimatedImage 64 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Neo 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, 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, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # react-native-flanimatedimage 2 | FLAnimatedImage for React Native 3 | 4 | This module is modified from https://github.com/browniefed/react-native-flanimatedimage with the following changes: 5 | * use _Carthage_ or _CocoaPods_ for FLAnimatedImage dependency 6 | * async image loading 7 | * return the image size `onLoadEnd` 8 | 9 | ## Install 10 | 11 | **You have to install [FLAnimatedImage](https://github.com/Flipboard/FLAnimatedImage) first** via _Carthage_ or If you're using CocoaPods, you can put the following in your Podfile: 12 | 13 | ``` 14 | pod 'FLAnimatedImage' 15 | ``` 16 | 17 | then 18 | 19 | ```shell 20 | npm install react-native-flanimatedimage --save 21 | ``` 22 | 23 | If you are using react-native@0.40 or below 24 | ```shell 25 | npm install react-native-flanimatedimage@0.0.3 --save 26 | ``` 27 | 28 | ## Link 29 | 30 | In XCode, in the project navigator: 31 | - Right click _Libraries_ 32 | - Add Files to _[your project's name]_ 33 | - Go to `node_modules/react-native-flanimatedimage/RNFLAnimatedImage` 34 | - Add the `.xcodeproj` file 35 | 36 | In XCode, in the project navigator, select your project. 37 | - Add the `libRNFLAnimatedImage.a` from the _deviceinfo_ project to your project's _Build Phases ➜ Link Binary With Libraries_ 38 | 39 | **If your `Catrhage`/`Pods` folder is not under `ios` folder, please modify the `Headers Search Paths` in `Build Settings - Search Paths - Header Search Paths`** 40 | - Click `.xcodeproj` file you added before in the project navigator and go the _Build Settings_ tab. Make sure _All_ is toggled on (instead of _Basic_). 41 | - Look for _Header Search Paths_ and add the path where the `FLAnimatedImage`'s header files are placed. 42 | 43 | ## Usage 44 | 45 | ```js 46 | import FLAnimatedImage from 'react-native-flanimatedimage'; 47 | 48 | ... 49 | onLoadEnd = (e) => { 50 | if (!e.nativeEvent.size) return; 51 | const { width, height } = e.nativeEvent.size; 52 | this.setState({ 53 | width, 54 | height, 55 | }); 56 | } 57 | ... 58 | 59 | ... 60 | ``` 61 | -------------------------------------------------------------------------------- /RNFLAnimatedImage/RNFLAnimatedImage.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | B5EE7B901D884FA5008938BC /* RNFLAnimatedImage.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = B5EE7B8F1D884FA5008938BC /* RNFLAnimatedImage.h */; }; 11 | B5EE7B921D884FA5008938BC /* RNFLAnimatedImage.m in Sources */ = {isa = PBXBuildFile; fileRef = B5EE7B911D884FA5008938BC /* RNFLAnimatedImage.m */; }; 12 | B5EE7B9A1D885034008938BC /* RNFLAnimatedImageManager.m in Sources */ = {isa = PBXBuildFile; fileRef = B5EE7B991D885034008938BC /* RNFLAnimatedImageManager.m */; }; 13 | /* End PBXBuildFile section */ 14 | 15 | /* Begin PBXCopyFilesBuildPhase section */ 16 | B5EE7B8A1D884FA5008938BC /* CopyFiles */ = { 17 | isa = PBXCopyFilesBuildPhase; 18 | buildActionMask = 2147483647; 19 | dstPath = "include/$(PRODUCT_NAME)"; 20 | dstSubfolderSpec = 16; 21 | files = ( 22 | B5EE7B901D884FA5008938BC /* RNFLAnimatedImage.h in CopyFiles */, 23 | ); 24 | runOnlyForDeploymentPostprocessing = 0; 25 | }; 26 | /* End PBXCopyFilesBuildPhase section */ 27 | 28 | /* Begin PBXFileReference section */ 29 | B5EE7B8C1D884FA5008938BC /* libRNFLAnimatedImage.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRNFLAnimatedImage.a; sourceTree = BUILT_PRODUCTS_DIR; }; 30 | B5EE7B8F1D884FA5008938BC /* RNFLAnimatedImage.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNFLAnimatedImage.h; sourceTree = ""; }; 31 | B5EE7B911D884FA5008938BC /* RNFLAnimatedImage.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNFLAnimatedImage.m; sourceTree = ""; }; 32 | B5EE7B981D885026008938BC /* RNFLAnimatedImageManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNFLAnimatedImageManager.h; sourceTree = ""; }; 33 | B5EE7B991D885034008938BC /* RNFLAnimatedImageManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNFLAnimatedImageManager.m; sourceTree = ""; }; 34 | /* End PBXFileReference section */ 35 | 36 | /* Begin PBXFrameworksBuildPhase section */ 37 | B5EE7B891D884FA5008938BC /* Frameworks */ = { 38 | isa = PBXFrameworksBuildPhase; 39 | buildActionMask = 2147483647; 40 | files = ( 41 | ); 42 | runOnlyForDeploymentPostprocessing = 0; 43 | }; 44 | /* End PBXFrameworksBuildPhase section */ 45 | 46 | /* Begin PBXGroup section */ 47 | B5EE7B831D884FA5008938BC = { 48 | isa = PBXGroup; 49 | children = ( 50 | B5EE7B8E1D884FA5008938BC /* RNFLAnimatedImage */, 51 | B5EE7B8D1D884FA5008938BC /* Products */, 52 | ); 53 | indentWidth = 2; 54 | sourceTree = ""; 55 | tabWidth = 2; 56 | }; 57 | B5EE7B8D1D884FA5008938BC /* Products */ = { 58 | isa = PBXGroup; 59 | children = ( 60 | B5EE7B8C1D884FA5008938BC /* libRNFLAnimatedImage.a */, 61 | ); 62 | name = Products; 63 | sourceTree = ""; 64 | }; 65 | B5EE7B8E1D884FA5008938BC /* RNFLAnimatedImage */ = { 66 | isa = PBXGroup; 67 | children = ( 68 | B5EE7B8F1D884FA5008938BC /* RNFLAnimatedImage.h */, 69 | B5EE7B911D884FA5008938BC /* RNFLAnimatedImage.m */, 70 | B5EE7B981D885026008938BC /* RNFLAnimatedImageManager.h */, 71 | B5EE7B991D885034008938BC /* RNFLAnimatedImageManager.m */, 72 | ); 73 | path = RNFLAnimatedImage; 74 | sourceTree = ""; 75 | }; 76 | /* End PBXGroup section */ 77 | 78 | /* Begin PBXNativeTarget section */ 79 | B5EE7B8B1D884FA5008938BC /* RNFLAnimatedImage */ = { 80 | isa = PBXNativeTarget; 81 | buildConfigurationList = B5EE7B951D884FA5008938BC /* Build configuration list for PBXNativeTarget "RNFLAnimatedImage" */; 82 | buildPhases = ( 83 | B5EE7B881D884FA5008938BC /* Sources */, 84 | B5EE7B891D884FA5008938BC /* Frameworks */, 85 | B5EE7B8A1D884FA5008938BC /* CopyFiles */, 86 | ); 87 | buildRules = ( 88 | ); 89 | dependencies = ( 90 | ); 91 | name = RNFLAnimatedImage; 92 | productName = RNFLAnimatedImage; 93 | productReference = B5EE7B8C1D884FA5008938BC /* libRNFLAnimatedImage.a */; 94 | productType = "com.apple.product-type.library.static"; 95 | }; 96 | /* End PBXNativeTarget section */ 97 | 98 | /* Begin PBXProject section */ 99 | B5EE7B841D884FA5008938BC /* Project object */ = { 100 | isa = PBXProject; 101 | attributes = { 102 | LastUpgradeCheck = 0730; 103 | ORGANIZATIONNAME = Neo; 104 | TargetAttributes = { 105 | B5EE7B8B1D884FA5008938BC = { 106 | CreatedOnToolsVersion = 7.3.1; 107 | }; 108 | }; 109 | }; 110 | buildConfigurationList = B5EE7B871D884FA5008938BC /* Build configuration list for PBXProject "RNFLAnimatedImage" */; 111 | compatibilityVersion = "Xcode 3.2"; 112 | developmentRegion = English; 113 | hasScannedForEncodings = 0; 114 | knownRegions = ( 115 | en, 116 | ); 117 | mainGroup = B5EE7B831D884FA5008938BC; 118 | productRefGroup = B5EE7B8D1D884FA5008938BC /* Products */; 119 | projectDirPath = ""; 120 | projectRoot = ""; 121 | targets = ( 122 | B5EE7B8B1D884FA5008938BC /* RNFLAnimatedImage */, 123 | ); 124 | }; 125 | /* End PBXProject section */ 126 | 127 | /* Begin PBXSourcesBuildPhase section */ 128 | B5EE7B881D884FA5008938BC /* Sources */ = { 129 | isa = PBXSourcesBuildPhase; 130 | buildActionMask = 2147483647; 131 | files = ( 132 | B5EE7B9A1D885034008938BC /* RNFLAnimatedImageManager.m in Sources */, 133 | B5EE7B921D884FA5008938BC /* RNFLAnimatedImage.m in Sources */, 134 | ); 135 | runOnlyForDeploymentPostprocessing = 0; 136 | }; 137 | /* End PBXSourcesBuildPhase section */ 138 | 139 | /* Begin XCBuildConfiguration section */ 140 | B5EE7B931D884FA5008938BC /* Debug */ = { 141 | isa = XCBuildConfiguration; 142 | buildSettings = { 143 | ALWAYS_SEARCH_USER_PATHS = NO; 144 | CLANG_ANALYZER_NONNULL = YES; 145 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 146 | CLANG_CXX_LIBRARY = "libc++"; 147 | CLANG_ENABLE_MODULES = YES; 148 | CLANG_ENABLE_OBJC_ARC = YES; 149 | CLANG_WARN_BOOL_CONVERSION = YES; 150 | CLANG_WARN_CONSTANT_CONVERSION = YES; 151 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 152 | CLANG_WARN_EMPTY_BODY = YES; 153 | CLANG_WARN_ENUM_CONVERSION = YES; 154 | CLANG_WARN_INT_CONVERSION = YES; 155 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 156 | CLANG_WARN_UNREACHABLE_CODE = YES; 157 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 158 | COPY_PHASE_STRIP = NO; 159 | DEBUG_INFORMATION_FORMAT = dwarf; 160 | ENABLE_STRICT_OBJC_MSGSEND = YES; 161 | ENABLE_TESTABILITY = YES; 162 | GCC_C_LANGUAGE_STANDARD = gnu99; 163 | GCC_DYNAMIC_NO_PIC = NO; 164 | GCC_NO_COMMON_BLOCKS = YES; 165 | GCC_OPTIMIZATION_LEVEL = 0; 166 | GCC_PREPROCESSOR_DEFINITIONS = ( 167 | "DEBUG=1", 168 | "$(inherited)", 169 | ); 170 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 171 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 172 | GCC_WARN_UNDECLARED_SELECTOR = YES; 173 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 174 | GCC_WARN_UNUSED_FUNCTION = YES; 175 | GCC_WARN_UNUSED_VARIABLE = YES; 176 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 177 | MTL_ENABLE_DEBUG_INFO = YES; 178 | ONLY_ACTIVE_ARCH = YES; 179 | SDKROOT = iphoneos; 180 | }; 181 | name = Debug; 182 | }; 183 | B5EE7B941D884FA5008938BC /* Release */ = { 184 | isa = XCBuildConfiguration; 185 | buildSettings = { 186 | ALWAYS_SEARCH_USER_PATHS = NO; 187 | CLANG_ANALYZER_NONNULL = YES; 188 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 189 | CLANG_CXX_LIBRARY = "libc++"; 190 | CLANG_ENABLE_MODULES = YES; 191 | CLANG_ENABLE_OBJC_ARC = YES; 192 | CLANG_WARN_BOOL_CONVERSION = YES; 193 | CLANG_WARN_CONSTANT_CONVERSION = YES; 194 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 195 | CLANG_WARN_EMPTY_BODY = YES; 196 | CLANG_WARN_ENUM_CONVERSION = YES; 197 | CLANG_WARN_INT_CONVERSION = YES; 198 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 199 | CLANG_WARN_UNREACHABLE_CODE = YES; 200 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 201 | COPY_PHASE_STRIP = NO; 202 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 203 | ENABLE_NS_ASSERTIONS = NO; 204 | ENABLE_STRICT_OBJC_MSGSEND = YES; 205 | GCC_C_LANGUAGE_STANDARD = gnu99; 206 | GCC_NO_COMMON_BLOCKS = YES; 207 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 208 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 209 | GCC_WARN_UNDECLARED_SELECTOR = YES; 210 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 211 | GCC_WARN_UNUSED_FUNCTION = YES; 212 | GCC_WARN_UNUSED_VARIABLE = YES; 213 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 214 | MTL_ENABLE_DEBUG_INFO = NO; 215 | SDKROOT = iphoneos; 216 | VALIDATE_PRODUCT = YES; 217 | }; 218 | name = Release; 219 | }; 220 | B5EE7B961D884FA5008938BC /* Debug */ = { 221 | isa = XCBuildConfiguration; 222 | buildSettings = { 223 | HEADER_SEARCH_PATHS = ( 224 | "$(inherited)", 225 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, 226 | "$(SRCROOT)/../../react-native/React/**", 227 | "$(SRCROOT)/../../react-native/Libraries/Image/**", 228 | "$(SRCROOT)/../../../ios/Carthage/Build/iOS/FLAnimatedImage.framework/Headers", 229 | "$(SRCROOT)/../../../ios/Pods/Headers/Public/FLAnimatedImage", 230 | "$(SRCROOT)/../../../ios/Pods/FLAnimatedImage/FLAnimatedImage", 231 | ); 232 | OTHER_LDFLAGS = "-ObjC"; 233 | PRODUCT_NAME = "$(TARGET_NAME)"; 234 | SKIP_INSTALL = YES; 235 | }; 236 | name = Debug; 237 | }; 238 | B5EE7B971D884FA5008938BC /* Release */ = { 239 | isa = XCBuildConfiguration; 240 | buildSettings = { 241 | HEADER_SEARCH_PATHS = ( 242 | "$(inherited)", 243 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, 244 | "$(SRCROOT)/../../react-native/React/**", 245 | "$(SRCROOT)/../../react-native/Libraries/Image/**", 246 | "$(SRCROOT)/../../../ios/Carthage/Build/iOS/FLAnimatedImage.framework/Headers", 247 | "$(SRCROOT)/../../../ios/Pods/Headers/Public/FLAnimatedImage", 248 | "$(SRCROOT)/../../../ios/Pods/FLAnimatedImage/FLAnimatedImage", 249 | ); 250 | OTHER_LDFLAGS = "-ObjC"; 251 | PRODUCT_NAME = "$(TARGET_NAME)"; 252 | SKIP_INSTALL = YES; 253 | }; 254 | name = Release; 255 | }; 256 | /* End XCBuildConfiguration section */ 257 | 258 | /* Begin XCConfigurationList section */ 259 | B5EE7B871D884FA5008938BC /* Build configuration list for PBXProject "RNFLAnimatedImage" */ = { 260 | isa = XCConfigurationList; 261 | buildConfigurations = ( 262 | B5EE7B931D884FA5008938BC /* Debug */, 263 | B5EE7B941D884FA5008938BC /* Release */, 264 | ); 265 | defaultConfigurationIsVisible = 0; 266 | defaultConfigurationName = Release; 267 | }; 268 | B5EE7B951D884FA5008938BC /* Build configuration list for PBXNativeTarget "RNFLAnimatedImage" */ = { 269 | isa = XCConfigurationList; 270 | buildConfigurations = ( 271 | B5EE7B961D884FA5008938BC /* Debug */, 272 | B5EE7B971D884FA5008938BC /* Release */, 273 | ); 274 | defaultConfigurationIsVisible = 0; 275 | }; 276 | /* End XCConfigurationList section */ 277 | }; 278 | rootObject = B5EE7B841D884FA5008938BC /* Project object */; 279 | } 280 | -------------------------------------------------------------------------------- /RNFLAnimatedImage/RNFLAnimatedImage.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /RNFLAnimatedImage/RNFLAnimatedImage/RNFLAnimatedImage.h: -------------------------------------------------------------------------------- 1 | // 2 | // RNFLAnimatedImage.h 3 | // RNFLAnimatedImage 4 | // 5 | // Created by Neo on 16/9/13. 6 | // Copyright © 2016 Neo. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "FLAnimatedImage.h" 11 | 12 | @class RNFLAnimatedImage; 13 | 14 | @interface RNFLAnimatedImage : UIView 15 | 16 | @property (nonatomic, copy) NSString *src; 17 | @property (nonatomic, assign) NSNumber *contentMode; 18 | 19 | @property (nonatomic, copy) RCTDirectEventBlock onFrameChange; 20 | @property (nonatomic, copy) RCTDirectEventBlock onLoadEnd; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /RNFLAnimatedImage/RNFLAnimatedImage/RNFLAnimatedImage.m: -------------------------------------------------------------------------------- 1 | // 2 | // RNFLAnimatedImage.m 3 | // RNFLAnimatedImage 4 | // 5 | // Created by Neo on 16/9/13. 6 | // Copyright © 2016 Neo. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | #import "FLAnimatedImage.h" 13 | #import "RNFLAnimatedImage.h" 14 | 15 | #import 16 | #import "RCTImageUtils.h" 17 | #import 18 | #import 19 | 20 | @implementation RNFLAnimatedImage { 21 | 22 | FLAnimatedImage *_image; 23 | FLAnimatedImageView *_imageView; 24 | 25 | } 26 | 27 | - (instancetype)initWithFrame:(CGRect)frame 28 | { 29 | if ((self = [super initWithFrame:frame])) { 30 | _imageView = [[FLAnimatedImageView alloc] init]; 31 | 32 | [_imageView addObserver:self forKeyPath:@"currentFrameIndex" options:0 context:nil]; 33 | } 34 | return self; 35 | } 36 | 37 | RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:(NSCoder *)aDecoder) 38 | 39 | 40 | - (void)dealloc 41 | { 42 | [_imageView removeObserver:self forKeyPath:@"currentFrameIndex"]; 43 | } 44 | 45 | - (void)layoutSubviews 46 | { 47 | _imageView.frame = self.bounds; 48 | [self addSubview:_imageView]; 49 | } 50 | 51 | - (void)setSrc:(NSString *)src 52 | { 53 | if (![src isEqual:_src]) { 54 | _src = [src copy]; 55 | [self reloadImage]; 56 | } 57 | } 58 | 59 | - (void)setContentMode:(NSNumber *)contentMode 60 | { 61 | if(![contentMode isEqual:_contentMode]) { 62 | _contentMode = contentMode; 63 | [self reloadImage]; 64 | } 65 | } 66 | 67 | -(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { 68 | if (object == _imageView) { 69 | if ([keyPath isEqualToString:@"currentFrameIndex"]) { 70 | if(_onFrameChange){ 71 | _onFrameChange(@{ 72 | @"currentFrameIndex":[NSNumber numberWithUnsignedInteger:[object currentFrameIndex]], 73 | @"frameCount": [NSNumber numberWithUnsignedInteger:[_image frameCount]], 74 | }); 75 | } 76 | } 77 | } 78 | } 79 | 80 | -(void)reloadImage { 81 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 82 | NSData *_imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:_src]]; 83 | 84 | if(_imageData == nil) { 85 | _imageData = [NSData dataWithContentsOfFile:[NSURL URLWithString:_src]]; 86 | } 87 | 88 | if(_imageData == nil) { 89 | if(_onLoadEnd) { 90 | _onLoadEnd(@{}); 91 | } 92 | return; 93 | } 94 | 95 | dispatch_async(dispatch_get_main_queue(), ^{ 96 | NSDictionary *meta = RCTGetImageMetadata(_imageData); 97 | CGSize size = (CGSize) { 98 | [meta[(id)kCGImagePropertyPixelWidth] doubleValue], 99 | [meta[(id)kCGImagePropertyPixelHeight] doubleValue], 100 | }; 101 | 102 | if(_onLoadEnd) { 103 | _onLoadEnd(@{ 104 | @"size":@{ 105 | @"width": @(size.width), 106 | @"height": @(size.height), 107 | } 108 | }); 109 | } 110 | 111 | _image = [FLAnimatedImage animatedImageWithGIFData:_imageData]; 112 | _imageView.contentMode = [_contentMode integerValue]; 113 | _imageView.animatedImage = _image; 114 | }); 115 | }); 116 | } 117 | 118 | @end 119 | -------------------------------------------------------------------------------- /RNFLAnimatedImage/RNFLAnimatedImage/RNFLAnimatedImageManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // RNFLAnimatedImageManager.h 3 | // RNFLAnimatedImage 4 | // 5 | // Created by Neo on 16/9/13. 6 | // Copyright © 2016 Neo. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface RNFLAnimatedImageManager : RCTViewManager 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /RNFLAnimatedImage/RNFLAnimatedImage/RNFLAnimatedImageManager.m: -------------------------------------------------------------------------------- 1 | // 2 | // RNFLAnimatedImageManager.m 3 | // RNFLAnimatedImage 4 | // 5 | // Created by Neo on 16/9/13. 6 | // Copyright © 2016 Neo. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import 12 | #import 13 | 14 | #import "RNFLAnimatedImageManager.h" 15 | #import "RNFLAnimatedImage.h" 16 | 17 | @implementation RNFLAnimatedImageManager 18 | 19 | RCT_EXPORT_MODULE(); 20 | 21 | @synthesize bridge = _bridge; 22 | 23 | - (UIView *)view 24 | { 25 | RNFLAnimatedImage *animatedImage = [RNFLAnimatedImage new]; 26 | return animatedImage; 27 | } 28 | 29 | + (BOOL)requiresMainQueueSetup 30 | { 31 | return NO; 32 | } 33 | 34 | - (dispatch_queue_t)methodQueue 35 | { 36 | return dispatch_get_main_queue(); 37 | } 38 | 39 | RCT_EXPORT_VIEW_PROPERTY(src, NSString); 40 | RCT_EXPORT_VIEW_PROPERTY(contentMode, NSNumber); 41 | RCT_EXPORT_VIEW_PROPERTY(onFrameChange, RCTDirectEventBlock) 42 | RCT_EXPORT_VIEW_PROPERTY(onLoadEnd, RCTDirectEventBlock) 43 | 44 | - (NSDictionary *) constantsToExport { 45 | return @{ 46 | @"ScaleAspectFit": @(UIViewContentModeScaleAspectFit), 47 | @"ScaleAspectFill": @(UIViewContentModeScaleAspectFill), 48 | @"ScaleToFill": @(UIViewContentModeScaleToFill) 49 | }; 50 | } 51 | 52 | @end 53 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | import FLAnimatedImage from './FLAnimatedImage' 2 | 3 | export default FLAnimatedImage 4 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-flanimatedimage", 3 | "version": "0.4.0", 4 | "description": "FLAnimatedImage for React Native", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/nihgwu/react-native-flanimatedimage.git" 12 | }, 13 | "keywords": [ 14 | "react-native", 15 | "flanimatedimage", 16 | "animated", 17 | "image", 18 | "gif" 19 | ], 20 | "author": "Neo (nihgwu@live.com)", 21 | "license": "MIT", 22 | "bugs": { 23 | "url": "https://github.com/nihgwu/react-native-flanimatedimage/issues" 24 | }, 25 | "homepage": "https://github.com/nihgwu/react-native-flanimatedimage#readme", 26 | "peerDependencies": { 27 | "react-native": "*", 28 | "prop-types": "*" 29 | } 30 | } 31 | --------------------------------------------------------------------------------