Change Frame of Subview in Superview - ios

I have a ViewController that adds an UIView, SpeciesImageView as a subview in viewDidLoad and set constraints in viewWillLayoutSubviews.
SpeciesImageView does not have a nib file. When we create speciesImageView in viewDidLoad, it calls initWithFrame in SpeciesImageView class.
This works fine (in both landscape and portrait) until the phone rotates. I tried setting the constraints as speciesImageView.frame.size.width, but that doesn't work because initWithFrame isn't called when the orientation changes, so the height/width of the speciesImageView remains unchanged.
On the other hand, using screenRect doesn't change the actual size of the UIView, it changes its size within the superview. So in other words, I haven't found a way to change the size of the actual speciesImageView on orientation change.
And for reasons lost to me, it gets completely messed up when you rotate it back to the original position.
- (void)viewDidLoad
{
self.tabBarController.tabBar.hidden=YES;
self.navigationController.navigationBar.barStyle = UIBarStyleBlack;
self.navigationController.navigationBar.hidden = NO;
//self.navigationController.navigationBar.translucent = YES;
UIImage *plantinfo;
if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_6_1) {
plantinfo = [UIImage imageNamed:#"plantinfo_frame.png"];
} else {
plantinfo = [UIImage imageNamed:#"plantinfo.png"];
}
UIBarButtonItem *tempButton = [[UIBarButtonItem alloc] initWithImage:plantinfo
style:UIBarButtonItemStylePlain
target:self
action:#selector(toggleText:)];
self.navigationItem.rightBarButtonItem = tempButton;
[tempButton release];
self.title = theSpecies.scientificName;
//[self.navigationItem.backBarButtonItem setTitle:#""];
self.navigationItem.backBarButtonItem.title = #"";
infoViewSegmentedControl.backgroundColor = [UIColor blackColor];
webView.backgroundColor = [UIColor blackColor];
_activityIndicator.hidden = YES;
[webView setOpaque:YES];
webView.delegate = self;
// Do double justification
[webView loadHTMLString:[self formatHTML:theSpecies] baseURL:nil];
showingInfoView = NO;
//
// Resize containerView, infoview according to iphone 5 screen size.
//
infoView.autoresizingMask = UIViewAutoresizingFlexibleWidth |UIViewAutoresizingFlexibleHeight;
CGPoint screenOrigin = [[UIScreen mainScreen] bounds].origin;
CGSize viewSize = [[UIScreen mainScreen] bounds].size;
CGPoint origin = infoView.frame.origin;
CGRect statusBarFrame = [[UIApplication sharedApplication] statusBarFrame];
if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_6_1) {
infoView.frame = CGRectMake(screenOrigin.x,
screenOrigin.y + statusBarFrame.size.height,
viewSize.width,
viewSize.height - origin.y - statusBarFrame.size.height);
speciesImageView = [[SpeciesImageView alloc]
initWithFrame:CGRectMake(screenOrigin.x,
screenOrigin.y,
viewSize.width,
viewSize.height)];
} else {
infoView.frame = CGRectMake(screenOrigin.x,
screenOrigin.y,
viewSize.width,
viewSize.height - origin.y - statusBarFrame.size.height);
speciesImageView = [[SpeciesImageView alloc]
initWithFrame:CGRectMake(screenOrigin.x,
screenOrigin.y,
viewSize.width,
viewSize.height - statusBarFrame.size.height)];
}
speciesImageView.delegate = self;
[containerView addSubview:speciesImageView];
managedObjectContext = [(LeafletAppDelegate*)[[UIApplication sharedApplication] delegate] managedObjectContext];
[self parseImageURLArray];
}
-(void)viewWillLayoutSubviews{
if(speciesImageView.window != nil){
CGRect screenRect = [[UIScreen mainScreen] bounds];
speciesImageView.translatesAutoresizingMaskIntoConstraints = NO;
NSLayoutConstraint *widthConst = [NSLayoutConstraint
constraintWithItem:speciesImageView
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute:NSLayoutAttributeNotAnAttribute
multiplier:1.0
constant:screenRect.size.width];
NSLayoutConstraint *heightConst = [NSLayoutConstraint
constraintWithItem:speciesImageView
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute:NSLayoutAttributeNotAnAttribute
multiplier:1.0
constant:screenRect.size.height];
NSLayoutConstraint *rightConstraint = [NSLayoutConstraint
constraintWithItem:speciesImageView
attribute:NSLayoutAttributeCenterX
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeCenterX
multiplier:1.0
constant:0.0];
NSLayoutConstraint *bottomConstraint = [NSLayoutConstraint
constraintWithItem:speciesImageView
attribute:NSLayoutAttributeBottom
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeBottom
multiplier:1.0
constant:0.0];
[self.view addConstraints:#[widthConst, heightConst, bottomConstraint, rightConstraint]];
}
}
- (id)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame])
{
imageScrollView = [[UIScrollView alloc] initWithFrame:frame];
imageScrollView.delegate = self;
imageScrollView.backgroundColor = [UIColor blackColor];
[self addSubview:imageScrollView];
imageScrollView.translatesAutoresizingMaskIntoConstraints = NO;
NSLayoutConstraint *widthConst = [NSLayoutConstraint constraintWithItem:imageScrollView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:imageScrollView.frame.size.width];
NSLayoutConstraint *heightConst = [NSLayoutConstraint constraintWithItem:imageScrollView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:imageScrollView.frame.size.height];
NSLayoutConstraint *rightConstraint = [NSLayoutConstraint
constraintWithItem:imageScrollView
attribute:NSLayoutAttributeRight
relatedBy:NSLayoutRelationEqual
toItem:self
attribute:NSLayoutAttributeRight
multiplier:1.0
constant:0.0];
NSLayoutConstraint *bottomConstraint = [NSLayoutConstraint
constraintWithItem:imageScrollView
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:self
attribute:NSLayoutAttributeTop
multiplier:1.0
constant:0.0];
[self addConstraints:#[widthConst, heightConst, bottomConstraint, rightConstraint]];
}
return self;
}

