I created a UISlider programmatically, and after adding two auto layout constraints the slider bar no longer appears. I am seeing the nub / circle for the slider, but nothing else.
// create slider programmatically
_sliderFrame = CGRectMake(10.0f, 10.0f, 250.0f, 400.0f);
_sliderCalibrate = [[UISlider alloc] initWithFrame:_sliderFrame];
_sliderCalibrate.minimumValue = 1.0f;
_sliderCalibrate.maximumValue = 100.0f;
_sliderCalibrate.value = 50.0f;
// manually specify Auto Layout constraints in code
[_sliderCalibrate setTranslatesAutoresizingMaskIntoConstraints:NO];
// add slider to view
[self.view addSubview:_sliderCalibrate];
NSLayoutConstraint *centerSliderX = [NSLayoutConstraint constraintWithItem:_sliderCalibrate
attribute:NSLayoutAttributeCenterX
relatedBy:NSLayoutRelationEqual toItem:_sliderCalibrate.superview
attribute:NSLayoutAttributeCenterX
multiplier:1.0
constant:0.0];
NSLayoutConstraint *centerSliderY = [NSLayoutConstraint constraintWithItem:_sliderCalibrate
attribute:NSLayoutAttributeCenterY
relatedBy:NSLayoutRelationEqual toItem:_sliderCalibrate.superview
attribute:NSLayoutAttributeCenterY
multiplier:1.0
constant:0.0];
[_sliderCalibrate.superview addConstraints:#[centerSliderX, centerSliderY]];
You shouldn't set any frame when using auto layout, so just create the slider with [UISlider new]; Add either a width constraint, or delete the centerX constraint, and add constraints to both edges of the superview to give the slider a non-zero width.
By calling setFrame: for initializing an object, you don't need to call setTranslatesAutoresizingMaskIntoConstraints: with the argument NO on views that you place manually.
Just remove this line of code.
Related
I have the following hierarchy in my application
- UIScrollView
- UIStackView
- UIView 1 // load with xib and added in arrangedSubviews
- UIScrollView 1.1 // horizontal scrolling, fixed height constraint 38
- UIView 1.2 // called it childView. has fixed height 0 (I load the view from xib and add it here dynamically and update its height)
- UIView 1.2.1 // called it New View
- UIView 2
- UIView 3
So my problem is when I have loaded a view from xib and added it to UIView1.2 also increased height constraint 0 to a height of newly added sub-view but nothing will happen.UIView1.2height did not update expectedly .
self.constraintChildViewHeight.constant = 95;
[self layoutIfNeeded];
NewView *newView = (NewView *)[[[NSBundle mainBundle]loadNibNamed:NSStringFromClass([FieldPhotoView class]) owner:self options:nil]objectAtIndex:0];
[newView setTranslatesAutoresizingMaskIntoConstraints:false];
[self.childView addSubview:newView];
[self applyConstraintsToParent:self.childView andSubView:newView];
Method
- (void)applyConstraintsToParent:(UIView *)parentView andSubView:(UIView *)subView {
//constraints
NSLayoutConstraint *leading = [NSLayoutConstraint constraintWithItem:subView attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:parentView attribute:NSLayoutAttributeLeading multiplier:1.0 constant:0];
[parentView addConstraint:leading];
NSLayoutConstraint *trailing = [NSLayoutConstraint constraintWithItem:subView attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:parentView attribute:NSLayoutAttributeTrailing multiplier:1.0 constant:0];
[parentView addConstraint:trailing];
NSLayoutConstraint *top = [NSLayoutConstraint constraintWithItem:subView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:parentView attribute:NSLayoutAttributeTop multiplier:1.0 constant:0];
[parentView addConstraint:top];
NSLayoutConstraint *bottom = [NSLayoutConstraint constraintWithItem:subView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:parentView attribute:NSLayoutAttributeBottom multiplier:1.0 constant:-8];
[parentView addConstraint:bottom];
NSLayoutConstraint *equalWidth = [NSLayoutConstraint constraintWithItem:subView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:parentView attribute:NSLayoutAttributeWidth multiplier:1.0 constant:0];
[parentView addConstraint:equalWidth];
leading.active = true;
trailing.active = true;
top.active = true;
bottom.active = true;
equalWidth.active = true;
}
#Edit1 - Child view constraints
#Edit2 - For better understanding, I want to achieve this functionality programmatically using xib's(In UIStoryBoard is just working fine.)
From your question what i understood is that you are not able to scroll your content in the scrollview 1.1.
Try the following steps :
For the scrollview 1.1
give top, bottom,leading, trailing constraints w.r.t View1.
give scrollview height constraint = 38
For the childview UIView 1.2
give top, bottom,leading, trailing constraints w.r.t scrollview1.1
pin childview w.r.t View1 for leading & trailing edges
give childview height constraints
give childview vertically center constraint.
For the newView UIView 1.2.1
Load view from nib.
Add it to the childview
Set its constraints - top, bottom, leading & trailing w.r.t childview.
This will make your content scrollable.
I have shared a sample project here: https://github.com/Abhie87/StackExchangeSample
Hope this will be helpful.
Tried to do the same and it worked as expected.
What I did:
Initial views hierarchy looks like this:
Stack view constraints are on the next image:
Each view in stack view has only its' height set by constraint (the button in last view I use to add/remove the new view to the stack view at index 0)
The view to add is loaded from .xib file called SomeView.xib view hierarchy and constraints for which are on the next image (constraint called View Height Constraint is set to 1 and is changed to 95 when SomeView is added to the stack view):
The function that is called when the button is tapped looks like this:
- (IBAction)buttonTap:(UIButton *)sender {
if (self.theView) {
[self.stackView removeArrangedSubview:self.theView];
[self.theView removeFromSuperview];
self.theView = nil;
} else {
self.theView = [[[NSBundle mainBundle] loadNibNamed:#"SomeView" owner:nil options:nil] firstObject];
self.theView.translatesAutoresizingMaskIntoConstraints = NO;
[self.stackView addSubview:self.theView];
[self.stackView insertArrangedSubview:self.theView atIndex:0];
self.theView.viewHeightConstraint.constant = 95;
}
}
Hope this will give you any suggestions in how to fix your situation
I am trying to add a custom view as the leftCalloutAccessoryView in my custom MKAnnotationView. All of the examples I have found use either an image, or some type of view where the frame is specified on init. I want to use autolayout for the view.
This is the code I have in my init method for myMKAnnotationView. I am just trying to use simple width and height constraints:
UIView* contentView = [[UIView alloc] init];
contentView.backgroundColor = [UIColor redColor];
contentView.translatesAutoresizingMaskIntoConstraints = NO;
NSLayoutConstraint* height = [NSLayoutConstraint constraintWithItem:contentView
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute:NSLayoutAttributeNotAnAttribute
multiplier:1
constant:32];
NSLayoutConstraint* width = [NSLayoutConstraint constraintWithItem:contentView
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute:NSLayoutAttributeNotAnAttribute
multiplier:1
constant:50];
[contentView addConstraints:#[height,width]];
self.leftCalloutAccessoryView = contentView;
I can never get the view to show up with constraints. If I remove the constraints and init the view with a frame it will show up. What do I need to do to get constraints working with the leftCalloutAccessoryView?
Also, if I change leftCalloutAccessoryView to detailCalloutAccessoryView, which was added in iOS 9, and it shows up correctly.
What i want to achieve is set buttons/images Horizontally Centered with main view, including its width set to 75% of the screen width.
I want to fit like 7 such images/buttons vertically on the screen (line-by-line).
I am using the following code, which is working perfect:
UIImageView *l1 = [[UIImageView alloc] initWithFrame:CGRectMake(20, 20, 100, 100)];
[l1 setImage:[UIImage imageNamed:#"level-1"]];
[l1 setContentMode:UIViewContentModeScaleAspectFit];
l1.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:l1];
NSLayoutConstraint *c1 = [NSLayoutConstraint
constraintWithItem:l1
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeTop
multiplier:1.0f
constant:20.f
];
[self.view addConstraint:c1];
NSLayoutConstraint *c1b = [NSLayoutConstraint
constraintWithItem:l1
attribute:NSLayoutAttributeCenterX
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeCenterX
multiplier:1.0f
constant:0.f
];
[self.view addConstraint:c1b];
NSLayoutConstraint *c1c = [NSLayoutConstraint
constraintWithItem:l1
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeWidth
multiplier:0.75f
constant:0.f
];
[self.view addConstraint:c1c];
Instead of repeating the same code for different images, i want to use some iteration process and increment the image name [UIImage imageNamed:#"level-xxx"]] and bind top position to the bottom position of the last added item.
How it would be possible? Thx
iOS 9 introduces a new class called UIStackView that allows you to do this :
https://www.hackingwithswift.com/read/31/2/uistackview-by-example
There are even back-ports of this to iOS 7 on Github.
Some people might downvote me for this but sometimes , when it comes to autolayout I just say , $##& this I'll write the layout code myself. And this is one of those cases (especially when UIStackView is not available).
First create all your views and store them in an array in viewDidLoad.
Override viewDidLayoutSubviews on your view controller and loop through the array , set the frames and lay them out one by one.
-(void)viewDidLayoutSubviews
{
NSArray* imageList = self.imageViewList
// calculate it if necessary
CGPoint startPoint = CGPointMake(200,200)
CGFloat spacing = 50
for(UIView *view in imageList) {
view.center = startPoint
startPoint = CGPointMake(startPoint.x , startPoint.y + spacing)
}
}
This is way more obvious , way easier to debug than a mess of constraints created in code.
Problem: How to change the height of the UISegmentedControl in iOS?
After Searching, I got the following answers:
-(void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
CGRect frame= segmentedControl.frame;
[segmentedControl setFrame:CGRectMake(10.0, 20.0, 200.0, 50.0)];
}
But this resets the height of the control to default if I select any option of the segmented control in iOS 7
If you have autolayout, set the constraints of the UISegmentedControl. Please see pic of where's easiest to set this, make sure width and height are ticked, plus vertical and horizontal space constraints (select where lines that are deep orange in pic).
Now that you have this, control-drag the constraint that sets the height of the segmented control to your header file and name it something like segmentedControlHeightConstraint.
Once you have done that, within your viewDidLoad in your view controller implementation file add this code
self.segmentedControlHeightConstraint.constant = 50; // or whatever height you wish
This is the best way using auto layout to set the height for this.
Hope this helps
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:segmentContl
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute:NSLayoutAttributeHeight
multiplier:1.0
constant:18]];
"change constant value for changing height"
NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:mySegmentedControl
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute:NSLayoutAttributeNotAnAttribute
multiplier:1
constant:fNewHeight];
[mySegmentedControl addConstraint:constraint];
I'm trying to build a rather simple animated custom UI using the Auto Layout API newly available iOS 6. The custom view I'm building has a circle that I want to be both vertically and horizontally centered.
Unfortunately I can't figure out why my constraints appear to work fine for UIButton, and UILabel elements but yield weird results when I use a custom view with and custom CALayer (in this case a circle, that will eventually be animated).
To be clear I don't want my view to expand to fill the whole screen, but rather to have dynamic "padding" so that the view is vertically centered both on the iPhone 4 and 5. I should also note that I'm very new to Cocoa and UIKit.
RootViewController.m:
...
- (void)viewDidLoad {
[super viewDidLoad];
// Create Circle View
CGRect circle_view_rect = CGRectMake(0, 0, 100, 100);
UIView *circle_view = [[UIView alloc] initWithFrame:circle_view_rect];
// Create Circle Layer
CircleLayer *circle_layer = [[CircleLayer alloc] init];
circle_layer.needsDisplayOnBoundsChange = YES;
circle_layer.frame = circle_view.bounds;
[circle_view.layer addSublayer:circle_layer];
// Enable Auto Layout
[circle_view setTranslatesAutoresizingMaskIntoConstraints:NO];
[self.view addSubview:circle_view];
// Center Vertically
NSLayoutConstraint *centerYConstraint =
[NSLayoutConstraint constraintWithItem:circle_view
attribute:NSLayoutAttributeCenterY
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeCenterY
multiplier:1.0
constant:0.0];
[self.view addConstraint:centerYConstraint];
// Center Horizontally
NSLayoutConstraint *centerXConstraint =
[NSLayoutConstraint constraintWithItem:circle_view
attribute:NSLayoutAttributeCenterX
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeCenterX
multiplier:1.0
constant:0.0];
[self.view addConstraint:centerXConstraint];
}
...
CircleLayer.m:
...
- (void)drawInContext:(CGContextRef)context {
CGContextAddArc(context, 50, 50, 50, 0.0, 2*M_PI, 0);
CGContextSetFillColorWithColor(context, [UIColor yellowColor].CGColor);
CGContextFillPath(context);
}
...
Basically the constraints I've implemented are:
center vertically inside parent view
center horizontally inside parent view
And this is the result I get:
Any help would be greatly appreciated, I've been pondering this one for a few days now.
Thanks
Try adding a height and width constraint to your circle_view. I couldn't even get just a pain square view to appear at all without adding those (using your code, minus the layer stuff).
NSLayoutConstraint *heightConstraint =
[NSLayoutConstraint constraintWithItem:circle_view
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute:NSLayoutAttributeNotAnAttribute
multiplier:1.0
constant:100.0];
[circle_view addConstraint:heightConstraint];
NSLayoutConstraint *widthConstraint =
[NSLayoutConstraint constraintWithItem:circle_view
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute:NSLayoutAttributeNotAnAttribute
multiplier:1.0
constant:100.0];
[circle_view addConstraint:widthConstraint];
Just to add to rdelmar's answer:
The core issue is that as soon as you go the NSLayoutConstraint route, and specify setTranslatesAutoresizingMaskIntoConstraints:NO, the frame you made with CGRectMake is rendered irrelevant for AutoLayout purposes. That's why it didn't use the info from the frame's height and width.