xml地图|网站地图|网站标签 [设为首页] [加入收藏]

自己写顶部滚动标签栏,Guides的动画效果

来源:http://www.ccidsi.com 作者:集成经验 人气:113 发布时间:2020-03-22
摘要:点此下载源码下载:源码 (会随处修正,招待star。有限援救绚烂,平交易!) 点此下载源码下载:源码 (会四处更新,迎接star。有限扶助绚烂,公平买卖!) 好久没写博客了,前段

点此下载源码下载:源码(会随处修正,招待star。有限援救绚烂,平交易!)

点此下载源码下载:源码(会四处更新,迎接star。有限扶助绚烂,公平买卖!)

好久没写博客了,前段时间和煦参考了部分源码写了三个标签页,并把她传到了CocoaPods上。我们能够融合为一到花色中张开应用,也足以看看源码本人写四个越来越好的,也希望假使有啥样意见能够告诉本人,笔者会实行宏观。

图片 1city guides插图.jpg

图片 2City Guides App.jpg

和煦写了二种样式的德姆o,一种恍若乐乎云音乐的稳固的标签栏,一种是周边乐视网、博客园的可滚动的标签栏。一同首只是草草的写,后来经过师傅提醒寻思了下优化,唯有移动到十三分页面才会对ViewController举行加载,那样就算是很复杂的页面相当多互联网诉求数据加载应该也不会有卡顿的地方。

数字动态变化的卡通效果

本篇小说要兑现的动漫片效果如下。

图片 3ZFCityGuides-stats.gif

是因为生成gif帧动漫时间相当的短的主题素材,有部分动漫片效果并不曾显体面现出来。小编剖判一下上边的gif动漫效果。

本篇随笔最终有最后兑现的成效图。

从dribbble的设计员的作品中驾驭到City Guides上相当美丽的卡通片效果。惊叹设计员很棒的希图的同偶然候,小编也在心里探讨这么些动漫片是怎么落到实处的。于是从App Store上下载了应用程式,使用然后细心研究后便有了此篇随笔。

图片 4wait图片 5wait

浅析动漫
  1. 从上二个viewController踏入到StatsViewController,是一个动漫片转场。(本篇作品不详细讲授)

  2. 体现当前视图,视图是从底部滑入。在滑入步入的经过中,视图上的一些子视图动漫的变通(如:UILabel上的数字,CAGradientLayer的水彩等)。

  3. 时下视图加载完结,滚动视图。在滚动进程中,有的视图同不常间向两边移动慢慢消退或出现,有的视图向左逐步移动未有或现身,而有个别视图向右移动慢慢消散或现身。

  4. 子视图向左或许向右移动的进度中,部分子视图动态的改动。

City Guides中大致具备的分界面呈现与交互作用格局都是有动漫效果的。小编也就分几有的来落实动漫效果。

万一有想插足项目中使用的同学能够应用CocoaPods,具体运用自家放在github上了,迎接使用。也得以把github上的zip直接下载下来看使用模式。接下来简单介绍下完毕原理。

设计思路

本着地点的每一步举行稳步设计达成。

  1. 参见源码,不详细介绍。
  2. StatsViewController上是由叁个UIScrollView,从最底层滑入的动画片。
 CGRect offsetFrame = self.view.frame; offsetFrame.origin.y = self.view.frame.size.height; CGRect frame = self.view.frame; UIScrollView *scrollView = [UIScrollView new]; frame.origin.y = CGRectGetMaxY(self.navigationBarView.frame)   10; scrollView.delegate = self; [self.view addSubview:scrollView]; scrollView.frame = offsetFrame; [UIView animateWithDuration:1.5 delay:0.0 options:UIViewAnimationOptionCurveEaseInOut animations:^{ scrollView.frame = frame; } completion:^(BOOL finished) { }];

什么兑现UILabel数字的动态变化呢?

开源项目pop动漫帮大家落到实处了,作者来上课怎么着完结吗。封装完毕动漫的UILabel的章程。