If you want your views to adjust to the size of the superview,
then you need something like this (set the margin to whatever you like):
CGFloat margin = 0;
NSString * visualFormatH = [NSString stringWithFormat:#"|-(%f)-[speciesImageView]-(%f)-|", margin, margin];
[self.containerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:visualFormatH
options:0
metrics:Nil
views:#{#"speciesImageView": speciesImageView}]];
NSString * visualFormatV = [NSString stringWithFormat:#"V:|-(%f)-[speciesImageView]-(%f)-|", margin, margin];
[self.containerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:visualFormatV
options:0
metrics:Nil
views:#{#"speciesImageView": speciesImageView}]];
Now speciesImageView will adjust its frame whenever the superview frame changes.
Here is a generic example:
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
UIView * sampleView = [UIView new];
sampleView.backgroundColor = [UIColor redColor];
sampleView.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:sampleView];
CGFloat margin = 0;
NSString * visualFormatH = [NSString stringWithFormat:#"|-(%f)-[sampleView]-(%f)-|", margin, margin];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:visualFormatH
options:0
metrics:Nil
views:#{#"sampleView": sampleView}]];
NSString * visualFormatV = [NSString stringWithFormat:#"V:|-(%f)-[sampleView]-(%f)-|", margin, margin];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:visualFormatV
options:0
metrics:Nil
views:#{#"sampleView": sampleView}]];
}
Auto Layout Getting Started
Auto Layout Visual Format Documentation

Related

Can't able to click a UICollectionViewCell in a UICollectionView

Let's say I have a view controller OptionsToCreateViewController which inherits UICollectionViewController and I have used that View Controller in another view controller like this.. I can able to see the view but can't able to click the cell
self.optionsToCreateViewController = [[OptionsToCreateViewController alloc] init];
self.optionsToCreateViewController.view.translatesAutoresizingMaskIntoConstraints = FALSE;
[self.optionsToCreateViewController didMoveToParentViewController:self];
[self addChildViewController:self.optionsToCreateViewController];
[self.view addSubview:self.optionsToCreateViewController.view];
OrganizerBottomBar *orgBB = [OrganizerBottomBar new];
CGRect applicationFrame = [[UIScreen mainScreen] bounds];
CGFloat viewWidth = applicationFrame.size.width / 2;
if(![MyUIResources isPhone]){
viewWidth = applicationFrame.size.width / 4;
}
[self.view addConstraints:#[
[NSLayoutConstraint constraintWithItem:self.optionsToCreateViewController.view attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterY multiplier:1 constant:-(orgBB.frame.size.height + 75)],
[NSLayoutConstraint constraintWithItem:self.optionsToCreateViewController.view attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:1 constant:-viewWidth]
]];
is this the right implementation of a view controller in another view controller
In Collection view cell:
[button addTarget:self action:#selector(buttonPressed:) forControlEvents: UIControlEventTouchUpInside];
self.contentView.userInteractionEnabled = FALSE;
self.userInteractionEnabled = TRUE;
I also put a break point to buttonPressed function, it's not hitting. i also used
-(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
UIView *view = [self->button hitTest:[self->button convertPoint:point fromView:self] withEvent:event];
if (view == nil) {
view = [super hitTest:point withEvent:event];
}
return view;
}
-(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
if ([super pointInside:point withEvent:event]) {
return YES;
}
return !self->button.hidden && [self->button pointInside:[self->button convertPoint:point fromView:self] withEvent:event];
}
but no use. Could anyone please help me here, I'm stuck here badly
CGRect applicationFrame = [[UIScreen mainScreen] bounds];
self.view = [UIView new];
self.view.translatesAutoresizingMaskIntoConstraints = NO;
self.view.backgroundColor = [UIColor colorWhite];
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
self.collection = [[UICollectionView alloc] initWithFrame:self.view.frame collectionViewLayout:layout];
self.collection.translatesAutoresizingMaskIntoConstraints = NO;
self.collection.backgroundColor = [UIColor colorWhite];
self.collection.contentInset = UIEdgeInsetsMake(0, 7.0, 0, 16.0);
[self.collection registerClass:[OptionsToCreateCollectionViewCell class] forCellWithReuseIdentifier: [OptionsToCreateCollectionViewCell cellIdentifier]];
[self.collection setDataSource:self]; // UICollectionViewDataSource
[self.collection setDelegate:self]; // UICollectionViewDelegate
[self.view addSubview:self.collection];
CGFloat viewWidth = applicationFrame.size.width;
CGFloat frameWidth = viewWidth;
if(![MyUIResources isPhone]){
frameWidth = viewWidth/2;
}
[self.view addConstraints:
#[
[NSLayoutConstraint constraintWithItem:self.collection attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeft multiplier:1.0 constant:10],
[NSLayoutConstraint constraintWithItem:self.collection attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTop multiplier:1.0 constant:20],
[NSLayoutConstraint constraintWithItem:self.collection attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeRight multiplier:1.0 constant:frameWidth],
[NSLayoutConstraint constraintWithItem:self.collection attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeHeight multiplier:1.0 constant:114*2.5]
]
];
What is the button's superview? Add the button on the cell.contentView, not cell self.
1.check that button frame(if outside cell not working, then any view overlapping that button not working ) and user interaction enabled or not
Otherwise
2.check that cell frame and height(check if there inside of collection view)
Otherwise
3.collection view supper frame set correctly (collection view frame need inside of superview)
If Frame working correct so assign that clipsToBounds = YES
self.yourview.clipsToBounds = YES;
notes:past that button Action in collection didselecteditem . then check working or not because easily identified issue only that button or that class based.

Program Subview's Vertical Spacing to Bottom Constraint

SecondViewController adds a UIView that contains a MKMapView as a subview inside an IBAction method:
if(_tagTwo == 4){
seg2_buttonImg = #"Maps.png";
UIImage *btnImage1 = [UIImage imageNamed:seg2_buttonImg];
[_left_button setImage:btnImage1 forState:UIControlStateNormal];
[_table removeFromSuperview];
[mapVC layoutMapView];
[self.view addSubview:mapVC.view];
return;
}
mapVC is created in ViewDidLoad with mapVC = [[CollectionMapViewController alloc] init];
Edit: new code for adding constraints, taken from #Reinier Melian:
#implementation CollectionMapViewController
#synthesize mapView;
- (void)viewDidLoad
{
if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_6_1) {
//[segmentedControl setBackgroundColor:[UIColor whiteColor]];
//[segmentedControl setBackgroundColor:[UIColor leafletBrown]];
[segmentedControl setBackgroundColor:[UIColor leafletLightBrown]];
segmentedControl.layer.cornerRadius = 5;
}
self.mapView.translatesAutoresizingMaskIntoConstraints = NO;
NSArray * verticalConstraints = [NSLayoutConstraint constraintsWithVisualFormat:#"V:|[mapView]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(self.mapView)];
NSArray * horizontalConstraints = [NSLayoutConstraint constraintsWithVisualFormat:#"H:|[mapView]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(self.mapView)];
//Add constraints to the Parent
[self.view addConstraints:verticalConstraints];
[self.view addConstraints:horizontalConstraints];
}
CollectionMapViewController.h:
#interface SecondViewController : UIViewController <NSFetchedResultsControllerDelegate, CollectionMapViewControllerDelegate>{
CollectionMapViewController* mapVC;
}
#property (nonatomic, retain) CollectionMapViewController* mapVC;
The problem is that it adds the MKMapView to the top of the screen:
I tried to constrain the MKMapView to the bottom of the screen by adding following code to viewDidLoad of MapViewController
mapView.translatesAutoresizingMaskIntoConstraints = NO;
NSLayoutConstraint *bottom =[NSLayoutConstraint
constraintWithItem:mapView
attribute:NSLayoutAttributeBottom
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeBottom
multiplier:1.0f
constant:0.f];
//Add constraints to the Parent
[self.view addConstraint:bottom];
But it just makes the map go black (or more likely moves it completely off the screen?).
What I am trying to get is this:
I would appreciate any help! Thank you so much!
When you add mapView.translatesAutoresizingMaskIntoConstraints = NO; your map rect size is equal to zero if there are not enough constraints to define the correct frame, that is why you have your screen black, you need define all the constraints needed by your MKMapView
Updated using dynamic height constraints
try with this code
self.mapView.translatesAutoresizingMaskIntoConstraints = NO;
CGFloat mapHeigthValue = self.view.frame.size.height/3; //setting the mapView heigth = 1/3 of view height this is an example
NSArray * verticalConstraints = [NSLayoutConstraint constraintsWithVisualFormat:[NSString stringWithFormat:#"V:[mapView(%f)]|",mapHeigthValue] options:0 metrics:nil views:#{#"mapView":self.mapView}];
NSArray * horizontalConstraints = [NSLayoutConstraint constraintsWithVisualFormat:#"H:|[mapView]|" options:0 metrics:nil views:#{#"mapView":self.mapView}];
//Add constraints to the Parent
[self.view addConstraints:verticalConstraints];
[self.view addConstraints:horizontalConstraints];
In viewDidLoad:
mapView.translatesAutoresizingMaskIntoConstraints = NO;
/*Set width and height of mapview */
NSLayoutConstraint *widthConst = [NSLayoutConstraint constraintWithItem:mapView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:400];
NSLayoutConstraint *heightConst = [NSLayoutConstraint constraintWithItem:mapView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:300];
[self.view addConstraint:widthConst];
[self.view addConstraint:heightConst];
/*creater X and Y constraints for mapview */
NSLayoutConstraint *centreHorizontallyConstraint = [NSLayoutConstraint
constraintWithItem:mapView
attribute:NSLayoutAttributeCenterX
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeCenterX
multiplier:1.0
constant:0];
[self.view addConstraint:centreHorizontallyConstraint];
NSLayoutConstraint *bottomConstraint = [NSLayoutConstraint
constraintWithItem:mapView
attribute:NSLayoutAttributeBottom
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeBottom
multiplier:1.0
constant:140];
[self.view addConstraint:bottomConstraint];

Xcode Unable to change second childViewController's frame

I have a MenuViewController and inside this viewController I have two childViewControllers which first one is on left part and second one is on the right side.
VIEW_WIDTH = self.view.frame.size.width;
WIDTH_ListTableView = 0.4;
ListViewController *listViewController = [[ListViewController alloc] init];
ListNavigationViewController *listViewNavigation = [[ListNavigationViewController alloc] initWithRootViewController:listViewController];
[self addChildViewController:listViewNavigation];
[self.view insertSubview:listViewNavigation.view belowSubview:self.searchBarView.view];
[listViewNavigation didMoveToParentViewController:self];
listViewNavigation.view.frame = CGRectMake(0,
y,
VIEW_WIDTH*WIDTH_ListTableView,
height);
PreViewViewController *readViewController = [[PreViewViewController alloc] init];
[self addChildViewController:readViewController];
[self.view insertSubview:readViewController.view belowSubview:listViewNavigation.view];
[readViewController didMoveToParentViewController:self];
readViewController.view.frame = CGRectMake(listViewNavigation.view.frame.origin.x + listViewNavigation.view.frame.size.width,
listViewNavigation.view.frame.origin.y,
VIEW_WIDTH - listViewNavigation.view.frame.size.width,
listViewNavigation.view.frame.size.height);
But I cannot change the frame of readViewController and its width and height are always (768.0, 1024.0).
I added constraint to listViewNavigation, but listViewNavigation.view.y = 0
- (void)addConstraintWithListNavigationViewController:(UIView *)listViewNavigation y:(CGFloat)y height:(CGFloat)height
{
//set x = 0;
NSLayoutConstraint *constraintToAnimate1 = [NSLayoutConstraint constraintWithItem:listViewNavigation
attribute:NSLayoutAttributeLeft
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeLeft
multiplier:0.00
constant:0];
[self.view addConstraint:constraintToAnimate1];
//set y = y;
NSLayoutConstraint *constraintToAnimate2 = [NSLayoutConstraint constraintWithItem:listViewNavigation
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeBottom
multiplier:0.00
constant:y];
[self.view addConstraint:constraintToAnimate2];
//set Width = self.view.frame.size.width*0.4
NSLayoutConstraint *constraintToAnimate3 = [NSLayoutConstraint constraintWithItem:listViewNavigation
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeWidth
multiplier:WIDTH_ListTableView
constant:0.0];
[self.view addConstraint:constraintToAnimate3];
//Set height = height
NSLayoutConstraint *constraintToAnimate4 = [NSLayoutConstraint constraintWithItem:listViewNavigation
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute:NSLayoutAttributeNotAnAttribute
multiplier:0.00
constant:height];
[self.view addConstraint:constraintToAnimate4];
}
this is because you are have auto layout enabled. Try to update the constraints after changing frame by using the function [readViewController.view setTranslatesAutoresizingMaskIntoConstraints:YES]

UIView breaking in iOS7 but not in iOS8

I have created a custom view to show 2 labels inside a circle. It is suppose to look like this:
but in iOS 7 it looks like this:
That happens because the constraints hat are supposed to stick the labels to the top/bottom are breaking for some reason, but only on iOS 7. I get the following error:
(
"<NSLayoutConstraint:0x7f96e500a540 H:|-(-1)-[UILabel:0x7f96e2dd84d0] (Names: '|':UIView:0x7f96e2df6350 )>" )
Will attempt to recover by breaking constraint <NSLayoutConstraint:0x7f96e500a540 H:|-(-1)-[UILabel:0x7f96e2dd84d0] (Names: '|':UIView:0x7f96e2df6350 )>
I have confirmed that those are in fact the constraints called (I only gave one error as an example)
self.dayLabelStickButtomConstraint
self.monthLabelStickTopConstraint
Here is the code for the custom view, can anyone maybe understand why is it breaking on iOS 7 but not on 8?
- (instancetype) initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if (self) {
[self initiateValues];
[self buildHeirarchy];
}
return self;
}
- (instancetype) initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
[self initiateValues];
[self buildHeirarchy];
}
return self;
}
-(void)initiateValues{
self.fillColor = [UIColor blackColor];
self.month = #"jan";
self.monthFontSize = 8.0f;
self.monthTextColor = [UIColor blackColor];
self.monthLabelInsetDistance = 1.0f;
self.day = #"01";
self.dayFontSize = 12.0f;
self.dayTextColor = [UIColor blackColor];
self.dayLabelInsetDistance = 1.0f;
}
-(void)buildHeirarchy{
self.innerContainer = [[UIView alloc] initWithFrame:CGRectInset(self.bounds, 5.0, 5.0)];
[self.innerContainer setTranslatesAutoresizingMaskIntoConstraints:NO];
[self addSubview:self.innerContainer];
[self addConstraint:[NSLayoutConstraint constraintWithItem:self.innerContainer
attribute:NSLayoutAttributeCenterX
relatedBy:NSLayoutRelationEqual
toItem:self
attribute:NSLayoutAttributeCenterX
multiplier:1.0
constant:0.0]];
[self addConstraint:[NSLayoutConstraint constraintWithItem:self.innerContainer
attribute:NSLayoutAttributeCenterY
relatedBy:NSLayoutRelationEqual
toItem:self
attribute:NSLayoutAttributeCenterY
multiplier:1.0
constant:0.0]];
[self addConstraint:[NSLayoutConstraint constraintWithItem:self.innerContainer
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:self
attribute:NSLayoutAttributeWidth
multiplier:0.7
constant:0.0]];
[self addConstraint:[NSLayoutConstraint constraintWithItem:self.innerContainer
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:self
attribute:NSLayoutAttributeHeight
multiplier:0.7
constant:0.0]];
self.monthLabel = [[UILabel alloc] initWithFrame:CGRectInset(self.bounds, 5.0, 5.0)];
[self.monthLabel setTranslatesAutoresizingMaskIntoConstraints:NO];
self.monthLabel.textAlignment = NSTextAlignmentCenter;
[self.innerContainer addSubview:self.monthLabel];
[self.innerContainer addConstraint:[NSLayoutConstraint constraintWithItem:self.monthLabel
attribute:NSLayoutAttributeCenterX
relatedBy:NSLayoutRelationEqual
toItem:self.innerContainer
attribute:NSLayoutAttributeCenterX
multiplier:1.0
constant:0.0]];
NSLayoutConstraint *monthTopConstraint = [NSLayoutConstraint constraintWithItem:self.monthLabel
attribute:NSLayoutAttributeTopMargin
relatedBy:NSLayoutRelationEqual
toItem:self.innerContainer
attribute:NSLayoutAttributeTopMargin
multiplier:1.0
constant:self.monthLabelInsetDistance];
self.monthLabelStickTopConstraint = monthTopConstraint;
[self.innerContainer addConstraint:self.monthLabelStickTopConstraint];
self.dayLabel = [[UILabel alloc] initWithFrame:CGRectInset(self.bounds, 5.0, 5.0)];
[self.dayLabel setTranslatesAutoresizingMaskIntoConstraints:NO];
[self.innerContainer addSubview:self.dayLabel];
self.dayLabel.textAlignment = NSTextAlignmentCenter;
[self.innerContainer addConstraint:[NSLayoutConstraint constraintWithItem:self.dayLabel
attribute:NSLayoutAttributeCenterX
relatedBy:NSLayoutRelationEqual
toItem:self.innerContainer
attribute:NSLayoutAttributeCenterX
multiplier:1.0
constant:0.0]];
NSLayoutConstraint *dayButtomConstraint = [NSLayoutConstraint constraintWithItem:self.dayLabel
attribute:NSLayoutAttributeBottomMargin
relatedBy:NSLayoutRelationEqual
toItem:self.innerContainer
attribute:NSLayoutAttributeBottomMargin
multiplier:1.0
constant:self.dayLabelInsetDistance];
self.dayLabelStickButtomConstraint = dayButtomConstraint;
[self.innerContainer addConstraint:self.dayLabelStickButtomConstraint];
}
-(void)layoutSubviews{
// get the graphics context
if (!self.backgroundColorRoundView) {
self.backgroundColorRoundView = [[UIView alloc]initWithFrame:self.bounds];
[self addSubview:self.backgroundColorRoundView];
[self sendSubviewToBack:self.backgroundColorRoundView];
self.backgroundColorRoundLayer = [CAShapeLayer new];
UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:self.backgroundColorRoundView.bounds];
self.backgroundColorRoundLayer.path = path.CGPath;
//imageMaskLayer.fillColor = self.fillColor.CGColor;
[self.backgroundColorRoundView.layer addSublayer:self.backgroundColorRoundLayer];
}
self.backgroundColorRoundView.frame = self.bounds;
self.backgroundColorRoundLayer.frame = self.bounds;
[self updateViews];
[super layoutSubviews];
}
-(void)updateViews{
self.monthLabel.textColor = self.monthTextColor;
self.dayLabel.textColor = self.dayTextColor;
self.backgroundColorRoundLayer.fillColor = self.fillColor.CGColor;
}
-(void)updateConstraints{
self.dayLabelStickButtomConstraint.constant = self.dayLabelInsetDistance;
self.monthLabelStickTopConstraint.constant = self.monthLabelInsetDistance;
[super updateConstraints];
}
After a lot of messing around the answer lied in the restraints themselves. Once i switched from topMargin,bottomMargin to just top and bottom it worked

iOS Auto layout Rows

I'm trying to understand auto layout better and I created some static methods that can help me out. Now I'm trying to setup an array of views in like a tableview structure (in rows). This works kinda.
See here my problem:
To achieve this I use this code:
//In the update constraints method
UIView *view1 = [self createView];
view1.backgroundColor = [UIColor redColor];
UIView *view2 = [self createView];
view2.backgroundColor = [UIColor yellowColor];
[self addSubview:view1];
[self addSubview:view2];
[self addConstraints:[DXVFL row:#[view1, view2] inView:self]];
//The row method
+ (NSArray *) row:(NSArray const *)views inView:(UIView const *)superview {
NSMutableArray *constraints = [NSMutableArray new];
CGFloat multiplier = 1.f / [views count];
UIView *prev = nil;
for (UIView *view in views) {
if (!view.hidden) {
[constraints addObject:[NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:superview attribute:NSLayoutAttributeWidth multiplier:1.f constant:0.f]];
[constraints addObject:[NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:superview attribute:NSLayoutAttributeHeight multiplier:multiplier constant:0.f]];
if (prev) {
[constraints addObject:[NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:prev attribute:NSLayoutAttributeBottom multiplier:1.f constant:0.f]];
}
prev = view;
}
}
return [constraints copy];
}
So this part works (I guess). But when I want to split the yellow view again in rows. The views are always added into the top region?
In the update constraints method I do this:
UIView *view1 = [self createView];
view1.backgroundColor = [UIColor redColor];
UIView *view2 = [self createView];
view2.backgroundColor = [UIColor yellowColor];
[self addSubview:view1];
[self addSubview:view2];
UIView *view3 = [self createView];
UIView *view4 = [self createView];
[view2 addSubview:view3];
[view2 addSubview:view4];
[self addConstraints:[DXVFL row:#[view1, view2] inView:self]];
[view2 addConstraints:[DXVFL row:#[view3, view4] inView:view2]];
But I want those two rows in the bottom? What am I doing wrong?
Off the top of my head:
You need to add a constraint to tell it to align the view to the top of the superview. At the moment, you just set the height and width but you don't tell it where to put its top edge.
Try changing your code to this:
if (!prev) {
[constraints addObject:[NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:superview attribute:NSLayoutAttributeTop multiplier:1.f constant:0.f]];
} else {
[constraints addObject:[NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:prev attribute:NSLayoutAttributeBottom multiplier:1.f constant:0.f]];
}

Resources