├── SilentScrolly.xcodeproj
├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
├── xcshareddata
│ └── xcschemes
│ │ └── SilentScrolly.xcscheme
└── project.pbxproj
├── SilentScrolly
├── SilentScrolly.h
├── Info.plist
├── SilentScrolly.swift
└── SilentScrollable.swift
├── Example
├── Sources
│ ├── Controllers
│ │ ├── TabBar
│ │ │ ├── NavigationController.swift
│ │ │ ├── TabBarController.swift
│ │ │ └── TabBarController.storyboard
│ │ ├── Table
│ │ │ ├── TableVIewController.swift
│ │ │ └── TableViewController.storyboard
│ │ ├── ToolBar
│ │ │ ├── ToolBarViewController.storyboard
│ │ │ └── ToolBarViewController.swift
│ │ ├── Web
│ │ │ ├── WebViewController.swift
│ │ │ └── WebViewController.storyboard
│ │ └── Collection
│ │ │ ├── CollectionViewController.swift
│ │ │ └── CollectionViewController.storyboard
│ └── AppDelegate.swift
└── Resources
│ ├── Info.plist
│ ├── Assets.xcassets
│ └── AppIcon.appiconset
│ │ └── Contents.json
│ └── LaunchScreen.storyboard
├── SilentScrolly.podspec
├── LICENSE
├── .gitignore
└── README.md
/SilentScrolly.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/SilentScrolly.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/SilentScrolly/SilentScrolly.h:
--------------------------------------------------------------------------------
1 | //
2 | // SilentScrolly.h
3 | // SilentScrolly
4 | //
5 | // Created by Takuma Horiuchi on 2018/02/19.
6 | // Copyright © 2018年 Takuma Horiuchi. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | //! Project version number for SilentScrolly.
12 | FOUNDATION_EXPORT double SilentScrollyVersionNumber;
13 |
14 | //! Project version string for SilentScrolly.
15 | FOUNDATION_EXPORT const unsigned char SilentScrollyVersionString[];
16 |
17 | // In this header, you should import all the public headers of your framework using statements like #import
18 |
19 |
20 |
--------------------------------------------------------------------------------
/Example/Sources/Controllers/TabBar/NavigationController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NavigationController.swift
3 | // Example
4 | //
5 | // Created by Takuma Horiuchi on 2018/03/11.
6 | // Copyright © 2018年 Takuma Horiuchi. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | final class NavigationController: UINavigationController {
12 |
13 | override var preferredStatusBarStyle: UIStatusBarStyle {
14 | return topViewController?.preferredStatusBarStyle ?? .default
15 | }
16 |
17 | override func viewDidLoad() {
18 | super.viewDidLoad()
19 |
20 | navigationBar.barTintColor = .darkGray
21 | navigationBar.tintColor = .white
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/Example/Sources/Controllers/TabBar/TabBarController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TabBarController.swift
3 | // Example
4 | //
5 | // Created by Takuma Horiuchi on 2018/02/20.
6 | // Copyright © 2018年 Takuma Horiuchi. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | final class TabBarController: UITabBarController {
12 |
13 | private enum Const {
14 | static let tabBarItemTitles = ["First"]
15 | }
16 |
17 | override func viewDidLoad() {
18 | super.viewDidLoad()
19 |
20 | for (index, title) in Const.tabBarItemTitles.enumerated() {
21 | tabBar.items?[index].title = title
22 | }
23 |
24 | tabBar.barTintColor = .darkGray
25 | tabBar.tintColor = .white
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/SilentScrolly/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | $(CURRENT_PROJECT_VERSION)
21 | NSPrincipalClass
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/SilentScrolly.podspec:
--------------------------------------------------------------------------------
1 | Pod::Spec.new do |s|
2 | s.name = "SilentScrolly"
3 | s.version = "1.0.8"
4 | s.summary = "Scroll to hide navigationBar, tabBar and toolBar."
5 | s.description = <<-DESC
6 | Adding too much UIGestureRecognizer to the UIView makes handling difficult, so it was handled by UIScrollViewDelegate.
7 | DESC
8 | s.homepage = "https://github.com/horitaku46/SilentScrolly"
9 | s.license = { :type => "MIT", :file => "./LICENSE" }
10 | s.author = { "Takuma Horiuchi" => "horitaku46@gmail.com" }
11 | s.social_media_url = "https://twitter.com/horitaku46"
12 | s.platform = :ios, "11.0"
13 | s.source = { :git => "https://github.com/horitaku46/SilentScrolly.git", :tag => "#{s.version}" }
14 | s.source_files = "SilentScrolly/**/*.{swift}"
15 | s.swift_version = "4.0"
16 | end
17 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Takuma Horiuchi
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 |
--------------------------------------------------------------------------------
/SilentScrolly/SilentScrolly.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SilentScrolly.swift
3 | // SilentScrolly
4 | //
5 | // Created by Takuma Horiuchi on 2018/02/22.
6 | // Copyright © 2018年 Takuma Horiuchi. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | public struct SilentScrolly {
12 |
13 | public enum Const {
14 | public static let minDoNothingAdjustNavigationBarVelocityY: CGFloat = 0
15 | public static let maxDoNothingAdjustNavigationBarVelocityY: CGFloat = 1400
16 | public static let animateDuration: TimeInterval = 0.3
17 | }
18 |
19 | public var preferredStatusBarStyle: UIStatusBarStyle? = nil
20 | public var showStatusBarStyle: UIStatusBarStyle = .default
21 | public var hideStatusBarStyle: UIStatusBarStyle = .default
22 |
23 | public var scrollView: UIScrollView? = nil
24 |
25 | public var isNavigationBarShow = true
26 | public var isTransitionCompleted = true
27 | public var isAddObserver = true
28 |
29 | public var prevPositiveContentOffsetY: CGFloat = 0
30 |
31 | public var showNavigationBarFrameOriginY: CGFloat = 0
32 | public var hideNavigationBarFrameOriginY: CGFloat = 0
33 | public var showScrollIndicatorInsetsTop: CGFloat = 0
34 | public var hideScrollIndicatorInsetsTop: CGFloat = 0
35 |
36 | public var bottomView: UIView?
37 | public var showBottomViewFrameOriginY: CGFloat = 0
38 | public var hideBottomViewFrameOriginY: CGFloat = 0
39 | public var showContentInsetBottom: CGFloat = 0
40 | public var hideContentInsetBottom: CGFloat = 0
41 | }
42 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | #
3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
4 |
5 | ## Build generated
6 | build/
7 | DerivedData/
8 |
9 | ## Various settings
10 | *.pbxuser
11 | !default.pbxuser
12 | *.mode1v3
13 | !default.mode1v3
14 | *.mode2v3
15 | !default.mode2v3
16 | *.perspectivev3
17 | !default.perspectivev3
18 | xcuserdata/
19 |
20 | ## Other
21 | *.moved-aside
22 | *.xccheckout
23 | *.xcscmblueprint
24 |
25 | ## Obj-C/Swift specific
26 | *.hmap
27 | *.ipa
28 | *.dSYM.zip
29 | *.dSYM
30 |
31 | ## Playgrounds
32 | timeline.xctimeline
33 | playground.xcworkspace
34 |
35 | # Swift Package Manager
36 | #
37 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
38 | # Packages/
39 | # Package.pins
40 | .build/
41 |
42 | # CocoaPods
43 | #
44 | # We recommend against adding the Pods directory to your .gitignore. However
45 | # you should judge for yourself, the pros and cons are mentioned at:
46 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
47 | #
48 | # Pods/
49 |
50 | # Carthage
51 | #
52 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
53 |
54 | Carthage/
55 |
56 | # fastlane
57 | #
58 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
59 | # screenshots whenever they are needed.
60 | # For more information about the recommended setup visit:
61 | # https://docs.fastlane.tools/best-practices/source-control/#source-control
62 |
63 | fastlane/report.xml
64 | fastlane/Preview.html
65 | fastlane/screenshots
66 | fastlane/test_output
67 |
--------------------------------------------------------------------------------
/Example/Resources/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | SilentScrolly
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 | LSRequiresIPhoneOS
22 |
23 | NSAppTransportSecurity
24 |
25 | NSAllowsArbitraryLoads
26 |
27 |
28 | UILaunchStoryboardName
29 | LaunchScreen
30 | UIMainStoryboardFile
31 | TabBarController
32 | UIRequiredDeviceCapabilities
33 |
34 | armv7
35 |
36 | UISupportedInterfaceOrientations
37 |
38 | UIInterfaceOrientationPortrait
39 | UIInterfaceOrientationLandscapeLeft
40 | UIInterfaceOrientationLandscapeRight
41 |
42 | UISupportedInterfaceOrientations~ipad
43 |
44 | UIInterfaceOrientationPortrait
45 | UIInterfaceOrientationPortraitUpsideDown
46 | UIInterfaceOrientationLandscapeLeft
47 | UIInterfaceOrientationLandscapeRight
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/Example/Resources/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 | "idiom" : "ios-marketing",
90 | "size" : "1024x1024",
91 | "scale" : "1x"
92 | }
93 | ],
94 | "info" : {
95 | "version" : 1,
96 | "author" : "xcode"
97 | }
98 | }
--------------------------------------------------------------------------------
/Example/Sources/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // Example
4 | //
5 | // Created by Takuma Horiuchi on 2018/02/20.
6 | // Copyright © 2018年 Takuma Horiuchi. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | @UIApplicationMain
12 | class AppDelegate: UIResponder, UIApplicationDelegate {
13 |
14 | var window: UIWindow? {
15 | didSet {
16 | window?.backgroundColor = .white
17 | }
18 | }
19 |
20 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
21 | // Override point for customization after application launch.
22 | return true
23 | }
24 |
25 | func applicationWillResignActive(_ application: UIApplication) {
26 | // 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.
27 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
28 | }
29 |
30 | func applicationDidEnterBackground(_ application: UIApplication) {
31 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
32 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
33 | }
34 |
35 | func applicationWillEnterForeground(_ application: UIApplication) {
36 | // 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.
37 | }
38 |
39 | func applicationDidBecomeActive(_ application: UIApplication) {
40 | // 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.
41 | }
42 |
43 | func applicationWillTerminate(_ application: UIApplication) {
44 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
45 | }
46 |
47 |
48 | }
49 |
50 |
--------------------------------------------------------------------------------
/Example/Sources/Controllers/Table/TableVIewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TableVIewController.swift
3 | // Example
4 | //
5 | // Created by Takuma Horiuchi on 2018/03/21.
6 | // Copyright © 2018年 Takuma Horiuchi. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | final class TableViewController: UIViewController, SilentScrollable {
12 |
13 | override var preferredStatusBarStyle: UIStatusBarStyle {
14 | return statusBarStyle(showStyle: .lightContent, hideStyle: .default)
15 | }
16 |
17 | @IBOutlet weak var tableView: UITableView! {
18 | didSet {
19 | tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell")
20 | tableView.delegate = self
21 | tableView.dataSource = self
22 | }
23 | }
24 |
25 | var silentScrolly: SilentScrolly?
26 |
27 | override func viewDidLoad() {
28 | super.viewDidLoad()
29 |
30 | let label = UILabel()
31 | label.text = "Table"
32 | label.textColor = .white
33 | label.font = UIFont.boldSystemFont(ofSize: 17)
34 | navigationItem.titleView = label
35 | }
36 |
37 | override func viewDidLayoutSubviews() {
38 | super.viewDidLayoutSubviews()
39 | silentDidLayoutSubviews()
40 | }
41 |
42 | override func viewDidAppear(_ animated: Bool) {
43 | super.viewDidAppear(animated)
44 | configureSilentScrolly(tableView, followBottomView: tabBarController?.tabBar)
45 | }
46 |
47 | override func viewWillDisappear(_ animated: Bool) {
48 | super.viewWillDisappear(animated)
49 | silentWillDisappear()
50 | }
51 |
52 | override func viewDidDisappear(_ animated: Bool) {
53 | super.viewDidDisappear(animated)
54 | silentDidDisappear()
55 | }
56 |
57 | override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
58 | super.viewWillTransition(to: size, with: coordinator)
59 | silentWillTranstion()
60 | }
61 | }
62 |
63 | extension TableViewController: UITableViewDelegate {
64 |
65 | func scrollViewDidScroll(_ scrollView: UIScrollView) {
66 | silentDidScroll()
67 | }
68 |
69 | func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
70 | tableView.deselectRow(at: indexPath, animated: true)
71 | }
72 |
73 | func scrollViewShouldScrollToTop(_ scrollView: UIScrollView) -> Bool {
74 | showNavigationBar()
75 | return true
76 | }
77 | }
78 |
79 | extension TableViewController: UITableViewDataSource {
80 |
81 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
82 | return 100
83 | }
84 |
85 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
86 | let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
87 | cell.textLabel?.text = "Row: \(indexPath.row)"
88 | return cell
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/Example/Sources/Controllers/ToolBar/ToolBarViewController.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 |
--------------------------------------------------------------------------------
/Example/Sources/Controllers/Web/WebViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // WebViewController.swift
3 | // Example
4 | //
5 | // Created by Takuma Horiuchi on 2018/02/20.
6 | // Copyright © 2018年 Takuma Horiuchi. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import WebKit
11 |
12 | final class WebViewController: UIViewController, SilentScrollable {
13 |
14 | override var preferredStatusBarStyle: UIStatusBarStyle {
15 | return statusBarStyle(showStyle: .lightContent, hideStyle: .default)
16 | }
17 |
18 | @IBOutlet weak var webView: WKWebView! {
19 | didSet {
20 | webView.navigationDelegate = self
21 | webView.scrollView.delegate = self
22 | let url = URL(string: "http://www.keyakizaka46.com/")
23 | let urlRequest = URLRequest(url: url!)
24 | webView.load(urlRequest)
25 | }
26 | }
27 |
28 | var silentScrolly: SilentScrolly?
29 |
30 | override func viewDidLoad() {
31 | super.viewDidLoad()
32 |
33 | let rightShowBarButtonItem = UIBarButtonItem(title: "Show",
34 | style: .plain,
35 | target: self,
36 | action: #selector(tapRightShowBarButtonItem))
37 | navigationItem.setRightBarButton(rightShowBarButtonItem, animated: true)
38 |
39 | let label = UILabel()
40 | label.text = "Web"
41 | label.textColor = .white
42 | label.font = UIFont.boldSystemFont(ofSize: 17)
43 | navigationItem.titleView = label
44 | }
45 |
46 | override func viewDidLayoutSubviews() {
47 | super.viewDidLayoutSubviews()
48 | silentDidLayoutSubviews()
49 | }
50 |
51 | override func viewDidAppear(_ animated: Bool) {
52 | super.viewDidAppear(animated)
53 | configureSilentScrolly(webView.scrollView, followBottomView: tabBarController?.tabBar)
54 | }
55 |
56 | override func viewWillDisappear(_ animated: Bool) {
57 | super.viewWillDisappear(animated)
58 | silentWillDisappear()
59 | }
60 |
61 | override func viewDidDisappear(_ animated: Bool) {
62 | super.viewDidDisappear(animated)
63 | silentDidDisappear()
64 | }
65 |
66 | override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
67 | super.viewWillTransition(to: size, with: coordinator)
68 | silentWillTranstion()
69 | }
70 |
71 | @objc private func tapRightShowBarButtonItem() {
72 | let viewController = ToolBarViewController.make()
73 | navigationController?.show(viewController, sender: nil)
74 | }
75 | }
76 |
77 | extension WebViewController: UIScrollViewDelegate {
78 |
79 | func scrollViewDidScroll(_ scrollView: UIScrollView) {
80 | silentDidScroll()
81 | }
82 |
83 | func scrollViewShouldScrollToTop(_ scrollView: UIScrollView) -> Bool {
84 | showNavigationBar()
85 | return true
86 | }
87 | }
88 |
89 | extension WebViewController: WKNavigationDelegate {
90 |
91 | func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
92 | showNavigationBar()
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/SilentScrolly.xcodeproj/xcshareddata/xcschemes/SilentScrolly.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
34 |
35 |
45 |
46 |
52 |
53 |
54 |
55 |
56 |
57 |
63 |
64 |
70 |
71 |
72 |
73 |
75 |
76 |
79 |
80 |
81 |
--------------------------------------------------------------------------------
/Example/Sources/Controllers/Table/TableViewController.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 |
--------------------------------------------------------------------------------
/Example/Sources/Controllers/Web/WebViewController.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 |
--------------------------------------------------------------------------------
/Example/Sources/Controllers/Collection/CollectionViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CollectionViewController.swift
3 | // Example
4 | //
5 | // Created by Takuma Horiuchi on 2018/03/21.
6 | // Copyright © 2018年 Takuma Horiuchi. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | final class CollectionViewController: UIViewController, SilentScrollable {
12 |
13 | override var preferredStatusBarStyle: UIStatusBarStyle {
14 | return .lightContent
15 | }
16 |
17 | @IBOutlet weak var collectionView: UICollectionView! {
18 | didSet {
19 | collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "Cell")
20 | collectionView.delegate = self
21 | collectionView.dataSource = self
22 | }
23 | }
24 |
25 | @IBOutlet weak var flowLayout: UICollectionViewFlowLayout! {
26 | didSet {
27 | flowLayout.scrollDirection = .vertical
28 | flowLayout.minimumInteritemSpacing = 1
29 | flowLayout.minimumLineSpacing = 1
30 | }
31 | }
32 |
33 | var silentScrolly: SilentScrolly?
34 |
35 | override func viewDidLoad() {
36 | super.viewDidLoad()
37 |
38 | let label = UILabel()
39 | label.text = "Collection"
40 | label.textColor = .white
41 | label.font = UIFont.boldSystemFont(ofSize: 17)
42 | navigationItem.titleView = label
43 | }
44 |
45 | override func viewDidLayoutSubviews() {
46 | super.viewDidLayoutSubviews()
47 | silentDidLayoutSubviews()
48 | }
49 |
50 | override func viewDidAppear(_ animated: Bool) {
51 | super.viewDidAppear(animated)
52 | configureSilentScrolly(collectionView, followBottomView: tabBarController?.tabBar)
53 | }
54 |
55 | override func viewWillDisappear(_ animated: Bool) {
56 | super.viewWillDisappear(animated)
57 | silentWillDisappear()
58 | }
59 |
60 | override func viewDidDisappear(_ animated: Bool) {
61 | super.viewDidDisappear(animated)
62 | silentDidDisappear()
63 | }
64 |
65 | override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
66 | super.viewWillTransition(to: size, with: coordinator)
67 | silentWillTranstion()
68 | }
69 | }
70 |
71 | extension CollectionViewController: UICollectionViewDelegate {
72 |
73 | func scrollViewDidScroll(_ scrollView: UIScrollView) {
74 | silentDidScroll()
75 | }
76 |
77 | func scrollViewShouldScrollToTop(_ scrollView: UIScrollView) -> Bool {
78 | showNavigationBar()
79 | return true
80 | }
81 | }
82 |
83 | extension CollectionViewController: UICollectionViewDataSource {
84 |
85 | func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
86 | return 100
87 | }
88 |
89 | func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
90 | let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath)
91 | cell.contentView.backgroundColor = .lightGray
92 | return cell
93 | }
94 | }
95 |
96 | extension CollectionViewController: UICollectionViewDelegateFlowLayout {
97 |
98 | func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
99 | let isPortraint = UIInterfaceOrientationIsPortrait(UIApplication.shared.statusBarOrientation)
100 | let itemSide: CGFloat = isPortraint ? (collectionView.frame.width - 2) / 3 : (collectionView.frame.width - 3) / 4
101 | return CGSize(width: floor(itemSide), height: floor(itemSide))
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/Example/Sources/Controllers/ToolBar/ToolBarViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ToolBarViewController.swift
3 | // Example
4 | //
5 | // Created by Takuma Horiuchi on 2018/02/20.
6 | // Copyright © 2018年 Takuma Horiuchi. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import WebKit
11 |
12 | final class ToolBarViewController: UIViewController, SilentScrollable {
13 |
14 | override var preferredStatusBarStyle: UIStatusBarStyle {
15 | return statusBarStyle(showStyle: .lightContent, hideStyle: .default)
16 | }
17 |
18 | class func make() -> ToolBarViewController {
19 | let viewController = UIStoryboard(name: "ToolBarViewController", bundle: nil)
20 | .instantiateViewController(withIdentifier: "ToolBarViewController") as! ToolBarViewController
21 | viewController.hidesBottomBarWhenPushed = true
22 | return viewController
23 | }
24 |
25 | private var webView: WKWebView = {
26 | let webConfiguration = WKWebViewConfiguration()
27 | webConfiguration.ignoresViewportScaleLimits = true
28 | let webView = WKWebView(frame: .zero, configuration: webConfiguration)
29 | webView.translatesAutoresizingMaskIntoConstraints = false
30 | webView.load(URLRequest(url: URL(string: "http://www.keyakizaka46.com/")!))
31 | return webView
32 | }()
33 |
34 | @IBOutlet weak var toolBar: UIToolbar! {
35 | didSet {
36 | toolBar.barTintColor = .darkGray
37 | toolBar.tintColor = .white
38 | }
39 | }
40 |
41 | var silentScrolly: SilentScrolly?
42 |
43 | override func viewDidLoad() {
44 | super.viewDidLoad()
45 |
46 | webView.navigationDelegate = self
47 | webView.scrollView.delegate = self
48 | view.addSubview(webView)
49 | NSLayoutConstraint.activate([
50 | webView.topAnchor.constraint(equalTo: view.topAnchor),
51 | webView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor),
52 | webView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
53 | webView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor)
54 | ])
55 |
56 | view.bringSubview(toFront: toolBar)
57 |
58 | let label = UILabel()
59 | label.text = "ToolBar"
60 | label.textColor = .white
61 | label.font = UIFont.boldSystemFont(ofSize: 17)
62 | navigationItem.titleView = label
63 | }
64 |
65 | override func viewDidLayoutSubviews() {
66 | super.viewDidLayoutSubviews()
67 | silentDidLayoutSubviews()
68 | }
69 |
70 | override func viewDidAppear(_ animated: Bool) {
71 | super.viewDidAppear(animated)
72 | configureSilentScrolly(webView.scrollView, followBottomView: toolBar)
73 | }
74 |
75 | override func viewWillDisappear(_ animated: Bool) {
76 | super.viewWillDisappear(animated)
77 | silentWillDisappear()
78 | }
79 |
80 | override func viewDidDisappear(_ animated: Bool) {
81 | super.viewDidDisappear(animated)
82 | silentDidDisappear()
83 | }
84 |
85 | override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
86 | super.viewWillTransition(to: size, with: coordinator)
87 | silentWillTranstion()
88 | }
89 | }
90 |
91 | extension ToolBarViewController: UIScrollViewDelegate {
92 |
93 | func scrollViewDidScroll(_ scrollView: UIScrollView) {
94 | silentDidScroll()
95 | }
96 |
97 | func scrollViewDidZoom(_ scrollView: UIScrollView) {
98 | silentDidZoom()
99 | }
100 |
101 | func scrollViewShouldScrollToTop(_ scrollView: UIScrollView) -> Bool {
102 | showNavigationBar()
103 | return true
104 | }
105 | }
106 |
107 | extension ToolBarViewController: WKNavigationDelegate {
108 |
109 | func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
110 | showNavigationBar()
111 | }
112 | }
113 |
--------------------------------------------------------------------------------
/Example/Sources/Controllers/Collection/CollectionViewController.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 |
--------------------------------------------------------------------------------
/Example/Resources/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
27 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | [](https://developer.apple.com/iphone/index.action)
6 | 
7 | [](https://img.shields.io/badge/Cocoapods-compatible-brightgreen.svg)
8 | [](https://github.com/Carthage/Carthage)
9 | [](http://mit-license.org)
10 |
11 | ## Overview
12 | Scroll to hide navigationBar, tabBar and toolBar.
13 |
14 |
15 |
16 |
17 |
18 | ## Features
19 | Adding too much `UIGestureRecognizer` to the `UIView` makes handling difficult, so it was handled by `UIScrollViewDelegate`.
20 |
21 | ## Translation
22 | Mr. [Gargo](https://github.com/Gargo) translated [this README into Russian](http://gargo.of.by/silentscrolly/)!🙇♂️
23 |
24 | ## Requirements
25 | - Xcode 9.0+
26 | - iOS 10+
27 | - Swift 4.0+
28 |
29 | ## Installation
30 | ### CocoaPods
31 | ```ruby
32 | pod 'SilentScrolly'
33 | ```
34 | ### Carthage
35 | ```ruby
36 | github "horitaku46/SilentScrolly"
37 | ```
38 | ## Usage
39 | **See [Example](https://github.com/horitaku46/SilentScrolly/tree/master/Example), for more details.**
40 |
41 | **《1》** If you want to change the color of the statusBar, add `func statusBarStyle(showStyle: UIStatusBarStyle, hideStyle: UIStatusBarStyle)` to the `UINavigationController`.
42 |
43 | ```swift
44 | import UIKit
45 |
46 | final class NavigationController: UINavigationController {
47 |
48 | override var preferredStatusBarStyle: UIStatusBarStyle {
49 | return topViewController?.preferredStatusBarStyle ?? .default
50 | }
51 | }
52 | ```
53 |
54 | **《2》** Please describe accordingly as below.
55 |
56 |
57 | ```swift
58 | import UIKit
59 |
60 | final class TableViewController: UIViewController, SilentScrollable {
61 |
62 | override var preferredStatusBarStyle: UIStatusBarStyle {
63 | return statusBarStyle(showStyle: .lightContent, hideStyle: .default) // Optional
64 | }
65 |
66 | @IBOutlet weak var tableView: UITableView! {
67 | didSet {
68 | tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell")
69 | tableView.delegate = self
70 | tableView.dataSource = self
71 | }
72 | }
73 |
74 | var silentScrolly: SilentScrolly?
75 |
76 | override func viewDidLayoutSubviews() {
77 | super.viewDidLayoutSubviews()
78 | silentDidLayoutSubviews()
79 | }
80 |
81 | override func viewDidAppear(_ animated: Bool) {
82 | super.viewDidAppear(animated)
83 | configureSilentScrolly(tableView, followBottomView: tabBarController?.tabBar)
84 | }
85 |
86 | override func viewWillDisappear(_ animated: Bool) {
87 | super.viewWillDisappear(animated)
88 | silentWillDisappear()
89 | }
90 |
91 | override func viewDidDisappear(_ animated: Bool) {
92 | super.viewDidDisappear(animated)
93 | silentDidDisappear()
94 | }
95 |
96 | override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
97 | super.viewWillTransition(to: size, with: coordinator)
98 | silentWillTranstion()
99 | }
100 | }
101 |
102 | extension TableViewController: UITableViewDelegate {
103 |
104 | func scrollViewDidScroll(_ scrollView: UIScrollView) {
105 | silentDidScroll()
106 | }
107 |
108 | func scrollViewDidZoom(_ scrollView: UIScrollView) {
109 | silentDidZoom() // Optional
110 | }
111 |
112 | func scrollViewShouldScrollToTop(_ scrollView: UIScrollView) -> Bool {
113 | showNavigationBar() // Optional
114 | return true
115 | }
116 | }
117 |
118 | extension TableViewController: UITableViewDataSource {
119 |
120 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
121 | return 100
122 | }
123 |
124 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
125 | let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
126 | cell.textLabel?.text = "Row: \(indexPath.row)"
127 | return cell
128 | }
129 | }
130 | ```
131 |
132 | ## Author
133 | ### Takuma Horiuchi
134 | - [Facebook](https://www.facebook.com/profile.php?id=100008388074028)
135 | - [Twitter](https://twitter.com/horitaku_)
136 | - [GitHub](https://github.com/horitaku46)
137 |
138 | ## License
139 | `SilentScrolly` is available under the MIT license. See the [LICENSE](./LICENSE) file for more info.
140 |
--------------------------------------------------------------------------------
/Example/Sources/Controllers/TabBar/TabBarController.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 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
--------------------------------------------------------------------------------
/SilentScrolly/SilentScrollable.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SilentScrollable.swift
3 | // SilentScrolly
4 | //
5 | // Created by Takuma Horiuchi on 2018/02/22.
6 | // Copyright © 2018年 Takuma Horiuchi. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | public protocol SilentScrollable: class {
12 | var silentScrolly: SilentScrolly? { get set }
13 | func statusBarStyle(showStyle: UIStatusBarStyle, hideStyle: UIStatusBarStyle) -> UIStatusBarStyle
14 | func configureSilentScrolly(_ scrollView: UIScrollView, followBottomView: UIView?, completion: (() -> Void)?)
15 | func showNavigationBar()
16 | func hideNavigationBar()
17 | func silentWillDisappear()
18 | func silentDidDisappear()
19 | func silentDidLayoutSubviews()
20 | func silentWillTranstion()
21 | func silentDidScroll()
22 | func silentDidZoom()
23 | }
24 |
25 | public extension SilentScrollable where Self: UIViewController {
26 |
27 | public func statusBarStyle(showStyle: UIStatusBarStyle, hideStyle: UIStatusBarStyle) -> UIStatusBarStyle {
28 | guard let preferredStatusBarStyle = silentScrolly?.preferredStatusBarStyle else {
29 | /// To consider whether statusBarStyle and configureSilentScrolly precede.
30 | if silentScrolly == nil {
31 | silentScrolly = SilentScrolly()
32 | }
33 | silentScrolly?.preferredStatusBarStyle = showStyle
34 | silentScrolly?.showStatusBarStyle = showStyle
35 | silentScrolly?.hideStatusBarStyle = hideStyle
36 | return showStyle
37 | }
38 | return preferredStatusBarStyle
39 | }
40 |
41 | private func setStatusBarAppearanceShow() {
42 | guard let showStyle = silentScrolly?.showStatusBarStyle else {
43 | return
44 | }
45 | silentScrolly?.preferredStatusBarStyle = showStyle
46 | setNeedsStatusBarAppearanceUpdate()
47 | }
48 |
49 | private func setStatusBarAppearanceHide() {
50 | guard let hideStyle = silentScrolly?.hideStatusBarStyle else {
51 | return
52 | }
53 | silentScrolly?.preferredStatusBarStyle = hideStyle
54 | setNeedsStatusBarAppearanceUpdate()
55 | }
56 |
57 | public func configureSilentScrolly(_ scrollView: UIScrollView, followBottomView: UIView?, completion: (() -> Void)? = nil) {
58 | guard let navigationBarHeight = navigationController?.navigationBar.bounds.height,
59 | let safeAreaInsetsBottom = UIApplication.shared.keyWindow?.safeAreaInsets.bottom else {
60 | return
61 | }
62 | let statusBarHeight = UIApplication.shared.statusBarFrame.height
63 | let totalHeight = statusBarHeight + navigationBarHeight
64 |
65 | /// To consider whether statusBarStyle and configureSilentScrolly precede.
66 | if silentScrolly == nil {
67 | silentScrolly = SilentScrolly()
68 | }
69 |
70 | silentScrolly?.scrollView = scrollView
71 |
72 | silentScrolly?.isNavigationBarShow = true
73 | silentScrolly?.isTransitionCompleted = true
74 |
75 | silentScrolly?.showNavigationBarFrameOriginY = statusBarHeight
76 | silentScrolly?.hideNavigationBarFrameOriginY = -navigationBarHeight
77 | silentScrolly?.showScrollIndicatorInsetsTop = scrollView.scrollIndicatorInsets.top
78 | silentScrolly?.hideScrollIndicatorInsetsTop = scrollView.scrollIndicatorInsets.top - totalHeight
79 |
80 | // FIXME: Because the following adjusts it to the setting that I showed with a example.
81 | if let bottomView = followBottomView {
82 | let screenHeight = UIScreen.main.bounds.height
83 | let eitherSafeAreaInsetsBottom = bottomView is UITabBar ? 0 : safeAreaInsetsBottom
84 | let bottomViewHeight = bottomView.bounds.height + eitherSafeAreaInsetsBottom
85 | silentScrolly?.bottomView = bottomView
86 | silentScrolly?.showBottomViewFrameOriginY = screenHeight - bottomViewHeight
87 | silentScrolly?.hideBottomViewFrameOriginY = screenHeight
88 | silentScrolly?.showContentInsetBottom = bottomView is UITabBar ? 0 : bottomViewHeight
89 | silentScrolly?.hideContentInsetBottom = bottomView is UITabBar ? -bottomViewHeight : -eitherSafeAreaInsetsBottom
90 | }
91 |
92 | if let isAddObserver = silentScrolly?.isAddObserver {
93 | if isAddObserver {
94 | NotificationCenter.default.addObserver(forName: .UIDeviceOrientationDidChange, object: nil, queue: nil) { [weak self] in
95 | self?.orientationDidChange($0)
96 | }
97 | NotificationCenter.default.addObserver(forName: .UIApplicationDidEnterBackground, object: nil, queue: nil) { [weak self] in
98 | self?.didEnterBackground($0)
99 | }
100 | }
101 | silentScrolly?.isAddObserver = false
102 | }
103 |
104 | completion?()
105 | }
106 |
107 | private func orientationDidChange(_ notification: Notification) {
108 | guard isViewLoaded,
109 | let _ = view.window,
110 | let scrollView = silentScrolly?.scrollView,
111 | let isShow = silentScrolly?.isNavigationBarShow else {
112 | return
113 | }
114 | adjustEitherView(scrollView, isShow: isShow, animated: false)
115 | }
116 |
117 | private func didEnterBackground(_ notification: Notification) {
118 | guard isViewLoaded,
119 | let _ = view.window,
120 | let scrollView = silentScrolly?.scrollView else {
121 | return
122 | }
123 | adjustEitherView(scrollView, isShow: true, animated: false)
124 | }
125 |
126 | public func showNavigationBar() {
127 | guard let scrollView = silentScrolly?.scrollView else {
128 | return
129 | }
130 | adjustEitherView(scrollView, isShow: true)
131 | }
132 |
133 | public func hideNavigationBar() {
134 | guard let scrollView = silentScrolly?.scrollView else {
135 | return
136 | }
137 | adjustEitherView(scrollView, isShow: false)
138 | }
139 |
140 | public func silentWillDisappear() {
141 | showNavigationBar()
142 | silentScrolly?.isTransitionCompleted = false
143 | }
144 |
145 | public func silentDidDisappear() {
146 | silentScrolly?.isTransitionCompleted = true
147 | }
148 |
149 | public func silentDidLayoutSubviews() {
150 | guard let scrollView = silentScrolly?.scrollView else {
151 | return
152 | }
153 | // animation completed because the calculation is crazy
154 | adjustEitherView(scrollView, isShow: true, animated: false) { [weak self] in
155 | guard let me = self else { return }
156 | me.configureSilentScrolly(scrollView, followBottomView: me.silentScrolly?.bottomView) { [weak self] in
157 | self?.adjustEitherView(scrollView, isShow: true, animated: false)
158 | scrollView.setZoomScale(1, animated: false)
159 | }
160 | }
161 | }
162 |
163 | public func silentWillTranstion() {
164 | guard let scrollView = silentScrolly?.scrollView else {
165 | return
166 | }
167 | adjustEitherView(scrollView, isShow: true, animated: false)
168 | }
169 |
170 | public func silentDidScroll() {
171 | guard let scrollView = silentScrolly?.scrollView,
172 | let prevPositiveContentOffsetY = silentScrolly?.prevPositiveContentOffsetY else {
173 | return
174 | }
175 |
176 | if scrollView.contentSize.height < scrollView.bounds.height || scrollView.isZooming {
177 | return
178 | }
179 |
180 | if scrollView.contentOffset.y <= 0 {
181 | adjustEitherView(scrollView, isShow: true)
182 | return
183 | }
184 |
185 | let positiveContentOffsetY = calcPositiveContentOffsetY(scrollView)
186 | let velocityY = scrollView.panGestureRecognizer.velocity(in: view).y
187 |
188 | if positiveContentOffsetY != prevPositiveContentOffsetY && scrollView.isTracking {
189 | if velocityY < SilentScrolly.Const.minDoNothingAdjustNavigationBarVelocityY {
190 | adjustEitherView(scrollView, isShow: false)
191 | } else if velocityY > SilentScrolly.Const.maxDoNothingAdjustNavigationBarVelocityY {
192 | adjustEitherView(scrollView, isShow: true)
193 | }
194 | }
195 |
196 | silentScrolly?.prevPositiveContentOffsetY = positiveContentOffsetY
197 | }
198 |
199 | public func silentDidZoom() {
200 | guard let scrollView = silentScrolly?.scrollView else {
201 | return
202 | }
203 | func setNavigationBar() {
204 | scrollView.zoomScale <= 1 ? showNavigationBar() : hideNavigationBar()
205 | }
206 | scrollView.isZooming ? setNavigationBar() : scrollView.setZoomScale(1, animated: true)
207 | }
208 |
209 | private func calcPositiveContentOffsetY(_ scrollView: UIScrollView) -> CGFloat {
210 | var contentOffsetY = scrollView.contentOffset.y + scrollView.contentInset.top
211 | contentOffsetY = contentOffsetY > 0 ? contentOffsetY : 0
212 | return contentOffsetY
213 | }
214 |
215 | private func adjustEitherView(_ scrollView: UIScrollView, isShow: Bool, animated: Bool = true, completion: (() -> Void)? = nil) {
216 | guard let isTransitionCompleted = silentScrolly?.isTransitionCompleted,
217 | let showNavigationBarFrameOriginY = silentScrolly?.showNavigationBarFrameOriginY,
218 | let hideNavigationBarFrameOriginY = silentScrolly?.hideNavigationBarFrameOriginY,
219 | let showScrollIndicatorInsetsTop = silentScrolly?.showScrollIndicatorInsetsTop,
220 | let hideScrollIndicatorInsetsTop = silentScrolly?.hideScrollIndicatorInsetsTop,
221 | let currentNavigationBarOriginY = navigationController?.navigationBar.frame.origin.y else {
222 | return
223 | }
224 |
225 | if scrollView.contentSize.height < scrollView.bounds.height || !isTransitionCompleted {
226 | return
227 | }
228 |
229 | let eitherNavigationBarFrameOriginY = isShow ? showNavigationBarFrameOriginY : hideNavigationBarFrameOriginY
230 | let eitherScrollIndicatorInsetsTop = isShow ? showScrollIndicatorInsetsTop : hideScrollIndicatorInsetsTop
231 | let navigationBarContentsAlpha: CGFloat = isShow ? 1 : 0
232 |
233 | func setPosition() {
234 | if silentScrolly?.preferredStatusBarStyle != nil {
235 | isShow ? setStatusBarAppearanceShow() : setStatusBarAppearanceHide()
236 | }
237 | navigationController?.navigationBar.frame.origin.y = eitherNavigationBarFrameOriginY
238 | scrollView.scrollIndicatorInsets.top = eitherScrollIndicatorInsetsTop
239 | setNavigationBarContentsAlpha(navigationBarContentsAlpha)
240 | silentScrolly?.isNavigationBarShow = isShow
241 | }
242 |
243 | if !animated {
244 | setPosition()
245 | animateBottomView(scrollView, isShow: isShow, animated: animated)
246 | completion?()
247 | return
248 | }
249 |
250 | if currentNavigationBarOriginY != eitherNavigationBarFrameOriginY && scrollView.scrollIndicatorInsets.top != eitherScrollIndicatorInsetsTop {
251 | UIView.animate(withDuration: SilentScrolly.Const.animateDuration, animations: {
252 | setPosition()
253 | }, completion: { _ in
254 | completion?()
255 | })
256 |
257 | animateBottomView(scrollView, isShow: isShow, animated: animated)
258 | }
259 | }
260 |
261 | private func animateBottomView(_ scrollView: UIScrollView, isShow: Bool, animated: Bool = true) {
262 | guard let bottomView = silentScrolly?.bottomView,
263 | let showBottomViewFrameOriginY = silentScrolly?.showBottomViewFrameOriginY,
264 | let hideBottomViewFrameOriginY = silentScrolly?.hideBottomViewFrameOriginY,
265 | let showContentInsetBottom = silentScrolly?.showContentInsetBottom,
266 | let hideContentInsetBottom = silentScrolly?.hideContentInsetBottom else {
267 | return
268 | }
269 |
270 | let eitherBottomViewFrameOriginY = isShow ? showBottomViewFrameOriginY : hideBottomViewFrameOriginY
271 | let eitherContentInsetBottom = isShow ? showContentInsetBottom : hideContentInsetBottom
272 |
273 | func setPosition() {
274 | bottomView.frame.origin.y = eitherBottomViewFrameOriginY
275 | scrollView.contentInset.bottom = eitherContentInsetBottom
276 | scrollView.scrollIndicatorInsets.bottom = eitherContentInsetBottom
277 | }
278 |
279 | if !animated {
280 | setPosition()
281 | return
282 | }
283 |
284 | UIView.animate(withDuration: SilentScrolly.Const.animateDuration) {
285 | setPosition()
286 | }
287 | }
288 |
289 | private func setNavigationBarContentsAlpha(_ alpha: CGFloat) {
290 | guard let navigationBar = navigationController?.navigationBar else {
291 | return
292 | }
293 | navigationItem.titleView?.alpha = alpha
294 | navigationBar.tintColor = navigationBar.tintColor.withAlphaComponent(alpha)
295 | }
296 | }
297 |
--------------------------------------------------------------------------------
/SilentScrolly.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 48;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 6154F5ED203B1CC600040F47 /* SilentScrolly.h in Headers */ = {isa = PBXBuildFile; fileRef = 6154F5EB203B1CC600040F47 /* SilentScrolly.h */; settings = {ATTRIBUTES = (Public, ); }; };
11 | 615EC445205574EC00F2A392 /* SilentScrolly.swift in Sources */ = {isa = PBXBuildFile; fileRef = 615EC443205574EC00F2A392 /* SilentScrolly.swift */; };
12 | 615EC446205574EC00F2A392 /* SilentScrollable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 615EC444205574EC00F2A392 /* SilentScrollable.swift */; };
13 | 615EC4472055750800F2A392 /* SilentScrollable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 615EC444205574EC00F2A392 /* SilentScrollable.swift */; };
14 | 615EC4482055750800F2A392 /* SilentScrolly.swift in Sources */ = {isa = PBXBuildFile; fileRef = 615EC443205574EC00F2A392 /* SilentScrolly.swift */; };
15 | 6176604D203BDD330049B35E /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6176603D203BDC2F0049B35E /* AppDelegate.swift */; };
16 | 6176604E203BDD3F0049B35E /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 61766037203BDC2F0049B35E /* Assets.xcassets */; };
17 | 61F540C8206238BF006E11FB /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 61F540C7206238BF006E11FB /* LaunchScreen.storyboard */; };
18 | 61F540DE20625D61006E11FB /* TabBarController.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 61F540D520625D61006E11FB /* TabBarController.storyboard */; };
19 | 61F540DF20625D61006E11FB /* NavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61F540D620625D61006E11FB /* NavigationController.swift */; };
20 | 61F540E020625D61006E11FB /* TabBarController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61F540D720625D61006E11FB /* TabBarController.swift */; };
21 | 61F540E120625D61006E11FB /* ToolBarViewController.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 61F540D920625D61006E11FB /* ToolBarViewController.storyboard */; };
22 | 61F540E220625D61006E11FB /* ToolBarViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61F540DA20625D61006E11FB /* ToolBarViewController.swift */; };
23 | 61F540E320625D61006E11FB /* WebViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61F540DC20625D61006E11FB /* WebViewController.swift */; };
24 | 61F540E420625D61006E11FB /* WebViewController.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 61F540DD20625D61006E11FB /* WebViewController.storyboard */; };
25 | 61F540E820625DDC006E11FB /* TableVIewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61F540E720625DDC006E11FB /* TableVIewController.swift */; };
26 | 61F540EA20625DEA006E11FB /* TableViewController.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 61F540E920625DEA006E11FB /* TableViewController.storyboard */; };
27 | 61F540EC20625DFE006E11FB /* CollectionViewController.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 61F540EB20625DFE006E11FB /* CollectionViewController.storyboard */; };
28 | 61F540EE20625E05006E11FB /* CollectionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61F540ED20625E05006E11FB /* CollectionViewController.swift */; };
29 | /* End PBXBuildFile section */
30 |
31 | /* Begin PBXFileReference section */
32 | 6154F5E8203B1CC600040F47 /* SilentScrolly.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SilentScrolly.framework; sourceTree = BUILT_PRODUCTS_DIR; };
33 | 6154F5EB203B1CC600040F47 /* SilentScrolly.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SilentScrolly.h; sourceTree = ""; };
34 | 6154F5EC203B1CC600040F47 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
35 | 615EC443205574EC00F2A392 /* SilentScrolly.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SilentScrolly.swift; sourceTree = ""; };
36 | 615EC444205574EC00F2A392 /* SilentScrollable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SilentScrollable.swift; sourceTree = ""; };
37 | 61766023203BCD6D0049B35E /* Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Example.app; sourceTree = BUILT_PRODUCTS_DIR; };
38 | 61766037203BDC2F0049B35E /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
39 | 61766038203BDC2F0049B35E /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
40 | 6176603D203BDC2F0049B35E /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
41 | 61F540C7206238BF006E11FB /* LaunchScreen.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = ""; };
42 | 61F540D520625D61006E11FB /* TabBarController.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = TabBarController.storyboard; sourceTree = ""; };
43 | 61F540D620625D61006E11FB /* NavigationController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NavigationController.swift; sourceTree = ""; };
44 | 61F540D720625D61006E11FB /* TabBarController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TabBarController.swift; sourceTree = ""; };
45 | 61F540D920625D61006E11FB /* ToolBarViewController.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = ToolBarViewController.storyboard; sourceTree = ""; };
46 | 61F540DA20625D61006E11FB /* ToolBarViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ToolBarViewController.swift; sourceTree = ""; };
47 | 61F540DC20625D61006E11FB /* WebViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WebViewController.swift; sourceTree = ""; };
48 | 61F540DD20625D61006E11FB /* WebViewController.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = WebViewController.storyboard; sourceTree = ""; };
49 | 61F540E720625DDC006E11FB /* TableVIewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TableVIewController.swift; sourceTree = ""; };
50 | 61F540E920625DEA006E11FB /* TableViewController.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = TableViewController.storyboard; sourceTree = ""; };
51 | 61F540EB20625DFE006E11FB /* CollectionViewController.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = CollectionViewController.storyboard; sourceTree = ""; };
52 | 61F540ED20625E05006E11FB /* CollectionViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollectionViewController.swift; sourceTree = ""; };
53 | /* End PBXFileReference section */
54 |
55 | /* Begin PBXFrameworksBuildPhase section */
56 | 6154F5E4203B1CC600040F47 /* Frameworks */ = {
57 | isa = PBXFrameworksBuildPhase;
58 | buildActionMask = 2147483647;
59 | files = (
60 | );
61 | runOnlyForDeploymentPostprocessing = 0;
62 | };
63 | 61766020203BCD6D0049B35E /* Frameworks */ = {
64 | isa = PBXFrameworksBuildPhase;
65 | buildActionMask = 2147483647;
66 | files = (
67 | );
68 | runOnlyForDeploymentPostprocessing = 0;
69 | };
70 | /* End PBXFrameworksBuildPhase section */
71 |
72 | /* Begin PBXGroup section */
73 | 6154F5DE203B1CC600040F47 = {
74 | isa = PBXGroup;
75 | children = (
76 | 61766035203BDC2F0049B35E /* Example */,
77 | 6154F5EA203B1CC600040F47 /* SilentScrolly */,
78 | 6154F5E9203B1CC600040F47 /* Products */,
79 | );
80 | sourceTree = "";
81 | };
82 | 6154F5E9203B1CC600040F47 /* Products */ = {
83 | isa = PBXGroup;
84 | children = (
85 | 6154F5E8203B1CC600040F47 /* SilentScrolly.framework */,
86 | 61766023203BCD6D0049B35E /* Example.app */,
87 | );
88 | name = Products;
89 | sourceTree = "";
90 | };
91 | 6154F5EA203B1CC600040F47 /* SilentScrolly */ = {
92 | isa = PBXGroup;
93 | children = (
94 | 615EC444205574EC00F2A392 /* SilentScrollable.swift */,
95 | 615EC443205574EC00F2A392 /* SilentScrolly.swift */,
96 | 6154F5EB203B1CC600040F47 /* SilentScrolly.h */,
97 | 6154F5EC203B1CC600040F47 /* Info.plist */,
98 | );
99 | path = SilentScrolly;
100 | sourceTree = "";
101 | };
102 | 61766035203BDC2F0049B35E /* Example */ = {
103 | isa = PBXGroup;
104 | children = (
105 | 61766036203BDC2F0049B35E /* Resources */,
106 | 61766039203BDC2F0049B35E /* Sources */,
107 | );
108 | path = Example;
109 | sourceTree = "";
110 | };
111 | 61766036203BDC2F0049B35E /* Resources */ = {
112 | isa = PBXGroup;
113 | children = (
114 | 61F540C7206238BF006E11FB /* LaunchScreen.storyboard */,
115 | 61766037203BDC2F0049B35E /* Assets.xcassets */,
116 | 61766038203BDC2F0049B35E /* Info.plist */,
117 | );
118 | path = Resources;
119 | sourceTree = "";
120 | };
121 | 61766039203BDC2F0049B35E /* Sources */ = {
122 | isa = PBXGroup;
123 | children = (
124 | 61F540C920625CD3006E11FB /* Controllers */,
125 | 6176603D203BDC2F0049B35E /* AppDelegate.swift */,
126 | );
127 | path = Sources;
128 | sourceTree = "";
129 | };
130 | 61F540C920625CD3006E11FB /* Controllers */ = {
131 | isa = PBXGroup;
132 | children = (
133 | 61F540E520625DBF006E11FB /* Table */,
134 | 61F540E620625DBF006E11FB /* Collection */,
135 | 61F540DB20625D61006E11FB /* Web */,
136 | 61F540D820625D61006E11FB /* ToolBar */,
137 | 61F540D420625D61006E11FB /* TabBar */,
138 | );
139 | path = Controllers;
140 | sourceTree = "";
141 | };
142 | 61F540D420625D61006E11FB /* TabBar */ = {
143 | isa = PBXGroup;
144 | children = (
145 | 61F540D520625D61006E11FB /* TabBarController.storyboard */,
146 | 61F540D720625D61006E11FB /* TabBarController.swift */,
147 | 61F540D620625D61006E11FB /* NavigationController.swift */,
148 | );
149 | path = TabBar;
150 | sourceTree = "";
151 | };
152 | 61F540D820625D61006E11FB /* ToolBar */ = {
153 | isa = PBXGroup;
154 | children = (
155 | 61F540D920625D61006E11FB /* ToolBarViewController.storyboard */,
156 | 61F540DA20625D61006E11FB /* ToolBarViewController.swift */,
157 | );
158 | path = ToolBar;
159 | sourceTree = "";
160 | };
161 | 61F540DB20625D61006E11FB /* Web */ = {
162 | isa = PBXGroup;
163 | children = (
164 | 61F540DD20625D61006E11FB /* WebViewController.storyboard */,
165 | 61F540DC20625D61006E11FB /* WebViewController.swift */,
166 | );
167 | path = Web;
168 | sourceTree = "";
169 | };
170 | 61F540E520625DBF006E11FB /* Table */ = {
171 | isa = PBXGroup;
172 | children = (
173 | 61F540E920625DEA006E11FB /* TableViewController.storyboard */,
174 | 61F540E720625DDC006E11FB /* TableVIewController.swift */,
175 | );
176 | path = Table;
177 | sourceTree = "";
178 | };
179 | 61F540E620625DBF006E11FB /* Collection */ = {
180 | isa = PBXGroup;
181 | children = (
182 | 61F540EB20625DFE006E11FB /* CollectionViewController.storyboard */,
183 | 61F540ED20625E05006E11FB /* CollectionViewController.swift */,
184 | );
185 | path = Collection;
186 | sourceTree = "";
187 | };
188 | /* End PBXGroup section */
189 |
190 | /* Begin PBXHeadersBuildPhase section */
191 | 6154F5E5203B1CC600040F47 /* Headers */ = {
192 | isa = PBXHeadersBuildPhase;
193 | buildActionMask = 2147483647;
194 | files = (
195 | 6154F5ED203B1CC600040F47 /* SilentScrolly.h in Headers */,
196 | );
197 | runOnlyForDeploymentPostprocessing = 0;
198 | };
199 | /* End PBXHeadersBuildPhase section */
200 |
201 | /* Begin PBXNativeTarget section */
202 | 6154F5E7203B1CC600040F47 /* SilentScrolly */ = {
203 | isa = PBXNativeTarget;
204 | buildConfigurationList = 6154F5F0203B1CC600040F47 /* Build configuration list for PBXNativeTarget "SilentScrolly" */;
205 | buildPhases = (
206 | 6154F5E3203B1CC600040F47 /* Sources */,
207 | 6154F5E4203B1CC600040F47 /* Frameworks */,
208 | 6154F5E5203B1CC600040F47 /* Headers */,
209 | 6154F5E6203B1CC600040F47 /* Resources */,
210 | );
211 | buildRules = (
212 | );
213 | dependencies = (
214 | );
215 | name = SilentScrolly;
216 | productName = SilentScrolly;
217 | productReference = 6154F5E8203B1CC600040F47 /* SilentScrolly.framework */;
218 | productType = "com.apple.product-type.framework";
219 | };
220 | 61766022203BCD6D0049B35E /* Example */ = {
221 | isa = PBXNativeTarget;
222 | buildConfigurationList = 61766034203BCD6D0049B35E /* Build configuration list for PBXNativeTarget "Example" */;
223 | buildPhases = (
224 | 6176601F203BCD6D0049B35E /* Sources */,
225 | 61766020203BCD6D0049B35E /* Frameworks */,
226 | 61766021203BCD6D0049B35E /* Resources */,
227 | );
228 | buildRules = (
229 | );
230 | dependencies = (
231 | );
232 | name = Example;
233 | productName = Example;
234 | productReference = 61766023203BCD6D0049B35E /* Example.app */;
235 | productType = "com.apple.product-type.application";
236 | };
237 | /* End PBXNativeTarget section */
238 |
239 | /* Begin PBXProject section */
240 | 6154F5DF203B1CC600040F47 /* Project object */ = {
241 | isa = PBXProject;
242 | attributes = {
243 | LastSwiftUpdateCheck = 0920;
244 | LastUpgradeCheck = 0930;
245 | ORGANIZATIONNAME = "Takuma Horiuchi";
246 | TargetAttributes = {
247 | 6154F5E7203B1CC600040F47 = {
248 | CreatedOnToolsVersion = 9.2;
249 | LastSwiftMigration = 0920;
250 | ProvisioningStyle = Automatic;
251 | };
252 | 61766022203BCD6D0049B35E = {
253 | CreatedOnToolsVersion = 9.2;
254 | LastSwiftMigration = 0920;
255 | ProvisioningStyle = Automatic;
256 | };
257 | };
258 | };
259 | buildConfigurationList = 6154F5E2203B1CC600040F47 /* Build configuration list for PBXProject "SilentScrolly" */;
260 | compatibilityVersion = "Xcode 8.0";
261 | developmentRegion = en;
262 | hasScannedForEncodings = 0;
263 | knownRegions = (
264 | en,
265 | Base,
266 | );
267 | mainGroup = 6154F5DE203B1CC600040F47;
268 | productRefGroup = 6154F5E9203B1CC600040F47 /* Products */;
269 | projectDirPath = "";
270 | projectRoot = "";
271 | targets = (
272 | 6154F5E7203B1CC600040F47 /* SilentScrolly */,
273 | 61766022203BCD6D0049B35E /* Example */,
274 | );
275 | };
276 | /* End PBXProject section */
277 |
278 | /* Begin PBXResourcesBuildPhase section */
279 | 6154F5E6203B1CC600040F47 /* Resources */ = {
280 | isa = PBXResourcesBuildPhase;
281 | buildActionMask = 2147483647;
282 | files = (
283 | );
284 | runOnlyForDeploymentPostprocessing = 0;
285 | };
286 | 61766021203BCD6D0049B35E /* Resources */ = {
287 | isa = PBXResourcesBuildPhase;
288 | buildActionMask = 2147483647;
289 | files = (
290 | 61F540E120625D61006E11FB /* ToolBarViewController.storyboard in Resources */,
291 | 6176604E203BDD3F0049B35E /* Assets.xcassets in Resources */,
292 | 61F540EA20625DEA006E11FB /* TableViewController.storyboard in Resources */,
293 | 61F540DE20625D61006E11FB /* TabBarController.storyboard in Resources */,
294 | 61F540E420625D61006E11FB /* WebViewController.storyboard in Resources */,
295 | 61F540C8206238BF006E11FB /* LaunchScreen.storyboard in Resources */,
296 | 61F540EC20625DFE006E11FB /* CollectionViewController.storyboard in Resources */,
297 | );
298 | runOnlyForDeploymentPostprocessing = 0;
299 | };
300 | /* End PBXResourcesBuildPhase section */
301 |
302 | /* Begin PBXSourcesBuildPhase section */
303 | 6154F5E3203B1CC600040F47 /* Sources */ = {
304 | isa = PBXSourcesBuildPhase;
305 | buildActionMask = 2147483647;
306 | files = (
307 | 615EC445205574EC00F2A392 /* SilentScrolly.swift in Sources */,
308 | 615EC446205574EC00F2A392 /* SilentScrollable.swift in Sources */,
309 | );
310 | runOnlyForDeploymentPostprocessing = 0;
311 | };
312 | 6176601F203BCD6D0049B35E /* Sources */ = {
313 | isa = PBXSourcesBuildPhase;
314 | buildActionMask = 2147483647;
315 | files = (
316 | 61F540EE20625E05006E11FB /* CollectionViewController.swift in Sources */,
317 | 61F540E320625D61006E11FB /* WebViewController.swift in Sources */,
318 | 61F540E220625D61006E11FB /* ToolBarViewController.swift in Sources */,
319 | 615EC4472055750800F2A392 /* SilentScrollable.swift in Sources */,
320 | 61F540E820625DDC006E11FB /* TableVIewController.swift in Sources */,
321 | 61F540DF20625D61006E11FB /* NavigationController.swift in Sources */,
322 | 615EC4482055750800F2A392 /* SilentScrolly.swift in Sources */,
323 | 6176604D203BDD330049B35E /* AppDelegate.swift in Sources */,
324 | 61F540E020625D61006E11FB /* TabBarController.swift in Sources */,
325 | );
326 | runOnlyForDeploymentPostprocessing = 0;
327 | };
328 | /* End PBXSourcesBuildPhase section */
329 |
330 | /* Begin XCBuildConfiguration section */
331 | 6154F5EE203B1CC600040F47 /* Debug */ = {
332 | isa = XCBuildConfiguration;
333 | buildSettings = {
334 | ALWAYS_SEARCH_USER_PATHS = NO;
335 | CLANG_ANALYZER_NONNULL = YES;
336 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
337 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
338 | CLANG_CXX_LIBRARY = "libc++";
339 | CLANG_ENABLE_MODULES = YES;
340 | CLANG_ENABLE_OBJC_ARC = YES;
341 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
342 | CLANG_WARN_BOOL_CONVERSION = YES;
343 | CLANG_WARN_COMMA = YES;
344 | CLANG_WARN_CONSTANT_CONVERSION = YES;
345 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
346 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
347 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
348 | CLANG_WARN_EMPTY_BODY = YES;
349 | CLANG_WARN_ENUM_CONVERSION = YES;
350 | CLANG_WARN_INFINITE_RECURSION = YES;
351 | CLANG_WARN_INT_CONVERSION = YES;
352 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
353 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
354 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
355 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
356 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
357 | CLANG_WARN_STRICT_PROTOTYPES = YES;
358 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
359 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
360 | CLANG_WARN_UNREACHABLE_CODE = YES;
361 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
362 | CODE_SIGN_IDENTITY = "iPhone Developer";
363 | COPY_PHASE_STRIP = NO;
364 | CURRENT_PROJECT_VERSION = 1;
365 | DEBUG_INFORMATION_FORMAT = dwarf;
366 | ENABLE_STRICT_OBJC_MSGSEND = YES;
367 | ENABLE_TESTABILITY = YES;
368 | GCC_C_LANGUAGE_STANDARD = gnu11;
369 | GCC_DYNAMIC_NO_PIC = NO;
370 | GCC_NO_COMMON_BLOCKS = YES;
371 | GCC_OPTIMIZATION_LEVEL = 0;
372 | GCC_PREPROCESSOR_DEFINITIONS = (
373 | "DEBUG=1",
374 | "$(inherited)",
375 | );
376 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
377 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
378 | GCC_WARN_UNDECLARED_SELECTOR = YES;
379 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
380 | GCC_WARN_UNUSED_FUNCTION = YES;
381 | GCC_WARN_UNUSED_VARIABLE = YES;
382 | IPHONEOS_DEPLOYMENT_TARGET = 11.2;
383 | MTL_ENABLE_DEBUG_INFO = YES;
384 | ONLY_ACTIVE_ARCH = YES;
385 | SDKROOT = iphoneos;
386 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
387 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
388 | VERSIONING_SYSTEM = "apple-generic";
389 | VERSION_INFO_PREFIX = "";
390 | };
391 | name = Debug;
392 | };
393 | 6154F5EF203B1CC600040F47 /* Release */ = {
394 | isa = XCBuildConfiguration;
395 | buildSettings = {
396 | ALWAYS_SEARCH_USER_PATHS = NO;
397 | CLANG_ANALYZER_NONNULL = YES;
398 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
399 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
400 | CLANG_CXX_LIBRARY = "libc++";
401 | CLANG_ENABLE_MODULES = YES;
402 | CLANG_ENABLE_OBJC_ARC = YES;
403 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
404 | CLANG_WARN_BOOL_CONVERSION = YES;
405 | CLANG_WARN_COMMA = YES;
406 | CLANG_WARN_CONSTANT_CONVERSION = YES;
407 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
408 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
409 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
410 | CLANG_WARN_EMPTY_BODY = YES;
411 | CLANG_WARN_ENUM_CONVERSION = YES;
412 | CLANG_WARN_INFINITE_RECURSION = YES;
413 | CLANG_WARN_INT_CONVERSION = YES;
414 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
415 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
416 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
417 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
418 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
419 | CLANG_WARN_STRICT_PROTOTYPES = YES;
420 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
421 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
422 | CLANG_WARN_UNREACHABLE_CODE = YES;
423 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
424 | CODE_SIGN_IDENTITY = "iPhone Developer";
425 | COPY_PHASE_STRIP = NO;
426 | CURRENT_PROJECT_VERSION = 1;
427 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
428 | ENABLE_NS_ASSERTIONS = NO;
429 | ENABLE_STRICT_OBJC_MSGSEND = YES;
430 | GCC_C_LANGUAGE_STANDARD = gnu11;
431 | GCC_NO_COMMON_BLOCKS = YES;
432 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
433 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
434 | GCC_WARN_UNDECLARED_SELECTOR = YES;
435 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
436 | GCC_WARN_UNUSED_FUNCTION = YES;
437 | GCC_WARN_UNUSED_VARIABLE = YES;
438 | IPHONEOS_DEPLOYMENT_TARGET = 11.2;
439 | MTL_ENABLE_DEBUG_INFO = NO;
440 | SDKROOT = iphoneos;
441 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
442 | VALIDATE_PRODUCT = YES;
443 | VERSIONING_SYSTEM = "apple-generic";
444 | VERSION_INFO_PREFIX = "";
445 | };
446 | name = Release;
447 | };
448 | 6154F5F1203B1CC600040F47 /* Debug */ = {
449 | isa = XCBuildConfiguration;
450 | buildSettings = {
451 | CLANG_ENABLE_MODULES = YES;
452 | CODE_SIGN_IDENTITY = "";
453 | CODE_SIGN_STYLE = Automatic;
454 | DEFINES_MODULE = YES;
455 | DEVELOPMENT_TEAM = 4ZJ5LV82G2;
456 | DYLIB_COMPATIBILITY_VERSION = 1;
457 | DYLIB_CURRENT_VERSION = 1;
458 | DYLIB_INSTALL_NAME_BASE = "@rpath";
459 | INFOPLIST_FILE = SilentScrolly/Info.plist;
460 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
461 | IPHONEOS_DEPLOYMENT_TARGET = 11.0;
462 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
463 | PRODUCT_BUNDLE_IDENTIFIER = TakumaHoriuchi.SilentScrolly;
464 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
465 | SKIP_INSTALL = YES;
466 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
467 | SWIFT_VERSION = 4.0;
468 | TARGETED_DEVICE_FAMILY = "1,2";
469 | };
470 | name = Debug;
471 | };
472 | 6154F5F2203B1CC600040F47 /* Release */ = {
473 | isa = XCBuildConfiguration;
474 | buildSettings = {
475 | CLANG_ENABLE_MODULES = YES;
476 | CODE_SIGN_IDENTITY = "";
477 | CODE_SIGN_STYLE = Automatic;
478 | DEFINES_MODULE = YES;
479 | DEVELOPMENT_TEAM = 4ZJ5LV82G2;
480 | DYLIB_COMPATIBILITY_VERSION = 1;
481 | DYLIB_CURRENT_VERSION = 1;
482 | DYLIB_INSTALL_NAME_BASE = "@rpath";
483 | INFOPLIST_FILE = SilentScrolly/Info.plist;
484 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
485 | IPHONEOS_DEPLOYMENT_TARGET = 11.0;
486 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
487 | PRODUCT_BUNDLE_IDENTIFIER = TakumaHoriuchi.SilentScrolly;
488 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
489 | SKIP_INSTALL = YES;
490 | SWIFT_VERSION = 4.0;
491 | TARGETED_DEVICE_FAMILY = "1,2";
492 | };
493 | name = Release;
494 | };
495 | 61766032203BCD6D0049B35E /* Debug */ = {
496 | isa = XCBuildConfiguration;
497 | buildSettings = {
498 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
499 | CLANG_ENABLE_MODULES = YES;
500 | CODE_SIGN_STYLE = Automatic;
501 | DEVELOPMENT_TEAM = 4ZJ5LV82G2;
502 | INFOPLIST_FILE = "$(SRCROOT)/Example/Resources/Info.plist";
503 | IPHONEOS_DEPLOYMENT_TARGET = 11.0;
504 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
505 | PRODUCT_BUNDLE_IDENTIFIER = TakumaHoriuchi.SilentScrolly.Example;
506 | PRODUCT_NAME = "$(TARGET_NAME)";
507 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
508 | SWIFT_VERSION = 4.0;
509 | TARGETED_DEVICE_FAMILY = "1,2";
510 | };
511 | name = Debug;
512 | };
513 | 61766033203BCD6D0049B35E /* Release */ = {
514 | isa = XCBuildConfiguration;
515 | buildSettings = {
516 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
517 | CLANG_ENABLE_MODULES = YES;
518 | CODE_SIGN_STYLE = Automatic;
519 | DEVELOPMENT_TEAM = 4ZJ5LV82G2;
520 | INFOPLIST_FILE = "$(SRCROOT)/Example/Resources/Info.plist";
521 | IPHONEOS_DEPLOYMENT_TARGET = 11.0;
522 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
523 | PRODUCT_BUNDLE_IDENTIFIER = TakumaHoriuchi.SilentScrolly.Example;
524 | PRODUCT_NAME = "$(TARGET_NAME)";
525 | SWIFT_VERSION = 4.0;
526 | TARGETED_DEVICE_FAMILY = "1,2";
527 | };
528 | name = Release;
529 | };
530 | /* End XCBuildConfiguration section */
531 |
532 | /* Begin XCConfigurationList section */
533 | 6154F5E2203B1CC600040F47 /* Build configuration list for PBXProject "SilentScrolly" */ = {
534 | isa = XCConfigurationList;
535 | buildConfigurations = (
536 | 6154F5EE203B1CC600040F47 /* Debug */,
537 | 6154F5EF203B1CC600040F47 /* Release */,
538 | );
539 | defaultConfigurationIsVisible = 0;
540 | defaultConfigurationName = Release;
541 | };
542 | 6154F5F0203B1CC600040F47 /* Build configuration list for PBXNativeTarget "SilentScrolly" */ = {
543 | isa = XCConfigurationList;
544 | buildConfigurations = (
545 | 6154F5F1203B1CC600040F47 /* Debug */,
546 | 6154F5F2203B1CC600040F47 /* Release */,
547 | );
548 | defaultConfigurationIsVisible = 0;
549 | defaultConfigurationName = Release;
550 | };
551 | 61766034203BCD6D0049B35E /* Build configuration list for PBXNativeTarget "Example" */ = {
552 | isa = XCConfigurationList;
553 | buildConfigurations = (
554 | 61766032203BCD6D0049B35E /* Debug */,
555 | 61766033203BCD6D0049B35E /* Release */,
556 | );
557 | defaultConfigurationIsVisible = 0;
558 | defaultConfigurationName = Release;
559 | };
560 | /* End XCConfigurationList section */
561 | };
562 | rootObject = 6154F5DF203B1CC600040F47 /* Project object */;
563 | }
564 |
--------------------------------------------------------------------------------