├── .DS_Store ├── .gitignore ├── README.md └── ZLDashboard ├── .DS_Store ├── 090171AC90DADBC5099B0D5C6DAB22F3.jpg ├── ZLDashboard.xcodeproj ├── project.pbxproj └── project.xcworkspace │ └── contents.xcworkspacedata ├── ZLDashboard ├── AppDelegate.h ├── AppDelegate.m ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard ├── Info.plist ├── UIColor+Extensions.h ├── UIColor+Extensions.m ├── UIView+Extensions.h ├── UIView+Extensions.m ├── ViewController.h ├── ViewController.m ├── ZLDashboardView.h ├── ZLDashboardView.m ├── ZLGradientView.h ├── ZLGradientView.m ├── backgroundImage@2x.png └── main.m ├── ZLDashboardTests ├── Info.plist └── ZLDashboardTests.m └── ZLDashboardUITests ├── Info.plist └── ZLDashboardUITests.m /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZLFighting/ZLDashboard/a60ab2ea8033133cfc82c577a058a0e22dfe7b1a/.DS_Store -------------------------------------------------------------------------------- /.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 | *.moved-aside 22 | *.xccheckout 23 | *.xcscmblueprint 24 | 25 | ## Obj-C/Swift specific 26 | *.hmap 27 | *.ipa 28 | *.dSYM.zip 29 | *.dSYM 30 | 31 | # CocoaPods 32 | # 33 | # We recommend against adding the Pods directory to your .gitignore. However 34 | # you should judge for yourself, the pros and cons are mentioned at: 35 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 36 | # 37 | # Pods/ 38 | 39 | # Carthage 40 | # 41 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 42 | # Carthage/Checkouts 43 | 44 | Carthage/Build 45 | 46 | # fastlane 47 | # 48 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 49 | # screenshots whenever they are needed. 50 | # For more information about the recommended setup visit: 51 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 52 | 53 | fastlane/report.xml 54 | fastlane/Preview.html 55 | fastlane/screenshots 56 | fastlane/test_output 57 | 58 | # Code Injection 59 | # 60 | # After new code Injection tools there's a generated folder /iOSInjectionProject 61 | # https://github.com/johnno1962/injectionforxcode 62 | 63 | iOSInjectionProject/ 64 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ZLDashboard 2 | 仿支付宝仪表盘 3 | 4 | 自定义View之高仿支付宝芝麻信用分数仪表盘动画效果 5 | 6 | ![仪表盘动画效果.jpg](https://github.com/ZLFighting/ZLDashboard/blob/master/ZLDashboard/090171AC90DADBC5099B0D5C6DAB22F3.jpg) 7 | 8 | > 主要思路: 9 | * 1. 圆环上绿点的旋转 10 | * 2. 分数值及提示语的变化 11 | * 3. 背景色的变化 12 | 13 | 直接上主要核心代码: 14 | 15 | ## 一. 自定义ZLDashboardView仪表盘文件: 16 | 17 | 根据跃动数字, 确定百分比, 现在的跳动数字 ----> 背景颜色变化 18 | .h 文件里公开跃动数字刷新方法: 19 | ``` 20 | @property (nonatomic, copy) void(^TimerBlock)(NSInteger); 21 | 22 | /** 23 | * 跃动数字刷新 24 | * 25 | */ 26 | - (void)refreshJumpNOFromNO:(NSString *)startNO toNO:(NSString *)toNO; 27 | ``` 28 | .m 文件 29 | 1.自定义Lift cycle 30 | ``` 31 | #pragma mark - Life cycle 32 | - (instancetype)initWithFrame:(CGRect)frame { 33 | self = [super initWithFrame:frame]; 34 | if (self) { 35 | self.backgroundColor = [UIColor clearColor]; 36 | self.circelRadius = self.frame.size.width - 10.f; 37 | self.lineWidth = 2.f; 38 | self.startAngle = -200.f; 39 | self.endAngle = 20.f; 40 | // 尺寸需根据图片进行调整 41 | self.bgImageView.frame = CGRectMake(6, 6, self.circelRadius, self.circelRadius * 2 / 3); self.bgImageView.backgroundColor = [UIColor clearColor]; 42 | [self addSubview:self.bgImageView]; 43 | // 添加圆框 44 | [self setupCircleBg]; 45 | // 光标 46 | [self setupMarkerImageView]; 47 | // 添加跃动数字 及 提示语 48 | [self setupJumpNOView]; 49 | } 50 | return self; 51 | } 52 | ``` 53 | 2.添加圆框 54 | ``` 55 | - (void)setupCircleBg { 56 | // 圆形路径 57 | UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(self.width / 2, self.height / 2) 58 | radius:(self.circelRadius - self.lineWidth) / 2 59 | startAngle:degreesToRadians(self.startAngle) 60 | endAngle:degreesToRadians(self.endAngle) 61 | clockwise:YES]; 62 | // 底色 63 | self.bottomLayer = [CAShapeLayer layer]; 64 | self.bottomLayer.frame = self.bounds; 65 | self.bottomLayer.fillColor = [[UIColor clearColor] CGColor]; 66 | self.bottomLayer.strokeColor = [[UIColor colorWithRed:206.f / 256.f green:241.f / 256.f blue:227.f alpha:1.f] CGColor]; 67 | self.bottomLayer.opacity = 0.5; 68 | self.bottomLayer.lineCap = kCALineCapRound; 69 | self.bottomLayer.lineWidth = self.lineWidth; 70 | self.bottomLayer.path = [path CGPath]; 71 | [self.layer addSublayer:self.bottomLayer]; 72 | // 240 是用整个弧度的角度之和 |-200| + 20 = 220 73 | // [self createAnimationWithStartAngle:degreesToRadians(self.startAngle) 74 | // endAngle:degreesToRadians(self.startAngle + 220 * 1)]; 75 | } 76 | ``` 77 | 3.设置光标 78 | ``` 79 | - (void)setupMarkerImageView { 80 | if (_markerImageView) { 81 | return; 82 | } 83 | _markerImageView = [[UIImageView alloc] init]; 84 | _markerImageView.backgroundColor = [UIColor clearColor]; 85 | _markerImageView.layer.backgroundColor = [UIColor greenColor].CGColor; 86 | _markerImageView.layer.shadowColor = [UIColor whiteColor].CGColor; 87 | _markerImageView.layer.shadowOffset = CGSizeMake(0, 0); 88 | _markerImageView.layer.shadowRadius = kMarkerRadius*0.5; 89 | _markerImageView.layer.shadowOpacity = 1; 90 | _markerImageView.layer.masksToBounds = NO; 91 | self.markerImageView.layer.cornerRadius = self.markerImageView.frame.size.height / 2; 92 | [self addSubview:self.markerImageView]; 93 | _markerImageView.frame = CGRectMake(-100, self.height, kMarkerRadius, kMarkerRadius); 94 | } 95 | ``` 96 | 4.添加跳跃文字及提示语 97 | ``` 98 | - (void)setupJumpNOView { 99 | if (_showLable) { 100 | return; 101 | } 102 | CGFloat width = self.circelRadius / 2 + 50; 103 | CGFloat height = self.circelRadius / 2 - 50; 104 | CGFloat xPixel = self.bgImageView.left + (self.bgImageView.width - width)*0.5;//self.circelRadius / 4; 105 | CGFloat yPixel = self.circelRadius / 4; 106 | CGRect labelFrame = CGRectMake(xPixel, yPixel, width, height); 107 | _showLable = [[UILabel alloc] initWithFrame:labelFrame]; 108 | _showLable.backgroundColor = [UIColor clearColor]; 109 | _showLable.textColor = [UIColor greenColor]; 110 | _showLable.textAlignment = NSTextAlignmentCenter; 111 | _showLable.font = [UIFont systemFontOfSize:100.f]; 112 | _showLable.text = [NSString stringWithFormat:@"%ld",jumpCurrentNO]; 113 | [self addSubview:_showLable]; // 提示语 114 | _markedLabel = [[UILabel alloc] initWithFrame:CGRectMake(xPixel, CGRectGetMaxY(_showLable.frame), width, 30)]; 115 | _markedLabel.backgroundColor = [UIColor clearColor]; 116 | _markedLabel.textColor = [UIColor greenColor]; 117 | _markedLabel.textAlignment = NSTextAlignmentCenter; 118 | _markedLabel.font = [UIFont systemFontOfSize:20.f]; 119 | _markedLabel.text = @"营养良好"; 120 | [self addSubview:_markedLabel]; 121 | } 122 | ``` 123 | 5.动画相关 124 | ``` 125 | #pragma mark - Animation 126 | - (void)createAnimationWithStartAngle:(CGFloat)startAngle endAngle:(CGFloat)endAngle { // 光标动画 127 | 128 | //启动定时器 129 | [_fastTimer setFireDate:[NSDate distantPast]]; // 设置动画属性 130 | CAKeyframeAnimation *pathAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"]; 131 | pathAnimation.calculationMode = kCAAnimationPaced; 132 | pathAnimation.fillMode = kCAFillModeForwards; 133 | pathAnimation.removedOnCompletion = NO; 134 | pathAnimation.duration = _percent * kTimerInterval; 135 | pathAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]; 136 | pathAnimation.repeatCount = 1; // 设置动画路径 137 | CGMutablePathRef path = CGPathCreateMutable(); CGPathAddArc(path, NULL, self.width / 2, self.height / 2, (self.circelRadius - kMarkerRadius / 2) / 2, startAngle, endAngle, 0); 138 | pathAnimation.path = path; CGPathRelease(path); 139 | 140 | [self.markerImageView.layer addAnimation:pathAnimation forKey:@"moveMarker"]; 141 | 142 | } 143 | ``` 144 | 6.开始动画,确定百分比 145 | ``` 146 | - (void)refreshJumpNOFromNO:(NSString *)startNO toNO:(NSString *)toNO { 147 | 148 | beginNO = 0;//[startNO integerValue]; 149 | jumpCurrentNO = 0;//[startNO integerValue]; 150 | endNO = [toNO integerValue]; 151 | _percent = endNO * 100 / MaxNumber; 152 | NSInteger diffNum = endNO - beginNO; 153 | if (diffNum <= 0) { 154 | return; 155 | } if (diffNum < 100) { 156 | _intervalNum = 5; 157 | } else if (diffNum < 300) { 158 | _intervalNum = 15; 159 | } else if (diffNum <= MaxNumber) { 160 | _intervalNum = 10; 161 | } 162 | NSLog(@"数字间隔:%ld",_intervalNum); 163 | //数字 164 | [self setupJumpThings]; 165 | // 设置角度 166 | NSInteger angle = 0; 167 | NSInteger num = [toNO floatValue] - [startNO floatValue]; 168 | if (num < 200) { 169 | angle = self.startAngle + 220 * (num / 200.0) / 5.0; 170 | } else if (num < 350) { 171 | angle = self.startAngle + 220 / 5.0 + (3 / 5.0 * 220) * (num - 200) / 150.0; 172 | } else { 173 | angle = self.startAngle + 220 / 5.0 * 4 + (220 / 5.0) * (num - 350) / 250.0; 174 | } 175 | //光标 176 | [self createAnimationWithStartAngle:degreesToRadians(self.startAngle) 177 | endAngle:degreesToRadians(angle)]; 178 | } 179 | 180 | - (void)setBgImage:(UIImage *)bgImage { 181 | 182 | _bgImage = bgImage; self.bgImageView.image = bgImage; 183 | } 184 | 185 | - (UIImageView *)bgImageView { if (nil == _bgImageView) { 186 | _bgImageView = [[UIImageView alloc] init]; 187 | } return _bgImageView; 188 | } 189 | ``` 190 | 7.跃动数字 191 | ``` 192 | - (void)setupJumpThings { 193 | 194 | animationTime = _percent * kTimerInterval; 195 | self.fastTimer = [NSTimer timerWithTimeInterval:kTimerInterval*kFastProportion 196 | target:self 197 | selector:@selector(fastTimerAction) 198 | userInfo:nil 199 | repeats:YES]; 200 | [[NSRunLoop currentRunLoop] addTimer:_fastTimer forMode:NSRunLoopCommonModes]; 201 | //时间间隔 = (总时间 - 快时间间隔*变化次数)/ 再次需要变化的次数 202 | //快时间 203 | NSInteger fastEndNO = endNO * kFastProportion; 204 | NSInteger fastJump = fastEndNO/_intervalNum; 205 | if (fastJump % _intervalNum) { 206 | fastJump++; 207 | fastEndNO += _intervalNum; 208 | } 209 | CGFloat fastTTime = fastJump*kTimerInterval*kFastProportion; 210 | //剩余应跳动次数 211 | NSInteger changNO = endNO - fastEndNO; 212 | NSInteger endJump = changNO / _intervalNum + changNO % _intervalNum; 213 | //慢时间间隔 214 | NSTimeInterval slowInterval = (animationTime - fastTTime) / endJump; 215 | self.slowTimer = [NSTimer timerWithTimeInterval:slowInterval 216 | target:self 217 | selector:@selector(slowTimerAction) 218 | userInfo:nil 219 | repeats:YES]; 220 | [[NSRunLoop currentRunLoop] addTimer:_slowTimer forMode:NSRunLoopCommonModes]; 221 | [_fastTimer setFireDate:[NSDate distantFuture]]; 222 | [_slowTimer setFireDate:[NSDate distantFuture]]; 223 | } 224 | ``` 225 | 8.定时器触发事件 226 | ``` 227 | #pragma mark 加速定时器触发事件 228 | - (void)fastTimerAction { 229 | if (jumpCurrentNO >= endNO) { 230 | [self.fastTimer invalidate]; 231 | return; 232 | } if (jumpCurrentNO >= endNO * kFastProportion) { 233 | [self.fastTimer invalidate]; 234 | [self.slowTimer setFireDate:[NSDate distantPast]]; 235 | return; 236 | } 237 | [self commonTimerAction]; 238 | } 239 | #pragma mark 减速定时器触发事件 240 | - (void)slowTimerAction { 241 | if (jumpCurrentNO >= endNO) { 242 | [self.slowTimer invalidate]; 243 | return; 244 | } 245 | [self commonTimerAction]; 246 | } 247 | 248 | #pragma mark 计时器共性事件 - lable赋值 背景颜色及提示语变化 249 | - (void)commonTimerAction { 250 | if (jumpCurrentNO % 100 == 0 && jumpCurrentNO != 0) { 251 | NSInteger colorIndex = jumpCurrentNO / 100; 252 | dispatch_async(dispatch_get_main_queue(), ^{ 253 | if (self.TimerBlock) { 254 | self.TimerBlock(colorIndex); 255 | } 256 | }); 257 | } 258 | NSInteger changeValueBy = endNO - jumpCurrentNO; 259 | if (changeValueBy/10 < 1) { 260 | jumpCurrentNO++; 261 | } else { 262 | // NSInteger changeBy = changeValueBy / 10; 263 | jumpCurrentNO += _intervalNum; 264 | } 265 | 266 | _showLable.text = [NSString stringWithFormat:@"%ld",jumpCurrentNO]; 267 | if (jumpCurrentNO < 350) { 268 | _markedLabel.text = @"营养太差"; 269 | } else if (jumpCurrentNO <= 550) { 270 | _markedLabel.text = @"营养较差"; 271 | } else if (jumpCurrentNO <= 600) { 272 | _markedLabel.text = @"营养中等"; 273 | } else if (jumpCurrentNO <= 650) { 274 | _markedLabel.text = @"营养良好"; 275 | } else if (jumpCurrentNO <= 700) { 276 | _markedLabel.text = @"营养优秀"; 277 | } else if (jumpCurrentNO <= 950) { 278 | _markedLabel.text = @"营养较好"; 279 | } 280 | } 281 | ``` 282 | 283 | ## 二. 在所需的当前控制器里展示: 284 | 285 | 1.创建背景色 286 | ``` 287 | - (void)setupGradientView { 288 | self.gradientView = [[ZLGradientView alloc] initWithFrame:self.view.bounds]; 289 | [self.view addSubview:self.gradientView]; 290 | } 291 | ``` 292 | 2.创建仪表盘 293 | 294 | ``` 295 | - (void)setupCircleView { 296 | self.dashboardView = [[ZLDashboardView alloc] initWithFrame:CGRectMake(40.f, 70.f, SCREEN_WIDTH - 80.f, SCREEN_WIDTH - 80.f)]; 297 | self.dashboardView.bgImage = [UIImage imageNamed:@"backgroundImage"]; 298 | [self.view addSubview:self.dashboardView]; 299 | } 300 | ``` 301 | 3.添加触发动画的点击按钮 302 | ``` 303 | - (void)addActionButton { 304 | UIButton *stareButton = [UIButton buttonWithType:UIButtonTypeCustom]; 305 | stareButton.frame = CGRectMake(10.f, self.dashboardView.bottom + 50.f, SCREEN_WIDTH - 20.f, 38.f); 306 | [stareButton addTarget:self action:@selector(onStareButtonClick:) forControlEvents:UIControlEventTouchUpInside]; 307 | [stareButton setTitle:@"Start Animation" forState:UIControlStateNormal]; 308 | [stareButton setBackgroundColor:[UIColor lightGrayColor]]; 309 | stareButton.layer.masksToBounds = YES; 310 | stareButton.layer.cornerRadius = 4.f; 311 | [self.view addSubview:stareButton]; 312 | 313 | _clickBtn = stareButton; 314 | } 315 | ``` 316 | 4.改变 Value 317 | ``` 318 | - (void)addSlideChnageValue { 319 | CGFloat width = 280; 320 | CGFloat height = 40; 321 | CGFloat xPixel = (SCREEN_WIDTH - width) * 0.5; 322 | CGFloat yPixel = CGRectGetMaxY(_clickBtn.frame) + 20; 323 | CGRect slideFrame = CGRectMake(xPixel, yPixel, width, height); 324 | UISlider *slider = [[UISlider alloc] initWithFrame:slideFrame]; 325 | 326 | slider.minimumValue = MinNumber; 327 | slider.maximumValue = MaxNumber; 328 | 329 | slider.minimumTrackTintColor = [UIColor colorWithRed:0.000 green:1.000 blue:0.502 alpha:1.000]; 330 | slider.maximumTrackTintColor = [UIColor colorWithWhite:0.800 alpha:1.000]; /** 331 | * 注意这个属性:如果你没有设置滑块的图片,那个这个属性将只会改变已划过一段线条的颜色,不会改变滑块的颜色,如果你设置了滑块的图片,又设置了这个属性,那么滑块的图片将不显示,滑块的颜色会改变(IOS7) 332 | */ 333 | [slider setThumbImage:[UIImage imageNamed:@""] forState:UIControlStateNormal]; 334 | slider.thumbTintColor = [UIColor cyanColor]; 335 | 336 | 337 | [slider setValue:0.5 animated:YES]; 338 | 339 | [slider addTarget:self action:@selector(slideTap:)forControlEvents:UIControlEventValueChanged]; 340 | 341 | [self.view addSubview:slider]; 342 | 343 | _slider = slider; 344 | } 345 | ``` 346 | ``` 347 | - (void)slideTap:(UISlider *)sender { 348 | CGFloat value = sender.value; 349 | NSLog(@"%.f",value); 350 | } 351 | 352 | - (void)setupGradientView { 353 | self.gradientView = [[ZLGradientView alloc] initWithFrame:self.view.bounds]; 354 | [self.view addSubview:self.gradientView]; 355 | } 356 | - (void)setupCircleView { 357 | self.dashboardView = [[ZLDashboardView alloc] initWithFrame:CGRectMake(40.f, 70.f, SCREEN_WIDTH - 80.f, SCREEN_WIDTH - 80.f)]; 358 | self.dashboardView.bgImage = [UIImage imageNamed:@"backgroundImage"]; 359 | [self.view addSubview:self.dashboardView]; 360 | } 361 | 362 | - (void)onStareButtonClick:(UIButton *)sender { 363 | if (sender.selected) { 364 | [self.gradientView removeFromSuperview]; 365 | self.gradientView = nil; 366 | [self.dashboardView removeFromSuperview]; 367 | self.dashboardView = nil; 368 | 369 | [self setupGradientView]; 370 | [self setupCircleView]; 371 | 372 | [self.view bringSubviewToFront:self.clickBtn]; 373 | [self.view bringSubviewToFront:_slider]; 374 | } 375 | sender.selected = YES; 376 | CGFloat value = _slider.value; 377 | NSString *startNO = [NSString stringWithFormat:@"%d", MinNumber]; 378 | NSString *toNO = [NSString stringWithFormat:@"%.f",value];//@"693"; 950 379 | NSLog(@"endNO:%@",toNO); 380 | [self.dashboardView refreshJumpNOFromNO:startNO toNO:toNO]; 381 | 382 | __block typeof(self)blockSelf = self; self.dashboardView.TimerBlock = ^(NSInteger index) { 383 | [blockSelf.gradientView setUpBackGroundColorWithColorArrayIndex:index]; 384 | }; 385 | } 386 | ``` 387 | 界面性问题可以根据自己项目需求调整即可, 具体可参考代码, Demo能够直接运行! 388 | 389 | 390 | 您的支持是作为程序媛的我最大的动力, 如果觉得对你有帮助请送个Star吧,谢谢啦 391 | 392 | -------------------------------------------------------------------------------- /ZLDashboard/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZLFighting/ZLDashboard/a60ab2ea8033133cfc82c577a058a0e22dfe7b1a/ZLDashboard/.DS_Store -------------------------------------------------------------------------------- /ZLDashboard/090171AC90DADBC5099B0D5C6DAB22F3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZLFighting/ZLDashboard/a60ab2ea8033133cfc82c577a058a0e22dfe7b1a/ZLDashboard/090171AC90DADBC5099B0D5C6DAB22F3.jpg -------------------------------------------------------------------------------- /ZLDashboard/ZLDashboard.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 2E4358061D8F7DA60063BE3B /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 2E4358051D8F7DA60063BE3B /* main.m */; }; 11 | 2E4358091D8F7DA60063BE3B /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 2E4358081D8F7DA60063BE3B /* AppDelegate.m */; }; 12 | 2E43580C1D8F7DA60063BE3B /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 2E43580B1D8F7DA60063BE3B /* ViewController.m */; }; 13 | 2E43580F1D8F7DA60063BE3B /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 2E43580D1D8F7DA60063BE3B /* Main.storyboard */; }; 14 | 2E4358111D8F7DA60063BE3B /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2E4358101D8F7DA60063BE3B /* Assets.xcassets */; }; 15 | 2E4358141D8F7DA60063BE3B /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 2E4358121D8F7DA60063BE3B /* LaunchScreen.storyboard */; }; 16 | 2E43581F1D8F7DA60063BE3B /* ZLDashboardTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 2E43581E1D8F7DA60063BE3B /* ZLDashboardTests.m */; }; 17 | 2E43582A1D8F7DA60063BE3B /* ZLDashboardUITests.m in Sources */ = {isa = PBXBuildFile; fileRef = 2E4358291D8F7DA60063BE3B /* ZLDashboardUITests.m */; }; 18 | 2E43583A1D8F82B20063BE3B /* UIView+Extensions.m in Sources */ = {isa = PBXBuildFile; fileRef = 2E4358391D8F82B20063BE3B /* UIView+Extensions.m */; }; 19 | 2E43583D1D8F83500063BE3B /* UIColor+Extensions.m in Sources */ = {isa = PBXBuildFile; fileRef = 2E43583C1D8F834F0063BE3B /* UIColor+Extensions.m */; }; 20 | 2E4358401D8F83BE0063BE3B /* ZLDashboardView.m in Sources */ = {isa = PBXBuildFile; fileRef = 2E43583F1D8F83BE0063BE3B /* ZLDashboardView.m */; }; 21 | 2E4358441D8F85B50063BE3B /* ZLGradientView.m in Sources */ = {isa = PBXBuildFile; fileRef = 2E4358431D8F85B50063BE3B /* ZLGradientView.m */; }; 22 | 2E4358461D8F88310063BE3B /* backgroundImage@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 2E4358451D8F88310063BE3B /* backgroundImage@2x.png */; }; 23 | /* End PBXBuildFile section */ 24 | 25 | /* Begin PBXContainerItemProxy section */ 26 | 2E43581B1D8F7DA60063BE3B /* PBXContainerItemProxy */ = { 27 | isa = PBXContainerItemProxy; 28 | containerPortal = 2E4357F91D8F7DA60063BE3B /* Project object */; 29 | proxyType = 1; 30 | remoteGlobalIDString = 2E4358001D8F7DA60063BE3B; 31 | remoteInfo = ZLDashboard; 32 | }; 33 | 2E4358261D8F7DA60063BE3B /* PBXContainerItemProxy */ = { 34 | isa = PBXContainerItemProxy; 35 | containerPortal = 2E4357F91D8F7DA60063BE3B /* Project object */; 36 | proxyType = 1; 37 | remoteGlobalIDString = 2E4358001D8F7DA60063BE3B; 38 | remoteInfo = ZLDashboard; 39 | }; 40 | /* End PBXContainerItemProxy section */ 41 | 42 | /* Begin PBXFileReference section */ 43 | 2E4358011D8F7DA60063BE3B /* ZLDashboard.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ZLDashboard.app; sourceTree = BUILT_PRODUCTS_DIR; }; 44 | 2E4358051D8F7DA60063BE3B /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 45 | 2E4358071D8F7DA60063BE3B /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 46 | 2E4358081D8F7DA60063BE3B /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 47 | 2E43580A1D8F7DA60063BE3B /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 48 | 2E43580B1D8F7DA60063BE3B /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 49 | 2E43580E1D8F7DA60063BE3B /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 50 | 2E4358101D8F7DA60063BE3B /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 51 | 2E4358131D8F7DA60063BE3B /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 52 | 2E4358151D8F7DA60063BE3B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 53 | 2E43581A1D8F7DA60063BE3B /* ZLDashboardTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ZLDashboardTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 54 | 2E43581E1D8F7DA60063BE3B /* ZLDashboardTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ZLDashboardTests.m; sourceTree = ""; }; 55 | 2E4358201D8F7DA60063BE3B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 56 | 2E4358251D8F7DA60063BE3B /* ZLDashboardUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ZLDashboardUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 57 | 2E4358291D8F7DA60063BE3B /* ZLDashboardUITests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ZLDashboardUITests.m; sourceTree = ""; }; 58 | 2E43582B1D8F7DA60063BE3B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 59 | 2E4358381D8F82B20063BE3B /* UIView+Extensions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIView+Extensions.h"; sourceTree = ""; }; 60 | 2E4358391D8F82B20063BE3B /* UIView+Extensions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIView+Extensions.m"; sourceTree = ""; }; 61 | 2E43583B1D8F834F0063BE3B /* UIColor+Extensions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIColor+Extensions.h"; sourceTree = ""; }; 62 | 2E43583C1D8F834F0063BE3B /* UIColor+Extensions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIColor+Extensions.m"; sourceTree = ""; }; 63 | 2E43583E1D8F83BE0063BE3B /* ZLDashboardView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZLDashboardView.h; sourceTree = ""; }; 64 | 2E43583F1D8F83BE0063BE3B /* ZLDashboardView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ZLDashboardView.m; sourceTree = ""; }; 65 | 2E4358421D8F85B50063BE3B /* ZLGradientView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZLGradientView.h; sourceTree = ""; }; 66 | 2E4358431D8F85B50063BE3B /* ZLGradientView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ZLGradientView.m; sourceTree = ""; }; 67 | 2E4358451D8F88310063BE3B /* backgroundImage@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "backgroundImage@2x.png"; sourceTree = ""; }; 68 | /* End PBXFileReference section */ 69 | 70 | /* Begin PBXFrameworksBuildPhase section */ 71 | 2E4357FE1D8F7DA60063BE3B /* Frameworks */ = { 72 | isa = PBXFrameworksBuildPhase; 73 | buildActionMask = 2147483647; 74 | files = ( 75 | ); 76 | runOnlyForDeploymentPostprocessing = 0; 77 | }; 78 | 2E4358171D8F7DA60063BE3B /* Frameworks */ = { 79 | isa = PBXFrameworksBuildPhase; 80 | buildActionMask = 2147483647; 81 | files = ( 82 | ); 83 | runOnlyForDeploymentPostprocessing = 0; 84 | }; 85 | 2E4358221D8F7DA60063BE3B /* Frameworks */ = { 86 | isa = PBXFrameworksBuildPhase; 87 | buildActionMask = 2147483647; 88 | files = ( 89 | ); 90 | runOnlyForDeploymentPostprocessing = 0; 91 | }; 92 | /* End PBXFrameworksBuildPhase section */ 93 | 94 | /* Begin PBXGroup section */ 95 | 2E4357F81D8F7DA60063BE3B = { 96 | isa = PBXGroup; 97 | children = ( 98 | 2E4358031D8F7DA60063BE3B /* ZLDashboard */, 99 | 2E43581D1D8F7DA60063BE3B /* ZLDashboardTests */, 100 | 2E4358281D8F7DA60063BE3B /* ZLDashboardUITests */, 101 | 2E4358021D8F7DA60063BE3B /* Products */, 102 | ); 103 | sourceTree = ""; 104 | }; 105 | 2E4358021D8F7DA60063BE3B /* Products */ = { 106 | isa = PBXGroup; 107 | children = ( 108 | 2E4358011D8F7DA60063BE3B /* ZLDashboard.app */, 109 | 2E43581A1D8F7DA60063BE3B /* ZLDashboardTests.xctest */, 110 | 2E4358251D8F7DA60063BE3B /* ZLDashboardUITests.xctest */, 111 | ); 112 | name = Products; 113 | sourceTree = ""; 114 | }; 115 | 2E4358031D8F7DA60063BE3B /* ZLDashboard */ = { 116 | isa = PBXGroup; 117 | children = ( 118 | 2E4358411D8F85490063BE3B /* DashboardView */, 119 | 2E4358071D8F7DA60063BE3B /* AppDelegate.h */, 120 | 2E4358081D8F7DA60063BE3B /* AppDelegate.m */, 121 | 2E43580A1D8F7DA60063BE3B /* ViewController.h */, 122 | 2E43580B1D8F7DA60063BE3B /* ViewController.m */, 123 | 2E43580D1D8F7DA60063BE3B /* Main.storyboard */, 124 | 2E4358101D8F7DA60063BE3B /* Assets.xcassets */, 125 | 2E4358121D8F7DA60063BE3B /* LaunchScreen.storyboard */, 126 | 2E4358151D8F7DA60063BE3B /* Info.plist */, 127 | 2E4358041D8F7DA60063BE3B /* Supporting Files */, 128 | ); 129 | path = ZLDashboard; 130 | sourceTree = ""; 131 | }; 132 | 2E4358041D8F7DA60063BE3B /* Supporting Files */ = { 133 | isa = PBXGroup; 134 | children = ( 135 | 2E4358051D8F7DA60063BE3B /* main.m */, 136 | ); 137 | name = "Supporting Files"; 138 | sourceTree = ""; 139 | }; 140 | 2E43581D1D8F7DA60063BE3B /* ZLDashboardTests */ = { 141 | isa = PBXGroup; 142 | children = ( 143 | 2E43581E1D8F7DA60063BE3B /* ZLDashboardTests.m */, 144 | 2E4358201D8F7DA60063BE3B /* Info.plist */, 145 | ); 146 | path = ZLDashboardTests; 147 | sourceTree = ""; 148 | }; 149 | 2E4358281D8F7DA60063BE3B /* ZLDashboardUITests */ = { 150 | isa = PBXGroup; 151 | children = ( 152 | 2E4358291D8F7DA60063BE3B /* ZLDashboardUITests.m */, 153 | 2E43582B1D8F7DA60063BE3B /* Info.plist */, 154 | ); 155 | path = ZLDashboardUITests; 156 | sourceTree = ""; 157 | }; 158 | 2E4358371D8F82780063BE3B /* Category */ = { 159 | isa = PBXGroup; 160 | children = ( 161 | 2E4358381D8F82B20063BE3B /* UIView+Extensions.h */, 162 | 2E4358391D8F82B20063BE3B /* UIView+Extensions.m */, 163 | 2E43583B1D8F834F0063BE3B /* UIColor+Extensions.h */, 164 | 2E43583C1D8F834F0063BE3B /* UIColor+Extensions.m */, 165 | ); 166 | name = Category; 167 | sourceTree = ""; 168 | }; 169 | 2E4358411D8F85490063BE3B /* DashboardView */ = { 170 | isa = PBXGroup; 171 | children = ( 172 | 2E4358451D8F88310063BE3B /* backgroundImage@2x.png */, 173 | 2E4358371D8F82780063BE3B /* Category */, 174 | 2E43583E1D8F83BE0063BE3B /* ZLDashboardView.h */, 175 | 2E43583F1D8F83BE0063BE3B /* ZLDashboardView.m */, 176 | 2E4358421D8F85B50063BE3B /* ZLGradientView.h */, 177 | 2E4358431D8F85B50063BE3B /* ZLGradientView.m */, 178 | ); 179 | name = DashboardView; 180 | sourceTree = ""; 181 | }; 182 | /* End PBXGroup section */ 183 | 184 | /* Begin PBXNativeTarget section */ 185 | 2E4358001D8F7DA60063BE3B /* ZLDashboard */ = { 186 | isa = PBXNativeTarget; 187 | buildConfigurationList = 2E43582E1D8F7DA60063BE3B /* Build configuration list for PBXNativeTarget "ZLDashboard" */; 188 | buildPhases = ( 189 | 2E4357FD1D8F7DA60063BE3B /* Sources */, 190 | 2E4357FE1D8F7DA60063BE3B /* Frameworks */, 191 | 2E4357FF1D8F7DA60063BE3B /* Resources */, 192 | ); 193 | buildRules = ( 194 | ); 195 | dependencies = ( 196 | ); 197 | name = ZLDashboard; 198 | productName = ZLDashboard; 199 | productReference = 2E4358011D8F7DA60063BE3B /* ZLDashboard.app */; 200 | productType = "com.apple.product-type.application"; 201 | }; 202 | 2E4358191D8F7DA60063BE3B /* ZLDashboardTests */ = { 203 | isa = PBXNativeTarget; 204 | buildConfigurationList = 2E4358311D8F7DA60063BE3B /* Build configuration list for PBXNativeTarget "ZLDashboardTests" */; 205 | buildPhases = ( 206 | 2E4358161D8F7DA60063BE3B /* Sources */, 207 | 2E4358171D8F7DA60063BE3B /* Frameworks */, 208 | 2E4358181D8F7DA60063BE3B /* Resources */, 209 | ); 210 | buildRules = ( 211 | ); 212 | dependencies = ( 213 | 2E43581C1D8F7DA60063BE3B /* PBXTargetDependency */, 214 | ); 215 | name = ZLDashboardTests; 216 | productName = ZLDashboardTests; 217 | productReference = 2E43581A1D8F7DA60063BE3B /* ZLDashboardTests.xctest */; 218 | productType = "com.apple.product-type.bundle.unit-test"; 219 | }; 220 | 2E4358241D8F7DA60063BE3B /* ZLDashboardUITests */ = { 221 | isa = PBXNativeTarget; 222 | buildConfigurationList = 2E4358341D8F7DA60063BE3B /* Build configuration list for PBXNativeTarget "ZLDashboardUITests" */; 223 | buildPhases = ( 224 | 2E4358211D8F7DA60063BE3B /* Sources */, 225 | 2E4358221D8F7DA60063BE3B /* Frameworks */, 226 | 2E4358231D8F7DA60063BE3B /* Resources */, 227 | ); 228 | buildRules = ( 229 | ); 230 | dependencies = ( 231 | 2E4358271D8F7DA60063BE3B /* PBXTargetDependency */, 232 | ); 233 | name = ZLDashboardUITests; 234 | productName = ZLDashboardUITests; 235 | productReference = 2E4358251D8F7DA60063BE3B /* ZLDashboardUITests.xctest */; 236 | productType = "com.apple.product-type.bundle.ui-testing"; 237 | }; 238 | /* End PBXNativeTarget section */ 239 | 240 | /* Begin PBXProject section */ 241 | 2E4357F91D8F7DA60063BE3B /* Project object */ = { 242 | isa = PBXProject; 243 | attributes = { 244 | LastUpgradeCheck = 0800; 245 | ORGANIZATIONNAME = ZL; 246 | TargetAttributes = { 247 | 2E4358001D8F7DA60063BE3B = { 248 | CreatedOnToolsVersion = 8.0; 249 | DevelopmentTeam = 7734U6Q8V5; 250 | ProvisioningStyle = Automatic; 251 | }; 252 | 2E4358191D8F7DA60063BE3B = { 253 | CreatedOnToolsVersion = 8.0; 254 | ProvisioningStyle = Automatic; 255 | TestTargetID = 2E4358001D8F7DA60063BE3B; 256 | }; 257 | 2E4358241D8F7DA60063BE3B = { 258 | CreatedOnToolsVersion = 8.0; 259 | ProvisioningStyle = Automatic; 260 | TestTargetID = 2E4358001D8F7DA60063BE3B; 261 | }; 262 | }; 263 | }; 264 | buildConfigurationList = 2E4357FC1D8F7DA60063BE3B /* Build configuration list for PBXProject "ZLDashboard" */; 265 | compatibilityVersion = "Xcode 3.2"; 266 | developmentRegion = English; 267 | hasScannedForEncodings = 0; 268 | knownRegions = ( 269 | en, 270 | Base, 271 | ); 272 | mainGroup = 2E4357F81D8F7DA60063BE3B; 273 | productRefGroup = 2E4358021D8F7DA60063BE3B /* Products */; 274 | projectDirPath = ""; 275 | projectRoot = ""; 276 | targets = ( 277 | 2E4358001D8F7DA60063BE3B /* ZLDashboard */, 278 | 2E4358191D8F7DA60063BE3B /* ZLDashboardTests */, 279 | 2E4358241D8F7DA60063BE3B /* ZLDashboardUITests */, 280 | ); 281 | }; 282 | /* End PBXProject section */ 283 | 284 | /* Begin PBXResourcesBuildPhase section */ 285 | 2E4357FF1D8F7DA60063BE3B /* Resources */ = { 286 | isa = PBXResourcesBuildPhase; 287 | buildActionMask = 2147483647; 288 | files = ( 289 | 2E4358141D8F7DA60063BE3B /* LaunchScreen.storyboard in Resources */, 290 | 2E4358111D8F7DA60063BE3B /* Assets.xcassets in Resources */, 291 | 2E4358461D8F88310063BE3B /* backgroundImage@2x.png in Resources */, 292 | 2E43580F1D8F7DA60063BE3B /* Main.storyboard in Resources */, 293 | ); 294 | runOnlyForDeploymentPostprocessing = 0; 295 | }; 296 | 2E4358181D8F7DA60063BE3B /* Resources */ = { 297 | isa = PBXResourcesBuildPhase; 298 | buildActionMask = 2147483647; 299 | files = ( 300 | ); 301 | runOnlyForDeploymentPostprocessing = 0; 302 | }; 303 | 2E4358231D8F7DA60063BE3B /* Resources */ = { 304 | isa = PBXResourcesBuildPhase; 305 | buildActionMask = 2147483647; 306 | files = ( 307 | ); 308 | runOnlyForDeploymentPostprocessing = 0; 309 | }; 310 | /* End PBXResourcesBuildPhase section */ 311 | 312 | /* Begin PBXSourcesBuildPhase section */ 313 | 2E4357FD1D8F7DA60063BE3B /* Sources */ = { 314 | isa = PBXSourcesBuildPhase; 315 | buildActionMask = 2147483647; 316 | files = ( 317 | 2E43580C1D8F7DA60063BE3B /* ViewController.m in Sources */, 318 | 2E4358091D8F7DA60063BE3B /* AppDelegate.m in Sources */, 319 | 2E4358441D8F85B50063BE3B /* ZLGradientView.m in Sources */, 320 | 2E43583D1D8F83500063BE3B /* UIColor+Extensions.m in Sources */, 321 | 2E43583A1D8F82B20063BE3B /* UIView+Extensions.m in Sources */, 322 | 2E4358061D8F7DA60063BE3B /* main.m in Sources */, 323 | 2E4358401D8F83BE0063BE3B /* ZLDashboardView.m in Sources */, 324 | ); 325 | runOnlyForDeploymentPostprocessing = 0; 326 | }; 327 | 2E4358161D8F7DA60063BE3B /* Sources */ = { 328 | isa = PBXSourcesBuildPhase; 329 | buildActionMask = 2147483647; 330 | files = ( 331 | 2E43581F1D8F7DA60063BE3B /* ZLDashboardTests.m in Sources */, 332 | ); 333 | runOnlyForDeploymentPostprocessing = 0; 334 | }; 335 | 2E4358211D8F7DA60063BE3B /* Sources */ = { 336 | isa = PBXSourcesBuildPhase; 337 | buildActionMask = 2147483647; 338 | files = ( 339 | 2E43582A1D8F7DA60063BE3B /* ZLDashboardUITests.m in Sources */, 340 | ); 341 | runOnlyForDeploymentPostprocessing = 0; 342 | }; 343 | /* End PBXSourcesBuildPhase section */ 344 | 345 | /* Begin PBXTargetDependency section */ 346 | 2E43581C1D8F7DA60063BE3B /* PBXTargetDependency */ = { 347 | isa = PBXTargetDependency; 348 | target = 2E4358001D8F7DA60063BE3B /* ZLDashboard */; 349 | targetProxy = 2E43581B1D8F7DA60063BE3B /* PBXContainerItemProxy */; 350 | }; 351 | 2E4358271D8F7DA60063BE3B /* PBXTargetDependency */ = { 352 | isa = PBXTargetDependency; 353 | target = 2E4358001D8F7DA60063BE3B /* ZLDashboard */; 354 | targetProxy = 2E4358261D8F7DA60063BE3B /* PBXContainerItemProxy */; 355 | }; 356 | /* End PBXTargetDependency section */ 357 | 358 | /* Begin PBXVariantGroup section */ 359 | 2E43580D1D8F7DA60063BE3B /* Main.storyboard */ = { 360 | isa = PBXVariantGroup; 361 | children = ( 362 | 2E43580E1D8F7DA60063BE3B /* Base */, 363 | ); 364 | name = Main.storyboard; 365 | sourceTree = ""; 366 | }; 367 | 2E4358121D8F7DA60063BE3B /* LaunchScreen.storyboard */ = { 368 | isa = PBXVariantGroup; 369 | children = ( 370 | 2E4358131D8F7DA60063BE3B /* Base */, 371 | ); 372 | name = LaunchScreen.storyboard; 373 | sourceTree = ""; 374 | }; 375 | /* End PBXVariantGroup section */ 376 | 377 | /* Begin XCBuildConfiguration section */ 378 | 2E43582C1D8F7DA60063BE3B /* Debug */ = { 379 | isa = XCBuildConfiguration; 380 | buildSettings = { 381 | ALWAYS_SEARCH_USER_PATHS = NO; 382 | CLANG_ANALYZER_NONNULL = YES; 383 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 384 | CLANG_CXX_LIBRARY = "libc++"; 385 | CLANG_ENABLE_MODULES = YES; 386 | CLANG_ENABLE_OBJC_ARC = YES; 387 | CLANG_WARN_BOOL_CONVERSION = YES; 388 | CLANG_WARN_CONSTANT_CONVERSION = YES; 389 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 390 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 391 | CLANG_WARN_EMPTY_BODY = YES; 392 | CLANG_WARN_ENUM_CONVERSION = YES; 393 | CLANG_WARN_INFINITE_RECURSION = YES; 394 | CLANG_WARN_INT_CONVERSION = YES; 395 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 396 | CLANG_WARN_SUSPICIOUS_MOVES = YES; 397 | CLANG_WARN_UNREACHABLE_CODE = YES; 398 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 399 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 400 | COPY_PHASE_STRIP = NO; 401 | DEBUG_INFORMATION_FORMAT = dwarf; 402 | ENABLE_STRICT_OBJC_MSGSEND = YES; 403 | ENABLE_TESTABILITY = YES; 404 | GCC_C_LANGUAGE_STANDARD = gnu99; 405 | GCC_DYNAMIC_NO_PIC = NO; 406 | GCC_NO_COMMON_BLOCKS = YES; 407 | GCC_OPTIMIZATION_LEVEL = 0; 408 | GCC_PREPROCESSOR_DEFINITIONS = ( 409 | "DEBUG=1", 410 | "$(inherited)", 411 | ); 412 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 413 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 414 | GCC_WARN_UNDECLARED_SELECTOR = YES; 415 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 416 | GCC_WARN_UNUSED_FUNCTION = YES; 417 | GCC_WARN_UNUSED_VARIABLE = YES; 418 | IPHONEOS_DEPLOYMENT_TARGET = 10.0; 419 | MTL_ENABLE_DEBUG_INFO = YES; 420 | ONLY_ACTIVE_ARCH = YES; 421 | SDKROOT = iphoneos; 422 | }; 423 | name = Debug; 424 | }; 425 | 2E43582D1D8F7DA60063BE3B /* Release */ = { 426 | isa = XCBuildConfiguration; 427 | buildSettings = { 428 | ALWAYS_SEARCH_USER_PATHS = NO; 429 | CLANG_ANALYZER_NONNULL = YES; 430 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 431 | CLANG_CXX_LIBRARY = "libc++"; 432 | CLANG_ENABLE_MODULES = YES; 433 | CLANG_ENABLE_OBJC_ARC = YES; 434 | CLANG_WARN_BOOL_CONVERSION = YES; 435 | CLANG_WARN_CONSTANT_CONVERSION = YES; 436 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 437 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 438 | CLANG_WARN_EMPTY_BODY = YES; 439 | CLANG_WARN_ENUM_CONVERSION = YES; 440 | CLANG_WARN_INFINITE_RECURSION = YES; 441 | CLANG_WARN_INT_CONVERSION = YES; 442 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 443 | CLANG_WARN_SUSPICIOUS_MOVES = YES; 444 | CLANG_WARN_UNREACHABLE_CODE = YES; 445 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 446 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 447 | COPY_PHASE_STRIP = NO; 448 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 449 | ENABLE_NS_ASSERTIONS = NO; 450 | ENABLE_STRICT_OBJC_MSGSEND = YES; 451 | GCC_C_LANGUAGE_STANDARD = gnu99; 452 | GCC_NO_COMMON_BLOCKS = YES; 453 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 454 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 455 | GCC_WARN_UNDECLARED_SELECTOR = YES; 456 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 457 | GCC_WARN_UNUSED_FUNCTION = YES; 458 | GCC_WARN_UNUSED_VARIABLE = YES; 459 | IPHONEOS_DEPLOYMENT_TARGET = 10.0; 460 | MTL_ENABLE_DEBUG_INFO = NO; 461 | SDKROOT = iphoneos; 462 | VALIDATE_PRODUCT = YES; 463 | }; 464 | name = Release; 465 | }; 466 | 2E43582F1D8F7DA60063BE3B /* Debug */ = { 467 | isa = XCBuildConfiguration; 468 | buildSettings = { 469 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 470 | DEVELOPMENT_TEAM = 7734U6Q8V5; 471 | INFOPLIST_FILE = ZLDashboard/Info.plist; 472 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 473 | PRODUCT_BUNDLE_IDENTIFIER = com.ysmx.ZLDashboard; 474 | PRODUCT_NAME = "$(TARGET_NAME)"; 475 | }; 476 | name = Debug; 477 | }; 478 | 2E4358301D8F7DA60063BE3B /* Release */ = { 479 | isa = XCBuildConfiguration; 480 | buildSettings = { 481 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 482 | DEVELOPMENT_TEAM = 7734U6Q8V5; 483 | INFOPLIST_FILE = ZLDashboard/Info.plist; 484 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 485 | PRODUCT_BUNDLE_IDENTIFIER = com.ysmx.ZLDashboard; 486 | PRODUCT_NAME = "$(TARGET_NAME)"; 487 | }; 488 | name = Release; 489 | }; 490 | 2E4358321D8F7DA60063BE3B /* Debug */ = { 491 | isa = XCBuildConfiguration; 492 | buildSettings = { 493 | BUNDLE_LOADER = "$(TEST_HOST)"; 494 | INFOPLIST_FILE = ZLDashboardTests/Info.plist; 495 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 496 | PRODUCT_BUNDLE_IDENTIFIER = com.ysmx.ZLDashboardTests; 497 | PRODUCT_NAME = "$(TARGET_NAME)"; 498 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/ZLDashboard.app/ZLDashboard"; 499 | }; 500 | name = Debug; 501 | }; 502 | 2E4358331D8F7DA60063BE3B /* Release */ = { 503 | isa = XCBuildConfiguration; 504 | buildSettings = { 505 | BUNDLE_LOADER = "$(TEST_HOST)"; 506 | INFOPLIST_FILE = ZLDashboardTests/Info.plist; 507 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 508 | PRODUCT_BUNDLE_IDENTIFIER = com.ysmx.ZLDashboardTests; 509 | PRODUCT_NAME = "$(TARGET_NAME)"; 510 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/ZLDashboard.app/ZLDashboard"; 511 | }; 512 | name = Release; 513 | }; 514 | 2E4358351D8F7DA60063BE3B /* Debug */ = { 515 | isa = XCBuildConfiguration; 516 | buildSettings = { 517 | INFOPLIST_FILE = ZLDashboardUITests/Info.plist; 518 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 519 | PRODUCT_BUNDLE_IDENTIFIER = com.ysmx.ZLDashboardUITests; 520 | PRODUCT_NAME = "$(TARGET_NAME)"; 521 | TEST_TARGET_NAME = ZLDashboard; 522 | }; 523 | name = Debug; 524 | }; 525 | 2E4358361D8F7DA60063BE3B /* Release */ = { 526 | isa = XCBuildConfiguration; 527 | buildSettings = { 528 | INFOPLIST_FILE = ZLDashboardUITests/Info.plist; 529 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 530 | PRODUCT_BUNDLE_IDENTIFIER = com.ysmx.ZLDashboardUITests; 531 | PRODUCT_NAME = "$(TARGET_NAME)"; 532 | TEST_TARGET_NAME = ZLDashboard; 533 | }; 534 | name = Release; 535 | }; 536 | /* End XCBuildConfiguration section */ 537 | 538 | /* Begin XCConfigurationList section */ 539 | 2E4357FC1D8F7DA60063BE3B /* Build configuration list for PBXProject "ZLDashboard" */ = { 540 | isa = XCConfigurationList; 541 | buildConfigurations = ( 542 | 2E43582C1D8F7DA60063BE3B /* Debug */, 543 | 2E43582D1D8F7DA60063BE3B /* Release */, 544 | ); 545 | defaultConfigurationIsVisible = 0; 546 | defaultConfigurationName = Release; 547 | }; 548 | 2E43582E1D8F7DA60063BE3B /* Build configuration list for PBXNativeTarget "ZLDashboard" */ = { 549 | isa = XCConfigurationList; 550 | buildConfigurations = ( 551 | 2E43582F1D8F7DA60063BE3B /* Debug */, 552 | 2E4358301D8F7DA60063BE3B /* Release */, 553 | ); 554 | defaultConfigurationIsVisible = 0; 555 | defaultConfigurationName = Release; 556 | }; 557 | 2E4358311D8F7DA60063BE3B /* Build configuration list for PBXNativeTarget "ZLDashboardTests" */ = { 558 | isa = XCConfigurationList; 559 | buildConfigurations = ( 560 | 2E4358321D8F7DA60063BE3B /* Debug */, 561 | 2E4358331D8F7DA60063BE3B /* Release */, 562 | ); 563 | defaultConfigurationIsVisible = 0; 564 | defaultConfigurationName = Release; 565 | }; 566 | 2E4358341D8F7DA60063BE3B /* Build configuration list for PBXNativeTarget "ZLDashboardUITests" */ = { 567 | isa = XCConfigurationList; 568 | buildConfigurations = ( 569 | 2E4358351D8F7DA60063BE3B /* Debug */, 570 | 2E4358361D8F7DA60063BE3B /* Release */, 571 | ); 572 | defaultConfigurationIsVisible = 0; 573 | defaultConfigurationName = Release; 574 | }; 575 | /* End XCConfigurationList section */ 576 | }; 577 | rootObject = 2E4357F91D8F7DA60063BE3B /* Project object */; 578 | } 579 | -------------------------------------------------------------------------------- /ZLDashboard/ZLDashboard.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ZLDashboard/ZLDashboard/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // ZLDashboard 4 | // 5 | // Created by qtx on 16/9/19. 6 | // Copyright © 2016年 ZL. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /ZLDashboard/ZLDashboard/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // ZLDashboard 4 | // 5 | // Created by qtx on 16/9/19. 6 | // Copyright © 2016年 ZL. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | return YES; 21 | } 22 | 23 | 24 | - (void)applicationWillResignActive:(UIApplication *)application { 25 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 26 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 27 | } 28 | 29 | 30 | - (void)applicationDidEnterBackground:(UIApplication *)application { 31 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 32 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 33 | } 34 | 35 | 36 | - (void)applicationWillEnterForeground:(UIApplication *)application { 37 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 38 | } 39 | 40 | 41 | - (void)applicationDidBecomeActive:(UIApplication *)application { 42 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 43 | } 44 | 45 | 46 | - (void)applicationWillTerminate:(UIApplication *)application { 47 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 48 | } 49 | 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /ZLDashboard/ZLDashboard/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /ZLDashboard/ZLDashboard/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /ZLDashboard/ZLDashboard/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /ZLDashboard/ZLDashboard/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | 仪表盘 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /ZLDashboard/ZLDashboard/UIColor+Extensions.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIColor+Extension.h 3 | // ZLDashboard 4 | // 5 | // Created by qtx on 16/9/19. 6 | // Copyright © 2016年 ZL. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UIColor (Extensions) 12 | 13 | + (UIColor *)colorWithHex:(long)hexColor; 14 | 15 | + (UIColor *)colorWithHex:(long)hexColor alpha:(CGFloat)alpha; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /ZLDashboard/ZLDashboard/UIColor+Extensions.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIColor+Extension.m 3 | // ZLDashboard 4 | // 5 | // Created by qtx on 16/9/19. 6 | // Copyright © 2016年 ZL. All rights reserved. 7 | // 8 | 9 | #import "UIColor+Extensions.h" 10 | 11 | @implementation UIColor (Extensions) 12 | 13 | + (UIColor *)colorWithHex:(long)hexColor { 14 | CGFloat red = ((CGFloat)((hexColor & 0xFF0000) >> 16))/255.0f; 15 | CGFloat green = ((CGFloat)((hexColor & 0xFF00) >> 8))/255.0f; 16 | CGFloat blue = ((CGFloat)(hexColor & 0xFF))/255.0f; 17 | return [UIColor colorWithRed:red green:green blue:blue alpha:1.0f]; 18 | } 19 | 20 | + (UIColor *)colorWithHex:(long)hexColor alpha:(CGFloat)alpha{ 21 | CGFloat red = ((CGFloat)((hexColor & 0xFF0000) >> 16))/255.0f; 22 | CGFloat green = ((CGFloat)((hexColor & 0xFF00) >> 8))/255.0f; 23 | CGFloat blue = ((CGFloat)(hexColor & 0xFF))/255.0f; 24 | return [UIColor colorWithRed:red green:green blue:blue alpha:alpha]; 25 | } 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /ZLDashboard/ZLDashboard/UIView+Extensions.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+Extension.h 3 | // ZLDashboard 4 | // 5 | // Created by qtx on 16/9/19. 6 | // Copyright © 2016年 ZL. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface UIView (Extensions) 13 | 14 | @property CGPoint origin; 15 | @property CGSize size; 16 | 17 | @property (readonly) CGPoint bottomLeft; 18 | @property (readonly) CGPoint bottomRight; 19 | @property (readonly) CGPoint topRight; 20 | 21 | @property CGFloat height; 22 | @property CGFloat width; 23 | 24 | @property CGFloat top; 25 | @property CGFloat left; 26 | 27 | @property CGFloat bottom; 28 | @property CGFloat right; 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /ZLDashboard/ZLDashboard/UIView+Extensions.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+Extension.m 3 | // ZLDashboard 4 | // 5 | // Created by qtx on 16/9/19. 6 | // Copyright © 2016年 ZL. All rights reserved. 7 | // 8 | 9 | #import "UIView+Extensions.h" 10 | 11 | @implementation UIView (Extensions) 12 | 13 | // Retrieve and set the origin 14 | - (CGPoint)origin { 15 | return self.frame.origin; 16 | } 17 | 18 | - (void)setOrigin:(CGPoint)aPoint{ 19 | CGRect newframe = self.frame; 20 | newframe.origin = aPoint; 21 | self.frame = newframe; 22 | } 23 | 24 | // Retrieve and set the size 25 | - (CGSize)size { 26 | return self.frame.size; 27 | } 28 | 29 | - (void)setSize:(CGSize)aSize { 30 | CGRect newframe = self.frame; 31 | newframe.size = aSize; 32 | self.frame = newframe; 33 | } 34 | 35 | // Query other frame locations 36 | - (CGPoint)bottomRight { 37 | CGFloat x = self.frame.origin.x + self.frame.size.width; 38 | CGFloat y = self.frame.origin.y + self.frame.size.height; 39 | return CGPointMake(x, y); 40 | } 41 | 42 | - (CGPoint)bottomLeft { 43 | CGFloat x = self.frame.origin.x; 44 | CGFloat y = self.frame.origin.y + self.frame.size.height; 45 | return CGPointMake(x, y); 46 | } 47 | 48 | - (CGPoint)topRight { 49 | CGFloat x = self.frame.origin.x + self.frame.size.width; 50 | CGFloat y = self.frame.origin.y; 51 | return CGPointMake(x, y); 52 | } 53 | 54 | 55 | // Retrieve and set height, width, top, bottom, left, right 56 | - (CGFloat)height { 57 | return self.frame.size.height; 58 | } 59 | 60 | - (void)setHeight:(CGFloat)newheight { 61 | CGRect newframe = self.frame; 62 | newframe.size.height = newheight; 63 | self.frame = newframe; 64 | } 65 | 66 | - (CGFloat)width { 67 | return self.frame.size.width; 68 | } 69 | 70 | - (void)setWidth:(CGFloat)newwidth { 71 | CGRect newframe = self.frame; 72 | newframe.size.width = newwidth; 73 | self.frame = newframe; 74 | } 75 | 76 | - (CGFloat)top { 77 | return self.frame.origin.y; 78 | } 79 | 80 | - (void)setTop:(CGFloat)newtop { 81 | CGRect newframe = self.frame; 82 | newframe.origin.y = newtop; 83 | self.frame = newframe; 84 | } 85 | 86 | - (CGFloat)left { 87 | return self.frame.origin.x; 88 | } 89 | 90 | - (void)setLeft:(CGFloat)newleft { 91 | CGRect newframe = self.frame; 92 | newframe.origin.x = newleft; 93 | self.frame = newframe; 94 | } 95 | 96 | - (CGFloat)bottom { 97 | return self.frame.origin.y + self.frame.size.height; 98 | } 99 | 100 | - (void)setBottom:(CGFloat)newbottom { 101 | CGRect newframe = self.frame; 102 | newframe.origin.y = newbottom - self.frame.size.height; 103 | self.frame = newframe; 104 | } 105 | 106 | - (CGFloat)right{ 107 | return self.frame.origin.x + self.frame.size.width; 108 | } 109 | 110 | - (void)setRight:(CGFloat)newright { 111 | CGFloat delta = newright - (self.frame.origin.x + self.frame.size.width); 112 | CGRect newframe = self.frame; 113 | newframe.origin.x += delta ; 114 | self.frame = newframe; 115 | } 116 | 117 | @end 118 | -------------------------------------------------------------------------------- /ZLDashboard/ZLDashboard/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // ZLDashboard 4 | // 5 | // Created by qtx on 16/9/19. 6 | // Copyright © 2016年 ZL. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /ZLDashboard/ZLDashboard/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // ZLDashboard 4 | // 5 | // Created by qtx on 16/9/19. 6 | // Copyright © 2016年 ZL. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "ZLDashboardView.h" 11 | #import "ZLGradientView.h" 12 | #import "UIView+Extensions.h" 13 | 14 | 15 | #define SCREEN_WIDTH ([[UIScreen mainScreen] bounds].size.width) 16 | #define SCREEN_HEIGHT ([[UIScreen mainScreen] bounds].size.height) 17 | 18 | #define MinNumber 350 19 | #define MaxNumber 950 20 | 21 | 22 | @interface ViewController () 23 | 24 | @property (nonatomic, strong) ZLDashboardView *dashboardView; 25 | 26 | @property (nonatomic, strong) ZLGradientView * gradientView; 27 | 28 | @property (nonatomic, strong) UIButton * clickBtn; 29 | 30 | @property (nonatomic, strong) UISlider * slider; 31 | 32 | @end 33 | 34 | @implementation ViewController 35 | 36 | - (void)viewDidLoad { 37 | [super viewDidLoad]; 38 | 39 | //创建背景色 40 | [self setupGradientView]; 41 | 42 | //创建仪表盘 43 | [self setupCircleView]; 44 | 45 | //添加触发动画的点击button 46 | [self addActionButton]; 47 | 48 | //改变value 49 | [self addSlideChnageValue]; 50 | 51 | } 52 | 53 | - (void)addActionButton { 54 | UIButton *stareButton = [UIButton buttonWithType:UIButtonTypeCustom]; 55 | stareButton.frame = CGRectMake(10.f, self.dashboardView.bottom + 50.f, SCREEN_WIDTH - 20.f, 38.f); 56 | [stareButton addTarget:self action:@selector(onStareButtonClick:) forControlEvents:UIControlEventTouchUpInside]; 57 | [stareButton setTitle:@"Start Animation" forState:UIControlStateNormal]; 58 | [stareButton setBackgroundColor:[UIColor lightGrayColor]]; 59 | stareButton.layer.masksToBounds = YES; 60 | stareButton.layer.cornerRadius = 4.f; 61 | [self.view addSubview:stareButton]; 62 | 63 | _clickBtn = stareButton; 64 | } 65 | 66 | - (void)addSlideChnageValue { 67 | 68 | CGFloat width = 280; 69 | CGFloat height = 40; 70 | CGFloat xPixel = (SCREEN_WIDTH - width) * 0.5; 71 | CGFloat yPixel = CGRectGetMaxY(_clickBtn.frame) + 20; 72 | CGRect slideFrame = CGRectMake(xPixel, yPixel, width, height); 73 | 74 | UISlider *slider = [[UISlider alloc] initWithFrame:slideFrame]; 75 | 76 | slider.minimumValue = MinNumber; 77 | slider.maximumValue = MaxNumber; 78 | 79 | slider.minimumTrackTintColor = [UIColor colorWithRed:0.000 green:1.000 blue:0.502 alpha:1.000]; 80 | slider.maximumTrackTintColor = [UIColor colorWithWhite:0.800 alpha:1.000]; 81 | /** 82 | * 注意这个属性:如果你没有设置滑块的图片,那个这个属性将只会改变已划过一段线条的颜色,不会改变滑块的颜色,如果你设置了滑块的图片,又设置了这个属性,那么滑块的图片将不显示,滑块的颜色会改变(IOS7) 83 | */ 84 | [slider setThumbImage:[UIImage imageNamed:@""] forState:UIControlStateNormal]; 85 | slider.thumbTintColor = [UIColor cyanColor]; 86 | 87 | 88 | [slider setValue:0.5 animated:YES]; 89 | 90 | [slider addTarget:self action:@selector(slideTap:)forControlEvents:UIControlEventValueChanged]; 91 | 92 | [self.view addSubview:slider]; 93 | 94 | _slider = slider; 95 | } 96 | 97 | - (void)slideTap:(UISlider *)sender { 98 | CGFloat value = sender.value; 99 | NSLog(@"%.f",value); 100 | } 101 | 102 | - (void)setupGradientView { 103 | self.gradientView = [[ZLGradientView alloc] initWithFrame:self.view.bounds]; 104 | [self.view addSubview:self.gradientView]; 105 | } 106 | 107 | - (void)setupCircleView { 108 | self.dashboardView = [[ZLDashboardView alloc] initWithFrame:CGRectMake(40.f, 70.f, SCREEN_WIDTH - 80.f, SCREEN_WIDTH - 80.f)]; 109 | self.dashboardView.bgImage = [UIImage imageNamed:@"backgroundImage"]; 110 | [self.view addSubview:self.dashboardView]; 111 | } 112 | 113 | - (void)onStareButtonClick:(UIButton *)sender { 114 | 115 | if (sender.selected) { 116 | [self.gradientView removeFromSuperview]; 117 | self.gradientView = nil; 118 | [self.dashboardView removeFromSuperview]; 119 | self.dashboardView = nil; 120 | 121 | [self setupGradientView]; 122 | [self setupCircleView]; 123 | 124 | [self.view bringSubviewToFront:self.clickBtn]; 125 | [self.view bringSubviewToFront:_slider]; 126 | } 127 | sender.selected = YES; 128 | 129 | CGFloat value = _slider.value; 130 | 131 | NSString *startNO = [NSString stringWithFormat:@"%d", MinNumber]; 132 | NSString *toNO = [NSString stringWithFormat:@"%.f",value];//@"693"; 950 133 | NSLog(@"endNO:%@",toNO); 134 | [self.dashboardView refreshJumpNOFromNO:startNO toNO:toNO]; 135 | 136 | __block typeof(self)blockSelf = self; 137 | self.dashboardView.TimerBlock = ^(NSInteger index) { 138 | [blockSelf.gradientView setUpBackGroundColorWithColorArrayIndex:index]; 139 | }; 140 | } 141 | 142 | 143 | 144 | @end 145 | -------------------------------------------------------------------------------- /ZLDashboard/ZLDashboard/ZLDashboardView.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZLDashboardView.h 3 | // ZLDashboard 4 | // 5 | // Created by qtx on 16/9/19. 6 | // Copyright © 2016年 ZL. All rights reserved. 7 | // 8 | 9 | /** 10 | * 根据跃动数字 11 | * 12 | * 确定百分比 13 | * 现在的跳动数字——>背景颜色变化 14 | * 15 | */ 16 | 17 | #import 18 | 19 | @interface ZLDashboardView : UIView 20 | 21 | @property (nonatomic, strong) UIImage *bgImage; 22 | 23 | @property (nonatomic, copy) void(^TimerBlock)(NSInteger); 24 | 25 | /** 26 | * 跃动数字刷新 27 | * 28 | */ 29 | - (void)refreshJumpNOFromNO:(NSString *)startNO toNO:(NSString *)toNO; 30 | 31 | @end 32 | -------------------------------------------------------------------------------- /ZLDashboard/ZLDashboard/ZLDashboardView.m: -------------------------------------------------------------------------------- 1 | // 2 | // ZLDashboardView.m 3 | // ZLDashboard 4 | // 5 | // Created by qtx on 16/9/19. 6 | // Copyright © 2016年 ZL. All rights reserved. 7 | // 8 | 9 | #import "ZLDashboardView.h" 10 | 11 | #import "UIView+Extensions.h" 12 | 13 | #define degreesToRadians(x) (M_PI*(x)/180.0) //把角度转换成PI的方式 14 | static const CGFloat kMarkerRadius = 5.f; // 光标直径 15 | static const CGFloat kTimerInterval = 0.03; 16 | static const CGFloat kFastProportion = 0.9; 17 | 18 | static const NSInteger MaxNumber = 1000; 19 | 20 | @interface ZLDashboardView () { 21 | CGFloat animationTime; 22 | NSInteger beginNO; 23 | NSInteger jumpCurrentNO; 24 | NSInteger endNO; 25 | } 26 | 27 | // 百分比 0 - 100 根据跃动数字设置 28 | @property (nonatomic, assign) CGFloat percent; 29 | 30 | @property (nonatomic, strong) CAShapeLayer *bottomLayer; // 进度条底色 31 | @property (nonatomic, assign) CGFloat lineWidth; // 弧线宽度 32 | 33 | @property (nonatomic, strong) UIImageView *markerImageView; // 光标 34 | 35 | @property (nonatomic, strong) UIImageView *bgImageView; // 背景图片 36 | 37 | @property (nonatomic, assign) CGFloat circelRadius; //圆直径 38 | @property (nonatomic, assign) CGFloat startAngle; // 开始角度 39 | @property (nonatomic, assign) CGFloat endAngle; // 结束角度 40 | 41 | @property (nonatomic, strong) UILabel *showLable; // 跳跃数字 42 | @property (nonatomic, strong) UILabel *markedLabel; // 提示语 43 | @property (nonatomic, strong) NSTimer *fastTimer; 44 | @property (nonatomic, strong) NSTimer *slowTimer; 45 | 46 | @property (nonatomic, assign) NSInteger intervalNum; 47 | 48 | @end 49 | 50 | @implementation ZLDashboardView 51 | 52 | #pragma mark - Life cycle 53 | 54 | - (instancetype)initWithFrame:(CGRect)frame { 55 | 56 | self = [super initWithFrame:frame]; 57 | if (self) { 58 | self.backgroundColor = [UIColor clearColor]; 59 | 60 | self.circelRadius = self.frame.size.width - 10.f; 61 | self.lineWidth = 2.f; 62 | self.startAngle = -200.f; 63 | self.endAngle = 20.f; 64 | 65 | // 尺寸需根据图片进行调整 66 | self.bgImageView.frame = CGRectMake(6, 6, self.circelRadius, self.circelRadius * 2 / 3); 67 | self.bgImageView.backgroundColor = [UIColor clearColor]; 68 | [self addSubview:self.bgImageView]; 69 | 70 | //添加圆框 71 | [self setupCircleBg]; 72 | 73 | //光标 74 | [self setupMarkerImageView]; 75 | 76 | //添加跃动数字 及 提示语 77 | [self setupJumpNOView]; 78 | } 79 | return self; 80 | } 81 | 82 | 83 | - (void)setupCircleBg { 84 | 85 | // 圆形路径 86 | UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(self.width / 2, self.height / 2) 87 | radius:(self.circelRadius - self.lineWidth) / 2 88 | startAngle:degreesToRadians(self.startAngle) 89 | endAngle:degreesToRadians(self.endAngle) 90 | clockwise:YES]; 91 | 92 | // 底色 93 | self.bottomLayer = [CAShapeLayer layer]; 94 | self.bottomLayer.frame = self.bounds; 95 | self.bottomLayer.fillColor = [[UIColor clearColor] CGColor]; 96 | self.bottomLayer.strokeColor = [[UIColor colorWithRed:206.f / 256.f green:241.f / 256.f blue:227.f alpha:1.f] CGColor]; 97 | self.bottomLayer.opacity = 0.5; 98 | self.bottomLayer.lineCap = kCALineCapRound; 99 | self.bottomLayer.lineWidth = self.lineWidth; 100 | self.bottomLayer.path = [path CGPath]; 101 | [self.layer addSublayer:self.bottomLayer]; 102 | 103 | // 240 是用整个弧度的角度之和 |-200| + 20 = 220 104 | // [self createAnimationWithStartAngle:degreesToRadians(self.startAngle) 105 | // endAngle:degreesToRadians(self.startAngle + 220 * 1)]; 106 | } 107 | 108 | - (void)setupMarkerImageView { 109 | if (_markerImageView) { 110 | return; 111 | } 112 | _markerImageView = [[UIImageView alloc] init]; 113 | _markerImageView.backgroundColor = [UIColor clearColor]; 114 | _markerImageView.layer.backgroundColor = [UIColor greenColor].CGColor; 115 | _markerImageView.layer.shadowColor = [UIColor whiteColor].CGColor; 116 | _markerImageView.layer.shadowOffset = CGSizeMake(0, 0); 117 | _markerImageView.layer.shadowRadius = kMarkerRadius*0.5; 118 | _markerImageView.layer.shadowOpacity = 1; 119 | _markerImageView.layer.masksToBounds = NO; 120 | self.markerImageView.layer.cornerRadius = self.markerImageView.frame.size.height / 2; 121 | [self addSubview:self.markerImageView]; 122 | _markerImageView.frame = CGRectMake(-100, self.height, kMarkerRadius, kMarkerRadius); 123 | } 124 | 125 | - (void)setupJumpNOView { 126 | if (_showLable) { 127 | return; 128 | } 129 | CGFloat width = self.circelRadius / 2 + 20; 130 | CGFloat height = self.circelRadius / 2 - 40; 131 | CGFloat xPixel = self.bgImageView.left + (self.bgImageView.width - width)*0.5;//self.circelRadius / 4; 132 | CGFloat yPixel = self.circelRadius / 4; 133 | CGRect labelFrame = CGRectMake(xPixel, yPixel, width, height); 134 | _showLable = [[UILabel alloc] initWithFrame:labelFrame]; 135 | _showLable.backgroundColor = [UIColor clearColor]; 136 | _showLable.textColor = [UIColor greenColor]; 137 | _showLable.textAlignment = NSTextAlignmentCenter; 138 | _showLable.font = [UIFont systemFontOfSize:70.f]; 139 | _showLable.text = [NSString stringWithFormat:@"%ld",jumpCurrentNO]; 140 | [self addSubview:_showLable]; 141 | 142 | // TODO:提示语 143 | _markedLabel = [[UILabel alloc] initWithFrame:CGRectMake(xPixel, CGRectGetMaxY(_showLable.frame), width, 20)]; 144 | _markedLabel.backgroundColor = [UIColor clearColor]; 145 | _markedLabel.textColor = [UIColor greenColor]; 146 | _markedLabel.textAlignment = NSTextAlignmentCenter; 147 | _markedLabel.font = [UIFont systemFontOfSize:16.f]; 148 | _markedLabel.text = @"营养良好"; 149 | [self addSubview:_markedLabel]; 150 | } 151 | 152 | #pragma mark - Animation 153 | 154 | - (void)createAnimationWithStartAngle:(CGFloat)startAngle endAngle:(CGFloat)endAngle { // 光标动画 155 | 156 | //启动定时器 157 | [_fastTimer setFireDate:[NSDate distantPast]]; 158 | // 设置动画属性 159 | CAKeyframeAnimation *pathAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"]; 160 | pathAnimation.calculationMode = kCAAnimationPaced; 161 | pathAnimation.fillMode = kCAFillModeForwards; 162 | pathAnimation.removedOnCompletion = NO; 163 | pathAnimation.duration = _percent * kTimerInterval; 164 | pathAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]; 165 | pathAnimation.repeatCount = 1; 166 | 167 | // 设置动画路径 168 | CGMutablePathRef path = CGPathCreateMutable(); 169 | CGPathAddArc(path, NULL, self.width / 2, self.height / 2, (self.circelRadius - kMarkerRadius / 2) / 2, startAngle, endAngle, 0); 170 | pathAnimation.path = path; 171 | CGPathRelease(path); 172 | 173 | [self.markerImageView.layer addAnimation:pathAnimation forKey:@"moveMarker"]; 174 | 175 | } 176 | 177 | #pragma mark - Setters / Getters 178 | 179 | 180 | /** 181 | * 开始动画 确定百分比 182 | * 183 | */ 184 | - (void)refreshJumpNOFromNO:(NSString *)startNO toNO:(NSString *)toNO { 185 | 186 | beginNO = 0; // [startNO integerValue]; 187 | jumpCurrentNO = 0; // [startNO integerValue]; 188 | endNO = [toNO integerValue]; 189 | _percent = endNO * 100 / MaxNumber; 190 | 191 | NSInteger diffNum = endNO - beginNO; 192 | if (diffNum <= 0) { 193 | return; 194 | } 195 | if (diffNum < 100) { 196 | _intervalNum = 5; 197 | } else if (diffNum < 300) { 198 | _intervalNum = 15; 199 | } else if (diffNum <= MaxNumber) { 200 | _intervalNum = 10; 201 | } 202 | NSLog(@"数字间隔:%ld",_intervalNum); 203 | 204 | //数字 205 | [self setupJumpThings]; 206 | 207 | // 设置角度 208 | 209 | NSInteger angle = 0; 210 | NSInteger num = [toNO floatValue] - [startNO floatValue]; 211 | if (num < 200) { 212 | angle = self.startAngle + 220 * (num / 200.0) / 5.0; 213 | } else if (num < 350) { 214 | angle = self.startAngle + 220 / 5.0 + (3 / 5.0 * 220) * (num - 200) / 150.0; 215 | } else { 216 | angle = self.startAngle + 220 / 5.0 * 4 + (220 / 5.0) * (num - 350) / 250.0; 217 | } 218 | //光标 219 | [self createAnimationWithStartAngle:degreesToRadians(self.startAngle) 220 | endAngle:degreesToRadians(angle)]; 221 | } 222 | 223 | - (void)setBgImage:(UIImage *)bgImage { 224 | 225 | _bgImage = bgImage; 226 | self.bgImageView.image = bgImage; 227 | } 228 | 229 | - (UIImageView *)bgImageView { 230 | 231 | if (nil == _bgImageView) { 232 | _bgImageView = [[UIImageView alloc] init]; 233 | } 234 | return _bgImageView; 235 | } 236 | 237 | #pragma mark - 跃动数字 238 | 239 | - (void)setupJumpThings { 240 | 241 | animationTime = _percent * kTimerInterval; 242 | 243 | self.fastTimer = [NSTimer timerWithTimeInterval:kTimerInterval*kFastProportion 244 | target:self 245 | selector:@selector(fastTimerAction) 246 | userInfo:nil 247 | repeats:YES]; 248 | [[NSRunLoop currentRunLoop] addTimer:_fastTimer forMode:NSRunLoopCommonModes]; 249 | 250 | //时间间隔 = (总时间 - 快时间间隔*变化次数)/ 再次需要变化的次数 251 | //快时间 252 | NSInteger fastEndNO = endNO * kFastProportion; 253 | 254 | NSInteger fastJump = fastEndNO/_intervalNum; 255 | if (fastJump % _intervalNum) { 256 | fastJump++; 257 | fastEndNO += _intervalNum; 258 | } 259 | CGFloat fastTTime = fastJump*kTimerInterval*kFastProportion; 260 | 261 | //剩余应跳动次数 262 | NSInteger changNO = endNO - fastEndNO; 263 | NSInteger endJump = changNO / _intervalNum + changNO % _intervalNum; 264 | //慢时间间隔 265 | NSTimeInterval slowInterval = (animationTime - fastTTime) / endJump; 266 | 267 | self.slowTimer = [NSTimer timerWithTimeInterval:slowInterval 268 | target:self 269 | selector:@selector(slowTimerAction) 270 | userInfo:nil 271 | repeats:YES]; 272 | [[NSRunLoop currentRunLoop] addTimer:_slowTimer forMode:NSRunLoopCommonModes]; 273 | [_fastTimer setFireDate:[NSDate distantFuture]]; 274 | [_slowTimer setFireDate:[NSDate distantFuture]]; 275 | } 276 | 277 | #pragma mark 加速定时器触发事件 278 | - (void)fastTimerAction { 279 | if (jumpCurrentNO >= endNO) { 280 | [self.fastTimer invalidate]; 281 | return; 282 | } 283 | if (jumpCurrentNO >= endNO * kFastProportion) { 284 | [self.fastTimer invalidate]; 285 | [self.slowTimer setFireDate:[NSDate distantPast]]; 286 | return; 287 | } 288 | [self commonTimerAction]; 289 | } 290 | 291 | #pragma mark 减速定时器触发事件 292 | - (void)slowTimerAction { 293 | if (jumpCurrentNO >= endNO) { 294 | [self.slowTimer invalidate]; 295 | return; 296 | } 297 | [self commonTimerAction]; 298 | } 299 | 300 | #pragma mark 计时器共性事件 - lable赋值 背景颜色变化 301 | - (void)commonTimerAction { 302 | 303 | if (jumpCurrentNO % 100 == 0 && jumpCurrentNO != 0) { 304 | NSInteger colorIndex = jumpCurrentNO / 100; 305 | dispatch_async(dispatch_get_main_queue(), ^{ 306 | if (self.TimerBlock) { 307 | self.TimerBlock(colorIndex); 308 | } 309 | }); 310 | } 311 | NSInteger changeValueBy = endNO - jumpCurrentNO; 312 | 313 | if (changeValueBy/10 < 1) { 314 | jumpCurrentNO++; 315 | } else { 316 | // NSInteger changeBy = changeValueBy / 10; 317 | jumpCurrentNO += _intervalNum; 318 | } 319 | 320 | _showLable.text = [NSString stringWithFormat:@"%ld",jumpCurrentNO]; 321 | if (jumpCurrentNO <= 350) { 322 | _markedLabel.text = @"营养太差"; 323 | } else if (jumpCurrentNO <= 550) { 324 | _markedLabel.text = @"营养较差"; 325 | } else if (jumpCurrentNO <= 600) { 326 | _markedLabel.text = @"营养中等"; 327 | } else if (jumpCurrentNO <= 650) { 328 | _markedLabel.text = @"营养良好"; 329 | } else if (jumpCurrentNO <= 700) { 330 | _markedLabel.text = @"营养优势"; 331 | } else if (jumpCurrentNO <= 950) { 332 | _markedLabel.text = @"营养较好"; 333 | } 334 | } 335 | 336 | 337 | @end 338 | -------------------------------------------------------------------------------- /ZLDashboard/ZLDashboard/ZLGradientView.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZLGradientView.h 3 | // ZLDashboard 4 | // 5 | // Created by qtx on 16/9/19. 6 | // Copyright © 2016年 ZL. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ZLGradientView : UIView 12 | 13 | - (void)setUpBackGroundColorWithColorArrayIndex:(NSInteger)index; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /ZLDashboard/ZLDashboard/ZLGradientView.m: -------------------------------------------------------------------------------- 1 | // 2 | // ZLGradientView.m 3 | // ZLDashboard 4 | // 5 | // Created by qtx on 16/9/19. 6 | // Copyright © 2016年 ZL. All rights reserved. 7 | // 8 | 9 | #import "ZLGradientView.h" 10 | #import "UIColor+Extensions.h" 11 | 12 | #define HEXCOLOR(hexColor) [UIColor colorWithHex:hexColor] 13 | 14 | @interface ZLGradientView () 15 | 16 | @property (nonatomic, strong) CAGradientLayer * gradientLayer; 17 | 18 | //@property (nonatomic, strong) NSMutableArray * allColors; 19 | 20 | //@property (nonatomic, strong) NSArray * colors1; 21 | // 22 | //@property (nonatomic, strong) NSArray * colors2; 23 | // 24 | //@property (nonatomic, strong) NSArray * colors3; 25 | // 26 | //@property (nonatomic, strong) NSArray * colors4; 27 | 28 | @property (nonatomic, strong) NSArray * upColorArray; 29 | 30 | @property (nonatomic, strong) NSArray * middleColorArray; 31 | 32 | @property (nonatomic, strong) NSArray * downColorArray; 33 | 34 | @property (nonatomic, assign) NSInteger bgCount; 35 | 36 | @property (nonatomic, assign) NSInteger changeCount; 37 | 38 | @property (nonatomic, strong) NSTimer * bgTimer; 39 | 40 | @property (nonatomic, assign) CGFloat totalAnimationTime; 41 | 42 | @end 43 | 44 | 45 | @implementation ZLGradientView 46 | 47 | - (void)setupColors { 48 | NSArray * upColorArray = @[HEXCOLOR(0xff2a01),HEXCOLOR(0xec1f41), 49 | HEXCOLOR(0xff2a01),HEXCOLOR(0xff5801), 50 | HEXCOLOR(0xf15916),HEXCOLOR(0xf57d0c), 51 | HEXCOLOR(0xdba337),HEXCOLOR(0xdbd034), 52 | HEXCOLOR(0xffad01),HEXCOLOR(0xe5df1f), 53 | HEXCOLOR(0x5ec36d),HEXCOLOR(0x5fc36d), 54 | HEXCOLOR(0x69bff3),HEXCOLOR(0x17afc0), 55 | HEXCOLOR(0x108ef2)]; 56 | NSArray * middleColorArray = @[HEXCOLOR(0xF5311E),HEXCOLOR(0xf0418d), 57 | HEXCOLOR(0xf66042),HEXCOLOR(0xffab3a), 58 | HEXCOLOR(0xf87b43),HEXCOLOR(0xf6960b), 59 | HEXCOLOR(0xe9c34f),HEXCOLOR(0xe6d733), 60 | HEXCOLOR(0xf8d423),HEXCOLOR(0xe2ec3c), 61 | HEXCOLOR(0x30cb9a),HEXCOLOR(0x82d273), 62 | HEXCOLOR(0x2adbbd),HEXCOLOR(0x19c5b5), 63 | HEXCOLOR(0x4baef3)]; 64 | NSArray * downColorArray = @[HEXCOLOR(0xf3735a),HEXCOLOR(0xf14ea9), 65 | HEXCOLOR(0xf3735a),HEXCOLOR(0xffcf53), 66 | HEXCOLOR(0xfa814c),HEXCOLOR(0xf7a20a), 67 | HEXCOLOR(0xf7e568),HEXCOLOR(0xf6e232), 68 | HEXCOLOR(0xf6e12f),HEXCOLOR(0xe0f956), 69 | HEXCOLOR(0x1bcfae),HEXCOLOR(0x92d975), 70 | HEXCOLOR(0x05ec9d),HEXCOLOR(0x1acfaf), 71 | HEXCOLOR(0x69bdf4)]; 72 | self.upColorArray = upColorArray; 73 | self.middleColorArray = middleColorArray; 74 | self.downColorArray = downColorArray; 75 | 76 | } 77 | 78 | //- (NSMutableArray *)allColors { 79 | // if (!_allColors) { 80 | // _allColors = [NSMutableArray array]; 81 | // } 82 | // return _allColors; 83 | //} 84 | 85 | //- (NSArray *)colors1 { 86 | // if (_colors1.count == 0) { 87 | // _colors1 = [NSArray arrayWithObjects: 88 | // (__bridge id)[[UIColor colorWithRed:1.000 green:0.679 blue:0.650 alpha:1.000] CGColor], 89 | // (__bridge id)[[UIColor colorWithRed:1.000 green:0.398 blue:0.362 alpha:1.000] CGColor], 90 | // (__bridge id)[[UIColor colorWithRed:1.000 green:0.276 blue:0.294 alpha:1.000] CGColor], nil]; 91 | // } 92 | // return _colors1; 93 | //} 94 | // 95 | //- (NSArray *)colors2 { 96 | // if (_colors2.count == 0) { 97 | // _colors2 = [NSArray arrayWithObjects: 98 | // (__bridge id)[[UIColor colorWithRed:1.000 green:0.843 blue:0.681 alpha:1.000] CGColor], 99 | // (__bridge id)[[UIColor colorWithRed:1.000 green:0.686 blue:0.383 alpha:1.000] CGColor], 100 | // (__bridge id)[[UIColor colorWithRed:1.000 green:0.620 blue:0.066 alpha:1.000] CGColor], nil]; 101 | // } 102 | // return _colors2; 103 | //} 104 | // 105 | //- (NSArray *)colors3 { 106 | // if (_colors3.count == 0) { 107 | // _colors3 = [NSArray arrayWithObjects: 108 | // (__bridge id)[[UIColor colorWithRed:0.672 green:1.000 blue:0.652 alpha:1.000] CGColor], 109 | // (__bridge id)[[UIColor colorWithRed:0.450 green:1.000 blue:0.406 alpha:1.000] CGColor], 110 | // (__bridge id)[[UIColor colorWithRed:0.139 green:1.000 blue:0.111 alpha:1.000] CGColor], nil]; 111 | // } 112 | // return _colors3; 113 | //} 114 | // 115 | //- (NSArray *)colors4 { 116 | // if (_colors4.count == 0) { 117 | // _colors4 = [NSArray arrayWithObjects: 118 | // (__bridge id)[[UIColor colorWithRed:0.664 green:0.693 blue:1.000 alpha:1.000] CGColor], 119 | // (__bridge id)[[UIColor colorWithRed:0.517 green:0.541 blue:1.000 alpha:1.000] CGColor], 120 | // (__bridge id)[[UIColor colorWithRed:0.259 green:0.304 blue:1.000 alpha:1.000] CGColor], nil]; 121 | // } 122 | // return _colors4; 123 | //} 124 | 125 | - (CAGradientLayer *)gradientLayer { 126 | 127 | if (_gradientLayer == nil) { 128 | CAGradientLayer *gradientLayer = [CAGradientLayer layer]; 129 | gradientLayer.frame = self.bounds; 130 | UIColor *upColor = self.upColorArray[0]; 131 | UIColor *middleColor = self.middleColorArray[0]; 132 | UIColor *downColor = self.downColorArray[0]; 133 | gradientLayer.colors = [NSArray arrayWithObjects: 134 | (__bridge id)[downColor CGColor], 135 | (__bridge id)[middleColor CGColor], 136 | (__bridge id)[upColor CGColor],nil]; 137 | [gradientLayer setLocations:@[@0.3, @0.7, @1 ]]; 138 | [gradientLayer setStartPoint:CGPointMake(0.5, 1)]; 139 | [gradientLayer setEndPoint:CGPointMake(0.5, 0)]; 140 | _gradientLayer = gradientLayer; 141 | } 142 | return _gradientLayer; 143 | } 144 | 145 | - (instancetype)initWithFrame:(CGRect)frame { 146 | self = [super initWithFrame:frame]; 147 | if (self) { 148 | self.backgroundColor = [UIColor clearColor]; 149 | 150 | // self.allColors = [NSMutableArray arrayWithArray:@[self.colors1,self.colors2,self.colors3,self.colors4]]; 151 | [self setupColors]; 152 | [self.layer addSublayer:self.gradientLayer]; 153 | 154 | } 155 | return self; 156 | } 157 | 158 | #pragma mark - set 159 | 160 | //- (void)setPercent:(CGFloat)percent { 161 | // _percent = percent; 162 | // self.bgCount = percent / kPurePercent + 1;//个数不能超出colors的个数 163 | // self.totalAnimationTime = kTimerInterval * percent; 164 | // NSTimeInterval time = self.totalAnimationTime / self.bgCount; 165 | // 166 | // self.bgTimer = [NSTimer timerWithTimeInterval:time 167 | // target:self 168 | // selector:@selector(bgAnimation) 169 | // userInfo:nil 170 | // repeats:YES]; 171 | // [[NSRunLoop currentRunLoop] addTimer:_bgTimer forMode:NSRunLoopCommonModes]; 172 | //} 173 | 174 | - (void)setUpBackGroundColorWithColorArrayIndex:(NSInteger)index { 175 | UIColor *upColor = self.upColorArray[index]; 176 | UIColor *middleColor = self.middleColorArray[index]; 177 | UIColor *downColor = self.downColorArray[index]; 178 | _gradientLayer.colors = [NSArray arrayWithObjects: 179 | (__bridge id)[downColor CGColor], 180 | (__bridge id)[middleColor CGColor], 181 | (__bridge id)[upColor CGColor],nil]; 182 | [self setNeedsLayout]; 183 | } 184 | 185 | //- (void)bgAnimation { 186 | // 187 | // if (self.bgCount > self.allColors.count) { 188 | // NSLog(@"颜色数组错误"); 189 | // [self.bgTimer invalidate]; 190 | // return; 191 | // } 192 | // 193 | // _changeCount++; 194 | // if (_changeCount == _bgCount) { 195 | // _changeCount = 0; 196 | // [self.bgTimer invalidate]; 197 | // return; 198 | // } 199 | // 200 | // self.gradientLayer.colors = //self.allColors[(self.changeCount)]; 201 | // [self setNeedsLayout]; 202 | //} 203 | 204 | @end 205 | -------------------------------------------------------------------------------- /ZLDashboard/ZLDashboard/backgroundImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZLFighting/ZLDashboard/a60ab2ea8033133cfc82c577a058a0e22dfe7b1a/ZLDashboard/ZLDashboard/backgroundImage@2x.png -------------------------------------------------------------------------------- /ZLDashboard/ZLDashboard/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // ZLDashboard 4 | // 5 | // Created by qtx on 16/9/19. 6 | // Copyright © 2016年 ZL. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /ZLDashboard/ZLDashboardTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /ZLDashboard/ZLDashboardTests/ZLDashboardTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // ZLDashboardTests.m 3 | // ZLDashboardTests 4 | // 5 | // Created by qtx on 16/9/19. 6 | // Copyright © 2016年 ZL. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ZLDashboardTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation ZLDashboardTests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | // Put setup code here. This method is called before the invocation of each test method in the class. 20 | } 21 | 22 | - (void)tearDown { 23 | // Put teardown code here. This method is called after the invocation of each test method in the class. 24 | [super tearDown]; 25 | } 26 | 27 | - (void)testExample { 28 | // This is an example of a functional test case. 29 | // Use XCTAssert and related functions to verify your tests produce the correct results. 30 | } 31 | 32 | - (void)testPerformanceExample { 33 | // This is an example of a performance test case. 34 | [self measureBlock:^{ 35 | // Put the code you want to measure the time of here. 36 | }]; 37 | } 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /ZLDashboard/ZLDashboardUITests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /ZLDashboard/ZLDashboardUITests/ZLDashboardUITests.m: -------------------------------------------------------------------------------- 1 | // 2 | // ZLDashboardUITests.m 3 | // ZLDashboardUITests 4 | // 5 | // Created by qtx on 16/9/19. 6 | // Copyright © 2016年 ZL. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ZLDashboardUITests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation ZLDashboardUITests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | 22 | // In UI tests it is usually best to stop immediately when a failure occurs. 23 | self.continueAfterFailure = NO; 24 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. 25 | [[[XCUIApplication alloc] init] launch]; 26 | 27 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 28 | } 29 | 30 | - (void)tearDown { 31 | // Put teardown code here. This method is called after the invocation of each test method in the class. 32 | [super tearDown]; 33 | } 34 | 35 | - (void)testExample { 36 | // Use recording to get started writing UI tests. 37 | // Use XCTAssert and related functions to verify your tests produce the correct results. 38 | } 39 | 40 | @end 41 | --------------------------------------------------------------------------------