swift 实现导航栏随tableView滑动颜色渐变、头部图片往上移动效果和往下放大效果

版权声明:本文为博主原创文章,未经博主允许不得转载。 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

猜你喜欢

转载自blog.csdn.net/lin1109221208/article/details/85690189