├── Example
├── WBSegmentControl-Example
│ ├── Assets.xcassets
│ │ ├── Contents.json
│ │ ├── 9.imageset
│ │ │ ├── 1461434779_82.png
│ │ │ ├── 1461434779_82@2x.png
│ │ │ ├── 1461434779_82@3x.png
│ │ │ └── Contents.json
│ │ ├── 8.imageset
│ │ │ ├── 1461434737_calendar.png
│ │ │ ├── 1461434737_calendar@2x.png
│ │ │ ├── 1461434737_calendar@3x.png
│ │ │ └── Contents.json
│ │ ├── 7.imageset
│ │ │ ├── 1461433662_snow_flake_3.png
│ │ │ ├── 1461433662_snow_flake_3@2x.png
│ │ │ ├── 1461433662_snow_flake_3@3x.png
│ │ │ └── Contents.json
│ │ ├── 3.imageset
│ │ │ ├── 1454576053_icon-114-lock.png
│ │ │ ├── 1454576053_icon-114-lock@2x.png
│ │ │ ├── 1454576053_icon-114-lock@3x.png
│ │ │ └── Contents.json
│ │ ├── 1.imageset
│ │ │ ├── 1454576025_icon-141-box-filled.png
│ │ │ ├── 1454576025_icon-141-box-filled@2x.png
│ │ │ ├── 1454576025_icon-141-box-filled@3x.png
│ │ │ └── Contents.json
│ │ ├── 6.imageset
│ │ │ ├── 1454576094_icon-115-lock-open.png
│ │ │ ├── 1454576094_icon-115-lock-open@2x.png
│ │ │ ├── 1454576094_icon-115-lock-open@3x.png
│ │ │ └── Contents.json
│ │ ├── 2.imageset
│ │ │ ├── 1454576043_icon-40-clipboard-list.png
│ │ │ ├── 1454576043_icon-40-clipboard-list@2x.png
│ │ │ ├── 1454576043_icon-40-clipboard-list@3x.png
│ │ │ └── Contents.json
│ │ ├── 4.imageset
│ │ │ ├── 1454576060_icon-144-box-bookmark.png
│ │ │ ├── 1454576060_icon-144-box-bookmark@2x.png
│ │ │ ├── 1454576060_icon-144-box-bookmark@3x.png
│ │ │ └── Contents.json
│ │ ├── 5.imageset
│ │ │ ├── 1454576071_icon-92-inbox-download.png
│ │ │ ├── 1454576071_icon-92-inbox-download@2x.png
│ │ │ ├── 1454576071_icon-92-inbox-download@3x.png
│ │ │ └── Contents.json
│ │ └── AppIcon.appiconset
│ │ │ └── Contents.json
│ ├── Info.plist
│ ├── Base.lproj
│ │ └── LaunchScreen.storyboard
│ ├── AppDelegate.swift
│ ├── ViewController1.swift
│ └── ViewController2.swift
├── WBSegmentControl-Example.xcodeproj
│ ├── project.xcworkspace
│ │ └── contents.xcworkspacedata
│ └── project.pbxproj
├── WBSegmentControl-ExampleTests
│ ├── Info.plist
│ └── WBSegmentControl_ExampleTests.swift
└── WBSegmentControl-ExampleUITests
│ ├── Info.plist
│ └── WBSegmentControl_ExampleUITests.swift
├── Framework
├── ScreenShot
│ ├── WBSegmentControl.gif
│ ├── Simulator Screen Shot 27 Nov 2016, 8.10.29 PM.png
│ └── Simulator Screen Shot 27 Nov 2016, 8.10.29 PM_result1.jpg
├── WBSegmentControl.xcodeproj
│ ├── project.xcworkspace
│ │ └── contents.xcworkspacedata
│ ├── xcshareddata
│ │ └── xcschemes
│ │ │ └── WBSegmentControl.xcscheme
│ └── project.pbxproj
├── WBSegmentControl
│ ├── WBSegmentControl.h
│ ├── Info.plist
│ ├── WBSegments.swift
│ ├── WBSegmentControl.swift
│ └── WBSegmentControl.swift.orig
├── WBSegmentControlTests
│ ├── Info.plist
│ └── WBSegmentControlTests.swift
└── WBSegmentControl.podspec
├── WBSegmentControl.xcworkspace
└── contents.xcworkspacedata
├── LICENSE
├── .gitignore
└── README.md
/Example/WBSegmentControl-Example/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/Framework/ScreenShot/WBSegmentControl.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiongxiong/WBSegmentControl/HEAD/Framework/ScreenShot/WBSegmentControl.gif
--------------------------------------------------------------------------------
/Framework/ScreenShot/Simulator Screen Shot 27 Nov 2016, 8.10.29 PM.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiongxiong/WBSegmentControl/HEAD/Framework/ScreenShot/Simulator Screen Shot 27 Nov 2016, 8.10.29 PM.png
--------------------------------------------------------------------------------
/Example/WBSegmentControl-Example/Assets.xcassets/9.imageset/1461434779_82.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiongxiong/WBSegmentControl/HEAD/Example/WBSegmentControl-Example/Assets.xcassets/9.imageset/1461434779_82.png
--------------------------------------------------------------------------------
/Example/WBSegmentControl-Example/Assets.xcassets/9.imageset/1461434779_82@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiongxiong/WBSegmentControl/HEAD/Example/WBSegmentControl-Example/Assets.xcassets/9.imageset/1461434779_82@2x.png
--------------------------------------------------------------------------------
/Example/WBSegmentControl-Example/Assets.xcassets/9.imageset/1461434779_82@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiongxiong/WBSegmentControl/HEAD/Example/WBSegmentControl-Example/Assets.xcassets/9.imageset/1461434779_82@3x.png
--------------------------------------------------------------------------------
/Framework/ScreenShot/Simulator Screen Shot 27 Nov 2016, 8.10.29 PM_result1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiongxiong/WBSegmentControl/HEAD/Framework/ScreenShot/Simulator Screen Shot 27 Nov 2016, 8.10.29 PM_result1.jpg
--------------------------------------------------------------------------------
/Example/WBSegmentControl-Example/Assets.xcassets/8.imageset/1461434737_calendar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiongxiong/WBSegmentControl/HEAD/Example/WBSegmentControl-Example/Assets.xcassets/8.imageset/1461434737_calendar.png
--------------------------------------------------------------------------------
/Example/WBSegmentControl-Example/Assets.xcassets/7.imageset/1461433662_snow_flake_3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiongxiong/WBSegmentControl/HEAD/Example/WBSegmentControl-Example/Assets.xcassets/7.imageset/1461433662_snow_flake_3.png
--------------------------------------------------------------------------------
/Example/WBSegmentControl-Example/Assets.xcassets/8.imageset/1461434737_calendar@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiongxiong/WBSegmentControl/HEAD/Example/WBSegmentControl-Example/Assets.xcassets/8.imageset/1461434737_calendar@2x.png
--------------------------------------------------------------------------------
/Example/WBSegmentControl-Example/Assets.xcassets/8.imageset/1461434737_calendar@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiongxiong/WBSegmentControl/HEAD/Example/WBSegmentControl-Example/Assets.xcassets/8.imageset/1461434737_calendar@3x.png
--------------------------------------------------------------------------------
/Example/WBSegmentControl-Example/Assets.xcassets/3.imageset/1454576053_icon-114-lock.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiongxiong/WBSegmentControl/HEAD/Example/WBSegmentControl-Example/Assets.xcassets/3.imageset/1454576053_icon-114-lock.png
--------------------------------------------------------------------------------
/Example/WBSegmentControl-Example/Assets.xcassets/7.imageset/1461433662_snow_flake_3@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiongxiong/WBSegmentControl/HEAD/Example/WBSegmentControl-Example/Assets.xcassets/7.imageset/1461433662_snow_flake_3@2x.png
--------------------------------------------------------------------------------
/Example/WBSegmentControl-Example/Assets.xcassets/7.imageset/1461433662_snow_flake_3@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiongxiong/WBSegmentControl/HEAD/Example/WBSegmentControl-Example/Assets.xcassets/7.imageset/1461433662_snow_flake_3@3x.png
--------------------------------------------------------------------------------
/Example/WBSegmentControl-Example/Assets.xcassets/3.imageset/1454576053_icon-114-lock@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiongxiong/WBSegmentControl/HEAD/Example/WBSegmentControl-Example/Assets.xcassets/3.imageset/1454576053_icon-114-lock@2x.png
--------------------------------------------------------------------------------
/Example/WBSegmentControl-Example/Assets.xcassets/3.imageset/1454576053_icon-114-lock@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiongxiong/WBSegmentControl/HEAD/Example/WBSegmentControl-Example/Assets.xcassets/3.imageset/1454576053_icon-114-lock@3x.png
--------------------------------------------------------------------------------
/Example/WBSegmentControl-Example/Assets.xcassets/1.imageset/1454576025_icon-141-box-filled.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiongxiong/WBSegmentControl/HEAD/Example/WBSegmentControl-Example/Assets.xcassets/1.imageset/1454576025_icon-141-box-filled.png
--------------------------------------------------------------------------------
/Example/WBSegmentControl-Example/Assets.xcassets/6.imageset/1454576094_icon-115-lock-open.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiongxiong/WBSegmentControl/HEAD/Example/WBSegmentControl-Example/Assets.xcassets/6.imageset/1454576094_icon-115-lock-open.png
--------------------------------------------------------------------------------
/Example/WBSegmentControl-Example/Assets.xcassets/1.imageset/1454576025_icon-141-box-filled@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiongxiong/WBSegmentControl/HEAD/Example/WBSegmentControl-Example/Assets.xcassets/1.imageset/1454576025_icon-141-box-filled@2x.png
--------------------------------------------------------------------------------
/Example/WBSegmentControl-Example/Assets.xcassets/1.imageset/1454576025_icon-141-box-filled@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiongxiong/WBSegmentControl/HEAD/Example/WBSegmentControl-Example/Assets.xcassets/1.imageset/1454576025_icon-141-box-filled@3x.png
--------------------------------------------------------------------------------
/Example/WBSegmentControl-Example/Assets.xcassets/2.imageset/1454576043_icon-40-clipboard-list.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiongxiong/WBSegmentControl/HEAD/Example/WBSegmentControl-Example/Assets.xcassets/2.imageset/1454576043_icon-40-clipboard-list.png
--------------------------------------------------------------------------------
/Example/WBSegmentControl-Example/Assets.xcassets/4.imageset/1454576060_icon-144-box-bookmark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiongxiong/WBSegmentControl/HEAD/Example/WBSegmentControl-Example/Assets.xcassets/4.imageset/1454576060_icon-144-box-bookmark.png
--------------------------------------------------------------------------------
/Example/WBSegmentControl-Example/Assets.xcassets/5.imageset/1454576071_icon-92-inbox-download.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiongxiong/WBSegmentControl/HEAD/Example/WBSegmentControl-Example/Assets.xcassets/5.imageset/1454576071_icon-92-inbox-download.png
--------------------------------------------------------------------------------
/Example/WBSegmentControl-Example/Assets.xcassets/6.imageset/1454576094_icon-115-lock-open@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiongxiong/WBSegmentControl/HEAD/Example/WBSegmentControl-Example/Assets.xcassets/6.imageset/1454576094_icon-115-lock-open@2x.png
--------------------------------------------------------------------------------
/Example/WBSegmentControl-Example/Assets.xcassets/6.imageset/1454576094_icon-115-lock-open@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiongxiong/WBSegmentControl/HEAD/Example/WBSegmentControl-Example/Assets.xcassets/6.imageset/1454576094_icon-115-lock-open@3x.png
--------------------------------------------------------------------------------
/Example/WBSegmentControl-Example/Assets.xcassets/2.imageset/1454576043_icon-40-clipboard-list@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiongxiong/WBSegmentControl/HEAD/Example/WBSegmentControl-Example/Assets.xcassets/2.imageset/1454576043_icon-40-clipboard-list@2x.png
--------------------------------------------------------------------------------
/Example/WBSegmentControl-Example/Assets.xcassets/2.imageset/1454576043_icon-40-clipboard-list@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiongxiong/WBSegmentControl/HEAD/Example/WBSegmentControl-Example/Assets.xcassets/2.imageset/1454576043_icon-40-clipboard-list@3x.png
--------------------------------------------------------------------------------
/Example/WBSegmentControl-Example/Assets.xcassets/4.imageset/1454576060_icon-144-box-bookmark@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiongxiong/WBSegmentControl/HEAD/Example/WBSegmentControl-Example/Assets.xcassets/4.imageset/1454576060_icon-144-box-bookmark@2x.png
--------------------------------------------------------------------------------
/Example/WBSegmentControl-Example/Assets.xcassets/4.imageset/1454576060_icon-144-box-bookmark@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiongxiong/WBSegmentControl/HEAD/Example/WBSegmentControl-Example/Assets.xcassets/4.imageset/1454576060_icon-144-box-bookmark@3x.png
--------------------------------------------------------------------------------
/Example/WBSegmentControl-Example/Assets.xcassets/5.imageset/1454576071_icon-92-inbox-download@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiongxiong/WBSegmentControl/HEAD/Example/WBSegmentControl-Example/Assets.xcassets/5.imageset/1454576071_icon-92-inbox-download@2x.png
--------------------------------------------------------------------------------
/Example/WBSegmentControl-Example/Assets.xcassets/5.imageset/1454576071_icon-92-inbox-download@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiongxiong/WBSegmentControl/HEAD/Example/WBSegmentControl-Example/Assets.xcassets/5.imageset/1454576071_icon-92-inbox-download@3x.png
--------------------------------------------------------------------------------
/Framework/WBSegmentControl.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Example/WBSegmentControl-Example.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/WBSegmentControl.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/Example/WBSegmentControl-Example/Assets.xcassets/9.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "1461434779_82.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "1461434779_82@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "1461434779_82@3x.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/Example/WBSegmentControl-Example/Assets.xcassets/8.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "1461434737_calendar.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "1461434737_calendar@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "1461434737_calendar@3x.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/Example/WBSegmentControl-Example/Assets.xcassets/3.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "1454576053_icon-114-lock.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "1454576053_icon-114-lock@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "1454576053_icon-114-lock@3x.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/Example/WBSegmentControl-Example/Assets.xcassets/7.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "1461433662_snow_flake_3.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "1461433662_snow_flake_3@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "1461433662_snow_flake_3@3x.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/Example/WBSegmentControl-Example/Assets.xcassets/6.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "1454576094_icon-115-lock-open.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "1454576094_icon-115-lock-open@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "1454576094_icon-115-lock-open@3x.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/Example/WBSegmentControl-Example/Assets.xcassets/1.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "1454576025_icon-141-box-filled.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "1454576025_icon-141-box-filled@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "1454576025_icon-141-box-filled@3x.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/Example/WBSegmentControl-Example/Assets.xcassets/4.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "1454576060_icon-144-box-bookmark.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "1454576060_icon-144-box-bookmark@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "1454576060_icon-144-box-bookmark@3x.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/Example/WBSegmentControl-Example/Assets.xcassets/2.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "1454576043_icon-40-clipboard-list.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "1454576043_icon-40-clipboard-list@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "1454576043_icon-40-clipboard-list@3x.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/Example/WBSegmentControl-Example/Assets.xcassets/5.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "1454576071_icon-92-inbox-download.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "1454576071_icon-92-inbox-download@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "1454576071_icon-92-inbox-download@3x.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/Framework/WBSegmentControl/WBSegmentControl.h:
--------------------------------------------------------------------------------
1 | //
2 | // WBSegmentControl.h
3 | // WBSegmentControl
4 | //
5 | // Created by 王继荣 on 9/19/16.
6 | // Copyright © 2016 snowflyer. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | //! Project version number for WBSegmentControl.
12 | FOUNDATION_EXPORT double WBSegmentControlVersionNumber;
13 |
14 | //! Project version string for WBSegmentControl.
15 | FOUNDATION_EXPORT const unsigned char WBSegmentControlVersionString[];
16 |
17 | // In this header, you should import all the public headers of your framework using statements like #import
18 |
19 |
20 |
--------------------------------------------------------------------------------
/Framework/WBSegmentControlTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/Example/WBSegmentControl-ExampleTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/Example/WBSegmentControl-ExampleUITests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/Framework/WBSegmentControl/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 0.2.0
19 | CFBundleVersion
20 | $(CURRENT_PROJECT_VERSION)
21 | NSPrincipalClass
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/Framework/WBSegmentControl/WBSegments.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Segment.swift
3 | // WBSegmentControl
4 | //
5 | // Created by 王继荣 on 7/28/16.
6 | // Copyright © 2016 CocoaPods. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | public class TextSegment: NSObject, WBSegmentContentProtocol {
12 |
13 | public var text: String!
14 | public var otherAttr: String!
15 |
16 | public var type: WBSegmentType {
17 | return WBSegmentType.text(text)
18 | }
19 |
20 | public init(text: String, otherAttr: String = "") {
21 | super.init()
22 |
23 | self.text = text
24 | self.otherAttr = otherAttr
25 | }
26 | }
27 |
28 | public class IconSegment: NSObject, WBSegmentContentProtocol {
29 |
30 | public var icon: UIImage!
31 |
32 | public var type: WBSegmentType {
33 | return WBSegmentType.icon(icon)
34 | }
35 |
36 | public init(icon: UIImage) {
37 | super.init()
38 |
39 | self.icon = icon
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/Example/WBSegmentControl-Example/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 | "info" : {
45 | "version" : 1,
46 | "author" : "xcode"
47 | }
48 | }
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2016 xiongxiong
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is
8 | furnished to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in
11 | all copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | THE SOFTWARE.
20 |
--------------------------------------------------------------------------------
/Framework/WBSegmentControlTests/WBSegmentControlTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // WBSegmentControlTests.swift
3 | // WBSegmentControlTests
4 | //
5 | // Created by 王继荣 on 9/19/16.
6 | // Copyright © 2016 snowflyer. All rights reserved.
7 | //
8 |
9 | import XCTest
10 | @testable import WBSegmentControl
11 |
12 | class WBSegmentControlTests: XCTestCase {
13 |
14 | override func setUp() {
15 | super.setUp()
16 | // Put setup code here. This method is called before the invocation of each test method in the class.
17 | }
18 |
19 | override func tearDown() {
20 | // Put teardown code here. This method is called after the invocation of each test method in the class.
21 | super.tearDown()
22 | }
23 |
24 | func testExample() {
25 | // This is an example of a functional test case.
26 | // Use XCTAssert and related functions to verify your tests produce the correct results.
27 | }
28 |
29 | func testPerformanceExample() {
30 | // This is an example of a performance test case.
31 | self.measure {
32 | // Put the code you want to measure the time of here.
33 | }
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/Example/WBSegmentControl-ExampleTests/WBSegmentControl_ExampleTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // WBSegmentControl_ExampleTests.swift
3 | // WBSegmentControl-ExampleTests
4 | //
5 | // Created by 王继荣 on 9/19/16.
6 | // Copyright © 2016 snowflyer. All rights reserved.
7 | //
8 |
9 | import XCTest
10 | @testable import WBSegmentControl_Example
11 |
12 | class WBSegmentControl_ExampleTests: XCTestCase {
13 |
14 | override func setUp() {
15 | super.setUp()
16 | // Put setup code here. This method is called before the invocation of each test method in the class.
17 | }
18 |
19 | override func tearDown() {
20 | // Put teardown code here. This method is called after the invocation of each test method in the class.
21 | super.tearDown()
22 | }
23 |
24 | func testExample() {
25 | // This is an example of a functional test case.
26 | // Use XCTAssert and related functions to verify your tests produce the correct results.
27 | }
28 |
29 | func testPerformanceExample() {
30 | // This is an example of a performance test case.
31 | self.measure {
32 | // Put the code you want to measure the time of here.
33 | }
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/Example/WBSegmentControl-ExampleUITests/WBSegmentControl_ExampleUITests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // WBSegmentControl_ExampleUITests.swift
3 | // WBSegmentControl-ExampleUITests
4 | //
5 | // Created by 王继荣 on 9/19/16.
6 | // Copyright © 2016 snowflyer. All rights reserved.
7 | //
8 |
9 | import XCTest
10 |
11 | class WBSegmentControl_ExampleUITests: XCTestCase {
12 |
13 | override func setUp() {
14 | super.setUp()
15 |
16 | // Put setup code here. This method is called before the invocation of each test method in the class.
17 |
18 | // In UI tests it is usually best to stop immediately when a failure occurs.
19 | continueAfterFailure = false
20 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method.
21 | XCUIApplication().launch()
22 |
23 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.
24 | }
25 |
26 | override func tearDown() {
27 | // Put teardown code here. This method is called after the invocation of each test method in the class.
28 | super.tearDown()
29 | }
30 |
31 | func testExample() {
32 | // Use recording to get started writing UI tests.
33 | // Use XCTAssert and related functions to verify your tests produce the correct results.
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/Example/WBSegmentControl-Example/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 | LSRequiresIPhoneOS
22 |
23 | UILaunchStoryboardName
24 | LaunchScreen
25 | UIRequiredDeviceCapabilities
26 |
27 | armv7
28 |
29 | UISupportedInterfaceOrientations
30 |
31 | UIInterfaceOrientationPortrait
32 | UIInterfaceOrientationLandscapeLeft
33 | UIInterfaceOrientationLandscapeRight
34 |
35 | UISupportedInterfaceOrientations~ipad
36 |
37 | UIInterfaceOrientationPortrait
38 | UIInterfaceOrientationPortraitUpsideDown
39 | UIInterfaceOrientationLandscapeLeft
40 | UIInterfaceOrientationLandscapeRight
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | #
3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
4 |
5 | ## Build generated
6 | build/
7 | DerivedData/
8 |
9 | ## Various settings
10 | *.pbxuser
11 | !default.pbxuser
12 | *.mode1v3
13 | !default.mode1v3
14 | *.mode2v3
15 | !default.mode2v3
16 | *.perspectivev3
17 | !default.perspectivev3
18 | xcuserdata/
19 |
20 | ## Other
21 | *.moved-aside
22 | *.xcuserstate
23 |
24 | ## Obj-C/Swift specific
25 | *.hmap
26 | *.ipa
27 | *.dSYM.zip
28 | *.dSYM
29 |
30 | ## Playgrounds
31 | timeline.xctimeline
32 | playground.xcworkspace
33 |
34 | # Swift Package Manager
35 | #
36 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
37 | # Packages/
38 | .build/
39 |
40 | # CocoaPods
41 | #
42 | # We recommend against adding the Pods directory to your .gitignore. However
43 | # you should judge for yourself, the pros and cons are mentioned at:
44 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
45 | #
46 | # Pods/
47 |
48 | # Carthage
49 | #
50 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
51 | # Carthage/Checkouts
52 |
53 | Carthage/Build
54 |
55 | # fastlane
56 | #
57 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
58 | # screenshots whenever they are needed.
59 | # For more information about the recommended setup visit:
60 | # https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md
61 |
62 | fastlane/report.xml
63 | fastlane/Preview.html
64 | fastlane/screenshots
65 | fastlane/test_output
66 |
--------------------------------------------------------------------------------
/Framework/WBSegmentControl.podspec:
--------------------------------------------------------------------------------
1 | #
2 | # Be sure to run `pod lib lint WBSegmentControl.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 http://guides.cocoapods.org/syntax/podspec.html
7 | #
8 |
9 | Pod::Spec.new do |s|
10 | s.name = "WBSegmentControl"
11 | s.version = "0.2.2"
12 | s.summary = "An easy to use, customizable segment control."
13 |
14 | # This description is used to generate tags and improve search results.
15 | # * Think: What does it do? Why did you write it? What is the focus?
16 | # * Try to keep it short, snappy and to the point.
17 | # * Write the description between the DESC delimiters below.
18 | # * Finally, don't worry about the indent, CocoaPods strips it!
19 |
20 | s.description = <<-DESC
21 | WBSegmentedControl is an easy to use, customizable segment control, has several effects, can be used to show labels or tabs.
22 | DESC
23 |
24 | s.homepage = "https://github.com/xiongxiong/WBSegmentControl"
25 | # s.screenshots = "www.example.com/screenshots_1", "www.example.com/screenshots_2"
26 | s.license = 'MIT'
27 | s.author = { "xiongxiong" => "ximengwuheng@163.com" }
28 | s.source = { :git => "https://github.com/xiongxiong/WBSegmentControl.git", :tag => s.version.to_s }
29 | # s.social_media_url = 'https://twitter.com/'
30 |
31 | s.ios.deployment_target = '8.0'
32 |
33 | s.source_files = 'Framework/WBSegmentControl/**/*'
34 | # s.resource_bundles = {
35 | # 'WBSegmentControl' => ['WBSegmentControl/Assets/*.png']
36 | # }
37 |
38 | s.public_header_files = 'Framework/WBSegmentControl/*.h'
39 | s.frameworks = 'UIKit'
40 | # s.dependency 'AFNetworking', '~> 2.3'
41 | end
42 |
--------------------------------------------------------------------------------
/Example/WBSegmentControl-Example/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/Example/WBSegmentControl-Example/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // WBSegmentControl
4 | //
5 | // Created by xiongxiong on 04/24/2016.
6 | // Copyright (c) 2016 xiongxiong. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | @UIApplicationMain
12 | class AppDelegate: UIResponder, UIApplicationDelegate {
13 |
14 | var window: UIWindow?
15 |
16 |
17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
18 | // Override point for customization after application launch.
19 | window = UIWindow()
20 |
21 | let vcRoot = UITabBarController()
22 | let vc1 = ViewController1()
23 | vc1.tabBarItem.title = "item 1"
24 | let vc2 = ViewController2()
25 | vc2.tabBarItem.title = "item 2"
26 | vcRoot.setViewControllers([vc1, vc2], animated: false)
27 |
28 | window?.rootViewController = vcRoot
29 | window?.backgroundColor = UIColor.white
30 | window?.makeKeyAndVisible()
31 |
32 | return true
33 | }
34 |
35 | func applicationWillResignActive(_ application: UIApplication) {
36 | // 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.
37 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
38 | }
39 |
40 | func applicationDidEnterBackground(_ application: UIApplication) {
41 | // 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.
42 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
43 | }
44 |
45 | func applicationWillEnterForeground(_ application: UIApplication) {
46 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
47 | }
48 |
49 | func applicationDidBecomeActive(_ application: UIApplication) {
50 | // 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.
51 | }
52 |
53 | func applicationWillTerminate(_ application: UIApplication) {
54 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
55 | }
56 |
57 |
58 | }
59 |
60 |
--------------------------------------------------------------------------------
/Framework/WBSegmentControl.xcodeproj/xcshareddata/xcschemes/WBSegmentControl.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
33 |
39 |
40 |
41 |
42 |
43 |
49 |
50 |
51 |
52 |
53 |
54 |
64 |
65 |
71 |
72 |
73 |
74 |
75 |
76 |
82 |
83 |
89 |
90 |
91 |
92 |
94 |
95 |
98 |
99 |
100 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # WBSegmentControl
2 |
3 | [](https://developer.apple.com/swift/)
4 | [](https://travis-ci.org/xiongxiong/WBSegmentControl)
5 | [](http://cocoapods.org/pods/WBSegmentControl)
6 | [](http://cocoapods.org/pods/WBSegmentControl)
7 | [](https://github.com/Carthage/Carthage)
8 | [](http://cocoapods.org/pods/WBSegmentControl)
9 |
10 | An easy to use, customizable segment control, can be used to show tabs.
11 |
12 | 
13 |
14 | ## Contents
15 | - [Features](#features)
16 | - [Requirements](#requirements)
17 | - [Example](#example)
18 | - [Installation](#installation)
19 | - [Protocols](#protocols)
20 | - [Usage](#usage)
21 | - [Properties](#properties)
22 | - [Author](#author)
23 | - [License](#license)
24 |
25 | ## Features
26 | - [x] Flexible style - rainbow | cover | strip | arrow | arrowStrip
27 | - [x] Action delegate support
28 | - [x] Customized segment
29 |
30 | ## Requirements
31 |
32 | - iOS 8.0+ / Mac OS X 10.11+ / tvOS 9.0+
33 | - Xcode 8.0+
34 | - Swift 3.0+
35 |
36 | ## Installation
37 |
38 | ### CocoaPods
39 |
40 | [CocoaPods](http://cocoapods.org) is a dependency manager for Cocoa projects. You can install it with the following command:
41 |
42 | ```bash
43 | $ gem install cocoapods
44 | ```
45 | To integrate WBSegmentControl into your Xcode project using CocoaPods, specify it in your `Podfile`:
46 |
47 | ```ruby
48 | source 'https://github.com/CocoaPods/Specs.git'
49 | platform :ios, '8.0'
50 | use_frameworks!
51 |
52 | target '' do
53 | pod 'WBSegmentControl', '~> 0.2.0'
54 | end
55 | ```
56 |
57 | Then, run the following command:
58 |
59 | ```bash
60 | $ pod install
61 | ```
62 |
63 | ### Carthage
64 |
65 | [Carthage](https://github.com/Carthage/Carthage) is a decentralized dependency manager that builds your dependencies and provides you with binary frameworks.
66 |
67 | You can install Carthage with [Homebrew](http://brew.sh/) using the following command:
68 |
69 | ```bash
70 | $ brew update
71 | $ brew install carthage
72 | ```
73 |
74 | To integrate WBSegmentControl into your Xcode project using Carthage, specify it in your `Cartfile`:
75 |
76 | ```ogdl
77 | github "xiongxiong/WBSegmentControl" ~> 0.2.0
78 | ```
79 |
80 | Run `carthage update` to build the framework and drag the built `WBSegmentControl.framework` into your Xcode project.
81 |
82 | ### Manually
83 |
84 | If you prefer not to use either of the aforementioned dependency managers, you can integrate WBSegmentControl into your project manually.
85 |
86 | ## Example
87 |
88 | Open the example project, build and run.
89 |
90 | ## Protocols
91 |
92 | ### WBSegmentControlDelegate
93 |
94 | ```swift
95 | public protocol WBSegmentControlDelegate {
96 | func segmentControl(segmentControl: WBSegmentControl, selectIndex newIndex: Int, oldIndex: Int)
97 | }
98 | ```
99 |
100 | ### WBSegmentProtocol
101 |
102 | ```swift
103 | public protocol WBSegmentContentProtocol {
104 | var type: WBSegmentType { get }
105 | }
106 | ```
107 |
108 | ## Usage
109 |
110 | ### Implement WBSegmentContentProtocol
111 |
112 | ```swift
113 | class TextSegment: NSObject, WBSegmentContentProtocol {
114 |
115 | var text: String!
116 |
117 | var type: WBSegmentType {
118 | return WBSegmentType.Text(text)
119 | }
120 |
121 | init(text: String) {
122 | super.init()
123 |
124 | self.text = text
125 | }
126 | }
127 | ```
128 |
129 | IconSegment & TextSegment are already implemented, you can use it straightforwardly without implementing WBSegmentContentProtocol, or you can choose to implement WBSegmentContentProtocol to use your own segment type.
130 |
131 | ### Initialize segmentControl
132 |
133 | ```swift
134 | let segmentControl = WBSegmentControl() // initialize
135 | view.addSubview(segmentControl)
136 | ...
137 | segmentControl.segments = [
138 | TextSegment(text: "News China"),
139 | TextSegment(text: "Breaking News"),
140 | ] // set segments
141 | segmentControl.style = .Rainbow // set style
142 | segmentControl.selectedIndex = 0 // set selected index
143 | ```
144 |
145 | ### Implement WBSegmentControlDelegate
146 |
147 | ```swift
148 | extension MyViewController: WBSegmentControlDelegate {
149 | func segmentControl(segmentControl: WBSegmentControl, selectIndex newIndex: Int, oldIndex: Int) {
150 |
151 | }
152 | }
153 | ```
154 |
155 | ### Get selected segment
156 |
157 | ```swift
158 | let selectedIndex = segmentControl.selectedIndex
159 | let selectedSegment: TextSegment? = segmentControl.selectedSegment as? TextSegment
160 | ```
161 |
162 | ## Properties
163 |
164 | ### Settings - Common
165 |
166 | * indicatorStyle: IndicatorStyle = rainbow | cover | strip | arrow | arrowStrip
167 | * nonScrollDistributionStyle: NonScrollDistributionStyle = center | left | right | average
168 | * enableSeparator: Bool
169 | * separatorColor: UIColor
170 | * separatorWidth: CGFloat
171 | * separatorEdgeInsets: UIEdgeInsets
172 | * enableSlideway: Bool
173 | * slidewayHeight: CGFloat
174 | * slidewayColor: UIColor
175 | * enableAnimation: Bool
176 | * animationDuration: NSTimeInterval
177 | * contentBackgroundColor: UIColor
178 | * segmentMinWidth: CGFloat
179 | * segmentEdgeInsets: UIEdgeInsets
180 | * segmentTextBold: Bool
181 | * segmentTextFontSize: CGFloat
182 | * segmentTextForegroundColor: UIColor
183 | * segmentTextForegroundColorSelected: UIColor
184 |
185 | ### Settings - indicatorStyle == .Rainbow
186 |
187 | * rainbow_colors: [UIColor]
188 | * rainbow_height: CGFloat
189 | * rainbow_roundCornerRadius: CGFloat
190 | * rainbow_location: RainbowLocation = up | down
191 | * rainbow_outsideColor: UIColor
192 |
193 | ### Settings - indicatorStyle == .Cover
194 |
195 | * cover_range: CoverRange = segment | content
196 | * cover_opacity: Float
197 | * cover_color: UIColor
198 |
199 | ### Settings - indicatorStyle == .Strip
200 |
201 | * strip_range: StripRange = segment | content
202 | * strip_location: StripLocation = up | down
203 | * strip_color: UIColor
204 | * strip_height: CGFloat
205 |
206 | ### Settings - indicatorStyle == .Rainbow
207 | public var rainbow_colors: [UIColor] = []
208 | public var rainbow_height: CGFloat = 3
209 | public var rainbow_roundCornerRadius: CGFloat = 4
210 | public var rainbow_location: RainbowLocation = .Down
211 | public var rainbow_outsideColor: UIColor = UIColor.grayColor()
212 |
213 | ### Settings - indicatorStyle == .Arrow
214 |
215 | * arrow_size: CGSize
216 | * arrow_location: ArrowLocation = up | down
217 | * arrow_color: UIColor
218 |
219 | ### Settings - indicatorStyle == .ArrowStrip
220 |
221 | * arrowStrip_location: ArrowStripLocation = up | down
222 | * arrowStrip_color: UIColor
223 | * arrowStrip_arrowSize: CGSize
224 | * arrowStrip_stripHeight: CGFloat
225 | * arrowStrip_stripRange: ArrowStripRange = segment | content
226 |
227 | ## Author
228 |
229 | xiongxiong, ximengwuheng@163.com
230 |
231 | ## License
232 |
233 | WBSegmentControl is available under the MIT license. See the LICENSE file for more info.
234 |
--------------------------------------------------------------------------------
/Example/WBSegmentControl-Example/ViewController1.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController1.swift
3 | // WBSegmentControl
4 | //
5 | // Created by 王继荣 on 7/5/16.
6 | // Copyright © 2016 CocoaPods. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import WBSegmentControl
11 |
12 | class ViewController1: UIViewController {
13 |
14 | var segmentControl: WBSegmentControl!
15 | var viewPages = UIView()
16 | var viewLabel = UILabel()
17 | var pagesController: UIPageViewController!
18 | var pages: [UIViewController] = []
19 |
20 | override func loadView() {
21 | super.loadView()
22 |
23 | initSegmentControl()
24 | initPagesController()
25 |
26 | view.addSubview(segmentControl)
27 | view.addSubview(viewPages)
28 | viewPages.addSubview(pagesController.view)
29 | view.addSubview(viewLabel)
30 |
31 | segmentControl.translatesAutoresizingMaskIntoConstraints = false
32 | view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[segmentControl]|", options: .alignAllLeading, metrics: nil, views: ["segmentControl": segmentControl]))
33 | view.addConstraint(NSLayoutConstraint(item: segmentControl, attribute: .top, relatedBy: .equal, toItem: self.topLayoutGuide, attribute: .bottom, multiplier: 1, constant: 0))
34 | view.addConstraint(NSLayoutConstraint(item: segmentControl, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .height, multiplier: 0, constant: 40))
35 |
36 | viewPages.gestureRecognizers = pagesController.gestureRecognizers
37 | viewPages.translatesAutoresizingMaskIntoConstraints = false
38 | view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[viewPages]|", options: .alignAllLeading, metrics: nil, views: ["viewPages": viewPages]))
39 | view.addConstraint(NSLayoutConstraint(item: viewPages, attribute: .top, relatedBy: .equal, toItem: segmentControl, attribute: .bottom, multiplier: 1, constant: 0))
40 | view.addConstraint(NSLayoutConstraint(item: viewPages, attribute: .bottom, relatedBy: .equal, toItem: viewLabel, attribute: .top, multiplier: 1, constant: 0))
41 |
42 | pagesController.view.translatesAutoresizingMaskIntoConstraints = false
43 | viewPages.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[pagesView]|", options: .alignAllLeading, metrics: nil, views: ["pagesView": pagesController.view]))
44 | viewPages.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[pagesView]|", options: .alignAllFirstBaseline, metrics: nil, views: ["pagesView": pagesController.view]))
45 |
46 | viewLabel.translatesAutoresizingMaskIntoConstraints = false
47 | view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[viewLabel]|", options: .alignAllLeading, metrics: nil, views: ["viewLabel": viewLabel]))
48 | view.addConstraint(NSLayoutConstraint(item: viewLabel, attribute: .top, relatedBy: .equal, toItem: self.bottomLayoutGuide, attribute: .top, multiplier: 1, constant: 0))
49 | view.addConstraint(NSLayoutConstraint(item: viewLabel, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .height, multiplier: 0, constant: 40))
50 |
51 | viewLabel.textAlignment = .center
52 | viewLabel.textColor = UIColor.black
53 | viewLabel.backgroundColor = UIColor.white
54 | }
55 |
56 | override func viewDidLoad() {
57 | super.viewDidLoad()
58 |
59 | segmentControl.selectedIndex = 0
60 | }
61 |
62 | override func didReceiveMemoryWarning() {
63 | super.didReceiveMemoryWarning()
64 | // Dispose of any resources that can be recreated.
65 | }
66 |
67 | func initSegmentControl() {
68 | segmentControl = WBSegmentControl()
69 | segmentControl.segments = [
70 | TextSegment(text: "News China", otherAttr: "News China"),
71 | TextSegment(text: "Breaking News", otherAttr: "Breaking News"),
72 | TextSegment(text: "World", otherAttr: "World"),
73 | TextSegment(text: "Science", otherAttr: "Science"),
74 | TextSegment(text: "Entertainment & Arts", otherAttr: "Entertainment & Arts"),
75 | TextSegment(text: "Finance", otherAttr: "Finance"),
76 | TextSegment(text: "Video", otherAttr: "Video"),
77 | TextSegment(text: "Radio", otherAttr: "Radio"),
78 | TextSegment(text: "Education", otherAttr: "Education"),
79 | TextSegment(text: "Sports", otherAttr: "Sports"),
80 | TextSegment(text: "Weather", otherAttr: "Weather"),
81 | TextSegment(text: "Headlines", otherAttr: "Headlines"),
82 | ]
83 | segmentControl.style = .rainbow
84 | segmentControl.segmentTextBold = false
85 | segmentControl.rainbow_colors = [
86 | UIColor(red:0.91, green:0.18, blue:0.24, alpha:1.00),
87 | UIColor(red:1.00, green:0.71, blue:0.26, alpha:1.00),
88 | UIColor(red:0.47, green:0.78, blue:0.97, alpha:1.00)
89 | ]
90 | segmentControl.delegate = self
91 | }
92 |
93 | func initPagesController() {
94 | pagesController = UIPageViewController(transitionStyle: .scroll, navigationOrientation: .horizontal, options: nil)
95 | pagesController.dataSource = self
96 | pagesController.delegate = self
97 |
98 | segmentControl.segments.enumerated().forEach { (index, _) in
99 | let vc = UIViewController()
100 | vc.view.backgroundColor = [
101 | UIColor(red:0.91, green:0.18, blue:0.24, alpha:1.00),
102 | UIColor(red:1.00, green:0.71, blue:0.26, alpha:1.00),
103 | UIColor(red:0.47, green:0.78, blue:0.97, alpha:1.00)
104 | ][index % 3]
105 | pages.append(vc)
106 | }
107 | }
108 |
109 | }
110 |
111 | extension ViewController1: WBSegmentControlDelegate {
112 | func segmentControl(_ segmentControl: WBSegmentControl, selectIndex newIndex: Int, oldIndex: Int) {
113 | let targetPages = [pages[newIndex]]
114 | let direction = ((newIndex > oldIndex) ? UIPageViewControllerNavigationDirection.forward : UIPageViewControllerNavigationDirection.reverse)
115 | pagesController.setViewControllers(targetPages, direction: direction, animated: true, completion: nil)
116 |
117 | if let selectedSegment = segmentControl.selectedSegment as? TextSegment {
118 | viewLabel.text = selectedSegment.otherAttr
119 | }
120 | }
121 | }
122 |
123 | extension ViewController1: UIPageViewControllerDataSource {
124 | func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
125 | let index = pages.index(of: viewController)!
126 | return index > 0 ? pages[index - 1] : nil
127 | }
128 |
129 | func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
130 | let index = pages.index(of: viewController)!
131 | return index < pages.count - 1 ? pages[index + 1] : nil
132 | }
133 |
134 | func presentationCount(for pageViewController: UIPageViewController) -> Int {
135 | return pages.count
136 | }
137 |
138 | func presentationIndex(for pageViewController: UIPageViewController) -> Int {
139 | return 0
140 | }
141 | }
142 |
143 | extension ViewController1: UIPageViewControllerDelegate {
144 | func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
145 | if completed == false {
146 | guard let targetPage = previousViewControllers.first else {
147 | return
148 | }
149 | guard let targetIndex = pages.index(of: targetPage) else {
150 | return
151 | }
152 | segmentControl.selectedIndex = targetIndex
153 | pageViewController.setViewControllers(previousViewControllers, direction: .reverse, animated: true, completion: nil)
154 | }
155 | }
156 |
157 | func pageViewController(_ pageViewController: UIPageViewController, willTransitionTo pendingViewControllers: [UIViewController]) {
158 | guard let targetPage = pendingViewControllers.first else {
159 | return
160 | }
161 | guard let targetIndex = pages.index(of: targetPage) else {
162 | return
163 | }
164 | segmentControl.selectedIndex = targetIndex
165 | }
166 | }
167 |
--------------------------------------------------------------------------------
/Example/WBSegmentControl-Example/ViewController2.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.swift
3 | // WBSegmentControl
4 | //
5 | // Created by xiongxiong on 04/24/2016.
6 | // Copyright (c) 2016 xiongxiong. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import WBSegmentControl
11 |
12 | class ViewController2: UIViewController {
13 |
14 | let segmentCtrl_A = WBSegmentControl()
15 | let segmentCtrl_B = WBSegmentControl()
16 | let segmentCtrl_C = WBSegmentControl()
17 | let segmentCtrl_D = WBSegmentControl()
18 | let segmentCtrl_E = WBSegmentControl()
19 | let segmentCtrl_F = WBSegmentControl()
20 | let segmentCtrl_G = WBSegmentControl()
21 |
22 | override func loadView() {
23 | super.loadView()
24 |
25 | view.addSubview(segmentCtrl_A)
26 | segmentCtrl_A.translatesAutoresizingMaskIntoConstraints = false
27 | view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[segmentControl]|", options: .alignAllLeading, metrics: nil, views: ["segmentControl": segmentCtrl_A]))
28 | view.addConstraint(NSLayoutConstraint(item: segmentCtrl_A, attribute: .top, relatedBy: .equal, toItem: self.topLayoutGuide, attribute: .bottom, multiplier: 1, constant: 8))
29 | view.addConstraint(NSLayoutConstraint(item: segmentCtrl_A, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .height, multiplier: 0, constant: 40))
30 | segmentCtrl_A.segments = [
31 | TextSegment(text: "News China"),
32 | TextSegment(text: "Breaking News"),
33 | TextSegment(text: "World"),
34 | TextSegment(text: "Science"),
35 | TextSegment(text: "Entertainment & Arts"),
36 | TextSegment(text: "Finance"),
37 | TextSegment(text: "Video"),
38 | TextSegment(text: "Radio"),
39 | TextSegment(text: "Education"),
40 | TextSegment(text: "Sports"),
41 | TextSegment(text: "Weather"),
42 | TextSegment(text: "Headlines"),
43 | ]
44 | segmentCtrl_A.style = .rainbow
45 | segmentCtrl_A.rainbow_colors = [
46 | UIColor(red:0.91, green:0.18, blue:0.24, alpha:1.00),
47 | UIColor(red:1.00, green:0.71, blue:0.26, alpha:1.00),
48 | UIColor(red:0.47, green:0.78, blue:0.97, alpha:1.00)
49 | ]
50 |
51 | self.view.addSubview(segmentCtrl_B)
52 | segmentCtrl_B.translatesAutoresizingMaskIntoConstraints = false
53 | view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[segmentControl]|", options: .alignAllLeading, metrics: nil, views: ["segmentControl": segmentCtrl_B]))
54 | view.addConstraint(NSLayoutConstraint(item: segmentCtrl_B, attribute: .top, relatedBy: .equal, toItem: segmentCtrl_A, attribute: .bottom, multiplier: 1, constant: 15))
55 | view.addConstraint(NSLayoutConstraint(item: segmentCtrl_B, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .height, multiplier: 0, constant: 40))
56 | segmentCtrl_B.segments = [
57 | IconSegment(icon: UIImage(named: "1")!),
58 | IconSegment(icon: UIImage(named: "2")!),
59 | IconSegment(icon: UIImage(named: "3")!),
60 | IconSegment(icon: UIImage(named: "4")!),
61 | IconSegment(icon: UIImage(named: "5")!),
62 | IconSegment(icon: UIImage(named: "6")!),
63 | IconSegment(icon: UIImage(named: "7")!),
64 | IconSegment(icon: UIImage(named: "8")!),
65 | IconSegment(icon: UIImage(named: "9")!),
66 | ]
67 | segmentCtrl_B.style = .strip
68 | segmentCtrl_B.rainbow_colors = [
69 | UIColor(red:0.91, green:0.18, blue:0.24, alpha:1.00),
70 | UIColor(red:1.00, green:0.71, blue:0.26, alpha:1.00),
71 | UIColor(red:0.47, green:0.78, blue:0.97, alpha:1.00)
72 | ]
73 | segmentCtrl_B.enableSlideway = false
74 | segmentCtrl_B.strip_range = .segment
75 |
76 | self.view.addSubview(segmentCtrl_C)
77 | segmentCtrl_C.translatesAutoresizingMaskIntoConstraints = false
78 | view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[segmentControl]|", options: .alignAllLeading, metrics: nil, views: ["segmentControl": segmentCtrl_C]))
79 | view.addConstraint(NSLayoutConstraint(item: segmentCtrl_C, attribute: .top, relatedBy: .equal, toItem: segmentCtrl_B, attribute: .bottom, multiplier: 1, constant: 15))
80 | view.addConstraint(NSLayoutConstraint(item: segmentCtrl_C, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .height, multiplier: 0, constant: 40))
81 | segmentCtrl_C.segments = [
82 | TextSegment(text: "News China"),
83 | TextSegment(text: "Breaking News"),
84 | TextSegment(text: "World"),
85 | TextSegment(text: "Science"),
86 | TextSegment(text: "Entertainment & Arts"),
87 | TextSegment(text: "Finance"),
88 | TextSegment(text: "Video"),
89 | TextSegment(text: "Radio"),
90 | TextSegment(text: "Education"),
91 | TextSegment(text: "Sports"),
92 | TextSegment(text: "Weather"),
93 | TextSegment(text: "Headlines"),
94 | ]
95 | segmentCtrl_C.style = .arrow
96 | segmentCtrl_C.enableSlideway = true
97 | segmentCtrl_C.enableSeparator = true
98 |
99 | self.view.addSubview(segmentCtrl_D)
100 | segmentCtrl_D.translatesAutoresizingMaskIntoConstraints = false
101 | view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[segmentControl]|", options: .alignAllLeading, metrics: nil, views: ["segmentControl": segmentCtrl_D]))
102 | view.addConstraint(NSLayoutConstraint(item: segmentCtrl_D, attribute: .top, relatedBy: .equal, toItem: segmentCtrl_C, attribute: .bottom, multiplier: 1, constant: 15))
103 | view.addConstraint(NSLayoutConstraint(item: segmentCtrl_D, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .height, multiplier: 0, constant: 40))
104 | segmentCtrl_D.segments = [
105 | TextSegment(text: "News China"),
106 | TextSegment(text: "Breaking News"),
107 | TextSegment(text: "World"),
108 | TextSegment(text: "Science"),
109 | TextSegment(text: "Entertainment & Arts"),
110 | TextSegment(text: "Finance"),
111 | TextSegment(text: "Video"),
112 | TextSegment(text: "Radio"),
113 | TextSegment(text: "Education"),
114 | TextSegment(text: "Sports"),
115 | TextSegment(text: "Weather"),
116 | TextSegment(text: "Headlines"),
117 | ]
118 | segmentCtrl_D.style = .arrowStrip
119 |
120 | self.view.addSubview(segmentCtrl_E)
121 | segmentCtrl_E.translatesAutoresizingMaskIntoConstraints = false
122 | view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[segmentControl]|", options: .alignAllLeading, metrics: nil, views: ["segmentControl": segmentCtrl_E]))
123 | view.addConstraint(NSLayoutConstraint(item: segmentCtrl_E, attribute: .top, relatedBy: .equal, toItem: segmentCtrl_D, attribute: .bottom, multiplier: 1, constant: 15))
124 | view.addConstraint(NSLayoutConstraint(item: segmentCtrl_E, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .height, multiplier: 0, constant: 40))
125 | segmentCtrl_E.segments = [
126 | TextSegment(text: "News China"),
127 | TextSegment(text: "Breaking News"),
128 | TextSegment(text: "World"),
129 | TextSegment(text: "Science"),
130 | TextSegment(text: "Entertainment & Arts"),
131 | TextSegment(text: "Finance"),
132 | TextSegment(text: "Video"),
133 | TextSegment(text: "Radio"),
134 | TextSegment(text: "Education"),
135 | TextSegment(text: "Sports"),
136 | TextSegment(text: "Weather"),
137 | TextSegment(text: "Headlines"),
138 | ]
139 | segmentCtrl_E.style = .arrowStrip
140 | segmentCtrl_E.enableSlideway = false
141 |
142 | self.view.addSubview(segmentCtrl_F)
143 | segmentCtrl_F.translatesAutoresizingMaskIntoConstraints = false
144 | view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[segmentControl]|", options: .alignAllLeading, metrics: nil, views: ["segmentControl": segmentCtrl_F]))
145 | view.addConstraint(NSLayoutConstraint(item: segmentCtrl_F, attribute: .top, relatedBy: .equal, toItem: segmentCtrl_E, attribute: .bottom, multiplier: 1, constant: 15))
146 | view.addConstraint(NSLayoutConstraint(item: segmentCtrl_F, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .height, multiplier: 0, constant: 40))
147 | segmentCtrl_F.segments = [
148 | TextSegment(text: "News China"),
149 | TextSegment(text: "Breaking News"),
150 | TextSegment(text: "World"),
151 | TextSegment(text: "Science"),
152 | TextSegment(text: "Entertainment & Arts"),
153 | TextSegment(text: "Finance"),
154 | TextSegment(text: "Video"),
155 | TextSegment(text: "Radio"),
156 | TextSegment(text: "Education"),
157 | TextSegment(text: "Sports"),
158 | TextSegment(text: "Weather"),
159 | TextSegment(text: "Headlines"),
160 | ]
161 | segmentCtrl_F.style = .cover
162 | segmentCtrl_F.backgroundColor = UIColor.cyan
163 |
164 | self.view.addSubview(segmentCtrl_G)
165 | segmentCtrl_G.translatesAutoresizingMaskIntoConstraints = false
166 | view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[segmentControl]|", options: .alignAllLeading, metrics: nil, views: ["segmentControl": segmentCtrl_G]))
167 | view.addConstraint(NSLayoutConstraint(item: segmentCtrl_G, attribute: .top, relatedBy: .equal, toItem: segmentCtrl_F, attribute: .bottom, multiplier: 1, constant: 15))
168 | view.addConstraint(NSLayoutConstraint(item: segmentCtrl_G, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .height, multiplier: 0, constant: 40))
169 | segmentCtrl_G.segments = [
170 | TextSegment(text: "News China"),
171 | TextSegment(text: "World"),
172 | TextSegment(text: "Science"),
173 | ]
174 | segmentCtrl_G.style = .strip
175 | segmentCtrl_G.nonScrollDistributionStyle = .center
176 | }
177 |
178 | override func viewDidLoad() {
179 | super.viewDidLoad()
180 |
181 | segmentCtrl_A.selectedIndex = 0
182 | segmentCtrl_B.selectedIndex = 0
183 | segmentCtrl_C.selectedIndex = 0
184 | segmentCtrl_D.selectedIndex = 0
185 | segmentCtrl_E.selectedIndex = 0
186 | segmentCtrl_F.selectedIndex = 0
187 | segmentCtrl_G.selectedIndex = 0
188 | }
189 | }
190 |
191 |
--------------------------------------------------------------------------------
/Framework/WBSegmentControl.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 42DDC7A71D8F6F25005409EE /* WBSegmentControl.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 42DDC79D1D8F6F25005409EE /* WBSegmentControl.framework */; };
11 | 42DDC7AC1D8F6F25005409EE /* WBSegmentControlTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42DDC7AB1D8F6F25005409EE /* WBSegmentControlTests.swift */; };
12 | 42DDC7AE1D8F6F25005409EE /* WBSegmentControl.h in Headers */ = {isa = PBXBuildFile; fileRef = 42DDC7A01D8F6F25005409EE /* WBSegmentControl.h */; settings = {ATTRIBUTES = (Public, ); }; };
13 | 42DDC7B91D8F6FB3005409EE /* WBSegmentControl.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42DDC7B81D8F6FB3005409EE /* WBSegmentControl.swift */; };
14 | 42DDC7FA1D8F77F7005409EE /* WBSegments.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42DDC7F91D8F77F7005409EE /* WBSegments.swift */; };
15 | /* End PBXBuildFile section */
16 |
17 | /* Begin PBXContainerItemProxy section */
18 | 42DDC7A81D8F6F25005409EE /* PBXContainerItemProxy */ = {
19 | isa = PBXContainerItemProxy;
20 | containerPortal = 42DDC7941D8F6F25005409EE /* Project object */;
21 | proxyType = 1;
22 | remoteGlobalIDString = 42DDC79C1D8F6F25005409EE;
23 | remoteInfo = WBSegmentControl;
24 | };
25 | /* End PBXContainerItemProxy section */
26 |
27 | /* Begin PBXFileReference section */
28 | 42DDC79D1D8F6F25005409EE /* WBSegmentControl.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = WBSegmentControl.framework; sourceTree = BUILT_PRODUCTS_DIR; };
29 | 42DDC7A01D8F6F25005409EE /* WBSegmentControl.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WBSegmentControl.h; sourceTree = ""; };
30 | 42DDC7A11D8F6F25005409EE /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
31 | 42DDC7A61D8F6F25005409EE /* WBSegmentControlTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = WBSegmentControlTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
32 | 42DDC7AB1D8F6F25005409EE /* WBSegmentControlTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WBSegmentControlTests.swift; sourceTree = ""; };
33 | 42DDC7AD1D8F6F25005409EE /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
34 | 42DDC7B81D8F6FB3005409EE /* WBSegmentControl.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WBSegmentControl.swift; sourceTree = ""; };
35 | 42DDC7F91D8F77F7005409EE /* WBSegments.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WBSegments.swift; sourceTree = ""; };
36 | /* End PBXFileReference section */
37 |
38 | /* Begin PBXFrameworksBuildPhase section */
39 | 42DDC7991D8F6F25005409EE /* Frameworks */ = {
40 | isa = PBXFrameworksBuildPhase;
41 | buildActionMask = 2147483647;
42 | files = (
43 | );
44 | runOnlyForDeploymentPostprocessing = 0;
45 | };
46 | 42DDC7A31D8F6F25005409EE /* Frameworks */ = {
47 | isa = PBXFrameworksBuildPhase;
48 | buildActionMask = 2147483647;
49 | files = (
50 | 42DDC7A71D8F6F25005409EE /* WBSegmentControl.framework in Frameworks */,
51 | );
52 | runOnlyForDeploymentPostprocessing = 0;
53 | };
54 | /* End PBXFrameworksBuildPhase section */
55 |
56 | /* Begin PBXGroup section */
57 | 42DDC7931D8F6F25005409EE = {
58 | isa = PBXGroup;
59 | children = (
60 | 42DDC79F1D8F6F25005409EE /* WBSegmentControl */,
61 | 42DDC7AA1D8F6F25005409EE /* WBSegmentControlTests */,
62 | 42DDC79E1D8F6F25005409EE /* Products */,
63 | );
64 | sourceTree = "";
65 | };
66 | 42DDC79E1D8F6F25005409EE /* Products */ = {
67 | isa = PBXGroup;
68 | children = (
69 | 42DDC79D1D8F6F25005409EE /* WBSegmentControl.framework */,
70 | 42DDC7A61D8F6F25005409EE /* WBSegmentControlTests.xctest */,
71 | );
72 | name = Products;
73 | sourceTree = "";
74 | };
75 | 42DDC79F1D8F6F25005409EE /* WBSegmentControl */ = {
76 | isa = PBXGroup;
77 | children = (
78 | 42DDC7B81D8F6FB3005409EE /* WBSegmentControl.swift */,
79 | 42DDC7F91D8F77F7005409EE /* WBSegments.swift */,
80 | 42DDC7B71D8F6F3B005409EE /* Support Files */,
81 | );
82 | path = WBSegmentControl;
83 | sourceTree = "";
84 | };
85 | 42DDC7AA1D8F6F25005409EE /* WBSegmentControlTests */ = {
86 | isa = PBXGroup;
87 | children = (
88 | 42DDC7AB1D8F6F25005409EE /* WBSegmentControlTests.swift */,
89 | 42DDC7AD1D8F6F25005409EE /* Info.plist */,
90 | );
91 | path = WBSegmentControlTests;
92 | sourceTree = "";
93 | };
94 | 42DDC7B71D8F6F3B005409EE /* Support Files */ = {
95 | isa = PBXGroup;
96 | children = (
97 | 42DDC7A01D8F6F25005409EE /* WBSegmentControl.h */,
98 | 42DDC7A11D8F6F25005409EE /* Info.plist */,
99 | );
100 | name = "Support Files";
101 | sourceTree = "";
102 | };
103 | /* End PBXGroup section */
104 |
105 | /* Begin PBXHeadersBuildPhase section */
106 | 42DDC79A1D8F6F25005409EE /* Headers */ = {
107 | isa = PBXHeadersBuildPhase;
108 | buildActionMask = 2147483647;
109 | files = (
110 | 42DDC7AE1D8F6F25005409EE /* WBSegmentControl.h in Headers */,
111 | );
112 | runOnlyForDeploymentPostprocessing = 0;
113 | };
114 | /* End PBXHeadersBuildPhase section */
115 |
116 | /* Begin PBXNativeTarget section */
117 | 42DDC79C1D8F6F25005409EE /* WBSegmentControl */ = {
118 | isa = PBXNativeTarget;
119 | buildConfigurationList = 42DDC7B11D8F6F25005409EE /* Build configuration list for PBXNativeTarget "WBSegmentControl" */;
120 | buildPhases = (
121 | 42DDC7981D8F6F25005409EE /* Sources */,
122 | 42DDC7991D8F6F25005409EE /* Frameworks */,
123 | 42DDC79A1D8F6F25005409EE /* Headers */,
124 | 42DDC79B1D8F6F25005409EE /* Resources */,
125 | );
126 | buildRules = (
127 | );
128 | dependencies = (
129 | );
130 | name = WBSegmentControl;
131 | productName = WBSegmentControl;
132 | productReference = 42DDC79D1D8F6F25005409EE /* WBSegmentControl.framework */;
133 | productType = "com.apple.product-type.framework";
134 | };
135 | 42DDC7A51D8F6F25005409EE /* WBSegmentControlTests */ = {
136 | isa = PBXNativeTarget;
137 | buildConfigurationList = 42DDC7B41D8F6F25005409EE /* Build configuration list for PBXNativeTarget "WBSegmentControlTests" */;
138 | buildPhases = (
139 | 42DDC7A21D8F6F25005409EE /* Sources */,
140 | 42DDC7A31D8F6F25005409EE /* Frameworks */,
141 | 42DDC7A41D8F6F25005409EE /* Resources */,
142 | );
143 | buildRules = (
144 | );
145 | dependencies = (
146 | 42DDC7A91D8F6F25005409EE /* PBXTargetDependency */,
147 | );
148 | name = WBSegmentControlTests;
149 | productName = WBSegmentControlTests;
150 | productReference = 42DDC7A61D8F6F25005409EE /* WBSegmentControlTests.xctest */;
151 | productType = "com.apple.product-type.bundle.unit-test";
152 | };
153 | /* End PBXNativeTarget section */
154 |
155 | /* Begin PBXProject section */
156 | 42DDC7941D8F6F25005409EE /* Project object */ = {
157 | isa = PBXProject;
158 | attributes = {
159 | LastSwiftUpdateCheck = 0800;
160 | LastUpgradeCheck = 0800;
161 | ORGANIZATIONNAME = snowflyer;
162 | TargetAttributes = {
163 | 42DDC79C1D8F6F25005409EE = {
164 | CreatedOnToolsVersion = 8.0;
165 | LastSwiftMigration = 0800;
166 | ProvisioningStyle = Automatic;
167 | };
168 | 42DDC7A51D8F6F25005409EE = {
169 | CreatedOnToolsVersion = 8.0;
170 | ProvisioningStyle = Automatic;
171 | };
172 | };
173 | };
174 | buildConfigurationList = 42DDC7971D8F6F25005409EE /* Build configuration list for PBXProject "WBSegmentControl" */;
175 | compatibilityVersion = "Xcode 3.2";
176 | developmentRegion = English;
177 | hasScannedForEncodings = 0;
178 | knownRegions = (
179 | en,
180 | );
181 | mainGroup = 42DDC7931D8F6F25005409EE;
182 | productRefGroup = 42DDC79E1D8F6F25005409EE /* Products */;
183 | projectDirPath = "";
184 | projectRoot = "";
185 | targets = (
186 | 42DDC79C1D8F6F25005409EE /* WBSegmentControl */,
187 | 42DDC7A51D8F6F25005409EE /* WBSegmentControlTests */,
188 | );
189 | };
190 | /* End PBXProject section */
191 |
192 | /* Begin PBXResourcesBuildPhase section */
193 | 42DDC79B1D8F6F25005409EE /* Resources */ = {
194 | isa = PBXResourcesBuildPhase;
195 | buildActionMask = 2147483647;
196 | files = (
197 | );
198 | runOnlyForDeploymentPostprocessing = 0;
199 | };
200 | 42DDC7A41D8F6F25005409EE /* Resources */ = {
201 | isa = PBXResourcesBuildPhase;
202 | buildActionMask = 2147483647;
203 | files = (
204 | );
205 | runOnlyForDeploymentPostprocessing = 0;
206 | };
207 | /* End PBXResourcesBuildPhase section */
208 |
209 | /* Begin PBXSourcesBuildPhase section */
210 | 42DDC7981D8F6F25005409EE /* Sources */ = {
211 | isa = PBXSourcesBuildPhase;
212 | buildActionMask = 2147483647;
213 | files = (
214 | 42DDC7FA1D8F77F7005409EE /* WBSegments.swift in Sources */,
215 | 42DDC7B91D8F6FB3005409EE /* WBSegmentControl.swift in Sources */,
216 | );
217 | runOnlyForDeploymentPostprocessing = 0;
218 | };
219 | 42DDC7A21D8F6F25005409EE /* Sources */ = {
220 | isa = PBXSourcesBuildPhase;
221 | buildActionMask = 2147483647;
222 | files = (
223 | 42DDC7AC1D8F6F25005409EE /* WBSegmentControlTests.swift in Sources */,
224 | );
225 | runOnlyForDeploymentPostprocessing = 0;
226 | };
227 | /* End PBXSourcesBuildPhase section */
228 |
229 | /* Begin PBXTargetDependency section */
230 | 42DDC7A91D8F6F25005409EE /* PBXTargetDependency */ = {
231 | isa = PBXTargetDependency;
232 | target = 42DDC79C1D8F6F25005409EE /* WBSegmentControl */;
233 | targetProxy = 42DDC7A81D8F6F25005409EE /* PBXContainerItemProxy */;
234 | };
235 | /* End PBXTargetDependency section */
236 |
237 | /* Begin XCBuildConfiguration section */
238 | 42DDC7AF1D8F6F25005409EE /* Debug */ = {
239 | isa = XCBuildConfiguration;
240 | buildSettings = {
241 | ALWAYS_SEARCH_USER_PATHS = NO;
242 | CLANG_ANALYZER_NONNULL = YES;
243 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
244 | CLANG_CXX_LIBRARY = "libc++";
245 | CLANG_ENABLE_MODULES = YES;
246 | CLANG_ENABLE_OBJC_ARC = YES;
247 | CLANG_WARN_BOOL_CONVERSION = YES;
248 | CLANG_WARN_CONSTANT_CONVERSION = YES;
249 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
250 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
251 | CLANG_WARN_EMPTY_BODY = YES;
252 | CLANG_WARN_ENUM_CONVERSION = YES;
253 | CLANG_WARN_INFINITE_RECURSION = YES;
254 | CLANG_WARN_INT_CONVERSION = YES;
255 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
256 | CLANG_WARN_SUSPICIOUS_MOVES = YES;
257 | CLANG_WARN_UNREACHABLE_CODE = YES;
258 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
259 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
260 | COPY_PHASE_STRIP = NO;
261 | CURRENT_PROJECT_VERSION = 1;
262 | DEBUG_INFORMATION_FORMAT = dwarf;
263 | ENABLE_STRICT_OBJC_MSGSEND = YES;
264 | ENABLE_TESTABILITY = YES;
265 | GCC_C_LANGUAGE_STANDARD = gnu99;
266 | GCC_DYNAMIC_NO_PIC = NO;
267 | GCC_NO_COMMON_BLOCKS = YES;
268 | GCC_OPTIMIZATION_LEVEL = 0;
269 | GCC_PREPROCESSOR_DEFINITIONS = (
270 | "DEBUG=1",
271 | "$(inherited)",
272 | );
273 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
274 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
275 | GCC_WARN_UNDECLARED_SELECTOR = YES;
276 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
277 | GCC_WARN_UNUSED_FUNCTION = YES;
278 | GCC_WARN_UNUSED_VARIABLE = YES;
279 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
280 | MTL_ENABLE_DEBUG_INFO = YES;
281 | ONLY_ACTIVE_ARCH = YES;
282 | SDKROOT = iphoneos;
283 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
284 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
285 | TARGETED_DEVICE_FAMILY = "1,2";
286 | VERSIONING_SYSTEM = "apple-generic";
287 | VERSION_INFO_PREFIX = "";
288 | };
289 | name = Debug;
290 | };
291 | 42DDC7B01D8F6F25005409EE /* Release */ = {
292 | isa = XCBuildConfiguration;
293 | buildSettings = {
294 | ALWAYS_SEARCH_USER_PATHS = NO;
295 | CLANG_ANALYZER_NONNULL = YES;
296 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
297 | CLANG_CXX_LIBRARY = "libc++";
298 | CLANG_ENABLE_MODULES = YES;
299 | CLANG_ENABLE_OBJC_ARC = YES;
300 | CLANG_WARN_BOOL_CONVERSION = YES;
301 | CLANG_WARN_CONSTANT_CONVERSION = YES;
302 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
303 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
304 | CLANG_WARN_EMPTY_BODY = YES;
305 | CLANG_WARN_ENUM_CONVERSION = YES;
306 | CLANG_WARN_INFINITE_RECURSION = YES;
307 | CLANG_WARN_INT_CONVERSION = YES;
308 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
309 | CLANG_WARN_SUSPICIOUS_MOVES = YES;
310 | CLANG_WARN_UNREACHABLE_CODE = YES;
311 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
312 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
313 | COPY_PHASE_STRIP = NO;
314 | CURRENT_PROJECT_VERSION = 1;
315 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
316 | ENABLE_NS_ASSERTIONS = NO;
317 | ENABLE_STRICT_OBJC_MSGSEND = YES;
318 | GCC_C_LANGUAGE_STANDARD = gnu99;
319 | GCC_NO_COMMON_BLOCKS = YES;
320 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
321 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
322 | GCC_WARN_UNDECLARED_SELECTOR = YES;
323 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
324 | GCC_WARN_UNUSED_FUNCTION = YES;
325 | GCC_WARN_UNUSED_VARIABLE = YES;
326 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
327 | MTL_ENABLE_DEBUG_INFO = NO;
328 | SDKROOT = iphoneos;
329 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
330 | TARGETED_DEVICE_FAMILY = "1,2";
331 | VALIDATE_PRODUCT = YES;
332 | VERSIONING_SYSTEM = "apple-generic";
333 | VERSION_INFO_PREFIX = "";
334 | };
335 | name = Release;
336 | };
337 | 42DDC7B21D8F6F25005409EE /* Debug */ = {
338 | isa = XCBuildConfiguration;
339 | buildSettings = {
340 | CLANG_ENABLE_MODULES = YES;
341 | CODE_SIGN_IDENTITY = "";
342 | DEFINES_MODULE = YES;
343 | DYLIB_COMPATIBILITY_VERSION = 1;
344 | DYLIB_CURRENT_VERSION = 1;
345 | DYLIB_INSTALL_NAME_BASE = "@rpath";
346 | INFOPLIST_FILE = WBSegmentControl/Info.plist;
347 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
348 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
349 | PRODUCT_BUNDLE_IDENTIFIER = com.snowflyer.WBSegmentControl;
350 | PRODUCT_NAME = "$(TARGET_NAME)";
351 | SKIP_INSTALL = YES;
352 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
353 | SWIFT_VERSION = 3.0;
354 | };
355 | name = Debug;
356 | };
357 | 42DDC7B31D8F6F25005409EE /* Release */ = {
358 | isa = XCBuildConfiguration;
359 | buildSettings = {
360 | CLANG_ENABLE_MODULES = YES;
361 | CODE_SIGN_IDENTITY = "";
362 | DEFINES_MODULE = YES;
363 | DYLIB_COMPATIBILITY_VERSION = 1;
364 | DYLIB_CURRENT_VERSION = 1;
365 | DYLIB_INSTALL_NAME_BASE = "@rpath";
366 | INFOPLIST_FILE = WBSegmentControl/Info.plist;
367 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
368 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
369 | PRODUCT_BUNDLE_IDENTIFIER = com.snowflyer.WBSegmentControl;
370 | PRODUCT_NAME = "$(TARGET_NAME)";
371 | SKIP_INSTALL = YES;
372 | SWIFT_VERSION = 3.0;
373 | };
374 | name = Release;
375 | };
376 | 42DDC7B51D8F6F25005409EE /* Debug */ = {
377 | isa = XCBuildConfiguration;
378 | buildSettings = {
379 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
380 | INFOPLIST_FILE = WBSegmentControlTests/Info.plist;
381 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
382 | PRODUCT_BUNDLE_IDENTIFIER = com.snowflyer.WBSegmentControlTests;
383 | PRODUCT_NAME = "$(TARGET_NAME)";
384 | SWIFT_VERSION = 3.0;
385 | };
386 | name = Debug;
387 | };
388 | 42DDC7B61D8F6F25005409EE /* Release */ = {
389 | isa = XCBuildConfiguration;
390 | buildSettings = {
391 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
392 | INFOPLIST_FILE = WBSegmentControlTests/Info.plist;
393 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
394 | PRODUCT_BUNDLE_IDENTIFIER = com.snowflyer.WBSegmentControlTests;
395 | PRODUCT_NAME = "$(TARGET_NAME)";
396 | SWIFT_VERSION = 3.0;
397 | };
398 | name = Release;
399 | };
400 | /* End XCBuildConfiguration section */
401 |
402 | /* Begin XCConfigurationList section */
403 | 42DDC7971D8F6F25005409EE /* Build configuration list for PBXProject "WBSegmentControl" */ = {
404 | isa = XCConfigurationList;
405 | buildConfigurations = (
406 | 42DDC7AF1D8F6F25005409EE /* Debug */,
407 | 42DDC7B01D8F6F25005409EE /* Release */,
408 | );
409 | defaultConfigurationIsVisible = 0;
410 | defaultConfigurationName = Release;
411 | };
412 | 42DDC7B11D8F6F25005409EE /* Build configuration list for PBXNativeTarget "WBSegmentControl" */ = {
413 | isa = XCConfigurationList;
414 | buildConfigurations = (
415 | 42DDC7B21D8F6F25005409EE /* Debug */,
416 | 42DDC7B31D8F6F25005409EE /* Release */,
417 | );
418 | defaultConfigurationIsVisible = 0;
419 | defaultConfigurationName = Release;
420 | };
421 | 42DDC7B41D8F6F25005409EE /* Build configuration list for PBXNativeTarget "WBSegmentControlTests" */ = {
422 | isa = XCConfigurationList;
423 | buildConfigurations = (
424 | 42DDC7B51D8F6F25005409EE /* Debug */,
425 | 42DDC7B61D8F6F25005409EE /* Release */,
426 | );
427 | defaultConfigurationIsVisible = 0;
428 | defaultConfigurationName = Release;
429 | };
430 | /* End XCConfigurationList section */
431 | };
432 | rootObject = 42DDC7941D8F6F25005409EE /* Project object */;
433 | }
434 |
--------------------------------------------------------------------------------
/Example/WBSegmentControl-Example.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 424209281E0CC1790081F7A1 /* WBSegmentControl.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 424209231E0CC1620081F7A1 /* WBSegmentControl.framework */; };
11 | 424209291E0CC1860081F7A1 /* WBSegmentControl.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 424209231E0CC1620081F7A1 /* WBSegmentControl.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
12 | 42DDC7C71D8F7022005409EE /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42DDC7C61D8F7022005409EE /* AppDelegate.swift */; };
13 | 42DDC7C91D8F7022005409EE /* ViewController1.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42DDC7C81D8F7022005409EE /* ViewController1.swift */; };
14 | 42DDC7CE1D8F7022005409EE /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 42DDC7CD1D8F7022005409EE /* Assets.xcassets */; };
15 | 42DDC7D11D8F7022005409EE /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 42DDC7CF1D8F7022005409EE /* LaunchScreen.storyboard */; };
16 | 42DDC7DC1D8F7022005409EE /* WBSegmentControl_ExampleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42DDC7DB1D8F7022005409EE /* WBSegmentControl_ExampleTests.swift */; };
17 | 42DDC7E71D8F7022005409EE /* WBSegmentControl_ExampleUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42DDC7E61D8F7022005409EE /* WBSegmentControl_ExampleUITests.swift */; };
18 | 42DDC7F81D8F72B4005409EE /* ViewController2.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42DDC7F71D8F72B4005409EE /* ViewController2.swift */; };
19 | /* End PBXBuildFile section */
20 |
21 | /* Begin PBXContainerItemProxy section */
22 | 424209221E0CC1620081F7A1 /* PBXContainerItemProxy */ = {
23 | isa = PBXContainerItemProxy;
24 | containerPortal = 4242091D1E0CC1620081F7A1 /* WBSegmentControl.xcodeproj */;
25 | proxyType = 2;
26 | remoteGlobalIDString = 42DDC79D1D8F6F25005409EE;
27 | remoteInfo = WBSegmentControl;
28 | };
29 | 424209241E0CC1620081F7A1 /* PBXContainerItemProxy */ = {
30 | isa = PBXContainerItemProxy;
31 | containerPortal = 4242091D1E0CC1620081F7A1 /* WBSegmentControl.xcodeproj */;
32 | proxyType = 2;
33 | remoteGlobalIDString = 42DDC7A61D8F6F25005409EE;
34 | remoteInfo = WBSegmentControlTests;
35 | };
36 | 424209261E0CC1700081F7A1 /* PBXContainerItemProxy */ = {
37 | isa = PBXContainerItemProxy;
38 | containerPortal = 4242091D1E0CC1620081F7A1 /* WBSegmentControl.xcodeproj */;
39 | proxyType = 1;
40 | remoteGlobalIDString = 42DDC79C1D8F6F25005409EE;
41 | remoteInfo = WBSegmentControl;
42 | };
43 | 42DDC7D81D8F7022005409EE /* PBXContainerItemProxy */ = {
44 | isa = PBXContainerItemProxy;
45 | containerPortal = 42DDC7BB1D8F7022005409EE /* Project object */;
46 | proxyType = 1;
47 | remoteGlobalIDString = 42DDC7C21D8F7022005409EE;
48 | remoteInfo = "WBSegmentControl-Example";
49 | };
50 | 42DDC7E31D8F7022005409EE /* PBXContainerItemProxy */ = {
51 | isa = PBXContainerItemProxy;
52 | containerPortal = 42DDC7BB1D8F7022005409EE /* Project object */;
53 | proxyType = 1;
54 | remoteGlobalIDString = 42DDC7C21D8F7022005409EE;
55 | remoteInfo = "WBSegmentControl-Example";
56 | };
57 | /* End PBXContainerItemProxy section */
58 |
59 | /* Begin PBXCopyFilesBuildPhase section */
60 | 4294CB6E1DEB075E0053068B /* Embed Frameworks */ = {
61 | isa = PBXCopyFilesBuildPhase;
62 | buildActionMask = 2147483647;
63 | dstPath = "";
64 | dstSubfolderSpec = 10;
65 | files = (
66 | 424209291E0CC1860081F7A1 /* WBSegmentControl.framework in Embed Frameworks */,
67 | );
68 | name = "Embed Frameworks";
69 | runOnlyForDeploymentPostprocessing = 0;
70 | };
71 | /* End PBXCopyFilesBuildPhase section */
72 |
73 | /* Begin PBXFileReference section */
74 | 4242091D1E0CC1620081F7A1 /* WBSegmentControl.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = WBSegmentControl.xcodeproj; path = ../Framework/WBSegmentControl.xcodeproj; sourceTree = ""; };
75 | 42DDC7C31D8F7022005409EE /* WBSegmentControl-Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "WBSegmentControl-Example.app"; sourceTree = BUILT_PRODUCTS_DIR; };
76 | 42DDC7C61D8F7022005409EE /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
77 | 42DDC7C81D8F7022005409EE /* ViewController1.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController1.swift; sourceTree = ""; };
78 | 42DDC7CD1D8F7022005409EE /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
79 | 42DDC7D01D8F7022005409EE /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
80 | 42DDC7D21D8F7022005409EE /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
81 | 42DDC7D71D8F7022005409EE /* WBSegmentControl-ExampleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "WBSegmentControl-ExampleTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
82 | 42DDC7DB1D8F7022005409EE /* WBSegmentControl_ExampleTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WBSegmentControl_ExampleTests.swift; sourceTree = ""; };
83 | 42DDC7DD1D8F7022005409EE /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
84 | 42DDC7E21D8F7022005409EE /* WBSegmentControl-ExampleUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "WBSegmentControl-ExampleUITests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
85 | 42DDC7E61D8F7022005409EE /* WBSegmentControl_ExampleUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WBSegmentControl_ExampleUITests.swift; sourceTree = ""; };
86 | 42DDC7E81D8F7022005409EE /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
87 | 42DDC7F71D8F72B4005409EE /* ViewController2.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ViewController2.swift; sourceTree = ""; };
88 | /* End PBXFileReference section */
89 |
90 | /* Begin PBXFrameworksBuildPhase section */
91 | 42A231161DE829C100351DA5 /* Frameworks */ = {
92 | isa = PBXFrameworksBuildPhase;
93 | buildActionMask = 2147483647;
94 | files = (
95 | 424209281E0CC1790081F7A1 /* WBSegmentControl.framework in Frameworks */,
96 | );
97 | runOnlyForDeploymentPostprocessing = 0;
98 | };
99 | 42DDC7D41D8F7022005409EE /* Frameworks */ = {
100 | isa = PBXFrameworksBuildPhase;
101 | buildActionMask = 2147483647;
102 | files = (
103 | );
104 | runOnlyForDeploymentPostprocessing = 0;
105 | };
106 | 42DDC7DF1D8F7022005409EE /* Frameworks */ = {
107 | isa = PBXFrameworksBuildPhase;
108 | buildActionMask = 2147483647;
109 | files = (
110 | );
111 | runOnlyForDeploymentPostprocessing = 0;
112 | };
113 | /* End PBXFrameworksBuildPhase section */
114 |
115 | /* Begin PBXGroup section */
116 | 4242091E1E0CC1620081F7A1 /* Products */ = {
117 | isa = PBXGroup;
118 | children = (
119 | 424209231E0CC1620081F7A1 /* WBSegmentControl.framework */,
120 | 424209251E0CC1620081F7A1 /* WBSegmentControlTests.xctest */,
121 | );
122 | name = Products;
123 | sourceTree = "";
124 | };
125 | 42DDC7BA1D8F7022005409EE = {
126 | isa = PBXGroup;
127 | children = (
128 | 4242091D1E0CC1620081F7A1 /* WBSegmentControl.xcodeproj */,
129 | 42DDC7C51D8F7022005409EE /* WBSegmentControl-Example */,
130 | 42DDC7DA1D8F7022005409EE /* WBSegmentControl-ExampleTests */,
131 | 42DDC7E51D8F7022005409EE /* WBSegmentControl-ExampleUITests */,
132 | 42DDC7C41D8F7022005409EE /* Products */,
133 | 42DDC7F41D8F728F005409EE /* Frameworks */,
134 | );
135 | sourceTree = "";
136 | };
137 | 42DDC7C41D8F7022005409EE /* Products */ = {
138 | isa = PBXGroup;
139 | children = (
140 | 42DDC7C31D8F7022005409EE /* WBSegmentControl-Example.app */,
141 | 42DDC7D71D8F7022005409EE /* WBSegmentControl-ExampleTests.xctest */,
142 | 42DDC7E21D8F7022005409EE /* WBSegmentControl-ExampleUITests.xctest */,
143 | );
144 | name = Products;
145 | sourceTree = "";
146 | };
147 | 42DDC7C51D8F7022005409EE /* WBSegmentControl-Example */ = {
148 | isa = PBXGroup;
149 | children = (
150 | 42DDC7C61D8F7022005409EE /* AppDelegate.swift */,
151 | 42DDC7C81D8F7022005409EE /* ViewController1.swift */,
152 | 42DDC7F71D8F72B4005409EE /* ViewController2.swift */,
153 | 42DDC7CD1D8F7022005409EE /* Assets.xcassets */,
154 | 42DDC7CF1D8F7022005409EE /* LaunchScreen.storyboard */,
155 | 42DDC7D21D8F7022005409EE /* Info.plist */,
156 | );
157 | path = "WBSegmentControl-Example";
158 | sourceTree = "";
159 | };
160 | 42DDC7DA1D8F7022005409EE /* WBSegmentControl-ExampleTests */ = {
161 | isa = PBXGroup;
162 | children = (
163 | 42DDC7DB1D8F7022005409EE /* WBSegmentControl_ExampleTests.swift */,
164 | 42DDC7DD1D8F7022005409EE /* Info.plist */,
165 | );
166 | path = "WBSegmentControl-ExampleTests";
167 | sourceTree = "";
168 | };
169 | 42DDC7E51D8F7022005409EE /* WBSegmentControl-ExampleUITests */ = {
170 | isa = PBXGroup;
171 | children = (
172 | 42DDC7E61D8F7022005409EE /* WBSegmentControl_ExampleUITests.swift */,
173 | 42DDC7E81D8F7022005409EE /* Info.plist */,
174 | );
175 | path = "WBSegmentControl-ExampleUITests";
176 | sourceTree = "";
177 | };
178 | 42DDC7F41D8F728F005409EE /* Frameworks */ = {
179 | isa = PBXGroup;
180 | children = (
181 | );
182 | name = Frameworks;
183 | sourceTree = "";
184 | };
185 | /* End PBXGroup section */
186 |
187 | /* Begin PBXNativeTarget section */
188 | 42DDC7C21D8F7022005409EE /* WBSegmentControl-Example */ = {
189 | isa = PBXNativeTarget;
190 | buildConfigurationList = 42DDC7EB1D8F7022005409EE /* Build configuration list for PBXNativeTarget "WBSegmentControl-Example" */;
191 | buildPhases = (
192 | 42DDC7BF1D8F7022005409EE /* Sources */,
193 | 42A231161DE829C100351DA5 /* Frameworks */,
194 | 42DDC7C11D8F7022005409EE /* Resources */,
195 | 4294CB6E1DEB075E0053068B /* Embed Frameworks */,
196 | );
197 | buildRules = (
198 | );
199 | dependencies = (
200 | 424209271E0CC1700081F7A1 /* PBXTargetDependency */,
201 | );
202 | name = "WBSegmentControl-Example";
203 | productName = "WBSegmentControl-Example";
204 | productReference = 42DDC7C31D8F7022005409EE /* WBSegmentControl-Example.app */;
205 | productType = "com.apple.product-type.application";
206 | };
207 | 42DDC7D61D8F7022005409EE /* WBSegmentControl-ExampleTests */ = {
208 | isa = PBXNativeTarget;
209 | buildConfigurationList = 42DDC7EE1D8F7022005409EE /* Build configuration list for PBXNativeTarget "WBSegmentControl-ExampleTests" */;
210 | buildPhases = (
211 | 42DDC7D31D8F7022005409EE /* Sources */,
212 | 42DDC7D41D8F7022005409EE /* Frameworks */,
213 | 42DDC7D51D8F7022005409EE /* Resources */,
214 | );
215 | buildRules = (
216 | );
217 | dependencies = (
218 | 42DDC7D91D8F7022005409EE /* PBXTargetDependency */,
219 | );
220 | name = "WBSegmentControl-ExampleTests";
221 | productName = "WBSegmentControl-ExampleTests";
222 | productReference = 42DDC7D71D8F7022005409EE /* WBSegmentControl-ExampleTests.xctest */;
223 | productType = "com.apple.product-type.bundle.unit-test";
224 | };
225 | 42DDC7E11D8F7022005409EE /* WBSegmentControl-ExampleUITests */ = {
226 | isa = PBXNativeTarget;
227 | buildConfigurationList = 42DDC7F11D8F7022005409EE /* Build configuration list for PBXNativeTarget "WBSegmentControl-ExampleUITests" */;
228 | buildPhases = (
229 | 42DDC7DE1D8F7022005409EE /* Sources */,
230 | 42DDC7DF1D8F7022005409EE /* Frameworks */,
231 | 42DDC7E01D8F7022005409EE /* Resources */,
232 | );
233 | buildRules = (
234 | );
235 | dependencies = (
236 | 42DDC7E41D8F7022005409EE /* PBXTargetDependency */,
237 | );
238 | name = "WBSegmentControl-ExampleUITests";
239 | productName = "WBSegmentControl-ExampleUITests";
240 | productReference = 42DDC7E21D8F7022005409EE /* WBSegmentControl-ExampleUITests.xctest */;
241 | productType = "com.apple.product-type.bundle.ui-testing";
242 | };
243 | /* End PBXNativeTarget section */
244 |
245 | /* Begin PBXProject section */
246 | 42DDC7BB1D8F7022005409EE /* Project object */ = {
247 | isa = PBXProject;
248 | attributes = {
249 | LastSwiftUpdateCheck = 0800;
250 | LastUpgradeCheck = 0800;
251 | ORGANIZATIONNAME = snowflyer;
252 | TargetAttributes = {
253 | 42DDC7C21D8F7022005409EE = {
254 | CreatedOnToolsVersion = 8.0;
255 | DevelopmentTeam = M793737CLS;
256 | ProvisioningStyle = Automatic;
257 | };
258 | 42DDC7D61D8F7022005409EE = {
259 | CreatedOnToolsVersion = 8.0;
260 | ProvisioningStyle = Automatic;
261 | TestTargetID = 42DDC7C21D8F7022005409EE;
262 | };
263 | 42DDC7E11D8F7022005409EE = {
264 | CreatedOnToolsVersion = 8.0;
265 | ProvisioningStyle = Automatic;
266 | TestTargetID = 42DDC7C21D8F7022005409EE;
267 | };
268 | };
269 | };
270 | buildConfigurationList = 42DDC7BE1D8F7022005409EE /* Build configuration list for PBXProject "WBSegmentControl-Example" */;
271 | compatibilityVersion = "Xcode 3.2";
272 | developmentRegion = English;
273 | hasScannedForEncodings = 0;
274 | knownRegions = (
275 | en,
276 | Base,
277 | );
278 | mainGroup = 42DDC7BA1D8F7022005409EE;
279 | productRefGroup = 42DDC7C41D8F7022005409EE /* Products */;
280 | projectDirPath = "";
281 | projectReferences = (
282 | {
283 | ProductGroup = 4242091E1E0CC1620081F7A1 /* Products */;
284 | ProjectRef = 4242091D1E0CC1620081F7A1 /* WBSegmentControl.xcodeproj */;
285 | },
286 | );
287 | projectRoot = "";
288 | targets = (
289 | 42DDC7C21D8F7022005409EE /* WBSegmentControl-Example */,
290 | 42DDC7D61D8F7022005409EE /* WBSegmentControl-ExampleTests */,
291 | 42DDC7E11D8F7022005409EE /* WBSegmentControl-ExampleUITests */,
292 | );
293 | };
294 | /* End PBXProject section */
295 |
296 | /* Begin PBXReferenceProxy section */
297 | 424209231E0CC1620081F7A1 /* WBSegmentControl.framework */ = {
298 | isa = PBXReferenceProxy;
299 | fileType = wrapper.framework;
300 | path = WBSegmentControl.framework;
301 | remoteRef = 424209221E0CC1620081F7A1 /* PBXContainerItemProxy */;
302 | sourceTree = BUILT_PRODUCTS_DIR;
303 | };
304 | 424209251E0CC1620081F7A1 /* WBSegmentControlTests.xctest */ = {
305 | isa = PBXReferenceProxy;
306 | fileType = wrapper.cfbundle;
307 | path = WBSegmentControlTests.xctest;
308 | remoteRef = 424209241E0CC1620081F7A1 /* PBXContainerItemProxy */;
309 | sourceTree = BUILT_PRODUCTS_DIR;
310 | };
311 | /* End PBXReferenceProxy section */
312 |
313 | /* Begin PBXResourcesBuildPhase section */
314 | 42DDC7C11D8F7022005409EE /* Resources */ = {
315 | isa = PBXResourcesBuildPhase;
316 | buildActionMask = 2147483647;
317 | files = (
318 | 42DDC7D11D8F7022005409EE /* LaunchScreen.storyboard in Resources */,
319 | 42DDC7CE1D8F7022005409EE /* Assets.xcassets in Resources */,
320 | );
321 | runOnlyForDeploymentPostprocessing = 0;
322 | };
323 | 42DDC7D51D8F7022005409EE /* Resources */ = {
324 | isa = PBXResourcesBuildPhase;
325 | buildActionMask = 2147483647;
326 | files = (
327 | );
328 | runOnlyForDeploymentPostprocessing = 0;
329 | };
330 | 42DDC7E01D8F7022005409EE /* Resources */ = {
331 | isa = PBXResourcesBuildPhase;
332 | buildActionMask = 2147483647;
333 | files = (
334 | );
335 | runOnlyForDeploymentPostprocessing = 0;
336 | };
337 | /* End PBXResourcesBuildPhase section */
338 |
339 | /* Begin PBXSourcesBuildPhase section */
340 | 42DDC7BF1D8F7022005409EE /* Sources */ = {
341 | isa = PBXSourcesBuildPhase;
342 | buildActionMask = 2147483647;
343 | files = (
344 | 42DDC7C91D8F7022005409EE /* ViewController1.swift in Sources */,
345 | 42DDC7C71D8F7022005409EE /* AppDelegate.swift in Sources */,
346 | 42DDC7F81D8F72B4005409EE /* ViewController2.swift in Sources */,
347 | );
348 | runOnlyForDeploymentPostprocessing = 0;
349 | };
350 | 42DDC7D31D8F7022005409EE /* Sources */ = {
351 | isa = PBXSourcesBuildPhase;
352 | buildActionMask = 2147483647;
353 | files = (
354 | 42DDC7DC1D8F7022005409EE /* WBSegmentControl_ExampleTests.swift in Sources */,
355 | );
356 | runOnlyForDeploymentPostprocessing = 0;
357 | };
358 | 42DDC7DE1D8F7022005409EE /* Sources */ = {
359 | isa = PBXSourcesBuildPhase;
360 | buildActionMask = 2147483647;
361 | files = (
362 | 42DDC7E71D8F7022005409EE /* WBSegmentControl_ExampleUITests.swift in Sources */,
363 | );
364 | runOnlyForDeploymentPostprocessing = 0;
365 | };
366 | /* End PBXSourcesBuildPhase section */
367 |
368 | /* Begin PBXTargetDependency section */
369 | 424209271E0CC1700081F7A1 /* PBXTargetDependency */ = {
370 | isa = PBXTargetDependency;
371 | name = WBSegmentControl;
372 | targetProxy = 424209261E0CC1700081F7A1 /* PBXContainerItemProxy */;
373 | };
374 | 42DDC7D91D8F7022005409EE /* PBXTargetDependency */ = {
375 | isa = PBXTargetDependency;
376 | target = 42DDC7C21D8F7022005409EE /* WBSegmentControl-Example */;
377 | targetProxy = 42DDC7D81D8F7022005409EE /* PBXContainerItemProxy */;
378 | };
379 | 42DDC7E41D8F7022005409EE /* PBXTargetDependency */ = {
380 | isa = PBXTargetDependency;
381 | target = 42DDC7C21D8F7022005409EE /* WBSegmentControl-Example */;
382 | targetProxy = 42DDC7E31D8F7022005409EE /* PBXContainerItemProxy */;
383 | };
384 | /* End PBXTargetDependency section */
385 |
386 | /* Begin PBXVariantGroup section */
387 | 42DDC7CF1D8F7022005409EE /* LaunchScreen.storyboard */ = {
388 | isa = PBXVariantGroup;
389 | children = (
390 | 42DDC7D01D8F7022005409EE /* Base */,
391 | );
392 | name = LaunchScreen.storyboard;
393 | sourceTree = "";
394 | };
395 | /* End PBXVariantGroup section */
396 |
397 | /* Begin XCBuildConfiguration section */
398 | 42DDC7E91D8F7022005409EE /* Debug */ = {
399 | isa = XCBuildConfiguration;
400 | buildSettings = {
401 | ALWAYS_SEARCH_USER_PATHS = NO;
402 | CLANG_ANALYZER_NONNULL = YES;
403 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
404 | CLANG_CXX_LIBRARY = "libc++";
405 | CLANG_ENABLE_MODULES = YES;
406 | CLANG_ENABLE_OBJC_ARC = YES;
407 | CLANG_WARN_BOOL_CONVERSION = YES;
408 | CLANG_WARN_CONSTANT_CONVERSION = YES;
409 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
410 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
411 | CLANG_WARN_EMPTY_BODY = YES;
412 | CLANG_WARN_ENUM_CONVERSION = YES;
413 | CLANG_WARN_INFINITE_RECURSION = YES;
414 | CLANG_WARN_INT_CONVERSION = YES;
415 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
416 | CLANG_WARN_SUSPICIOUS_MOVES = YES;
417 | CLANG_WARN_UNREACHABLE_CODE = YES;
418 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
419 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
420 | COPY_PHASE_STRIP = NO;
421 | DEBUG_INFORMATION_FORMAT = dwarf;
422 | ENABLE_STRICT_OBJC_MSGSEND = YES;
423 | ENABLE_TESTABILITY = YES;
424 | GCC_C_LANGUAGE_STANDARD = gnu99;
425 | GCC_DYNAMIC_NO_PIC = NO;
426 | GCC_NO_COMMON_BLOCKS = YES;
427 | GCC_OPTIMIZATION_LEVEL = 0;
428 | GCC_PREPROCESSOR_DEFINITIONS = (
429 | "DEBUG=1",
430 | "$(inherited)",
431 | );
432 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
433 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
434 | GCC_WARN_UNDECLARED_SELECTOR = YES;
435 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
436 | GCC_WARN_UNUSED_FUNCTION = YES;
437 | GCC_WARN_UNUSED_VARIABLE = YES;
438 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
439 | MTL_ENABLE_DEBUG_INFO = YES;
440 | ONLY_ACTIVE_ARCH = YES;
441 | SDKROOT = iphoneos;
442 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
443 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
444 | TARGETED_DEVICE_FAMILY = "1,2";
445 | };
446 | name = Debug;
447 | };
448 | 42DDC7EA1D8F7022005409EE /* Release */ = {
449 | isa = XCBuildConfiguration;
450 | buildSettings = {
451 | ALWAYS_SEARCH_USER_PATHS = NO;
452 | CLANG_ANALYZER_NONNULL = YES;
453 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
454 | CLANG_CXX_LIBRARY = "libc++";
455 | CLANG_ENABLE_MODULES = YES;
456 | CLANG_ENABLE_OBJC_ARC = YES;
457 | CLANG_WARN_BOOL_CONVERSION = YES;
458 | CLANG_WARN_CONSTANT_CONVERSION = YES;
459 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
460 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
461 | CLANG_WARN_EMPTY_BODY = YES;
462 | CLANG_WARN_ENUM_CONVERSION = YES;
463 | CLANG_WARN_INFINITE_RECURSION = YES;
464 | CLANG_WARN_INT_CONVERSION = YES;
465 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
466 | CLANG_WARN_SUSPICIOUS_MOVES = YES;
467 | CLANG_WARN_UNREACHABLE_CODE = YES;
468 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
469 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
470 | COPY_PHASE_STRIP = NO;
471 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
472 | ENABLE_NS_ASSERTIONS = NO;
473 | ENABLE_STRICT_OBJC_MSGSEND = YES;
474 | GCC_C_LANGUAGE_STANDARD = gnu99;
475 | GCC_NO_COMMON_BLOCKS = YES;
476 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
477 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
478 | GCC_WARN_UNDECLARED_SELECTOR = YES;
479 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
480 | GCC_WARN_UNUSED_FUNCTION = YES;
481 | GCC_WARN_UNUSED_VARIABLE = YES;
482 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
483 | MTL_ENABLE_DEBUG_INFO = NO;
484 | SDKROOT = iphoneos;
485 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
486 | TARGETED_DEVICE_FAMILY = "1,2";
487 | VALIDATE_PRODUCT = YES;
488 | };
489 | name = Release;
490 | };
491 | 42DDC7EC1D8F7022005409EE /* Debug */ = {
492 | isa = XCBuildConfiguration;
493 | buildSettings = {
494 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
495 | DEVELOPMENT_TEAM = M793737CLS;
496 | FRAMEWORK_SEARCH_PATHS = (
497 | "$(inherited)",
498 | "$(PROJECT_DIR)/WBSegmentControl-Example",
499 | "$(PROJECT_DIR)",
500 | );
501 | INFOPLIST_FILE = "WBSegmentControl-Example/Info.plist";
502 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
503 | PRODUCT_BUNDLE_IDENTIFIER = "com.snowflyer.WBSegmentControl-Example";
504 | PRODUCT_NAME = "$(TARGET_NAME)";
505 | SWIFT_VERSION = 3.0;
506 | };
507 | name = Debug;
508 | };
509 | 42DDC7ED1D8F7022005409EE /* Release */ = {
510 | isa = XCBuildConfiguration;
511 | buildSettings = {
512 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
513 | DEVELOPMENT_TEAM = M793737CLS;
514 | FRAMEWORK_SEARCH_PATHS = (
515 | "$(inherited)",
516 | "$(PROJECT_DIR)/WBSegmentControl-Example",
517 | "$(PROJECT_DIR)",
518 | );
519 | INFOPLIST_FILE = "WBSegmentControl-Example/Info.plist";
520 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
521 | PRODUCT_BUNDLE_IDENTIFIER = "com.snowflyer.WBSegmentControl-Example";
522 | PRODUCT_NAME = "$(TARGET_NAME)";
523 | SWIFT_VERSION = 3.0;
524 | };
525 | name = Release;
526 | };
527 | 42DDC7EF1D8F7022005409EE /* Debug */ = {
528 | isa = XCBuildConfiguration;
529 | buildSettings = {
530 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
531 | BUNDLE_LOADER = "$(TEST_HOST)";
532 | INFOPLIST_FILE = "WBSegmentControl-ExampleTests/Info.plist";
533 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
534 | PRODUCT_BUNDLE_IDENTIFIER = "com.snowflyer.WBSegmentControl-ExampleTests";
535 | PRODUCT_NAME = "$(TARGET_NAME)";
536 | SWIFT_VERSION = 3.0;
537 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/WBSegmentControl-Example.app/WBSegmentControl-Example";
538 | };
539 | name = Debug;
540 | };
541 | 42DDC7F01D8F7022005409EE /* Release */ = {
542 | isa = XCBuildConfiguration;
543 | buildSettings = {
544 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
545 | BUNDLE_LOADER = "$(TEST_HOST)";
546 | INFOPLIST_FILE = "WBSegmentControl-ExampleTests/Info.plist";
547 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
548 | PRODUCT_BUNDLE_IDENTIFIER = "com.snowflyer.WBSegmentControl-ExampleTests";
549 | PRODUCT_NAME = "$(TARGET_NAME)";
550 | SWIFT_VERSION = 3.0;
551 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/WBSegmentControl-Example.app/WBSegmentControl-Example";
552 | };
553 | name = Release;
554 | };
555 | 42DDC7F21D8F7022005409EE /* Debug */ = {
556 | isa = XCBuildConfiguration;
557 | buildSettings = {
558 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
559 | INFOPLIST_FILE = "WBSegmentControl-ExampleUITests/Info.plist";
560 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
561 | PRODUCT_BUNDLE_IDENTIFIER = "com.snowflyer.WBSegmentControl-ExampleUITests";
562 | PRODUCT_NAME = "$(TARGET_NAME)";
563 | SWIFT_VERSION = 3.0;
564 | TEST_TARGET_NAME = "WBSegmentControl-Example";
565 | };
566 | name = Debug;
567 | };
568 | 42DDC7F31D8F7022005409EE /* Release */ = {
569 | isa = XCBuildConfiguration;
570 | buildSettings = {
571 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
572 | INFOPLIST_FILE = "WBSegmentControl-ExampleUITests/Info.plist";
573 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
574 | PRODUCT_BUNDLE_IDENTIFIER = "com.snowflyer.WBSegmentControl-ExampleUITests";
575 | PRODUCT_NAME = "$(TARGET_NAME)";
576 | SWIFT_VERSION = 3.0;
577 | TEST_TARGET_NAME = "WBSegmentControl-Example";
578 | };
579 | name = Release;
580 | };
581 | /* End XCBuildConfiguration section */
582 |
583 | /* Begin XCConfigurationList section */
584 | 42DDC7BE1D8F7022005409EE /* Build configuration list for PBXProject "WBSegmentControl-Example" */ = {
585 | isa = XCConfigurationList;
586 | buildConfigurations = (
587 | 42DDC7E91D8F7022005409EE /* Debug */,
588 | 42DDC7EA1D8F7022005409EE /* Release */,
589 | );
590 | defaultConfigurationIsVisible = 0;
591 | defaultConfigurationName = Release;
592 | };
593 | 42DDC7EB1D8F7022005409EE /* Build configuration list for PBXNativeTarget "WBSegmentControl-Example" */ = {
594 | isa = XCConfigurationList;
595 | buildConfigurations = (
596 | 42DDC7EC1D8F7022005409EE /* Debug */,
597 | 42DDC7ED1D8F7022005409EE /* Release */,
598 | );
599 | defaultConfigurationIsVisible = 0;
600 | defaultConfigurationName = Release;
601 | };
602 | 42DDC7EE1D8F7022005409EE /* Build configuration list for PBXNativeTarget "WBSegmentControl-ExampleTests" */ = {
603 | isa = XCConfigurationList;
604 | buildConfigurations = (
605 | 42DDC7EF1D8F7022005409EE /* Debug */,
606 | 42DDC7F01D8F7022005409EE /* Release */,
607 | );
608 | defaultConfigurationIsVisible = 0;
609 | defaultConfigurationName = Release;
610 | };
611 | 42DDC7F11D8F7022005409EE /* Build configuration list for PBXNativeTarget "WBSegmentControl-ExampleUITests" */ = {
612 | isa = XCConfigurationList;
613 | buildConfigurations = (
614 | 42DDC7F21D8F7022005409EE /* Debug */,
615 | 42DDC7F31D8F7022005409EE /* Release */,
616 | );
617 | defaultConfigurationIsVisible = 0;
618 | defaultConfigurationName = Release;
619 | };
620 | /* End XCConfigurationList section */
621 | };
622 | rootObject = 42DDC7BB1D8F7022005409EE /* Project object */;
623 | }
624 |
--------------------------------------------------------------------------------
/Framework/WBSegmentControl/WBSegmentControl.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CustomSegmentControl2.swift
3 | // TrafficSecretary
4 | //
5 | // Created by 王继荣 on 4/9/16.
6 | // Copyright © 2016 wonderbear. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | public protocol WBSegmentControlDelegate: class {
12 | func segmentControl(_ segmentControl: WBSegmentControl, selectIndex newIndex: Int, oldIndex: Int)
13 | }
14 |
15 | public protocol WBSegmentContentProtocol {
16 | var type: WBSegmentType { get }
17 | }
18 |
19 | public protocol WBTouchViewDelegate {
20 | func didTouch(_ location: CGPoint)
21 | }
22 |
23 | public class WBSegmentControl: UIControl {
24 |
25 | // MARK: Configuration - Content
26 | public var segments: [WBSegmentContentProtocol] = [] {
27 | didSet {
28 | innerSegments = segments.map({ (content) -> WBInnerSegment in
29 | return WBInnerSegment(content: content)
30 | })
31 | self.setNeedsLayout()
32 | if segments.count == 0 {
33 | selectedIndex = -1
34 | }
35 | }
36 | }
37 | var innerSegments: [WBInnerSegment] = []
38 |
39 | // MARK: Configuration - Interaction
40 | public weak var delegate: WBSegmentControlDelegate?
41 | public var selectedIndex: Int = -1 {
42 | didSet {
43 | if selectedIndex != oldValue && validIndex(selectedIndex) {
44 | selectedIndexChanged(selectedIndex, oldIndex: oldValue)
45 | delegate?.segmentControl(self, selectIndex: selectedIndex, oldIndex: oldValue)
46 | }
47 | }
48 | }
49 | public var selectedSegment: WBSegmentContentProtocol? {
50 | return validIndex(selectedIndex) ? segments[selectedIndex] : nil
51 | }
52 |
53 | // MARK: Configuration - Appearance
54 | public var style: WBSegmentIndicatorStyle = .rainbow
55 | public var nonScrollDistributionStyle: WBSegmentNonScrollDistributionStyle = .average
56 | public var enableSeparator: Bool = false
57 | public var separatorColor: UIColor = UIColor.black
58 | public var separatorWidth: CGFloat = 9
59 | public var separatorEdgeInsets: UIEdgeInsets = UIEdgeInsets(top: 8, left: 4, bottom: 8, right: 4)
60 | public var enableSlideway: Bool = false
61 | public var slidewayHeight: CGFloat = 1
62 | public var slidewayColor: UIColor = UIColor.lightGray
63 | public var enableAnimation: Bool = true
64 | public var animationDuration: TimeInterval = 0.15
65 | public var segmentMinWidth: CGFloat = 50
66 | public var segmentEdgeInsets: UIEdgeInsets = UIEdgeInsets(top: 0, left: 10, bottom: 0, right: 10)
67 | public var segmentTextBold: Bool = true
68 | public var segmentTextFontSize: CGFloat = 12
69 | public var segmentForegroundColor: UIColor = UIColor.gray
70 | public var segmentForegroundColorSelected: UIColor = UIColor.black
71 |
72 | // Settings - Cover
73 | public typealias CoverRange = WBSegmentIndicatorRange
74 |
75 | public var cover_range: CoverRange = .segment
76 | public var cover_opacity: Float = 0.2
77 | public var cover_color: UIColor = UIColor.black
78 |
79 | // Settings - Strip
80 | public typealias StripRange = WBSegmentIndicatorRange
81 | public typealias StripLocation = WBSegmentIndicatorLocation
82 |
83 | public var strip_range: StripRange = .content
84 | public var strip_location: StripLocation = .down
85 | public var strip_color: UIColor = UIColor.orange
86 | public var strip_height: CGFloat = 3
87 |
88 | // Settings - Rainbow
89 | public typealias RainbowLocation = WBSegmentIndicatorLocation
90 |
91 | public var rainbow_colors: [UIColor] = []
92 | public var rainbow_height: CGFloat = 3
93 | public var rainbow_roundCornerRadius: CGFloat = 4
94 | public var rainbow_location: RainbowLocation = .down
95 | public var rainbow_outsideColor: UIColor = UIColor.gray
96 |
97 | // Settings - Arrow
98 | public typealias ArrowLocation = WBSegmentIndicatorLocation
99 |
100 | public var arrow_size: CGSize = CGSize(width: 6, height: 6)
101 | public var arrow_location: ArrowLocation = .down
102 | public var arrow_color: UIColor = UIColor.orange
103 |
104 | // Settings - ArrowStrip
105 | public typealias ArrowStripLocation = WBSegmentIndicatorLocation
106 | public typealias ArrowStripRange = WBSegmentIndicatorRange
107 |
108 | public var arrowStrip_location: ArrowStripLocation = .up
109 | public var arrowStrip_color: UIColor = UIColor.orange
110 | public var arrowStrip_arrowSize: CGSize = CGSize(width: 6, height: 6)
111 | public var arrowStrip_stripHeight: CGFloat = 2
112 | public var arrowStrip_stripRange: ArrowStripRange = .content
113 |
114 | // MARK: Inner properties
115 | fileprivate var scrollView: UIScrollView!
116 | fileprivate var touchView: WBTouchView = WBTouchView()
117 | fileprivate var layerContainer: CALayer = CALayer()
118 | fileprivate var layerCover: CALayer = CALayer()
119 | fileprivate var layerStrip: CALayer = CALayer()
120 | fileprivate var layerArrow: CALayer = CALayer()
121 | fileprivate var segmentControlContentWidth: CGFloat {
122 | let sum = self.innerSegments.reduce(0, { (max_x, segment) -> CGFloat in
123 | return max(max_x, segment.segmentFrame.maxX)
124 | })
125 | return sum + ((self.enableSeparator && self.style != .rainbow) ? self.separatorWidth / 2 : 0)
126 | }
127 |
128 | // MARK: Initialization
129 | override init(frame: CGRect) {
130 | super.init(frame: frame)
131 |
132 | scrollView = UIScrollView()
133 | self.addSubview(scrollView)
134 | scrollView.translatesAutoresizingMaskIntoConstraints = false
135 | self.addConstraint(NSLayoutConstraint(item: scrollView, attribute: .top, relatedBy: .equal, toItem: self, attribute: .top, multiplier: 1, constant: 0))
136 | self.addConstraint(NSLayoutConstraint(item: scrollView, attribute: .bottom, relatedBy: .equal, toItem: self, attribute: .bottom, multiplier: 1, constant: 0))
137 | self.addConstraint(NSLayoutConstraint(item: scrollView, attribute: .left, relatedBy: .equal, toItem: self, attribute: .left, multiplier: 1, constant: 0))
138 | self.addConstraint(NSLayoutConstraint(item: scrollView, attribute: .right, relatedBy: .equal, toItem: self, attribute: .right, multiplier: 1, constant: 0))
139 | scrollView.showsHorizontalScrollIndicator = false
140 | scrollView.showsVerticalScrollIndicator = false
141 | scrollView.layer.addSublayer(layerContainer)
142 |
143 | scrollView.addSubview(touchView)
144 | touchView.delegate = self
145 | }
146 |
147 | required public init?(coder aDecoder: NSCoder) {
148 | fatalError("init(coder:) has not been implemented")
149 | }
150 |
151 | // MARK: Override methods
152 | override public func layoutSubviews() {
153 | super.layoutSubviews()
154 | layerContainer.sublayers?.removeAll()
155 |
156 | // Compute Segment Size
157 | for (index, segment) in self.innerSegments.enumerated() {
158 | segment.contentSize = self.segmentContentSize(segment)
159 | segment.segmentWidth = max(segment.contentSize.width + self.segmentEdgeInsets.left + self.segmentEdgeInsets.right, self.segmentMinWidth)
160 | segment.segmentFrame = self.segmentFrame(index)
161 | }
162 |
163 | // Adjust Control Content Size & Segment Size
164 | self.scrollView.contentSize = CGSize(width: self.segmentControlContentWidth, height: self.scrollView.frame.height)
165 | if self.scrollView.contentSize.width < self.scrollView.frame.width {
166 | switch self.nonScrollDistributionStyle {
167 | case .center:
168 | self.scrollView.contentInset = UIEdgeInsets(top: 0, left: (self.scrollView.frame.width - self.scrollView.contentSize.width) / 2, bottom: 0, right: 0)
169 | case .left:
170 | self.scrollView.contentInset = UIEdgeInsets.zero
171 | case .right:
172 | self.scrollView.contentInset = UIEdgeInsets(top: 0, left: self.scrollView.frame.width - self.scrollView.contentSize.width, bottom: 0, right: 0)
173 | case .average:
174 | self.scrollView.contentInset = UIEdgeInsets.zero
175 | self.scrollView.contentSize = self.scrollView.frame.size
176 | var averageWidth: CGFloat = (self.scrollView.frame.width - (self.enableSeparator && self.style != .rainbow ? CGFloat(self.innerSegments.count) * self.separatorWidth : 0)) / CGFloat(self.innerSegments.count)
177 | let largeSegments = self.innerSegments.filter({ (segment) -> Bool in
178 | return segment.segmentWidth >= averageWidth
179 | })
180 | let smallSegments = self.innerSegments.filter({ (segment) -> Bool in
181 | return segment.segmentWidth < averageWidth
182 | })
183 | let sumLarge = largeSegments.reduce(0, { (total, segment) -> CGFloat in
184 | return total + segment.segmentWidth
185 | })
186 | averageWidth = (self.scrollView.frame.width - (self.enableSeparator && self.style != .rainbow ? CGFloat(self.innerSegments.count) * self.separatorWidth : 0) - sumLarge) / CGFloat(smallSegments.count)
187 | for segment in smallSegments {
188 | segment.segmentWidth = averageWidth
189 | }
190 | for (index, segment) in self.innerSegments.enumerated() {
191 | segment.segmentFrame = self.segmentFrame(index)
192 | segment.segmentFrame.origin.x += self.separatorWidth / 2
193 | }
194 | }
195 | } else {
196 | self.scrollView.contentInset = UIEdgeInsets.zero
197 | }
198 |
199 | // Add Touch View
200 | touchView.frame = CGRect(origin: CGPoint.zero, size: self.scrollView.contentSize)
201 |
202 | // Add Segment SubLayers
203 | for (index, segment) in self.innerSegments.enumerated() {
204 | let content_x = segment.segmentFrame.origin.x + (segment.segmentFrame.width - segment.contentSize.width) / 2
205 | let content_y = (self.scrollView.frame.height - segment.contentSize.height) / 2
206 | let content_frame = CGRect(x: content_x, y: content_y, width: segment.contentSize.width, height: segment.contentSize.height)
207 |
208 | // Add Decoration Layer
209 | switch self.style {
210 | case .rainbow:
211 | let layerStrip = CALayer()
212 | layerStrip.frame = CGRect(x: segment.segmentFrame.origin.x, y: index == self.selectedIndex ? 0 : segment.segmentFrame.height - self.rainbow_height, width: segment.segmentFrame.width, height: index == self.selectedIndex ? self.scrollView.frame.height : self.rainbow_height)
213 | if self.rainbow_colors.isEmpty == false {
214 | layerStrip.backgroundColor = self.rainbow_colors[index % self.rainbow_colors.count].cgColor
215 | }
216 | layerContainer.addSublayer(layerStrip)
217 | self.switchRoundCornerForLayer(layerStrip, isRoundCorner: index == self.selectedIndex)
218 | segment.layerStrip = layerStrip
219 | default:
220 | break
221 | }
222 |
223 | // Add Content Layer
224 | switch segment.content.type {
225 | case let .text(text):
226 | let layerText = CATextLayer()
227 | layerText.string = text
228 | let font = segmentTextBold ? UIFont.boldSystemFont(ofSize: self.segmentTextFontSize) : UIFont.systemFont(ofSize: self.segmentTextFontSize)
229 | layerText.font = CGFont(NSString(string:font.fontName))
230 | layerText.fontSize = font.pointSize
231 | layerText.frame = content_frame
232 | layerText.alignmentMode = kCAAlignmentCenter
233 | layerText.truncationMode = kCATruncationEnd
234 | layerText.contentsScale = UIScreen.main.scale
235 | layerText.foregroundColor = index == self.selectedIndex ? self.segmentForegroundColorSelected.cgColor : self.segmentForegroundColor.cgColor
236 | layerContainer.addSublayer(layerText)
237 | segment.layerText = layerText
238 | case let .icon(icon):
239 | let layerIcon = CALayer()
240 | let image = icon
241 | layerIcon.frame = content_frame
242 | layerIcon.contents = image.cgImage
243 | layerContainer.addSublayer(layerIcon)
244 | segment.layerIcon = layerIcon
245 | }
246 | }
247 |
248 | // Add Indicator Layer
249 | let initLayerSeparator = { [unowned self] in
250 | let layerSeparator = CALayer()
251 | layerSeparator.frame = CGRect(x: 0, y: 0, width: self.scrollView.contentSize.width, height: self.scrollView.contentSize.height)
252 | layerSeparator.backgroundColor = self.separatorColor.cgColor
253 |
254 | let layerMask = CAShapeLayer()
255 | layerMask.fillColor = UIColor.white.cgColor
256 | let maskPath = UIBezierPath()
257 | for (index, segment) in self.innerSegments.enumerated() {
258 | index < self.innerSegments.count - 1 ? maskPath.append(UIBezierPath(rect: CGRect(x: segment.segmentFrame.maxX + self.separatorEdgeInsets.left, y: self.separatorEdgeInsets.top, width: self.separatorWidth - self.separatorEdgeInsets.left - self.separatorEdgeInsets.right, height: self.scrollView.frame.height - self.separatorEdgeInsets.top - self.separatorEdgeInsets.bottom))) : ()
259 | }
260 | layerMask.path = maskPath.cgPath
261 | layerSeparator.mask = layerMask
262 | self.layerContainer.addSublayer(layerSeparator)
263 | }
264 | let initLayerCover = { [unowned self] in
265 | self.layerCover.frame = self.indicatorCoverFrame(self.selectedIndex)
266 | self.layerCover.backgroundColor = self.cover_color.cgColor
267 | self.layerCover.opacity = self.cover_opacity
268 | self.layerContainer.addSublayer(self.layerCover)
269 | }
270 | let addLayerOutside = { [unowned self] in
271 | let outsideLayerLeft = CALayer()
272 | outsideLayerLeft.frame = CGRect(x: -1 * self.scrollView.frame.width, y: self.scrollView.frame.height - self.rainbow_height, width: self.scrollView.frame.width, height: self.rainbow_height)
273 | outsideLayerLeft.backgroundColor = self.rainbow_outsideColor.cgColor
274 | self.layerContainer.addSublayer(outsideLayerLeft)
275 |
276 | let outsideLayerRight = CALayer()
277 | outsideLayerRight.frame = CGRect(x: self.scrollView.contentSize.width, y: self.scrollView.frame.height - self.rainbow_height, width: self.scrollView.frame.width, height: self.rainbow_height)
278 | outsideLayerRight.backgroundColor = self.rainbow_outsideColor.cgColor
279 | self.layerContainer.addSublayer(outsideLayerRight)
280 | }
281 | let addLayerSlideway = { [unowned self] (slidewayPosition: CGFloat, slidewayHeight: CGFloat, slidewayColor: UIColor) in
282 | let layerSlideway = CALayer()
283 | layerSlideway.frame = CGRect(x: -1 * self.scrollView.frame.width, y: slidewayPosition - slidewayHeight / 2, width: self.scrollView.contentSize.width + self.scrollView.frame.width * 2, height: slidewayHeight)
284 | layerSlideway.backgroundColor = slidewayColor.cgColor
285 | self.layerContainer.addSublayer(layerSlideway)
286 | }
287 | let initLayerStrip = { [unowned self] (stripFrame: CGRect, stripColor: UIColor) in
288 | self.layerStrip.frame = stripFrame
289 | self.layerStrip.backgroundColor = stripColor.cgColor
290 | self.layerContainer.addSublayer(self.layerStrip)
291 | }
292 | let initLayerArrow = { [unowned self] (arrowFrame: CGRect, arrowLocation: WBSegmentIndicatorLocation, arrowColor: UIColor) in
293 | self.layerArrow.frame = arrowFrame
294 | self.layerArrow.backgroundColor = arrowColor.cgColor
295 |
296 | let layerMask = CAShapeLayer()
297 | layerMask.fillColor = UIColor.white.cgColor
298 | let maskPath = UIBezierPath()
299 | var pointA = CGPoint.zero
300 | var pointB = CGPoint.zero
301 | var pointC = CGPoint.zero
302 | switch arrowLocation {
303 | case .up:
304 | pointA = CGPoint(x: 0, y: 0)
305 | pointB = CGPoint(x: self.layerArrow.bounds.width, y: 0)
306 | pointC = CGPoint(x: self.layerArrow.bounds.width / 2, y: self.layerArrow.bounds.height)
307 | case .down:
308 | pointA = CGPoint(x: 0, y: self.layerArrow.bounds.height)
309 | pointB = CGPoint(x: self.layerArrow.bounds.width, y: self.layerArrow.bounds.height)
310 | pointC = CGPoint(x: self.layerArrow.bounds.width / 2, y: 0)
311 | }
312 | maskPath.move(to: pointA)
313 | maskPath.addLine(to: pointB)
314 | maskPath.addLine(to: pointC)
315 | maskPath.close()
316 | layerMask.path = maskPath.cgPath
317 | self.layerArrow.mask = layerMask
318 |
319 | self.layerContainer.addSublayer(self.layerArrow)
320 | }
321 | switch self.style {
322 | case .cover:
323 | initLayerCover()
324 | self.enableSeparator ? initLayerSeparator() : ()
325 | case .strip:
326 | let strip_frame = self.indicatorStripFrame(self.selectedIndex, stripHeight: self.strip_height, stripLocation: self.strip_location, stripRange: self.strip_range)
327 | self.enableSlideway ? addLayerSlideway(strip_frame.midY, self.slidewayHeight, self.slidewayColor) : ()
328 | initLayerStrip(strip_frame, self.strip_color)
329 | self.enableSeparator ? initLayerSeparator() : ()
330 | case .rainbow:
331 | addLayerOutside()
332 | case .arrow:
333 | let arrow_frame = self.indicatorArrowFrame(self.selectedIndex, arrowLocation: self.arrow_location, arrowSize: self.arrow_size)
334 | var slideway_y: CGFloat = 0
335 | switch self.arrow_location {
336 | case .up:
337 | slideway_y = arrow_frame.origin.y + self.slidewayHeight / 2
338 | case .down:
339 | slideway_y = arrow_frame.maxY - self.slidewayHeight / 2
340 | }
341 | self.enableSlideway ? addLayerSlideway(slideway_y, self.slidewayHeight, self.slidewayColor) : ()
342 | initLayerArrow(arrow_frame, self.arrow_location, self.arrow_color)
343 | self.enableSeparator ? initLayerSeparator() : ()
344 | case .arrowStrip:
345 | let strip_frame = self.indicatorStripFrame(self.selectedIndex, stripHeight: self.arrowStrip_stripHeight, stripLocation: self.arrowStrip_location, stripRange: self.arrowStrip_stripRange)
346 | self.enableSlideway ? addLayerSlideway(strip_frame.midY, self.slidewayHeight, self.slidewayColor) : ()
347 | initLayerStrip(strip_frame, self.arrowStrip_color)
348 | let arrow_frame = self.indicatorArrowFrame(self.selectedIndex, arrowLocation: self.arrowStrip_location, arrowSize: self.arrowStrip_arrowSize)
349 | initLayerArrow(arrow_frame, self.arrowStrip_location, self.arrowStrip_color)
350 | self.enableSeparator ? initLayerSeparator() : ()
351 | }
352 | }
353 |
354 | // MARK: Custom methods
355 | func selectedIndexChanged(_ newIndex: Int, oldIndex: Int) {
356 | if self.enableAnimation && validIndex(oldIndex) {
357 | CATransaction.begin()
358 | CATransaction.setAnimationDuration(self.animationDuration)
359 | CATransaction.setAnimationTimingFunction(CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear))
360 | CATransaction.setCompletionBlock({ [unowned self] in
361 | switch self.style {
362 | case .rainbow:
363 | if self.validIndex(oldIndex) {
364 | self.switchRoundCornerForLayer(self.innerSegments[oldIndex].layerStrip!, isRoundCorner: false)
365 | }
366 | default:
367 | break
368 | }
369 | })
370 | self.scrollView.contentSize.width > self.scrollView.frame.width ? self.scrollToSegment(newIndex) : ()
371 | self.didSelectedIndexChanged(newIndex, oldIndex: oldIndex)
372 | CATransaction.commit()
373 | } else {
374 | self.didSelectedIndexChanged(newIndex, oldIndex: oldIndex)
375 | }
376 |
377 | self.sendActions(for: .valueChanged)
378 | }
379 |
380 | func didSelectedIndexChanged(_ newIndex: Int, oldIndex: Int) {
381 | switch style {
382 | case .cover:
383 | self.layerCover.actions = nil
384 | self.layerCover.frame = self.indicatorCoverFrame(newIndex)
385 | case .strip:
386 | self.layerStrip.actions = nil
387 | self.layerStrip.frame = self.indicatorStripFrame(newIndex, stripHeight: self.strip_height, stripLocation: self.strip_location, stripRange: self.strip_range)
388 | case .rainbow:
389 | if validIndex(oldIndex), let old_StripLayer = self.innerSegments[oldIndex].layerStrip {
390 | let old_StripFrame = old_StripLayer.frame
391 | old_StripLayer.frame = CGRect(x: old_StripFrame.origin.x, y: self.scrollView.frame.height - self.strip_height, width: old_StripFrame.width, height: self.strip_height)
392 | }
393 | if let new_StripLayer = self.innerSegments[newIndex].layerStrip {
394 | let new_StripFrame = new_StripLayer.frame
395 | new_StripLayer.frame = CGRect(x: new_StripFrame.origin.x, y: 0, width: new_StripFrame.width, height: self.scrollView.frame.height)
396 | self.switchRoundCornerForLayer(new_StripLayer, isRoundCorner: true)
397 | }
398 | case .arrow:
399 | self.layerArrow.actions = nil
400 | self.layerArrow.frame = self.indicatorArrowFrame(newIndex, arrowLocation: self.arrow_location, arrowSize: self.arrow_size)
401 | case .arrowStrip:
402 | self.layerStrip.actions = nil
403 | self.layerStrip.frame = self.indicatorStripFrame(newIndex, stripHeight: self.arrowStrip_stripHeight, stripLocation: self.arrowStrip_location, stripRange: self.arrowStrip_stripRange)
404 | self.layerArrow.actions = nil
405 | self.layerArrow.frame = self.indicatorArrowFrame(newIndex, arrowLocation: self.arrowStrip_location, arrowSize: self.arrowStrip_arrowSize)
406 | }
407 |
408 | if validIndex(oldIndex) {
409 | switch self.innerSegments[oldIndex].content.type {
410 | case .text:
411 | if let old_contentLayer = self.innerSegments[oldIndex].layerText as? CATextLayer {
412 | old_contentLayer.foregroundColor = self.segmentForegroundColor.cgColor
413 | }
414 | default:
415 | break
416 | }
417 | }
418 | switch self.innerSegments[newIndex].content.type {
419 | case .text:
420 | if let new_contentLayer = self.innerSegments[newIndex].layerText as? CATextLayer {
421 | new_contentLayer.foregroundColor = self.segmentForegroundColorSelected.cgColor
422 | }
423 | default:
424 | break
425 | }
426 | }
427 |
428 | func switchRoundCornerForLayer(_ layer: CALayer, isRoundCorner: Bool) {
429 | if isRoundCorner {
430 | let layerMask = CAShapeLayer()
431 | layerMask.fillColor = UIColor.white.cgColor
432 | layerMask.path = UIBezierPath(roundedRect: CGRect(origin: CGPoint.zero, size: layer.frame.size), byRoundingCorners: [.topLeft, .topRight], cornerRadii: CGSize(width: self.rainbow_roundCornerRadius, height: self.rainbow_roundCornerRadius)).cgPath
433 | layer.mask = layerMask
434 | } else {
435 | layer.mask = nil
436 | }
437 | }
438 |
439 | func scrollToSegment(_ index: Int) {
440 | let segmentFrame = self.innerSegments[index].segmentFrame
441 | let targetRect = CGRect(x: segmentFrame.origin.x - (self.scrollView.frame.width - segmentFrame.width) / 2, y: 0, width: self.scrollView.frame.width, height: self.scrollView.frame.height)
442 | self.scrollView.scrollRectToVisible(targetRect, animated: true)
443 | }
444 |
445 | func segmentContentSize(_ segment: WBInnerSegment) -> CGSize {
446 | var size = CGSize.zero
447 | switch segment.content.type {
448 | case let .text(text):
449 | size = (text as NSString).size(attributes: [
450 | NSFontAttributeName: segmentTextBold ? UIFont.boldSystemFont(ofSize: self.segmentTextFontSize) : UIFont.systemFont(ofSize: self.segmentTextFontSize)
451 | ])
452 | case let .icon(icon):
453 | size = icon.size
454 | }
455 | return CGSize(width: ceil(size.width), height: ceil(size.height))
456 | }
457 |
458 | func segmentFrame(_ index: Int) -> CGRect {
459 | var segmentOffset: CGFloat = (self.enableSeparator && self.style != .rainbow ? self.separatorWidth / 2 : 0)
460 | for (idx, segment) in self.innerSegments.enumerated() {
461 | if idx == index {
462 | break
463 | } else {
464 | segmentOffset += segment.segmentWidth + (self.enableSeparator && self.style != .rainbow ? self.separatorWidth : 0)
465 | }
466 | }
467 | return CGRect(x: segmentOffset , y: 0, width: self.innerSegments[index].segmentWidth, height: self.scrollView.frame.height)
468 | }
469 |
470 | func indicatorCoverFrame(_ index: Int) -> CGRect {
471 | if validIndex(index) {
472 | var box_x: CGFloat = self.innerSegments[index].segmentFrame.origin.x
473 | var box_width: CGFloat = 0
474 | switch self.cover_range {
475 | case .content:
476 | box_x += (self.innerSegments[index].segmentWidth - self.innerSegments[index].contentSize.width) / 2
477 | box_width = self.innerSegments[index].contentSize.width
478 | case .segment:
479 | box_width = self.innerSegments[index].segmentWidth
480 | }
481 | return CGRect(x: box_x, y: 0, width: box_width, height: self.scrollView.frame.height)
482 | } else {
483 | return CGRect.zero
484 | }
485 | }
486 |
487 | func indicatorStripFrame(_ index: Int, stripHeight: CGFloat, stripLocation: WBSegmentIndicatorLocation, stripRange: WBSegmentIndicatorRange) -> CGRect {
488 | if validIndex(index) {
489 | var strip_x: CGFloat = self.innerSegments[index].segmentFrame.origin.x
490 | var strip_y: CGFloat = 0
491 | var strip_width: CGFloat = 0
492 | switch stripLocation {
493 | case .down:
494 | strip_y = self.innerSegments[index].segmentFrame.height - stripHeight
495 | case .up:
496 | strip_y = 0
497 | }
498 | switch stripRange {
499 | case .content:
500 | strip_width = self.innerSegments[index].contentSize.width
501 | strip_x += (self.innerSegments[index].segmentWidth - strip_width) / 2
502 | case .segment:
503 | strip_width = self.innerSegments[index].segmentWidth
504 | }
505 | return CGRect(x: strip_x, y: strip_y, width: strip_width, height: stripHeight)
506 | } else {
507 | return CGRect.zero
508 | }
509 | }
510 |
511 | func indicatorArrowFrame(_ index: Int, arrowLocation: WBSegmentIndicatorLocation, arrowSize: CGSize) -> CGRect {
512 | if validIndex(index) {
513 | let arrow_x: CGFloat = self.innerSegments[index].segmentFrame.origin.x + (self.innerSegments[index].segmentFrame.width - arrowSize.width) / 2
514 | var arrow_y: CGFloat = 0
515 | switch arrowLocation {
516 | case .up:
517 | arrow_y = 0
518 | case .down:
519 | arrow_y = self.innerSegments[index].segmentFrame.height - self.arrow_size.height
520 | }
521 | return CGRect(x: arrow_x, y: arrow_y, width: arrowSize.width, height: arrowSize.height)
522 | } else {
523 | return CGRect.zero
524 | }
525 | }
526 |
527 | func indexForTouch(_ location: CGPoint) -> Int {
528 | var touch_offset_x = location.x
529 | var touch_index = 0
530 | for (index, segment) in self.innerSegments.enumerated() {
531 | touch_offset_x -= segment.segmentWidth + (self.enableSeparator && self.style != .rainbow ? self.separatorWidth : 0)
532 | if touch_offset_x < 0 {
533 | touch_index = index
534 | break
535 | }
536 | }
537 | return touch_index
538 | }
539 |
540 | func validIndex(_ index: Int) -> Bool {
541 | return index >= 0 && index < segments.count
542 | }
543 | }
544 |
545 | extension WBSegmentControl: WBTouchViewDelegate {
546 | public func didTouch(_ location: CGPoint) {
547 | selectedIndex = indexForTouch(location)
548 | }
549 | }
550 |
551 | class WBInnerSegment {
552 |
553 | let content: WBSegmentContentProtocol
554 |
555 | var segmentFrame: CGRect = CGRect.zero
556 | var segmentWidth: CGFloat = 0
557 | var contentSize: CGSize = CGSize.zero
558 |
559 | var layerText: CALayer!
560 | var layerIcon: CALayer!
561 | var layerStrip: CALayer!
562 |
563 | init(content: WBSegmentContentProtocol) {
564 | self.content = content
565 | }
566 | }
567 |
568 | public enum WBSegmentType {
569 | case text(String)
570 | case icon(UIImage)
571 | }
572 |
573 | public enum WBSegmentIndicatorStyle {
574 | case cover, strip, rainbow, arrow, arrowStrip
575 | }
576 |
577 | public enum WBSegmentIndicatorLocation {
578 | case up, down
579 | }
580 |
581 | public enum WBSegmentIndicatorRange {
582 | case content, segment
583 | }
584 |
585 | public enum WBSegmentNonScrollDistributionStyle {
586 | case center, left, right, average
587 | }
588 |
589 | class WBTouchView: UIView {
590 |
591 | var delegate: WBTouchViewDelegate?
592 |
593 | override func touchesEnded(_ touches: Set, with event: UIEvent?) {
594 | if let touch = touches.first {
595 | delegate?.didTouch(touch.location(in: self))
596 | }
597 | }
598 | }
599 |
--------------------------------------------------------------------------------
/Framework/WBSegmentControl/WBSegmentControl.swift.orig:
--------------------------------------------------------------------------------
1 | //
2 | // CustomSegmentControl2.swift
3 | // TrafficSecretary
4 | //
5 | // Created by 王继荣 on 4/9/16.
6 | // Copyright © 2016 wonderbear. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | public protocol WBSegmentControlDelegate: class {
12 | func segmentControl(_ segmentControl: WBSegmentControl, selectIndex newIndex: Int, oldIndex: Int)
13 | }
14 |
15 | public protocol WBSegmentContentProtocol {
16 | var type: WBSegmentType { get }
17 | }
18 |
19 | public protocol WBTouchViewDelegate {
20 | func didTouch(_ location: CGPoint)
21 | }
22 |
23 | public class WBSegmentControl: UIControl {
24 |
25 | // MARK: Configuration - Content
26 | public var segments: [WBSegmentContentProtocol] = [] {
27 | didSet {
28 | innerSegments = segments.map({ (content) -> WBInnerSegment in
29 | return WBInnerSegment(content: content)
30 | })
31 | self.setNeedsLayout()
32 | if segments.count == 0 {
33 | selectedIndex = -1
34 | }
35 | }
36 | }
37 | var innerSegments: [WBInnerSegment] = []
38 |
39 | // MARK: Configuration - Interaction
40 | <<<<<<< HEAD
41 | public var delegate: WBSegmentControlDelegate?
42 | public var selectedIndex: Int = -1 {
43 | =======
44 | public weak var delegate: WBSegmentControlDelegate?
45 | public var selectedIndex: Int = 0 {
46 | >>>>>>> daee6619dc33562f676bb2bd4af3be0204273206
47 | didSet {
48 | if selectedIndex != oldValue && validIndex(selectedIndex) {
49 | selectedIndexChanged(selectedIndex, oldIndex: oldValue)
50 | delegate?.segmentControl(self, selectIndex: selectedIndex, oldIndex: oldValue)
51 | }
52 | }
53 | }
54 | public var selectedSegment: WBSegmentContentProtocol? {
55 | return validIndex(selectedIndex) ? segments[selectedIndex] : nil
56 | }
57 |
58 | // MARK: Configuration - Appearance
59 | public var style: WBSegmentIndicatorStyle = .rainbow
60 | public var nonScrollDistributionStyle: WBSegmentNonScrollDistributionStyle = .average
61 | public var enableSeparator: Bool = false
62 | public var separatorColor: UIColor = UIColor.black
63 | public var separatorWidth: CGFloat = 9
64 | public var separatorEdgeInsets: UIEdgeInsets = UIEdgeInsets(top: 8, left: 4, bottom: 8, right: 4)
65 | public var enableSlideway: Bool = false
66 | public var slidewayHeight: CGFloat = 1
67 | public var slidewayColor: UIColor = UIColor.lightGray
68 | public var enableAnimation: Bool = true
69 | public var animationDuration: TimeInterval = 0.15
70 | public var segmentMinWidth: CGFloat = 50
71 | public var segmentEdgeInsets: UIEdgeInsets = UIEdgeInsets(top: 0, left: 10, bottom: 0, right: 10)
72 | public var segmentTextBold: Bool = true
73 | public var segmentTextFontSize: CGFloat = 12
74 | public var segmentForegroundColor: UIColor = UIColor.gray
75 | public var segmentForegroundColorSelected: UIColor = UIColor.black
76 |
77 | // Settings - Cover
78 | public typealias CoverRange = WBSegmentIndicatorRange
79 |
80 | public var cover_range: CoverRange = .segment
81 | public var cover_opacity: Float = 0.2
82 | public var cover_color: UIColor = UIColor.black
83 |
84 | // Settings - Strip
85 | public typealias StripRange = WBSegmentIndicatorRange
86 | public typealias StripLocation = WBSegmentIndicatorLocation
87 |
88 | public var strip_range: StripRange = .content
89 | public var strip_location: StripLocation = .down
90 | public var strip_color: UIColor = UIColor.orange
91 | public var strip_height: CGFloat = 3
92 |
93 | // Settings - Rainbow
94 | public typealias RainbowLocation = WBSegmentIndicatorLocation
95 |
96 | public var rainbow_colors: [UIColor] = []
97 | public var rainbow_height: CGFloat = 3
98 | public var rainbow_roundCornerRadius: CGFloat = 4
99 | public var rainbow_location: RainbowLocation = .down
100 | public var rainbow_outsideColor: UIColor = UIColor.gray
101 |
102 | // Settings - Arrow
103 | public typealias ArrowLocation = WBSegmentIndicatorLocation
104 |
105 | public var arrow_size: CGSize = CGSize(width: 6, height: 6)
106 | public var arrow_location: ArrowLocation = .down
107 | public var arrow_color: UIColor = UIColor.orange
108 |
109 | // Settings - ArrowStrip
110 | public typealias ArrowStripLocation = WBSegmentIndicatorLocation
111 | public typealias ArrowStripRange = WBSegmentIndicatorRange
112 |
113 | public var arrowStrip_location: ArrowStripLocation = .up
114 | public var arrowStrip_color: UIColor = UIColor.orange
115 | public var arrowStrip_arrowSize: CGSize = CGSize(width: 6, height: 6)
116 | public var arrowStrip_stripHeight: CGFloat = 2
117 | public var arrowStrip_stripRange: ArrowStripRange = .content
118 |
119 | // MARK: Inner properties
120 | fileprivate var scrollView: UIScrollView!
121 | fileprivate var touchView: WBTouchView = WBTouchView()
122 | fileprivate var layerContainer: CALayer = CALayer()
123 | fileprivate var layerCover: CALayer = CALayer()
124 | fileprivate var layerStrip: CALayer = CALayer()
125 | fileprivate var layerArrow: CALayer = CALayer()
126 | fileprivate var segmentControlContentWidth: CGFloat {
127 | let sum = self.innerSegments.reduce(0, { (max_x, segment) -> CGFloat in
128 | return max(max_x, segment.segmentFrame.maxX)
129 | })
130 | return sum + ((self.enableSeparator && self.style != .rainbow) ? self.separatorWidth / 2 : 0)
131 | }
132 |
133 | // MARK: Initialization
134 | override init(frame: CGRect) {
135 | super.init(frame: frame)
136 |
137 | scrollView = UIScrollView()
138 | self.addSubview(scrollView)
139 | scrollView.translatesAutoresizingMaskIntoConstraints = false
140 | self.addConstraint(NSLayoutConstraint(item: scrollView, attribute: .top, relatedBy: .equal, toItem: self, attribute: .top, multiplier: 1, constant: 0))
141 | self.addConstraint(NSLayoutConstraint(item: scrollView, attribute: .bottom, relatedBy: .equal, toItem: self, attribute: .bottom, multiplier: 1, constant: 0))
142 | self.addConstraint(NSLayoutConstraint(item: scrollView, attribute: .left, relatedBy: .equal, toItem: self, attribute: .left, multiplier: 1, constant: 0))
143 | self.addConstraint(NSLayoutConstraint(item: scrollView, attribute: .right, relatedBy: .equal, toItem: self, attribute: .right, multiplier: 1, constant: 0))
144 | scrollView.showsHorizontalScrollIndicator = false
145 | scrollView.showsVerticalScrollIndicator = false
146 | scrollView.layer.addSublayer(layerContainer)
147 |
148 | scrollView.addSubview(touchView)
149 | touchView.delegate = self
150 | }
151 |
152 | required public init?(coder aDecoder: NSCoder) {
153 | fatalError("init(coder:) has not been implemented")
154 | }
155 |
156 | // MARK: Override methods
157 | override public func layoutSubviews() {
158 | super.layoutSubviews()
159 | layerContainer.sublayers?.removeAll()
160 |
161 | // Compute Segment Size
162 | for (index, segment) in self.innerSegments.enumerated() {
163 | segment.contentSize = self.segmentContentSize(segment)
164 | segment.segmentWidth = max(segment.contentSize.width + self.segmentEdgeInsets.left + self.segmentEdgeInsets.right, self.segmentMinWidth)
165 | segment.segmentFrame = self.segmentFrame(index)
166 | }
167 |
168 | // Adjust Control Content Size & Segment Size
169 | self.scrollView.contentSize = CGSize(width: self.segmentControlContentWidth, height: self.scrollView.frame.height)
170 | if self.scrollView.contentSize.width < self.scrollView.frame.width {
171 | switch self.nonScrollDistributionStyle {
172 | case .center:
173 | self.scrollView.contentInset = UIEdgeInsets(top: 0, left: (self.scrollView.frame.width - self.scrollView.contentSize.width) / 2, bottom: 0, right: 0)
174 | case .left:
175 | self.scrollView.contentInset = UIEdgeInsets.zero
176 | case .right:
177 | self.scrollView.contentInset = UIEdgeInsets(top: 0, left: self.scrollView.frame.width - self.scrollView.contentSize.width, bottom: 0, right: 0)
178 | case .average:
179 | self.scrollView.contentInset = UIEdgeInsets.zero
180 | self.scrollView.contentSize = self.scrollView.frame.size
181 | var averageWidth: CGFloat = (self.scrollView.frame.width - (self.enableSeparator && self.style != .rainbow ? CGFloat(self.innerSegments.count) * self.separatorWidth : 0)) / CGFloat(self.innerSegments.count)
182 | let largeSegments = self.innerSegments.filter({ (segment) -> Bool in
183 | return segment.segmentWidth >= averageWidth
184 | })
185 | let smallSegments = self.innerSegments.filter({ (segment) -> Bool in
186 | return segment.segmentWidth < averageWidth
187 | })
188 | let sumLarge = largeSegments.reduce(0, { (total, segment) -> CGFloat in
189 | return total + segment.segmentWidth
190 | })
191 | averageWidth = (self.scrollView.frame.width - (self.enableSeparator && self.style != .rainbow ? CGFloat(self.innerSegments.count) * self.separatorWidth : 0) - sumLarge) / CGFloat(smallSegments.count)
192 | for segment in smallSegments {
193 | segment.segmentWidth = averageWidth
194 | }
195 | for (index, segment) in self.innerSegments.enumerated() {
196 | segment.segmentFrame = self.segmentFrame(index)
197 | segment.segmentFrame.origin.x += self.separatorWidth / 2
198 | }
199 | }
200 | } else {
201 | self.scrollView.contentInset = UIEdgeInsets.zero
202 | }
203 |
204 | // Add Touch View
205 | touchView.frame = CGRect(origin: CGPoint.zero, size: self.scrollView.contentSize)
206 |
207 | // Add Segment SubLayers
208 | for (index, segment) in self.innerSegments.enumerated() {
209 | let content_x = segment.segmentFrame.origin.x + (segment.segmentFrame.width - segment.contentSize.width) / 2
210 | let content_y = (self.scrollView.frame.height - segment.contentSize.height) / 2
211 | let content_frame = CGRect(x: content_x, y: content_y, width: segment.contentSize.width, height: segment.contentSize.height)
212 |
213 | // Add Decoration Layer
214 | switch self.style {
215 | case .rainbow:
216 | let layerStrip = CALayer()
217 | layerStrip.frame = CGRect(x: segment.segmentFrame.origin.x, y: index == self.selectedIndex ? 0 : segment.segmentFrame.height - self.rainbow_height, width: segment.segmentFrame.width, height: index == self.selectedIndex ? self.scrollView.frame.height : self.rainbow_height)
218 | if self.rainbow_colors.isEmpty == false {
219 | layerStrip.backgroundColor = self.rainbow_colors[index % self.rainbow_colors.count].cgColor
220 | }
221 | layerContainer.addSublayer(layerStrip)
222 | self.switchRoundCornerForLayer(layerStrip, isRoundCorner: index == self.selectedIndex)
223 | segment.layerStrip = layerStrip
224 | default:
225 | break
226 | }
227 |
228 | // Add Content Layer
229 | switch segment.content.type {
230 | case let .text(text):
231 | let layerText = CATextLayer()
232 | layerText.string = text
233 | let font = segmentTextBold ? UIFont.boldSystemFont(ofSize: self.segmentTextFontSize) : UIFont.systemFont(ofSize: self.segmentTextFontSize)
234 | layerText.font = CGFont(NSString(string:font.fontName))
235 | layerText.fontSize = font.pointSize
236 | layerText.frame = content_frame
237 | layerText.alignmentMode = kCAAlignmentCenter
238 | layerText.truncationMode = kCATruncationEnd
239 | layerText.contentsScale = UIScreen.main.scale
240 | layerText.foregroundColor = index == self.selectedIndex ? self.segmentForegroundColorSelected.cgColor : self.segmentForegroundColor.cgColor
241 | layerContainer.addSublayer(layerText)
242 | segment.layerText = layerText
243 | case let .icon(icon):
244 | let layerIcon = CALayer()
245 | let image = icon
246 | layerIcon.frame = content_frame
247 | layerIcon.contents = image.cgImage
248 | layerContainer.addSublayer(layerIcon)
249 | segment.layerIcon = layerIcon
250 | }
251 | }
252 |
253 | // Add Indicator Layer
254 | let initLayerSeparator = { [unowned self] in
255 | let layerSeparator = CALayer()
256 | layerSeparator.frame = CGRect(x: 0, y: 0, width: self.scrollView.contentSize.width, height: self.scrollView.contentSize.height)
257 | layerSeparator.backgroundColor = self.separatorColor.cgColor
258 |
259 | let layerMask = CAShapeLayer()
260 | layerMask.fillColor = UIColor.white.cgColor
261 | let maskPath = UIBezierPath()
262 | for (index, segment) in self.innerSegments.enumerated() {
263 | index < self.innerSegments.count - 1 ? maskPath.append(UIBezierPath(rect: CGRect(x: segment.segmentFrame.maxX + self.separatorEdgeInsets.left, y: self.separatorEdgeInsets.top, width: self.separatorWidth - self.separatorEdgeInsets.left - self.separatorEdgeInsets.right, height: self.scrollView.frame.height - self.separatorEdgeInsets.top - self.separatorEdgeInsets.bottom))) : ()
264 | }
265 | layerMask.path = maskPath.cgPath
266 | layerSeparator.mask = layerMask
267 | self.layerContainer.addSublayer(layerSeparator)
268 | }
269 | let initLayerCover = { [unowned self] in
270 | self.layerCover.frame = self.indicatorCoverFrame(self.selectedIndex)
271 | self.layerCover.backgroundColor = self.cover_color.cgColor
272 | self.layerCover.opacity = self.cover_opacity
273 | self.layerContainer.addSublayer(self.layerCover)
274 | }
275 | let addLayerOutside = { [unowned self] in
276 | let outsideLayerLeft = CALayer()
277 | outsideLayerLeft.frame = CGRect(x: -1 * self.scrollView.frame.width, y: self.scrollView.frame.height - self.rainbow_height, width: self.scrollView.frame.width, height: self.rainbow_height)
278 | outsideLayerLeft.backgroundColor = self.rainbow_outsideColor.cgColor
279 | self.layerContainer.addSublayer(outsideLayerLeft)
280 |
281 | let outsideLayerRight = CALayer()
282 | outsideLayerRight.frame = CGRect(x: self.scrollView.contentSize.width, y: self.scrollView.frame.height - self.rainbow_height, width: self.scrollView.frame.width, height: self.rainbow_height)
283 | outsideLayerRight.backgroundColor = self.rainbow_outsideColor.cgColor
284 | self.layerContainer.addSublayer(outsideLayerRight)
285 | }
286 | let addLayerSlideway = { [unowned self] (slidewayPosition: CGFloat, slidewayHeight: CGFloat, slidewayColor: UIColor) in
287 | let layerSlideway = CALayer()
288 | layerSlideway.frame = CGRect(x: -1 * self.scrollView.frame.width, y: slidewayPosition - slidewayHeight / 2, width: self.scrollView.contentSize.width + self.scrollView.frame.width * 2, height: slidewayHeight)
289 | layerSlideway.backgroundColor = slidewayColor.cgColor
290 | self.layerContainer.addSublayer(layerSlideway)
291 | }
292 | let initLayerStrip = { [unowned self] (stripFrame: CGRect, stripColor: UIColor) in
293 | self.layerStrip.frame = stripFrame
294 | self.layerStrip.backgroundColor = stripColor.cgColor
295 | self.layerContainer.addSublayer(self.layerStrip)
296 | }
297 | let initLayerArrow = { [unowned self] (arrowFrame: CGRect, arrowLocation: WBSegmentIndicatorLocation, arrowColor: UIColor) in
298 | self.layerArrow.frame = arrowFrame
299 | self.layerArrow.backgroundColor = arrowColor.cgColor
300 |
301 | let layerMask = CAShapeLayer()
302 | layerMask.fillColor = UIColor.white.cgColor
303 | let maskPath = UIBezierPath()
304 | var pointA = CGPoint.zero
305 | var pointB = CGPoint.zero
306 | var pointC = CGPoint.zero
307 | switch arrowLocation {
308 | case .up:
309 | pointA = CGPoint(x: 0, y: 0)
310 | pointB = CGPoint(x: self.layerArrow.bounds.width, y: 0)
311 | pointC = CGPoint(x: self.layerArrow.bounds.width / 2, y: self.layerArrow.bounds.height)
312 | case .down:
313 | pointA = CGPoint(x: 0, y: self.layerArrow.bounds.height)
314 | pointB = CGPoint(x: self.layerArrow.bounds.width, y: self.layerArrow.bounds.height)
315 | pointC = CGPoint(x: self.layerArrow.bounds.width / 2, y: 0)
316 | }
317 | maskPath.move(to: pointA)
318 | maskPath.addLine(to: pointB)
319 | maskPath.addLine(to: pointC)
320 | maskPath.close()
321 | layerMask.path = maskPath.cgPath
322 | self.layerArrow.mask = layerMask
323 |
324 | self.layerContainer.addSublayer(self.layerArrow)
325 | }
326 | switch self.style {
327 | case .cover:
328 | initLayerCover()
329 | self.enableSeparator ? initLayerSeparator() : ()
330 | case .strip:
331 | let strip_frame = self.indicatorStripFrame(self.selectedIndex, stripHeight: self.strip_height, stripLocation: self.strip_location, stripRange: self.strip_range)
332 | self.enableSlideway ? addLayerSlideway(strip_frame.midY, self.slidewayHeight, self.slidewayColor) : ()
333 | initLayerStrip(strip_frame, self.strip_color)
334 | self.enableSeparator ? initLayerSeparator() : ()
335 | case .rainbow:
336 | addLayerOutside()
337 | case .arrow:
338 | let arrow_frame = self.indicatorArrowFrame(self.selectedIndex, arrowLocation: self.arrow_location, arrowSize: self.arrow_size)
339 | var slideway_y: CGFloat = 0
340 | switch self.arrow_location {
341 | case .up:
342 | slideway_y = arrow_frame.origin.y + self.slidewayHeight / 2
343 | case .down:
344 | slideway_y = arrow_frame.maxY - self.slidewayHeight / 2
345 | }
346 | self.enableSlideway ? addLayerSlideway(slideway_y, self.slidewayHeight, self.slidewayColor) : ()
347 | initLayerArrow(arrow_frame, self.arrow_location, self.arrow_color)
348 | self.enableSeparator ? initLayerSeparator() : ()
349 | case .arrowStrip:
350 | let strip_frame = self.indicatorStripFrame(self.selectedIndex, stripHeight: self.arrowStrip_stripHeight, stripLocation: self.arrowStrip_location, stripRange: self.arrowStrip_stripRange)
351 | self.enableSlideway ? addLayerSlideway(strip_frame.midY, self.slidewayHeight, self.slidewayColor) : ()
352 | initLayerStrip(strip_frame, self.arrowStrip_color)
353 | let arrow_frame = self.indicatorArrowFrame(self.selectedIndex, arrowLocation: self.arrowStrip_location, arrowSize: self.arrowStrip_arrowSize)
354 | initLayerArrow(arrow_frame, self.arrowStrip_location, self.arrowStrip_color)
355 | self.enableSeparator ? initLayerSeparator() : ()
356 | }
357 | }
358 |
359 | // MARK: Custom methods
360 | func selectedIndexChanged(_ newIndex: Int, oldIndex: Int) {
361 | if self.enableAnimation && validIndex(oldIndex) {
362 | CATransaction.begin()
363 | CATransaction.setAnimationDuration(self.animationDuration)
364 | CATransaction.setAnimationTimingFunction(CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear))
365 | CATransaction.setCompletionBlock({ [unowned self] in
366 | switch self.style {
367 | case .rainbow:
368 | if self.validIndex(oldIndex) {
369 | self.switchRoundCornerForLayer(self.innerSegments[oldIndex].layerStrip!, isRoundCorner: false)
370 | }
371 | default:
372 | break
373 | }
374 | })
375 | self.scrollView.contentSize.width > self.scrollView.frame.width ? self.scrollToSegment(newIndex) : ()
376 | self.didSelectedIndexChanged(newIndex, oldIndex: oldIndex)
377 | CATransaction.commit()
378 | } else {
379 | self.didSelectedIndexChanged(newIndex, oldIndex: oldIndex)
380 | }
381 |
382 | self.sendActions(for: .valueChanged)
383 | }
384 |
385 | func didSelectedIndexChanged(_ newIndex: Int, oldIndex: Int) {
386 | switch style {
387 | case .cover:
388 | self.layerCover.actions = nil
389 | self.layerCover.frame = self.indicatorCoverFrame(newIndex)
390 | case .strip:
391 | self.layerStrip.actions = nil
392 | self.layerStrip.frame = self.indicatorStripFrame(newIndex, stripHeight: self.strip_height, stripLocation: self.strip_location, stripRange: self.strip_range)
393 | case .rainbow:
394 | if validIndex(oldIndex), let old_StripLayer = self.innerSegments[oldIndex].layerStrip {
395 | let old_StripFrame = old_StripLayer.frame
396 | old_StripLayer.frame = CGRect(x: old_StripFrame.origin.x, y: self.scrollView.frame.height - self.strip_height, width: old_StripFrame.width, height: self.strip_height)
397 | }
398 | if let new_StripLayer = self.innerSegments[newIndex].layerStrip {
399 | let new_StripFrame = new_StripLayer.frame
400 | new_StripLayer.frame = CGRect(x: new_StripFrame.origin.x, y: 0, width: new_StripFrame.width, height: self.scrollView.frame.height)
401 | self.switchRoundCornerForLayer(new_StripLayer, isRoundCorner: true)
402 | }
403 | case .arrow:
404 | self.layerArrow.actions = nil
405 | self.layerArrow.frame = self.indicatorArrowFrame(newIndex, arrowLocation: self.arrow_location, arrowSize: self.arrow_size)
406 | case .arrowStrip:
407 | self.layerStrip.actions = nil
408 | self.layerStrip.frame = self.indicatorStripFrame(newIndex, stripHeight: self.arrowStrip_stripHeight, stripLocation: self.arrowStrip_location, stripRange: self.arrowStrip_stripRange)
409 | self.layerArrow.actions = nil
410 | self.layerArrow.frame = self.indicatorArrowFrame(newIndex, arrowLocation: self.arrowStrip_location, arrowSize: self.arrowStrip_arrowSize)
411 | }
412 |
413 | if validIndex(oldIndex) {
414 | switch self.innerSegments[oldIndex].content.type {
415 | case .text:
416 | if let old_contentLayer = self.innerSegments[oldIndex].layerText as? CATextLayer {
417 | old_contentLayer.foregroundColor = self.segmentForegroundColor.cgColor
418 | }
419 | default:
420 | break
421 | }
422 | }
423 | switch self.innerSegments[newIndex].content.type {
424 | case .text:
425 | if let new_contentLayer = self.innerSegments[newIndex].layerText as? CATextLayer {
426 | new_contentLayer.foregroundColor = self.segmentForegroundColorSelected.cgColor
427 | }
428 | default:
429 | break
430 | }
431 | }
432 |
433 | func switchRoundCornerForLayer(_ layer: CALayer, isRoundCorner: Bool) {
434 | if isRoundCorner {
435 | let layerMask = CAShapeLayer()
436 | layerMask.fillColor = UIColor.white.cgColor
437 | layerMask.path = UIBezierPath(roundedRect: CGRect(origin: CGPoint.zero, size: layer.frame.size), byRoundingCorners: [.topLeft, .topRight], cornerRadii: CGSize(width: self.rainbow_roundCornerRadius, height: self.rainbow_roundCornerRadius)).cgPath
438 | layer.mask = layerMask
439 | } else {
440 | layer.mask = nil
441 | }
442 | }
443 |
444 | func scrollToSegment(_ index: Int) {
445 | let segmentFrame = self.innerSegments[index].segmentFrame
446 | let targetRect = CGRect(x: segmentFrame.origin.x - (self.scrollView.frame.width - segmentFrame.width) / 2, y: 0, width: self.scrollView.frame.width, height: self.scrollView.frame.height)
447 | self.scrollView.scrollRectToVisible(targetRect, animated: true)
448 | }
449 |
450 | func segmentContentSize(_ segment: WBInnerSegment) -> CGSize {
451 | var size = CGSize.zero
452 | switch segment.content.type {
453 | case let .text(text):
454 | size = (text as NSString).size(attributes: [
455 | NSFontAttributeName: segmentTextBold ? UIFont.boldSystemFont(ofSize: self.segmentTextFontSize) : UIFont.systemFont(ofSize: self.segmentTextFontSize)
456 | ])
457 | case let .icon(icon):
458 | size = icon.size
459 | }
460 | return CGSize(width: ceil(size.width), height: ceil(size.height))
461 | }
462 |
463 | func segmentFrame(_ index: Int) -> CGRect {
464 | var segmentOffset: CGFloat = (self.enableSeparator && self.style != .rainbow ? self.separatorWidth / 2 : 0)
465 | for (idx, segment) in self.innerSegments.enumerated() {
466 | if idx == index {
467 | break
468 | } else {
469 | segmentOffset += segment.segmentWidth + (self.enableSeparator && self.style != .rainbow ? self.separatorWidth : 0)
470 | }
471 | }
472 | return CGRect(x: segmentOffset , y: 0, width: self.innerSegments[index].segmentWidth, height: self.scrollView.frame.height)
473 | }
474 |
475 | func indicatorCoverFrame(_ index: Int) -> CGRect {
476 | if validIndex(index) {
477 | var box_x: CGFloat = self.innerSegments[index].segmentFrame.origin.x
478 | var box_width: CGFloat = 0
479 | switch self.cover_range {
480 | case .content:
481 | box_x += (self.innerSegments[index].segmentWidth - self.innerSegments[index].contentSize.width) / 2
482 | box_width = self.innerSegments[index].contentSize.width
483 | case .segment:
484 | box_width = self.innerSegments[index].segmentWidth
485 | }
486 | return CGRect(x: box_x, y: 0, width: box_width, height: self.scrollView.frame.height)
487 | } else {
488 | return CGRect.zero
489 | }
490 | }
491 |
492 | func indicatorStripFrame(_ index: Int, stripHeight: CGFloat, stripLocation: WBSegmentIndicatorLocation, stripRange: WBSegmentIndicatorRange) -> CGRect {
493 | if validIndex(index) {
494 | var strip_x: CGFloat = self.innerSegments[index].segmentFrame.origin.x
495 | var strip_y: CGFloat = 0
496 | var strip_width: CGFloat = 0
497 | switch stripLocation {
498 | case .down:
499 | strip_y = self.innerSegments[index].segmentFrame.height - stripHeight
500 | case .up:
501 | strip_y = 0
502 | }
503 | switch stripRange {
504 | case .content:
505 | strip_width = self.innerSegments[index].contentSize.width
506 | strip_x += (self.innerSegments[index].segmentWidth - strip_width) / 2
507 | case .segment:
508 | strip_width = self.innerSegments[index].segmentWidth
509 | }
510 | return CGRect(x: strip_x, y: strip_y, width: strip_width, height: stripHeight)
511 | } else {
512 | return CGRect.zero
513 | }
514 | }
515 |
516 | func indicatorArrowFrame(_ index: Int, arrowLocation: WBSegmentIndicatorLocation, arrowSize: CGSize) -> CGRect {
517 | if validIndex(index) {
518 | let arrow_x: CGFloat = self.innerSegments[index].segmentFrame.origin.x + (self.innerSegments[index].segmentFrame.width - arrowSize.width) / 2
519 | var arrow_y: CGFloat = 0
520 | switch arrowLocation {
521 | case .up:
522 | arrow_y = 0
523 | case .down:
524 | arrow_y = self.innerSegments[index].segmentFrame.height - self.arrow_size.height
525 | }
526 | return CGRect(x: arrow_x, y: arrow_y, width: arrowSize.width, height: arrowSize.height)
527 | } else {
528 | return CGRect.zero
529 | }
530 | }
531 |
532 | func indexForTouch(_ location: CGPoint) -> Int {
533 | var touch_offset_x = location.x
534 | var touch_index = 0
535 | for (index, segment) in self.innerSegments.enumerated() {
536 | touch_offset_x -= segment.segmentWidth + (self.enableSeparator && self.style != .rainbow ? self.separatorWidth : 0)
537 | if touch_offset_x < 0 {
538 | touch_index = index
539 | break
540 | }
541 | }
542 | return touch_index
543 | }
544 |
545 | func validIndex(_ index: Int) -> Bool {
546 | return index >= 0 && index < segments.count
547 | }
548 | }
549 |
550 | extension WBSegmentControl: WBTouchViewDelegate {
551 | public func didTouch(_ location: CGPoint) {
552 | selectedIndex = indexForTouch(location)
553 | }
554 | }
555 |
556 | class WBInnerSegment {
557 |
558 | let content: WBSegmentContentProtocol
559 |
560 | var segmentFrame: CGRect = CGRect.zero
561 | var segmentWidth: CGFloat = 0
562 | var contentSize: CGSize = CGSize.zero
563 |
564 | var layerText: CALayer!
565 | var layerIcon: CALayer!
566 | var layerStrip: CALayer!
567 |
568 | init(content: WBSegmentContentProtocol) {
569 | self.content = content
570 | }
571 | }
572 |
573 | public enum WBSegmentType {
574 | case text(String)
575 | case icon(UIImage)
576 | }
577 |
578 | public enum WBSegmentIndicatorStyle {
579 | case cover, strip, rainbow, arrow, arrowStrip
580 | }
581 |
582 | public enum WBSegmentIndicatorLocation {
583 | case up, down
584 | }
585 |
586 | public enum WBSegmentIndicatorRange {
587 | case content, segment
588 | }
589 |
590 | public enum WBSegmentNonScrollDistributionStyle {
591 | case center, left, right, average
592 | }
593 |
594 | class WBTouchView: UIView {
595 |
596 | var delegate: WBTouchViewDelegate?
597 |
598 | override func touchesEnded(_ touches: Set, with event: UIEvent?) {
599 | if let touch = touches.first {
600 | delegate?.didTouch(touch.location(in: self))
601 | }
602 | }
603 | }
604 |
--------------------------------------------------------------------------------