一,效果图:
二。状态分析:
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
这些状态的,需要自己打印 offsetY 与 deltaOfOffsetY 这2个值的变化才能够知道
下面直接给出判断结果,注释有分析:
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") } } }