如何在ios push presentt出来的viewController里使用push方法

[iOS]设置页面跳转的样式(presentViewController) - 简书
<div class="fixed-btn note-fixed-download" data-toggle="popover" data-placement="left" data-html="true" data-trigger="hover" data-content=''>
写了1830字,被41人关注,获得了70个喜欢
[iOS]设置页面跳转的样式(presentViewController)
在项目中没有创建 UINavgationController,无法使用默认的 push 方法 进行页面的跳转时。
使用另一种页面跳转方法 :
- (void)presentViewController:(UIViewController *)viewControllerToPresent animated: (BOOL)flag completion:(void (^ __nullable)(void))completion NS_AVAILABLE_IOS(5_0);
常用的方法:
结合控件的点击事件,例:常用的UIButton
UIButton * button = [UIButton alloc] init];
[button addTarget:self action:@selector(buttonClick) forControlEvents:(UIControlEventTouchUpInside)];
默认跳转方式,从底部推出
- (void)buttonClick {
UIViewController * viewController = [UIViewController alloc] init];
[self presentViewController: viewController animated:YES completion:nil];
根据需求设置跳转时的样式:
- (void)buttonClick {
CATransition * animation = [CATransition animation];
animation.duration = 0.5;
type:动画类型
向上翻一页
pageUnCurl
向下翻一页
rippleEffect
suckEffect
animation.type = @"pageCurl";
type:页面转换类型
kCATransitionFade
kCATransitionMoveIn
kCATransitionReveal
kCATransitionPush
animation.type = kCATransitionP
//PS:type 更多效果请 搜索: CATransition
subtype:出现的方向
kCATransitionFromRight
kCATransitionFromLeft
kCATransitionFromTop
kCATransitionFromBottom
animation.subtype = kCATransitionFromR
[self.view.window.layer addAnimation:animation forKey:nil];
[self presentViewController: viewController animated:YES completion:nil];
PS:设置 type 属性时,两种写法
在 UIViewController 中才可以调用 presentViewController 方法。但如果是监听 [自定义View] 中的一个 [UIButton事件] 进行跳转:
自定义 View.h 文件中
@property (nonatomic, strong) UIViewController
---------------------
自定义 View.m 文件中
自定义View视图中的 UIButton
self.button = [UIButton alloc] init];
[self.button addTarget:self action:@selector(selfButtonClick:) forControlEvents:(UIControlEventTouchUpInside)];
self.button 点击方法
- (void)selfButtonClick:(UIViewController *)otherVC {
self.viewC
[self presentViewController:otherVC animated:YES completion:nil];
-------------------
绑定 自定义View 的 Controller 中
self.自定义View.viewController =
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮
被以下专题收入,发现更多相似内容:
分享 iOS 开发的知识,解决大家遇到的问题,讨论iOS开发的前沿,欢迎大家投稿~
· 28544人关注
【最新投稿方式】
为了保证专题文章的质量,暂时关闭投稿申请,改为【私信文章链接】给本专题的管理员 (花前月下) (判若...
· 7673人关注
学习从点滴开始 !
(PS: 拒绝部分投稿的文章仅仅是由于专题内已收录相关知识点的文章, 并非是投稿的文章技术含量不够好, 望谅解.)
· 5885人关注
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
选择支付方式:IOS开发小记-关于presentViewController 后调用pushViewController 无效解决方案 - 简书
<div class="fixed-btn note-fixed-download" data-toggle="popover" data-placement="left" data-html="true" data-trigger="hover" data-content=''>
写了1884字,被0人关注,获得了3个喜欢
IOS开发小记-关于presentViewController 后调用pushViewController 无效解决方案
错误代码:LoginViewController *loginVc = [[LoginViewController alloc] int];[self presentViewController :loginVc animated:YES completion:nil];以上代码运行结果,返回到loginVc后再次登录调用 pushViewController 无效没有任何反应。解决方案:UINavigationController *uiNavC = [[UINavigationController alloc] initWithRowViewController:[[LoginViewController alloc] int]];[self presentViewController :uiNavC animated:YES completion:nil];
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
选择支付方式:iOS7新特性 ViewController转场切换(二) 系统视图控制器容器的切换动画---push pop present dismis
iOS7新特性 ViewController转场切换(二) 系统视图控制器容器的切换动画---push pop present dismis
@上一章,介绍了主要的iOS7所增加的API,可以发现,它们不是一个个死的方法,苹果给我们开发者提供的是都是协议接口,所以我们能够很好的单独提出来写成一个个类,在里面实现我们各种自定义效果.
1.先来看看实现UIViewControllerAnimatedTransitioning的自定义动画类
自定义的动画类
实现协议------&@protocol UIViewControllerAnimatedTransitioning
这个接口负责切换的具体内容,也即“切换中应该发生什么”
@interface MTHCustomAnimator : NSObject &UIViewControllerAnimatedTransitioning&
@implementation MTHCustomAnimator
// 系统给出一个切换上下文,我们根据上下文环境返回这个切换所需要的花费时间
- (NSTimeInterval)transitionDuration:(id&UIViewControllerContextTransitioning&)transitionContext
return 1.0;
// 完成容器转场动画的主要方法,我们对于切换时的UIView的设置和动画都在这个方法中完成
- (void)animateTransition:(id&UIViewControllerContextTransitioning&)transitionContext
// 可以看做为destination ViewController
UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
// 可以看做为source ViewController
UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
// 添加toView到容器上
[[transitionContext containerView] addSubview:toViewController.view];
toViewController.view.alpha = 0.0;
[UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{
// 动画效果有很多,这里就展示个左偏移
fromViewController.view.transform = CGAffineTransformMakeTranslation(-320, 0);
toViewController.view.alpha = 1.0;
} completion:^(BOOL finished) {
fromViewController.view.transform = CGAffineTransformI
// 声明过渡结束--&记住,一定别忘了在过渡结束时调用 completeTransition: 这个方法
[transitionContext completeTransition:![transitionContext transitionWasCancelled]];
PS:从协议中两个方法可以看出,上面两个必须实现的方法需要一个转场上下文参数,这是一个遵从UIViewControllerContextTransitioning 协议的对象。通常情况下,当我们使用系统的类时,系统框架为我们提供的转场代理(Transitioning Delegates),为我们创建了转场上下文对象,并把它传递给动画控制器。
// MainViewController
@interface MTHMainViewController () &UINavigationControllerDelegate,UIViewControllerTransitioningDelegate&
@property (nonatomic,strong) MTHCustomAnimator *customA
@property (nonatomic,strong) PDTransitionAnimator *minToMaxA
@property (nonatomic,strong) MTHNextViewController *nextVC;
// 交互控制器 (Interaction Controllers) 通过遵从 UIViewControllerInteractiveTransitioning 协议来控制可交互式的转场。
@property (strong, nonatomic) UIPercentDrivenInteractiveTransition* interactionC
@implementation MTHMainViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
- (void)viewDidLoad
[super viewDidLoad];
// Do any additional setup after loading the view.
self.navigationItem.title = @"Demo";
self.view.backgroundColor = [UIColor yellowColor];
// 设置代理
self.navigationController.delegate =
// 设置转场动画
self.customAnimator = [[MTHCustomAnimator alloc] init];
self.minToMaxAnimator = [PDTransitionAnimator new];
self.nextVC = [[MTHNextViewController alloc] init];
// Present的代理和自定义设置
_nextVC.transitioningDelegate =
_nextVC.modalPresentationStyle = UIModalPresentationC
UIButton *pushButton = [UIButton buttonWithType:UIButtonTypeSystem];
pushButton.frame = CGRectMake(140, 200, 40, 40);
[pushButton setTitle:@"Push" forState:UIControlStateNormal];
[pushButton addTarget:self action:@selector(push) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:pushButton];
// Present
UIButton *modalButton = [UIButton buttonWithType:UIButtonTypeSystem];
modalButton.frame = CGRectMake(265, 500, 50, 50);
[modalButton setTitle:@"Modal" forState:UIControlStateNormal];
[modalButton addTarget:self action:@selector(modal) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:modalButton];
// 实现交互操作的手势
UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(didClickPanGestureRecognizer:)];
[self.navigationController.view addGestureRecognizer:panRecognizer];
- (void)push
[self.navigationController pushViewController:_nextVC animated:YES];
- (void)modal
[self presentViewController:_nextVC animated:YES completion:nil];
#pragma mark - UINavigationControllerDelegate iOS7新增的2个方法
// 动画特效
- (id&UIViewControllerAnimatedTransitioning&) navigationController:(UINavigationController *)navigationController animationControllerForOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController *)fromVC toViewController:(UIViewController *)toVC
typedef NS_ENUM(NSInteger, UINavigationControllerOperation) {
UINavigationControllerOperationNone,
UINavigationControllerOperationPush,
UINavigationControllerOperationPop,
if (operation == UINavigationControllerOperationPush) {
return self.customA
- (id &UIViewControllerInteractiveTransitioning&)navigationController:(UINavigationController*)navigationController
interactionControllerForAnimationController:(id &UIViewControllerAnimatedTransitioning&)animationController
在非交互式动画效果中,该方法返回 nil
交互式转场,自我理解意思是,用户能通过自己的动作来(常见:手势)控制,不同于系统缺省给定的push或者pop(非交互式)
return _interactionC
#pragma mark - Transitioning Delegate (Modal)
// 前2个用于动画
-(id&UIViewControllerAnimatedTransitioning&)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source
self.minToMaxAnimator.animationType = AnimationTypeP
return _minToMaxA
-(id&UIViewControllerAnimatedTransitioning&)animationControllerForDismissedController:(UIViewController *)dismissed
self.minToMaxAnimator.animationType = AnimationTypeD
return _minToMaxA
// 后2个用于交互
- (id &UIViewControllerInteractiveTransitioning&)interactionControllerForPresentation:(id &UIViewControllerAnimatedTransitioning&)animator
return _interactionC
- (id &UIViewControllerInteractiveTransitioning&)interactionControllerForDismissal:(id &UIViewControllerAnimatedTransitioning&)animator
@以上实现的是非交互的转场,指的是完全按照系统指定的切换机制,用户无法中途取消或者控制进度切换.那怎么来实现交互转场呢:
UIPercentDrivenInteractiveTransition实现了UIViewControllerInteractiveTransitioning接口的类,,可以用一个百分比来控制交互式切换的过程。我们在手势识别中只需要告诉这个类的实例当前的状态百分比如何,系统便根据这个百分比和我们之前设定的迁移方式为我们计算当前应该的UI渲染,十分方便。具体的几个重要方法:
-(void)updateInteractiveTransition:(CGFloat)percentComplete 更新百分比,一般通过手势识别的长度之类的来计算一个值,然后进行更新。之后的例子里会看到详细的用法
-(void)cancelInteractiveTransition 报告交互取消,返回切换前的状态
–(void)finishInteractiveTransition 报告交互完成,更新到切换后的状态
#pragma mark - 手势交互的主要实现---&UIPercentDrivenInteractiveTransition
- (void)didClickPanGestureRecognizer:(UIPanGestureRecognizer*)recognizer
UIView* view = self.
if (recognizer.state == UIGestureRecognizerStateBegan) {
// 获取手势的触摸点坐标
CGPoint location = [recognizer locationInView:view];
// 判断,用户从右半边滑动的时候,推出下一个VC(根据实际需要是推进还是推出)
if (location.x & CGRectGetMidX(view.bounds) && self.navigationController.viewControllers.count == 1){
self.interactionController = [[UIPercentDrivenInteractiveTransition alloc] init];
[self presentViewController:_nextVC animated:YES completion:nil];
} else if (recognizer.state == UIGestureRecognizerStateChanged) {
// 获取手势在视图上偏移的坐标
CGPoint translation = [recognizer translationInView:view];
// 根据手指拖动的距离计算一个百分比,切换的动画效果也随着这个百分比来走
CGFloat distance = fabs(translation.x / CGRectGetWidth(view.bounds));
// 交互控制器控制动画的进度
[self.interactionController updateInteractiveTransition:distance];
} else if (recognizer.state == UIGestureRecognizerStateEnded) {
CGPoint translation = [recognizer translationInView:view];
// 根据手指拖动的距离计算一个百分比,切换的动画效果也随着这个百分比来走
CGFloat distance = fabs(translation.x / CGRectGetWidth(view.bounds));
// 移动超过一半就强制完成
if (distance & 0.5) {
[self.interactionController finishInteractiveTransition];
[self.interactionController cancelInteractiveTransition];
// 结束后一定要置为nil
self.interactionController =
@最后,给大家分享一个动画特效:类似于飞兔云传的发送ViewController切换
@implementation PDTransitionAnimator
#define Switch_Time 1.2
- (NSTimeInterval)transitionDuration:(id &UIViewControllerContextTransitioning&)transitionContext {
return Switch_T
#define Button_Width 50.f
#define Button_Space 10.f
- (void)animateTransition:(id &UIViewControllerContextTransitioning&)transitionContext {
UIViewController* toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
UIViewController* fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
UIView * toView = toViewController.
UIView * fromView = fromViewController.
if (self.animationType == AnimationTypeDismiss) {
// 这个方法能够高效的将当前显示的view截取成一个新的view.你可以用这个截取的view用来显示.例如,也许你只想用一张截图来做动画,毕竟用原始的view做动画代价太高.因为是截取了已经存在的内容,这个方法只能反应出这个被截取的view当前的状态信息,而不能反应这个被截取的view以后要显示的信息.然而,不管怎么样,调用这个方法都会比将view做成截图来加载效率更高.
UIView * snap = [toView snapshotViewAfterScreenUpdates:YES];
[transitionContext.containerView addSubview:snap];
[snap setFrame:CGRectMake([UIScreen mainScreen].bounds.size.width - Button_Width - Button_Space, [UIScreen mainScreen].bounds.size.height - Button_Width - Button_Space, Button_Width, Button_Width)];
[UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{
[snap setFrame:[UIScreen mainScreen].bounds];
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.5 animations:^{
[[transitionContext containerView] addSubview:toView];
snap.alpha = 0;
} completion:^(BOOL finished) {
[snap removeFromSuperview];
[transitionContext completeTransition:![transitionContext transitionWasCancelled]];
UIView * snap2 = [toView snapshotViewAfterScreenUpdates:YES];
[transitionContext.containerView addSubview:snap2];
UIView * snap = [fromView snapshotViewAfterScreenUpdates:YES];
[transitionContext.containerView addSubview:snap];
[UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{
[snap setFrame:CGRectMake([UIScreen mainScreen].bounds.size.width - Button_Width - Button_Space+ (Button_Width/2), [UIScreen mainScreen].bounds.size.height - Button_Width - Button_Space + (Button_Width/2), 0, 0)];
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.5 animations:^{
//snap.alpha = 0;
} completion:^(BOOL finished) {
[snap removeFromSuperview];
[snap2 removeFromSuperview];
[[transitionContext containerView] addSubview:toView];
// 切记不要忘记了噢
[transitionContext completeTransition:![transitionContext transitionWasCancelled]];
@其中,snapshotViewAfterScreenUpdates 方法的解释,我也不是很懂,反正初级来说会用就行,还可以参照下面的解析:
在iOS7 以前, 获取一个UIView的快照有以下步骤: 首先创建一个UIGraphics的图像上下文,然后将视图的layer渲染到该上下文中,从而取得一个图像,最后关闭图像上下文,并将图像显示在UIImageView中。现在我们只需要一行代码就可以完成上述步骤了:
[view snapshotViewAfterScreenUpdates:NO];
这个方法制作了一个UIView的副本,如果我们希望视图在执行动画之前保存现在的外观,以备之后使用(动画中视图可能会被子视图遮盖或者发生其他一些变化),该方法就特别方便。
afterUpdates参数表示是否在所有效果应用在视图上了以后再获取快照。例如,如果该参数为NO,则立马获取该视图现在状态的快照,反之,以下代码只能得到一个空白快照:
[view snapshotViewAfterScreenUpdates:YES];
[view setAlpha:0.0];
由于我们设置afterUpdates参数为YES,而视图的透明度值被设置成了0,所以方法将在该设置应用在视图上了之后才进行快照,于是乎屏幕空空如也。另外就是……你可以对快照再进行快照……继续快照……
最后,主要代码已经给出,我已经上传完整代码了,大家有意向的可以去下载下来看看(唉,主要是CSDN不支持gif动态图,好蛋疼,朋友在博客园的博客都支持,但是我又不喜欢博客园的风格,看来以后自己弄个域名博客是王道,后续我也会把我的一些代码分享到github上)
@转载请注明,转自iOS@迷糊小书童
@待续.....下一章给出自定义ViewController容器的转场.
如果您想提高自己的技术水平,认识同行朋友、开拓技术视野,请加入QQ群:
Powered by
& 2014 &&&联系本站:请使用支持脚本的浏览器!
该日志尚未公开,你暂时不能查看。博主可在此
不如去逛逛吧。
网易公司版权所有&&&}

我要回帖

更多关于 ios present push效果 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信