视图导航器与导航模式
1.导航模式
- 平铺导航模式:内容没有层次关系,展示的内容都放置在一个主屏幕上,采用分屏或者分页控制器进行导航,可以左右或者上下滑动屏幕查看内容。
- 标签导航模式:内容被分成几个功能模块,每个功能模块之间没有什么关系。通过标签管理各个功能模块,点击标签可以切换功能模块。
- 树形结构导航模式:内容是有层次的,从上到下细分或者具有分类包含等关系。
2.模态视图
在导航过程中,有时候需要放弃主要任务转而做其他次要任务,然后再返回到主要任务,这个次要任务就是在模态视图中完成的。默认情况下,模态视图是从屏幕下方滑出来的。完成的时候需要关闭这个模块视图,如果不关闭,就不能做别的事情,这就是“模态”的含义。它具有响应处理的意思。
负责控制模态视图的控制器称为模态视图控制器。模态视图控制器并非一个专门的类,它可以是上面提到的控制器的子类。负责主要任务视图的控制器称为主视图控制器,它与模态视图控制器之间是父子关系。由于UIViewController类提供了如下两个方法,所以任何视图控制器中都可以呈现和关闭模态视图。
- presentViewController:animated:completion。呈现模态视图。
- dismissViewControllerAnimated:completion。关闭模态视图。
在呈现模态视图时,有两个选择: - 代码实现:UIViewController的presentViewController:animated:completion方法实现。
- Interface Builder实现:在storyboard的过渡(segue)中实现,不需要编写代码。
3.平铺导航
3.1 基于分屏导航的实现
基于分屏导航是平铺导航模式的主要实现方式,涉及的控件有分屏控件(UIPageControl)和屏幕滚动视图(UIscrollView)
基于分屏导航的手势有两种:1、点击高亮小点的左边(右边)或者上边(下边)实现翻屏;2、是用手在屏幕上滑动实现翻屏。**屏幕的总数应该限制在20个以内,超过20个小点的分屏控件就会溢出。**事实上,当一个应用超过10屏时,使用基于分屏导航模式就不是很方便了。
示例:
import UIKit
//定义屏幕的高度和宽度
let S_Width:CGFloat = UIScreen.main.bounds.size.width
let S_Height:CGFloat = UIScreen.main.bounds.size.height
class ViewController: UIViewController,UIScrollViewDelegate {
var imageView_01:UIImageView!
var imageView_02:UIImageView!
var imageView_03:UIImageView!
var scrollView:UIScrollView!
var pageControl:UIPageControl!
override func viewDidLoad() {
super.viewDidLoad()
self.scrollView = UIScrollView()
self.view.addSubview(self.scrollView)
//设置委托对象
self.scrollView.delegate = self
//设置滚动视图中内容视图的大小
self.scrollView.contentSize = CGSize(width: S_Width * 3, height: S_Height) //预计要放多少(n)屏,相应的宽度就是S_Width * n
self.scrollView.frame = self.view.frame //设置frame属性为当前视图大小
self.scrollView.isPagingEnabled = true //设置屏幕滚动视图每次滑动时翻一屏
self.scrollView.showsVerticalScrollIndicator = false
self.scrollView.showsHorizontalScrollIndicator = false
//添加视图的素材图片
self.imageView_01 = UIImageView(frame: CGRect(x: 0, y: 0, width: S_Width, height: S_Height))
self.imageView_01.image = UIImage(named: "girl_01")
self.scrollView.addSubview(self.imageView_01)
self.imageView_02 = UIImageView(frame: CGRect(x: S_Width, y: 0, width: S_Width, height: S_Height))
self.imageView_02.image = UIImage(named: "girl_02")
self.scrollView.addSubview(self.imageView_02)
self.imageView_03 = UIImageView(frame: CGRect(x: S_Width * 2, y: 0, width: S_Width, height: S_Height))
self.imageView_03.image = UIImage(named: "girl_03")
self.scrollView.addSubview(self.imageView_03)
let pageConrolWidth:CGFloat = 300.0
let pageControlHeight:CGFloat = 37.0
self.pageControl = UIPageControl(frame: CGRect(x: (S_Width - pageConrolWidth)/2, y: S_Height - pageControlHeight, width: pageConrolWidth, height: pageControlHeight))
self.pageControl.numberOfPages = 3
self.pageControl.addTarget(self, action: #selector(changePage(_:)), for: .valueChanged)
self.view.addSubview(self.pageControl)
}
//显示当前页面为第几屏
func scrollViewDidScroll(_ scrollView: UIScrollView) {
//ScrollViewdelegate委托协议的实现方法(当屏幕滚动时,会回调该方法)
let offset = scrollView.contentOffset //内容视图的原点到滚动视图偏移的点
self.pageControl.currentPage = Int(offset.x / S_Width)
//用偏移距离除以屏幕宽度,得出当前页面是第几屏,并通过高亮点显示到界面上
}
//切换当前页面
@objc func changePage(_ sender:AnyObject){
UIView.animate(withDuration: 0.3,animations: {
let whichPage = self.pageControl.currentPage
self.scrollView.contentOffset = CGPoint(x: Int(S_Width) * whichPage, y: 0)
})
}
}
效果如下图所示:
3.2 基于电子书导航的实现
在基于电子书导航实现的应用中,需要的类和协议有UIPageViewControllerDataSourse协议、UIPageViewControllerDelegate协议和UIPageViewController类。其中UIPageViewController类没有对应的视图类。
UIPageViewControllerDataSourse数据源协议中必须实现的方法有以下两个:
- pageViewController:viewControllerBeforeViewController:。返回当前视图控制器之前的视图控制器,用于上一个页面的显示。
- pageViewController:viewControllerAfterViewController:。返回当前视图控制器之后的视图控制器,用于下一个页面的显示。
在UIPageViewControllerDelegate委托协议中,最重要的方法为pageViewController:spineLocationForInterfaceOrientation:,它根据屏幕旋转方向设置书脊位置(spineLocation)和初始化首页。
UIPageViewController*有两个常用的属性**:双面显示(double Sided)和书脊位置(spine Location)** - 双面显示:doubleSided设置为true,则翻起偶数页面会在背面显示。为false时为单面显示,即用户在页面翻起时,看到页面的背面是当前页面透过去的,与当前内容是相反的镜像。
- 书脊位置:也是很重要的属性,但是它是只读的。书脊位置由枚举UIPageViewControllerSpineLocation定义,该枚举类型下的成员变量如下所示:
min:定义了书脊位置在书的最左边(或最上面)
max:定义了书脊位置在书的最右边(或最下面)
mid:定义了书脊位置在书的中间。