#pragma mark - animationLabel method-animatedForLabel:(UILabel *)label forKey:(NSString *)key fromValue:fromValue toValue: toValue decimal:decimal{ POPAnimatableProperty *prop = [POPAnimatableProperty propertyWithName:key initializer:^(POPMutableAnimatableProperty *prop) { prop.readBlock = ^(id obj, CGFloat values[]) { }; prop.writeBlock = ^(id obj, const CGFloat values[]) { NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init]; formatter.numberStyle = NSNumberFormatterDecimalStyle; NSString *string = nil; //是否带有小数点 if  { string = [NSString stringWithFormat:@"%.1f",values[0]]; } else{ string = [formatter stringFromNumber:[NSNumber numberWithInt:values[0]]]; } if ([key isEqualToString:@"first"]) { int number = roundf(values[0]); for (int i = 0; i < number; i  ) { UIButton *button = [self.firstRainDropIcons objectAtIndex:i]; button.enabled = fromValue > toValue ? NO : YES; } } else if ([key isEqualToString:@"second"]){ int number = roundf(values[0]); for (int i = 0; i < number; i  ) { UIButton *button = [self.secondRainDropIcons objectAtIndex:i]; button.enabled = fromValue > toValue ? NO : YES; } } if (fromValue > toValue) { label.alpha = 0.5; } else{ label.alpha = 1.0; } label.text = string; }; // prop.threshold = 0.1; }]; POPBasicAnimation *anBasic = [POPBasicAnimation easeInEaseOutAnimation]; //动画属性 anBasic.property = prop; //自定义属性 anBasic.fromValue = @(fromValue); //从0开始 anBasic.toValue = @; // anBasic.duration = 1.5; //持续时间 anBasic.beginTime = CACurrentMediaTime()   0.1; //延迟0.1秒开始 [label pop_addAnimation:anBasic forKey:key];}

成立UILabel参预到当下视图中,完毕数值由0到238874变型。

 UILabel *animationLabel = [UILabel new]; animationLabel.text = @"0"; animationLabel.textAlignment = NSTextAlignmentCenter; animationLabel.font = [UIFont fontWithName:TitleFontName size:65.0]; animationLabel.textColor = kTextlightGrayColor; animationLabel.frame = CGRectMake(0, 200, 300, 90); [self.view addSubview:animationLabel]; [self animatedForLabel:animationLabel forKey:@"animation" fromValue:0 toValue: 238874 decimal:NO];

图片 6digitAnimation.gif

3.自定义封装UIScrollView上的子视图。(详细讲授这一部分的笔触)

我的筹算思路是:每一行是三个ZFSliderAnimationView。ZFSliderAnimationView中,有一个或五个ZFSliderAnimationItem组成。

ZFSliderAnimationItem的定义,如下:

@interface ZFSliderAnimationItem : NSObject@property (nonatomic,strong) NSString *headerTitle; //标题@property (nonatomic,strong) NSString *content; //中间内容@property (nonatomic,strong) NSString *footerTitle;//底部标题@property (nonatomic,strong) NSString *detailContent;//详细内容@property (nonatomic,strong) UIColor *itemBackgroundColor;//背景颜色@property (nonatomic,assign) BOOL showDetail;//是否显示详细按钮@property (nonatomic,assign) BOOL showAnimated;//是否动画@end

创造ZFSliderAnimationView能够定义七个连串如下:

