├── .gitignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── README_zh-CN.md ├── WMPageController.podspec ├── WMPageController ├── UIViewController+WMPageController.h ├── UIViewController+WMPageController.m ├── WMMenuView │ ├── WMMenuItem.h │ ├── WMMenuItem.m │ ├── WMMenuView.h │ ├── WMMenuView.m │ ├── WMProgressView.h │ ├── WMProgressView.m │ ├── WMScrollView.h │ └── WMScrollView.m ├── WMPageController.h └── WMPageController.m └── WMPageControllerDemo ├── Overview.gif ├── StickyExample ├── Podfile ├── Podfile.lock ├── Pods │ ├── Headers │ │ ├── Private │ │ │ └── WMPageController │ │ │ │ ├── UIViewController+WMPageController.h │ │ │ │ ├── WMMenuItem.h │ │ │ │ ├── WMMenuView.h │ │ │ │ ├── WMPageController.h │ │ │ │ ├── WMProgressView.h │ │ │ │ └── WMScrollView.h │ │ └── Public │ │ │ └── WMPageController │ │ │ ├── UIViewController+WMPageController.h │ │ │ ├── WMMenuItem.h │ │ │ ├── WMMenuView.h │ │ │ ├── WMPageController.h │ │ │ ├── WMProgressView.h │ │ │ └── WMScrollView.h │ ├── Local Podspecs │ │ └── WMPageController.podspec.json │ ├── Manifest.lock │ ├── Pods.xcodeproj │ │ └── project.pbxproj │ └── Target Support Files │ │ ├── Pods-StickyExample │ │ ├── Pods-StickyExample-acknowledgements.markdown │ │ ├── Pods-StickyExample-acknowledgements.plist │ │ ├── Pods-StickyExample-dummy.m │ │ ├── Pods-StickyExample-frameworks.sh │ │ ├── Pods-StickyExample-resources.sh │ │ ├── Pods-StickyExample.debug.xcconfig │ │ └── Pods-StickyExample.release.xcconfig │ │ ├── Pods-StickyExampleTests │ │ ├── Pods-StickyExampleTests-acknowledgements.markdown │ │ ├── Pods-StickyExampleTests-acknowledgements.plist │ │ ├── Pods-StickyExampleTests-dummy.m │ │ ├── Pods-StickyExampleTests-frameworks.sh │ │ ├── Pods-StickyExampleTests-resources.sh │ │ ├── Pods-StickyExampleTests.debug.xcconfig │ │ └── Pods-StickyExampleTests.release.xcconfig │ │ ├── Pods-StickyExampleUITests │ │ ├── Pods-StickyExampleUITests-acknowledgements.markdown │ │ ├── Pods-StickyExampleUITests-acknowledgements.plist │ │ ├── Pods-StickyExampleUITests-dummy.m │ │ ├── Pods-StickyExampleUITests-frameworks.sh │ │ ├── Pods-StickyExampleUITests-resources.sh │ │ ├── Pods-StickyExampleUITests.debug.xcconfig │ │ └── Pods-StickyExampleUITests.release.xcconfig │ │ └── WMPageController │ │ ├── WMPageController-dummy.m │ │ ├── WMPageController-prefix.pch │ │ └── WMPageController.xcconfig ├── StickyExample.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── StickyExample.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── StickyExample │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── Assets.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── Base.lproj │ │ └── LaunchScreen.storyboard │ ├── Controllers │ │ ├── WMDetailViewController.h │ │ ├── WMDetailViewController.m │ │ ├── WMHomeViewController.h │ │ ├── WMHomeViewController.m │ │ ├── WMTableViewController.h │ │ └── WMTableViewController.m │ ├── Info.plist │ ├── WMStickyPageController │ │ ├── WMMagicScrollView.h │ │ ├── WMMagicScrollView.m │ │ ├── WMStickyPageController.h │ │ └── WMStickyPageController.m │ └── main.m ├── StickyExampleTests │ ├── Info.plist │ └── StickyExampleTests.m └── StickyExampleUITests │ ├── Info.plist │ └── StickyExampleUITests.m ├── StoryboardExample ├── Storyboard.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ └── contents.xcworkspacedata ├── Storyboard │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── Assets.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ ├── Controller │ │ ├── WMViewController.h │ │ └── WMViewController.m │ ├── CustomPageViewController.h │ ├── CustomPageViewController.m │ ├── Info.plist │ └── main.m ├── StoryboardTests │ ├── Info.plist │ └── StoryboardTests.m └── StoryboardUITests │ ├── Info.plist │ └── StoryboardUITests.m ├── ViewFrameExample ├── ViewFrameDemo.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ └── contents.xcworkspacedata ├── ViewFrameDemo │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── Assets.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ ├── Controllers │ │ ├── WMHomeViewController.h │ │ ├── WMHomeViewController.m │ │ ├── WMTableViewController.h │ │ └── WMTableViewController.m │ ├── Gesture │ │ ├── WMPanGestureRecognizer.h │ │ └── WMPanGestureRecognizer.m │ ├── Info.plist │ └── main.m └── ViewFrameDemoUITests │ ├── Info.plist │ └── ViewFrameDemoUITests.m └── WMPageControllerExample ├── WMPageControllerExample.xcodeproj ├── project.pbxproj └── project.xcworkspace │ └── contents.xcworkspacedata ├── WMPageControllerExample ├── AppDelegate.h ├── AppDelegate.m ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ └── Contents.json ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard ├── Controller │ ├── WMCollectionViewController.h │ ├── WMCollectionViewController.m │ ├── WMSecondViewController.h │ ├── WMSecondViewController.m │ ├── WMTableViewController.h │ ├── WMTableViewController.m │ ├── WMViewController.h │ └── WMViewController.m ├── Images │ ├── Dragon Spirit.jpg │ ├── Night.jpg │ ├── The roar.jpg │ ├── github.png │ ├── hitMark.jpg │ ├── onepiece.jpg │ ├── three.jpg │ └── zoro.jpg ├── Info.plist ├── Views │ ├── WMImageViewCell.h │ ├── WMImageViewCell.m │ ├── WMLoopView.h │ └── WMLoopView.m ├── WMCustomizedPageController.h ├── WMCustomizedPageController.m ├── WMMainTableViewController.h ├── WMMainTableViewController.m └── main.m ├── WMPageControllerExampleTests ├── Info.plist └── WMPageControllerExampleTests.m └── WMPageControllerExampleUITests ├── Info.plist └── WMPageControllerExampleUITests.m /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | build/ 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | xcuserdata 13 | *.xccheckout 14 | *.moved-aside 15 | DerivedData 16 | *.hmap 17 | *.ipa 18 | *.xcuserstate 19 | 20 | # CocoaPods 21 | # 22 | # We recommend against adding the Pods directory to your .gitignore. However 23 | # you should judge for yourself, the pros and cons are mentioned at: 24 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control 25 | # 26 | # Pods/ 27 | 28 | # Carthage 29 | # 30 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 31 | # Carthage/Checkouts 32 | 33 | Carthage/Build 34 | 35 | *.DS_Store 36 | 37 | *.xcbkptlist 38 | 39 | *.xcuserstate 40 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## [2.5.0 [Adapt iOS 11]]() 2 | ### Adapt iOS 11 when .showOnNavigationBar = YES 3 | ```objective-c 4 | // Wait for a better solution 5 | - (void)setFrame:(CGRect)frame { 6 | // Adapt iOS 11 if is a titleView 7 | if (@available(iOS 11.0, *)) { 8 | if (self.showOnNavigationBar) { frame.origin.x = 0; } 9 | } 10 | 11 | [super setFrame:frame]; 12 | // ... 13 | // ... 14 | } 15 | ``` 16 | 17 | ## [2.4.3 [BUGFIXS]]() 18 | ### Remove observer / Cancel performSelector when dealloc. 19 | ### -initWithNib supoort. 20 | 21 | ## [2.4.1 [BUGFIXS]](https://github.com/wangmchn/WMPageController/releases/tag/2.4.1) 22 | ### FIX [#286](https://github.com/wangmchn/WMPageController/issues/286), Layout Stragety adjusted. 23 | 24 | - Now: WMPageController will layout every time when `-viewDidLayoutSubviews` called. 25 | - Before: Early returned if `self.view.frame.size.height` is not changed. 26 | 27 | ## [2.4.0 [API CHANGED][BETA]]() 28 | **[IMPORTANT] WMPAGECONTROLLER ARE NO LONGER ADAPT VIEW'S FRAMES & SOME GESTURES CONFLICTS!!** 29 | ### [DELETE] Some properties have been deleted. 30 | - `viewFrame / menuHeight / menuBGColor / menuViewBottomSpace / otherGestureRecognizerSimultaneously` 31 | ### [ADD] Two datasource methods have been added. 32 | - `-pageController:preferredFrameForMenuView:` 33 | - `-pageController:preferredFrameForContentView:` 34 | ### [GUIDE] 35 | - If you want a right frame of menuView or contentView, implement `-pageController:preferredFrameForMenuView: & -pageController:preferredFrameForContentView:` methods and give WMPageController a right frame. 36 | - Call `-forceLayoutSubViews` to re-layout view's frames, these will recall the datasource methods above. 37 | - Change menuView's backgroundColor by setting `self.menuView.backgroundColor = perferredColor` directly.(AFTER THE VIEW IS LOADED, e.g. in viewDidLoad) 38 | - Deal gesture's conflicts by implement `UIGestureRecognizerDelegate` IF NEEDED, see [UIGestureRecognizerDelegate](https://developer.apple.com/documentation/uikit/uigesturerecognizerdelegate) for more information. 39 | 40 | ## [1.0.0 ~ 2.3.1 [OLD VERSION]]() 41 | **OLD VERSION & NO LONGER MAINTAIN** 42 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # WMPageController [中文介绍](https://github.com/wangmchn/WMPageController/blob/master/README_zh-CN.md) 2 | [![Platform](http://img.shields.io/badge/platform-iOS-blue.svg?style=flat 3 | )](https://developer.apple.com/iphone/index.action) 4 | [![License](http://img.shields.io/badge/license-MIT-lightgrey.svg?style=flat 5 | )](http://mit-license.org) 6 | ![CocoaPods Version](https://img.shields.io/badge/pod-v0.36.4-brightgreen.svg) 7 | 8 | An easy solution to page controllers like `NetEase News` 9 | ## Overview 10 | 11 | 12 | ## Change Log 13 | See [CHANGELOG](https://github.com/wangmchn/WMPageController/blob/master/CHANGELOG.md) for more information. 14 | 15 | ## Basic use 16 | Create an controller extends from `WMPageController`.There are two ways to init the `WMPageController`: 17 | 18 | #### Init with Classes 19 | Use the following constructor to init the controller: 20 | ```objective-c 21 | - (instancetype)initWithViewControllerClasses:(NSArray *)classes 22 | andTheirTitles:(NSArray *)titles; 23 | ``` 24 | Here are two important porperties: 25 | 26 | classes :contains the classes of child view controllers, just like [UITableViewController class]; 27 | titles :Each View controller's title to show in the menu view at the top of the view; 28 | 29 | #### Use datasource (Recommend This Way!) 30 | The usage is very familiar to `UITableView`, these are the methods need to implement: 31 | ```objective-c 32 | - (NSInteger)numbersOfChildControllersInPageController:(WMPageController *)pageController; 33 | 34 | - (__kindof UIViewController *)pageController:(WMPageController *)pageController viewControllerAtIndex:(NSInteger)index; 35 | 36 | - (NSString *)pageController:(WMPageController *)pageController titleAtIndex:(NSInteger)index; 37 | ``` 38 | Just implement these datasource methods in YOUR WMPageController after initialize it. 39 | 40 | ## Customize Content's Frame 41 | It's easy for you to customize your controller as following, just implement these two datasource methods.
42 | ``` 43 | - (CGRect)pageController:(WMPageController *)pageController preferredFrameForContentView:(WMScrollView *)contentView; 44 | 45 | - (CGRect)pageController:(WMPageController *)pageController preferredFrameForMenuView:(WMMenuView *)menuView; 46 | ``` 47 | When you want to change the frame of contentView, you need to call `-forceLayoutSubViews` method. This will recall the datasource method above and re-layout subviews. 48 | If you are interested, see `viewFrameExample` for more detail. 49 | 50 | ## Use Storyboard / xib 51 | 1.If you init the `WMPageController` with child controller's class,override the `-init` method in `WMPageController's childViewController`, For example: 52 | ```objective-c 53 | - (instancetype)init { 54 | return [self initWithNibName:@"xxxViewController" bundle:nil]; 55 | } 56 | ``` 57 | 2.If you are using datasource, Just implement `-pageController:viewControllerAtIndex:` as following: 58 | ```objective-c 59 | - (UIViewController *)pageController:(WMPageController *)pageController viewControllerAtIndex:(NSInteger)index { 60 | UIStoryboard *sb = [UIStoryboard storyboardWithName:@"Main" bundle:nil]; 61 | UIViewController *vc = [sb instantiateViewControllerWithIdentifier:@"WMViewController"]; 62 | return vc; 63 | } 64 | ``` 65 | See `StoryboardExample` for more detail. 66 | 67 | ## Styles 68 | 69 | You can easily change style by setting `xxxPageController.style = WMMenuViewStyleLine`.
70 | If you want `menuView` to show on the navigation bar, set `.showOnNavigationBar = YES`; 71 | 72 | ## Using CocoaPods 73 | If you want the newest version, try 2.4.0 (This has some API modified) 74 | ``` 75 | pod 'WMPageController', '~> 2.4.0' 76 | ``` 77 | If you perfer the old, just use 2.3.0 and it's fine. 78 | ``` 79 | pod 'WMPageController', '2.3.0' 80 | ``` 81 | 82 | ## Note 83 | 1. If you have any trouble with content controller's frame or size,just try set `viewFrame` property, which make you free to customize your own size. 84 | 85 | 2. You can put every controller in `WMPageController`,But if you want have a `UICollectionViewController` in, please have an attention to `UICollectionViewController's` init method.
86 | You should override the `- init` to give `UICollectionViewController` a `UICollectionViewLayout`. 87 | Here is an example: 88 | ```objective-c 89 | - (instancetype)init { 90 | // init layout here... 91 | self = [self initWithCollectionViewLayout:layout]; 92 | if (self) { 93 | // insert code here... 94 | } 95 | return self; 96 | } 97 | ``` 98 | 99 | ## License 100 | This project is under MIT License. See LICENSE file for more information. 101 | -------------------------------------------------------------------------------- /README_zh-CN.md: -------------------------------------------------------------------------------- 1 | # 中文介绍 2 | 原谅我拙劣的英文 3 | 4 | ## Issue 须知 5 | 鉴于很多朋友在提 issue 的时候没有提供足够的信息,在此希望大家在提 issue 时能够包含下面信息: 6 | ``` 7 | 1. Xcode / iOS / WMPageController 的版本信息; 8 | 2. 编译错误或者运行时错误时,编译器提供的所有信息; 9 | 3. 你设置的关键的代码片段; (如果能够提供 demo 复现那就更好了,我就是懒-。-) 10 | 4. 其他任何你觉得有可能帮助的信息; 11 | ``` 12 | 以上信息会更好的帮助我改善这个项目(不要再提为什么我的xxx方法没用这样的问题了,没有信息我真的做不出判断😭)。 13 | 如果你有什么好的建议或者修改,非常欢迎提出 issue 或者直接发起 Pull request. 14 | 任何改进都非常欢迎:bug 修复, 拼写错误或者用词语法错误, 以及文档补充以及特性需求等等。期待你的贡献! 15 | 16 | ## 特性 17 | * 增加了缓存机制,对加载过的控制器进行缓存,当内存过高时自动清理缓存。 18 | * 可通过`itemMargin`和`itemsMargins`来定制顶部标题的间距,通过`viewFrame`来定制子控制器的`frame`属性。 19 | * 当标题宽度之和不足宽度时,自动计算并为顶部`item`添加间隙。 20 | * 适配横屏,当设备旋转时自动调整`frame`。 21 | * 可通过设置`itemsWidths`属性来设置不同的标题宽度,例如 `@[@(100),@(80),@(50).....]`; 22 | * 增加了`reload`功能,可以像网易新闻那样重新更新标题和控制器。 23 | * 新类型 `WMMenuViewStyleSegmented`, 用于实现 #120 24 | * 如果自动计算的大小有误,可以设置 viewFrame 来获得正确的子控制器大小! 25 | 26 | ## 使用 27 | 28 | 创建一个控制器继承自`WMPageController`, 可以通过两种方式来初始化控制器
29 | #### 通过 Class 创建 30 | 使用以下方法创建控制器: 31 | ```objective-c 32 | - (instancetype)initWithViewControllerClasses:(NSArray *)classes 33 | andTheirTitles:(NSArray *)titles; 34 | ``` 35 | 其中,`Classes`是要传人显示的控制器的类型,比如`[UITableViewController class]`, `titles`是要显示的控制对应的标题。 36 | #### 使用 datasource (推荐!) 37 | 使用方法和 UITableView 相似,在子类中实现以下数据源方法即可: 38 | ```objective-c 39 | - (NSInteger)numbersOfChildControllersInPageController:(WMPageController *)pageController; 40 | 41 | - (__kindof UIViewController *)pageController:(WMPageController *)pageController viewControllerAtIndex:(NSInteger)index; 42 | 43 | - (NSString *)pageController:(WMPageController *)pageController titleAtIndex:(NSInteger)index; 44 | ``` 45 | 46 | ## 使用 Storyboard / xib 47 | 1.如果用了 **-initWithViewControllerClasses: andTheirTitles:** 来初始化, 那么需要重写子控制器(子控制器是指你添加到 WMPageController 的控制器)的 `-init` 方法,例如: 48 | ```objective-c 49 | - (instancetype)init { 50 | return [self initWithNibName:@"xxxViewController" bundle:nil]; 51 | } 52 | ``` 53 | 2.如果使用 datasource,那么实现对应的数据源即可,例如: 54 | ```objective-c 55 | - (UIViewController *)pageController:(WMPageController *)pageController viewControllerAtIndex:(NSInteger)index { 56 | UIStoryboard *sb = [UIStoryboard storyboardWithName:@"Main" bundle:nil]; 57 | UIViewController *vc = [sb instantiateViewControllerWithIdentifier:@"WMViewController"]; 58 | return vc; 59 | } 60 | ``` 61 | 62 | ## Styles 63 | 现在有5种样式提供选择,可通过设置 `xxxPageController.style = WMMenuViewStyleLine` 来改变样式.
64 | 如果想要在 NavigationBar 上显示导航栏, 设置`.showOnNavigationBar = YES`即可。 65 | 66 | ## 使用Pod管理 67 | 最新版本是2.4.0,相比较2.3.0有一些 API 接口改动,谨慎选择(可以更加自由的定义 menuView 和 contentView 的 frame) 68 | 69 |    pod 'WMPageController', ~> '2.4.0' 70 | 71 | 使用旧的稳定版本: 72 | 73 |    pod 'WMPageController', ~> '2.3.0' 74 | 75 | ## 要点 76 | 1.如果你的控制器的位置或者大小出现了任何问题,试试设置下 `viewFrame` 这个属性可以帮助你自定义你的控制器大小及位置 77 | 78 | 2.如果需要传入 `UICollectionViewController`, 需要重写 `- init` 方法,来为`UICollectionViewController`提供一个 `UICollectionViewLayout`。 79 | 方式如下: 80 | ```objective-c 81 | - (instancetype)init { 82 | // init layout here... 83 | self = [self initWithCollectionViewLayout:layout]; 84 | if (self) { 85 | // insert code here... 86 | } 87 | return self; 88 | } 89 | ``` 90 | 91 | ## 许可 92 | 该项目使用 `MIT` 许可证,详情见 `LICENSE` 文件。 93 | -------------------------------------------------------------------------------- /WMPageController.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = "WMPageController" 3 | s.version = "2.5.2" 4 | s.summary = "An easy solution to page controllers like NetEase News" 5 | s.homepage = "https://github.com/wangmchn/WMPageController" 6 | s.license = 'MIT (LICENSE)' 7 | s.author = { "wangmchn" => "wangmchn@163.com" } 8 | s.source = { :git => "https://github.com/wangmchn/WMPageController.git", :tag => s.version.to_s } 9 | s.ios.deployment_target = '6.0' 10 | 11 | s.source_files = 'WMPageController/', 'WMPageController/**/*.{h,m}' 12 | 13 | s.frameworks = 'Foundation', 'CoreGraphics', 'UIKit' 14 | s.requires_arc = true 15 | end -------------------------------------------------------------------------------- /WMPageController/UIViewController+WMPageController.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIViewController+WMPageController.h 3 | // WMPageController 4 | // 5 | // Created by Mark on 15/6/11. 6 | // Copyright (c) 2015年 yq. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class WMPageController; 12 | 13 | @interface UIViewController (WMPageController) 14 | 15 | /** 16 | 获取控制器所在的WMPageController 17 | */ 18 | @property (nonatomic, nullable, strong, readonly) WMPageController *wm_pageController; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /WMPageController/UIViewController+WMPageController.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIViewController+WMPageController.m 3 | // WMPageController 4 | // 5 | // Created by Mark on 15/6/11. 6 | // Copyright (c) 2015年 yq. All rights reserved. 7 | // 8 | 9 | #import "UIViewController+WMPageController.h" 10 | #import "WMPageController.h" 11 | 12 | @implementation UIViewController (WMPageController) 13 | 14 | - (WMPageController *)wm_pageController { 15 | UIViewController *parentViewController = self.parentViewController; 16 | while (parentViewController) { 17 | if ([parentViewController isKindOfClass:[WMPageController class]]) { 18 | return (WMPageController *)parentViewController; 19 | } 20 | parentViewController = parentViewController.parentViewController; 21 | } 22 | return nil; 23 | } 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /WMPageController/WMMenuView/WMMenuItem.h: -------------------------------------------------------------------------------- 1 | // 2 | // WMMenuItem.h 3 | // WMPageController 4 | // 5 | // Created by Mark on 15/4/26. 6 | // Copyright (c) 2015年 yq. All rights reserved. 7 | // 8 | 9 | #import 10 | @class WMMenuItem; 11 | 12 | typedef NS_ENUM(NSUInteger, WMMenuItemState) { 13 | WMMenuItemStateSelected, 14 | WMMenuItemStateNormal, 15 | }; 16 | 17 | NS_ASSUME_NONNULL_BEGIN 18 | @protocol WMMenuItemDelegate 19 | @optional 20 | - (void)didPressedMenuItem:(WMMenuItem *)menuItem; 21 | @end 22 | 23 | @interface WMMenuItem : UILabel 24 | 25 | @property (nonatomic, assign) CGFloat rate; ///> 设置 rate, 并刷新标题状态 (0~1) 26 | @property (nonatomic, assign) CGFloat normalSize; ///> Normal状态的字体大小,默认大小为15 27 | @property (nonatomic, assign) CGFloat selectedSize; ///> Selected状态的字体大小,默认大小为18 28 | @property (nonatomic, strong) UIColor *normalColor; ///> Normal状态的字体颜色,默认为黑色 (可动画) 29 | @property (nonatomic, strong) UIColor *selectedColor; ///> Selected状态的字体颜色,默认为红色 (可动画) 30 | @property (nonatomic, assign) CGFloat speedFactor; ///> 进度条的速度因数,默认 15,越小越快, 必须大于0 31 | @property (nonatomic, nullable, weak) id delegate; 32 | @property (nonatomic, assign, readonly) BOOL selected; 33 | 34 | - (void)setSelected:(BOOL)selected withAnimation:(BOOL)animation; 35 | 36 | @end 37 | NS_ASSUME_NONNULL_END 38 | -------------------------------------------------------------------------------- /WMPageController/WMMenuView/WMMenuItem.m: -------------------------------------------------------------------------------- 1 | // 2 | // WMMenuItem.m 3 | // WMPageController 4 | // 5 | // Created by Mark on 15/4/26. 6 | // Copyright (c) 2015年 yq. All rights reserved. 7 | // 8 | 9 | #import "WMMenuItem.h" 10 | 11 | @implementation WMMenuItem { 12 | CGFloat _selectedRed, _selectedGreen, _selectedBlue, _selectedAlpha; 13 | CGFloat _normalRed, _normalGreen, _normalBlue, _normalAlpha; 14 | int _sign; 15 | CGFloat _gap; 16 | CGFloat _step; 17 | __weak CADisplayLink *_link; 18 | } 19 | 20 | #pragma mark - Public Methods 21 | - (instancetype)initWithFrame:(CGRect)frame { 22 | if (self = [super initWithFrame:frame]) { 23 | self.normalColor = [UIColor blackColor]; 24 | self.selectedColor = [UIColor blackColor]; 25 | self.normalSize = 15; 26 | self.selectedSize = 18; 27 | self.numberOfLines = 0; 28 | 29 | [self setupGestureRecognizer]; 30 | } 31 | return self; 32 | } 33 | 34 | - (CGFloat)speedFactor { 35 | if (_speedFactor <= 0) { 36 | _speedFactor = 15.0; 37 | } 38 | return _speedFactor; 39 | } 40 | 41 | - (void)setupGestureRecognizer { 42 | UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(touchUpInside:)]; 43 | [self addGestureRecognizer:tap]; 44 | } 45 | 46 | - (void)setSelected:(BOOL)selected withAnimation:(BOOL)animation { 47 | _selected = selected; 48 | if (!animation) { 49 | self.rate = selected ? 1.0 : 0.0; 50 | return; 51 | } 52 | _sign = (selected == YES) ? 1 : -1; 53 | _gap = (selected == YES) ? (1.0 - self.rate) : (self.rate - 0.0); 54 | _step = _gap / self.speedFactor; 55 | if (_link) { 56 | [_link invalidate]; 57 | } 58 | CADisplayLink *link = [CADisplayLink displayLinkWithTarget:self selector:@selector(rateChange)]; 59 | [link addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes]; 60 | _link = link; 61 | } 62 | 63 | - (void)rateChange { 64 | if (_gap > 0.000001) { 65 | _gap -= _step; 66 | if (_gap < 0.0) { 67 | self.rate = (int)(self.rate + _sign * _step + 0.5); 68 | return; 69 | } 70 | self.rate += _sign * _step; 71 | } else { 72 | self.rate = (int)(self.rate + 0.5); 73 | [_link invalidate]; 74 | _link = nil; 75 | } 76 | } 77 | 78 | // 设置rate,并刷新标题状态 79 | - (void)setRate:(CGFloat)rate { 80 | if (rate < 0.0 || rate > 1.0) { return; } 81 | _rate = rate; 82 | CGFloat r = _normalRed + (_selectedRed - _normalRed) * rate; 83 | CGFloat g = _normalGreen + (_selectedGreen - _normalGreen) * rate; 84 | CGFloat b = _normalBlue + (_selectedBlue - _normalBlue) * rate; 85 | CGFloat a = _normalAlpha + (_selectedAlpha - _normalAlpha) * rate; 86 | self.textColor = [UIColor colorWithRed:r green:g blue:b alpha:a]; 87 | CGFloat minScale = self.normalSize / self.selectedSize; 88 | CGFloat trueScale = minScale + (1 - minScale)*rate; 89 | self.transform = CGAffineTransformMakeScale(trueScale, trueScale); 90 | } 91 | 92 | - (void)setSelectedColor:(UIColor *)selectedColor { 93 | _selectedColor = selectedColor; 94 | [selectedColor getRed:&_selectedRed green:&_selectedGreen blue:&_selectedBlue alpha:&_selectedAlpha]; 95 | } 96 | 97 | - (void)setNormalColor:(UIColor *)normalColor { 98 | _normalColor = normalColor; 99 | [normalColor getRed:&_normalRed green:&_normalGreen blue:&_normalBlue alpha:&_normalAlpha]; 100 | } 101 | 102 | - (void)touchUpInside:(id)sender { 103 | if ([self.delegate respondsToSelector:@selector(didPressedMenuItem:)]) { 104 | [self.delegate didPressedMenuItem:self]; 105 | } 106 | } 107 | 108 | @end 109 | -------------------------------------------------------------------------------- /WMPageController/WMMenuView/WMMenuView.h: -------------------------------------------------------------------------------- 1 | // 2 | // WMMenuView.h 3 | // WMPageController 4 | // 5 | // Created by Mark on 15/4/26. 6 | // Copyright (c) 2015年 yq. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "WMMenuItem.h" 11 | #import "WMProgressView.h" 12 | #define WMUNDEFINED_VALUE -1 13 | 14 | @class WMMenuView; 15 | 16 | typedef NS_ENUM(NSUInteger, WMMenuViewStyle) { 17 | WMMenuViewStyleDefault, // 默认 18 | WMMenuViewStyleLine, // 带下划线 (若要选中字体大小不变,设置选中和非选中大小一样即可) 19 | WMMenuViewStyleTriangle, // 三角形 (progressHeight 为三角形的高, progressWidths 为底边长) 20 | WMMenuViewStyleFlood, // 涌入效果 (填充) 21 | WMMenuViewStyleFloodHollow, // 涌入效果 (空心的) 22 | WMMenuViewStyleSegmented, // 涌入带边框,即网易新闻选项卡 23 | }; 24 | 25 | // 原先基础上添加了几个方便布局的枚举,更多布局格式可以通过设置 `itemsMargins` 属性来自定义 26 | // 以下布局均只在 item 个数较少的情况下生效,即无法滚动 MenuView 时. 27 | typedef NS_ENUM(NSUInteger, WMMenuViewLayoutMode) { 28 | WMMenuViewLayoutModeScatter, // 默认的布局模式, item 会均匀分布在屏幕上,呈分散状 29 | WMMenuViewLayoutModeLeft, // Item 紧靠屏幕左侧 30 | WMMenuViewLayoutModeRight, // Item 紧靠屏幕右侧 31 | WMMenuViewLayoutModeCenter, // Item 紧挨且居中分布 32 | }; 33 | 34 | @protocol WMMenuViewDelegate 35 | @optional 36 | - (BOOL)menuView:(WMMenuView *)menu shouldSelesctedIndex:(NSInteger)index; 37 | - (void)menuView:(WMMenuView *)menu didSelectedIndex:(NSInteger)index currentIndex:(NSInteger)currentIndex; 38 | - (CGFloat)menuView:(WMMenuView *)menu widthForItemAtIndex:(NSInteger)index; 39 | - (CGFloat)menuView:(WMMenuView *)menu itemMarginAtIndex:(NSInteger)index; 40 | - (CGFloat)menuView:(WMMenuView *)menu titleSizeForState:(WMMenuItemState)state atIndex:(NSInteger)index; 41 | - (UIColor *)menuView:(WMMenuView *)menu titleColorForState:(WMMenuItemState)state atIndex:(NSInteger)index; 42 | - (void)menuView:(WMMenuView *)menu didLayoutItemFrame:(WMMenuItem *)menuItem atIndex:(NSInteger)index; 43 | @end 44 | 45 | @protocol WMMenuViewDataSource 46 | 47 | @required 48 | - (NSInteger)numbersOfTitlesInMenuView:(WMMenuView *)menu; 49 | - (NSString *)menuView:(WMMenuView *)menu titleAtIndex:(NSInteger)index; 50 | 51 | @optional 52 | /** 53 | * 角标 (例如消息提醒的小红点) 的数据源方法,在 WMPageController 中实现这个方法来为 menuView 提供一个 badgeView 54 | 需要在返回的时候同时设置角标的 frame 属性,该 frame 为相对于 menuItem 的位置 55 | * 56 | * @param index 角标的序号 57 | * 58 | * @return 返回一个设置好 frame 的角标视图 59 | */ 60 | - (UIView *)menuView:(WMMenuView *)menu badgeViewAtIndex:(NSInteger)index; 61 | 62 | /** 63 | * 用于定制 WMMenuItem,可以对传出的 initialMenuItem 进行修改定制,也可以返回自己创建的子类,需要注意的是,此时的 item 的 frame 是不确定的,所以请勿根据此时的 frame 做计算! 64 | 如需根据 frame 修改,请使用代理 65 | * 66 | * @param menu 当前的 menuView,frame 也是不确定的 67 | * @param initialMenuItem 初始化完成的 menuItem 68 | * @param index Item 所属的位置; 69 | * 70 | * @return 定制完成的 MenuItem 71 | */ 72 | - (WMMenuItem *)menuView:(WMMenuView *)menu initialMenuItem:(WMMenuItem *)initialMenuItem atIndex:(NSInteger)index; 73 | 74 | @end 75 | 76 | @interface WMMenuView : UIView 77 | @property (nonatomic, strong) NSArray *progressWidths; 78 | @property (nonatomic, weak) WMProgressView *progressView; 79 | @property (nonatomic, assign) CGFloat progressHeight; 80 | @property (nonatomic, assign) WMMenuViewStyle style; 81 | @property (nonatomic, assign) WMMenuViewLayoutMode layoutMode; 82 | @property (nonatomic, assign) CGFloat contentMargin; 83 | @property (nonatomic, strong) UIColor *lineColor; 84 | @property (nonatomic, assign) CGFloat progressViewBottomSpace; 85 | @property (nonatomic, weak) id delegate; 86 | @property (nonatomic, weak) id dataSource; 87 | @property (nonatomic, weak) UIView *leftView; 88 | @property (nonatomic, weak) UIView *rightView; 89 | @property (nonatomic, copy) NSString *fontName; 90 | @property (nonatomic, weak) UIScrollView *scrollView; 91 | /** 进度条的速度因数,默认为 15,越小越快, 大于 0 */ 92 | @property (nonatomic, assign) CGFloat speedFactor; 93 | @property (nonatomic, assign) CGFloat progressViewCornerRadius; 94 | @property (nonatomic, assign) BOOL progressViewIsNaughty; 95 | @property (nonatomic, assign) BOOL showOnNavigationBar; 96 | 97 | - (void)slideMenuAtProgress:(CGFloat)progress; 98 | - (void)selectItemAtIndex:(NSInteger)index; 99 | - (void)resetFrames; 100 | - (void)reload; 101 | - (void)updateTitle:(NSString *)title atIndex:(NSInteger)index andWidth:(BOOL)update; 102 | - (void)updateAttributeTitle:(NSAttributedString *)title atIndex:(NSInteger)index andWidth:(BOOL)update; 103 | - (WMMenuItem *)itemAtIndex:(NSInteger)index; 104 | /// 立即刷新 menuView 的 contentOffset,使 title 居中 105 | - (void)refreshContenOffset; 106 | - (void)deselectedItemsIfNeeded; 107 | /** 108 | * 更新角标视图,如要移除,在 -menuView:badgeViewAtIndex: 中返回 nil 即可 109 | */ 110 | - (void)updateBadgeViewAtIndex:(NSInteger)index; 111 | 112 | @end 113 | -------------------------------------------------------------------------------- /WMPageController/WMMenuView/WMProgressView.h: -------------------------------------------------------------------------------- 1 | // 2 | // WMProgressView.h 3 | // WMPageController 4 | // 5 | // Created by Mark on 15/6/20. 6 | // Copyright (c) 2015年 yq. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | @interface WMProgressView : UIView 13 | @property (nonatomic, strong) NSArray *itemFrames; 14 | @property (nonatomic, assign) CGColorRef color; 15 | @property (nonatomic, assign) CGFloat progress; 16 | /** 进度条的速度因数,默认为 15,越小越快, 大于 0 */ 17 | @property (nonatomic, assign) CGFloat speedFactor; 18 | @property (nonatomic, assign) CGFloat cornerRadius; 19 | /// 调皮属性,用于实现新腾讯视频效果 20 | @property (nonatomic, assign) BOOL naughty; 21 | @property (nonatomic, assign) BOOL isTriangle; 22 | @property (nonatomic, assign) BOOL hollow; 23 | @property (nonatomic, assign) BOOL hasBorder; 24 | 25 | - (void)setProgressWithOutAnimate:(CGFloat)progress; 26 | - (void)moveToPostion:(NSInteger)pos; 27 | 28 | @end 29 | NS_ASSUME_NONNULL_END 30 | -------------------------------------------------------------------------------- /WMPageController/WMMenuView/WMProgressView.m: -------------------------------------------------------------------------------- 1 | // 2 | // WMProgressView.m 3 | // WMPageController 4 | // 5 | // Created by Mark on 15/6/20. 6 | // Copyright (c) 2015年 yq. All rights reserved. 7 | // 8 | 9 | #import "WMProgressView.h" 10 | @implementation WMProgressView { 11 | int _sign; 12 | CGFloat _gap; 13 | CGFloat _step; 14 | __weak CADisplayLink *_link; 15 | } 16 | 17 | - (CGFloat)speedFactor { 18 | if (_speedFactor <= 0) { 19 | _speedFactor = 15.0; 20 | } 21 | return _speedFactor; 22 | } 23 | 24 | - (void)setProgressWithOutAnimate:(CGFloat)progress { 25 | if (self.progress == progress) return; 26 | _progress = progress; 27 | [self setNeedsDisplay]; 28 | } 29 | 30 | - (void)setNaughty:(BOOL)naughty { 31 | _naughty = naughty; 32 | [self setNeedsDisplay]; 33 | } 34 | 35 | - (void)setCornerRadius:(CGFloat)cornerRadius { 36 | _cornerRadius = cornerRadius; 37 | [self setNeedsDisplay]; 38 | } 39 | 40 | - (void)moveToPostion:(NSInteger)pos { 41 | _gap = fabs(self.progress - pos); 42 | _sign = self.progress > pos ? -1 : 1; 43 | _step = _gap / self.speedFactor; 44 | if (_link) { 45 | [_link invalidate]; 46 | } 47 | CADisplayLink *link = [CADisplayLink displayLinkWithTarget:self selector:@selector(progressChanged)]; 48 | [link addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes]; 49 | _link = link; 50 | } 51 | 52 | - (void)setProgress:(CGFloat)progress { 53 | if (self.progress == progress) return; 54 | _progress = progress; 55 | [self setNeedsDisplay]; 56 | } 57 | 58 | - (void)progressChanged { 59 | if (_gap > 0.000001) { 60 | _gap -= _step; 61 | if (_gap < 0.0) { 62 | self.progress = (int)(self.progress + _sign * _step + 0.5); 63 | return; 64 | } 65 | self.progress += _sign * _step; 66 | } else { 67 | self.progress = (int)(self.progress + 0.5); 68 | [_link invalidate]; 69 | _link = nil; 70 | } 71 | } 72 | 73 | - (void)drawRect:(CGRect)rect { 74 | // Drawing code 75 | [super drawRect:rect]; 76 | CGContextRef ctx = UIGraphicsGetCurrentContext(); 77 | CGFloat height = self.frame.size.height; 78 | int index = (int)self.progress; 79 | index = (index <= self.itemFrames.count - 1) ? index : (int)self.itemFrames.count - 1; 80 | CGFloat rate = self.progress - index; 81 | CGRect currentFrame = [self.itemFrames[index] CGRectValue]; 82 | CGFloat currentWidth = currentFrame.size.width; 83 | int nextIndex = index + 1 < self.itemFrames.count ? index + 1 : index; 84 | CGFloat nextWidth = [self.itemFrames[nextIndex] CGRectValue].size.width; 85 | 86 | CGFloat currentX = currentFrame.origin.x; 87 | CGFloat nextX = [self.itemFrames[nextIndex] CGRectValue].origin.x; 88 | CGFloat startX = currentX + (nextX - currentX) * rate; 89 | CGFloat width = currentWidth + (nextWidth - currentWidth)*rate; 90 | CGFloat endX = startX + width; 91 | 92 | if (self.naughty) { 93 | CGFloat currentMidX = currentX + currentWidth / 2.0; 94 | CGFloat nextMidX = nextX + nextWidth / 2.0; 95 | 96 | if (rate <= 0.5) { 97 | startX = currentX + (currentMidX - currentX) * rate * 2.0; 98 | CGFloat currentMaxX = currentX + currentWidth; 99 | endX = currentMaxX + (nextMidX - currentMaxX) * rate * 2.0; 100 | } else { 101 | startX = currentMidX + (nextX - currentMidX) * (rate - 0.5) * 2.0; 102 | CGFloat nextMaxX = nextX + nextWidth; 103 | endX = nextMidX + (nextMaxX - nextMidX) * (rate - 0.5) * 2.0; 104 | } 105 | width = endX - startX; 106 | } 107 | 108 | CGFloat lineWidth = (self.hollow || self.hasBorder) ? 1.0 : 0.0; 109 | 110 | if (self.isTriangle) { 111 | CGContextMoveToPoint(ctx, startX, height); 112 | CGContextAddLineToPoint(ctx, endX, height); 113 | CGContextAddLineToPoint(ctx, startX + width / 2.0, 0); 114 | CGContextClosePath(ctx); 115 | CGContextSetFillColorWithColor(ctx, self.color); 116 | CGContextFillPath(ctx); 117 | return; 118 | } 119 | 120 | UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(startX, lineWidth / 2.0, width, height - lineWidth) cornerRadius:self.cornerRadius]; 121 | CGContextAddPath(ctx, path.CGPath); 122 | 123 | if (self.hollow) { 124 | CGContextSetStrokeColorWithColor(ctx, self.color); 125 | CGContextStrokePath(ctx); 126 | return; 127 | } 128 | CGContextSetFillColorWithColor(ctx, self.color); 129 | CGContextFillPath(ctx); 130 | 131 | if (self.hasBorder) { 132 | // 计算点 133 | CGFloat startX = CGRectGetMinX([self.itemFrames.firstObject CGRectValue]); 134 | CGFloat endX = CGRectGetMaxX([self.itemFrames.lastObject CGRectValue]); 135 | UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(startX, lineWidth / 2.0, (endX - startX), height - lineWidth) cornerRadius:self.cornerRadius]; 136 | CGContextSetLineWidth(ctx, lineWidth); 137 | CGContextAddPath(ctx, path.CGPath); 138 | 139 | // 绘制 140 | CGContextSetStrokeColorWithColor(ctx, self.color); 141 | CGContextStrokePath(ctx); 142 | } 143 | } 144 | 145 | @end 146 | -------------------------------------------------------------------------------- /WMPageController/WMMenuView/WMScrollView.h: -------------------------------------------------------------------------------- 1 | // 2 | // WMScrollView.h 3 | // WMPageController 4 | // 5 | // Created by lh on 15/11/21. 6 | // Copyright (c) 2015年 yq. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface WMScrollView : UIScrollView 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /WMPageController/WMMenuView/WMScrollView.m: -------------------------------------------------------------------------------- 1 | // 2 | // WMScrollView.m 3 | // WMPageController 4 | // 5 | // Created by lh on 15/11/21. 6 | // Copyright (c) 2015年 yq. All rights reserved. 7 | // 8 | 9 | #import "WMScrollView.h" 10 | 11 | @implementation WMScrollView 12 | 13 | #pragma mark - 14 | 15 | - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRequireFailureOfGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer { 16 | //MARK: UITableViewCell 删除手势 17 | if ([NSStringFromClass(otherGestureRecognizer.view.class) isEqualToString:@"UITableViewWrapperView"] && [otherGestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]]) { 18 | return YES; 19 | } 20 | return NO; 21 | } 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /WMPageControllerDemo/Overview.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangmchn/WMPageController/75ab2422d4a3e76a50d6903bdf4f6598c584d6fb/WMPageControllerDemo/Overview.gif -------------------------------------------------------------------------------- /WMPageControllerDemo/StickyExample/Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment the next line to define a global platform for your project 2 | # platform :ios, '9.0' 3 | 4 | target 'StickyExample' do 5 | # Uncomment the next line if you're using Swift or would like to use dynamic frameworks 6 | # use_frameworks! 7 | 8 | # Pods for StickyExample 9 | pod 'WMPageController', :path => '../../' 10 | target 'StickyExampleTests' do 11 | inherit! :search_paths 12 | # Pods for testing 13 | end 14 | 15 | target 'StickyExampleUITests' do 16 | inherit! :search_paths 17 | # Pods for testing 18 | end 19 | 20 | end 21 | -------------------------------------------------------------------------------- /WMPageControllerDemo/StickyExample/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - WMPageController (2.5.2) 3 | 4 | DEPENDENCIES: 5 | - WMPageController (from `../../`) 6 | 7 | EXTERNAL SOURCES: 8 | WMPageController: 9 | :path: "../../" 10 | 11 | SPEC CHECKSUMS: 12 | WMPageController: b5b72347e9394e455da09379a96b832966260cd8 13 | 14 | PODFILE CHECKSUM: 307332daa66e1c9da256c398e5f735fc96889a0d 15 | 16 | COCOAPODS: 1.5.0 17 | -------------------------------------------------------------------------------- /WMPageControllerDemo/StickyExample/Pods/Headers/Private/WMPageController/UIViewController+WMPageController.h: -------------------------------------------------------------------------------- 1 | ../../../../../../WMPageController/UIViewController+WMPageController.h -------------------------------------------------------------------------------- /WMPageControllerDemo/StickyExample/Pods/Headers/Private/WMPageController/WMMenuItem.h: -------------------------------------------------------------------------------- 1 | ../../../../../../WMPageController/WMMenuView/WMMenuItem.h -------------------------------------------------------------------------------- /WMPageControllerDemo/StickyExample/Pods/Headers/Private/WMPageController/WMMenuView.h: -------------------------------------------------------------------------------- 1 | ../../../../../../WMPageController/WMMenuView/WMMenuView.h -------------------------------------------------------------------------------- /WMPageControllerDemo/StickyExample/Pods/Headers/Private/WMPageController/WMPageController.h: -------------------------------------------------------------------------------- 1 | ../../../../../../WMPageController/WMPageController.h -------------------------------------------------------------------------------- /WMPageControllerDemo/StickyExample/Pods/Headers/Private/WMPageController/WMProgressView.h: -------------------------------------------------------------------------------- 1 | ../../../../../../WMPageController/WMMenuView/WMProgressView.h -------------------------------------------------------------------------------- /WMPageControllerDemo/StickyExample/Pods/Headers/Private/WMPageController/WMScrollView.h: -------------------------------------------------------------------------------- 1 | ../../../../../../WMPageController/WMMenuView/WMScrollView.h -------------------------------------------------------------------------------- /WMPageControllerDemo/StickyExample/Pods/Headers/Public/WMPageController/UIViewController+WMPageController.h: -------------------------------------------------------------------------------- 1 | ../../../../../../WMPageController/UIViewController+WMPageController.h -------------------------------------------------------------------------------- /WMPageControllerDemo/StickyExample/Pods/Headers/Public/WMPageController/WMMenuItem.h: -------------------------------------------------------------------------------- 1 | ../../../../../../WMPageController/WMMenuView/WMMenuItem.h -------------------------------------------------------------------------------- /WMPageControllerDemo/StickyExample/Pods/Headers/Public/WMPageController/WMMenuView.h: -------------------------------------------------------------------------------- 1 | ../../../../../../WMPageController/WMMenuView/WMMenuView.h -------------------------------------------------------------------------------- /WMPageControllerDemo/StickyExample/Pods/Headers/Public/WMPageController/WMPageController.h: -------------------------------------------------------------------------------- 1 | ../../../../../../WMPageController/WMPageController.h -------------------------------------------------------------------------------- /WMPageControllerDemo/StickyExample/Pods/Headers/Public/WMPageController/WMProgressView.h: -------------------------------------------------------------------------------- 1 | ../../../../../../WMPageController/WMMenuView/WMProgressView.h -------------------------------------------------------------------------------- /WMPageControllerDemo/StickyExample/Pods/Headers/Public/WMPageController/WMScrollView.h: -------------------------------------------------------------------------------- 1 | ../../../../../../WMPageController/WMMenuView/WMScrollView.h -------------------------------------------------------------------------------- /WMPageControllerDemo/StickyExample/Pods/Local Podspecs/WMPageController.podspec.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "WMPageController", 3 | "version": "2.5.2", 4 | "summary": "An easy solution to page controllers like NetEase News", 5 | "homepage": "https://github.com/wangmchn/WMPageController", 6 | "license": "MIT (LICENSE)", 7 | "authors": { 8 | "wangmchn": "wangmchn@163.com" 9 | }, 10 | "source": { 11 | "git": "https://github.com/wangmchn/WMPageController.git", 12 | "tag": "2.5.2" 13 | }, 14 | "platforms": { 15 | "ios": "6.0" 16 | }, 17 | "source_files": "WMPageController/**/*.{h,m}", 18 | "frameworks": [ 19 | "Foundation", 20 | "CoreGraphics", 21 | "UIKit" 22 | ], 23 | "requires_arc": true 24 | } 25 | -------------------------------------------------------------------------------- /WMPageControllerDemo/StickyExample/Pods/Manifest.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - WMPageController (2.5.2) 3 | 4 | DEPENDENCIES: 5 | - WMPageController (from `../../`) 6 | 7 | EXTERNAL SOURCES: 8 | WMPageController: 9 | :path: "../../" 10 | 11 | SPEC CHECKSUMS: 12 | WMPageController: b5b72347e9394e455da09379a96b832966260cd8 13 | 14 | PODFILE CHECKSUM: 307332daa66e1c9da256c398e5f735fc96889a0d 15 | 16 | COCOAPODS: 1.5.0 17 | -------------------------------------------------------------------------------- /WMPageControllerDemo/StickyExample/Pods/Target Support Files/Pods-StickyExample/Pods-StickyExample-acknowledgements.markdown: -------------------------------------------------------------------------------- 1 | # Acknowledgements 2 | This application makes use of the following third party libraries: 3 | 4 | ## WMPageController 5 | 6 | The MIT License (MIT) 7 | 8 | Copyright (c) 2015 9 | 10 | Permission is hereby granted, free of charge, to any person obtaining a copy 11 | of this software and associated documentation files (the "Software"), to deal 12 | in the Software without restriction, including without limitation the rights 13 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | copies of the Software, and to permit persons to whom the Software is 15 | furnished to do so, subject to the following conditions: 16 | 17 | The above copyright notice and this permission notice shall be included in all 18 | copies or substantial portions of the Software. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | SOFTWARE. 27 | 28 | Generated by CocoaPods - https://cocoapods.org 29 | -------------------------------------------------------------------------------- /WMPageControllerDemo/StickyExample/Pods/Target Support Files/Pods-StickyExample/Pods-StickyExample-acknowledgements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreferenceSpecifiers 6 | 7 | 8 | FooterText 9 | This application makes use of the following third party libraries: 10 | Title 11 | Acknowledgements 12 | Type 13 | PSGroupSpecifier 14 | 15 | 16 | FooterText 17 | The MIT License (MIT) 18 | 19 | Copyright (c) 2015 20 | 21 | Permission is hereby granted, free of charge, to any person obtaining a copy 22 | of this software and associated documentation files (the "Software"), to deal 23 | in the Software without restriction, including without limitation the rights 24 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 25 | copies of the Software, and to permit persons to whom the Software is 26 | furnished to do so, subject to the following conditions: 27 | 28 | The above copyright notice and this permission notice shall be included in all 29 | copies or substantial portions of the Software. 30 | 31 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 32 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 33 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 34 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 35 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 36 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 37 | SOFTWARE. 38 | 39 | License 40 | MIT (LICENSE) 41 | Title 42 | WMPageController 43 | Type 44 | PSGroupSpecifier 45 | 46 | 47 | FooterText 48 | Generated by CocoaPods - https://cocoapods.org 49 | Title 50 | 51 | Type 52 | PSGroupSpecifier 53 | 54 | 55 | StringsTable 56 | Acknowledgements 57 | Title 58 | Acknowledgements 59 | 60 | 61 | -------------------------------------------------------------------------------- /WMPageControllerDemo/StickyExample/Pods/Target Support Files/Pods-StickyExample/Pods-StickyExample-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods_StickyExample : NSObject 3 | @end 4 | @implementation PodsDummy_Pods_StickyExample 5 | @end 6 | -------------------------------------------------------------------------------- /WMPageControllerDemo/StickyExample/Pods/Target Support Files/Pods-StickyExample/Pods-StickyExample-frameworks.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | set -u 4 | set -o pipefail 5 | 6 | if [ -z ${FRAMEWORKS_FOLDER_PATH+x} ]; then 7 | # If FRAMEWORKS_FOLDER_PATH is not set, then there's nowhere for us to copy 8 | # frameworks to, so exit 0 (signalling the script phase was successful). 9 | exit 0 10 | fi 11 | 12 | echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 13 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 14 | 15 | COCOAPODS_PARALLEL_CODE_SIGN="${COCOAPODS_PARALLEL_CODE_SIGN:-false}" 16 | SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" 17 | 18 | # Used as a return value for each invocation of `strip_invalid_archs` function. 19 | STRIP_BINARY_RETVAL=0 20 | 21 | # This protects against multiple targets copying the same framework dependency at the same time. The solution 22 | # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html 23 | RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") 24 | 25 | # Copies and strips a vendored framework 26 | install_framework() 27 | { 28 | if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then 29 | local source="${BUILT_PRODUCTS_DIR}/$1" 30 | elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then 31 | local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" 32 | elif [ -r "$1" ]; then 33 | local source="$1" 34 | fi 35 | 36 | local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 37 | 38 | if [ -L "${source}" ]; then 39 | echo "Symlinked..." 40 | source="$(readlink "${source}")" 41 | fi 42 | 43 | # Use filter instead of exclude so missing patterns don't throw errors. 44 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" 45 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" 46 | 47 | local basename 48 | basename="$(basename -s .framework "$1")" 49 | binary="${destination}/${basename}.framework/${basename}" 50 | if ! [ -r "$binary" ]; then 51 | binary="${destination}/${basename}" 52 | fi 53 | 54 | # Strip invalid architectures so "fat" simulator / device frameworks work on device 55 | if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then 56 | strip_invalid_archs "$binary" 57 | fi 58 | 59 | # Resign the code if required by the build settings to avoid unstable apps 60 | code_sign_if_enabled "${destination}/$(basename "$1")" 61 | 62 | # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. 63 | if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then 64 | local swift_runtime_libs 65 | swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]}) 66 | for lib in $swift_runtime_libs; do 67 | echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" 68 | rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" 69 | code_sign_if_enabled "${destination}/${lib}" 70 | done 71 | fi 72 | } 73 | 74 | # Copies and strips a vendored dSYM 75 | install_dsym() { 76 | local source="$1" 77 | if [ -r "$source" ]; then 78 | # Copy the dSYM into a the targets temp dir. 79 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${DERIVED_FILES_DIR}\"" 80 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${DERIVED_FILES_DIR}" 81 | 82 | local basename 83 | basename="$(basename -s .framework.dSYM "$source")" 84 | binary="${DERIVED_FILES_DIR}/${basename}.framework.dSYM/Contents/Resources/DWARF/${basename}" 85 | 86 | # Strip invalid architectures so "fat" simulator / device frameworks work on device 87 | if [[ "$(file "$binary")" == *"Mach-O dSYM companion"* ]]; then 88 | strip_invalid_archs "$binary" 89 | fi 90 | 91 | if [[ $STRIP_BINARY_RETVAL == 1 ]]; then 92 | # Move the stripped file into its final destination. 93 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${DERIVED_FILES_DIR}/${basename}.framework.dSYM\" \"${DWARF_DSYM_FOLDER_PATH}\"" 94 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${DERIVED_FILES_DIR}/${basename}.framework.dSYM" "${DWARF_DSYM_FOLDER_PATH}" 95 | else 96 | # The dSYM was not stripped at all, in this case touch a fake folder so the input/output paths from Xcode do not reexecute this script because the file is missing. 97 | touch "${DWARF_DSYM_FOLDER_PATH}/${basename}.framework.dSYM" 98 | fi 99 | fi 100 | } 101 | 102 | # Signs a framework with the provided identity 103 | code_sign_if_enabled() { 104 | if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED:-}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then 105 | # Use the current code_sign_identitiy 106 | echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" 107 | local code_sign_cmd="/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS:-} --preserve-metadata=identifier,entitlements '$1'" 108 | 109 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then 110 | code_sign_cmd="$code_sign_cmd &" 111 | fi 112 | echo "$code_sign_cmd" 113 | eval "$code_sign_cmd" 114 | fi 115 | } 116 | 117 | # Strip invalid architectures 118 | strip_invalid_archs() { 119 | binary="$1" 120 | # Get architectures for current target binary 121 | binary_archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | awk '{$1=$1;print}' | rev)" 122 | # Intersect them with the architectures we are building for 123 | intersected_archs="$(echo ${ARCHS[@]} ${binary_archs[@]} | tr ' ' '\n' | sort | uniq -d)" 124 | # If there are no archs supported by this binary then warn the user 125 | if [[ -z "$intersected_archs" ]]; then 126 | echo "warning: [CP] Vendored binary '$binary' contains architectures ($binary_archs) none of which match the current build architectures ($ARCHS)." 127 | STRIP_BINARY_RETVAL=0 128 | return 129 | fi 130 | stripped="" 131 | for arch in $binary_archs; do 132 | if ! [[ "${ARCHS}" == *"$arch"* ]]; then 133 | # Strip non-valid architectures in-place 134 | lipo -remove "$arch" -output "$binary" "$binary" || exit 1 135 | stripped="$stripped $arch" 136 | fi 137 | done 138 | if [[ "$stripped" ]]; then 139 | echo "Stripped $binary of architectures:$stripped" 140 | fi 141 | STRIP_BINARY_RETVAL=1 142 | } 143 | 144 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then 145 | wait 146 | fi 147 | -------------------------------------------------------------------------------- /WMPageControllerDemo/StickyExample/Pods/Target Support Files/Pods-StickyExample/Pods-StickyExample-resources.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | set -u 4 | set -o pipefail 5 | 6 | if [ -z ${UNLOCALIZED_RESOURCES_FOLDER_PATH+x} ]; then 7 | # If UNLOCALIZED_RESOURCES_FOLDER_PATH is not set, then there's nowhere for us to copy 8 | # resources to, so exit 0 (signalling the script phase was successful). 9 | exit 0 10 | fi 11 | 12 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 13 | 14 | RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt 15 | > "$RESOURCES_TO_COPY" 16 | 17 | XCASSET_FILES=() 18 | 19 | # This protects against multiple targets copying the same framework dependency at the same time. The solution 20 | # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html 21 | RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") 22 | 23 | case "${TARGETED_DEVICE_FAMILY:-}" in 24 | 1,2) 25 | TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" 26 | ;; 27 | 1) 28 | TARGET_DEVICE_ARGS="--target-device iphone" 29 | ;; 30 | 2) 31 | TARGET_DEVICE_ARGS="--target-device ipad" 32 | ;; 33 | 3) 34 | TARGET_DEVICE_ARGS="--target-device tv" 35 | ;; 36 | 4) 37 | TARGET_DEVICE_ARGS="--target-device watch" 38 | ;; 39 | *) 40 | TARGET_DEVICE_ARGS="--target-device mac" 41 | ;; 42 | esac 43 | 44 | install_resource() 45 | { 46 | if [[ "$1" = /* ]] ; then 47 | RESOURCE_PATH="$1" 48 | else 49 | RESOURCE_PATH="${PODS_ROOT}/$1" 50 | fi 51 | if [[ ! -e "$RESOURCE_PATH" ]] ; then 52 | cat << EOM 53 | error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script. 54 | EOM 55 | exit 1 56 | fi 57 | case $RESOURCE_PATH in 58 | *.storyboard) 59 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true 60 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 61 | ;; 62 | *.xib) 63 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true 64 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 65 | ;; 66 | *.framework) 67 | echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true 68 | mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 69 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true 70 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 71 | ;; 72 | *.xcdatamodel) 73 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\"" || true 74 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom" 75 | ;; 76 | *.xcdatamodeld) 77 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\"" || true 78 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd" 79 | ;; 80 | *.xcmappingmodel) 81 | echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\"" || true 82 | xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm" 83 | ;; 84 | *.xcassets) 85 | ABSOLUTE_XCASSET_FILE="$RESOURCE_PATH" 86 | XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") 87 | ;; 88 | *) 89 | echo "$RESOURCE_PATH" || true 90 | echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY" 91 | ;; 92 | esac 93 | } 94 | 95 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 96 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 97 | if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then 98 | mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 99 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 100 | fi 101 | rm -f "$RESOURCES_TO_COPY" 102 | 103 | if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "${XCASSET_FILES:-}" ] 104 | then 105 | # Find all other xcassets (this unfortunately includes those of path pods and other targets). 106 | OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d) 107 | while read line; do 108 | if [[ $line != "${PODS_ROOT}*" ]]; then 109 | XCASSET_FILES+=("$line") 110 | fi 111 | done <<<"$OTHER_XCASSETS" 112 | 113 | if [ -z ${ASSETCATALOG_COMPILER_APPICON_NAME+x} ]; then 114 | printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 115 | else 116 | printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" --app-icon "${ASSETCATALOG_COMPILER_APPICON_NAME}" --output-partial-info-plist "${TARGET_BUILD_DIR}/assetcatalog_generated_info.plist" 117 | fi 118 | fi 119 | -------------------------------------------------------------------------------- /WMPageControllerDemo/StickyExample/Pods/Target Support Files/Pods-StickyExample/Pods-StickyExample.debug.xcconfig: -------------------------------------------------------------------------------- 1 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 2 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/WMPageController" 3 | LIBRARY_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/WMPageController" 4 | OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/WMPageController" 5 | OTHER_LDFLAGS = $(inherited) -ObjC -l"WMPageController" -framework "CoreGraphics" -framework "Foundation" -framework "UIKit" 6 | PODS_BUILD_DIR = ${BUILD_DIR} 7 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 8 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 9 | PODS_ROOT = ${SRCROOT}/Pods 10 | -------------------------------------------------------------------------------- /WMPageControllerDemo/StickyExample/Pods/Target Support Files/Pods-StickyExample/Pods-StickyExample.release.xcconfig: -------------------------------------------------------------------------------- 1 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 2 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/WMPageController" 3 | LIBRARY_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/WMPageController" 4 | OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/WMPageController" 5 | OTHER_LDFLAGS = $(inherited) -ObjC -l"WMPageController" -framework "CoreGraphics" -framework "Foundation" -framework "UIKit" 6 | PODS_BUILD_DIR = ${BUILD_DIR} 7 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 8 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 9 | PODS_ROOT = ${SRCROOT}/Pods 10 | -------------------------------------------------------------------------------- /WMPageControllerDemo/StickyExample/Pods/Target Support Files/Pods-StickyExampleTests/Pods-StickyExampleTests-acknowledgements.markdown: -------------------------------------------------------------------------------- 1 | # Acknowledgements 2 | This application makes use of the following third party libraries: 3 | Generated by CocoaPods - https://cocoapods.org 4 | -------------------------------------------------------------------------------- /WMPageControllerDemo/StickyExample/Pods/Target Support Files/Pods-StickyExampleTests/Pods-StickyExampleTests-acknowledgements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreferenceSpecifiers 6 | 7 | 8 | FooterText 9 | This application makes use of the following third party libraries: 10 | Title 11 | Acknowledgements 12 | Type 13 | PSGroupSpecifier 14 | 15 | 16 | FooterText 17 | Generated by CocoaPods - https://cocoapods.org 18 | Title 19 | 20 | Type 21 | PSGroupSpecifier 22 | 23 | 24 | StringsTable 25 | Acknowledgements 26 | Title 27 | Acknowledgements 28 | 29 | 30 | -------------------------------------------------------------------------------- /WMPageControllerDemo/StickyExample/Pods/Target Support Files/Pods-StickyExampleTests/Pods-StickyExampleTests-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods_StickyExampleTests : NSObject 3 | @end 4 | @implementation PodsDummy_Pods_StickyExampleTests 5 | @end 6 | -------------------------------------------------------------------------------- /WMPageControllerDemo/StickyExample/Pods/Target Support Files/Pods-StickyExampleTests/Pods-StickyExampleTests-frameworks.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | set -u 4 | set -o pipefail 5 | 6 | if [ -z ${FRAMEWORKS_FOLDER_PATH+x} ]; then 7 | # If FRAMEWORKS_FOLDER_PATH is not set, then there's nowhere for us to copy 8 | # frameworks to, so exit 0 (signalling the script phase was successful). 9 | exit 0 10 | fi 11 | 12 | echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 13 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 14 | 15 | COCOAPODS_PARALLEL_CODE_SIGN="${COCOAPODS_PARALLEL_CODE_SIGN:-false}" 16 | SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" 17 | 18 | # Used as a return value for each invocation of `strip_invalid_archs` function. 19 | STRIP_BINARY_RETVAL=0 20 | 21 | # This protects against multiple targets copying the same framework dependency at the same time. The solution 22 | # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html 23 | RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") 24 | 25 | # Copies and strips a vendored framework 26 | install_framework() 27 | { 28 | if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then 29 | local source="${BUILT_PRODUCTS_DIR}/$1" 30 | elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then 31 | local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" 32 | elif [ -r "$1" ]; then 33 | local source="$1" 34 | fi 35 | 36 | local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 37 | 38 | if [ -L "${source}" ]; then 39 | echo "Symlinked..." 40 | source="$(readlink "${source}")" 41 | fi 42 | 43 | # Use filter instead of exclude so missing patterns don't throw errors. 44 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" 45 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" 46 | 47 | local basename 48 | basename="$(basename -s .framework "$1")" 49 | binary="${destination}/${basename}.framework/${basename}" 50 | if ! [ -r "$binary" ]; then 51 | binary="${destination}/${basename}" 52 | fi 53 | 54 | # Strip invalid architectures so "fat" simulator / device frameworks work on device 55 | if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then 56 | strip_invalid_archs "$binary" 57 | fi 58 | 59 | # Resign the code if required by the build settings to avoid unstable apps 60 | code_sign_if_enabled "${destination}/$(basename "$1")" 61 | 62 | # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. 63 | if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then 64 | local swift_runtime_libs 65 | swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]}) 66 | for lib in $swift_runtime_libs; do 67 | echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" 68 | rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" 69 | code_sign_if_enabled "${destination}/${lib}" 70 | done 71 | fi 72 | } 73 | 74 | # Copies and strips a vendored dSYM 75 | install_dsym() { 76 | local source="$1" 77 | if [ -r "$source" ]; then 78 | # Copy the dSYM into a the targets temp dir. 79 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${DERIVED_FILES_DIR}\"" 80 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${DERIVED_FILES_DIR}" 81 | 82 | local basename 83 | basename="$(basename -s .framework.dSYM "$source")" 84 | binary="${DERIVED_FILES_DIR}/${basename}.framework.dSYM/Contents/Resources/DWARF/${basename}" 85 | 86 | # Strip invalid architectures so "fat" simulator / device frameworks work on device 87 | if [[ "$(file "$binary")" == *"Mach-O dSYM companion"* ]]; then 88 | strip_invalid_archs "$binary" 89 | fi 90 | 91 | if [[ $STRIP_BINARY_RETVAL == 1 ]]; then 92 | # Move the stripped file into its final destination. 93 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${DERIVED_FILES_DIR}/${basename}.framework.dSYM\" \"${DWARF_DSYM_FOLDER_PATH}\"" 94 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${DERIVED_FILES_DIR}/${basename}.framework.dSYM" "${DWARF_DSYM_FOLDER_PATH}" 95 | else 96 | # The dSYM was not stripped at all, in this case touch a fake folder so the input/output paths from Xcode do not reexecute this script because the file is missing. 97 | touch "${DWARF_DSYM_FOLDER_PATH}/${basename}.framework.dSYM" 98 | fi 99 | fi 100 | } 101 | 102 | # Signs a framework with the provided identity 103 | code_sign_if_enabled() { 104 | if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED:-}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then 105 | # Use the current code_sign_identitiy 106 | echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" 107 | local code_sign_cmd="/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS:-} --preserve-metadata=identifier,entitlements '$1'" 108 | 109 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then 110 | code_sign_cmd="$code_sign_cmd &" 111 | fi 112 | echo "$code_sign_cmd" 113 | eval "$code_sign_cmd" 114 | fi 115 | } 116 | 117 | # Strip invalid architectures 118 | strip_invalid_archs() { 119 | binary="$1" 120 | # Get architectures for current target binary 121 | binary_archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | awk '{$1=$1;print}' | rev)" 122 | # Intersect them with the architectures we are building for 123 | intersected_archs="$(echo ${ARCHS[@]} ${binary_archs[@]} | tr ' ' '\n' | sort | uniq -d)" 124 | # If there are no archs supported by this binary then warn the user 125 | if [[ -z "$intersected_archs" ]]; then 126 | echo "warning: [CP] Vendored binary '$binary' contains architectures ($binary_archs) none of which match the current build architectures ($ARCHS)." 127 | STRIP_BINARY_RETVAL=0 128 | return 129 | fi 130 | stripped="" 131 | for arch in $binary_archs; do 132 | if ! [[ "${ARCHS}" == *"$arch"* ]]; then 133 | # Strip non-valid architectures in-place 134 | lipo -remove "$arch" -output "$binary" "$binary" || exit 1 135 | stripped="$stripped $arch" 136 | fi 137 | done 138 | if [[ "$stripped" ]]; then 139 | echo "Stripped $binary of architectures:$stripped" 140 | fi 141 | STRIP_BINARY_RETVAL=1 142 | } 143 | 144 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then 145 | wait 146 | fi 147 | -------------------------------------------------------------------------------- /WMPageControllerDemo/StickyExample/Pods/Target Support Files/Pods-StickyExampleTests/Pods-StickyExampleTests-resources.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | set -u 4 | set -o pipefail 5 | 6 | if [ -z ${UNLOCALIZED_RESOURCES_FOLDER_PATH+x} ]; then 7 | # If UNLOCALIZED_RESOURCES_FOLDER_PATH is not set, then there's nowhere for us to copy 8 | # resources to, so exit 0 (signalling the script phase was successful). 9 | exit 0 10 | fi 11 | 12 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 13 | 14 | RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt 15 | > "$RESOURCES_TO_COPY" 16 | 17 | XCASSET_FILES=() 18 | 19 | # This protects against multiple targets copying the same framework dependency at the same time. The solution 20 | # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html 21 | RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") 22 | 23 | case "${TARGETED_DEVICE_FAMILY:-}" in 24 | 1,2) 25 | TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" 26 | ;; 27 | 1) 28 | TARGET_DEVICE_ARGS="--target-device iphone" 29 | ;; 30 | 2) 31 | TARGET_DEVICE_ARGS="--target-device ipad" 32 | ;; 33 | 3) 34 | TARGET_DEVICE_ARGS="--target-device tv" 35 | ;; 36 | 4) 37 | TARGET_DEVICE_ARGS="--target-device watch" 38 | ;; 39 | *) 40 | TARGET_DEVICE_ARGS="--target-device mac" 41 | ;; 42 | esac 43 | 44 | install_resource() 45 | { 46 | if [[ "$1" = /* ]] ; then 47 | RESOURCE_PATH="$1" 48 | else 49 | RESOURCE_PATH="${PODS_ROOT}/$1" 50 | fi 51 | if [[ ! -e "$RESOURCE_PATH" ]] ; then 52 | cat << EOM 53 | error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script. 54 | EOM 55 | exit 1 56 | fi 57 | case $RESOURCE_PATH in 58 | *.storyboard) 59 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true 60 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 61 | ;; 62 | *.xib) 63 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true 64 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 65 | ;; 66 | *.framework) 67 | echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true 68 | mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 69 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true 70 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 71 | ;; 72 | *.xcdatamodel) 73 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\"" || true 74 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom" 75 | ;; 76 | *.xcdatamodeld) 77 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\"" || true 78 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd" 79 | ;; 80 | *.xcmappingmodel) 81 | echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\"" || true 82 | xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm" 83 | ;; 84 | *.xcassets) 85 | ABSOLUTE_XCASSET_FILE="$RESOURCE_PATH" 86 | XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") 87 | ;; 88 | *) 89 | echo "$RESOURCE_PATH" || true 90 | echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY" 91 | ;; 92 | esac 93 | } 94 | 95 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 96 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 97 | if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then 98 | mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 99 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 100 | fi 101 | rm -f "$RESOURCES_TO_COPY" 102 | 103 | if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "${XCASSET_FILES:-}" ] 104 | then 105 | # Find all other xcassets (this unfortunately includes those of path pods and other targets). 106 | OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d) 107 | while read line; do 108 | if [[ $line != "${PODS_ROOT}*" ]]; then 109 | XCASSET_FILES+=("$line") 110 | fi 111 | done <<<"$OTHER_XCASSETS" 112 | 113 | if [ -z ${ASSETCATALOG_COMPILER_APPICON_NAME+x} ]; then 114 | printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 115 | else 116 | printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" --app-icon "${ASSETCATALOG_COMPILER_APPICON_NAME}" --output-partial-info-plist "${TARGET_BUILD_DIR}/assetcatalog_generated_info.plist" 117 | fi 118 | fi 119 | -------------------------------------------------------------------------------- /WMPageControllerDemo/StickyExample/Pods/Target Support Files/Pods-StickyExampleTests/Pods-StickyExampleTests.debug.xcconfig: -------------------------------------------------------------------------------- 1 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 2 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/WMPageController" 3 | LIBRARY_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/WMPageController" 4 | OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/WMPageController" 5 | OTHER_LDFLAGS = $(inherited) -ObjC -framework "CoreGraphics" -framework "Foundation" -framework "UIKit" 6 | PODS_BUILD_DIR = ${BUILD_DIR} 7 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 8 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 9 | PODS_ROOT = ${SRCROOT}/Pods 10 | -------------------------------------------------------------------------------- /WMPageControllerDemo/StickyExample/Pods/Target Support Files/Pods-StickyExampleTests/Pods-StickyExampleTests.release.xcconfig: -------------------------------------------------------------------------------- 1 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 2 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/WMPageController" 3 | LIBRARY_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/WMPageController" 4 | OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/WMPageController" 5 | OTHER_LDFLAGS = $(inherited) -ObjC -framework "CoreGraphics" -framework "Foundation" -framework "UIKit" 6 | PODS_BUILD_DIR = ${BUILD_DIR} 7 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 8 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 9 | PODS_ROOT = ${SRCROOT}/Pods 10 | -------------------------------------------------------------------------------- /WMPageControllerDemo/StickyExample/Pods/Target Support Files/Pods-StickyExampleUITests/Pods-StickyExampleUITests-acknowledgements.markdown: -------------------------------------------------------------------------------- 1 | # Acknowledgements 2 | This application makes use of the following third party libraries: 3 | Generated by CocoaPods - https://cocoapods.org 4 | -------------------------------------------------------------------------------- /WMPageControllerDemo/StickyExample/Pods/Target Support Files/Pods-StickyExampleUITests/Pods-StickyExampleUITests-acknowledgements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreferenceSpecifiers 6 | 7 | 8 | FooterText 9 | This application makes use of the following third party libraries: 10 | Title 11 | Acknowledgements 12 | Type 13 | PSGroupSpecifier 14 | 15 | 16 | FooterText 17 | Generated by CocoaPods - https://cocoapods.org 18 | Title 19 | 20 | Type 21 | PSGroupSpecifier 22 | 23 | 24 | StringsTable 25 | Acknowledgements 26 | Title 27 | Acknowledgements 28 | 29 | 30 | -------------------------------------------------------------------------------- /WMPageControllerDemo/StickyExample/Pods/Target Support Files/Pods-StickyExampleUITests/Pods-StickyExampleUITests-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods_StickyExampleUITests : NSObject 3 | @end 4 | @implementation PodsDummy_Pods_StickyExampleUITests 5 | @end 6 | -------------------------------------------------------------------------------- /WMPageControllerDemo/StickyExample/Pods/Target Support Files/Pods-StickyExampleUITests/Pods-StickyExampleUITests-frameworks.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | set -u 4 | set -o pipefail 5 | 6 | if [ -z ${FRAMEWORKS_FOLDER_PATH+x} ]; then 7 | # If FRAMEWORKS_FOLDER_PATH is not set, then there's nowhere for us to copy 8 | # frameworks to, so exit 0 (signalling the script phase was successful). 9 | exit 0 10 | fi 11 | 12 | echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 13 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 14 | 15 | COCOAPODS_PARALLEL_CODE_SIGN="${COCOAPODS_PARALLEL_CODE_SIGN:-false}" 16 | SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" 17 | 18 | # Used as a return value for each invocation of `strip_invalid_archs` function. 19 | STRIP_BINARY_RETVAL=0 20 | 21 | # This protects against multiple targets copying the same framework dependency at the same time. The solution 22 | # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html 23 | RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") 24 | 25 | # Copies and strips a vendored framework 26 | install_framework() 27 | { 28 | if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then 29 | local source="${BUILT_PRODUCTS_DIR}/$1" 30 | elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then 31 | local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" 32 | elif [ -r "$1" ]; then 33 | local source="$1" 34 | fi 35 | 36 | local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 37 | 38 | if [ -L "${source}" ]; then 39 | echo "Symlinked..." 40 | source="$(readlink "${source}")" 41 | fi 42 | 43 | # Use filter instead of exclude so missing patterns don't throw errors. 44 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" 45 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" 46 | 47 | local basename 48 | basename="$(basename -s .framework "$1")" 49 | binary="${destination}/${basename}.framework/${basename}" 50 | if ! [ -r "$binary" ]; then 51 | binary="${destination}/${basename}" 52 | fi 53 | 54 | # Strip invalid architectures so "fat" simulator / device frameworks work on device 55 | if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then 56 | strip_invalid_archs "$binary" 57 | fi 58 | 59 | # Resign the code if required by the build settings to avoid unstable apps 60 | code_sign_if_enabled "${destination}/$(basename "$1")" 61 | 62 | # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. 63 | if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then 64 | local swift_runtime_libs 65 | swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]}) 66 | for lib in $swift_runtime_libs; do 67 | echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" 68 | rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" 69 | code_sign_if_enabled "${destination}/${lib}" 70 | done 71 | fi 72 | } 73 | 74 | # Copies and strips a vendored dSYM 75 | install_dsym() { 76 | local source="$1" 77 | if [ -r "$source" ]; then 78 | # Copy the dSYM into a the targets temp dir. 79 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${DERIVED_FILES_DIR}\"" 80 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${DERIVED_FILES_DIR}" 81 | 82 | local basename 83 | basename="$(basename -s .framework.dSYM "$source")" 84 | binary="${DERIVED_FILES_DIR}/${basename}.framework.dSYM/Contents/Resources/DWARF/${basename}" 85 | 86 | # Strip invalid architectures so "fat" simulator / device frameworks work on device 87 | if [[ "$(file "$binary")" == *"Mach-O dSYM companion"* ]]; then 88 | strip_invalid_archs "$binary" 89 | fi 90 | 91 | if [[ $STRIP_BINARY_RETVAL == 1 ]]; then 92 | # Move the stripped file into its final destination. 93 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${DERIVED_FILES_DIR}/${basename}.framework.dSYM\" \"${DWARF_DSYM_FOLDER_PATH}\"" 94 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${DERIVED_FILES_DIR}/${basename}.framework.dSYM" "${DWARF_DSYM_FOLDER_PATH}" 95 | else 96 | # The dSYM was not stripped at all, in this case touch a fake folder so the input/output paths from Xcode do not reexecute this script because the file is missing. 97 | touch "${DWARF_DSYM_FOLDER_PATH}/${basename}.framework.dSYM" 98 | fi 99 | fi 100 | } 101 | 102 | # Signs a framework with the provided identity 103 | code_sign_if_enabled() { 104 | if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED:-}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then 105 | # Use the current code_sign_identitiy 106 | echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" 107 | local code_sign_cmd="/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS:-} --preserve-metadata=identifier,entitlements '$1'" 108 | 109 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then 110 | code_sign_cmd="$code_sign_cmd &" 111 | fi 112 | echo "$code_sign_cmd" 113 | eval "$code_sign_cmd" 114 | fi 115 | } 116 | 117 | # Strip invalid architectures 118 | strip_invalid_archs() { 119 | binary="$1" 120 | # Get architectures for current target binary 121 | binary_archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | awk '{$1=$1;print}' | rev)" 122 | # Intersect them with the architectures we are building for 123 | intersected_archs="$(echo ${ARCHS[@]} ${binary_archs[@]} | tr ' ' '\n' | sort | uniq -d)" 124 | # If there are no archs supported by this binary then warn the user 125 | if [[ -z "$intersected_archs" ]]; then 126 | echo "warning: [CP] Vendored binary '$binary' contains architectures ($binary_archs) none of which match the current build architectures ($ARCHS)." 127 | STRIP_BINARY_RETVAL=0 128 | return 129 | fi 130 | stripped="" 131 | for arch in $binary_archs; do 132 | if ! [[ "${ARCHS}" == *"$arch"* ]]; then 133 | # Strip non-valid architectures in-place 134 | lipo -remove "$arch" -output "$binary" "$binary" || exit 1 135 | stripped="$stripped $arch" 136 | fi 137 | done 138 | if [[ "$stripped" ]]; then 139 | echo "Stripped $binary of architectures:$stripped" 140 | fi 141 | STRIP_BINARY_RETVAL=1 142 | } 143 | 144 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then 145 | wait 146 | fi 147 | -------------------------------------------------------------------------------- /WMPageControllerDemo/StickyExample/Pods/Target Support Files/Pods-StickyExampleUITests/Pods-StickyExampleUITests-resources.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | set -u 4 | set -o pipefail 5 | 6 | if [ -z ${UNLOCALIZED_RESOURCES_FOLDER_PATH+x} ]; then 7 | # If UNLOCALIZED_RESOURCES_FOLDER_PATH is not set, then there's nowhere for us to copy 8 | # resources to, so exit 0 (signalling the script phase was successful). 9 | exit 0 10 | fi 11 | 12 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 13 | 14 | RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt 15 | > "$RESOURCES_TO_COPY" 16 | 17 | XCASSET_FILES=() 18 | 19 | # This protects against multiple targets copying the same framework dependency at the same time. The solution 20 | # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html 21 | RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") 22 | 23 | case "${TARGETED_DEVICE_FAMILY:-}" in 24 | 1,2) 25 | TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" 26 | ;; 27 | 1) 28 | TARGET_DEVICE_ARGS="--target-device iphone" 29 | ;; 30 | 2) 31 | TARGET_DEVICE_ARGS="--target-device ipad" 32 | ;; 33 | 3) 34 | TARGET_DEVICE_ARGS="--target-device tv" 35 | ;; 36 | 4) 37 | TARGET_DEVICE_ARGS="--target-device watch" 38 | ;; 39 | *) 40 | TARGET_DEVICE_ARGS="--target-device mac" 41 | ;; 42 | esac 43 | 44 | install_resource() 45 | { 46 | if [[ "$1" = /* ]] ; then 47 | RESOURCE_PATH="$1" 48 | else 49 | RESOURCE_PATH="${PODS_ROOT}/$1" 50 | fi 51 | if [[ ! -e "$RESOURCE_PATH" ]] ; then 52 | cat << EOM 53 | error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script. 54 | EOM 55 | exit 1 56 | fi 57 | case $RESOURCE_PATH in 58 | *.storyboard) 59 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true 60 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 61 | ;; 62 | *.xib) 63 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true 64 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 65 | ;; 66 | *.framework) 67 | echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true 68 | mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 69 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true 70 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 71 | ;; 72 | *.xcdatamodel) 73 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\"" || true 74 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom" 75 | ;; 76 | *.xcdatamodeld) 77 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\"" || true 78 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd" 79 | ;; 80 | *.xcmappingmodel) 81 | echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\"" || true 82 | xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm" 83 | ;; 84 | *.xcassets) 85 | ABSOLUTE_XCASSET_FILE="$RESOURCE_PATH" 86 | XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") 87 | ;; 88 | *) 89 | echo "$RESOURCE_PATH" || true 90 | echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY" 91 | ;; 92 | esac 93 | } 94 | 95 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 96 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 97 | if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then 98 | mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 99 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 100 | fi 101 | rm -f "$RESOURCES_TO_COPY" 102 | 103 | if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "${XCASSET_FILES:-}" ] 104 | then 105 | # Find all other xcassets (this unfortunately includes those of path pods and other targets). 106 | OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d) 107 | while read line; do 108 | if [[ $line != "${PODS_ROOT}*" ]]; then 109 | XCASSET_FILES+=("$line") 110 | fi 111 | done <<<"$OTHER_XCASSETS" 112 | 113 | if [ -z ${ASSETCATALOG_COMPILER_APPICON_NAME+x} ]; then 114 | printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 115 | else 116 | printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" --app-icon "${ASSETCATALOG_COMPILER_APPICON_NAME}" --output-partial-info-plist "${TARGET_BUILD_DIR}/assetcatalog_generated_info.plist" 117 | fi 118 | fi 119 | -------------------------------------------------------------------------------- /WMPageControllerDemo/StickyExample/Pods/Target Support Files/Pods-StickyExampleUITests/Pods-StickyExampleUITests.debug.xcconfig: -------------------------------------------------------------------------------- 1 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 2 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/WMPageController" 3 | LIBRARY_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/WMPageController" 4 | OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/WMPageController" 5 | OTHER_LDFLAGS = $(inherited) -ObjC -framework "CoreGraphics" -framework "Foundation" -framework "UIKit" 6 | PODS_BUILD_DIR = ${BUILD_DIR} 7 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 8 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 9 | PODS_ROOT = ${SRCROOT}/Pods 10 | -------------------------------------------------------------------------------- /WMPageControllerDemo/StickyExample/Pods/Target Support Files/Pods-StickyExampleUITests/Pods-StickyExampleUITests.release.xcconfig: -------------------------------------------------------------------------------- 1 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 2 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/WMPageController" 3 | LIBRARY_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/WMPageController" 4 | OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/WMPageController" 5 | OTHER_LDFLAGS = $(inherited) -ObjC -framework "CoreGraphics" -framework "Foundation" -framework "UIKit" 6 | PODS_BUILD_DIR = ${BUILD_DIR} 7 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 8 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 9 | PODS_ROOT = ${SRCROOT}/Pods 10 | -------------------------------------------------------------------------------- /WMPageControllerDemo/StickyExample/Pods/Target Support Files/WMPageController/WMPageController-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_WMPageController : NSObject 3 | @end 4 | @implementation PodsDummy_WMPageController 5 | @end 6 | -------------------------------------------------------------------------------- /WMPageControllerDemo/StickyExample/Pods/Target Support Files/WMPageController/WMPageController-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | -------------------------------------------------------------------------------- /WMPageControllerDemo/StickyExample/Pods/Target Support Files/WMPageController/WMPageController.xcconfig: -------------------------------------------------------------------------------- 1 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/WMPageController 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/WMPageController" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/WMPageController" 4 | OTHER_LDFLAGS = -framework "CoreGraphics" -framework "Foundation" -framework "UIKit" 5 | PODS_BUILD_DIR = ${BUILD_DIR} 6 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 7 | PODS_ROOT = ${SRCROOT} 8 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/../../.. 9 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 10 | SKIP_INSTALL = YES 11 | -------------------------------------------------------------------------------- /WMPageControllerDemo/StickyExample/StickyExample.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /WMPageControllerDemo/StickyExample/StickyExample.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /WMPageControllerDemo/StickyExample/StickyExample.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /WMPageControllerDemo/StickyExample/StickyExample.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /WMPageControllerDemo/StickyExample/StickyExample/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // StickyExample 4 | // 5 | // Created by Tpphha on 2017/7/22. 6 | // Copyright © 2017年 Tpphha. 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 | -------------------------------------------------------------------------------- /WMPageControllerDemo/StickyExample/StickyExample/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // StickyExample 4 | // 5 | // Created by Tpphha on 2017/7/22. 6 | // Copyright © 2017年 Tpphha. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | #import "WMHomeViewController.h" 11 | 12 | @interface AppDelegate () 13 | 14 | @end 15 | 16 | @implementation AppDelegate 17 | 18 | 19 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 20 | // Override point for customization after application launch. 21 | WMHomeViewController *homeController = [[WMHomeViewController alloc] init]; 22 | UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:homeController]; 23 | self.window = [UIWindow new]; 24 | self.window.rootViewController = nav; 25 | [self.window makeKeyAndVisible]; 26 | return YES; 27 | } 28 | 29 | 30 | - (void)applicationWillResignActive:(UIApplication *)application { 31 | // 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. 32 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 33 | } 34 | 35 | 36 | - (void)applicationDidEnterBackground:(UIApplication *)application { 37 | // 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. 38 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 39 | } 40 | 41 | 42 | - (void)applicationWillEnterForeground:(UIApplication *)application { 43 | // 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. 44 | } 45 | 46 | 47 | - (void)applicationDidBecomeActive:(UIApplication *)application { 48 | // 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. 49 | } 50 | 51 | 52 | - (void)applicationWillTerminate:(UIApplication *)application { 53 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 54 | } 55 | 56 | 57 | @end 58 | -------------------------------------------------------------------------------- /WMPageControllerDemo/StickyExample/StickyExample/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 | } -------------------------------------------------------------------------------- /WMPageControllerDemo/StickyExample/StickyExample/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 | -------------------------------------------------------------------------------- /WMPageControllerDemo/StickyExample/StickyExample/Controllers/WMDetailViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // WMDetailViewController.h 3 | // StickyExample 4 | // 5 | // Created by Tpphha on 2017/7/22. 6 | // Copyright © 2017年 Tpphha. All rights reserved. 7 | // 8 | 9 | #import "WMPageController.h" 10 | 11 | @interface WMDetailViewController : WMPageController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /WMPageControllerDemo/StickyExample/StickyExample/Controllers/WMDetailViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // WMDetailViewController.m 3 | // StickyExample 4 | // 5 | // Created by Tpphha on 2017/7/22. 6 | // Copyright © 2017年 Tpphha. All rights reserved. 7 | // 8 | 9 | #import "WMDetailViewController.h" 10 | #import "WMTableViewController.h" 11 | 12 | @interface WMDetailViewController () 13 | @property (nonatomic, strong) NSArray *musicCategories; 14 | @end 15 | 16 | @implementation WMDetailViewController 17 | 18 | - (instancetype)init { 19 | if (self = [super init]) { 20 | self.titleSizeNormal = 15; 21 | self.titleSizeSelected = 15; 22 | self.menuViewStyle = WMMenuViewStyleLine; 23 | self.menuItemWidth = [UIScreen mainScreen].bounds.size.width / self.musicCategories.count; 24 | self.titleColorSelected = [UIColor colorWithRed:0.5 green:0.5 blue:0.5 alpha:1.0]; 25 | self.titleColorNormal = [UIColor colorWithRed:0.4 green:0.8 blue:0.1 alpha:1.0]; 26 | self.postNotification = YES; 27 | 28 | } 29 | return self; 30 | } 31 | 32 | 33 | - (void)viewDidLoad { 34 | [super viewDidLoad]; 35 | // Do any additional setup after loading the view. 36 | } 37 | 38 | - (void)didReceiveMemoryWarning { 39 | [super didReceiveMemoryWarning]; 40 | // Dispose of any resources that can be recreated. 41 | } 42 | 43 | #pragma mark - Datasource & Delegate 44 | - (NSInteger)numbersOfChildControllersInPageController:(WMPageController *)pageController { 45 | return self.musicCategories.count; 46 | } 47 | 48 | - (UIViewController *)pageController:(WMPageController *)pageController viewControllerAtIndex:(NSInteger)index { 49 | return [WMTableViewController new]; 50 | } 51 | 52 | - (NSString *)pageController:(WMPageController *)pageController titleAtIndex:(NSInteger)index { 53 | return self.musicCategories[index]; 54 | } 55 | 56 | - (CGRect)pageController:(WMPageController *)pageController preferredFrameForMenuView:(WMMenuView *)menuView { 57 | return CGRectMake(0, 0, self.view.frame.size.width, 44); 58 | } 59 | 60 | - (CGRect)pageController:(WMPageController *)pageController preferredFrameForContentView:(WMScrollView *)contentView { 61 | CGFloat menuViewHeight = [self pageController:pageController preferredFrameForMenuView:self.menuView].size.height; 62 | return CGRectMake(0, menuViewHeight, self.view.frame.size.width, self.view.frame.size.height - menuViewHeight); 63 | } 64 | 65 | #pragma mark - lazy 66 | - (NSArray *)musicCategories { 67 | if (!_musicCategories) { 68 | _musicCategories = @[@"单曲", @"详情", @"歌词"]; 69 | } 70 | return _musicCategories; 71 | } 72 | 73 | @end 74 | -------------------------------------------------------------------------------- /WMPageControllerDemo/StickyExample/StickyExample/Controllers/WMHomeViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // WMHomeViewController.h 3 | // Demo 4 | // 5 | // Created by Mark on 16/7/25. 6 | // Copyright © 2016年 Wecan Studio. All rights reserved. 7 | // 8 | 9 | #import "WMStickyPageController.h" 10 | 11 | @interface WMHomeViewController : WMStickyPageController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /WMPageControllerDemo/StickyExample/StickyExample/Controllers/WMHomeViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // WMHomeViewController.m 3 | // Demo 4 | // 5 | // Created by Mark on 16/7/25. 6 | // Copyright © 2016年 Wecan Studio. All rights reserved. 7 | // 8 | 9 | #import "WMHomeViewController.h" 10 | #import "WMTableViewController.h" 11 | #import "WMDetailViewController.h" 12 | 13 | static CGFloat const kWMMenuViewHeight = 44.0; 14 | static CGFloat const kWMHeaderViewHeight = 200; 15 | static CGFloat const kNavigationBarHeight = 64; 16 | 17 | @interface WMHomeViewController () 18 | @property (nonatomic, strong) NSArray *musicCategories; 19 | @property (nonatomic, strong) UIView *redView; 20 | @end 21 | 22 | @implementation WMHomeViewController 23 | 24 | - (instancetype)init { 25 | if (self = [super init]) { 26 | self.titleSizeNormal = 15; 27 | self.titleSizeSelected = 15; 28 | self.menuViewStyle = WMMenuViewStyleLine; 29 | self.menuItemWidth = [UIScreen mainScreen].bounds.size.width / self.musicCategories.count; 30 | self.titleColorSelected = [UIColor colorWithRed:0.5 green:0.5 blue:0.5 alpha:1.0]; 31 | self.titleColorNormal = [UIColor colorWithRed:0.4 green:0.8 blue:0.1 alpha:1.0]; 32 | 33 | self.menuViewHeight = kWMMenuViewHeight; 34 | self.maximumHeaderViewHeight = kWMHeaderViewHeight; 35 | self.minimumHeaderViewHeight = kNavigationBarHeight; 36 | } 37 | return self; 38 | } 39 | 40 | - (void)viewDidLoad { 41 | [super viewDidLoad]; 42 | // Do any additional setup after loading the view. 43 | self.title = @"专辑"; 44 | self.redView = [[UIView alloc] initWithFrame:CGRectZero]; 45 | self.redView.backgroundColor = [UIColor redColor]; 46 | [self.view addSubview:self.redView]; 47 | 48 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 49 | [self reloadData]; 50 | }); 51 | } 52 | 53 | - (void)viewDidLayoutSubviews { 54 | [super viewDidLayoutSubviews]; 55 | CGFloat headerViewHeight = kWMHeaderViewHeight; 56 | CGFloat headerViewX = 0; 57 | UIScrollView *scrollView = (UIScrollView *)self.view; 58 | if (scrollView.contentOffset.y < 0) { 59 | headerViewX = scrollView.contentOffset.y; 60 | headerViewHeight -= headerViewX; 61 | } 62 | self.redView.frame = CGRectMake(0, headerViewX, CGRectGetWidth(self.view.bounds), headerViewHeight); 63 | } 64 | 65 | - (void)didReceiveMemoryWarning { 66 | [super didReceiveMemoryWarning]; 67 | // Dispose of any resources that can be recreated. 68 | } 69 | 70 | #pragma mark - Action 71 | 72 | - (void)btnClicked:(id)sender { 73 | NSLog(@"touch up inside"); 74 | } 75 | 76 | #pragma mark - ScrollViewDelegate 77 | 78 | - (void)scrollViewDidScroll:(UIScrollView *)scrollView { 79 | [super scrollViewDidScroll:scrollView]; 80 | if (scrollView.contentOffset.y < 0) { 81 | [self.view setNeedsLayout]; 82 | } 83 | } 84 | 85 | #pragma mark - Datasource & Delegate 86 | - (NSInteger)numbersOfChildControllersInPageController:(WMPageController *)pageController { 87 | return self.musicCategories.count; 88 | } 89 | 90 | - (UIViewController *)pageController:(WMPageController *)pageController viewControllerAtIndex:(NSInteger)index { 91 | switch (index) { 92 | case 0: 93 | return [WMTableViewController new]; 94 | case 1:{ 95 | return [WMDetailViewController new]; 96 | } 97 | default: 98 | return [UIViewController new]; 99 | } 100 | } 101 | 102 | - (NSString *)pageController:(WMPageController *)pageController titleAtIndex:(NSInteger)index { 103 | return self.musicCategories[index]; 104 | } 105 | 106 | #pragma mark - lazy 107 | - (NSArray *)musicCategories { 108 | if (!_musicCategories) { 109 | _musicCategories = @[@"单曲", @"详情", @"歌词"]; 110 | } 111 | return _musicCategories; 112 | } 113 | 114 | @end 115 | -------------------------------------------------------------------------------- /WMPageControllerDemo/StickyExample/StickyExample/Controllers/WMTableViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // WMTableViewController.h 3 | // Demo 4 | // 5 | // Created by Mark on 16/7/25. 6 | // Copyright © 2016年 Wecan Studio. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface WMTableViewController : UITableViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /WMPageControllerDemo/StickyExample/StickyExample/Controllers/WMTableViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // WMTableViewController.m 3 | // Demo 4 | // 5 | // Created by Mark on 16/7/25. 6 | // Copyright © 2016年 Wecan Studio. All rights reserved. 7 | // 8 | 9 | #import "WMTableViewController.h" 10 | 11 | @interface WMTableViewController () 12 | 13 | @end 14 | 15 | static NSString *const kTablewCellIdentifier = @"kTablewCellIdentifier"; 16 | @implementation WMTableViewController 17 | 18 | - (void)viewDidLoad { 19 | [super viewDidLoad]; 20 | 21 | // Uncomment the following line to preserve selection between presentations. 22 | // self.clearsSelectionOnViewWillAppear = NO; 23 | 24 | // Uncomment the following line to display an Edit button in the navigation bar for this view controller. 25 | // self.navigationItem.rightBarButtonItem = self.editButtonItem; 26 | [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:kTablewCellIdentifier]; 27 | 28 | #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000 29 | if (@available(iOS 11.0, *)) { 30 | self.tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; 31 | } 32 | #endif 33 | self.automaticallyAdjustsScrollViewInsets = NO; 34 | } 35 | 36 | - (void)didReceiveMemoryWarning { 37 | [super didReceiveMemoryWarning]; 38 | // Dispose of any resources that can be recreated. 39 | } 40 | 41 | #pragma mark - Table view data source 42 | 43 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { 44 | return 1; 45 | } 46 | 47 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 48 | return 100; 49 | } 50 | 51 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 52 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kTablewCellIdentifier forIndexPath:indexPath]; 53 | cell.textLabel.text = @"歌曲"; 54 | return cell; 55 | } 56 | 57 | @end 58 | -------------------------------------------------------------------------------- /WMPageControllerDemo/StickyExample/StickyExample/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 | UIRequiredDeviceCapabilities 26 | 27 | armv7 28 | 29 | UISupportedInterfaceOrientations 30 | 31 | UIInterfaceOrientationPortrait 32 | UIInterfaceOrientationLandscapeLeft 33 | UIInterfaceOrientationLandscapeRight 34 | 35 | UISupportedInterfaceOrientations~ipad 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationPortraitUpsideDown 39 | UIInterfaceOrientationLandscapeLeft 40 | UIInterfaceOrientationLandscapeRight 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /WMPageControllerDemo/StickyExample/StickyExample/WMStickyPageController/WMMagicScrollView.h: -------------------------------------------------------------------------------- 1 | // MXScrollView.h 2 | // 3 | // Copyright (c) 2017 Maxime Epain 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 13 | // all 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 21 | // THE SOFTWARE. 22 | 23 | #import 24 | 25 | NS_ASSUME_NONNULL_BEGIN 26 | 27 | @class WMMagicScrollView; 28 | 29 | /** 30 | The delegate of a WMMagicScrollView object may adopt the WMMagicScrollViewDelegate protocol to control subview's scrolling effect. 31 | */ 32 | @protocol WMMagicScrollViewDelegate 33 | 34 | @optional 35 | /** 36 | Asks the page if the scrollview should scroll with the subview. 37 | 38 | @param scrollView The scrollview. This is the object sending the message. 39 | @param subview An instance of a sub view. 40 | 41 | @return YES to allow scrollview and subview to scroll together. YES by default. 42 | */ 43 | - (BOOL)scrollView:(WMMagicScrollView *)scrollView shouldScrollWithSubview:(UIScrollView *)subview; 44 | 45 | @end 46 | 47 | /** 48 | The WMMagicScrollView is a UIScrollView subclass with the ability to hook the vertical scroll from its subviews. 49 | */ 50 | @interface WMMagicScrollView : UIScrollView 51 | 52 | @property(nonatomic, assign) CGFloat minimumHeaderViewHeight; 53 | 54 | @property(nonatomic, assign) CGFloat maximumHeaderViewHeight; 55 | 56 | /** 57 | Delegate instance that adopt the MXScrollViewDelegate. 58 | */ 59 | @property (nonatomic, weak, nullable) IBOutlet id delegate; 60 | 61 | @end 62 | 63 | NS_ASSUME_NONNULL_END 64 | -------------------------------------------------------------------------------- /WMPageControllerDemo/StickyExample/StickyExample/WMStickyPageController/WMStickyPageController.h: -------------------------------------------------------------------------------- 1 | // 2 | // WMStickyPageViewController.h 3 | // StickyExample 4 | // 5 | // Created by Tpphha on 2017/7/22. 6 | // Copyright © 2017年 Tpphha. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class WMStickyPageController; 12 | 13 | @protocol WMStickyPageControllerDelegate; 14 | 15 | /** 16 | The self.view is custom UIScrollView 17 | */ 18 | @interface WMStickyPageController : WMPageController 19 | 20 | /** 21 | It's determine the sticky locatio. 22 | */ 23 | @property (nonatomic, assign) CGFloat minimumHeaderViewHeight; 24 | 25 | /** 26 | The custom headerView's height, default 0 means no effective. 27 | */ 28 | @property (nonatomic, assign) CGFloat maximumHeaderViewHeight; 29 | 30 | /** 31 | The menuView's height, default 44 32 | */ 33 | @property (nonatomic, assign) CGFloat menuViewHeight; 34 | 35 | @end 36 | 37 | @protocol WMStickyPageControllerDelegate 38 | 39 | @optional 40 | - (BOOL)pageController:(WMStickyPageController *)pageController shouldScrollWithSubview:(UIScrollView *)subview; 41 | 42 | @end 43 | -------------------------------------------------------------------------------- /WMPageControllerDemo/StickyExample/StickyExample/WMStickyPageController/WMStickyPageController.m: -------------------------------------------------------------------------------- 1 | // 2 | // WMStickyPageViewController.m 3 | // StickyExample 4 | // 5 | // Created by Tpphha on 2017/7/22. 6 | // Copyright © 2017年 Tpphha. All rights reserved. 7 | // 8 | 9 | #import "WMStickyPageController.h" 10 | #import "WMMagicScrollView.h" 11 | 12 | @interface WMStickyPageController () 13 | 14 | @property(nonatomic, strong) WMMagicScrollView *contentView; 15 | 16 | @end 17 | 18 | @implementation WMStickyPageController 19 | @dynamic delegate; 20 | 21 | #pragma mark - Life Cycle 22 | - (void)loadView { 23 | self.contentView.frame = [UIScreen mainScreen].bounds; 24 | self.view = self.contentView; 25 | } 26 | 27 | - (void)viewDidLayoutSubviews { 28 | [super viewDidLayoutSubviews]; 29 | self.contentView.contentSize = CGSizeMake(CGRectGetWidth(self.view.bounds), 30 | CGRectGetHeight(self.view.bounds) + 31 | self.maximumHeaderViewHeight); 32 | } 33 | 34 | #pragma mark - WMMagicScrollViewDelegate 35 | 36 | - (BOOL)scrollView:(WMMagicScrollView *)scrollView shouldScrollWithSubview:(UIScrollView *)subview { 37 | if ([subview isKindOfClass:WMScrollView.class]) { 38 | return NO; 39 | } 40 | 41 | if ([self.delegate conformsToProtocol:@protocol(WMStickyPageControllerDelegate)]) { 42 | id delegate = (id)self.delegate; 43 | if ([delegate respondsToSelector:@selector(pageController:shouldScrollWithSubview:)]) { 44 | return [delegate pageController:self shouldScrollWithSubview:subview]; 45 | } 46 | } 47 | 48 | return YES; 49 | } 50 | 51 | #pragma mark - WMPageControllerDataSource 52 | 53 | - (CGRect)pageController:(WMPageController *)pageController preferredFrameForMenuView:(WMMenuView *)menuView { 54 | CGFloat originY = self.maximumHeaderViewHeight; 55 | if (originY <= 0) { 56 | UINavigationBar *navigationBar = self.navigationController.navigationBar; 57 | originY = (self.showOnNavigationBar && navigationBar) ? 0 : CGRectGetMaxY(navigationBar.frame); 58 | } 59 | return CGRectMake(0, originY, CGRectGetWidth( self.view.frame), self.menuViewHeight); 60 | } 61 | 62 | - (CGRect)pageController:(WMPageController *)pageController preferredFrameForContentView:(WMScrollView *)contentView { 63 | CGRect preferredFrameForMenuView = [self pageController:pageController preferredFrameForMenuView:pageController.menuView]; 64 | UITabBar *tabBar = self.tabBarController.tabBar; 65 | CGFloat tabBarHeight = tabBar && !tabBar.hidden ? CGRectGetHeight(tabBar.frame) : 0; 66 | return CGRectMake(0, 67 | CGRectGetMaxY(preferredFrameForMenuView), 68 | CGRectGetWidth(preferredFrameForMenuView), 69 | CGRectGetHeight(self.view.frame) - 70 | self.minimumHeaderViewHeight - 71 | CGRectGetHeight(preferredFrameForMenuView) - 72 | tabBarHeight); 73 | 74 | } 75 | 76 | #pragma mark - setter & getter 77 | 78 | - (WMMagicScrollView *)contentView { 79 | if (!_contentView) { 80 | _contentView = [WMMagicScrollView new]; 81 | _contentView.delegate = self; 82 | } 83 | return _contentView; 84 | } 85 | 86 | - (void)setMinimumHeaderViewHeight:(CGFloat)minimumHeaderViewHeight { 87 | self.contentView.minimumHeaderViewHeight = minimumHeaderViewHeight; 88 | } 89 | 90 | - (CGFloat)minimumHeaderViewHeight { 91 | return self.contentView.minimumHeaderViewHeight; 92 | } 93 | 94 | - (void)setMaximumHeaderViewHeight:(CGFloat)maximumHeaderViewHeight { 95 | self.contentView.maximumHeaderViewHeight = maximumHeaderViewHeight; 96 | } 97 | 98 | - (CGFloat)maximumHeaderViewHeight { 99 | return self.contentView.maximumHeaderViewHeight; 100 | } 101 | 102 | @end 103 | 104 | -------------------------------------------------------------------------------- /WMPageControllerDemo/StickyExample/StickyExample/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // StickyExample 4 | // 5 | // Created by Tpphha on 2017/7/22. 6 | // Copyright © 2017年 Tpphha. 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 | -------------------------------------------------------------------------------- /WMPageControllerDemo/StickyExample/StickyExampleTests/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 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /WMPageControllerDemo/StickyExample/StickyExampleTests/StickyExampleTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // StickyExampleTests.m 3 | // StickyExampleTests 4 | // 5 | // Created by Tpphha on 2017/7/22. 6 | // Copyright © 2017年 Tpphha. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface StickyExampleTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation StickyExampleTests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | // Put setup code here. This method is called before the invocation of each test method in the class. 20 | } 21 | 22 | - (void)tearDown { 23 | // Put teardown code here. This method is called after the invocation of each test method in the class. 24 | [super tearDown]; 25 | } 26 | 27 | - (void)testExample { 28 | // This is an example of a functional test case. 29 | // Use XCTAssert and related functions to verify your tests produce the correct results. 30 | } 31 | 32 | - (void)testPerformanceExample { 33 | // This is an example of a performance test case. 34 | [self measureBlock:^{ 35 | // Put the code you want to measure the time of here. 36 | }]; 37 | } 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /WMPageControllerDemo/StickyExample/StickyExampleUITests/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 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /WMPageControllerDemo/StickyExample/StickyExampleUITests/StickyExampleUITests.m: -------------------------------------------------------------------------------- 1 | // 2 | // StickyExampleUITests.m 3 | // StickyExampleUITests 4 | // 5 | // Created by Tpphha on 2017/7/22. 6 | // Copyright © 2017年 Tpphha. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface StickyExampleUITests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation StickyExampleUITests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | 22 | // In UI tests it is usually best to stop immediately when a failure occurs. 23 | self.continueAfterFailure = NO; 24 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. 25 | [[[XCUIApplication alloc] init] launch]; 26 | 27 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 28 | } 29 | 30 | - (void)tearDown { 31 | // Put teardown code here. This method is called after the invocation of each test method in the class. 32 | [super tearDown]; 33 | } 34 | 35 | - (void)testExample { 36 | // Use recording to get started writing UI tests. 37 | // Use XCTAssert and related functions to verify your tests produce the correct results. 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /WMPageControllerDemo/StoryboardExample/Storyboard.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /WMPageControllerDemo/StoryboardExample/Storyboard/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // Storyboard 4 | // 5 | // Created by Mark on 15/12/5. 6 | // Copyright © 2015年 Wecan Studio. 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 | -------------------------------------------------------------------------------- /WMPageControllerDemo/StoryboardExample/Storyboard/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // Storyboard 4 | // 5 | // Created by Mark on 15/12/5. 6 | // Copyright © 2015年 Wecan Studio. 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 | self.window.backgroundColor = [UIColor whiteColor]; 21 | return YES; 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 throttle down OpenGL ES frame rates. Games should use this method to pause the game. 27 | } 28 | 29 | - (void)applicationDidEnterBackground:(UIApplication *)application { 30 | // 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. 31 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 32 | } 33 | 34 | - (void)applicationWillEnterForeground:(UIApplication *)application { 35 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 36 | } 37 | 38 | - (void)applicationDidBecomeActive:(UIApplication *)application { 39 | // 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. 40 | } 41 | 42 | - (void)applicationWillTerminate:(UIApplication *)application { 43 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 44 | } 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /WMPageControllerDemo/StoryboardExample/Storyboard/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 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /WMPageControllerDemo/StoryboardExample/Storyboard/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 | -------------------------------------------------------------------------------- /WMPageControllerDemo/StoryboardExample/Storyboard/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 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /WMPageControllerDemo/StoryboardExample/Storyboard/Controller/WMViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // WMViewController.h 3 | // WMPageController 4 | // 5 | // Created by Mark on 15/6/13. 6 | // Copyright (c) 2015年 yq. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface WMViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /WMPageControllerDemo/StoryboardExample/Storyboard/Controller/WMViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // WMViewController.m 3 | // WMPageController 4 | // 5 | // Created by Mark on 15/6/13. 6 | // Copyright (c) 2015年 yq. All rights reserved. 7 | // 8 | 9 | #import "WMViewController.h" 10 | 11 | @interface WMViewController () 12 | 13 | @end 14 | 15 | @implementation WMViewController 16 | 17 | - (void)dealloc { 18 | 19 | } 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /WMPageControllerDemo/StoryboardExample/Storyboard/CustomPageViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // CustomPageViewController.h 3 | // Storyboard 4 | // 5 | // Created by Mark on 15/12/5. 6 | // Copyright © 2015年 Wecan Studio. All rights reserved. 7 | // 8 | 9 | #import "WMPageController.h" 10 | 11 | @interface CustomPageViewController : WMPageController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /WMPageControllerDemo/StoryboardExample/Storyboard/CustomPageViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // CustomPageViewController.m 3 | // Storyboard 4 | // 5 | // Created by Mark on 15/12/5. 6 | // Copyright © 2015年 Wecan Studio. All rights reserved. 7 | // 8 | 9 | #import "CustomPageViewController.h" 10 | #import "WMViewController.h" 11 | 12 | @interface CustomPageViewController () 13 | 14 | @end 15 | 16 | @implementation CustomPageViewController 17 | - (NSArray *)titles { 18 | return @[@"你好", @"支持我", @"点赞"]; 19 | } 20 | 21 | - (instancetype)initWithCoder:(NSCoder *)aDecoder { 22 | self = [super initWithCoder:aDecoder]; 23 | if (self) { 24 | self.menuItemWidth = 60; 25 | self.menuViewStyle = WMMenuViewStyleLine; 26 | self.titleSizeSelected = 15.0; 27 | } 28 | return self; 29 | } 30 | 31 | - (void)viewDidLoad { 32 | [super viewDidLoad]; 33 | // Do any additional setup after loading the view. 34 | } 35 | 36 | - (void)didReceiveMemoryWarning { 37 | [super didReceiveMemoryWarning]; 38 | // Dispose of any resources that can be recreated. 39 | } 40 | 41 | #pragma mark - WMPageController DataSource 42 | - (NSInteger)numbersOfChildControllersInPageController:(WMPageController *)pageController { 43 | return self.titles.count; 44 | } 45 | 46 | - (NSString *)pageController:(WMPageController *)pageController titleAtIndex:(NSInteger)index { 47 | return self.titles[index]; 48 | } 49 | 50 | - (UIViewController *)pageController:(WMPageController *)pageController viewControllerAtIndex:(NSInteger)index { 51 | UIStoryboard *sb = [UIStoryboard storyboardWithName:@"Main" bundle:nil]; 52 | UIViewController *vc = [sb instantiateViewControllerWithIdentifier:@"WMViewController"]; 53 | return vc; 54 | } 55 | 56 | @end 57 | -------------------------------------------------------------------------------- /WMPageControllerDemo/StoryboardExample/Storyboard/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 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /WMPageControllerDemo/StoryboardExample/Storyboard/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // Storyboard 4 | // 5 | // Created by Mark on 15/12/5. 6 | // Copyright © 2015年 Wecan Studio. 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 | -------------------------------------------------------------------------------- /WMPageControllerDemo/StoryboardExample/StoryboardTests/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 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /WMPageControllerDemo/StoryboardExample/StoryboardTests/StoryboardTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // StoryboardTests.m 3 | // StoryboardTests 4 | // 5 | // Created by Mark on 15/12/5. 6 | // Copyright © 2015年 Wecan Studio. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface StoryboardTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation StoryboardTests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | // Put setup code here. This method is called before the invocation of each test method in the class. 20 | } 21 | 22 | - (void)tearDown { 23 | // Put teardown code here. This method is called after the invocation of each test method in the class. 24 | [super tearDown]; 25 | } 26 | 27 | - (void)testExample { 28 | // This is an example of a functional test case. 29 | // Use XCTAssert and related functions to verify your tests produce the correct results. 30 | } 31 | 32 | - (void)testPerformanceExample { 33 | // This is an example of a performance test case. 34 | [self measureBlock:^{ 35 | // Put the code you want to measure the time of here. 36 | }]; 37 | } 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /WMPageControllerDemo/StoryboardExample/StoryboardUITests/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 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /WMPageControllerDemo/StoryboardExample/StoryboardUITests/StoryboardUITests.m: -------------------------------------------------------------------------------- 1 | // 2 | // StoryboardUITests.m 3 | // StoryboardUITests 4 | // 5 | // Created by Mark on 15/12/5. 6 | // Copyright © 2015年 Wecan Studio. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface StoryboardUITests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation StoryboardUITests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | 22 | // In UI tests it is usually best to stop immediately when a failure occurs. 23 | self.continueAfterFailure = NO; 24 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. 25 | [[[XCUIApplication alloc] init] launch]; 26 | 27 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 28 | } 29 | 30 | - (void)tearDown { 31 | // Put teardown code here. This method is called after the invocation of each test method in the class. 32 | [super tearDown]; 33 | } 34 | 35 | - (void)testExample { 36 | // Use recording to get started writing UI tests. 37 | // Use XCTAssert and related functions to verify your tests produce the correct results. 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /WMPageControllerDemo/ViewFrameExample/ViewFrameDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /WMPageControllerDemo/ViewFrameExample/ViewFrameDemo/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // ViewFrameDemo 4 | // 5 | // Created by Mark on 16/7/25. 6 | // Copyright © 2016年 Wecan Studio. 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 | -------------------------------------------------------------------------------- /WMPageControllerDemo/ViewFrameExample/ViewFrameDemo/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // ViewFrameDemo 4 | // 5 | // Created by Mark on 16/7/25. 6 | // Copyright © 2016年 Wecan Studio. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | #import "WMHomeViewController.h" 11 | 12 | @interface AppDelegate () 13 | 14 | @end 15 | 16 | @implementation AppDelegate 17 | 18 | 19 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 20 | // Override point for customization after application launch. 21 | WMHomeViewController *homeController = [[WMHomeViewController alloc] init]; 22 | UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:homeController]; 23 | self.window.rootViewController = nav; 24 | return YES; 25 | } 26 | 27 | - (void)applicationWillResignActive:(UIApplication *)application { 28 | // 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. 29 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 30 | } 31 | 32 | - (void)applicationDidEnterBackground:(UIApplication *)application { 33 | // 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. 34 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 35 | } 36 | 37 | - (void)applicationWillEnterForeground:(UIApplication *)application { 38 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 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 | - (void)applicationWillTerminate:(UIApplication *)application { 46 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 47 | } 48 | 49 | @end 50 | -------------------------------------------------------------------------------- /WMPageControllerDemo/ViewFrameExample/ViewFrameDemo/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 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /WMPageControllerDemo/ViewFrameExample/ViewFrameDemo/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 | -------------------------------------------------------------------------------- /WMPageControllerDemo/ViewFrameExample/ViewFrameDemo/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 | 25 | 26 | -------------------------------------------------------------------------------- /WMPageControllerDemo/ViewFrameExample/ViewFrameDemo/Controllers/WMHomeViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // WMHomeViewController.h 3 | // Demo 4 | // 5 | // Created by Mark on 16/7/25. 6 | // Copyright © 2016年 Wecan Studio. All rights reserved. 7 | // 8 | 9 | #import "WMPageController.h" 10 | 11 | static CGFloat const kWMHeaderViewHeight = 200; 12 | static CGFloat const kNavigationBarHeight = 64; 13 | @interface WMHomeViewController : WMPageController 14 | @property (nonatomic, assign) CGFloat viewTop; 15 | @end 16 | -------------------------------------------------------------------------------- /WMPageControllerDemo/ViewFrameExample/ViewFrameDemo/Controllers/WMHomeViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // WMHomeViewController.m 3 | // Demo 4 | // 5 | // Created by Mark on 16/7/25. 6 | // Copyright © 2016年 Wecan Studio. All rights reserved. 7 | // 8 | 9 | #import "WMHomeViewController.h" 10 | #import "WMTableViewController.h" 11 | #import "WMPanGestureRecognizer.h" 12 | 13 | static CGFloat const kWMMenuViewHeight = 44.0; 14 | @interface WMHomeViewController () 15 | @property (nonatomic, strong) NSArray *musicCategories; 16 | @property (nonatomic, strong) WMPanGestureRecognizer *panGesture; 17 | @property (nonatomic, assign) CGPoint lastPoint; 18 | @property (nonatomic, strong) UIView *redView; 19 | @end 20 | 21 | @implementation WMHomeViewController 22 | 23 | - (NSArray *)musicCategories { 24 | if (!_musicCategories) { 25 | _musicCategories = @[@"单曲", @"详情", @"歌词"]; 26 | } 27 | return _musicCategories; 28 | } 29 | 30 | - (instancetype)init { 31 | if (self = [super init]) { 32 | self.titleSizeNormal = 15; 33 | self.titleSizeSelected = 15; 34 | self.menuViewStyle = WMMenuViewStyleLine; 35 | self.menuItemWidth = [UIScreen mainScreen].bounds.size.width / self.musicCategories.count; 36 | self.viewTop = kNavigationBarHeight + kWMHeaderViewHeight; 37 | self.titleColorSelected = [UIColor colorWithRed:0.5 green:0.5 blue:0.5 alpha:1.0]; 38 | self.titleColorNormal = [UIColor colorWithRed:0.4 green:0.8 blue:0.1 alpha:1.0]; 39 | } 40 | return self; 41 | } 42 | 43 | - (void)viewDidLoad { 44 | [super viewDidLoad]; 45 | // Do any additional setup after loading the view. 46 | self.title = @"专辑"; 47 | UIView *redView = [[UIView alloc] initWithFrame:CGRectMake(0, kNavigationBarHeight, [UIScreen mainScreen].bounds.size.width, kWMHeaderViewHeight)]; 48 | redView.backgroundColor = [UIColor redColor]; 49 | self.redView = redView; 50 | [self.view addSubview:self.redView]; 51 | self.panGesture = [[WMPanGestureRecognizer alloc] initWithTarget:self action:@selector(panOnView:)]; 52 | [self.view addGestureRecognizer:self.panGesture]; 53 | } 54 | 55 | - (void)btnClicked:(id)sender { 56 | NSLog(@"touch up inside"); 57 | } 58 | 59 | - (void)panOnView:(WMPanGestureRecognizer *)recognizer { 60 | NSLog(@"pannnnnning received.."); 61 | 62 | CGPoint currentPoint = [recognizer locationInView:self.view]; 63 | 64 | if (recognizer.state == UIGestureRecognizerStateBegan) { 65 | self.lastPoint = currentPoint; 66 | } else if (recognizer.state == UIGestureRecognizerStateEnded) { 67 | 68 | CGPoint velocity = [recognizer velocityInView:self.view]; 69 | CGFloat targetPoint = velocity.y < 0 ? kNavigationBarHeight : kNavigationBarHeight + kWMHeaderViewHeight; 70 | NSTimeInterval duration = fabs((targetPoint - self.viewTop) / velocity.y); 71 | 72 | if (fabs(velocity.y) * 1.0 > fabs(targetPoint - self.viewTop)) { 73 | NSLog(@"velocity: %lf", velocity.y); 74 | [UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{ 75 | self.viewTop = targetPoint; 76 | } completion:nil]; 77 | 78 | return; 79 | } 80 | 81 | } 82 | CGFloat yChange = currentPoint.y - self.lastPoint.y; 83 | 84 | self.viewTop += yChange; 85 | self.lastPoint = currentPoint; 86 | } 87 | 88 | // MARK: ChangeViewFrame (Animatable) 89 | - (void)setViewTop:(CGFloat)viewTop { 90 | _viewTop = viewTop; 91 | 92 | if (_viewTop <= kNavigationBarHeight) { 93 | _viewTop = kNavigationBarHeight; 94 | } 95 | 96 | if (_viewTop > kWMHeaderViewHeight + kNavigationBarHeight) { 97 | _viewTop = kWMHeaderViewHeight + kNavigationBarHeight; 98 | } 99 | 100 | self.redView.frame = ({ 101 | CGRect oriFrame = self.redView.frame; 102 | oriFrame.origin.y = _viewTop - kWMHeaderViewHeight; 103 | oriFrame; 104 | }); 105 | 106 | [self forceLayoutSubviews]; 107 | } 108 | 109 | - (void)didReceiveMemoryWarning { 110 | [super didReceiveMemoryWarning]; 111 | // Dispose of any resources that can be recreated. 112 | } 113 | 114 | #pragma mark - Datasource & Delegate 115 | - (NSInteger)numbersOfChildControllersInPageController:(WMPageController *)pageController { 116 | return self.musicCategories.count; 117 | } 118 | 119 | - (UIViewController *)pageController:(WMPageController *)pageController viewControllerAtIndex:(NSInteger)index { 120 | WMTableViewController *vc = [[WMTableViewController alloc] init]; 121 | return vc; 122 | } 123 | 124 | - (NSString *)pageController:(WMPageController *)pageController titleAtIndex:(NSInteger)index { 125 | return self.musicCategories[index]; 126 | } 127 | 128 | - (CGRect)pageController:(WMPageController *)pageController preferredFrameForMenuView:(WMMenuView *)menuView { 129 | return CGRectMake(0, _viewTop, self.view.frame.size.width, kWMMenuViewHeight); 130 | } 131 | 132 | - (CGRect)pageController:(WMPageController *)pageController preferredFrameForContentView:(WMScrollView *)contentView { 133 | CGFloat originY = _viewTop + kWMMenuViewHeight; 134 | return CGRectMake(0, originY, self.view.frame.size.width, self.view.frame.size.height - originY); 135 | } 136 | 137 | @end 138 | -------------------------------------------------------------------------------- /WMPageControllerDemo/ViewFrameExample/ViewFrameDemo/Controllers/WMTableViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // WMTableViewController.h 3 | // Demo 4 | // 5 | // Created by Mark on 16/7/25. 6 | // Copyright © 2016年 Wecan Studio. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface WMTableViewController : UITableViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /WMPageControllerDemo/ViewFrameExample/ViewFrameDemo/Controllers/WMTableViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // WMTableViewController.m 3 | // Demo 4 | // 5 | // Created by Mark on 16/7/25. 6 | // Copyright © 2016年 Wecan Studio. All rights reserved. 7 | // 8 | 9 | #import "WMTableViewController.h" 10 | 11 | @interface WMTableViewController () 12 | 13 | @end 14 | 15 | static NSString *const kTablewCellIdentifier = @"kTablewCellIdentifier"; 16 | @implementation WMTableViewController 17 | 18 | - (void)viewDidLoad { 19 | [super viewDidLoad]; 20 | 21 | // Uncomment the following line to preserve selection between presentations. 22 | // self.clearsSelectionOnViewWillAppear = NO; 23 | 24 | // Uncomment the following line to display an Edit button in the navigation bar for this view controller. 25 | // self.navigationItem.rightBarButtonItem = self.editButtonItem; 26 | [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:kTablewCellIdentifier]; 27 | } 28 | 29 | - (void)didReceiveMemoryWarning { 30 | [super didReceiveMemoryWarning]; 31 | // Dispose of any resources that can be recreated. 32 | } 33 | 34 | #pragma mark - Table view data source 35 | 36 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { 37 | return 1; 38 | } 39 | 40 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 41 | return 100; 42 | } 43 | 44 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 45 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kTablewCellIdentifier forIndexPath:indexPath]; 46 | cell.textLabel.text = @"歌曲"; 47 | return cell; 48 | } 49 | 50 | @end 51 | -------------------------------------------------------------------------------- /WMPageControllerDemo/ViewFrameExample/ViewFrameDemo/Gesture/WMPanGestureRecognizer.h: -------------------------------------------------------------------------------- 1 | // 2 | // WMPanGestureRecognizer.h 3 | // ViewFrameDemo 4 | // 5 | // Created by Mark on 2016/12/13. 6 | // Copyright © 2016年 Wecan Studio. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface WMPanGestureRecognizer : UIPanGestureRecognizer 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /WMPageControllerDemo/ViewFrameExample/ViewFrameDemo/Gesture/WMPanGestureRecognizer.m: -------------------------------------------------------------------------------- 1 | // 2 | // WMPanGestureRecognizer.m 3 | // ViewFrameDemo 4 | // 5 | // Created by Mark on 2016/12/13. 6 | // Copyright © 2016年 Wecan Studio. All rights reserved. 7 | // 8 | 9 | #import "WMPanGestureRecognizer.h" 10 | 11 | @interface WMPanGestureRecognizer () 12 | 13 | @end 14 | 15 | @implementation WMPanGestureRecognizer 16 | 17 | - (instancetype)initWithTarget:(id)target action:(SEL)action { 18 | if (self = [super initWithTarget:target action:action]) { 19 | self.delegate = self; 20 | } 21 | return self; 22 | } 23 | 24 | #pragma mark - Gesture Delegate 25 | - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer { 26 | if ([otherGestureRecognizer.view isKindOfClass:NSClassFromString(@"WMScrollView")]) { 27 | return NO; 28 | } 29 | return YES; 30 | } 31 | 32 | @end 33 | -------------------------------------------------------------------------------- /WMPageControllerDemo/ViewFrameExample/ViewFrameDemo/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 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /WMPageControllerDemo/ViewFrameExample/ViewFrameDemo/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // ViewFrameDemo 4 | // 5 | // Created by Mark on 16/7/25. 6 | // Copyright © 2016年 Wecan Studio. 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 | -------------------------------------------------------------------------------- /WMPageControllerDemo/ViewFrameExample/ViewFrameDemoUITests/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 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /WMPageControllerDemo/ViewFrameExample/ViewFrameDemoUITests/ViewFrameDemoUITests.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewFrameDemoUITests.m 3 | // ViewFrameDemoUITests 4 | // 5 | // Created by Mark on 16/7/25. 6 | // Copyright © 2016年 Wecan Studio. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewFrameDemoUITests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation ViewFrameDemoUITests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | 22 | // In UI tests it is usually best to stop immediately when a failure occurs. 23 | self.continueAfterFailure = NO; 24 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. 25 | [[[XCUIApplication alloc] init] launch]; 26 | 27 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 28 | } 29 | 30 | - (void)tearDown { 31 | // Put teardown code here. This method is called after the invocation of each test method in the class. 32 | [super tearDown]; 33 | } 34 | 35 | - (void)testExample { 36 | // Use recording to get started writing UI tests. 37 | // Use XCTAssert and related functions to verify your tests produce the correct results. 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /WMPageControllerDemo/WMPageControllerExample/WMPageControllerExample.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /WMPageControllerDemo/WMPageControllerExample/WMPageControllerExample/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // WMPageControllerExample 4 | // 5 | // Created by Mark on 2017/6/21. 6 | // Copyright © 2017年 Mark. 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 | -------------------------------------------------------------------------------- /WMPageControllerDemo/WMPageControllerExample/WMPageControllerExample/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // WMPageControllerExample 4 | // 5 | // Created by Mark on 2017/6/21. 6 | // Copyright © 2017年 Mark. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | #import "WMMainTableViewController.h" 11 | 12 | @interface AppDelegate () 13 | 14 | @end 15 | 16 | @implementation AppDelegate 17 | 18 | 19 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 20 | // Override point for customization after application launch. 21 | WMMainTableViewController *main = [[WMMainTableViewController alloc] init]; 22 | UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:main]; 23 | self.window.backgroundColor = [UIColor whiteColor]; 24 | self.window.rootViewController = nav; 25 | return YES; 26 | } 27 | 28 | 29 | - (void)applicationWillResignActive:(UIApplication *)application { 30 | // 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. 31 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 32 | } 33 | 34 | 35 | - (void)applicationDidEnterBackground:(UIApplication *)application { 36 | // 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. 37 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 38 | } 39 | 40 | 41 | - (void)applicationWillEnterForeground:(UIApplication *)application { 42 | // 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. 43 | } 44 | 45 | 46 | - (void)applicationDidBecomeActive:(UIApplication *)application { 47 | // 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. 48 | } 49 | 50 | 51 | - (void)applicationWillTerminate:(UIApplication *)application { 52 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 53 | } 54 | 55 | 56 | @end 57 | -------------------------------------------------------------------------------- /WMPageControllerDemo/WMPageControllerExample/WMPageControllerExample/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | } 88 | ], 89 | "info" : { 90 | "version" : 1, 91 | "author" : "xcode" 92 | } 93 | } -------------------------------------------------------------------------------- /WMPageControllerDemo/WMPageControllerExample/WMPageControllerExample/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /WMPageControllerDemo/WMPageControllerExample/WMPageControllerExample/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 | -------------------------------------------------------------------------------- /WMPageControllerDemo/WMPageControllerExample/WMPageControllerExample/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 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /WMPageControllerDemo/WMPageControllerExample/WMPageControllerExample/Controller/WMCollectionViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // WMCollectionViewController.h 3 | // WMPageController 4 | // 5 | // Created by Mark on 15/6/14. 6 | // Copyright (c) 2015年 yq. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface WMCollectionViewController : UICollectionViewController 12 | @property (nonatomic, copy) NSString *name; 13 | @end 14 | -------------------------------------------------------------------------------- /WMPageControllerDemo/WMPageControllerExample/WMPageControllerExample/Controller/WMCollectionViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // WMCollectionViewController.m 3 | // WMPageController 4 | // 5 | // Created by Mark on 15/6/14. 6 | // Copyright (c) 2015年 yq. All rights reserved. 7 | // 8 | 9 | #import "WMCollectionViewController.h" 10 | #import "WMImageViewCell.h" 11 | 12 | @interface WMCollectionViewController () 13 | @property (nonatomic, strong) NSArray *imageNames; 14 | @end 15 | 16 | @implementation WMCollectionViewController 17 | 18 | static NSString * const reuseIdentifier = @"WMCollectionCell"; 19 | 20 | - (instancetype)init { 21 | UICollectionViewFlowLayout *flow = [[UICollectionViewFlowLayout alloc] init]; 22 | flow.minimumLineSpacing = 1; 23 | flow.minimumInteritemSpacing = .1; 24 | CGFloat width = [[UIScreen mainScreen] bounds].size.width / 4 - 3*0.1; 25 | flow.itemSize = CGSizeMake(width,width); 26 | self = [self initWithCollectionViewLayout:flow]; 27 | if (self) { 28 | // insert code here... 29 | } 30 | return self; 31 | } 32 | 33 | - (void)viewDidLoad { 34 | [super viewDidLoad]; 35 | self.imageNames = @[@"The roar.jpg",@"Dragon Spirit.jpg",@"Night.jpg"]; 36 | self.collectionView.backgroundColor = [UIColor whiteColor]; 37 | [self.collectionView registerClass:[WMImageViewCell class] forCellWithReuseIdentifier:reuseIdentifier]; 38 | NSLog(@"%@",self.name); 39 | } 40 | 41 | - (void)viewWillAppear:(BOOL)animated{ 42 | [super viewWillAppear:animated]; 43 | NSLog(@"------------------------------%@ viewWillAppear",[self class]); 44 | } 45 | 46 | - (void)viewDidAppear:(BOOL)animated { 47 | [super viewDidAppear:animated]; 48 | NSLog(@"------------------------------%@ viewDidAppear",[self class]); 49 | } 50 | 51 | - (void)didReceiveMemoryWarning { 52 | [super didReceiveMemoryWarning]; 53 | // Dispose of any resources that can be recreated. 54 | } 55 | 56 | - (void)dealloc{ 57 | NSLog(@"%@ destroyed",[self class]); 58 | } 59 | 60 | #pragma mark 61 | - (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView { 62 | return 1; 63 | } 64 | 65 | - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { 66 | return 100; 67 | } 68 | 69 | - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { 70 | WMImageViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath]; 71 | NSInteger i = indexPath.row % self.imageNames.count; 72 | NSString *imageName = self.imageNames[i]; 73 | cell.imageView.image = [UIImage imageNamed:imageName]; 74 | return cell; 75 | } 76 | 77 | @end 78 | -------------------------------------------------------------------------------- /WMPageControllerDemo/WMPageControllerExample/WMPageControllerExample/Controller/WMSecondViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // WMSecondViewController.h 3 | // WMPageController 4 | // 5 | // Created by Mark on 16/2/27. 6 | // Copyright © 2016年 yq. All rights reserved. 7 | // 8 | 9 | #import 10 | @class WMPageController; 11 | 12 | @interface WMSecondViewController : UIViewController 13 | @property (nonatomic, strong) WMPageController *pageController; 14 | @end 15 | -------------------------------------------------------------------------------- /WMPageControllerDemo/WMPageControllerExample/WMPageControllerExample/Controller/WMSecondViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // WMSecondViewController.m 3 | // WMPageController 4 | // 5 | // Created by Mark on 16/2/27. 6 | // Copyright © 2016年 yq. All rights reserved. 7 | // 8 | 9 | #import "WMSecondViewController.h" 10 | #import "WMPageController.h" 11 | #import "WMTableViewController.h" 12 | 13 | @interface WMSecondViewController () 14 | 15 | @end 16 | 17 | @implementation WMSecondViewController 18 | 19 | - (void)viewDidLoad { 20 | [super viewDidLoad]; 21 | // Do any additional setup after loading the view. 22 | self.view.backgroundColor = [UIColor whiteColor]; 23 | if ([self.pageController isKindOfClass:[WMPageController class]]) { 24 | self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"刷新" style:UIBarButtonItemStyleDone target:self action:@selector(reloadPageController)]; 25 | self.title = @"刷新"; 26 | } else { 27 | UIView *redView = [[UIView alloc] initWithFrame:CGRectMake((self.view.frame.size.width - 100) / 2, 100, 100, 100)]; 28 | redView.backgroundColor = [UIColor redColor]; 29 | [self.view addSubview:redView]; 30 | } 31 | } 32 | 33 | - (void)viewWillAppear:(BOOL)animated { 34 | [super viewWillAppear:animated]; 35 | } 36 | 37 | - (void)reloadPageController { 38 | self.pageController.viewControllerClasses = @[[WMTableViewController class], [WMTableViewController class], [WMTableViewController class]]; 39 | self.pageController.titles = @[@"新闻", @"资讯", @"娱乐"]; 40 | self.pageController.values = nil; 41 | self.pageController.keys = nil; 42 | self.pageController.selectIndex = 1; 43 | [self.pageController reloadData]; 44 | [self.navigationController popViewControllerAnimated:YES]; 45 | } 46 | 47 | - (void)didReceiveMemoryWarning { 48 | [super didReceiveMemoryWarning]; 49 | // Dispose of any resources that can be recreated. 50 | } 51 | 52 | /* 53 | #pragma mark - Navigation 54 | 55 | // In a storyboard-based application, you will often want to do a little preparation before navigation 56 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 57 | // Get the new view controller using [segue destinationViewController]. 58 | // Pass the selected object to the new view controller. 59 | } 60 | */ 61 | 62 | @end 63 | -------------------------------------------------------------------------------- /WMPageControllerDemo/WMPageControllerExample/WMPageControllerExample/Controller/WMTableViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // WMTableViewController.h 3 | // WMPageController 4 | // 5 | // Created by Mark on 15/6/13. 6 | // Copyright (c) 2015年 yq. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface WMTableViewController : UITableViewController 12 | @property (nonatomic, copy) NSNumber *age; 13 | @end 14 | -------------------------------------------------------------------------------- /WMPageControllerDemo/WMPageControllerExample/WMPageControllerExample/Controller/WMTableViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // WMTableViewController.m 3 | // WMPageController 4 | // 5 | // Created by Mark on 15/6/13. 6 | // Copyright (c) 2015年 yq. All rights reserved. 7 | // 8 | 9 | #import "WMTableViewController.h" 10 | #import "WMSecondViewController.h" 11 | #import "WMLoopView.h" 12 | 13 | @interface WMTableViewController () 14 | 15 | @end 16 | 17 | @implementation WMTableViewController 18 | 19 | - (void)viewDidLoad { 20 | [super viewDidLoad]; 21 | self.tableView.showsVerticalScrollIndicator = NO; 22 | 23 | NSArray *images = @[@"zoro.jpg",@"three.jpg",@"onepiece.jpg"]; 24 | WMLoopView *loopView = [[WMLoopView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.width/1.8) images:images autoPlay:YES delay:10.0]; 25 | loopView.delegate = self; 26 | self.tableView.tableHeaderView = loopView; 27 | self.tableView.rowHeight = 80; 28 | NSLog(@"%@", self.age); 29 | } 30 | 31 | - (void)didReceiveMemoryWarning { 32 | [super didReceiveMemoryWarning]; 33 | // Dispose of any resources that can be recreated. 34 | } 35 | 36 | #pragma mark - Table view data source 37 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { 38 | return 1; 39 | } 40 | 41 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 42 | return 30; 43 | } 44 | 45 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 46 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"WMCell"]; 47 | if (cell == nil) { 48 | cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"WMCell"]; 49 | } 50 | cell.textLabel.text = @"Hello,I'm Mark."; 51 | cell.detailTextLabel.text = @"And I'm now a student."; 52 | cell.detailTextLabel.textColor = [UIColor grayColor]; 53 | cell.imageView.image = [UIImage imageNamed:@"github.png"]; 54 | return cell; 55 | } 56 | 57 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 58 | WMSecondViewController *vc = [[WMSecondViewController alloc] init]; 59 | vc.pageController = (WMPageController *)self.parentViewController; 60 | [self.navigationController pushViewController:vc animated:YES]; 61 | } 62 | 63 | - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath { 64 | if (indexPath.row % 2 == 0) { 65 | return YES; 66 | } 67 | return NO; 68 | } 69 | 70 | - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { 71 | 72 | } 73 | 74 | - (void)dealloc { 75 | NSLog(@"%@ destroyed",[self class]); 76 | } 77 | 78 | @end 79 | -------------------------------------------------------------------------------- /WMPageControllerDemo/WMPageControllerExample/WMPageControllerExample/Controller/WMViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // WMViewController.h 3 | // WMPageController 4 | // 5 | // Created by Mark on 15/6/13. 6 | // Copyright (c) 2015年 yq. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface WMViewController : UIViewController 12 | @property (nonatomic, strong) NSDictionary *model; 13 | @end 14 | -------------------------------------------------------------------------------- /WMPageControllerDemo/WMPageControllerExample/WMPageControllerExample/Controller/WMViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // WMViewController.m 3 | // WMPageController 4 | // 5 | // Created by Mark on 15/6/13. 6 | // Copyright (c) 2015年 yq. All rights reserved. 7 | // 8 | 9 | #import "WMViewController.h" 10 | 11 | @interface WMViewController () 12 | @property (nonatomic, weak) UIImageView *imageView; 13 | @property (nonatomic, weak) UILabel *label; 14 | @end 15 | 16 | @implementation WMViewController 17 | 18 | - (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { 19 | if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) { 20 | 21 | } 22 | return self; 23 | } 24 | 25 | - (void)viewDidLoad { 26 | [super viewDidLoad]; 27 | // Do any additional setup after loading the view. 28 | self.view.backgroundColor = [UIColor whiteColor]; 29 | 30 | UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 200, 180)]; 31 | imageView.image = [UIImage imageNamed:@"hitMark.jpg"]; 32 | self.imageView = imageView; 33 | [self.view addSubview:imageView]; 34 | UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 180, self.view.frame.size.width, 120)]; 35 | label.text = @"Hey,\ndo you have any suggestions?\nPlease contact me.\n:)"; 36 | label.numberOfLines = 0; 37 | label.font = [UIFont fontWithName:@"CourierNewPS-BoldMT" size:20]; 38 | self.label = label; 39 | label.textAlignment = NSTextAlignmentCenter; 40 | [self.view addSubview:label]; 41 | NSLog(@"%@",self.model); 42 | } 43 | 44 | - (void)viewDidLayoutSubviews { 45 | [super viewDidLayoutSubviews]; 46 | self.label.frame = CGRectMake(0, 180, self.view.frame.size.width, 120); 47 | self.imageView.frame = CGRectMake((self.view.frame.size.width-200)/2.0, 10, 200, 180); 48 | } 49 | 50 | - (void)didReceiveMemoryWarning { 51 | [super didReceiveMemoryWarning]; 52 | // Dispose of any resources that can be recreated. 53 | } 54 | 55 | - (void)dealloc { 56 | 57 | } 58 | 59 | @end 60 | -------------------------------------------------------------------------------- /WMPageControllerDemo/WMPageControllerExample/WMPageControllerExample/Images/Dragon Spirit.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangmchn/WMPageController/75ab2422d4a3e76a50d6903bdf4f6598c584d6fb/WMPageControllerDemo/WMPageControllerExample/WMPageControllerExample/Images/Dragon Spirit.jpg -------------------------------------------------------------------------------- /WMPageControllerDemo/WMPageControllerExample/WMPageControllerExample/Images/Night.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangmchn/WMPageController/75ab2422d4a3e76a50d6903bdf4f6598c584d6fb/WMPageControllerDemo/WMPageControllerExample/WMPageControllerExample/Images/Night.jpg -------------------------------------------------------------------------------- /WMPageControllerDemo/WMPageControllerExample/WMPageControllerExample/Images/The roar.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangmchn/WMPageController/75ab2422d4a3e76a50d6903bdf4f6598c584d6fb/WMPageControllerDemo/WMPageControllerExample/WMPageControllerExample/Images/The roar.jpg -------------------------------------------------------------------------------- /WMPageControllerDemo/WMPageControllerExample/WMPageControllerExample/Images/github.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangmchn/WMPageController/75ab2422d4a3e76a50d6903bdf4f6598c584d6fb/WMPageControllerDemo/WMPageControllerExample/WMPageControllerExample/Images/github.png -------------------------------------------------------------------------------- /WMPageControllerDemo/WMPageControllerExample/WMPageControllerExample/Images/hitMark.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangmchn/WMPageController/75ab2422d4a3e76a50d6903bdf4f6598c584d6fb/WMPageControllerDemo/WMPageControllerExample/WMPageControllerExample/Images/hitMark.jpg -------------------------------------------------------------------------------- /WMPageControllerDemo/WMPageControllerExample/WMPageControllerExample/Images/onepiece.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangmchn/WMPageController/75ab2422d4a3e76a50d6903bdf4f6598c584d6fb/WMPageControllerDemo/WMPageControllerExample/WMPageControllerExample/Images/onepiece.jpg -------------------------------------------------------------------------------- /WMPageControllerDemo/WMPageControllerExample/WMPageControllerExample/Images/three.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangmchn/WMPageController/75ab2422d4a3e76a50d6903bdf4f6598c584d6fb/WMPageControllerDemo/WMPageControllerExample/WMPageControllerExample/Images/three.jpg -------------------------------------------------------------------------------- /WMPageControllerDemo/WMPageControllerExample/WMPageControllerExample/Images/zoro.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangmchn/WMPageController/75ab2422d4a3e76a50d6903bdf4f6598c584d6fb/WMPageControllerDemo/WMPageControllerExample/WMPageControllerExample/Images/zoro.jpg -------------------------------------------------------------------------------- /WMPageControllerDemo/WMPageControllerExample/WMPageControllerExample/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 | -------------------------------------------------------------------------------- /WMPageControllerDemo/WMPageControllerExample/WMPageControllerExample/Views/WMImageViewCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // WMImageViewCell.h 3 | // WMPageController 4 | // 5 | // Created by Mark on 15/6/14. 6 | // Copyright (c) 2015年 yq. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface WMImageViewCell : UICollectionViewCell 12 | @property (nonatomic, weak) UIImageView *imageView; 13 | @end 14 | -------------------------------------------------------------------------------- /WMPageControllerDemo/WMPageControllerExample/WMPageControllerExample/Views/WMImageViewCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // WMImageViewCell.m 3 | // WMPageController 4 | // 5 | // Created by Mark on 15/6/14. 6 | // Copyright (c) 2015年 yq. All rights reserved. 7 | // 8 | 9 | #import "WMImageViewCell.h" 10 | 11 | @interface WMImageViewCell () 12 | 13 | @end 14 | 15 | @implementation WMImageViewCell 16 | 17 | - (instancetype)initWithFrame:(CGRect)frame { 18 | if (self = [super initWithFrame:frame]) { 19 | UIImageView *imageView = [[UIImageView alloc] init]; 20 | [self addSubview:imageView]; 21 | _imageView = imageView; 22 | } 23 | return self; 24 | } 25 | 26 | - (void)layoutSubviews { 27 | [super layoutSubviews]; 28 | self.imageView.frame = self.bounds; 29 | } 30 | 31 | @end 32 | -------------------------------------------------------------------------------- /WMPageControllerDemo/WMPageControllerExample/WMPageControllerExample/Views/WMLoopView.h: -------------------------------------------------------------------------------- 1 | // 2 | // WMLoopView.h 3 | // WMLoopView 4 | // 5 | // Created by Mark on 15/3/30. 6 | // Copyright (c) 2015年 yq. All rights reserved. 7 | // 8 | 9 | #import 10 | @class WMLoopView; 11 | @protocol WMLoopViewDelegate 12 | @optional 13 | - (void)loopViewDidSelectedImage:(WMLoopView *)loopView index:(int)index; 14 | @end 15 | 16 | @interface WMLoopView : UIView 17 | @property (nonatomic, weak) id delegate; 18 | @property (nonatomic, assign) BOOL autoPlay; 19 | @property (nonatomic, assign) NSTimeInterval timeInterval; 20 | @property (nonatomic, strong) NSArray *images; 21 | 22 | - (instancetype)initWithFrame:(CGRect)frame images:(NSArray *)images autoPlay:(BOOL)isAuto delay:(NSTimeInterval)timeInterval; 23 | @end 24 | -------------------------------------------------------------------------------- /WMPageControllerDemo/WMPageControllerExample/WMPageControllerExample/Views/WMLoopView.m: -------------------------------------------------------------------------------- 1 | // 2 | // WMLoopView.m 3 | // WMLoopView 4 | // 5 | // Created by Mark on 15/3/30. 6 | // Copyright (c) 2015年 yq. All rights reserved. 7 | // 8 | 9 | #import "WMLoopView.h" 10 | #define kIdentifier @"WMLoopViewCellIdentifier" 11 | #define kPageH 20 12 | @interface WMLoopView() 13 | @property (nonatomic, strong) NSMutableArray *currentImages; 14 | @property (nonatomic, assign) int currentPage; 15 | @property (nonatomic, weak) UIPageControl *pageControl; 16 | @property (nonatomic, weak) UIScrollView *scrollView; 17 | @end 18 | 19 | @implementation WMLoopView 20 | - (instancetype)initWithFrame:(CGRect)frame images:(NSArray *)images autoPlay:(BOOL)isAuto delay:(NSTimeInterval)timeInterval { 21 | if (self = [super initWithFrame:frame]) { 22 | _autoPlay = isAuto; 23 | _timeInterval = timeInterval; 24 | _images = images; 25 | _currentPage = 0; 26 | 27 | [self addScrollView]; 28 | [self addPageControl]; 29 | if (self.autoPlay == YES) { 30 | [self toPlay]; 31 | } 32 | } 33 | return self; 34 | } 35 | 36 | #pragma mark - Public Methods 37 | - (void)addPageControl { 38 | CGFloat height = self.frame.size.height; 39 | CGFloat width = self.frame.size.width; 40 | UIView *bgView = [[UIView alloc] initWithFrame:CGRectMake(0, height-kPageH, width, kPageH)]; 41 | bgView.backgroundColor = [UIColor colorWithRed:0.3 green:0.3 blue:0.3 alpha:0.2]; 42 | UIPageControl *pageControl = [[UIPageControl alloc] initWithFrame:CGRectMake(0, 0, width, kPageH)]; 43 | pageControl.numberOfPages = self.images.count; 44 | pageControl.currentPage = 0; 45 | pageControl.userInteractionEnabled = NO; 46 | _pageControl = pageControl; 47 | [bgView addSubview:self.pageControl]; 48 | [self addSubview:bgView]; 49 | } 50 | 51 | #pragma mark - Private Methods 52 | - (void)toPlay { 53 | [self performSelector:@selector(autoPlayToNextPage) withObject:nil afterDelay:_timeInterval]; 54 | } 55 | 56 | - (void)autoPlayToNextPage { 57 | [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(autoPlayToNextPage) object:nil]; 58 | [self.scrollView setContentOffset:CGPointMake(self.frame.size.width * 2, 0) animated:YES]; 59 | [self performSelector:@selector(autoPlayToNextPage) withObject:nil afterDelay:_timeInterval]; 60 | } 61 | 62 | - (NSMutableArray *)currentImages { 63 | if (_currentImages == nil) { 64 | _currentImages = [[NSMutableArray alloc] init]; 65 | } 66 | [_currentImages removeAllObjects]; 67 | NSInteger count = self.images.count; 68 | int i = (int)(_currentPage + count - 1)%count; 69 | [_currentImages addObject:self.images[i]]; 70 | [_currentImages addObject:self.images[_currentPage]]; 71 | i = (int)(_currentPage + 1)%count; 72 | [_currentImages addObject:self.images[i]]; 73 | return _currentImages; 74 | } 75 | 76 | - (void)addScrollView { 77 | UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:self.bounds]; 78 | CGFloat width = self.frame.size.width; 79 | CGFloat height = self.frame.size.height; 80 | for (int i = 0; i < 3; i++) { 81 | UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(i * width, 0, width, height)]; 82 | imageView.image = [UIImage imageNamed:self.currentImages[i]]; 83 | [scrollView addSubview:imageView]; 84 | } 85 | scrollView.scrollsToTop = NO; 86 | scrollView.contentSize = CGSizeMake(3*width, height); 87 | scrollView.contentOffset = CGPointMake(width, 0); 88 | scrollView.pagingEnabled = YES; 89 | scrollView.showsHorizontalScrollIndicator = NO; 90 | scrollView.showsVerticalScrollIndicator = NO; 91 | scrollView.delegate = self; 92 | UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(singleTapped:)]; 93 | [scrollView addGestureRecognizer:tap]; 94 | 95 | [self addSubview:scrollView]; 96 | _scrollView = scrollView; 97 | } 98 | 99 | - (void)refreshImages { 100 | NSArray *subViews = self.scrollView.subviews; 101 | for (int i = 0; i < subViews.count; i++) { 102 | UIImageView *imageView = (UIImageView *)subViews[i]; 103 | imageView.image = [UIImage imageNamed:self.currentImages[i]]; 104 | } 105 | 106 | [self.scrollView setContentOffset:CGPointMake(self.frame.size.width, 0)]; 107 | } 108 | 109 | #pragma mark - delegate 110 | - (void)singleTapped:(UITapGestureRecognizer *)recognizer { 111 | if ([self.delegate respondsToSelector:@selector(loopViewDidSelectedImage:index:)]) { 112 | [self.delegate loopViewDidSelectedImage:self index:_currentPage]; 113 | } 114 | } 115 | 116 | - (void)scrollViewDidScroll:(UIScrollView *)scrollView { 117 | CGFloat x = scrollView.contentOffset.x; 118 | CGFloat width = self.frame.size.width; 119 | if (x >= 2 * width) { 120 | _currentPage = (++_currentPage) % self.images.count; 121 | self.pageControl.currentPage = _currentPage; 122 | [self refreshImages]; 123 | } 124 | if (x <= 0) { 125 | _currentPage = (int)(_currentPage + self.images.count - 1)%self.images.count; 126 | self.pageControl.currentPage = _currentPage; 127 | [self refreshImages]; 128 | } 129 | 130 | } 131 | 132 | - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { 133 | [scrollView setContentOffset:CGPointMake(self.frame.size.width, 0) animated:YES]; 134 | } 135 | 136 | @end 137 | -------------------------------------------------------------------------------- /WMPageControllerDemo/WMPageControllerExample/WMPageControllerExample/WMCustomizedPageController.h: -------------------------------------------------------------------------------- 1 | // 2 | // WMCustomizedPageController.h 3 | // WMPageControllerExample 4 | // 5 | // Created by Mark on 2017/6/21. 6 | // Copyright © 2017年 Mark. All rights reserved. 7 | // 8 | 9 | #import "WMPageController.h" 10 | 11 | typedef NS_ENUM(NSUInteger, WMMenuViewPosition) { 12 | WMMenuViewPositionDefault, 13 | WMMenuViewPositionBottom, 14 | }; 15 | 16 | @interface WMCustomizedPageController : WMPageController 17 | @property (nonatomic, assign) WMMenuViewPosition menuViewPosition; 18 | @end 19 | -------------------------------------------------------------------------------- /WMPageControllerDemo/WMPageControllerExample/WMPageControllerExample/WMCustomizedPageController.m: -------------------------------------------------------------------------------- 1 | // 2 | // WMCustomizedPageController.m 3 | // WMPageControllerExample 4 | // 5 | // Created by Mark on 2017/6/21. 6 | // Copyright © 2017年 Mark. All rights reserved. 7 | // 8 | 9 | #import "WMCustomizedPageController.h" 10 | #import "WMTableViewController.h" 11 | #import "WMViewController.h" 12 | #import "WMCollectionViewController.h" 13 | 14 | @interface WMCustomizedPageController () 15 | @property (nonatomic, strong) UIView *redView; 16 | @end 17 | 18 | @implementation WMCustomizedPageController 19 | 20 | - (UIView *)redView { 21 | if (!_redView) { 22 | _redView = [[UIView alloc] initWithFrame:CGRectZero]; 23 | _redView.backgroundColor = [UIColor colorWithRed:168.0/255.0 green:20.0/255.0 blue:4/255.0 alpha:1]; 24 | } 25 | return _redView; 26 | } 27 | 28 | - (void)viewDidLoad { 29 | [super viewDidLoad]; 30 | // Do any additional setup after loading the view. 31 | if (self.menuViewStyle == WMMenuViewStyleTriangle) { 32 | [self.view addSubview:self.redView]; 33 | } 34 | } 35 | 36 | - (void)viewDidLayoutSubviews { 37 | [super viewDidLayoutSubviews]; 38 | self.redView.frame = CGRectMake(0, CGRectGetMaxY(self.menuView.frame), self.view.frame.size.width, 2.0); 39 | } 40 | 41 | - (void)didReceiveMemoryWarning { 42 | [super didReceiveMemoryWarning]; 43 | // Dispose of any resources that can be recreated. 44 | } 45 | 46 | - (NSInteger)numbersOfChildControllersInPageController:(WMPageController *)pageController { 47 | switch (self.menuViewStyle) { 48 | case WMMenuViewStyleFlood: return 3; 49 | case WMMenuViewStyleSegmented: return 3; 50 | default: return 10; 51 | } 52 | } 53 | 54 | - (NSString *)pageController:(WMPageController *)pageController titleAtIndex:(NSInteger)index { 55 | switch (index % 3) { 56 | case 0: return @"LIST"; 57 | case 1: return @"INTRODUCTION"; 58 | case 2: return @"IMAGES"; 59 | } 60 | return @"NONE"; 61 | } 62 | 63 | - (UIViewController *)pageController:(WMPageController *)pageController viewControllerAtIndex:(NSInteger)index { 64 | switch (index % 3) { 65 | case 0: return [[WMTableViewController alloc] init]; 66 | case 1: return [[WMViewController alloc] init]; 67 | case 2: return [[WMCollectionViewController alloc] init]; 68 | } 69 | return [[UIViewController alloc] init]; 70 | } 71 | 72 | - (CGFloat)menuView:(WMMenuView *)menu widthForItemAtIndex:(NSInteger)index { 73 | CGFloat width = [super menuView:menu widthForItemAtIndex:index]; 74 | return width + 20; 75 | } 76 | 77 | - (CGRect)pageController:(WMPageController *)pageController preferredFrameForMenuView:(WMMenuView *)menuView { 78 | if (self.menuViewPosition == WMMenuViewPositionBottom) { 79 | menuView.backgroundColor = [UIColor colorWithWhite:0.95 alpha:1.0]; 80 | return CGRectMake(0, self.view.frame.size.height - 44, self.view.frame.size.width, 44); 81 | } 82 | CGFloat leftMargin = self.showOnNavigationBar ? 50 : 0; 83 | CGFloat originY = self.showOnNavigationBar ? 0 : CGRectGetMaxY(self.navigationController.navigationBar.frame); 84 | return CGRectMake(leftMargin, originY, self.view.frame.size.width - 2*leftMargin, 44); 85 | } 86 | 87 | - (CGRect)pageController:(WMPageController *)pageController preferredFrameForContentView:(WMScrollView *)contentView { 88 | if (self.menuViewPosition == WMMenuViewPositionBottom) { 89 | return CGRectMake(0, 64, self.view.frame.size.width, self.view.frame.size.height - 64 - 44); 90 | } 91 | CGFloat originY = CGRectGetMaxY([self pageController:pageController preferredFrameForMenuView:self.menuView]); 92 | if (self.menuViewStyle == WMMenuViewStyleTriangle) { 93 | originY += self.redView.frame.size.height; 94 | } 95 | return CGRectMake(0, originY, self.view.frame.size.width, self.view.frame.size.height - originY); 96 | } 97 | 98 | @end 99 | -------------------------------------------------------------------------------- /WMPageControllerDemo/WMPageControllerExample/WMPageControllerExample/WMMainTableViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // WMMainTableViewController.h 3 | // WMPageControllerExample 4 | // 5 | // Created by Mark on 2017/6/21. 6 | // Copyright © 2017年 Mark. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface WMMainTableViewController : UITableViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /WMPageControllerDemo/WMPageControllerExample/WMPageControllerExample/WMMainTableViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // WMMainTableViewController.m 3 | // WMPageControllerExample 4 | // 5 | // Created by Mark on 2017/6/21. 6 | // Copyright © 2017年 Mark. All rights reserved. 7 | // 8 | 9 | #import "WMMainTableViewController.h" 10 | #import "WMCustomizedPageController.h" 11 | 12 | @interface WMMainTableViewController () 13 | @property (nonatomic, strong) NSArray *titles; 14 | @property (nonatomic, strong) NSDictionary *stylesMap; 15 | @end 16 | 17 | @implementation WMMainTableViewController 18 | 19 | - (NSArray *)titles { 20 | if (_titles == nil) { 21 | _titles = @[@"WMMenuViewStyleDefault", 22 | @"WMMenuViewStyleLine", 23 | @"WMMenuViewStyleFlood", 24 | @"WMMenuViewStyleFloodHollow", 25 | @"WMMenuViewShowOnNav", 26 | @"WMMenuViewStyleSegmented", 27 | @"WMMenuViewStyleTriangle", 28 | @"WMMenuViewStyleNaughty", 29 | @"WMMenuViewCornerRadius", 30 | @"WMMenuViewPositionBottom"]; 31 | } 32 | return _titles; 33 | } 34 | 35 | - (NSDictionary *)stylesMap { 36 | if (!_stylesMap) { 37 | _stylesMap = @{@"WMMenuViewStyleDefault": @(WMMenuViewStyleDefault), 38 | @"WMMenuViewStyleLine": @(WMMenuViewStyleLine), 39 | @"WMMenuViewStyleFlood": @(WMMenuViewStyleFlood), 40 | @"WMMenuViewStyleFloodHollow": @(WMMenuViewStyleFloodHollow), 41 | @"WMMenuViewShowOnNav": @(WMMenuViewStyleFlood), 42 | @"WMMenuViewStyleSegmented": @(WMMenuViewStyleSegmented), 43 | @"WMMenuViewStyleTriangle": @(WMMenuViewStyleTriangle), 44 | @"WMMenuViewStyleNaughty": @(WMMenuViewStyleLine), 45 | @"WMMenuViewCornerRadius": @(WMMenuViewStyleFlood), 46 | @"WMMenuViewPositionBottom": @(WMMenuViewStyleDefault)}; 47 | } 48 | return _stylesMap; 49 | } 50 | 51 | - (void)viewDidLoad { 52 | [super viewDidLoad]; 53 | 54 | // Uncomment the following line to preserve selection between presentations. 55 | // self.clearsSelectionOnViewWillAppear = NO; 56 | 57 | // Uncomment the following line to display an Edit button in the navigation bar for this view controller. 58 | // self.navigationItem.rightBarButtonItem = self.editButtonItem; 59 | } 60 | 61 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { 62 | return 1; 63 | } 64 | 65 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 66 | return self.titles.count; 67 | } 68 | 69 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 70 | static NSString *const cellIdentifier = @"WMMainCell"; 71 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier]; 72 | if (cell == nil) { 73 | cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault 74 | reuseIdentifier:cellIdentifier]; 75 | } 76 | cell.textLabel.text = self.titles[indexPath.row]; 77 | return cell; 78 | } 79 | 80 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 81 | NSString *key = self.titles[indexPath.row]; 82 | WMMenuViewStyle style = [self.stylesMap[key] integerValue]; 83 | 84 | WMCustomizedPageController *vc = [[WMCustomizedPageController alloc] init]; 85 | vc.selectIndex = 1; 86 | vc.title = key; 87 | vc.menuViewStyle = style; 88 | vc.automaticallyCalculatesItemWidths = YES; 89 | if ([key isEqualToString:@"WMMenuViewStyleNaughty"]) { 90 | vc.progressViewIsNaughty = YES; 91 | vc.progressWidth = 10; 92 | } 93 | if ([key isEqualToString:@"WMMenuViewCornerRadius"]) { 94 | vc.progressViewCornerRadius = 5.0f; 95 | } 96 | if ([key isEqualToString:@"WMMenuViewPositionBottom"]) { 97 | vc.menuViewPosition = WMMenuViewPositionBottom; 98 | } 99 | [self customizePageController:vc]; 100 | [self.navigationController pushViewController:vc animated:YES]; 101 | } 102 | 103 | - (void)customizePageController:(WMPageController *)vc { 104 | switch (vc.menuViewStyle) { 105 | case WMMenuViewStyleSegmented: 106 | case WMMenuViewStyleFlood: { 107 | vc.titleColorSelected = [UIColor whiteColor]; 108 | vc.titleColorNormal = [UIColor colorWithRed:168.0/255.0 green:20.0/255.0 blue:4/255.0 alpha:1]; 109 | vc.progressColor = [UIColor colorWithRed:168.0/255.0 green:20.0/255.0 blue:4/255.0 alpha:1]; 110 | vc.showOnNavigationBar = YES; 111 | vc.menuViewLayoutMode = WMMenuViewLayoutModeCenter; 112 | vc.titleSizeSelected = 15; 113 | } 114 | break; 115 | case WMMenuViewStyleTriangle: { 116 | vc.progressWidth = 6; 117 | vc.progressHeight = 4; 118 | vc.titleSizeSelected = 15; 119 | } 120 | break; 121 | case WMMenuViewStyleDefault: { 122 | vc.titleSizeSelected = 16; 123 | } 124 | break; 125 | default: 126 | break; 127 | } 128 | } 129 | 130 | @end 131 | -------------------------------------------------------------------------------- /WMPageControllerDemo/WMPageControllerExample/WMPageControllerExample/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // WMPageControllerExample 4 | // 5 | // Created by Mark on 2017/6/21. 6 | // Copyright © 2017年 Mark. 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 | -------------------------------------------------------------------------------- /WMPageControllerDemo/WMPageControllerExample/WMPageControllerExampleTests/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 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /WMPageControllerDemo/WMPageControllerExample/WMPageControllerExampleTests/WMPageControllerExampleTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // WMPageControllerExampleTests.m 3 | // WMPageControllerExampleTests 4 | // 5 | // Created by Mark on 2017/6/21. 6 | // Copyright © 2017年 Mark. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface WMPageControllerExampleTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation WMPageControllerExampleTests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | // Put setup code here. This method is called before the invocation of each test method in the class. 20 | } 21 | 22 | - (void)tearDown { 23 | // Put teardown code here. This method is called after the invocation of each test method in the class. 24 | [super tearDown]; 25 | } 26 | 27 | - (void)testExample { 28 | // This is an example of a functional test case. 29 | // Use XCTAssert and related functions to verify your tests produce the correct results. 30 | } 31 | 32 | - (void)testPerformanceExample { 33 | // This is an example of a performance test case. 34 | [self measureBlock:^{ 35 | // Put the code you want to measure the time of here. 36 | }]; 37 | } 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /WMPageControllerDemo/WMPageControllerExample/WMPageControllerExampleUITests/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 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /WMPageControllerDemo/WMPageControllerExample/WMPageControllerExampleUITests/WMPageControllerExampleUITests.m: -------------------------------------------------------------------------------- 1 | // 2 | // WMPageControllerExampleUITests.m 3 | // WMPageControllerExampleUITests 4 | // 5 | // Created by Mark on 2017/6/21. 6 | // Copyright © 2017年 Mark. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface WMPageControllerExampleUITests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation WMPageControllerExampleUITests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | 22 | // In UI tests it is usually best to stop immediately when a failure occurs. 23 | self.continueAfterFailure = NO; 24 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. 25 | [[[XCUIApplication alloc] init] launch]; 26 | 27 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 28 | } 29 | 30 | - (void)tearDown { 31 | // Put teardown code here. This method is called after the invocation of each test method in the class. 32 | [super tearDown]; 33 | } 34 | 35 | - (void)testExample { 36 | // Use recording to get started writing UI tests. 37 | // Use XCTAssert and related functions to verify your tests produce the correct results. 38 | } 39 | 40 | @end 41 | --------------------------------------------------------------------------------