UITableViewCell with autolayout left margin different on iPhone and iPad

后端 未结 5 932
臣服心动
臣服心动 2020-11-28 19:47

I am using a grouped UITableView with static cells for an options screen/scene. Everything is done in Xcode 6.1 / iOS 8.1.x / Storyboard using Autolayout. Withi

5条回答
  •  失恋的感觉
    2020-11-28 20:20

    After reading through the existing answers and not finding an obvious programmatic solution, I did some more digging and now have a good answer for anyone else facing this issue.

    First off, it's not necessary to set preservesSuperviewLayoutMargins to the cell's view or content view as other answers imply. While the default value is false, changing it to true had no noticeable effect that I could see.

    The key for making this actually work is the layoutMarginsGuide property on UIView. Using this value, we can just easily pin the leadingAnchor of any subview to the leadingAnchor of the guide. Here's how it looks in code (and may very well be what IB is doing behind the scenes as in Jonas's answer).

    In a UITableViewCell subclass, you would do something like this:

    override func updateConstraints() {
        let margins = contentView.layoutMarginsGuide
        let leading = margins.leadingAnchor
        subview1.leadingAnchor.constraintEqualToAnchor(leading).active = true
        subview2.leadingAnchor.constraintEqualToAnchor(leading).active = true
    
        super.updateConstraints()
    }
    

    Swift 4.1 update

    override func updateConstraints() {
        let margins = contentView.layoutMarginsGuide
        let leading = margins.leadingAnchor
        subview1.leadingAnchor.constraint(equalTo: leading).isActive = true
        subview2.leadingAnchor.constraint(equalTo: leading).isActive = true
    
        super.updateConstraints()
    }
    

    That's all! If you're developing for iOS versions pre-iOS 9, you'll need to substitute out the layout anchors and use the layoutMargins inset instead.


    Note: I wrote a library to make the anchor pinning a little prettier, if you'd prefer a cleaner syntax. It's called SuperLayout and is available on Cocoapods. At the top of your source file, import SuperLayout:

    import SuperLayout
    

    And then in your layout block, use ~~, ≤≤, and ≥≥ to pin constraints:

    override func updateConstraints() {
        let margins = contentView.layoutMarginsGuide
    
        subview1.leadingAnchor ~~ margins.leadingAnchor
        subview2.leadingAnchor ~~ margins.leadingAnchor
    
        super.updateConstraints()
    }
    

    ios 11+: let margins = contentView.directionalLayoutMargins ... in case you need to adapt to LTR and RTL out of the box. I assume most folks do need that.

提交回复
热议问题