0

I have a custom alterviewcontroller which subclasses UIViewController. It works great in apps that are portrait, but in landscape, it's running into issues with the frame orientation. I've tried a bunch of fixes, but none seem to be getting it right.

In the current version, it displays correctly but the main view is the wrong size, so the buttons that are outside of that view are not clickable.

In this image, the Next Turn button is not Clickable, the Go to Black button is. This is landscape left.

screenshot of alert

.h file

#import <UIKit/UIKit.h>
#import "SPRTitleFontLabel.h"

@protocol SPRAlertViewControllerDelegate;

@interface SPRAlertViewController : UIViewController

@property (nonatomic, weak) id <SPRAlertViewControllerDelegate> delegate;

@property (weak, nonatomic) IBOutlet UIView *alertview;
@property (weak, nonatomic) IBOutlet SPRTitleFontLabel *titleLabel;
@property (weak, nonatomic) IBOutlet UITextView *messageLabel;
@property (weak, nonatomic) IBOutlet UIButton *yesButton;
@property (weak, nonatomic) IBOutlet UIButton *noButton;
@property (weak, nonatomic) IBOutlet UIButton *okButton;

@property int tag;

-(void)setTitle:(NSString *)title message:(NSString *)message andButtonCount:(int)buttonCount;

- (IBAction)doDismiss:(id)sender;

- (void)show;

@end


@protocol SPRAlertViewControllerDelegate <NSObject>

- (void)alert:(SPRAlertViewController *)alert didDismissWithButtonClick:(int)buttonIndex;

@end

.m file

#import "SPRAlertViewController.h"
#import "SPRAudioHelper.h"

@interface SPRAlertViewController ()
{
    UIWindow *alertWindow;
}
@end

@implementation SPRAlertViewController

+(instancetype)new
{
    SPRAlertViewController *alvc = [super new];

    return alvc;
}


- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self)
    {
        alertWindow = [self windowWithLevel:UIWindowLevelAlert];

        if (!alertWindow)
        {
        //rotate the window frame to get the right orientation
            CGRect tempFrame = [UIScreen mainScreen].bounds;
            CGRect tempFrame2 = tempFrame;
            tempFrame2.size.height = tempFrame.size.width;
            tempFrame2.size.width = tempFrame.size.height;

            alertWindow = [[UIWindow alloc] initWithFrame:tempFrame2];


            alertWindow.windowLevel = UIWindowLevelAlert;

            [alertWindow makeKeyAndVisible];

            NSLog(@"window frame %@", NSStringFromCGRect(alertWindow.frame));

        }

        alertWindow.rootViewController = self;
    }
    return self;
}



- (void)setTitle:(NSString *)title message:(NSString *)message andButtonCount:(int)buttonCount
{
    self.titleLabel.text = title;
    self.messageLabel.text = message;

    if (buttonCount == 1)
    {
        self.yesButton.hidden = YES;
        self.noButton.hidden = YES;
        self.okButton.hidden = NO;
    }
    else
    {
        self.yesButton.hidden = NO;
        self.noButton.hidden = NO;
        self.okButton.hidden = YES;
    }

    CGRect frame = self.messageLabel.frame;
    CGSize size = [self.messageLabel sizeThatFits:CGSizeMake(self.messageLabel.frame.size.width, FLT_MAX)];



    frame.size.height = size.height;


    self.messageLabel.frame = frame;
    [self.messageLabel setNeedsDisplay];


    float buttonTop = frame.size.height + frame.origin.y;

    self.yesButton.frame = CGRectMake(self.yesButton.frame.origin.x, buttonTop, self.yesButton.frame.size.width, self.yesButton.frame.size.height);
    self.noButton.frame = CGRectMake(self.noButton.frame.origin.x, buttonTop, self.noButton.frame.size.width, self.noButton.frame.size.height);
    self.okButton.frame = CGRectMake(self.okButton.frame.origin.x, buttonTop, self.okButton.frame.size.width, self.okButton.frame.size.height);

    self.alertview.frame = CGRectMake(self.alertview.frame.origin.x, self.alertview.frame.origin.y, self.alertview.frame.size.width, buttonTop+55);

    NSLog(@"parent frame %@", NSStringFromCGRect(self.parentViewController.view.frame));
    NSLog(@"view frame %@", NSStringFromCGRect(self.view.frame));
    NSLog(@"alert frame %@", NSStringFromCGRect(self.alertview.frame));
    NSLog(@"button frame %@", NSStringFromCGRect(self.yesButton.frame));

}

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


    UIInterpolatingMotionEffect* m1 =
    [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"center.x"
                                                    type:UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis];
    m1.maximumRelativeValue = @0.0;
    m1.minimumRelativeValue = @0.0;
    UIInterpolatingMotionEffect* m2 =
    [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"center.y"
                                                    type:UIInterpolatingMotionEffectTypeTiltAlongVerticalAxis];
    m2.maximumRelativeValue = @20.0;
    m2.minimumRelativeValue = @-20.0;
    UIMotionEffectGroup* g = [UIMotionEffectGroup new];
    g.motionEffects = @[m1,m2];
    [self.alertview addMotionEffect:g];

}

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


