几句代码快捷集成自定义转场效果 全手势驱动

2019-10-04 12:02栏目:编程学习

不久前项目中直播间里增多了实时弹幕要求,本篇记录一下兑现过程。

写在前方

在简书写完第一篇的自定义转场小说后,已经非常久未有碰过转场了,究竟在铺子,作用完成才是最重视的,那个转场的动作效果,只可以是神来之笔,不太轻易被注重,不过自身的率先篇文章照旧广大人的喜欢和座谈,很两个人还建议些建议,非常多谢我们,这是本身首先篇小说的地方自定义转场动画,里面含有了有的转场的基础知识,那篇文章笔者就不再探究这么些基础知识了。为啥会有那第二篇小说,首要缘由有如下几点:

1、能否更简约?当自家十分久未有动用转场的时候,再次来行使它,认为照旧比较繁琐,有一大堆记不住的漫漫代理方法,都要去copy,长长的代理方法也把调节器弄得有一点点乱,固然苹果已经将全方位进程丰裕解耦了,小编在想,假使能大约的一两句话就能够融会转场效果多好,或许通过接二连三和复写一几个形式就会轻便实现和谐的转场效果,不供给关切转场逻辑,只需关心卡通逻辑

2、闪烁和平板?在率先篇作品中有人提到的一些的bug,比方小圆点扩散效果,假诺手势在半路撤消,不会有撤除动画,特别刚烈,何况会有闪光的bug,我在想能还是无法化解那五个难题,性冷淡接受不了oo,作者明天找到了贰个比较好的格局来解决难题,原理和对照图会在背后给出

3、能还是不可能多增添一些效果?所以作者把温馨写的效果与利益封装,再仿效网络一些效应,总过加多了将近十多个效用

4、手势万岁!任何作用自身都想能够手势驱动

先看一下最后做出来的职能

作用图(图相当多,请手提式有线话机客商谨严,可下载demo真机运转作效果果越来越好)

截图中,右上角的switch开关代表push和present,全数功效都补帮手势,小编就不一一演示了

1、CircleSpreadTransition 小圆点扩散

图片 1CircleSpreadTransition.gif

2、MagicMoveTransition 奇妙移动

图片 2MagicMoveTransition1.gif图片 3MagicMoveTransition2.gif

3、XWDrawerAnimator 抽屉效果,仿照QQ和天猫

图片 4XWDrawerAnimator1.gif图片 5XWDrawerAnimator2.gif

4、XWCoolAnimator 自定义一些功效

图片 6XWCoolAnimator2.gif图片 7XWCoolAnimator1.gif图片 8XWCoolAnimator3.gif图片 9XWCoolAnimator4.gif图片 10XWCoolAnimator5.gif图片 11XWCoolAnimator6.gif图片 12XWCoolAnimator7.gif

5、XWFilterAnimator 通过CIFilter滤镜自定义一些功效,请在真机上运维

图片 13XWFilterAnimator1.gif图片 14XWFilterAnimator6.gif图片 15XWFilterAnimator5.gif图片 16XWFilterAnimator4.gif图片 17XWFilterAnimator3.gif图片 18XWFilterAnimator2.gif图片 19XWFilterAnimator8.gif图片 20XWFilterAnimator7.gif

图片 21功效图.gif基本的落实逻辑,客商端在接到到一条弹幕新闻之后,依据新闻生成对应的弹幕样式,加多到显示屏上,然后做轻便的位移动画,当移动超过显示屏范围之后自动移除,幸免内部存款和储蓄器持续增高。有了一个不难的思路,下边就起来入手用代码来兑现。

如何选取

1、git地址:几句代码急速集成自定义转场效果 全手势驱动,clone后将整个XWTranstion文件夹导入工程

2、导入UINavigationController XWTransition.h或者UIViewController XWTransition.h八个分类

3、选用你需求的效果器实行依据开始化方法开展初叶化,比如上面包车型客车小圆点扩散,最初化钦命初始圆心和半径

XWCircleSpreadAnimator *animator = [XWCircleSpreadAnimator xw_animatorWithStartCenter:self.button.center radius:20]; 

