You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Stretchy header is cool. People are familiar with changing frames to achieve this, like Design Teardown: Stretchy Headers. But with Auto Layout, we can achieve this with much nicer declarative constraints
I use SnapKit to make it clear what constraints we need
scrollView
The scrollView should pin its 4 edges to the ViewController 's view
func setupScrollView(){
scrollView =UIScrollView()
scrollView.delegate =self
view.addSubview(scrollView)
scrollView.snp_makeConstraints{ make in
make.edges.equalTo(view)}}
scrollViewContentView
The scrollViewContentView must pin its 4 edges to the scrollView to help determine scrollViewcontentSize
The height of scrollViewContentView is determined by its subviews. The subviews inside must pin their top and bottom to the scrollViewContentView
func setupScrollViewContentView(){
scrollViewContentView =UIView()
scrollView.addSubview(scrollViewContentView)
scrollViewContentView.snp_makeConstraints{ make in
make.edges.equalTo(scrollView)
make.width.equalTo(view.snp_width)}}
header
The header must pin its top to the scrollView parent, which is the ViewController 's view
Read the title section, you 'll see that in order to make header stretchy, it must be pinned top and bottom
But if we scroll up, there will be a constraint conflict between these pinned top and bottom constraints
So we must declare headerTopConstraint priority as 999, and headerLessThanTopConstraint
func setupHeader(){
header =UIImageView()
header.image =UIImage(named:"onepiece")!
scrollViewContentView.addSubview(header)
header.snp_makeConstraints{ make in// Pin header to scrollView 's parent, which is now ViewController 's view// When header is moved up, headerTopConstraint is not enough, so make its priority 999, and add another less than or equal constraint
make.leading.trailing.equalTo(scrollViewContentView)self.headerTopConstraint = make.top.equalTo(view.snp_top).priority(999).constraint
self.headerLessThanTopConstraint = make.top.lessThanOrEqualTo(view.snp_top).constraint
}}
title
The title must pin its top to the scrollViewContentView to help determine scrollViewContentView height
The title must also pin its top the header bottom in order to make header stretchy
func setupTitleLabel(){
titleLabel =UILabel()
titleLabel.numberOfLines =0
titleLabel.font =UIFont.preferredFontForTextStyle(UIFontTextStyleTitle1)
titleLabel.text ="One Piece"
scrollViewContentView.addSubview(titleLabel)
titleLabel.snp_makeConstraints{ make in
make.leading.equalTo(scrollViewContentView).offset(20)
make.trailing.equalTo(scrollViewContentView).offset(-20)// Pin to the header to make it stretchy
make.top.equalTo(header.snp_bottom).offset(20)// Pin to the content view to help determine scrollView contentSize
make.top.equalTo(scrollViewContentView.snp_top).offset(headerHeight)}}
scrollViewDidScroll
The header is always pinned to the top, unless you adjust it, here in scrollViewDidScroll
Here I use Constraint, which is a class from SnapKit, but the idea is to change the constant of the NSLayoutConstraint
func scrollViewDidScroll(scrollView:UIScrollView){
guard let headerTopConstraint = headerTopConstraint,
headerLessThanTopConstraint = headerLessThanTopConstraint
else{return}lety= scrollView.contentOffset.y
letoffset= y >0 ? -y :0
headerLessThanTopConstraint.updateOffset(offset)
headerTopConstraint.updateOffset(offset)}
By the way, did you just learn the story of One Piece :]
Stretchy header is cool. People are familiar with changing frames to achieve this, like Design Teardown: Stretchy Headers. But with Auto Layout, we can achieve this with much nicer declarative constraints
The demo project is StretchyHeader
I use SnapKit to make it clear what constraints we need
scrollView
The
scrollView
should pin its 4 edges to theViewController 's view
scrollViewContentView
The
scrollViewContentView
must pin its 4 edges to thescrollView
to help determinescrollView
contentSize
The height of
scrollViewContentView
is determined by its subviews. The subviews inside must pin theirtop
andbottom
to thescrollViewContentView
header
The
header
must pin its top to thescrollView
parent, which is theViewController 's view
Read the
title
section, you 'll see that in order to makeheader
stretchy, it must be pinned top and bottomBut if we scroll up, there will be a constraint conflict between these pinned
top
andbottom
constraintsSo we must declare
headerTopConstraint
priority as 999, andheaderLessThanTopConstraint
title
The
title
must pin its top to thescrollViewContentView
to help determinescrollViewContentView
heightThe
title
must also pin its top theheader
bottom in order to makeheader
stretchyscrollViewDidScroll
The header is always pinned to the top, unless you adjust it, here in
scrollViewDidScroll
Here I use
Constraint
, which is a class fromSnapKit
, but the idea is to change theconstant
of theNSLayoutConstraint
By the way, did you just learn the story of One Piece :]
Reference
The text was updated successfully, but these errors were encountered: