0

Hi i am very new for Auto-layouts and in my project i have added Two UIViews programmatically using Auto-layouts and i have added two UIButton which are Next and Back button and when i click Next button i push MyFirst UIView to second UIView using UIView animations and when i click Back button i push back from Second UIView to First UIView ok Everything is all right based on my code

But here my main problem is when i change First UIView orientation in simulator at portrait to landscape then Second UIView overlapped on my First UIView, And i know that it is must be Constrains issue i mean i have to remove and adding Constraints each time when we change Orientation for this i have tried below code but that's not working please help me and for this i have tried since long time but no one saying right answers using constrains

when we run program at portrait mode screen is coming like image1 and when i change land scape mode second UIview overlapped on my first UIview like below second image that's my main problem

my code:-

  #import "SubViewController.h"


@interface SubViewController (){

    UIButton * GoNext;
    UIButton * GoBack;

    NSArray * FHorizental;
    NSArray * FVertical;

    NSArray * SHorizental;
    NSArray * SVertical;
}

@end

@implementation SubViewController

@synthesize MyFisrtView,MySecondView;

- (void)viewDidLoad {

    [super viewDidLoad];

    NSLog(@"How are you");

    [self callAutolayouts];

    MyFisrtView.hidden = NO;
    MySecondView.hidden = YES;
}

-(void)callAutolayouts{

    NSLog(@"Hi");

    MyFisrtView = [[UIView alloc] init];
    MyFisrtView.backgroundColor = [UIColor orangeColor];
    MyFisrtView.translatesAutoresizingMaskIntoConstraints = NO;
    [self.view addSubview:MyFisrtView];

    MySecondView = [[UIView alloc] init];
    MySecondView.backgroundColor = [UIColor lightGrayColor];
    MySecondView.translatesAutoresizingMaskIntoConstraints = NO;
    [self.view addSubview:MySecondView];

    //Applying autolayouts for  MyFirstView and MySecondView

    NSDictionary * HeaderDictionary = NSDictionaryOfVariableBindings(MyFisrtView,MySecondView);

    //Appliying Autolayouts for FirstView

    FHorizental =[NSLayoutConstraint constraintsWithVisualFormat:[NSString stringWithFormat:@"H:|-0-[MyFisrtView]-0-|"]
                                                         options:0
                                                         metrics:nil
                                                           views:HeaderDictionary];


    FVertical = [NSLayoutConstraint constraintsWithVisualFormat:[NSString stringWithFormat:@"V:|-0-[MyFisrtView]-0-|"]
                                                        options:0
                                                        metrics:nil
                                                          views:HeaderDictionary];

    [self.view addConstraints:FHorizental];
    [self.view addConstraints:FVertical];

    //Appliying Autolayouts for SEcondView

    SHorizental =[NSLayoutConstraint constraintsWithVisualFormat:[NSString stringWithFormat:@"H:|-0-[MySecondView]-0-|"]
                                                         options:0
                                                         metrics:nil
                                                           views:HeaderDictionary];


    SVertical = [NSLayoutConstraint constraintsWithVisualFormat:[NSString stringWithFormat:@"V:|-0-[MySecondView]-0-|"]
                                                        options:0
                                                        metrics:nil
                                                          views:HeaderDictionary];

    [self.view addConstraints:SHorizental];
    [self.view addConstraints:SVertical];


    GoNext = [UIButton buttonWithType: UIButtonTypeRoundedRect];
    GoNext.frame = CGRectMake(50, 50, 100, 18);
    [GoNext setTitle:@"Next" forState:UIControlStateNormal];
    [GoNext addTarget:self action:@selector(GoNext:) forControlEvents:UIControlEventTouchUpInside];
    GoNext.backgroundColor = [UIColor lightGrayColor];
    [MyFisrtView addSubview:GoNext];

    GoBack = [UIButton buttonWithType: UIButtonTypeRoundedRect];
    GoBack.frame = CGRectMake(50, 50, 100, 18);
    [GoBack setTitle:@"Back" forState:UIControlStateNormal];
    [GoBack addTarget:self action:@selector(GoBack:) forControlEvents:UIControlEventTouchUpInside];
    GoBack.backgroundColor = [UIColor orangeColor];
    [MySecondView addSubview:GoBack];
}