- (void)show
{
    CGRect tempFrame = [UIScreen mainScreen].bounds;
    CGRect tempFrame2 = tempFrame;
    tempFrame2.size.height = tempFrame.size.width;
    tempFrame2.size.width = tempFrame.size.height;

    self.alertview.center = CGPointMake(CGRectGetMidX(tempFrame2), CGRectGetMidY(tempFrame2));

    self.alertview.transform = CGAffineTransformMakeScale(1,1.6);
    self.alertview.alpha = 0;
    self.view.alpha = 0;

    [UIView animateWithDuration:0.1 animations:^{
        self.view.alpha = 1;
    }
                     completion:
     ^(BOOL finished){

                         [UIView animateWithDuration:0.25 animations:^{
                             self.alertview.alpha = 1;
                             self.alertview.transform = CGAffineTransformIdentity;
                         }];
                     }
     ];



}

- (UIWindow *)windowWithLevel:(UIWindowLevel)windowLevel
{
    NSArray *windows = [[UIApplication sharedApplication] windows];
    for (UIWindow *window in windows) {
        if (window.windowLevel == windowLevel) {
            return window;
        }
    }
    return nil;
}




- (IBAction)doDismiss:(id)sender
{

//    [[SPRAudioHelper sharedHelper] playSoundFromTag:lightClick];


    NSLog(@"check");

    [UIView animateWithDuration:0.25 animations:^{

        self.alertview.transform = CGAffineTransformScale(self.alertview.transform, 1,0.5);
        self.alertview.alpha = 0;

    }completion:^(BOOL finished)
    {
        [UIView animateWithDuration:0.1 animations:^{
            self.view.alpha = 0;
        }completion:^(BOOL finished)
         {

         [alertWindow removeFromSuperview];
         alertWindow = nil;

             if (sender == self.yesButton)
                 [self.delegate alert:self didDismissWithButtonClick:1];
             else
                 [self.delegate alert:self didDismissWithButtonClick:0];

         }];

    }];

}
@end

Here's the NSLog results:

2014-07-10 10:59:18.603 Damage Report Timer[5166:60b] window frame {{0, 0}, {568, 320}} 2014-07-10 10:59:18.720 Damage Report Timer[5166:60b] parent frame {{0, 0}, {0, 0}} 2014-07-10 10:59:18.722 Damage Report Timer[5166:60b] view frame {{0, 0}, {320, 568}} 2014-07-10 10:59:18.724 Damage Report Timer[5166:60b] alert frame {{0,51}, {568, 146.5}} 2014-07-10 10:59:18.726 Damage Report Timer[5166:60b] button frame {{101, 91.5}, {150, 50}}

stevenpaulr
  • 306
  • 2
  • 8
  • 1
    Have you tried doing anything to fix it? I don't see any AutoResizingMasks, mentioning of constraints, or even the callbacks for didOrientationChange. – LyricalPanda Jul 10 '14 at 16:47
  • I've done quite a bit of switching the height and width of the frames. I'm not allowing portrait mode in this app, so I didn't think I would need any orientation change stuff. – stevenpaulr Jul 10 '14 at 16:53
  • As for auto resize masks, both the self.view and alertview are set to lock their distance from edge and resize. Putting NSLog results above – stevenpaulr Jul 10 '14 at 17:01

1 Answers1

0

I figured it out after doing more and more digging. I was really making the whole thing way more complicated than it is. 2 functions needed to be fixed, here's the updated functions:

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self)
    {
        alertWindow = [self windowWithLevel:UIWindowLevelAlert];

        if (!alertWindow)
        {
            alertWindow = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];

            alertWindow.windowLevel = UIWindowLevelAlert;

            [alertWindow makeKeyAndVisible];

        }

        alertWindow.rootViewController = self;
    }
    return self;
}

and

- (void)show
{
    CGRect frame = self.view.bounds;


    self.alertview.center = CGPointMake(CGRectGetMidX(frame), CGRectGetMidY(frame));

    self.alertview.transform = CGAffineTransformMakeScale(1,1.6);
    self.alertview.alpha = 0;
    self.view.alpha = 0;

    [UIView animateWithDuration:0.1 animations:^{
        self.view.alpha = 1;
    }
                     completion:
     ^(BOOL finished){

                         [UIView animateWithDuration:0.25 animations:^{
                             self.alertview.alpha = 1;
                             self.alertview.transform = CGAffineTransformIdentity;
                         }];
                     }
     ];
}

Originally since show was centering the view on mainscreen bounds, it was putting it in the wrong place, since mainscreen bounds doesn't get updated on rotation. Then I made the mistake of resizing the window to accommodate for that. Which made buttons no longer be in the window.

stevenpaulr
  • 306
  • 2
  • 8