Swift*UINavigationBar动态颜色/透明度/隐藏

一、透明度变化,类京东首页

11.gif

一般透明度变化都会牵扯到滚动视图(scrollView)包括UIScrollView、UITableView、UICollectionView等,可以使用通用的一些属性作响应处理。

最后实现“导航栏”透明度变化的并不是导航栏,只是实现了一种相同的效果,因为直接使用NavigationBar的过程中遇到一些问题,导致实际体验有些瑕疵,下面作简单说明。

1、最简单的方式,直接改变navigationBar透明度,有些问题

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    let offset = scrollView.contentOffset.y;
    if (offset <= 0 && offset <= -90) {

       self.navigationController?.navigationBar.alpha = 0;

    }else if(offset<=300){ //取值可以根据自己的需求
       //alpha最大值为1
        self.navigationController?.navigationBar.alpha = offset/200;
    }
}

这是一种最简单的方式,只要改变navigationBar的透明度就可以了,并且效果很好。
但是这个方式的问题是,UINavigationController只有当前页面,那这是最好的选择,但如果对应还有上下层viewController,在也页面切换的过程中就会出现一些不太友好的情况。
这里改变的navigationBar并非当前viewController所独有的,而是属于NavigationController下所有viewcontrollers的,所以在改变当前页面透明度时,其他的也都会改变。

影响下一级

当然也尝试在对应页面重新设置navigationBar的alpha,但在返回/切换的过程中,效果并不理想,尤其是当两个页面的navigationBar的颜色不同时(一般情况下,这种情况都是首页->详情页,导航栏不同是绝对正常的情况),那个画面就更美了。

所以,虽然很想省功夫,直接在navigationBar的基础上去做更改,但实际情况却很尴尬。尝试了做一些修改,但结果都不怎么理想。

所以尝试使用偷懒的方式,就是自定义一个view“假装”navigationBar。所以如果你坚持想要使用源生navigationBar,可以继续尝试,会有办法的。现在主要目的是实现需求,达到效果就好。

2、偷懒又好用的方法,隐藏navigationBar,自定义view

为什么这么用呢?
1、一般导航栏颜色/透明度变换页面只有首页/个人中心/其他主视图页面使用,不会多。
2、可以集成三方自定义的导航栏,一般没有必要这么麻烦,因为自定义view很easy
主要代码:

func scrollViewDidScroll(_ scrollView: UIScrollView) { 
    let offset = scrollView.contentOffset.y;
    if (offset <= 0 && offset <= -90) {
        navigationBarView.backgroundColor = UIColor.red//可以忽略,想要动态改变颜色,可以保留
        navigationBarView.alpha = 0;
    }else if(offset<=300){
        navigationBarView.backgroundColor = UIColor.red//可以忽略,想要动态改变颜色,可以保留
        //alpha最大值为1
        navigationBarView.alpha = offset/255;//调整alpha值

    } else {
        navigationBarView.backgroundColor = UIColor.green //可以选择改变颜色
    }

}

navigationBarView即为自定义仿制导航栏,这个很简单,只是一个view,手动添加可以,storyboard添加也可以,这里只是调整view的透明度,标题、按钮均可自定义。

这里也提供了tableView的Cell自动布局的方式,需要在storyboard中设置对应约束关系。

tableView.rowHeight = UITableViewAutomaticDimension;

tableView.estimatedRowHeight = 100;

viewController.swift完整代码:

class ViewController: UIViewController,UITableViewDataSource,UITableViewDelegate {
    @IBOutlet var navigationBarView: UIView!
    @IBOutlet var titleLabel: UILabel!
    @IBOutlet var tableView: UITableView!
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        tableView.rowHeight = UITableViewAutomaticDimension;
        tableView.estimatedRowHeight = 100;
        tableView.separatorStyle = UITableViewCellSeparatorStyle.none;

        self.navigationItem.title = "透明"

        navigationBarView.alpha = 0;
    }

    override func viewWillAppear(_ animated: Bool) {
        super .viewWillAppear(animated)

        self.navigationController?.setNavigationBarHidden(true, animated: true)
    }

    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        self.navigationController?.setNavigationBarHidden(false, animated: true)
    }



    // MARK: UIScrollView Delegate
    func scrollViewDidScroll(_ scrollView: UIScrollView) {



        let offset = scrollView.contentOffset.y;
        if (offset <= 0 && offset <= -90) {
            navigationBarView.backgroundColor = UIColor.red
            navigationBarView.alpha = 0;
        }else if(offset<=300){
            navigationBarView.backgroundColor = UIColor.red
            //alpha最大值为1
            navigationBarView.alpha = offset/255;

        } else {
            navigationBarView.backgroundColor = UIColor.green
        }
        return;

    }


    // MARK: UITableviewDataSource
    func numberOfSections(in tableView: UITableView) -> Int {
        return 1;
    }
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 20;
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "TestCell") as! TestCell
        cell.itemImageView.image = UIImage.init(named: "bear\(indexPath.row%9+1)")
        cell.contentLbl.text = "这个内容有点多:\n\(indexPath.row*999999999) \n凑行数\n你猜猜还有多少\n应该没有了\n好吧"
        return cell
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


}

二、滑动隐藏/显示

有一种很简单的方式,通过判断scrollView的滚动方向来隐藏/显示navigationBar,可以满足一般需求。

// MARK: UIScrollView Delegate
    func scrollViewDidScroll(_ scrollView: UIScrollView) {


        //滚动判断 tableView的方向,确定是否隐藏navigationBar
        if scrollView.contentOffset.y > currentOffset && scrollView.contentOffset.y > 60 {
            UIView.animate(withDuration: 2, animations: {

                self.navigationController?.setNavigationBarHidden(true, animated: true)

            }, completion: { (finish) in

            })
        } else {
            UIView.animate(withDuration: 2, animations: {
                self.navigationController?.setNavigationBarHidden(false, animated: true)
            }, completion: { (finish) in

            })
        }
    }

    //根据手指拖动方向判断是否隐藏,
    func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
        currentOffset = scrollView.contentOffset.y;//记录开始拖拽的位置,以作对比,判断方向
    }

13.gif

这种方式可以满足大多数需求,只是隐藏/显示只能保留一种状态,不能停留在一半的状态,虽然这种状态并不合理,但如果有这种变态需求,该做还是要做的。就像上面说的透明度一样,可以采用自定义的view方式来做处理,这样更灵活。

完整代码

猜你喜欢

转载自blog.csdn.net/fengzhixinfei/article/details/77480860