iOS仿支付宝芝麻信用仪表盘效果
概述
详细
仿支付宝芝麻信用仪表盘效果

一、主要思路
1.圆环上绿点的旋转
2.分数值及提示语的变化
3.背景色的变化
二、程序实现
一. 自定义ZLDashboardView仪表盘文件:
根据跃动数字, 确定百分比, 现在的跳动数字 ----> 背景颜色变化
.h 文件里公开跃动数字刷新方法:
@property (nonatomic, copy) void(^TimerBlock)(NSInteger);
/**
* 跃动数字刷新
*
*/
- (void)refreshJumpNOFromNO:(NSString *)startNO toNO:(NSString *)toNO;
.m 文件
自定义Lift cycle
#pragma mark - Life cycle
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
self.backgroundColor = [UIColor clearColor];
self.circelRadius = self.frame.size.width - 10.f;
self.lineWidth = 2.f;
self.startAngle = -200.f;
self.endAngle = 20.f;
// 尺寸需根据图片进行调整
self.bgImageView.frame = CGRectMake(6, 6, self.circelRadius, self.circelRadius * 2 / 3); self.bgImageView.backgroundColor = [UIColor clearColor];
[self addSubview:self.bgImageView];
// 添加圆框
[self setupCircleBg];
// 光标
[self setupMarkerImageView];
// 添加跃动数字 及 提示语
[self setupJumpNOView];
}
return self;
}
2.添加圆框
- (void)setupCircleBg {
// 圆形路径
UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(self.width / 2, self.height / 2)
radius:(self.circelRadius - self.lineWidth) / 2
startAngle:degreesToRadians(self.startAngle)
endAngle:degreesToRadians(self.endAngle)
clockwise:YES];
// 底色
self.bottomLayer = [CAShapeLayer layer];
self.bottomLayer.frame = self.bounds;
self.bottomLayer.fillColor = [[UIColor clearColor] CGColor];
self.bottomLayer.strokeColor = [[UIColor colorWithRed:206.f / 256.f green:241.f / 256.f blue:227.f alpha:1.f] CGColor];
self.bottomLayer.opacity = 0.5;
self.bottomLayer.lineCap = kCALineCapRound;
self.bottomLayer.lineWidth = self.lineWidth;
self.bottomLayer.path = [path CGPath];
[self.layer addSublayer:self.bottomLayer];
// 240 是用整个弧度的角度之和 |-200| + 20 = 220
// [self createAnimationWithStartAngle:degreesToRadians(self.startAngle)
// endAngle:degreesToRadians(self.startAngle + 220 * 1)];
}
3.设置光标
- (void)setupMarkerImageView {
if (_markerImageView) {
return;
}
_markerImageView = [[UIImageView alloc] init];
_markerImageView.backgroundColor = [UIColor clearColor];
_markerImageView.layer.backgroundColor = [UIColor greenColor].CGColor;
_markerImageView.layer.shadowColor = [UIColor whiteColor].CGColor;
_markerImageView.layer.shadowOffset = CGSizeMake(0, 0);
_markerImageView.layer.shadowRadius = kMarkerRadius*0.5;
_markerImageView.layer.shadowOpacity = 1;
_markerImageView.layer.masksToBounds = NO;
self.markerImageView.layer.cornerRadius = self.markerImageView.frame.size.height / 2;
[self addSubview:self.markerImageView];
_markerImageView.frame = CGRectMake(-100, self.height, kMarkerRadius, kMarkerRadius);
}
4.添加跳跃文字及提示语
- (void)setupJumpNOView {
if (_showLable) {
return;
}
CGFloat width = self.circelRadius / 2 + 50;
CGFloat height = self.circelRadius / 2 - 50;
CGFloat xPixel = self.bgImageView.left + (self.bgImageView.width - width)*0.5;//self.circelRadius / 4;
CGFloat yPixel = self.circelRadius / 4;
CGRect labelFrame = CGRectMake(xPixel, yPixel, width, height);
_showLable = [[UILabel alloc] initWithFrame:labelFrame];
_showLable.backgroundColor = [UIColor clearColor];
_showLable.textColor = [UIColor greenColor];
_showLable.textAlignment = NSTextAlignmentCenter;
_showLable.font = [UIFont systemFontOfSize:100.f];
_showLable.text = [NSString stringWithFormat:@"%ld",jumpCurrentNO];
[self addSubview:_showLable]; // 提示语
_markedLabel = [[UILabel alloc] initWithFrame:CGRectMake(xPixel, CGRectGetMaxY(_showLable.frame), width, 30)];
_markedLabel.backgroundColor = [UIColor clearColor];
_markedLabel.textColor = [UIColor greenColor];
_markedLabel.textAlignment = NSTextAlignmentCenter;
_markedLabel.font = [UIFont systemFontOfSize:20.f];
_markedLabel.text = @"营养良好";
[self addSubview:_markedLabel];
}
5.动画相关
#pragma mark - Animation
- (void)createAnimationWithStartAngle:(CGFloat)startAngle endAngle:(CGFloat)endAngle { // 光标动画 //启动定时器
[_fastTimer setFireDate:[NSDate distantPast]]; // 设置动画属性
CAKeyframeAnimation *pathAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
pathAnimation.calculationMode = kCAAnimationPaced;
pathAnimation.fillMode = kCAFillModeForwards;
pathAnimation.removedOnCompletion = NO;
pathAnimation.duration = _percent * kTimerInterval;
pathAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
pathAnimation.repeatCount = 1; // 设置动画路径
CGMutablePathRef path = CGPathCreateMutable(); CGPathAddArc(path, NULL, self.width / 2, self.height / 2, (self.circelRadius - kMarkerRadius / 2) / 2, startAngle, endAngle, 0);
pathAnimation.path = path; CGPathRelease(path); [self.markerImageView.layer addAnimation:pathAnimation forKey:@"moveMarker"]; }
6.开始动画,确定百分比
- (void)refreshJumpNOFromNO:(NSString *)startNO toNO:(NSString *)toNO {
beginNO = 0;//[startNO integerValue];
jumpCurrentNO = 0;//[startNO integerValue];
endNO = [toNO integerValue];
_percent = endNO * 100 / MaxNumber;
NSInteger diffNum = endNO - beginNO;
if (diffNum <= 0) {
return;
} if (diffNum < 100) {
_intervalNum = 5;
} else if (diffNum < 300) {
_intervalNum = 15;
} else if (diffNum <= MaxNumber) {
_intervalNum = 10;
}
NSLog(@"数字间隔:%ld",_intervalNum);
//数字
[self setupJumpThings];
// 设置角度
NSInteger angle = 0;
NSInteger num = [toNO floatValue] - [startNO floatValue];
if (num < 200) {
angle = self.startAngle + 220 * (num / 200.0) / 5.0;
} else if (num < 350) {
angle = self.startAngle + 220 / 5.0 + (3 / 5.0 * 220) * (num - 200) / 150.0;
} else {
angle = self.startAngle + 220 / 5.0 * 4 + (220 / 5.0) * (num - 350) / 250.0;
}
//光标
[self createAnimationWithStartAngle:degreesToRadians(self.startAngle)
endAngle:degreesToRadians(angle)];
}
- (void)setBgImage:(UIImage *)bgImage {
_bgImage = bgImage; self.bgImageView.image = bgImage;
}
- (UIImageView *)bgImageView { if (nil == _bgImageView) {
_bgImageView = [[UIImageView alloc] init];
} return _bgImageView;
}
7.跃动数字
- (void)setupJumpThings {
animationTime = _percent * kTimerInterval;
self.fastTimer = [NSTimer timerWithTimeInterval:kTimerInterval*kFastProportion
target:self
selector:@selector(fastTimerAction)
userInfo:nil
repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:_fastTimer forMode:NSRunLoopCommonModes];
//时间间隔 = (总时间 - 快时间间隔*变化次数)/ 再次需要变化的次数
//快时间
NSInteger fastEndNO = endNO * kFastProportion;
NSInteger fastJump = fastEndNO/_intervalNum;
if (fastJump % _intervalNum) {
fastJump++;
fastEndNO += _intervalNum;
}
CGFloat fastTTime = fastJump*kTimerInterval*kFastProportion;
//剩余应跳动次数
NSInteger changNO = endNO - fastEndNO;
NSInteger endJump = changNO / _intervalNum + changNO % _intervalNum;
//慢时间间隔
NSTimeInterval slowInterval = (animationTime - fastTTime) / endJump;
self.slowTimer = [NSTimer timerWithTimeInterval:slowInterval
target:self
selector:@selector(slowTimerAction)
userInfo:nil
repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:_slowTimer forMode:NSRunLoopCommonModes];
[_fastTimer setFireDate:[NSDate distantFuture]];
[_slowTimer setFireDate:[NSDate distantFuture]];
}
8.定时器触发事件
#pragma mark 加速定时器触发事件
- (void)fastTimerAction {
if (jumpCurrentNO >= endNO) {
[self.fastTimer invalidate];
return;
} if (jumpCurrentNO >= endNO * kFastProportion) {
[self.fastTimer invalidate];
[self.slowTimer setFireDate:[NSDate distantPast]];
return;
}
[self commonTimerAction];
}
#pragma mark 减速定时器触发事件
- (void)slowTimerAction {
if (jumpCurrentNO >= endNO) {
[self.slowTimer invalidate];
return;
}
[self commonTimerAction];
} #pragma mark 计时器共性事件 - lable赋值 背景颜色及提示语变化
- (void)commonTimerAction {
if (jumpCurrentNO % 100 == 0 && jumpCurrentNO != 0) {
NSInteger colorIndex = jumpCurrentNO / 100;
dispatch_async(dispatch_get_main_queue(), ^{
if (self.TimerBlock) {
self.TimerBlock(colorIndex);
}
});
}
NSInteger changeValueBy = endNO - jumpCurrentNO;
if (changeValueBy/10 < 1) {
jumpCurrentNO++;
} else {
// NSInteger changeBy = changeValueBy / 10;
jumpCurrentNO += _intervalNum;
} _showLable.text = [NSString stringWithFormat:@"%ld",jumpCurrentNO];
if (jumpCurrentNO < 350) {
_markedLabel.text = @"营养太差";
} else if (jumpCurrentNO <= 550) {
_markedLabel.text = @"营养较差";
} else if (jumpCurrentNO <= 600) {
_markedLabel.text = @"营养中等";
} else if (jumpCurrentNO <= 650) {
_markedLabel.text = @"营养良好";
} else if (jumpCurrentNO <= 700) {
_markedLabel.text = @"营养优秀";
} else if (jumpCurrentNO <= 950) {
_markedLabel.text = @"营养较好";
}
}
二. 在所需的当前控制器里展示:
创建背景色
- (void)setupGradientView {
self.gradientView = [[ZLGradientView alloc] initWithFrame:self.view.bounds];
[self.view addSubview:self.gradientView];
}
2. 创建仪表盘
- (void)setupCircleView {
self.dashboardView = [[ZLDashboardView alloc] initWithFrame:CGRectMake(40.f, 70.f, SCREEN_WIDTH - 80.f, SCREEN_WIDTH - 80.f)];
self.dashboardView.bgImage = [UIImage imageNamed:@"backgroundImage"];
[self.view addSubview:self.dashboardView];
}
3. 添加触发动画的点击按钮
- (void)addActionButton {
UIButton *stareButton = [UIButton buttonWithType:UIButtonTypeCustom];
stareButton.frame = CGRectMake(10.f, self.dashboardView.bottom + 50.f, SCREEN_WIDTH - 20.f, 38.f);
[stareButton addTarget:self action:@selector(onStareButtonClick:) forControlEvents:UIControlEventTouchUpInside];
[stareButton setTitle:@"Start Animation" forState:UIControlStateNormal];
[stareButton setBackgroundColor:[UIColor lightGrayColor]];
stareButton.layer.masksToBounds = YES;
stareButton.layer.cornerRadius = 4.f;
[self.view addSubview:stareButton];
_clickBtn = stareButton;
}
4. 改变 Value
- (void)addSlideChnageValue {
CGFloat width = 280;
CGFloat height = 40;
CGFloat xPixel = (SCREEN_WIDTH - width) * 0.5;
CGFloat yPixel = CGRectGetMaxY(_clickBtn.frame) + 20;
CGRect slideFrame = CGRectMake(xPixel, yPixel, width, height);
UISlider *slider = [[UISlider alloc] initWithFrame:slideFrame];
slider.minimumValue = MinNumber;
slider.maximumValue = MaxNumber;
slider.minimumTrackTintColor = [UIColor colorWithRed:0.000 green:1.000 blue:0.502 alpha:1.000];
slider.maximumTrackTintColor = [UIColor colorWithWhite:0.800 alpha:1.000]; /**
* 注意这个属性:如果你没有设置滑块的图片,那个这个属性将只会改变已划过一段线条的颜色,不会改变滑块的颜色,如果你设置了滑块的图片,又设置了这个属性,那么滑块的图片将不显示,滑块的颜色会改变(IOS7)
*/
[slider setThumbImage:[UIImage imageNamed:@""] forState:UIControlStateNormal];
slider.thumbTintColor = [UIColor cyanColor];
[slider setValue:0.5 animated:YES];
[slider addTarget:self action:@selector(slideTap:)forControlEvents:UIControlEventValueChanged];
[self.view addSubview:slider];
_slider = slider;
}
- (void)slideTap:(UISlider *)sender {
CGFloat value = sender.value;
NSLog(@"%.f",value);
}
- (void)setupGradientView {
self.gradientView = [[ZLGradientView alloc] initWithFrame:self.view.bounds];
[self.view addSubview:self.gradientView];
}
- (void)setupCircleView {
self.dashboardView = [[ZLDashboardView alloc] initWithFrame:CGRectMake(40.f, 70.f, SCREEN_WIDTH - 80.f, SCREEN_WIDTH - 80.f)];
self.dashboardView.bgImage = [UIImage imageNamed:@"backgroundImage"];
[self.view addSubview:self.dashboardView];
}
- (void)onStareButtonClick:(UIButton *)sender {
if (sender.selected) {
[self.gradientView removeFromSuperview];
self.gradientView = nil;
[self.dashboardView removeFromSuperview];
self.dashboardView = nil;
[self setupGradientView];
[self setupCircleView];
[self.view bringSubviewToFront:self.clickBtn];
[self.view bringSubviewToFront:_slider];
}
sender.selected = YES;
CGFloat value = _slider.value;
NSString *startNO = [NSString stringWithFormat:@"%d", MinNumber];
NSString *toNO = [NSString stringWithFormat:@"%.f",value];//@"693"; 950
NSLog(@"endNO:%@",toNO);
[self.dashboardView refreshJumpNOFromNO:startNO toNO:toNO];
__block typeof(self)blockSelf = self; self.dashboardView.TimerBlock = ^(NSInteger index) {
[blockSelf.gradientView setUpBackGroundColorWithColorArrayIndex:index];
};
}
三、运行效果与文件截图
1、运行效果:

至此, 一个简单的示例完成. 界面性问题可以根据自己项目需求调整即可。
2、文件截图:
压缩文件截图:

项目内文件截图:

四、其他补充
界面性问题可以根据自己项目需求调整即可, 具体可参考代码, 项目能够直接运行!
注:本文著作权归作者,由demo大师发表,拒绝转载,转载需要作者授权
iOS仿支付宝芝麻信用仪表盘效果的更多相关文章
- 自定义View(三),仿支付宝芝麻信用自定义控件
仿支付宝的芝麻信用仪表盘 实现的效果 实现的功能: 指针和数字动态改变 背景动态变化 没了... 代码如下 MyCustomView.java package com.example.testcust ...
- iOS仿支付宝首页效果
代码地址如下:http://www.demodashi.com/demo/12776.html 首先看一下效果 状态栏红色是因为使用手机录屏的原因. 1.问题分析 1.导航栏A有两组控件,随着tabl ...
- iOS仿支付宝首页的刷新布局效果
代码地址如下:http://www.demodashi.com/demo/12753.html XYAlipayRefreshDemo 运行效果 动画效果分析 1.UI需要变动,向上滑动的时候,顶部部 ...
- iOS 仿支付宝密码支付
代码地址如下:http://www.demodashi.com/demo/11484.html 一.准备工作 xcode 主要实现输入密码的时候不可见 二.程序实现 实现思路怎样 在支付宝输入密码的时 ...
- canvas仿芝麻信用分仪表盘
这是一个仿支付宝芝麻信用分的一个canvas,其实就是一个动画仪表盘. 首先, 上原图: 这个是在下支付宝上的截图,分低各位见笑了.然后看下我用canvas实现的效果图: <canvas id= ...
- iOS-仿支付宝刮刮乐效果
概述 仿支付宝刮刮乐效果, 可以按照自己需求更改展示刮出来的效果的view(即刮开后刮刮乐效果展示) 详细 代码下载:http://www.demodashi.com/demo/10673.html ...
- [ios仿系列]仿支付宝手势解码
呀~.这么快就转到ios阵营了???.android还有那么多坑呢???为此我也仅仅能啃着馒头留下屈辱的眼泪了. . 本次因为开发公司产品的android版,继而ios版也负责一部分.当中一部分就是手 ...
- 仿支付宝/微信的password输入框效果GridPasswordView解析
仿支付宝/微信的password输入框效果GridPasswordView解析,把一些设置和一些关键的地方列了出来,方便大家使用,可能能够省一部分的时间,也算是自己的积累吧. 1.password框能 ...
- 微信小程序 - IOS 仿饿了么"我的",下拉橡皮筋效果
这个需求是在wepy交流群里有群友提到的. 一个小花样. 注册mixins /** * IOS专用 顶部下拉橡皮筋效果 * 安卓的Page在到达顶部的时候,不能继续下拉...略过 * * 效果见 饿了 ...
随机推荐
- SQL:(转)数据库中的锁机制(数据库中有哪些锁)
数据库中的锁机制 锁是网络数据库中的一个非常重要的概念,它主要用于多用户环境下保证数据库完整性和一致性.各种大型数 据库所采用的锁的基本理论是一致的,但在具体实现上各有差别.目前,大多数数据库管理系统 ...
- hdu3117之矩阵快速幂
Fibonacci Numbers Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others ...
- SCSI contrller的几种类型的区别
在VMware vSphere Web Client中, 可以为虚拟机添加一个新的SCSI controller, 选项中包含如下的类型, 那么他们有什么区别呢? 如何选择呢? BusLogic ...
- 日程管理app
背景: 普通的笔记本显然具有保存占用较大空间的弊端.而笔记类app又借助于虚拟按键输入,便利度稍逊.假设使用电脑,又产生了较大空间的弊端. 手段: 成熟的书写识别技术 方法: 一.专有的划分有制定格子 ...
- Android -- ViewPager、Fragment、状态保存、通信
工程架构 TabAFm到Tab ...
- 解决spark中遇到的数据倾斜问题
一. 数据倾斜的现象 多数task执行速度较快,少数task执行时间非常长,或者等待很长时间后提示你内存不足,执行失败. 二. 数据倾斜的原因 常见于各种shuffle操作,例如reduceByKey ...
- Terminix:基于 GTK3 的平铺式 Linux 终端模拟器
现在,你可以很容易的找到大量的 Linux 终端模拟器,每一个都可以给用户留下深刻的印象.但是,很多时候,我们会很难根据我们的喜好来找到一款心仪的日常使用的终端模拟器.这篇文章中,我们将会推荐一款叫做 ...
- Ubuntu 16.04 LTS安装好之后需要做的15件事
看到这篇文章说明你已经从老版本升级到 Ubuntu 16.04 或进行了全新安装,在安装好 Ubuntu 16.04 LTS 之后建议大家先做如下 15 件事.无论你是刚加入 Ubuntu 行列的新用 ...
- (转)Unity3D占用内存太大的解决方法
自:http://www.cnblogs.com/88999660/archive/2013/03/15/2961663.html 最近网友通过网站搜索Unity3D在手机及其他平台下占用内存太大. ...
- 在不重装系统的情况下撤底删除oracle数据库及oralce的相关软件
先从控制面板删除oracle的相关应用及数据库, 删除系统变量 ORACLE_OEM_CLASSPATH=%JAVA_HOME%\lib\ext\access-bridge-64.jar;%JAVA_ ...