2014-09-21 13 views
5

Tôi có một UIViewController bên trong một UINavigationController, được trình bày một cách khiêm tốn trên một iPad với iOS8. Tôi đang sử dụngDi chuyển một UIViewController được trình bày một cách bình thường khi bàn phím xuất hiện trên iPad với iOS8

self.myNavController.modalPresentationStyle = UIModalPresentationFormSheet; 

Trong trình điều khiển chế độ xem của tôi, tôi có trường văn bản. Do thiết kế giao diện người dùng của bộ điều khiển chế độ xem, khi người dùng chạm vào trường văn bản và bàn phím xuất hiện, tôi cần di chuyển bộ điều khiển chế độ xem lên trên màn hình. Trên iOS7, tôi đã tạo hoạt ảnh thay đổi cho

self.myNavController.view.superview.frame.origin 

để di chuyển bộ điều khiển chế độ xem và quay xuống. Điều này làm việc tốt.

Tuy nhiên, trên iOS8, tính năng này không còn hoạt động nữa. Trong thực tế, kỳ quặc, hành vi là để bộ điều khiển chế độ xem di chuyển một chút xuống và sau đó sao lưu (tất cả khi tôi chỉ định self.myNavController.view.superview.frame.origin một CGPoint với nhỏ hơn toạ độ Y có giá trị).

Ban đầu, tôi đã làm việc từ một gợi ý được đưa ra trong câu hỏi này SO Resize ModalViewController and position it at center in iOS 7

Và gần đây tôi đã cố gắng đề nghị được đưa ra trong Moving dialog up when keyboard present works except when ipad is turned around nhưng để ít kết quả. Trên thực tế, với ý tưởng biến đổi trong một câu trả lời ở đó, tôi có thể ít nhất có được bộ điều khiển xem để di chuyển đúng hướng (tức là, lên), nhưng nó không ở đó. Nó nhanh chóng quay trở lại.

Ý tưởng?

Trả lời

2

Chúng tôi sẽ thực hiện, ngay bây giờ tôi đã được nói. Tôi đã tìm ra điều này. Điều này có thể được giải quyết bằng cách sử dụng UIPresentationController mới, iOS8. Tôi sẽ đưa ra một số mã mẫu dưới đây. Và cố gắng liên kết trong tệp zip dự án đang hoạt động sau.

Trình điều khiển chế độ xem đầu tiên là bộ điều khiển chế độ xem gốc của ứng dụng mẫu. Mã cho ChangeFrameTransitioningDelegate theo sau. "Hộp thoại" chỉ là một lớp trình điều khiển chế độ xem trống.

// 
// ViewController.m 
// TestPresentationController 
// 
// Created by Christopher Prince on 9/21/14. 
// Copyright (c) 2014 Spastic Muffin, LLC. Use at your own discretion. 
// 

#import "ViewController.h" 
#import "ChangeFrameTransitioningDelegate.h" 
#import "Dialog.h" 

@interface ViewController() 

@end 

@implementation ViewController 

- (void)viewDidLoad { 
    [super viewDidLoad]; 
    // Do any additional setup after loading the view, typically from a nib. 
} 

- (void) viewDidAppear:(BOOL)animated; 
{ 
    [super viewDidAppear:animated]; 

    ChangeFrameTransitioningDelegate *td = [ChangeFrameTransitioningDelegate new]; 
    td.viewControllerFrame = CGRectMake(100, 0, 100, 100); 

    Dialog *d = [Dialog new]; 
    // Just to make the VC stand out. 
    d.view.backgroundColor = [UIColor greenColor]; 

    // Need to make this custom in order to have the presentationControllerForPresentedViewController method of the transitioning delegate called. 
    d.modalPresentationStyle = UIModalPresentationCustom; 

    d.modalTransitionStyle = UIModalTransitionStyleCoverVertical; 
    d.transitioningDelegate = td; 

    [self presentViewController:d animated:YES completion:^{ 

     // Any time after the view controller is presented you can change the 
     // viewControllerFrame property to change the size and/or position of the 
     // presented view controller. 
     [UIView animateWithDuration:0.5 animations:^{ 
      td.viewControllerFrame = CGRectMake(100, 800, 100, 100); 
     }]; 
    }]; 
} 

