自定義轉(zhuǎn)場動畫

效果圖:


自定義轉(zhuǎn)場


1.封裝好的工具類(可以根據(jù)需求改變圓心的位置再封裝)

WeCircleAnimation.h文件

#import<Foundation/Foundation.h>

#import<UIKit/UIKit.h>

@interface WeCircleAnimation :NSObject<UIViewControllerTransitioningDelegate>

@end

WeCircleAnimation.m文件

@interface WeCircleAnimation ()<UIViewControllerAnimatedTransitioning,CAAnimationDelegate>

//動畫是呈現(xiàn)還是解除

@property (nonatomic, assign) BOOL isPresented;

//保存動畫上下文(必須要弱引用,如果強引用則會導致循環(huán)引用,內(nèi)存泄露)

@property (nonatomic, weak) id<UIViewControllerContextTransitioning> transitionContext;

@end

@implementation WeCircleAnimation

//告訴控制器誰來提供展現(xiàn)轉(zhuǎn)場動畫

- (nullable id)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source{? ??

self.isPresented = YES;? ? return self;

}

//告訴控制器誰來提供解除轉(zhuǎn)場動畫

- (nullable id)animationControllerForDismissedController:(UIViewController *)dismissed{

self.isPresented = NO;

return self;

}

/** 返回動畫時長 @param transitionContext 轉(zhuǎn)場上下文 @return 轉(zhuǎn)場動畫 */

- (NSTimeInterval)transitionDuration:(nullable id)transitionContext{

return 0.3;

}

** 轉(zhuǎn)場動畫最核心的方法-有程序員提供自己的動畫實現(xiàn) @param transitionContext 轉(zhuǎn)場上下文提供轉(zhuǎn)場動畫的所有細節(jié) 容器視圖-轉(zhuǎn)場動畫的表演的舞臺 轉(zhuǎn)場上下文會對展現(xiàn)的控制器強引用 */

- (void)animateTransition:(id)transitionContext{

//1.獲取容器視圖

UIView *containerView = transitionContext.containerView;

//2.獲取目標視圖,如果是展現(xiàn)去toView,如果是解除,去fromView;

UIView *fromView = [transitionContext viewForKey:UITransitionContextFromViewKey];

UIView *toView = [transitionContext viewForKey:UITransitionContextToViewKey];

UIView *view = self.isPresented?toView:fromView;

NSLog(@"%@---%@",fromView,toView);

//3.添加目標視圖到容器視圖

[containerView addSubview:view];

//4.動畫

[self layerAnimationWithView:view];

//5.一定要完成轉(zhuǎn)場,如果不完成,系統(tǒng)會一直等待轉(zhuǎn)場完成,就無法接收用戶的任何交互

//應該在動畫完成之后在通知系統(tǒng)轉(zhuǎn)場結(jié)束

self.transitionContext = transitionContext;

}

-(void)layerAnimationWithView:(UIView *)view{

//1.創(chuàng)建形狀圖層ShapeLayer

CAShapeLayer *shapeLayer = [[CAShapeLayer alloc] init];

//圓的屏幕邊距

CGFloat mergin = 20;

//圓的半徑

CGFloat radiu = 25;

CGRect startRect = CGRectMake(view.bounds.size.width - mergin - radiu*2, mergin, radiu*2, radiu*2);

//2.創(chuàng)建圓形貝塞爾路徑 參數(shù)是圓的外界矩形

UIBezierPath *startBezierPath = [UIBezierPath bezierPathWithOvalInRect:startRect];

CGFloat sWidth = view.bounds.size.width;

CGFloat sHeight = view.bounds.size.height;

//結(jié)束圓的半徑(屏幕的半徑)

CGFloat endRadius = sqrt(sWidth * sWidth + sHeight * sHeight);

//使用縮進矩形創(chuàng)建圓的外接矩形

CGRect endRect = CGRectInset(startRect, -endRadius, -endRadius);

//3.外接圓的的貝塞爾路徑

UIBezierPath *endPath = [UIBezierPath bezierPathWithOvalInRect:endRect];

//設(shè)置形狀圖層的填充顏色 fillColor:填充圓 strokeColor:邊框圓

//? ? shapeLayer.fillColor = [UIColor redColor].CGColor;

//4.繪制號的貝塞爾路徑為形狀圖層的路徑

shapeLayer.path = startBezierPath.CGPath;

//設(shè)置shapeLayer為控制器視圖的遮罩圖層

//5.設(shè)置mask遮罩圖層:1.會裁切圖層,讓圖層只能看見shapelayer的形狀的區(qū)域 2.一旦將layer設(shè)置為遮罩圖層之后,填充顏色會失效

view.layer.mask = shapeLayer;

//將shape添加到視圖中,addSublayer實在當前的圖層上添加一個layer的形狀區(qū)域

//? ? [self.view.layer addSublayer:shapeLayer];

//5.動畫 -如果要做layer視圖的動畫,不能使用UIView的動畫,應該使用核心動畫

//? ? [UIView animateWithDuration:3 animations:^{

//? ? ? ? ? ? ? ? //設(shè)置圖層的路徑

//? ? ? ? layer.path = endPath.CGPath;

//

//? ? }];

//6.實例化對象

CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"path"];

//7.設(shè)置動畫的屬性:1.時間? 2.填充模式

//設(shè)置動畫屬性

//時長

animation.duration = [self transitionDuration:self.transitionContext];

//判斷是展現(xiàn)還是解除

if (self.isPresented) {

//formValue

animation.fromValue = (__bridge id _Nullable)(startBezierPath.CGPath);

animation.toValue = (__bridge id _Nullable)(endPath.CGPath);

}else{

animation.fromValue = (__bridge id _Nullable)(endPath.CGPath);

animation.toValue = (__bridge id _Nullable)(startBezierPath.CGPath);

}

//設(shè)置向前填充模式

animation.fillMode = kCAFillModeForwards;

//完成之后不刪除

animation.removedOnCompletion = NO;

//設(shè)置動畫代理 必須要寫在添加動畫到圖層的前面,否則代理不會調(diào)用(一旦將動畫添加到圖層,動畫已經(jīng)開啟,在設(shè)置代理已經(jīng)來不及了)

animation.delegate = self;

//8.將動畫添加到圖層 -shapeLayer,讓哪個圖層執(zhí)行動畫就應該將動畫添加到哪個圖層

[shapeLayer addAnimation:animation forKey:nil];

}

/**

監(jiān)聽動畫完成

@param anim 動畫

@param flag 完成

*/

- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag{

[self.transitionContext completeTransition:YES];

}

@end


運用:

ViewController.m?

#import "ViewController.h"

#import "WeCircleAnimation.h"

@interface ViewController ()

@property (nonatomic, strong) WeCircleAnimation *circleAnnimation;

@end

@implementation ViewController

-(void)awakeFromNib{?

?? [super awakeFromNib];? ??

//1.設(shè)置展示樣式為自定義? ??

self.modalPresentationStyle = UIModalPresentationCustom;??

? //2.設(shè)置轉(zhuǎn)場代理? ??

self.circleAnnimation = [[WeCircleAnimation alloc]init];? ? self.transitioningDelegate = self.circleAnnimation;

}

- (void)viewDidLoad {? ? [super viewDidLoad];}-(void)touchesBegan:(NSSet*)touches withEvent:(UIEvent *)event{

[self dismissViewControllerAnimated:YES completion:nil];

}

@end

storyBoard中的控件效果圖



GitHub鏈接地址:https://github.com/KeithBigBather666/CircleAnnimation.git

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容