目錄
1. UIViewController生命周期
2. 跳轉
3. 高度自定義控制器間過渡
4. ViewController 間傳值
5. 容器視圖控制器
6. CGFloat、CGPoint、CGSize、CGRect
7. 屏幕旋轉
- UIViewController生命周期
注意:上下拉手機的菜單,并不會走VC的apperar、disappear方法
- 跳轉
方式一(present從下方彈出)
// present下一頁
[self presentViewController:vc animated:true completion:^{
}];
// 返回上一頁
[self dismissViewControllerAnimated:true completion:^{
}];
彈出氣泡視圖
// 1.自定義控制器(:UIViewController)
YTGrabOrderPopViewController *grabPopC=[YTGrabOrderPopViewController new];
// 設置pop視圖顯示大小
[grabPopC setPreferredContentSize:CGSizeMake(142, 160)];
// 設置presentVC的彈出方式為pop
[grabPopC setModalPresentationStyle:UIModalPresentationPopover];
// 2.
UIPopoverPresentationController *popVC=[grabPopC popoverPresentationController];
[popVC setDelegate:self]; // <UIPopoverPresentationControllerDelegate>
// 方式一:對于View
[popVC setSourceView:button]; //
[popVC setSourceRect:button.bounds]; // 位置:可調整
// 方式二:對于UIBarButtonItem
[popVC setBarButtonItem:[UIBarButtonItem new]];
// 3.彈出
[self presentViewController:grabPopC animated:true completion:^{
}];
present前可以配置過渡類型(高度自定義 參見下一節)
[vc setModalTransitionStyle:UIModalTransitionStyleCoverVertical];
/*
過渡style
UIModalTransitionStyleCoverVertical 由下而上(默認)
UIModalTransitionStyleCrossDissolve 淡入淡出
UIModalTransitionStyleFlipHorizontal 右側向上翻轉
UIModalTransitionStylePartialCurl 向上翻頁
*/
[vc setModalPresentationStyle:UIModalPresentationFullScreen];
/*
彈出style
UIModalPresentationFullScreen 全屏(默認,原VC的View消失)
UIModalPresentationOverFullScreen 占滿全屏(原VC的View不消失)
UIModalPresentationPageSheet
UIModalPresentationFormSheet
UIModalPresentationCurrentContext
UIModalPresentationCustom
UIModalPresentationOverCurrentContext
UIModalPresentationPopover 氣泡
UIModalPresentationNone
*/
// 彈出我的是誰
id presentVC=self.presentingViewController;
// 我彈出的是誰
id presentedVC=self.presentedViewController;
方式二(具體參見iOS之UINavigationController篇)
push(從右側彈出)
前提:在push棧中,[[UINavigationController alloc]initWithRootViewController:[UIViewController new]];
》》》跳轉到下一頁(2種)
// 方式一
[self.navigationController pushViewController:[UIViewController new] animated:true];
// 方式二
[self.navigationController showViewController:[UIViewController new] sender:nil];
》》》返回到上一頁(3種)
// 一:返回到上一頁
[self.navigationController popViewControllerAnimated:true];
// 二:返回到根視圖頁
[self.navigationController popToRootViewControllerAnimated:true];
// 三:返回到指定頁(頁面必須在堆棧中)
[self.navigationController popToViewController:self.navigationController.viewControllers[0] animated:true];
- 高度自定義控制器間過渡
TransitionManager.h
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface TransitionManager : NSObject<UIViewControllerAnimatedTransitioning,UIViewControllerTransitioningDelegate>
/**
true:正在present
false:正在dismiss
*/
@property (nonatomic,assign) BOOL presenting;
@end
TransitionManager.m
#import "TransitionManager.h"
@interface TransitionManager()
@end
@implementation TransitionManager
// 動畫結束時(不一定和過渡時間一致,只要動畫停止)調用
-(void)animationEnded:(BOOL)transitionCompleted{
if(!transitionCompleted){ //
}else{
}
}
#pragma mark UIViewControllerAnimatedTransitioning
// 過渡時調用(1.獲取到2個VC的View(2個階段VC代表的不一樣) 2. 分為兩個階段做不同的變化)
-(void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext{
//
UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
UIView *toView = toVC.view;
UIView *fromView = fromVC.view;
// [toVC beginAppearanceTransition:YES animated:YES]; toVC 調用viewWillAppear 不加不會調用
if(self.presenting){
// 階段1
[self RunPresentAnimation:transitionContext fromVC:fromVC toVC:toVC fromView:fromView toView:toView];
}else{
// 階段2
[self RunDismissAnimation:transitionContext fromVC:fromVC toVC:toVC fromView:fromView toView:toView];
}
// [fromVC beginAppearanceTransition:NO animated:YES]; fromVC 調用viewDidDisappear
}
// 過渡時間(沒什么影響,真正決定的還是以上方法中動畫設置的時間)
-(NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext{
return 0.82;
}
#pragma mark UIViewControllerTransitioningDelegate
// 當present VC后調用,返回 過渡動畫管理者(實現了UIViewControllerAnimatedTransitioning的類),一般返回單獨的遵守該協議的動畫類
-(id<UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source{
self.presenting=true;
return self;
}
// 當dismiss VC后調用,返回 過渡動畫管理者
- (id <UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed{
self.presenting=false;
return self;
}
// 返回<UIViewControllerInteractiveTransitioning>
//- (id <UIViewControllerInteractiveTransitioning>)interactionControllerForPresentation:(id <UIViewControllerAnimatedTransitioning>)animator{
//
//}
// 返回<UIViewControllerInteractiveTransitioning>
//- (id <UIViewControllerInteractiveTransitioning>)interactionControllerForDismissal:(id <UIViewControllerAnimatedTransitioning>)animator{
//
//}
//
//// 返回 :UIPresentationController
//- (UIPresentationController *)presentationControllerForPresentedViewController:(UIViewController *)presented presentingViewController:(nullable UIViewController *)presenting sourceViewController:(UIViewController *)source{
//
//}
// 動畫階段1(presenting)-——自定義方法
-(void)RunPresentAnimation:(id<UIViewControllerContextTransitioning>)transitionContext fromVC:(UIViewController *)fromVC toVC:(UIViewController *)toVC fromView:(UIView *)fromView toView:(UIView *)toView {
/*
設置toVC的初始位置,并添加到總容器View上(此時fromView已經在上面)
*/
// 獲取總容器View
UIView* containerView = [transitionContext containerView];
// 獲取fromVC的frame
CGRect frame = [transitionContext initialFrameForViewController:fromVC];
// 底部滑進 離屏滑入 即y坐標 從height --->0
CGRect offScreenFrame = frame;
offScreenFrame.origin.y = offScreenFrame.size.height;
toView.frame = offScreenFrame;
//
[containerView insertSubview:toView aboveSubview:fromView];
/*
對formView 和 toView 進行動畫
*/
//三維變化
CATransform3D t1 = CATransform3DIdentity;
t1.m34 = 1.0/-1000;
//x y方向各縮放比例為0.95
t1 = CATransform3DScale(t1, 0.95, 0.95, 1);
//x方向旋轉15°
t1 = CATransform3DRotate(t1, 15.0f * M_PI/180.0f, 1, 0, 0);
CATransform3D t2 = CATransform3DIdentity;
t2.m34 = 1.0/-1000;
//沿Y方向向上移動
t2 = CATransform3DTranslate(t2, 0, -fromView.frame.size.height*0.08, 0);
//在x y方向各縮放比例為0.8
t2 = CATransform3DScale(t2, 0.8, 0.8, 1);
//UIView關鍵幀動畫 總的持續時間:1.0
[UIView animateKeyframesWithDuration:1.0 delay:0.0 options:UIViewKeyframeAnimationOptionCalculationModeCubic animations:^{
//開始時間:1.0*0.0 持續時間:1.0*0.4
[UIView addKeyframeWithRelativeStartTime:0.0f relativeDuration:0.4f animations:^{
//執行t1動畫 縮放并旋轉角度
fromView.layer.transform = t1;
//fromView的透明度
fromView.alpha = 0.6;
}];
//開始時間:1.0*0.1 持續時間:1.0*0.5
[UIView addKeyframeWithRelativeStartTime:0.1f relativeDuration:0.5f animations:^{
//執行t2動畫 向上平移和縮放
fromView.layer.transform = t2;
}];
//開始時間:1.0*0.0 持續時間:1.0*1.0
[UIView addKeyframeWithRelativeStartTime:0.0f relativeDuration:1.0f animations:^{
//toView向上滑入
toView.frame = frame;
}];
} completion:^(BOOL finished) {
// 過渡動畫結束
[transitionContext completeTransition:![transitionContext transitionWasCancelled]];
}];
}
// 動畫階段2-——自定義方法
-(void)RunDismissAnimation:(id<UIViewControllerContextTransitioning>)transitionContext fromVC:(UIViewController *)fromVC toVC:(UIViewController *)toVC fromView:(UIView *)fromView toView:(UIView *)toView {
/*
隱藏vc2,還原vc1
*/
CGRect frame = [transitionContext initialFrameForViewController:fromVC];
toView.frame = frame;
CGRect frameOffScreen = frame;
frameOffScreen.origin.y = frame.size.height;
CATransform3D t1 = CATransform3DIdentity;
t1.m34 = 1.0/-1000;
t1 = CATransform3DScale(t1, 0.95, 0.95, 1);
t1 = CATransform3DRotate(t1, 15.0f * M_PI/180.0f, 1, 0, 0);
// 關鍵幀過渡動畫
[UIView animateKeyframesWithDuration:1.0 delay:0 options:UIViewKeyframeAnimationOptionCalculationModeCubic animations:^{
[UIView addKeyframeWithRelativeStartTime:0.0f relativeDuration:1.0f animations:^{
fromView.frame = frameOffScreen;
}];
[UIView addKeyframeWithRelativeStartTime:0.35f relativeDuration:0.35f animations:^{
toView.layer.transform = t1;
//透明度為1.0
toView.alpha = 1.0;
}];
[UIView addKeyframeWithRelativeStartTime:0.75f relativeDuration:0.25f animations:^{
//還原3D狀態
toView.layer.transform = CATransform3DIdentity;
}];
} completion:^(BOOL finished) {
[transitionContext completeTransition:![transitionContext transitionWasCancelled]];
}];
}
@end
- ViewController 間傳值
方式一 (通過屬性傳值)
/**
id
*/
@property (nonatomic,copy) NSString *expertId;
方式二 (通過block傳值)
/**
attentionBlock
*/
@property (nonatomic,copy) void (^attentionBlock)(NSString *expertId);
方式三 (dele)
@protocol ExpertViewControllerDele <NSObject>
-(void)attentionExpert:(NSString *)expertId;
@end
@property (nonatomic,weak) id<ExpertViewControllerDele> *dele;
方式四 (通知)
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(handleAttention:) name:@"AttentionExpert" object:nil];
[[NSNotificationCenter defaultCenter]postNotificationName:@"AttentionExpert" object:@{@"expertId":@"110",@"isAttention":@(1)}];
方式五 (target+action)
- 容器視圖控制器
系統自帶的容器視圖控制器:UINavigationController, UITabBarController和UISplitViewController
普通子控制器
點擊按鈕進入頁面B(根據接口獲取的不同的狀態,進入不同的頁面)
一般把判斷的邏輯放在頁面B,而不是按鈕所在的頁面A。這時需要根據不同的條件添加不同的控制器以顯示不同的頁面。
// 添加
[self addChildViewController:vc];
[self.view addSubview:vc.view]; // 注意:這里會調用viewDidLoad等方法
// 移除
[vc removeFromParentViewController]; // 將vc從總VC中移除,此時視圖還在屏幕上
[vc.view removeFromSuperview]; // 將vc的view移除
6. CGFloat、CGPoint、CGSize、CGRect
CGFloat
在UIView的坐標系統中,使用CGFloat類型的數據而不是Double或者Float
let x=CGFloat(12.0) :將Double或者Float轉換成CGFloat
CGPoint
var point=CGPoint(x:30.0,y:50.0)
CGSize
var size=CGSize(width:20.0,height:10.0)
CGRect
var rect=CGRect(origin:point,size:size)
var rect=CGRect(x:10.0,y:10.0,width:20.0,height:5.0)
使用:
minX minY midX midY maxX maxY rect1.intersects(rect2) 是否 相交
rect1.intersect(rect2) 返回相交部分
rect1.contains(rect2) 是否 包含
常用:
//
CGRectZero
// 是否有交集
CGRectIntersectsRect(rect1, rect2)
// 返回交集rect
CGRectIntersection(rect1, rect2)
// 是否相同
CGRectEqualToRect(rect1, rect2)
// 是否包含
CGRectContainsRect(rect1, rect2)
// 是否包含某點
CGRectContainsPoint(rect, CGPointMake(0, 0))
// 返回合集
CGRectUnion(rect1, rect2)
// frame<——>str
CGRectFromString(NSStringFromCGRect(frame))
//
CGRectGetMidX(rect)
CGRectGetMinX(rect)
CGRectGetMaxX(rect)
CGRectGetMidY(rect)
CGRectGetMinY(rect)
CGRectGetMaxY(rect)
CGRectGetWidth(rect)
CGRectGetHeight(rect)
7. 屏幕旋轉
- 選擇項目支持的旋轉方向
方式1
項目 | General | Deployment Info 下選擇項目支持的方向
Portrait 正常方向 (Home鍵在下)
Landscape Left (Home鍵在)
Landscape Right (Home鍵在)
Upside Down (Home鍵在上)
App支持的旋轉方向
方式2
AppDelegate中+
- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
return UIInterfaceOrientationMaskPortrait;
}
- 指定頁面旋轉
/**
想讓某頁面旋轉,那它的父級頁面也必須支持旋轉
*/
1.自定義UITabbarController中+
// IOS6后
// 是否允許旋轉
-(BOOL)shouldAutorotate{
return self.selectedViewController.shouldAutorotate;
}
// 返回 哪些方向允許旋轉
-(UIInterfaceOrientationMask)supportedInterfaceOrientations{
return self.selectedViewController.supportedInterfaceOrientations;
}
/*
UIInterfaceOrientationMaskPortrait = (1 << UIInterfaceOrientationPortrait),//向上為正方向的豎屏
UIInterfaceOrientationMaskLandscapeLeft = (1 << UIInterfaceOrientationLandscapeLeft),//向左移旋轉的橫屏
UIInterfaceOrientationMaskLandscapeRight = (1 << UIInterfaceOrientationLandscapeRight),//向右旋轉的橫屏
UIInterfaceOrientationMaskPortraitUpsideDown = (1 << UIInterfaceOrientationPortraitUpsideDown),//向下為正方向的豎屏
UIInterfaceOrientationMaskLandscape = (UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight),//向左或者向右的橫屏
UIInterfaceOrientationMaskAll = (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight | UIInterfaceOrientationMaskPortraitUpsideDown),//所有的橫豎屏方向都支持
UIInterfaceOrientationMaskAllButUpsideDown = (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight),//支持向上的豎屏和左右方向的橫屏
*/
// 返回 最優先使用的方向
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation{
return UIInterfaceOrientationPortrait;
}
/*
UIInterfaceOrientationUnknown = UIDeviceOrientationUnknown,//屏幕方向未知
UIInterfaceOrientationPortrait = UIDeviceOrientationPortrait,//向上正方向的豎屏
UIInterfaceOrientationPortraitUpsideDown = UIDeviceOrientationPortraitUpsideDown,//向下正方向的豎屏
UIInterfaceOrientationLandscapeLeft = UIDeviceOrientationLandscapeRight,//向右旋轉的橫屏
UIInterfaceOrientationLandscapeRight = UIDeviceOrientationLandscapeLeft//向左旋轉的橫屏
此方法用來設置當前頁面默認第一次進入的時候顯示的屏幕方向
*/
// IOS6前
// VC是否支持旋轉屏幕(不支持則旋轉屏幕時界面不動)
//- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation{
// return toInterfaceOrientation==UIInterfaceOrientationPortrait;
//}
2.自定義Nav中+
-(BOOL)shouldAutorotate{
return self.topViewController.shouldAutorotate;
}
-(UIInterfaceOrientationMask)supportedInterfaceOrientations{
return self.topViewController.supportedInterfaceOrientations;
}
3.自定義基類VC中+
-(UIInterfaceOrientationMask)supportedInterfaceOrientations{
return UIInterfaceOrientationMaskPortrait;
}
-(BOOL)shouldAutorotate{
return false;
}
4.需要旋轉的VC中+
-(BOOL)shouldAutorotate{
return true;
}
- 主動旋轉
當用戶設置iPhone禁止旋轉后,以上方法失效(即不會旋轉)
[[UIDevice currentDevice]setValue:[NSNumber numberWithInt:UIInterfaceOrientationLandscapeRight] forKey:@"orientation"];
- 監聽旋轉
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(orientationChange:) name:UIDeviceOrientationDidChangeNotification object:nil];