iOS - anchor view to the top of the screen, behind status bar

6.1k Views Asked by At

I've a CollectionViewController with the default status bar and all it's embedded in a NavigationController.

I'm trying to reproduce an effect in which I have a View anchored to the top of the screen, since my navController is fully transparent and my status bar is also transparent, but somehow when I anchor my view to the topAnchor it stays clipped to the NavigationController bottomAnchor, because it 'thinks' the top of the screen is the navController's bottom.

I managed to bypass this simply after anchoring the view to the top, I gave it a negative topPadding and it now is where I desired it to be.

I know there's a way to extend the layout to the top screen but I can't figure it out.

Can you give me an hint?

I'm trying this:

desired

I'm getting this:

result

The white space is the status bar height + NavigationController height

Thanks

3

There are 3 best solutions below

1
On BEST ANSWER

Well, this pins my UIImageView to the Top of the screen... underneath the nav and status bars. Shouldn't be any different with a collection view:

NSLayoutConstraint *top = [NSLayoutConstraint
                           constraintWithItem:imageView
                           attribute:NSLayoutAttributeTop
                           relatedBy:NSLayoutRelationEqual
                           toItem:self.view
                           attribute:NSLayoutAttributeTop
                           multiplier:1
                           constant:0];

Edit: Sorry, was working in an Obj-C project... here it is in Swift:

    let img = UIImage(named: "Man")
    let imageView = UIImageView(image: img)
    imageView.translatesAutoresizingMaskIntoConstraints = false

    self.view.addSubview(imageView)

    imageView.widthAnchor.constraint(equalToConstant: 200.0).isActive = true
    imageView.heightAnchor.constraint(equalToConstant: 200.0).isActive = true

    imageView.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true

    imageView.topAnchor.constraint(equalTo: self.view.topAnchor).isActive = true

enter image description here

and... here it is with a collection view also (kinda hard to tell with a plain screen-cap):

    self.view.backgroundColor = .white

    let img = UIImage(named: "Man")
    let imageView = UIImageView(image: img)
    imageView.translatesAutoresizingMaskIntoConstraints = false

    self.view.addSubview(imageView)

    imageView.widthAnchor.constraint(equalToConstant: 200.0).isActive = true
    imageView.heightAnchor.constraint(equalToConstant: 200.0).isActive = true

    imageView.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true

    imageView.topAnchor.constraint(equalTo: self.view.topAnchor).isActive = true

    let layout = UICollectionViewFlowLayout()
    let cv = UICollectionView(frame: CGRect.zero, collectionViewLayout: layout)
    cv.backgroundColor = .clear

    cv.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "defaultCell")
    cv.dataSource = self

    cv.translatesAutoresizingMaskIntoConstraints = false
    self.view.addSubview(cv)

    cv.widthAnchor.constraint(equalTo: self.view.widthAnchor, multiplier: 0.9).isActive = true
    cv.heightAnchor.constraint(equalToConstant: 300.0).isActive = true

    cv.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true

    cv.topAnchor.constraint(equalTo: self.view.topAnchor).isActive = true

enter image description here

1
On

If you don't want a ViewControllers contents view to extend under the top/bottom bars, you can use the Extend Edges Under Top Bars/Under Bottom Bars settings in Interface Builder.

Try using this

ObjectiveC:

self.edgesForExtendedLayout = UIRectEdgeNone;

Swift3:

self.edgesForExtendedLayout = []

Hope this may help you :)

0
On
class DetailsPage : UIViewController {

    let topView:UIView = UIView()
    let topSliderImage:UIImageView = UIImageView()

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white
        setUI()
    }

    override func viewWillAppear(_ animated: Bool) { 
        navigationController?.navigationBar.isTranslucent = true
        navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
        navigationController?.navigationBar.shadowImage = UIImage() 
    }

    func setUI(){

        self.view.addSubview(topSliderImage)
        topSliderImage.image = UIImage(named: "img-1")
        topSliderImage.contentMode = .scaleAspectFit
        topSliderImage.translatesAutoresizingMaskIntoConstraints = false
        topSliderImage.topAnchor.constraint(equalTo: view.topAnchor, constant: 0).isActive = true
        topSliderImage.heightAnchor.constraint(equalToConstant: 300).isActive = true
        topSliderImage.widthAnchor.constraint(equalToConstant: view.frame.width).isActive = true
    }
}

enter image description here