gpt4 book ai didi

ios - 取消呈现的 View Controller 的交互式关闭转换后, View Controller 不会自动旋转

转载 作者:可可西里 更新时间:2023-11-01 03:17:33 25 4
gpt4 key购买 nike

我有一个 View Controller ,使用 modalPresentationStyle = UIModalPresentationCustom 呈现另一个 View Controller 。事物的设置使得呈现 View Controller 的 View 的一部分显示在呈现 View Controller 的 View 下方。在这种状态下,呈现 View Controller 仍然正确处理自动旋转,我使用自动布局处理呈现 View Controller 的旋转。

我现在正在尝试使用 iOS 7 的自定义 View Controller 转换 API 以交互方式关闭呈现的 View Controller 。它的工作原理是,当交互式关闭被取消时,自动旋转的处理停止工作。 (它在呈现的 View Controller 稍后被关闭后再次工作。)为什么会发生这种情况,我该如何解决这个问题?

编辑:这是您可以运行以演示问题的代码。从下方弹出一个 View ,您可以通过向下滑动将其关闭。如果您通过不一直向下滑动来取消取消,则呈现 View Controller 的 View 将不再响应旋转,并且呈现 View Controller 的 View 布局困惑。

编辑:这是作为 Xcode 项目的以下代码的链接: https://drive.google.com/file/d/0BwcBqUuDfCG2YlhVWE1QekhUWlk/edit?usp=sharing

对于大量代码转储,我深表歉意,但我不知道我做错了什么。这是正在发生的事情的草图:ViewController1 呈现 ViewController2ViewController1 实现了 UIViewControllerTransitioningDelegate,因此它返回过渡的动画/交互 Controller 。 ViewController2 有一个平移手势识别器,可以驱动交互式关闭;它实现了 UIViewControllerInteractiveTransitioning 来充当解雇的交互式 Controller 。它还保留对动画 Controller 的引用,以便在用户将 View 向下拖动得足够远时关闭以完成过渡。最后,有两个动画 Controller 对象。 PresentAnimationController 设置自动布局约束来处理呈现的 View Controller View 的旋转,DismissAnimationController 完成关闭。

ViewController1.h

#import <UIKit/UIKit.h>

@interface ViewController1 : UIViewController <UIViewControllerTransitioningDelegate>

@end

ViewController1.m

#import "ViewController1.h"

#import "ViewController2.h"

#import "PresentAnimationController.h"
#import "DismissAnimationController.h"

@implementation ViewController1

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
self.title = @"View 1";

self.navigationItem.prompt = @"Press “Present” and then swipe down to dismiss.";
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Present" style:UIBarButtonItemStylePlain target:self action:@selector(pressedPresentButton:)];
}
return self;
}

- (void)viewDidLoad
{
[super viewDidLoad];

self.view.backgroundColor = [UIColor whiteColor];

// Some subview just to check if layout is working.
UIView * someSubview = [[UIView alloc] initWithFrame:self.view.bounds];
someSubview.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
someSubview.backgroundColor = [UIColor orangeColor];
someSubview.layer.borderColor = [UIColor redColor].CGColor;
someSubview.layer.borderWidth = 2;
[self.view addSubview:someSubview];
}

// --------------------

- (void)pressedPresentButton:(id)sender
{
ViewController2 * presentedVC = [[ViewController2 alloc] initWithNibName:nil bundle:nil];

presentedVC.modalPresentationStyle = UIModalPresentationCustom;
presentedVC.transitioningDelegate = self;

[self presentViewController:presentedVC animated:YES completion:nil];
}

// --------------------

// View Controller Transitioning Delegate Methods.

- (id <UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source
{
return [[PresentAnimationController alloc] init];;
}

- (id <UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed
{
DismissAnimationController * animationController = [[DismissAnimationController alloc] init];

ViewController2 * presentedVC = (ViewController2 *)self.presentedViewController;

if (presentedVC.dismissalIsInteractive) {
presentedVC.dismissAnimationController = animationController;
}

return animationController;
}

- (id <UIViewControllerInteractiveTransitioning>)interactionControllerForPresentation:(id <UIViewControllerAnimatedTransitioning>)animator
{
return nil;
}

- (id <UIViewControllerInteractiveTransitioning>)interactionControllerForDismissal:(id <UIViewControllerAnimatedTransitioning>)animator
{
ViewController2 * presentedVC = (ViewController2 *)self.presentedViewController;

if (presentedVC.dismissalIsInteractive) {
return presentedVC;
}
else {
return nil;
}
}

@end

ViewController2.h

#import <UIKit/UIKit.h>

#import "DismissAnimationController.h"

@interface ViewController2 : UIViewController <UIViewControllerInteractiveTransitioning>

@property (weak, nonatomic) UIView * contentView;

@property (nonatomic, readonly) BOOL dismissalIsInteractive;
@property (strong, nonatomic) DismissAnimationController * dismissAnimationController;

@end

ViewController2.m

#import "ViewController2.h"

@interface ViewController2 ()

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

@end

@implementation ViewController2

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
_dismissalIsInteractive = NO;
}
return self;
}

