一、透明度变化,类京东首页
一般透明度变化都会牵扯到滚动视图(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;//记录开始拖拽的位置,以作对比,判断方向
}
这种方式可以满足大多数需求,只是隐藏/显示只能保留一种状态,不能停留在一半的状态,虽然这种状态并不合理,但如果有这种变态需求,该做还是要做的。就像上面说的透明度一样,可以采用自定义的view方式来做处理,这样更灵活。