I would like to pin a button to the bottom right corner of a textfield. I completed this in Android using a relativelayout. I don't know how to do this in IOS. I attempted to set top and bottom constraints, but it didn't work.
Help?
Example
UITextField * rightField;
rightField.rightViewMode = UITextFieldViewModeAlways;
UIImageView *rightImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"image.png"]];
rightField.rightView = rightImageView; // Set right view as image view
set UITextField rightView as your button. Here in my example I added UIImageView to UITextField rightView.
Since you're using a storyboard you'd probably want something like this if I'm not mistaken:
To do this set the following trailing and leading constraints on your textfield:
Your button should have the following constraints:
Ok I have successfully pinned the button.
This is what I did.
I used control+click to set bottom and trailing constraints between the textfield and the button. Then I set equal height and equal width constraints between the button and the view and used a multiplier.
Related
I have button and a label in my table view cell placing one after other vertically.
In my xib design i placed my button then below it placed my label.
if the string for label is empty then i want to set the button as vertically center in table view cell and hide the label.
if have tried following code for my implementation but button does not come in vertical center position.
if([labelString isEqualToString:#""]){
_label.hidden = YES;
_button.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
}
it would be helpful if get suggestion for fixing this problem.
One approach: use dynamic setting of constraints.
In InterfaceBuilder:
Put your button and label inside an enclosing wrapper view.
Constrain the wrapper view to be centered in the main view.
Constrain the button and the label to be of fixed height, and the top of the label to be constrained to the bottom of the button (with spacing if desired).
Constrain the top of the wrapper to the top of the button.
Constrain the bottom of the wrapper with two separate constraints: one to the bottom of the button (but make this inactive), and one to the bottom of the label (active.).
Make both of those constraints outlets so that you can access them in code.
Leave the wrapper height otherwise unconstrained. Thus it will "shrink-wrap" to the combined height of the button and label.
In code:
When the label is empty, activate the constraint that pins the wrapper to the button instead of to the label:
BOOL hideLabel = [labelString isEqualToString:#""];
_label.hidden = hideLabel;
_wrapperToButtonConstraint.active = hideLabel;
_wrapperToLabelConstraint.active = !hideLabel;
Now the shrink-wrap effect will make the wrapper have the same height as the button, and since the wrapper is centered, so will the button be centered.
I have UILabel in a UITableViewCell whose neighboring subview is UIControlSwitch. When the UIControlSwitch is hidden, the UILabel's width is expected to grow. Below is my custom class implementation:
- (void)setBounds:(CGRect)bounds
{
[super setBounds:bounds];
self.contentView.frame = self.bounds;
}
- (void)layoutSubviews
{
[super layoutSubviews];
[self.contentView updateConstraintsIfNeeded];
[self.contentView layoutIfNeeded];
self.numberLabel.preferredMaxLayoutWidth = CGRectGetWidth(self.numberLabel.frame);
self.quoteLabel.preferredMaxLayoutWidth = CGRectGetWidth(self.quoteLabel.frame);
}
#end
I have uploaded a sample code to explain the constraints on the storyboard.
The UILabel's width is not changing. If I set a trailing space between the UILabel and the UIControlSwitch, the control is partially hidden beyond the screen bounds. Hence the constraint for the UILabel has trailing space to the superview instead of the UIControlSwitch.
When you hide a view, it still takes part in the layout process. So simply hiding your UISwitch will not cause anything to change.
So you either have to add/remove constraints, remove the UISwitch from its containing view or change how you are doing the constraints.
Option 1: Instead of hide/show do remove/add.
If you put the UISwitch in its own view, you can pin the UILabel to the switches containing view. Instead of hiding the UISwitch, remove it from its containing view. The result will be that the containing view collapses and your UILabel will stretch as long as the label is pinned to the switches view and the switches view to the edge.
Instead of show, add the UILabel back into the container view. The view will stretch and your UILabel will shrink.
Option 2: Use simple trailing constraint for UILabel.
Make your UILabel have a trailing constraint to the superview and CTRL drag that constraint into your code so you can set its value. Or you could add it manually if that is what you are doing.
Do not pin the UILabel to the UISwitch at all. Pin the UILabel to the right h§and side so it has the required position.
So your UILabel is now pinned to the right edge with an offset of your choosing. If you set this small, the UILabel will be over/under the switch. If set to the width of the switch plus left and right margin it will appear to stretch up to the switch.
In your code, you can find the width of the UISwitch by looking at its frame.
1) When the UISwitch is to be visible, set the trailing pin constraint of the UILabel to be the margin you want + width of UISwitch + margin to left of UISwitch you want.
2) When the UISwitch is to be hidden, set the trailing pin constraint of the UILabel to be the margin you want to the superview.
This should then cause the UILabel to extend to the switch when not hidden, or to the edge when the switch is hidden.
I am looking for a way to enter a label within a table cell that also has a disclosure indicator. The problem i'm having at the moment is that it seems like the disclosure indicator is being ignored when calculating the label's positions
Heres a picture:
So as you can see the label is centred in the area between the left side of the cell and the left side of the indicator, if it was centred in the cell it would sit below the nav bar heading.
Any help is appreciated thankyou
From within the storyboard
Okay, first an explanation for your issue. It has to do with the anatomy of a UITableViewCell. With anatomy, I mean the fact that the UITableViewCell for you is just a container for another container, which is the contentView (you can also see this one in your storyboard).
When you are operating in Storyboards, you are solely operating on the contentView, not on the actual UITableViewCell. So, when you setup your UILabel to be centered on the X-axis with AutoLayout, AutoLayout will always try to center it within the contentView, not in the outer container (i.e. the UITableViewCell). Then, when you add a disclosure indicator to the UITableViewCell, the contentView automatically gets shrinked in its width because the cell makes space for the disclosure indicator and wants to prevent you from adding UI elements in the right area that is reserved for the disclosure indicator.
Now, you have a few options around this:
you can edit the constraint directly and add a constant to it (which has to be the same value that the label gets shifted when you'd remove the indicator)
don't use the default disclosure indicator (i.e. don't tick the checkbox in Storyboards) and just add a UIImageView with an image that looks identical.
To not be bound to any constants you can calculate the difference in widths of frame and contentView.frame. So first create an outlet collection like so:
#property (strong, nonatomic) IBOutletCollection(NSLayoutConstraint) NSArray *centerConstraintsToOffset;
Then add the center constraints that you want to be centered horizontally in cell to that outlet collection:
And finally add this code to your cell:
override func layoutSubviews() {
super.layoutSubviews()
for constraint in centerConstraintsToOffset {
constraint.constant = (frame.size.width - contentView.frame.size.width) / 2.0
}
}
This also gives you flexibility of adding or removing cell accessories on the go, and your views will always be perfectly center aligned. Even if you remove the accessory at all.
Pavel's answer fixed the issue for me. After creating the IBOutlet collection as his answer demonstrates, here is his code example edited for Swift 3:
override func layoutSubviews() {
super.layoutSubviews()
for constraint: NSLayoutConstraint in self.centerConstraintsToOffset {
constraint.constant = (frame.size.width - contentView.frame.size.width) / 2.0
}
}
As you've already noticed, adding a 'UITableViewCellAccessoryDisclosureIndicator' will shrink the space allotted for your cell's contentView. Another solution that doesn't require a custom indicator or guessing at an offset would be to programmatically add a UILabel to the root view of the cell, not the contentView. For example:
#property UILabel *label;
// ...
- (void)layoutSubviews
{
[super layoutSubviews];
[self.label removeFromSuperview];
self.label = [[UILabel alloc] init];
self.label.text = #"Motorsport";
[self.label sizeToFit];
label.center = CGPointMake(self.center.x, self.size.height/2);
[self addSubview:self.label];
}
I defined a view which contains an UImageView and a UILabel. I setted constraints for each elements.
In wanted to do a circle with the first view, so I did that in the code :
self.mainView.layer.cornerRadius = self.mainView.frame.size.width / 2;
self.mainView.clipsToBounds = YES;
So it works, I have a circle, BUT the UImageView and the UILabel seems don't follow the constraints setted in the storyboard.
For example, on my UILabel, I setted a margin left and right 5px to the mainView, but I can see my UILabel "out" the mainView....
I tried to do a "setNeedsUpdateConstraints", but it's not the solution.
So, what I need to do to have my UILabel correctly positioned ?
Thanks,
I think this is what you are looking for:
self.mainView.layer.masksToBounds = YES;
Your problem is that when changing the mainView's layer you are not actually changing the bounds of the view. The bounds of the view are still represented in a rectangle manner. what you need to do is change the width constraint of the UILable.
To do so just create a autolayout constrain to your UILable (is you don't have it already). Control-Drag it to your viewController and change it dynamically using the constant value in the constraint.
If you don't need to set it dynamically just set the left & right margins to a bigger margin
I have a label that I create using the following way:
UILabel *label = [[UILabel alloc] initWithFrame:cell.contentView.bounds];
label.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
label.textAlignment = UITextAlignmentCenter;
I would like to center the on the bottom of the label and center it horizontally.
I did not find any UITextAlignmentBottom in the typedef enums.
Can somebody suggest a solution?
To 'align' the text to the bottom, you will want to make the UILabel the height of the text it needs to display - Google UILabel sizeToFit.
I'm not entirely sure what you mean by "center the on the bottom of the label", but I'm thinking you might be asking about how to center a label at the bottom of the view controller that it's in. To do this, you will want to add some NSLayoutConstraints to specify where in the window you want the label to go.
To do this programmatically, you will use constraintWithItem:attribute:relatedBy:toItem:attribute:multiplier:constant:. The "attribute" argument refers to NSLayoutAttribute, which can be set as NSLayoutAttributeCenterX when attempting to center the label, and NSLayoutAttributeBottom to specify the amount of space between the label and the bottom of the view controller.