├── README.md ├── ZKBanner.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ │ └── cain.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcuserdata │ └── cain.xcuserdatad │ └── xcschemes │ ├── ZKBanner.xcscheme │ └── xcschememanagement.plist ├── ZKBanner ├── NewBannerView.h ├── NewBannerView.m ├── NewBannerViewManager.h ├── NewBannerViewManager.m └── SDCycleScrollView │ ├── PageControl │ ├── TAAbstractDotView.h │ ├── TAAbstractDotView.m │ ├── TAAnimatedDotView.h │ ├── TAAnimatedDotView.m │ ├── TADotView.h │ ├── TADotView.m │ ├── TAPageControl.h │ └── TAPageControl.m │ ├── SDCollectionViewCell.h │ ├── SDCollectionViewCell.m │ ├── SDCycleScrollView.h │ ├── SDCycleScrollView.m │ ├── UIView+SDExtension.h │ └── UIView+SDExtension.m ├── components └── NewBanner.js ├── index.js └── package.json /README.md: -------------------------------------------------------------------------------- 1 | # react-native-zkbanner 2 | 3 | 4 | 5 | ## Demo 6 | The [Project Demo](https://github.com/cainvan/ReactBannerDemo) 7 | 8 | 9 | ![Image](https://github.com/cainvan/ReactBannerDemo/blob/master/image/demoImage.gif) 10 | 11 | ## Introduction 12 | 13 | The aim of this library is to provide reusable React Native components that can Use a network or local image as a dynamic banner. 14 | 15 | ## Installation 16 | 17 | 1. Run `npm install --save react-native-zkbanner`. 18 | 19 | 2. Add all the files under node_modules/react-native-zkbanner/ZKBanner. (In Xcode: File -> Add files to "App Name"). 20 | 21 | 3. Then you need to add [SDWebImage](https://github.com/rs/SDWebImage) to the Xcode project. Here, you can use the react-native-zkbanner. 22 | 23 | 24 | # Usage 25 | 26 | Example code: 27 | 28 | ```JavaScript 29 | /** 30 | * Sample React Native App 31 | * https://github.com/facebook/react-native 32 | * @flow 33 | */ 34 | 35 | import React, { Component } from 'react'; 36 | import { 37 | AppRegistry, 38 | StyleSheet, 39 | Dimensions, 40 | Text, 41 | View 42 | } from 'react-native'; 43 | 44 | import { Banner } from 'react-native-zkbanner'; 45 | 46 | class ReactBannerDemo extends Component { 47 | render() { 48 | var bannerImgs = [ 49 | 'https://www.umeng.com/img/index/demo/0901-2.c1df5ebf79f4c2b31f5ded9b13970826.png', 50 | 'https://www.umeng.com/img/index/demo/0912.97aa0956cef2b613001d28d394eb4bd0.png', 51 | 'https://www.umeng.com/img/index/demo/8.a0a7379becc230ef38295a74956ec8f2.png', 52 | 'https://www.umeng.com/img/index/demo/825-1.58787216c12fb39bb6d384ad4d278037.jpg' 53 | ]; 54 | return ( 55 | 56 | { 61 | console.log('react' + event.nativeEvent.value); 62 | }} 63 | /> 64 | 65 | ); 66 | } 67 | } 68 | 69 | const styles = StyleSheet.create({ 70 | map0: { 71 | width:Dimensions.get('window').width, 72 | height:Dimensions.get('window').height, 73 | alignItems:'center', 74 | justifyContent:'center', 75 | }, 76 | map1: { 77 | width:Dimensions.get('window').width, 78 | height:200, 79 | }, 80 | }); 81 | 82 | AppRegistry.registerComponent('ReactBannerDemo', () => ReactBannerDemo); 83 | 84 | ``` 85 | # License 86 | The MIT License (MIT) 87 | 88 | Copyright (C) 2016 cain_van@163.com 89 | 90 |   Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 91 | 92 |   The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 93 | 94 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 95 | 96 | -------------------------------------------------------------------------------- /ZKBanner.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | A4387CA61D8935D900BDB11A /* NewBannerView.m in Sources */ = {isa = PBXBuildFile; fileRef = A4387C931D8935D900BDB11A /* NewBannerView.m */; }; 11 | A4387CA71D8935D900BDB11A /* NewBannerViewManager.m in Sources */ = {isa = PBXBuildFile; fileRef = A4387C951D8935D900BDB11A /* NewBannerViewManager.m */; }; 12 | A4387CA81D8935D900BDB11A /* TAAbstractDotView.m in Sources */ = {isa = PBXBuildFile; fileRef = A4387C991D8935D900BDB11A /* TAAbstractDotView.m */; }; 13 | A4387CA91D8935D900BDB11A /* TAAnimatedDotView.m in Sources */ = {isa = PBXBuildFile; fileRef = A4387C9B1D8935D900BDB11A /* TAAnimatedDotView.m */; }; 14 | A4387CAA1D8935D900BDB11A /* TADotView.m in Sources */ = {isa = PBXBuildFile; fileRef = A4387C9D1D8935D900BDB11A /* TADotView.m */; }; 15 | A4387CAB1D8935D900BDB11A /* TAPageControl.m in Sources */ = {isa = PBXBuildFile; fileRef = A4387C9F1D8935D900BDB11A /* TAPageControl.m */; }; 16 | A4387CAC1D8935D900BDB11A /* SDCollectionViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = A4387CA11D8935D900BDB11A /* SDCollectionViewCell.m */; }; 17 | A4387CAD1D8935D900BDB11A /* SDCycleScrollView.m in Sources */ = {isa = PBXBuildFile; fileRef = A4387CA31D8935D900BDB11A /* SDCycleScrollView.m */; }; 18 | A4387CAE1D8935D900BDB11A /* UIView+SDExtension.m in Sources */ = {isa = PBXBuildFile; fileRef = A4387CA51D8935D900BDB11A /* UIView+SDExtension.m */; }; 19 | /* End PBXBuildFile section */ 20 | 21 | /* Begin PBXContainerItemProxy section */ 22 | A4387C761D89356D00BDB11A /* PBXContainerItemProxy */ = { 23 | isa = PBXContainerItemProxy; 24 | containerPortal = A4387C541D89356D00BDB11A /* Project object */; 25 | proxyType = 1; 26 | remoteGlobalIDString = A4387C5B1D89356D00BDB11A; 27 | remoteInfo = ZKBanner; 28 | }; 29 | A4387C811D89356D00BDB11A /* PBXContainerItemProxy */ = { 30 | isa = PBXContainerItemProxy; 31 | containerPortal = A4387C541D89356D00BDB11A /* Project object */; 32 | proxyType = 1; 33 | remoteGlobalIDString = A4387C5B1D89356D00BDB11A; 34 | remoteInfo = ZKBanner; 35 | }; 36 | /* End PBXContainerItemProxy section */ 37 | 38 | /* Begin PBXFileReference section */ 39 | A4387C921D8935D900BDB11A /* NewBannerView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NewBannerView.h; sourceTree = ""; }; 40 | A4387C931D8935D900BDB11A /* NewBannerView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NewBannerView.m; sourceTree = ""; }; 41 | A4387C941D8935D900BDB11A /* NewBannerViewManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NewBannerViewManager.h; sourceTree = ""; }; 42 | A4387C951D8935D900BDB11A /* NewBannerViewManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NewBannerViewManager.m; sourceTree = ""; }; 43 | A4387C981D8935D900BDB11A /* TAAbstractDotView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TAAbstractDotView.h; sourceTree = ""; }; 44 | A4387C991D8935D900BDB11A /* TAAbstractDotView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TAAbstractDotView.m; sourceTree = ""; }; 45 | A4387C9A1D8935D900BDB11A /* TAAnimatedDotView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TAAnimatedDotView.h; sourceTree = ""; }; 46 | A4387C9B1D8935D900BDB11A /* TAAnimatedDotView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TAAnimatedDotView.m; sourceTree = ""; }; 47 | A4387C9C1D8935D900BDB11A /* TADotView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TADotView.h; sourceTree = ""; }; 48 | A4387C9D1D8935D900BDB11A /* TADotView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TADotView.m; sourceTree = ""; }; 49 | A4387C9E1D8935D900BDB11A /* TAPageControl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TAPageControl.h; sourceTree = ""; }; 50 | A4387C9F1D8935D900BDB11A /* TAPageControl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TAPageControl.m; sourceTree = ""; }; 51 | A4387CA01D8935D900BDB11A /* SDCollectionViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDCollectionViewCell.h; sourceTree = ""; }; 52 | A4387CA11D8935D900BDB11A /* SDCollectionViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDCollectionViewCell.m; sourceTree = ""; }; 53 | A4387CA21D8935D900BDB11A /* SDCycleScrollView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDCycleScrollView.h; sourceTree = ""; }; 54 | A4387CA31D8935D900BDB11A /* SDCycleScrollView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDCycleScrollView.m; sourceTree = ""; }; 55 | A4387CA41D8935D900BDB11A /* UIView+SDExtension.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIView+SDExtension.h"; sourceTree = ""; }; 56 | A4387CA51D8935D900BDB11A /* UIView+SDExtension.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIView+SDExtension.m"; sourceTree = ""; }; 57 | A4387CAF1D89361400BDB11A /* ZKBanner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; name = ZKBanner.app; path = "/Users/cain/Desktop/react-banner/ZKBanner/build/Debug-iphoneos/ZKBanner.app"; sourceTree = ""; }; 58 | A4387CB01D89361400BDB11A /* ZKBannerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; name = ZKBannerTests.xctest; path = "/Users/cain/Desktop/react-banner/ZKBanner/build/Debug-iphoneos/ZKBannerTests.xctest"; sourceTree = ""; }; 59 | A4387CB11D89361400BDB11A /* ZKBannerUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; name = ZKBannerUITests.xctest; path = "/Users/cain/Desktop/react-banner/ZKBanner/build/Debug-iphoneos/ZKBannerUITests.xctest"; sourceTree = ""; }; 60 | /* End PBXFileReference section */ 61 | 62 | /* Begin PBXFrameworksBuildPhase section */ 63 | A4387C591D89356D00BDB11A /* Frameworks */ = { 64 | isa = PBXFrameworksBuildPhase; 65 | buildActionMask = 2147483647; 66 | files = ( 67 | ); 68 | runOnlyForDeploymentPostprocessing = 0; 69 | }; 70 | A4387C721D89356D00BDB11A /* Frameworks */ = { 71 | isa = PBXFrameworksBuildPhase; 72 | buildActionMask = 2147483647; 73 | files = ( 74 | ); 75 | runOnlyForDeploymentPostprocessing = 0; 76 | }; 77 | A4387C7D1D89356D00BDB11A /* Frameworks */ = { 78 | isa = PBXFrameworksBuildPhase; 79 | buildActionMask = 2147483647; 80 | files = ( 81 | ); 82 | runOnlyForDeploymentPostprocessing = 0; 83 | }; 84 | /* End PBXFrameworksBuildPhase section */ 85 | 86 | /* Begin PBXGroup section */ 87 | A4387C531D89356D00BDB11A = { 88 | isa = PBXGroup; 89 | children = ( 90 | A4387C5E1D89356D00BDB11A /* ZKBanner */, 91 | ); 92 | sourceTree = ""; 93 | }; 94 | A4387C5E1D89356D00BDB11A /* ZKBanner */ = { 95 | isa = PBXGroup; 96 | children = ( 97 | A4387C921D8935D900BDB11A /* NewBannerView.h */, 98 | A4387C931D8935D900BDB11A /* NewBannerView.m */, 99 | A4387C941D8935D900BDB11A /* NewBannerViewManager.h */, 100 | A4387C951D8935D900BDB11A /* NewBannerViewManager.m */, 101 | A4387C961D8935D900BDB11A /* SDCycleScrollView */, 102 | ); 103 | path = ZKBanner; 104 | sourceTree = ""; 105 | }; 106 | A4387C961D8935D900BDB11A /* SDCycleScrollView */ = { 107 | isa = PBXGroup; 108 | children = ( 109 | A4387C971D8935D900BDB11A /* PageControl */, 110 | A4387CA01D8935D900BDB11A /* SDCollectionViewCell.h */, 111 | A4387CA11D8935D900BDB11A /* SDCollectionViewCell.m */, 112 | A4387CA21D8935D900BDB11A /* SDCycleScrollView.h */, 113 | A4387CA31D8935D900BDB11A /* SDCycleScrollView.m */, 114 | A4387CA41D8935D900BDB11A /* UIView+SDExtension.h */, 115 | A4387CA51D8935D900BDB11A /* UIView+SDExtension.m */, 116 | ); 117 | path = SDCycleScrollView; 118 | sourceTree = ""; 119 | }; 120 | A4387C971D8935D900BDB11A /* PageControl */ = { 121 | isa = PBXGroup; 122 | children = ( 123 | A4387C981D8935D900BDB11A /* TAAbstractDotView.h */, 124 | A4387C991D8935D900BDB11A /* TAAbstractDotView.m */, 125 | A4387C9A1D8935D900BDB11A /* TAAnimatedDotView.h */, 126 | A4387C9B1D8935D900BDB11A /* TAAnimatedDotView.m */, 127 | A4387C9C1D8935D900BDB11A /* TADotView.h */, 128 | A4387C9D1D8935D900BDB11A /* TADotView.m */, 129 | A4387C9E1D8935D900BDB11A /* TAPageControl.h */, 130 | A4387C9F1D8935D900BDB11A /* TAPageControl.m */, 131 | ); 132 | path = PageControl; 133 | sourceTree = ""; 134 | }; 135 | /* End PBXGroup section */ 136 | 137 | /* Begin PBXNativeTarget section */ 138 | A4387C5B1D89356D00BDB11A /* ZKBanner */ = { 139 | isa = PBXNativeTarget; 140 | buildConfigurationList = A4387C891D89356D00BDB11A /* Build configuration list for PBXNativeTarget "ZKBanner" */; 141 | buildPhases = ( 142 | A4387C581D89356D00BDB11A /* Sources */, 143 | A4387C591D89356D00BDB11A /* Frameworks */, 144 | A4387C5A1D89356D00BDB11A /* Resources */, 145 | ); 146 | buildRules = ( 147 | ); 148 | dependencies = ( 149 | ); 150 | name = ZKBanner; 151 | productName = ZKBanner; 152 | productReference = A4387CAF1D89361400BDB11A /* ZKBanner.app */; 153 | productType = "com.apple.product-type.application"; 154 | }; 155 | A4387C741D89356D00BDB11A /* ZKBannerTests */ = { 156 | isa = PBXNativeTarget; 157 | buildConfigurationList = A4387C8C1D89356D00BDB11A /* Build configuration list for PBXNativeTarget "ZKBannerTests" */; 158 | buildPhases = ( 159 | A4387C711D89356D00BDB11A /* Sources */, 160 | A4387C721D89356D00BDB11A /* Frameworks */, 161 | A4387C731D89356D00BDB11A /* Resources */, 162 | ); 163 | buildRules = ( 164 | ); 165 | dependencies = ( 166 | A4387C771D89356D00BDB11A /* PBXTargetDependency */, 167 | ); 168 | name = ZKBannerTests; 169 | productName = ZKBannerTests; 170 | productReference = A4387CB01D89361400BDB11A /* ZKBannerTests.xctest */; 171 | productType = "com.apple.product-type.bundle.unit-test"; 172 | }; 173 | A4387C7F1D89356D00BDB11A /* ZKBannerUITests */ = { 174 | isa = PBXNativeTarget; 175 | buildConfigurationList = A4387C8F1D89356D00BDB11A /* Build configuration list for PBXNativeTarget "ZKBannerUITests" */; 176 | buildPhases = ( 177 | A4387C7C1D89356D00BDB11A /* Sources */, 178 | A4387C7D1D89356D00BDB11A /* Frameworks */, 179 | A4387C7E1D89356D00BDB11A /* Resources */, 180 | ); 181 | buildRules = ( 182 | ); 183 | dependencies = ( 184 | A4387C821D89356D00BDB11A /* PBXTargetDependency */, 185 | ); 186 | name = ZKBannerUITests; 187 | productName = ZKBannerUITests; 188 | productReference = A4387CB11D89361400BDB11A /* ZKBannerUITests.xctest */; 189 | productType = "com.apple.product-type.bundle.ui-testing"; 190 | }; 191 | /* End PBXNativeTarget section */ 192 | 193 | /* Begin PBXProject section */ 194 | A4387C541D89356D00BDB11A /* Project object */ = { 195 | isa = PBXProject; 196 | attributes = { 197 | LastUpgradeCheck = 0730; 198 | ORGANIZATIONNAME = Cain; 199 | TargetAttributes = { 200 | A4387C5B1D89356D00BDB11A = { 201 | CreatedOnToolsVersion = 7.3.1; 202 | DevelopmentTeam = 8G79A736F5; 203 | }; 204 | A4387C741D89356D00BDB11A = { 205 | CreatedOnToolsVersion = 7.3.1; 206 | DevelopmentTeam = 8G79A736F5; 207 | TestTargetID = A4387C5B1D89356D00BDB11A; 208 | }; 209 | A4387C7F1D89356D00BDB11A = { 210 | CreatedOnToolsVersion = 7.3.1; 211 | DevelopmentTeam = 8G79A736F5; 212 | TestTargetID = A4387C5B1D89356D00BDB11A; 213 | }; 214 | }; 215 | }; 216 | buildConfigurationList = A4387C571D89356D00BDB11A /* Build configuration list for PBXProject "ZKBanner" */; 217 | compatibilityVersion = "Xcode 3.2"; 218 | developmentRegion = English; 219 | hasScannedForEncodings = 0; 220 | knownRegions = ( 221 | en, 222 | Base, 223 | ); 224 | mainGroup = A4387C531D89356D00BDB11A; 225 | productRefGroup = A4387C531D89356D00BDB11A; 226 | projectDirPath = ""; 227 | projectRoot = ""; 228 | targets = ( 229 | A4387C5B1D89356D00BDB11A /* ZKBanner */, 230 | A4387C741D89356D00BDB11A /* ZKBannerTests */, 231 | A4387C7F1D89356D00BDB11A /* ZKBannerUITests */, 232 | ); 233 | }; 234 | /* End PBXProject section */ 235 | 236 | /* Begin PBXResourcesBuildPhase section */ 237 | A4387C5A1D89356D00BDB11A /* Resources */ = { 238 | isa = PBXResourcesBuildPhase; 239 | buildActionMask = 2147483647; 240 | files = ( 241 | ); 242 | runOnlyForDeploymentPostprocessing = 0; 243 | }; 244 | A4387C731D89356D00BDB11A /* Resources */ = { 245 | isa = PBXResourcesBuildPhase; 246 | buildActionMask = 2147483647; 247 | files = ( 248 | ); 249 | runOnlyForDeploymentPostprocessing = 0; 250 | }; 251 | A4387C7E1D89356D00BDB11A /* Resources */ = { 252 | isa = PBXResourcesBuildPhase; 253 | buildActionMask = 2147483647; 254 | files = ( 255 | ); 256 | runOnlyForDeploymentPostprocessing = 0; 257 | }; 258 | /* End PBXResourcesBuildPhase section */ 259 | 260 | /* Begin PBXSourcesBuildPhase section */ 261 | A4387C581D89356D00BDB11A /* Sources */ = { 262 | isa = PBXSourcesBuildPhase; 263 | buildActionMask = 2147483647; 264 | files = ( 265 | A4387CA91D8935D900BDB11A /* TAAnimatedDotView.m in Sources */, 266 | A4387CA61D8935D900BDB11A /* NewBannerView.m in Sources */, 267 | A4387CAC1D8935D900BDB11A /* SDCollectionViewCell.m in Sources */, 268 | A4387CA81D8935D900BDB11A /* TAAbstractDotView.m in Sources */, 269 | A4387CAE1D8935D900BDB11A /* UIView+SDExtension.m in Sources */, 270 | A4387CA71D8935D900BDB11A /* NewBannerViewManager.m in Sources */, 271 | A4387CAA1D8935D900BDB11A /* TADotView.m in Sources */, 272 | A4387CAB1D8935D900BDB11A /* TAPageControl.m in Sources */, 273 | A4387CAD1D8935D900BDB11A /* SDCycleScrollView.m in Sources */, 274 | ); 275 | runOnlyForDeploymentPostprocessing = 0; 276 | }; 277 | A4387C711D89356D00BDB11A /* Sources */ = { 278 | isa = PBXSourcesBuildPhase; 279 | buildActionMask = 2147483647; 280 | files = ( 281 | ); 282 | runOnlyForDeploymentPostprocessing = 0; 283 | }; 284 | A4387C7C1D89356D00BDB11A /* Sources */ = { 285 | isa = PBXSourcesBuildPhase; 286 | buildActionMask = 2147483647; 287 | files = ( 288 | ); 289 | runOnlyForDeploymentPostprocessing = 0; 290 | }; 291 | /* End PBXSourcesBuildPhase section */ 292 | 293 | /* Begin PBXTargetDependency section */ 294 | A4387C771D89356D00BDB11A /* PBXTargetDependency */ = { 295 | isa = PBXTargetDependency; 296 | target = A4387C5B1D89356D00BDB11A /* ZKBanner */; 297 | targetProxy = A4387C761D89356D00BDB11A /* PBXContainerItemProxy */; 298 | }; 299 | A4387C821D89356D00BDB11A /* PBXTargetDependency */ = { 300 | isa = PBXTargetDependency; 301 | target = A4387C5B1D89356D00BDB11A /* ZKBanner */; 302 | targetProxy = A4387C811D89356D00BDB11A /* PBXContainerItemProxy */; 303 | }; 304 | /* End PBXTargetDependency section */ 305 | 306 | /* Begin XCBuildConfiguration section */ 307 | A4387C871D89356D00BDB11A /* Debug */ = { 308 | isa = XCBuildConfiguration; 309 | buildSettings = { 310 | ALWAYS_SEARCH_USER_PATHS = NO; 311 | CLANG_ANALYZER_NONNULL = YES; 312 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 313 | CLANG_CXX_LIBRARY = "libc++"; 314 | CLANG_ENABLE_MODULES = YES; 315 | CLANG_ENABLE_OBJC_ARC = YES; 316 | CLANG_WARN_BOOL_CONVERSION = YES; 317 | CLANG_WARN_CONSTANT_CONVERSION = YES; 318 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 319 | CLANG_WARN_EMPTY_BODY = YES; 320 | CLANG_WARN_ENUM_CONVERSION = YES; 321 | CLANG_WARN_INT_CONVERSION = YES; 322 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 323 | CLANG_WARN_UNREACHABLE_CODE = YES; 324 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 325 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 326 | COPY_PHASE_STRIP = NO; 327 | DEBUG_INFORMATION_FORMAT = dwarf; 328 | ENABLE_STRICT_OBJC_MSGSEND = YES; 329 | ENABLE_TESTABILITY = YES; 330 | GCC_C_LANGUAGE_STANDARD = gnu99; 331 | GCC_DYNAMIC_NO_PIC = NO; 332 | GCC_NO_COMMON_BLOCKS = YES; 333 | GCC_OPTIMIZATION_LEVEL = 0; 334 | GCC_PREPROCESSOR_DEFINITIONS = ( 335 | "DEBUG=1", 336 | "$(inherited)", 337 | ); 338 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 339 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 340 | GCC_WARN_UNDECLARED_SELECTOR = YES; 341 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 342 | GCC_WARN_UNUSED_FUNCTION = YES; 343 | GCC_WARN_UNUSED_VARIABLE = YES; 344 | IPHONEOS_DEPLOYMENT_TARGET = 9.3; 345 | MTL_ENABLE_DEBUG_INFO = YES; 346 | ONLY_ACTIVE_ARCH = YES; 347 | SDKROOT = iphoneos; 348 | }; 349 | name = Debug; 350 | }; 351 | A4387C881D89356D00BDB11A /* Release */ = { 352 | isa = XCBuildConfiguration; 353 | buildSettings = { 354 | ALWAYS_SEARCH_USER_PATHS = NO; 355 | CLANG_ANALYZER_NONNULL = YES; 356 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 357 | CLANG_CXX_LIBRARY = "libc++"; 358 | CLANG_ENABLE_MODULES = YES; 359 | CLANG_ENABLE_OBJC_ARC = YES; 360 | CLANG_WARN_BOOL_CONVERSION = YES; 361 | CLANG_WARN_CONSTANT_CONVERSION = YES; 362 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 363 | CLANG_WARN_EMPTY_BODY = YES; 364 | CLANG_WARN_ENUM_CONVERSION = YES; 365 | CLANG_WARN_INT_CONVERSION = YES; 366 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 367 | CLANG_WARN_UNREACHABLE_CODE = YES; 368 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 369 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 370 | COPY_PHASE_STRIP = NO; 371 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 372 | ENABLE_NS_ASSERTIONS = NO; 373 | ENABLE_STRICT_OBJC_MSGSEND = YES; 374 | GCC_C_LANGUAGE_STANDARD = gnu99; 375 | GCC_NO_COMMON_BLOCKS = YES; 376 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 377 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 378 | GCC_WARN_UNDECLARED_SELECTOR = YES; 379 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 380 | GCC_WARN_UNUSED_FUNCTION = YES; 381 | GCC_WARN_UNUSED_VARIABLE = YES; 382 | IPHONEOS_DEPLOYMENT_TARGET = 9.3; 383 | MTL_ENABLE_DEBUG_INFO = NO; 384 | SDKROOT = iphoneos; 385 | VALIDATE_PRODUCT = YES; 386 | }; 387 | name = Release; 388 | }; 389 | A4387C8A1D89356D00BDB11A /* Debug */ = { 390 | isa = XCBuildConfiguration; 391 | buildSettings = { 392 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 393 | INFOPLIST_FILE = ZKBanner/Info.plist; 394 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 395 | PRODUCT_BUNDLE_IDENTIFIER = WZK.ZKBanner; 396 | PRODUCT_NAME = "$(TARGET_NAME)"; 397 | }; 398 | name = Debug; 399 | }; 400 | A4387C8B1D89356D00BDB11A /* Release */ = { 401 | isa = XCBuildConfiguration; 402 | buildSettings = { 403 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 404 | INFOPLIST_FILE = ZKBanner/Info.plist; 405 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 406 | PRODUCT_BUNDLE_IDENTIFIER = WZK.ZKBanner; 407 | PRODUCT_NAME = "$(TARGET_NAME)"; 408 | }; 409 | name = Release; 410 | }; 411 | A4387C8D1D89356D00BDB11A /* Debug */ = { 412 | isa = XCBuildConfiguration; 413 | buildSettings = { 414 | BUNDLE_LOADER = "$(TEST_HOST)"; 415 | INFOPLIST_FILE = ZKBannerTests/Info.plist; 416 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 417 | PRODUCT_BUNDLE_IDENTIFIER = WZK.ZKBannerTests; 418 | PRODUCT_NAME = "$(TARGET_NAME)"; 419 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/ZKBanner.app/ZKBanner"; 420 | }; 421 | name = Debug; 422 | }; 423 | A4387C8E1D89356D00BDB11A /* Release */ = { 424 | isa = XCBuildConfiguration; 425 | buildSettings = { 426 | BUNDLE_LOADER = "$(TEST_HOST)"; 427 | INFOPLIST_FILE = ZKBannerTests/Info.plist; 428 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 429 | PRODUCT_BUNDLE_IDENTIFIER = WZK.ZKBannerTests; 430 | PRODUCT_NAME = "$(TARGET_NAME)"; 431 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/ZKBanner.app/ZKBanner"; 432 | }; 433 | name = Release; 434 | }; 435 | A4387C901D89356D00BDB11A /* Debug */ = { 436 | isa = XCBuildConfiguration; 437 | buildSettings = { 438 | INFOPLIST_FILE = ZKBannerUITests/Info.plist; 439 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 440 | PRODUCT_BUNDLE_IDENTIFIER = WZK.ZKBannerUITests; 441 | PRODUCT_NAME = "$(TARGET_NAME)"; 442 | TEST_TARGET_NAME = ZKBanner; 443 | }; 444 | name = Debug; 445 | }; 446 | A4387C911D89356D00BDB11A /* Release */ = { 447 | isa = XCBuildConfiguration; 448 | buildSettings = { 449 | INFOPLIST_FILE = ZKBannerUITests/Info.plist; 450 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 451 | PRODUCT_BUNDLE_IDENTIFIER = WZK.ZKBannerUITests; 452 | PRODUCT_NAME = "$(TARGET_NAME)"; 453 | TEST_TARGET_NAME = ZKBanner; 454 | }; 455 | name = Release; 456 | }; 457 | /* End XCBuildConfiguration section */ 458 | 459 | /* Begin XCConfigurationList section */ 460 | A4387C571D89356D00BDB11A /* Build configuration list for PBXProject "ZKBanner" */ = { 461 | isa = XCConfigurationList; 462 | buildConfigurations = ( 463 | A4387C871D89356D00BDB11A /* Debug */, 464 | A4387C881D89356D00BDB11A /* Release */, 465 | ); 466 | defaultConfigurationIsVisible = 0; 467 | defaultConfigurationName = Release; 468 | }; 469 | A4387C891D89356D00BDB11A /* Build configuration list for PBXNativeTarget "ZKBanner" */ = { 470 | isa = XCConfigurationList; 471 | buildConfigurations = ( 472 | A4387C8A1D89356D00BDB11A /* Debug */, 473 | A4387C8B1D89356D00BDB11A /* Release */, 474 | ); 475 | defaultConfigurationIsVisible = 0; 476 | defaultConfigurationName = Release; 477 | }; 478 | A4387C8C1D89356D00BDB11A /* Build configuration list for PBXNativeTarget "ZKBannerTests" */ = { 479 | isa = XCConfigurationList; 480 | buildConfigurations = ( 481 | A4387C8D1D89356D00BDB11A /* Debug */, 482 | A4387C8E1D89356D00BDB11A /* Release */, 483 | ); 484 | defaultConfigurationIsVisible = 0; 485 | defaultConfigurationName = Release; 486 | }; 487 | A4387C8F1D89356D00BDB11A /* Build configuration list for PBXNativeTarget "ZKBannerUITests" */ = { 488 | isa = XCConfigurationList; 489 | buildConfigurations = ( 490 | A4387C901D89356D00BDB11A /* Debug */, 491 | A4387C911D89356D00BDB11A /* Release */, 492 | ); 493 | defaultConfigurationIsVisible = 0; 494 | defaultConfigurationName = Release; 495 | }; 496 | /* End XCConfigurationList section */ 497 | }; 498 | rootObject = A4387C541D89356D00BDB11A /* Project object */; 499 | } 500 | -------------------------------------------------------------------------------- /ZKBanner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ZKBanner.xcodeproj/project.xcworkspace/xcuserdata/cain.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cainvan/react-native-zkbanner/20412cb42c5a36f0a1d5a56678032ca9877974da/ZKBanner.xcodeproj/project.xcworkspace/xcuserdata/cain.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /ZKBanner.xcodeproj/xcuserdata/cain.xcuserdatad/xcschemes/ZKBanner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 43 | 49 | 50 | 51 | 52 | 53 | 59 | 60 | 61 | 62 | 63 | 64 | 74 | 76 | 82 | 83 | 84 | 85 | 86 | 87 | 93 | 95 | 101 | 102 | 103 | 104 | 106 | 107 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /ZKBanner.xcodeproj/xcuserdata/cain.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | ZKBanner.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | A4387C5B1D89356D00BDB11A 16 | 17 | primary 18 | 19 | 20 | A4387C741D89356D00BDB11A 21 | 22 | primary 23 | 24 | 25 | A4387C7F1D89356D00BDB11A 26 | 27 | primary 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /ZKBanner/NewBannerView.h: -------------------------------------------------------------------------------- 1 | // 2 | // newBannerView.h 3 | // NativeView 4 | // 5 | // Created by Cain on 16/9/13. 6 | // Copyright © 2016年 Facebook. All rights reserved. 7 | // 8 | 9 | #import "SDCycleScrollView.h" 10 | 11 | #import "RCTComponent.h" 12 | #import "UIView+React.h" 13 | 14 | @interface NewBannerView : SDCycleScrollView 15 | 16 | @property (nonatomic, copy) RCTBubblingEventBlock onClickBanner; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /ZKBanner/NewBannerView.m: -------------------------------------------------------------------------------- 1 | // 2 | // newBannerView.m 3 | // NativeView 4 | // 5 | // Created by Cain on 16/9/13. 6 | // Copyright © 2016年 Facebook. All rights reserved. 7 | // 8 | 9 | #import "NewBannerView.h" 10 | 11 | @implementation NewBannerView 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /ZKBanner/NewBannerViewManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // newBannerViewManager.h 3 | // NativeView 4 | // 5 | // Created by Cain on 16/9/13. 6 | // Copyright © 2016年 Facebook. All rights reserved. 7 | // 8 | 9 | #import "RCTViewManager.h" 10 | 11 | @interface NewBanner : RCTViewManager 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /ZKBanner/NewBannerViewManager.m: -------------------------------------------------------------------------------- 1 | // 2 | // newBannerViewManager.m 3 | // NativeView 4 | // 5 | // Created by Cain on 16/9/13. 6 | // Copyright © 2016年 Facebook. All rights reserved. 7 | // 8 | 9 | #import "NewBannerViewManager.h" 10 | #import "NewBannerView.h" 11 | 12 | #import "RCTBridge.h" //进行通信的头文件 13 | #import "RCTEventDispatcher.h" //事件派发,不导入会引起Xcode警告 14 | 15 | @interface NewBanner() 16 | 17 | @end 18 | 19 | @implementation NewBanner 20 | 21 | RCT_EXPORT_MODULE() 22 | 23 | RCT_EXPORT_VIEW_PROPERTY(autoScrollTimeInterval, CGFloat); 24 | 25 | RCT_EXPORT_VIEW_PROPERTY(imageURLStringsGroup, NSArray); 26 | 27 | RCT_EXPORT_VIEW_PROPERTY(autoScroll, BOOL); 28 | 29 | RCT_EXPORT_VIEW_PROPERTY(pageControlAliment, NSInteger); 30 | 31 | RCT_EXPORT_VIEW_PROPERTY(onClickBanner, RCTBubblingEventBlock); 32 | 33 | RCT_EXPORT_VIEW_PROPERTY(localizationImageNamesGroup, NSArray); 34 | 35 | - (UIView *)view 36 | { 37 | NewBannerView *bannerScrollView = [NewBannerView cycleScrollViewWithFrame:CGRectZero delegate:self placeholderImage:nil]; 38 | bannerScrollView.pageControlStyle = SDCycleScrollViewPageContolStyleClassic; 39 | bannerScrollView.pageControlAliment = SDCycleScrollViewPageContolAlimentCenter; 40 | return bannerScrollView; 41 | } 42 | 43 | #pragma mark SDCycleScrollViewDelegate 44 | 45 | //- (NSArray *) customDirectEventTypes { 46 | // return @[@"onClickBanner"]; 47 | //} 48 | 49 | /** 50 | * banner点击 51 | */ 52 | - (void)cycleScrollView:(NewBannerView *)cycleScrollView didSelectItemAtIndex:(NSInteger)index{ 53 | 54 | if (!cycleScrollView.onClickBanner) { 55 | return; 56 | } 57 | 58 | NSLog(@"oc did click %li", [cycleScrollView.reactTag integerValue]); 59 | 60 | cycleScrollView.onClickBanner(@{@"target": cycleScrollView.reactTag, 61 | @"value": [NSNumber numberWithInteger:index+1]}); 62 | 63 | } 64 | 65 | //- (NSDictionary *)constantsToExport{ 66 | // return @{ 67 | // @"SDCycleScrollViewPageContolAliment": @{ 68 | // @"right": @(SDCycleScrollViewPageContolAlimentRight), 69 | // @"center": @(SDCycleScrollViewPageContolAlimentCenter) 70 | // } 71 | // }; 72 | //} 73 | // 74 | //RCT_EXPORT_METHOD(testResetTime:(RCTResponseSenderBlock)callback) { 75 | // 76 | // callback(@[@(234)]); 77 | //} 78 | 79 | @end 80 | -------------------------------------------------------------------------------- /ZKBanner/SDCycleScrollView/PageControl/TAAbstractDotView.h: -------------------------------------------------------------------------------- 1 | // 2 | // TAAbstractDotView.h 3 | // TAPageControl 4 | // 5 | // Created by Tanguy Aladenise on 2015-01-22. 6 | // Copyright (c) 2015 Tanguy Aladenise. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | @interface TAAbstractDotView : UIView 13 | 14 | 15 | /** 16 | * A method call let view know which state appearance it should take. Active meaning it's current page. Inactive not the current page. 17 | * 18 | * @param active BOOL to tell if view is active or not 19 | */ 20 | - (void)changeActivityState:(BOOL)active; 21 | 22 | 23 | @end 24 | 25 | -------------------------------------------------------------------------------- /ZKBanner/SDCycleScrollView/PageControl/TAAbstractDotView.m: -------------------------------------------------------------------------------- 1 | // 2 | // TAAbstractDotView.m 3 | // TAPageControl 4 | // 5 | // Created by Tanguy Aladenise on 2015-01-22. 6 | // Copyright (c) 2015 Tanguy Aladenise. All rights reserved. 7 | // 8 | 9 | #import "TAAbstractDotView.h" 10 | 11 | 12 | @implementation TAAbstractDotView 13 | 14 | 15 | - (id)init 16 | { 17 | @throw [NSException exceptionWithName:NSInternalInconsistencyException 18 | reason:[NSString stringWithFormat:@"You must override %@ in %@", NSStringFromSelector(_cmd), self.class] 19 | userInfo:nil]; 20 | } 21 | 22 | 23 | - (void)changeActivityState:(BOOL)active 24 | { 25 | @throw [NSException exceptionWithName:NSInternalInconsistencyException 26 | reason:[NSString stringWithFormat:@"You must override %@ in %@", NSStringFromSelector(_cmd), self.class] 27 | userInfo:nil]; 28 | } 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /ZKBanner/SDCycleScrollView/PageControl/TAAnimatedDotView.h: -------------------------------------------------------------------------------- 1 | // 2 | // TAAnimatedDotView.h 3 | // TAPageControl 4 | // 5 | // Created by Tanguy Aladenise on 2015-01-22. 6 | // Copyright (c) 2015 Tanguy Aladenise. All rights reserved. 7 | // 8 | 9 | #import "TAAbstractDotView.h" 10 | 11 | @interface TAAnimatedDotView : TAAbstractDotView 12 | 13 | @property (nonatomic, strong) UIColor *dotColor; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /ZKBanner/SDCycleScrollView/PageControl/TAAnimatedDotView.m: -------------------------------------------------------------------------------- 1 | // 2 | // TAAnimatedDotView.m 3 | // TAPageControl 4 | // 5 | // Created by Tanguy Aladenise on 2015-01-22. 6 | // Copyright (c) 2015 Tanguy Aladenise. All rights reserved. 7 | // 8 | 9 | #import "TAAnimatedDotView.h" 10 | 11 | static CGFloat const kAnimateDuration = 1; 12 | 13 | @implementation TAAnimatedDotView 14 | 15 | - (instancetype)init 16 | { 17 | self = [super init]; 18 | if (self) { 19 | [self initialization]; 20 | } 21 | 22 | return self; 23 | } 24 | 25 | 26 | - (id)initWithFrame:(CGRect)frame 27 | { 28 | self = [super initWithFrame:frame]; 29 | if (self) { 30 | [self initialization]; 31 | } 32 | return self; 33 | } 34 | 35 | 36 | - (id)initWithCoder:(NSCoder *)aDecoder 37 | { 38 | self = [super initWithCoder:aDecoder]; 39 | if (self) { 40 | [self initialization]; 41 | } 42 | 43 | return self; 44 | } 45 | 46 | - (void)setDotColor:(UIColor *)dotColor 47 | { 48 | _dotColor = dotColor; 49 | self.layer.borderColor = dotColor.CGColor; 50 | } 51 | 52 | - (void)initialization 53 | { 54 | _dotColor = [UIColor whiteColor]; 55 | self.backgroundColor = [UIColor clearColor]; 56 | self.layer.cornerRadius = CGRectGetWidth(self.frame) / 2; 57 | self.layer.borderColor = [UIColor whiteColor].CGColor; 58 | self.layer.borderWidth = 2; 59 | } 60 | 61 | 62 | - (void)changeActivityState:(BOOL)active 63 | { 64 | if (active) { 65 | [self animateToActiveState]; 66 | } else { 67 | [self animateToDeactiveState]; 68 | } 69 | } 70 | 71 | 72 | - (void)animateToActiveState 73 | { 74 | [UIView animateWithDuration:kAnimateDuration delay:0 usingSpringWithDamping:.5 initialSpringVelocity:-20 options:UIViewAnimationOptionCurveLinear animations:^{ 75 | self.backgroundColor = _dotColor; 76 | self.transform = CGAffineTransformMakeScale(1.4, 1.4); 77 | } completion:nil]; 78 | } 79 | 80 | - (void)animateToDeactiveState 81 | { 82 | [UIView animateWithDuration:kAnimateDuration delay:0 usingSpringWithDamping:.5 initialSpringVelocity:0 options:UIViewAnimationOptionCurveLinear animations:^{ 83 | self.backgroundColor = [UIColor clearColor]; 84 | self.transform = CGAffineTransformIdentity; 85 | } completion:nil]; 86 | } 87 | 88 | @end 89 | -------------------------------------------------------------------------------- /ZKBanner/SDCycleScrollView/PageControl/TADotView.h: -------------------------------------------------------------------------------- 1 | // 2 | // TADotView.h 3 | // TAPageControl 4 | // 5 | // Created by Tanguy Aladenise on 2015-01-22. 6 | // Copyright (c) 2015 Tanguy Aladenise. All rights reserved. 7 | // 8 | 9 | #import "TAAbstractDotView.h" 10 | 11 | @interface TADotView : TAAbstractDotView 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /ZKBanner/SDCycleScrollView/PageControl/TADotView.m: -------------------------------------------------------------------------------- 1 | // 2 | // TADotView.m 3 | // TAPageControl 4 | // 5 | // Created by Tanguy Aladenise on 2015-01-22. 6 | // Copyright (c) 2015 Tanguy Aladenise. All rights reserved. 7 | // 8 | 9 | #import "TADotView.h" 10 | 11 | @implementation TADotView 12 | 13 | 14 | - (instancetype)init 15 | { 16 | self = [super init]; 17 | if (self) { 18 | [self initialization]; 19 | } 20 | 21 | return self; 22 | } 23 | 24 | 25 | - (id)initWithFrame:(CGRect)frame 26 | { 27 | self = [super initWithFrame:frame]; 28 | if (self) { 29 | [self initialization]; 30 | } 31 | return self; 32 | } 33 | 34 | 35 | - (id)initWithCoder:(NSCoder *)aDecoder 36 | { 37 | self = [super initWithCoder:aDecoder]; 38 | if (self) { 39 | [self initialization]; 40 | } 41 | 42 | return self; 43 | } 44 | 45 | - (void)initialization 46 | { 47 | self.backgroundColor = [UIColor clearColor]; 48 | self.layer.cornerRadius = CGRectGetWidth(self.frame) / 2; 49 | self.layer.borderColor = [UIColor whiteColor].CGColor; 50 | self.layer.borderWidth = 2; 51 | } 52 | 53 | 54 | - (void)changeActivityState:(BOOL)active 55 | { 56 | if (active) { 57 | self.backgroundColor = [UIColor whiteColor]; 58 | } else { 59 | self.backgroundColor = [UIColor clearColor]; 60 | } 61 | } 62 | 63 | @end 64 | -------------------------------------------------------------------------------- /ZKBanner/SDCycleScrollView/PageControl/TAPageControl.h: -------------------------------------------------------------------------------- 1 | // 2 | // TAPageControl.h 3 | // TAPageControl 4 | // 5 | // Created by Tanguy Aladenise on 2015-01-21. 6 | // Copyright (c) 2015 Tanguy Aladenise. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @protocol TAPageControlDelegate; 12 | 13 | 14 | @interface TAPageControl : UIControl 15 | 16 | 17 | /** 18 | * Dot view customization properties 19 | */ 20 | 21 | /** 22 | * The Class of your custom UIView, make sure to respect the TAAbstractDotView class. 23 | */ 24 | @property (nonatomic) Class dotViewClass; 25 | 26 | 27 | /** 28 | * UIImage to represent a dot. 29 | */ 30 | @property (nonatomic) UIImage *dotImage; 31 | 32 | 33 | /** 34 | * UIImage to represent current page dot. 35 | */ 36 | @property (nonatomic) UIImage *currentDotImage; 37 | 38 | 39 | /** 40 | * Dot size for dot views. Default is 8 by 8. 41 | */ 42 | @property (nonatomic) CGSize dotSize; 43 | 44 | 45 | @property (nonatomic, strong) UIColor *dotColor; 46 | 47 | /** 48 | * Spacing between two dot views. Default is 8. 49 | */ 50 | @property (nonatomic) NSInteger spacingBetweenDots; 51 | 52 | 53 | /** 54 | * Page control setup properties 55 | */ 56 | 57 | 58 | /** 59 | * Delegate for TAPageControl 60 | */ 61 | @property(nonatomic,assign) id delegate; 62 | 63 | 64 | /** 65 | * Number of pages for control. Default is 0. 66 | */ 67 | @property (nonatomic) NSInteger numberOfPages; 68 | 69 | 70 | /** 71 | * Current page on which control is active. Default is 0. 72 | */ 73 | @property (nonatomic) NSInteger currentPage; 74 | 75 | 76 | /** 77 | * Hide the control if there is only one page. Default is NO. 78 | */ 79 | @property (nonatomic) BOOL hidesForSinglePage; 80 | 81 | 82 | /** 83 | * Let the control know if should grow bigger by keeping center, or just get longer (right side expanding). By default YES. 84 | */ 85 | @property (nonatomic) BOOL shouldResizeFromCenter; 86 | 87 | 88 | /** 89 | * Return the minimum size required to display control properly for the given page count. 90 | * 91 | * @param pageCount Number of dots that will require display 92 | * 93 | * @return The CGSize being the minimum size required. 94 | */ 95 | - (CGSize)sizeForNumberOfPages:(NSInteger)pageCount; 96 | 97 | 98 | @end 99 | 100 | 101 | @protocol TAPageControlDelegate 102 | 103 | @optional 104 | - (void)TAPageControl:(TAPageControl *)pageControl didSelectPageAtIndex:(NSInteger)index; 105 | 106 | @end 107 | -------------------------------------------------------------------------------- /ZKBanner/SDCycleScrollView/PageControl/TAPageControl.m: -------------------------------------------------------------------------------- 1 | // 2 | // TAPageControl.m 3 | // TAPageControl 4 | // 5 | // Created by Tanguy Aladenise on 2015-01-21. 6 | // Copyright (c) 2015 Tanguy Aladenise. All rights reserved. 7 | // 8 | 9 | #import "TAPageControl.h" 10 | #import "TAAbstractDotView.h" 11 | #import "TAAnimatedDotView.h" 12 | #import "TADotView.h" 13 | 14 | /** 15 | * Default number of pages for initialization 16 | */ 17 | static NSInteger const kDefaultNumberOfPages = 0; 18 | 19 | /** 20 | * Default current page for initialization 21 | */ 22 | static NSInteger const kDefaultCurrentPage = 0; 23 | 24 | /** 25 | * Default setting for hide for single page feature. For initialization 26 | */ 27 | static BOOL const kDefaultHideForSinglePage = NO; 28 | 29 | /** 30 | * Default setting for shouldResizeFromCenter. For initialiation 31 | */ 32 | static BOOL const kDefaultShouldResizeFromCenter = YES; 33 | 34 | /** 35 | * Default spacing between dots 36 | */ 37 | static NSInteger const kDefaultSpacingBetweenDots = 8; 38 | 39 | /** 40 | * Default dot size 41 | */ 42 | static CGSize const kDefaultDotSize = {8, 8}; 43 | 44 | 45 | @interface TAPageControl() 46 | 47 | 48 | /** 49 | * Array of dot views for reusability and touch events. 50 | */ 51 | @property (strong, nonatomic) NSMutableArray *dots; 52 | 53 | 54 | @end 55 | 56 | @implementation TAPageControl 57 | 58 | 59 | #pragma mark - Lifecycle 60 | 61 | 62 | - (id)init 63 | { 64 | self = [super init]; 65 | if (self) { 66 | [self initialization]; 67 | } 68 | 69 | return self; 70 | } 71 | 72 | 73 | - (id)initWithFrame:(CGRect)frame 74 | { 75 | self = [super initWithFrame:frame]; 76 | if (self) { 77 | [self initialization]; 78 | } 79 | return self; 80 | } 81 | 82 | 83 | - (id)initWithCoder:(NSCoder *)aDecoder 84 | { 85 | self = [super initWithCoder:aDecoder]; 86 | if (self) { 87 | [self initialization]; 88 | } 89 | 90 | return self; 91 | } 92 | 93 | 94 | /** 95 | * Default setup when initiating control 96 | */ 97 | - (void)initialization 98 | { 99 | self.dotViewClass = [TAAnimatedDotView class]; 100 | self.spacingBetweenDots = kDefaultSpacingBetweenDots; 101 | self.numberOfPages = kDefaultNumberOfPages; 102 | self.currentPage = kDefaultCurrentPage; 103 | self.hidesForSinglePage = kDefaultHideForSinglePage; 104 | self.shouldResizeFromCenter = kDefaultShouldResizeFromCenter; 105 | } 106 | 107 | 108 | #pragma mark - Touch event 109 | 110 | - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 111 | { 112 | UITouch *touch = [touches anyObject]; 113 | if (touch.view != self) { 114 | NSInteger index = [self.dots indexOfObject:touch.view]; 115 | if ([self.delegate respondsToSelector:@selector(TAPageControl:didSelectPageAtIndex:)]) { 116 | [self.delegate TAPageControl:self didSelectPageAtIndex:index]; 117 | } 118 | } 119 | } 120 | 121 | #pragma mark - Layout 122 | 123 | 124 | /** 125 | * Resizes and moves the receiver view so it just encloses its subviews. 126 | */ 127 | - (void)sizeToFit 128 | { 129 | [self updateFrame:YES]; 130 | } 131 | 132 | 133 | - (CGSize)sizeForNumberOfPages:(NSInteger)pageCount 134 | { 135 | return CGSizeMake((self.dotSize.width + self.spacingBetweenDots) * pageCount - self.spacingBetweenDots , self.dotSize.height); 136 | } 137 | 138 | 139 | /** 140 | * Will update dots display and frame. Reuse existing views or instantiate one if required. Update their position in case frame changed. 141 | */ 142 | - (void)updateDots 143 | { 144 | if (self.numberOfPages == 0) { 145 | return; 146 | } 147 | 148 | for (NSInteger i = 0; i < self.numberOfPages; i++) { 149 | 150 | UIView *dot; 151 | if (i < self.dots.count) { 152 | dot = [self.dots objectAtIndex:i]; 153 | } else { 154 | dot = [self generateDotView]; 155 | } 156 | 157 | [self updateDotFrame:dot atIndex:i]; 158 | } 159 | 160 | [self changeActivity:YES atIndex:self.currentPage]; 161 | 162 | [self hideForSinglePage]; 163 | } 164 | 165 | 166 | /** 167 | * Update frame control to fit current number of pages. It will apply required size if authorize and required. 168 | * 169 | * @param overrideExistingFrame BOOL to allow frame to be overriden. Meaning the required size will be apply no mattter what. 170 | */ 171 | - (void)updateFrame:(BOOL)overrideExistingFrame 172 | { 173 | CGPoint center = self.center; 174 | CGSize requiredSize = [self sizeForNumberOfPages:self.numberOfPages]; 175 | 176 | // We apply requiredSize only if authorize to and necessary 177 | if (overrideExistingFrame || ((CGRectGetWidth(self.frame) < requiredSize.width || CGRectGetHeight(self.frame) < requiredSize.height) && !overrideExistingFrame)) { 178 | self.frame = CGRectMake(CGRectGetMinX(self.frame), CGRectGetMinY(self.frame), requiredSize.width, requiredSize.height); 179 | if (self.shouldResizeFromCenter) { 180 | self.center = center; 181 | } 182 | } 183 | 184 | [self resetDotViews]; 185 | } 186 | 187 | 188 | /** 189 | * Update the frame of a specific dot at a specific index 190 | * 191 | * @param dot Dot view 192 | * @param index Page index of dot 193 | */ 194 | - (void)updateDotFrame:(UIView *)dot atIndex:(NSInteger)index 195 | { 196 | // Dots are always centered within view 197 | CGFloat x = (self.dotSize.width + self.spacingBetweenDots) * index + ( (CGRectGetWidth(self.frame) - [self sizeForNumberOfPages:self.numberOfPages].width) / 2); 198 | CGFloat y = (CGRectGetHeight(self.frame) - self.dotSize.height) / 2; 199 | 200 | dot.frame = CGRectMake(x, y, self.dotSize.width, self.dotSize.height); 201 | } 202 | 203 | 204 | #pragma mark - Utils 205 | 206 | 207 | /** 208 | * Generate a dot view and add it to the collection 209 | * 210 | * @return The UIView object representing a dot 211 | */ 212 | - (UIView *)generateDotView 213 | { 214 | UIView *dotView; 215 | 216 | if (self.dotViewClass) { 217 | dotView = [[self.dotViewClass alloc] initWithFrame:CGRectMake(0, 0, self.dotSize.width, self.dotSize.height)]; 218 | if ([dotView isKindOfClass:[TAAnimatedDotView class]] && self.dotColor) { 219 | ((TAAnimatedDotView *)dotView).dotColor = self.dotColor; 220 | } 221 | } else { 222 | dotView = [[UIImageView alloc] initWithImage:self.dotImage]; 223 | dotView.frame = CGRectMake(0, 0, self.dotSize.width, self.dotSize.height); 224 | } 225 | 226 | if (dotView) { 227 | [self addSubview:dotView]; 228 | [self.dots addObject:dotView]; 229 | } 230 | 231 | dotView.userInteractionEnabled = YES; 232 | return dotView; 233 | } 234 | 235 | 236 | /** 237 | * Change activity state of a dot view. Current/not currrent. 238 | * 239 | * @param active Active state to apply 240 | * @param index Index of dot for state update 241 | */ 242 | - (void)changeActivity:(BOOL)active atIndex:(NSInteger)index 243 | { 244 | if (self.dotViewClass) { 245 | TAAbstractDotView *abstractDotView = (TAAbstractDotView *)[self.dots objectAtIndex:index]; 246 | if ([abstractDotView respondsToSelector:@selector(changeActivityState:)]) { 247 | [abstractDotView changeActivityState:active]; 248 | } else { 249 | NSLog(@"Custom view : %@ must implement an 'changeActivityState' method or you can subclass %@ to help you.", self.dotViewClass, [TAAbstractDotView class]); 250 | } 251 | } else if (self.dotImage && self.currentDotImage) { 252 | UIImageView *dotView = (UIImageView *)[self.dots objectAtIndex:index]; 253 | dotView.image = (active) ? self.currentDotImage : self.dotImage; 254 | } 255 | } 256 | 257 | 258 | - (void)resetDotViews 259 | { 260 | for (UIView *dotView in self.dots) { 261 | [dotView removeFromSuperview]; 262 | } 263 | 264 | [self.dots removeAllObjects]; 265 | [self updateDots]; 266 | } 267 | 268 | 269 | - (void)hideForSinglePage 270 | { 271 | if (self.dots.count == 1 && self.hidesForSinglePage) { 272 | self.hidden = YES; 273 | } else { 274 | self.hidden = NO; 275 | } 276 | } 277 | 278 | #pragma mark - Setters 279 | 280 | 281 | - (void)setNumberOfPages:(NSInteger)numberOfPages 282 | { 283 | _numberOfPages = numberOfPages; 284 | 285 | // Update dot position to fit new number of pages 286 | [self resetDotViews]; 287 | } 288 | 289 | 290 | - (void)setSpacingBetweenDots:(NSInteger)spacingBetweenDots 291 | { 292 | _spacingBetweenDots = spacingBetweenDots; 293 | 294 | [self resetDotViews]; 295 | } 296 | 297 | 298 | - (void)setCurrentPage:(NSInteger)currentPage 299 | { 300 | // If no pages, no current page to treat. 301 | if (self.numberOfPages == 0 || currentPage == _currentPage) { 302 | _currentPage = currentPage; 303 | return; 304 | } 305 | 306 | // Pre set 307 | [self changeActivity:NO atIndex:_currentPage]; 308 | _currentPage = currentPage; 309 | // Post set 310 | [self changeActivity:YES atIndex:_currentPage]; 311 | } 312 | 313 | 314 | - (void)setDotImage:(UIImage *)dotImage 315 | { 316 | _dotImage = dotImage; 317 | [self resetDotViews]; 318 | self.dotViewClass = nil; 319 | } 320 | 321 | 322 | - (void)setCurrentDotImage:(UIImage *)currentDotimage 323 | { 324 | _currentDotImage = currentDotimage; 325 | [self resetDotViews]; 326 | self.dotViewClass = nil; 327 | } 328 | 329 | 330 | - (void)setDotViewClass:(Class)dotViewClass 331 | { 332 | _dotViewClass = dotViewClass; 333 | self.dotSize = CGSizeZero; 334 | [self resetDotViews]; 335 | } 336 | 337 | 338 | #pragma mark - Getters 339 | 340 | 341 | - (NSMutableArray *)dots 342 | { 343 | if (!_dots) { 344 | _dots = [[NSMutableArray alloc] init]; 345 | } 346 | 347 | return _dots; 348 | } 349 | 350 | 351 | - (CGSize)dotSize 352 | { 353 | // Dot size logic depending on the source of the dot view 354 | if (self.dotImage && CGSizeEqualToSize(_dotSize, CGSizeZero)) { 355 | _dotSize = self.dotImage.size; 356 | } else if (self.dotViewClass && CGSizeEqualToSize(_dotSize, CGSizeZero)) { 357 | _dotSize = kDefaultDotSize; 358 | return _dotSize; 359 | } 360 | 361 | return _dotSize; 362 | } 363 | 364 | @end 365 | -------------------------------------------------------------------------------- /ZKBanner/SDCycleScrollView/SDCollectionViewCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // SDCollectionViewCell.h 3 | // SDCycleScrollView 4 | // 5 | // Created by aier on 15-3-22. 6 | // Copyright (c) 2015年 GSD. All rights reserved. 7 | // 8 | 9 | 10 | #import 11 | 12 | @interface SDCollectionViewCell : UICollectionViewCell 13 | 14 | @property (weak, nonatomic) UIImageView *imageView; 15 | @property (copy, nonatomic) NSString *title; 16 | 17 | @property (nonatomic, strong) UIColor *titleLabelTextColor; 18 | @property (nonatomic, strong) UIFont *titleLabelTextFont; 19 | @property (nonatomic, strong) UIColor *titleLabelBackgroundColor; 20 | @property (nonatomic, assign) CGFloat titleLabelHeight; 21 | 22 | @property (nonatomic, assign) BOOL hasConfigured; 23 | 24 | /** 只展示文字轮播 */ 25 | @property (nonatomic, assign) BOOL onlyDisplayText; 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /ZKBanner/SDCycleScrollView/SDCollectionViewCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // SDCollectionViewCell.m 3 | // SDCycleScrollView 4 | // 5 | // Created by aier on 15-3-22. 6 | // Copyright (c) 2015年 GSD. All rights reserved. 7 | // 8 | 9 | 10 | 11 | #import "SDCollectionViewCell.h" 12 | #import "UIView+SDExtension.h" 13 | 14 | @implementation SDCollectionViewCell 15 | { 16 | __weak UILabel *_titleLabel; 17 | } 18 | 19 | 20 | - (instancetype)initWithFrame:(CGRect)frame 21 | { 22 | if (self = [super initWithFrame:frame]) { 23 | [self setupImageView]; 24 | [self setupTitleLabel]; 25 | } 26 | 27 | return self; 28 | } 29 | 30 | - (void)setTitleLabelBackgroundColor:(UIColor *)titleLabelBackgroundColor 31 | { 32 | _titleLabelBackgroundColor = titleLabelBackgroundColor; 33 | _titleLabel.backgroundColor = titleLabelBackgroundColor; 34 | } 35 | 36 | - (void)setTitleLabelTextColor:(UIColor *)titleLabelTextColor 37 | { 38 | _titleLabelTextColor = titleLabelTextColor; 39 | _titleLabel.textColor = titleLabelTextColor; 40 | } 41 | 42 | - (void)setTitleLabelTextFont:(UIFont *)titleLabelTextFont 43 | { 44 | _titleLabelTextFont = titleLabelTextFont; 45 | _titleLabel.font = titleLabelTextFont; 46 | } 47 | 48 | - (void)setupImageView 49 | { 50 | UIImageView *imageView = [[UIImageView alloc] init]; 51 | _imageView = imageView; 52 | [self.contentView addSubview:imageView]; 53 | } 54 | 55 | - (void)setupTitleLabel 56 | { 57 | UILabel *titleLabel = [[UILabel alloc] init]; 58 | _titleLabel = titleLabel; 59 | _titleLabel.hidden = YES; 60 | [self.contentView addSubview:titleLabel]; 61 | } 62 | 63 | - (void)setTitle:(NSString *)title 64 | { 65 | _title = [title copy]; 66 | _titleLabel.text = [NSString stringWithFormat:@" %@", title]; 67 | if (_titleLabel.hidden) { 68 | _titleLabel.hidden = NO; 69 | } 70 | } 71 | 72 | 73 | - (void)layoutSubviews 74 | { 75 | [super layoutSubviews]; 76 | 77 | if (self.onlyDisplayText) { 78 | _titleLabel.frame = self.bounds; 79 | } else { 80 | _imageView.frame = self.bounds; 81 | CGFloat titleLabelW = self.sd_width; 82 | CGFloat titleLabelH = _titleLabelHeight; 83 | CGFloat titleLabelX = 0; 84 | CGFloat titleLabelY = self.sd_height - titleLabelH; 85 | _titleLabel.frame = CGRectMake(titleLabelX, titleLabelY, titleLabelW, titleLabelH); 86 | } 87 | } 88 | 89 | @end 90 | -------------------------------------------------------------------------------- /ZKBanner/SDCycleScrollView/SDCycleScrollView.h: -------------------------------------------------------------------------------- 1 | // 2 | // SDCycleScrollView.h 3 | // SDCycleScrollView 4 | // 5 | // Created by aier on 15-3-22. 6 | // Copyright (c) 2015年 GSD. All rights reserved. 7 | // 8 | 9 | 10 | /* 11 | * 当前版本为1.62 12 | * 更新日期:2016.04.21 13 | */ 14 | 15 | #import 16 | 17 | typedef enum { 18 | SDCycleScrollViewPageContolAlimentRight, 19 | SDCycleScrollViewPageContolAlimentCenter 20 | } SDCycleScrollViewPageContolAliment; 21 | 22 | typedef enum { 23 | SDCycleScrollViewPageContolStyleClassic, // 系统自带经典样式 24 | SDCycleScrollViewPageContolStyleAnimated, // 动画效果pagecontrol 25 | SDCycleScrollViewPageContolStyleNone // 不显示pagecontrol 26 | } SDCycleScrollViewPageContolStyle; 27 | 28 | @class SDCycleScrollView; 29 | 30 | @protocol SDCycleScrollViewDelegate 31 | 32 | @optional 33 | 34 | /** 点击图片回调 */ 35 | - (void)cycleScrollView:(SDCycleScrollView *)cycleScrollView didSelectItemAtIndex:(NSInteger)index; 36 | 37 | /** 图片滚动回调 */ 38 | - (void)cycleScrollView:(SDCycleScrollView *)cycleScrollView didScrollToIndex:(NSInteger)index; 39 | 40 | @end 41 | 42 | @interface SDCycleScrollView : UIView 43 | 44 | 45 | /** 初始轮播图(推荐使用) */ 46 | + (instancetype)cycleScrollViewWithFrame:(CGRect)frame delegate:(id)delegate placeholderImage:(UIImage *)placeholderImage; 47 | 48 | + (instancetype)cycleScrollViewWithFrame:(CGRect)frame imageURLStringsGroup:(NSArray *)imageURLStringsGroup; 49 | 50 | 51 | /** 本地图片轮播初始化方式 */ 52 | + (instancetype)cycleScrollViewWithFrame:(CGRect)frame imageNamesGroup:(NSArray *)imageNamesGroup; 53 | 54 | /** 本地图片轮播初始化方式2,infiniteLoop:是否无限循环 */ 55 | + (instancetype)cycleScrollViewWithFrame:(CGRect)frame shouldInfiniteLoop:(BOOL)infiniteLoop imageNamesGroup:(NSArray *)imageNamesGroup; 56 | 57 | 58 | ////////////////////// 数据源接口 ////////////////////// 59 | 60 | /** 网络图片 url string 数组 */ 61 | @property (nonatomic, strong) NSArray *imageURLStringsGroup; 62 | 63 | /** 每张图片对应要显示的文字数组 */ 64 | @property (nonatomic, strong) NSArray *titlesGroup; 65 | 66 | /** 本地图片数组 */ 67 | @property (nonatomic, strong) NSArray *localizationImageNamesGroup; 68 | 69 | 70 | 71 | 72 | 73 | ////////////////////// 滚动控制接口 ////////////////////// 74 | 75 | /** 自动滚动间隔时间,默认2s */ 76 | @property (nonatomic, assign) CGFloat autoScrollTimeInterval; 77 | 78 | /** 是否无限循环,默认Yes */ 79 | @property (nonatomic,assign) BOOL infiniteLoop; 80 | 81 | /** 是否自动滚动,默认Yes */ 82 | @property (nonatomic,assign) BOOL autoScroll; 83 | 84 | /** 图片滚动方向,默认为水平滚动 */ 85 | @property (nonatomic, assign) UICollectionViewScrollDirection scrollDirection; 86 | 87 | @property (nonatomic, weak) id delegate; 88 | 89 | /** block方式监听点击 */ 90 | @property (nonatomic, copy) void (^clickItemOperationBlock)(NSInteger currentIndex); 91 | 92 | /** block方式监听滚动 */ 93 | @property (nonatomic, copy) void (^itemDidScrollOperationBlock)(NSInteger currentIndex); 94 | 95 | /** 解决viewWillAppear时出现时轮播图卡在一半的问题,在控制器viewWillAppear时调用此方法 */ 96 | - (void)adjustWhenControllerViewWillAppera; 97 | 98 | ////////////////////// 自定义样式接口 ////////////////////// 99 | 100 | 101 | /** 轮播图片的ContentMode,默认为 UIViewContentModeScaleToFill */ 102 | @property (nonatomic, assign) UIViewContentMode bannerImageViewContentMode; 103 | 104 | /** 占位图,用于网络未加载到图片时 */ 105 | @property (nonatomic, strong) UIImage *placeholderImage; 106 | 107 | /** 是否显示分页控件 */ 108 | @property (nonatomic, assign) BOOL showPageControl; 109 | 110 | /** 是否在只有一张图时隐藏pagecontrol,默认为YES */ 111 | @property(nonatomic) BOOL hidesForSinglePage; 112 | 113 | /** 只展示文字轮播 */ 114 | @property (nonatomic, assign) BOOL onlyDisplayText; 115 | 116 | /** pagecontrol 样式,默认为动画样式 */ 117 | @property (nonatomic, assign) SDCycleScrollViewPageContolStyle pageControlStyle; 118 | 119 | /** 分页控件位置 */ 120 | @property (nonatomic, assign) SDCycleScrollViewPageContolAliment pageControlAliment; 121 | 122 | /** 分页控件小圆标大小 */ 123 | @property (nonatomic, assign) CGSize pageControlDotSize; 124 | 125 | /** 当前分页控件小圆标颜色 */ 126 | @property (nonatomic, strong) UIColor *currentPageDotColor; 127 | 128 | /** 其他分页控件小圆标颜色 */ 129 | @property (nonatomic, strong) UIColor *pageDotColor; 130 | 131 | /** 当前分页控件小圆标图片 */ 132 | @property (nonatomic, strong) UIImage *currentPageDotImage; 133 | 134 | /** 其他分页控件小圆标图片 */ 135 | @property (nonatomic, strong) UIImage *pageDotImage; 136 | 137 | /** 轮播文字label字体颜色 */ 138 | @property (nonatomic, strong) UIColor *titleLabelTextColor; 139 | 140 | /** 轮播文字label字体大小 */ 141 | @property (nonatomic, strong) UIFont *titleLabelTextFont; 142 | 143 | /** 轮播文字label背景颜色 */ 144 | @property (nonatomic, strong) UIColor *titleLabelBackgroundColor; 145 | 146 | /** 轮播文字label高度 */ 147 | @property (nonatomic, assign) CGFloat titleLabelHeight; 148 | 149 | 150 | 151 | ////////////////////// 清除缓存接口 ////////////////////// 152 | 153 | /** 清除图片缓存(此次升级后统一使用SDWebImage管理图片加载和缓存) */ 154 | + (void)clearImagesCache; 155 | 156 | /** 清除图片缓存(兼容旧版本方法) */ 157 | - (void)clearCache; 158 | 159 | @end 160 | -------------------------------------------------------------------------------- /ZKBanner/SDCycleScrollView/SDCycleScrollView.m: -------------------------------------------------------------------------------- 1 | // 2 | // SDCycleScrollView.m 3 | // SDCycleScrollView 4 | // 5 | // Created by aier on 15-3-22. 6 | // Copyright (c) 2015年 GSD. All rights reserved. 7 | // 8 | 9 | 10 | #import "SDCycleScrollView.h" 11 | #import "SDCollectionViewCell.h" 12 | #import "UIView+SDExtension.h" 13 | #import "TAPageControl.h" 14 | #import "UIImageView+WebCache.h" 15 | #import "SDImageCache.h" 16 | 17 | #define kCycleScrollViewInitialPageControlDotSize CGSizeMake(10, 10) 18 | 19 | NSString * const ID = @"cycleCell"; 20 | 21 | @interface SDCycleScrollView () 22 | 23 | 24 | @property (nonatomic, weak) UICollectionView *mainView; // 显示图片的collectionView 25 | @property (nonatomic, weak) UICollectionViewFlowLayout *flowLayout; 26 | @property (nonatomic, strong) NSArray *imagePathsGroup; 27 | @property (nonatomic, weak) NSTimer *timer; 28 | @property (nonatomic, assign) NSInteger totalItemsCount; 29 | @property (nonatomic, weak) UIControl *pageControl; 30 | 31 | @property (nonatomic, strong) UIImageView *backgroundImageView; // 当imageURLs为空时的背景图 32 | 33 | @end 34 | 35 | @implementation SDCycleScrollView 36 | 37 | - (instancetype)initWithFrame:(CGRect)frame 38 | { 39 | if (self = [super initWithFrame:frame]) { 40 | [self initialization]; 41 | [self setupMainView]; 42 | } 43 | return self; 44 | } 45 | 46 | - (void)awakeFromNib 47 | { 48 | [self initialization]; 49 | [self setupMainView]; 50 | } 51 | 52 | - (void)initialization 53 | { 54 | _pageControlAliment = SDCycleScrollViewPageContolAlimentCenter; 55 | _autoScrollTimeInterval = 2.0; 56 | _titleLabelTextColor = [UIColor whiteColor]; 57 | _titleLabelTextFont= [UIFont systemFontOfSize:14]; 58 | _titleLabelBackgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.5]; 59 | _titleLabelHeight = 30; 60 | _autoScroll = YES; 61 | _infiniteLoop = YES; 62 | _showPageControl = YES; 63 | _pageControlDotSize = kCycleScrollViewInitialPageControlDotSize; 64 | _pageControlStyle = SDCycleScrollViewPageContolStyleClassic; 65 | _hidesForSinglePage = YES; 66 | _currentPageDotColor = [UIColor whiteColor]; 67 | _pageDotColor = [UIColor lightGrayColor]; 68 | _bannerImageViewContentMode = UIViewContentModeScaleToFill; 69 | 70 | self.backgroundColor = [UIColor whiteColor]; 71 | 72 | } 73 | 74 | + (instancetype)cycleScrollViewWithFrame:(CGRect)frame imageNamesGroup:(NSArray *)imageNamesGroup 75 | { 76 | SDCycleScrollView *cycleScrollView = [[self alloc] initWithFrame:frame]; 77 | cycleScrollView.localizationImageNamesGroup = [NSMutableArray arrayWithArray:imageNamesGroup]; 78 | return cycleScrollView; 79 | } 80 | 81 | + (instancetype)cycleScrollViewWithFrame:(CGRect)frame shouldInfiniteLoop:(BOOL)infiniteLoop imageNamesGroup:(NSArray *)imageNamesGroup 82 | { 83 | SDCycleScrollView *cycleScrollView = [[self alloc] initWithFrame:frame]; 84 | cycleScrollView.infiniteLoop = infiniteLoop; 85 | cycleScrollView.localizationImageNamesGroup = [NSMutableArray arrayWithArray:imageNamesGroup]; 86 | return cycleScrollView; 87 | } 88 | 89 | + (instancetype)cycleScrollViewWithFrame:(CGRect)frame imageURLStringsGroup:(NSArray *)imageURLsGroup 90 | { 91 | SDCycleScrollView *cycleScrollView = [[self alloc] initWithFrame:frame]; 92 | cycleScrollView.imageURLStringsGroup = [NSMutableArray arrayWithArray:imageURLsGroup]; 93 | return cycleScrollView; 94 | } 95 | 96 | + (instancetype)cycleScrollViewWithFrame:(CGRect)frame delegate:(id)delegate placeholderImage:(UIImage *)placeholderImage 97 | { 98 | SDCycleScrollView *cycleScrollView = [[self alloc] initWithFrame:frame]; 99 | cycleScrollView.delegate = delegate; 100 | cycleScrollView.placeholderImage = placeholderImage; 101 | 102 | return cycleScrollView; 103 | } 104 | 105 | // 设置显示图片的collectionView 106 | - (void)setupMainView 107 | { 108 | UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc] init]; 109 | flowLayout.minimumLineSpacing = 0; 110 | flowLayout.scrollDirection = UICollectionViewScrollDirectionHorizontal; 111 | _flowLayout = flowLayout; 112 | 113 | UICollectionView *mainView = [[UICollectionView alloc] initWithFrame:self.bounds collectionViewLayout:flowLayout]; 114 | mainView.backgroundColor = [UIColor clearColor]; 115 | mainView.pagingEnabled = YES; 116 | mainView.showsHorizontalScrollIndicator = NO; 117 | mainView.showsVerticalScrollIndicator = NO; 118 | [mainView registerClass:[SDCollectionViewCell class] forCellWithReuseIdentifier:ID]; 119 | mainView.dataSource = self; 120 | mainView.delegate = self; 121 | mainView.scrollsToTop = NO; 122 | [self addSubview:mainView]; 123 | _mainView = mainView; 124 | } 125 | 126 | 127 | #pragma mark - properties 128 | 129 | - (void)setPlaceholderImage:(UIImage *)placeholderImage 130 | { 131 | _placeholderImage = placeholderImage; 132 | 133 | if (!self.backgroundImageView) { 134 | UIImageView *bgImageView = [UIImageView new]; 135 | bgImageView.contentMode = UIViewContentModeScaleAspectFit; 136 | [self insertSubview:bgImageView belowSubview:self.mainView]; 137 | self.backgroundImageView = bgImageView; 138 | } 139 | 140 | self.backgroundImageView.image = placeholderImage; 141 | } 142 | 143 | - (void)setPageControlDotSize:(CGSize)pageControlDotSize 144 | { 145 | _pageControlDotSize = pageControlDotSize; 146 | [self setupPageControl]; 147 | if ([self.pageControl isKindOfClass:[TAPageControl class]]) { 148 | TAPageControl *pageContol = (TAPageControl *)_pageControl; 149 | pageContol.dotSize = pageControlDotSize; 150 | } 151 | } 152 | 153 | - (void)setShowPageControl:(BOOL)showPageControl 154 | { 155 | _showPageControl = showPageControl; 156 | 157 | _pageControl.hidden = !showPageControl; 158 | } 159 | 160 | - (void)setCurrentPageDotColor:(UIColor *)currentPageDotColor 161 | { 162 | _currentPageDotColor = currentPageDotColor; 163 | if ([self.pageControl isKindOfClass:[TAPageControl class]]) { 164 | TAPageControl *pageControl = (TAPageControl *)_pageControl; 165 | pageControl.dotColor = currentPageDotColor; 166 | } else { 167 | UIPageControl *pageControl = (UIPageControl *)_pageControl; 168 | pageControl.currentPageIndicatorTintColor = currentPageDotColor; 169 | } 170 | 171 | } 172 | 173 | - (void)setPageDotColor:(UIColor *)pageDotColor 174 | { 175 | _pageDotColor = pageDotColor; 176 | 177 | if ([self.pageControl isKindOfClass:[UIPageControl class]]) { 178 | UIPageControl *pageControl = (UIPageControl *)_pageControl; 179 | pageControl.pageIndicatorTintColor = pageDotColor; 180 | } 181 | } 182 | 183 | - (void)setCurrentPageDotImage:(UIImage *)currentPageDotImage 184 | { 185 | _currentPageDotImage = currentPageDotImage; 186 | 187 | if (self.pageControlStyle != SDCycleScrollViewPageContolStyleAnimated) { 188 | self.pageControlStyle = SDCycleScrollViewPageContolStyleAnimated; 189 | } 190 | 191 | [self setCustomPageControlDotImage:currentPageDotImage isCurrentPageDot:YES]; 192 | } 193 | 194 | - (void)setPageDotImage:(UIImage *)pageDotImage 195 | { 196 | _pageDotImage = pageDotImage; 197 | 198 | if (self.pageControlStyle != SDCycleScrollViewPageContolStyleAnimated) { 199 | self.pageControlStyle = SDCycleScrollViewPageContolStyleAnimated; 200 | } 201 | 202 | [self setCustomPageControlDotImage:pageDotImage isCurrentPageDot:NO]; 203 | } 204 | 205 | - (void)setCustomPageControlDotImage:(UIImage *)image isCurrentPageDot:(BOOL)isCurrentPageDot 206 | { 207 | if (!image || !self.pageControl) return; 208 | 209 | if ([self.pageControl isKindOfClass:[TAPageControl class]]) { 210 | TAPageControl *pageControl = (TAPageControl *)_pageControl; 211 | if (isCurrentPageDot) { 212 | pageControl.currentDotImage = image; 213 | } else { 214 | pageControl.dotImage = image; 215 | } 216 | } 217 | } 218 | 219 | - (void)setInfiniteLoop:(BOOL)infiniteLoop 220 | { 221 | _infiniteLoop = infiniteLoop; 222 | 223 | if (self.imagePathsGroup.count) { 224 | self.imagePathsGroup = self.imagePathsGroup; 225 | } 226 | } 227 | 228 | -(void)setAutoScroll:(BOOL)autoScroll{ 229 | _autoScroll = autoScroll; 230 | 231 | [self invalidateTimer]; 232 | 233 | if (_autoScroll) { 234 | [self setupTimer]; 235 | } 236 | } 237 | 238 | - (void)setScrollDirection:(UICollectionViewScrollDirection)scrollDirection 239 | { 240 | _scrollDirection = scrollDirection; 241 | 242 | _flowLayout.scrollDirection = scrollDirection; 243 | } 244 | 245 | - (void)setAutoScrollTimeInterval:(CGFloat)autoScrollTimeInterval 246 | { 247 | _autoScrollTimeInterval = autoScrollTimeInterval; 248 | 249 | [self setAutoScroll:self.autoScroll]; 250 | } 251 | 252 | - (void)setPageControlStyle:(SDCycleScrollViewPageContolStyle)pageControlStyle 253 | { 254 | _pageControlStyle = pageControlStyle; 255 | 256 | [self setupPageControl]; 257 | } 258 | 259 | - (void)setImagePathsGroup:(NSArray *)imagePathsGroup 260 | { 261 | [self invalidateTimer]; 262 | 263 | _imagePathsGroup = imagePathsGroup; 264 | 265 | _totalItemsCount = self.infiniteLoop ? self.imagePathsGroup.count * 100 : self.imagePathsGroup.count; 266 | 267 | if (imagePathsGroup.count != 1) { 268 | self.mainView.scrollEnabled = YES; 269 | [self setAutoScroll:self.autoScroll]; 270 | } else { 271 | self.mainView.scrollEnabled = NO; 272 | } 273 | 274 | [self setupPageControl]; 275 | [self.mainView reloadData]; 276 | } 277 | 278 | - (void)setImageURLStringsGroup:(NSArray *)imageURLStringsGroup 279 | { 280 | _imageURLStringsGroup = imageURLStringsGroup; 281 | 282 | NSMutableArray *temp = [NSMutableArray new]; 283 | [_imageURLStringsGroup enumerateObjectsUsingBlock:^(NSString * obj, NSUInteger idx, BOOL * stop) { 284 | NSString *urlString; 285 | if ([obj isKindOfClass:[NSString class]]) { 286 | urlString = obj; 287 | } else if ([obj isKindOfClass:[NSURL class]]) { 288 | NSURL *url = (NSURL *)obj; 289 | urlString = [url absoluteString]; 290 | } 291 | if (urlString) { 292 | [temp addObject:urlString]; 293 | } 294 | }]; 295 | self.imagePathsGroup = [temp copy]; 296 | } 297 | 298 | - (void)setLocalizationImageNamesGroup:(NSArray *)localizationImageNamesGroup 299 | { 300 | _localizationImageNamesGroup = localizationImageNamesGroup; 301 | self.imagePathsGroup = [localizationImageNamesGroup copy]; 302 | } 303 | 304 | - (void)setTitlesGroup:(NSArray *)titlesGroup 305 | { 306 | _titlesGroup = titlesGroup; 307 | if (self.onlyDisplayText) { 308 | NSMutableArray *temp = [NSMutableArray new]; 309 | for (int i = 0; i < _titlesGroup.count; i++) { 310 | [temp addObject:@""]; 311 | } 312 | self.backgroundColor = [UIColor clearColor]; 313 | self.imageURLStringsGroup = [temp copy]; 314 | } 315 | } 316 | 317 | #pragma mark - actions 318 | 319 | - (void)setupTimer 320 | { 321 | NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:self.autoScrollTimeInterval target:self selector:@selector(automaticScroll) userInfo:nil repeats:YES]; 322 | _timer = timer; 323 | [[NSRunLoop mainRunLoop] addTimer:timer forMode:NSRunLoopCommonModes]; 324 | } 325 | 326 | - (void)invalidateTimer 327 | { 328 | [_timer invalidate]; 329 | _timer = nil; 330 | } 331 | 332 | - (void)setupPageControl 333 | { 334 | if (_pageControl) [_pageControl removeFromSuperview]; // 重新加载数据时调整 335 | 336 | if (self.imagePathsGroup.count == 0 || self.onlyDisplayText) return; 337 | 338 | if ((self.imagePathsGroup.count == 1) && self.hidesForSinglePage) return; 339 | 340 | int indexOnPageControl = [self pageControlIndexWithCurrentCellIndex:[self currentIndex]]; 341 | 342 | switch (self.pageControlStyle) { 343 | case SDCycleScrollViewPageContolStyleAnimated: 344 | { 345 | TAPageControl *pageControl = [[TAPageControl alloc] init]; 346 | pageControl.numberOfPages = self.imagePathsGroup.count; 347 | pageControl.dotColor = self.currentPageDotColor; 348 | pageControl.userInteractionEnabled = NO; 349 | pageControl.currentPage = indexOnPageControl; 350 | [self addSubview:pageControl]; 351 | _pageControl = pageControl; 352 | } 353 | break; 354 | 355 | case SDCycleScrollViewPageContolStyleClassic: 356 | { 357 | UIPageControl *pageControl = [[UIPageControl alloc] init]; 358 | pageControl.numberOfPages = self.imagePathsGroup.count; 359 | pageControl.currentPageIndicatorTintColor = self.currentPageDotColor; 360 | pageControl.pageIndicatorTintColor = self.pageDotColor; 361 | pageControl.userInteractionEnabled = NO; 362 | pageControl.currentPage = indexOnPageControl; 363 | [self addSubview:pageControl]; 364 | _pageControl = pageControl; 365 | } 366 | break; 367 | 368 | default: 369 | break; 370 | } 371 | 372 | // 重设pagecontroldot图片 373 | if (self.currentPageDotImage) { 374 | self.currentPageDotImage = self.currentPageDotImage; 375 | } 376 | if (self.pageDotImage) { 377 | self.pageDotImage = self.pageDotImage; 378 | } 379 | } 380 | 381 | 382 | - (void)automaticScroll 383 | { 384 | if (0 == _totalItemsCount) return; 385 | int currentIndex = [self currentIndex]; 386 | int targetIndex = currentIndex + 1; 387 | [self scrollToIndex:targetIndex]; 388 | } 389 | 390 | - (void)scrollToIndex:(int)targetIndex 391 | { 392 | if (targetIndex >= _totalItemsCount) { 393 | if (self.infiniteLoop) { 394 | targetIndex = _totalItemsCount * 0.5; 395 | [_mainView scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:targetIndex inSection:0] atScrollPosition:UICollectionViewScrollPositionNone animated:NO]; 396 | } 397 | return; 398 | } 399 | [_mainView scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:targetIndex inSection:0] atScrollPosition:UICollectionViewScrollPositionNone animated:YES]; 400 | } 401 | 402 | - (int)currentIndex 403 | { 404 | if (_mainView.sd_width == 0 || _mainView.sd_height == 0) { 405 | return 0; 406 | } 407 | 408 | int index = 0; 409 | if (_flowLayout.scrollDirection == UICollectionViewScrollDirectionHorizontal) { 410 | index = (_mainView.contentOffset.x + _flowLayout.itemSize.width * 0.5) / _flowLayout.itemSize.width; 411 | } else { 412 | index = (_mainView.contentOffset.y + _flowLayout.itemSize.height * 0.5) / _flowLayout.itemSize.height; 413 | } 414 | 415 | return MAX(0, index); 416 | } 417 | 418 | - (int)pageControlIndexWithCurrentCellIndex:(NSInteger)index 419 | { 420 | return (int)index % self.imagePathsGroup.count; 421 | } 422 | 423 | - (void)clearCache 424 | { 425 | [[self class] clearImagesCache]; 426 | } 427 | 428 | + (void)clearImagesCache 429 | { 430 | [[[SDWebImageManager sharedManager] imageCache] clearDisk]; 431 | } 432 | 433 | #pragma mark - life circles 434 | 435 | - (void)layoutSubviews 436 | { 437 | [super layoutSubviews]; 438 | 439 | _flowLayout.itemSize = self.frame.size; 440 | 441 | _mainView.frame = self.bounds; 442 | if (_mainView.contentOffset.x == 0 && _totalItemsCount) { 443 | int targetIndex = 0; 444 | if (self.infiniteLoop) { 445 | targetIndex = _totalItemsCount * 0.5; 446 | }else{ 447 | targetIndex = 0; 448 | } 449 | [_mainView scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:targetIndex inSection:0] atScrollPosition:UICollectionViewScrollPositionNone animated:NO]; 450 | } 451 | 452 | CGSize size = CGSizeZero; 453 | if ([self.pageControl isKindOfClass:[TAPageControl class]]) { 454 | TAPageControl *pageControl = (TAPageControl *)_pageControl; 455 | if (!(self.pageDotImage && self.currentPageDotImage && CGSizeEqualToSize(kCycleScrollViewInitialPageControlDotSize, self.pageControlDotSize))) { 456 | pageControl.dotSize = self.pageControlDotSize; 457 | } 458 | size = [pageControl sizeForNumberOfPages:self.imagePathsGroup.count]; 459 | } else { 460 | size = CGSizeMake(self.imagePathsGroup.count * self.pageControlDotSize.width * 1.2, self.pageControlDotSize.height); 461 | } 462 | CGFloat x = (self.sd_width - size.width) * 0.5; 463 | if (self.pageControlAliment == SDCycleScrollViewPageContolAlimentRight) { 464 | x = self.mainView.sd_width - size.width - 10; 465 | } 466 | CGFloat y = self.mainView.sd_height - size.height - 10; 467 | 468 | if ([self.pageControl isKindOfClass:[TAPageControl class]]) { 469 | TAPageControl *pageControl = (TAPageControl *)_pageControl; 470 | [pageControl sizeToFit]; 471 | } 472 | 473 | self.pageControl.frame = CGRectMake(x, y, size.width, size.height); 474 | self.pageControl.hidden = !_showPageControl; 475 | 476 | if (self.backgroundImageView) { 477 | self.backgroundImageView.frame = self.bounds; 478 | } 479 | 480 | } 481 | 482 | //解决当父View释放时,当前视图因为被Timer强引用而不能释放的问题 483 | - (void)willMoveToSuperview:(UIView *)newSuperview 484 | { 485 | if (!newSuperview) { 486 | [self invalidateTimer]; 487 | } 488 | } 489 | 490 | //解决当timer释放后 回调scrollViewDidScroll时访问野指针导致崩溃 491 | - (void)dealloc { 492 | _mainView.delegate = nil; 493 | _mainView.dataSource = nil; 494 | } 495 | 496 | #pragma mark - public actions 497 | 498 | - (void)adjustWhenControllerViewWillAppera 499 | { 500 | long targetIndex = [self currentIndex]; 501 | if (targetIndex < _totalItemsCount) { 502 | [_mainView scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:targetIndex inSection:0] atScrollPosition:UICollectionViewScrollPositionNone animated:NO]; 503 | } 504 | } 505 | 506 | 507 | #pragma mark - UICollectionViewDataSource 508 | 509 | - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section 510 | { 511 | return _totalItemsCount; 512 | } 513 | 514 | - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath 515 | { 516 | SDCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:ID forIndexPath:indexPath]; 517 | long itemIndex = [self pageControlIndexWithCurrentCellIndex:indexPath.item]; 518 | 519 | NSString *imagePath = self.imagePathsGroup[itemIndex]; 520 | 521 | if (!self.onlyDisplayText && [imagePath isKindOfClass:[NSString class]]) { 522 | if ([imagePath hasPrefix:@"http"]) { 523 | [cell.imageView sd_setImageWithURL:[NSURL URLWithString:imagePath] placeholderImage:self.placeholderImage]; 524 | } else { 525 | UIImage *image = [UIImage imageNamed:imagePath]; 526 | if (!image) { 527 | [UIImage imageWithContentsOfFile:imagePath]; 528 | } 529 | cell.imageView.image = image; 530 | } 531 | } else if (!self.onlyDisplayText && [imagePath isKindOfClass:[UIImage class]]) { 532 | cell.imageView.image = (UIImage *)imagePath; 533 | } 534 | 535 | if (_titlesGroup.count && itemIndex < _titlesGroup.count) { 536 | cell.title = _titlesGroup[itemIndex]; 537 | } 538 | 539 | if (!cell.hasConfigured) { 540 | cell.titleLabelBackgroundColor = self.titleLabelBackgroundColor; 541 | cell.titleLabelHeight = self.titleLabelHeight; 542 | cell.titleLabelTextColor = self.titleLabelTextColor; 543 | cell.titleLabelTextFont = self.titleLabelTextFont; 544 | cell.hasConfigured = YES; 545 | cell.imageView.contentMode = self.bannerImageViewContentMode; 546 | cell.clipsToBounds = YES; 547 | cell.onlyDisplayText = self.onlyDisplayText; 548 | } 549 | 550 | return cell; 551 | } 552 | 553 | - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath 554 | { 555 | if ([self.delegate respondsToSelector:@selector(cycleScrollView:didSelectItemAtIndex:)]) { 556 | [self.delegate cycleScrollView:self didSelectItemAtIndex:[self pageControlIndexWithCurrentCellIndex:indexPath.item]]; 557 | } 558 | if (self.clickItemOperationBlock) { 559 | self.clickItemOperationBlock([self pageControlIndexWithCurrentCellIndex:indexPath.item]); 560 | } 561 | } 562 | 563 | 564 | #pragma mark - UIScrollViewDelegate 565 | 566 | - (void)scrollViewDidScroll:(UIScrollView *)scrollView 567 | { 568 | if (!self.imagePathsGroup.count) return; // 解决清除timer时偶尔会出现的问题 569 | int itemIndex = [self currentIndex]; 570 | int indexOnPageControl = [self pageControlIndexWithCurrentCellIndex:itemIndex]; 571 | 572 | if ([self.pageControl isKindOfClass:[TAPageControl class]]) { 573 | TAPageControl *pageControl = (TAPageControl *)_pageControl; 574 | pageControl.currentPage = indexOnPageControl; 575 | } else { 576 | UIPageControl *pageControl = (UIPageControl *)_pageControl; 577 | pageControl.currentPage = indexOnPageControl; 578 | } 579 | } 580 | 581 | - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView 582 | { 583 | if (self.autoScroll) { 584 | [self invalidateTimer]; 585 | } 586 | } 587 | 588 | - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate 589 | { 590 | if (self.autoScroll) { 591 | [self setupTimer]; 592 | } 593 | } 594 | 595 | - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView 596 | { 597 | [self scrollViewDidEndScrollingAnimation:self.mainView]; 598 | } 599 | 600 | - (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView 601 | { 602 | if (!self.imagePathsGroup.count) return; // 解决清除timer时偶尔会出现的问题 603 | int itemIndex = [self currentIndex]; 604 | int indexOnPageControl = [self pageControlIndexWithCurrentCellIndex:itemIndex]; 605 | 606 | if ([self.delegate respondsToSelector:@selector(cycleScrollView:didScrollToIndex:)]) { 607 | [self.delegate cycleScrollView:self didScrollToIndex:indexOnPageControl]; 608 | } else if (self.itemDidScrollOperationBlock) { 609 | self.itemDidScrollOperationBlock(indexOnPageControl); 610 | } 611 | } 612 | 613 | 614 | @end 615 | -------------------------------------------------------------------------------- /ZKBanner/SDCycleScrollView/UIView+SDExtension.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+SDExtension.h 3 | // SDRefreshView 4 | // 5 | // Created by aier on 15-2-23. 6 | // Copyright (c) 2015年 GSD. All rights reserved. 7 | // 8 | 9 | 10 | #import 11 | 12 | #define SDColorCreater(r, g, b, a) [UIColor colorWithRed:(r / 255.0) green:(g / 255.0) blue:(b / 255.0) alpha:a] 13 | 14 | 15 | @interface UIView (SDExtension) 16 | 17 | @property (nonatomic, assign) CGFloat sd_height; 18 | @property (nonatomic, assign) CGFloat sd_width; 19 | 20 | @property (nonatomic, assign) CGFloat sd_y; 21 | @property (nonatomic, assign) CGFloat sd_x; 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /ZKBanner/SDCycleScrollView/UIView+SDExtension.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+SDExtension.m 3 | // SDRefreshView 4 | // 5 | // Created by aier on 15-2-23. 6 | // Copyright (c) 2015年 GSD. All rights reserved. 7 | // 8 | 9 | 10 | #import "UIView+SDExtension.h" 11 | 12 | @implementation UIView (SDExtension) 13 | 14 | - (CGFloat)sd_height 15 | { 16 | return self.frame.size.height; 17 | } 18 | 19 | - (void)setSd_height:(CGFloat)sd_height 20 | { 21 | CGRect temp = self.frame; 22 | temp.size.height = sd_height; 23 | self.frame = temp; 24 | } 25 | 26 | - (CGFloat)sd_width 27 | { 28 | return self.frame.size.width; 29 | } 30 | 31 | - (void)setSd_width:(CGFloat)sd_width 32 | { 33 | CGRect temp = self.frame; 34 | temp.size.width = sd_width; 35 | self.frame = temp; 36 | } 37 | 38 | 39 | - (CGFloat)sd_y 40 | { 41 | return self.frame.origin.y; 42 | } 43 | 44 | - (void)setSd_y:(CGFloat)sd_y 45 | { 46 | CGRect temp = self.frame; 47 | temp.origin.y = sd_y; 48 | self.frame = temp; 49 | } 50 | 51 | - (CGFloat)sd_x 52 | { 53 | return self.frame.origin.x; 54 | } 55 | 56 | - (void)setSd_x:(CGFloat)sd_x 57 | { 58 | CGRect temp = self.frame; 59 | temp.origin.x = sd_x; 60 | self.frame = temp; 61 | } 62 | 63 | 64 | 65 | @end 66 | -------------------------------------------------------------------------------- /components/NewBanner.js: -------------------------------------------------------------------------------- 1 | import React, { Component, PropTypes } from 'react'; 2 | import { requireNativeComponent} from 'react-native'; 3 | 4 | var NewBanner = requireNativeComponent('NewBanner', NewBannerView); 5 | 6 | export default class NewBannerView extends Component { 7 | static propTypes = { 8 | /** 9 | * 属性 10 | * 定义组件需要传到原生端的属性 11 | * 使用React.PropTypes来进行校验 12 | */ 13 | 14 | //自动滑动间隔时间 15 | autoScrollTimeInterval: PropTypes.number, 16 | //是否自动滑动 17 | autoScroll: PropTypes.bool, 18 | //图片点击事件 19 | onClickBanner: PropTypes.func, 20 | //网络图片数组 21 | imageURLStringsGroup:PropTypes.array, 22 | //本地图片 23 | localizationImageNamesGroup:PropTypes.array, 24 | }; 25 | render() { 26 | return ( 27 | 28 | ); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | import Banner from './components/NewBanner'; 2 | 3 | module.exports = { 4 | Banner 5 | } 6 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-zkbanner", 3 | "version": "1.0.0", 4 | "description": "...", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [ 10 | "react-native", 11 | "banner", 12 | "react-native-zkbanner" 13 | ], 14 | "author": "Cain", 15 | "license": "MIT" 16 | } 17 | --------------------------------------------------------------------------------