I have some problem setting margin on some view inside uiscrollview, I create via IB a scrollview and 3 view (they are outside of self.view), in my app I add this view with:
[scrollview addsubview:view1], eccc
after this I add constrains in this way:
[_ingredienti setTranslatesAutoresizingMaskIntoConstraints:NO];
[_scrollView addSubview:_ingredienti];
[_scrollView addConstraint:[NSLayoutConstraint constraintWithItem:_ingredienti
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:_scrollView
attribute:NSLayoutAttributeHeight
multiplier:1
constant:0]];
[_scrollView addConstraint:[NSLayoutConstraint constraintWithItem:_ingredienti
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:_scrollView
attribute:NSLayoutAttributeWidth
multiplier:1
constant:0]];
[_scrollView addConstraint:[NSLayoutConstraint constraintWithItem:_ingredienti
attribute:NSLayoutAttributeLeftMargin
relatedBy:NSLayoutRelationEqual
toItem:_scrollView
attribute:NSLayoutAttributeLeft
multiplier:1
constant:self.scrollView.frame.size.width * 2]];
this for all 3 views, obviously NSLayoutAttributeLeftMargin has 3 different value, 0, self.scrollView.frame.size.width and 2 * self.scrollView.frame.size.width, the problem is that the margin is wrong, is some pixel less then self.scrollView.frame.size.width, where is the mistake?
It appears that there are no constraints linking the _ingredienti top, bottom or right position to the _scrollview, which it needs to size its contentview. See the "Pure Autolayout" subsection of Technical Note TN2154: UIScrollView And Autolayout
Related
UIViewController's topLayoutGuide and bottomLayoutGuide are deprecated in iOS 11. What should be the replacement?
Previously in your UIViewController:
customView.topAnchor.constraint(equalTo: topLayoutGuide.bottomAnchor).isActive = true
customView.bottomAnchor.constraint(equalTo: bottomLayoutGuide.topAnchor).isActive = true
Now you should use:
customView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
customView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor).isActive = true
Note the change from bottomAnchor to topAnchor. This is because the top layout guide was a rectangle at the top of the view controller, so in order to constraint your content to the top, you wanted the bottom anchor of the guide. The new safe are layout guide is a rectangle portion of the view unobscured by bars and other content, so you want the top anchor. And vice-versa for the bottom layout guide.
I have a tableview cell and im using the UIAutomaticDimensions functionality to make sure the tableview cell can size itself. The cell has 3 labels and an imageview as its contents. Now the problem is with the labels and their vertical constraints. unless there is text in the label the label will not show. It just overwrites the previous position of the label on top of it and makes the cell very very small. What i want to be able to do is always display all three labels so the height of the cell is always the same as another cell.
How can i achieve showing the label even if there is no text in the label?
Heres an explination of the contents constraints.
[self.contentView addConstraint:[NSLayoutConstraint constraintWithItem:_prospect_avatar
attribute:NSLayoutAttributeLeading
relatedBy:NSLayoutRelationEqual
toItem:self.contentView
attribute:NSLayoutAttributeLeading
multiplier:1.0
constant:0.0f]];
[self.contentView addConstraint:[NSLayoutConstraint constraintWithItem:_prospect_avatar
attribute:NSLayoutAttributeTrailing
relatedBy:NSLayoutRelationEqual
toItem:self.contentView
attribute:NSLayoutAttributeLeading
multiplier:1.0f
constant:100.0f]];
[self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[_prospect_avatar]|"
options:0
metrics:nil
views:NSDictionaryOfVariableBindings(_prospect_avatar)]];
[self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:[_prospect_avatar][_full_name_label]-|"
options:NSLayoutFormatDirectionLeadingToTrailing
metrics:nil
views:NSDictionaryOfVariableBindings(_prospect_avatar,_full_name_label)]];
[self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:[_prospect_avatar][_phone_number_label]-|"
options:NSLayoutFormatDirectionLeadingToTrailing
metrics:nil
views:NSDictionaryOfVariableBindings(_prospect_avatar,_phone_number_label)]];
[self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:[_prospect_avatar][_email_label]-|"
options:NSLayoutFormatDirectionLeadingToTrailing
metrics:nil
views:NSDictionaryOfVariableBindings(_prospect_avatar,_email_label)]];
[self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|-10-[_full_name_label][_email_label][_phone_number_label]-10-|"
options:NSLayoutFormatAlignAllLeading
metrics:nil
views:NSDictionaryOfVariableBindings(_full_name_label,_email_label,_phone_number_label)]];
Mahesh Agrawala has the correct answer. In the vertical constraints for eah of the labels i have to add a greater than or less than value for the labels height. So for example what i previously had set for the constraints was
[self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|-10-[_full_name_label][_email_label][_phone_number_label]-10-|"
options:NSLayoutFormatAlignAllLeading
metrics:nil
views:NSDictionaryOfVariableBindings(_full_name_label,_email_label,_phone_number_label)]];
WHen really the constraint should have looked like
[self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|-10-[_full_name_label(>=20)][_email_label(>=20)][_phone_number_label(>=20)]-10-|"
options:NSLayoutFormatAlignAllLeading
metrics:nil
views:NSDictionaryOfVariableBindings(_full_name_label,_email_label,_phone_number_label)]];
If you look at my new constraints at the end of each label in the constraint i have added (>=20) right before the trailing ] this tells autolayout that i at least want this label to 20 points or greater in height
There are numerous other ways to do this so this is not the only way to accomplish my task but in this circumstance it was the quickest.
Goal: to be able to animate a container-view's frame while it's subviews keep their original layout & scale in proportion to their container view.
Scenario:
Elements positioned via constraints/autolayout; within green container.
Green containerView's physical coordinates (frame/bounds) are adjusted per animation.
Members' compression & hugging properties are set to a low priority.
UIView.animateWithDuration(0, animations: {
self.bounds = myBounds
}) {(One) in
UIView.animateWithDuration(1, animations: {
self.frame = myFrame
}) {(Two) in
UIView.animateWithDuration(0.5, animations: {
self.frame = origFrame
// self.center = myCenter
}) {(Three) in
UIView.animateWithDuration(0.2, animations: {
self.frame = distantFrame
})
}
}
}
Here's the original layout:
I would like to have member element scale proportionally with their container view like this:
But the member elements (the one label 'Hello World!') don't adjust accordingly as their green containerView animates to a square in the upper left-hand corner:
How do I keep a UIView's members' layout in proportion to the prevailing their prevailing container view's frame?
Note: This would apply to any type of member (UIView, UITextView, ...etc.); for simple position/layout & transformation (pivot) animations.
In your example, you have a green background view (BG) and a hello world view (HW), and you want HW to scale in proportion to BG.
You can achieve this easily:
Open the Utilities pane in Xcode (top rightmost icon), and the Document outline (bottom left icon of storyboard).
Let’s assume that HW is already centered in BG, i.e. that you already set the alignment constraints for HW center horizontally and vertically in container.
Now, select BG as well as HW in the Document outline, and click the „Pin“ icon bottom right. It will offer the constraints „Equal widths“ and „Equal heights“. Activate both.
After these constraints have been created, open one of them in the Document outline. The utilities pane will then show the Equal Width constraint with the 2 views and a Multiplier field.
In the Multiplier field, you can enter the required proportions for the selected dimension, e.g. 1:3. This will fix the proportion for the selected dimension.
For the other dimension of course analogously. Of course you had then to update the frame of HW.
Here is an example:
I would like to make numbers of uiview in the center of the red area.
How could I do that with NSAutolayout ? Even when users rotate?
landscape mode
top
....................................
- view - ... 200px margin from right
| gap
- view -
| gap
- view -
| gap
- view -
....................................
bottom
Your question isn't really clear.
You can create constraints to center a view with respect to another view in a given orientation. For example, you can set one view's "centerX" attribute to equal some other view's centerX. (You could also make it equal that other view's leading, trailing, left, or right edge. Or even other attributes that don't make much intuitive sense, like width, top, etc., if that's what you want.)
If you're trying to vertically center a group like the stack of views in your diagram, there are a couple of approaches. First, you can embed the group into another view that closely encloses it. Its top would equal the top of the first view in the stack and its bottom would equal the bottom of the last view in the stack. Then you could set up a constraint to keep that container view centered within its superview.
The other approach is to create hidden spacer views. Put one view, the top spacer, above the first view in your stack. Make its top equal the top of the superview. Make its bottom equal the top of the first view in your stack. Similarly, set up a spacer at the bottom. Its top would equal the bottom of the last view in your stack. Its bottom would equal the bottom of the superview. Then, set a constraint between the top spacer and the bottom spacer to make their heights equal. That ensures that the space between the stack and the superview is the same on the top and the bottom.
The same techniques work for the horizontal direction, too, if necessary.
Update:
Here's some code which I haven't tested at all:
UIView* redArea = /* ... */;
NSArray* stackViews = /* ... */;
UIView* container = [[UIView alloc] initWithFrame:NSZeroRect];
[redArea addSubview:container];
UIView* previousView = nil;
for (UIView* view in stackViews)
{
[container addSubview:view];
if (previousView)
{
// Make a gap between the stacked views
NSDictionary* views = NSDictionaryOfVariableBindings(view, previousView);
NSArray* constraints = [NSLayoutConstraint constraintsWithVisualFormat:#"V:[previousView]-[view]" options:0 metrics:nil views:views];
[container addConstaints:constraints];
}
else
{
// Make the top of the container the same as the top of the first stacked view
NSDictionary* views = NSDictionaryOfVariableBindings(view);
NSArray* constraints = [NSLayoutConstraint constraintsWithVisualFormat:#"V:|[view]" options:0 metrics:nil views:views];
[container addConstaints:constraints];
}
// Make sure the container is at least as wide as each stacked view
NSDictionary* views = NSDictionaryOfVariableBindings(view);
NSArray* constraints = [NSLayoutConstraint constraintsWithVisualFormat:#"H:|-(>=0)-[view]-(>=0)-|" options:0 metrics:nil views:views];
[container addConstaints:constraints];
previousView = view;
}
if (previousView)
{
// Make the bottom of the container the same as the bottom of the last stacked view
NSDictionary* views = NSDictionaryOfVariableBindings(previousView);
NSArray* constraints = [NSLayoutConstraint constraintsWithVisualFormat:#"V:[previousView]|" options:0 metrics:nil views:views];
[container addConstaints:constraints];
}
// Make the container as narrow as possible after satisfying other constraints
NSLayoutConstraint* minimalWidth = [NSLayoutConstraint constraintWithItem:container attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:0];
minimalWidth.priority = UILayoutPriorityFittingSizeLevel - 1;
[container addConstraint:minimalWidth];
// Center the container within the red area
NSLayoutConstraint* centerVertically = [NSLayoutConstraint constraintWithItem:container attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:redArea attribute:NSLayoutAttributeCenterY multiplier:1 constant:0];
NSLayoutConstraint* centerHorizontally = [NSLayoutConstraint constraintWithItem:container attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:redArea attribute:NSLayoutAttributeCenterX multiplier:1 constant:0];
[redArea addConstraints:#[centerVertically, centerHorizontally]];
This would all be easier to set up in IB.
I have a question that might seem "basic" but I just cannot figure out how to do it...
I have a box and I'd like to change the borderColor. Till there, nothing special. Just a box.bordercolor = xxxxxx...
BUT, I'd like to have the top and bottom border with one color, and the left and right border with another color... And that's the part where I'm stuck.
Any tips? Suggestions?
Thanks for your help and time! ;)
Regards,
BS_C3
#Senz
Hi!
Unfortunately, I won't be able to share the code without making it "incomprehensible"...
But this is the idea... We have 2 main components: ArrowButton and Navigator.
ArrowButton is a hbox containing a label and an image (this image is the arrow tip and it changes depeding on the state of the ArrowButton).
Navigator is a hbox containing a series of ArrowButton. An ArrowButton overlaps the arrowButton on its right in order to create the pointed end of the button.
And then you just create a whole bunch of functionnalities around these components.
I hope this helps... Do not hesitate if you have some more questions =)
Regards.
I noticed you are asking about the Flex 3 SDK. Skins are a good approach. They have changed somewhat in Flex 4(for the better IMHO). If you are wanting to use the Flex Drawing API, then just extend the Box class into a custom class that would look something like this:
public class MultiColorBorderBox extends Box
{
// You could add getters/setters or constructor parameters to be able to change these values.
private var topColor:uint = 0xFF0000;
private var rightColor:uint = 0x00FF00;
private var bottomColor:uint = 0x0000FF;
private var leftColor:uint = 0xFF00FF;
private var borderWidth:Number = 20;
public function MultiColorBorderBox()
{
super();
}
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
{
super.updateDisplayList(unscaledWidth, unscaledHeight);
// This just ensures you dont have content under your border
this.setStyle("paddingLeft", borderWidth);
this.setStyle("paddingRight", borderWidth);
this.setStyle("paddingTop", borderWidth);
this.setStyle("paddingBottom", borderWidth);
var g:Graphics = this.graphics; // This creates a new Graphics object and sets it to the MultiColorBorderBox graphics object. Since Box (superclass) descends from a Sprite object, it has a graphics object automatically.
g.clear();
g.moveTo(0,0); // Moves the position to the top left corner
g.lineStyle(borderWidth, topColor); // Sets the line style with the width and color
g.lineTo(unscaledWidth, 0); // Draws the top border from top left to top right corners
g.lineStyle(borderWidth, rightColor); // Changes the line style
g.lineTo(unscaledWidth, unscaledHeight); // Draws the line from top right to bottom right
g.lineStyle(borderWidth, bottomColor); //Changes the bottom border style
g.lineTo(0, unscaledHeight); // Draws the line from bottom right to bottom left
g.lineStyle(borderWidth, leftColor); // Changes the border color
g.lineTo(0,0); // Closes the box by drawing from bottom left to top left
}
I'm pretty sure you're going to have to create a borderSkin to accomplish this. I believe these are created in an external program, such as Flash Professional; but more info is in the docs.
I don't think that Flex makes any distinction between top/bottom borders and left/right borders. Creating a skin would certainly be the nifty-slick way to do it. A programmatic way might be to use box.graphics to draw your border by hand. I'd start by trying to override the updateDisplayList() function to draw your border...
I finally did a pretty simple thing.
I guess I wasn't detailed enough regarding the specifications.
The actual aim was to create a navigator with arrow shaped buttons.
Each button had to be highlighted when it was selected. And this http://www.freeimagehosting.net/uploads/bcd0d762d7.jpg is how the navigator looked like.
Each button is actually an HBox containing a Box (with a label) and an Image (for the arrow tip), with a horizontalGap = 0.
I didn't think about adding a glowfilter to the button. So I was trying to just change the colors of the top and bottom part of the Box...
So, the glowfilter in the button worked pretty well.
Sorry for the lack of explanations about the context >_< And thanks for your answers!!
Regards.