- (void)viewDidLoad
{
[super viewDidLoad];

self.view.backgroundColor = [UIColor colorWithWhite:0 alpha:0.5];

// Set up content view.
CGRect frame = UIEdgeInsetsInsetRect(self.view.bounds, UIEdgeInsetsMake(15, 15, 15, 15));
UIView * contentView = [[UIView alloc] initWithFrame:frame];
self.contentView = contentView;
contentView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
contentView.backgroundColor = [UIColor cyanColor];
contentView.layer.borderColor = [UIColor blueColor].CGColor;
contentView.layer.borderWidth = 2;
[self.view addSubview:contentView];

// Set up pan dismissal gesture recognizer.
UIPanGestureRecognizer * panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(dismissalPan:)];
[self.view addGestureRecognizer:panGesture];
}

// --------------------

- (void)dismissalPan:(UIPanGestureRecognizer *)panGesture
{
switch (panGesture.state) {
case UIGestureRecognizerStateBegan: {
_dismissalIsInteractive = YES;

[self.presentingViewController dismissViewControllerAnimated:YES completion:nil];

break;
}

case UIGestureRecognizerStateChanged: {
CGPoint translation = [panGesture translationInView:self.view];

CGFloat percent;
if (translation.y > 0) {
percent = translation.y / self.view.bounds.size.height;
percent = MIN(percent, 1.0);
}
else {
percent = 0;
}

// Swiping content view down.
CGPoint center;
center.x = CGRectGetMidX(self.view.bounds);
center.y = CGRectGetMidY(self.view.bounds);
if (translation.y > 0) {
center.y += translation.y; // Only allow swiping down.
}
self.contentView.center = center;

self.view.backgroundColor = [UIColor colorWithWhite:0 alpha:(0.5 * (1.0 - percent))];

[self.transitionContext updateInteractiveTransition:percent];

break;
}

case UIGestureRecognizerStateEnded: // Fall through.
case UIGestureRecognizerStateCancelled: {
_dismissalIsInteractive = NO;

id<UIViewControllerContextTransitioning> transitionContext = self.transitionContext;
self.transitionContext = nil;

DismissAnimationController * dismissAnimationController = self.dismissAnimationController;
self.dismissAnimationController = nil;

CGPoint translation = [panGesture translationInView:self.view];

if (translation.y > 100) {
// Complete dismissal.

[dismissAnimationController animateTransition:transitionContext];
}
else {
// Cancel dismissal.

void (^animations)() = ^() {
CGPoint center;
center.x = CGRectGetMidX(self.view.bounds);
center.y = CGRectGetMidY(self.view.bounds);
self.contentView.center = center;

self.view.backgroundColor = [UIColor colorWithWhite:0 alpha:0.5];
};
void (^completion)(BOOL) = ^(BOOL finished) {
[transitionContext cancelInteractiveTransition];
[transitionContext completeTransition:NO];
};
[UIView animateWithDuration:0.5 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:animations completion:completion];
}

break;
}

default: {

break;
}
}
}

// --------------------

// View Controller Interactive Transitioning Methods.

- (void)startInteractiveTransition:(id<UIViewControllerContextTransitioning>)transitionContext
{
self.transitionContext = transitionContext;
}

@end

PresentAnimationController.h

#import <Foundation/Foundation.h>

@interface PresentAnimationController : NSObject <UIViewControllerAnimatedTransitioning>

@end

PresentAnimationController.m

#import "PresentAnimationController.h"

#import "ViewController2.h"

@implementation PresentAnimationController

- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext
{
UIViewController * fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
ViewController2 * toVC = (ViewController2 *)[transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];

UIView * containerView = [transitionContext containerView];

CGPoint toCenter = fromVC.view.center;
CGRect toBounds = fromVC.view.bounds;

toVC.view.center = toCenter;
toVC.view.bounds = toBounds;
[toVC.view layoutIfNeeded];

[containerView addSubview:fromVC.view];
[containerView addSubview:toVC.view];

CGRect contentViewEndFrame = toVC.contentView.frame;

CGRect contentViewStartFrame = contentViewEndFrame;
contentViewStartFrame.origin.y += contentViewStartFrame.size.height;
toVC.contentView.frame = contentViewStartFrame;

UIColor * endBackgroundColor = toVC.view.backgroundColor;

toVC.view.backgroundColor = [UIColor clearColor];

void (^animations)() = ^() {
toVC.contentView.frame = contentViewEndFrame;

toVC.view.backgroundColor = endBackgroundColor;
};
void (^completion)(BOOL) = ^(BOOL finished) {
toVC.view.autoresizingMask = UIViewAutoresizingNone;

toVC.view.translatesAutoresizingMaskIntoConstraints = NO;

NSLayoutConstraint * centerXConstraint = [NSLayoutConstraint constraintWithItem:toVC.view
attribute:NSLayoutAttributeCenterX
relatedBy:NSLayoutRelationEqual
toItem:fromVC.view
attribute:NSLayoutAttributeCenterX
multiplier:1
constant:0];
NSLayoutConstraint * centerYConstraint = [NSLayoutConstraint constraintWithItem:toVC.view
attribute:NSLayoutAttributeCenterY
relatedBy:NSLayoutRelationEqual
toItem:fromVC.view
attribute:NSLayoutAttributeCenterY
multiplier:1
constant:0];
NSLayoutConstraint * widthConstraint = [NSLayoutConstraint constraintWithItem:toVC.view
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:fromVC.view
attribute:NSLayoutAttributeWidth
multiplier:1
constant:0];
NSLayoutConstraint * heightConstraint = [NSLayoutConstraint constraintWithItem:toVC.view
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:fromVC.view
attribute:NSLayoutAttributeHeight
multiplier:1
constant:0];
[containerView addConstraint:centerXConstraint];
[containerView addConstraint:centerYConstraint];
[containerView addConstraint:widthConstraint];
[containerView addConstraint:heightConstraint];

[transitionContext completeTransition:YES];
};
[UIView animateWithDuration:0.5 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:animations completion:completion];
}

- (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext
{
return 0.5;
}

@end

DismissAnimationController.h

#import <Foundation/Foundation.h>

@interface DismissAnimationController : NSObject <UIViewControllerAnimatedTransitioning>

@end

DismissAnimationController.m

#import "DismissAnimationController.h"

#import "ViewController2.h"

@implementation DismissAnimationController

- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext
{
ViewController2 * fromVC = (ViewController2 *)[transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
UIViewController * toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];

UIView * containerView = [transitionContext containerView];

[containerView addSubview:toVC.view];
[containerView addSubview:fromVC.view];

void (^animations)() = ^() {
CGRect contentViewEndFrame = fromVC.contentView.frame;
contentViewEndFrame.origin.y = CGRectGetMaxY(fromVC.view.bounds) + 15;
fromVC.contentView.frame = contentViewEndFrame;

fromVC.view.backgroundColor = [UIColor clearColor];
};
void (^completion)(BOOL) = ^(BOOL finished) {
if ([transitionContext isInteractive]) {
[transitionContext finishInteractiveTransition];
}

[transitionContext completeTransition:YES];
};
[UIView animateWithDuration:0.5 delay:0 options:UIViewAnimationOptionCurveLinear animations:animations completion:completion];
}

- (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext
{
return 0.5;
}

@end

AppDelegate.m

#import "AppDelegate.h"

#import "ViewController1.h"

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

ViewController1 * vc = [[ViewController1 alloc] initWithNibName:nil bundle:nil];
UINavigationController * nav = [[UINavigationController alloc] initWithRootViewController:vc];
self.window.rootViewController = nav;

[self.window makeKeyAndVisible];
return YES;
}

@end

最佳答案

我想我发现了你的问题。在您的 PresentAnimationController.m 中指定 toVC.view.translatesAutoresizingMaskIntoConstraints = NO; 并在您设置的完成 block 中设置所有约束- (void)animateTransition:

注释该行和所有约束以及 addConstraint: 调用,它应该可以工作

编辑:

刚刚看到它仅在取消手势时起作用,而不是在最初显示 View 时起作用。注释掉完成 block 中的所有内容,除了

[transitionContext completeTransition:YES];

关于ios - 取消呈现的 View Controller 的交互式关闭转换后, View Controller 不会自动旋转,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25213023/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com