4、通过开头化的效果器转场,依据分类提供的法子实行push恐怕present,就完了了!

[self.navigationController xw_pushViewController:toVC withAnimator:animator];或者[self xw_presentViewController:toVC withAnimator:animator];

首先定义二个弹幕容器,实现接收弹幕音讯方法,使容器能够管理服务再次来到的弹幕音讯

手势驱动

1、在UIViewController XWTransition.h分类中提供了多少个主意,用来注册手势驱动,在viewDidLoad的时候调用注册手势就能够了,详见demo,注意制止循环援引,手势帮忙边缘属性

/** * 注册to手势(push或者Present手势) * * @param direction 手势方向 * @param tansitionConfig 手势触发的block,block中需要包含你的push或者Present的逻辑代码,注意避免循环引用问题 * @param edgeSpacing 手势触发的边缘距离,该值为0,表示在整个控制器视图上都有效,否者这在边缘的edgeSpacing之类有效 */- xw_registerToInteractiveTransitionWithDirection:(XWInteractiveTransitionGestureDirection)direction transitonBlock:(dispatch_block_t)tansitionConfig edgeSpacing:edgeSpacing;/** * 注册back手势(pop或者dismiss手势) * * @param direction 手势方向 * @param tansitionConfig 手势触发的block,block中需要包含你的pop或者dismiss的逻辑代码,注意避免循环引用问题 * @param edgeSpacing 手势触发的边缘距离,该值为0,表示在整个控制器视图上都有效,否者这在边缘的edgeSpacing之类有效 */- xw_registerBackInteractiveTransitionWithDirection:(XWInteractiveTransitionGestureDirection)direction transitonBlock:(dispatch_block_t)tansitionConfig edgeSpacing:edgeSpacing;

2、事例代码

 __weak typeofweakSelf = self; //注册一个全屏的back转场 [self xw_registerBackInteractiveTransitionWithDirection:XWInteractiveTransitionGestureDirectionDown transitonBlock:^{ //pop或者dismiss操作 [weakSelf xw_transiton]; } edgeSpacing:0];
@interface DSHBarrageView : UIView@property (strong ,nonatomic) CADisplayLink *timer; // 用来实现弹幕的平移动画- destroy; // 销毁定时器- receivedMessage:message; // 收到一条弹幕消息@end

至于奇妙移动作效果果

1、在UIViewController XWTransition.h分类中提供了八个关于奇妙移动的办法,你须要在转场前和转场后的调控器中分头登记美妙移动前后的视图(用来报告玄妙移动前后的frame),然后通过美妙移动作效果果器就能够触发巧妙移动转场了

/** * 注册神奇移动起始视图 * * @param group 神奇移动起始视图数组 */- xw_addMagicMoveStartViewGroup:(NSArray<UIView *> *)group;/** * 注册神奇移动终止视图 * * @param group 神奇移动终止视图数组,注意起始视图数组和终止视图数组的视图需要一一对应才能有正确的效果 */- xw_addMagicMoveEndViewGroup:(NSArray<UIView *> *)group;/** * 改变神奇移动起始视图,因为在back的时候,有可能不需要再回到原来起始的位置,需要去一个新的视图位置,所以在back前需要调用该方法改变起始视图数组 * * @param group 新的起始视图数组 */- xw_changeMagicMoveStartViewGroup:(NSArray<UIView *> *)group;

2、事例代码

 //fromVC转场前控制器中注册神奇移动前视图 [self xw_addMagicMoveStartViewGroup:@[imgView, view1, view2]]; //toVC转场后控制器中注册神奇移动前视图 [self xw_addMagicMoveEndViewGroup:@[imgView, view1, view2]]; //初始化神奇移动效果器转场 XWMagicMoveToController *toVC = [XWMagicMoveToController new]; [self xw_presentViewController:toVC withAnimator:animator]; 

3、转场中存在cell,由于在转场进度中cell还从未加载,所以不能登记cell为奇妙移动视图,这种情景要求生产三个零时视图注册为转场视图来利用,具体请参见demo中的九宫格例子

