Auto Layout Leading and Trailing Margin Defaults to 15?

I am in the process of learning and playing around with Auto Layout using Constraints and Visual Format Language. I have a UITableViewCell that I am trying to give 4 columns and I was testing out the following:

    cellConstraints.AddRange(
                    NSLayoutConstraint.FromVisualFormat(
                        "H:|-[col1(==55)]-[col2(==113)]-[col3(==48)]-[col4(==48)]-|",

                        NSLayoutFormatOptions.AlignAllCenterY,
                        cellViewConstraints
                    )
                );

I kept getting a constraint size error and I was confused as to why. The above totals up too 320 (The width of the screen) assuming the left and right leading and trailing margins are as apple states:

The default margins are 8 points on each side. You can modify these margins based on your app’s needs.

[https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/AutolayoutPG/WorkingwithConstraintsinInterfaceBuidler.html#//apple_ref/doc/uid/TP40010853-CH10-SW1]

So I thought:

16-55-8-113-8-48-8-48-16 for the width parameters. Which as mentioned totals = 320.

So I did a quick WriteLine to figure out what the values were and:

Console.Write ("Leading Margin: " + this.ContentView.LayoutMargins.Left);

Reads:

Leading Margin: 15

So if I Change my width value to:

15-55-8-115-8-48-8-48-15 assuming the Leading and Trailing Margins are 15 it works.

This has got me confused. As far as I am aware I am not attempting to change any property that might affect the Layout Margins. Why would it be 15?

Best Answer

Answers

  • ChrisShieldsChrisShields SEMember ✭✭

    Ok, good to know about the difference between generic views and specific type views when it comes to margins.

  • ChrisShieldsChrisShields SEMember ✭✭

    Hmm I seem to be running into an issue related to this.

    I want my first column to be exactly the same width as my ImageView.Image.

    So I set

        cellConstraints.AddRange(
                        NSLayoutConstraint.FromVisualFormat(
                            "H:|-[col1(==image)]-[col2(>=100,<=260)]-[col3(>=50,<=110)]-[col4(>=50,<=110)]-|",
                            NSLayoutFormatOptions.AlignAllCenterY,
                            cellViewConstraints
                        )
                    );
    

    Where image is a reference to ImageView. I get a constraint fault on the col3 - col4 relation. I am assuming what is happening is that because ImageView.Frame is uninitialized in my setConstaints it assumes the width is 0 and adjusts col2's width to take up more space, but when the ImageView is initialized the width of the image pushes the entire width of my constraints outside the bounds of the superview.

    If this is indeed what is happening how do I remedy the solution? My ImageView's width is relative to the height of the cell if I am not mistaken, so its hard to figure out how to determine the width of col1 if it is to be the same width of the ImageView when the said width is dependant on other constraints. Like how high the column will be dependant on dynamic text row heights in the said column.

    I could always just implement my own image in a UILabel or UIImage I suppose but, I like the idea of not needing to rewrite that code. Unless maybe I need to!

  • adamkempadamkemp USInsider, Developer Group Leader mod

    I have a really hard time making sense of the visual language, and I think you've reached the limits of what I can help you with here.

  • ChrisShieldsChrisShields SEMember ✭✭
    edited October 2015

    Ok, thanks adam. I read, I read some more, I thought, I thought harder and I found a solution :). I'm not sure if its the best solution but it works as I want it to anyways. Here is the way I have it working:

    col1 in

    "H:|-[col1(==image)]-[col2(>=100,<=260)]-[col3(>=50,<=110)]-[col4(>=50,<=110)]-|",

    needs to be adaptive. I want it to take up a % of the cell width so that when it is in landscape mode for example, col1 will expand correctly and also look good on both the iPhone4 and iPhone6, all columns need to grow and shrink for that matter.

    I want the column to be the same width as the image in it. Except the width of the column can't be determined outright without the width of the image being decided.

    To resolve this I had to decide the images width myself. So instead of using my UITableViewCell's ImageView property, I add my own UIImageView and this way have more control.

    The new VFL entry for the cell's horizontal layout looks like this:

    "H:|-[col1(>=20,<=45)]-[col2(>=90,<=400)]-[col3(>=60,[email protected])]-[col4(>=50,[email protected])]-|",

    col1 will now always be between 20 and 45 points
    col2 will be between 90 and 400 points.
    col3 will always be at least 60 points indicated by ==60, however it can grow if needed to fill the cell as the width condition includes the line >=60 and ==60 is set at a lower priority by @900. The same applies to col4.

    To get the image to work well in col1

    I use two VFL constraints:

            cellConstraints.AddRange (
                NSLayoutConstraint.FromVisualFormat (
                    "V:[col1]-(<=0)-[image(<=col1)]-16-|",
                    NSLayoutFormatOptions.AlignAllCenterX,
                    this.ConstraintDictionary
                )
            );
    
            cellConstraints.AddRange (
                NSLayoutConstraint.FromVisualFormat (
                    "H:[col1]-(<=0)-[image(<=col1)]-5-|",
                    NSLayoutFormatOptions.AlignAllCenterY,
                    this.ConstraintDictionary
                )
            );
    

    V:[superview]-(<=0)-[y]-| is a nifty little trick that centers y in its super view. From this stack overflow answer.

    Then I set the images width to always be less than that of col1.

    With that in place I can adjust the margins as needed to size my image how I want it with -16- and -5-.

    Provided now the image is not the size of my column as instead I decided it was easier to give the column a greater range and let the column's width determine the image size.

    The numbers in my VFL are all magic numbers but they are the ranges that look best aesthetically. Ill maybe put them in a dictionary later on.

    Hope this helps someone!

    EDIT:

    Forgot a very important step!

    I had to create one standard Constraint that you can't do in VFL which is an aspect constraint:

    cellConstraints.Add (
                    NSLayoutConstraint.Create (
                        _myImage,
                        NSLayoutAttribute.Width,
                        NSLayoutRelation.Equal,
                        _myImage,
                        NSLayoutAttribute.Height,
                        1,
                        0
                    )
                );
    

    This way we keep the dimensions of the image at the correct aspect ratio always, which keeps it a square :)

Sign In or Register to comment.