教你制作可移动的导航栏
2017-05-25 本文已影响82人
Dwyane_Coding

前言:
目前可移动的导航栏非常常见,以网易、京东、淘宝为首,都用到了此类导航栏,即可以左右滑动,选择更多。见下图紫色圈内

本文将会介绍这类导航栏的做法,方法很多,但关键思路是一样的,希望给大家带来帮助
一、最顶的滚动条
上面可移动的那个条,我们会想到带有滚动功能的控件,无非就是
UITableView
、UICollectionView
、UIScrollView
,在此,我们优先选择scrollView,至于那一个个栏目,我的思路是UIButton
即可。如果选择的是UICollectionView
,那一个个栏目便是UICollectionView
的item
1、创建常量
private let titleWidth : CGFloat = 80
private let titleHeight : CGFloat = 40
private let ScreenWidth = UIScreen.main.bounds.size.width
private let ScreenHeight = UIScreen.main.bounds.size.height
2、创建属性
private var selectButton:UIButton?//选择的栏目
private var sliderView:UIView?//指示器
private var topScroll:UIScrollView?
var titleArray = [String]()//暂存栏目title
var buttonArray = [UIButton]() //暂存所有栏目
3、创建滚动条
func createScrollableTopBar(){
//滑动ScrollView
let scroll = UIScrollView(frame: CGRect(x: 0, y: 0, width:self.ScreenWidth, height: self.titleHeight))
scroll.contentSize = CGSize(width: self.titleArray.count * NSInteger(titleWidth), height: 40)
scroll.bounces = false
scroll.showsHorizontalScrollIndicator = false
scroll.flashScrollIndicators()
scroll.backgroundColor = UIColor.gray
self.view.addSubview(scroll)
self.topScroll = scroll
//栏目按钮
for(index,value) in self.titleArray.enumerated(){
let titleButton = UIButton(frame: CGRect(x: self.titleWidth * CGFloat(index), y: 0, width: self.titleWidth, height: self.titleHeight))
titleButton.setTitle(value, for: .normal)
titleButton.setTitleColor(UIColor.black, for: .normal)
titleButton.backgroundColor = UIColor.white
titleButton.tag = 100 + index
titleButton.titleLabel?.font = UIFont.systemFont(ofSize: 14)
scroll.addSubview(titleButton)
self.buttonArray.append(titleButton)
}
}
效果如下:

4、添加选中时的颜色和滑块指示器
在for(index,value) in self.titleArray.enumerated(){}
循环中,添加
if(index == 0){
self.selectButton = titleButton
self.selectButton?.setTitleColor(UIColor.orange, for: .normal)
}
在createScrollableTopBar
最底下,添加
//滑块 indicator
let sliderView = UIView(frame: CGRect(x: 15, y: self.titleHeight - 2, width: self.titleWidth - 20, height: 2))
sliderView.backgroundColor = UIColor.orange
scroll.addSubview(sliderView)
self.sliderView = sliderView;
效果如下:

5、选中栏目时所触发的方法
在createScrollableTopBar
为titleButton
添加点击方法
titleButton.addTarget(self, action: #selector(scrollViewSelectToIndex), for:.touchUpInside)
完成点击方法里面的内容:
1、为每个栏目设置
tag
值
2、为每个选中的栏目设置背景颜色为orange
3、为了人性化,选中的栏目尽可能移到界面中间。
这也是本文重点:根据选中的栏目(按钮),分别为topScroll设置不同的ContentOffset,主要有三种情况:一、选中的栏目是前几个 二、选中的栏目时后几个 三、选中其他栏目
前两种情况没办法偏移到界面中间
/**选择某个项目*/
func selectButton(index:NSInteger){
//把当前的按钮重置为原来颜色
self.selectButton?.setTitleColor(UIColor.black, for: .normal)
//取出选中的按钮
selectButton = self.buttonArray[index]
self.selectButton?.setTitleColor(UIColor.orange, for: .normal)
// 将rect由rect所在视图转换到目标视图view中,返回在目标视图view中的rect 相对于当前显示窗口
let rect = selectButton!.superview!.convert(selectButton!.frame, to: self.view)
UIView .animate(withDuration: 0) {
let contentOffset = self.topScroll!.contentOffset;
//选中栏目的最前几个:scrollView偏移值 + 那个按钮的X值 <= 当前显示窗口中间X值
if contentOffset.x <= (self.ScreenWidth/2 - rect.origin.x - self.titleWidth/2) {
print("1")
self.topScroll!.setContentOffset(CGPoint(x:0,y:contentOffset.y), animated: true)
//(self.ScreenWidth/2 - rect.origin.x - self.titleWidth/2) 判断选中的按钮是在左边还是右边
} else if (rect.origin.x - self.ScreenWidth/2 + self.titleWidth/2) >= CGFloat(self.titleArray.count) * self.titleWidth - self.ScreenWidth - contentOffset.x { //选中栏目的最后几个: 那个按钮的X值 -当前显示窗口中间X值 + 栏目的一半,即scrollView偏移值 >= 总栏目的长 - self.ScreenWidth - 偏移量contentOffset.x
self.topScroll!.setContentOffset(CGPoint(x:CGFloat(self.titleArray.count) * self.titleWidth - self.ScreenWidth,y:contentOffset.y), animated: true)
print("2")
} else {
print("3")//
self.topScroll!.setContentOffset(CGPoint(x:contentOffset.x - (self.ScreenWidth/2 - rect.origin.x - self.titleWidth/2),y:contentOffset.y), animated: true)
}
}
}
现在,点击任意一个栏目,栏目(按钮)的背景色都会变成橙色,而上一个选中的栏目会变成原来的灰色
效果如下:

6、选中