4、关于提供的imageMode属性:在奇妙移动中,有个难题,正是活动中的有的时候视图日常都以用截图大法截图而来的,然而只要从从小图产生大图,由于截图为小图截图,变大进度中会有模糊的场景,固然设置了该属性,笔者会对美妙移动视图中的包涵了image的视图举办检查测试,就算能质量评定到image则一向取image,而不截图,就能够化解模糊的难题,代码如下

- _xw_snapshotView:view{ CALayer *layer = view.layer; UIView *snapView = [UIView new]; snapView.frame = view.frame; BOOL imgMode = [objc_getAssociatedObject(view, &kXWMagicMovePropertyInViewKey) boolValue] || _imageMode; UIImage *img = nil; if  {//如果开启imgMode,优先直接获取图片,避免截图时时从小到大造成的模糊 if ([view isKindOfClass:[UIImageView class]]) {//取imageView中的image img = [(UIImageView *)view image]; }else if ([view isKindOfClass:[UIButton class]]){//取button中的image img = [(UIButton *)view currentImage]; } if (!img && [view isKindOfClass:[UIView class]]) {//没取到尝试取content img = [UIImage imageWithCGImage:(__bridge CGImageRef)view.layer.contents]; } } //若都没有取到,则截图 if  { UIGraphicsBeginImageContextWithOptions(layer.bounds.size, layer.opaque, 0); CGContextRef context = UIGraphicsGetCurrentContext(); [layer renderInContext:context]; img = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); } snapView.layer.contents = (__bridge id)img.CGImage; return snapView;}

实现

有关抽屉效果的全屏拖动

1、抽屉效果由于挂号的手势都是在调节器的的视图上,假如做QQ设置分界面包车型客车作用,不容许在toVC之外点击和拖动能够back,作者的思路是会在toVC未有掩瞒的区域增进贰个透明视图,给透明视图加上点击和拖入手势,具体代码如下

//首先需要设置点击和拖动的back操作,block中应该包含你的dismiss或者pop逻辑/** * 开启边缘(就是屏幕除开toView所占用的部分)back手势和边缘点击返回效果,类似于QQ设置界面的返回效果 * * @param backConfig 返回操作,您的dismiss或者pop操作 */- xw_enableEdgeGestureAndBackTapWithConfig:(dispatch_block_t)backConfig;//添加全屏手势代码如下/** * 添加全局手势和点击视图 */- _xw_addFullGestureAndTapBackViewInContainerView:containerView toView:toView distance:distance{ CGFloat width = _vertical ? containerView.frame.size.width : containerView.frame.size.width - fabs; CGFloat height = _vertical ? containerView.frame.size.height - fabs : containerView.frame.size.height; //如果toVC是全屏铺满则无需添加全局手势,直接使用toVC的view的手势就好了 if (width == 0 || height == 0)return; if (!_backConfig) return; //如果toView注册过手势,我们直接获取这个手势 NSArray<UIGestureRecognizer *> *gestures = toView.gestureRecognizers; __block id target = nil; [gestures enumerateObjectsUsingBlock:^(UIGestureRecognizer * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { NSString *panType = objc_getAssociatedObject(obj, "xw_interactivePanKey"); if ([panType isEqualToString:@"xw_interactiveBackPan"] && obj.delegate) { target = obj.delegate; *stop = YES; } }]; CGFloat x = _vertical || _direction == XWDrawerAnimatorDirectionRight ? 0 : -distance; CGFloat y = !_vertical || _direction == XWDrawerAnimatorDirectionBottom ? 0 : -distance; UIControl *gestureView = [UIControl new]; //添加点击事件 [gestureView addTarget:self action:@selector(_xw_backConfig) forControlEvents:UIControlEventTouchUpInside]; gestureView.frame = CGRectMake(x, y, width, height); gestureView.backgroundColor = [UIColor clearColor]; //第一种情况,toView已经添加了返回手势,我们直接拿到该手势的target和action if  { //给containerView添加全局手势 UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:target action:NSSelectorFromString(@"_xw_handleGesture:")]; [containerView addGestureRecognizer:pan]; }else{ //第二种情况,toView没有添加手势,我们需要创建一个 __weak typeofweakSelf = self; XWInteractiveTransition *backTransition = [XWInteractiveTransition xw_interactiveTransitionWithDirection:(XWInteractiveTransitionGestureDirection)_direction config:^{ weakSelf.backConfig(); } edgeSpacing:0]; backTransition.panRatioBaseValue = _vertical ? containerView.frame.size.height : containerView.frame.size.width; [backTransition xw_addPanGestureForView:gestureView to:NO];// [self xw_setBackInteractiveTransition:backTransition]; [self setValue:backTransition forKey:@"backTransition"]; } [containerView addSubview:gestureView];}
@implementation DSHBarrageView// 收到一条弹幕消息- receivedMessage:message; { UILabel *cell = [[UILabel alloc] init]; cell.font = [UIFont systemFontOfSize:14]; cell.textColor = [UIColor whiteColor]; cell.backgroundColor = [UIColor blackColor]; cell.textAlignment = NSTextAlignmentCenter; cell.text = [NSString stringWithFormat:@"弹幕消息:%@" ,message]; [self addSubview:cell]; [cell sizeToFit]; CGRect frame = cell.frame; frame.origin.x = self.frame.size.width; frame.origin.y = 44.f; frame.size.width = 100.f; cell.frame = frame; if  { // 当接收到弹幕消息后开启定时器 _timer = [CADisplayLink displayLinkWithTarget:self selector:@selector]; [_timer addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes]; }}- update { NSInteger cellCount = 0; for (UILabel *cell in self.subviews) { if ([cell isKindOfClass:[UILabel class]]) { CGRect frame = cell.frame; frame.origin.x -= 1.f; cell.frame = frame; if (CGRectGetMaxX <= 0) { [cell removeFromSuperview]; // 当超出屏幕时自动移除 } else { cellCount   ; } } } if (cellCount <= 0) { [self destroy]; // 检测到没有弹幕时自动销毁定时器 }}- destroy; { [_timer invalidate]; _timer = nil;}- hitTest:point withEvent:(UIEvent *)event { UIView *view = [super hitTest:point withEvent:event]; if (view == self) { return nil; } return view;}@end

焚林而猎动画猛烈

1、先看小圆点效果的事例,后边是杀鸡取卵前写的,前边是明日的

未解决

图片 22小圆点未张开timer.gif

解决后

图片 23小圆开启timer.gif

2、难点由来:在手势甘休后该意义不会动画的连结到成功大概战败,而是整个转场进程会一直update到0只怕1,就木有动画了

3、化解:在手指放手的时候,作者会开启二个CADisplayLink来不断的刷新整个转场进程到1大概0,来到达动画的作用,具体代码如下

case UIGestureRecognizerStateEnded:{//转场结束后 //判断是否需要timer if (!_timerEable) { _percent >= 0.5 ? [self _xw_finish] : [self _xw_cancle]; return; } //判断此时是否已经转场完成,大于1或者小于0 BOOL canEnd = [self _xw_canEndInteractiveTransitionWithPercent:_percent]; if  return; //开启timer [self _xw_setEndAnimationTimerWithPercent:_percent]; //设置开启timer- _xw_setEndAnimationTimerWithPercent:percent{ _percent = percent; //根据失败还是成功设置刷新间隔 if (percent > 0.5) { _timeDis = (1 - percent) / ((1 - percent) * 60); }else{ _timeDis = percent / (percent * 60); } //开启timer [self _xw_startTimer];}//开启timer- _xw_startTimer{ if  { return; } _timer = [CADisplayLink displayLinkWithTarget:self selector:@selector(_xw_timerEvent)]; [_timer addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];}//timer 事件- _xw_timerEvent{ if (_percent > 0.5) { _percent  = _timeDis; }else{ _percent -= _timeDis; } //通过timer不断刷新转场进度,达到动画效果 [self _xw_updatingWithPercent:_percent]; //判断进度是否达到0和1,达到则结束timer,结束转场 BOOL canEnd = [self _xw_canEndInteractiveTransitionWithPercent:_percent]; if  { [self _xw_stopTimer]; }}

此间早就轻巧的贯彻了一条弹幕从创设到活动再到销毁的全体进度,在ViewController.m达成以下代码,运营看一下成效。

减轻闪烁难点

1、闪烁原因:在不采纳UIView的动画block时,大家平素为layer增加一个CAAnimtion,此时会先安装modelLayer为转场成功的状态,举个例子小圆点效果会设置path为大圆的path,不过纵然转场退步,presentLayer仍旧会先成为modelLayer设置的打响值,然后动画才截止,走我们的转场失利逻辑,所以就能够闪烁

2、消除:笔者把手势更改的有些第一状态通过代理传出来,在手势截止前,大家借使检查到倒闭,能够先将modelLayer的值标识为失败时候的值,也正是开始值,就一挥而就了该难题

3、事例代码

//手势转场时的代理事件,animator默认为为其手势的代理,复写对应的代理事件可处理一些手势失败闪烁的情况@protocol XWInteractiveTransitionDelegate <NSObject>@optional/**手势转场即将开始时调用*/- xw_interactiveTransitionWillBegin:(XWInteractiveTransition *)interactiveTransition;/**手势转场中调用*/- xw_interactiveTransition:(XWInteractiveTransition *)interactiveTransition isUpdating:percent;/**如果开始了转场手势timer,会在松开手指,timer开始的时候调用*/- xw_interactiveTransitionWillBeginTimerAnimation:(XWInteractiveTransition *)interactiveTransition;/**手势转场结束的时候调用*/- xw_interactiveTransition:(XWInteractiveTransition *)interactiveTransition willEndWithSuccessFlag:flag percent:percent;@end//我在小圆点扩散效果中处理的如下- xw_interactiveTransition:(XWInteractiveTransition *)interactiveTransition willEndWithSuccessFlag:flag percent:percent{ if  { //防止失败后的闪烁,如果失败将遮罩的path设置为其实的小圆path _maskLayer.path = _startPath.CGPath; } _containerView.userInteractionEnabled = YES;}
#import "ViewController.h"#import "DSHBarrageView.h"@interface ViewController ()@property (strong ,nonatomic) DSHBarrageView *barrageView;@end@implementation ViewController- viewDidLoad { [super viewDidLoad]; _barrageView = [[DSHBarrageView alloc] initWithFrame:[UIScreen mainScreen].bounds]; [self.view addSubview:_barrageView];}- touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { static NSInteger index = 0; index   ; [_barrageView receivedMessage:@];}@end

关于coolTransiton

1、直接通过枚举伊始化就有曾经集成的局部机能,具体如下:

typedef NS_ENUM(NSUInteger, XWCoolTransitionAnimatorType){ //全屏翻页 XWCoolTransitionAnimatorTypePageFlip, //中间翻页 XWCoolTransitionAnimatorTypePageMiddleFlipFromLeft, XWCoolTransitionAnimatorTypePageMiddleFlipFromRight, XWCoolTransitionAnimatorTypePageMiddleFlipFromTop, XWCoolTransitionAnimatorTypePageMiddleFlipFromBottom, //开窗 XWCoolTransitionAnimatorTypePortal, //折叠 XWCoolTransitionAnimatorTypeFoldFromLeft, XWCoolTransitionAnimatorTypeFoldFromRight, //爆炸 XWCoolTransitionAnimatorTypeExplode, //酷炫线条效果 XWCoolTransitionAnimatorTypeHorizontalLines, XWCoolTransitionAnimatorTypeVerticalLines, //扫描效果 XWCoolTransitionAnimatorTypeScanningFromLeft, XWCoolTransitionAnimatorTypeScanningFromRight, XWCoolTransitionAnimatorTypeScanningFromTop, XWCoolTransitionAnimatorTypeScanningFromBottom,};

2、 cool转场效果中的Portal、Fold、Explode效果的片段代码逻辑来源于ColinEberhardt/VCTransitionsLibrary,特别多谢笔者,作者只是将其开展了有的改换,以便对手势的援救尤其周详,里面还有好多任何功效,本人经历有限就从不再并入进来了,我们能够自动查看;cool转场效果的Lines的主见来自于cinkster/HUAnimator, 特别多谢小编,不过出于作者在对toVC截图选拔了延期的章程来拍卖,导致了不佳管理的bug和一些手势上的bug,对此小编动用了另一种艺术来减轻截图的主题材料,使用了layer的contentRect属性,消除了意识的标题,相关代码请自行查看

图片 24效果图.gif

关于FilterTransition

1、XWFilterAnimator 全部都以遵照不一样的CIFilter发生的部分滤镜效果,貌似在模拟器不恐怕运转那些功用,请在真机上测量试验,直接通过枚举最初化就有一度合併的局地机能,具体如下:

typedef NS_ENUM(NSUInteger, XWFilterAnimatorType) { XWFilterAnimatorTypeBoxBlur,//模糊转场,对应CIBoxBlur XWFilterAnimatorTypeSwipe,//滑动过渡转场,对应CISwipeTranstion XWFilterAnimatorTypeBarSwipe,//对应CIBarSwipeTranstion XWFilterAnimatorTypeMask,//按指定遮罩图片转场,对应CIDisintegrateWithMaskTransition XWFilterAnimatorTypeFlash,//闪烁转场,对应CIFlashTransition XWFilterAnimatorTypeMod,//条纹转场 对应CIModTransition XWFilterAnimatorTypePageCurl,//翻页转场 对应CIPageCurlWithShadowTransition XWFilterAnimatorTypeRipple,//波纹转场,对应CIRippleTransition XWFilterAnimatorTypeCopyMachine, //效果和XWCoolAnimator中的Scanning效果类似,对应CICopyMachineTransition};

2、假如想要增多任何滤镜转场,能够品尝本身的FilterTransition中书写分类的秘籍,只须求钦赐CIFilter和连锁逻辑就可以

哦即便很粗大劣,可是弹幕已经能够出去了,但是有个难题正是弹幕重叠了,这里能够加个数组来有的时候保留接收到的弹幕音讯,等检查测量试验到空闲位置了再管理。

关于自定义转场效果

1、你只必要继续于XWTransitionAnimator,就疑似我上面装有的效果器一样,然后复写须求的属性和七个必得的点子就能够,然后您就足以行让你自定义的效果器转场,XWTransitionAnimator头文件如下:

@interface XWTransitionAnimator : NSObject<UIViewControllerTransitioningDelegate, UINavigationControllerDelegate, UITabBarControllerDelegate, XWInteractiveTransitionDelegate>//to转场时间 默认0.5@property (nonatomic, assign) NSTimeInterval toDuration;//back转场时间 默认0.5@property (nonatomic, assign) NSTimeInterval backDuration;//是否需要开启手势timer,某些转场如果在转成过程中所开手指,不会有动画过渡,显得很生硬,开启timer后,松开手指,会用timer不断的刷新转场百分比,消除生硬的缺点@property (nonatomic, assign) BOOL needInteractiveTimer;/** * 配置To过程动画(push, present),自定义转场动画应该复写该方法 */- xw_setToAnimation:(id<UIViewControllerContextTransitioning>)transitionContext;/** * 配置back过程动画(pop, dismiss),自定义转场动画应该复写该方法 */- xw_setBackAnimation:(id<UIViewControllerContextTransitioning>)transitionContext;@end

2、那样就只须求关注动画的逻辑,别的的业务就毫无管了,然则倘若遇上闪烁难点,你只须求复写相关的手势代理方法,就如作者在小圆点转场中平等,因为XWTransitionAnimator暗中认可是手势管理者的代办,所以直接实今世理方法就好了

@interface DSHBarrageView : UIView@property (strong ,nonatomic) NSMutableArray *barrageMessages; // 管理队列中的弹幕消息@end

写在终极

陆续的就这个了,东西比非常多,恐怕本人的叙说也还应该有一定难点,有些内容恐怕描述的不太明了,请大家多多参谋demo,希望本文能让我们从此再规划到自定义转场的时候能够快速化解难题,再度复习一下地方几句代码飞快集成自定义转场效果 全手势驱动 ,借使对您有接济款待给予star援救!

相应的修改.m文件贯彻检查评定逻辑

更新 2016-06-24

前几天晚上想想了须臾间,优化了一下DrawerAnimator,以前的toVC的frame不会随着设置的distance改动,暗许经常都以显示屏的宽和高,也正是说展现之后,toVC的有一对实际上是在显示器外面包车型大巴,那对于持续的布局是不太有利的,所以作者修改了一晃,未来toVC的frame是和装置的distance相关的,所见到的toVC的一部分就是toVC的全方位

// 收到一条弹幕消息- receivedMessage:message; { BOOL idle = [self idle]; if  { if (!_barrageMessages) { _barrageMessages = [NSMutableArray array]; } [_barrageMessages addObject:message]; } else { [self showBarrageCellWithBarrageMessage:message]; }}// 检测是否有空位置可供弹幕展示- idle { BOOL idle = YES; for (UILabel *label in self.subviews) { if ([label isKindOfClass:[UILabel class]]) { if (CGRectGetMaxX(label.frame) >= self.frame.size.width) { idle = NO; break; } } } return idle;}- showBarrageCellWithBarrageMessage:message { UILabel *cell = [[UILabel alloc] init]; cell.font = [UIFont systemFontOfSize:14]; cell.textColor = [UIColor whiteColor]; cell.backgroundColor = [UIColor blackColor]; cell.textAlignment = NSTextAlignmentCenter; cell.text = [NSString stringWithFormat:@"弹幕消息:%@" ,message]; [self addSubview:cell]; [cell sizeToFit]; CGRect frame = cell.frame; frame.origin.x = self.frame.size.width; frame.origin.y = 44.f; frame.size.width = 100.f; cell.frame = frame; if  { // 当接收到弹幕消息后开启定时器 _timer = [CADisplayLink displayLinkWithTarget:self selector:@selector]; [_timer addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes]; }}- update { NSInteger cellCount = 0; for (UILabel *cell in self.subviews) { if ([cell isKindOfClass:[UILabel class]]) { CGRect frame = cell.frame; frame.origin.x -= 1.f; cell.frame = frame; if (CGRectGetMaxX <= 0) { [cell removeFromSuperview]; // 当超出屏幕时自动移除 } else { cellCount   ; } } } id message = _barrageMessages.firstObject; if (message && [self idle]) { // 检测到位置已经空出来了,处理队列中的消息 [_barrageMessages removeObject:message]; [self showBarrageCellWithBarrageMessage:message]; cellCount   ; } if (cellCount <= 0) { [self destroy]; // 检测到没有弹幕时自动销毁定时器 }}

更新 2016-07-05

1、前几日意识了三个题材,正是在扩充差别的意义往往push的时候,在pop的时候,在此之前的法力会失效,笔者修复了那一个主题材料,请看截图,上边是修复前,下边是修补后

图片 25改进在此以前.gif图片 26校勘之后.gif

能够望见,修复前,在结尾一遍back的时候,那些放炮的功能已经失效了,2、难点由来:在每便push时作者会切换navigationController的delegate为当前效果器,进而能不负职责转场效果的逻辑,所以反复push后,代理始终是最终三个效果器,而在pop的时候特别效果器随着对应的pop操作已经被灭绝了,而代理并从未切换为事前的爆炸效果器,所以自定义转场就不可能接触了3、解决:由于自个儿每多少个效果器是和被push出的VC绑定的,所以当被pushVC被销毁的时候,效果器就能销毁,此刻,应该去检查评定一下代理,若是上三个VC存在效果器,则须求切换回该效果器,所以须要在pushVC的dealloc方法中要求对代理举办检验和切换,为了达到指标,供给对VC的dealloc方法开展调节和测量试验,调理的秘诀某个有一点复杂,具体请看本人另一篇简书作品:一句代码,更Gavin雅的调用KVO和文告中关于调护治疗dealloc方法的有关代码,在dealloc中增添了代理检查实验和切换的不二等秘书籍来达成目标

好的再一次运转

图片 27功能图.gif到这里弹幕的主导逻辑就完结了,接下去须要支持多条弹幕通道,自定义弹幕样式,自定义弹幕滚动速度,完整的代码可以点击这里查看,整个德姆o代码不算少,这里就不贴全部了。

版权声明:本文由威尼斯人app发布于编程学习,转载请注明出处:几句代码快捷集成自定义转场效果 全手势驱动