分页菜单(分段菜单)在许多 App 上都会用到。比如大多数新闻 App,如网易新闻、今日头条等,顶部都有个导航菜单。这个导航菜单是一组标签的集合,每个标签表示一个新闻类别,我们点击这个标签后下面就会切换到相应的分页面。同时左右滑动分页面,上方的标签也会跟着移动。
本文介绍一个优秀的第三方分页视图控件:PagingMenuController,不仅可以自定义菜单,而且可以自由地修改样式。
一、安装配置
(1)从 GitHub 上下载最新的代码:https://github.com/kitasuke/PagingMenuController
(2)将下载下来的源码包中 PagingMenuController.xcodeproj 拖拽至你的工程中。
(3)工程 -> General -> Embedded Binaries 项,把 PagingMenuController.framework 添加进来。
(4)最后,在需要使用 PagingMenuController 的地方 import 进来就可以了。
1
|
import PagingMenuController
|
二、纯代码使用样例
1,效果图
(1)主视图顶部分页菜单中有两个菜单标签,分别对应两个子视图。
(2)点击菜单标签,下方便会切换显示相应的子视图。
(3)也可以直接左右滑动子视图进行切换,上方的菜单标签状态也会同步更新。
2,样例代码
(1)子视图控制器1(ViewController1.swift)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
import UIKit
//子视图控制器1 class ViewController1 : UIViewController {
override func viewDidLoad() {
super .viewDidLoad()
view.backgroundColor = UIColor .orange
let textLabel = UILabel (frame: CGRect (x: 0, y: 100, width: self .view.frame.width,
height: 30))
textLabel.textAlignment = .center
textLabel.font = UIFont .systemFont(ofSize: 33)
textLabel.textColor = .white
textLabel.text = "电影"
view.addSubview(textLabel)
}
} |
(2)子视图控制器2(ViewController2.swift)
(3)主视图控制器(ViewController.swift)
源码下载:hangge_1656.zip
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
import UIKit
//子视图控制器2 class ViewController2 : UIViewController {
override func viewDidLoad() {
super .viewDidLoad()
view.backgroundColor = UIColor .darkGray
let textLabel = UILabel (frame: CGRect (x: 0, y: 100, width: self .view.frame.width,
height: 30))
textLabel.textAlignment = .center
textLabel.font = UIFont .systemFont(ofSize: 33)
textLabel.textColor = .white
textLabel.text = "音乐"
view.addSubview(textLabel)
}
} |
(3)主视图控制器(ViewController.swift)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
|
import UIKit
import PagingMenuController
//分页菜单配置 private struct PagingMenuOptions : PagingMenuControllerCustomizable {
//第1个子视图控制器
private let viewController1 = ViewController1 ()
//第2个子视图控制器
private let viewController2 = ViewController2 ()
//组件类型
fileprivate var componentType: ComponentType {
return .all(menuOptions: MenuOptions (), pagingControllers: pagingControllers)
}
//所有子视图控制器
fileprivate var pagingControllers: [ UIViewController ] {
return [viewController1, viewController2]
}
//菜单配置项
fileprivate struct MenuOptions : MenuViewCustomizable {
//菜单显示模式
var displayMode: MenuDisplayMode {
return .segmentedControl
}
//菜单项
var itemsOptions: [ MenuItemViewCustomizable ] {
return [ MenuItem1 (), MenuItem2 ()]
}
}
//第1个菜单项
fileprivate struct MenuItem1 : MenuItemViewCustomizable {
//自定义菜单项名称
var displayMode: MenuItemDisplayMode {
return .text(title: MenuItemText (text: "电影" ))
}
}
//第2个菜单项
fileprivate struct MenuItem2 : MenuItemViewCustomizable {
//自定义菜单项名称
var displayMode: MenuItemDisplayMode {
return .text(title: MenuItemText (text: "音乐" ))
}
}
} //主视图控制器 class ViewController : UIViewController {
override func viewDidLoad() {
super .viewDidLoad()
//分页菜单配置
let options = PagingMenuOptions ()
//分页菜单控制器初始化
let pagingMenuController = PagingMenuController (options: options)
//分页菜单控制器尺寸设置
pagingMenuController.view.frame.origin.y += 64
pagingMenuController.view.frame.size.height -= 64
//建立父子关系
addChildViewController(pagingMenuController)
//分页菜单控制器视图添加到当前视图中
view.addSubview(pagingMenuController.view)
}
override func didReceiveMemoryWarning() {
super .didReceiveMemoryWarning()
}
} |
三、Storyboard 使用样例
1,效果图
具体功能同上面的是一样的。
2,Storyboard 相关操作
(1)在主视图中添加一个 Container View,并设置好相关约束。(2)Container View 默认embed的是 UIViewController,我们将其改成 PagingMenuController。
3,样例代码
(1)子视图控制器(ViewController1.swift、ViewController2.swift)
1
|
//具体参考上面的纯代码实现部分 |
(2)主视图控制器(ViewController.swift)
高亮处表示与上面纯代码实现不相同的地方。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
|
import UIKit
import PagingMenuController
//分页菜单配置 private struct PagingMenuOptions : PagingMenuControllerCustomizable {
//第1个子视图控制器
private let viewController1 = ViewController1 ()
//第2个子视图控制器
private let viewController2 = ViewController2 ()
//组件类型
fileprivate var componentType: ComponentType {
return .all(menuOptions: MenuOptions (), pagingControllers: pagingControllers)
}
//所有子视图控制器
fileprivate var pagingControllers: [ UIViewController ] {
return [viewController1, viewController2]
}
//菜单配置项
fileprivate struct MenuOptions : MenuViewCustomizable {
//菜单显示模式
var displayMode: MenuDisplayMode {
return .segmentedControl
}
//菜单项
var itemsOptions: [ MenuItemViewCustomizable ] {
return [ MenuItem1 (), MenuItem2 ()]
}
}
//第1个菜单项
fileprivate struct MenuItem1 : MenuItemViewCustomizable {
//自定义菜单项名称
var displayMode: MenuItemDisplayMode {
return .text(title: MenuItemText (text: "电影" ))
}
}
//第2个菜单项
fileprivate struct MenuItem2 : MenuItemViewCustomizable {
//自定义菜单项名称
var displayMode: MenuItemDisplayMode {
return .text(title: MenuItemText (text: "音乐" ))
}
}
} //主视图控制器 class ViewController : UIViewController {
override func viewDidLoad() {
super .viewDidLoad()
//获取分页菜单配置
let options = PagingMenuOptions ()
//设置分页菜单配置
let pagingMenuController = self .childViewControllers.first as ! PagingMenuController
pagingMenuController.setup(options)
}
override func didReceiveMemoryWarning() {
super .didReceiveMemoryWarning()
}
} |
四、标签、页面切换响应
有时我们需要监听页面切换事件进行一些操作,比如当切换到新的页面时可以去请求数据等。这个通过 PagingMenuController 的 onMove 回调就可以实现。每当菜单移动前后、页面切换前后、手指滑动页面前后,该方法都会被调用。
1,样例代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
//分页菜单控制器初始化 let pagingMenuController = PagingMenuController (options: options)
//....省略一些代码 view.addSubview(pagingMenuController.view) //页面切换响应 pagingMenuController.onMove = { state in
switch state {
case let .willMoveItem(menuItemView, previousMenuItemView):
print ( "--- 标签将要切换 ---" )
print ( "老标签:\(previousMenuItemView.titleLabel.text!)" )
print ( "新标签:\(menuItemView.titleLabel.text!)" )
case let .didMoveItem(menuItemView, previousMenuItemView):
print ( "--- 标签切换完毕 ---" )
print ( "老标签:\(previousMenuItemView.titleLabel.text!)" )
print ( "新标签:\(menuItemView.titleLabel.text!)" )
case let .willMoveController(menuController, previousMenuController):
print ( "--- 页面将要切换 ---" )
print ( "老页面:\(previousMenuController)" )
print ( "新页面:\(menuController)" )
case let .didMoveController(menuController, previousMenuController):
print ( "--- 页面切换完毕 ---" )
print ( "老页面:\(previousMenuController)" )
print ( "新页面:\(menuController)" )
case .didScrollStart:
print ( "--- 分页开始左右滑动 ---" )
case .didScrollEnd:
print ( "--- 分页停止左右滑动 ---" )
}
} |
2,运行效果
(1)我们点击顶部菜单标签进行页面切换,可以看到控制台打印出如下信息:(2)而如果通过手指滑动切换页面,控制台打印出如下信息:
五、使用代码切换标签
比如下面代码自动将分页菜单控制器切换到第 2 个页面。
1
|
pagingMenuController.move(toPage: 1, animated: true )
|
六、自定义分页控制器样式
PagingMenuControllerCustomizable 对象有如下几个属性可以对整个视图控制器进行自定义:
1,defaultPage: Int
设置默认页面的索引,如果不指定则默认显示第一个视图页。
2,animationDuration: TimeInterval
页面切换动画时间。
3,isScrollEnabled: Bool
是否允许手指左右滑动进行页面切换,设置为 false 则只能点击菜单标签切换页面。
4,backgroundColor: UIColor
设置页面背景色。
5,lazyLoadingPage: LazyLoadingPage
lazy loading 的页面数量,这个是一个枚举,可选值如下:
1
2
3
4
5
|
public enum LazyLoadingPage {
case one // Currently sets false to isScrollEnabled at this moment. Should be fixed in the future.
case three
case all // Currently not available for Infinite mode
} |
6,menuControllerSet: MenuControllerSet
这个不太清楚做什么用的,也是一个枚举可选值如下:
1
2
3
4
|
public enum MenuControllerSet {
case single
case multiple
} |
7,componentType: ComponentType
这个很重要,用来配置整个分页菜单控制器包含的页面和菜单标签。这也是一个枚举,可选值如下:
1
2
3
4
5
|
public enum ComponentType {
case menuView(menuOptions: MenuViewCustomizable )
case pagingController(pagingControllers: [ UIViewController ])
case all(menuOptions: MenuViewCustomizable , pagingControllers: [ UIViewController ])
} |
8,下面是一个完整的配置样例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
|
//分页菜单配置 private struct PagingMenuOptions : PagingMenuControllerCustomizable {
//默认显示第2页
var defaultPage: Int = 1
//页面切换动画播放时间为0.5秒
var animationDuration: TimeInterval = 0.5
//不允许手指左右滑动页面切换
var isScrollEnabled: Bool = false
//页面背景色为紫色
var backgroundColor: UIColor = .purple
//lazy loading的页面数量(默认值就是.three)
var lazyLoadingPage: LazyLoadingPage = .three
//不太清楚干嘛用的(默认值就是.multiple)
var menuControllerSet: MenuControllerSet = .multiple
//第1个子视图控制器
private let viewController1 = ViewController1 ()
//第2个子视图控制器
private let viewController2 = ViewController2 ()
//组件类型
fileprivate var componentType: ComponentType {
return .all(menuOptions: MenuOptions (), pagingControllers: pagingControllers)
}
//所有子视图控制器
fileprivate var pagingControllers: [ UIViewController ] {
return [viewController1, viewController2]
}
//菜单配置项
fileprivate struct MenuOptions : MenuViewCustomizable {
//菜单显示模式
var displayMode: MenuDisplayMode {
return .segmentedControl
}
//菜单项
var itemsOptions: [ MenuItemViewCustomizable ] {
return [ MenuItem1 (), MenuItem2 ()]
}
}
//第1个菜单项
fileprivate struct MenuItem1 : MenuItemViewCustomizable {
//自定义菜单项名称
var displayMode: MenuItemDisplayMode {
return .text(title: MenuItemText (text: "电影" ))
}
}
//第2个菜单项
fileprivate struct MenuItem2 : MenuItemViewCustomizable {
//自定义菜单项名称
var displayMode: MenuItemDisplayMode {
return .text(title: MenuItemText (text: "音乐" ))
}
}
} |
七、自定义菜单栏样式
MenuViewCustomizable 对象有如下几个属性对菜单栏进行自定义:
1,backgroundColor: UIColor
设置未选中的菜单标签背景色。
2,selectedBackgroundColor: UIColor
设置选中的菜单标签背景色。
3,height: CGFloat
设置菜单标签的高度。
4,animationDuration: TimeInterval
设置菜单标签切换时动画持续时长。
5,deceleratingRate: CGFloat
设置菜单切换动画减速率(默认为:UIScrollViewDecelerationRateFast)
6,menuSelectedItemCenter: Bool
不太清楚干嘛的。
7,displayMode: MenuDisplayMode
菜单显示模式,它是一个枚举有三个可选值:
专题导读
上一篇:
[Swift]LeetCode1196.最多可以买到的苹果数量|HowManyApplesCanYouPutintotheBasket ...发布时间:2022-07-13下一篇:
[Swift]LeetCode28.实现strStr()|ImplementstrStr()发布时间:2022-07-13热门推荐
热门话题
阅读排行榜
请发表评论