- (void)didReceiveMemoryWarning { 
    [super didReceiveMemoryWarning]; 
    // Dispose of any resources that can be recreated. 
} 

@end 
// 
// ChangeFrameTransitioningDelegate.h 
// TestPresentationController 
// 
// Created by Christopher Prince on 9/21/14. 
// Copyright (c) 2014 Spastic Muffin, LLC. Use at your own discretion. 
// 

// For iOS8 and later, use this to change the size/position of a view controller after it has been presented. See TextPresentationController example. 
#import <Foundation/Foundation.h> 
#import <UIKit/UIKit.h> 

@interface ChangeFrameTransitioningDelegate : NSObject<UIViewControllerTransitioningDelegate> 

// This is the size and position that the PresentationController used by this class will use when its frameOfPresentedViewInContainerView method is called. So, this is the size and position that your view controller will have. 
@property (nonatomic) CGRect viewControllerFrame; 

@end 
// 
// ChangeFrameTransitioningDelegate.m 
// TestPresentationController 
// 
// Created by Christopher Prince on 9/21/14. 
// Copyright (c) 2014 Spastic Muffin, LLC. Use at your own discretion. 
// 

// Some help from http://stackoverflow.com/questions/25903412/editing-bounds-of-uiview-when-presenting-hides-keyboard-in-ios-8 
// http://stackoverflow.com/questions/25811199/ios-8-change-the-size-of-presented-modal-view-controller 
// Some code from https://developer.apple.com/devcenter/download.action?path=/wwdc_2014/wwdc_2014_sample_code/lookinsidepresentationcontrollersadaptivityandcustomanimatorobjects.zip (though, beware, this example doesn't work straight out of the box). 
// And see http://stackoverflow.com/questions/25957343/moving-a-modally-presented-uiviewcontroller-up-when-keyboard-appears-on-ipad-wit 

#ifndef SPASLogDetail 
#define SPASLogDetail NSLog 
#endif 

#import "ChangeFrameTransitioningDelegate.h" 

@interface PresentationController : UIPresentationController 
{ 
    UIView *_dimmingView; 
} 
// This is the size and position that the PresentationController will use when its frameOfPresentedViewInContainerView method is called. 
@property (nonatomic) CGRect currentFrame; 
@end 

@implementation PresentationController 

- (instancetype)initWithPresentedViewController:(UIViewController *)presentedViewController presentingViewController:(UIViewController *)presentingViewController; 
{ 
    self = [super initWithPresentedViewController:presentedViewController presentingViewController:presentingViewController]; 
    // Some random default size. 
    self.currentFrame = CGRectMake(0, 0, 100, 100); 
    [self prepareDimmingView]; 
    return self; 
} 

// 4/22/15; Added, for rotation. 
- (void) viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator; 
{ 
    CGSize increasedSize = size; 
    // 4/22/15; I'm getting some odd effects: In a rotation transition from landscape to portrait, the RHS goes white momentarily, and from portrait to landscape, the bottom goes white momentarily. A hack, but increase the size of the dimming view to get around this. 
    increasedSize.width *= 1.5; 
    increasedSize.height *= 1.5; 
    _dimmingView.frameSize = increasedSize; 

    // There appears to be no transitionCoordinator available for this "transition". Therefore using the regular UIView animation, below. 
    /* 
    if([self.presentedViewController transitionCoordinator]) 
    { 
     [[self.presentedViewController transitionCoordinator] animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context) { 
      recenterViewController(); 
     } completion:nil]; 
    } 
    else 
    { 
     recenterViewController(); 
    }*/ 

    // 4/23/15; See [1]. Given that I've turned off resizing with the autoresizingMask, this has messed up the repositioning of the (x, y) coordinate of the presentedViewController. Make up for that here. 
    [UIView animateWithDuration: coordinator.transitionDuration animations:^{ 
     // I'm assuming the size here refers to the entire window. 
     CGPoint center = CGPointMake(size.width/2.0, size.height/2.0); 
     self.presentedViewController.view.center = center; 
    } completion:nil]; 
} 

