一,效果图:
二。状态分析:
IOS这种滚动列表的滑动总共有四种状态(需要将弹性效果打开才有)
对于状态更新主要通过两个关键值判断:
let offset : CGPoint = change![NSKeyValueChangeKey.newKey] as! CGPoint
let offsetY : CGFloat = offset.y
let oldOffset : CGPoint = change![NSKeyValueChangeKey.oldKey] as! CGPoint
let oldOffsetY : CGFloat = oldOffset.y
let deltaOfOffsetY : CGFloat = offsetY - oldOffsetY
下面直接给出判断结果,注释有分析:
if deltaOfOffsetY < 0 && offsetY < 0 { //单纯向下滑
//print("208-----------: down")
// if ((self.headerHeightConstraint?.constant)! >= self.headerHeight) {
//
// self.headerHeightConstraint?.constant = self.headerHeight;
//
// } else {
//
// self.headerHeightConstraint?.constant -= deltaOfOffsetY;
//
// }
}
if (deltaOfOffsetY > 0 && offsetY < 0){ //单纯向下拉,然后向上回弹
//print("224-----------: down---up")
}
if(deltaOfOffsetY > 0 && offsetY > 0 ){ //单纯向上滑
//print("229-----------: up")
if ((self.headerHeightConstraint?.constant)! <= self.segmentMiniTopInset + 60) {
self.headerHeightConstraint?.constant = self.segmentMiniTopInset + 60;
}else{
self.headerHeightConstraint?.constant -= deltaOfOffsetY;
}
//调整UItableView的位置 ,防止出现空白,,当列表中的内容大于列表可见框的高度时,才调整列表的位置
// if (listView?.contentSize.height)! > (getScreenSize().height - headerHeight){
//
// var frame : CGRect = (listView?.frame)!
//
// if frame.origin.y <= 63{
//
// frame.origin.y = 63
//
// }else{
//
// frame.origin.y -= deltaOfOffsetY
// }
//
// listView?.frame = frame
// }
//调整搜索框的宽度。达到缩放动画效果
if (labelWidthConstraint?.constant)! <= 280{
labelWidthConstraint?.constant = 280
}else{
labelWidthConstraint?.constant -= deltaOfOffsetY
}
}
if(deltaOfOffsetY < 0 && offsetY > 0 ){ //1.单纯向上滑,然后向下回弹 2.向下滑时--滚动视图有一部滑出了滚动视图,还未滑动到可视范围
if offsetY > 200 { //2.向下滑时--滚动视图有一部滑出了滚动视图,还未滑动到可视范围
}else{
if ((self.headerHeightConstraint?.constant)! >= self.headerHeight) {
self.headerHeightConstraint?.constant = self.headerHeight;
} else {
self.headerHeightConstraint?.constant -= deltaOfOffsetY;
}
// var frame : CGRect = (listView?.frame)!
//
// if frame.origin.y >= 250{
//
// frame.origin.y = 250
//
// }else{
//
// frame.origin.y -= deltaOfOffsetY
// }
//
// listView?.frame = frame
//调整搜索框的宽度。达到缩放动画效果
if (labelWidthConstraint?.constant)! >= getScreenSize().width - 40{
labelWidthConstraint?.constant = getScreenSize().width - 40
}else{
labelWidthConstraint?.constant -= deltaOfOffsetY
}
}
//print("250-----------:up-------- down")
}
}
三.头部视图高度的变化:
在第二步可以监听到UIScrollView的滚动状态变化,根据这些变化再配合头部视图的约束更新,即能达到头部视图的动态变化
四。UIScrollView kVO的全部代码如下:
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
if keyPath == "contentOffset"{
let offset : CGPoint = change![NSKeyValueChangeKey.newKey] as! CGPoint
let offsetY : CGFloat = offset.y
let oldOffset : CGPoint = change![NSKeyValueChangeKey.oldKey] as! CGPoint
let oldOffsetY : CGFloat = oldOffset.y
let deltaOfOffsetY : CGFloat = offsetY - oldOffsetY
//print("203---------------deltaOfOffsetY: \(deltaOfOffsetY) offsetY: \(offsetY)")
if deltaOfOffsetY < 0 && offsetY < 0 { //单纯向下滑
//print("208-----------: down")
// if ((self.headerHeightConstraint?.constant)! >= self.headerHeight) {
//
// self.headerHeightConstraint?.constant = self.headerHeight;
//
// } else {
//
// self.headerHeightConstraint?.constant -= deltaOfOffsetY;
//
// }
}
if (deltaOfOffsetY > 0 && offsetY < 0){ //单纯向下拉,然后向上回弹
//print("224-----------: down---up")
}
if(deltaOfOffsetY > 0 && offsetY > 0 ){ //单纯向上滑
//print("229-----------: up")
if ((self.headerHeightConstraint?.constant)! <= self.segmentMiniTopInset + 60) {
self.headerHeightConstraint?.constant = self.segmentMiniTopInset + 60;
}else{
self.headerHeightConstraint?.constant -= deltaOfOffsetY;
}
//调整UItableView的位置 ,防止出现空白,,当列表中的内容大于列表可见框的高度时,才调整列表的位置
// if (listView?.contentSize.height)! > (getScreenSize().height - headerHeight){
//
// var frame : CGRect = (listView?.frame)!
//
// if frame.origin.y <= 63{
//
// frame.origin.y = 63
//
// }else{
//
// frame.origin.y -= deltaOfOffsetY
// }
//
// listView?.frame = frame
// }
//调整搜索框的宽度。达到缩放动画效果
if (labelWidthConstraint?.constant)! <= 280{
labelWidthConstraint?.constant = 280
}else{
labelWidthConstraint?.constant -= deltaOfOffsetY
}
}
if(deltaOfOffsetY < 0 && offsetY > 0 ){ //1.单纯向上滑,然后向下回弹 2.向下滑时--滚动视图有一部滑出了滚动视图,还未滑动到可视范围
if offsetY > 200 { //2.向下滑时--滚动视图有一部滑出了滚动视图,还未滑动到可视范围
}else{
if ((self.headerHeightConstraint?.constant)! >= self.headerHeight) {
self.headerHeightConstraint?.constant = self.headerHeight;
} else {
self.headerHeightConstraint?.constant -= deltaOfOffsetY;
}
// var frame : CGRect = (listView?.frame)!
//
// if frame.origin.y >= 250{
//
// frame.origin.y = 250
//
// }else{
//
// frame.origin.y -= deltaOfOffsetY
// }
//
// listView?.frame = frame
//调整搜索框的宽度。达到缩放动画效果
if (labelWidthConstraint?.constant)! >= getScreenSize().width - 40{
labelWidthConstraint?.constant = getScreenSize().width - 40
}else{
labelWidthConstraint?.constant -= deltaOfOffsetY
}
}
//print("250-----------:up-------- down")
}
}
}