-(void)GoNext:(id)sender{

    MySecondView.hidden = NO;

    MySecondView.frame=CGRectMake(248, 0, self.view.frame.size.width, self.view.frame.size.height); // starting visible position

    [UIView animateWithDuration:0.5f
                          delay:0.0f
                        options:UIViewAnimationOptionBeginFromCurrentState
                     animations:^{

                         [self.view removeConstraints:self.view.constraints];
                         [self callAutolayouts];
                         [self.view setNeedsLayout];

                         [MySecondView setFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];   // final visible position

                     }
                     completion:nil];
}

-(void)GoBack:(id)sender{

    MySecondView.frame=CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height); // starting visible position

    [UIView animateWithDuration:0.5f
                          delay:0.0f
                        options:UIViewAnimationOptionBeginFromCurrentState
                     animations:^{

                         [self.view removeConstraints:self.view.constraints];
                         [self callAutolayouts];
                         [self.view setNeedsLayout];

                         [MySecondView setFrame:CGRectMake(MyFisrtView.frame.size.width, 0, self.view.frame.size.width, self.view.frame.size.height)];   // final visible position
                     }
                     completion:nil];
}

-(void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration{

    if(toInterfaceOrientation == UIInterfaceOrientationPortrait){

        NSLog(@"portrait");

         [self.view removeConstraints:self.view.constraints];

         [self callAutolayouts];

         [self.view setNeedsLayout];

    }

    else if(toInterfaceOrientation == UIInterfaceOrientationLandscapeRight) {

        NSLog(@"LandscapeRight");

        [self.view removeConstraints:self.view.constraints];

        [self callAutolayouts];

        [self.view setNeedsLayout];
    }

    else if(toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft) {

        NSLog(@"LandscapeLeft");

        [self.view removeConstraints:self.view.constraints];

        [self callAutolayouts];

        [self.view setNeedsLayout];
    }
}

@end

image1:-

enter image description here

image2:-

enter image description here

AbhiRam
  • 2,033
  • 7
  • 41
  • 94
  • i am also facing same problems AbhiRam and i like this Question –  Nov 18 '15 at 05:53
  • @AbhiRam what i understand is you want to display only one view in portrait mode (View with next) and in landscape mode you want to display both view (view with next and back) is that right ? – Jageen Nov 18 '15 at 07:18
  • there are two ways ti get rid out of this issue, make your interface with base layout (600,600) and take IBOutlet for height constraint and connect this height constraint to file owner and put your height constraint zero according to views and when you want to show your second and first view you can change your height constraint values like suppose IBOutlet NSLayoutConstraint *heightFirstView; [heightFirstView setConstant:0.0f] initially and when you want to overlap your first view change this constraint value in appropriate delegate methods – Latika Tiwari Nov 18 '15 at 07:23
  • Jaggen my meaning is when i click "Next" Button i want to move first UIView to second UIView and when "Back" Button i want push back to Second UIView to First UIView, And there when i change orientation at portrait to land scape then second UIView overlapped on my First UIView that is main issues here – AbhiRam Nov 18 '15 at 07:46
  • Latika Tiwari i am using autolayouts here programmatically and so please tell me what did i do thre mistack – AbhiRam Nov 18 '15 at 07:49

3 Answers3

0

First you have to remove the constraints and then add agin as you did in your question.

shlok
  • 113
  • 8
  • i don't have much knowlwdge about constraints that's i am posting this qiestion – AbhiRam Nov 18 '15 at 06:58
  • What part of the documentation didn't you understand? You read the documentation, right? And "you have to remove the constraints and then add again" is exactly the answer. – gnasher729 Nov 18 '15 at 09:57
  • well gnasher729 and i have updated my code add means removing and adding constraints when orientation is changing but that's not working can you please explain what what did i do threre wrong – AbhiRam Nov 18 '15 at 10:09
0

Based on your comments below I'm updating my answer but leaving the original below as it may help you or others down the road.

Your issue isn't really Auto Layout then, your real issue is an architecture design issue. Every view that comes onto screen should have a different view controller running it. It sounds like you are drawing one view that is double the width of the device, one half (I'm guessing the left half) has the next button on it while the other half includes the back button. As soon as your app runs on a screen with a different size this will break unless you are checking for the screen size. Even then it breaks (as you have seen) when the device is rotated.

You need to make two different view controller subclasses, one to run the 'Next' view and one for the 'Back' view then you will never have the both views onscreen because the device got rotated.

The really hard way to get the effect you want is to do it all in code like you've tried thus far. If there is some strange reason that you just have to code it all instead of using the storyboard that was included when you started the project you will need to look at the animation methods of UIView (specifically look at the documentation for + (void)transitionFromView: toView: duration: options: completion: if you want something like a flip or page curl). If you want to slide between the two views you should really look into UINavigationController as it does all that for you. The other option would be when the Next button gets pressed create the second view controller, who will create the second view, and set it's frame to be off screen. Then animate the frame of the view to the onscreen position. Back would have to animate the frame of the Back view off the screen again and remove the view. It will take a lot of code to get all of this working which will mean reading a lot of documentation, I highly recommend using a storyboard to take care of this issue.

If you want the easy way use the storyboard and drag out a second view controller. Add a button to each scene in whatever location you want them to be in and set the text as desired. Control drag from the Next button to the second scene and select the kind of transition you would like. Add the following code to the view controller running the view with the Next button

@IBAction func exitToViewController (sender: UIStoryboardSegue){ }

Control drag from the Back button to the Exit icon (top of the scene all the way to the right, it's red with a white box and an arrow point to the right) select exitToViewController. Select one of the scenes and select Editor -> Resolve Auto Layout Issues -> Reset To Suggested Constraints (the second one under all views). It takes five minutes to do and works wonderfully.

If you need help with any of the tasks mentioned in the Storyboard route consider finding a beginner level tutorial on Xcode (there is a pretty good overview class on Coursera.org that isn't terribly long but covers many of the basics called,Foundations of Objective-C App Development and it's free if you don't care about a verified certificate.

Original Answer

Is there a reason the UI has to be built programmatically? Building it in IB will make your life much easier as you can build the base version of the UI and then create overrides for specific size classes (look at the bottom of IB where it says w Any h Any and change the selection to be compact height). Once in the compact height make any modifications you need to the constraints and visibility of UI elements. The system should take care of things from there (you might have to manually hide and show the correct UI elements as need for the orientations). When building in IB one of the Assistant editors is preview. You can select various devices and change the orientation between landscape and portrait, this will allow you to see in real time what your view is going to do when run for real rather than making a change in code and then running the app again. You can add one of each device if you want and they can all have their own orientation allowing you to see the UI in landscape and portrait at the same time.

If it does has to be done in code and you have to actually remove the unused elements from the UI rather than hiding them you will have to set all the constraints for the landscape orientation every time the device rotates to that orientation, the same is true for the portrait orientation. The best thing to do is to make the constraint changes in an animation block rather than manually updating the frames, this will cause the views to animate into place (you can do any alpha adjustments at the same time to fade elements in and out).

theMikeSwan
  • 4,739
  • 2
  • 31
  • 44
  • so your saying that remove the unused elements from the UI rather than hiding them you will have to set all the constraints for the landscape orientation every time the device rotates to that orientation, can you explain me that through programatically please because i am very new for autolayouts – AbhiRam Nov 18 '15 at 07:54
  • Based on your additional comments it sounds like what you actually want to do is have the app start with `view A` on screen wether the phone is in landscape or portrait. That view should have a button that says 'Next'. tapping the Next button should bring up `view B` (again in either landscape or portrait). View B should have a button that says 'Back' and tapping it should switch back to view A. The issue you are having is that when you rotate to landscape you are seeing both views. Is that a correct assessment? – theMikeSwan Nov 19 '15 at 04:46
  • hello i want to do my requirement though programmatically and i should not take two view controllers here that's not solve my requirement – AbhiRam Nov 20 '15 at 03:58
  • You are required to at least make two views, a controller for each view is better and the standard for iOS. Perhaps you need more clarification of the requirements or whoever has given you a requirement to put two views into one view needs to rethink things. – theMikeSwan Nov 20 '15 at 07:44
0

You could follow a tutorial on auto layout so that you can get a little know how about it. Here's a link.

Another option is the use of springs and struts.

I hope that answers your question.

Community
  • 1
  • 1
UsamaMan
  • 695
  • 10
  • 28