18 |
19 |
20 |
--------------------------------------------------------------------------------
/Package.swift:
--------------------------------------------------------------------------------
1 | // swift-tools-version:5.1
2 | import PackageDescription
3 |
4 | let package = Package(
5 | name: "SplitView",
6 | platforms: [
7 | .iOS(.v9),
8 | .macOS(.v10_15)
9 | ],
10 | products: [
11 | .library(name: "SplitView", targets: ["SplitView"])
12 | ],
13 | dependencies: [],
14 | targets: [
15 | .target(
16 | name: "SplitView",
17 | dependencies: [],
18 | path: "SplitView"),
19 | .testTarget(
20 | name: "SplitViewTests",
21 | dependencies: ["SplitView"],
22 | path: "SplitViewTests"),
23 | ]
24 | )
25 |
--------------------------------------------------------------------------------
/docs/undocumented.json:
--------------------------------------------------------------------------------
1 | {
2 | "warnings": [
3 | {
4 | "file": "/Users/twodayslate/Development/splitview/SplitView/SplitView.swift",
5 | "line": 80,
6 | "symbol": "SplitView.init(frame:)",
7 | "symbol_kind": "source.lang.swift.decl.function.method.instance",
8 | "warning": "undocumented"
9 | },
10 | {
11 | "file": "/Users/twodayslate/Development/splitview/SplitView/SplitView.swift",
12 | "line": 97,
13 | "symbol": "SplitView.init()",
14 | "symbol_kind": "source.lang.swift.decl.function.method.instance",
15 | "warning": "undocumented"
16 | }
17 | ],
18 | "source_directory": "/Users/twodayslate/Development/splitview"
19 | }
--------------------------------------------------------------------------------
/docs/docsets/SplitView.docset/Contents/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleIdentifier
6 | com.jazzy.splitview
7 | CFBundleName
8 | SplitView
9 | DocSetPlatformFamily
10 | splitview
11 | isDashDocset
12 |
13 | dashIndexFilePath
14 | index.html
15 | isJavaScriptEnabled
16 |
17 | DashDocSetFamily
18 | dashtoc
19 |
20 |
21 |
--------------------------------------------------------------------------------
/SplitViewTests/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 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: [twodayslate] # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
4 | patreon: twodayslate # Replace with a single Patreon username
5 | open_collective: # Replace with a single Open Collective username
6 | ko_fi: # Replace with a single Ko-fi username
7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
9 | liberapay: # Replace with a single Liberapay username
10 | issuehunt: # Replace with a single IssueHunt username
11 | otechie: # Replace with a single Otechie username
12 | custom: ['https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=DU6YN99AQNAGQ&source=url'] # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
13 |
--------------------------------------------------------------------------------
/SplitView/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleDisplayName
8 | SplitView
9 | CFBundleExecutable
10 | $(EXECUTABLE_NAME)
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | FMWK
19 | CFBundleShortVersionString
20 | $(MARKETING_VERSION)
21 | CFBundleVersion
22 | $(CURRENT_PROJECT_VERSION)
23 |
24 |
25 |
--------------------------------------------------------------------------------
/SplitViewTests/splitviewTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // splitviewTests.swift
3 | // splitviewTests
4 | //
5 | // Created by Zachary Gorak on 8/23/19.
6 | // Copyright © 2019 Zac Gorak. All rights reserved.
7 | //
8 |
9 | import XCTest
10 | @testable import SplitView
11 |
12 | class splitviewTests: XCTestCase {
13 |
14 | override func setUp() {
15 | // Put setup code here. This method is called before the invocation of each test method in the class.
16 | }
17 |
18 | override func tearDown() {
19 | // Put teardown code here. This method is called after the invocation of each test method in the class.
20 | }
21 |
22 | func testExample() {
23 | // This is an example of a functional test case.
24 | // Use XCTAssert and related functions to verify your tests produce the correct results.
25 | }
26 |
27 | func testPerformanceExample() {
28 | // This is an example of a performance test case.
29 | self.measure {
30 | // Put the code you want to measure the time of here.
31 | }
32 | }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/docs/badge.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | documentation
17 |
18 |
19 | documentation
20 |
21 |
22 | 95%
23 |
24 |
25 | 95%
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/SplitView.podspec:
--------------------------------------------------------------------------------
1 | #
2 | # Be sure to run `pod lib lint SplitViewTest.podspec' to ensure this is a
3 | # valid spec before submitting.
4 | #
5 | # Any lines starting with a # are optional, but their use is encouraged
6 | # To learn more about a Podspec see https://guides.cocoapods.org/syntax/podspec.html
7 | #
8 |
9 | Pod::Spec.new do |s|
10 | s.name = 'SplitView'
11 | s.version = '2.0.2'
12 | s.summary = 'A resizable Split View'
13 | s.swift_versions = ['4.2', '5.0', '5.1']
14 |
15 | s.description = <<-DESC
16 | A resizable Split View inspired by Apple's Split View for iPadOS
17 | DESC
18 |
19 | s.homepage = 'https://github.com/twodayslate/SplitView'
20 | s.screenshots = 'https://github.com/twodayslate/SplitView/raw/master/images/horizontal.png', 'https://github.com/twodayslate/SplitView/raw/master/images/vertical.png'
21 | s.license = { :type => 'MIT', :file => 'LICENSE' }
22 | s.author = { 'twodayslate' => 'zac@gorak.us' }
23 | s.source = { :git => 'https://github.com/twodayslate/SplitView.git', :tag => "v#{s.version}" }
24 | s.social_media_url = 'https://twitter.com/twodayslate'
25 |
26 | s.ios.deployment_target = '11.0'
27 | #s.osx.deployment_target = '10.15'
28 |
29 | s.source_files = 'SplitView/*'
30 | s.exclude_files = [ 'SplitView/Info.plist']
31 |
32 | s.public_header_files = 'splitview/*.h'
33 | s.frameworks = 'UIKit'
34 | end
35 |
--------------------------------------------------------------------------------
/generate-docs.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | command -v jazzy
4 |
5 | if [ $? != 0 ]; then
6 | echo "jazzy not found. Install jazzy:"
7 | echo "\t[sudo] gem install jazzy"
8 | exit 1
9 | fi
10 |
11 | set -e # don't print
12 |
13 | module="SplitView"
14 | github="twodayslate/SplitView"
15 | project="splitview.xcodeproj"
16 | scheme="SplitView"
17 |
18 | # get version number from podspec
19 | version="$(egrep "^\s*s.version\s*" SplitView.podspec | awk '{ gsub("\"", "", $3); print $3 }')"
20 | today="$(date '+%Y-%m-%d')"
21 |
22 | if git rev-parse "v$version" >/dev/null 2>&1; then
23 | # Use the tagged commit when we have one
24 | ref="v$version"
25 | else
26 | # Otherwise, use the current commit.
27 | ref="$(git rev-parse HEAD)"
28 | fi
29 |
30 | # since tagging releases doesn't happen very much - let's just use head
31 | ref="master"
32 |
33 | jazzy \
34 | --clean \
35 | --github_url "https://github.com/$github" \
36 | --github-file-prefix "https://github.com/$github/tree/$ref" \
37 | --module-version "$version" \
38 | --xcodebuild-arguments "-project,$project,-scheme,$scheme" \
39 | --module "$module" \
40 | --root-url "https://twodayslate.github.io/$module/reference/" \
41 | --output docs \
42 | --min-acl public\
43 | --copyright "[© 2019 SplitView](https://github.com/twodayslate/SplitView/blob/master/LICENSE). (Last updated: $today)" \
44 | --author "twodayslate" \
45 | --author_url "https://github.com/twodayslate" \
46 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # SplitView
2 |
3 | Resizable Split View, inspired by [Apple's Split View](https://support.apple.com/en-us/HT207582#split) for iPadOS and [SplitKit](https://github.com/macteo/SplitKit)
4 |
5 |
6 |
7 |
8 |
9 | ## Requirements
10 |
11 | ### Swift Package Manager (SPM)
12 |
13 | ```
14 | .Package(url: "https://github.com/twodayslate/SplitView.git", majorVersion: 1)
15 | ```
16 |
17 | For the latest updates use:
18 | ```
19 | .Package(url: "https://github.com/twodayslate/SplitView.git", branch: "master")
20 | ```
21 |
22 | ### CocoaPods
23 |
24 | ```
25 | pod 'SplitView'
26 | ```
27 |
28 | For the latest updates use:
29 | ```
30 | pod 'SplitView', :git => 'https://github.com/twodayslate/SplitView.git'
31 | ```
32 |
33 | ## Usage
34 |
35 | Using `SplitView` is easy! Simply create a `SplitView` and add your views to it - just like a `UIStackView`.
36 |
37 | ```
38 | import SplitView
39 | //
40 | let mySplitView = SplitView()
41 | mySplitView.addSplitSubview(myFirstView)
42 | mySplitView.addSplitSubview(mySecondView)
43 | ```
44 |
45 | There are certain customizations available including minimum sizing and snapping. Custom handles are also supported.
46 |
47 | Be sure to checkout the [example App](https://github.com/twodayslate/SplitView/tree/master/app).
48 |
--------------------------------------------------------------------------------
/app/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 |
--------------------------------------------------------------------------------
/docs/js/jazzy.js:
--------------------------------------------------------------------------------
1 | window.jazzy = {'docset': false}
2 | if (typeof window.dash != 'undefined') {
3 | document.documentElement.className += ' dash'
4 | window.jazzy.docset = true
5 | }
6 | if (navigator.userAgent.match(/xcode/i)) {
7 | document.documentElement.className += ' xcode'
8 | window.jazzy.docset = true
9 | }
10 |
11 | function toggleItem($link, $content) {
12 | var animationDuration = 300;
13 | $link.toggleClass('token-open');
14 | $content.slideToggle(animationDuration);
15 | }
16 |
17 | function itemLinkToContent($link) {
18 | return $link.parent().parent().next();
19 | }
20 |
21 | // On doc load + hash-change, open any targetted item
22 | function openCurrentItemIfClosed() {
23 | if (window.jazzy.docset) {
24 | return;
25 | }
26 | var $link = $(`.token[href="${location.hash}"]`);
27 | $content = itemLinkToContent($link);
28 | if ($content.is(':hidden')) {
29 | toggleItem($link, $content);
30 | }
31 | }
32 |
33 | $(openCurrentItemIfClosed);
34 | $(window).on('hashchange', openCurrentItemIfClosed);
35 |
36 | // On item link ('token') click, toggle its discussion
37 | $('.token').on('click', function(event) {
38 | if (window.jazzy.docset) {
39 | return;
40 | }
41 | var $link = $(this);
42 | toggleItem($link, itemLinkToContent($link));
43 |
44 | // Keeps the document from jumping to the hash.
45 | var href = $link.attr('href');
46 | if (history.pushState) {
47 | history.pushState({}, '', href);
48 | } else {
49 | location.hash = href;
50 | }
51 | event.preventDefault();
52 | });
53 |
54 | // Clicks on links to the current, closed, item need to open the item
55 | $("a:not('.token')").on('click', function() {
56 | if (location == this.href) {
57 | openCurrentItemIfClosed();
58 | }
59 | });
60 |
--------------------------------------------------------------------------------
/app/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 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 | LSApplicationCategoryType
22 | public.app-category.developer-tools
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 | UIInterfaceOrientationPortraitUpsideDown
39 |
40 | UISupportedInterfaceOrientations~ipad
41 |
42 | UIInterfaceOrientationPortrait
43 | UIInterfaceOrientationPortraitUpsideDown
44 | UIInterfaceOrientationLandscapeLeft
45 | UIInterfaceOrientationLandscapeRight
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/docs/docsets/SplitView.docset/Contents/Resources/Documents/js/jazzy.js:
--------------------------------------------------------------------------------
1 | window.jazzy = {'docset': false}
2 | if (typeof window.dash != 'undefined') {
3 | document.documentElement.className += ' dash'
4 | window.jazzy.docset = true
5 | }
6 | if (navigator.userAgent.match(/xcode/i)) {
7 | document.documentElement.className += ' xcode'
8 | window.jazzy.docset = true
9 | }
10 |
11 | function toggleItem($link, $content) {
12 | var animationDuration = 300;
13 | $link.toggleClass('token-open');
14 | $content.slideToggle(animationDuration);
15 | }
16 |
17 | function itemLinkToContent($link) {
18 | return $link.parent().parent().next();
19 | }
20 |
21 | // On doc load + hash-change, open any targetted item
22 | function openCurrentItemIfClosed() {
23 | if (window.jazzy.docset) {
24 | return;
25 | }
26 | var $link = $(`.token[href="${location.hash}"]`);
27 | $content = itemLinkToContent($link);
28 | if ($content.is(':hidden')) {
29 | toggleItem($link, $content);
30 | }
31 | }
32 |
33 | $(openCurrentItemIfClosed);
34 | $(window).on('hashchange', openCurrentItemIfClosed);
35 |
36 | // On item link ('token') click, toggle its discussion
37 | $('.token').on('click', function(event) {
38 | if (window.jazzy.docset) {
39 | return;
40 | }
41 | var $link = $(this);
42 | toggleItem($link, itemLinkToContent($link));
43 |
44 | // Keeps the document from jumping to the hash.
45 | var href = $link.attr('href');
46 | if (history.pushState) {
47 | history.pushState({}, '', href);
48 | } else {
49 | location.hash = href;
50 | }
51 | event.preventDefault();
52 | });
53 |
54 | // Clicks on links to the current, closed, item need to open the item
55 | $("a:not('.token')").on('click', function() {
56 | if (location == this.href) {
57 | openCurrentItemIfClosed();
58 | }
59 | });
60 |
--------------------------------------------------------------------------------
/app/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 |
--------------------------------------------------------------------------------
/app/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 | }
--------------------------------------------------------------------------------
/app/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // app
4 | //
5 | // Created by Zachary Gorak on 8/23/19.
6 | // Copyright © 2019 Zac Gorak. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | @UIApplicationMain
12 | class AppDelegate: UIResponder, UIApplicationDelegate {
13 |
14 | var window: UIWindow?
15 |
16 |
17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
18 | // Override point for customization after application launch.
19 | return true
20 | }
21 |
22 | func applicationWillResignActive(_ application: UIApplication) {
23 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
24 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
25 | }
26 |
27 | func applicationDidEnterBackground(_ application: UIApplication) {
28 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
30 | }
31 |
32 | func applicationWillEnterForeground(_ application: UIApplication) {
33 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
34 | }
35 |
36 | func applicationDidBecomeActive(_ application: UIApplication) {
37 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
38 | }
39 |
40 | func applicationWillTerminate(_ application: UIApplication) {
41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
42 | }
43 |
44 |
45 | }
46 |
47 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | #
3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
4 |
5 | ## User settings
6 | xcuserdata/
7 |
8 | ## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9)
9 | *.xcscmblueprint
10 | *.xccheckout
11 |
12 | ## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4)
13 | build/
14 | DerivedData/
15 | *.moved-aside
16 | *.pbxuser
17 | !default.pbxuser
18 | *.mode1v3
19 | !default.mode1v3
20 | *.mode2v3
21 | !default.mode2v3
22 | *.perspectivev3
23 | !default.perspectivev3
24 |
25 | ## Obj-C/Swift specific
26 | *.hmap
27 |
28 | ## App packaging
29 | *.ipa
30 | *.dSYM.zip
31 | *.dSYM
32 |
33 | ## Playgrounds
34 | timeline.xctimeline
35 | playground.xcworkspace
36 |
37 | # Swift Package Manager
38 | #
39 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
40 | # Packages/
41 | # Package.pins
42 | # Package.resolved
43 | # *.xcodeproj
44 | #
45 | # Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata
46 | # hence it is not needed unless you have added a package configuration file to your project
47 | # .swiftpm
48 |
49 | .build/
50 |
51 | # CocoaPods
52 | #
53 | # We recommend against adding the Pods directory to your .gitignore. However
54 | # you should judge for yourself, the pros and cons are mentioned at:
55 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
56 | #
57 | # Pods/
58 | #
59 | # Add this line if you want to avoid checking in source code from the Xcode workspace
60 | # *.xcworkspace
61 |
62 | # Carthage
63 | #
64 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
65 | # Carthage/Checkouts
66 |
67 | Carthage/Build/
68 |
69 | # Accio dependency management
70 | Dependencies/
71 | .accio/
72 |
73 | # fastlane
74 | #
75 | # It is recommended to not store the screenshots in the git repo.
76 | # Instead, use fastlane to re-generate the screenshots whenever they are needed.
77 | # For more information about the recommended setup visit:
78 | # https://docs.fastlane.tools/best-practices/source-control/#source-control
79 |
80 | fastlane/report.xml
81 | fastlane/Preview.html
82 | fastlane/screenshots/**/*.png
83 | fastlane/test_output
84 |
85 | # Code Injection
86 | #
87 | # After new code Injection tools there's a generated folder /iOSInjectionProject
88 | # https://github.com/johnno1962/injectionforxcode
89 |
90 | iOSInjectionProject/
91 |
92 |
--------------------------------------------------------------------------------
/SplitView/SplitViewSnapBehavior.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SplitViewSnapBehavior.swift
3 | // SplitView
4 | //
5 | // Created by Zachary Gorak on 9/3/19.
6 | // Copyright © 2019 Zac Gorak. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import UIKit
11 |
12 | /// A structure that contains a snap point that is percentage based and a tolerance for when to snap
13 | public struct SplitViewSnapPoint: Equatable {
14 | /// The point at which to snap
15 | public let percentage: CGFloat
16 | /// The amount of range to induce a snap effects
17 | public let tolerance: CGFloat
18 |
19 | /// The global default tolernace
20 | public static var defaultTolerance:CGFloat = 0.04
21 | }
22 |
23 | /// The specefied snap behavior
24 | public enum SplitViewSnapBehavior: Equatable {
25 | /// Snap every 25% (0%, 25%, 50%, 75%, 80%) with the default tolerance
26 | case quarter
27 | /// Snap every 33% (0%, 33%, 66%, 100%) with a the default tolerance
28 | case third
29 | /// Snap at a given percentage and tolerance
30 | case custom(percentage: CGFloat, tolerance: CGFloat)
31 | /// Snap at a given SnapPoint
32 | case withPoint(SplitViewSnapPoint)
33 | /// Snap at the given SnapPoints
34 | case withPoints([SplitViewSnapPoint])
35 |
36 | /// The points at which to snap
37 | var snapPoints: [SplitViewSnapPoint] {
38 | switch self {
39 | case .quarter:
40 | return [SplitViewSnapPoint(percentage: 0.0, tolerance: SplitViewSnapPoint.defaultTolerance),
41 | SplitViewSnapPoint(percentage: 0.25, tolerance: SplitViewSnapPoint.defaultTolerance),
42 | SplitViewSnapPoint(percentage: 0.50, tolerance: SplitViewSnapPoint.defaultTolerance),
43 | SplitViewSnapPoint(percentage: 0.75, tolerance: SplitViewSnapPoint.defaultTolerance),
44 | SplitViewSnapPoint(percentage: 1.0, tolerance: SplitViewSnapPoint.defaultTolerance)]
45 | case .third:
46 | return [SplitViewSnapPoint(percentage: 0.0, tolerance: SplitViewSnapPoint.defaultTolerance),
47 | SplitViewSnapPoint(percentage: 1.0/3.0, tolerance: SplitViewSnapPoint.defaultTolerance),
48 | SplitViewSnapPoint(percentage: 2.0/3.0, tolerance: SplitViewSnapPoint.defaultTolerance),
49 | SplitViewSnapPoint(percentage: 1.0, tolerance: SplitViewSnapPoint.defaultTolerance)
50 | ]
51 | case .withPoint(let point):
52 | return [point]
53 | case .withPoints(let points):
54 | return points
55 | case .custom(let percentage, let tolerance):
56 | return [SplitViewSnapPoint(percentage: percentage, tolerance: tolerance)]
57 | }
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/SplitView.xcodeproj/xcshareddata/xcschemes/app.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
43 |
45 |
51 |
52 |
53 |
54 |
60 |
62 |
68 |
69 |
70 |
71 |
73 |
74 |
77 |
78 |
79 |
--------------------------------------------------------------------------------
/SplitView.xcodeproj/xcshareddata/xcschemes/SplitView.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
33 |
39 |
40 |
41 |
42 |
43 |
53 |
54 |
60 |
61 |
62 |
63 |
69 |
70 |
76 |
77 |
78 |
79 |
81 |
82 |
85 |
86 |
87 |
--------------------------------------------------------------------------------
/app/ViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.swift
3 | // app
4 | //
5 | // Created by Zachary Gorak on 8/23/19.
6 | // Copyright © 2019 Zac Gorak. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import SplitView
11 | import WebKit
12 |
13 |
14 | class ViewController: UIViewController {
15 |
16 | var splitView: SplitView!
17 |
18 | let browser = WKWebView()
19 | let label = UITextView()
20 | let removeButton = UIBarButtonItem(title: "Remove", style: .plain, target: self, action: #selector(removeView(_:)))
21 |
22 | override func viewDidLoad() {
23 | super.viewDidLoad()
24 |
25 | let stack = UIStackView()
26 | stack.translatesAutoresizingMaskIntoConstraints = false
27 | stack.axis = .vertical
28 |
29 | let toolbar = UIToolbar()
30 | stack.addArrangedSubview(toolbar)
31 |
32 | toolbar.items = [
33 | UIBarButtonItem(title: "Rotate", style: .plain, target: self, action: #selector(rotate(_:))),
34 | UIBarButtonItem(title: "Toggle Snapping", style: .plain, target: self, action: #selector(toggleSnap(_:))),
35 | UIBarButtonItem(title: "Add", style: .plain, target: self, action: #selector(addView(_:))),
36 | removeButton
37 | ]
38 |
39 | splitView = SplitView()
40 | splitView.backgroundColor = .black
41 | stack.addArrangedSubview(splitView)
42 |
43 | browser.layer.cornerRadius = 15.0
44 | browser.backgroundColor = .systemBackground
45 | browser.layer.masksToBounds = true
46 | label.backgroundColor = .systemBackground
47 | label.layer.cornerRadius = 15.0
48 | label.layer.masksToBounds = true
49 |
50 | splitView.addSplitSubview(browser)
51 | splitView.addSplitSubview(label)
52 |
53 | self.view.addSubview(stack)
54 |
55 | view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-[stack]-|", options: .alignAllCenterY, metrics: nil, views: ["stack": stack]))
56 | view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[stack]|", options: .alignAllCenterY, metrics: nil, views: ["stack": stack]))
57 | }
58 |
59 | override func viewDidAppear(_ animated: Bool) {
60 | super.viewDidAppear(animated)
61 |
62 | let url = URL(string: "https://zac.gorak.us/")!
63 |
64 | browser.load(URLRequest(url: url))
65 |
66 | DispatchQueue.init(label: "background", qos: .userInitiated).async {
67 | let source = (try? String(contentsOf: url)) ?? "UNABLE TO GET SOURCE"
68 | DispatchQueue.main.async {
69 | self.label.text = source
70 | }
71 | }
72 |
73 | }
74 |
75 | @objc func rotate(_ sender: UIBarButtonItem) {
76 | print("rotate")
77 | if self.splitView.axis == .horizontal {
78 | self.splitView.axis = .vertical
79 | } else {
80 | self.splitView.axis = .horizontal
81 | }
82 | }
83 |
84 | @objc func toggleSnap(_ sender: UIBarButtonItem) {
85 | if splitView.snap.isEmpty {
86 | sender.title = "Turn off Snapping"
87 | splitView.snap.append(SplitViewSnapBehavior.quarter)
88 | } else {
89 | sender.title = "Turn on Snapping"
90 | splitView.snap.removeAll()
91 | }
92 | }
93 |
94 | @objc func addView(_ sender: UIBarButtonItem) {
95 |
96 | let label = UILabel()
97 | label.text = splitView.splitSubviews.count.description
98 | label.textAlignment = .center
99 | label.font = UIFont.boldSystemFont(ofSize: 50.0)
100 | label.adjustsFontSizeToFitWidth = true
101 | label.backgroundColor = .systemBackground
102 | label.layer.cornerRadius = 15.0
103 | label.layer.masksToBounds = true
104 |
105 | splitView.addSplitSubview(label)
106 |
107 | removeButton.isEnabled = true
108 | }
109 |
110 | @objc func removeView(_ sender: UIBarButtonItem) {
111 | splitView.removeSplitSubview(splitView.splitSubviews.last!)
112 | if splitView.splitSubviews.count <= 0 {
113 | removeButton.isEnabled = false
114 | }
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/docs/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | SplitView Reference
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
21 |
22 |
23 | SplitView Reference
24 |
25 | SplitView Reference
26 |
27 |
28 |
29 |
60 |
61 |
62 |
63 |
64 | SplitView
65 |
66 | Resizable Split View, inspired by Apple’s Split View for iPadOS and SplitKit
67 |
68 |
69 |
70 |
71 | Requirements
72 | Swift Package Manager (SPM)
73 | .Package(url: "https://github.com/twodayslate/SplitView.git", majorVersion: 1)
74 |
75 |
76 | For the latest updates use:
77 | .Package(url: "https://github.com/twodayslate/SplitView.git", branch: "master")
78 |
79 | CocoaPods
80 | pod 'SplitView'
81 |
82 |
83 | For the latest updates use:
84 | pod 'SplitView', :git => 'https://github.com/twodayslate/SplitView.git'
85 |
86 | Usage
87 |
88 | Using SplitView is easy! Simply create a SplitView and add your views to it - just like a UIStackView.
89 | import SplitView
90 | //
91 | let mySplitView = SplitView()
92 | mySplitView.addSplitSubview(myFirstView)
93 | mySplitView.addSplitSubview(mySecondView)
94 |
95 |
96 | There are certain customizations available including minimum sizing and snapping. Custom handles are also supported.
97 |
98 | Be sure to checkout the example App .
99 |
100 |
101 |
102 |
106 |
107 |
108 |
109 |
110 |
111 |
--------------------------------------------------------------------------------
/docs/docsets/SplitView.docset/Contents/Resources/Documents/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | SplitView Reference
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
21 |
22 |
23 | SplitView Reference
24 |
25 | SplitView Reference
26 |
27 |
28 |
29 |
60 |
61 |
62 |
63 |
64 | SplitView
65 |
66 | Resizable Split View, inspired by Apple’s Split View for iPadOS and SplitKit
67 |
68 |
69 |
70 |
71 | Requirements
72 | Swift Package Manager (SPM)
73 | .Package(url: "https://github.com/twodayslate/SplitView.git", majorVersion: 1)
74 |
75 |
76 | For the latest updates use:
77 | .Package(url: "https://github.com/twodayslate/SplitView.git", branch: "master")
78 |
79 | CocoaPods
80 | pod 'SplitView'
81 |
82 |
83 | For the latest updates use:
84 | pod 'SplitView', :git => 'https://github.com/twodayslate/SplitView.git'
85 |
86 | Usage
87 |
88 | Using SplitView is easy! Simply create a SplitView and add your views to it - just like a UIStackView.
89 | import SplitView
90 | //
91 | let mySplitView = SplitView()
92 | mySplitView.addSplitSubview(myFirstView)
93 | mySplitView.addSplitSubview(mySecondView)
94 |
95 |
96 | There are certain customizations available including minimum sizing and snapping. Custom handles are also supported.
97 |
98 | Be sure to checkout the example App .
99 |
100 |
101 |
102 |
106 |
107 |
108 |
109 |
110 |
111 |
--------------------------------------------------------------------------------
/docs/Enums.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Enumerations Reference
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
22 |
23 |
24 | SplitView Reference
25 |
26 | Enumerations Reference
27 |
28 |
29 |
30 |
61 |
62 |
63 |
64 | Enumerations
65 | The following enumerations are available globally.
66 |
67 |
68 |
69 |
70 |
71 |
72 |
79 |
80 |
81 |
82 |
83 |
84 |
The specefied snap behavior
85 |
86 |
See more
87 |
88 |
89 |
Declaration
90 |
91 |
Swift
92 |
public enum SplitViewSnapBehavior : Equatable
93 |
94 |
95 |
96 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
110 |
111 |
112 |
113 |
114 |
115 |
--------------------------------------------------------------------------------
/docs/Structs.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Structures Reference
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
22 |
23 |
24 | SplitView Reference
25 |
26 | Structures Reference
27 |
28 |
29 |
30 |
61 |
62 |
63 |
64 | Structures
65 | The following structures are available globally.
66 |
67 |
68 |
69 |
70 |
71 |
72 |
79 |
80 |
81 |
82 |
83 |
84 |
A structure that contains a snap point that is percentage based and a tolerance for when to snap
85 |
86 |
See more
87 |
88 |
89 |
Declaration
90 |
91 |
Swift
92 |
public struct SplitViewSnapPoint : Equatable
93 |
94 |
95 |
96 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
110 |
111 |
112 |
113 |
114 |
115 |
--------------------------------------------------------------------------------
/docs/docsets/SplitView.docset/Contents/Resources/Documents/Enums.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Enumerations Reference
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
22 |
23 |
24 | SplitView Reference
25 |
26 | Enumerations Reference
27 |
28 |
29 |
30 |
61 |
62 |
63 |
64 | Enumerations
65 | The following enumerations are available globally.
66 |
67 |
68 |
69 |
70 |
71 |
72 |
79 |
80 |
81 |
82 |
83 |
84 |
The specefied snap behavior
85 |
86 |
See more
87 |
88 |
89 |
Declaration
90 |
91 |
Swift
92 |
public enum SplitViewSnapBehavior : Equatable
93 |
94 |
95 |
96 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
110 |
111 |
112 |
113 |
114 |
115 |
--------------------------------------------------------------------------------
/docs/css/highlight.css:
--------------------------------------------------------------------------------
1 | /* Credit to https://gist.github.com/wataru420/2048287 */
2 | .highlight {
3 | /* Comment */
4 | /* Error */
5 | /* Keyword */
6 | /* Operator */
7 | /* Comment.Multiline */
8 | /* Comment.Preproc */
9 | /* Comment.Single */
10 | /* Comment.Special */
11 | /* Generic.Deleted */
12 | /* Generic.Deleted.Specific */
13 | /* Generic.Emph */
14 | /* Generic.Error */
15 | /* Generic.Heading */
16 | /* Generic.Inserted */
17 | /* Generic.Inserted.Specific */
18 | /* Generic.Output */
19 | /* Generic.Prompt */
20 | /* Generic.Strong */
21 | /* Generic.Subheading */
22 | /* Generic.Traceback */
23 | /* Keyword.Constant */
24 | /* Keyword.Declaration */
25 | /* Keyword.Pseudo */
26 | /* Keyword.Reserved */
27 | /* Keyword.Type */
28 | /* Literal.Number */
29 | /* Literal.String */
30 | /* Name.Attribute */
31 | /* Name.Builtin */
32 | /* Name.Class */
33 | /* Name.Constant */
34 | /* Name.Entity */
35 | /* Name.Exception */
36 | /* Name.Function */
37 | /* Name.Namespace */
38 | /* Name.Tag */
39 | /* Name.Variable */
40 | /* Operator.Word */
41 | /* Text.Whitespace */
42 | /* Literal.Number.Float */
43 | /* Literal.Number.Hex */
44 | /* Literal.Number.Integer */
45 | /* Literal.Number.Oct */
46 | /* Literal.String.Backtick */
47 | /* Literal.String.Char */
48 | /* Literal.String.Doc */
49 | /* Literal.String.Double */
50 | /* Literal.String.Escape */
51 | /* Literal.String.Heredoc */
52 | /* Literal.String.Interpol */
53 | /* Literal.String.Other */
54 | /* Literal.String.Regex */
55 | /* Literal.String.Single */
56 | /* Literal.String.Symbol */
57 | /* Name.Builtin.Pseudo */
58 | /* Name.Variable.Class */
59 | /* Name.Variable.Global */
60 | /* Name.Variable.Instance */
61 | /* Literal.Number.Integer.Long */ }
62 | .highlight .c {
63 | color: #999988;
64 | font-style: italic; }
65 | .highlight .err {
66 | color: #a61717;
67 | background-color: #e3d2d2; }
68 | .highlight .k {
69 | color: #000000;
70 | font-weight: bold; }
71 | .highlight .o {
72 | color: #000000;
73 | font-weight: bold; }
74 | .highlight .cm {
75 | color: #999988;
76 | font-style: italic; }
77 | .highlight .cp {
78 | color: #999999;
79 | font-weight: bold; }
80 | .highlight .c1 {
81 | color: #999988;
82 | font-style: italic; }
83 | .highlight .cs {
84 | color: #999999;
85 | font-weight: bold;
86 | font-style: italic; }
87 | .highlight .gd {
88 | color: #000000;
89 | background-color: #ffdddd; }
90 | .highlight .gd .x {
91 | color: #000000;
92 | background-color: #ffaaaa; }
93 | .highlight .ge {
94 | color: #000000;
95 | font-style: italic; }
96 | .highlight .gr {
97 | color: #aa0000; }
98 | .highlight .gh {
99 | color: #999999; }
100 | .highlight .gi {
101 | color: #000000;
102 | background-color: #ddffdd; }
103 | .highlight .gi .x {
104 | color: #000000;
105 | background-color: #aaffaa; }
106 | .highlight .go {
107 | color: #888888; }
108 | .highlight .gp {
109 | color: #555555; }
110 | .highlight .gs {
111 | font-weight: bold; }
112 | .highlight .gu {
113 | color: #aaaaaa; }
114 | .highlight .gt {
115 | color: #aa0000; }
116 | .highlight .kc {
117 | color: #000000;
118 | font-weight: bold; }
119 | .highlight .kd {
120 | color: #000000;
121 | font-weight: bold; }
122 | .highlight .kp {
123 | color: #000000;
124 | font-weight: bold; }
125 | .highlight .kr {
126 | color: #000000;
127 | font-weight: bold; }
128 | .highlight .kt {
129 | color: #445588; }
130 | .highlight .m {
131 | color: #009999; }
132 | .highlight .s {
133 | color: #d14; }
134 | .highlight .na {
135 | color: #008080; }
136 | .highlight .nb {
137 | color: #0086B3; }
138 | .highlight .nc {
139 | color: #445588;
140 | font-weight: bold; }
141 | .highlight .no {
142 | color: #008080; }
143 | .highlight .ni {
144 | color: #800080; }
145 | .highlight .ne {
146 | color: #990000;
147 | font-weight: bold; }
148 | .highlight .nf {
149 | color: #990000; }
150 | .highlight .nn {
151 | color: #555555; }
152 | .highlight .nt {
153 | color: #000080; }
154 | .highlight .nv {
155 | color: #008080; }
156 | .highlight .ow {
157 | color: #000000;
158 | font-weight: bold; }
159 | .highlight .w {
160 | color: #bbbbbb; }
161 | .highlight .mf {
162 | color: #009999; }
163 | .highlight .mh {
164 | color: #009999; }
165 | .highlight .mi {
166 | color: #009999; }
167 | .highlight .mo {
168 | color: #009999; }
169 | .highlight .sb {
170 | color: #d14; }
171 | .highlight .sc {
172 | color: #d14; }
173 | .highlight .sd {
174 | color: #d14; }
175 | .highlight .s2 {
176 | color: #d14; }
177 | .highlight .se {
178 | color: #d14; }
179 | .highlight .sh {
180 | color: #d14; }
181 | .highlight .si {
182 | color: #d14; }
183 | .highlight .sx {
184 | color: #d14; }
185 | .highlight .sr {
186 | color: #009926; }
187 | .highlight .s1 {
188 | color: #d14; }
189 | .highlight .ss {
190 | color: #990073; }
191 | .highlight .bp {
192 | color: #999999; }
193 | .highlight .vc {
194 | color: #008080; }
195 | .highlight .vg {
196 | color: #008080; }
197 | .highlight .vi {
198 | color: #008080; }
199 | .highlight .il {
200 | color: #009999; }
201 |
--------------------------------------------------------------------------------
/docs/docsets/SplitView.docset/Contents/Resources/Documents/Structs.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Structures Reference
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
22 |
23 |
24 | SplitView Reference
25 |
26 | Structures Reference
27 |
28 |
29 |
30 |
61 |
62 |
63 |
64 | Structures
65 | The following structures are available globally.
66 |
67 |
68 |
69 |
70 |
71 |
72 |
79 |
80 |
81 |
82 |
83 |
84 |
A structure that contains a snap point that is percentage based and a tolerance for when to snap
85 |
86 |
See more
87 |
88 |
89 |
Declaration
90 |
91 |
Swift
92 |
public struct SplitViewSnapPoint : Equatable
93 |
94 |
95 |
96 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
110 |
111 |
112 |
113 |
114 |
115 |
--------------------------------------------------------------------------------
/docs/docsets/SplitView.docset/Contents/Resources/Documents/css/highlight.css:
--------------------------------------------------------------------------------
1 | /* Credit to https://gist.github.com/wataru420/2048287 */
2 | .highlight {
3 | /* Comment */
4 | /* Error */
5 | /* Keyword */
6 | /* Operator */
7 | /* Comment.Multiline */
8 | /* Comment.Preproc */
9 | /* Comment.Single */
10 | /* Comment.Special */
11 | /* Generic.Deleted */
12 | /* Generic.Deleted.Specific */
13 | /* Generic.Emph */
14 | /* Generic.Error */
15 | /* Generic.Heading */
16 | /* Generic.Inserted */
17 | /* Generic.Inserted.Specific */
18 | /* Generic.Output */
19 | /* Generic.Prompt */
20 | /* Generic.Strong */
21 | /* Generic.Subheading */
22 | /* Generic.Traceback */
23 | /* Keyword.Constant */
24 | /* Keyword.Declaration */
25 | /* Keyword.Pseudo */
26 | /* Keyword.Reserved */
27 | /* Keyword.Type */
28 | /* Literal.Number */
29 | /* Literal.String */
30 | /* Name.Attribute */
31 | /* Name.Builtin */
32 | /* Name.Class */
33 | /* Name.Constant */
34 | /* Name.Entity */
35 | /* Name.Exception */
36 | /* Name.Function */
37 | /* Name.Namespace */
38 | /* Name.Tag */
39 | /* Name.Variable */
40 | /* Operator.Word */
41 | /* Text.Whitespace */
42 | /* Literal.Number.Float */
43 | /* Literal.Number.Hex */
44 | /* Literal.Number.Integer */
45 | /* Literal.Number.Oct */
46 | /* Literal.String.Backtick */
47 | /* Literal.String.Char */
48 | /* Literal.String.Doc */
49 | /* Literal.String.Double */
50 | /* Literal.String.Escape */
51 | /* Literal.String.Heredoc */
52 | /* Literal.String.Interpol */
53 | /* Literal.String.Other */
54 | /* Literal.String.Regex */
55 | /* Literal.String.Single */
56 | /* Literal.String.Symbol */
57 | /* Name.Builtin.Pseudo */
58 | /* Name.Variable.Class */
59 | /* Name.Variable.Global */
60 | /* Name.Variable.Instance */
61 | /* Literal.Number.Integer.Long */ }
62 | .highlight .c {
63 | color: #999988;
64 | font-style: italic; }
65 | .highlight .err {
66 | color: #a61717;
67 | background-color: #e3d2d2; }
68 | .highlight .k {
69 | color: #000000;
70 | font-weight: bold; }
71 | .highlight .o {
72 | color: #000000;
73 | font-weight: bold; }
74 | .highlight .cm {
75 | color: #999988;
76 | font-style: italic; }
77 | .highlight .cp {
78 | color: #999999;
79 | font-weight: bold; }
80 | .highlight .c1 {
81 | color: #999988;
82 | font-style: italic; }
83 | .highlight .cs {
84 | color: #999999;
85 | font-weight: bold;
86 | font-style: italic; }
87 | .highlight .gd {
88 | color: #000000;
89 | background-color: #ffdddd; }
90 | .highlight .gd .x {
91 | color: #000000;
92 | background-color: #ffaaaa; }
93 | .highlight .ge {
94 | color: #000000;
95 | font-style: italic; }
96 | .highlight .gr {
97 | color: #aa0000; }
98 | .highlight .gh {
99 | color: #999999; }
100 | .highlight .gi {
101 | color: #000000;
102 | background-color: #ddffdd; }
103 | .highlight .gi .x {
104 | color: #000000;
105 | background-color: #aaffaa; }
106 | .highlight .go {
107 | color: #888888; }
108 | .highlight .gp {
109 | color: #555555; }
110 | .highlight .gs {
111 | font-weight: bold; }
112 | .highlight .gu {
113 | color: #aaaaaa; }
114 | .highlight .gt {
115 | color: #aa0000; }
116 | .highlight .kc {
117 | color: #000000;
118 | font-weight: bold; }
119 | .highlight .kd {
120 | color: #000000;
121 | font-weight: bold; }
122 | .highlight .kp {
123 | color: #000000;
124 | font-weight: bold; }
125 | .highlight .kr {
126 | color: #000000;
127 | font-weight: bold; }
128 | .highlight .kt {
129 | color: #445588; }
130 | .highlight .m {
131 | color: #009999; }
132 | .highlight .s {
133 | color: #d14; }
134 | .highlight .na {
135 | color: #008080; }
136 | .highlight .nb {
137 | color: #0086B3; }
138 | .highlight .nc {
139 | color: #445588;
140 | font-weight: bold; }
141 | .highlight .no {
142 | color: #008080; }
143 | .highlight .ni {
144 | color: #800080; }
145 | .highlight .ne {
146 | color: #990000;
147 | font-weight: bold; }
148 | .highlight .nf {
149 | color: #990000; }
150 | .highlight .nn {
151 | color: #555555; }
152 | .highlight .nt {
153 | color: #000080; }
154 | .highlight .nv {
155 | color: #008080; }
156 | .highlight .ow {
157 | color: #000000;
158 | font-weight: bold; }
159 | .highlight .w {
160 | color: #bbbbbb; }
161 | .highlight .mf {
162 | color: #009999; }
163 | .highlight .mh {
164 | color: #009999; }
165 | .highlight .mi {
166 | color: #009999; }
167 | .highlight .mo {
168 | color: #009999; }
169 | .highlight .sb {
170 | color: #d14; }
171 | .highlight .sc {
172 | color: #d14; }
173 | .highlight .sd {
174 | color: #d14; }
175 | .highlight .s2 {
176 | color: #d14; }
177 | .highlight .se {
178 | color: #d14; }
179 | .highlight .sh {
180 | color: #d14; }
181 | .highlight .si {
182 | color: #d14; }
183 | .highlight .sx {
184 | color: #d14; }
185 | .highlight .sr {
186 | color: #009926; }
187 | .highlight .s1 {
188 | color: #d14; }
189 | .highlight .ss {
190 | color: #990073; }
191 | .highlight .bp {
192 | color: #999999; }
193 | .highlight .vc {
194 | color: #008080; }
195 | .highlight .vg {
196 | color: #008080; }
197 | .highlight .vi {
198 | color: #008080; }
199 | .highlight .il {
200 | color: #009999; }
201 |
--------------------------------------------------------------------------------
/SplitView/SplitViewHandle.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | import UIKit
3 |
4 | /// The seperator/handle that is between each view in a `SplitView`
5 | open class SplitViewHandle: UIView {
6 | // MARK: - Properties
7 |
8 | // MARK: Public
9 | /// The center view used for grabbing
10 | public var grabber: UIView
11 | /// The width/height of the view
12 | public var size: CGFloat
13 | /// Used for position tracking
14 | public var initialOrigin: CGPoint? = nil
15 | /// - returns:
16 | /// If being dragged returns `true`, `false` otherwise
17 | public var isBeingUsed = false
18 |
19 | /// This property determines the orientation of the arranged views.
20 | /// Assigning the `NSLayoutConstraint.Axis.vertical` value creates a column of views.
21 | /// Assigning the `NSLayoutConstraint.Axis.horizontal` value creates a row.
22 | public var axis: NSLayoutConstraint.Axis = .horizontal {
23 | didSet {
24 | self.layoutConstraints()
25 | }
26 | }
27 |
28 | /// The current constraints on the handle
29 | /// This is used when changing axises and should only be modified
30 | /// when overriding
31 | public var handleConstraints = [NSLayoutConstraint]()
32 |
33 | // MARK: - Initilizers
34 | init(with view: UIView, size: CGFloat) {
35 | self.size = size
36 | self.grabber = view
37 |
38 | super.init(frame: .zero)
39 |
40 | self.translatesAutoresizingMaskIntoConstraints = false
41 |
42 | self.addSubview(self.grabber)
43 |
44 | self.grabber.translatesAutoresizingMaskIntoConstraints = false
45 | self.grabber.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true
46 | self.grabber.centerYAnchor.constraint(equalTo: self.centerYAnchor).isActive = true
47 | self.layoutConstraints()
48 | }
49 |
50 | /// Not implemented
51 | required public init?(coder aDecoder: NSCoder) {
52 | fatalError("init(coder:) has not been implemented")
53 | }
54 |
55 | // MARK: - View Handling
56 |
57 | /// Override this if you are cusomizing your seperator/handle
58 | /// Use `handleConstraints` as necessary
59 | open func layoutConstraints() {
60 | var tmpHandleConstraints = [NSLayoutConstraint]()
61 |
62 | // If they forgot to set a custom layout we will do the basics for them
63 | if self.axis == .vertical {
64 | tmpHandleConstraints.append(NSLayoutConstraint(item: self, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .height, multiplier: 0.0, constant: self.size))
65 | } else {
66 | tmpHandleConstraints.append(NSLayoutConstraint(item: self, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .width, multiplier: 0.0, constant: self.size))
67 | }
68 |
69 | NSLayoutConstraint.deactivate(self.handleConstraints)
70 | NSLayoutConstraint.activate(tmpHandleConstraints)
71 | self.handleConstraints = tmpHandleConstraints
72 | }
73 | }
74 |
75 | internal class DefaultSplitViewHandle: SplitViewHandle {
76 | override func layoutConstraints() {
77 | let defaultSize: CGFloat = 48.0
78 | var tmpHandleConstraints = [NSLayoutConstraint]()
79 |
80 | if self.axis == .vertical {
81 | tmpHandleConstraints = [
82 | NSLayoutConstraint(item: self.grabber, attribute: .height, relatedBy: .equal, toItem: self, attribute: .height, multiplier: 0.5, constant: 0.0),
83 | NSLayoutConstraint(item: self.grabber, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .width, multiplier: 0.0, constant: defaultSize),
84 | NSLayoutConstraint(item: self, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .height, multiplier: 0.0, constant: self.size)
85 | ]
86 | } else {
87 | tmpHandleConstraints = [
88 | NSLayoutConstraint(item: self.grabber, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .height, multiplier: 0.0, constant: defaultSize),
89 | NSLayoutConstraint(item: self.grabber, attribute: .width, relatedBy: .equal, toItem: self, attribute: .width, multiplier: 0.5, constant: 0.0),
90 | NSLayoutConstraint(item: self, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .width, multiplier: 0.0, constant: self.size)
91 | ]
92 | }
93 |
94 | NSLayoutConstraint.deactivate(self.handleConstraints)
95 | NSLayoutConstraint.activate(tmpHandleConstraints)
96 | self.handleConstraints = tmpHandleConstraints
97 | }
98 |
99 | override var isBeingUsed: Bool {
100 | didSet {
101 | if self.isBeingUsed {
102 | DispatchQueue.main.async {
103 | UIView.animate(withDuration: 0.5) {
104 | self.grabber.backgroundColor = self.grabber.backgroundColor?.withAlphaComponent(0.85)
105 | }
106 | }
107 | } else {
108 | DispatchQueue.main.async {
109 | UIView.animate(withDuration: 0.2) {
110 | self.grabber.backgroundColor = self.grabber.backgroundColor?.withAlphaComponent(0.6)
111 | }
112 | }
113 | }
114 | }
115 | }
116 | }
117 |
118 | // MARK: - Default
119 | extension SplitViewHandle {
120 | /// The default handle.
121 | public class func useDefault() -> SplitViewHandle {
122 | let innerHandle = UIView()
123 | innerHandle.backgroundColor = UIColor.white.withAlphaComponent(0.6)
124 | innerHandle.layer.cornerRadius = 4.0
125 |
126 | let handle = DefaultSplitViewHandle(with: innerHandle, size: 11.0)
127 | handle.backgroundColor = .black
128 |
129 | return handle
130 | }
131 | }
132 |
--------------------------------------------------------------------------------
/docs/Classes.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Classes Reference
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
22 |
23 |
24 | SplitView Reference
25 |
26 | Classes Reference
27 |
28 |
29 |
30 |
61 |
62 |
63 |
64 | Classes
65 | The following classes are available globally.
66 |
67 |
68 |
69 |
70 |
71 |
72 |
79 |
80 |
81 |
82 |
83 |
88 |
89 |
Declaration
90 |
91 |
Swift
92 |
open class SplitView : UIView
93 |
94 |
95 |
96 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
114 |
115 |
116 |
117 |
118 |
119 |
The seperator/handle that is between each view in a SplitView
120 |
121 |
See more
122 |
123 |
124 |
Declaration
125 |
126 |
Swift
127 |
open class SplitViewHandle : UIView
128 |
129 |
130 |
131 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
145 |
146 |
147 |
148 |
149 |
150 |
--------------------------------------------------------------------------------
/docs/docsets/SplitView.docset/Contents/Resources/Documents/Classes.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Classes Reference
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
22 |
23 |
24 | SplitView Reference
25 |
26 | Classes Reference
27 |
28 |
29 |
30 |
61 |
62 |
63 |
64 | Classes
65 | The following classes are available globally.
66 |
67 |
68 |
69 |
70 |
71 |
72 |
79 |
80 |
81 |
82 |
83 |
88 |
89 |
Declaration
90 |
91 |
Swift
92 |
open class SplitView : UIView
93 |
94 |
95 |
96 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
114 |
115 |
116 |
117 |
118 |
119 |
The seperator/handle that is between each view in a SplitView
120 |
121 |
See more
122 |
123 |
124 |
Declaration
125 |
126 |
Swift
127 |
open class SplitViewHandle : UIView
128 |
129 |
130 |
131 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
145 |
146 |
147 |
148 |
149 |
150 |
--------------------------------------------------------------------------------
/docs/search.json:
--------------------------------------------------------------------------------
1 | {"Structs/SplitViewSnapPoint.html#/s:9SplitView0aB9SnapPointV10percentage12CoreGraphics7CGFloatVvp":{"name":"percentage","abstract":"The point at which to snap
","parent_name":"SplitViewSnapPoint"},"Structs/SplitViewSnapPoint.html#/s:9SplitView0aB9SnapPointV9tolerance12CoreGraphics7CGFloatVvp":{"name":"tolerance","abstract":"The amount of range to induce a snap effects
","parent_name":"SplitViewSnapPoint"},"Structs/SplitViewSnapPoint.html#/s:9SplitView0aB9SnapPointV16defaultTolerance12CoreGraphics7CGFloatVvpZ":{"name":"defaultTolerance","abstract":"The global default tolernace
","parent_name":"SplitViewSnapPoint"},"Structs/SplitViewSnapPoint.html":{"name":"SplitViewSnapPoint","abstract":"A structure that contains a snap point that is percentage based and a tolerance for when to snap
"},"Enums/SplitViewSnapBehavior.html#/s:9SplitView0aB12SnapBehaviorO7quarteryA2CmF":{"name":"quarter","abstract":"Snap every 25% (0%, 25%, 50%, 75%, 80%) with the default tolerance
","parent_name":"SplitViewSnapBehavior"},"Enums/SplitViewSnapBehavior.html#/s:9SplitView0aB12SnapBehaviorO5thirdyA2CmF":{"name":"third","abstract":"Snap every 33% (0%, 33%, 66%, 100%) with a the default tolerance
","parent_name":"SplitViewSnapBehavior"},"Enums/SplitViewSnapBehavior.html#/s:9SplitView0aB12SnapBehaviorO6customyAC12CoreGraphics7CGFloatV_AGtcACmF":{"name":"custom(percentage:tolerance:)","abstract":"Snap at a given percentage and tolerance
","parent_name":"SplitViewSnapBehavior"},"Enums/SplitViewSnapBehavior.html#/s:9SplitView0aB12SnapBehaviorO9withPointyAcA0abcF0VcACmF":{"name":"withPoint(_:)","abstract":"Snap at a given SnapPoint
","parent_name":"SplitViewSnapBehavior"},"Enums/SplitViewSnapBehavior.html#/s:9SplitView0aB12SnapBehaviorO10withPointsyACSayAA0abC5PointVGcACmF":{"name":"withPoints(_:)","abstract":"Snap at the given SnapPoints
","parent_name":"SplitViewSnapBehavior"},"Enums/SplitViewSnapBehavior.html":{"name":"SplitViewSnapBehavior","abstract":"The specefied snap behavior
"},"Classes/SplitViewHandle.html#/s:9SplitView0aB6HandleC7grabberSo6UIViewCvp":{"name":"grabber","abstract":"The center view used for grabbing
","parent_name":"SplitViewHandle"},"Classes/SplitViewHandle.html#/s:9SplitView0aB6HandleC4size12CoreGraphics7CGFloatVvp":{"name":"size","abstract":"The width/height of the view
","parent_name":"SplitViewHandle"},"Classes/SplitViewHandle.html#/s:9SplitView0aB6HandleC13initialOriginSo7CGPointVSgvp":{"name":"initialOrigin","abstract":"Used for position tracking
","parent_name":"SplitViewHandle"},"Classes/SplitViewHandle.html#/s:9SplitView0aB6HandleC11isBeingUsedSbvp":{"name":"isBeingUsed","parent_name":"SplitViewHandle"},"Classes/SplitViewHandle.html#/s:9SplitView0aB6HandleC4axisSo22UILayoutConstraintAxisVvp":{"name":"axis","abstract":"This property determines the orientation of the arranged views.","parent_name":"SplitViewHandle"},"Classes/SplitViewHandle.html#/s:9SplitView0aB6HandleC17handleConstraintsSaySo18NSLayoutConstraintCGvp":{"name":"handleConstraints","abstract":"
The current constraints on the handle","parent_name":"SplitViewHandle"},"Classes/SplitViewHandle.html#/c:@M@SplitView@objc(cs)SplitViewHandle(im)initWithCoder:":{"name":"init(coder:)","abstract":"
Not implemented
","parent_name":"SplitViewHandle"},"Classes/SplitViewHandle.html#/s:9SplitView0aB6HandleC17layoutConstraintsyyF":{"name":"layoutConstraints()","abstract":"Override this if you are cusomizing your seperator/handle","parent_name":"SplitViewHandle"},"Classes/SplitViewHandle.html#/s:9SplitView0aB6HandleC10useDefaultACyFZ":{"name":"useDefault()","abstract":"
The default handle.
","parent_name":"SplitViewHandle"},"Classes/SplitView.html#/s:9SplitViewAAC13splitSubviewsSaySo6UIViewCGvp":{"name":"splitSubviews","abstract":"The list of views split by the split view.
","parent_name":"SplitView"},"Classes/SplitView.html#/s:9SplitViewAAC7handlesSayAA0aB6HandleCGvp":{"name":"handles","abstract":"The handles between views
","parent_name":"SplitView"},"Classes/SplitView.html#/s:9SplitViewAAC12minimumRatio12CoreGraphics7CGFloatVvp":{"name":"minimumRatio","abstract":"The minimum width/height ratio for each view
","parent_name":"SplitView"},"Classes/SplitView.html#/s:9SplitViewAAC17animationDurationSdvp":{"name":"animationDuration","abstract":"The animation duration when resizing views
","parent_name":"SplitView"},"Classes/SplitView.html#/s:9SplitViewAAC9precisionSivp":{"name":"precision","abstract":"The precision of the movements. 1 is every 10%, 2 is every 1%, etc
","parent_name":"SplitView"},"Classes/SplitView.html#/s:9SplitViewAAC4snapSayAA0aB12SnapBehaviorOGvp":{"name":"snap","abstract":"Snap Behavior
","parent_name":"SplitView"},"Classes/SplitView.html#/s:9SplitViewAAC4axisSo22UILayoutConstraintAxisVvp":{"name":"axis","abstract":"The axis along which the split views are laid out.
","parent_name":"SplitView"},"Classes/SplitView.html#/c:@M@SplitView@objc(cs)SplitView(im)initWithFrame:":{"name":"init(frame:)","abstract":"Undocumented
","parent_name":"SplitView"},"Classes/SplitView.html#/c:@M@SplitView@objc(cs)SplitView(im)init":{"name":"init()","abstract":"Undocumented
","parent_name":"SplitView"},"Classes/SplitView.html#/s:9SplitViewAAC13splitSubviewsABSaySo6UIViewCG_tcfc":{"name":"init(splitSubviews:)","abstract":"Returns a new split view object that manages the provided views.
","parent_name":"SplitView"},"Classes/SplitView.html#/c:@M@SplitView@objc(cs)SplitView(im)initWithCoder:":{"name":"init(coder:)","abstract":"Not implemented
","parent_name":"SplitView"},"Classes/SplitView.html#/s:9SplitViewAAC03addA7Subview_12desiredRatio07minimumF010withHandleySo6UIViewC_12CoreGraphics7CGFloatVAkA0abI0CSgtF":{"name":"addSplitSubview(_:desiredRatio:minimumRatio:withHandle:)","abstract":"Adds a view to the end of the splitSupportingViews array
","parent_name":"SplitView"},"Classes/SplitView.html#/s:9SplitViewAAC06insertA7Subview_2at12desiredRatio07minimumG010withHandleySo6UIViewC_Si12CoreGraphics7CGFloatVAlA0abJ0CSgtF":{"name":"insertSplitSubview(_:at:desiredRatio:minimumRatio:withHandle:)","abstract":"Adds the provided view to the array of split subviews at the specified index.
","parent_name":"SplitView"},"Classes/SplitView.html#/s:9SplitViewAAC06removeA7SubviewyySo6UIViewCF":{"name":"removeSplitSubview(_:)","abstract":"Removes the provided view from the stack’s array of split subviews.
","parent_name":"SplitView"},"Classes/SplitView.html#/s:9SplitViewAAC6ratiosSay12CoreGraphics7CGFloatVGvp":{"name":"ratios","abstract":"The current ratio for all the split subviews
","parent_name":"SplitView"},"Classes/SplitView.html#/s:9SplitViewAAC13minimumRatiosSay12CoreGraphics7CGFloatVGvp":{"name":"minimumRatios","abstract":"The minimum ratios for all the split subviews
","parent_name":"SplitView"},"Classes/SplitView.html#/s:9SplitViewAAC15setMinimumRatio_3fory12CoreGraphics7CGFloatV_So6UIViewCtF":{"name":"setMinimumRatio(_:for:)","abstract":"Set the minimum ratio for a specific view
","parent_name":"SplitView"},"Classes/SplitView.html#/s:9SplitViewAAC34isLayoutMarginsRelativeArrangementSbvp":{"name":"isLayoutMarginsRelativeArrangement","abstract":"A Boolean value that determines whether the split view lays out its split views relative to","parent_name":"SplitView"},"Classes/SplitView.html":{"name":"SplitView","abstract":"
Resizable Split View, inspired by Apple’s Split View for iPadOS and SplitKit
"},"Classes/SplitViewHandle.html":{"name":"SplitViewHandle","abstract":"The seperator/handle that is between each view in a SplitView
"},"Classes.html":{"name":"Classes","abstract":"The following classes are available globally.
"},"Enums.html":{"name":"Enumerations","abstract":"The following enumerations are available globally.
"},"Structs.html":{"name":"Structures","abstract":"The following structures are available globally.
"}}
--------------------------------------------------------------------------------
/docs/docsets/SplitView.docset/Contents/Resources/Documents/search.json:
--------------------------------------------------------------------------------
1 | {"Structs/SplitViewSnapPoint.html#/s:9SplitView0aB9SnapPointV10percentage12CoreGraphics7CGFloatVvp":{"name":"percentage","abstract":"The point at which to snap
","parent_name":"SplitViewSnapPoint"},"Structs/SplitViewSnapPoint.html#/s:9SplitView0aB9SnapPointV9tolerance12CoreGraphics7CGFloatVvp":{"name":"tolerance","abstract":"The amount of range to induce a snap effects
","parent_name":"SplitViewSnapPoint"},"Structs/SplitViewSnapPoint.html#/s:9SplitView0aB9SnapPointV16defaultTolerance12CoreGraphics7CGFloatVvpZ":{"name":"defaultTolerance","abstract":"The global default tolernace
","parent_name":"SplitViewSnapPoint"},"Structs/SplitViewSnapPoint.html":{"name":"SplitViewSnapPoint","abstract":"A structure that contains a snap point that is percentage based and a tolerance for when to snap
"},"Enums/SplitViewSnapBehavior.html#/s:9SplitView0aB12SnapBehaviorO7quarteryA2CmF":{"name":"quarter","abstract":"Snap every 25% (0%, 25%, 50%, 75%, 80%) with the default tolerance
","parent_name":"SplitViewSnapBehavior"},"Enums/SplitViewSnapBehavior.html#/s:9SplitView0aB12SnapBehaviorO5thirdyA2CmF":{"name":"third","abstract":"Snap every 33% (0%, 33%, 66%, 100%) with a the default tolerance
","parent_name":"SplitViewSnapBehavior"},"Enums/SplitViewSnapBehavior.html#/s:9SplitView0aB12SnapBehaviorO6customyAC12CoreGraphics7CGFloatV_AGtcACmF":{"name":"custom(percentage:tolerance:)","abstract":"Snap at a given percentage and tolerance
","parent_name":"SplitViewSnapBehavior"},"Enums/SplitViewSnapBehavior.html#/s:9SplitView0aB12SnapBehaviorO9withPointyAcA0abcF0VcACmF":{"name":"withPoint(_:)","abstract":"Snap at a given SnapPoint
","parent_name":"SplitViewSnapBehavior"},"Enums/SplitViewSnapBehavior.html#/s:9SplitView0aB12SnapBehaviorO10withPointsyACSayAA0abC5PointVGcACmF":{"name":"withPoints(_:)","abstract":"Snap at the given SnapPoints
","parent_name":"SplitViewSnapBehavior"},"Enums/SplitViewSnapBehavior.html":{"name":"SplitViewSnapBehavior","abstract":"The specefied snap behavior
"},"Classes/SplitViewHandle.html#/s:9SplitView0aB6HandleC7grabberSo6UIViewCvp":{"name":"grabber","abstract":"The center view used for grabbing
","parent_name":"SplitViewHandle"},"Classes/SplitViewHandle.html#/s:9SplitView0aB6HandleC4size12CoreGraphics7CGFloatVvp":{"name":"size","abstract":"The width/height of the view
","parent_name":"SplitViewHandle"},"Classes/SplitViewHandle.html#/s:9SplitView0aB6HandleC13initialOriginSo7CGPointVSgvp":{"name":"initialOrigin","abstract":"Used for position tracking
","parent_name":"SplitViewHandle"},"Classes/SplitViewHandle.html#/s:9SplitView0aB6HandleC11isBeingUsedSbvp":{"name":"isBeingUsed","parent_name":"SplitViewHandle"},"Classes/SplitViewHandle.html#/s:9SplitView0aB6HandleC4axisSo22UILayoutConstraintAxisVvp":{"name":"axis","abstract":"This property determines the orientation of the arranged views.","parent_name":"SplitViewHandle"},"Classes/SplitViewHandle.html#/s:9SplitView0aB6HandleC17handleConstraintsSaySo18NSLayoutConstraintCGvp":{"name":"handleConstraints","abstract":"
The current constraints on the handle","parent_name":"SplitViewHandle"},"Classes/SplitViewHandle.html#/c:@M@SplitView@objc(cs)SplitViewHandle(im)initWithCoder:":{"name":"init(coder:)","abstract":"
Not implemented
","parent_name":"SplitViewHandle"},"Classes/SplitViewHandle.html#/s:9SplitView0aB6HandleC17layoutConstraintsyyF":{"name":"layoutConstraints()","abstract":"Override this if you are cusomizing your seperator/handle","parent_name":"SplitViewHandle"},"Classes/SplitViewHandle.html#/s:9SplitView0aB6HandleC10useDefaultACyFZ":{"name":"useDefault()","abstract":"
The default handle.
","parent_name":"SplitViewHandle"},"Classes/SplitView.html#/s:9SplitViewAAC13splitSubviewsSaySo6UIViewCGvp":{"name":"splitSubviews","abstract":"The list of views split by the split view.
","parent_name":"SplitView"},"Classes/SplitView.html#/s:9SplitViewAAC7handlesSayAA0aB6HandleCGvp":{"name":"handles","abstract":"The handles between views
","parent_name":"SplitView"},"Classes/SplitView.html#/s:9SplitViewAAC12minimumRatio12CoreGraphics7CGFloatVvp":{"name":"minimumRatio","abstract":"The minimum width/height ratio for each view
","parent_name":"SplitView"},"Classes/SplitView.html#/s:9SplitViewAAC17animationDurationSdvp":{"name":"animationDuration","abstract":"The animation duration when resizing views
","parent_name":"SplitView"},"Classes/SplitView.html#/s:9SplitViewAAC9precisionSivp":{"name":"precision","abstract":"The precision of the movements. 1 is every 10%, 2 is every 1%, etc
","parent_name":"SplitView"},"Classes/SplitView.html#/s:9SplitViewAAC4snapSayAA0aB12SnapBehaviorOGvp":{"name":"snap","abstract":"Snap Behavior
","parent_name":"SplitView"},"Classes/SplitView.html#/s:9SplitViewAAC4axisSo22UILayoutConstraintAxisVvp":{"name":"axis","abstract":"The axis along which the split views are laid out.
","parent_name":"SplitView"},"Classes/SplitView.html#/c:@M@SplitView@objc(cs)SplitView(im)initWithFrame:":{"name":"init(frame:)","abstract":"Undocumented
","parent_name":"SplitView"},"Classes/SplitView.html#/c:@M@SplitView@objc(cs)SplitView(im)init":{"name":"init()","abstract":"Undocumented
","parent_name":"SplitView"},"Classes/SplitView.html#/s:9SplitViewAAC13splitSubviewsABSaySo6UIViewCG_tcfc":{"name":"init(splitSubviews:)","abstract":"Returns a new split view object that manages the provided views.
","parent_name":"SplitView"},"Classes/SplitView.html#/c:@M@SplitView@objc(cs)SplitView(im)initWithCoder:":{"name":"init(coder:)","abstract":"Not implemented
","parent_name":"SplitView"},"Classes/SplitView.html#/s:9SplitViewAAC03addA7Subview_12desiredRatio07minimumF010withHandleySo6UIViewC_12CoreGraphics7CGFloatVAkA0abI0CSgtF":{"name":"addSplitSubview(_:desiredRatio:minimumRatio:withHandle:)","abstract":"Adds a view to the end of the splitSupportingViews array
","parent_name":"SplitView"},"Classes/SplitView.html#/s:9SplitViewAAC06insertA7Subview_2at12desiredRatio07minimumG010withHandleySo6UIViewC_Si12CoreGraphics7CGFloatVAlA0abJ0CSgtF":{"name":"insertSplitSubview(_:at:desiredRatio:minimumRatio:withHandle:)","abstract":"Adds the provided view to the array of split subviews at the specified index.
","parent_name":"SplitView"},"Classes/SplitView.html#/s:9SplitViewAAC06removeA7SubviewyySo6UIViewCF":{"name":"removeSplitSubview(_:)","abstract":"Removes the provided view from the stack’s array of split subviews.
","parent_name":"SplitView"},"Classes/SplitView.html#/s:9SplitViewAAC6ratiosSay12CoreGraphics7CGFloatVGvp":{"name":"ratios","abstract":"The current ratio for all the split subviews
","parent_name":"SplitView"},"Classes/SplitView.html#/s:9SplitViewAAC13minimumRatiosSay12CoreGraphics7CGFloatVGvp":{"name":"minimumRatios","abstract":"The minimum ratios for all the split subviews
","parent_name":"SplitView"},"Classes/SplitView.html#/s:9SplitViewAAC15setMinimumRatio_3fory12CoreGraphics7CGFloatV_So6UIViewCtF":{"name":"setMinimumRatio(_:for:)","abstract":"Set the minimum ratio for a specific view
","parent_name":"SplitView"},"Classes/SplitView.html#/s:9SplitViewAAC34isLayoutMarginsRelativeArrangementSbvp":{"name":"isLayoutMarginsRelativeArrangement","abstract":"A Boolean value that determines whether the split view lays out its split views relative to","parent_name":"SplitView"},"Classes/SplitView.html":{"name":"SplitView","abstract":"
Resizable Split View, inspired by Apple’s Split View for iPadOS and SplitKit
"},"Classes/SplitViewHandle.html":{"name":"SplitViewHandle","abstract":"The seperator/handle that is between each view in a SplitView
"},"Classes.html":{"name":"Classes","abstract":"The following classes are available globally.
"},"Enums.html":{"name":"Enumerations","abstract":"The following enumerations are available globally.
"},"Structs.html":{"name":"Structures","abstract":"The following structures are available globally.
"}}
--------------------------------------------------------------------------------
/docs/css/jazzy.css:
--------------------------------------------------------------------------------
1 | html, body, div, span, h1, h3, h4, p, a, code, em, img, ul, li, table, tbody, tr, td {
2 | background: transparent;
3 | border: 0;
4 | margin: 0;
5 | outline: 0;
6 | padding: 0;
7 | vertical-align: baseline; }
8 |
9 | body {
10 | background-color: #f2f2f2;
11 | font-family: Helvetica, freesans, Arial, sans-serif;
12 | font-size: 14px;
13 | -webkit-font-smoothing: subpixel-antialiased;
14 | word-wrap: break-word; }
15 |
16 | h1, h2, h3 {
17 | margin-top: 0.8em;
18 | margin-bottom: 0.3em;
19 | font-weight: 100;
20 | color: black; }
21 |
22 | h1 {
23 | font-size: 2.5em; }
24 |
25 | h2 {
26 | font-size: 2em;
27 | border-bottom: 1px solid #e2e2e2; }
28 |
29 | h4 {
30 | font-size: 13px;
31 | line-height: 1.5;
32 | margin-top: 21px; }
33 |
34 | h5 {
35 | font-size: 1.1em; }
36 |
37 | h6 {
38 | font-size: 1.1em;
39 | color: #777; }
40 |
41 | .section-name {
42 | color: gray;
43 | display: block;
44 | font-family: Helvetica;
45 | font-size: 22px;
46 | font-weight: 100;
47 | margin-bottom: 15px; }
48 |
49 | pre, code {
50 | font: 0.95em Menlo, monospace;
51 | color: #777;
52 | word-wrap: normal; }
53 |
54 | p code, li code {
55 | background-color: #eee;
56 | padding: 2px 4px;
57 | border-radius: 4px; }
58 |
59 | a {
60 | color: #0088cc;
61 | text-decoration: none; }
62 |
63 | ul {
64 | padding-left: 15px; }
65 |
66 | li {
67 | line-height: 1.8em; }
68 |
69 | img {
70 | max-width: 100%; }
71 |
72 | blockquote {
73 | margin-left: 0;
74 | padding: 0 10px;
75 | border-left: 4px solid #ccc; }
76 |
77 | .content-wrapper {
78 | margin: 0 auto;
79 | width: 980px; }
80 |
81 | header {
82 | font-size: 0.85em;
83 | line-height: 26px;
84 | background-color: #414141;
85 | position: fixed;
86 | width: 100%;
87 | z-index: 1; }
88 | header img {
89 | padding-right: 6px;
90 | vertical-align: -4px;
91 | height: 16px; }
92 | header a {
93 | color: #fff; }
94 | header p {
95 | float: left;
96 | color: #999; }
97 | header .header-right {
98 | float: right;
99 | margin-left: 16px; }
100 |
101 | #breadcrumbs {
102 | background-color: #f2f2f2;
103 | height: 27px;
104 | padding-top: 17px;
105 | position: fixed;
106 | width: 100%;
107 | z-index: 1;
108 | margin-top: 26px; }
109 | #breadcrumbs #carat {
110 | height: 10px;
111 | margin: 0 5px; }
112 |
113 | .sidebar {
114 | background-color: #f9f9f9;
115 | border: 1px solid #e2e2e2;
116 | overflow-y: auto;
117 | overflow-x: hidden;
118 | position: fixed;
119 | top: 70px;
120 | bottom: 0;
121 | width: 230px;
122 | word-wrap: normal; }
123 |
124 | .nav-groups {
125 | list-style-type: none;
126 | background: #fff;
127 | padding-left: 0; }
128 |
129 | .nav-group-name {
130 | border-bottom: 1px solid #e2e2e2;
131 | font-size: 1.1em;
132 | font-weight: 100;
133 | padding: 15px 0 15px 20px; }
134 | .nav-group-name > a {
135 | color: #333; }
136 |
137 | .nav-group-tasks {
138 | margin-top: 5px; }
139 |
140 | .nav-group-task {
141 | font-size: 0.9em;
142 | list-style-type: none;
143 | white-space: nowrap; }
144 | .nav-group-task a {
145 | color: #888; }
146 |
147 | .main-content {
148 | background-color: #fff;
149 | border: 1px solid #e2e2e2;
150 | margin-left: 246px;
151 | position: absolute;
152 | overflow: hidden;
153 | padding-bottom: 20px;
154 | top: 70px;
155 | width: 734px; }
156 | .main-content p, .main-content a, .main-content code, .main-content em, .main-content ul, .main-content table, .main-content blockquote {
157 | margin-bottom: 1em; }
158 | .main-content p {
159 | line-height: 1.8em; }
160 | .main-content section .section:first-child {
161 | margin-top: 0;
162 | padding-top: 0; }
163 | .main-content section .task-group-section .task-group:first-of-type {
164 | padding-top: 10px; }
165 | .main-content section .task-group-section .task-group:first-of-type .section-name {
166 | padding-top: 15px; }
167 | .main-content section .heading:before {
168 | content: "";
169 | display: block;
170 | padding-top: 70px;
171 | margin: -70px 0 0; }
172 |
173 | .section {
174 | padding: 0 25px; }
175 |
176 | .highlight {
177 | background-color: #eee;
178 | padding: 10px 12px;
179 | border: 1px solid #e2e2e2;
180 | border-radius: 4px;
181 | overflow-x: auto; }
182 |
183 | .declaration .highlight {
184 | overflow-x: initial;
185 | padding: 0 40px 40px 0;
186 | margin-bottom: -25px;
187 | background-color: transparent;
188 | border: none; }
189 |
190 | .section-name {
191 | margin: 0;
192 | margin-left: 18px; }
193 |
194 | .task-group-section {
195 | padding-left: 6px;
196 | border-top: 1px solid #e2e2e2; }
197 |
198 | .task-group {
199 | padding-top: 0px; }
200 |
201 | .task-name-container a[name]:before {
202 | content: "";
203 | display: block;
204 | padding-top: 70px;
205 | margin: -70px 0 0; }
206 |
207 | .item {
208 | padding-top: 8px;
209 | width: 100%;
210 | list-style-type: none; }
211 | .item a[name]:before {
212 | content: "";
213 | display: block;
214 | padding-top: 70px;
215 | margin: -70px 0 0; }
216 | .item code {
217 | background-color: transparent;
218 | padding: 0; }
219 | .item .token, .item .direct-link {
220 | padding-left: 3px;
221 | margin-left: 15px;
222 | font-size: 11.9px;
223 | transition: all 300ms; }
224 | .item .token-open {
225 | margin-left: 0px; }
226 | .item .discouraged {
227 | text-decoration: line-through; }
228 | .item .declaration-note {
229 | font-size: .85em;
230 | color: gray;
231 | font-style: italic; }
232 |
233 | .pointer-container {
234 | border-bottom: 1px solid #e2e2e2;
235 | left: -23px;
236 | padding-bottom: 13px;
237 | position: relative;
238 | width: 110%; }
239 |
240 | .pointer {
241 | background: #f9f9f9;
242 | border-left: 1px solid #e2e2e2;
243 | border-top: 1px solid #e2e2e2;
244 | height: 12px;
245 | left: 21px;
246 | top: -7px;
247 | -webkit-transform: rotate(45deg);
248 | -moz-transform: rotate(45deg);
249 | -o-transform: rotate(45deg);
250 | transform: rotate(45deg);
251 | position: absolute;
252 | width: 12px; }
253 |
254 | .height-container {
255 | display: none;
256 | left: -25px;
257 | padding: 0 25px;
258 | position: relative;
259 | width: 100%;
260 | overflow: hidden; }
261 | .height-container .section {
262 | background: #f9f9f9;
263 | border-bottom: 1px solid #e2e2e2;
264 | left: -25px;
265 | position: relative;
266 | width: 100%;
267 | padding-top: 10px;
268 | padding-bottom: 5px; }
269 |
270 | .aside, .language {
271 | padding: 6px 12px;
272 | margin: 12px 0;
273 | border-left: 5px solid #dddddd;
274 | overflow-y: hidden; }
275 | .aside .aside-title, .language .aside-title {
276 | font-size: 9px;
277 | letter-spacing: 2px;
278 | text-transform: uppercase;
279 | padding-bottom: 0;
280 | margin: 0;
281 | color: #aaa;
282 | -webkit-user-select: none; }
283 | .aside p:last-child, .language p:last-child {
284 | margin-bottom: 0; }
285 |
286 | .language {
287 | border-left: 5px solid #cde9f4; }
288 | .language .aside-title {
289 | color: #4b8afb; }
290 |
291 | .aside-warning, .aside-deprecated, .aside-unavailable {
292 | border-left: 5px solid #ff6666; }
293 | .aside-warning .aside-title, .aside-deprecated .aside-title, .aside-unavailable .aside-title {
294 | color: #ff0000; }
295 |
296 | .graybox {
297 | border-collapse: collapse;
298 | width: 100%; }
299 | .graybox p {
300 | margin: 0;
301 | word-break: break-word;
302 | min-width: 50px; }
303 | .graybox td {
304 | border: 1px solid #e2e2e2;
305 | padding: 5px 25px 5px 10px;
306 | vertical-align: middle; }
307 | .graybox tr td:first-of-type {
308 | text-align: right;
309 | padding: 7px;
310 | vertical-align: top;
311 | word-break: normal;
312 | width: 40px; }
313 |
314 | .slightly-smaller {
315 | font-size: 0.9em; }
316 |
317 | #footer {
318 | position: relative;
319 | top: 10px;
320 | bottom: 0px;
321 | margin-left: 25px; }
322 | #footer p {
323 | margin: 0;
324 | color: #aaa;
325 | font-size: 0.8em; }
326 |
327 | html.dash header, html.dash #breadcrumbs, html.dash .sidebar {
328 | display: none; }
329 |
330 | html.dash .main-content {
331 | width: 980px;
332 | margin-left: 0;
333 | border: none;
334 | width: 100%;
335 | top: 0;
336 | padding-bottom: 0; }
337 |
338 | html.dash .height-container {
339 | display: block; }
340 |
341 | html.dash .item .token {
342 | margin-left: 0; }
343 |
344 | html.dash .content-wrapper {
345 | width: auto; }
346 |
347 | html.dash #footer {
348 | position: static; }
349 |
--------------------------------------------------------------------------------
/docs/docsets/SplitView.docset/Contents/Resources/Documents/css/jazzy.css:
--------------------------------------------------------------------------------
1 | html, body, div, span, h1, h3, h4, p, a, code, em, img, ul, li, table, tbody, tr, td {
2 | background: transparent;
3 | border: 0;
4 | margin: 0;
5 | outline: 0;
6 | padding: 0;
7 | vertical-align: baseline; }
8 |
9 | body {
10 | background-color: #f2f2f2;
11 | font-family: Helvetica, freesans, Arial, sans-serif;
12 | font-size: 14px;
13 | -webkit-font-smoothing: subpixel-antialiased;
14 | word-wrap: break-word; }
15 |
16 | h1, h2, h3 {
17 | margin-top: 0.8em;
18 | margin-bottom: 0.3em;
19 | font-weight: 100;
20 | color: black; }
21 |
22 | h1 {
23 | font-size: 2.5em; }
24 |
25 | h2 {
26 | font-size: 2em;
27 | border-bottom: 1px solid #e2e2e2; }
28 |
29 | h4 {
30 | font-size: 13px;
31 | line-height: 1.5;
32 | margin-top: 21px; }
33 |
34 | h5 {
35 | font-size: 1.1em; }
36 |
37 | h6 {
38 | font-size: 1.1em;
39 | color: #777; }
40 |
41 | .section-name {
42 | color: gray;
43 | display: block;
44 | font-family: Helvetica;
45 | font-size: 22px;
46 | font-weight: 100;
47 | margin-bottom: 15px; }
48 |
49 | pre, code {
50 | font: 0.95em Menlo, monospace;
51 | color: #777;
52 | word-wrap: normal; }
53 |
54 | p code, li code {
55 | background-color: #eee;
56 | padding: 2px 4px;
57 | border-radius: 4px; }
58 |
59 | a {
60 | color: #0088cc;
61 | text-decoration: none; }
62 |
63 | ul {
64 | padding-left: 15px; }
65 |
66 | li {
67 | line-height: 1.8em; }
68 |
69 | img {
70 | max-width: 100%; }
71 |
72 | blockquote {
73 | margin-left: 0;
74 | padding: 0 10px;
75 | border-left: 4px solid #ccc; }
76 |
77 | .content-wrapper {
78 | margin: 0 auto;
79 | width: 980px; }
80 |
81 | header {
82 | font-size: 0.85em;
83 | line-height: 26px;
84 | background-color: #414141;
85 | position: fixed;
86 | width: 100%;
87 | z-index: 1; }
88 | header img {
89 | padding-right: 6px;
90 | vertical-align: -4px;
91 | height: 16px; }
92 | header a {
93 | color: #fff; }
94 | header p {
95 | float: left;
96 | color: #999; }
97 | header .header-right {
98 | float: right;
99 | margin-left: 16px; }
100 |
101 | #breadcrumbs {
102 | background-color: #f2f2f2;
103 | height: 27px;
104 | padding-top: 17px;
105 | position: fixed;
106 | width: 100%;
107 | z-index: 1;
108 | margin-top: 26px; }
109 | #breadcrumbs #carat {
110 | height: 10px;
111 | margin: 0 5px; }
112 |
113 | .sidebar {
114 | background-color: #f9f9f9;
115 | border: 1px solid #e2e2e2;
116 | overflow-y: auto;
117 | overflow-x: hidden;
118 | position: fixed;
119 | top: 70px;
120 | bottom: 0;
121 | width: 230px;
122 | word-wrap: normal; }
123 |
124 | .nav-groups {
125 | list-style-type: none;
126 | background: #fff;
127 | padding-left: 0; }
128 |
129 | .nav-group-name {
130 | border-bottom: 1px solid #e2e2e2;
131 | font-size: 1.1em;
132 | font-weight: 100;
133 | padding: 15px 0 15px 20px; }
134 | .nav-group-name > a {
135 | color: #333; }
136 |
137 | .nav-group-tasks {
138 | margin-top: 5px; }
139 |
140 | .nav-group-task {
141 | font-size: 0.9em;
142 | list-style-type: none;
143 | white-space: nowrap; }
144 | .nav-group-task a {
145 | color: #888; }
146 |
147 | .main-content {
148 | background-color: #fff;
149 | border: 1px solid #e2e2e2;
150 | margin-left: 246px;
151 | position: absolute;
152 | overflow: hidden;
153 | padding-bottom: 20px;
154 | top: 70px;
155 | width: 734px; }
156 | .main-content p, .main-content a, .main-content code, .main-content em, .main-content ul, .main-content table, .main-content blockquote {
157 | margin-bottom: 1em; }
158 | .main-content p {
159 | line-height: 1.8em; }
160 | .main-content section .section:first-child {
161 | margin-top: 0;
162 | padding-top: 0; }
163 | .main-content section .task-group-section .task-group:first-of-type {
164 | padding-top: 10px; }
165 | .main-content section .task-group-section .task-group:first-of-type .section-name {
166 | padding-top: 15px; }
167 | .main-content section .heading:before {
168 | content: "";
169 | display: block;
170 | padding-top: 70px;
171 | margin: -70px 0 0; }
172 |
173 | .section {
174 | padding: 0 25px; }
175 |
176 | .highlight {
177 | background-color: #eee;
178 | padding: 10px 12px;
179 | border: 1px solid #e2e2e2;
180 | border-radius: 4px;
181 | overflow-x: auto; }
182 |
183 | .declaration .highlight {
184 | overflow-x: initial;
185 | padding: 0 40px 40px 0;
186 | margin-bottom: -25px;
187 | background-color: transparent;
188 | border: none; }
189 |
190 | .section-name {
191 | margin: 0;
192 | margin-left: 18px; }
193 |
194 | .task-group-section {
195 | padding-left: 6px;
196 | border-top: 1px solid #e2e2e2; }
197 |
198 | .task-group {
199 | padding-top: 0px; }
200 |
201 | .task-name-container a[name]:before {
202 | content: "";
203 | display: block;
204 | padding-top: 70px;
205 | margin: -70px 0 0; }
206 |
207 | .item {
208 | padding-top: 8px;
209 | width: 100%;
210 | list-style-type: none; }
211 | .item a[name]:before {
212 | content: "";
213 | display: block;
214 | padding-top: 70px;
215 | margin: -70px 0 0; }
216 | .item code {
217 | background-color: transparent;
218 | padding: 0; }
219 | .item .token, .item .direct-link {
220 | padding-left: 3px;
221 | margin-left: 15px;
222 | font-size: 11.9px;
223 | transition: all 300ms; }
224 | .item .token-open {
225 | margin-left: 0px; }
226 | .item .discouraged {
227 | text-decoration: line-through; }
228 | .item .declaration-note {
229 | font-size: .85em;
230 | color: gray;
231 | font-style: italic; }
232 |
233 | .pointer-container {
234 | border-bottom: 1px solid #e2e2e2;
235 | left: -23px;
236 | padding-bottom: 13px;
237 | position: relative;
238 | width: 110%; }
239 |
240 | .pointer {
241 | background: #f9f9f9;
242 | border-left: 1px solid #e2e2e2;
243 | border-top: 1px solid #e2e2e2;
244 | height: 12px;
245 | left: 21px;
246 | top: -7px;
247 | -webkit-transform: rotate(45deg);
248 | -moz-transform: rotate(45deg);
249 | -o-transform: rotate(45deg);
250 | transform: rotate(45deg);
251 | position: absolute;
252 | width: 12px; }
253 |
254 | .height-container {
255 | display: none;
256 | left: -25px;
257 | padding: 0 25px;
258 | position: relative;
259 | width: 100%;
260 | overflow: hidden; }
261 | .height-container .section {
262 | background: #f9f9f9;
263 | border-bottom: 1px solid #e2e2e2;
264 | left: -25px;
265 | position: relative;
266 | width: 100%;
267 | padding-top: 10px;
268 | padding-bottom: 5px; }
269 |
270 | .aside, .language {
271 | padding: 6px 12px;
272 | margin: 12px 0;
273 | border-left: 5px solid #dddddd;
274 | overflow-y: hidden; }
275 | .aside .aside-title, .language .aside-title {
276 | font-size: 9px;
277 | letter-spacing: 2px;
278 | text-transform: uppercase;
279 | padding-bottom: 0;
280 | margin: 0;
281 | color: #aaa;
282 | -webkit-user-select: none; }
283 | .aside p:last-child, .language p:last-child {
284 | margin-bottom: 0; }
285 |
286 | .language {
287 | border-left: 5px solid #cde9f4; }
288 | .language .aside-title {
289 | color: #4b8afb; }
290 |
291 | .aside-warning, .aside-deprecated, .aside-unavailable {
292 | border-left: 5px solid #ff6666; }
293 | .aside-warning .aside-title, .aside-deprecated .aside-title, .aside-unavailable .aside-title {
294 | color: #ff0000; }
295 |
296 | .graybox {
297 | border-collapse: collapse;
298 | width: 100%; }
299 | .graybox p {
300 | margin: 0;
301 | word-break: break-word;
302 | min-width: 50px; }
303 | .graybox td {
304 | border: 1px solid #e2e2e2;
305 | padding: 5px 25px 5px 10px;
306 | vertical-align: middle; }
307 | .graybox tr td:first-of-type {
308 | text-align: right;
309 | padding: 7px;
310 | vertical-align: top;
311 | word-break: normal;
312 | width: 40px; }
313 |
314 | .slightly-smaller {
315 | font-size: 0.9em; }
316 |
317 | #footer {
318 | position: relative;
319 | top: 10px;
320 | bottom: 0px;
321 | margin-left: 25px; }
322 | #footer p {
323 | margin: 0;
324 | color: #aaa;
325 | font-size: 0.8em; }
326 |
327 | html.dash header, html.dash #breadcrumbs, html.dash .sidebar {
328 | display: none; }
329 |
330 | html.dash .main-content {
331 | width: 980px;
332 | margin-left: 0;
333 | border: none;
334 | width: 100%;
335 | top: 0;
336 | padding-bottom: 0; }
337 |
338 | html.dash .height-container {
339 | display: block; }
340 |
341 | html.dash .item .token {
342 | margin-left: 0; }
343 |
344 | html.dash .content-wrapper {
345 | width: auto; }
346 |
347 | html.dash #footer {
348 | position: static; }
349 |
--------------------------------------------------------------------------------
/docs/Structs/SplitViewSnapPoint.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | SplitViewSnapPoint Structure Reference
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
22 |
23 |
24 | SplitView Reference
25 |
26 | SplitViewSnapPoint Structure Reference
27 |
28 |
29 |
30 |
61 |
62 |
63 |
64 | SplitViewSnapPoint
65 |
66 |
67 |
public struct SplitViewSnapPoint : Equatable
68 |
69 |
70 |
71 | A structure that contains a snap point that is percentage based and a tolerance for when to snap
72 |
73 |
74 |
75 |
76 |
77 |
78 |
85 |
86 |
87 |
88 |
89 |
90 |
The point at which to snap
91 |
92 |
93 |
94 |
Declaration
95 |
96 |
Swift
97 |
public let percentage : CGFloat
98 |
99 |
100 |
101 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 | tolerance
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
The amount of range to induce a snap effects
121 |
122 |
123 |
124 |
Declaration
125 |
126 |
Swift
127 |
public let tolerance : CGFloat
128 |
129 |
130 |
131 |
134 |
135 |
136 |
137 |
138 |
145 |
146 |
147 |
148 |
149 |
150 |
The global default tolernace
151 |
152 |
153 |
154 |
Declaration
155 |
156 |
Swift
157 |
public static var defaultTolerance : CGFloat
158 |
159 |
160 |
161 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
175 |
176 |
177 |
178 |
179 |
180 |
--------------------------------------------------------------------------------
/docs/docsets/SplitView.docset/Contents/Resources/Documents/Structs/SplitViewSnapPoint.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | SplitViewSnapPoint Structure Reference
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
22 |
23 |
24 | SplitView Reference
25 |
26 | SplitViewSnapPoint Structure Reference
27 |
28 |
29 |
30 |
61 |
62 |
63 |
64 | SplitViewSnapPoint
65 |
66 |
67 |
public struct SplitViewSnapPoint : Equatable
68 |
69 |
70 |
71 | A structure that contains a snap point that is percentage based and a tolerance for when to snap
72 |
73 |
74 |
75 |
76 |
77 |
78 |
85 |
86 |
87 |
88 |
89 |
90 |
The point at which to snap
91 |
92 |
93 |
94 |
Declaration
95 |
96 |
Swift
97 |
public let percentage : CGFloat
98 |
99 |
100 |
101 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 | tolerance
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
The amount of range to induce a snap effects
121 |
122 |
123 |
124 |
Declaration
125 |
126 |
Swift
127 |
public let tolerance : CGFloat
128 |
129 |
130 |
131 |
134 |
135 |
136 |
137 |
138 |
145 |
146 |
147 |
148 |
149 |
150 |
The global default tolernace
151 |
152 |
153 |
154 |
Declaration
155 |
156 |
Swift
157 |
public static var defaultTolerance : CGFloat
158 |
159 |
160 |
161 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
175 |
176 |
177 |
178 |
179 |
180 |
--------------------------------------------------------------------------------
/docs/Enums/SplitViewSnapBehavior.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | SplitViewSnapBehavior Enumeration Reference
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
22 |
23 |
24 | SplitView Reference
25 |
26 | SplitViewSnapBehavior Enumeration Reference
27 |
28 |
29 |
30 |
61 |
62 |
63 |
64 | SplitViewSnapBehavior
65 |
66 |
67 |
public enum SplitViewSnapBehavior : Equatable
68 |
69 |
70 |
71 | The specefied snap behavior
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 | quarter
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
Snap every 25% (0%, 25%, 50%, 75%, 80%) with the default tolerance
91 |
92 |
93 |
94 |
Declaration
95 |
96 |
Swift
97 |
case quarter
98 |
99 |
100 |
101 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 | third
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
Snap every 33% (0%, 33%, 66%, 100%) with a the default tolerance
121 |
122 |
123 |
124 |
Declaration
125 |
126 |
Swift
127 |
case third
128 |
129 |
130 |
131 |
134 |
135 |
136 |
137 |
138 |
145 |
146 |
147 |
148 |
149 |
150 |
Snap at a given percentage and tolerance
151 |
152 |
153 |
154 |
Declaration
155 |
156 |
Swift
157 |
case custom ( percentage : CGFloat , tolerance : CGFloat )
158 |
159 |
160 |
161 |
164 |
165 |
166 |
167 |
168 |
175 |
176 |
177 |
178 |
179 |
180 |
Snap at a given SnapPoint
181 |
182 |
183 |
184 |
Declaration
185 |
190 |
191 |
194 |
195 |
196 |
197 |
198 |
205 |
206 |
207 |
208 |
209 |
210 |
Snap at the given SnapPoints
211 |
212 |
213 |
214 |
Declaration
215 |
220 |
221 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
235 |
236 |
237 |
238 |
239 |
240 |
--------------------------------------------------------------------------------
/docs/docsets/SplitView.docset/Contents/Resources/Documents/Enums/SplitViewSnapBehavior.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | SplitViewSnapBehavior Enumeration Reference
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
22 |
23 |
24 | SplitView Reference
25 |
26 | SplitViewSnapBehavior Enumeration Reference
27 |
28 |
29 |
30 |
61 |
62 |
63 |
64 | SplitViewSnapBehavior
65 |
66 |
67 |
public enum SplitViewSnapBehavior : Equatable
68 |
69 |
70 |
71 | The specefied snap behavior
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 | quarter
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
Snap every 25% (0%, 25%, 50%, 75%, 80%) with the default tolerance
91 |
92 |
93 |
94 |
Declaration
95 |
96 |
Swift
97 |
case quarter
98 |
99 |
100 |
101 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 | third
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
Snap every 33% (0%, 33%, 66%, 100%) with a the default tolerance
121 |
122 |
123 |
124 |
Declaration
125 |
126 |
Swift
127 |
case third
128 |
129 |
130 |
131 |
134 |
135 |
136 |
137 |
138 |
145 |
146 |
147 |
148 |
149 |
150 |
Snap at a given percentage and tolerance
151 |
152 |
153 |
154 |
Declaration
155 |
156 |
Swift
157 |
case custom ( percentage : CGFloat , tolerance : CGFloat )
158 |
159 |
160 |
161 |
164 |
165 |
166 |
167 |
168 |
175 |
176 |
177 |
178 |
179 |
180 |
Snap at a given SnapPoint
181 |
182 |
183 |
184 |
Declaration
185 |
190 |
191 |
194 |
195 |
196 |
197 |
198 |
205 |
206 |
207 |
208 |
209 |
210 |
Snap at the given SnapPoints
211 |
212 |
213 |
214 |
Declaration
215 |
220 |
221 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
235 |
236 |
237 |
238 |
239 |
240 |
--------------------------------------------------------------------------------
/SplitView/SplitView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SplitStackView.swift
3 | // ec3730
4 | //
5 | // Created by Zachary Gorak on 8/20/19.
6 | // Copyright © 2019 Zachary Gorak. All rights reserved.
7 | //
8 | // swiftlint:disable all
9 | import Foundation
10 | import UIKit
11 |
12 |
13 | extension CGFloat
14 | {
15 | /// https://stackoverflow.com/questions/35946499/how-to-truncate-decimals-to-x-places-in-swift
16 | func truncate(places : Int)-> CGFloat
17 | {
18 | return CGFloat(floor(pow(10.0, CGFloat(places)) * self)/pow(10.0, CGFloat(places)))
19 | }
20 | }
21 |
22 | /// Resizable Split View, inspired by [Apple’s Split View](https://support.apple.com/en-us/HT207582#split) for iPadOS and [SplitKit](https://github.com/macteo/SplitKit)
23 | open class SplitView: UIView {
24 | // MARK: - Properties
25 | // MARK: Private and internal
26 | private let stack = UIStackView()
27 |
28 | /// The list of supporting views split by the split view
29 | internal var splitSupportingViews = [SplitSupportingView]()
30 |
31 | // MARK: Public
32 |
33 | /// The list of views split by the split view.
34 | public var splitSubviews: [UIView] {
35 | return self.splitSupportingViews.compactMap({ $0.view })
36 | }
37 | /// The handles between views
38 | public var handles = [SplitViewHandle]()
39 |
40 | /// The minimum width/height ratio for each view
41 | ///
42 | /// The default is 0.0
43 | public var minimumRatio: CGFloat {
44 | didSet {
45 | self.update()
46 | }
47 | }
48 | /// The animation duration when resizing views
49 | ///
50 | /// If you specify a negative value or 0, the changes are made without animating them.
51 | /// The default is 0.0 seconds
52 | public var animationDuration: TimeInterval = 0.0
53 |
54 | /// The precision of the movements. 1 is every 10%, 2 is every 1%, etc
55 | ///
56 | /// The default is 5
57 | public var precision = 5
58 |
59 | /// Snap Behavior
60 | public var snap = [SplitViewSnapBehavior]() {
61 | didSet {
62 | self.update()
63 | }
64 | }
65 |
66 | /// The axis along which the split views are laid out.
67 | ///
68 | /// This property determines the orientation of the split views.
69 | /// Assigning the `NSLayoutConstraint.Axis.vertical` value creates a column of views.
70 | /// Assigning the `NSLayoutConstraint.Axis.horizontal` value creates a row.
71 | /// The default value is `NSLayoutConstraint.Axis.horizontal`.
72 | public var axis: NSLayoutConstraint.Axis {
73 | didSet {
74 | self.update()
75 | }
76 | }
77 |
78 | // MARK: - Initializers
79 |
80 | public override init(frame: CGRect) {
81 | self.minimumRatio = 0.0
82 | self.axis = .horizontal
83 |
84 | super.init(frame: frame)
85 |
86 | stack.translatesAutoresizingMaskIntoConstraints = false
87 | stack.distribution = .fill
88 | stack.spacing = 0.0
89 | stack.alignment = .fill
90 | stack.axis = self.axis
91 |
92 | self.addSubview(stack)
93 | self.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[stack]|", options: .alignAllCenterY, metrics: nil, views: ["stack": stack]))
94 | self.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[stack]|", options: .alignAllCenterY, metrics: nil, views: ["stack": stack]))
95 | }
96 |
97 | public convenience init() {
98 | self.init(frame: .zero)
99 | self.translatesAutoresizingMaskIntoConstraints = false
100 | }
101 |
102 | /// Returns a new split view object that manages the provided views.
103 | /// - parameters:
104 | /// - splitSubviews: The views to be split by the split view.
105 | public convenience init(splitSubviews: [UIView]) {
106 | self.init(frame: .zero)
107 |
108 | for view in splitSubviews {
109 | view.translatesAutoresizingMaskIntoConstraints = false
110 | self.addSplitSubview(view)
111 | }
112 | }
113 |
114 | /// Not implemented
115 | required public init?(coder aDecoder: NSCoder) {
116 | fatalError("init(coder:) has not been implemented")
117 | }
118 |
119 | // MARK: - View Handling
120 |
121 | private func addHandle(_ handle: SplitViewHandle, at: Int) {
122 | handle.axis = self.axis
123 | handle.translatesAutoresizingMaskIntoConstraints = false
124 | handles.append(handle) // XXX: make sure this is in the right order
125 | stack.insertArrangedSubview(handle, at: at)
126 |
127 | let gesture = UIPanGestureRecognizer(target: self, action: #selector(panHandle(_:)))
128 | handle.addGestureRecognizer(gesture)
129 | }
130 |
131 | /// Adds a view to the end of the splitSupportingViews array
132 | @available(swift, introduced: 1.3.0)
133 | open func addSplitSubview(_ view: UIView, desiredRatio: CGFloat = 0.5, minimumRatio: CGFloat = 0.0, withHandle: SplitViewHandle? = nil) {
134 | self.insertSplitSubview(view, at: self.splitSupportingViews.count, desiredRatio: desiredRatio, minimumRatio: minimumRatio, withHandle: withHandle)
135 | }
136 |
137 | /// Adds the provided view to the array of split subviews at the specified index.
138 | open func insertSplitSubview(_ view: UIView, at: Int, desiredRatio: CGFloat = 0.5, minimumRatio: CGFloat = 0.0, withHandle: SplitViewHandle? = nil) {
139 | precondition(desiredRatio >= 0.0, "Ratio must be greater than zero")
140 | precondition(desiredRatio <= 1.0, "Ratio must be less than one")
141 |
142 | var insertAtIndex = at
143 |
144 | view.translatesAutoresizingMaskIntoConstraints = false
145 |
146 | let beforeSize = splitSupportingViews.count
147 |
148 | let organizer = SplitSupportingView(view: view, ratio: desiredRatio, minRatio: minimumRatio, constraint: nil)
149 | splitSupportingViews.insert(organizer, at: at)
150 |
151 | if beforeSize != 0 && at >= beforeSize {
152 | let handle = withHandle ?? SplitViewHandle.useDefault()
153 | insertAtIndex = self.stack.arrangedSubviews.count
154 | self.addHandle(handle, at: insertAtIndex)
155 | insertAtIndex += 1
156 | }
157 |
158 | stack.insertArrangedSubview(organizer.view, at: insertAtIndex)
159 |
160 | if beforeSize != 0 && at < beforeSize {
161 | let handle = withHandle ?? SplitViewHandle.useDefault()
162 | self.addHandle(handle, at: insertAtIndex + 1)
163 | }
164 |
165 | self.assignRatios(newRatio: self.ratio(given: desiredRatio, for: organizer), for: at)
166 | self.setRatios()
167 | }
168 |
169 | /// Removes the provided view from the stack’s array of split subviews.
170 | open func removeSplitSubview(_ view: UIView) {
171 | guard let index = self.splitSubviews.firstIndex(of: view) else {
172 | return
173 | }
174 |
175 | let organizer = splitSupportingViews.remove(at: index)
176 |
177 | stack.removeArrangedSubview(organizer.view)
178 | organizer.view.removeFromSuperview()
179 |
180 | if handles.count > 0 {
181 | let handle = self.handles.remove(at: max(index-1,0))
182 | stack.removeArrangedSubview(handle)
183 | handle.removeFromSuperview()
184 | }
185 |
186 | self.setRatios()
187 | }
188 |
189 | /// Add a view to your `SplitView`
190 | @available(swift, deprecated: 1.3.0, obsoleted: 2.0.0, renamed: "addSplitSubview")
191 | open func addView(_ view: UIView, ratio: CGFloat = 0.5, minRatio: CGFloat = 0.0, withHandle: SplitViewHandle? = nil) {
192 | self.addSplitSubview(view, desiredRatio: ratio, minimumRatio: minRatio, withHandle: withHandle)
193 | }
194 |
195 | private func update() {
196 | self.stack.axis = self.axis
197 |
198 | for handle in self.handles {
199 | handle.axis = self.axis
200 | }
201 |
202 | self.setRatios()
203 |
204 | UIView.animate(withDuration: self.animationDuration) {
205 | self.layoutIfNeeded()
206 | }
207 | }
208 |
209 | private func setRatios() {
210 | let minimumRatioToHoldHandle: CGFloat = 0.01
211 | let totalHandleSize: CGFloat = handles.reduce(0.0) { $0 + $1.size }
212 | let count = splitSupportingViews.filter({ $0.ratio > minimumRatioToHoldHandle }).count
213 |
214 | let handleConstant = totalHandleSize/CGFloat(count)
215 |
216 | let original_constraints = splitSupportingViews.compactMap({$0.constraint})
217 |
218 | for (i, view) in splitSupportingViews.enumerated() {
219 | // using greaterThanOrEqual and lesser ratio to ignore rounding errors
220 | // also subtracting 0.01 to fix rounding errors
221 |
222 | let constant = view.ratio > minimumRatioToHoldHandle ? -handleConstant: 0.0
223 | let ratio = max(view.ratio, 0.0)
224 |
225 | if self.axis == .vertical {
226 | splitSupportingViews[i].constraint = NSLayoutConstraint(item: splitSupportingViews[i].view, attribute: .height, relatedBy: .greaterThanOrEqual, toItem: stack, attribute: .height, multiplier: ratio, constant: constant)
227 | } else {
228 | splitSupportingViews[i].constraint = NSLayoutConstraint(item: splitSupportingViews[i].view, attribute: .width, relatedBy: .greaterThanOrEqual, toItem: stack, attribute: .width, multiplier: ratio, constant: constant)
229 | }
230 | }
231 |
232 | let new_constraints = splitSupportingViews.compactMap({$0.constraint})
233 |
234 | NSLayoutConstraint.deactivate(original_constraints)
235 | NSLayoutConstraint.activate(new_constraints)
236 | }
237 |
238 | private func ratio(given ratio: CGFloat, for organizer: SplitSupportingView)->CGFloat {
239 | if splitSupportingViews.count == 1 {
240 | return 1.0
241 | }
242 |
243 | var minRatio: CGFloat = 0.0
244 | for view in splitSupportingViews {
245 | if view == organizer {
246 | continue
247 | }
248 | minRatio += max(minimumRatio, view.minRatio)
249 | }
250 | if ratio >= 1.0 {
251 | return 1.0 - minRatio
252 | }
253 |
254 | let curMinRatio = max(minimumRatio, organizer.minRatio)
255 |
256 | if ratio <= curMinRatio {
257 | return curMinRatio
258 | }
259 |
260 | if ratio < curMinRatio {
261 | return curMinRatio
262 | }
263 |
264 | if ratio + minRatio >= 1.0 {
265 | return ratio - (ratio + minRatio - 1.0)
266 | }
267 |
268 | return ratio
269 | }
270 |
271 | private func assignRatios(newRatio: CGFloat, for index: Int) {
272 | var ratio = newRatio
273 |
274 | var maxRatio: CGFloat = 1.0
275 |
276 | if splitSupportingViews.count == 1 {
277 | splitSupportingViews[0].ratio = maxRatio
278 | return
279 | }
280 |
281 | for snapBehavior in self.snap {
282 | for point in snapBehavior.snapPoints {
283 | if ratio > (point.percentage - point.tolerance) && ratio < (point.percentage + point.tolerance) {
284 | ratio = point.percentage
285 | }
286 | }
287 | }
288 |
289 | var closestIndex = index == 0 ? 1 : 0
290 |
291 | if splitSupportingViews.count > 2 {
292 | // the handle controls this view and the view above
293 | closestIndex = index + 1
294 | if closestIndex >= splitSupportingViews.count {
295 | closestIndex = index - 1
296 | }
297 |
298 | // XXX: use reducers
299 | var ratioTotal: CGFloat = 0.0
300 | for (i, support) in splitSupportingViews.enumerated() {
301 | if i == index || i == closestIndex {
302 | continue
303 | }
304 | ratioTotal += support.ratio
305 | }
306 | maxRatio = maxRatio - ratioTotal
307 | }
308 |
309 | var secondRatio = (maxRatio - ratio)
310 |
311 | let secondSmallestRatio = max(self.minimumRatio, splitSupportingViews[closestIndex].minRatio)
312 | if secondRatio < secondSmallestRatio {
313 | secondRatio = secondSmallestRatio
314 | ratio = maxRatio - secondRatio
315 | }
316 |
317 | ratio = ratio.truncate(places: self.precision)
318 | secondRatio = secondRatio.truncate(places: self.precision)
319 |
320 | splitSupportingViews[index].ratio = ratio
321 | splitSupportingViews[closestIndex].ratio = secondRatio
322 | }
323 |
324 | @objc func panHandle(_ sender: UIPanGestureRecognizer) {
325 | guard let handle = sender.view as? SplitViewHandle else {
326 | return
327 | }
328 |
329 | guard let handleIndex = handles.firstIndex(of: handle) else {
330 | return
331 | }
332 |
333 | let organizer = splitSupportingViews[handleIndex]
334 |
335 | switch sender.state {
336 | case .began:
337 | handle.initialOrigin = handle.frame.origin
338 | handle.isBeingUsed = true
339 | break
340 | case .changed:
341 | var newPoint = handle.initialOrigin!.y + sender.translation(in: handle).y
342 | var curPoint = handle.frame.origin.y
343 | if self.axis == .horizontal {
344 | newPoint = handle.initialOrigin!.x + sender.translation(in: handle).x
345 | curPoint = handle.frame.origin.x
346 | }
347 |
348 | var ratio: CGFloat = 0.0
349 | if curPoint != 0 {
350 | if organizer.ratio <= 0 {
351 | ratio = max(0.0, (newPoint/curPoint) - 1.0)
352 | } else {
353 | ratio = organizer.ratio * (newPoint/curPoint)
354 | }
355 | } else {
356 | ratio = newPoint/stack.frame.height
357 | if self.axis == .horizontal {
358 | ratio = newPoint/stack.frame.width
359 | }
360 |
361 | ratio = max(ratio, self.minimumRatio)
362 | }
363 |
364 | splitSupportingViews[handleIndex].ratio = self.ratio(given: max(ratio, splitSupportingViews[handleIndex].minRatio), for: splitSupportingViews[handleIndex])
365 | self.assignRatios(newRatio: splitSupportingViews[handleIndex].ratio, for: handleIndex)
366 |
367 | self.setRatios()
368 | UIView.animate(withDuration: self.animationDuration) {
369 | self.layoutIfNeeded()
370 | }
371 |
372 | break
373 | case .ended:
374 | handle.isBeingUsed = false
375 | handle.initialOrigin = nil
376 | default:
377 | break
378 | }
379 | }
380 | }
381 |
382 | // MARK: - Ratio
383 | extension SplitView {
384 | /// The current ratio for all the split subviews
385 | public var ratios: [CGFloat] {
386 | return self.splitSupportingViews.compactMap({ $0.ratio })
387 | }
388 |
389 | /// The minimum ratios for all the split subviews
390 | public var minimumRatios: [CGFloat] {
391 | return self.splitSupportingViews.compactMap({ $0.minRatio })
392 | }
393 |
394 | /// Set the minimum ratio for a specific view
395 | public func setMinimumRatio(_ ratio: CGFloat, for view: UIView) {
396 | precondition(minimumRatio >= 0.0, "Ratio must be 0.0 or greater")
397 | precondition(minimumRatio < 1.0, "Ratio must be less than 1.0")
398 |
399 | guard let index = self.splitSubviews.firstIndex(of: view) else {
400 | return
401 | }
402 |
403 | self.splitSupportingViews[index].minRatio = ratio
404 | }
405 | }
406 |
407 | // MARK: - Stack
408 |
409 | extension SplitView {
410 | /// A Boolean value that determines whether the split view lays out its split views relative to
411 | /// its layout margins.
412 | ///
413 | /// If `true`, the stack view will layout its split views relative to its layout margins.
414 | /// If `false`, it lays out the split views relative to its bounds. The default is `false`.
415 | public var isLayoutMarginsRelativeArrangement: Bool {
416 | set {
417 | stack.isLayoutMarginsRelativeArrangement = newValue
418 | }
419 | get {
420 | return stack.isLayoutMarginsRelativeArrangement
421 | }
422 | }
423 | }
424 |
--------------------------------------------------------------------------------
/docs/Classes/SplitViewHandle.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | SplitViewHandle Class Reference
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
22 |
23 |
24 | SplitView Reference
25 |
26 | SplitViewHandle Class Reference
27 |
28 |
29 |
30 |
61 |
62 |
63 |
64 | SplitViewHandle
65 |
66 |
67 |
open class SplitViewHandle : UIView
68 |
69 |
70 |
71 | The seperator/handle that is between each view in a SplitView
72 |
73 |
74 |
75 |
76 |
83 |
84 |
85 |
86 |
87 |
88 |
89 | grabber
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
The center view used for grabbing
98 |
99 |
100 |
101 |
Declaration
102 |
103 |
Swift
104 |
public var grabber : UIView
105 |
106 |
107 |
108 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 | size
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
The width/height of the view
128 |
129 |
130 |
131 |
Declaration
132 |
133 |
Swift
134 |
public var size : CGFloat
135 |
136 |
137 |
138 |
141 |
142 |
143 |
144 |
145 |
152 |
153 |
154 |
155 |
156 |
157 |
Used for position tracking
158 |
159 |
160 |
161 |
Declaration
162 |
163 |
Swift
164 |
public var initialOrigin : CGPoint ?
165 |
166 |
167 |
168 |
171 |
172 |
173 |
174 |
175 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
Declaration
191 |
192 |
Swift
193 |
public var isBeingUsed : Bool
194 |
195 |
196 |
197 |
198 |
Return Value
199 |
If being dragged returns true, false otherwise
200 |
201 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 | axis
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
This property determines the orientation of the arranged views.
221 | Assigning the NSLayoutConstraint.Axis.vertical value creates a column of views.
222 | Assigning the NSLayoutConstraint.Axis.horizontal value creates a row.
223 |
224 |
225 |
226 |
Declaration
227 |
228 |
Swift
229 |
public var axis : NSLayoutConstraint . Axis { get set }
230 |
231 |
232 |
233 |
236 |
237 |
238 |
239 |
240 |
247 |
248 |
249 |
250 |
251 |
252 |
The current constraints on the handle
253 | This is used when changing axises and should only be modified
254 | when overriding
255 |
256 |
257 |
258 |
Declaration
259 |
260 |
Swift
261 |
public var handleConstraints : [ NSLayoutConstraint ]
262 |
263 |
264 |
265 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
281 |
282 |
283 |
290 |
291 |
292 |
293 |
294 |
295 |
Not implemented
296 |
297 |
298 |
299 |
Declaration
300 |
301 |
Swift
302 |
required public init ?( coder aDecoder : NSCoder )
303 |
304 |
305 |
306 |
309 |
310 |
311 |
312 |
313 |
314 |
315 |
322 |
323 |
324 |
331 |
332 |
333 |
334 |
335 |
336 |
Override this if you are cusomizing your seperator/handle
337 | Use handleConstraints as necessary
338 |
339 |
340 |
341 |
Declaration
342 |
343 |
Swift
344 |
open func layoutConstraints ()
345 |
346 |
347 |
348 |
351 |
352 |
353 |
354 |
355 |
356 |
357 |
364 |
365 |
366 |
373 |
374 |
375 |
376 |
377 |
378 |
The default handle.
379 |
380 |
381 |
382 |
Declaration
383 |
384 |
Swift
385 |
public class func useDefault () -> SplitViewHandle
386 |
387 |
388 |
389 |
392 |
393 |
394 |
395 |
396 |
397 |
398 |
399 |
403 |
404 |
405 |
406 |
407 |
408 |
--------------------------------------------------------------------------------