├── .gitignore
├── .slather.yml
├── .swift-version
├── .swiftpm
└── xcode
│ └── package.xcworkspace
│ └── contents.xcworkspacedata
├── .travis.yml
├── Assets
├── demo_ipad_cursor.gif
├── demo_main.gif
├── logo-transparent-background.png
└── logo-white-background.png
├── BetterSegmentedControl.podspec
├── Example
├── BetterSegmentedControl.xcodeproj
│ ├── project.pbxproj
│ ├── project.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ │ └── IDEWorkspaceChecks.plist
│ └── xcshareddata
│ │ └── xcschemes
│ │ └── BetterSegmentedControl.xcscheme
├── BetterSegmentedControl.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
├── BetterSegmentedControl
│ ├── AppDelegate.swift
│ ├── Base.lproj
│ │ ├── LaunchScreen.xib
│ │ └── Main.storyboard
│ ├── Images.xcassets
│ │ ├── AppIcon.appiconset
│ │ │ └── Contents.json
│ │ ├── Contents.json
│ │ ├── facebook.imageset
│ │ │ ├── Contents.json
│ │ │ ├── icons8-facebook-100.png
│ │ │ └── icons8-facebook-50.png
│ │ └── twitter.imageset
│ │ │ ├── Contents.json
│ │ │ ├── icons8-twitter-100.png
│ │ │ └── icons8-twitter-50.png
│ ├── Info.plist
│ └── ViewController.swift
├── Podfile
├── Podfile.lock
└── Tests
│ ├── BetterSegmentedControlTests.swift
│ ├── Info.plist
│ ├── ReferenceImages
│ └── BetterSegmentedControlTests
│ │ ├── a_BetterSegmentedControl__its_appleStyled_extension__renders_correctly@3x.png
│ │ ├── a_BetterSegmentedControl__its_cornerRadius_property__the_control_renders_correctly_when_setting_it_to_0@3x.png
│ │ ├── a_BetterSegmentedControl__its_cornerRadius_property__the_control_renders_correctly_when_setting_it_to_10@3x.png
│ │ ├── a_BetterSegmentedControl__its_indicatorViewBackgroundColor_property__the_control_renders_correctly_after_updating_it@3x.png
│ │ ├── a_BetterSegmentedControl__its_indicatorViewBorderColor_property__the_control_renders_correctly_when_setting_it_to_green@3x.png
│ │ ├── a_BetterSegmentedControl__its_indicatorViewBorderWidth_property__the_control_renders_correctly_when_setting_it_to_4@3x.png
│ │ ├── a_BetterSegmentedControl__its_indicatorViewInset_property__the_control_renders_correctly_when_setting_it_to_0@3x.png
│ │ ├── a_BetterSegmentedControl__its_indicatorViewInset_property__the_control_renders_correctly_when_setting_it_to_4@3x.png
│ │ ├── a_BetterSegmentedControl__its_init_coder___initializer__when_called__when_an_expicit_size_is_set_in_Auto_Layout__the_control_renders_correctly@3x.png
│ │ ├── a_BetterSegmentedControl__its_init_coder___initializer__when_called__when_the_control_auto_sizes_itself_in_Auto_Layout__the_control_renders_correctly@3x.png
│ │ ├── a_BetterSegmentedControl__its_init_frame___initializer__when_called__the_control_renders_correctly@3x.png
│ │ ├── a_BetterSegmentedControl__its_init_frame_segments_index_options___initializer__when_calling_it__with_0_segments__the_control_renders_correctly@3x.png
│ │ ├── a_BetterSegmentedControl__its_init_frame_segments_index_options___initializer__when_calling_it__with_1_segment__the_control_renders_correctly@3x.png
│ │ ├── a_BetterSegmentedControl__its_init_frame_segments_index_options___initializer__when_calling_it__with_2_segments__the_control_renders_correctly@3x.png
│ │ ├── a_BetterSegmentedControl__its_init_frame_segments_index_options___initializer__when_calling_it__with_3_segments__the_control_renders_correctly@3x.png
│ │ ├── a_BetterSegmentedControl__its_init_frame_segments_index_options___initializer__when_calling_it__with_a_valid_index__that_is_0__the_control_renders_correctly@3x.png
│ │ ├── a_BetterSegmentedControl__its_init_frame_segments_index_options___initializer__when_calling_it__with_a_valid_index__that_is_1__the_control_renders_correctly@3x.png
│ │ ├── a_BetterSegmentedControl__its_init_frame_segments_index_options___initializer__when_calling_it__with_a_valid_index__that_is_2__the_control_renders_correctly@3x.png
│ │ ├── a_BetterSegmentedControl__its_init_frame_segments_index_options___initializer__when_calling_it__with_a_valid_index__that_is_minus_1__the_control_renders_correctly@3x.png
│ │ ├── a_BetterSegmentedControl__its_init_frame_segments_index_options___initializer__when_calling_it__with_an_invalid_index__that_is_beyond_the_valid_segment_indices__the_control_renders_correctly@3x.png
│ │ ├── a_BetterSegmentedControl__its_init_frame_segments_index_options___initializer__when_calling_it__with_an_invalid_index__that_is_minus_2__the_control_renders_correctly@3x.png
│ │ ├── a_BetterSegmentedControl__its_init_frame_segments_index_options___initializer__when_calling_it__with_options__setting_the_backgroundColor__the_control_renders_correctly@3x.png
│ │ ├── a_BetterSegmentedControl__its_init_frame_segments_index_options___initializer__when_calling_it__with_options__setting_the_cornerRadius__the_control_renders_correctly@3x.png
│ │ ├── a_BetterSegmentedControl__its_init_frame_segments_index_options___initializer__when_calling_it__with_options__setting_the_indicatorViewBackgroundColor__the_control_renders_correctly@3x.png
│ │ ├── a_BetterSegmentedControl__its_init_frame_segments_index_options___initializer__when_calling_it__with_options__setting_the_indicatorViewBorderColor__the_control_renders_correctly@3x.png
│ │ ├── a_BetterSegmentedControl__its_init_frame_segments_index_options___initializer__when_calling_it__with_options__setting_the_indicatorViewBorderWidth__the_control_renders_correctly@3x.png
│ │ ├── a_BetterSegmentedControl__its_init_frame_segments_index_options___initializer__when_calling_it__with_options__setting_the_indicatorViewInset__the_control_renders_correctly@3x.png
│ │ ├── a_BetterSegmentedControl__its_segmentPadding_property__when_setting_it_to_28__the_control_renders_correctly@3x.png
│ │ ├── a_BetterSegmentedControl__its_segmentPadding_property__when_setting_it_to_8__the_control_renders_correctly@3x.png
│ │ ├── a_BetterSegmentedControl__its_segmentPadding_property__when_setting_it_to_zero__the_control_renders_correctly@3x.png
│ │ ├── a_BetterSegmentedControl__its_segments_property__when_the_control_is_initialized_with_one_segment__when_setting_segments_to_one__renders_correctly@3x.png
│ │ ├── a_BetterSegmentedControl__its_segments_property__when_the_control_is_initialized_with_one_segment__when_setting_segments_to_three_and_then_two__renders_correctly@3x.png
│ │ ├── a_BetterSegmentedControl__its_segments_property__when_the_control_is_initialized_with_one_segment__when_setting_segments_to_two__renders_correctly@3x.png
│ │ ├── a_BetterSegmentedControl__its_segments_property__when_the_control_is_initialized_with_one_segment__when_setting_segments_to_two_and_then_three__renders_correctly@3x.png
│ │ ├── a_BetterSegmentedControl__its_segments_property__when_the_control_is_initialized_with_one_segment__when_setting_segments_to_zero__renders_correctly@3x.png
│ │ ├── a_BetterSegmentedControl__its_segments_property__when_the_control_is_initialized_with_two_segments__when_setting_segments_to_one__renders_correctly@3x.png
│ │ ├── a_BetterSegmentedControl__its_segments_property__when_the_control_is_initialized_with_two_segments__when_setting_segments_to_three_and_then_two__renders_correctly@3x.png
│ │ ├── a_BetterSegmentedControl__its_segments_property__when_the_control_is_initialized_with_two_segments__when_setting_segments_to_two__renders_correctly@3x.png
│ │ ├── a_BetterSegmentedControl__its_segments_property__when_the_control_is_initialized_with_two_segments__when_setting_segments_to_two_and_then_three__renders_correctly@3x.png
│ │ ├── a_BetterSegmentedControl__its_segments_property__when_the_control_is_initialized_with_two_segments__when_setting_segments_to_zero__renders_correctly@3x.png
│ │ ├── a_BetterSegmentedControl__its_segments_property__when_the_control_is_initialized_with_zero_segments__when_setting_segments_to_one__renders_correctly@3x.png
│ │ ├── a_BetterSegmentedControl__its_segments_property__when_the_control_is_initialized_with_zero_segments__when_setting_segments_to_three_and_then_two__renders_correctly@3x.png
│ │ ├── a_BetterSegmentedControl__its_segments_property__when_the_control_is_initialized_with_zero_segments__when_setting_segments_to_two__renders_correctly@3x.png
│ │ ├── a_BetterSegmentedControl__its_segments_property__when_the_control_is_initialized_with_zero_segments__when_setting_segments_to_two_and_then_three__renders_correctly@3x.png
│ │ ├── a_BetterSegmentedControl__its_segments_property__when_the_control_is_initialized_with_zero_segments__when_setting_segments_to_zero__renders_correctly@3x.png
│ │ ├── a_BetterSegmentedControl__its_setIndex___method__when_called_with_a_valid_index__that_is_0__the_control_renders_correctly@3x.png
│ │ ├── a_BetterSegmentedControl__its_setIndex___method__when_called_with_a_valid_index__that_is_1__the_control_renders_correctly@3x.png
│ │ ├── a_BetterSegmentedControl__its_setIndex___method__when_called_with_a_valid_index__that_is_2__the_control_renders_correctly@3x.png
│ │ ├── a_BetterSegmentedControl__its_setIndex___method__when_called_with_a_valid_index__that_is_3__the_control_renders_correctly@3x.png
│ │ ├── a_BetterSegmentedControl__its_setIndex___method__when_called_with_a_valid_index__that_is_minus_1__the_control_renders_correctly@3x.png
│ │ ├── a_BetterSegmentedControl__its_setOptions___method__when_setting_backgroundColor__renders_correctly@3x.png
│ │ ├── a_BetterSegmentedControl__its_setOptions___method__when_setting_cornerRadius__renders_correctly@3x.png
│ │ ├── a_BetterSegmentedControl__its_setOptions___method__when_setting_indicatorViewBackgroundColor__renders_correctly@3x.png
│ │ ├── a_BetterSegmentedControl__its_setOptions___method__when_setting_indicatorViewBorderWidth_and_indicatorViewBorderColor__renders_correctly@3x.png
│ │ ├── a_BetterSegmentedControl__its_setOptions___method__when_setting_indicatorViewInset__renders_correctly@3x.png
│ │ ├── a_BetterSegmentedControl__when_adding_a_shadow_to_the_indicator_view__renders_correctly@3x.png
│ │ ├── a_BetterSegmentedControl__when_setting_cornerRadius_and_indicatorViewInset__first_cornerRadius_then_indicatorViewInset__renders_correctly@3x.png
│ │ └── a_BetterSegmentedControl__when_setting_cornerRadius_and_indicatorViewInset__first_indicatorViewInset_then_cornerRadius__renders_correctly@3x.png
│ ├── SnapshotHelpers.swift
│ ├── Test.storyboard
│ └── TestViewControllers.swift
├── Gemfile
├── Gemfile.lock
├── LICENSE
├── Package.swift
├── Pod
├── Assets
│ └── .gitkeep
└── Classes
│ ├── .gitkeep
│ ├── BetterSegmentedControl+IBDesignable.swift
│ ├── BetterSegmentedControl+IndicatorView.swift
│ ├── BetterSegmentedControl+Options.swift
│ ├── BetterSegmentedControl+PredefinedStyles.swift
│ ├── BetterSegmentedControl+UIPointerInteractionDelegate.swift
│ ├── BetterSegmentedControl.swift
│ ├── Helpers
│ ├── UIColor+Helpers.swift
│ └── UIView+Helpers.swift
│ └── Segments
│ ├── BetterSegmentedControlSegment.swift
│ ├── IconSegment.swift
│ └── LabelSegment.swift
├── README.md
└── _Pods.xcodeproj
/.gitignore:
--------------------------------------------------------------------------------
1 | # OS X
2 | .DS_Store
3 |
4 | # Xcode
5 | build/
6 | *.pbxuser
7 | !default.pbxuser
8 | *.mode1v3
9 | !default.mode1v3
10 | *.mode2v3
11 | !default.mode2v3
12 | *.perspectivev3
13 | !default.perspectivev3
14 | xcuserdata
15 | *.xccheckout
16 | profile
17 | *.moved-aside
18 | DerivedData
19 | *.hmap
20 | *.ipa
21 |
22 | # Bundler
23 | .bundle
24 |
25 | Carthage
26 |
27 | Example/Pods/
28 |
29 | # Swift Package Manager
30 | .build
31 |
--------------------------------------------------------------------------------
/.slather.yml:
--------------------------------------------------------------------------------
1 | xcodeproj: Example/BetterSegmentedControl.xcodeproj
2 | scheme: BetterSegmentedControl_Example
3 | workspace: Example/BetterSegmentedControl.xcworkspace
4 | source_directory: Pod/Classes
5 | binary_basename: BetterSegmentedControl
6 |
--------------------------------------------------------------------------------
/.swift-version:
--------------------------------------------------------------------------------
1 | 5.1
--------------------------------------------------------------------------------
/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | # references:
2 | # * http://www.objc.io/issue-6/travis-ci.html
3 | # * https://github.com/supermarin/xcpretty#usage
4 |
5 | language: objective-c
6 | # cache: cocoapods
7 | # podfile: Example/Podfile
8 | # before_install:
9 | # - gem install cocoapods # Since Travis is not always on latest version
10 | # - pod install --project-directory=Example
11 | script:
12 | - set -o pipefail && xcodebuild test -workspace Example/BetterSegmentedControl.xcworkspace -scheme BetterSegmentedControl-Example -sdk iphonesimulator ONLY_ACTIVE_ARCH=NO | xcpretty
13 | - pod lib lint
14 |
--------------------------------------------------------------------------------
/Assets/demo_ipad_cursor.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gmarm/BetterSegmentedControl/32348f8fc700c78a6aefa731214cb4497757a48b/Assets/demo_ipad_cursor.gif
--------------------------------------------------------------------------------
/Assets/demo_main.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gmarm/BetterSegmentedControl/32348f8fc700c78a6aefa731214cb4497757a48b/Assets/demo_main.gif
--------------------------------------------------------------------------------
/Assets/logo-transparent-background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gmarm/BetterSegmentedControl/32348f8fc700c78a6aefa731214cb4497757a48b/Assets/logo-transparent-background.png
--------------------------------------------------------------------------------
/Assets/logo-white-background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gmarm/BetterSegmentedControl/32348f8fc700c78a6aefa731214cb4497757a48b/Assets/logo-white-background.png
--------------------------------------------------------------------------------
/BetterSegmentedControl.podspec:
--------------------------------------------------------------------------------
1 | Pod::Spec.new do |s|
2 | s.name = "BetterSegmentedControl"
3 | s.version = "2.0.1"
4 | s.swift_version = "5.1"
5 | s.summary = "An easy to use, customizable replacement for UISegmentedControl & UISwitch."
6 | s.description = <<-DESC
7 | BetterSegmentedControl is an easy to use, customizable replacement for UISegmentedControl and UISwitch written in Swift.
8 | DESC
9 | s.homepage = "https://github.com/gmarm/BetterSegmentedControl"
10 | s.license = 'MIT'
11 | s.author = { "George Marmaridis" => "gmarmas@gmail.com" }
12 | s.source = { :git => "https://github.com/gmarm/BetterSegmentedControl.git", :tag => "2.0.1" }
13 | s.social_media_url = 'https://twitter.com/gmarmas'
14 | s.platform = :ios, '9.0'
15 | s.requires_arc = true
16 | s.source_files = 'Pod/Classes/**/*'
17 | s.frameworks = 'UIKit'
18 | end
19 |
--------------------------------------------------------------------------------
/Example/BetterSegmentedControl.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 4BC57C101CCB8D0700A85349 /* Test.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4BC57C0F1CCB8D0700A85349 /* Test.storyboard */; };
11 | 4BC57C121CCB8EDD00A85349 /* TestViewControllers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BC57C111CCB8EDD00A85349 /* TestViewControllers.swift */; };
12 | 5E3D40EA253C486400FCF131 /* SnapshotHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E3D40E9253C486400FCF131 /* SnapshotHelpers.swift */; };
13 | 607FACD61AFB9204008FA782 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607FACD51AFB9204008FA782 /* AppDelegate.swift */; };
14 | 607FACD81AFB9204008FA782 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607FACD71AFB9204008FA782 /* ViewController.swift */; };
15 | 607FACDB1AFB9204008FA782 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 607FACD91AFB9204008FA782 /* Main.storyboard */; };
16 | 607FACDD1AFB9204008FA782 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 607FACDC1AFB9204008FA782 /* Images.xcassets */; };
17 | 607FACE01AFB9204008FA782 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 607FACDE1AFB9204008FA782 /* LaunchScreen.xib */; };
18 | 607FACEC1AFB9204008FA782 /* BetterSegmentedControlTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607FACEB1AFB9204008FA782 /* BetterSegmentedControlTests.swift */; };
19 | 90FFFDFEEFCF420B32DC095F /* Pods_BetterSegmentedControl_Tests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2FAF265B133EF9D144E4D6FB /* Pods_BetterSegmentedControl_Tests.framework */; };
20 | D36BA20F2BF5FBB03233C68B /* Pods_BetterSegmentedControl_Example.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 61D9FAAAFFAE7994D65963C2 /* Pods_BetterSegmentedControl_Example.framework */; };
21 | /* End PBXBuildFile section */
22 |
23 | /* Begin PBXContainerItemProxy section */
24 | 607FACE61AFB9204008FA782 /* PBXContainerItemProxy */ = {
25 | isa = PBXContainerItemProxy;
26 | containerPortal = 607FACC81AFB9204008FA782 /* Project object */;
27 | proxyType = 1;
28 | remoteGlobalIDString = 607FACCF1AFB9204008FA782;
29 | remoteInfo = BetterSegmentedControl;
30 | };
31 | /* End PBXContainerItemProxy section */
32 |
33 | /* Begin PBXFileReference section */
34 | 04381095F08ECC8EEFC64A13 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = ""; };
35 | 12CB0D1475C52C17775132BF /* Pods-BetterSegmentedControl_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-BetterSegmentedControl_Example.release.xcconfig"; path = "Pods/Target Support Files/Pods-BetterSegmentedControl_Example/Pods-BetterSegmentedControl_Example.release.xcconfig"; sourceTree = ""; };
36 | 2FAF265B133EF9D144E4D6FB /* Pods_BetterSegmentedControl_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_BetterSegmentedControl_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
37 | 4BC57C0F1CCB8D0700A85349 /* Test.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Test.storyboard; sourceTree = ""; };
38 | 4BC57C111CCB8EDD00A85349 /* TestViewControllers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestViewControllers.swift; sourceTree = ""; };
39 | 5E3D40E9253C486400FCF131 /* SnapshotHelpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SnapshotHelpers.swift; sourceTree = ""; };
40 | 607FACD01AFB9204008FA782 /* BetterSegmentedControl_Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = BetterSegmentedControl_Example.app; sourceTree = BUILT_PRODUCTS_DIR; };
41 | 607FACD41AFB9204008FA782 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
42 | 607FACD51AFB9204008FA782 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
43 | 607FACD71AFB9204008FA782 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; };
44 | 607FACDA1AFB9204008FA782 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
45 | 607FACDC1AFB9204008FA782 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; };
46 | 607FACDF1AFB9204008FA782 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; };
47 | 607FACE51AFB9204008FA782 /* BetterSegmentedControl_Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = BetterSegmentedControl_Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
48 | 607FACEA1AFB9204008FA782 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
49 | 607FACEB1AFB9204008FA782 /* BetterSegmentedControlTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BetterSegmentedControlTests.swift; sourceTree = ""; };
50 | 61D9FAAAFFAE7994D65963C2 /* Pods_BetterSegmentedControl_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_BetterSegmentedControl_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; };
51 | 82FBC36B5CC2D9017CEACA5B /* BetterSegmentedControl.podspec */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = BetterSegmentedControl.podspec; path = ../BetterSegmentedControl.podspec; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.ruby; };
52 | BA399992832E9047B3FF6F8B /* Pods-BetterSegmentedControl_Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-BetterSegmentedControl_Tests.release.xcconfig"; path = "Pods/Target Support Files/Pods-BetterSegmentedControl_Tests/Pods-BetterSegmentedControl_Tests.release.xcconfig"; sourceTree = ""; };
53 | E35EF8EE3A68B8AA955DE5DE /* Pods-BetterSegmentedControl_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-BetterSegmentedControl_Example.debug.xcconfig"; path = "Pods/Target Support Files/Pods-BetterSegmentedControl_Example/Pods-BetterSegmentedControl_Example.debug.xcconfig"; sourceTree = ""; };
54 | F6F6B8A01C1E078308A9EB93 /* Pods-BetterSegmentedControl_Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-BetterSegmentedControl_Tests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-BetterSegmentedControl_Tests/Pods-BetterSegmentedControl_Tests.debug.xcconfig"; sourceTree = ""; };
55 | F8ECFF07790385FABB531EC7 /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = LICENSE; path = ../LICENSE; sourceTree = ""; };
56 | /* End PBXFileReference section */
57 |
58 | /* Begin PBXFrameworksBuildPhase section */
59 | 607FACCD1AFB9204008FA782 /* Frameworks */ = {
60 | isa = PBXFrameworksBuildPhase;
61 | buildActionMask = 2147483647;
62 | files = (
63 | D36BA20F2BF5FBB03233C68B /* Pods_BetterSegmentedControl_Example.framework in Frameworks */,
64 | );
65 | runOnlyForDeploymentPostprocessing = 0;
66 | };
67 | 607FACE21AFB9204008FA782 /* Frameworks */ = {
68 | isa = PBXFrameworksBuildPhase;
69 | buildActionMask = 2147483647;
70 | files = (
71 | 90FFFDFEEFCF420B32DC095F /* Pods_BetterSegmentedControl_Tests.framework in Frameworks */,
72 | );
73 | runOnlyForDeploymentPostprocessing = 0;
74 | };
75 | /* End PBXFrameworksBuildPhase section */
76 |
77 | /* Begin PBXGroup section */
78 | 2E0C0F03ED9410652539F30B /* Pods */ = {
79 | isa = PBXGroup;
80 | children = (
81 | E35EF8EE3A68B8AA955DE5DE /* Pods-BetterSegmentedControl_Example.debug.xcconfig */,
82 | 12CB0D1475C52C17775132BF /* Pods-BetterSegmentedControl_Example.release.xcconfig */,
83 | F6F6B8A01C1E078308A9EB93 /* Pods-BetterSegmentedControl_Tests.debug.xcconfig */,
84 | BA399992832E9047B3FF6F8B /* Pods-BetterSegmentedControl_Tests.release.xcconfig */,
85 | );
86 | name = Pods;
87 | sourceTree = "";
88 | };
89 | 5EA6C5B32539E65400776C82 /* Helpers */ = {
90 | isa = PBXGroup;
91 | children = (
92 | 4BC57C0F1CCB8D0700A85349 /* Test.storyboard */,
93 | 4BC57C111CCB8EDD00A85349 /* TestViewControllers.swift */,
94 | 5E3D40E9253C486400FCF131 /* SnapshotHelpers.swift */,
95 | );
96 | name = Helpers;
97 | sourceTree = "";
98 | };
99 | 607FACC71AFB9204008FA782 = {
100 | isa = PBXGroup;
101 | children = (
102 | 607FACF51AFB993E008FA782 /* Podspec Metadata */,
103 | 607FACD21AFB9204008FA782 /* Example for BetterSegmentedControl */,
104 | 607FACE81AFB9204008FA782 /* Tests */,
105 | 607FACD11AFB9204008FA782 /* Products */,
106 | 2E0C0F03ED9410652539F30B /* Pods */,
107 | D6EA7141AF371DB117A8E6FC /* Frameworks */,
108 | );
109 | sourceTree = "";
110 | };
111 | 607FACD11AFB9204008FA782 /* Products */ = {
112 | isa = PBXGroup;
113 | children = (
114 | 607FACD01AFB9204008FA782 /* BetterSegmentedControl_Example.app */,
115 | 607FACE51AFB9204008FA782 /* BetterSegmentedControl_Tests.xctest */,
116 | );
117 | name = Products;
118 | sourceTree = "";
119 | };
120 | 607FACD21AFB9204008FA782 /* Example for BetterSegmentedControl */ = {
121 | isa = PBXGroup;
122 | children = (
123 | 607FACD51AFB9204008FA782 /* AppDelegate.swift */,
124 | 607FACD91AFB9204008FA782 /* Main.storyboard */,
125 | 607FACD71AFB9204008FA782 /* ViewController.swift */,
126 | 607FACDC1AFB9204008FA782 /* Images.xcassets */,
127 | 607FACDE1AFB9204008FA782 /* LaunchScreen.xib */,
128 | 607FACD31AFB9204008FA782 /* Supporting Files */,
129 | );
130 | name = "Example for BetterSegmentedControl";
131 | path = BetterSegmentedControl;
132 | sourceTree = "";
133 | };
134 | 607FACD31AFB9204008FA782 /* Supporting Files */ = {
135 | isa = PBXGroup;
136 | children = (
137 | 607FACD41AFB9204008FA782 /* Info.plist */,
138 | );
139 | name = "Supporting Files";
140 | sourceTree = "";
141 | };
142 | 607FACE81AFB9204008FA782 /* Tests */ = {
143 | isa = PBXGroup;
144 | children = (
145 | 607FACEB1AFB9204008FA782 /* BetterSegmentedControlTests.swift */,
146 | 5EA6C5B32539E65400776C82 /* Helpers */,
147 | 607FACE91AFB9204008FA782 /* Supporting Files */,
148 | );
149 | path = Tests;
150 | sourceTree = "";
151 | };
152 | 607FACE91AFB9204008FA782 /* Supporting Files */ = {
153 | isa = PBXGroup;
154 | children = (
155 | 607FACEA1AFB9204008FA782 /* Info.plist */,
156 | );
157 | name = "Supporting Files";
158 | sourceTree = "";
159 | };
160 | 607FACF51AFB993E008FA782 /* Podspec Metadata */ = {
161 | isa = PBXGroup;
162 | children = (
163 | 82FBC36B5CC2D9017CEACA5B /* BetterSegmentedControl.podspec */,
164 | 04381095F08ECC8EEFC64A13 /* README.md */,
165 | F8ECFF07790385FABB531EC7 /* LICENSE */,
166 | );
167 | name = "Podspec Metadata";
168 | sourceTree = "";
169 | };
170 | D6EA7141AF371DB117A8E6FC /* Frameworks */ = {
171 | isa = PBXGroup;
172 | children = (
173 | 61D9FAAAFFAE7994D65963C2 /* Pods_BetterSegmentedControl_Example.framework */,
174 | 2FAF265B133EF9D144E4D6FB /* Pods_BetterSegmentedControl_Tests.framework */,
175 | );
176 | name = Frameworks;
177 | sourceTree = "";
178 | };
179 | /* End PBXGroup section */
180 |
181 | /* Begin PBXNativeTarget section */
182 | 607FACCF1AFB9204008FA782 /* BetterSegmentedControl_Example */ = {
183 | isa = PBXNativeTarget;
184 | buildConfigurationList = 607FACEF1AFB9204008FA782 /* Build configuration list for PBXNativeTarget "BetterSegmentedControl_Example" */;
185 | buildPhases = (
186 | CBB0F927E437CCE27B11AF92 /* [CP] Check Pods Manifest.lock */,
187 | 607FACCC1AFB9204008FA782 /* Sources */,
188 | 607FACCD1AFB9204008FA782 /* Frameworks */,
189 | 607FACCE1AFB9204008FA782 /* Resources */,
190 | 7A32436EFA69C4B146882841 /* [CP] Embed Pods Frameworks */,
191 | );
192 | buildRules = (
193 | );
194 | dependencies = (
195 | );
196 | name = BetterSegmentedControl_Example;
197 | productName = BetterSegmentedControl;
198 | productReference = 607FACD01AFB9204008FA782 /* BetterSegmentedControl_Example.app */;
199 | productType = "com.apple.product-type.application";
200 | };
201 | 607FACE41AFB9204008FA782 /* BetterSegmentedControl_Tests */ = {
202 | isa = PBXNativeTarget;
203 | buildConfigurationList = 607FACF21AFB9204008FA782 /* Build configuration list for PBXNativeTarget "BetterSegmentedControl_Tests" */;
204 | buildPhases = (
205 | 213972DCD2D93B301F89BEF2 /* [CP] Check Pods Manifest.lock */,
206 | 607FACE11AFB9204008FA782 /* Sources */,
207 | 607FACE21AFB9204008FA782 /* Frameworks */,
208 | 607FACE31AFB9204008FA782 /* Resources */,
209 | 723B1B079BEB381EA4CF7DBC /* [CP] Embed Pods Frameworks */,
210 | );
211 | buildRules = (
212 | );
213 | dependencies = (
214 | 607FACE71AFB9204008FA782 /* PBXTargetDependency */,
215 | );
216 | name = BetterSegmentedControl_Tests;
217 | productName = Tests;
218 | productReference = 607FACE51AFB9204008FA782 /* BetterSegmentedControl_Tests.xctest */;
219 | productType = "com.apple.product-type.bundle.unit-test";
220 | };
221 | /* End PBXNativeTarget section */
222 |
223 | /* Begin PBXProject section */
224 | 607FACC81AFB9204008FA782 /* Project object */ = {
225 | isa = PBXProject;
226 | attributes = {
227 | LastSwiftUpdateCheck = 0720;
228 | LastUpgradeCheck = 1200;
229 | ORGANIZATIONNAME = CocoaPods;
230 | TargetAttributes = {
231 | 607FACCF1AFB9204008FA782 = {
232 | CreatedOnToolsVersion = 6.3.1;
233 | LastSwiftMigration = 1020;
234 | };
235 | 607FACE41AFB9204008FA782 = {
236 | CreatedOnToolsVersion = 6.3.1;
237 | LastSwiftMigration = 1020;
238 | TestTargetID = 607FACCF1AFB9204008FA782;
239 | };
240 | };
241 | };
242 | buildConfigurationList = 607FACCB1AFB9204008FA782 /* Build configuration list for PBXProject "BetterSegmentedControl" */;
243 | compatibilityVersion = "Xcode 3.2";
244 | developmentRegion = English;
245 | hasScannedForEncodings = 0;
246 | knownRegions = (
247 | English,
248 | en,
249 | Base,
250 | );
251 | mainGroup = 607FACC71AFB9204008FA782;
252 | productRefGroup = 607FACD11AFB9204008FA782 /* Products */;
253 | projectDirPath = "";
254 | projectRoot = "";
255 | targets = (
256 | 607FACCF1AFB9204008FA782 /* BetterSegmentedControl_Example */,
257 | 607FACE41AFB9204008FA782 /* BetterSegmentedControl_Tests */,
258 | );
259 | };
260 | /* End PBXProject section */
261 |
262 | /* Begin PBXResourcesBuildPhase section */
263 | 607FACCE1AFB9204008FA782 /* Resources */ = {
264 | isa = PBXResourcesBuildPhase;
265 | buildActionMask = 2147483647;
266 | files = (
267 | 607FACDB1AFB9204008FA782 /* Main.storyboard in Resources */,
268 | 607FACE01AFB9204008FA782 /* LaunchScreen.xib in Resources */,
269 | 607FACDD1AFB9204008FA782 /* Images.xcassets in Resources */,
270 | );
271 | runOnlyForDeploymentPostprocessing = 0;
272 | };
273 | 607FACE31AFB9204008FA782 /* Resources */ = {
274 | isa = PBXResourcesBuildPhase;
275 | buildActionMask = 2147483647;
276 | files = (
277 | 4BC57C101CCB8D0700A85349 /* Test.storyboard in Resources */,
278 | );
279 | runOnlyForDeploymentPostprocessing = 0;
280 | };
281 | /* End PBXResourcesBuildPhase section */
282 |
283 | /* Begin PBXShellScriptBuildPhase section */
284 | 213972DCD2D93B301F89BEF2 /* [CP] Check Pods Manifest.lock */ = {
285 | isa = PBXShellScriptBuildPhase;
286 | buildActionMask = 2147483647;
287 | files = (
288 | );
289 | inputPaths = (
290 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
291 | "${PODS_ROOT}/Manifest.lock",
292 | );
293 | name = "[CP] Check Pods Manifest.lock";
294 | outputPaths = (
295 | "$(DERIVED_FILE_DIR)/Pods-BetterSegmentedControl_Tests-checkManifestLockResult.txt",
296 | );
297 | runOnlyForDeploymentPostprocessing = 0;
298 | shellPath = /bin/sh;
299 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
300 | showEnvVarsInLog = 0;
301 | };
302 | 723B1B079BEB381EA4CF7DBC /* [CP] Embed Pods Frameworks */ = {
303 | isa = PBXShellScriptBuildPhase;
304 | buildActionMask = 2147483647;
305 | files = (
306 | );
307 | inputPaths = (
308 | "${PODS_ROOT}/Target Support Files/Pods-BetterSegmentedControl_Tests/Pods-BetterSegmentedControl_Tests-frameworks.sh",
309 | "${BUILT_PRODUCTS_DIR}/BetterSegmentedControl/BetterSegmentedControl.framework",
310 | "${BUILT_PRODUCTS_DIR}/Nimble/Nimble.framework",
311 | "${BUILT_PRODUCTS_DIR}/Nimble-Snapshots/Nimble_Snapshots.framework",
312 | "${BUILT_PRODUCTS_DIR}/Quick/Quick.framework",
313 | "${BUILT_PRODUCTS_DIR}/iOSSnapshotTestCase/FBSnapshotTestCase.framework",
314 | );
315 | name = "[CP] Embed Pods Frameworks";
316 | outputPaths = (
317 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/BetterSegmentedControl.framework",
318 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Nimble.framework",
319 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Nimble_Snapshots.framework",
320 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Quick.framework",
321 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FBSnapshotTestCase.framework",
322 | );
323 | runOnlyForDeploymentPostprocessing = 0;
324 | shellPath = /bin/sh;
325 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-BetterSegmentedControl_Tests/Pods-BetterSegmentedControl_Tests-frameworks.sh\"\n";
326 | showEnvVarsInLog = 0;
327 | };
328 | 7A32436EFA69C4B146882841 /* [CP] Embed Pods Frameworks */ = {
329 | isa = PBXShellScriptBuildPhase;
330 | buildActionMask = 2147483647;
331 | files = (
332 | );
333 | inputPaths = (
334 | "${PODS_ROOT}/Target Support Files/Pods-BetterSegmentedControl_Example/Pods-BetterSegmentedControl_Example-frameworks.sh",
335 | "${BUILT_PRODUCTS_DIR}/BetterSegmentedControl/BetterSegmentedControl.framework",
336 | );
337 | name = "[CP] Embed Pods Frameworks";
338 | outputPaths = (
339 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/BetterSegmentedControl.framework",
340 | );
341 | runOnlyForDeploymentPostprocessing = 0;
342 | shellPath = /bin/sh;
343 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-BetterSegmentedControl_Example/Pods-BetterSegmentedControl_Example-frameworks.sh\"\n";
344 | showEnvVarsInLog = 0;
345 | };
346 | CBB0F927E437CCE27B11AF92 /* [CP] Check Pods Manifest.lock */ = {
347 | isa = PBXShellScriptBuildPhase;
348 | buildActionMask = 2147483647;
349 | files = (
350 | );
351 | inputPaths = (
352 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
353 | "${PODS_ROOT}/Manifest.lock",
354 | );
355 | name = "[CP] Check Pods Manifest.lock";
356 | outputPaths = (
357 | "$(DERIVED_FILE_DIR)/Pods-BetterSegmentedControl_Example-checkManifestLockResult.txt",
358 | );
359 | runOnlyForDeploymentPostprocessing = 0;
360 | shellPath = /bin/sh;
361 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
362 | showEnvVarsInLog = 0;
363 | };
364 | /* End PBXShellScriptBuildPhase section */
365 |
366 | /* Begin PBXSourcesBuildPhase section */
367 | 607FACCC1AFB9204008FA782 /* Sources */ = {
368 | isa = PBXSourcesBuildPhase;
369 | buildActionMask = 2147483647;
370 | files = (
371 | 607FACD81AFB9204008FA782 /* ViewController.swift in Sources */,
372 | 607FACD61AFB9204008FA782 /* AppDelegate.swift in Sources */,
373 | );
374 | runOnlyForDeploymentPostprocessing = 0;
375 | };
376 | 607FACE11AFB9204008FA782 /* Sources */ = {
377 | isa = PBXSourcesBuildPhase;
378 | buildActionMask = 2147483647;
379 | files = (
380 | 4BC57C121CCB8EDD00A85349 /* TestViewControllers.swift in Sources */,
381 | 607FACEC1AFB9204008FA782 /* BetterSegmentedControlTests.swift in Sources */,
382 | 5E3D40EA253C486400FCF131 /* SnapshotHelpers.swift in Sources */,
383 | );
384 | runOnlyForDeploymentPostprocessing = 0;
385 | };
386 | /* End PBXSourcesBuildPhase section */
387 |
388 | /* Begin PBXTargetDependency section */
389 | 607FACE71AFB9204008FA782 /* PBXTargetDependency */ = {
390 | isa = PBXTargetDependency;
391 | target = 607FACCF1AFB9204008FA782 /* BetterSegmentedControl_Example */;
392 | targetProxy = 607FACE61AFB9204008FA782 /* PBXContainerItemProxy */;
393 | };
394 | /* End PBXTargetDependency section */
395 |
396 | /* Begin PBXVariantGroup section */
397 | 607FACD91AFB9204008FA782 /* Main.storyboard */ = {
398 | isa = PBXVariantGroup;
399 | children = (
400 | 607FACDA1AFB9204008FA782 /* Base */,
401 | );
402 | name = Main.storyboard;
403 | sourceTree = "";
404 | };
405 | 607FACDE1AFB9204008FA782 /* LaunchScreen.xib */ = {
406 | isa = PBXVariantGroup;
407 | children = (
408 | 607FACDF1AFB9204008FA782 /* Base */,
409 | );
410 | name = LaunchScreen.xib;
411 | sourceTree = "";
412 | };
413 | /* End PBXVariantGroup section */
414 |
415 | /* Begin XCBuildConfiguration section */
416 | 607FACED1AFB9204008FA782 /* Debug */ = {
417 | isa = XCBuildConfiguration;
418 | buildSettings = {
419 | ALWAYS_SEARCH_USER_PATHS = NO;
420 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
421 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
422 | CLANG_CXX_LIBRARY = "libc++";
423 | CLANG_ENABLE_MODULES = YES;
424 | CLANG_ENABLE_OBJC_ARC = YES;
425 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
426 | CLANG_WARN_BOOL_CONVERSION = YES;
427 | CLANG_WARN_COMMA = YES;
428 | CLANG_WARN_CONSTANT_CONVERSION = YES;
429 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
430 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
431 | CLANG_WARN_EMPTY_BODY = YES;
432 | CLANG_WARN_ENUM_CONVERSION = YES;
433 | CLANG_WARN_INFINITE_RECURSION = YES;
434 | CLANG_WARN_INT_CONVERSION = YES;
435 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
436 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
437 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
438 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
439 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
440 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
441 | CLANG_WARN_STRICT_PROTOTYPES = YES;
442 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
443 | CLANG_WARN_UNREACHABLE_CODE = YES;
444 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
445 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
446 | COPY_PHASE_STRIP = NO;
447 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
448 | ENABLE_STRICT_OBJC_MSGSEND = YES;
449 | ENABLE_TESTABILITY = YES;
450 | GCC_C_LANGUAGE_STANDARD = gnu99;
451 | GCC_DYNAMIC_NO_PIC = NO;
452 | GCC_NO_COMMON_BLOCKS = YES;
453 | GCC_OPTIMIZATION_LEVEL = 0;
454 | GCC_PREPROCESSOR_DEFINITIONS = (
455 | "DEBUG=1",
456 | "$(inherited)",
457 | );
458 | GCC_SYMBOLS_PRIVATE_EXTERN = NO;
459 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
460 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
461 | GCC_WARN_UNDECLARED_SELECTOR = YES;
462 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
463 | GCC_WARN_UNUSED_FUNCTION = YES;
464 | GCC_WARN_UNUSED_VARIABLE = YES;
465 | IPHONEOS_DEPLOYMENT_TARGET = 9.0;
466 | MTL_ENABLE_DEBUG_INFO = YES;
467 | ONLY_ACTIVE_ARCH = YES;
468 | SDKROOT = iphoneos;
469 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
470 | SWIFT_VERSION = 5.0;
471 | };
472 | name = Debug;
473 | };
474 | 607FACEE1AFB9204008FA782 /* Release */ = {
475 | isa = XCBuildConfiguration;
476 | buildSettings = {
477 | ALWAYS_SEARCH_USER_PATHS = NO;
478 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
479 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
480 | CLANG_CXX_LIBRARY = "libc++";
481 | CLANG_ENABLE_MODULES = YES;
482 | CLANG_ENABLE_OBJC_ARC = YES;
483 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
484 | CLANG_WARN_BOOL_CONVERSION = YES;
485 | CLANG_WARN_COMMA = YES;
486 | CLANG_WARN_CONSTANT_CONVERSION = YES;
487 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
488 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
489 | CLANG_WARN_EMPTY_BODY = YES;
490 | CLANG_WARN_ENUM_CONVERSION = YES;
491 | CLANG_WARN_INFINITE_RECURSION = YES;
492 | CLANG_WARN_INT_CONVERSION = YES;
493 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
494 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
495 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
496 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
497 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
498 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
499 | CLANG_WARN_STRICT_PROTOTYPES = YES;
500 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
501 | CLANG_WARN_UNREACHABLE_CODE = YES;
502 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
503 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
504 | COPY_PHASE_STRIP = NO;
505 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
506 | ENABLE_NS_ASSERTIONS = NO;
507 | ENABLE_STRICT_OBJC_MSGSEND = YES;
508 | GCC_C_LANGUAGE_STANDARD = gnu99;
509 | GCC_NO_COMMON_BLOCKS = YES;
510 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
511 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
512 | GCC_WARN_UNDECLARED_SELECTOR = YES;
513 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
514 | GCC_WARN_UNUSED_FUNCTION = YES;
515 | GCC_WARN_UNUSED_VARIABLE = YES;
516 | IPHONEOS_DEPLOYMENT_TARGET = 9.0;
517 | MTL_ENABLE_DEBUG_INFO = NO;
518 | SDKROOT = iphoneos;
519 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
520 | SWIFT_VERSION = 5.0;
521 | VALIDATE_PRODUCT = YES;
522 | };
523 | name = Release;
524 | };
525 | 607FACF01AFB9204008FA782 /* Debug */ = {
526 | isa = XCBuildConfiguration;
527 | baseConfigurationReference = E35EF8EE3A68B8AA955DE5DE /* Pods-BetterSegmentedControl_Example.debug.xcconfig */;
528 | buildSettings = {
529 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
530 | INFOPLIST_FILE = BetterSegmentedControl/Info.plist;
531 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
532 | MODULE_NAME = ExampleApp;
533 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.$(PRODUCT_NAME:rfc1034identifier)";
534 | PRODUCT_NAME = "$(TARGET_NAME)";
535 | TARGETED_DEVICE_FAMILY = "1,2";
536 | };
537 | name = Debug;
538 | };
539 | 607FACF11AFB9204008FA782 /* Release */ = {
540 | isa = XCBuildConfiguration;
541 | baseConfigurationReference = 12CB0D1475C52C17775132BF /* Pods-BetterSegmentedControl_Example.release.xcconfig */;
542 | buildSettings = {
543 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
544 | INFOPLIST_FILE = BetterSegmentedControl/Info.plist;
545 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
546 | MODULE_NAME = ExampleApp;
547 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.$(PRODUCT_NAME:rfc1034identifier)";
548 | PRODUCT_NAME = "$(TARGET_NAME)";
549 | TARGETED_DEVICE_FAMILY = "1,2";
550 | };
551 | name = Release;
552 | };
553 | 607FACF31AFB9204008FA782 /* Debug */ = {
554 | isa = XCBuildConfiguration;
555 | baseConfigurationReference = F6F6B8A01C1E078308A9EB93 /* Pods-BetterSegmentedControl_Tests.debug.xcconfig */;
556 | buildSettings = {
557 | BUNDLE_LOADER = "$(TEST_HOST)";
558 | FRAMEWORK_SEARCH_PATHS = "$(inherited)";
559 | GCC_PREPROCESSOR_DEFINITIONS = (
560 | "DEBUG=1",
561 | "$(inherited)",
562 | );
563 | INFOPLIST_FILE = Tests/Info.plist;
564 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
565 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.$(PRODUCT_NAME:rfc1034identifier)";
566 | PRODUCT_NAME = "$(TARGET_NAME)";
567 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/BetterSegmentedControl_Example.app/BetterSegmentedControl_Example";
568 | };
569 | name = Debug;
570 | };
571 | 607FACF41AFB9204008FA782 /* Release */ = {
572 | isa = XCBuildConfiguration;
573 | baseConfigurationReference = BA399992832E9047B3FF6F8B /* Pods-BetterSegmentedControl_Tests.release.xcconfig */;
574 | buildSettings = {
575 | BUNDLE_LOADER = "$(TEST_HOST)";
576 | FRAMEWORK_SEARCH_PATHS = "$(inherited)";
577 | INFOPLIST_FILE = Tests/Info.plist;
578 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
579 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.$(PRODUCT_NAME:rfc1034identifier)";
580 | PRODUCT_NAME = "$(TARGET_NAME)";
581 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/BetterSegmentedControl_Example.app/BetterSegmentedControl_Example";
582 | };
583 | name = Release;
584 | };
585 | /* End XCBuildConfiguration section */
586 |
587 | /* Begin XCConfigurationList section */
588 | 607FACCB1AFB9204008FA782 /* Build configuration list for PBXProject "BetterSegmentedControl" */ = {
589 | isa = XCConfigurationList;
590 | buildConfigurations = (
591 | 607FACED1AFB9204008FA782 /* Debug */,
592 | 607FACEE1AFB9204008FA782 /* Release */,
593 | );
594 | defaultConfigurationIsVisible = 0;
595 | defaultConfigurationName = Release;
596 | };
597 | 607FACEF1AFB9204008FA782 /* Build configuration list for PBXNativeTarget "BetterSegmentedControl_Example" */ = {
598 | isa = XCConfigurationList;
599 | buildConfigurations = (
600 | 607FACF01AFB9204008FA782 /* Debug */,
601 | 607FACF11AFB9204008FA782 /* Release */,
602 | );
603 | defaultConfigurationIsVisible = 0;
604 | defaultConfigurationName = Release;
605 | };
606 | 607FACF21AFB9204008FA782 /* Build configuration list for PBXNativeTarget "BetterSegmentedControl_Tests" */ = {
607 | isa = XCConfigurationList;
608 | buildConfigurations = (
609 | 607FACF31AFB9204008FA782 /* Debug */,
610 | 607FACF41AFB9204008FA782 /* Release */,
611 | );
612 | defaultConfigurationIsVisible = 0;
613 | defaultConfigurationName = Release;
614 | };
615 | /* End XCConfigurationList section */
616 | };
617 | rootObject = 607FACC81AFB9204008FA782 /* Project object */;
618 | }
619 |
--------------------------------------------------------------------------------
/Example/BetterSegmentedControl.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Example/BetterSegmentedControl.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Example/BetterSegmentedControl.xcodeproj/xcshareddata/xcschemes/BetterSegmentedControl.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
43 |
44 |
50 |
51 |
53 |
54 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/Example/BetterSegmentedControl.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/Example/BetterSegmentedControl.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Example/BetterSegmentedControl/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // BetterSegmentedControl
4 | //
5 | // Created by George Marmaridis on 04/03/2016.
6 | // Copyright (c) 2016 George Marmaridis. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | @UIApplicationMain
12 | class AppDelegate: UIResponder, UIApplicationDelegate {
13 |
14 | var window: UIWindow?
15 |
16 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
17 | // Override point for customization after application launch.
18 | return true
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/Example/BetterSegmentedControl/Base.lproj/LaunchScreen.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/Example/BetterSegmentedControl/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
--------------------------------------------------------------------------------
/Example/BetterSegmentedControl/Images.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "20x20",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "20x20",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "29x29",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "29x29",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "40x40",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "40x40",
31 | "scale" : "3x"
32 | },
33 | {
34 | "idiom" : "iphone",
35 | "size" : "60x60",
36 | "scale" : "2x"
37 | },
38 | {
39 | "idiom" : "iphone",
40 | "size" : "60x60",
41 | "scale" : "3x"
42 | },
43 | {
44 | "idiom" : "ios-marketing",
45 | "size" : "1024x1024",
46 | "scale" : "1x"
47 | }
48 | ],
49 | "info" : {
50 | "version" : 1,
51 | "author" : "xcode"
52 | }
53 | }
--------------------------------------------------------------------------------
/Example/BetterSegmentedControl/Images.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/Example/BetterSegmentedControl/Images.xcassets/facebook.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "icons8-facebook-50.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "icons8-facebook-100.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "scale" : "3x"
16 | }
17 | ],
18 | "info" : {
19 | "version" : 1,
20 | "author" : "xcode"
21 | }
22 | }
--------------------------------------------------------------------------------
/Example/BetterSegmentedControl/Images.xcassets/facebook.imageset/icons8-facebook-100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gmarm/BetterSegmentedControl/32348f8fc700c78a6aefa731214cb4497757a48b/Example/BetterSegmentedControl/Images.xcassets/facebook.imageset/icons8-facebook-100.png
--------------------------------------------------------------------------------
/Example/BetterSegmentedControl/Images.xcassets/facebook.imageset/icons8-facebook-50.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gmarm/BetterSegmentedControl/32348f8fc700c78a6aefa731214cb4497757a48b/Example/BetterSegmentedControl/Images.xcassets/facebook.imageset/icons8-facebook-50.png
--------------------------------------------------------------------------------
/Example/BetterSegmentedControl/Images.xcassets/twitter.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "icons8-twitter-50.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "icons8-twitter-100.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "scale" : "3x"
16 | }
17 | ],
18 | "info" : {
19 | "version" : 1,
20 | "author" : "xcode"
21 | }
22 | }
--------------------------------------------------------------------------------
/Example/BetterSegmentedControl/Images.xcassets/twitter.imageset/icons8-twitter-100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gmarm/BetterSegmentedControl/32348f8fc700c78a6aefa731214cb4497757a48b/Example/BetterSegmentedControl/Images.xcassets/twitter.imageset/icons8-twitter-100.png
--------------------------------------------------------------------------------
/Example/BetterSegmentedControl/Images.xcassets/twitter.imageset/icons8-twitter-50.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gmarm/BetterSegmentedControl/32348f8fc700c78a6aefa731214cb4497757a48b/Example/BetterSegmentedControl/Images.xcassets/twitter.imageset/icons8-twitter-50.png
--------------------------------------------------------------------------------
/Example/BetterSegmentedControl/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 | LSRequiresIPhoneOS
24 |
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIMainStoryboardFile
28 | Main
29 | UIRequiredDeviceCapabilities
30 |
31 | armv7
32 |
33 | UISupportedInterfaceOrientations
34 |
35 | UIInterfaceOrientationPortrait
36 | UIInterfaceOrientationLandscapeLeft
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/Example/BetterSegmentedControl/ViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.swift
3 | // BetterSegmentedControl
4 | //
5 | // Created by George Marmaridis on 04/03/2016.
6 | // Copyright (c) 2016 George Marmaridis. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import BetterSegmentedControl
11 |
12 | class ViewController: UIViewController {
13 |
14 | @IBOutlet weak var control1: BetterSegmentedControl!
15 | @IBOutlet weak var control2: BetterSegmentedControl!
16 | @IBOutlet weak var control3: BetterSegmentedControl!
17 |
18 | // MARK: - Examples
19 | override func viewDidLoad() {
20 | super.viewDidLoad()
21 |
22 | let navigationSegmentedControl = BetterSegmentedControl(
23 | frame: CGRect(x: 0, y: 0, width: 200.0, height: 30.0),
24 | segments: LabelSegment.segments(withTitles: ["Lights On", "Lights Off"],
25 | normalTextColor: .lightGray,
26 | selectedTextColor: .white),
27 | options:[.backgroundColor(.darkGray),
28 | .indicatorViewBackgroundColor(UIColor(red: 0.36, green: 0.38, blue: 0.87, alpha: 1.00)),
29 | .cornerRadius(3.0),
30 | .animationSpringDamping(1.0)])
31 | navigationSegmentedControl.addTarget(self,
32 | action: #selector(ViewController.navigationSegmentedControlValueChanged(_:)),
33 | for: .valueChanged)
34 | navigationItem.titleView = navigationSegmentedControl
35 |
36 | // Control 1: Created and designed in IB
37 | control1.segments = LabelSegment.segments(withTitles: ["Recent", "Nearby", "All"],
38 | normalTextColor: UIColor(red: 0.48, green: 0.48, blue: 0.51, alpha: 1.00))
39 |
40 | // Control 2: Created and designed in IB
41 | control2.segments = LabelSegment.segments(withTitles: ["Music", "Movies", "Apps"],
42 | normalTextColor: .white,
43 | selectedTextColor: UIColor(red: 0.92, green: 0.29, blue: 0.15, alpha: 1.00))
44 |
45 | // Control 3: Many options
46 | control3.segments = LabelSegment.segments(withTitles: ["One", "Two", "Three", "Four", "Five"],
47 | normalFont: .systemFont(ofSize: 14.0),
48 | normalTextColor: UIColor(red: 0.15, green: 0.39, blue: 0.96, alpha: 0.9),
49 | selectedFont: .systemFont(ofSize: 14.0),
50 | selectedTextColor: UIColor(red: 0.16, green: 0.40, blue: 0.96, alpha: 1.00))
51 |
52 | // Control 4: Created and designed in IB, self-sizing
53 |
54 | // Control 5: Basic Icons
55 | let iconsSegmentedControl = BetterSegmentedControl(
56 | frame: CGRect(x: 0.0, y: 380.0, width: 160, height: 30.0),
57 | segments: IconSegment.segments(withIcons: [UIImage(named: "facebook")!, UIImage(named: "twitter")!],
58 | iconSize: CGSize(width: 20.0, height: 20.0),
59 | normalIconTintColor: .white,
60 | selectedIconTintColor: UIColor(red: 0.16, green: 0.64, blue: 0.94, alpha: 1.00)),
61 | options: [.cornerRadius(15.0),
62 | .backgroundColor(UIColor(red: 0.16, green: 0.64, blue: 0.94, alpha: 1.00)),
63 | .indicatorViewBackgroundColor(.white)])
64 | iconsSegmentedControl.center.x = view.center.x
65 | view.addSubview(iconsSegmentedControl)
66 |
67 | // Control 6: Apple style
68 | let appleStyledControl: BetterSegmentedControl = .appleStyled(frame: CGRect(x: 16.0,
69 | y: 435,
70 | width: view.bounds.width - 32.0,
71 | height: 32.0),
72 | titles: ["First", "Second", "Third"])
73 | view.addSubview(appleStyledControl)
74 |
75 | // Control 7: No initially selected segment
76 | let noSelectedSegmentControl = BetterSegmentedControl(
77 | frame: CGRect(x: 16.0, y: 490, width: view.bounds.width - 32.0, height: 44.0),
78 | segments: LabelSegment.segments(withTitles: ["One", "Two", "Three", "Four"]),
79 | index: -1)
80 | noSelectedSegmentControl.addTarget(self, action: #selector(segmentedControl1ValueChanged(_:)), for: .valueChanged)
81 | view.addSubview(noSelectedSegmentControl)
82 | }
83 |
84 | // MARK: - Action handlers
85 | @objc func navigationSegmentedControlValueChanged(_ sender: BetterSegmentedControl) {
86 | if sender.index == 0 {
87 | print("Turning lights on.")
88 | if #available(iOS 13.0, *) {
89 | view.backgroundColor = .systemGray5
90 | } else {
91 | view.backgroundColor = .white
92 | }
93 | } else {
94 | print("Turning lights off.")
95 | view.backgroundColor = .darkGray
96 | }
97 | }
98 |
99 | @IBAction func segmentedControl1ValueChanged(_ sender: BetterSegmentedControl) {
100 | print("The selected index is \(sender.index)")
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/Example/Podfile:
--------------------------------------------------------------------------------
1 | source 'https://github.com/CocoaPods/Specs.git'
2 | platform :ios, '9.0'
3 | use_frameworks!
4 | inhibit_all_warnings!
5 |
6 | def betterSegmentedControl
7 | pod 'BetterSegmentedControl', :path => '../', :inhibit_warnings => false
8 | end
9 |
10 | target 'BetterSegmentedControl_Example' do
11 | betterSegmentedControl
12 | end
13 |
14 | target 'BetterSegmentedControl_Tests' do
15 | betterSegmentedControl
16 |
17 | pod 'Quick', '~> 2.2'
18 | pod 'Nimble', '~> 7.3'
19 | pod 'Nimble-Snapshots', '~> 6.9'
20 | end
21 |
22 | post_install do |pi|
23 | pi.pods_project.targets.each do |t|
24 | t.build_configurations.each do |config|
25 | config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '9.0'
26 | end
27 | end
28 | end
29 |
--------------------------------------------------------------------------------
/Example/Podfile.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - BetterSegmentedControl (2.0)
3 | - iOSSnapshotTestCase (5.0.2):
4 | - iOSSnapshotTestCase/SwiftSupport (= 5.0.2)
5 | - iOSSnapshotTestCase/Core (5.0.2)
6 | - iOSSnapshotTestCase/SwiftSupport (5.0.2):
7 | - iOSSnapshotTestCase/Core
8 | - Nimble (7.3.4)
9 | - Nimble-Snapshots (6.9.1):
10 | - Nimble-Snapshots/Core (= 6.9.1)
11 | - Nimble-Snapshots/Core (6.9.1):
12 | - iOSSnapshotTestCase (~> 5.0)
13 | - Nimble (~> 7.0)
14 | - Quick (2.2.0)
15 |
16 | DEPENDENCIES:
17 | - BetterSegmentedControl (from `../`)
18 | - Nimble (~> 7.3)
19 | - Nimble-Snapshots (~> 6.9)
20 | - Quick (~> 2.2)
21 |
22 | SPEC REPOS:
23 | https://github.com/CocoaPods/Specs.git:
24 | - iOSSnapshotTestCase
25 | - Nimble
26 | - Nimble-Snapshots
27 | - Quick
28 |
29 | EXTERNAL SOURCES:
30 | BetterSegmentedControl:
31 | :path: "../"
32 |
33 | SPEC CHECKSUMS:
34 | BetterSegmentedControl: ce9b68b81c963991211c561026ed2cf711f9ac63
35 | iOSSnapshotTestCase: 2d51aa06775e95cecb0a1fb9c5c159ccd1dd4596
36 | Nimble: 051e3d8912d40138fa5591c78594f95fb172af37
37 | Nimble-Snapshots: bbd1ab264bacc24a9ce24a8363bc05aac783aeb0
38 | Quick: 7fb19e13be07b5dfb3b90d4f9824c855a11af40e
39 |
40 | PODFILE CHECKSUM: 609c5442f2ad21fe0424eaab055f9caa5c2944a1
41 |
42 | COCOAPODS: 1.9.3
43 |
--------------------------------------------------------------------------------
/Example/Tests/BetterSegmentedControlTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // BetterSegmentedControlTests.swift
3 | // BetterSegmentedControl
4 | //
5 | // Created by George Marmaridis on 23/04/16.
6 | // Copyright © 2020 George Marmaridis. All rights reserved.
7 | //
8 |
9 | import Quick
10 | import Nimble
11 | import Nimble_Snapshots
12 | @testable import BetterSegmentedControl
13 |
14 | final class BetterSegmentedControlSpec: QuickSpec {
15 | override func spec() {
16 | describe("a BetterSegmentedControl") {
17 | let testFrame = CGRect(x: 0, y: 0, width: 300, height: 44)
18 | let basicSegmentOne: [LabelSegment] = [.init(text: "One")]
19 | let basicSegmentsTwo: [LabelSegment] = [.init(text: "One"), .init(text: "Two")]
20 | let basicSegmentsThree: [LabelSegment] = [.init(text: "One"), .init(text: "Two"), .init(text: "Three")]
21 | let basicSegmentsFour: [LabelSegment] = [.init(text: "One"), .init(text: "Two"), .init(text: "Three"), .init(text: "Four")]
22 |
23 | var control: BetterSegmentedControl!
24 |
25 | // MARK: segments
26 | describe("its segments property") {
27 | context("when the control is initialized with zero segments") {
28 | beforeEach {
29 | control = .init(frame: testFrame, segments: [])
30 | }
31 |
32 | context("when setting segments to zero") {
33 | beforeEach {
34 | control.segments = []
35 | }
36 |
37 | it("renders correctly") {
38 | //📷(control)
39 | expect(control).to(haveValidSnapshotWithAcceptableTolerance())
40 | }
41 |
42 | it("has the expected index property") {
43 | expect(control.index).to(equal(-1))
44 | }
45 | }
46 |
47 | context("when setting segments to one") {
48 | beforeEach {
49 | control.segments = basicSegmentOne
50 | }
51 |
52 | it("renders correctly") {
53 | //📷(control)
54 | expect(control).to(haveValidSnapshotWithAcceptableTolerance())
55 | }
56 |
57 | it("has the expected index property") {
58 | expect(control.index).to(equal(0))
59 | }
60 | }
61 |
62 | context("when setting segments to two") {
63 | beforeEach {
64 | control.segments = basicSegmentsTwo
65 | }
66 |
67 | it("renders correctly") {
68 | //📷(control)
69 | expect(control).to(haveValidSnapshotWithAcceptableTolerance())
70 | }
71 |
72 | it("has the expected index property") {
73 | expect(control.index).to(equal(0))
74 | }
75 | }
76 |
77 | context("when setting segments to two and then three") {
78 | beforeEach {
79 | control.segments = basicSegmentsTwo
80 | control.segments = basicSegmentsThree
81 | }
82 |
83 | it("renders correctly") {
84 | //📷(control)
85 | expect(control).to(haveValidSnapshotWithAcceptableTolerance())
86 | }
87 |
88 | it("has the expected index property") {
89 | expect(control.index).to(equal(0))
90 | }
91 | }
92 |
93 | context("when setting segments to three and then two") {
94 | beforeEach {
95 | control.segments = basicSegmentsThree
96 | control.segments = basicSegmentsTwo
97 | }
98 |
99 | it("renders correctly") {
100 | //📷(control)
101 | expect(control).to(haveValidSnapshotWithAcceptableTolerance())
102 | }
103 |
104 | it("has the expected index property") {
105 | expect(control.index).to(equal(0))
106 | }
107 | }
108 | }
109 |
110 | context("when the control is initialized with one segment") {
111 | beforeEach {
112 | control = .init(frame: testFrame, segments: basicSegmentOne)
113 | }
114 |
115 | context("when setting segments to zero") {
116 | beforeEach {
117 | control.segments = []
118 | }
119 |
120 | it("renders correctly") {
121 | //📷(control)
122 | expect(control).to(haveValidSnapshotWithAcceptableTolerance())
123 | }
124 |
125 | it("has the expected index property") {
126 | expect(control.index).to(equal(-1))
127 | }
128 | }
129 |
130 | context("when setting segments to one") {
131 | beforeEach {
132 | control.segments = basicSegmentOne
133 | }
134 |
135 | it("renders correctly") {
136 | //📷(control)
137 | expect(control).to(haveValidSnapshotWithAcceptableTolerance())
138 | }
139 |
140 | it("has the expected index property") {
141 | expect(control.index).to(equal(0))
142 | }
143 | }
144 |
145 | context("when setting segments to two") {
146 | beforeEach {
147 | control.segments = basicSegmentsTwo
148 | }
149 |
150 | it("renders correctly") {
151 | //📷(control)
152 | expect(control).to(haveValidSnapshotWithAcceptableTolerance())
153 | }
154 |
155 | it("has the expected index property") {
156 | expect(control.index).to(equal(0))
157 | }
158 | }
159 |
160 | context("when setting segments to two and then three") {
161 | beforeEach {
162 | control.segments = basicSegmentsTwo
163 | control.segments = basicSegmentsThree
164 | }
165 |
166 | it("renders correctly") {
167 | //📷(control)
168 | expect(control).to(haveValidSnapshotWithAcceptableTolerance())
169 | }
170 |
171 | it("has the expected index property") {
172 | expect(control.index).to(equal(0))
173 | }
174 | }
175 |
176 | context("when setting segments to three and then two") {
177 | beforeEach {
178 | control.segments = basicSegmentsThree
179 | control.segments = basicSegmentsTwo
180 | }
181 |
182 | it("renders correctly") {
183 | //📷(control)
184 | expect(control).to(haveValidSnapshotWithAcceptableTolerance())
185 | }
186 |
187 | it("has the expected index property") {
188 | expect(control.index).to(equal(0))
189 | }
190 | }
191 | }
192 |
193 | context("when the control is initialized with two segments") {
194 | beforeEach {
195 | control = .init(frame: testFrame, segments: basicSegmentsTwo)
196 | }
197 |
198 | context("when setting segments to zero") {
199 | beforeEach {
200 | control.segments = []
201 | }
202 |
203 | it("renders correctly") {
204 | //📷(control)
205 | expect(control).to(haveValidSnapshotWithAcceptableTolerance())
206 | }
207 |
208 | it("has the expected index property") {
209 | expect(control.index).to(equal(-1))
210 | }
211 | }
212 |
213 | context("when setting segments to one") {
214 | beforeEach {
215 | control.segments = basicSegmentOne
216 | }
217 |
218 | it("renders correctly") {
219 | //📷(control)
220 | expect(control).to(haveValidSnapshotWithAcceptableTolerance())
221 | }
222 |
223 | it("has the expected index property") {
224 | expect(control.index).to(equal(0))
225 | }
226 | }
227 |
228 | context("when setting segments to two") {
229 | beforeEach {
230 | control.segments = basicSegmentsTwo
231 | }
232 |
233 | it("renders correctly") {
234 | //📷(control)
235 | expect(control).to(haveValidSnapshotWithAcceptableTolerance())
236 | }
237 |
238 | it("has the expected index property") {
239 | expect(control.index).to(equal(0))
240 | }
241 | }
242 |
243 | context("when setting segments to two and then three") {
244 | beforeEach {
245 | control.segments = basicSegmentsTwo
246 | control.segments = basicSegmentsThree
247 | }
248 |
249 | it("renders correctly") {
250 | //📷(control)
251 | expect(control).to(haveValidSnapshotWithAcceptableTolerance())
252 | }
253 |
254 | it("has the expected index property") {
255 | expect(control.index).to(equal(0))
256 | }
257 | }
258 |
259 | context("when setting segments to three and then two") {
260 | beforeEach {
261 | control.segments = basicSegmentsThree
262 | control.segments = basicSegmentsTwo
263 | }
264 |
265 | it("renders correctly") {
266 | //📷(control)
267 | expect(control).to(haveValidSnapshotWithAcceptableTolerance())
268 | }
269 |
270 | it("has the expected index property") {
271 | expect(control.index).to(equal(0))
272 | }
273 | }
274 | }
275 | }
276 |
277 | // MARK: cornerRadius
278 | describe("its cornerRadius property") {
279 | beforeEach {
280 | control = .init(frame: testFrame, segments: basicSegmentsThree)
281 | control.backgroundColor = .black
282 | }
283 |
284 | it("the control renders correctly when setting it to 0") {
285 | control.cornerRadius = 0
286 |
287 | //📷(control)
288 | expect(control).to(haveValidSnapshotWithAcceptableTolerance())
289 | }
290 |
291 | it("the control renders correctly when setting it to 10") {
292 | control.cornerRadius = 10
293 |
294 | //📷(control)
295 | expect(control).to(haveValidSnapshotWithAcceptableTolerance())
296 | }
297 | }
298 |
299 | // MARK: indicatorViewBackgroundColor
300 | describe("its indicatorViewBackgroundColor property") {
301 | beforeEach {
302 | control = .init(frame: testFrame, segments: basicSegmentsThree)
303 | }
304 |
305 | it("the control renders correctly after updating it") {
306 | control.indicatorViewBackgroundColor = .green
307 |
308 | //📷(control)
309 | expect(control).to(haveValidSnapshotWithAcceptableTolerance())
310 | }
311 | }
312 |
313 | // MARK: indicatorViewInset
314 | describe("its indicatorViewInset property") {
315 | beforeEach {
316 | control = .init(frame: testFrame, segments: basicSegmentsThree)
317 | control.backgroundColor = .black
318 | }
319 |
320 | it("the control renders correctly when setting it to 0") {
321 | control.indicatorViewInset = 0
322 |
323 | //📷(control)
324 | expect(control).to(haveValidSnapshotWithAcceptableTolerance())
325 | }
326 |
327 | it("the control renders correctly when setting it to 4") {
328 | control.indicatorViewInset = 4
329 |
330 | //📷(control)
331 | expect(control).to(haveValidSnapshotWithAcceptableTolerance())
332 | }
333 | }
334 |
335 | // MARK: indicatorViewBorderWidth
336 | describe("its indicatorViewBorderWidth property") {
337 | beforeEach {
338 | control = .init(frame: testFrame, segments: basicSegmentsThree)
339 | }
340 |
341 | it("the control renders correctly when setting it to 4") {
342 | control.indicatorViewBorderWidth = 4
343 |
344 | //📷(control)
345 | expect(control).to(haveValidSnapshotWithAcceptableTolerance())
346 | }
347 | }
348 |
349 | // MARK: indicatorViewBorderColor
350 | describe("its indicatorViewBorderColor property") {
351 | beforeEach {
352 | control = .init(frame: testFrame, segments: basicSegmentsThree)
353 | control.indicatorViewBorderWidth = 4
354 | }
355 |
356 | it("the control renders correctly when setting it to green") {
357 | control.indicatorViewBorderColor = .green
358 |
359 | //📷(control)
360 | expect(control).to(haveValidSnapshotWithAcceptableTolerance())
361 | }
362 | }
363 |
364 | // MARK: segmentPadding
365 | describe("its segmentPadding property") {
366 | var viewController: StoryboardTestViewController!
367 |
368 | beforeEach({
369 | let storyboard = UIStoryboard(name: "Test", bundle: Bundle(for: type(of: self)))
370 | viewController = storyboard.instantiateInitialViewController() as? StoryboardTestViewController
371 | UIApplication.shared.keyWindow!.rootViewController = viewController
372 | _ = viewController.view
373 |
374 | control = viewController.selfSizingControl
375 | })
376 |
377 | context("when setting it to zero") {
378 | beforeEach {
379 | control.segmentPadding = 0
380 | }
381 |
382 | it("the control renders correctly", closure: {
383 | //📷(control)
384 | expect(control).to(haveValidSnapshotWithAcceptableTolerance())
385 | })
386 | }
387 |
388 | context("when setting it to 8") {
389 | beforeEach {
390 | control.segmentPadding = 8
391 | }
392 |
393 | it("the control renders correctly", closure: {
394 | //📷(control)
395 | expect(control).to(haveValidSnapshotWithAcceptableTolerance())
396 | })
397 | }
398 |
399 | context("when setting it to 28") {
400 | beforeEach {
401 | control.segmentPadding = 28
402 | }
403 |
404 | it("the control renders correctly", closure: {
405 | //📷(control)
406 | expect(control).to(haveValidSnapshotWithAcceptableTolerance())
407 | })
408 | }
409 | }
410 |
411 | // MARK: init(frame:segments:index:options:)
412 | describe("its init(frame:segments:index:options:) initializer") {
413 | context("when calling it") {
414 | context("in the most basic fashion") {
415 | beforeEach {
416 | control = .init(frame: testFrame, segments: basicSegmentsThree)
417 | }
418 |
419 | it("the control has the expected default property values") {
420 | expect(control.alwaysAnnouncesValue).to(beFalse())
421 | expect(control.announcesValueImmediately).to(beTrue())
422 | expect(control.panningDisabled).to(beFalse())
423 | expect(control.animationDuration).to(equal(0.3))
424 | expect(control.animationSpringDamping).to(equal(0.75))
425 | expect(control.segmentPadding).to(equal(14.0))
426 | }
427 | }
428 |
429 | // segments
430 | context("with 0 segments") {
431 | beforeEach {
432 | control = .init(frame: testFrame, segments: [])
433 | }
434 |
435 | it("the control renders correctly") {
436 | //📷(control)
437 | expect(control).to(haveValidSnapshotWithAcceptableTolerance())
438 | }
439 | }
440 |
441 | context("with 1 segment") {
442 | beforeEach {
443 | control = .init(frame: testFrame, segments: basicSegmentOne)
444 | }
445 |
446 | it("the control renders correctly") {
447 | //📷(control)
448 | expect(control).to(haveValidSnapshotWithAcceptableTolerance())
449 | }
450 | }
451 |
452 | context("with 2 segments") {
453 | beforeEach {
454 | control = .init(frame: testFrame, segments: basicSegmentsTwo)
455 | }
456 |
457 | it("the control renders correctly") {
458 | //📷(control)
459 | expect(control).to(haveValidSnapshotWithAcceptableTolerance())
460 | }
461 | }
462 |
463 | context("with 3 segments") {
464 | beforeEach {
465 | control = .init(frame: testFrame, segments: basicSegmentsThree)
466 | }
467 |
468 | it("the control renders correctly") {
469 | //📷(control)
470 | expect(control).to(haveValidSnapshotWithAcceptableTolerance())
471 | }
472 | }
473 |
474 | // index
475 | context("with a valid index") {
476 | context("that is minus 1") {
477 | beforeEach {
478 | control = .init(frame: testFrame, segments: basicSegmentsThree, index: -1)
479 | }
480 |
481 | it("the control renders correctly") {
482 | //📷(control)
483 | expect(control).to(haveValidSnapshotWithAcceptableTolerance())
484 | }
485 |
486 | it("the index property has the expected value") {
487 | expect(control.index).to(equal(-1))
488 | }
489 | }
490 |
491 | context("that is 0") {
492 | beforeEach {
493 | control = .init(frame: testFrame, segments: basicSegmentsThree, index: 0)
494 | }
495 |
496 | it("the control renders correctly") {
497 | //📷(control)
498 | expect(control).to(haveValidSnapshotWithAcceptableTolerance())
499 | }
500 |
501 | it("the index property has the expected value") {
502 | expect(control.index).to(equal(0))
503 | }
504 | }
505 |
506 | context("that is 1") {
507 | beforeEach {
508 | control = .init(frame: testFrame, segments: basicSegmentsThree, index: 1)
509 | }
510 |
511 | it("the control renders correctly") {
512 | //📷(control)
513 | expect(control).to(haveValidSnapshotWithAcceptableTolerance())
514 | }
515 |
516 | it("the index property has the expected value") {
517 | expect(control.index).to(equal(1))
518 | }
519 | }
520 |
521 | context("that is 2") {
522 | beforeEach {
523 | control = .init(frame: testFrame, segments: basicSegmentsThree, index: 2)
524 | }
525 |
526 | it("the control renders correctly") {
527 | //📷(control)
528 | expect(control).to(haveValidSnapshotWithAcceptableTolerance())
529 | }
530 |
531 | it("the index property has the expected value") {
532 | expect(control.index).to(equal(2))
533 | }
534 | }
535 | }
536 |
537 | context("with an invalid index") {
538 | context("that is minus 2") {
539 | beforeEach {
540 | control = .init(frame: testFrame, segments: basicSegmentsThree, index: -2)
541 | }
542 |
543 | it("the control renders correctly") {
544 | //📷(control)
545 | expect(control).to(haveValidSnapshotWithAcceptableTolerance())
546 | }
547 |
548 | it("the index property has the expected value") {
549 | expect(control.index).to(equal(0))
550 | }
551 | }
552 |
553 | context("that is beyond the valid segment indices") {
554 | beforeEach {
555 | control = .init(frame: testFrame, segments: basicSegmentsThree, index: 10)
556 | }
557 |
558 | it("the control renders correctly") {
559 | //📷(control)
560 | expect(control).to(haveValidSnapshotWithAcceptableTolerance())
561 | }
562 |
563 | it("the index property has the expected value") {
564 | expect(control.index).to(equal(0))
565 | }
566 | }
567 | }
568 |
569 | context("with options") {
570 | context("setting the indicatorViewBackgroundColor") {
571 | beforeEach {
572 | control = .init(frame: testFrame,
573 | segments: basicSegmentsThree,
574 | options: [.indicatorViewBackgroundColor(.green)])
575 | }
576 |
577 | it("the control renders correctly") {
578 | //📷(control)
579 | expect(control).to(haveValidSnapshotWithAcceptableTolerance())
580 | }
581 | }
582 |
583 | context("setting the indicatorViewInset") {
584 | beforeEach {
585 | control = .init(frame: testFrame,
586 | segments: basicSegmentsThree,
587 | options: [.indicatorViewInset(8.0)])
588 | }
589 |
590 | it("the control renders correctly") {
591 | //📷(control)
592 | expect(control).to(haveValidSnapshotWithAcceptableTolerance())
593 | }
594 | }
595 |
596 | context("setting the indicatorViewBorderWidth") {
597 | beforeEach {
598 | control = .init(frame: testFrame,
599 | segments: basicSegmentsThree,
600 | options: [.indicatorViewBorderWidth(4.0)])
601 | }
602 |
603 | it("the control renders correctly") {
604 | //📷(control)
605 | expect(control).to(haveValidSnapshotWithAcceptableTolerance())
606 | }
607 | }
608 |
609 | context("setting the indicatorViewBorderColor") {
610 | beforeEach {
611 | control = .init(frame: testFrame,
612 | segments: basicSegmentsThree,
613 | options: [.indicatorViewBorderColor(.green)])
614 | control.indicatorViewBorderWidth = 4.0
615 | }
616 |
617 | it("the control renders correctly") {
618 | //📷(control)
619 | expect(control).to(haveValidSnapshotWithAcceptableTolerance())
620 | }
621 | }
622 |
623 | context("setting the alwaysAnnouncesValue property") {
624 | context("to true") {
625 | beforeEach {
626 | control = .init(frame: testFrame,
627 | segments: basicSegmentsThree,
628 | options: [.alwaysAnnouncesValue(true)])
629 | }
630 |
631 | it("has the expected value") {
632 | expect(control.alwaysAnnouncesValue).to(beTrue())
633 | }
634 | }
635 |
636 | context("to false") {
637 | beforeEach {
638 | control = .init(frame: testFrame,
639 | segments: basicSegmentsThree,
640 | options: [.alwaysAnnouncesValue(false)])
641 | }
642 |
643 | it("has the expected value") {
644 | expect(control.alwaysAnnouncesValue).to(beFalse())
645 | }
646 | }
647 | }
648 |
649 | context("setting the announcesValueImmediately property") {
650 | context("to true") {
651 | beforeEach {
652 | control = .init(frame: testFrame,
653 | segments: basicSegmentsThree,
654 | options: [.announcesValueImmediately(true)])
655 | }
656 |
657 | it("has the expected value") {
658 | expect(control.announcesValueImmediately).to(beTrue())
659 | }
660 | }
661 |
662 | context("to false") {
663 | beforeEach {
664 | control = .init(frame: testFrame,
665 | segments: basicSegmentsThree,
666 | options: [.announcesValueImmediately(false)])
667 | }
668 |
669 | it("has the expected value") {
670 | expect(control.announcesValueImmediately).to(beFalse())
671 | }
672 | }
673 | }
674 |
675 | context("setting the panningDisabled property") {
676 | context("to true") {
677 | beforeEach {
678 | control = .init(frame: testFrame,
679 | segments: basicSegmentsThree,
680 | options: [.panningDisabled(true)])
681 | }
682 |
683 | it("has the expected value") {
684 | expect(control.panningDisabled).to(beTrue())
685 | }
686 | }
687 |
688 | context("to false") {
689 | beforeEach {
690 | control = .init(frame: testFrame,
691 | segments: basicSegmentsThree,
692 | options: [.panningDisabled(false)])
693 | }
694 |
695 | it("has the expected value") {
696 | expect(control.panningDisabled).to(beFalse())
697 | }
698 | }
699 | }
700 |
701 | context("setting the animationDuration property") {
702 | beforeEach {
703 | control = .init(frame: testFrame,
704 | segments: basicSegmentsThree,
705 | options: [.animationDuration(10)])
706 | }
707 |
708 | it("has the expected value") {
709 | expect(control.animationDuration).to(equal(10))
710 | }
711 | }
712 |
713 | context("setting the animationSpringDamping property") {
714 | beforeEach {
715 | control = .init(frame: testFrame,
716 | segments: basicSegmentsThree,
717 | options: [.animationSpringDamping(0.1)])
718 | }
719 |
720 | it("has the expected value") {
721 | expect(control.animationSpringDamping).to(equal(0.1))
722 | }
723 | }
724 |
725 | context("setting the backgroundColor") {
726 | beforeEach {
727 | control = .init(frame: testFrame,
728 | segments: basicSegmentsThree,
729 | options: [.backgroundColor(.green)])
730 | }
731 |
732 | it("the control renders correctly") {
733 | //📷(control)
734 | expect(control).to(haveValidSnapshotWithAcceptableTolerance())
735 | }
736 | }
737 |
738 | context("setting the cornerRadius") {
739 | beforeEach {
740 | control = .init(frame: testFrame,
741 | segments: basicSegmentsThree,
742 | options: [.cornerRadius(16.0)])
743 | }
744 |
745 | it("the control renders correctly") {
746 | //📷(control)
747 | expect(control).to(haveValidSnapshotWithAcceptableTolerance())
748 | }
749 | }
750 | }
751 | }
752 | }
753 |
754 | // MARK: init(coder:)
755 | describe("its init(coder:) initializer") {
756 | context("when called") {
757 | var viewController: StoryboardTestViewController!
758 |
759 | beforeEach({
760 | let storyboard = UIStoryboard(name: "Test", bundle: Bundle(for: type(of: self)))
761 | viewController = storyboard.instantiateInitialViewController() as? StoryboardTestViewController
762 | UIApplication.shared.keyWindow!.rootViewController = viewController
763 | _ = viewController.view
764 |
765 | control = viewController.explicitSizeControl
766 | })
767 |
768 | context("when an expicit size is set in Auto Layout") {
769 | beforeEach {
770 | control = viewController.explicitSizeControl
771 | }
772 |
773 | it("the control renders correctly", closure: {
774 | //📷(control)
775 | expect(control).to(haveValidSnapshotWithAcceptableTolerance())
776 | })
777 | }
778 |
779 | context("when the control auto sizes itself in Auto Layout") {
780 | beforeEach {
781 | control = viewController.selfSizingControl
782 | }
783 |
784 | it("the control renders correctly", closure: {
785 | //📷(control)
786 | expect(control).to(haveValidSnapshotWithAcceptableTolerance())
787 | })
788 | }
789 | }
790 | }
791 |
792 | // MARK: init(frame:)
793 | describe("its init(frame:) initializer") {
794 | context("when called") {
795 | beforeEach {
796 | control = .init(frame: testFrame)
797 | }
798 |
799 | it("the control renders correctly") {
800 | //📷(control)
801 | expect(control).to(haveValidSnapshotWithAcceptableTolerance())
802 | }
803 | }
804 | }
805 |
806 | // MARK: init()
807 | describe("its init() initializer") {
808 | context("when called") {
809 | beforeEach {
810 | control = .init()
811 | }
812 |
813 | it("the frame to be zero") {
814 | expect(control.frame).to(equal(.zero))
815 | }
816 | }
817 | }
818 |
819 | // MARK: setIndex()
820 | describe("its setIndex() method") {
821 | beforeEach {
822 | control = .init(frame: testFrame, segments: basicSegmentsFour)
823 | }
824 |
825 | // index
826 | context("when called with an invalid index") {
827 | context("that is too low") {
828 | beforeEach {
829 | control.setIndex(-2)
830 | }
831 |
832 | it("does not update the control index") {
833 | expect(control.index).to(equal(0))
834 | }
835 | }
836 |
837 | context("that is too high") {
838 | beforeEach {
839 | control.setIndex(10)
840 | }
841 |
842 | it("does not update the control index") {
843 | expect(control.index).to(equal(0))
844 | }
845 | }
846 | }
847 |
848 | context("when called with a valid index") {
849 | context("that is minus 1") {
850 | beforeEach {
851 | control.setIndex(-1)
852 | }
853 |
854 | it("the index property has the expected value") {
855 | expect(control.index).to(equal(-1))
856 | }
857 |
858 | it("the control renders correctly") {
859 | //📷(control)
860 | expect(control).to(haveValidSnapshotWithAcceptableTolerance())
861 | }
862 | }
863 |
864 | context("that is 0") {
865 | beforeEach {
866 | control.setIndex(0)
867 | }
868 |
869 | it("the index property has the expected value") {
870 | expect(control.index).to(equal(0))
871 | }
872 |
873 | it("the control renders correctly") {
874 | //📷(control)
875 | expect(control).to(haveValidSnapshotWithAcceptableTolerance())
876 | }
877 | }
878 |
879 | context("that is 1") {
880 | beforeEach {
881 | control.setIndex(1)
882 | }
883 |
884 | it("the index property has the expected value") {
885 | expect(control.index).to(equal(1))
886 | }
887 |
888 | it("the control renders correctly") {
889 | //📷(control)
890 | expect(control).to(haveValidSnapshotWithAcceptableTolerance())
891 | }
892 | }
893 |
894 | context("that is 2") {
895 | beforeEach {
896 | control.setIndex(2)
897 | }
898 |
899 | it("the index property has the expected value") {
900 | expect(control.index).to(equal(2))
901 | }
902 |
903 | it("the control renders correctly") {
904 | //📷(control)
905 | expect(control).to(haveValidSnapshotWithAcceptableTolerance())
906 | }
907 | }
908 |
909 | context("that is 3") {
910 | beforeEach {
911 | control.setIndex(3)
912 | }
913 |
914 | it("the index property has the expected value") {
915 | expect(control.index).to(equal(3))
916 | }
917 |
918 | it("the control renders correctly") {
919 | //📷(control)
920 | expect(control).to(haveValidSnapshotWithAcceptableTolerance())
921 | }
922 | }
923 | }
924 |
925 | // alwaysAnnouncesValue
926 | context("when called with a alwaysAnnouncesValue parameter") {
927 | var testViewController: TestViewController!
928 |
929 | beforeEach {
930 | testViewController = TestViewController()
931 | control = .init(frame: testFrame, segments: basicSegmentsThree)
932 | control.addTarget(testViewController, action: #selector(TestViewController.valueChanged), for: .valueChanged)
933 | }
934 |
935 | context("when it is false") {
936 | beforeEach {
937 | control.alwaysAnnouncesValue = false
938 | }
939 |
940 | it("the control sends the expected events") {
941 | control.setIndex(0, shouldSendValueChangedEvent: true)
942 | expect(testViewController.valueChangedCalledCount).to(equal(0))
943 |
944 | control.setIndex(1, shouldSendValueChangedEvent: true)
945 | expect(testViewController.valueChangedCalledCount).to(equal(1))
946 |
947 | control.setIndex(0, shouldSendValueChangedEvent: true)
948 | expect(testViewController.valueChangedCalledCount).to(equal(2))
949 |
950 | control.setIndex(0, shouldSendValueChangedEvent: true)
951 | expect(testViewController.valueChangedCalledCount).to(equal(2))
952 | }
953 | }
954 |
955 | context("when it is true") {
956 | beforeEach {
957 | control.alwaysAnnouncesValue = true
958 | }
959 |
960 | it("the control sends the expected events") {
961 | control.setIndex(0, shouldSendValueChangedEvent: true)
962 | expect(testViewController.valueChangedCalledCount).to(equal(1))
963 |
964 | control.setIndex(1, shouldSendValueChangedEvent: true)
965 | expect(testViewController.valueChangedCalledCount).to(equal(2))
966 |
967 | control.setIndex(0, shouldSendValueChangedEvent: true)
968 | expect(testViewController.valueChangedCalledCount).to(equal(3))
969 |
970 | control.setIndex(0, shouldSendValueChangedEvent: true)
971 | expect(testViewController.valueChangedCalledCount).to(equal(4))
972 | }
973 | }
974 | }
975 |
976 | // shouldSendValueChangedEvent
977 | context("when called with a shouldSendValueChangedEvent parameter") {
978 | var testViewController: TestViewController!
979 |
980 | beforeEach {
981 | testViewController = TestViewController()
982 | control = .init(frame: testFrame, segments: basicSegmentsThree)
983 | control.addTarget(testViewController, action: #selector(TestViewController.valueChanged), for: .valueChanged)
984 | }
985 |
986 | context("when it is false") {
987 | beforeEach {
988 | control.setIndex(1, shouldSendValueChangedEvent: false)
989 | control.setIndex(2, shouldSendValueChangedEvent: false)
990 | }
991 |
992 | it("the control does not send a valueChanged event") {
993 | expect(testViewController.valueChangedCalledCount).to(equal(0))
994 | }
995 | }
996 |
997 | context("when it is true") {
998 | beforeEach {
999 | control.setIndex(1, shouldSendValueChangedEvent: true)
1000 | control.setIndex(2, shouldSendValueChangedEvent: true)
1001 | }
1002 |
1003 | it("the control does send valueChanged events") {
1004 | expect(testViewController.valueChangedCalledCount).to(equal(2))
1005 | }
1006 | }
1007 | }
1008 | }
1009 |
1010 | // MARK: setOptions()
1011 | describe("its setOptions() method") {
1012 | beforeEach {
1013 | control = .init(frame: testFrame, segments: basicSegmentsThree)
1014 | }
1015 |
1016 | context("when setting indicatorViewBackgroundColor") {
1017 | beforeEach {
1018 | control.setOptions([.indicatorViewBackgroundColor(.green)])
1019 | }
1020 |
1021 | it("renders correctly") {
1022 | //📷(control)
1023 | expect(control).to(haveValidSnapshotWithAcceptableTolerance())
1024 | }
1025 | }
1026 |
1027 | context("when setting indicatorViewInset") {
1028 | beforeEach {
1029 | control.setOptions([.indicatorViewInset(8)])
1030 | }
1031 |
1032 | it("renders correctly") {
1033 | //📷(control)
1034 | expect(control).to(haveValidSnapshotWithAcceptableTolerance())
1035 | }
1036 |
1037 | it("has the expected value") {
1038 | expect(control.indicatorViewInset).to(equal(8))
1039 | }
1040 | }
1041 |
1042 | context("when setting indicatorViewBorderWidth and indicatorViewBorderColor") {
1043 | beforeEach {
1044 | control.setOptions([.indicatorViewBorderWidth(4), .indicatorViewBorderColor(.green)])
1045 | }
1046 |
1047 | it("renders correctly") {
1048 | //📷(control)
1049 | expect(control).to(haveValidSnapshotWithAcceptableTolerance())
1050 | }
1051 |
1052 | it("has the expected values") {
1053 | expect(control.indicatorViewBorderWidth).to(equal(4))
1054 | expect(control.indicatorViewBorderColor).to(equal(.green))
1055 | }
1056 | }
1057 |
1058 | context("when setting alwaysAnnouncesValue") {
1059 | context("to true") {
1060 | beforeEach {
1061 | control.setOptions([.alwaysAnnouncesValue(true)])
1062 | }
1063 |
1064 | it("returns the expected property value") {
1065 | expect(control.alwaysAnnouncesValue).to(beTrue())
1066 | }
1067 | }
1068 | context("to false") {
1069 | beforeEach {
1070 | control.setOptions([.alwaysAnnouncesValue(false)])
1071 | }
1072 |
1073 | it("returns the expected property value") {
1074 | expect(control.alwaysAnnouncesValue).to(beFalse())
1075 | }
1076 | }
1077 | }
1078 |
1079 | context("when setting announcesValueImmediately") {
1080 | context("to true") {
1081 | beforeEach {
1082 | control.setOptions([.announcesValueImmediately(true)])
1083 | }
1084 |
1085 | it("returns the expected property value") {
1086 | expect(control.announcesValueImmediately).to(beTrue())
1087 | }
1088 | }
1089 | context("to false") {
1090 | beforeEach {
1091 | control.setOptions([.announcesValueImmediately(false)])
1092 | }
1093 |
1094 | it("returns the expected property value") {
1095 | expect(control.announcesValueImmediately).to(beFalse())
1096 | }
1097 | }
1098 | }
1099 |
1100 | context("when setting panningDisabled") {
1101 | context("to true") {
1102 | beforeEach {
1103 | control.setOptions([.panningDisabled(true)])
1104 | }
1105 |
1106 | it("returns the expected property value") {
1107 | expect(control.panningDisabled).to(beTrue())
1108 | }
1109 | }
1110 | context("to false") {
1111 | beforeEach {
1112 | control.setOptions([.panningDisabled(false)])
1113 | }
1114 |
1115 | it("returns the expected property value") {
1116 | expect(control.panningDisabled).to(beFalse())
1117 | }
1118 | }
1119 | }
1120 |
1121 | context("when setting animationDuration") {
1122 | beforeEach {
1123 | control.setOptions([.animationDuration(10.0)])
1124 | }
1125 |
1126 | it("returns the expected property value") {
1127 | expect(control.animationDuration).to(equal(10.0))
1128 | }
1129 | }
1130 |
1131 | context("when setting animationSpringDamping") {
1132 | beforeEach {
1133 | control.setOptions([.animationSpringDamping(0.1)])
1134 | }
1135 |
1136 | it("returns the expected property value") {
1137 | expect(control.animationSpringDamping).to(equal(0.1))
1138 | }
1139 | }
1140 |
1141 | context("when setting backgroundColor") {
1142 | beforeEach {
1143 | control.setOptions([.backgroundColor(.green)])
1144 | }
1145 |
1146 | it("renders correctly") {
1147 | //📷(control)
1148 | expect(control).to(haveValidSnapshotWithAcceptableTolerance())
1149 | }
1150 |
1151 | it("has the expected value") {
1152 | expect(control.backgroundColor).to(equal(.green))
1153 | }
1154 | }
1155 |
1156 | context("when setting cornerRadius") {
1157 | beforeEach {
1158 | control.setOptions([.cornerRadius(10.0)])
1159 | }
1160 |
1161 | it("renders correctly") {
1162 | //📷(control)
1163 | expect(control).to(haveValidSnapshotWithAcceptableTolerance())
1164 | }
1165 | }
1166 | }
1167 |
1168 | // MARK: Indicator view shadow
1169 | context("when adding a shadow to the indicator view") {
1170 | beforeEach {
1171 | control = .init(frame: testFrame, segments: basicSegmentsThree)
1172 | control.indicatorView.layer.shadowColor = UIColor.black.cgColor
1173 | control.indicatorView.layer.shadowOpacity = 0.1
1174 | control.indicatorView.layer.shadowOffset = CGSize(width: 1, height: 1)
1175 | control.indicatorView.layer.shadowRadius = 2
1176 | }
1177 |
1178 | it("renders correctly") {
1179 | //📷(control)
1180 | expect(control).to(haveValidSnapshotWithAcceptableTolerance())
1181 | }
1182 | }
1183 |
1184 | // MARK: appleStyled() extension
1185 | describe("its appleStyled extension") {
1186 | beforeEach {
1187 | control = .appleStyled(frame: testFrame, titles: ["One", "Two", "Three"])
1188 | }
1189 |
1190 | it("renders correctly") {
1191 | //📷(control)
1192 | expect(control).to(haveValidSnapshotWithAcceptableTolerance())
1193 | }
1194 | }
1195 |
1196 | // added to prevent regression of https://github.com/gmarm/BetterSegmentedControl/issues/83
1197 | context("when setting cornerRadius and indicatorViewInset") {
1198 | context("first cornerRadius then indicatorViewInset") {
1199 | beforeEach {
1200 | control = .init(frame: testFrame, segments: basicSegmentsThree, options: [.cornerRadius(10.0),
1201 | .indicatorViewInset(4.0)])
1202 | control.backgroundColor = .black
1203 | }
1204 |
1205 | it("renders correctly") {
1206 | //📷(control)
1207 | expect(control).to(haveValidSnapshotWithAcceptableTolerance())
1208 | }
1209 | }
1210 |
1211 | context("first indicatorViewInset then cornerRadius") {
1212 | beforeEach {
1213 | control = .init(frame: testFrame, segments: basicSegmentsThree, options: [.indicatorViewInset(4.0),
1214 | .cornerRadius(10.0)])
1215 | control.backgroundColor = .black
1216 | }
1217 |
1218 | it("renders correctly") {
1219 | //📷(control)
1220 | expect(control).to(haveValidSnapshotWithAcceptableTolerance())
1221 | }
1222 | }
1223 | }
1224 | }
1225 | }
1226 | }
1227 |
--------------------------------------------------------------------------------
/Example/Tests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 |
24 |
25 |
--------------------------------------------------------------------------------
/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_appleStyled_extension__renders_correctly@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gmarm/BetterSegmentedControl/32348f8fc700c78a6aefa731214cb4497757a48b/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_appleStyled_extension__renders_correctly@3x.png
--------------------------------------------------------------------------------
/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_cornerRadius_property__the_control_renders_correctly_when_setting_it_to_0@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gmarm/BetterSegmentedControl/32348f8fc700c78a6aefa731214cb4497757a48b/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_cornerRadius_property__the_control_renders_correctly_when_setting_it_to_0@3x.png
--------------------------------------------------------------------------------
/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_cornerRadius_property__the_control_renders_correctly_when_setting_it_to_10@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gmarm/BetterSegmentedControl/32348f8fc700c78a6aefa731214cb4497757a48b/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_cornerRadius_property__the_control_renders_correctly_when_setting_it_to_10@3x.png
--------------------------------------------------------------------------------
/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_indicatorViewBackgroundColor_property__the_control_renders_correctly_after_updating_it@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gmarm/BetterSegmentedControl/32348f8fc700c78a6aefa731214cb4497757a48b/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_indicatorViewBackgroundColor_property__the_control_renders_correctly_after_updating_it@3x.png
--------------------------------------------------------------------------------
/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_indicatorViewBorderColor_property__the_control_renders_correctly_when_setting_it_to_green@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gmarm/BetterSegmentedControl/32348f8fc700c78a6aefa731214cb4497757a48b/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_indicatorViewBorderColor_property__the_control_renders_correctly_when_setting_it_to_green@3x.png
--------------------------------------------------------------------------------
/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_indicatorViewBorderWidth_property__the_control_renders_correctly_when_setting_it_to_4@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gmarm/BetterSegmentedControl/32348f8fc700c78a6aefa731214cb4497757a48b/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_indicatorViewBorderWidth_property__the_control_renders_correctly_when_setting_it_to_4@3x.png
--------------------------------------------------------------------------------
/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_indicatorViewInset_property__the_control_renders_correctly_when_setting_it_to_0@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gmarm/BetterSegmentedControl/32348f8fc700c78a6aefa731214cb4497757a48b/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_indicatorViewInset_property__the_control_renders_correctly_when_setting_it_to_0@3x.png
--------------------------------------------------------------------------------
/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_indicatorViewInset_property__the_control_renders_correctly_when_setting_it_to_4@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gmarm/BetterSegmentedControl/32348f8fc700c78a6aefa731214cb4497757a48b/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_indicatorViewInset_property__the_control_renders_correctly_when_setting_it_to_4@3x.png
--------------------------------------------------------------------------------
/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_init_coder___initializer__when_called__when_an_expicit_size_is_set_in_Auto_Layout__the_control_renders_correctly@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gmarm/BetterSegmentedControl/32348f8fc700c78a6aefa731214cb4497757a48b/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_init_coder___initializer__when_called__when_an_expicit_size_is_set_in_Auto_Layout__the_control_renders_correctly@3x.png
--------------------------------------------------------------------------------
/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_init_coder___initializer__when_called__when_the_control_auto_sizes_itself_in_Auto_Layout__the_control_renders_correctly@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gmarm/BetterSegmentedControl/32348f8fc700c78a6aefa731214cb4497757a48b/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_init_coder___initializer__when_called__when_the_control_auto_sizes_itself_in_Auto_Layout__the_control_renders_correctly@3x.png
--------------------------------------------------------------------------------
/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_init_frame___initializer__when_called__the_control_renders_correctly@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gmarm/BetterSegmentedControl/32348f8fc700c78a6aefa731214cb4497757a48b/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_init_frame___initializer__when_called__the_control_renders_correctly@3x.png
--------------------------------------------------------------------------------
/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_init_frame_segments_index_options___initializer__when_calling_it__with_0_segments__the_control_renders_correctly@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gmarm/BetterSegmentedControl/32348f8fc700c78a6aefa731214cb4497757a48b/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_init_frame_segments_index_options___initializer__when_calling_it__with_0_segments__the_control_renders_correctly@3x.png
--------------------------------------------------------------------------------
/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_init_frame_segments_index_options___initializer__when_calling_it__with_1_segment__the_control_renders_correctly@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gmarm/BetterSegmentedControl/32348f8fc700c78a6aefa731214cb4497757a48b/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_init_frame_segments_index_options___initializer__when_calling_it__with_1_segment__the_control_renders_correctly@3x.png
--------------------------------------------------------------------------------
/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_init_frame_segments_index_options___initializer__when_calling_it__with_2_segments__the_control_renders_correctly@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gmarm/BetterSegmentedControl/32348f8fc700c78a6aefa731214cb4497757a48b/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_init_frame_segments_index_options___initializer__when_calling_it__with_2_segments__the_control_renders_correctly@3x.png
--------------------------------------------------------------------------------
/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_init_frame_segments_index_options___initializer__when_calling_it__with_3_segments__the_control_renders_correctly@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gmarm/BetterSegmentedControl/32348f8fc700c78a6aefa731214cb4497757a48b/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_init_frame_segments_index_options___initializer__when_calling_it__with_3_segments__the_control_renders_correctly@3x.png
--------------------------------------------------------------------------------
/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_init_frame_segments_index_options___initializer__when_calling_it__with_a_valid_index__that_is_0__the_control_renders_correctly@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gmarm/BetterSegmentedControl/32348f8fc700c78a6aefa731214cb4497757a48b/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_init_frame_segments_index_options___initializer__when_calling_it__with_a_valid_index__that_is_0__the_control_renders_correctly@3x.png
--------------------------------------------------------------------------------
/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_init_frame_segments_index_options___initializer__when_calling_it__with_a_valid_index__that_is_1__the_control_renders_correctly@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gmarm/BetterSegmentedControl/32348f8fc700c78a6aefa731214cb4497757a48b/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_init_frame_segments_index_options___initializer__when_calling_it__with_a_valid_index__that_is_1__the_control_renders_correctly@3x.png
--------------------------------------------------------------------------------
/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_init_frame_segments_index_options___initializer__when_calling_it__with_a_valid_index__that_is_2__the_control_renders_correctly@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gmarm/BetterSegmentedControl/32348f8fc700c78a6aefa731214cb4497757a48b/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_init_frame_segments_index_options___initializer__when_calling_it__with_a_valid_index__that_is_2__the_control_renders_correctly@3x.png
--------------------------------------------------------------------------------
/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_init_frame_segments_index_options___initializer__when_calling_it__with_a_valid_index__that_is_minus_1__the_control_renders_correctly@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gmarm/BetterSegmentedControl/32348f8fc700c78a6aefa731214cb4497757a48b/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_init_frame_segments_index_options___initializer__when_calling_it__with_a_valid_index__that_is_minus_1__the_control_renders_correctly@3x.png
--------------------------------------------------------------------------------
/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_init_frame_segments_index_options___initializer__when_calling_it__with_an_invalid_index__that_is_beyond_the_valid_segment_indices__the_control_renders_correctly@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gmarm/BetterSegmentedControl/32348f8fc700c78a6aefa731214cb4497757a48b/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_init_frame_segments_index_options___initializer__when_calling_it__with_an_invalid_index__that_is_beyond_the_valid_segment_indices__the_control_renders_correctly@3x.png
--------------------------------------------------------------------------------
/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_init_frame_segments_index_options___initializer__when_calling_it__with_an_invalid_index__that_is_minus_2__the_control_renders_correctly@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gmarm/BetterSegmentedControl/32348f8fc700c78a6aefa731214cb4497757a48b/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_init_frame_segments_index_options___initializer__when_calling_it__with_an_invalid_index__that_is_minus_2__the_control_renders_correctly@3x.png
--------------------------------------------------------------------------------
/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_init_frame_segments_index_options___initializer__when_calling_it__with_options__setting_the_backgroundColor__the_control_renders_correctly@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gmarm/BetterSegmentedControl/32348f8fc700c78a6aefa731214cb4497757a48b/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_init_frame_segments_index_options___initializer__when_calling_it__with_options__setting_the_backgroundColor__the_control_renders_correctly@3x.png
--------------------------------------------------------------------------------
/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_init_frame_segments_index_options___initializer__when_calling_it__with_options__setting_the_cornerRadius__the_control_renders_correctly@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gmarm/BetterSegmentedControl/32348f8fc700c78a6aefa731214cb4497757a48b/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_init_frame_segments_index_options___initializer__when_calling_it__with_options__setting_the_cornerRadius__the_control_renders_correctly@3x.png
--------------------------------------------------------------------------------
/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_init_frame_segments_index_options___initializer__when_calling_it__with_options__setting_the_indicatorViewBackgroundColor__the_control_renders_correctly@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gmarm/BetterSegmentedControl/32348f8fc700c78a6aefa731214cb4497757a48b/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_init_frame_segments_index_options___initializer__when_calling_it__with_options__setting_the_indicatorViewBackgroundColor__the_control_renders_correctly@3x.png
--------------------------------------------------------------------------------
/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_init_frame_segments_index_options___initializer__when_calling_it__with_options__setting_the_indicatorViewBorderColor__the_control_renders_correctly@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gmarm/BetterSegmentedControl/32348f8fc700c78a6aefa731214cb4497757a48b/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_init_frame_segments_index_options___initializer__when_calling_it__with_options__setting_the_indicatorViewBorderColor__the_control_renders_correctly@3x.png
--------------------------------------------------------------------------------
/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_init_frame_segments_index_options___initializer__when_calling_it__with_options__setting_the_indicatorViewBorderWidth__the_control_renders_correctly@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gmarm/BetterSegmentedControl/32348f8fc700c78a6aefa731214cb4497757a48b/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_init_frame_segments_index_options___initializer__when_calling_it__with_options__setting_the_indicatorViewBorderWidth__the_control_renders_correctly@3x.png
--------------------------------------------------------------------------------
/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_init_frame_segments_index_options___initializer__when_calling_it__with_options__setting_the_indicatorViewInset__the_control_renders_correctly@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gmarm/BetterSegmentedControl/32348f8fc700c78a6aefa731214cb4497757a48b/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_init_frame_segments_index_options___initializer__when_calling_it__with_options__setting_the_indicatorViewInset__the_control_renders_correctly@3x.png
--------------------------------------------------------------------------------
/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_segmentPadding_property__when_setting_it_to_28__the_control_renders_correctly@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gmarm/BetterSegmentedControl/32348f8fc700c78a6aefa731214cb4497757a48b/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_segmentPadding_property__when_setting_it_to_28__the_control_renders_correctly@3x.png
--------------------------------------------------------------------------------
/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_segmentPadding_property__when_setting_it_to_8__the_control_renders_correctly@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gmarm/BetterSegmentedControl/32348f8fc700c78a6aefa731214cb4497757a48b/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_segmentPadding_property__when_setting_it_to_8__the_control_renders_correctly@3x.png
--------------------------------------------------------------------------------
/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_segmentPadding_property__when_setting_it_to_zero__the_control_renders_correctly@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gmarm/BetterSegmentedControl/32348f8fc700c78a6aefa731214cb4497757a48b/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_segmentPadding_property__when_setting_it_to_zero__the_control_renders_correctly@3x.png
--------------------------------------------------------------------------------
/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_segments_property__when_the_control_is_initialized_with_one_segment__when_setting_segments_to_one__renders_correctly@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gmarm/BetterSegmentedControl/32348f8fc700c78a6aefa731214cb4497757a48b/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_segments_property__when_the_control_is_initialized_with_one_segment__when_setting_segments_to_one__renders_correctly@3x.png
--------------------------------------------------------------------------------
/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_segments_property__when_the_control_is_initialized_with_one_segment__when_setting_segments_to_three_and_then_two__renders_correctly@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gmarm/BetterSegmentedControl/32348f8fc700c78a6aefa731214cb4497757a48b/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_segments_property__when_the_control_is_initialized_with_one_segment__when_setting_segments_to_three_and_then_two__renders_correctly@3x.png
--------------------------------------------------------------------------------
/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_segments_property__when_the_control_is_initialized_with_one_segment__when_setting_segments_to_two__renders_correctly@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gmarm/BetterSegmentedControl/32348f8fc700c78a6aefa731214cb4497757a48b/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_segments_property__when_the_control_is_initialized_with_one_segment__when_setting_segments_to_two__renders_correctly@3x.png
--------------------------------------------------------------------------------
/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_segments_property__when_the_control_is_initialized_with_one_segment__when_setting_segments_to_two_and_then_three__renders_correctly@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gmarm/BetterSegmentedControl/32348f8fc700c78a6aefa731214cb4497757a48b/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_segments_property__when_the_control_is_initialized_with_one_segment__when_setting_segments_to_two_and_then_three__renders_correctly@3x.png
--------------------------------------------------------------------------------
/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_segments_property__when_the_control_is_initialized_with_one_segment__when_setting_segments_to_zero__renders_correctly@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gmarm/BetterSegmentedControl/32348f8fc700c78a6aefa731214cb4497757a48b/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_segments_property__when_the_control_is_initialized_with_one_segment__when_setting_segments_to_zero__renders_correctly@3x.png
--------------------------------------------------------------------------------
/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_segments_property__when_the_control_is_initialized_with_two_segments__when_setting_segments_to_one__renders_correctly@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gmarm/BetterSegmentedControl/32348f8fc700c78a6aefa731214cb4497757a48b/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_segments_property__when_the_control_is_initialized_with_two_segments__when_setting_segments_to_one__renders_correctly@3x.png
--------------------------------------------------------------------------------
/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_segments_property__when_the_control_is_initialized_with_two_segments__when_setting_segments_to_three_and_then_two__renders_correctly@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gmarm/BetterSegmentedControl/32348f8fc700c78a6aefa731214cb4497757a48b/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_segments_property__when_the_control_is_initialized_with_two_segments__when_setting_segments_to_three_and_then_two__renders_correctly@3x.png
--------------------------------------------------------------------------------
/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_segments_property__when_the_control_is_initialized_with_two_segments__when_setting_segments_to_two__renders_correctly@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gmarm/BetterSegmentedControl/32348f8fc700c78a6aefa731214cb4497757a48b/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_segments_property__when_the_control_is_initialized_with_two_segments__when_setting_segments_to_two__renders_correctly@3x.png
--------------------------------------------------------------------------------
/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_segments_property__when_the_control_is_initialized_with_two_segments__when_setting_segments_to_two_and_then_three__renders_correctly@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gmarm/BetterSegmentedControl/32348f8fc700c78a6aefa731214cb4497757a48b/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_segments_property__when_the_control_is_initialized_with_two_segments__when_setting_segments_to_two_and_then_three__renders_correctly@3x.png
--------------------------------------------------------------------------------
/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_segments_property__when_the_control_is_initialized_with_two_segments__when_setting_segments_to_zero__renders_correctly@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gmarm/BetterSegmentedControl/32348f8fc700c78a6aefa731214cb4497757a48b/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_segments_property__when_the_control_is_initialized_with_two_segments__when_setting_segments_to_zero__renders_correctly@3x.png
--------------------------------------------------------------------------------
/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_segments_property__when_the_control_is_initialized_with_zero_segments__when_setting_segments_to_one__renders_correctly@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gmarm/BetterSegmentedControl/32348f8fc700c78a6aefa731214cb4497757a48b/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_segments_property__when_the_control_is_initialized_with_zero_segments__when_setting_segments_to_one__renders_correctly@3x.png
--------------------------------------------------------------------------------
/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_segments_property__when_the_control_is_initialized_with_zero_segments__when_setting_segments_to_three_and_then_two__renders_correctly@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gmarm/BetterSegmentedControl/32348f8fc700c78a6aefa731214cb4497757a48b/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_segments_property__when_the_control_is_initialized_with_zero_segments__when_setting_segments_to_three_and_then_two__renders_correctly@3x.png
--------------------------------------------------------------------------------
/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_segments_property__when_the_control_is_initialized_with_zero_segments__when_setting_segments_to_two__renders_correctly@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gmarm/BetterSegmentedControl/32348f8fc700c78a6aefa731214cb4497757a48b/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_segments_property__when_the_control_is_initialized_with_zero_segments__when_setting_segments_to_two__renders_correctly@3x.png
--------------------------------------------------------------------------------
/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_segments_property__when_the_control_is_initialized_with_zero_segments__when_setting_segments_to_two_and_then_three__renders_correctly@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gmarm/BetterSegmentedControl/32348f8fc700c78a6aefa731214cb4497757a48b/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_segments_property__when_the_control_is_initialized_with_zero_segments__when_setting_segments_to_two_and_then_three__renders_correctly@3x.png
--------------------------------------------------------------------------------
/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_segments_property__when_the_control_is_initialized_with_zero_segments__when_setting_segments_to_zero__renders_correctly@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gmarm/BetterSegmentedControl/32348f8fc700c78a6aefa731214cb4497757a48b/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_segments_property__when_the_control_is_initialized_with_zero_segments__when_setting_segments_to_zero__renders_correctly@3x.png
--------------------------------------------------------------------------------
/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_setIndex___method__when_called_with_a_valid_index__that_is_0__the_control_renders_correctly@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gmarm/BetterSegmentedControl/32348f8fc700c78a6aefa731214cb4497757a48b/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_setIndex___method__when_called_with_a_valid_index__that_is_0__the_control_renders_correctly@3x.png
--------------------------------------------------------------------------------
/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_setIndex___method__when_called_with_a_valid_index__that_is_1__the_control_renders_correctly@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gmarm/BetterSegmentedControl/32348f8fc700c78a6aefa731214cb4497757a48b/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_setIndex___method__when_called_with_a_valid_index__that_is_1__the_control_renders_correctly@3x.png
--------------------------------------------------------------------------------
/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_setIndex___method__when_called_with_a_valid_index__that_is_2__the_control_renders_correctly@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gmarm/BetterSegmentedControl/32348f8fc700c78a6aefa731214cb4497757a48b/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_setIndex___method__when_called_with_a_valid_index__that_is_2__the_control_renders_correctly@3x.png
--------------------------------------------------------------------------------
/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_setIndex___method__when_called_with_a_valid_index__that_is_3__the_control_renders_correctly@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gmarm/BetterSegmentedControl/32348f8fc700c78a6aefa731214cb4497757a48b/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_setIndex___method__when_called_with_a_valid_index__that_is_3__the_control_renders_correctly@3x.png
--------------------------------------------------------------------------------
/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_setIndex___method__when_called_with_a_valid_index__that_is_minus_1__the_control_renders_correctly@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gmarm/BetterSegmentedControl/32348f8fc700c78a6aefa731214cb4497757a48b/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_setIndex___method__when_called_with_a_valid_index__that_is_minus_1__the_control_renders_correctly@3x.png
--------------------------------------------------------------------------------
/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_setOptions___method__when_setting_backgroundColor__renders_correctly@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gmarm/BetterSegmentedControl/32348f8fc700c78a6aefa731214cb4497757a48b/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_setOptions___method__when_setting_backgroundColor__renders_correctly@3x.png
--------------------------------------------------------------------------------
/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_setOptions___method__when_setting_cornerRadius__renders_correctly@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gmarm/BetterSegmentedControl/32348f8fc700c78a6aefa731214cb4497757a48b/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_setOptions___method__when_setting_cornerRadius__renders_correctly@3x.png
--------------------------------------------------------------------------------
/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_setOptions___method__when_setting_indicatorViewBackgroundColor__renders_correctly@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gmarm/BetterSegmentedControl/32348f8fc700c78a6aefa731214cb4497757a48b/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_setOptions___method__when_setting_indicatorViewBackgroundColor__renders_correctly@3x.png
--------------------------------------------------------------------------------
/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_setOptions___method__when_setting_indicatorViewBorderWidth_and_indicatorViewBorderColor__renders_correctly@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gmarm/BetterSegmentedControl/32348f8fc700c78a6aefa731214cb4497757a48b/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_setOptions___method__when_setting_indicatorViewBorderWidth_and_indicatorViewBorderColor__renders_correctly@3x.png
--------------------------------------------------------------------------------
/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_setOptions___method__when_setting_indicatorViewInset__renders_correctly@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gmarm/BetterSegmentedControl/32348f8fc700c78a6aefa731214cb4497757a48b/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__its_setOptions___method__when_setting_indicatorViewInset__renders_correctly@3x.png
--------------------------------------------------------------------------------
/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__when_adding_a_shadow_to_the_indicator_view__renders_correctly@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gmarm/BetterSegmentedControl/32348f8fc700c78a6aefa731214cb4497757a48b/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__when_adding_a_shadow_to_the_indicator_view__renders_correctly@3x.png
--------------------------------------------------------------------------------
/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__when_setting_cornerRadius_and_indicatorViewInset__first_cornerRadius_then_indicatorViewInset__renders_correctly@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gmarm/BetterSegmentedControl/32348f8fc700c78a6aefa731214cb4497757a48b/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__when_setting_cornerRadius_and_indicatorViewInset__first_cornerRadius_then_indicatorViewInset__renders_correctly@3x.png
--------------------------------------------------------------------------------
/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__when_setting_cornerRadius_and_indicatorViewInset__first_indicatorViewInset_then_cornerRadius__renders_correctly@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gmarm/BetterSegmentedControl/32348f8fc700c78a6aefa731214cb4497757a48b/Example/Tests/ReferenceImages/BetterSegmentedControlTests/a_BetterSegmentedControl__when_setting_cornerRadius_and_indicatorViewInset__first_indicatorViewInset_then_cornerRadius__renders_correctly@3x.png
--------------------------------------------------------------------------------
/Example/Tests/SnapshotHelpers.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SnapshotHelpers.swift
3 | // BetterSegmentedControl_Tests
4 | //
5 | // Created by George Marmaridis on 18.10.20.
6 | // Copyright © 2020 CocoaPods. All rights reserved.
7 | //
8 |
9 | import Nimble
10 | import Nimble_Snapshots
11 |
12 | public func haveValidSnapshotWithAcceptableTolerance() -> Predicate {
13 | haveValidSnapshot(named: nil, identifier: nil, usesDrawRect: false, tolerance: 0.01)
14 | }
15 |
--------------------------------------------------------------------------------
/Example/Tests/Test.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
--------------------------------------------------------------------------------
/Example/Tests/TestViewControllers.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TestViewController.swift
3 | // BetterSegmentedControl
4 | //
5 | // Created by George Marmaridis on 23/04/16.
6 | // Copyright © 2020 George Marmaridis. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import UIKit
11 | import BetterSegmentedControl
12 |
13 | final class StoryboardTestViewController: UIViewController {
14 | @IBOutlet weak var explicitSizeControl: BetterSegmentedControl!
15 | @IBOutlet weak var selfSizingControl: BetterSegmentedControl!
16 | }
17 |
18 | final class TestViewController: UIViewController {
19 | var valueChangedCalledCount = 0
20 | @objc func valueChanged() {
21 | valueChangedCalledCount += 1
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 |
3 | gem 'slather'
4 |
--------------------------------------------------------------------------------
/Gemfile.lock:
--------------------------------------------------------------------------------
1 | GEM
2 | remote: https://rubygems.org/
3 | specs:
4 | CFPropertyList (3.0.2)
5 | activesupport (6.0.3.4)
6 | concurrent-ruby (~> 1.0, >= 1.0.2)
7 | i18n (>= 0.7, < 2)
8 | minitest (~> 5.1)
9 | tzinfo (~> 1.1)
10 | zeitwerk (~> 2.2, >= 2.2.2)
11 | atomos (0.1.3)
12 | claide (1.0.3)
13 | clamp (1.3.2)
14 | colored2 (3.1.2)
15 | concurrent-ruby (1.1.7)
16 | i18n (1.8.5)
17 | concurrent-ruby (~> 1.0)
18 | mini_portile2 (2.4.0)
19 | minitest (5.14.2)
20 | nanaimo (0.3.0)
21 | nokogiri (1.10.10)
22 | mini_portile2 (~> 2.4.0)
23 | slather (2.5.0)
24 | CFPropertyList (>= 2.2, < 4)
25 | activesupport
26 | clamp (~> 1.3)
27 | nokogiri (~> 1.8)
28 | xcodeproj (~> 1.7)
29 | thread_safe (0.3.6)
30 | tzinfo (1.2.7)
31 | thread_safe (~> 0.1)
32 | xcodeproj (1.19.0)
33 | CFPropertyList (>= 2.3.3, < 4.0)
34 | atomos (~> 0.1.3)
35 | claide (>= 1.0.2, < 2.0)
36 | colored2 (~> 3.1)
37 | nanaimo (~> 0.3.0)
38 | zeitwerk (2.4.0)
39 |
40 | PLATFORMS
41 | ruby
42 |
43 | DEPENDENCIES
44 | slather
45 |
46 | BUNDLED WITH
47 | 2.1.4
48 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2016 George Marmaridis
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 |
--------------------------------------------------------------------------------
/Package.swift:
--------------------------------------------------------------------------------
1 | // swift-tools-version:5.1
2 | import PackageDescription
3 |
4 | let package = Package(
5 | name: "BetterSegmentedControl",
6 | platforms: [
7 | .iOS(.v9),
8 | ],
9 | products: [
10 | .library(
11 | name: "BetterSegmentedControl",
12 | targets: ["BetterSegmentedControl"]
13 | )
14 | ],
15 | targets: [
16 | .target(
17 | name: "BetterSegmentedControl",
18 | path: "Pod/Classes"
19 | )
20 | ],
21 | swiftLanguageVersions: [.v5]
22 | )
23 |
--------------------------------------------------------------------------------
/Pod/Assets/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gmarm/BetterSegmentedControl/32348f8fc700c78a6aefa731214cb4497757a48b/Pod/Assets/.gitkeep
--------------------------------------------------------------------------------
/Pod/Classes/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gmarm/BetterSegmentedControl/32348f8fc700c78a6aefa731214cb4497757a48b/Pod/Classes/.gitkeep
--------------------------------------------------------------------------------
/Pod/Classes/BetterSegmentedControl+IBDesignable.swift:
--------------------------------------------------------------------------------
1 | //
2 | // BetterSegmentedControl+IBDesignable.swift
3 | // BetterSegmentedControl
4 | //
5 | // Created by George Marmaridis on 20.10.20.
6 | //
7 |
8 | #if canImport(UIKit)
9 |
10 | import UIKit
11 |
12 | extension BetterSegmentedControl {
13 | open override func prepareForInterfaceBuilder() {
14 | super.prepareForInterfaceBuilder()
15 |
16 | setDefaultColorsIfNeeded()
17 | }
18 | open override func awakeFromNib() {
19 | super.awakeFromNib()
20 |
21 | setDefaultColorsIfNeeded()
22 | }
23 | private func setDefaultColorsIfNeeded() {
24 | if #available(iOS 13.0, *) {
25 | if backgroundColor == UIColor.systemBackground || backgroundColor == nil {
26 | backgroundColor = .appleSegmentedControlDefaultControlBackground
27 | }
28 | if indicatorViewBackgroundColor == UIColor.systemBackground || indicatorViewBackgroundColor == nil {
29 | indicatorViewBackgroundColor = .appleSegmentedControlDefaultIndicatorBackground
30 | }
31 | } else {
32 | if backgroundColor == nil {
33 | backgroundColor = .appleSegmentedControlDefaultControlBackground
34 | }
35 | if indicatorViewBackgroundColor == nil {
36 | indicatorViewBackgroundColor = .appleSegmentedControlDefaultIndicatorBackground
37 | }
38 | }
39 | }
40 | }
41 |
42 | #endif
43 |
--------------------------------------------------------------------------------
/Pod/Classes/BetterSegmentedControl+IndicatorView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // BetterSegmentedControl+IndicatorView.swift
3 | // BetterSegmentedControl
4 | //
5 | // Created by George Marmaridis on 19.10.20.
6 | //
7 |
8 | #if canImport(UIKit)
9 |
10 | import UIKit
11 |
12 | extension BetterSegmentedControl {
13 | open class IndicatorView: UIView {
14 | // MARK: Properties
15 | let segmentMaskView = UIView()
16 | var cornerRadius: CGFloat = 0.0 {
17 | didSet {
18 | layer.cornerRadius = cornerRadius
19 | segmentMaskView.layer.cornerRadius = cornerRadius
20 | }
21 | }
22 | override open var frame: CGRect {
23 | didSet {
24 | segmentMaskView.frame = frame
25 | }
26 | }
27 |
28 | // MARK: Initialization
29 | init() {
30 | super.init(frame: CGRect.zero)
31 | completeInit()
32 | }
33 | required public init?(coder aDecoder: NSCoder) {
34 | super.init(coder: aDecoder)
35 | completeInit()
36 | }
37 | private func completeInit() {
38 | segmentMaskView.backgroundColor = .black
39 | }
40 | }
41 | }
42 |
43 | #endif
44 |
--------------------------------------------------------------------------------
/Pod/Classes/BetterSegmentedControl+Options.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Options.swift
3 | // Pods
4 | //
5 | // Created by George Marmaridis on 15/05/2017.
6 | //
7 | //
8 |
9 | #if canImport(UIKit)
10 |
11 | import UIKit
12 |
13 | public extension BetterSegmentedControl {
14 | enum Option {
15 | /* Selected segment */
16 | case indicatorViewBackgroundColor(UIColor)
17 | case indicatorViewInset(CGFloat)
18 | case indicatorViewBorderWidth(CGFloat)
19 | case indicatorViewBorderColor(UIColor)
20 |
21 | /* Behavior */
22 | case alwaysAnnouncesValue(Bool)
23 | case announcesValueImmediately(Bool)
24 | case panningDisabled(Bool)
25 |
26 | /* Animation */
27 | case animationDuration(TimeInterval)
28 | case animationSpringDamping(CGFloat)
29 |
30 | /* Other */
31 | case backgroundColor(UIColor)
32 | case cornerRadius(CGFloat)
33 | }
34 | }
35 |
36 | #endif
37 |
--------------------------------------------------------------------------------
/Pod/Classes/BetterSegmentedControl+PredefinedStyles.swift:
--------------------------------------------------------------------------------
1 | //
2 | // BetterSegmentedControl+PredefinedStyles.swift
3 | // BetterSegmentedControl
4 | //
5 | // Created by George Marmaridis on 18.10.20.
6 | //
7 |
8 | #if canImport(UIKit)
9 |
10 | import UIKit
11 |
12 | public extension BetterSegmentedControl {
13 | class func appleStyled(frame: CGRect, titles: [String]) -> BetterSegmentedControl {
14 | let control = BetterSegmentedControl(
15 | frame: frame,
16 | segments: LabelSegment.segments(withTitles: titles),
17 | options: [.cornerRadius(8)])
18 | control.indicatorView.layer.shadowColor = UIColor.black.cgColor
19 | control.indicatorView.layer.shadowOpacity = 0.1
20 | control.indicatorView.layer.shadowOffset = CGSize(width: 1, height: 1)
21 | control.indicatorView.layer.shadowRadius = 2
22 |
23 | return control
24 | }
25 | }
26 |
27 | #endif
28 |
--------------------------------------------------------------------------------
/Pod/Classes/BetterSegmentedControl+UIPointerInteractionDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // BetterSegmentedControl+UIPointerInteractionDelegate.swift
3 | // BetterSegmentedControl
4 | //
5 | // Created by George Marmaridis on 19.10.20.
6 | //
7 |
8 | #if canImport(UIKit)
9 |
10 | import UIKit
11 |
12 | @available(iOS 13.4, *)
13 | extension BetterSegmentedControl: UIPointerInteractionDelegate {
14 | public func pointerInteraction(_ interaction: UIPointerInteraction,
15 | regionFor request: UIPointerRegionRequest,
16 | defaultRegion: UIPointerRegion) -> UIPointerRegion? {
17 | let closestIndexToRequestRegion = closestIndex(toPoint: request.location)
18 |
19 | let view = (closestIndexToRequestRegion == index) ? indicatorView : pointerInteractionViews[closestIndexToRequestRegion]
20 | pointerInteractionView = view
21 |
22 | return .init(rect: view.frame)
23 | }
24 |
25 | public func pointerInteraction(_ interaction: UIPointerInteraction,
26 | styleFor region: UIPointerRegion) -> UIPointerStyle? {
27 | guard let view = pointerInteractionView else {
28 | return nil
29 | }
30 |
31 | if view === indicatorView {
32 | return .init(effect: .lift(.init(view: view)))
33 | }
34 | return .init(effect: .highlight(.init(view: view)))
35 | }
36 | }
37 |
38 | #endif
39 |
--------------------------------------------------------------------------------
/Pod/Classes/BetterSegmentedControl.swift:
--------------------------------------------------------------------------------
1 | //
2 | // BetterSegmentedControl.swift
3 | //
4 | // Created by George Marmaridis on 01/04/16.
5 | // Copyright © 2020 George Marmaridis. All rights reserved.
6 | //
7 |
8 | #if canImport(UIKit)
9 |
10 | import UIKit
11 |
12 | @IBDesignable open class BetterSegmentedControl: UIControl {
13 | private struct Constants {
14 | static let minimumIntrinsicContentSizeHeight: CGFloat = 32.0
15 | static let minimumSegmentIntrinsicContentSizeWidth: CGFloat = 20.0
16 | }
17 |
18 | // MARK: Properties
19 |
20 | // Public
21 | /// Indicates a no-segment-selected state.
22 | public static let noSegment = -1
23 |
24 | /// The selected index. Use `setIndex()` for setting the index.
25 | public private(set) var index: Int
26 |
27 | /// The segments available for selection.
28 | public var segments: [BetterSegmentedControlSegment] {
29 | didSet {
30 | applySegments()
31 | }
32 | }
33 |
34 | /// The currently selected index indicator view.
35 | public let indicatorView = IndicatorView()
36 |
37 | /// Whether the the control should always send the .valueChanged event, regardless of the index remaining unchanged after interaction. Defaults to `false`.
38 | @IBInspectable public var alwaysAnnouncesValue: Bool = false
39 |
40 | /// Whether to send the .valueChanged event immediately or wait for animations to complete. Defaults to `true`.
41 | @IBInspectable public var announcesValueImmediately: Bool = true
42 |
43 | /// Whether the the control should ignore pan gestures. Defaults to `false`.
44 | @IBInspectable public var panningDisabled: Bool = false
45 |
46 | /// The control's and indicator's corner radii.
47 | @IBInspectable public var cornerRadius: CGFloat {
48 | get {
49 | layer.cornerRadius
50 | }
51 | set {
52 | layer.cornerRadius = newValue
53 | updateCornerRadii()
54 | }
55 | }
56 |
57 | /// The indicator view's background color.
58 | @IBInspectable public var indicatorViewBackgroundColor: UIColor? {
59 | get {
60 | indicatorView.backgroundColor
61 | }
62 | set {
63 | indicatorView.backgroundColor = newValue
64 | }
65 | }
66 |
67 | /// The indicator view's inset. Defaults to `2.0`.
68 | @IBInspectable public var indicatorViewInset: CGFloat = 2.0 {
69 | didSet {
70 | updateCornerRadii()
71 | }
72 | }
73 |
74 | /// The indicator view's border width.
75 | @IBInspectable public var indicatorViewBorderWidth: CGFloat {
76 | get {
77 | indicatorView.layer.borderWidth
78 | }
79 | set {
80 | indicatorView.layer.borderWidth = newValue
81 | }
82 | }
83 |
84 | /// The indicator view's border color.
85 | @IBInspectable public var indicatorViewBorderColor: UIColor? {
86 | get {
87 | guard let color = indicatorView.layer.borderColor else {
88 | return nil
89 | }
90 | return UIColor(cgColor: color)
91 | }
92 | set {
93 | indicatorView.layer.borderColor = newValue?.cgColor
94 | }
95 | }
96 |
97 | /// The duration of the animation of an index change. Defaults to `0.3`.
98 | @IBInspectable public var animationDuration: TimeInterval = 0.3
99 |
100 | /// The spring damping ratio of the animation of an index change. Defaults to `0.75`. Set to `1.0` for a no bounce effect.
101 | @IBInspectable public var animationSpringDamping: CGFloat = 0.75
102 |
103 | /// When the control auto-sizes itself, this controls the additional side padding between the segments.
104 | @IBInspectable public var segmentPadding: CGFloat = 14.0 {
105 | didSet {
106 | invalidateIntrinsicContentSize()
107 | }
108 | }
109 |
110 | open override var intrinsicContentSize: CGSize {
111 | let segmentIntrinsicContentSizes = segments.map {
112 | $0.intrinsicContentSize ?? .zero
113 | }
114 |
115 | let maxSegmentIntrinsicContentSizeWidth = segmentIntrinsicContentSizes.max(by: { (a, b) in
116 | return a.width < b.width
117 | })?.width ?? 0.0
118 |
119 | let maxSegmentIntrinsicContentSizeHeight = segmentIntrinsicContentSizes.max(by: { (a, b) in
120 | return a.height < b.height
121 | })?.height ?? 0.0
122 |
123 | let singleSegmentWidth = totalInsetSize + max(maxSegmentIntrinsicContentSizeWidth, Constants.minimumSegmentIntrinsicContentSizeWidth) + segmentPadding
124 |
125 | let width = ceil(CGFloat(segments.count) * singleSegmentWidth)
126 | let height = ceil(max(maxSegmentIntrinsicContentSizeHeight + totalInsetSize, Constants.minimumIntrinsicContentSizeHeight))
127 |
128 | return .init(width: width, height: height)
129 | }
130 |
131 | // Private
132 | private let normalSegmentViewsContainerView = UIView()
133 | private let selectedSegmentViewsContainerView = UIView()
134 | private let pointerInteractionViewsContainerView = UIView()
135 |
136 | private var initialIndicatorViewFrame: CGRect?
137 |
138 | private var tapGestureRecognizer: UITapGestureRecognizer!
139 | private var panGestureRecognizer: UIPanGestureRecognizer!
140 |
141 | private var normalSegmentViews: [UIView] = []
142 | private var normalSegmentViewCount: Int { normalSegmentViews.count }
143 |
144 | /// `selectedSegmentViews` provide accessibility traits.
145 | private var selectedSegmentViews: [UIView] = []
146 |
147 | var pointerInteractionViews: [UIView] = []
148 | /// Used for iPad Pointer Interaction support. Holds the reference to the view that should be highlighted, if any.
149 | weak var pointerInteractionView: UIView?
150 |
151 | /// Contains normal segment views, selected segment views and pointer interaction views.
152 | private var allSegmentViews: [UIView] { normalSegmentViews + selectedSegmentViews + pointerInteractionViews }
153 |
154 | private var safeIndex: Int {
155 | index >= 0 ? index : 0
156 | }
157 | private var lastIndex: Int { segments.endIndex - 1 }
158 |
159 | private var totalInsetSize: CGFloat { indicatorViewInset * 2.0 }
160 |
161 | private var isLayoutDirectionRightToLeft: Bool {
162 | let layoutDirection = UIView.userInterfaceLayoutDirection(for: semanticContentAttribute)
163 | return layoutDirection == .rightToLeft
164 | }
165 |
166 | private static var defaultOptions: [Option] = [.backgroundColor(.appleSegmentedControlDefaultControlBackground),
167 | .indicatorViewBackgroundColor(.appleSegmentedControlDefaultIndicatorBackground)]
168 |
169 | // MARK: Initialization
170 | /// Initializes a new `BetterSegmentedControl` with the parameters passed.
171 | ///
172 | /// - Parameters:
173 | /// - frame: The frame of the control.
174 | /// - segments: The segments to configure the control with.
175 | /// - index: The initially selected index. Passing `BetterSegmentedControl.noSegment` sets the index to `-1` and hides the
176 | /// indicator view. Passing an index beyond the segment indices will set the index to `0`.
177 | /// - options: An array of customization options to style and change the behavior of the control.
178 | public init(frame: CGRect,
179 | segments: [BetterSegmentedControlSegment],
180 | index: Int = 0,
181 | options: [Option]? = nil) {
182 | if segments.indices.contains(index) || index == Self.noSegment {
183 | self.index = index
184 | } else {
185 | self.index = 0
186 | }
187 |
188 | self.segments = segments
189 |
190 | super.init(frame: frame)
191 |
192 | completeInit()
193 |
194 | if index == -1 {
195 | setIndicatorViewVisible(false, animated: false, completion: nil)
196 | }
197 |
198 | setOptions(BetterSegmentedControl.defaultOptions)
199 | if let options = options {
200 | setOptions(options)
201 | }
202 | }
203 |
204 | required public init?(coder aDecoder: NSCoder) {
205 | self.index = 0
206 | self.segments = Self.generateDefaultSegments()
207 |
208 | super.init(coder: aDecoder)
209 |
210 | completeInit()
211 | }
212 |
213 | convenience override public init(frame: CGRect) {
214 | self.init(frame: frame, segments: Self.generateDefaultSegments())
215 | }
216 |
217 | convenience init() {
218 | self.init(frame: .zero, segments: Self.generateDefaultSegments())
219 | }
220 |
221 | private func completeInit() {
222 | layer.masksToBounds = true
223 |
224 | if #available(iOS 13.4, *) {
225 | let interaction = UIPointerInteraction(delegate: self)
226 | addInteraction(interaction)
227 | }
228 |
229 | // set up view hierarchy
230 | normalSegmentViewsContainerView.clipsToBounds = true
231 | addSubview(normalSegmentViewsContainerView)
232 |
233 | addSubview(indicatorView)
234 |
235 | selectedSegmentViewsContainerView.clipsToBounds = true
236 | addSubview(selectedSegmentViewsContainerView)
237 | selectedSegmentViewsContainerView.layer.mask = indicatorView.segmentMaskView.layer
238 |
239 | pointerInteractionViewsContainerView.clipsToBounds = true
240 | addSubview(pointerInteractionViewsContainerView)
241 |
242 | // configure gestures
243 | tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(tapped(_:)))
244 | addGestureRecognizer(tapGestureRecognizer)
245 |
246 | panGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(panned(_:)))
247 | panGestureRecognizer.delegate = self
248 | addGestureRecognizer(panGestureRecognizer)
249 |
250 | applySegments(shouldResetIndex: false)
251 | }
252 |
253 | // MARK: View lifecycle
254 | override open func layoutSubviews() {
255 | super.layoutSubviews()
256 | guard normalSegmentViewCount >= 1 else {
257 | return
258 | }
259 |
260 | normalSegmentViewsContainerView.frame = bounds
261 | selectedSegmentViewsContainerView.frame = bounds
262 | pointerInteractionViewsContainerView.frame = bounds
263 |
264 | indicatorView.frame = frameForElement(atIndex: safeIndex)
265 |
266 | for (index, _) in normalSegmentViews.enumerated() {
267 | let frame = frameForElement(atIndex: index)
268 | normalSegmentViews[index].frame = frame
269 | selectedSegmentViews[index].frame = frame
270 | pointerInteractionViews[index].frame = frame
271 | }
272 | }
273 |
274 | // MARK: Index Setting
275 | /// Sets the control's index.
276 | ///
277 | /// - Parameters:
278 | /// - index: The new index. Passing `BetterSegmentedControl.noSegment` sets the index to `-1` and hides the indicator view.
279 | /// Passing an index beyond the segment indices will have no effect.
280 | /// - animated: Whether the change should be animated or not. Defaults to `true`.
281 | /// - shouldSendValueChangedEvent: Whether the index change should trigger a `.valueChanged` event or not. Defaults to
282 | /// `false`. This takes precedence over `alwaysAnnouncesValue`.
283 | public func setIndex(_ index: Int, animated: Bool = true, shouldSendValueChangedEvent: Bool = false) {
284 | guard segments.indices.contains(index) || index == Self.noSegment else { return }
285 |
286 | let previousIndex = self.index
287 | self.index = index
288 |
289 | let shouldUpdateSegmentViewTraits = (index != previousIndex)
290 | let shouldUpdateSegmentViewTraitsBeforeAnimations = announcesValueImmediately && shouldUpdateSegmentViewTraits
291 | let shouldUpdateSegmentViewTraitsAfterAnimations = !announcesValueImmediately && shouldUpdateSegmentViewTraits
292 |
293 | let shouldSendEvent = (index != previousIndex || alwaysAnnouncesValue) && shouldSendValueChangedEvent
294 | let shouldSendEventBeforeAnimations = announcesValueImmediately && shouldSendEvent
295 | let shouldSendEventAfterAnimations = !announcesValueImmediately && shouldSendEvent
296 |
297 | if shouldSendEventBeforeAnimations {
298 | sendActions(for: .valueChanged)
299 | }
300 | if shouldUpdateSegmentViewTraitsBeforeAnimations {
301 | updateSegmentViewTraits()
302 | }
303 | performIndexChange(fromPreviousIndex: previousIndex, toNewIndex: index, animated: animated, completion: { [weak self] in
304 | guard let weakSelf = self else { return }
305 |
306 | if shouldSendEventAfterAnimations {
307 | weakSelf.sendActions(for: .valueChanged)
308 | }
309 | if shouldUpdateSegmentViewTraitsAfterAnimations {
310 | weakSelf.updateSegmentViewTraits()
311 | }
312 | })
313 | }
314 |
315 | // MARK: Option Setting
316 | /// A list of options to configure the control with.
317 | public func setOptions(_ options: [Option]) {
318 | for option in options {
319 | switch option {
320 | case let .indicatorViewBackgroundColor(value):
321 | indicatorViewBackgroundColor = value
322 | case let .indicatorViewInset(value):
323 | indicatorViewInset = value
324 | case let .indicatorViewBorderWidth(value):
325 | indicatorViewBorderWidth = value
326 | case let .indicatorViewBorderColor(value):
327 | indicatorViewBorderColor = value
328 | case let .alwaysAnnouncesValue(value):
329 | alwaysAnnouncesValue = value
330 | case let .announcesValueImmediately(value):
331 | announcesValueImmediately = value
332 | case let .panningDisabled(value):
333 | panningDisabled = value
334 | case let .backgroundColor(value):
335 | backgroundColor = value
336 | case let .cornerRadius(value):
337 | cornerRadius = value
338 | case let .animationDuration(value):
339 | animationDuration = value
340 | case let .animationSpringDamping(value):
341 | animationSpringDamping = value
342 | }
343 | }
344 | }
345 |
346 | // MARK: Animations
347 | /// Hides the indicator and selected segments view.
348 | private func setIndicatorViewVisible(_ isVisible: Bool, animated: Bool, completion: (() -> Void)?) {
349 | UIView.animate(withDuration: (animated ? 0.1 : 0.0),
350 | delay: 0.0,
351 | options: [.beginFromCurrentState, .curveEaseIn],
352 | animations: { () -> Void in
353 | self.selectedSegmentViewsContainerView.alpha = isVisible ? 1.0 : 0.0
354 | self.indicatorView.alpha = isVisible ? 1.0 : 0.0
355 | }, completion: { finished -> Void in
356 | completion?()
357 | })
358 | }
359 |
360 | private func performIndexChange(fromPreviousIndex previousIndex: Int,
361 | toNewIndex newIndex: Int,
362 | animated: Bool,
363 | completion: @escaping () -> Void) {
364 | func moveIndicatorViewToIndex(animated: Bool, completion: @escaping () -> Void) {
365 | guard index >= 0 else { return }
366 |
367 | UIView.animate(withDuration: animated ? animationDuration : 0.0,
368 | delay: 0.0,
369 | usingSpringWithDamping: animationSpringDamping,
370 | initialSpringVelocity: 0.0,
371 | options: [.beginFromCurrentState, .curveEaseOut],
372 | animations: { () -> Void in
373 | self.indicatorView.frame = self.normalSegmentViews[self.index].frame
374 | self.layoutIfNeeded()
375 | }, completion: { finished -> Void in
376 | completion()
377 | })
378 | }
379 |
380 | if index == Self.noSegment {
381 | setIndicatorViewVisible(false, animated: animated) {
382 | completion()
383 | }
384 | } else if previousIndex == Self.noSegment {
385 | moveIndicatorViewToIndex(animated: false, completion: { [weak self] in
386 | self?.setIndicatorViewVisible(true, animated: animated) {
387 | completion()
388 | }
389 | })
390 | } else {
391 | moveIndicatorViewToIndex(animated: animated, completion: {
392 | completion()
393 | })
394 | }
395 | }
396 |
397 | // MARK: Helpers
398 | /// Updates the segments and triggers a layout refresh. Resets the index if needed.
399 | private func applySegments(shouldResetIndex: Bool = true) {
400 | normalSegmentViews.forEach { $0.removeFromSuperview() }
401 | normalSegmentViews.removeAll()
402 |
403 | selectedSegmentViews.forEach { $0.removeFromSuperview() }
404 | selectedSegmentViews.removeAll()
405 |
406 | pointerInteractionViews.forEach { $0.removeFromSuperview() }
407 | pointerInteractionViews.removeAll()
408 |
409 | for segment in segments {
410 | segment.normalView.clipsToBounds = true
411 | segment.normalView.isAccessibilityElement = false
412 |
413 | segment.selectedView.clipsToBounds = true
414 |
415 | normalSegmentViewsContainerView.addSubview(segment.normalView)
416 | normalSegmentViews.append(segment.normalView)
417 |
418 | selectedSegmentViewsContainerView.addSubview(segment.selectedView)
419 | selectedSegmentViews.append(segment.selectedView)
420 |
421 | let pointerInteractionView = UIView()
422 | pointerInteractionViewsContainerView.addSubview(pointerInteractionView)
423 | pointerInteractionViews.append(pointerInteractionView)
424 | }
425 |
426 | updateSegmentViewTraits()
427 | updateCornerRadii()
428 | if shouldResetIndex {
429 | resetIndex()
430 | }
431 |
432 | invalidateIntrinsicContentSize()
433 | setNeedsLayout()
434 | }
435 |
436 | private func updateCornerRadii() {
437 | indicatorView.cornerRadius = cornerRadius - indicatorViewInset
438 | allSegmentViews.forEach { $0.layer.cornerRadius = indicatorView.cornerRadius }
439 | }
440 |
441 | private func updateSegmentViewTraits() {
442 | accessibilityElements = selectedSegmentViews
443 |
444 | for (index, _) in selectedSegmentViews.enumerated() {
445 | selectedSegmentViews[index].accessibilityTraits = (index == self.index ? [.button, .selected] : [.button])
446 | }
447 | }
448 |
449 | private func frameForElement(atIndex index: Int) -> CGRect {
450 | let elementWidth = (width - totalInsetSize) / CGFloat(normalSegmentViewCount)
451 | let x = CGFloat(isLayoutDirectionRightToLeft ? lastIndex - index : index) * elementWidth
452 |
453 | return CGRect(x: x + indicatorViewInset,
454 | y: indicatorViewInset,
455 | width: elementWidth,
456 | height: height - totalInsetSize)
457 | }
458 |
459 | private func resetIndex() {
460 | let newIndex = (segments.count > 0 ? 0 : -1)
461 | setIndex(newIndex, animated: false, shouldSendValueChangedEvent: false)
462 | }
463 |
464 | func closestIndex(toPoint point: CGPoint) -> Int {
465 | let distances = normalSegmentViews.map { abs(point.x - $0.center.x) }
466 | return Int(distances.firstIndex(of: distances.min()!)!)
467 | }
468 |
469 | private static func generateDefaultSegments() -> [LabelSegment] {
470 | [.init(text: "First"), .init(text: "Second"), .init(text: "Third")]
471 | }
472 |
473 | // MARK: Action handlers
474 | @objc private func tapped(_ gestureRecognizer: UITapGestureRecognizer!) {
475 | let location = gestureRecognizer.location(in: self)
476 | setIndex(closestIndex(toPoint: location), shouldSendValueChangedEvent: true)
477 | }
478 |
479 | @objc private func panned(_ gestureRecognizer: UIPanGestureRecognizer!) {
480 | switch gestureRecognizer.state {
481 | case .began:
482 | initialIndicatorViewFrame = indicatorView.frame
483 | case .changed:
484 | var frame = initialIndicatorViewFrame!
485 | frame.origin.x += gestureRecognizer.translation(in: self).x
486 | frame.origin.x = max(min(frame.origin.x, bounds.width - indicatorViewInset - frame.width), indicatorViewInset)
487 | indicatorView.frame = frame
488 | case .ended, .failed, .cancelled:
489 | setIndex(closestIndex(toPoint: indicatorView.center), shouldSendValueChangedEvent: true)
490 | default: break
491 | }
492 | }
493 | }
494 |
495 | // MARK: - UIGestureRecognizerDelegate
496 | extension BetterSegmentedControl: UIGestureRecognizerDelegate {
497 | override open func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
498 | if gestureRecognizer == panGestureRecognizer {
499 | return indicatorView.frame.contains(gestureRecognizer.location(in: self)) && !panningDisabled
500 | }
501 | return super.gestureRecognizerShouldBegin(gestureRecognizer)
502 | }
503 | }
504 |
505 | #endif
506 |
--------------------------------------------------------------------------------
/Pod/Classes/Helpers/UIColor+Helpers.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UIColor+Helpers.swift
3 | // BetterSegmentedControl
4 | //
5 | // Created by George Marmaridis on 16.10.20.
6 | //
7 |
8 | #if canImport(UIKit)
9 |
10 | import UIKit
11 |
12 | extension UIColor {
13 | class var appleSegmentedControlDefaultControlBackground: UIColor {
14 | .init(red: 238.0/255.0, green: 238.0/255.0, blue: 238.0/255.0, alpha: 1.0)
15 | }
16 | class var appleSegmentedControlDefaultIndicatorBackground: UIColor {
17 | .white
18 | }
19 | class var appleSegmentedControlDefaultSegmentText: UIColor {
20 | .black
21 | }
22 | }
23 |
24 | #endif
25 |
--------------------------------------------------------------------------------
/Pod/Classes/Helpers/UIView+Helpers.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UIView+Helpers.swift
3 | // BetterSegmentedControl
4 | //
5 | // Created by George Marmaridis on 19.10.20.
6 | //
7 |
8 | #if canImport(UIKit)
9 |
10 | import UIKit
11 |
12 | extension UIView {
13 | var width: CGFloat { bounds.width }
14 | var height: CGFloat { bounds.height }
15 | }
16 |
17 | #endif
18 |
--------------------------------------------------------------------------------
/Pod/Classes/Segments/BetterSegmentedControlSegment.swift:
--------------------------------------------------------------------------------
1 | //
2 | // BetterSegmentedControlSegment.swift
3 | // BetterSegmentedControl
4 | //
5 | // Created by George Marmaridis on 08/10/2017.
6 | //
7 |
8 | #if canImport(UIKit)
9 |
10 | import UIKit
11 |
12 | /// A segment is comprised of a normal state view and a selected state view. These need to be separate view instances.
13 | public protocol BetterSegmentedControlSegment {
14 | /// If provided, `BetterSegmentedControl` will use its value to calculate an `intrinsicContentSize` based on this.
15 | var intrinsicContentSize: CGSize? { get }
16 |
17 | /// The view to be shown for the normal or unselected state.
18 | var normalView: UIView { get }
19 |
20 | /// The view to be shown for the active or selected state.
21 | var selectedView: UIView { get }
22 | }
23 |
24 | #endif
25 |
--------------------------------------------------------------------------------
/Pod/Classes/Segments/IconSegment.swift:
--------------------------------------------------------------------------------
1 | //
2 | // IconSegment.swift
3 | // BetterSegmentedControl
4 | //
5 | // Created by George Marmaridis on 10/02/2018.
6 | //
7 |
8 | #if canImport(UIKit)
9 |
10 | import UIKit
11 |
12 | open class IconSegment: BetterSegmentedControlSegment {
13 | // MARK: Constants
14 | private struct DefaultValues {
15 | static let normalBackgroundColor: UIColor = .clear
16 | static let selectedBackgroundColor: UIColor = .clear
17 | }
18 |
19 | // MARK: Properties
20 | public var icon: UIImage
21 | public var iconSize: CGSize
22 |
23 | public var normalIconTintColor: UIColor
24 | public var normalBackgroundColor: UIColor
25 |
26 | public var selectedIconTintColor: UIColor
27 | public var selectedBackgroundColor: UIColor
28 |
29 | // MARK: Lifecycle
30 | public init(icon: UIImage,
31 | iconSize: CGSize,
32 | normalBackgroundColor: UIColor? = nil,
33 | normalIconTintColor: UIColor,
34 | selectedBackgroundColor: UIColor? = nil,
35 | selectedIconTintColor: UIColor) {
36 | self.icon = icon.withRenderingMode(.alwaysTemplate)
37 | self.iconSize = iconSize
38 | self.normalBackgroundColor = normalBackgroundColor ?? DefaultValues.normalBackgroundColor
39 | self.normalIconTintColor = normalIconTintColor
40 | self.selectedBackgroundColor = selectedBackgroundColor ?? DefaultValues.selectedBackgroundColor
41 | self.selectedIconTintColor = selectedIconTintColor
42 | }
43 |
44 | // MARK: BetterSegmentedControlSegment
45 | public var intrinsicContentSize: CGSize? { nil }
46 |
47 | public lazy var normalView: UIView = {
48 | return createView(withIcon: icon,
49 | iconSize: iconSize,
50 | backgroundColor: normalBackgroundColor,
51 | iconTintColor: normalIconTintColor)
52 | }()
53 | public lazy var selectedView: UIView = {
54 | return createView(withIcon: icon,
55 | iconSize: iconSize,
56 | backgroundColor: selectedBackgroundColor,
57 | iconTintColor: selectedIconTintColor)
58 | }()
59 | private func createView(withIcon icon: UIImage,
60 | iconSize: CGSize,
61 | backgroundColor: UIColor,
62 | iconTintColor: UIColor) -> UIView {
63 | let view = UIView()
64 | view.backgroundColor = backgroundColor
65 | let imageView = UIImageView(image: icon)
66 | imageView.frame = CGRect(x: 0,
67 | y: 0,
68 | width: iconSize.width,
69 | height: iconSize.height)
70 | imageView.contentMode = .scaleAspectFit
71 | imageView.tintColor = iconTintColor
72 | imageView.autoresizingMask = [.flexibleTopMargin,
73 | .flexibleLeftMargin,
74 | .flexibleRightMargin,
75 | .flexibleBottomMargin]
76 | view.addSubview(imageView)
77 | return view
78 | }
79 | }
80 |
81 | public extension IconSegment {
82 | class func segments(withIcons icons: [UIImage],
83 | iconSize: CGSize,
84 | normalBackgroundColor: UIColor? = nil,
85 | normalIconTintColor: UIColor,
86 | selectedBackgroundColor: UIColor? = nil,
87 | selectedIconTintColor: UIColor) -> [BetterSegmentedControlSegment] {
88 | return icons.map {
89 | IconSegment(icon: $0,
90 | iconSize: iconSize,
91 | normalBackgroundColor: normalBackgroundColor,
92 | normalIconTintColor: normalIconTintColor,
93 | selectedBackgroundColor: selectedBackgroundColor,
94 | selectedIconTintColor: selectedIconTintColor)
95 | }
96 | }
97 | }
98 |
99 | #endif
100 |
--------------------------------------------------------------------------------
/Pod/Classes/Segments/LabelSegment.swift:
--------------------------------------------------------------------------------
1 | //
2 | // LabelSegment.swift
3 | // BetterSegmentedControl
4 | //
5 | // Created by George Marmaridis on 08/10/2017.
6 | //
7 |
8 | #if canImport(UIKit)
9 |
10 | import UIKit
11 |
12 | open class LabelSegment: BetterSegmentedControlSegment {
13 | // MARK: Constants
14 | private struct DefaultValues {
15 | static let normalBackgroundColor: UIColor = .clear
16 | static let normalTextColor: UIColor = .black
17 | static let normalFont: UIFont = .systemFont(ofSize: 13)
18 | static let selectedBackgroundColor: UIColor = .clear
19 | static let selectedTextColor: UIColor = .black
20 | static let selectedFont: UIFont = .systemFont(ofSize: 13, weight: .medium)
21 | }
22 |
23 | // MARK: Properties
24 | public let text: String?
25 |
26 | public let normalFont: UIFont
27 | public let normalTextColor: UIColor
28 | public let normalBackgroundColor: UIColor
29 |
30 | public let selectedFont: UIFont
31 | public let selectedTextColor: UIColor
32 | public let selectedBackgroundColor: UIColor
33 |
34 | private let numberOfLines: Int
35 | private let accessibilityIdentifier: String?
36 |
37 | // MARK: Lifecycle
38 | public init(text: String? = nil,
39 | numberOfLines: Int = 1,
40 | normalBackgroundColor: UIColor? = nil,
41 | normalFont: UIFont? = nil,
42 | normalTextColor: UIColor? = nil,
43 | selectedBackgroundColor: UIColor? = nil,
44 | selectedFont: UIFont? = nil,
45 | selectedTextColor: UIColor? = nil,
46 | accessibilityIdentifier: String? = nil) {
47 | self.text = text
48 | self.numberOfLines = numberOfLines
49 | self.normalBackgroundColor = normalBackgroundColor ?? DefaultValues.normalBackgroundColor
50 | self.normalFont = normalFont ?? DefaultValues.normalFont
51 | self.normalTextColor = normalTextColor ?? DefaultValues.normalTextColor
52 | self.selectedBackgroundColor = selectedBackgroundColor ?? DefaultValues.selectedBackgroundColor
53 | self.selectedFont = selectedFont ?? DefaultValues.selectedFont
54 | self.selectedTextColor = selectedTextColor ?? DefaultValues.selectedTextColor
55 | self.accessibilityIdentifier = accessibilityIdentifier
56 | }
57 |
58 | // MARK: BetterSegmentedControlSegment
59 | public var intrinsicContentSize: CGSize? {
60 | selectedView.intrinsicContentSize
61 | }
62 |
63 | public lazy var normalView: UIView = {
64 | createLabel(withText: text,
65 | backgroundColor: normalBackgroundColor,
66 | font: normalFont,
67 | textColor: normalTextColor,
68 | accessibilityIdentifier: accessibilityIdentifier)
69 | }()
70 | public lazy var selectedView: UIView = {
71 | createLabel(withText: text,
72 | backgroundColor: selectedBackgroundColor,
73 | font: selectedFont,
74 | textColor: selectedTextColor,
75 | accessibilityIdentifier: accessibilityIdentifier)
76 | }()
77 | open func createLabel(withText text: String?,
78 | backgroundColor: UIColor,
79 | font: UIFont,
80 | textColor: UIColor,
81 | accessibilityIdentifier: String?) -> UILabel {
82 | let label = UILabel()
83 | label.text = text
84 | label.numberOfLines = numberOfLines
85 | label.backgroundColor = backgroundColor
86 | label.font = font
87 | label.textColor = textColor
88 | label.lineBreakMode = .byTruncatingTail
89 | label.textAlignment = .center
90 | label.accessibilityIdentifier = accessibilityIdentifier
91 | return label
92 | }
93 | }
94 |
95 | public extension LabelSegment {
96 | class func segments(withTitles titles: [String],
97 | numberOfLines: Int = 1,
98 | normalBackgroundColor: UIColor? = nil,
99 | normalFont: UIFont? = nil,
100 | normalTextColor: UIColor? = nil,
101 | selectedBackgroundColor: UIColor? = nil,
102 | selectedFont: UIFont? = nil,
103 | selectedTextColor: UIColor? = nil) -> [BetterSegmentedControlSegment] {
104 | titles.map {
105 | LabelSegment(text: $0,
106 | numberOfLines: numberOfLines,
107 | normalBackgroundColor: normalBackgroundColor,
108 | normalFont: normalFont,
109 | normalTextColor: normalTextColor,
110 | selectedBackgroundColor: selectedBackgroundColor,
111 | selectedFont: selectedFont,
112 | selectedTextColor: selectedTextColor)
113 | }
114 | }
115 | }
116 |
117 | #endif
118 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # BetterSegmentedControl
2 |
3 | 
4 | 
5 | [](http://cocoapods.org/pods/BetterSegmentedControl)
6 | [](http://cocoapods.org/pods/BetterSegmentedControl)
7 | [](http://cocoapods.org/pods/BetterSegmentedControl)
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | `BetterSegmentedControl` is an easy to use, customizable replacement for
17 | `UISegmentedControl` and `UISwitch` written in Swift.
18 |
19 | ## Features
20 |
21 | - [x] Can be used as a segmented control or switch
22 | - [x] Plethora of customizable options from colors to insets, radii and
23 | animations
24 | - [x] Use text or icons as segments, or add your own custom segments
25 | - [x] Designable straight in Interface Builder
26 | - [x] Accessibility support
27 | - [x] iPad cursor support
28 | - [x] Customizable behavior
29 | - [x] Right-to-left languages support
30 | - [x] Fully tested
31 |
32 | Check the latest release notes [here][release-notes]!
33 |
34 | [release-notes]: https://github.com/gmarm/BetterSegmentedControl/releases/tag/2.0.1
35 |
36 | ## Examples
37 |
38 | #### iOS
39 | 
40 |
41 | #### iPad cursor
42 |
43 | 
44 |
45 |
46 | ## Requirements
47 |
48 | - iOS 9.0+
49 | - Xcode 8+
50 |
51 |
52 | ## Installation
53 |
54 | ### Swift Package Manager
55 |
56 | BetterSegmentedControl is available through Swift Package Manager. To install
57 | it, simply go to Xcode under `File > Swift Packages > Add Package Dependency...`
58 |
59 | ### CocoaPods
60 |
61 | BetterSegmentedControl is available through [CocoaPods](http://cocoapods.org).
62 | To install it, simply add the following line to your Podfile:
63 |
64 | ```ruby
65 | # Swift 5.1
66 | pod 'BetterSegmentedControl', '~> 2.0'
67 |
68 | # Swift 4
69 | pod 'BetterSegmentedControl', '1.0'
70 |
71 | # Swift 3 / Objective-C
72 | pod 'BetterSegmentedControl', '0.8'
73 | ```
74 |
75 | ### Manually
76 |
77 | If you prefer not to use CocoaPods or Swift Package Manager, you can integrate
78 | BetterSegmentedControl into your project manually.
79 |
80 |
81 | ## Usage
82 |
83 | ```swift
84 | let control = BetterSegmentedControl(frame: CGRect(x: 16.0,
85 | y: 0,
86 | width: view.bounds.width - 32.0,
87 | height: 44.0))
88 | view.addSubview(control)
89 | ```
90 |
91 | You can find several ways of using it, such as by designing it in a Storyboard
92 | file or creating it in code in the example project.
93 |
94 | To run the example project, clone the repo, and run `pod install` from the
95 | Example directory first.
96 |
97 |
98 | ## Contribution
99 |
100 | Feel free to submit Pull Requests or send me your feedback and suggestions!
101 |
102 | Logo by [Guillaume Galante][guillaume-dribble].
103 |
104 | [guillaume-dribble]: https://dribbble.com/guillaumegalante
105 |
106 | ## Author
107 |
108 | George Marmaridis
109 |
110 | - https://github.com/gmarm
111 | - https://twitter.com/gmarmas
112 | - https://www.linkedin.com/in/gmarm
113 | - gmarmas@gmail.com
114 |
115 |
116 | ## License
117 |
118 | BetterSegmentedControl is available under the MIT license. See the LICENSE file
119 | for more info.
120 |
--------------------------------------------------------------------------------
/_Pods.xcodeproj:
--------------------------------------------------------------------------------
1 | Example/Pods/Pods.xcodeproj
--------------------------------------------------------------------------------