版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/lin1109221208/article/details/85690189
需求:实现导航栏随tableView滑动颜色渐变、头部图片往上移动效果和往下放大效果
最终效果如下:
准备工作:先用storyboard创建一个视图控制器(UIViewController),加入视图(TableView),并添加约束
1、用imageView作头部背景图片,并保存初始frame
//图片
self.bgView = UIImageView.init(frame: CGRect.init(x: 0, y: 0, width: Screen_Width, height: Screen_Width*0.751))
self.bgView.image = UIImage.init(named: "11")
self.view.addSubview(self.bgView)
self.view.sendSubviewToBack(self.bgView)
self.originalFrame = self.bgView.frame
2、创建tableView的透明头部,目的是显露出头部的背景图片
//头部
let headerView = UIView.init(frame: CGRect.init(x: 0, y: 0, width: Screen_Width, height: 160))
headerView.backgroundColor = UIColor.clear
self.tableVIew.tableHeaderView = headerView
3、顶部的导航栏可以使用系统的,也可以使用自定义的导航栏
1)使用系统导航栏:需要在storyboard或者代码设置导航栏属性
(1)将导航栏设置为透明并去掉下方黑线
//系统导航栏,利用push跳转,但是有个问题是状态栏的颜色未渐变
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.navigationController?.navigationBar.setBackgroundImage(UIImage.init(), for: .default)
self.navigationController?.navigationBar.shadowImage = UIImage.init()
}
(2)根据滑动时偏移的y值作相应操作
//往上滑动,offset是增加的,往下是减小的
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let offset = scrollView.contentOffset.y
//第一种:系统导航栏,利用push跳转,但是有个问题是状态栏的颜色未渐变
if offset<160 {
//滑倒底部之前
let coloralph = offset/160
self.navigationController?.navigationBar.backgroundColor = UIColor.white.withAlphaComponent(coloralph)
self.navigationController?.title = "测试标题"
}else{
//滑动超过导航栏底部
self.navigationController?.navigationBar.backgroundColor = UIColor.white
}
//处理图片放大效果、往上移动效果
if offset > 0 {
//往上
bgView.frame = {
var bgFrame = originalFrame
bgFrame?.origin.y = originalFrame.origin.y-offset
return bgFrame!
}()
}else{
//往下放大
var bgFrame = originalFrame
bgFrame?.size.height = originalFrame.size.height-offset//offset是负的
bgFrame!.size.width = (bgFrame?.size.height)!/CGFloat(ratio)
bgFrame!.origin.x = (originalFrame.size.width-(bgFrame?.size.width)!)/2
self.bgView.frame = bgFrame!
}
}
2)使用自定义导航栏
(1)自定义导航栏
let Screen_Width = UIScreen.main.bounds.size.width
let Screen_Height = UIScreen.main.bounds.size.height
let StateBar_Height = UIApplication.shared.statusBarFrame.height
let CustomHeight : CGFloat = 30
import UIKit
class CustomNaviBar: UIView {
// var title : String!
// var leftImage : String!
// var rightImage : String!
// var titleColor : UIColor!
var leftBtn : UIButton!
var rightBtn : UIButton!
var titleLabel : UILabel!
override init(frame: CGRect) {
super.init(frame: frame)
self.frame = frame
self.backgroundColor = UIColor.clear
self.leftBtn = UIButton.init(type: .custom)
self.leftBtn.frame = CGRect.init(x: 16, y: StateBar_Height+10, width: CustomHeight, height: CustomHeight)
self.leftBtn.setImage(UIImage.init(named: "button-返回"), for: .normal)
self.addSubview(self.leftBtn)
self.rightBtn = UIButton.init(type: .custom)
self.rightBtn.frame = CGRect.init(x: Screen_Width-15-CustomHeight, y: StateBar_Height+10, width: CustomHeight, height: CustomHeight)
self.addSubview(self.rightBtn)
self.titleLabel = UILabel.init(frame: CGRect.init(x: Screen_Width/2-50, y: StateBar_Height+10, width: 100, height: CustomHeight))
self.titleLabel.text = "测试标题"
self.titleLabel.textAlignment = .center
self.titleLabel.font = UIFont.systemFont(ofSize: 15)
self.titleLabel.textColor = UIColor.white
self.addSubview(self.titleLabel)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
/*
// Only override draw() if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
override func draw(_ rect: CGRect) {
// Drawing code
}
*/
}
(2)在控制器中定义导航栏变量,并初始化
//第二种:自定义导航栏 CustomNaviBar
//导航栏
self.customNavi = CustomNaviBar.init(frame: CGRect.init(x: 0, y: 0, width: Screen_Width, height: StateBar_Height+44))
self.customNavi.backgroundColor = UIColor.clear
self.view.addSubview(self.customNavi)
(3)实现图片的往下放大、往上移动效果
//往上滑动,offset是增加的,往下是减小的
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let offset = scrollView.contentOffset.y
//第二种:自定义导航栏
//导航栏颜色渐变
if offset < 160 {
//滑动到导航栏底部之前
let cocloralph = offset/160
self.customNavi.backgroundColor = UIColor.white.withAlphaComponent(cocloralph)
self.customNavi.titleLabel.textColor = UIColor.white
self.customNavi.leftBtn.setImage(UIImage.init(named: "button-返回"), for: .normal)
}else{
//滑动超过导航栏底部
self.customNavi.backgroundColor = UIColor.white
self.customNavi.titleLabel.textColor = UIColor.red
self.customNavi.leftBtn.setImage(UIImage.init(named: "button-返回B"), for: .normal)
}
//图片往上移动效果、往下放大效果
if offset > 0 {
//移动,offset值是正的
self.bgView.frame = {
var bgFrame = originalFrame
bgFrame?.origin.y = originalFrame.origin.y-offset
return bgFrame!
}()
}else{
//放大,往下offset是负的,负负得正
self.bgView.frame = {
var bgFrame = originalFrame
bgFrame!.size.height = originalFrame.size.height-offset
bgFrame!.size.width = ((bgFrame?.size.height)!)/CGFloat(ratio)
bgFrame!.origin.x = (originalFrame.size.width-((bgFrame?.size.width)!))/2
return bgFrame!
}()
}
print("bgView \(self.bgView.frame)")
}
具体的demo:demo下载地址 或者github下载:github下载demo