typedef NS_ENUM(NSInteger, ZFSliderStyle) { //一般类型 包括headTitle content footer detail ZFSliderStyleNormal, //可自定义单个视图 ZFSliderStyleView, //多个normal组成 ZFSliderStyleMultiple, //多个customView组成 ZFSliderStyleMultipleView,};

对应复杂的自定义视图,作为单身一个View传人到ZFSliderAnimationView中。在本篇小说中,ZFRainDropView和ZFGradientView都是自定义的视图传人到ZFSliderAnimationView中。那样的功利防止ZFSliderAnimationView类代码显得非常的重叠,并且耦合性裁减。只需求创建自个儿所企望的UIView传人就可以。

ZFSliderAnimationView根据style初始化:

-initSubViewsWithStyle:(ZFSliderStyle)style{ switch  { case ZFSliderStyleNormal: if (self.items) { [self addItemViewOnContentView:self.items[0] withCustomView:nil]; } break; case ZFSliderStyleView: if (self.customViews && self.items) { UIView *customView = [UIView new]; if (self.customViews.count > 0) { customView = self.customViews[0]; } [self addItemViewOnContentView:self.items[0] withCustomView:customView]; } break; case ZFSliderStyleMultiple: { NSMutableArray *itemWidthArray = [self countWidthForItems:self.items]; CGFloat orignX = 0; for (int i =0 ; i < self.items.count; i  ) { orignX  = i ? [itemWidthArray[i -1] floatValue]   gapWidth : gapWidth; [self addItemOnContentViewAtIndex:i animationItem:self.items[i] orignX:orignX withItemWidth:[itemWidthArray[i] floatValue]]; } } break; default: break; } }

在滚动UIScrollView时,每一种item是向左依旧向右移动。ZFSliderAnimationView的卡通类型定义如下:

typedef NS_ENUM(NSInteger, ZFSliderItemAnimation) { ZFSliderItemAnimationLeft,//向左移动 ZFSliderItemAnimationRight,//向右移动 ZFSliderItemAnimationBoth//分别向两侧移动};@property (nonatomic,assign) ZFSliderItemAnimation animation;

接下来依据ZFSliderItemAnimation的值完毕种种item移动:

-updateAnimationView:percent animated:animated{ if (self.animation == ZFSliderItemAnimationLeft) { //动态变化子视图内容 第4步 [self showItemAnimation:percent animated:animated]; if (percent < 0) { percent = 0; } if (percent >1) { percent =1; } percent = percent * 0.5; UIView *contentView = self.subviews[0]; CGRect frame = contentView.frame; //向左移动 frame.origin.x = (gapWidth - contentView.frame.size.width * percent); contentView.frame = frame; } else if (self.animation == ZFSliderItemAnimationRight){ //动态变化子视图内容 第4步 [self showItemAnimation:percent animated:animated]; if (percent < 0) { percent = 0; } if (percent >1) { percent =1; } percent = percent * 0.5; UIView *contentView = self.subviews[0]; CGRect frame = contentView.frame; //向右移动 frame.origin.x = (gapWidth   contentView.frame.size.width * percent); contentView.frame = frame; } else if (self.animation == ZFSliderItemAnimationBoth){ //动态变化子视图内容 第4步 [self showItemAnimation:percent animated:animated]; NSAssert(self.items.count > 1, @"Count can't less than two"); //此处只演示2个items if (percent < 0) { percent = 0; } if (percent >1) { percent =1; } percent = percent * 0.5; CGRect leftFrame = self.subviews[0].frame; CGRect rightFrame = self.subviews[1].frame; //左侧item 向左移动 leftFrame.origin.x = (gapWidth - self.subviews[0].frame.size.width * percent); self.subviews[0].frame = leftFrame; //右侧item 向右移动 rightFrame.origin.x = (self.subviews[0].frame.size.width   gapWidth *2   self.subviews[1].frame.size.width * percent); self.subviews[1].frame = rightFrame; } //改变透明度 self.alpha = 1 - percent *2;}

在StatsViewController中,滚动UIScrollView由UIScrollView的顶端和尾巴部分的偏移量鲜明当前哪位视图移动的比重。

#pragma mark - UIScrollViewDelegate-scrollViewDidScroll:(UIScrollView *)scrollView{ for (UIView *subView in _subViewsArray) { BOOL bContainedTopView = CGRectContainsPoint(subView.frame,scrollView.contentOffset); CGPoint point = scrollView.contentOffset; point.y  = (self.view.frame.size.height - CGRectGetMaxY(self.navigationBarView.frame) -10); BOOL bContainedBottomView = CGRectContainsPoint(subView.frame,point); ZFSliderAnimationView *sliderView = (ZFSliderAnimationView *)subView; UIView *middleView = nil; //自定义的view if (sliderView.style == ZFSliderStyleView || sliderView.style == ZFSliderStyleMultipleView) { middleView = sliderView.customView; } else{ middleView = sliderView.contentLabel; } //顶部视图的移动百分比 if (bContainedTopView) { CGFloat percent = (scrollView.contentOffset.y - subView.frame.origin.y - middleView.frame.origin.y) /middleView.frame.size.height; //更新动画视图 [sliderView updateAnimationView:percent animated:YES]; continue; } //底部视图的移动百分比 else if (bContainedBottomView){ CGFloat percent = (point.y - subView.frame.origin.y - middleView.frame.origin.y) /middleView.frame.size.height; //更新动画视图 [sliderView updateAnimationView:1- percent animated:YES]; continue; } else{ //不更新动画视图 [sliderView updateAnimationView:0.0 animated:NO]; } }}

4.动态变化子视图内容。

-showItemAnimation:percent animated:animated{ if (percent > 0 && percent < 1) { for (int i = 0; i < self.subItemViews.count; i  ) { NSArray *subViews = (self.subItemViews[i]).subviews; //ZFRainDropView 实现动画 if ([[subViews[1] class] isSubclassOfClass:[ZFRainDropView class]]) { ZFRainDropView *rainDropView = subViews[1]; if (!rainDropView.digitAnimated) { return; } [rainDropView increaseNumber:NO animated:animated]; rainDropView.digitAnimated = NO; return; } //ZFGradientView 实现动画 else if([[subViews[1] class] isSubclassOfClass:[ZFGradientView class]]){ ZFGradientView *gradientView = subViews[1]; if (!gradientView.digitAnimated) { return; } [gradientView increaseNumber:NO animated:animated]; gradientView.digitAnimated = NO; return; } for (UIView *subView in subViews) { if ([subView isKindOfClass:[UILabel class]]) { //无法用key 区分,根据子视图上的UILabel实现 ZFSliderAnimationItem *item = self.items[i]; if (!item.showAnimated) { return; } if ([item.content rangeOfString:@"."].length > 0) { [self animatedForLabel:(UILabel *)subView forKey:self.animationKey fromValue:[item.content floatValue] toValue:0 decimal:YES]; } else{ [self animatedForLabel:(UILabel *)subView forKey:self.animationKey fromValue:[item.content floatValue] toValue:0 decimal:NO]; } item.showAnimated = NO; } } } } else if(percent < 0){ for (int i = 0; i < self.subItemViews.count; i  ) { NSArray *subViews = (self.subItemViews[i]).subviews; if ([[subViews[1] class] isSubclassOfClass:[ZFRainDropView class]]) { //ZFRainDropView 实现动画 ZFRainDropView *rainDropView = subViews[1]; if (!rainDropView.digitAnimated) { [rainDropView increaseNumber:YES animated:animated]; rainDropView.digitAnimated = YES; } return; } else if([[subViews[1] class] isSubclassOfClass:[ZFGradientView class]]){ ZFGradientView *gradientView = subViews[1]; if (!gradientView.digitAnimated) { [gradientView increaseNumber:YES animated:animated]; gradientView.digitAnimated = YES; } return; } for (UIView *subView in subViews) { if ([subView isKindOfClass:[UILabel class]]) { UILabel *contentLabel = (UILabel *)subView; //无法用key 区分,根据子视图上的UILabel实现 ZFSliderAnimationItem *item = self.items[i]; if (!item.showAnimated) { if ([item.content rangeOfString:@"."].length > 0) { [self animatedForLabel:contentLabel forKey:self.animationKey fromValue:0 toValue:[item.content floatValue] decimal:YES]; } else{ [self animatedForLabel:contentLabel forKey:self.animationKey fromValue:0 toValue:[item.content floatValue] decimal:NO]; } item.showAnimated = YES; } } } } } else if(percent == 0){ if (!animated) { return; } for (int i = 0; i < self.subItemViews.count; i  ) { NSArray *subViews = (self.subItemViews[i]).subviews; if ([[subViews[1] class] isSubclassOfClass:[ZFRainDropView class]]) { //ZFRainDropView 实现动画 ZFRainDropView *rainDropView = subViews[1]; [rainDropView increaseNumber:NO animated:animated]; return; } else if([[subViews[1] class] isSubclassOfClass:[ZFGradientView class]]){ ZFGradientView *gradientView = subViews[1]; [gradientView increaseNumber:NO animated:animated]; return; } for (UIView *subView in subViews) { if ([subView isKindOfClass:[UILabel class]]) { //无法用key 区分,根据子视图上的UILabel实现 ZFSliderAnimationItem *item = self.items[i]; if ([item.content rangeOfString:@"."].length > 0) { [self animatedForLabel:(UILabel *)subView forKey:self.animationKey fromValue:0 toValue:[item.content floatValue] decimal:YES]; } else{ [self animatedForLabel:(UILabel *)subView forKey:self.animationKey fromValue:0 toValue:[item.content floatValue] decimal:NO]; } } } } } }

提起底效果图:

图片 7ZFCityGuides-stats1.gif

这一篇要促成的动漫片效果如下:

轻易易行的说,顶端的标签栏是UIScrollView,底下也是二个UIScrollView,将多个ViewController.view初阶化参加到下边ScrollView中的合适岗位,何况与最上部的标签栏相关联,而且给地方的标签栏扩张点击事件调节下局地的ScrollView能够移动到合适的任务就能够了!

结束语

在本篇演示的剧情中,还某个是关于渐变颜色的取值。等分插值取值,动态完结颜色的转换。详细的参阅源码中的ZFGradientView。

扩充阅读:

干货种类之完毕City Guides的卡通片效果

率先个卡通效果:

感到其实没什么难题,相比较须求观念的得以落成应有正是最上部标签栏随下边ScrollView的滑行,富含字体颜色,下划线移动。小编就对这一某些开展介绍,对别之处感兴趣的同学能够团结把源码下载下来看看。

图片 8ZFCityGuides-One.gif

此间先上代码,先上最上端标签栏的初阶化方法。这一片段比较麻烦,分明能够简化代码,时间有一些紧就没做了。

第叁个卡通效果:

- addScrollHeader:(NSArray *)titleArray{ self.headerView.frame = CGRectMake(0, 0, self.width, self.buttonHeight); self.headerView.contentSize = CGSizeMake(self.buttonWidth*titleArray.count, self.buttonHeight); [self addSubview:self.headerView]; for (NSInteger index = 0; index < titleArray.count; index  ) { _titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(self.buttonWidth*index, 0, self.buttonWidth, self.buttonHeight)]; _titleLabel.textColor = [UIColor blackColor]; _titleLabel.text = titleArray[index]; _titleLabel.textAlignment = NSTextAlignmentCenter; _titleLabel.adjustsFontSizeToFitWidth = YES; [self.headerView addSubview:_titleLabel]; _segmentBtn = [[UIButton alloc] initWithFrame:CGRectMake(self.buttonWidth*index, 0, self.buttonWidth, self.buttonHeight)]; _segmentBtn.tag = index; [_segmentBtn setBackgroundColor:[UIColor clearColor]]; [_segmentBtn addTarget:self action:@selector(btnClick:) forControlEvents:UIControlEventTouchUpInside]; [self.headerView addSubview:_segmentBtn]; } self.headerSelectedSuperView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.buttonWidth, self.buttonHeight)]; [self.headerView addSubview:self.headerSelectedSuperView]; self.headerSelectedView.frame =CGRectMake(0, 0, self.buttonWidth, self.buttonHeight); self.headerSelectedView.contentSize = CGSizeMake(self.buttonWidth*titleArray.count, self.buttonHeight); [self.headerSelectedSuperView addSubview:self.headerSelectedView]; for (NSInteger index = 0; index < titleArray.count; index  ) { _titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(self.buttonWidth*index, 0, self.buttonWidth, self.buttonHeight)]; _titleLabel.textColor = [UIColor blueColor]; _titleLabel.text = titleArray[index]; _titleLabel.textAlignment = NSTextAlignmentCenter; _titleLabel.adjustsFontSizeToFitWidth = YES; [self.headerSelectedView addSubview:_titleLabel]; } UIImageView *bottomLine = [[UIImageView alloc] initWithFrame:CGRectMake(0, self.headerSelectedView.contentSize.height - self.lineHeight, self.headerSelectedView.contentSize.width, self.lineHeight)]; bottomLine.backgroundColor = [UIColor blueColor]; [self.headerSelectedView addSubview:bottomLine];}

图片 9ZFCityGuides-two.gif

这里的落到实处首要分为五个步骤,一开头在顶端增加三个self.headerView,那是三个UIScrollView,他是标签栏视图的最终面部分,所以要求首先add上去。在self.headerView我们会助长若干个UILabel,那多少个UILabel正是没选中时的竹签样子,正是上文gif中青古铜色的标签。然后再增加若干个透明的Button方便增加点击事件,当然也得以用手势这里随便。

本文由68399皇家赌场发布于集成经验,转载请注明出处:自己写顶部滚动标签栏,Guides的动画效果

关键词: 68399皇家赌场 干货 效果 动画

最火资讯