- (void)presentationTransitionWillBegin 
{ 
    UIView* containerView = [self containerView]; 

    // 4/23/15; So, this seems to be related to my modal view resizing problem. When I disable autoresizesSubviews, I stop the resizing during the rotation. HOWEVER, this is at the price of two additional problems: (a) the (x, y) coordinate of the modal stops being changed during the rotation, and (b) the animation of the background (_dimmingView?) starts looking funky during the rotation. WHICH makes sense. The containerView size is the full window. 
    //containerView.autoresizesSubviews = NO; 

    UIViewController* presentedViewController = [self presentedViewController]; 

    // [1] 4/23/15; This is better. The _dimmingView animation is preserved. The (x, y) position of the presentedViewController, however isn't right after the rotation. 
    presentedViewController.view.autoresizingMask = UIViewAutoresizingNone; 

    [_dimmingView setFrame:[containerView bounds]]; 
    [_dimmingView setAlpha:0.0]; 

    [containerView insertSubview:_dimmingView atIndex:0]; 

    void (^setAlpha)() = ^{ 
     [_dimmingView setAlpha:1.0]; 
    }; 

    if([presentedViewController transitionCoordinator]) 
    { 
     [[presentedViewController transitionCoordinator] animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context) { 
      setAlpha(); 
     } completion:nil]; 
    } 
    else 
    { 
     setAlpha(); 
    } 
} 

- (void)dismissalTransitionWillBegin 
{ 
    void (^resetAlpha)() = ^{ 
     [_dimmingView setAlpha:0.0]; 
    }; 

    if([[self presentedViewController] transitionCoordinator]) 
    { 
     [[[self presentedViewController] transitionCoordinator] animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context) { 
      resetAlpha(); 
     } completion:nil]; 
    } 
    else 
    { 
     resetAlpha(); 
    } 
} 

- (CGRect)frameOfPresentedViewInContainerView 
{ 
    SPASLogDetail(@"frameOfPresentedViewInContainerView: %@", NSStringFromCGRect(self.currentFrame)); 
    return self.currentFrame; 
} 

- (void) setCurrentFrame:(CGRect)currentFrame 
{ 
    _currentFrame = currentFrame; 
    // This is the important part for changing the frame of the presented view controller *after* the view is presented. For some odd reason, its not right to change the frame of the containerView. 
    self.presentedView.frame = currentFrame; 
} 

- (void) containerViewWillLayoutSubviews; 
{ 
    SPASLogDetail(@"containerViewWillLayoutSubviews"); 
} 

- (void)prepareDimmingView 
{ 
    _dimmingView = [[UIView alloc] init]; 
    [_dimmingView setBackgroundColor:[UIColor colorWithWhite:0.0 alpha:0.4]]; 
    [_dimmingView setAlpha:0.0]; 

    //UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dimmingViewTapped:)]; 
    //[_dimmingView addGestureRecognizer:tap]; 
} 

/* 
- (void)dimmingViewTapped:(UIGestureRecognizer *)gesture 
{ 
    if([gesture state] == UIGestureRecognizerStateRecognized) 
    { 
     [[self presentingViewController] dismissViewControllerAnimated:YES completion:NULL]; 
    } 
}*/ 

@end 

@interface ChangeFrameTransitioningDelegate() 
@property (nonatomic, strong) PresentationController *presentationController; 
@end 

@implementation ChangeFrameTransitioningDelegate 

- (instancetype) init; 
{ 
    self = [super init]; 
    return self; 
} 

- (UIPresentationController *)presentationControllerForPresentedViewController:(UIViewController *)presented presentingViewController:(UIViewController *)presenting sourceViewController:(UIViewController *)source 
{ 
    self.presentationController = [[PresentationController alloc] initWithPresentedViewController:presented presentingViewController:presenting]; 
    self.presentationController.currentFrame = self.viewControllerFrame; 

    return self.presentationController; 
} 

- (void) setViewControllerFrame:(CGRect)viewControllerFrame 
{ 
    _viewControllerFrame = viewControllerFrame; 
    self.presentationController.currentFrame = viewControllerFrame; 
} 

@end 
+0

Hmmmm. Tôi đang gặp vấn đề với điều này. Nó đi kèm với xoay thiết bị. Các kích thước hộp thoại phương thức không được giữ nguyên khi phương thức được hiển thị và bạn xoay thiết bị. –

+0

Tôi vừa thêm một số thay đổi. Xem các nhận xét gần đây của tôi trong mã. Tôi nghĩ tôi đã sửa nó. –

Các vấn đề liên quan