├── ScreenShot
├── TYPagerController1.gif
├── TYPagerController2.gif
├── TYPagerController3.gif
├── TYPagerController4.gif
├── TYPagerController5.gif
├── TYPagerController6.gif
└── TYPagerController7.gif
├── TYPagerControllerDemo.xcodeproj
├── xcuserdata
│ ├── tany.xcuserdatad
│ │ ├── xcdebugger
│ │ │ └── Breakpoints_v2.xcbkptlist
│ │ └── xcschemes
│ │ │ ├── xcschememanagement.plist
│ │ │ └── TYPagerControllerDemo.xcscheme
│ └── tanyang.xcuserdatad
│ │ ├── xcdebugger
│ │ └── Breakpoints_v2.xcbkptlist
│ │ └── xcschemes
│ │ ├── xcschememanagement.plist
│ │ └── TYPagerControllerDemo.xcscheme
└── project.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcuserdata
│ └── tany.xcuserdatad
│ └── UserInterfaceState.xcuserstate
├── TYPagerControllerDemo_swift.xcodeproj
├── xcuserdata
│ ├── tany.xcuserdatad
│ │ ├── xcdebugger
│ │ │ └── Breakpoints_v2.xcbkptlist
│ │ └── xcschemes
│ │ │ ├── xcschememanagement.plist
│ │ │ └── TYPagerControllerDemo_swift.xcscheme
│ └── tanyang.xcuserdatad
│ │ ├── xcdebugger
│ │ └── Breakpoints_v2.xcbkptlist
│ │ └── xcschemes
│ │ ├── xcschememanagement.plist
│ │ └── TYPagerControllerDemo_swift.xcscheme
└── project.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcuserdata
│ └── tany.xcuserdatad
│ └── UserInterfaceState.xcuserstate
├── TYPagerControllerDemo
├── ViewController.h
├── PagerViewDmeoController.h
├── TabPagerViewDmeoController.h
├── PagerControllerDmeoController.h
├── TabPagerControllerDemoController.h
├── ListViewController.h
├── CustomViewController.h
├── AppDelegate.h
├── CollectionViewController.h
├── main.m
├── TYPagerController
│ ├── TabPager
│ │ ├── TYTabPagerBarCell.h
│ │ ├── TYTabPagerBarCell.m
│ │ ├── TYTabPagerView.h
│ │ ├── TYTabPagerController.h
│ │ ├── TYTabPagerBar.h
│ │ ├── TYTabPagerBarLayout.h
│ │ ├── TYTabPagerView.m
│ │ ├── TYTabPagerController.m
│ │ ├── TYTabPagerBar.m
│ │ └── TYTabPagerBarLayout.m
│ ├── TYPagerView.h
│ ├── TYPagerController.h
│ ├── TYPagerViewLayout.h
│ ├── TYPagerView.m
│ └── TYPagerController.m
├── Assets.xcassets
│ └── AppIcon.appiconset
│ │ └── Contents.json
├── Info.plist
├── ViewController.m
├── Base.lproj
│ ├── LaunchScreen.storyboard
│ └── Main.storyboard
├── AppDelegate.m
├── TabPagerViewDmeoController.m
├── TabPagerControllerDemoController.m
├── CollectionViewController.m
├── ListViewController.m
├── CustomViewController.m
├── PagerControllerDmeoController.m
└── PagerViewDmeoController.m
├── TYPagerControllerDemo_swift
├── TYPagerControllerDemo_swift-Brdging-Header.h
├── ViewController.swift
├── Assets.xcassets
│ └── AppIcon.appiconset
│ │ └── Contents.json
├── Info.plist
├── Base.lproj
│ ├── LaunchScreen.storyboard
│ └── Main.storyboard
├── TabPagerControllerDemoController.swift
├── AppDelegate.swift
├── TabPagerViewDemoController.swift
└── PagerControlerDemoController.swift
├── TYPagerController.podspec
├── LICENSE
└── README.md
/ScreenShot/TYPagerController1.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/12207480/TYPagerController/HEAD/ScreenShot/TYPagerController1.gif
--------------------------------------------------------------------------------
/ScreenShot/TYPagerController2.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/12207480/TYPagerController/HEAD/ScreenShot/TYPagerController2.gif
--------------------------------------------------------------------------------
/ScreenShot/TYPagerController3.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/12207480/TYPagerController/HEAD/ScreenShot/TYPagerController3.gif
--------------------------------------------------------------------------------
/ScreenShot/TYPagerController4.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/12207480/TYPagerController/HEAD/ScreenShot/TYPagerController4.gif
--------------------------------------------------------------------------------
/ScreenShot/TYPagerController5.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/12207480/TYPagerController/HEAD/ScreenShot/TYPagerController5.gif
--------------------------------------------------------------------------------
/ScreenShot/TYPagerController6.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/12207480/TYPagerController/HEAD/ScreenShot/TYPagerController6.gif
--------------------------------------------------------------------------------
/ScreenShot/TYPagerController7.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/12207480/TYPagerController/HEAD/ScreenShot/TYPagerController7.gif
--------------------------------------------------------------------------------
/TYPagerControllerDemo.xcodeproj/xcuserdata/tany.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
--------------------------------------------------------------------------------
/TYPagerControllerDemo.xcodeproj/xcuserdata/tanyang.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
--------------------------------------------------------------------------------
/TYPagerControllerDemo_swift.xcodeproj/xcuserdata/tany.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
--------------------------------------------------------------------------------
/TYPagerControllerDemo_swift.xcodeproj/xcuserdata/tanyang.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
--------------------------------------------------------------------------------
/TYPagerControllerDemo_swift.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/TYPagerControllerDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/TYPagerControllerDemo.xcodeproj/project.xcworkspace/xcuserdata/tany.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/12207480/TYPagerController/HEAD/TYPagerControllerDemo.xcodeproj/project.xcworkspace/xcuserdata/tany.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/TYPagerControllerDemo_swift.xcodeproj/project.xcworkspace/xcuserdata/tany.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/12207480/TYPagerController/HEAD/TYPagerControllerDemo_swift.xcodeproj/project.xcworkspace/xcuserdata/tany.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/TYPagerControllerDemo/ViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.h
3 | // TYPagerControllerDemo
4 | //
5 | // Created by tany on 2017/7/6.
6 | // Copyright © 2017年 tany. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface ViewController : UIViewController
12 |
13 |
14 | @end
15 |
16 |
--------------------------------------------------------------------------------
/TYPagerControllerDemo/PagerViewDmeoController.h:
--------------------------------------------------------------------------------
1 | //
2 | // PagerViewDmeoController.h
3 | // TYPagerControllerDemo
4 | //
5 | // Created by tanyang on 2017/7/6.
6 | // Copyright © 2017年 tany. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface PagerViewDmeoController : UIViewController
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/TYPagerControllerDemo/TabPagerViewDmeoController.h:
--------------------------------------------------------------------------------
1 | //
2 | // TabPagerViewDmeoController.h
3 | // TYPagerControllerDemo
4 | //
5 | // Created by tany on 2017/7/19.
6 | // Copyright © 2017年 tany. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface TabPagerViewDmeoController : UIViewController
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/TYPagerControllerDemo/PagerControllerDmeoController.h:
--------------------------------------------------------------------------------
1 | //
2 | // PagerControllerDmeoController.h
3 | // TYPagerControllerDemo
4 | //
5 | // Created by tany on 2017/7/19.
6 | // Copyright © 2017年 tany. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface PagerControllerDmeoController : UIViewController
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/TYPagerControllerDemo/TabPagerControllerDemoController.h:
--------------------------------------------------------------------------------
1 | //
2 | // PagerControllerDemoController.h
3 | // TYPagerControllerDemo
4 | //
5 | // Created by tanyang on 2017/7/18.
6 | // Copyright © 2017年 tany. All rights reserved.
7 | //
8 |
9 | #import "TYTabPagerController.h"
10 |
11 | @interface TabPagerControllerDemoController : TYTabPagerController
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/TYPagerControllerDemo/ListViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // ListViewController.h
3 | // TYPagerControllerDemo
4 | //
5 | // Created by tany on 16/5/17.
6 | // Copyright © 2016年 tanyang. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface ListViewController : UIViewController
12 |
13 | @property (nonatomic, strong) NSString *text;
14 |
15 | @end
16 |
--------------------------------------------------------------------------------
/TYPagerControllerDemo/CustomViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // CustomViewController.h
3 | // TYPagerControllerDemo
4 | //
5 | // Created by tany on 16/4/20.
6 | // Copyright © 2016年 tanyang. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface CustomViewController : UIViewController
12 |
13 | @property (nonatomic, strong) NSString *text;
14 |
15 | @end
16 |
--------------------------------------------------------------------------------
/TYPagerControllerDemo/AppDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.h
3 | // TYPagerControllerDemo
4 | //
5 | // Created by tany on 2017/7/6.
6 | // Copyright © 2017年 tany. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface AppDelegate : UIResponder
12 |
13 | @property (strong, nonatomic) UIWindow *window;
14 |
15 |
16 | @end
17 |
18 |
--------------------------------------------------------------------------------
/TYPagerControllerDemo/CollectionViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // CollectionViewController.h
3 | // TYPagerControllerDemo
4 | //
5 | // Created by tany on 16/5/17.
6 | // Copyright © 2016年 tanyang. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface CollectionViewController : UIViewController
12 |
13 | @property (nonatomic, strong) NSString *text;
14 |
15 | @end
16 |
--------------------------------------------------------------------------------
/TYPagerControllerDemo/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // main.m
3 | // TYPagerControllerDemo
4 | //
5 | // Created by tany on 2017/7/6.
6 | // Copyright © 2017年 tany. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "AppDelegate.h"
11 |
12 | int main(int argc, char * argv[]) {
13 | @autoreleasepool {
14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/TYPagerControllerDemo_swift/TYPagerControllerDemo_swift-Brdging-Header.h:
--------------------------------------------------------------------------------
1 | //
2 | // TYPagerControllerDemo_swift-Brdging-Header.h
3 | // TYPagerControllerDemo_swift
4 | //
5 | // Created by tany on 2017/7/19.
6 | // Copyright © 2017年 tany. All rights reserved.
7 | //
8 |
9 | #ifndef TYPagerControllerDemo_swift_Brdging_Header_h
10 | #define TYPagerControllerDemo_swift_Brdging_Header_h
11 |
12 | #import "TYTabPagerView.h"
13 | #import "TYTabPagerController.h"
14 |
15 | #endif /* TYPagerControllerDemo_swift_Brdging_Header_h */
16 |
--------------------------------------------------------------------------------
/TYPagerControllerDemo_swift.xcodeproj/xcuserdata/tany.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | TYPagerControllerDemo_swift.xcscheme
8 |
9 | orderHint
10 | 1
11 |
12 |
13 | SuppressBuildableAutocreation
14 |
15 | 2BE687901F1F3D67001FE46D
16 |
17 | primary
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/TYPagerControllerDemo_swift.xcodeproj/xcuserdata/tanyang.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | TYPagerControllerDemo_swift.xcscheme
8 |
9 | orderHint
10 | 0
11 |
12 |
13 | SuppressBuildableAutocreation
14 |
15 | 2BE687901F1F3D67001FE46D
16 |
17 | primary
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/TYPagerControllerDemo/TYPagerController/TabPager/TYTabPagerBarCell.h:
--------------------------------------------------------------------------------
1 | //
2 | // TYTabTitleViewCell.h
3 | // TYPagerControllerDemo
4 | //
5 | // Created by tany on 16/5/4.
6 | // Copyright © 2016年 tanyang. All rights reserved.
7 | //
8 |
9 | #import
10 | NS_ASSUME_NONNULL_BEGIN
11 | @protocol TYTabPagerBarCellProtocol
12 |
13 | /**
14 | font ,textColor will use TYTabPagerBarLayout's textFont,textColor
15 | */
16 | @property (nonatomic, strong, readonly) UILabel *titleLabel;
17 |
18 | @end
19 |
20 | @interface TYTabPagerBarCell : UICollectionViewCell
21 | @property (nonatomic, weak,readonly) UILabel *titleLabel;
22 |
23 | + (NSString *)cellIdentifier;
24 | @end
25 | NS_ASSUME_NONNULL_END
26 |
--------------------------------------------------------------------------------
/TYPagerControllerDemo.xcodeproj/xcuserdata/tany.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | TYPagerControllerDemo.xcscheme
8 |
9 | orderHint
10 | 0
11 |
12 |
13 | SuppressBuildableAutocreation
14 |
15 | 2B9C0F471F0E11E7009BC0BD
16 |
17 | primary
18 |
19 |
20 | 2B9C0F601F0E11E7009BC0BD
21 |
22 | primary
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/TYPagerControllerDemo.xcodeproj/xcuserdata/tanyang.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | TYPagerControllerDemo.xcscheme
8 |
9 | orderHint
10 | 0
11 |
12 |
13 | SuppressBuildableAutocreation
14 |
15 | 2B9C0F471F0E11E7009BC0BD
16 |
17 | primary
18 |
19 |
20 | 2B9C0F601F0E11E7009BC0BD
21 |
22 | primary
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/TYPagerController.podspec:
--------------------------------------------------------------------------------
1 | Pod::Spec.new do |s|
2 | # 名称 使用的时候pod search [name]
3 | s.name = "TYPagerController"
4 | # 代码库的版本
5 | s.version = "2.1.2"
6 | # 简介
7 | s.summary = "page scroll View controller,simple,high custom,and have tabBar styles."
8 | # 主页
9 | s.homepage = "https://github.com/12207480/TYPagerController"
10 | # 许可证书类型,要和仓库的LICENSE 的类型一致
11 | s.license = { :type => 'MIT', :file => 'LICENSE' }
12 | # 作者名称 和 邮箱
13 | s.author = { "tany" => "122074809@qq.com" }
14 | # 作者主页 s.social_media_url =""
15 | # 代码库最低支持的版本
16 | s.platform = :ios, "7.0"
17 | # 代码的Clone 地址 和 tag 版本
18 | s.source = { :git => "https://github.com/12207480/TYPagerController.git", :tag => s.version.to_s }
19 | # 如果使用pod 需要导入哪些资源
20 | s.source_files = "TYPagerControllerDemo/TYPagerController/**/*.{h,m}"
21 | # s.resources = "**/*/*.bundle"
22 | # 框架是否使用的ARC
23 | s.requires_arc = true
24 | end
25 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 tany
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/TYPagerControllerDemo_swift/ViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.swift
3 | // TYPagerControllerDemo_swift
4 | //
5 | // Created by tany on 2017/7/19.
6 | // Copyright © 2017年 tany. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class ViewController: UIViewController {
12 |
13 | override func viewDidLoad() {
14 | super.viewDidLoad()
15 | // Do any additional setup after loading the view, typically from a nib.
16 |
17 | }
18 |
19 | @IBAction func turnToPagerController(_ sender: Any) {
20 | let vc = PagerControlerDemoController()
21 | self.navigationController?.pushViewController(vc, animated: true)
22 | }
23 |
24 | @IBAction func turnToTabPagerView(_ sender: Any) {
25 | let vc = TabPagerViewDemoController()
26 | self.navigationController?.pushViewController(vc, animated: true)
27 | }
28 |
29 |
30 | @IBAction func turnToTabPagerController(_ sender: Any) {
31 | let vc = TabPagerControllerDemoController()
32 | self.navigationController?.pushViewController(vc, animated: true)
33 | }
34 |
35 | override func didReceiveMemoryWarning() {
36 | super.didReceiveMemoryWarning()
37 | // Dispose of any resources that can be recreated.
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/TYPagerControllerDemo/TYPagerController/TabPager/TYTabPagerBarCell.m:
--------------------------------------------------------------------------------
1 | //
2 | // TYTabTitleViewCell.m
3 | // TYPagerControllerDemo
4 | //
5 | // Created by tany on 16/5/4.
6 | // Copyright © 2016年 tanyang. All rights reserved.
7 | //
8 |
9 | #import "TYTabPagerBarCell.h"
10 |
11 | @interface TYTabPagerBarCell ()
12 | @property (nonatomic, weak) UILabel *titleLabel;
13 | @end
14 |
15 | @implementation TYTabPagerBarCell
16 |
17 | - (instancetype)initWithFrame:(CGRect)frame
18 | {
19 | if (self = [super initWithFrame:frame]) {
20 | [self addTabTitleLabel];
21 | }
22 | return self;
23 | }
24 |
25 | - (instancetype)initWithCoder:(NSCoder *)aDecoder
26 | {
27 | if (self = [super initWithCoder:aDecoder]) {
28 | [self addTabTitleLabel];
29 | }
30 | return self;
31 | }
32 |
33 | - (void)addTabTitleLabel
34 | {
35 | UILabel *titleLabel = [[UILabel alloc]init];
36 | titleLabel.font = [UIFont systemFontOfSize:15];
37 | titleLabel.textColor = [UIColor darkTextColor];
38 | titleLabel.textAlignment = NSTextAlignmentCenter;
39 | [self.contentView addSubview:titleLabel];
40 | _titleLabel = titleLabel;
41 | }
42 |
43 | + (NSString *)cellIdentifier {
44 | return @"TYTabPagerBarCell";
45 | }
46 |
47 | - (void)layoutSubviews
48 | {
49 | [super layoutSubviews];
50 | _titleLabel.frame = self.contentView.bounds;
51 | }
52 |
53 | @end
54 |
--------------------------------------------------------------------------------
/TYPagerControllerDemo/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "29x29",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "29x29",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "40x40",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "40x40",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "60x60",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "60x60",
31 | "scale" : "3x"
32 | },
33 | {
34 | "idiom" : "ipad",
35 | "size" : "29x29",
36 | "scale" : "1x"
37 | },
38 | {
39 | "idiom" : "ipad",
40 | "size" : "29x29",
41 | "scale" : "2x"
42 | },
43 | {
44 | "idiom" : "ipad",
45 | "size" : "40x40",
46 | "scale" : "1x"
47 | },
48 | {
49 | "idiom" : "ipad",
50 | "size" : "40x40",
51 | "scale" : "2x"
52 | },
53 | {
54 | "idiom" : "ipad",
55 | "size" : "76x76",
56 | "scale" : "1x"
57 | },
58 | {
59 | "idiom" : "ipad",
60 | "size" : "76x76",
61 | "scale" : "2x"
62 | }
63 | ],
64 | "info" : {
65 | "version" : 1,
66 | "author" : "xcode"
67 | }
68 | }
--------------------------------------------------------------------------------
/TYPagerControllerDemo_swift/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "29x29",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "29x29",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "40x40",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "40x40",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "60x60",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "60x60",
31 | "scale" : "3x"
32 | },
33 | {
34 | "idiom" : "ipad",
35 | "size" : "29x29",
36 | "scale" : "1x"
37 | },
38 | {
39 | "idiom" : "ipad",
40 | "size" : "29x29",
41 | "scale" : "2x"
42 | },
43 | {
44 | "idiom" : "ipad",
45 | "size" : "40x40",
46 | "scale" : "1x"
47 | },
48 | {
49 | "idiom" : "ipad",
50 | "size" : "40x40",
51 | "scale" : "2x"
52 | },
53 | {
54 | "idiom" : "ipad",
55 | "size" : "76x76",
56 | "scale" : "1x"
57 | },
58 | {
59 | "idiom" : "ipad",
60 | "size" : "76x76",
61 | "scale" : "2x"
62 | }
63 | ],
64 | "info" : {
65 | "version" : 1,
66 | "author" : "xcode"
67 | }
68 | }
--------------------------------------------------------------------------------
/TYPagerControllerDemo/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 | LSRequiresIPhoneOS
22 |
23 | UILaunchStoryboardName
24 | LaunchScreen
25 | UIMainStoryboardFile
26 | Main
27 | UIRequiredDeviceCapabilities
28 |
29 | armv7
30 |
31 | UISupportedInterfaceOrientations
32 |
33 | UIInterfaceOrientationPortrait
34 | UIInterfaceOrientationLandscapeLeft
35 | UIInterfaceOrientationLandscapeRight
36 |
37 | UISupportedInterfaceOrientations~ipad
38 |
39 | UIInterfaceOrientationPortrait
40 | UIInterfaceOrientationPortraitUpsideDown
41 | UIInterfaceOrientationLandscapeLeft
42 | UIInterfaceOrientationLandscapeRight
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/TYPagerControllerDemo_swift/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 | LSRequiresIPhoneOS
22 |
23 | UILaunchStoryboardName
24 | LaunchScreen
25 | UIMainStoryboardFile
26 | Main
27 | UIRequiredDeviceCapabilities
28 |
29 | armv7
30 |
31 | UISupportedInterfaceOrientations
32 |
33 | UIInterfaceOrientationPortrait
34 | UIInterfaceOrientationLandscapeLeft
35 | UIInterfaceOrientationLandscapeRight
36 |
37 | UISupportedInterfaceOrientations~ipad
38 |
39 | UIInterfaceOrientationPortrait
40 | UIInterfaceOrientationPortraitUpsideDown
41 | UIInterfaceOrientationLandscapeLeft
42 | UIInterfaceOrientationLandscapeRight
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/TYPagerControllerDemo/ViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.m
3 | // TYPagerControllerDemo
4 | //
5 | // Created by tany on 2017/7/6.
6 | // Copyright © 2017年 tany. All rights reserved.
7 | //
8 |
9 | #import "ViewController.h"
10 | #import "PagerViewDmeoController.h"
11 | #import "PagerControllerDmeoController.h"
12 | #import "TabPagerControllerDemoController.h"
13 | #import "TabPagerViewDmeoController.h"
14 |
15 | @interface ViewController ()
16 |
17 | @end
18 |
19 | @implementation ViewController
20 |
21 | - (void)viewDidLoad {
22 | [super viewDidLoad];
23 | // Do any additional setup after loading the view, typically from a nib.
24 |
25 | }
26 |
27 | #pragma mark - action
28 |
29 | - (IBAction)turnToPageViewDemo:(id)sender {
30 | PagerViewDmeoController *vc = [[PagerViewDmeoController alloc]init];
31 | [self.navigationController pushViewController:vc animated:YES];
32 | }
33 |
34 | - (IBAction)turnToTabPagerViewDemo:(id)sender {
35 | TabPagerViewDmeoController *vc = [[TabPagerViewDmeoController alloc]init];
36 | [self.navigationController pushViewController:vc animated:YES];
37 | }
38 |
39 | - (IBAction)turnToPageControllerDemo:(id)sender {
40 | PagerControllerDmeoController *pagerController = [[PagerControllerDmeoController alloc]init];
41 | [self.navigationController pushViewController:pagerController animated:YES];
42 | }
43 |
44 | - (IBAction)turnToTabPagerControllerDemo:(id)sender {
45 | TabPagerControllerDemoController *pagerController = [[TabPagerControllerDemoController alloc]init];
46 | //pagerController.pagerController.layout.prefetchItemCount = 1;
47 | [self.navigationController pushViewController:pagerController animated:YES];
48 | }
49 | - (void)didReceiveMemoryWarning {
50 | [super didReceiveMemoryWarning];
51 | // Dispose of any resources that can be recreated.
52 | }
53 |
54 |
55 | @end
56 |
--------------------------------------------------------------------------------
/TYPagerControllerDemo/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
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 |
--------------------------------------------------------------------------------
/TYPagerControllerDemo_swift/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
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 |
--------------------------------------------------------------------------------
/TYPagerControllerDemo_swift/TabPagerControllerDemoController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TabPagerControllerDemoController.swift
3 | // TYPagerControllerDemo_swift
4 | //
5 | // Created by tany on 2017/7/19.
6 | // Copyright © 2017年 tany. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class TabPagerControllerDemoController: TYTabPagerController {
12 |
13 | lazy var datas = [String]()
14 |
15 | override func viewDidLoad() {
16 | super.viewDidLoad()
17 |
18 | // Do any additional setup after loading the view.
19 | self.tabBar.layout.barStyle = TYPagerBarStyle.progressView
20 | self.dataSource = self
21 | self.delegate = self
22 |
23 | self.loadData()
24 | }
25 |
26 | func loadData() {
27 | var i = 0
28 | while i < 20 {
29 | self.datas.append(i%2==0 ?"Tab \(i)":"Tab Tab \(i)")
30 | i += 1
31 | }
32 | self.reloadData()
33 | }
34 |
35 | override func didReceiveMemoryWarning() {
36 | super.didReceiveMemoryWarning()
37 | // Dispose of any resources that can be recreated.
38 | }
39 |
40 | }
41 |
42 | extension TabPagerControllerDemoController: TYTabPagerControllerDataSource, TYTabPagerControllerDelegate {
43 | func numberOfControllersInTabPagerController() -> Int {
44 | return self.datas.count
45 | }
46 |
47 | func tabPagerController(_ tabPagerController: TYTabPagerController, controllerFor index: Int, prefetching: Bool) -> UIViewController {
48 | let vc = UIViewController()
49 | vc.view.backgroundColor = UIColor(red: CGFloat(arc4random()%255)/255.0, green: CGFloat(arc4random()%255)/255.0, blue: CGFloat(arc4random()%255)/255.0, alpha: 1)
50 | return vc
51 | }
52 |
53 | func tabPagerController(_ tabPagerController: TYTabPagerController, titleFor index: Int) -> String {
54 | let title = self.datas[index]
55 | return title
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/TYPagerControllerDemo/AppDelegate.m:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.m
3 | // TYPagerControllerDemo
4 | //
5 | // Created by tany on 2017/7/6.
6 | // Copyright © 2017年 tany. All rights reserved.
7 | //
8 |
9 | #import "AppDelegate.h"
10 |
11 | @interface AppDelegate ()
12 |
13 | @end
14 |
15 | @implementation AppDelegate
16 |
17 |
18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
19 | // Override point for customization after application launch.
20 | return YES;
21 | }
22 |
23 |
24 | - (void)applicationWillResignActive:(UIApplication *)application {
25 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
26 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
27 | }
28 |
29 |
30 | - (void)applicationDidEnterBackground:(UIApplication *)application {
31 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
32 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
33 | }
34 |
35 |
36 | - (void)applicationWillEnterForeground:(UIApplication *)application {
37 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
38 | }
39 |
40 |
41 | - (void)applicationDidBecomeActive:(UIApplication *)application {
42 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
43 | }
44 |
45 |
46 | - (void)applicationWillTerminate:(UIApplication *)application {
47 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
48 | }
49 |
50 |
51 | @end
52 |
--------------------------------------------------------------------------------
/TYPagerControllerDemo_swift/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // TYPagerControllerDemo_swift
4 | //
5 | // Created by tany on 2017/7/19.
6 | // Copyright © 2017年 tany. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | @UIApplicationMain
12 | class AppDelegate: UIResponder, UIApplicationDelegate {
13 |
14 | var window: UIWindow?
15 |
16 |
17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
18 | // Override point for customization after application launch.
19 | return true
20 | }
21 |
22 | func applicationWillResignActive(_ application: UIApplication) {
23 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
24 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
25 | }
26 |
27 | func applicationDidEnterBackground(_ application: UIApplication) {
28 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
30 | }
31 |
32 | func applicationWillEnterForeground(_ application: UIApplication) {
33 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
34 | }
35 |
36 | func applicationDidBecomeActive(_ application: UIApplication) {
37 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
38 | }
39 |
40 | func applicationWillTerminate(_ application: UIApplication) {
41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
42 | }
43 |
44 |
45 | }
46 |
47 |
--------------------------------------------------------------------------------
/TYPagerControllerDemo_swift/TabPagerViewDemoController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TabPagerViewDemoController.swift
3 | // TYPagerControllerDemo_swift
4 | //
5 | // Created by tany on 2017/7/19.
6 | // Copyright © 2017年 tany. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class TabPagerViewDemoController: UIViewController {
12 |
13 | lazy var pagerView = TYTabPagerView()
14 | lazy var datas = [String]()
15 |
16 | override func viewDidLoad() {
17 | super.viewDidLoad()
18 | // Do any additional setup after loading the view, typically from a nib.
19 | self.view.backgroundColor = UIColor.white
20 | addTabPagerView()
21 |
22 | loadData()
23 | }
24 |
25 | func addTabPagerView() {
26 | self.pagerView.tabBarHeight = 40
27 | self.pagerView.dataSource = self
28 | self.pagerView.delegate = self
29 | // you can rigsiter cell like tableView
30 | self.pagerView.register(UIView.classForCoder(), forPagerCellWithReuseIdentifier: "cellId");
31 | self.view.addSubview(self.pagerView)
32 | }
33 |
34 | func loadData() {
35 | var i = 0
36 | while i < 20 {
37 | self.datas.append(i%2==0 ?"Tab \(i)":"Tab Tab \(i)")
38 | i += 1
39 | }
40 | self.pagerView.reloadData()
41 | }
42 |
43 | override func viewWillLayoutSubviews() {
44 | super.viewWillLayoutSubviews();
45 | self.pagerView.frame = CGRect(x: 0, y: 64, width: self.view.frame.width, height: self.view.frame.height - 64);
46 | }
47 |
48 | override func didReceiveMemoryWarning() {
49 | super.didReceiveMemoryWarning()
50 | // Dispose of any resources that can be recreated.
51 | }
52 | }
53 |
54 | extension TabPagerViewDemoController: TYTabPagerViewDataSource, TYTabPagerViewDelegate {
55 | func numberOfViewsInTabPagerView() -> Int {
56 | return self.datas.count
57 | }
58 |
59 | func tabPagerView(_ tabPagerView: TYTabPagerView, viewFor index: Int, prefetching: Bool) -> UIView {
60 | //you can let view = UIView() or let view = UIView(frame: tabPagerView.layout.frameForItem(at: index))
61 | // or reigster and dequeue cell like tableView
62 | let view = tabPagerView.dequeueReusablePagerCell(withReuseIdentifier: "cellId", for: index)
63 | view.backgroundColor = UIColor(red: CGFloat(arc4random()%255)/255.0, green: CGFloat(arc4random()%255)/255.0, blue: CGFloat(arc4random()%255)/255.0, alpha: 1)
64 | return view
65 | }
66 |
67 | func tabPagerView(_ tabPagerView: TYTabPagerView, titleFor index: Int) -> String {
68 | let title = self.datas[index]
69 | return title
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/TYPagerControllerDemo/TYPagerController/TabPager/TYTabPagerView.h:
--------------------------------------------------------------------------------
1 | //
2 | // TYTabPagerView.h
3 | // TYPagerControllerDemo
4 | //
5 | // Created by tanyang on 2017/7/18.
6 | // Copyright © 2017年 tany. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "TYPagerView.h"
11 | #import "TYTabPagerBar.h"
12 |
13 | NS_ASSUME_NONNULL_BEGIN
14 |
15 | @class TYTabPagerView;
16 | @protocol TYTabPagerViewDataSource
17 |
18 | - (NSInteger)numberOfViewsInTabPagerView;
19 |
20 | - (UIView *)tabPagerView:(TYTabPagerView *)tabPagerView viewForIndex:(NSInteger)index prefetching:(BOOL)prefetching;
21 |
22 | - (NSString *)tabPagerView:(TYTabPagerView *)tabPagerView titleForIndex:(NSInteger)index;
23 |
24 | @end
25 |
26 | @protocol TYTabPagerViewDelegate
27 | @optional
28 |
29 | // display cell
30 | - (void)tabPagerView:(TYTabPagerView *)tabPagerView willDisplayCell:(UICollectionViewCell *)cell atIndex:(NSInteger)index;
31 |
32 | // did select cell item
33 | - (void)tabPagerView:(TYTabPagerView *)tabPagerView didSelectTabBarItemAtIndex:(NSInteger)index;
34 |
35 | // appear && disappear
36 | - (void)tabPagerView:(TYTabPagerView *)tabPagerView willAppearView:(UIView *)view forIndex:(NSInteger)index;
37 | - (void)tabPagerView:(TYTabPagerView *)tabPagerView didDisappearView:(UIView *)view forIndex:(NSInteger)index;
38 |
39 | // scrolling
40 | - (void)tabPagerViewWillBeginScrolling:(TYTabPagerView *)tabPagerView animate:(BOOL)animate;
41 | - (void)tabPagerViewDidEndScrolling:(TYTabPagerView *)tabPagerView animate:(BOOL)animate;
42 |
43 | @end
44 |
45 | @interface TYTabPagerView : UIView
46 |
47 | @property (nonatomic, weak, readonly) TYTabPagerBar *tabBar;
48 | @property (nonatomic, weak, readonly) TYPagerView *pageView;
49 |
50 | @property (nonatomic, strong, readonly) TYPagerViewLayout *layout;
51 |
52 | @property (nonatomic, weak, nullable) id dataSource;
53 | @property (nonatomic, weak, nullable) id delegate;
54 |
55 | @property (nonatomic, assign) CGFloat tabBarHeight;
56 |
57 | // register tabBar cell
58 | - (void)registerClass:(Class)Class forTabBarCellWithReuseIdentifier:(NSString *)identifier;
59 | - (void)registerNib:(UINib *)nib forTabBarCellWithReuseIdentifier:(NSString *)identifier;
60 |
61 | // register && dequeue pager Cell, usage like tableView
62 | - (void)registerClass:(Class)Class forPagerCellWithReuseIdentifier:(NSString *)identifier;
63 | - (void)registerNib:(UINib *)nib forPagerCellWithReuseIdentifier:(NSString *)identifier;
64 | - (UIView *)dequeueReusablePagerCellWithReuseIdentifier:(NSString *)identifier forIndex:(NSInteger)index;
65 |
66 |
67 | - (void)scrollToViewAtIndex:(NSInteger)index animate:(BOOL)animate;
68 |
69 | - (void)updateData;
70 |
71 | - (void)reloadData;
72 |
73 | @end
74 |
75 | NS_ASSUME_NONNULL_END
76 |
--------------------------------------------------------------------------------
/TYPagerControllerDemo/TYPagerController/TabPager/TYTabPagerController.h:
--------------------------------------------------------------------------------
1 | //
2 | // TYTabPagerController.h
3 | // TYPagerControllerDemo
4 | //
5 | // Created by tanyang on 2017/7/18.
6 | // Copyright © 2017年 tany. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "TYTabPagerBar.h"
11 | #import "TYPagerController.h"
12 |
13 | NS_ASSUME_NONNULL_BEGIN
14 |
15 | @class TYTabPagerController;
16 | @protocol TYTabPagerControllerDataSource
17 |
18 | - (NSInteger)numberOfControllersInTabPagerController;
19 |
20 | - (UIViewController *)tabPagerController:(TYTabPagerController *)tabPagerController controllerForIndex:(NSInteger)index prefetching:(BOOL)prefetching;
21 |
22 | - (NSString *)tabPagerController:(TYTabPagerController *)tabPagerController titleForIndex:(NSInteger)index;
23 |
24 | @end
25 |
26 | @protocol TYTabPagerControllerDelegate
27 | @optional
28 |
29 | // display cell
30 | - (void)tabPagerController:(TYTabPagerController *)tabPagerController willDisplayCell:(UICollectionViewCell *)cell atIndex:(NSInteger)index;
31 |
32 | // did select cell item
33 | - (void)tabPagerController:(TYTabPagerController *)tabPagerController didSelectTabBarItemAtIndex:(NSInteger)index;
34 |
35 | // scrolling
36 | - (void)tabPagerControllerWillBeginScrolling:(TYTabPagerController *)tabPagerController animate:(BOOL)animate;
37 | - (void)tabPagerControllerDidEndScrolling:(TYTabPagerController *)tabPagerController animate:(BOOL)animate;
38 |
39 | @end
40 |
41 | @interface TYTabPagerController : UIViewController
42 |
43 | @property (nonatomic, strong, readonly) TYTabPagerBar *tabBar;
44 | @property (nonatomic, strong, readonly) TYPagerController *pagerController;
45 | @property (nonatomic, strong, readonly) TYPagerViewLayout *layout;
46 |
47 | @property (nonatomic, weak, nullable) id dataSource;
48 | @property (nonatomic, weak, nullable) id delegate;
49 |
50 | // you can custom tabBar orignY and height.
51 | @property (nonatomic, assign) CGFloat tabBarOrignY;
52 | @property (nonatomic, assign) CGFloat tabBarHeight;
53 |
54 | // register tabBar cell
55 | - (void)registerClass:(Class)Class forTabBarCellWithReuseIdentifier:(NSString *)identifier;
56 | - (void)registerNib:(UINib *)nib forTabBarCellWithReuseIdentifier:(NSString *)identifier;
57 |
58 | // register && dequeue pager Cell, usage like tableView
59 | - (void)registerClass:(Class)Class forPagerCellWithReuseIdentifier:(NSString *)identifier;
60 | - (void)registerNib:(UINib *)nib forPagerCellWithReuseIdentifier:(NSString *)identifier;
61 | - (UIViewController *)dequeueReusablePagerCellWithReuseIdentifier:(NSString *)identifier forIndex:(NSInteger)index;
62 |
63 |
64 | - (void)scrollToControllerAtIndex:(NSInteger)index animate:(BOOL)animate;
65 |
66 | - (void)updateData;
67 |
68 | - (void)reloadData;
69 |
70 |
71 | @end
72 |
73 | NS_ASSUME_NONNULL_END
74 |
--------------------------------------------------------------------------------
/TYPagerControllerDemo/TabPagerViewDmeoController.m:
--------------------------------------------------------------------------------
1 | //
2 | // TabPagerViewDmeoController.m
3 | // TYPagerControllerDemo
4 | //
5 | // Created by tany on 2017/7/19.
6 | // Copyright © 2017年 tany. All rights reserved.
7 | //
8 |
9 | #import "TabPagerViewDmeoController.h"
10 | #import "TYTabPagerView.h"
11 |
12 | @interface TabPagerViewDmeoController ()
13 |
14 | @property (nonatomic, weak) TYTabPagerView *pagerView;
15 |
16 | @property (nonatomic, strong) NSArray *datas;
17 |
18 | @end
19 |
20 | @implementation TabPagerViewDmeoController
21 |
22 | - (void)viewDidLoad {
23 | [super viewDidLoad];
24 | // Do any additional setup after loading the view.
25 | self.title = @"TabPagerViewDmeoController";
26 | self.view.backgroundColor = [UIColor whiteColor];
27 | [self addTabPagerView];
28 |
29 | [self loadData];
30 | }
31 |
32 | - (void)addTabPagerView {
33 | TYTabPagerView *pagerView = [[TYTabPagerView alloc]init];
34 | pagerView.tabBar.layout.barStyle = TYPagerBarStyleCoverView;
35 | pagerView.tabBar.progressView.backgroundColor = [UIColor lightGrayColor];
36 | pagerView.dataSource = self;
37 | pagerView.delegate = self;
38 | [self.view addSubview:pagerView];
39 | _pagerView = pagerView;
40 | }
41 |
42 | - (void)viewWillLayoutSubviews {
43 | [super viewWillLayoutSubviews];
44 | _pagerView.frame = CGRectMake(0, CGRectGetMaxY(self.navigationController.navigationBar.frame), CGRectGetWidth(self.view.frame),CGRectGetHeight(self.view.frame)-CGRectGetMaxY(self.navigationController.navigationBar.frame));
45 | }
46 |
47 | - (void)loadData {
48 | NSMutableArray *datas = [NSMutableArray array];
49 | for (NSInteger i = 0; i < 20; ++i) {
50 | [datas addObject:i%2 == 0 ? [NSString stringWithFormat:@"Tab %ld",i]:[NSString stringWithFormat:@"Tab Tab %ld",i]];
51 | }
52 | _datas = [datas copy];
53 |
54 | [_pagerView reloadData];
55 | //[_pagerView scrollToViewAtIndex:1 animate:YES];
56 | }
57 |
58 |
59 | #pragma mark - TYTabPagerViewDataSource
60 |
61 | - (NSInteger)numberOfViewsInTabPagerView {
62 | return _datas.count;
63 | }
64 |
65 | - (UIView *)tabPagerView:(TYTabPagerView *)tabPagerView viewForIndex:(NSInteger)index prefetching:(BOOL)prefetching {
66 | UIView *view = [[UIView alloc]initWithFrame:[tabPagerView.layout frameForItemAtIndex:index]];
67 | view.backgroundColor = [UIColor colorWithRed:arc4random()%255/255.0 green:arc4random()%255/255.0 blue:arc4random()%255/255.0 alpha:arc4random()%255/255.0];
68 | //NSLog(@"viewForIndex:%ld prefetching:%d",index,prefetching);
69 | return view;
70 | }
71 |
72 | - (NSString *)tabPagerView:(TYTabPagerView *)tabPagerView titleForIndex:(NSInteger)index {
73 | NSString *title = _datas[index];
74 | return title;
75 | }
76 |
77 | - (void)didReceiveMemoryWarning {
78 | [super didReceiveMemoryWarning];
79 | // Dispose of any resources that can be recreated.
80 | }
81 |
82 | /*
83 | #pragma mark - Navigation
84 |
85 | // In a storyboard-based application, you will often want to do a little preparation before navigation
86 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
87 | // Get the new view controller using [segue destinationViewController].
88 | // Pass the selected object to the new view controller.
89 | }
90 | */
91 |
92 | @end
93 |
--------------------------------------------------------------------------------
/TYPagerControllerDemo/TabPagerControllerDemoController.m:
--------------------------------------------------------------------------------
1 | //
2 | // PagerControllerDemoController.m
3 | // TYPagerControllerDemo
4 | //
5 | // Created by tanyang on 2017/7/18.
6 | // Copyright © 2017年 tany. All rights reserved.
7 | //
8 |
9 | #import "TabPagerControllerDemoController.h"
10 | #import "CustomViewController.h"
11 | #import "ListViewController.h"
12 | #import "CollectionViewController.h"
13 |
14 | @interface TabPagerControllerDemoController ()
15 |
16 | @property (nonatomic, strong) NSArray *datas;
17 |
18 | @end
19 |
20 | @implementation TabPagerControllerDemoController
21 |
22 | - (void)viewDidLoad {
23 | [super viewDidLoad];
24 | // Do any additional setup after loading the view.
25 | self.title = @"TabPagerControllerDemoController";
26 | self.tabBarHeight = 50;
27 | self.tabBar.layout.barStyle = TYPagerBarStyleProgressView;
28 | self.tabBar.layout.cellWidth = CGRectGetWidth(self.view.frame)/3;
29 | self.tabBar.layout.cellSpacing = 0;
30 | self.tabBar.layout.cellEdging = 0;
31 | self.tabBar.layout.adjustContentCellsCenter = YES;
32 | self.dataSource = self;
33 | self.delegate = self;
34 |
35 | [self loadData];
36 | }
37 |
38 | - (void)loadData {
39 | NSMutableArray *datas = [NSMutableArray array];
40 | for (NSInteger i = 0; i < 3; ++i) {
41 | [datas addObject:i%2 == 0 ? [NSString stringWithFormat:@"Tab %ld",i]:[NSString stringWithFormat:@"Tab Tab %ld",i]];
42 | }
43 | _datas = [datas copy];
44 |
45 | // only add controller at index 1
46 | [self scrollToControllerAtIndex:1 animate:YES];
47 | [self reloadData];
48 |
49 | // first reloadData add controller at index 0,and scroll to index 1
50 | // [self reloadData];
51 | // [self scrollToControllerAtIndex:1 animate:YES];
52 | }
53 |
54 | #pragma mark - TYTabPagerControllerDataSource
55 |
56 | - (NSInteger)numberOfControllersInTabPagerController {
57 | return _datas.count;
58 | }
59 |
60 | - (UIViewController *)tabPagerController:(TYTabPagerController *)tabPagerController controllerForIndex:(NSInteger)index prefetching:(BOOL)prefetching {
61 | if (index%3 == 0) {
62 | CustomViewController *VC = [[CustomViewController alloc]init];
63 | VC.text = [@(index) stringValue];
64 | return VC;
65 | }else if (index%3 == 1) {
66 | ListViewController *VC = [[ListViewController alloc]init];
67 | VC.text = [@(index) stringValue];
68 | return VC;
69 | }else {
70 | CollectionViewController *VC = [[CollectionViewController alloc]init];
71 | VC.text = [@(index) stringValue];
72 | return VC;
73 | }
74 | }
75 |
76 | - (NSString *)tabPagerController:(TYTabPagerController *)tabPagerController titleForIndex:(NSInteger)index {
77 | NSString *title = _datas[index];
78 | return title;
79 | }
80 |
81 | - (void)didReceiveMemoryWarning {
82 | [super didReceiveMemoryWarning];
83 | // Dispose of any resources that can be recreated.
84 | }
85 |
86 | /*
87 | #pragma mark - Navigation
88 |
89 | // In a storyboard-based application, you will often want to do a little preparation before navigation
90 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
91 | // Get the new view controller using [segue destinationViewController].
92 | // Pass the selected object to the new view controller.
93 | }
94 | */
95 |
96 | @end
97 |
--------------------------------------------------------------------------------
/TYPagerControllerDemo/TYPagerController/TabPager/TYTabPagerBar.h:
--------------------------------------------------------------------------------
1 | //
2 | // TYTabPagerBar.h
3 | // TYPagerControllerDemo
4 | //
5 | // Created by tany on 2017/7/13.
6 | // Copyright © 2017年 tany. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "TYTabPagerBarLayout.h"
11 |
12 | NS_ASSUME_NONNULL_BEGIN
13 |
14 | @class TYTabPagerBar;
15 | @protocol TYTabPagerBarDataSource
16 |
17 | - (NSInteger)numberOfItemsInPagerTabBar;
18 |
19 | - (UICollectionViewCell *)pagerTabBar:(TYTabPagerBar *)pagerTabBar cellForItemAtIndex:(NSInteger)index;
20 |
21 | @end
22 |
23 | @protocol TYTabPagerBarDelegate
24 |
25 | @optional
26 |
27 | // configure layout
28 | - (void)pagerTabBar:(TYTabPagerBar *)pagerTabBar configureLayout:(TYTabPagerBarLayout *)layout;
29 |
30 | // if cell wdith is not variable,you can set layout.cellWidth. otherwise ,you can implement this return cell width. cell width not contain cell edge
31 | - (CGFloat)pagerTabBar:(TYTabPagerBar *)pagerTabBar widthForItemAtIndex:(NSInteger)index;
32 |
33 | // did select cell item
34 | - (void)pagerTabBar:(TYTabPagerBar *)pagerTabBar didSelectItemAtIndex:(NSInteger)index;
35 |
36 | // transition frome cell to cell with animated
37 | - (void)pagerTabBar:(TYTabPagerBar *)pagerTabBar transitionFromeCell:(UICollectionViewCell * _Nullable)fromCell toCell:(UICollectionViewCell * _Nullable)toCell animated:(BOOL)animated;
38 |
39 | // transition frome cell to cell with progress
40 | - (void)pagerTabBar:(TYTabPagerBar *)pagerTabBar transitionFromeCell:(UICollectionViewCell * _Nullable)fromCell toCell:(UICollectionViewCell * _Nullable)toCell progress:(CGFloat)progress;
41 |
42 | @end
43 |
44 | @interface TYTabPagerBar : UIView
45 |
46 | @property (nonatomic, weak, readonly) UICollectionView *collectionView;
47 | @property (nonatomic, strong) UIView *progressView;
48 | // automatically resized to self.bounds
49 | @property (nonatomic, strong) UIView *backgroundView;
50 |
51 | @property (nonatomic, weak, nullable) id dataSource;
52 |
53 | @property (nonatomic, weak, nullable) id delegate;
54 |
55 | @property (nonatomic, strong) TYTabPagerBarLayout *layout;
56 |
57 | @property (nonatomic, assign) BOOL autoScrollItemToCenter;
58 |
59 | @property (nonatomic, assign, readonly) NSInteger countOfItems;
60 |
61 | @property (nonatomic, assign, readonly) NSInteger curIndex;
62 |
63 | @property (nonatomic, assign) UIEdgeInsets contentInset;
64 |
65 | - (void)registerClass:(Class)Class forCellWithReuseIdentifier:(NSString *)identifier;
66 | - (void)registerNib:(UINib *)nib forCellWithReuseIdentifier:(NSString *)identifier;
67 |
68 | - (__kindof UICollectionViewCell *)dequeueReusableCellWithReuseIdentifier:(NSString *)identifier forIndex:(NSInteger)index;
69 |
70 | - (void)reloadData;
71 |
72 | - (void)scrollToItemFromIndex:(NSInteger)fromIndex toIndex:(NSInteger)toIndex animate:(BOOL)animate;
73 | - (void)scrollToItemFromIndex:(NSInteger)fromIndex toIndex:(NSInteger)toIndex progress:(CGFloat)progress;
74 | - (void)scrollToItemAtIndex:(NSInteger)index atScrollPosition:(UICollectionViewScrollPosition)scrollPosition animated:(BOOL)animated;
75 |
76 | - (CGFloat)cellWidthForTitle:(NSString * _Nullable)title;
77 | - (CGRect)cellFrameWithIndex:(NSInteger)index;
78 | - (nullable UICollectionViewCell *)cellForIndex:(NSInteger)index;
79 |
80 | @end
81 |
82 | NS_ASSUME_NONNULL_END
83 |
--------------------------------------------------------------------------------
/TYPagerControllerDemo/CollectionViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // CollectionViewController.m
3 | // TYPagerControllerDemo
4 | //
5 | // Created by tany on 16/5/17.
6 | // Copyright © 2016年 tanyang. All rights reserved.
7 | //
8 |
9 | #import "CollectionViewController.h"
10 |
11 | @interface CollectionViewController ()
12 | @property (nonatomic, weak) UICollectionView *collectionView;
13 | @end
14 |
15 | static NSString *const cellId = @"collectCellId";
16 |
17 | @implementation CollectionViewController
18 |
19 | - (void)viewDidLoad {
20 | [super viewDidLoad];
21 | // Do any additional setup after loading the view.
22 |
23 | [self addCollectionView];
24 | [_collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:cellId];
25 | }
26 |
27 | - (void)viewWillAppear:(BOOL)animated
28 | {
29 | [super viewWillAppear:animated];
30 | NSLog(@"viewWillAppear index %@",_text);
31 | }
32 |
33 | - (void)viewDidAppear:(BOOL)animated
34 | {
35 | [super viewWillAppear:animated];
36 | NSLog(@"viewDidAppear index %@",_text);
37 | }
38 |
39 | - (void)viewWillDisappear:(BOOL)animated
40 | {
41 | [super viewWillDisappear:animated];
42 | NSLog(@"viewWillDisappear index %@",_text);
43 | }
44 |
45 | - (void)viewDidDisappear:(BOOL)animated
46 | {
47 | [super viewWillDisappear:animated];
48 | NSLog(@"viewDidDisappear index %@",_text);
49 | }
50 |
51 |
52 | - (void)viewWillLayoutSubviews
53 | {
54 | [super viewWillLayoutSubviews];
55 | _collectionView.frame = self.view.bounds;
56 | }
57 |
58 | - (void)addCollectionView
59 | {
60 | UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc]init];
61 | layout.itemSize = CGSizeMake((CGRectGetWidth(self.view.frame)-20)/3, (CGRectGetWidth(self.view.frame)-20)/3);
62 | layout.minimumLineSpacing = 10;
63 | layout.sectionInset = UIEdgeInsetsMake(10, 0, 0, 0);
64 |
65 | UICollectionView *collectionView = [[UICollectionView alloc]initWithFrame:self.view.bounds collectionViewLayout:layout];
66 | collectionView.backgroundColor = [UIColor whiteColor];
67 | collectionView.dataSource = self;
68 | [self.view addSubview:collectionView];
69 | _collectionView = collectionView;
70 | }
71 |
72 | #pragma mark - UIViewControllerDisplayViewDelegate
73 |
74 | - (UIScrollView *)displayView
75 | {
76 | return _collectionView;
77 | }
78 |
79 | #pragma mark - UICollectionViewDataSource
80 |
81 | - (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
82 | {
83 | return 3;
84 | }
85 |
86 | - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
87 | {
88 | return 3*3;
89 | }
90 |
91 | - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
92 | {
93 | UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:cellId forIndexPath:indexPath];
94 | cell.backgroundColor = [UIColor colorWithRed:255/255.0 green:204/255.0 blue:204/255.0 alpha:1.0];
95 | return cell;
96 | }
97 |
98 | - (void)didReceiveMemoryWarning {
99 | [super didReceiveMemoryWarning];
100 | // Dispose of any resources that can be recreated.
101 | }
102 |
103 | /*
104 | #pragma mark - Navigation
105 |
106 | // In a storyboard-based application, you will often want to do a little preparation before navigation
107 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
108 | // Get the new view controller using [segue destinationViewController].
109 | // Pass the selected object to the new view controller.
110 | }
111 | */
112 |
113 | @end
114 |
--------------------------------------------------------------------------------
/TYPagerControllerDemo/TYPagerController/TabPager/TYTabPagerBarLayout.h:
--------------------------------------------------------------------------------
1 | //
2 | // TYTabPagerBarLayout.h
3 | // TYPagerControllerDemo
4 | //
5 | // Created by tanyang on 2017/7/17.
6 | // Copyright © 2017年 tany. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "TYTabPagerBarCell.h"
11 |
12 | NS_ASSUME_NONNULL_BEGIN
13 |
14 | typedef NS_ENUM(NSUInteger, TYPagerBarStyle) {
15 | TYPagerBarStyleNoneView,
16 | TYPagerBarStyleProgressView,
17 | TYPagerBarStyleProgressBounceView,
18 | TYPagerBarStyleProgressElasticView,
19 | TYPagerBarStyleCoverView,
20 | };
21 |
22 | @class TYTabPagerBar;
23 | @interface TYTabPagerBarLayout : NSObject
24 |
25 | @property (nonatomic, weak, readonly) TYTabPagerBar *pagerTabBar;
26 | @property (nonatomic, assign, readonly) CGFloat selectFontScale;
27 |
28 | // set barStyle will reset propertys, so you should first time set it,
29 | @property (nonatomic, assign) TYPagerBarStyle barStyle; // default TYPagerBarStyleProgressElasticView
30 |
31 | @property (nonatomic, assign) UIEdgeInsets sectionInset;
32 |
33 | // progress view
34 | @property (nonatomic, assign) CGFloat progressHeight; // default 2
35 | @property (nonatomic, assign) CGFloat progressWidth; //if > 0 progress width is equal,else progress width is cell width
36 | @property (nonatomic, strong, nullable) UIColor *progressColor;
37 |
38 | @property (nonatomic, assign) CGFloat progressRadius; // height/2
39 | @property (nonatomic, assign) CGFloat progressBorderWidth;
40 | @property (nonatomic, strong, nullable) UIColor *progressBorderColor;
41 |
42 | @property (nonatomic, assign) CGFloat progressHorEdging; // default 6, if < 0 width + edge ,if >0 width - edge
43 | @property (nonatomic, assign) CGFloat progressVerEdging; // default 0, cover style is 3.
44 |
45 | // cell frame
46 | @property (nonatomic, assign) CGFloat cellWidth; // default 0, if > 0 cells width is equal,else if = 0 cell will call delegate
47 | @property (nonatomic, assign) CGFloat cellSpacing; // default 2,cell space
48 | @property (nonatomic, assign) CGFloat cellEdging; // default 0,cell left right edge
49 | @property (nonatomic, assign) BOOL adjustContentCellsCenter;// default NO, cells center if contentSize < bar's width ,will set sectionInset
50 |
51 | // TYTabPagerBarCellProtocol -> cell's label
52 | @property (nonatomic, strong) UIFont *normalTextFont; // default 15
53 | @property (nonatomic, strong) UIFont *selectedTextFont; // default 17
54 | @property (nonatomic, strong) UIColor *normalTextColor; // default 51.51.51
55 | @property (nonatomic, strong) UIColor *selectedTextColor; // default white
56 | @property (nonatomic, assign) BOOL textColorProgressEnable; // default YES
57 |
58 | // animate duration
59 | @property (nonatomic, assign) CGFloat animateDuration; // default 0.3
60 |
61 | - (instancetype)init NS_UNAVAILABLE;
62 | + (instancetype)new NS_UNAVAILABLE;
63 |
64 | - (instancetype)initWithPagerTabBar:(TYTabPagerBar *)pagerTabBar NS_DESIGNATED_INITIALIZER;
65 |
66 | - (void)layoutIfNeed;
67 |
68 | - (void)invalidateLayout;
69 |
70 | - (void)layoutSubViews;
71 |
72 | - (void)adjustContentCellsCenterInBar;
73 |
74 | // override
75 | - (void)transitionFromCell:(UICollectionViewCell *_Nullable)fromCell toCell:(UICollectionViewCell *_Nullable)toCell animate:(BOOL)animate;
76 |
77 | - (void)transitionFromCell:(UICollectionViewCell *_Nullable)fromCell toCell:(UICollectionViewCell *_Nullable)toCell progress:(CGFloat)progress;
78 |
79 | - (void)setUnderLineFrameWithIndex:(NSInteger)index animated:(BOOL)animated;
80 |
81 | - (void)setUnderLineFrameWithfromIndex:(NSInteger)fromIndex toIndex:(NSInteger)toIndex progress:(CGFloat)progress;
82 | @end
83 |
84 | NS_ASSUME_NONNULL_END
85 |
--------------------------------------------------------------------------------
/TYPagerControllerDemo/ListViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // ListViewController.m
3 | // TYPagerControllerDemo
4 | //
5 | // Created by tany on 16/5/17.
6 | // Copyright © 2016年 tanyang. All rights reserved.
7 | //
8 |
9 | #import "ListViewController.h"
10 |
11 | @interface ListViewController ()
12 | @property (nonatomic, weak) UITableView *tableView;
13 | @end
14 |
15 | @implementation ListViewController
16 |
17 | - (void)viewDidLoad {
18 | [super viewDidLoad];
19 | // Do any additional setup after loading the view.
20 |
21 | [self addTableView];
22 |
23 | [self addHorHeaderScrollView];
24 | }
25 |
26 | - (void)viewWillAppear:(BOOL)animated
27 | {
28 | [super viewWillAppear:animated];
29 | NSLog(@"viewWillAppear index %@",_text);
30 | }
31 |
32 | - (void)viewDidAppear:(BOOL)animated
33 | {
34 | [super viewWillAppear:animated];
35 | NSLog(@"viewDidAppear index %@",_text);
36 | }
37 |
38 | - (void)viewWillDisappear:(BOOL)animated
39 | {
40 | [super viewWillDisappear:animated];
41 | NSLog(@"viewWillDisappear index %@",_text);
42 | }
43 |
44 | - (void)viewDidDisappear:(BOOL)animated
45 | {
46 | [super viewWillDisappear:animated];
47 | NSLog(@"viewDidDisappear index %@",_text);
48 | }
49 |
50 | - (void)viewDidLayoutSubviews
51 | {
52 | [super viewDidLayoutSubviews];
53 | self.tableView.frame = self.view.bounds;
54 | }
55 |
56 | - (void)addTableView
57 | {
58 | UITableView *tableView = [[UITableView alloc]init];
59 | tableView.delegate = self;
60 | tableView.dataSource = self;
61 |
62 | [self.view addSubview:tableView];
63 | _tableView = tableView;
64 | [tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"cellId"];
65 | }
66 |
67 | - (void)addHorHeaderScrollView
68 | {
69 | UIScrollView *scrollView = [[UIScrollView alloc]initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.view.frame), 200)];
70 | scrollView.pagingEnabled = YES;
71 | scrollView.showsHorizontalScrollIndicator = NO;
72 | scrollView.contentSize = CGSizeMake(2*CGRectGetWidth(self.view.frame), 0);
73 | [self.view addSubview:scrollView];
74 |
75 | UIView *page1View = [[UIView alloc]initWithFrame:scrollView.bounds];
76 | page1View.backgroundColor = [UIColor orangeColor];
77 | [scrollView addSubview:page1View];
78 | UIView *page2View = [[UIView alloc]initWithFrame:CGRectMake(CGRectGetWidth(self.view.frame), 0, CGRectGetWidth(self.view.frame), 200)];
79 | page2View.backgroundColor = [UIColor redColor];
80 | [scrollView addSubview:page2View];
81 |
82 | _tableView.tableHeaderView = scrollView;
83 | }
84 |
85 | #pragma mark - delegate
86 |
87 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
88 | {
89 | return 20;
90 | }
91 |
92 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
93 | {
94 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cellId" forIndexPath:indexPath];
95 | cell.textLabel.text = [NSString stringWithFormat:@"text row %ld",indexPath.row];
96 | return cell;
97 | }
98 |
99 | - (void)didReceiveMemoryWarning {
100 | [super didReceiveMemoryWarning];
101 | // Dispose of any resources that can be recreated.
102 | }
103 |
104 | /*
105 | #pragma mark - Navigation
106 |
107 | // In a storyboard-based application, you will often want to do a little preparation before navigation
108 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
109 | // Get the new view controller using [segue destinationViewController].
110 | // Pass the selected object to the new view controller.
111 | }
112 | */
113 |
114 | @end
115 |
--------------------------------------------------------------------------------
/TYPagerControllerDemo/TYPagerController/TYPagerView.h:
--------------------------------------------------------------------------------
1 | //
2 | // TYPagerView.h
3 | // TYPagerControllerDemo
4 | //
5 | // Created by tany on 2017/7/5.
6 | // Copyright © 2017年 tanyang. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "TYPagerViewLayout.h"
11 |
12 | NS_ASSUME_NONNULL_BEGIN
13 |
14 | @class TYPagerView;
15 | @protocol TYPagerViewDataSource
16 |
17 | - (NSInteger)numberOfViewsInPagerView;
18 |
19 | /* 1.if prefetching is YES, the prefetch view not display.
20 | 2.if view will diaplay,will call willAppearView:forIndex:.
21 | 3.layout.frameForItemAtIndex can get view's frame
22 | 4.you can register && dequeue view, usage like tableView
23 | */
24 | - (UIView *)pagerView:(TYPagerView *)pagerView viewForIndex:(NSInteger)index prefetching:(BOOL)prefetching;
25 |
26 | @end
27 |
28 | @protocol TYPagerViewDelegate
29 | @optional
30 |
31 | // Display customization
32 | // if want do something in view will display,you can implement this
33 | - (void)pagerView:(TYPagerView *)pagerView willAppearView:(UIView *)view forIndex:(NSInteger)index;
34 | - (void)pagerView:(TYPagerView *)pagerView didAppearView:(UIView *)view forIndex:(NSInteger)index;
35 |
36 | // Disappear customization
37 |
38 | - (void)pagerView:(TYPagerView *)pagerView willDisappearView:(UIView *)view forIndex:(NSInteger)index;
39 | - (void)pagerView:(TYPagerView *)pagerView didDisappearView:(UIView *)view forIndex:(NSInteger)index;
40 |
41 | // Transition animation customization
42 |
43 | // if you implement ↓↓↓transitionFromIndex:toIndex:progress:,only tap change index will call this, you can set progressAnimateEnabel NO that not call progress method
44 | - (void)pagerView:(TYPagerView *)pagerView transitionFromIndex:(NSInteger)fromIndex toIndex:(NSInteger)toIndex animated:(BOOL)animated;
45 |
46 | // if you implement the method,also you need implement ↑↑↑transitionFromIndex:toIndex:animated:,deal with tap change index animate
47 | - (void)pagerView:(TYPagerView *)pagerView transitionFromIndex:(NSInteger)fromIndex toIndex:(NSInteger)toIndex progress:(CGFloat)progress;
48 |
49 | // scrollView delegate
50 |
51 | - (void)pagerViewDidScroll:(TYPagerView *)pageView;
52 | - (void)pagerViewWillBeginScrolling:(TYPagerView *)pageView animate:(BOOL)animate;
53 | - (void)pagerViewDidEndScrolling:(TYPagerView *)pageView animate:(BOOL)animate;
54 |
55 |
56 | @end
57 |
58 | @interface TYPagerView : UIView
59 |
60 | @property (nonatomic, weak, nullable) id dataSource;
61 | @property (nonatomic, weak, nullable) id delegate;
62 | // pagerView's layout,don't set layout's dataSource to other
63 | @property (nonatomic, strong, readonly) TYPagerViewLayout *layout;
64 | @property (nonatomic, strong, readonly) UIScrollView *scrollView;
65 |
66 | @property (nonatomic, assign, readonly) NSInteger countOfPagerViews;
67 | @property (nonatomic, assign, readonly) NSInteger curIndex;// default -1
68 |
69 | @property (nonatomic, assign, nullable, readonly) NSArray *visibleViews;
70 |
71 | @property (nonatomic, assign) UIEdgeInsets contentInset;
72 |
73 | //if not visible, prefecth, cache view at index, return nil
74 | - (UIView *_Nullable)viewForIndex:(NSInteger)index;
75 |
76 | // register && dequeue's usage like tableView
77 | - (void)registerClass:(Class)Class forViewWithReuseIdentifier:(NSString *)identifier;
78 | - (void)registerNib:(UINib *)nib forViewWithReuseIdentifier:(NSString *)identifier;
79 | - (UIView *)dequeueReusableViewWithReuseIdentifier:(NSString *)identifier forIndex:(NSInteger)index;
80 |
81 | // scroll to index
82 | - (void)scrollToViewAtIndex:(NSInteger)index animate:(BOOL)animate;
83 |
84 | // update data and layout,but don't reset propertys(curIndex,visibleDatas,prefechDatas)
85 | - (void)updateData;
86 |
87 | // reload data and reset propertys
88 | - (void)reloadData;
89 |
90 | @end
91 |
92 | NS_ASSUME_NONNULL_END
93 |
94 |
--------------------------------------------------------------------------------
/TYPagerControllerDemo_swift.xcodeproj/xcuserdata/tany.xcuserdatad/xcschemes/TYPagerControllerDemo_swift.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
39 |
40 |
41 |
42 |
43 |
44 |
54 |
56 |
62 |
63 |
64 |
65 |
66 |
67 |
73 |
75 |
81 |
82 |
83 |
84 |
86 |
87 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/TYPagerControllerDemo_swift.xcodeproj/xcuserdata/tanyang.xcuserdatad/xcschemes/TYPagerControllerDemo_swift.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
39 |
40 |
41 |
42 |
43 |
44 |
54 |
56 |
62 |
63 |
64 |
65 |
66 |
67 |
73 |
75 |
81 |
82 |
83 |
84 |
86 |
87 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/TYPagerControllerDemo/TYPagerController/TYPagerController.h:
--------------------------------------------------------------------------------
1 | //
2 | // TYPagerController.h
3 | // TYPagerControllerDemo
4 | //
5 | // Created by tanyang on 16/4/13.
6 | // Copyright © 2016年 tanyang. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "TYPagerViewLayout.h"
11 |
12 | NS_ASSUME_NONNULL_BEGIN
13 |
14 | @class TYPagerController;
15 | @protocol TYPagerControllerDataSource
16 |
17 | // viewController's count in pagerController
18 | - (NSInteger)numberOfControllersInPagerController;
19 |
20 | /* 1.viewController at index in pagerController
21 | 2.if prefetching is YES,the controller is preload,not display.
22 | 3.if controller will display,will call viewWillAppear.
23 | 4.you can register && dequeue controller, usage like tableView
24 | */
25 | - (UIViewController *)pagerController:(TYPagerController *)pagerController controllerForIndex:(NSInteger)index prefetching:(BOOL)prefetching;
26 |
27 | @end
28 |
29 | @protocol TYPagerControllerDelegate
30 |
31 | @optional
32 |
33 | // Display customization
34 | // the same to viewWillAppear, also can use viewController's viewWillAppear
35 | - (void)pagerController:(TYPagerController *)pagerController viewWillAppear:(UIViewController *)viewController forIndex:(NSInteger)index;
36 | - (void)pagerController:(TYPagerController *)pagerController viewDidAppear:(UIViewController *)viewController forIndex:(NSInteger)index;
37 |
38 | // Disappear customization
39 | // the same to viewWillDisappear, also can use viewController's viewWillDisappear
40 | - (void)pagerController:(TYPagerController *)pagerController viewWillDisappear:(UIViewController *)viewController forIndex:(NSInteger)index;
41 | - (void)pagerController:(TYPagerController *)pagerController viewDidDisappear:(UIViewController *)viewController forIndex:(NSInteger)index;
42 |
43 | // Transition animation customization
44 |
45 | - (void)pagerController:(TYPagerController *)pagerController transitionFromIndex:(NSInteger)fromIndex toIndex:(NSInteger)toIndex animated:(BOOL)animated;
46 |
47 | - (void)pagerController:(TYPagerController *)pagerController transitionFromIndex:(NSInteger)fromIndex toIndex:(NSInteger)toIndex progress:(CGFloat)progress;
48 |
49 |
50 | // ScrollViewDelegate
51 |
52 | - (void)pagerControllerDidScroll:(TYPagerController *)pagerController;
53 | - (void)pagerControllerWillBeginScrolling:(TYPagerController *)pagerController animate:(BOOL)animate;
54 | - (void)pagerControllerDidEndScrolling:(TYPagerController *)pagerController animate:(BOOL)animate;
55 |
56 | @end
57 |
58 | @interface TYPagerController : UIViewController
59 |
60 | @property (nonatomic, weak, nullable) id dataSource;
61 | @property (nonatomic, weak, nullable) id delegate;
62 | // pagerController's layout,don't set layout's dataSource to other
63 | @property (nonatomic, strong, readonly) TYPagerViewLayout *layout;
64 | @property (nonatomic, weak, readonly) UIScrollView *scrollView;
65 |
66 | @property (nonatomic, assign, readonly) NSInteger countOfControllers;
67 | @property (nonatomic, assign, readonly) NSInteger curIndex;// default -1
68 |
69 | @property (nonatomic, strong, nullable, readonly) NSArray *visibleControllers;
70 |
71 | @property (nonatomic, assign) BOOL automaticallySystemManagerViewAppearanceMethods;// default YES.if YES system auto call view Appearance Methods(eg. viewWillAppear...)
72 |
73 | @property (nonatomic, assign) UIEdgeInsets contentInset;
74 |
75 | //if not visible, prefecth, cache view at index, return nil
76 | - (UIViewController *_Nullable)controllerForIndex:(NSInteger)index;
77 |
78 | // register && dequeue's usage like tableView
79 | - (void)registerClass:(Class)Class forControllerWithReuseIdentifier:(NSString *)identifier;
80 | - (void)registerNib:(UINib *)nib forControllerWithReuseIdentifier:(NSString *)identifier;
81 | - (UIViewController *)dequeueReusableControllerWithReuseIdentifier:(NSString *)identifier forIndex:(NSInteger)index;
82 |
83 | // scroll to index
84 | - (void)scrollToControllerAtIndex:(NSInteger)index animate:(BOOL)animate;
85 |
86 | // update data and layout,but don't reset propertys(curIndex,visibleDatas,prefechDatas)
87 | - (void)updateData;
88 |
89 | // reload data and reset propertys
90 | - (void)reloadData;
91 |
92 | @end
93 |
94 | NS_ASSUME_NONNULL_END
95 |
--------------------------------------------------------------------------------
/TYPagerControllerDemo/CustomViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // CustomViewController.m
3 | // TYPagerControllerDemo
4 | //
5 | // Created by tany on 16/4/20.
6 | // Copyright © 2016年 tanyang. All rights reserved.
7 | //
8 |
9 | #import "CustomViewController.h"
10 | #import "PagerControllerDmeoController.h"
11 |
12 | @interface CustomViewController ()
13 | @property (nonatomic, weak) UILabel *label;
14 | @property (nonatomic, weak) UIButton *pushBtn;
15 | @property (nonatomic, weak) UIButton *cancelBtn;
16 | @end
17 |
18 | @implementation CustomViewController
19 |
20 | - (void)viewDidLoad {
21 | [super viewDidLoad];
22 | // Do any additional setup after loading the view.
23 | //NSLog(@"text %@",_text);
24 | [self addPageLabel];
25 | [self addPushButton];
26 | [self addPopButton];
27 | }
28 |
29 | - (void)viewWillLayoutSubviews
30 | {
31 | [super viewWillLayoutSubviews];
32 | _label.center = CGPointMake(CGRectGetWidth(self.view.frame)/2, CGRectGetHeight(self.view.frame)/2);
33 | _cancelBtn.center = CGPointMake(_label.center.x,_label.center.y + 100);
34 | _pushBtn.center = CGPointMake(_label.center.x,_label.center.y + 50);
35 | }
36 |
37 | - (void)addPageLabel
38 | {
39 | UILabel *label = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, 200, 50)];
40 | label.text = _text;
41 | label.font = [UIFont systemFontOfSize:32];
42 | label.textAlignment = NSTextAlignmentCenter;
43 | [self.view addSubview:label];
44 | _label = label;
45 | self.view.backgroundColor = [UIColor colorWithRed:arc4random()%255/255.0 green:arc4random()%255/255.0 blue:arc4random()%255/255.0 alpha:arc4random()%255/255.0];
46 | }
47 |
48 | - (void)addPushButton
49 | {
50 | UIButton *cancelBtn = [UIButton buttonWithType:UIButtonTypeSystem];
51 | cancelBtn.titleLabel.font = [UIFont systemFontOfSize:21];
52 | [cancelBtn setTitle:@"posh VC" forState:UIControlStateNormal];
53 | [cancelBtn addTarget:self action:@selector(pushVC) forControlEvents:UIControlEventTouchUpInside];
54 | cancelBtn.frame = CGRectMake(0, 0, 100, 40);
55 | cancelBtn.center = CGPointMake(self.view.center.x, self.view.center.y + 60);
56 | [self.view addSubview:cancelBtn];
57 | _pushBtn = cancelBtn;
58 | }
59 |
60 | - (void)addPopButton
61 | {
62 | UIButton *cancelBtn = [UIButton buttonWithType:UIButtonTypeSystem];
63 | cancelBtn.titleLabel.font = [UIFont systemFontOfSize:21];
64 | [cancelBtn setTitle:@"pop back" forState:UIControlStateNormal];
65 | [cancelBtn addTarget:self action:@selector(popBack) forControlEvents:UIControlEventTouchUpInside];
66 | cancelBtn.frame = CGRectMake(0, 0, 100, 40);
67 | cancelBtn.center = CGPointMake(self.view.center.x, self.view.center.y + 60);
68 | [self.view addSubview:cancelBtn];
69 | _cancelBtn = cancelBtn;
70 | }
71 |
72 | - (void)viewWillAppear:(BOOL)animated
73 | {
74 | [super viewWillAppear:animated];
75 | NSLog(@"viewWillAppear index %@",_text);
76 | }
77 |
78 | - (void)viewDidAppear:(BOOL)animated
79 | {
80 | [super viewWillAppear:animated];
81 | NSLog(@"viewDidAppear index %@",_text);
82 | }
83 |
84 | - (void)viewWillDisappear:(BOOL)animated
85 | {
86 | [super viewWillDisappear:animated];
87 | NSLog(@"viewWillDisappear index %@",_text);
88 | }
89 |
90 | - (void)viewDidDisappear:(BOOL)animated
91 | {
92 | [super viewWillDisappear:animated];
93 | NSLog(@"viewDidDisappear index %@",_text);
94 | }
95 |
96 |
97 | - (void)pushVC {
98 | PagerControllerDmeoController *vc = [[PagerControllerDmeoController alloc]init];
99 | [self.navigationController pushViewController:vc animated:YES];
100 | }
101 |
102 | - (void)popBack
103 | {
104 | [self.navigationController popViewControllerAnimated:YES];
105 | }
106 |
107 | - (void)didReceiveMemoryWarning {
108 | [super didReceiveMemoryWarning];
109 | // Dispose of any resources that can be recreated.
110 | }
111 |
112 | /*
113 | #pragma mark - Navigation
114 |
115 | // In a storyboard-based application, you will often want to do a little preparation before navigation
116 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
117 | // Get the new view controller using [segue destinationViewController].
118 | // Pass the selected object to the new view controller.
119 | }
120 | */
121 |
122 | @end
123 |
--------------------------------------------------------------------------------
/TYPagerControllerDemo_swift/PagerControlerDemoController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PagerControlerDemoController.swift
3 | // TYPagerControllerDemo_swift
4 | //
5 | // Created by tany on 2017/7/19.
6 | // Copyright © 2017年 tany. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class PagerControlerDemoController: UIViewController {
12 |
13 | lazy var tabBar = TYTabPagerBar()
14 | lazy var pagerController = TYPagerController()
15 |
16 | lazy var datas = [String]()
17 |
18 | override func viewDidLoad() {
19 | super.viewDidLoad()
20 | // Do any additional setup after loading the view.
21 | self.view.backgroundColor = UIColor.white
22 | self.addTabPagerBar()
23 | self.addPagerController()
24 |
25 | self.loadData()
26 | }
27 |
28 | func addTabPagerBar() {
29 | self.tabBar.delegate = self
30 | self.tabBar.dataSource = self
31 | self.tabBar.register(TYTabPagerBarCell.classForCoder(), forCellWithReuseIdentifier: NSStringFromClass(TYTabPagerBarCell.classForCoder()))
32 | self.view.addSubview(self.tabBar)
33 | }
34 |
35 | func addPagerController() {
36 | self.pagerController.dataSource = self
37 | self.pagerController.delegate = self
38 | self.addChildViewController(self.pagerController)
39 | self.view.addSubview(self.pagerController.view)
40 | }
41 |
42 | override func viewWillLayoutSubviews() {
43 | super.viewWillLayoutSubviews()
44 | self.tabBar.frame = CGRect(x: 0, y: 64, width: self.view.frame.width, height: 40)
45 | self.pagerController.view.frame = CGRect(x: 0, y: self.tabBar.frame.maxY, width: self.view.frame.width, height: self.view.frame.height - self.tabBar.frame.maxY)
46 | }
47 |
48 | func loadData() {
49 | var i = 0
50 | while i < 20 {
51 | self.datas.append(i%2==0 ?"Tab \(i)":"Tab Tab \(i)")
52 | i += 1
53 | }
54 | self.reloadData()
55 | }
56 |
57 | func reloadData() {
58 | self.tabBar.reloadData()
59 | self.pagerController.reloadData()
60 | }
61 |
62 | override func didReceiveMemoryWarning() {
63 | super.didReceiveMemoryWarning()
64 | // Dispose of any resources that can be recreated.
65 | }
66 | }
67 |
68 | extension PagerControlerDemoController: TYTabPagerBarDataSource, TYTabPagerBarDelegate {
69 | func numberOfItemsInPagerTabBar() -> Int {
70 | return self.datas.count
71 | }
72 |
73 | func pagerTabBar(_ pagerTabBar: TYTabPagerBar, cellForItemAt index: Int) -> UICollectionViewCell {
74 | let cell = pagerTabBar.dequeueReusableCell(withReuseIdentifier: NSStringFromClass(TYTabPagerBarCell.classForCoder()), for: index)
75 | (cell as? TYTabPagerBarCellProtocol)?.titleLabel.text = self.datas[index]
76 | return cell
77 | }
78 |
79 | func pagerTabBar(_ pagerTabBar: TYTabPagerBar, widthForItemAt index: Int) -> CGFloat {
80 | let title = self.datas[index]
81 | return pagerTabBar.cellWidth(forTitle: title)
82 | }
83 |
84 | func pagerTabBar(_ pagerTabBar: TYTabPagerBar, didSelectItemAt index: Int) {
85 | self.pagerController.scrollToController(at: index, animate: true);
86 | }
87 | }
88 |
89 | extension PagerControlerDemoController: TYPagerControllerDataSource, TYPagerControllerDelegate {
90 | func numberOfControllersInPagerController() -> Int {
91 | return self.datas.count
92 | }
93 |
94 | func pagerController(_ pagerController: TYPagerController, controllerFor index: Int, prefetching: Bool) -> UIViewController {
95 | let vc = UIViewController()
96 | vc.view.backgroundColor = UIColor(red: CGFloat(arc4random()%255)/255.0, green: CGFloat(arc4random()%255)/255.0, blue: CGFloat(arc4random()%255)/255.0, alpha: 1)
97 | return vc
98 | }
99 |
100 | func pagerController(_ pagerController: TYPagerController, transitionFrom fromIndex: Int, to toIndex: Int, animated: Bool) {
101 | self.tabBar.scrollToItem(from: fromIndex, to: toIndex, animate: animated)
102 | }
103 | func pagerController(_ pagerController: TYPagerController, transitionFrom fromIndex: Int, to toIndex: Int, progress: CGFloat) {
104 | self.tabBar.scrollToItem(from: fromIndex, to: toIndex, progress: progress)
105 | }
106 | }
107 |
108 |
--------------------------------------------------------------------------------
/TYPagerControllerDemo.xcodeproj/xcuserdata/tany.xcuserdatad/xcschemes/TYPagerControllerDemo.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
33 |
39 |
40 |
41 |
42 |
43 |
49 |
50 |
51 |
52 |
53 |
54 |
64 |
66 |
72 |
73 |
74 |
75 |
76 |
77 |
83 |
85 |
91 |
92 |
93 |
94 |
96 |
97 |
100 |
101 |
102 |
--------------------------------------------------------------------------------
/TYPagerControllerDemo.xcodeproj/xcuserdata/tanyang.xcuserdatad/xcschemes/TYPagerControllerDemo.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
33 |
39 |
40 |
41 |
42 |
43 |
49 |
50 |
51 |
52 |
53 |
54 |
64 |
66 |
72 |
73 |
74 |
75 |
76 |
77 |
83 |
85 |
91 |
92 |
93 |
94 |
96 |
97 |
100 |
101 |
102 |
--------------------------------------------------------------------------------
/TYPagerControllerDemo/PagerControllerDmeoController.m:
--------------------------------------------------------------------------------
1 | //
2 | // PagerControllerDmeoController.m
3 | // TYPagerControllerDemo
4 | //
5 | // Created by tany on 2017/7/19.
6 | // Copyright © 2017年 tany. All rights reserved.
7 | //
8 |
9 | #import "PagerControllerDmeoController.h"
10 | #import "TYTabPagerBar.h"
11 | #import "TYPagerController.h"
12 | #import "ListViewController.h"
13 | #import "CollectionViewController.h"
14 | #import "CustomViewController.h"
15 |
16 | @interface PagerControllerDmeoController ()
17 |
18 | @property (nonatomic, weak) TYTabPagerBar *tabBar;
19 | @property (nonatomic, weak) TYPagerController *pagerController;
20 |
21 | @property (nonatomic, strong) NSArray *datas;
22 |
23 | @end
24 |
25 | @implementation PagerControllerDmeoController
26 |
27 | - (void)viewDidLoad {
28 | [super viewDidLoad];
29 | // Do any additional setup after loading the view.
30 | self.title = @"PagerControllerDmeoController";
31 | self.view.backgroundColor = [UIColor whiteColor];
32 |
33 | [self addTabPageBar];
34 |
35 | [self addPagerController];
36 |
37 | [self loadData];
38 | }
39 |
40 | - (void)addTabPageBar {
41 | TYTabPagerBar *tabBar = [[TYTabPagerBar alloc]init];
42 | tabBar.layout.barStyle = TYPagerBarStyleProgressElasticView;
43 | tabBar.dataSource = self;
44 | tabBar.delegate = self;
45 | [tabBar registerClass:[TYTabPagerBarCell class] forCellWithReuseIdentifier:[TYTabPagerBarCell cellIdentifier]];
46 | [self.view addSubview:tabBar];
47 | _tabBar = tabBar;
48 | }
49 |
50 | - (void)addPagerController {
51 | TYPagerController *pagerController = [[TYPagerController alloc]init];
52 | pagerController.layout.prefetchItemCount = 1;
53 | //pagerController.layout.autoMemoryCache = NO;
54 | // 只有当scroll滚动动画停止时才加载pagerview,用于优化滚动时性能
55 | pagerController.layout.addVisibleItemOnlyWhenScrollAnimatedEnd = YES;
56 | pagerController.dataSource = self;
57 | pagerController.delegate = self;
58 | [self addChildViewController:pagerController];
59 | [self.view addSubview:pagerController.view];
60 | _pagerController = pagerController;
61 | }
62 |
63 | - (void)viewWillAppear:(BOOL)animated {
64 | [super viewWillAppear:animated];
65 | }
66 |
67 | - (void)viewWillDisappear:(BOOL)animated {
68 | [super viewWillDisappear:animated];
69 | }
70 |
71 | - (void)viewWillLayoutSubviews {
72 | [super viewWillLayoutSubviews];
73 | _tabBar.frame = CGRectMake(0, CGRectGetMaxY(self.navigationController.navigationBar.frame), CGRectGetWidth(self.view.frame), 36);
74 | _pagerController.view.frame = CGRectMake(0, CGRectGetMaxY(_tabBar.frame), CGRectGetWidth(self.view.frame), CGRectGetHeight(self.view.frame)- CGRectGetMaxY(_tabBar.frame));
75 | }
76 |
77 | - (void)loadData {
78 | NSMutableArray *datas = [NSMutableArray array];
79 | for (NSInteger i = 0; i < 20; ++i) {
80 | [datas addObject:i%2 == 0 ? [NSString stringWithFormat:@"Tab %ld",i]:[NSString stringWithFormat:@"Tab Tab %ld",i]];
81 | }
82 | _datas = [datas copy];
83 |
84 | [self reloadData];
85 | }
86 |
87 | #pragma mark - TYTabPagerBarDataSource
88 |
89 | - (NSInteger)numberOfItemsInPagerTabBar {
90 | return _datas.count;
91 | }
92 |
93 | - (UICollectionViewCell *)pagerTabBar:(TYTabPagerBar *)pagerTabBar cellForItemAtIndex:(NSInteger)index {
94 | UICollectionViewCell *cell = [pagerTabBar dequeueReusableCellWithReuseIdentifier:[TYTabPagerBarCell cellIdentifier] forIndex:index];
95 | cell.titleLabel.text = _datas[index];
96 | return cell;
97 | }
98 |
99 | #pragma mark - TYTabPagerBarDelegate
100 |
101 | - (CGFloat)pagerTabBar:(TYTabPagerBar *)pagerTabBar widthForItemAtIndex:(NSInteger)index {
102 | NSString *title = _datas[index];
103 | return [pagerTabBar cellWidthForTitle:title];
104 | }
105 |
106 | - (void)pagerTabBar:(TYTabPagerBar *)pagerTabBar didSelectItemAtIndex:(NSInteger)index {
107 | [_pagerController scrollToControllerAtIndex:index animate:YES];
108 | }
109 |
110 | #pragma mark - TYPagerControllerDataSource
111 |
112 | - (NSInteger)numberOfControllersInPagerController {
113 | return 20;
114 | }
115 |
116 | - (UIViewController *)pagerController:(TYPagerController *)pagerController controllerForIndex:(NSInteger)index prefetching:(BOOL)prefetching {
117 | if (index%3 == 0) {
118 | CustomViewController *VC = [[CustomViewController alloc]init];
119 | VC.text = [@(index) stringValue];
120 | return VC;
121 | }else if (index%3 == 1) {
122 | ListViewController *VC = [[ListViewController alloc]init];
123 | VC.text = [@(index) stringValue];
124 | return VC;
125 | }else {
126 | CollectionViewController *VC = [[CollectionViewController alloc]init];
127 | VC.text = [@(index) stringValue];
128 | return VC;
129 | }
130 | }
131 |
132 | #pragma mark - TYPagerControllerDelegate
133 |
134 | - (void)pagerController:(TYPagerController *)pagerController transitionFromIndex:(NSInteger)fromIndex toIndex:(NSInteger)toIndex animated:(BOOL)animated {
135 | [_tabBar scrollToItemFromIndex:fromIndex toIndex:toIndex animate:animated];
136 | }
137 |
138 | -(void)pagerController:(TYPagerController *)pagerController transitionFromIndex:(NSInteger)fromIndex toIndex:(NSInteger)toIndex progress:(CGFloat)progress {
139 | [_tabBar scrollToItemFromIndex:fromIndex toIndex:toIndex progress:progress];
140 | }
141 |
142 | - (void)reloadData {
143 | [_tabBar reloadData];
144 | [_pagerController reloadData];
145 | }
146 |
147 | - (void)didReceiveMemoryWarning {
148 | [super didReceiveMemoryWarning];
149 | // Dispose of any resources that can be recreated.
150 | }
151 | @end
152 |
--------------------------------------------------------------------------------
/TYPagerControllerDemo_swift/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
31 |
38 |
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 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
--------------------------------------------------------------------------------
/TYPagerControllerDemo/TYPagerController/TYPagerViewLayout.h:
--------------------------------------------------------------------------------
1 | //
2 | // TYPagerViewLayout.h
3 | // TYPagerControllerDemo
4 | //
5 | // Created by tanyang on 2017/7/9.
6 | // Copyright © 2017年 tany. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | NS_ASSUME_NONNULL_BEGIN
12 |
13 | @interface NSObject (TY_PagerReuseIdentify)
14 | // resueId
15 | @property (nonatomic, strong, readonly, nullable) NSString *ty_pagerReuseIdentify;
16 |
17 | @end
18 |
19 | @class TYPagerViewLayout;
20 | @protocol TYPagerViewLayoutDataSource
21 |
22 | - (NSInteger)numberOfItemsInPagerViewLayout;
23 |
24 | // if item is preload, prefetch will YES
25 | - (id)pagerViewLayout:(TYPagerViewLayout *)pagerViewLayout itemForIndex:(NSInteger)index prefetching:(BOOL)prefetching;
26 |
27 | // return item's view
28 | - (UIView *)pagerViewLayout:(TYPagerViewLayout *)pagerViewLayout viewForItem:(id)item atIndex:(NSInteger)index;
29 |
30 | // see TYPagerView&&TYPagerController, add&&remove item ,must implement scrollView addSubView item's view
31 | - (void)pagerViewLayout:(TYPagerViewLayout *)pagerViewLayout addVisibleItem:(id)item atIndex:(NSInteger)index;
32 | - (void)pagerViewLayout:(TYPagerViewLayout *)pagerViewLayout removeInVisibleItem:(id)item atIndex:(NSInteger)index;
33 |
34 | @optional
35 |
36 | // if have not viewController return nil.
37 | - (UIViewController *)pagerViewLayout:(TYPagerViewLayout *)pagerViewLayout viewControllerForItem:(id)item atIndex:(NSInteger)index;
38 |
39 | @end
40 |
41 | @protocol TYPagerViewLayoutDelegate
42 |
43 | @optional
44 |
45 | // Transition animation customization
46 |
47 | // if you implement ↓↓↓transitionFromIndex:toIndex:progress:,only tap change index will call this, you can set progressAnimateEnabel NO that not call progress method
48 | - (void)pagerViewLayout:(TYPagerViewLayout *)pagerViewLayout transitionFromIndex:(NSInteger)fromIndex toIndex:(NSInteger)toIndex animated:(BOOL)animated;
49 |
50 | // if you implement the method,also you need implement ↑↑↑transitionFromIndex:toIndex:animated:,deal with tap change index animate
51 | - (void)pagerViewLayout:(TYPagerViewLayout *)pagerViewLayout transitionFromIndex:(NSInteger)fromIndex toIndex:(NSInteger)toIndex progress:(CGFloat)progress;
52 |
53 | // ScrollViewDelegate
54 |
55 | - (void)pagerViewLayoutDidScroll:(TYPagerViewLayout *)pagerViewLayout;
56 | - (void)pagerViewLayoutWillBeginScrollToView:(TYPagerViewLayout *)pagerViewLayout animate:(BOOL)animate;
57 | - (void)pagerViewLayoutDidEndScrollToView:(TYPagerViewLayout *)pagerViewLayout animate:(BOOL)animate;
58 | - (void)pagerViewLayoutWillBeginDragging:(TYPagerViewLayout *)pagerViewLayout;
59 | - (void)pagerViewLayoutDidEndDragging:(TYPagerViewLayout *)pagerViewLayout willDecelerate:(BOOL)decelerate;
60 | - (void)pagerViewLayoutWillBeginDecelerating:(TYPagerViewLayout *)pagerViewLayout;
61 | - (void)pagerViewLayoutDidEndDecelerating:(TYPagerViewLayout *)pagerViewLayout;
62 | - (void)pagerViewLayoutDidEndScrollingAnimation:(TYPagerViewLayout *)pagerViewLayout;
63 |
64 | @end
65 |
66 | @interface TYPagerViewLayout<__covariant ItemType> : NSObject
67 |
68 | @property (nonatomic, weak, nullable) id dataSource;
69 | @property (nonatomic, weak, nullable) id delegate;
70 |
71 | // strong,will control the delegate,don't set delegate on other place.
72 | @property (nonatomic, strong, readonly) UIScrollView *scrollView;
73 | // if viewcontroller's automaticallyAdjustsScrollViewInsets YES ,will cause frame problems, you can set YES, default YES
74 | @property (nonatomic, assign) BOOL adjustScrollViewInset;
75 |
76 | @property (nonatomic, assign, readonly) NSInteger countOfPagerItems;
77 | @property (nonatomic, assign, readonly) NSInteger curIndex;// default -1
78 |
79 | @property (nonatomic, strong, readonly) NSCache *memoryCache;; // will cache pagerView,you can set countLimit
80 | @property (nonatomic, assign) BOOL autoMemoryCache; // default YES
81 |
82 | @property (nonatomic, assign) NSInteger prefetchItemCount;// preload left and right item's count , default 0
83 | // because when superview add subview(have tableView) will call relodData,if set Yes will optimize. default NO
84 | @property (nonatomic, assign) BOOL prefetchItemWillAddToSuperView;
85 |
86 | @property (nonatomic, assign, readonly) NSRange prefetchRange;
87 | @property (nonatomic, assign, readonly) NSRange visibleRange;
88 |
89 | @property (nonatomic, strong, nullable, readonly) NSArray * visibleIndexs;
90 | @property (nonatomic, strong, nullable, readonly) NSArray * visibleItems;
91 |
92 | // default YES, if NO,will not call delegate transitionFromIndex:toIndex:progress:,but will call transitionFromIndex:toIndex:
93 | @property (nonatomic, assign) BOOL progressAnimateEnabel;
94 |
95 | // default NO, when scroll visible range change will add item.If YES add item only when scroll animate end, suggest set prefetchItemCount 1 or more
96 | @property (nonatomic, assign) BOOL addVisibleItemOnlyWhenScrollAnimatedEnd;
97 |
98 | // default 0.5,when scroll progress percent will change index, only progressAnimateEnabel is NO or don't implement delegate transitionFromIndex: toIndex: progress:
99 | @property (nonatomic, assign) CGFloat changeIndexWhenScrollProgress;
100 |
101 | - (instancetype)init NS_UNAVAILABLE;
102 | + (instancetype)new NS_UNAVAILABLE;
103 |
104 | /**
105 | initializer will strong scrollView,and control delegate,don't set delegate on other place.
106 | */
107 | - (instancetype)initWithScrollView:(UIScrollView *)scrollView NS_DESIGNATED_INITIALIZER; // strong scrollView
108 |
109 | - (ItemType _Nullable)itemForIndex:(NSInteger)idx;
110 |
111 | - (UIView *)viewForItem:(ItemType)item atIndex:(NSInteger)index;
112 | // if have not viewController return nil.
113 | - (UIViewController *_Nullable)viewControllerForItem:(id)item atIndex:(NSInteger)index;
114 |
115 | // view's frame at index
116 | - (CGRect)frameForItemAtIndex:(NSInteger)index;
117 |
118 | // register && dequeue's usage like tableView
119 | - (void)registerClass:(Class)Class forItemWithReuseIdentifier:(NSString *)identifier;
120 | - (void)registerNib:(UINib *)nib forItemWithReuseIdentifier:(NSString *)identifier;
121 | - (ItemType)dequeueReusableItemWithReuseIdentifier:(NSString *)identifier forIndex:(NSInteger)index;
122 |
123 | // scroll to index
124 | - (void)scrollToItemAtIndex:(NSInteger)index animate:(BOOL)animate;
125 |
126 | // update data and layout,the same to relaodData,but don't reset propertys(curIndex,visibleDatas,prefechDatas)
127 | - (void)updateData;
128 |
129 | // reload data and reset propertys
130 | - (void)reloadData;
131 |
132 | @end
133 |
134 | NS_ASSUME_NONNULL_END
135 |
--------------------------------------------------------------------------------
/TYPagerControllerDemo/PagerViewDmeoController.m:
--------------------------------------------------------------------------------
1 | //
2 | // PagerViewDmeoController.m
3 | // TYPagerControllerDemo
4 | //
5 | // Created by tanyang on 2017/7/6.
6 | // Copyright © 2017年 tany. All rights reserved.
7 | //
8 |
9 | #import "PagerViewDmeoController.h"
10 | #import "TYPagerView.h"
11 | #import "TYTabPagerBar.h"
12 |
13 | @interface PagerViewDmeoController ()
14 | @property (nonatomic, weak) TYTabPagerBar *tabBar;
15 | @property (nonatomic, weak) TYPagerView *pageView;
16 |
17 | @property (nonatomic, strong) NSArray *datas;
18 |
19 | @end
20 |
21 | @implementation PagerViewDmeoController
22 |
23 | - (void)viewDidLoad {
24 | [super viewDidLoad];
25 | // Do any additional setup after loading the view.
26 | //self.automaticallyAdjustsScrollViewInsets = NO;
27 | self.view.backgroundColor = [UIColor whiteColor];
28 | UIBarButtonItem *reloadItem = [[UIBarButtonItem alloc]initWithTitle:@"reload" style:UIBarButtonItemStylePlain target:self action:@selector(reloadData)];
29 | UIBarButtonItem *scrollItem = [[UIBarButtonItem alloc]initWithTitle:@"update" style:UIBarButtonItemStylePlain target:self action:@selector(updateData)];
30 | self.navigationItem.rightBarButtonItems = @[reloadItem,scrollItem];
31 | [self addPagerTabBar];
32 | [self addPagerView];
33 |
34 | [self loadData];
35 | }
36 |
37 | - (void)addPagerTabBar {
38 | TYTabPagerBar *tabBar = [[TYTabPagerBar alloc]init];
39 | tabBar.layout.barStyle = TYPagerBarStyleProgressElasticView;
40 | tabBar.dataSource = self;
41 | tabBar.delegate = self;
42 | [tabBar registerClass:[TYTabPagerBarCell class] forCellWithReuseIdentifier:[TYTabPagerBarCell cellIdentifier]];
43 | [self.view addSubview:tabBar];
44 | _tabBar = tabBar;
45 | }
46 |
47 | - (void)addPagerView {
48 | TYPagerView *pageView = [[TYPagerView alloc]init];
49 | //pageView.layout.progressAnimateEnabel = NO;
50 | //pageView.layout.prefetchItemCount = 1;
51 | pageView.layout.autoMemoryCache = NO;
52 | pageView.dataSource = self;
53 | pageView.delegate = self;
54 | // you can rigsiter cell like tableView
55 | [pageView.layout registerClass:[UIView class] forItemWithReuseIdentifier:@"cellId"];
56 | [self.view addSubview:pageView];
57 | _pageView = pageView;
58 | }
59 |
60 | - (void)loadData {
61 | NSMutableArray *datas = [NSMutableArray array];
62 | for (NSInteger i = 0; i < 10; ++i) {
63 | [datas addObject:i%2 == 0 ? [NSString stringWithFormat:@"Tab %ld",i]:[NSString stringWithFormat:@"Tab Tab %ld",i]];
64 | }
65 | _datas = [datas copy];
66 |
67 | [self reloadData];
68 | }
69 |
70 | - (void)updateData {
71 | NSMutableArray *datas = [NSMutableArray array];
72 | for (NSInteger i = 0; i *)pagerTabBar:(TYTabPagerBar *)pagerTabBar cellForItemAtIndex:(NSInteger)index {
100 | UICollectionViewCell *cell = [pagerTabBar dequeueReusableCellWithReuseIdentifier:[TYTabPagerBarCell cellIdentifier] forIndex:index];
101 | cell.titleLabel.text = _datas[index];
102 | return cell;
103 | }
104 |
105 | #pragma mark - TYTabPagerBarDelegate
106 |
107 | - (CGFloat)pagerTabBar:(TYTabPagerBar *)pagerTabBar widthForItemAtIndex:(NSInteger)index {
108 | NSString *title = _datas[index];
109 | return [pagerTabBar cellWidthForTitle:title];
110 | }
111 |
112 | - (void)pagerTabBar:(TYTabPagerBar *)pagerTabBar didSelectItemAtIndex:(NSInteger)index {
113 | [_pageView scrollToViewAtIndex:index animate:YES];
114 | }
115 |
116 | #pragma mark - TYPagerViewDataSource
117 |
118 | - (NSInteger)numberOfViewsInPagerView {
119 | return _datas.count;
120 | }
121 |
122 | - (UIView *)pagerView:(TYPagerView *)pagerView viewForIndex:(NSInteger)index prefetching:(BOOL)prefetching {
123 | //you can set UIView *view = [[UIView alloc]initWithFrame:[pagerView.layout frameForItemAtIndex:index]]; or UIView *view = [[UIView alloc]init];
124 | //or reigster and dequeue item like tableView
125 | UIView *view = [pagerView.layout dequeueReusableItemWithReuseIdentifier:@"cellId" forIndex:index];
126 | view.backgroundColor = [UIColor colorWithRed:arc4random()%255/255.0 green:arc4random()%255/255.0 blue:arc4random()%255/255.0 alpha:arc4random()%255/255.0];
127 | //NSLog(@"viewForIndex:%ld prefetching:%d",index,prefetching);
128 | return view;
129 | }
130 |
131 | #pragma mark - TYPagerViewDelegate
132 |
133 | - (void)pagerView:(TYPagerView *)pagerView willAppearView:(UIView *)view forIndex:(NSInteger)index {
134 | //NSLog(@"+++++++++willAppearViewIndex:%ld",index);
135 | }
136 |
137 | - (void)pagerView:(TYPagerView *)pagerView willDisappearView:(UIView *)view forIndex:(NSInteger)index {
138 | //NSLog(@"---------willDisappearView:%ld",index);
139 | }
140 |
141 | - (void)pagerView:(TYPagerView *)pagerView transitionFromIndex:(NSInteger)fromIndex toIndex:(NSInteger)toIndex animated:(BOOL)animated {
142 | NSLog(@"fromIndex:%ld, toIndex:%ld",fromIndex,toIndex);
143 | [_tabBar scrollToItemFromIndex:fromIndex toIndex:toIndex animate:animated];
144 | }
145 |
146 | - (void)pagerView:(TYPagerView *)pagerView transitionFromIndex:(NSInteger)fromIndex toIndex:(NSInteger)toIndex progress:(CGFloat)progress {
147 | //NSLog(@"fromIndex:%ld, toIndex:%ld progress%.3f",fromIndex,toIndex,progress);
148 | [_tabBar scrollToItemFromIndex:fromIndex toIndex:toIndex progress:progress];
149 | }
150 |
151 | - (void)pagerViewWillBeginScrolling:(TYPagerView *)pageView animate:(BOOL)animate {
152 | //NSLog(@"pagerViewWillBeginScrolling");
153 | }
154 |
155 | - (void)pagerViewDidEndScrolling:(TYPagerView *)pageView animate:(BOOL)animate {
156 | //NSLog(@"pagerViewDidEndScrolling");
157 | }
158 |
159 | - (void)didReceiveMemoryWarning {
160 | [super didReceiveMemoryWarning];
161 | // Dispose of any resources that can be recreated.
162 | }
163 |
164 | /*
165 | #pragma mark - Navigation
166 |
167 | // In a storyboard-based application, you will often want to do a little preparation before navigation
168 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
169 | // Get the new view controller using [segue destinationViewController].
170 | // Pass the selected object to the new view controller.
171 | }
172 | */
173 |
174 | @end
175 |
--------------------------------------------------------------------------------
/TYPagerControllerDemo/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
31 |
38 |
45 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
--------------------------------------------------------------------------------
/TYPagerControllerDemo/TYPagerController/TabPager/TYTabPagerView.m:
--------------------------------------------------------------------------------
1 | //
2 | // TYTabPagerView.m
3 | // TYPagerControllerDemo
4 | //
5 | // Created by tanyang on 2017/7/18.
6 | // Copyright © 2017年 tany. All rights reserved.
7 | //
8 |
9 | #import "TYTabPagerView.h"
10 |
11 | @interface TYTabPagerView ()
12 |
13 | // UI
14 | @property (nonatomic, weak) TYTabPagerBar *tabBar;
15 | @property (nonatomic, weak) TYPagerView *pageView;
16 |
17 | // Data
18 | @property (nonatomic, strong) NSString *identifier;
19 |
20 | @end
21 |
22 | @implementation TYTabPagerView
23 |
24 | - (instancetype)initWithFrame:(CGRect)frame {
25 | if (self = [super initWithFrame:frame]) {
26 | _tabBarHeight = 36;
27 | self.backgroundColor = [UIColor clearColor];
28 | [self addTabBar];
29 |
30 | [self addPagerView];
31 | }
32 | return self;
33 | }
34 |
35 | - (instancetype)initWithCoder:(NSCoder *)aDecoder {
36 | if (self = [super initWithCoder:aDecoder]) {
37 | _tabBarHeight = 36;
38 | self.backgroundColor = [UIColor clearColor];
39 | [self addTabBar];
40 |
41 | [self addPagerView];
42 | }
43 | return self;
44 | }
45 |
46 | - (void)addTabBar {
47 | TYTabPagerBar *tabBar = [[TYTabPagerBar alloc]initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.frame), _tabBarHeight)];
48 | tabBar.dataSource = self;
49 | tabBar.delegate = self;
50 | [self addSubview:tabBar];
51 | _tabBar = tabBar;
52 | [self registerClass:[TYTabPagerBarCell class] forTabBarCellWithReuseIdentifier:[TYTabPagerBarCell cellIdentifier]];
53 | }
54 |
55 | - (void)addPagerView {
56 | TYPagerView *pageView = [[TYPagerView alloc]initWithFrame:CGRectMake(0, _tabBarHeight, CGRectGetWidth(self.frame), MAX(CGRectGetHeight(self.frame) - _tabBarHeight, 0))];
57 | pageView.dataSource = self;
58 | pageView.delegate = self;
59 | [self addSubview:pageView];
60 | _pageView = pageView;
61 | }
62 |
63 | #pragma mark - getter setter
64 |
65 | - (void)setTabBarHeight:(CGFloat)tabBarHeight {
66 | BOOL isChangeValue = _tabBarHeight != tabBarHeight;
67 | _tabBarHeight = tabBarHeight;
68 | if (isChangeValue && self.superview && !CGRectEqualToRect(self.bounds, CGRectZero)) {
69 | [self setNeedsLayout];
70 | [self layoutIfNeeded];
71 | }
72 | }
73 |
74 | - (TYPagerViewLayout *)layout {
75 | return _pageView.layout;
76 | }
77 |
78 | #pragma mark - public
79 |
80 | - (void)updateData {
81 | [_tabBar reloadData];
82 | [_pageView updateData];
83 | }
84 |
85 | - (void)reloadData {
86 | [_tabBar reloadData];
87 | [_pageView reloadData];
88 | }
89 |
90 | // scroll to index
91 | - (void)scrollToViewAtIndex:(NSInteger)index animate:(BOOL)animate {
92 | [_pageView scrollToViewAtIndex:index animate:animate];
93 | }
94 |
95 | - (void)registerClass:(Class)Class forTabBarCellWithReuseIdentifier:(NSString *)identifier {
96 | _identifier = identifier;
97 | [_tabBar registerClass:Class forCellWithReuseIdentifier:identifier];
98 | }
99 | - (void)registerNib:(UINib *)nib forTabBarCellWithReuseIdentifier:(NSString *)identifier {
100 | _identifier = identifier;
101 | [_tabBar registerNib:nib forCellWithReuseIdentifier:identifier];
102 | }
103 |
104 | - (void)registerClass:(Class)Class forPagerCellWithReuseIdentifier:(NSString *)identifier {
105 | [_pageView registerClass:Class forViewWithReuseIdentifier:identifier];
106 | }
107 | - (void)registerNib:(UINib *)nib forPagerCellWithReuseIdentifier:(NSString *)identifier {
108 | [_pageView registerNib:nib forViewWithReuseIdentifier:identifier];
109 | }
110 | - (UIView *)dequeueReusablePagerCellWithReuseIdentifier:(NSString *)identifier forIndex:(NSInteger)index {
111 | return [_pageView dequeueReusableViewWithReuseIdentifier:identifier forIndex:index];
112 | }
113 |
114 | #pragma mark - TYTabPagerBarDataSource
115 |
116 | - (NSInteger)numberOfItemsInPagerTabBar {
117 | return [_dataSource numberOfViewsInTabPagerView];
118 | }
119 |
120 | - (UICollectionViewCell *)pagerTabBar:(TYTabPagerBar *)pagerTabBar cellForItemAtIndex:(NSInteger)index {
121 | UICollectionViewCell *cell = [pagerTabBar dequeueReusableCellWithReuseIdentifier:_identifier forIndex:index];
122 | cell.titleLabel.text = [_dataSource tabPagerView:self titleForIndex:index];
123 | if ([_delegate respondsToSelector:@selector(tabPagerView:willDisplayCell:atIndex:)]) {
124 | [_delegate tabPagerView:self willDisplayCell:cell atIndex:index];
125 | }
126 | return cell;
127 | }
128 |
129 | #pragma mark - TYTabPagerBarDelegate
130 |
131 | - (CGFloat)pagerTabBar:(TYTabPagerBar *)pagerTabBar widthForItemAtIndex:(NSInteger)index {
132 | NSString *title = [_dataSource tabPagerView:self titleForIndex:index];
133 | return [pagerTabBar cellWidthForTitle:title];
134 | }
135 |
136 | - (void)pagerTabBar:(TYTabPagerBar *)pagerTabBar didSelectItemAtIndex:(NSInteger)index {
137 | [_pageView scrollToViewAtIndex:index animate:YES];
138 | if ([_delegate respondsToSelector:@selector(tabPagerView:didSelectTabBarItemAtIndex:)]) {
139 | [_delegate tabPagerView:self didSelectTabBarItemAtIndex:index];
140 | }
141 | }
142 |
143 | #pragma mark - TYPagerViewDataSource
144 |
145 | - (NSInteger)numberOfViewsInPagerView {
146 | return [_dataSource numberOfViewsInTabPagerView];
147 | }
148 |
149 | - (UIView *)pagerView:(TYPagerView *)pagerView viewForIndex:(NSInteger)index prefetching:(BOOL)prefetching {
150 | UIView *view = [_dataSource tabPagerView:self viewForIndex:index prefetching:prefetching];
151 | return view;
152 | }
153 |
154 | #pragma mark - TYPagerViewDelegate
155 |
156 | - (void)pagerView:(TYPagerView *)pagerView transitionFromIndex:(NSInteger)fromIndex toIndex:(NSInteger)toIndex animated:(BOOL)animated {
157 | [_tabBar scrollToItemFromIndex:fromIndex toIndex:toIndex animate:animated];
158 | }
159 |
160 | - (void)pagerView:(TYPagerView *)pagerView transitionFromIndex:(NSInteger)fromIndex toIndex:(NSInteger)toIndex progress:(CGFloat)progress {
161 | [_tabBar scrollToItemFromIndex:fromIndex toIndex:toIndex progress:progress];
162 | }
163 |
164 | - (void)pagerView:(TYPagerView *)pagerView willAppearView:(UIView *)view forIndex:(NSInteger)index {
165 | if ([_delegate respondsToSelector:@selector(tabPagerView:willAppearView:forIndex:)]) {
166 | [_delegate tabPagerView:self willAppearView:view forIndex:index];
167 | }
168 | }
169 |
170 | - (void)pagerView:(TYPagerView *)pagerView didDisappearView:(UIView *)view forIndex:(NSInteger)index {
171 | if ([_delegate respondsToSelector:@selector(tabPagerView:didDisappearView:forIndex:)]) {
172 | [_delegate tabPagerView:self didDisappearView:view forIndex:index];
173 | }
174 | }
175 |
176 | - (void)pagerViewWillBeginScrolling:(TYPagerView *)pageView animate:(BOOL)animate {
177 | if ([_delegate respondsToSelector:@selector(tabPagerViewWillBeginScrolling:animate:)]) {
178 | [_delegate tabPagerViewWillBeginScrolling:self animate:animate];
179 | }
180 | }
181 |
182 | - (void)pagerViewDidEndScrolling:(TYPagerView *)pageView animate:(BOOL)animate {
183 | if ([_delegate respondsToSelector:@selector(tabPagerViewDidEndScrolling:animate:)]) {
184 | [_delegate tabPagerViewDidEndScrolling:self animate:animate];
185 | }
186 | }
187 |
188 | - (void)layoutSubviews {
189 | [super layoutSubviews];
190 | _tabBar.frame = CGRectMake(0, 0, CGRectGetWidth(self.frame), _tabBarHeight);
191 | _pageView.frame = CGRectMake(0, _tabBarHeight, CGRectGetWidth(self.frame), CGRectGetHeight(self.frame) - _tabBarHeight);
192 | }
193 |
194 | @end
195 |
--------------------------------------------------------------------------------
/TYPagerControllerDemo/TYPagerController/TabPager/TYTabPagerController.m:
--------------------------------------------------------------------------------
1 | //
2 | // TYTabPagerController.m
3 | // TYPagerControllerDemo
4 | //
5 | // Created by tanyang on 2017/7/18.
6 | // Copyright © 2017年 tany. All rights reserved.
7 | //
8 |
9 | #import "TYTabPagerController.h"
10 |
11 | @interface TYTabPagerController ()
12 |
13 | // UI
14 | @property (nonatomic, strong) TYTabPagerBar *tabBar;
15 | @property (nonatomic, strong) TYPagerController *pagerController;
16 |
17 | // Data
18 | @property (nonatomic, strong) NSString *identifier;
19 |
20 | @end
21 |
22 | #define kTabBarOrignY -999999
23 |
24 | @implementation TYTabPagerController
25 |
26 | - (instancetype)initWithCoder:(NSCoder *)aDecoder {
27 | if (self = [super initWithCoder:aDecoder]) {
28 | _tabBarHeight = 36;
29 | _tabBarOrignY = kTabBarOrignY;
30 | }
31 | return self;
32 | }
33 |
34 | - (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
35 | if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
36 | _tabBarHeight = 36;
37 | _tabBarOrignY = kTabBarOrignY;
38 | }
39 | return self;
40 | }
41 |
42 | - (void)viewDidLoad {
43 | [super viewDidLoad];
44 | // Do any additional setup after loading the view.
45 | self.view.backgroundColor = [UIColor whiteColor];
46 |
47 | [self addTabBar];
48 |
49 | [self addPagerController];
50 | }
51 |
52 | - (void)addTabBar {
53 | self.tabBar.dataSource = self;
54 | self.tabBar.delegate = self;
55 | [self registerClass:[TYTabPagerBarCell class] forTabBarCellWithReuseIdentifier:[TYTabPagerBarCell cellIdentifier]];
56 | [self.view addSubview:self.tabBar];;
57 | }
58 |
59 | - (void)addPagerController {
60 | self.pagerController.dataSource = self;
61 | self.pagerController.delegate = self;
62 | [self addChildViewController:self.pagerController];
63 | [self.view addSubview:self.pagerController.view];
64 | }
65 |
66 | - (void)viewWillLayoutSubviews {
67 | [super viewWillLayoutSubviews];
68 | CGFloat orignY = [self fixedTabBarOriginY];
69 | self.tabBar.frame = CGRectMake(0, orignY, CGRectGetWidth(self.view.frame), _tabBarHeight);
70 | self.pagerController.view.frame = CGRectMake(0, orignY+_tabBarHeight, CGRectGetWidth(self.view.frame), CGRectGetHeight(self.view.frame) - _tabBarHeight-orignY);
71 | }
72 |
73 | - (CGFloat)fixedTabBarOriginY {
74 | if (_tabBarOrignY > kTabBarOrignY) {
75 | return _tabBarOrignY;
76 | }
77 | if (!self.navigationController || self.parentViewController != self.navigationController) {
78 | return 0;
79 | }
80 | if (self.navigationController.navigationBarHidden || !(self.edgesForExtendedLayout&UIRectEdgeTop)) {
81 | return 0;
82 | }
83 | return CGRectGetMaxY(self.navigationController.navigationBar.frame);
84 | }
85 |
86 | #pragma mark - getter setter
87 |
88 | - (TYTabPagerBar *)tabBar {
89 | if (!_tabBar) {
90 | _tabBar = [[TYTabPagerBar alloc]init];
91 | }
92 | return _tabBar;
93 | }
94 |
95 | - (void)setTabBarOrignY:(CGFloat)tabBarOrignY {
96 | BOOL isChangeValue = _tabBarOrignY != tabBarOrignY;
97 | _tabBarOrignY = tabBarOrignY;
98 | if (isChangeValue && _tabBar.superview) {
99 | [self.view layoutIfNeeded];
100 | }
101 | }
102 |
103 | - (void)setTabBarHeight:(CGFloat)tabBarHeight {
104 | BOOL isChangeValue = _tabBarHeight != tabBarHeight;
105 | _tabBarHeight = tabBarHeight;
106 | if (isChangeValue && _tabBar.superview) {
107 | [self.view layoutIfNeeded];
108 | }
109 | }
110 |
111 | - (TYPagerController *)pagerController {
112 | if (!_pagerController) {
113 | _pagerController = [[TYPagerController alloc]init];
114 | }
115 | return _pagerController;
116 | }
117 |
118 | - (TYPagerViewLayout *)layout {
119 | return self.pagerController.layout;
120 | }
121 |
122 | #pragma mark - public
123 |
124 | - (void)updateData {
125 | [self.tabBar reloadData];
126 | [self.pagerController updateData];
127 | }
128 |
129 | - (void)reloadData {
130 | [self.tabBar reloadData];
131 | [self.pagerController reloadData];
132 | }
133 |
134 | - (void)scrollToControllerAtIndex:(NSInteger)index animate:(BOOL)animate {
135 | [self.pagerController scrollToControllerAtIndex:index animate:animate];
136 | }
137 |
138 | - (void)registerClass:(Class)Class forTabBarCellWithReuseIdentifier:(NSString *)identifier {
139 | _identifier = identifier;
140 | [self.tabBar registerClass:Class forCellWithReuseIdentifier:identifier];
141 | }
142 | - (void)registerNib:(UINib *)nib forTabBarCellWithReuseIdentifier:(NSString *)identifier {
143 | _identifier = identifier;
144 | [self.tabBar registerNib:nib forCellWithReuseIdentifier:identifier];
145 | }
146 |
147 | - (void)registerClass:(Class)Class forPagerCellWithReuseIdentifier:(NSString *)identifier {
148 | [_pagerController registerClass:Class forControllerWithReuseIdentifier:identifier];
149 | }
150 | - (void)registerNib:(UINib *)nib forPagerCellWithReuseIdentifier:(NSString *)identifier {
151 | [_pagerController registerNib:nib forControllerWithReuseIdentifier:identifier];
152 | }
153 | - (UIViewController *)dequeueReusablePagerCellWithReuseIdentifier:(NSString *)identifier forIndex:(NSInteger)index {
154 | return [_pagerController dequeueReusableControllerWithReuseIdentifier:identifier forIndex:index];
155 | }
156 |
157 | #pragma mark - TYTabPagerBarDataSource
158 |
159 | - (NSInteger)numberOfItemsInPagerTabBar {
160 | return [_dataSource numberOfControllersInTabPagerController];
161 | }
162 |
163 | - (UICollectionViewCell *)pagerTabBar:(TYTabPagerBar *)pagerTabBar cellForItemAtIndex:(NSInteger)index {
164 | UICollectionViewCell *cell = [pagerTabBar dequeueReusableCellWithReuseIdentifier:_identifier forIndex:index];
165 | cell.titleLabel.text = [_dataSource tabPagerController:self titleForIndex:index];
166 | if ([_delegate respondsToSelector:@selector(tabPagerController:willDisplayCell:atIndex:)]) {
167 | [_delegate tabPagerController:self willDisplayCell:cell atIndex:index];
168 | }
169 | return cell;
170 | }
171 |
172 | #pragma mark - TYTabPagerBarDelegate
173 |
174 | - (CGFloat)pagerTabBar:(TYTabPagerBar *)pagerTabBar widthForItemAtIndex:(NSInteger)index {
175 | NSString *title = [_dataSource tabPagerController:self titleForIndex:index];
176 | return [pagerTabBar cellWidthForTitle:title];
177 | }
178 |
179 | - (void)pagerTabBar:(TYTabPagerBar *)pagerTabBar didSelectItemAtIndex:(NSInteger)index {
180 | [_pagerController scrollToControllerAtIndex:index animate:YES];
181 | if ([_delegate respondsToSelector:@selector(tabPagerController:didSelectTabBarItemAtIndex:)]) {
182 | [_delegate tabPagerController:self didSelectTabBarItemAtIndex:index];
183 | }
184 | }
185 |
186 | #pragma mark - TYPagerControllerDataSource
187 |
188 | - (NSInteger)numberOfControllersInPagerController {
189 | return [_dataSource numberOfControllersInTabPagerController];
190 | }
191 |
192 | - (UIViewController *)pagerController:(TYPagerController *)pagerController controllerForIndex:(NSInteger)index prefetching:(BOOL)prefetching {
193 | UIViewController *viewController = [_dataSource tabPagerController:self controllerForIndex:index prefetching:prefetching];
194 | return viewController;
195 | }
196 |
197 | #pragma mark - TYPagerControllerDelegate
198 |
199 | - (void)pagerController:(TYPagerController *)pagerController transitionFromIndex:(NSInteger)fromIndex toIndex:(NSInteger)toIndex animated:(BOOL)animated {
200 | [self.tabBar scrollToItemFromIndex:fromIndex toIndex:toIndex animate:animated];
201 | }
202 |
203 | -(void)pagerController:(TYPagerController *)pagerController transitionFromIndex:(NSInteger)fromIndex toIndex:(NSInteger)toIndex progress:(CGFloat)progress {
204 | [self.tabBar scrollToItemFromIndex:fromIndex toIndex:toIndex progress:progress];
205 | }
206 |
207 | - (void)pagerControllerWillBeginScrolling:(TYPagerController *)pagerController animate:(BOOL)animate {
208 | if ([_delegate respondsToSelector:@selector(tabPagerControllerWillBeginScrolling:animate:)]) {
209 | [_delegate tabPagerControllerWillBeginScrolling:self animate:animate];
210 | }
211 | }
212 | - (void)pagerControllerDidEndScrolling:(TYPagerController *)pagerController animate:(BOOL)animate {
213 | if ([_delegate respondsToSelector:@selector(tabPagerControllerDidEndScrolling:animate:)]) {
214 | [_delegate tabPagerControllerDidEndScrolling:self animate:animate];
215 | }
216 | }
217 |
218 | - (void)didReceiveMemoryWarning {
219 | [super didReceiveMemoryWarning];
220 | // Dispose of any resources that can be recreated.
221 | }
222 |
223 | @end
224 |
--------------------------------------------------------------------------------
/TYPagerControllerDemo/TYPagerController/TYPagerView.m:
--------------------------------------------------------------------------------
1 | //
2 | // TYPagerView.m
3 | // TYPagerControllerDemo
4 | //
5 | // Created by tany on 2017/7/5.
6 | // Copyright © 2017年 tanyang. All rights reserved.
7 | //
8 |
9 | #import "TYPagerView.h"
10 |
11 | @interface TYPagerView () {
12 | // private
13 | struct {
14 | unsigned int willAppearViewForIndex :1;
15 | unsigned int didAppearViewForIndex :1;
16 | unsigned int willDisappearViewForIndex :1;
17 | unsigned int didDisappearViewForIndex :1;
18 | unsigned int transitionFromIndexToIndex :1;
19 | unsigned int transitionFromIndexToIndexProgress :1;
20 | unsigned int viewDidScroll: 1;
21 | unsigned int viewWillBeginScrolling: 1;
22 | unsigned int viewDidEndScrolling: 1;
23 | }_delegateFlags;
24 | }
25 |
26 | // Data
27 | @property (nonatomic, strong) TYPagerViewLayout *layout;
28 |
29 | @end
30 |
31 | @implementation TYPagerView
32 |
33 | #pragma mark - life cycle
34 |
35 | - (instancetype)initWithFrame:(CGRect)frame {
36 | if (self = [super initWithFrame:frame]) {
37 | self.backgroundColor = [UIColor clearColor];
38 | // prevent sysytem automaticallyAdjustsScrollViewInsets
39 | [self addFixAutoAdjustInsetScrollView];
40 | [self addLayoutScrollView];
41 | }
42 | return self;
43 | }
44 |
45 | - (instancetype)initWithCoder:(NSCoder *)aDecoder {
46 | if (self = [super initWithCoder:aDecoder]) {
47 | self.backgroundColor = [UIColor clearColor];
48 | // prevent sysytem automaticallyAdjustsScrollViewInsets
49 | [self addFixAutoAdjustInsetScrollView];
50 | [self addLayoutScrollView];
51 | }
52 | return self;
53 | }
54 |
55 | - (void)addFixAutoAdjustInsetScrollView {
56 | UIView *view = [[UIView alloc]init];
57 | [self addSubview:view];
58 | }
59 |
60 | - (void)addLayoutScrollView {
61 | UIScrollView *contentView = [[UIScrollView alloc]init];
62 | TYPagerViewLayout *layout = [[TYPagerViewLayout alloc]initWithScrollView:contentView];
63 | layout.dataSource = self;
64 | layout.delegate = self;
65 | [self addSubview:contentView];
66 | _layout = layout;
67 | _layout.scrollView.frame = self.bounds;
68 | }
69 |
70 | #pragma mark - getter && setter
71 |
72 | - (NSInteger)curIndex {
73 | return _layout.curIndex;
74 | }
75 |
76 | - (NSInteger)countOfPagerViews {
77 | return _layout.countOfPagerItems;
78 | }
79 |
80 | - (NSArray *)visibleViews {
81 | return _layout.visibleItems;
82 | }
83 |
84 | - (UIScrollView *)scrollView {
85 | return _layout.scrollView;
86 | }
87 |
88 | - (void)setContentInset:(UIEdgeInsets)contentInset {
89 | _contentInset = contentInset;
90 | [self setNeedsLayout];
91 | }
92 |
93 | - (void)setDelegate:(id)delegate {
94 | _delegate = delegate;
95 |
96 | _delegateFlags.willAppearViewForIndex = [delegate respondsToSelector:@selector(pagerView:willAppearView:forIndex:)];
97 | _delegateFlags.didAppearViewForIndex = [delegate respondsToSelector:@selector(pagerView:didAppearView:forIndex:)];
98 | _delegateFlags.willDisappearViewForIndex = [delegate respondsToSelector:@selector(pagerView:willDisappearView:forIndex:)];
99 | _delegateFlags.didDisappearViewForIndex = [delegate respondsToSelector:@selector(pagerView:didDisappearView:forIndex:)];
100 |
101 | _delegateFlags.transitionFromIndexToIndex = [delegate respondsToSelector:@selector(pagerView:transitionFromIndex:toIndex:animated:)];
102 | _delegateFlags.transitionFromIndexToIndexProgress = [delegate respondsToSelector:@selector(pagerView:transitionFromIndex:toIndex:progress:)];
103 |
104 | _delegateFlags.viewDidScroll = [delegate respondsToSelector:@selector(pagerViewDidScroll:)];
105 | _delegateFlags.viewWillBeginScrolling = [delegate respondsToSelector:@selector(pagerViewWillBeginScrolling:animate:)];
106 | _delegateFlags.viewDidEndScrolling = [delegate respondsToSelector:@selector(pagerViewDidEndScrolling:animate:)];
107 | }
108 |
109 | #pragma mark - public
110 |
111 | - (void)updateData {
112 | [_layout updateData];
113 | }
114 |
115 | - (void)reloadData {
116 | [_layout reloadData];
117 | }
118 |
119 | - (void)scrollToViewAtIndex:(NSInteger)index animate:(BOOL)animate {
120 | [_layout scrollToItemAtIndex:index animate:animate];
121 | }
122 |
123 | - (UIView *)viewForIndex:(NSInteger)idx {
124 | return [_layout itemForIndex:idx];
125 | }
126 |
127 | - (void)registerClass:(Class)Class forViewWithReuseIdentifier:(NSString *)identifier {
128 | [_layout registerClass:Class forItemWithReuseIdentifier:identifier];
129 | }
130 | - (void)registerNib:(UINib *)nib forViewWithReuseIdentifier:(NSString *)identifier {
131 | [_layout registerNib:nib forItemWithReuseIdentifier:identifier];
132 | }
133 | - (UIView *)dequeueReusableViewWithReuseIdentifier:(NSString *)identifier forIndex:(NSInteger)index {
134 | return [_layout dequeueReusableItemWithReuseIdentifier:identifier forIndex:index];
135 | }
136 |
137 | #pragma mark - private
138 |
139 | - (void)willBeginScrollingAnimate:(BOOL)animate {
140 | if (_delegateFlags.viewWillBeginScrolling) {
141 | [_delegate pagerViewWillBeginScrolling:self animate:animate];
142 | }
143 | }
144 |
145 | - (void)didEndScrollingAnimate:(BOOL)animate {
146 | if (_delegateFlags.viewDidEndScrolling) {
147 | [_delegate pagerViewDidEndScrolling:self animate:animate];
148 | }
149 | }
150 |
151 | #pragma mark - TYPagerViewLayoutDataSource
152 |
153 | - (NSInteger)numberOfItemsInPagerViewLayout {
154 | return [_dataSource numberOfViewsInPagerView];
155 | }
156 |
157 | - (id)pagerViewLayout:(TYPagerViewLayout *)pagerViewLayout itemForIndex:(NSInteger)index prefetching:(BOOL)prefetching {
158 | return [_dataSource pagerView:self viewForIndex:index prefetching:prefetching];
159 | }
160 |
161 | - (UIView *)pagerViewLayout:(TYPagerViewLayout *)pagerViewLayout viewForItem:(id)item atIndex:(NSInteger)index {
162 | return item;
163 | }
164 |
165 | - (void)pagerViewLayout:(TYPagerViewLayout *)pagerViewLayout addVisibleItem:(id)item atIndex:(NSInteger)index {
166 | UIView *visibleView = item;
167 | if (_delegateFlags.willAppearViewForIndex) {
168 | [_delegate pagerView:self willAppearView:visibleView forIndex:index];
169 | }
170 | [pagerViewLayout.scrollView addSubview:visibleView];
171 | if (_delegateFlags.didAppearViewForIndex) {
172 | [_delegate pagerView:self didAppearView:visibleView forIndex:index];
173 | }
174 | }
175 |
176 | - (void)pagerViewLayout:(TYPagerViewLayout *)pagerViewLayout removeInVisibleItem:(id)item atIndex:(NSInteger)index {
177 | UIView *invisibleView = item;
178 | if (_delegateFlags.willDisappearViewForIndex) {
179 | [_delegate pagerView:self willDisappearView:invisibleView forIndex:index];
180 | }
181 | [invisibleView removeFromSuperview];
182 | if (_delegateFlags.didDisappearViewForIndex) {
183 | [_delegate pagerView:self didDisappearView:invisibleView forIndex:index];
184 | }
185 | }
186 |
187 | #pragma mark - TYPagerViewLayoutDelegate
188 |
189 | - (void)pagerViewLayout:(TYPagerViewLayout *)pagerViewLayout transitionFromIndex:(NSInteger)fromIndex toIndex:(NSInteger)toIndex animated:(BOOL)animated {
190 | if (_delegateFlags.transitionFromIndexToIndex) {
191 | [_delegate pagerView:self transitionFromIndex:fromIndex toIndex:toIndex animated:animated];
192 | }
193 | }
194 |
195 | - (void)pagerViewLayout:(TYPagerViewLayout *)pagerViewLayout transitionFromIndex:(NSInteger)fromIndex toIndex:(NSInteger)toIndex progress:(CGFloat)progress {
196 | if (_delegateFlags.transitionFromIndexToIndexProgress) {
197 | [_delegate pagerView:self transitionFromIndex:fromIndex toIndex:toIndex progress:progress];
198 | }
199 | }
200 |
201 | - (void)pagerViewLayoutDidScroll:(TYPagerViewLayout *)pagerViewLayout {
202 | if (_delegateFlags.viewDidScroll) {
203 | [_delegate pagerViewDidScroll:self];
204 | }
205 | }
206 |
207 | - (void)pagerViewLayoutWillBeginDragging:(TYPagerViewLayout *)pagerViewLayout {
208 | [self willBeginScrollingAnimate:YES];
209 | }
210 |
211 | - (void)pagerViewLayoutWillBeginScrollToView:(TYPagerViewLayout *)pagerViewLayout animate:(BOOL)animate {
212 | [self willBeginScrollingAnimate:animate];
213 | }
214 |
215 | - (void)pagerViewLayoutDidEndDecelerating:(TYPagerViewLayout *)pagerViewLayout {
216 | [self didEndScrollingAnimate:YES];
217 | }
218 |
219 | - (void)pagerViewLayoutDidEndScrollToView:(TYPagerViewLayout *)pagerViewLayout animate:(BOOL)animate {
220 | [self didEndScrollingAnimate:animate];
221 | }
222 |
223 | - (void)pagerViewLayoutDidEndScrollingAnimation:(TYPagerViewLayout *)pagerViewLayout {
224 | [self didEndScrollingAnimate:YES];
225 | }
226 |
227 | #pragma mark - layoutSubviews
228 |
229 | - (void)layoutSubviews {
230 | [super layoutSubviews];
231 | _layout.scrollView.frame = UIEdgeInsetsInsetRect(self.bounds,_contentInset);
232 | }
233 |
234 | - (void)dealloc {
235 | _layout = nil;
236 | }
237 |
238 | @end
239 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # TYPagerController v2.0
2 | TYPagerController 简单,强大,高度定制,页面控制器,水平滚动内容和标题栏,包含多种barStyle。
3 | TYPagerController v2.0 重构优化代码,分离出TYPagerViewLayout布局类,添加更多功能,更加强大,稳定,已经在项目中使用
4 | 如果还想使用以前的版本可以查看分支v1.0.6 和 pod 'TYPagerController', '~> 1.0.6'
5 |
6 | * TYPagerViewLayout 水平滚动页面的layout类,只需要initWithScrollView:即可实现水平滚动页面.
7 | * TYPagerView 包含TYPagerViewLayout的水平滚动页面View
8 | * TYPagerController 包含TYPagerViewLayout的水平滚动页面Controller。
9 | * TYTabPagerBar Pager的标题 tabBar
10 | * TYTabPagerView 包含TabBar的TYPagerView
11 | * TYTabPagerController 包含TabBar的TYPagerController
12 |
13 | 注意:获取数据后必须调用reloadData.
14 | 更详细的使用请看[LovePlayNews](https://github.com/12207480/LovePlayNews)项目
15 |
16 | ## CocoaPods
17 | ```
18 | pod 'TYPagerController'
19 | ```
20 |
21 | ## Requirements
22 | * Xcode 7 or higher
23 | * iOS 7.0 or higher
24 | * ARC
25 |
26 | ## ScreenShot
27 | ### TYPagerBarStyle
28 |
29 | New TYPagerBarStyleProgressElasticView
30 | 
31 |
32 | 1 TYPagerBarStyleProgressBounceView
33 | 
34 |
35 | 2 TYPagerBarStyleProgressView
36 | 
37 |
38 | 3 TYPagerBarStyleCoverView
39 | 
40 | 
41 |
42 | 4 TYPagerBarStyleNoneView
43 | 
44 |
45 | ## API
46 |
47 | ### Class
48 | * TYPagerViewLayout
49 | ```objc
50 | @interface TYPagerViewLayout<__covariant ItemType> : NSObject
51 |
52 | @property (nonatomic, weak, nullable) id dataSource;
53 | @property (nonatomic, weak, nullable) id delegate;
54 |
55 | // strong,will control the delegate,don't set delegate on other place.
56 | @property (nonatomic, strong, readonly) UIScrollView *scrollView;
57 | // if viewcontroller's automaticallyAdjustsScrollViewInsets YES ,will cause frame problems, you can set YES, default YES
58 | @property (nonatomic, assign) BOOL adjustScrollViewInset;
59 |
60 | @property (nonatomic, assign, readonly) NSInteger countOfPagerItems;
61 | @property (nonatomic, assign, readonly) NSInteger curIndex;// default -1
62 |
63 | @property (nonatomic, strong, readonly) NSCache *memoryCache;; // will cache pagerView,you can set countLimit
64 | @property (nonatomic, assign) BOOL autoMemoryCache; // default YES
65 |
66 | @property (nonatomic, assign) NSInteger prefetchItemCount;// preload left and right item's count , default 0
67 |
68 | @property (nonatomic, assign, readonly) NSRange prefetchRange;
69 | @property (nonatomic, assign, readonly) NSRange visibleRange;
70 |
71 | @property (nonatomic, strong, nullable, readonly) NSArray * visibleIndexs;
72 | @property (nonatomic, strong, nullable, readonly) NSArray * visibleItems;
73 |
74 | // default YES, if NO,will not call delegate transitionFromIndex:toIndex:progress:,but will call transitionFromIndex:toIndex:
75 | @property (nonatomic, assign) BOOL progressAnimateEnabel;
76 |
77 | // default NO, when scroll visible range change will add item.If YES add item only when scroll animate end, suggest set prefetchItemCount 1 or more
78 | @property (nonatomic, assign) BOOL addVisibleItemOnlyWhenScrollAnimatedEnd;
79 |
80 | // default 0.5,when scroll progress percent will change index, only progressAnimateEnabel is NO or don't implement delegate transitionFromIndex: toIndex: progress:
81 | @property (nonatomic, assign) CGFloat changeIndexWhenScrollProgress;
82 | ```
83 | * TYPagerView
84 | ```objc
85 | @interface TYPagerView : UIView
86 |
87 | @property (nonatomic, weak, nullable) id dataSource;
88 | @property (nonatomic, weak, nullable) id delegate;
89 | // pagerView's layout,don't set layout's dataSource to other
90 | @property (nonatomic, strong, readonly) TYPagerViewLayout *layout;
91 | @property (nonatomic, strong, readonly) UIScrollView *scrollView;
92 |
93 | @property (nonatomic, assign, readonly) NSInteger countOfPagerViews;
94 | @property (nonatomic, assign, readonly) NSInteger curIndex;// default -1
95 |
96 | @property (nonatomic, assign, nullable, readonly) NSArray *visibleViews;
97 |
98 | @property (nonatomic, assign) UIEdgeInsets contentInset;
99 |
100 | //if not visible, prefecth, cache view at index, return nil
101 | - (UIView *_Nullable)viewForIndex:(NSInteger)index;
102 |
103 | // register && dequeue's usage like tableView
104 | - (void)registerClass:(Class)Class forViewWithReuseIdentifier:(NSString *)identifier;
105 | - (void)registerNib:(UINib *)nib forViewWithReuseIdentifier:(NSString *)identifier;
106 | - (UIView *)dequeueReusableViewWithReuseIdentifier:(NSString *)identifier forIndex:(NSInteger)index;
107 |
108 | // scroll to index
109 | - (void)scrollToViewAtIndex:(NSInteger)index animate:(BOOL)animate;
110 |
111 | // update data and layout,but don't reset propertys(curIndex,visibleDatas,prefechDatas)
112 | - (void)updateData;
113 |
114 | // reload data and reset propertys
115 | - (void)reloadData;
116 | ```
117 | ```objc
118 | @protocol TYTabPagerControllerDelegate
119 |
120 | // configre collectionview cell
121 | - (void)pagerController:(TYTabPagerController *)pagerController configreCell:(UICollectionViewCell *)cell forItemTitle:(NSString *)title atIndexPath:(NSIndexPath *)indexPath;
122 |
123 | // transition frome cell to cell with animated
124 | - (void)pagerController:(TYTabPagerController *)pagerController transitionFromeCell:(UICollectionViewCell *)fromCell toCell:(UICollectionViewCell *)toCell animated:(BOOL)animated;
125 |
126 | // transition frome cell to cell with progress
127 | - (void)pagerController:(TYTabPagerController *)pagerController transitionFromeCell:(UICollectionViewCell *)fromCell toCell:(UICollectionViewCell *)toCell progress:(CGFloat)progress;
128 |
129 | @end
130 | ```
131 | * TYPagerController
132 | ```objc
133 | @interface TYPagerController : UIViewController
134 |
135 | @property (nonatomic, weak, nullable) id dataSource;
136 | @property (nonatomic, weak, nullable) id delegate;
137 | // pagerController's layout,don't set layout's dataSource to other
138 | @property (nonatomic, strong, readonly) TYPagerViewLayout *layout;
139 | @property (nonatomic, weak, readonly) UIScrollView *scrollView;
140 |
141 | @property (nonatomic, assign, readonly) NSInteger countOfControllers;
142 | @property (nonatomic, assign, readonly) NSInteger curIndex;// default -1
143 |
144 | @property (nonatomic, strong, nullable, readonly) NSArray *visibleControllers;
145 |
146 | @property (nonatomic, assign) UIEdgeInsets contentInset;
147 |
148 | //if not visible, prefecth, cache view at index, return nil
149 | - (UIViewController *_Nullable)controllerForIndex:(NSInteger)index;
150 |
151 | // register && dequeue's usage like tableView
152 | - (void)registerClass:(Class)Class forControllerWithReuseIdentifier:(NSString *)identifier;
153 | - (void)registerNib:(UINib *)nib forControllerWithReuseIdentifier:(NSString *)identifier;
154 | - (UIViewController *)dequeueReusableControllerWithReuseIdentifier:(NSString *)identifier forIndex:(NSInteger)index;
155 |
156 | // scroll to index
157 | - (void)scrollToControllerAtIndex:(NSInteger)index animate:(BOOL)animate;
158 |
159 | // update data and layout,but don't reset propertys(curIndex,visibleDatas,prefechDatas)
160 | - (void)updateData;
161 |
162 | // reload data and reset propertys
163 | - (void)reloadData;
164 | ```
165 |
166 | ##Usage Demo
167 | * TYTabPagerView
168 | ```objc
169 | - (void)addTabPagerView {
170 | TYTabPagerView *pagerView = [[TYTabPagerView alloc]init];
171 | pagerView.tabBar.layout.barStyle = TYPagerBarStyleCoverView;
172 | pagerView.tabBar.progressView.backgroundColor = [UIColor lightGrayColor];
173 | pagerView.dataSource = self;
174 | pagerView.delegate = self;
175 | [self.view addSubview:pagerView];
176 | _pagerView = pagerView;
177 | }
178 |
179 | #pragma mark - TYTabPagerViewDataSource
180 |
181 | - (NSInteger)numberOfViewsInTabPagerView {
182 | return _datas.count;
183 | }
184 |
185 | - (UIView *)tabPagerView:(TYTabPagerView *)tabPagerView viewForIndex:(NSInteger)index prefetching:(BOOL)prefetching {
186 | UIView *view = [[UIView alloc]initWithFrame:[tabPagerView.layout frameForItemAtIndex:index]];
187 | view.backgroundColor = [UIColor colorWithRed:arc4random()%255/255.0 green:arc4random()%255/255.0 blue:arc4random()%255/255.0 alpha:arc4random()%255/255.0];
188 | //NSLog(@"viewForIndex:%ld prefetching:%d",index,prefetching);
189 | return view;
190 | }
191 |
192 | - (NSString *)tabPagerView:(TYTabPagerView *)tabPagerView titleForIndex:(NSInteger)index {
193 | NSString *title = _datas[index];
194 | return title;
195 | }
196 | ```
197 |
198 | * TYTabPagerController
199 | ```objc
200 | @interface TabPagerControllerDemoController : TYTabPagerController
201 |
202 | - (void)viewDidLoad {
203 | [super viewDidLoad];
204 | // Do any additional setup after loading the view.
205 | self.title = @"TabPagerControllerDemoController";
206 | self.tabBar.layout.barStyle = TYPagerBarStyleProgressView;
207 | self.dataSource = self;
208 | self.delegate = self;
209 |
210 | [self loadData];
211 | }
212 |
213 | - (void)loadData {
214 | _datas = [datas copy];
215 | // must call reloadData
216 | [self reloadData];
217 | }
218 |
219 | #pragma mark - TYTabPagerControllerDataSource
220 |
221 | - (NSInteger)numberOfControllersInTabPagerController {
222 | return _datas.count;
223 | }
224 |
225 | - (UIViewController *)tabPagerController:(TYTabPagerController *)tabPagerController controllerForIndex:(NSInteger)index prefetching:(BOOL)prefetching {
226 | if (index%3 == 0) {
227 | CustomViewController *VC = [[CustomViewController alloc]init];
228 | VC.text = [@(index) stringValue];
229 | return VC;
230 | }else if (index%3 == 1) {
231 | ListViewController *VC = [[ListViewController alloc]init];
232 | VC.text = [@(index) stringValue];
233 | return VC;
234 | }else {
235 | CollectionViewController *VC = [[CollectionViewController alloc]init];
236 | VC.text = [@(index) stringValue];
237 | return VC;
238 | }
239 | }
240 |
241 | - (NSString *)tabPagerController:(TYTabPagerController *)tabPagerController titleForIndex:(NSInteger)index {
242 | NSString *title = _datas[index];
243 | return title;
244 | }
245 | ```
246 |
247 |
248 | 更多的使用方法 请查看 demo。
249 |
250 | ### Contact
251 | 如果你发现bug,please pull reqeust me
252 | 如果你有更好的改进,please pull reqeust me
253 |
--------------------------------------------------------------------------------
/TYPagerControllerDemo/TYPagerController/TYPagerController.m:
--------------------------------------------------------------------------------
1 | //
2 | // TYPagerController.m
3 | // TYPagerControllerDemo
4 | //
5 | // Created by tanyang on 16/4/13.
6 | // Copyright © 2016年 tanyang. All rights reserved.
7 | //
8 |
9 | #import "TYPagerController.h"
10 |
11 | @interface TYPagerController () {
12 | // private
13 | struct {
14 | unsigned int viewWillAppearForIndex :1;
15 | unsigned int viewDidAppearForIndex :1;
16 | unsigned int viewWillDisappearForIndex :1;
17 | unsigned int viewDidDisappearForIndex :1;
18 |
19 | unsigned int transitionFromIndexToIndex :1;
20 | unsigned int transitionFromIndexToIndexProgress :1;
21 | unsigned int viewDidScroll: 1;
22 | unsigned int viewWillBeginScrolling: 1;
23 | unsigned int viewDidEndScrolling: 1;
24 | }_delegateFlags;
25 | }
26 |
27 | // Data
28 | @property (nonatomic, strong) TYPagerViewLayout *layout;
29 |
30 | @end
31 |
32 |
33 | @implementation TYPagerController
34 |
35 | - (TYPagerViewLayout *)layout {
36 | if (!_layout) {
37 | UIScrollView *scrollView = [[UIScrollView alloc]init];
38 | TYPagerViewLayout *layout = [[TYPagerViewLayout alloc]initWithScrollView:scrollView];
39 | layout.dataSource = self;
40 | layout.delegate = self;
41 | layout.adjustScrollViewInset = YES;
42 | _layout = layout;
43 | }
44 | return _layout;
45 | }
46 |
47 | - (instancetype)initWithCoder:(NSCoder *)aDecoder {
48 | if (self = [super initWithCoder:aDecoder]) {
49 | _automaticallySystemManagerViewAppearanceMethods = YES;
50 | }
51 | return self;
52 | }
53 |
54 | - (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
55 | if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
56 | _automaticallySystemManagerViewAppearanceMethods = YES;
57 | }
58 | return self;
59 | }
60 |
61 | #pragma mark - life cycle
62 |
63 | - (void)viewDidLoad {
64 | [super viewDidLoad];
65 | // Do any additional setup after loading the view.
66 | self.view.backgroundColor = [UIColor whiteColor];
67 | // prevent sysytem automaticallyAdjustsScrollViewInsets
68 | [self addFixAutoAdjustInsetScrollView];
69 | [self.view addSubview:self.layout.scrollView];
70 | }
71 |
72 | - (void)addFixAutoAdjustInsetScrollView {
73 | UIView *view = [[UIView alloc]init];
74 | [self.view addSubview:view];
75 | }
76 |
77 | - (void)viewWillAppear:(BOOL)animated {
78 | [super viewWillAppear:animated];
79 | _layout.scrollView.frame = UIEdgeInsetsInsetRect(self.view.bounds,_contentInset);
80 | }
81 |
82 | - (void)viewWillLayoutSubviews
83 | {
84 | [super viewWillLayoutSubviews];
85 | _layout.scrollView.frame = UIEdgeInsetsInsetRect(self.view.bounds,_contentInset);
86 | }
87 |
88 | #pragma mark - getter && setter
89 |
90 | - (void)setDelegate:(id)delegate
91 | {
92 | _delegate = delegate;
93 |
94 | _delegateFlags.viewWillAppearForIndex = [delegate respondsToSelector:@selector(pagerController:viewWillAppear:forIndex:)];
95 | _delegateFlags.viewDidAppearForIndex = [delegate respondsToSelector:@selector(pagerController:viewDidAppear:forIndex:)];
96 | _delegateFlags.viewWillDisappearForIndex = [delegate respondsToSelector:@selector(pagerController:viewWillDisappear:forIndex:)];
97 | _delegateFlags.viewDidDisappearForIndex = [delegate respondsToSelector:@selector(pagerController:viewDidDisappear:forIndex:)];
98 |
99 | _delegateFlags.transitionFromIndexToIndex = [delegate respondsToSelector:@selector(pagerController:transitionFromIndex:toIndex:animated:)];
100 | _delegateFlags.transitionFromIndexToIndexProgress = [delegate respondsToSelector:@selector(pagerController:transitionFromIndex:toIndex:progress:)];
101 |
102 | _delegateFlags.viewDidScroll = [delegate respondsToSelector:@selector(pagerControllerDidScroll:)];
103 | _delegateFlags.viewWillBeginScrolling = [delegate respondsToSelector:@selector(pagerControllerWillBeginScrolling:animate:)];
104 | _delegateFlags.viewDidEndScrolling = [delegate respondsToSelector:@selector(pagerControllerDidEndScrolling:animate:)];
105 | }
106 |
107 | - (NSInteger)curIndex {
108 | return _layout.curIndex;
109 | }
110 |
111 | - (NSInteger)countOfControllers {
112 | return _layout.countOfPagerItems;
113 | }
114 |
115 | - (NSArray *)visibleControllers {
116 | return _layout.visibleItems;
117 | }
118 |
119 | - (UIScrollView *)scrollView {
120 | return _layout.scrollView;
121 | }
122 |
123 | - (void)setContentInset:(UIEdgeInsets)contentInset {
124 | _contentInset = contentInset;
125 | [self.view setNeedsLayout];
126 | }
127 |
128 | - (BOOL)shouldAutomaticallyForwardAppearanceMethods {
129 | return _automaticallySystemManagerViewAppearanceMethods;
130 | }
131 |
132 | - (void)childViewController:(UIViewController *)childViewController BeginAppearanceTransition:(BOOL)isAppearing animated:(BOOL)animated {
133 | if (!_automaticallySystemManagerViewAppearanceMethods) {
134 | [childViewController beginAppearanceTransition:isAppearing animated:animated];
135 | }
136 | }
137 |
138 | - (void)childViewControllerEndAppearanceTransition:(UIViewController *)childViewController {
139 | if (!_automaticallySystemManagerViewAppearanceMethods) {
140 | [childViewController endAppearanceTransition];
141 | }
142 | }
143 |
144 | #pragma mark - public method
145 |
146 | - (UIViewController *)controllerForIndex:(NSInteger)index {
147 | return [_layout itemForIndex:index];
148 | }
149 |
150 | - (void)scrollToControllerAtIndex:(NSInteger)index animate:(BOOL)animate {
151 | [_layout scrollToItemAtIndex:index animate:animate];
152 | }
153 |
154 | - (void)updateData {
155 | [_layout updateData];
156 | }
157 |
158 | - (void)reloadData {
159 | [_layout reloadData];
160 | }
161 |
162 | - (void)registerClass:(Class)Class forControllerWithReuseIdentifier:(NSString *)identifier {
163 | [_layout registerClass:Class forItemWithReuseIdentifier:identifier];
164 | }
165 | - (void)registerNib:(UINib *)nib forControllerWithReuseIdentifier:(NSString *)identifier {
166 | [_layout registerNib:nib forItemWithReuseIdentifier:identifier];
167 | }
168 | - (UIViewController *)dequeueReusableControllerWithReuseIdentifier:(NSString *)identifier forIndex:(NSInteger)index {
169 | return [_layout dequeueReusableItemWithReuseIdentifier:identifier forIndex:index];
170 | }
171 |
172 | #pragma mark - private
173 |
174 | - (void)willBeginScrollingAnimate:(BOOL)animate {
175 | if (_delegateFlags.viewWillBeginScrolling) {
176 | [_delegate pagerControllerWillBeginScrolling:self animate:animate];
177 | }
178 | }
179 |
180 | - (void)didEndScrollingAnimate:(BOOL)animate {
181 | if (_delegateFlags.viewDidEndScrolling) {
182 | [_delegate pagerControllerDidEndScrolling:self animate:animate];
183 | }
184 | }
185 |
186 | #pragma mark - TYPagerViewLayoutDataSource
187 |
188 | - (NSInteger)numberOfItemsInPagerViewLayout {
189 | return [_dataSource numberOfControllersInPagerController];
190 | }
191 |
192 | - (id)pagerViewLayout:(TYPagerViewLayout *)pagerViewLayout itemForIndex:(NSInteger)index prefetching:(BOOL)prefetching {
193 | return [_dataSource pagerController:self controllerForIndex:index prefetching:prefetching];
194 | }
195 | - (UIView *)pagerViewLayout:(TYPagerViewLayout *)pagerViewLayout viewForItem:(id)item atIndex:(NSInteger)index {
196 | UIViewController *viewController = item;
197 | return viewController.view;
198 | }
199 |
200 | - (UIViewController *)pagerViewLayout:(TYPagerViewLayout *)pagerViewLayout viewControllerForItem:(id)item atIndex:(NSInteger)index {
201 | return item;
202 | }
203 |
204 | - (void)pagerViewLayout:(TYPagerViewLayout *)pagerViewLayout addVisibleItem:(id)item atIndex:(NSInteger)index {
205 | UIViewController *viewController = item;
206 | if (_delegateFlags.viewWillAppearForIndex) {
207 | [_delegate pagerController:self viewWillAppear:viewController forIndex:index];
208 | }
209 | // addChildViewController
210 | [self addChildViewController:viewController];
211 | [self childViewController:viewController BeginAppearanceTransition:YES animated:YES];
212 | [pagerViewLayout.scrollView addSubview:viewController.view];
213 | [self childViewControllerEndAppearanceTransition:viewController];
214 | [viewController didMoveToParentViewController:self];
215 | if (_delegateFlags.viewDidAppearForIndex) {
216 | [_delegate pagerController:self viewDidAppear:viewController forIndex:index];
217 | }
218 | }
219 |
220 | - (void)pagerViewLayout:(TYPagerViewLayout *)pagerViewLayout removeInVisibleItem:(id)item atIndex:(NSInteger)index {
221 | UIViewController *viewController = item;
222 | if (_delegateFlags.viewWillDisappearForIndex) {
223 | [_delegate pagerController:self viewWillDisappear:viewController forIndex:index];
224 | }
225 | // removeChildViewController
226 | [viewController willMoveToParentViewController:nil];
227 | [self childViewController:viewController BeginAppearanceTransition:NO animated:YES];
228 | [viewController.view removeFromSuperview];
229 | [self childViewControllerEndAppearanceTransition:viewController];
230 | [viewController removeFromParentViewController];
231 | if (_delegateFlags.viewDidDisappearForIndex) {
232 | [_delegate pagerController:self viewDidDisappear:viewController forIndex:index];
233 | }
234 | }
235 |
236 | #pragma mark - TYPagerViewLayoutDelegate
237 |
238 | - (void)pagerViewLayout:(TYPagerViewLayout *)pagerViewLayout transitionFromIndex:(NSInteger)fromIndex toIndex:(NSInteger)toIndex animated:(BOOL)animated {
239 | if (_delegateFlags.transitionFromIndexToIndex) {
240 | [_delegate pagerController:self transitionFromIndex:fromIndex toIndex:toIndex animated:animated];
241 | }
242 | }
243 |
244 | - (void)pagerViewLayout:(TYPagerViewLayout *)pagerViewLayout transitionFromIndex:(NSInteger)fromIndex toIndex:(NSInteger)toIndex progress:(CGFloat)progress {
245 | if (_delegateFlags.transitionFromIndexToIndexProgress) {
246 | [_delegate pagerController:self transitionFromIndex:fromIndex toIndex:toIndex progress:progress];
247 | }
248 | }
249 |
250 | - (void)pagerViewLayoutDidScroll:(TYPagerViewLayout *)pagerViewLayout {
251 | if (_delegateFlags.viewDidScroll) {
252 | [_delegate pagerControllerDidScroll:self];
253 | }
254 | }
255 |
256 | - (void)pagerViewLayoutWillBeginDragging:(TYPagerViewLayout *)pagerViewLayout {
257 | [self willBeginScrollingAnimate:YES];
258 | }
259 |
260 | - (void)pagerViewLayoutWillBeginScrollToView:(TYPagerViewLayout *)pagerViewLayout animate:(BOOL)animate {
261 | [self willBeginScrollingAnimate:animate];
262 | }
263 |
264 | - (void)pagerViewLayoutDidEndDecelerating:(TYPagerViewLayout *)pagerViewLayout {
265 | [self didEndScrollingAnimate:YES];
266 | }
267 |
268 | - (void)pagerViewLayoutDidEndScrollToView:(TYPagerViewLayout *)pagerViewLayout animate:(BOOL)animate {
269 | [self didEndScrollingAnimate:animate];
270 | }
271 |
272 | - (void)pagerViewLayoutDidEndScrollingAnimation:(TYPagerViewLayout *)pagerViewLayout {
273 | [self didEndScrollingAnimate:YES];
274 | }
275 |
276 | - (void)dealloc
277 | {
278 | _layout = nil;
279 | }
280 |
281 | @end
282 |
--------------------------------------------------------------------------------
/TYPagerControllerDemo/TYPagerController/TabPager/TYTabPagerBar.m:
--------------------------------------------------------------------------------
1 | //
2 | // TYTabPagerBar.m
3 | // TYPagerControllerDemo
4 | //
5 | // Created by tany on 2017/7/13.
6 | // Copyright © 2017年 tany. All rights reserved.
7 | //
8 |
9 | #import "TYTabPagerBar.h"
10 |
11 | @interface TYTabPagerBar () {
12 | struct {
13 | unsigned int transitionFromeCellAnimated :1;
14 | unsigned int transitionFromeCellProgress :1;
15 | unsigned int widthForItemAtIndex :1;
16 | }_delegateFlags;
17 | TYTabPagerBarLayout *_layout;
18 | }
19 |
20 | // UI
21 | @property (nonatomic, weak) UICollectionView *collectionView;
22 |
23 | // Data
24 |
25 | @property (nonatomic, assign) NSInteger countOfItems;
26 |
27 | @property (nonatomic, assign) NSInteger curIndex;
28 |
29 | @property (nonatomic, assign) BOOL isFirstLayout;
30 | @property (nonatomic, assign) BOOL didLayoutSubViews;
31 |
32 | @end
33 |
34 | @implementation TYTabPagerBar
35 |
36 | - (instancetype)initWithFrame:(CGRect)frame {
37 | if (self = [super initWithFrame:frame]) {
38 | _isFirstLayout = YES;
39 | _didLayoutSubViews = NO;
40 | _autoScrollItemToCenter = YES;
41 | self.backgroundColor = [UIColor clearColor];
42 | [self addFixAutoAdjustInsetScrollView];
43 | [self addCollectionView];
44 | [self addUnderLineView];
45 | }
46 | return self;
47 | }
48 |
49 | - (instancetype)initWithCoder:(NSCoder *)aDecoder {
50 | if (self = [super initWithCoder:aDecoder]) {
51 | _isFirstLayout = YES;
52 | _didLayoutSubViews = NO;
53 | _autoScrollItemToCenter = YES;
54 | self.backgroundColor = [UIColor clearColor];
55 | [self addFixAutoAdjustInsetScrollView];
56 | [self addCollectionView];
57 | [self addUnderLineView];
58 | }
59 | return self;
60 | }
61 |
62 | - (void)addFixAutoAdjustInsetScrollView {
63 | UIView *view = [[UIView alloc]init];
64 | [self addSubview:view];
65 | }
66 |
67 | - (void)addCollectionView {
68 | UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc]init];
69 | layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
70 | UICollectionView *collectionView = [[UICollectionView alloc]initWithFrame:UIEdgeInsetsInsetRect(self.bounds, _contentInset) collectionViewLayout:layout];
71 | collectionView.backgroundColor = [UIColor clearColor];
72 | collectionView.showsHorizontalScrollIndicator = NO;
73 | collectionView.showsVerticalScrollIndicator = NO;
74 | if ([collectionView respondsToSelector:@selector(setPrefetchingEnabled:)]) {
75 | collectionView.prefetchingEnabled = NO;
76 | }
77 | collectionView.delegate = self;
78 | collectionView.dataSource = self;
79 | [self addSubview:collectionView];
80 | _collectionView = collectionView;
81 | }
82 |
83 | - (void)addUnderLineView {
84 | UIView *progressView = [[UIView alloc]init];
85 | progressView.backgroundColor = [UIColor redColor];
86 | [_collectionView addSubview:progressView];
87 | _progressView = progressView;
88 | }
89 |
90 | #pragma mark - getter setter
91 |
92 | - (void)setProgressView:(UIView *)progressView {
93 | if (_progressView == progressView) {
94 | return;
95 | }
96 | if (_progressView) {
97 | [_progressView removeFromSuperview];
98 | }
99 | if (_layout && _layout.barStyle == TYPagerBarStyleCoverView) {
100 | progressView.layer.zPosition = -1;
101 | [_collectionView insertSubview: progressView atIndex:0];
102 | }else {
103 | [_collectionView addSubview:progressView];
104 | }
105 | if (_layout && self.superview) {
106 | [_layout layoutSubViews];
107 | }
108 | }
109 |
110 | - (void)setBackgroundView:(UIView *)backgroundView {
111 | if (_backgroundView) {
112 | [_backgroundView removeFromSuperview];
113 | }
114 | _backgroundView = backgroundView;
115 | backgroundView.frame = self.bounds;
116 | [self insertSubview:backgroundView atIndex:0];
117 | }
118 |
119 | - (void)setDelegate:(id)delegate {
120 | _delegate = delegate;
121 | _delegateFlags.transitionFromeCellAnimated = [delegate respondsToSelector:@selector(pagerTabBar:transitionFromeCell:toCell:animated:)];
122 | _delegateFlags.transitionFromeCellProgress = [delegate respondsToSelector:@selector(pagerTabBar:transitionFromeCell:toCell:progress:)];
123 | _delegateFlags.widthForItemAtIndex = [delegate respondsToSelector:@selector(pagerTabBar:widthForItemAtIndex:)];
124 | }
125 |
126 | - (void)setLayout:(TYTabPagerBarLayout *)layout {
127 | BOOL updateLayout = _layout && _layout != layout;
128 | _layout = layout;
129 | if (updateLayout) {
130 | [self reloadData];
131 | }
132 | }
133 |
134 | - (TYTabPagerBarLayout *)layout {
135 | if (!_layout) {
136 | _layout = [[TYTabPagerBarLayout alloc]initWithPagerTabBar:self];
137 | }
138 | return _layout;
139 | }
140 |
141 | #pragma mark - public
142 |
143 | - (void)reloadData {
144 | _countOfItems = [_dataSource numberOfItemsInPagerTabBar];
145 | if (_curIndex >= _countOfItems) {
146 | _curIndex = _countOfItems - 1;
147 | }
148 | if ([_delegate respondsToSelector:@selector(pagerTabBar:configureLayout:)]) {
149 | [_delegate pagerTabBar:self configureLayout:self.layout];
150 | }
151 | [self.layout layoutIfNeed];
152 | [_collectionView reloadData];
153 | [self.layout adjustContentCellsCenterInBar];
154 | [self.layout layoutSubViews];
155 | }
156 |
157 | - (void)registerClass:(Class)Class forCellWithReuseIdentifier:(NSString *)identifier {
158 | [_collectionView registerClass:Class forCellWithReuseIdentifier:identifier];
159 | }
160 |
161 | - (void)registerNib:(UINib *)nib forCellWithReuseIdentifier:(NSString *)identifier {
162 | [_collectionView registerNib:nib forCellWithReuseIdentifier:identifier];
163 | }
164 |
165 | - (__kindof UICollectionViewCell *)dequeueReusableCellWithReuseIdentifier:(NSString *)identifier forIndex:(NSInteger)index {
166 | UICollectionViewCell *cell = [_collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:[NSIndexPath indexPathForItem:index inSection:0]];
167 | return cell;
168 | }
169 |
170 | - (CGRect)cellFrameWithIndex:(NSInteger)index
171 | {
172 | if (index < 0) {
173 | return CGRectZero;
174 | }
175 | if (index >= _countOfItems) {
176 | return CGRectZero;
177 | }
178 | UICollectionViewLayoutAttributes * cellAttrs = [_collectionView layoutAttributesForItemAtIndexPath:[NSIndexPath indexPathForItem:index inSection:0]];
179 | if (!cellAttrs) {
180 | return CGRectZero;
181 | }
182 | return cellAttrs.frame;
183 | }
184 |
185 | - (UICollectionViewCell *)cellForIndex:(NSInteger)index
186 | {
187 | if (index >= _countOfItems) {
188 | return nil;
189 | }
190 | return (UICollectionViewCell *)[_collectionView cellForItemAtIndexPath:[NSIndexPath indexPathForItem:index inSection:0]];
191 | }
192 |
193 | - (void)scrollToItemFromIndex:(NSInteger)fromIndex toIndex:(NSInteger)toIndex animate:(BOOL)animate {
194 | if (toIndex < _countOfItems && toIndex >= 0 && fromIndex < _countOfItems && fromIndex >= 0) {
195 | _curIndex = toIndex;
196 | [self transitionFromIndex:fromIndex toIndex:toIndex animated:animate];
197 | if (_autoScrollItemToCenter) {
198 | if (!_didLayoutSubViews) {
199 | dispatch_async(dispatch_get_main_queue(), ^{
200 | [self scrollToItemAtIndex:toIndex atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally animated:animate];
201 | });
202 | }else {
203 | [self scrollToItemAtIndex:toIndex atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally animated:animate];
204 | }
205 | }
206 | }
207 | }
208 |
209 | - (void)scrollToItemFromIndex:(NSInteger)fromIndex toIndex:(NSInteger)toIndex progress:(CGFloat)progress {
210 | if (toIndex < _countOfItems && toIndex >= 0 && fromIndex < _countOfItems && fromIndex >= 0) {
211 | [self transitionFromIndex:fromIndex toIndex:toIndex progress:progress];
212 | }
213 | }
214 |
215 | - (void)scrollToItemAtIndex:(NSInteger)index atScrollPosition:(UICollectionViewScrollPosition)scrollPosition animated:(BOOL)animated {
216 | [_collectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:index inSection:0] atScrollPosition:scrollPosition animated:animated];
217 | }
218 |
219 | - (CGFloat)cellWidthForTitle:(NSString *)title {
220 | if (!title) {
221 | return CGSizeZero.width;
222 | }
223 | //iOS 7
224 | CGRect frame = [title boundingRectWithSize:CGSizeMake(1000, 1000) options:NSStringDrawingTruncatesLastVisibleLine | NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading attributes:@{ NSFontAttributeName:self.layout.selectedTextFont} context:nil];
225 | return CGSizeMake(ceil(frame.size.width), ceil(frame.size.height) + 1).width;
226 | }
227 |
228 | #pragma mark - UICollectionViewDataSource
229 |
230 | - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
231 | {
232 | _countOfItems = [_dataSource numberOfItemsInPagerTabBar];
233 | return _countOfItems;
234 | }
235 |
236 | - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
237 | {
238 | UICollectionViewCell *cell = [_dataSource pagerTabBar:self cellForItemAtIndex:indexPath.item];
239 | [self.layout transitionFromCell:(indexPath.item == _curIndex ? nil : cell) toCell:(indexPath.item == _curIndex ? cell : nil) animate:NO];
240 | return cell;
241 | }
242 |
243 | #pragma mark - UICollectionViewDelegateFlowLayout
244 |
245 | - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
246 | {
247 | if ([_delegate respondsToSelector:@selector(pagerTabBar:didSelectItemAtIndex:)]) {
248 | [_delegate pagerTabBar:self didSelectItemAtIndex:indexPath.item];
249 | }
250 | }
251 |
252 | - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
253 | {
254 | if (self.layout.cellWidth > 0) {
255 | return CGSizeMake(self.layout.cellWidth+self.layout.cellEdging*2, CGRectGetHeight(_collectionView.frame));
256 | }else if(_delegateFlags.widthForItemAtIndex){
257 | CGFloat width = [_delegate pagerTabBar:self widthForItemAtIndex:indexPath.item]+self.layout.cellEdging*2;
258 | return CGSizeMake(width, CGRectGetHeight(_collectionView.frame));
259 | }else {
260 | NSAssert(NO, @"you must return cell width!");
261 | }
262 | return CGSizeZero;
263 | }
264 |
265 | #pragma mark - transition cell
266 |
267 | - (void)transitionFromIndex:(NSInteger)fromIndex toIndex:(NSInteger)toIndex animated:(BOOL)animated
268 | {
269 | UICollectionViewCell *fromCell = [self cellForIndex:fromIndex];
270 | UICollectionViewCell *toCell = [self cellForIndex:toIndex];
271 | if (_delegateFlags.transitionFromeCellAnimated) {
272 | [_delegate pagerTabBar:self transitionFromeCell:fromCell toCell:toCell animated:animated];
273 | }else {
274 | [self.layout transitionFromCell:fromCell toCell:toCell animate:animated];
275 | }
276 | [self.layout setUnderLineFrameWithIndex:toIndex animated:fromCell && animated ? animated: NO];
277 | }
278 |
279 | - (void)transitionFromIndex:(NSInteger)fromIndex toIndex:(NSInteger)toIndex progress:(CGFloat)progress
280 | {
281 | UICollectionViewCell *fromCell = [self cellForIndex:fromIndex];
282 | UICollectionViewCell *toCell = [self cellForIndex:toIndex];
283 | if (_delegateFlags.transitionFromeCellProgress) {
284 | [_delegate pagerTabBar:self transitionFromeCell:fromCell toCell:toCell progress:progress];
285 | }else {
286 | [self.layout transitionFromCell:fromCell toCell:toCell progress:progress];
287 | }
288 | [self.layout setUnderLineFrameWithfromIndex:fromIndex toIndex:toIndex progress:progress];
289 | }
290 |
291 | -(void)layoutSubviews {
292 | [super layoutSubviews];
293 | _backgroundView.frame = self.bounds;
294 | CGRect frame = UIEdgeInsetsInsetRect(self.bounds, _contentInset);
295 | BOOL needUpdateLayout = (frame.size.height > 0 && _collectionView.frame.size.height != frame.size.height) || (frame.size.width > 0 && _collectionView.frame.size.width != frame.size.width);
296 | _collectionView.frame = frame;
297 | if (!_didLayoutSubViews && !CGRectIsEmpty(_collectionView.frame)) {
298 | _didLayoutSubViews = YES;
299 | }
300 | if (needUpdateLayout) {
301 | [_layout invalidateLayout];
302 | }
303 | if (frame.size.height > 0 && frame.size.width > 0) {
304 | [_layout adjustContentCellsCenterInBar];
305 | }
306 | _isFirstLayout = NO;
307 | [_layout layoutSubViews];
308 | }
309 |
310 | - (void)dealloc {
311 | _collectionView.dataSource = nil;
312 | _collectionView.delegate = nil;
313 | }
314 |
315 | @end
316 |
--------------------------------------------------------------------------------
/TYPagerControllerDemo/TYPagerController/TabPager/TYTabPagerBarLayout.m:
--------------------------------------------------------------------------------
1 | //
2 | // TYTabPagerBarLayout.m
3 | // TYPagerControllerDemo
4 | //
5 | // Created by tanyang on 2017/7/17.
6 | // Copyright © 2017年 tany. All rights reserved.
7 | //
8 |
9 | #import "TYTabPagerBarLayout.h"
10 | #import "TYTabPagerBar.h"
11 |
12 | @interface TYTabPagerBarLayout ()
13 |
14 | @property (nonatomic, weak) TYTabPagerBar *pagerTabBar;
15 |
16 | @property (nonatomic, assign) CGFloat selectFontScale;
17 |
18 | @end
19 |
20 | #define kUnderLineViewHeight 2
21 |
22 | @implementation TYTabPagerBarLayout
23 |
24 | - (instancetype)initWithPagerTabBar:(TYTabPagerBar *)pagerTabBar {
25 | if (self = [super init]) {
26 | _pagerTabBar = pagerTabBar;
27 | [self configurePropertys];
28 | self.barStyle = TYPagerBarStyleProgressElasticView;
29 | }
30 | return self;
31 | }
32 |
33 | - (void)configurePropertys {
34 | _cellSpacing = 2;
35 | _cellEdging = 3;
36 | _cellWidth = 0;
37 | _progressHorEdging = 6;
38 | _progressWidth = 0;
39 | _animateDuration = 0.25;
40 |
41 | _normalTextFont = [UIFont systemFontOfSize:15];
42 | _selectedTextFont = [UIFont systemFontOfSize:18];
43 | _normalTextColor = [UIColor colorWithRed:51/255.0 green:51/255.0 blue:51/255.0 alpha:1];
44 | _selectedTextColor = [UIColor redColor];
45 | _textColorProgressEnable = YES;
46 | //_adjustContentCellsCenter = YES;
47 | }
48 |
49 | #pragma mark - geter setter
50 |
51 | - (void)setProgressRadius:(CGFloat)progressRadius {
52 | _progressRadius = progressRadius;
53 | _pagerTabBar.progressView.layer.cornerRadius = progressRadius;
54 | }
55 |
56 | - (void)setProgressBorderWidth:(CGFloat)progressBorderWidth {
57 | _progressBorderWidth = progressBorderWidth;
58 | _pagerTabBar.progressView.layer.borderWidth = progressBorderWidth;
59 | }
60 |
61 | - (void)setProgressBorderColor:(UIColor *)progressBorderColor {
62 | _progressBorderColor = progressBorderColor;
63 | if (!_progressColor) {
64 | _pagerTabBar.progressView.backgroundColor = [UIColor clearColor];
65 | }
66 | _pagerTabBar.progressView.layer.borderColor = progressBorderColor.CGColor;
67 | }
68 |
69 | - (void)setProgressColor:(UIColor *)progressColor {
70 | _progressColor = progressColor;
71 | _pagerTabBar.progressView.backgroundColor = progressColor;
72 | }
73 |
74 | - (void)setProgressHeight:(CGFloat)progressHeight {
75 | _progressHeight = progressHeight;
76 | CGRect frame = _pagerTabBar.progressView.frame;
77 | CGFloat height = CGRectGetHeight(_pagerTabBar.collectionView.frame);
78 | frame.origin.y = _barStyle == TYPagerBarStyleCoverView ? (height - _progressHeight)/2:(height - _progressHeight - _progressVerEdging);
79 | frame.size.height = progressHeight;
80 | _pagerTabBar.progressView.frame = frame;
81 | }
82 |
83 | - (UIEdgeInsets)sectionInset {
84 | if (!UIEdgeInsetsEqualToEdgeInsets(_sectionInset, UIEdgeInsetsZero) || _barStyle != TYPagerBarStyleCoverView) {
85 | return _sectionInset;
86 | }
87 | if (_barStyle == TYPagerBarStyleCoverView && _adjustContentCellsCenter) {
88 | return _sectionInset;
89 | }
90 | CGFloat horEdging = -_progressHorEdging+_cellSpacing;
91 | return UIEdgeInsetsMake(0, horEdging, 0, horEdging);
92 | }
93 |
94 | - (void)setAdjustContentCellsCenter:(BOOL)adjustContentCellsCenter {
95 | BOOL change = _adjustContentCellsCenter != adjustContentCellsCenter;
96 | _adjustContentCellsCenter = adjustContentCellsCenter;
97 | if (change && _pagerTabBar.superview) {
98 | [_pagerTabBar setNeedsLayout];
99 | }
100 | }
101 |
102 | - (void)setBarStyle:(TYPagerBarStyle)barStyle
103 | {
104 | if (barStyle == _barStyle) {
105 | return;
106 | }
107 | if (_barStyle == TYPagerBarStyleCoverView) {
108 | self.progressBorderWidth = 0;
109 | self.progressBorderColor = nil;
110 | }
111 | _barStyle = barStyle;
112 | switch (barStyle) {
113 | case TYPagerBarStyleProgressView:
114 | self.progressWidth = 0;
115 | self.progressHorEdging = 6;
116 | self.progressVerEdging = 0;
117 | self.progressHeight = kUnderLineViewHeight;
118 | break;
119 | case TYPagerBarStyleProgressBounceView:
120 | case TYPagerBarStyleProgressElasticView:
121 | self.progressWidth = 30;
122 | self.progressVerEdging = 0;
123 | self.progressHorEdging = 0;
124 | self.progressHeight = kUnderLineViewHeight;
125 | break;
126 | case TYPagerBarStyleCoverView:
127 | self.progressWidth = 0;
128 | self.progressHorEdging = -self.progressHeight/4;
129 | self.progressVerEdging = 3;
130 | break;
131 | default:
132 | break;
133 | }
134 | _pagerTabBar.progressView.hidden = barStyle == TYPagerBarStyleNoneView;
135 | if (barStyle == TYPagerBarStyleCoverView) {
136 | _progressRadius = 0;
137 | _pagerTabBar.progressView.layer.zPosition = -1;
138 | [_pagerTabBar.progressView removeFromSuperview];
139 | [_pagerTabBar.collectionView insertSubview: _pagerTabBar.progressView atIndex:0];
140 | }else {
141 | self.progressRadius = _progressHeight/2;
142 | if (_pagerTabBar.progressView.layer.zPosition == -1) {
143 | _pagerTabBar.progressView.layer.zPosition = 0;
144 | [_pagerTabBar.progressView removeFromSuperview];
145 | [_pagerTabBar.collectionView addSubview:_pagerTabBar.progressView];
146 | }
147 |
148 | }
149 | }
150 |
151 | #pragma mark - public
152 |
153 | - (void)layoutIfNeed {
154 | UICollectionViewFlowLayout *collectionLayout = (UICollectionViewFlowLayout *)_pagerTabBar.collectionView.collectionViewLayout;
155 | collectionLayout.minimumLineSpacing = _cellSpacing;
156 | collectionLayout.minimumInteritemSpacing = _cellSpacing;
157 | _selectFontScale = self.normalTextFont.pointSize/(self.selectedTextFont ? self.selectedTextFont.pointSize:self.normalTextFont.pointSize);
158 | collectionLayout.sectionInset = _sectionInset;
159 | }
160 |
161 | - (void)invalidateLayout {
162 | [_pagerTabBar.collectionView.collectionViewLayout invalidateLayout];
163 | }
164 |
165 | - (void)adjustContentCellsCenterInBar {
166 | if (!_adjustContentCellsCenter || !_pagerTabBar.superview) {
167 | return;
168 | }
169 | CGRect frame = self.pagerTabBar.collectionView.frame;
170 | if (CGRectIsEmpty(frame)) {
171 | return;
172 | }
173 |
174 | UICollectionViewFlowLayout *collectionLayout = (UICollectionViewFlowLayout *)_pagerTabBar.collectionView.collectionViewLayout;
175 | CGSize contentSize = collectionLayout.collectionViewContentSize;
176 | NSArray *layoutAttribulte = [collectionLayout layoutAttributesForElementsInRect:CGRectMake(0, 0, MAX(contentSize.width, CGRectGetWidth(frame)), MAX(contentSize.height,CGRectGetHeight(frame)))];
177 | if (layoutAttribulte.count == 0) {
178 | return;
179 | }
180 |
181 | UICollectionViewLayoutAttributes *firstAttribute = layoutAttribulte.firstObject;
182 | UICollectionViewLayoutAttributes *lastAttribute = layoutAttribulte.lastObject;
183 | CGFloat left = CGRectGetMinX(firstAttribute.frame);
184 | CGFloat right = CGRectGetMaxX(lastAttribute.frame);
185 | if (right - left > CGRectGetWidth(self.pagerTabBar.frame)) {
186 | return;
187 | }
188 | CGFloat sapce = (CGRectGetWidth(self.pagerTabBar.frame) - (right - left))/2;
189 | _sectionInset = UIEdgeInsetsMake(_sectionInset.top, sapce, _sectionInset.bottom, sapce);
190 | collectionLayout.sectionInset = _sectionInset;
191 | }
192 |
193 | - (CGRect)cellFrameWithIndex:(NSInteger)index {
194 | return [_pagerTabBar cellFrameWithIndex:index];
195 | }
196 |
197 | #pragma mark - cell
198 |
199 | - (void)transitionFromCell:(UICollectionViewCell *)fromCell toCell:(UICollectionViewCell *)toCell animate:(BOOL)animate {
200 | if (_pagerTabBar.countOfItems == 0) {
201 | return;
202 | }
203 | void (^animateBlock)() = ^{
204 | if (fromCell) {
205 | fromCell.titleLabel.font = _normalTextFont;
206 | fromCell.titleLabel.textColor = _normalTextColor;
207 | fromCell.transform = CGAffineTransformMakeScale(_selectFontScale, _selectFontScale);
208 | }
209 | if (toCell) {
210 | toCell.titleLabel.font = _normalTextFont;
211 | toCell.titleLabel.textColor = _selectedTextColor ? _selectedTextColor : _normalTextColor;
212 | toCell.transform = CGAffineTransformIdentity;
213 | }
214 | };
215 | if (animate) {
216 | [UIView animateWithDuration:_animateDuration animations:^{
217 | animateBlock();
218 | }];
219 | }else{
220 | animateBlock();
221 | }
222 |
223 | }
224 |
225 | - (void)transitionFromCell:(UICollectionViewCell *)fromCell toCell:(UICollectionViewCell *)toCell progress:(CGFloat)progress {
226 | if (_pagerTabBar.countOfItems == 0 || !_textColorProgressEnable) {
227 | return;
228 | }
229 | CGFloat currentTransform = (1.0 - _selectFontScale)*progress;
230 | fromCell.transform = CGAffineTransformMakeScale(1.0-currentTransform, 1.0-currentTransform);
231 | toCell.transform = CGAffineTransformMakeScale(_selectFontScale+currentTransform, _selectFontScale+currentTransform);
232 |
233 | if (_normalTextColor == _selectedTextColor || !_selectedTextColor) {
234 | return;
235 | }
236 |
237 | CGFloat narR=0,narG=0,narB=0,narA=1;
238 | [_normalTextColor getRed:&narR green:&narG blue:&narB alpha:&narA];
239 | CGFloat selR=0,selG=0,selB=0,selA=1;
240 | [_selectedTextColor getRed:&selR green:&selG blue:&selB alpha:&selA];
241 | CGFloat detalR = narR - selR ,detalG = narG - selG,detalB = narB - selB,detalA = narA - selA;
242 |
243 | fromCell.titleLabel.textColor = [UIColor colorWithRed:selR+detalR*progress green:selG+detalG*progress blue:selB+detalB*progress alpha:selA+detalA*progress];
244 | toCell.titleLabel.textColor = [UIColor colorWithRed:narR-detalR*progress green:narG-detalG*progress blue:narB-detalB*progress alpha:narA-detalA*progress];
245 | }
246 |
247 | #pragma mark - progress View
248 |
249 | // set up progress view frame
250 | - (void)setUnderLineFrameWithIndex:(NSInteger)index animated:(BOOL)animated
251 | {
252 | UIView *progressView = _pagerTabBar.progressView;
253 | if (progressView.isHidden || _pagerTabBar.countOfItems == 0) {
254 | return;
255 | }
256 |
257 | CGRect cellFrame = [self cellFrameWithIndex:index];
258 | CGFloat progressHorEdging = _progressWidth > 0 ? (cellFrame.size.width - _progressWidth)/2 : _progressHorEdging;
259 | CGFloat progressX = cellFrame.origin.x+progressHorEdging;
260 | CGFloat progressY = _barStyle == TYPagerBarStyleCoverView ? (cellFrame.size.height - _progressHeight)/2:(cellFrame.size.height - _progressHeight - _progressVerEdging);
261 | CGFloat width = cellFrame.size.width-2*progressHorEdging;
262 |
263 | if (animated) {
264 | [UIView animateWithDuration:_animateDuration animations:^{
265 | progressView.frame = CGRectMake(progressX, progressY, width, _progressHeight);
266 | }];
267 | }else {
268 | progressView.frame = CGRectMake(progressX, progressY, width, _progressHeight);
269 | }
270 | }
271 |
272 | - (void)setUnderLineFrameWithfromIndex:(NSInteger)fromIndex toIndex:(NSInteger)toIndex progress:(CGFloat)progress
273 | {
274 | UIView *progressView = _pagerTabBar.progressView;
275 | if (progressView.isHidden || _pagerTabBar.countOfItems == 0) {
276 | return;
277 | }
278 |
279 | CGRect fromCellFrame = [self cellFrameWithIndex:fromIndex];
280 | CGRect toCellFrame = [self cellFrameWithIndex:toIndex];
281 |
282 | CGFloat progressFromEdging = _progressWidth > 0 ? (fromCellFrame.size.width - _progressWidth)/2 : _progressHorEdging;
283 | CGFloat progressToEdging = _progressWidth > 0 ? (toCellFrame.size.width - _progressWidth)/2 : _progressHorEdging;
284 | CGFloat progressY = _barStyle == TYPagerBarStyleCoverView ? (toCellFrame.size.height - _progressHeight)/2:(toCellFrame.size.height - _progressHeight - _progressVerEdging);
285 | CGFloat progressX = 0, width = 0;
286 |
287 | if (_barStyle == TYPagerBarStyleProgressBounceView) {
288 | if (fromCellFrame.origin.x < toCellFrame.origin.x) {
289 | if (progress <= 0.5) {
290 | progressX = fromCellFrame.origin.x + progressFromEdging;
291 | width = (toCellFrame.size.width-progressToEdging+progressFromEdging+_cellSpacing)*2*progress + fromCellFrame.size.width-2*progressFromEdging;
292 | }else {
293 | progressX = fromCellFrame.origin.x + progressFromEdging + (fromCellFrame.size.width-progressFromEdging+progressToEdging+_cellSpacing)*(progress-0.5)*2;
294 | width = CGRectGetMaxX(toCellFrame)-progressToEdging - progressX;
295 | }
296 | }else {
297 | if (progress <= 0.5) {
298 | progressX = fromCellFrame.origin.x + progressFromEdging - (toCellFrame.size.width-progressToEdging+progressFromEdging+_cellSpacing)*2*progress;
299 | width = CGRectGetMaxX(fromCellFrame) - progressFromEdging - progressX;
300 | }else {
301 | progressX = toCellFrame.origin.x + progressToEdging;
302 | width = (fromCellFrame.size.width-progressFromEdging+progressToEdging + _cellSpacing)*(1-progress)*2 + toCellFrame.size.width - 2*progressToEdging;
303 | }
304 | }
305 | }else if (_barStyle == TYPagerBarStyleProgressElasticView) {
306 | if (fromCellFrame.origin.x < toCellFrame.origin.x) {
307 | if (progress <= 0.5) {
308 | progressX = fromCellFrame.origin.x + progressFromEdging + (fromCellFrame.size.width-2*progressFromEdging)*progress;
309 | width = (toCellFrame.size.width-progressToEdging+progressFromEdging+_cellSpacing)*2*progress - (toCellFrame.size.width-2*progressToEdging)*progress + fromCellFrame.size.width-2*progressFromEdging-(fromCellFrame.size.width-2*progressFromEdging)*progress;
310 | }else {
311 | progressX = fromCellFrame.origin.x + progressFromEdging + (fromCellFrame.size.width-2*progressFromEdging)*0.5 + (fromCellFrame.size.width-progressFromEdging - (fromCellFrame.size.width-2*progressFromEdging)*0.5 +progressToEdging+_cellSpacing)*(progress-0.5)*2;
312 | width = CGRectGetMaxX(toCellFrame)-progressToEdging - progressX - (toCellFrame.size.width-2*progressToEdging)*(1-progress);
313 | }
314 | }else {
315 | if (progress <= 0.5) {
316 | progressX = fromCellFrame.origin.x + progressFromEdging - (toCellFrame.size.width-(toCellFrame.size.width-2*progressToEdging)/2-progressToEdging+progressFromEdging+_cellSpacing)*2*progress;
317 | width = CGRectGetMaxX(fromCellFrame) - (fromCellFrame.size.width-2*progressFromEdging)*progress - progressFromEdging - progressX;
318 | }else {
319 | progressX = toCellFrame.origin.x + progressToEdging+(toCellFrame.size.width-2*progressToEdging)*(1-progress);
320 | width = (fromCellFrame.size.width-progressFromEdging+progressToEdging-(fromCellFrame.size.width-2*progressFromEdging)/2 + _cellSpacing)*(1-progress)*2 + toCellFrame.size.width - 2*progressToEdging - (toCellFrame.size.width-2*progressToEdging)*(1-progress);
321 | }
322 | }
323 | }else {
324 | progressX = (toCellFrame.origin.x+progressToEdging-(fromCellFrame.origin.x+progressFromEdging))*progress+fromCellFrame.origin.x+progressFromEdging;
325 | width = (toCellFrame.size.width-2*progressToEdging)*progress + (fromCellFrame.size.width-2*progressFromEdging)*(1-progress);
326 | }
327 |
328 | progressView.frame = CGRectMake(progressX,progressY, width, _progressHeight);
329 | }
330 |
331 | - (void)layoutSubViews {
332 | if (CGRectIsEmpty(_pagerTabBar.frame)) {
333 | return;
334 | }
335 | if (_barStyle == TYPagerBarStyleCoverView) {
336 | self.progressHeight = CGRectGetHeight(_pagerTabBar.collectionView.frame) -self.progressVerEdging*2;
337 | self.progressRadius = _progressRadius > 0 ? _progressRadius : self.progressHeight/2;
338 | }
339 | [self setUnderLineFrameWithIndex:_pagerTabBar.curIndex animated:NO];
340 | }
341 |
342 | @end
343 |
--------------------------------------------------------------------------------