├── Screenshot.png ├── HMSegmentedControlExample ├── Images │ ├── 1.png │ ├── 2.png │ ├── 3.png │ ├── 4.png │ ├── 1@2x.png │ ├── 2@2x.png │ ├── 3@2x.png │ ├── 4@2x.png │ ├── 1-selected.png │ ├── 2-selected.png │ ├── 3-selected.png │ ├── 4-selected.png │ ├── 1-selected@2x.png │ ├── 2-selected@2x.png │ ├── 3-selected@2x.png │ └── 4-selected@2x.png ├── ViewController.h ├── HMSegmentedControlExample-Prefix.pch ├── main.m ├── AppDelegate.h ├── AppDelegate.m ├── Launch Screen.xib ├── HMSegmentedControlExample-Info.plist └── ViewController.m ├── Framework ├── module.modulemap ├── HMSegmentedControl-umbrella.h └── Info.plist ├── HMSegmentedControl.xcodeproj ├── project.xcworkspace │ └── contents.xcworkspacedata ├── xcshareddata │ └── xcschemes │ │ └── HMSegmentedControl.xcscheme └── project.pbxproj ├── .gitignore ├── HMSegmentedControl.podspec ├── LICENSE.md ├── README.md └── HMSegmentedControl ├── HMSegmentedControl.h └── HMSegmentedControl.m /Screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ml-archive/HMSegmentedControl/master/Screenshot.png -------------------------------------------------------------------------------- /HMSegmentedControlExample/Images/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ml-archive/HMSegmentedControl/master/HMSegmentedControlExample/Images/1.png -------------------------------------------------------------------------------- /HMSegmentedControlExample/Images/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ml-archive/HMSegmentedControl/master/HMSegmentedControlExample/Images/2.png -------------------------------------------------------------------------------- /HMSegmentedControlExample/Images/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ml-archive/HMSegmentedControl/master/HMSegmentedControlExample/Images/3.png -------------------------------------------------------------------------------- /HMSegmentedControlExample/Images/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ml-archive/HMSegmentedControl/master/HMSegmentedControlExample/Images/4.png -------------------------------------------------------------------------------- /HMSegmentedControlExample/Images/1@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ml-archive/HMSegmentedControl/master/HMSegmentedControlExample/Images/1@2x.png -------------------------------------------------------------------------------- /HMSegmentedControlExample/Images/2@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ml-archive/HMSegmentedControl/master/HMSegmentedControlExample/Images/2@2x.png -------------------------------------------------------------------------------- /HMSegmentedControlExample/Images/3@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ml-archive/HMSegmentedControl/master/HMSegmentedControlExample/Images/3@2x.png -------------------------------------------------------------------------------- /HMSegmentedControlExample/Images/4@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ml-archive/HMSegmentedControl/master/HMSegmentedControlExample/Images/4@2x.png -------------------------------------------------------------------------------- /HMSegmentedControlExample/Images/1-selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ml-archive/HMSegmentedControl/master/HMSegmentedControlExample/Images/1-selected.png -------------------------------------------------------------------------------- /HMSegmentedControlExample/Images/2-selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ml-archive/HMSegmentedControl/master/HMSegmentedControlExample/Images/2-selected.png -------------------------------------------------------------------------------- /HMSegmentedControlExample/Images/3-selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ml-archive/HMSegmentedControl/master/HMSegmentedControlExample/Images/3-selected.png -------------------------------------------------------------------------------- /HMSegmentedControlExample/Images/4-selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ml-archive/HMSegmentedControl/master/HMSegmentedControlExample/Images/4-selected.png -------------------------------------------------------------------------------- /HMSegmentedControlExample/Images/1-selected@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ml-archive/HMSegmentedControl/master/HMSegmentedControlExample/Images/1-selected@2x.png -------------------------------------------------------------------------------- /HMSegmentedControlExample/Images/2-selected@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ml-archive/HMSegmentedControl/master/HMSegmentedControlExample/Images/2-selected@2x.png -------------------------------------------------------------------------------- /HMSegmentedControlExample/Images/3-selected@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ml-archive/HMSegmentedControl/master/HMSegmentedControlExample/Images/3-selected@2x.png -------------------------------------------------------------------------------- /HMSegmentedControlExample/Images/4-selected@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ml-archive/HMSegmentedControl/master/HMSegmentedControlExample/Images/4-selected@2x.png -------------------------------------------------------------------------------- /Framework/module.modulemap: -------------------------------------------------------------------------------- 1 | framework module HMSegmentedControl { 2 | umbrella header "HMSegmentedControl-umbrella.h" 3 | export * 4 | module * { export * } 5 | } 6 | -------------------------------------------------------------------------------- /HMSegmentedControl.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | .DS_Store 3 | */build/* 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | xcuserdata 13 | profile 14 | *.moved-aside 15 | DerivedData 16 | .idea/ 17 | *.hmap -------------------------------------------------------------------------------- /HMSegmentedControlExample/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // HMSegmentedControlExample 4 | // 5 | // Created by Hesham Abd-Elmegid on 25/12/12. 6 | // Copyright (c) 2012 Hesham Abd-Elmegid. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /HMSegmentedControlExample/HMSegmentedControlExample-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'HMSegmentedControlExample' target in the 'HMSegmentedControlExample' project 3 | // 4 | 5 | #import 6 | 7 | #ifndef __IPHONE_4_0 8 | #warning "This project uses features only available in iOS SDK 4.0 and later." 9 | #endif 10 | 11 | #ifdef __OBJC__ 12 | #import 13 | #import 14 | #endif 15 | -------------------------------------------------------------------------------- /HMSegmentedControlExample/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // HMSegmentedControlExample 4 | // 5 | // Created by Hesham Abd-Elmegid on 25/12/12. 6 | // Copyright (c) 2012 Hesham Abd-Elmegid. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "AppDelegate.h" 12 | 13 | int main(int argc, char *argv[]) 14 | { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /HMSegmentedControlExample/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // HMSegmentedControlExample 4 | // 5 | // Created by Hesham Abd-Elmegid on 25/12/12. 6 | // Copyright (c) 2012 Hesham Abd-Elmegid. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class ViewController; 12 | 13 | @interface AppDelegate : UIResponder 14 | 15 | @property (strong, nonatomic) UIWindow *window; 16 | 17 | @property (strong, nonatomic) ViewController *viewController; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /Framework/HMSegmentedControl-umbrella.h: -------------------------------------------------------------------------------- 1 | // 2 | // HMSegmentedControl.h 3 | // HMSegmentedControl 4 | // 5 | // Created by Maxime Epain on 05/10/2016. 6 | // Copyright © 2012-2015 Hesham Abd-Elmegid. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for HMSegmentedControl. 12 | FOUNDATION_EXPORT double HMSegmentedControlVersionNumber; 13 | 14 | //! Project version string for HMSegmentedControl. 15 | FOUNDATION_EXPORT const unsigned char HMSegmentedControlVersionString[]; 16 | 17 | #import 18 | 19 | 20 | -------------------------------------------------------------------------------- /HMSegmentedControl.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = "HMSegmentedControl" 3 | s.version = "1.5.4" 4 | s.summary = "A drop-in replacement for UISegmentedControl mimicking the style of the one in Google Currents and various other Google products." 5 | s.homepage = "https://github.com/HeshamMegid/HMSegmentedControl" 6 | s.license = { :type => 'MIT', :file => 'LICENSE.md' } 7 | s.author = { "Hesham Abd-Elmegid" => "hesham.abdelmegid@gmail.com" } 8 | s.source = { :git => "https://github.com/fuzz-productions/HMSegmentedControl.git", :tag => "v1.5.4" } 9 | s.platform = :ios, '7.0' 10 | s.requires_arc = true 11 | s.source_files = 'HMSegmentedControl/*.{h,m}' 12 | s.framework = 'QuartzCore' 13 | end 14 | -------------------------------------------------------------------------------- /Framework/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.5.3 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | NSPrincipalClass 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /HMSegmentedControlExample/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // HMSegmentedControlExample 4 | // 5 | // Created by Hesham Abd-Elmegid on 25/12/12. 6 | // Copyright (c) 2012 Hesham Abd-Elmegid. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | #import "ViewController.h" 12 | 13 | @implementation AppDelegate 14 | 15 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 16 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 17 | self.viewController = [[ViewController alloc] init]; 18 | UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:self.viewController]; 19 | self.window.rootViewController = navigationController; 20 | [self.window makeKeyAndVisible]; 21 | return YES; 22 | } 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # License 2 | 3 | ## MIT License 4 | 5 | Copyright (c) 2012 Hesham Abd-Elmegid (http://www.hesh.am) 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in 15 | all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | THE SOFTWARE. -------------------------------------------------------------------------------- /HMSegmentedControlExample/Launch Screen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /HMSegmentedControlExample/HMSegmentedControlExample-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIcons 12 | 13 | CFBundleIcons~ipad 14 | 15 | CFBundleIdentifier 16 | $(PRODUCT_BUNDLE_IDENTIFIER) 17 | CFBundleInfoDictionaryVersion 18 | 6.0 19 | CFBundleName 20 | ${PRODUCT_NAME} 21 | CFBundlePackageType 22 | APPL 23 | CFBundleShortVersionString 24 | 1.0 25 | CFBundleSignature 26 | ???? 27 | CFBundleVersion 28 | 1.0 29 | LSRequiresIPhoneOS 30 | 31 | UILaunchStoryboardName 32 | Launch Screen 33 | UIRequiredDeviceCapabilities 34 | 35 | armv7 36 | 37 | UISupportedInterfaceOrientations 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationLandscapeLeft 41 | UIInterfaceOrientationLandscapeRight 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | HMSegmentedControl 2 | === 3 | 4 | [![Pod Version](http://img.shields.io/cocoapods/v/HMSegmentedControl.svg?style=flat)](http://cocoadocs.org/docsets/HMSegmentedControl) 5 | [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) 6 | [![Pod Platform](http://img.shields.io/cocoapods/p/HMSegmentedControl.svg?style=flat)](http://cocoadocs.org/docsets/HMSegmentedControl) 7 | [![Pod License](http://img.shields.io/cocoapods/l/HMSegmentedControl.svg?style=flat)](http://opensource.org/licenses/MIT) 8 | 9 | A drop-in replacement for UISegmentedControl mimicking the style of the segmented control used in Google Currents and various other Google products. 10 | 11 | # Features 12 | - Supports both text and images 13 | - Support horizontal scrolling 14 | - Supports advanced title styling with text attributes for font, color, kerning, shadow, etc. 15 | - Supports selection indicator both on top and bottom 16 | - Supports blocks 17 | - Works with ARC and iOS >= 7 18 | 19 | # Installation 20 | 21 | ### CocoaPods 22 | The easiest way of installing HMSegmentedControl is via [CocoaPods](http://cocoapods.org/). 23 | 24 | ``` 25 | pod 'HMSegmentedControl' 26 | ``` 27 | 28 | ### Old-fashioned way 29 | 30 | - Add `HMSegmentedControl.h` and `HMSegmentedControl.m` to your project. 31 | - Add `QuartzCore.framework` to your linked frameworks. 32 | - `#import "HMSegmentedControl.h"` where you want to add the control. 33 | 34 | # Usage 35 | 36 | The code below will create a segmented control with the default looks: 37 | 38 | ``` objective-c 39 | HMSegmentedControl *segmentedControl = [[HMSegmentedControl alloc] initWithSectionTitles:@[@"One", @"Two", @"Three"]]; 40 | segmentedControl.frame = CGRectMake(10, 10, 300, 60); 41 | [segmentedControl addTarget:self action:@selector(segmentedControlChangedValue:) forControlEvents:UIControlEventValueChanged]; 42 | [self.view addSubview:segmentedControl]; 43 | ``` 44 | 45 | Included is a demo project showing how to fully customise the control. 46 | 47 | ![HMSegmentedControl](https://raw.githubusercontent.com/HeshamMegid/HMSegmentedControl/master/Screenshot.png) 48 | 49 | # Apps using HMSegmentedControl 50 | 51 | If you are using HMSegmentedControl in your app or know of an app that uses it, please add it to [this list](https://github.com/HeshamMegid/HMSegmentedControl/wiki/Apps-using-HMSegmentedControl). 52 | 53 | 54 | # License 55 | 56 | HMSegmentedControl is licensed under the terms of the MIT License. Please see the [LICENSE](LICENSE.md) file for full details. 57 | 58 | If this code was helpful, I would love to hear from you. 59 | 60 | [@HeshamMegid](http://twitter.com/HeshamMegid) 61 | [http://hesh.am](http://hesh.am) 62 | -------------------------------------------------------------------------------- /HMSegmentedControl.xcodeproj/xcshareddata/xcschemes/HMSegmentedControl.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 34 | 35 | 45 | 46 | 52 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 70 | 71 | 72 | 73 | 75 | 76 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /HMSegmentedControl/HMSegmentedControl.h: -------------------------------------------------------------------------------- 1 | // 2 | // HMSegmentedControl.h 3 | // HMSegmentedControl 4 | // 5 | // Created by Hesham Abd-Elmegid on 23/12/12. 6 | // Copyright (c) 2012-2015 Hesham Abd-Elmegid. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class HMSegmentedControl; 12 | 13 | typedef void (^IndexChangeBlock)(NSInteger index); 14 | typedef NSAttributedString *(^HMTitleFormatterBlock)(HMSegmentedControl *segmentedControl, NSString *title, NSUInteger index, BOOL selected); 15 | 16 | typedef NS_ENUM(NSInteger, HMSegmentedControlSelectionStyle) { 17 | HMSegmentedControlSelectionStyleTextWidthStripe, // Indicator width will only be as big as the text width 18 | HMSegmentedControlSelectionStyleFullWidthStripe, // Indicator width will fill the whole segment 19 | HMSegmentedControlSelectionStyleBox, // A rectangle that covers the whole segment 20 | HMSegmentedControlSelectionStyleArrow // An arrow in the middle of the segment pointing up or down depending on `HMSegmentedControlSelectionIndicatorLocation` 21 | }; 22 | 23 | typedef NS_ENUM(NSInteger, HMSegmentedControlSelectionIndicatorLocation) { 24 | HMSegmentedControlSelectionIndicatorLocationUp, 25 | HMSegmentedControlSelectionIndicatorLocationDown, 26 | HMSegmentedControlSelectionIndicatorLocationNone // No selection indicator 27 | }; 28 | 29 | typedef NS_ENUM(NSInteger, HMSegmentedControlSegmentWidthStyle) { 30 | HMSegmentedControlSegmentWidthStyleFixed, // Segment width is fixed 31 | HMSegmentedControlSegmentWidthStyleDynamic, // Segment width will only be as big as the text width (including inset) 32 | }; 33 | 34 | typedef NS_OPTIONS(NSInteger, HMSegmentedControlBorderType) { 35 | HMSegmentedControlBorderTypeNone = 0, 36 | HMSegmentedControlBorderTypeTop = (1 << 0), 37 | HMSegmentedControlBorderTypeLeft = (1 << 1), 38 | HMSegmentedControlBorderTypeBottom = (1 << 2), 39 | HMSegmentedControlBorderTypeRight = (1 << 3) 40 | }; 41 | 42 | enum { 43 | HMSegmentedControlNoSegment = -1 // Segment index for no selected segment 44 | }; 45 | 46 | typedef NS_ENUM(NSInteger, HMSegmentedControlType) { 47 | HMSegmentedControlTypeText, 48 | HMSegmentedControlTypeImages, 49 | HMSegmentedControlTypeTextImages 50 | }; 51 | 52 | @interface HMSegmentedControl : UIControl 53 | 54 | @property (nonatomic, strong) NSArray *sectionTitles; 55 | @property (nonatomic, strong) NSArray *sectionImages; 56 | @property (nonatomic, strong) NSArray *sectionSelectedImages; 57 | 58 | /** 59 | Provide a block to be executed when selected index is changed. 60 | 61 | Alternativly, you could use `addTarget:action:forControlEvents:` 62 | */ 63 | @property (nonatomic, copy) IndexChangeBlock indexChangeBlock; 64 | 65 | /** 66 | Used to apply custom text styling to titles when set. 67 | 68 | When this block is set, no additional styling is applied to the `NSAttributedString` object returned from this block. 69 | */ 70 | @property (nonatomic, copy) HMTitleFormatterBlock titleFormatter; 71 | 72 | /** 73 | Text attributes to apply to item title text. 74 | */ 75 | @property (nonatomic, strong) NSDictionary *titleTextAttributes UI_APPEARANCE_SELECTOR; 76 | 77 | /* 78 | Text attributes to apply to selected item title text. 79 | 80 | Attributes not set in this dictionary are inherited from `titleTextAttributes`. 81 | */ 82 | @property (nonatomic, strong) NSDictionary *selectedTitleTextAttributes UI_APPEARANCE_SELECTOR; 83 | 84 | /** 85 | Segmented control background color. 86 | 87 | Default is `[UIColor whiteColor]` 88 | */ 89 | @property (nonatomic, strong) UIColor *backgroundColor UI_APPEARANCE_SELECTOR; 90 | 91 | /** 92 | Color for the selection indicator stripe 93 | 94 | Default is `R:52, G:181, B:229` 95 | */ 96 | @property (nonatomic, strong) UIColor *selectionIndicatorColor UI_APPEARANCE_SELECTOR; 97 | 98 | /** 99 | Color for the selection indicator box 100 | 101 | Default is selectionIndicatorColor 102 | */ 103 | @property (nonatomic, strong) UIColor *selectionIndicatorBoxColor UI_APPEARANCE_SELECTOR; 104 | 105 | /** 106 | Color for the vertical divider between segments. 107 | 108 | Default is `[UIColor blackColor]` 109 | */ 110 | @property (nonatomic, strong) UIColor *verticalDividerColor UI_APPEARANCE_SELECTOR; 111 | 112 | /** 113 | Opacity for the seletion indicator box. 114 | 115 | Default is `0.2f` 116 | */ 117 | @property (nonatomic) CGFloat selectionIndicatorBoxOpacity; 118 | 119 | /** 120 | Width the vertical divider between segments that is added when `verticalDividerEnabled` is set to YES. 121 | 122 | Default is `1.0f` 123 | */ 124 | @property (nonatomic, assign) CGFloat verticalDividerWidth; 125 | 126 | /** 127 | Specifies the style of the control 128 | 129 | Default is `HMSegmentedControlTypeText` 130 | */ 131 | @property (nonatomic, assign) HMSegmentedControlType type; 132 | 133 | /** 134 | Specifies the style of the selection indicator. 135 | 136 | Default is `HMSegmentedControlSelectionStyleTextWidthStripe` 137 | */ 138 | @property (nonatomic, assign) HMSegmentedControlSelectionStyle selectionStyle; 139 | 140 | /** 141 | Specifies the style of the segment's width. 142 | 143 | Default is `HMSegmentedControlSegmentWidthStyleFixed` 144 | */ 145 | @property (nonatomic, assign) HMSegmentedControlSegmentWidthStyle segmentWidthStyle; 146 | 147 | /** 148 | Specifies the location of the selection indicator. 149 | 150 | Default is `HMSegmentedControlSelectionIndicatorLocationUp` 151 | */ 152 | @property (nonatomic, assign) HMSegmentedControlSelectionIndicatorLocation selectionIndicatorLocation; 153 | 154 | /* 155 | Specifies the border type. 156 | 157 | Default is `HMSegmentedControlBorderTypeNone` 158 | */ 159 | @property (nonatomic, assign) HMSegmentedControlBorderType borderType; 160 | 161 | /** 162 | Specifies the border color. 163 | 164 | Default is `[UIColor blackColor]` 165 | */ 166 | @property (nonatomic, strong) UIColor *borderColor; 167 | 168 | /** 169 | Specifies the border width. 170 | 171 | Default is `1.0f` 172 | */ 173 | @property (nonatomic, assign) CGFloat borderWidth; 174 | 175 | /** 176 | Default is YES. Set to NO to deny scrolling by dragging the scrollView by the user. 177 | */ 178 | @property(nonatomic, getter = isUserDraggable) BOOL userDraggable; 179 | 180 | /** 181 | Default is YES. Set to NO to deny any touch events by the user. 182 | */ 183 | @property(nonatomic, getter = isTouchEnabled) BOOL touchEnabled; 184 | 185 | /** 186 | Default is NO. Set to YES to show a vertical divider between the segments. 187 | */ 188 | @property(nonatomic, getter = isVerticalDividerEnabled) BOOL verticalDividerEnabled; 189 | 190 | /** 191 | Index of the currently selected segment. 192 | */ 193 | @property (nonatomic, assign) NSInteger selectedSegmentIndex; 194 | 195 | /** 196 | Height of the selection indicator. Only effective when `HMSegmentedControlSelectionStyle` is either `HMSegmentedControlSelectionStyleTextWidthStripe` or `HMSegmentedControlSelectionStyleFullWidthStripe`. 197 | 198 | Default is 5.0 199 | */ 200 | @property (nonatomic, readwrite) CGFloat selectionIndicatorHeight; 201 | 202 | /** 203 | Edge insets for the selection indicator. 204 | NOTE: This does not affect the bounding box of HMSegmentedControlSelectionStyleBox 205 | 206 | When HMSegmentedControlSelectionIndicatorLocationUp is selected, bottom edge insets are not used 207 | 208 | When HMSegmentedControlSelectionIndicatorLocationDown is selected, top edge insets are not used 209 | 210 | Defaults are top: 0.0f 211 | left: 0.0f 212 | bottom: 0.0f 213 | right: 0.0f 214 | */ 215 | @property (nonatomic, readwrite) UIEdgeInsets selectionIndicatorEdgeInsets; 216 | 217 | /** 218 | Inset left and right edges of segments. 219 | 220 | Default is UIEdgeInsetsMake(0, 5, 0, 5) 221 | */ 222 | @property (nonatomic, readwrite) UIEdgeInsets segmentEdgeInset; 223 | 224 | @property (nonatomic, readwrite) UIEdgeInsets enlargeEdgeInset; 225 | 226 | /** 227 | Default is YES. Set to NO to disable animation during user selection. 228 | */ 229 | @property (nonatomic) BOOL shouldAnimateUserSelection; 230 | 231 | - (id)initWithSectionTitles:(NSArray *)sectiontitles; 232 | - (id)initWithSectionImages:(NSArray *)sectionImages sectionSelectedImages:(NSArray *)sectionSelectedImages; 233 | - (instancetype)initWithSectionImages:(NSArray *)sectionImages sectionSelectedImages:(NSArray *)sectionSelectedImages titlesForSections:(NSArray *)sectiontitles; 234 | - (void)setSelectedSegmentIndex:(NSUInteger)index animated:(BOOL)animated; 235 | - (void)setIndexChangeBlock:(IndexChangeBlock)indexChangeBlock; 236 | - (void)setTitleFormatter:(HMTitleFormatterBlock)titleFormatter; 237 | 238 | @end 239 | -------------------------------------------------------------------------------- /HMSegmentedControlExample/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // HMSegmentedControlExample 4 | // 5 | // Created by Hesham Abd-Elmegid on 23/12/12. 6 | // Copyright (c) 2012 Hesham Abd-Elmegid. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | @import HMSegmentedControl; 11 | 12 | @interface ViewController () 13 | 14 | @property (nonatomic, strong) UIScrollView *scrollView; 15 | @property (nonatomic, strong) HMSegmentedControl *segmentedControl4; 16 | 17 | @end 18 | 19 | @implementation ViewController 20 | 21 | - (void)viewDidLoad { 22 | [super viewDidLoad]; 23 | 24 | self.title = @"HMSegmentedControl Demo"; 25 | self.view.backgroundColor = [UIColor whiteColor]; 26 | self.edgesForExtendedLayout = UIRectEdgeNone; 27 | 28 | CGFloat viewWidth = CGRectGetWidth(self.view.frame); 29 | 30 | // Minimum code required to use the segmented control with the default styling. 31 | HMSegmentedControl *segmentedControl = [[HMSegmentedControl alloc] initWithSectionTitles:@[@"Trending", @"News", @"Library"]]; 32 | segmentedControl.frame = CGRectMake(0, 20, viewWidth, 40); 33 | segmentedControl.autoresizingMask = UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleWidth; 34 | [segmentedControl addTarget:self action:@selector(segmentedControlChangedValue:) forControlEvents:UIControlEventValueChanged]; 35 | [self.view addSubview:segmentedControl]; 36 | 37 | 38 | // Segmented control with scrolling 39 | HMSegmentedControl *segmentedControl1 = [[HMSegmentedControl alloc] initWithSectionTitles:@[@"One", @"Two", @"Three", @"Four", @"Five", @"Six", @"Seven", @"Eight"]]; 40 | segmentedControl1.autoresizingMask = UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleWidth; 41 | segmentedControl1.frame = CGRectMake(0, 60, viewWidth, 40); 42 | segmentedControl1.segmentEdgeInset = UIEdgeInsetsMake(0, 10, 0, 10); 43 | segmentedControl1.selectionStyle = HMSegmentedControlSelectionStyleFullWidthStripe; 44 | segmentedControl1.selectionIndicatorLocation = HMSegmentedControlSelectionIndicatorLocationDown; 45 | segmentedControl1.verticalDividerEnabled = YES; 46 | segmentedControl1.verticalDividerColor = [UIColor blackColor]; 47 | segmentedControl1.verticalDividerWidth = 1.0f; 48 | [segmentedControl1 setTitleFormatter:^NSAttributedString *(HMSegmentedControl *segmentedControl, NSString *title, NSUInteger index, BOOL selected) { 49 | NSAttributedString *attString = [[NSAttributedString alloc] initWithString:title attributes:@{NSForegroundColorAttributeName : [UIColor blueColor]}]; 50 | return attString; 51 | }]; 52 | [segmentedControl1 addTarget:self action:@selector(segmentedControlChangedValue:) forControlEvents:UIControlEventValueChanged]; 53 | [self.view addSubview:segmentedControl1]; 54 | 55 | 56 | // Segmented control with images 57 | NSArray *images = @[[UIImage imageNamed:@"1"], 58 | [UIImage imageNamed:@"2"], 59 | [UIImage imageNamed:@"3"], 60 | [UIImage imageNamed:@"4"]]; 61 | 62 | NSArray *selectedImages = @[[UIImage imageNamed:@"1-selected"], 63 | [UIImage imageNamed:@"2-selected"], 64 | [UIImage imageNamed:@"3-selected"], 65 | [UIImage imageNamed:@"4-selected"]]; 66 | 67 | HMSegmentedControl *segmentedControl2 = [[HMSegmentedControl alloc] initWithSectionImages:images sectionSelectedImages:selectedImages]; 68 | segmentedControl2.frame = CGRectMake(0, 120, viewWidth, 50); 69 | segmentedControl2.selectionIndicatorHeight = 4.0f; 70 | segmentedControl2.backgroundColor = [UIColor clearColor]; 71 | segmentedControl2.selectionIndicatorLocation = HMSegmentedControlSelectionIndicatorLocationDown; 72 | segmentedControl2.selectionStyle = HMSegmentedControlSelectionStyleTextWidthStripe; 73 | [segmentedControl2 addTarget:self action:@selector(segmentedControlChangedValue:) forControlEvents:UIControlEventValueChanged]; 74 | [self.view addSubview:segmentedControl2]; 75 | 76 | 77 | // Segmented control with more customization and indexChangeBlock 78 | HMSegmentedControl *segmentedControl3 = [[HMSegmentedControl alloc] initWithSectionTitles:@[@"One", @"Two", @"Three", @"4", @"Five"]]; 79 | [segmentedControl3 setFrame:CGRectMake(0, 180, viewWidth, 50)]; 80 | [segmentedControl3 setIndexChangeBlock:^(NSInteger index) { 81 | NSLog(@"Selected index %ld (via block)", (long)index); 82 | }]; 83 | segmentedControl3.selectionIndicatorHeight = 4.0f; 84 | segmentedControl3.backgroundColor = [UIColor colorWithRed:0.1 green:0.4 blue:0.8 alpha:1]; 85 | segmentedControl3.titleTextAttributes = @{NSForegroundColorAttributeName : [UIColor whiteColor]}; 86 | segmentedControl3.selectionIndicatorColor = [UIColor colorWithRed:0.5 green:0.8 blue:1 alpha:1]; 87 | segmentedControl3.selectionIndicatorBoxColor = [UIColor blackColor]; 88 | segmentedControl3.selectionIndicatorBoxOpacity = 1.0; 89 | segmentedControl3.selectionStyle = HMSegmentedControlSelectionStyleBox; 90 | segmentedControl3.selectedSegmentIndex = HMSegmentedControlNoSegment; 91 | segmentedControl3.selectionIndicatorLocation = HMSegmentedControlSelectionIndicatorLocationDown; 92 | segmentedControl3.shouldAnimateUserSelection = NO; 93 | segmentedControl3.tag = 2; 94 | [self.view addSubview:segmentedControl3]; 95 | 96 | // Tying up the segmented control to a scroll view 97 | self.segmentedControl4 = [[HMSegmentedControl alloc] initWithFrame:CGRectMake(0, 260, viewWidth, 50)]; 98 | self.segmentedControl4.sectionTitles = @[@"Worldwide", @"Local", @"Headlines"]; 99 | self.segmentedControl4.selectedSegmentIndex = 1; 100 | self.segmentedControl4.backgroundColor = [UIColor colorWithRed:0.7 green:0.7 blue:0.7 alpha:1]; 101 | self.segmentedControl4.titleTextAttributes = @{NSForegroundColorAttributeName : [UIColor whiteColor]}; 102 | self.segmentedControl4.selectedTitleTextAttributes = @{NSForegroundColorAttributeName : [UIColor colorWithRed:0.1 green:0.1 blue:0.1 alpha:1]}; 103 | self.segmentedControl4.selectionIndicatorColor = [UIColor colorWithRed:0.3 green:0.3 blue:0.3 alpha:1]; 104 | self.segmentedControl4.selectionStyle = HMSegmentedControlSelectionStyleBox; 105 | self.segmentedControl4.selectionIndicatorLocation = HMSegmentedControlSelectionIndicatorLocationUp; 106 | self.segmentedControl4.tag = 3; 107 | 108 | __weak typeof(self) weakSelf = self; 109 | [self.segmentedControl4 setIndexChangeBlock:^(NSInteger index) { 110 | [weakSelf.scrollView scrollRectToVisible:CGRectMake(viewWidth * index, 0, viewWidth, 200) animated:YES]; 111 | }]; 112 | 113 | [self.view addSubview:self.segmentedControl4]; 114 | 115 | self.scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 310, viewWidth, 210)]; 116 | self.scrollView.backgroundColor = [UIColor colorWithRed:0.7 green:0.7 blue:0.7 alpha:1]; 117 | self.scrollView.pagingEnabled = YES; 118 | self.scrollView.showsHorizontalScrollIndicator = NO; 119 | self.scrollView.contentSize = CGSizeMake(viewWidth * 3, 200); 120 | self.scrollView.delegate = self; 121 | [self.scrollView scrollRectToVisible:CGRectMake(viewWidth, 0, viewWidth, 200) animated:NO]; 122 | [self.view addSubview:self.scrollView]; 123 | 124 | UILabel *label1 = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, viewWidth, 210)]; 125 | [self setApperanceForLabel:label1]; 126 | label1.text = @"Worldwide"; 127 | [self.scrollView addSubview:label1]; 128 | 129 | UILabel *label2 = [[UILabel alloc] initWithFrame:CGRectMake(viewWidth, 0, viewWidth, 210)]; 130 | [self setApperanceForLabel:label2]; 131 | label2.text = @"Local"; 132 | [self.scrollView addSubview:label2]; 133 | 134 | UILabel *label3 = [[UILabel alloc] initWithFrame:CGRectMake(viewWidth * 2, 0, viewWidth, 210)]; 135 | [self setApperanceForLabel:label3]; 136 | label3.text = @"Headlines"; 137 | [self.scrollView addSubview:label3]; 138 | } 139 | 140 | - (void)setApperanceForLabel:(UILabel *)label { 141 | CGFloat hue = ( arc4random() % 256 / 256.0 ); // 0.0 to 1.0 142 | CGFloat saturation = ( arc4random() % 128 / 256.0 ) + 0.5; // 0.5 to 1.0, away from white 143 | CGFloat brightness = ( arc4random() % 128 / 256.0 ) + 0.5; // 0.5 to 1.0, away from black 144 | UIColor *color = [UIColor colorWithHue:hue saturation:saturation brightness:brightness alpha:1]; 145 | label.backgroundColor = color; 146 | label.textColor = [UIColor whiteColor]; 147 | label.font = [UIFont systemFontOfSize:21.0f]; 148 | label.textAlignment = NSTextAlignmentCenter; 149 | } 150 | 151 | - (void)segmentedControlChangedValue:(HMSegmentedControl *)segmentedControl { 152 | NSLog(@"Selected index %ld (via UIControlEventValueChanged)", (long)segmentedControl.selectedSegmentIndex); 153 | } 154 | 155 | - (void)uisegmentedControlChangedValue:(UISegmentedControl *)segmentedControl { 156 | NSLog(@"Selected index %ld", (long)segmentedControl.selectedSegmentIndex); 157 | } 158 | 159 | #pragma mark - UIScrollViewDelegate 160 | 161 | - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { 162 | CGFloat pageWidth = scrollView.frame.size.width; 163 | NSInteger page = scrollView.contentOffset.x / pageWidth; 164 | 165 | [self.segmentedControl4 setSelectedSegmentIndex:page animated:YES]; 166 | } 167 | 168 | @end 169 | -------------------------------------------------------------------------------- /HMSegmentedControl.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 9C1632E71DA57214001FB468 /* HMSegmentedControl-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 9C1632E41DA57214001FB468 /* HMSegmentedControl-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; 11 | 9C1632EC1DA57220001FB468 /* HMSegmentedControl.h in Headers */ = {isa = PBXBuildFile; fileRef = 9C1632EA1DA57220001FB468 /* HMSegmentedControl.h */; settings = {ATTRIBUTES = (Public, ); }; }; 12 | 9C1632ED1DA57220001FB468 /* HMSegmentedControl.m in Sources */ = {isa = PBXBuildFile; fileRef = 9C1632EB1DA57220001FB468 /* HMSegmentedControl.m */; }; 13 | 9C1633241DA57320001FB468 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 9C16330A1DA57320001FB468 /* AppDelegate.m */; }; 14 | 9C1633271DA57320001FB468 /* 1-selected.png in Resources */ = {isa = PBXBuildFile; fileRef = 9C1633111DA57320001FB468 /* 1-selected.png */; }; 15 | 9C1633281DA57320001FB468 /* 1-selected@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 9C1633121DA57320001FB468 /* 1-selected@2x.png */; }; 16 | 9C1633291DA57320001FB468 /* 1.png in Resources */ = {isa = PBXBuildFile; fileRef = 9C1633131DA57320001FB468 /* 1.png */; }; 17 | 9C16332A1DA57320001FB468 /* 1@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 9C1633141DA57320001FB468 /* 1@2x.png */; }; 18 | 9C16332B1DA57320001FB468 /* 2-selected.png in Resources */ = {isa = PBXBuildFile; fileRef = 9C1633151DA57320001FB468 /* 2-selected.png */; }; 19 | 9C16332C1DA57320001FB468 /* 2-selected@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 9C1633161DA57320001FB468 /* 2-selected@2x.png */; }; 20 | 9C16332D1DA57320001FB468 /* 2.png in Resources */ = {isa = PBXBuildFile; fileRef = 9C1633171DA57320001FB468 /* 2.png */; }; 21 | 9C16332E1DA57320001FB468 /* 2@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 9C1633181DA57320001FB468 /* 2@2x.png */; }; 22 | 9C16332F1DA57320001FB468 /* 3-selected.png in Resources */ = {isa = PBXBuildFile; fileRef = 9C1633191DA57320001FB468 /* 3-selected.png */; }; 23 | 9C1633301DA57320001FB468 /* 3-selected@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 9C16331A1DA57320001FB468 /* 3-selected@2x.png */; }; 24 | 9C1633311DA57320001FB468 /* 3.png in Resources */ = {isa = PBXBuildFile; fileRef = 9C16331B1DA57320001FB468 /* 3.png */; }; 25 | 9C1633321DA57320001FB468 /* 3@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 9C16331C1DA57320001FB468 /* 3@2x.png */; }; 26 | 9C1633331DA57320001FB468 /* 4-selected.png in Resources */ = {isa = PBXBuildFile; fileRef = 9C16331D1DA57320001FB468 /* 4-selected.png */; }; 27 | 9C1633341DA57320001FB468 /* 4-selected@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 9C16331E1DA57320001FB468 /* 4-selected@2x.png */; }; 28 | 9C1633351DA57320001FB468 /* 4.png in Resources */ = {isa = PBXBuildFile; fileRef = 9C16331F1DA57320001FB468 /* 4.png */; }; 29 | 9C1633361DA57320001FB468 /* 4@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 9C1633201DA57320001FB468 /* 4@2x.png */; }; 30 | 9C1633371DA57320001FB468 /* Launch Screen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9C1633211DA57320001FB468 /* Launch Screen.xib */; }; 31 | 9C1633381DA57320001FB468 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9C1633231DA57320001FB468 /* ViewController.m */; }; 32 | 9C16333B1DA573C5001FB468 /* HMSegmentedControl.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9C1632D81DA57134001FB468 /* HMSegmentedControl.framework */; }; 33 | 9C16333C1DA573C5001FB468 /* HMSegmentedControl.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9C1632D81DA57134001FB468 /* HMSegmentedControl.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 34 | 9C1633421DA574EB001FB468 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 9C1633411DA574EB001FB468 /* main.m */; }; 35 | /* End PBXBuildFile section */ 36 | 37 | /* Begin PBXContainerItemProxy section */ 38 | 9C1633391DA573BD001FB468 /* PBXContainerItemProxy */ = { 39 | isa = PBXContainerItemProxy; 40 | containerPortal = 9C1632CF1DA57134001FB468 /* Project object */; 41 | proxyType = 1; 42 | remoteGlobalIDString = 9C1632D71DA57134001FB468; 43 | remoteInfo = HMSegmentedControl; 44 | }; 45 | /* End PBXContainerItemProxy section */ 46 | 47 | /* Begin PBXCopyFilesBuildPhase section */ 48 | 9C16333D1DA573C5001FB468 /* Embed Frameworks */ = { 49 | isa = PBXCopyFilesBuildPhase; 50 | buildActionMask = 2147483647; 51 | dstPath = ""; 52 | dstSubfolderSpec = 10; 53 | files = ( 54 | 9C16333C1DA573C5001FB468 /* HMSegmentedControl.framework in Embed Frameworks */, 55 | ); 56 | name = "Embed Frameworks"; 57 | runOnlyForDeploymentPostprocessing = 0; 58 | }; 59 | /* End PBXCopyFilesBuildPhase section */ 60 | 61 | /* Begin PBXFileReference section */ 62 | 9C1632D81DA57134001FB468 /* HMSegmentedControl.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = HMSegmentedControl.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 63 | 9C1632E41DA57214001FB468 /* HMSegmentedControl-umbrella.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "HMSegmentedControl-umbrella.h"; sourceTree = ""; }; 64 | 9C1632E51DA57214001FB468 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 65 | 9C1632E61DA57214001FB468 /* module.modulemap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = ""; }; 66 | 9C1632EA1DA57220001FB468 /* HMSegmentedControl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HMSegmentedControl.h; sourceTree = ""; }; 67 | 9C1632EB1DA57220001FB468 /* HMSegmentedControl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HMSegmentedControl.m; sourceTree = ""; }; 68 | 9C1632F21DA572BA001FB468 /* HMSegmentedControlExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = HMSegmentedControlExample.app; sourceTree = BUILT_PRODUCTS_DIR; }; 69 | 9C1633091DA57320001FB468 /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 70 | 9C16330A1DA57320001FB468 /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 71 | 9C16330E1DA57320001FB468 /* HMSegmentedControlExample-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "HMSegmentedControlExample-Info.plist"; sourceTree = ""; }; 72 | 9C16330F1DA57320001FB468 /* HMSegmentedControlExample-Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "HMSegmentedControlExample-Prefix.pch"; sourceTree = ""; }; 73 | 9C1633111DA57320001FB468 /* 1-selected.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "1-selected.png"; sourceTree = ""; }; 74 | 9C1633121DA57320001FB468 /* 1-selected@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "1-selected@2x.png"; sourceTree = ""; }; 75 | 9C1633131DA57320001FB468 /* 1.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = 1.png; sourceTree = ""; }; 76 | 9C1633141DA57320001FB468 /* 1@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "1@2x.png"; sourceTree = ""; }; 77 | 9C1633151DA57320001FB468 /* 2-selected.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "2-selected.png"; sourceTree = ""; }; 78 | 9C1633161DA57320001FB468 /* 2-selected@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "2-selected@2x.png"; sourceTree = ""; }; 79 | 9C1633171DA57320001FB468 /* 2.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = 2.png; sourceTree = ""; }; 80 | 9C1633181DA57320001FB468 /* 2@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "2@2x.png"; sourceTree = ""; }; 81 | 9C1633191DA57320001FB468 /* 3-selected.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "3-selected.png"; sourceTree = ""; }; 82 | 9C16331A1DA57320001FB468 /* 3-selected@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "3-selected@2x.png"; sourceTree = ""; }; 83 | 9C16331B1DA57320001FB468 /* 3.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = 3.png; sourceTree = ""; }; 84 | 9C16331C1DA57320001FB468 /* 3@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "3@2x.png"; sourceTree = ""; }; 85 | 9C16331D1DA57320001FB468 /* 4-selected.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "4-selected.png"; sourceTree = ""; }; 86 | 9C16331E1DA57320001FB468 /* 4-selected@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "4-selected@2x.png"; sourceTree = ""; }; 87 | 9C16331F1DA57320001FB468 /* 4.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = 4.png; sourceTree = ""; }; 88 | 9C1633201DA57320001FB468 /* 4@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "4@2x.png"; sourceTree = ""; }; 89 | 9C1633211DA57320001FB468 /* Launch Screen.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = "Launch Screen.xib"; sourceTree = ""; }; 90 | 9C1633221DA57320001FB468 /* ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 91 | 9C1633231DA57320001FB468 /* ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 92 | 9C1633411DA574EB001FB468 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 93 | /* End PBXFileReference section */ 94 | 95 | /* Begin PBXFrameworksBuildPhase section */ 96 | 9C1632D41DA57134001FB468 /* Frameworks */ = { 97 | isa = PBXFrameworksBuildPhase; 98 | buildActionMask = 2147483647; 99 | files = ( 100 | ); 101 | runOnlyForDeploymentPostprocessing = 0; 102 | }; 103 | 9C1632EF1DA572BA001FB468 /* Frameworks */ = { 104 | isa = PBXFrameworksBuildPhase; 105 | buildActionMask = 2147483647; 106 | files = ( 107 | 9C16333B1DA573C5001FB468 /* HMSegmentedControl.framework in Frameworks */, 108 | ); 109 | runOnlyForDeploymentPostprocessing = 0; 110 | }; 111 | /* End PBXFrameworksBuildPhase section */ 112 | 113 | /* Begin PBXGroup section */ 114 | 9C1632CE1DA57134001FB468 = { 115 | isa = PBXGroup; 116 | children = ( 117 | 9C1632E91DA57220001FB468 /* HMSegmentedControl */, 118 | 9C1632F31DA572BA001FB468 /* HMSegmentedControlExample */, 119 | 9C1632E31DA57214001FB468 /* Framework */, 120 | 9C1632D91DA57134001FB468 /* Products */, 121 | ); 122 | sourceTree = ""; 123 | }; 124 | 9C1632D91DA57134001FB468 /* Products */ = { 125 | isa = PBXGroup; 126 | children = ( 127 | 9C1632D81DA57134001FB468 /* HMSegmentedControl.framework */, 128 | 9C1632F21DA572BA001FB468 /* HMSegmentedControlExample.app */, 129 | ); 130 | name = Products; 131 | sourceTree = ""; 132 | }; 133 | 9C1632E31DA57214001FB468 /* Framework */ = { 134 | isa = PBXGroup; 135 | children = ( 136 | 9C1632E41DA57214001FB468 /* HMSegmentedControl-umbrella.h */, 137 | 9C1632E51DA57214001FB468 /* Info.plist */, 138 | 9C1632E61DA57214001FB468 /* module.modulemap */, 139 | ); 140 | path = Framework; 141 | sourceTree = ""; 142 | }; 143 | 9C1632E91DA57220001FB468 /* HMSegmentedControl */ = { 144 | isa = PBXGroup; 145 | children = ( 146 | 9C1632EA1DA57220001FB468 /* HMSegmentedControl.h */, 147 | 9C1632EB1DA57220001FB468 /* HMSegmentedControl.m */, 148 | ); 149 | path = HMSegmentedControl; 150 | sourceTree = ""; 151 | }; 152 | 9C1632F31DA572BA001FB468 /* HMSegmentedControlExample */ = { 153 | isa = PBXGroup; 154 | children = ( 155 | 9C1633091DA57320001FB468 /* AppDelegate.h */, 156 | 9C16330A1DA57320001FB468 /* AppDelegate.m */, 157 | 9C1633221DA57320001FB468 /* ViewController.h */, 158 | 9C1633231DA57320001FB468 /* ViewController.m */, 159 | 9C1633101DA57320001FB468 /* Images */, 160 | 9C16330E1DA57320001FB468 /* HMSegmentedControlExample-Info.plist */, 161 | 9C16330F1DA57320001FB468 /* HMSegmentedControlExample-Prefix.pch */, 162 | 9C1633211DA57320001FB468 /* Launch Screen.xib */, 163 | 9C1632F41DA572BA001FB468 /* Supporting Files */, 164 | ); 165 | path = HMSegmentedControlExample; 166 | sourceTree = ""; 167 | }; 168 | 9C1632F41DA572BA001FB468 /* Supporting Files */ = { 169 | isa = PBXGroup; 170 | children = ( 171 | 9C1633411DA574EB001FB468 /* main.m */, 172 | ); 173 | name = "Supporting Files"; 174 | sourceTree = ""; 175 | }; 176 | 9C1633101DA57320001FB468 /* Images */ = { 177 | isa = PBXGroup; 178 | children = ( 179 | 9C1633111DA57320001FB468 /* 1-selected.png */, 180 | 9C1633121DA57320001FB468 /* 1-selected@2x.png */, 181 | 9C1633131DA57320001FB468 /* 1.png */, 182 | 9C1633141DA57320001FB468 /* 1@2x.png */, 183 | 9C1633151DA57320001FB468 /* 2-selected.png */, 184 | 9C1633161DA57320001FB468 /* 2-selected@2x.png */, 185 | 9C1633171DA57320001FB468 /* 2.png */, 186 | 9C1633181DA57320001FB468 /* 2@2x.png */, 187 | 9C1633191DA57320001FB468 /* 3-selected.png */, 188 | 9C16331A1DA57320001FB468 /* 3-selected@2x.png */, 189 | 9C16331B1DA57320001FB468 /* 3.png */, 190 | 9C16331C1DA57320001FB468 /* 3@2x.png */, 191 | 9C16331D1DA57320001FB468 /* 4-selected.png */, 192 | 9C16331E1DA57320001FB468 /* 4-selected@2x.png */, 193 | 9C16331F1DA57320001FB468 /* 4.png */, 194 | 9C1633201DA57320001FB468 /* 4@2x.png */, 195 | ); 196 | path = Images; 197 | sourceTree = ""; 198 | }; 199 | /* End PBXGroup section */ 200 | 201 | /* Begin PBXHeadersBuildPhase section */ 202 | 9C1632D51DA57134001FB468 /* Headers */ = { 203 | isa = PBXHeadersBuildPhase; 204 | buildActionMask = 2147483647; 205 | files = ( 206 | 9C1632EC1DA57220001FB468 /* HMSegmentedControl.h in Headers */, 207 | 9C1632E71DA57214001FB468 /* HMSegmentedControl-umbrella.h in Headers */, 208 | ); 209 | runOnlyForDeploymentPostprocessing = 0; 210 | }; 211 | /* End PBXHeadersBuildPhase section */ 212 | 213 | /* Begin PBXNativeTarget section */ 214 | 9C1632D71DA57134001FB468 /* HMSegmentedControl */ = { 215 | isa = PBXNativeTarget; 216 | buildConfigurationList = 9C1632E01DA57134001FB468 /* Build configuration list for PBXNativeTarget "HMSegmentedControl" */; 217 | buildPhases = ( 218 | 9C1632D31DA57134001FB468 /* Sources */, 219 | 9C1632D41DA57134001FB468 /* Frameworks */, 220 | 9C1632D51DA57134001FB468 /* Headers */, 221 | 9C1632D61DA57134001FB468 /* Resources */, 222 | ); 223 | buildRules = ( 224 | ); 225 | dependencies = ( 226 | ); 227 | name = HMSegmentedControl; 228 | productName = HMSegmentedControl; 229 | productReference = 9C1632D81DA57134001FB468 /* HMSegmentedControl.framework */; 230 | productType = "com.apple.product-type.framework"; 231 | }; 232 | 9C1632F11DA572BA001FB468 /* HMSegmentedControlExample */ = { 233 | isa = PBXNativeTarget; 234 | buildConfigurationList = 9C1633061DA572BA001FB468 /* Build configuration list for PBXNativeTarget "HMSegmentedControlExample" */; 235 | buildPhases = ( 236 | 9C1632EE1DA572BA001FB468 /* Sources */, 237 | 9C1632EF1DA572BA001FB468 /* Frameworks */, 238 | 9C1632F01DA572BA001FB468 /* Resources */, 239 | 9C16333D1DA573C5001FB468 /* Embed Frameworks */, 240 | ); 241 | buildRules = ( 242 | ); 243 | dependencies = ( 244 | 9C16333A1DA573BD001FB468 /* PBXTargetDependency */, 245 | ); 246 | name = HMSegmentedControlExample; 247 | productName = HMSegmentedControlExample; 248 | productReference = 9C1632F21DA572BA001FB468 /* HMSegmentedControlExample.app */; 249 | productType = "com.apple.product-type.application"; 250 | }; 251 | /* End PBXNativeTarget section */ 252 | 253 | /* Begin PBXProject section */ 254 | 9C1632CF1DA57134001FB468 /* Project object */ = { 255 | isa = PBXProject; 256 | attributes = { 257 | LastUpgradeCheck = 0800; 258 | ORGANIZATIONNAME = HeshamMegid; 259 | TargetAttributes = { 260 | 9C1632D71DA57134001FB468 = { 261 | CreatedOnToolsVersion = 8.0; 262 | DevelopmentTeam = C75GEDTP26; 263 | ProvisioningStyle = Automatic; 264 | }; 265 | 9C1632F11DA572BA001FB468 = { 266 | CreatedOnToolsVersion = 8.0; 267 | DevelopmentTeam = C75GEDTP26; 268 | ProvisioningStyle = Automatic; 269 | }; 270 | }; 271 | }; 272 | buildConfigurationList = 9C1632D21DA57134001FB468 /* Build configuration list for PBXProject "HMSegmentedControl" */; 273 | compatibilityVersion = "Xcode 3.2"; 274 | developmentRegion = English; 275 | hasScannedForEncodings = 0; 276 | knownRegions = ( 277 | en, 278 | Base, 279 | ); 280 | mainGroup = 9C1632CE1DA57134001FB468; 281 | productRefGroup = 9C1632D91DA57134001FB468 /* Products */; 282 | projectDirPath = ""; 283 | projectRoot = ""; 284 | targets = ( 285 | 9C1632D71DA57134001FB468 /* HMSegmentedControl */, 286 | 9C1632F11DA572BA001FB468 /* HMSegmentedControlExample */, 287 | ); 288 | }; 289 | /* End PBXProject section */ 290 | 291 | /* Begin PBXResourcesBuildPhase section */ 292 | 9C1632D61DA57134001FB468 /* Resources */ = { 293 | isa = PBXResourcesBuildPhase; 294 | buildActionMask = 2147483647; 295 | files = ( 296 | ); 297 | runOnlyForDeploymentPostprocessing = 0; 298 | }; 299 | 9C1632F01DA572BA001FB468 /* Resources */ = { 300 | isa = PBXResourcesBuildPhase; 301 | buildActionMask = 2147483647; 302 | files = ( 303 | 9C16332A1DA57320001FB468 /* 1@2x.png in Resources */, 304 | 9C1633281DA57320001FB468 /* 1-selected@2x.png in Resources */, 305 | 9C1633271DA57320001FB468 /* 1-selected.png in Resources */, 306 | 9C1633351DA57320001FB468 /* 4.png in Resources */, 307 | 9C16332B1DA57320001FB468 /* 2-selected.png in Resources */, 308 | 9C16332D1DA57320001FB468 /* 2.png in Resources */, 309 | 9C1633301DA57320001FB468 /* 3-selected@2x.png in Resources */, 310 | 9C1633371DA57320001FB468 /* Launch Screen.xib in Resources */, 311 | 9C1633361DA57320001FB468 /* 4@2x.png in Resources */, 312 | 9C1633341DA57320001FB468 /* 4-selected@2x.png in Resources */, 313 | 9C1633311DA57320001FB468 /* 3.png in Resources */, 314 | 9C16332F1DA57320001FB468 /* 3-selected.png in Resources */, 315 | 9C16332E1DA57320001FB468 /* 2@2x.png in Resources */, 316 | 9C16332C1DA57320001FB468 /* 2-selected@2x.png in Resources */, 317 | 9C1633331DA57320001FB468 /* 4-selected.png in Resources */, 318 | 9C1633321DA57320001FB468 /* 3@2x.png in Resources */, 319 | 9C1633291DA57320001FB468 /* 1.png in Resources */, 320 | ); 321 | runOnlyForDeploymentPostprocessing = 0; 322 | }; 323 | /* End PBXResourcesBuildPhase section */ 324 | 325 | /* Begin PBXSourcesBuildPhase section */ 326 | 9C1632D31DA57134001FB468 /* Sources */ = { 327 | isa = PBXSourcesBuildPhase; 328 | buildActionMask = 2147483647; 329 | files = ( 330 | 9C1632ED1DA57220001FB468 /* HMSegmentedControl.m in Sources */, 331 | ); 332 | runOnlyForDeploymentPostprocessing = 0; 333 | }; 334 | 9C1632EE1DA572BA001FB468 /* Sources */ = { 335 | isa = PBXSourcesBuildPhase; 336 | buildActionMask = 2147483647; 337 | files = ( 338 | 9C1633381DA57320001FB468 /* ViewController.m in Sources */, 339 | 9C1633421DA574EB001FB468 /* main.m in Sources */, 340 | 9C1633241DA57320001FB468 /* AppDelegate.m in Sources */, 341 | ); 342 | runOnlyForDeploymentPostprocessing = 0; 343 | }; 344 | /* End PBXSourcesBuildPhase section */ 345 | 346 | /* Begin PBXTargetDependency section */ 347 | 9C16333A1DA573BD001FB468 /* PBXTargetDependency */ = { 348 | isa = PBXTargetDependency; 349 | target = 9C1632D71DA57134001FB468 /* HMSegmentedControl */; 350 | targetProxy = 9C1633391DA573BD001FB468 /* PBXContainerItemProxy */; 351 | }; 352 | /* End PBXTargetDependency section */ 353 | 354 | /* Begin XCBuildConfiguration section */ 355 | 9C1632DE1DA57134001FB468 /* Debug */ = { 356 | isa = XCBuildConfiguration; 357 | buildSettings = { 358 | ALWAYS_SEARCH_USER_PATHS = NO; 359 | CLANG_ANALYZER_NONNULL = YES; 360 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 361 | CLANG_CXX_LIBRARY = "libc++"; 362 | CLANG_ENABLE_MODULES = YES; 363 | CLANG_ENABLE_OBJC_ARC = YES; 364 | CLANG_WARN_BOOL_CONVERSION = YES; 365 | CLANG_WARN_CONSTANT_CONVERSION = YES; 366 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 367 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 368 | CLANG_WARN_EMPTY_BODY = YES; 369 | CLANG_WARN_ENUM_CONVERSION = YES; 370 | CLANG_WARN_INFINITE_RECURSION = YES; 371 | CLANG_WARN_INT_CONVERSION = YES; 372 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 373 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 374 | CLANG_WARN_SUSPICIOUS_MOVES = YES; 375 | CLANG_WARN_UNREACHABLE_CODE = YES; 376 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 377 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 378 | COPY_PHASE_STRIP = NO; 379 | CURRENT_PROJECT_VERSION = 1; 380 | DEBUG_INFORMATION_FORMAT = dwarf; 381 | ENABLE_STRICT_OBJC_MSGSEND = YES; 382 | ENABLE_TESTABILITY = YES; 383 | GCC_C_LANGUAGE_STANDARD = gnu99; 384 | GCC_DYNAMIC_NO_PIC = NO; 385 | GCC_NO_COMMON_BLOCKS = YES; 386 | GCC_OPTIMIZATION_LEVEL = 0; 387 | GCC_PREPROCESSOR_DEFINITIONS = ( 388 | "DEBUG=1", 389 | "$(inherited)", 390 | ); 391 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 392 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 393 | GCC_WARN_UNDECLARED_SELECTOR = YES; 394 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 395 | GCC_WARN_UNUSED_FUNCTION = YES; 396 | GCC_WARN_UNUSED_VARIABLE = YES; 397 | IPHONEOS_DEPLOYMENT_TARGET = 10.0; 398 | MTL_ENABLE_DEBUG_INFO = YES; 399 | ONLY_ACTIVE_ARCH = YES; 400 | SDKROOT = iphoneos; 401 | TARGETED_DEVICE_FAMILY = "1,2"; 402 | VERSIONING_SYSTEM = "apple-generic"; 403 | VERSION_INFO_PREFIX = ""; 404 | }; 405 | name = Debug; 406 | }; 407 | 9C1632DF1DA57134001FB468 /* Release */ = { 408 | isa = XCBuildConfiguration; 409 | buildSettings = { 410 | ALWAYS_SEARCH_USER_PATHS = NO; 411 | CLANG_ANALYZER_NONNULL = YES; 412 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 413 | CLANG_CXX_LIBRARY = "libc++"; 414 | CLANG_ENABLE_MODULES = YES; 415 | CLANG_ENABLE_OBJC_ARC = YES; 416 | CLANG_WARN_BOOL_CONVERSION = YES; 417 | CLANG_WARN_CONSTANT_CONVERSION = YES; 418 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 419 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 420 | CLANG_WARN_EMPTY_BODY = YES; 421 | CLANG_WARN_ENUM_CONVERSION = YES; 422 | CLANG_WARN_INFINITE_RECURSION = YES; 423 | CLANG_WARN_INT_CONVERSION = YES; 424 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 425 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 426 | CLANG_WARN_SUSPICIOUS_MOVES = YES; 427 | CLANG_WARN_UNREACHABLE_CODE = YES; 428 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 429 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 430 | COPY_PHASE_STRIP = NO; 431 | CURRENT_PROJECT_VERSION = 1; 432 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 433 | ENABLE_NS_ASSERTIONS = NO; 434 | ENABLE_STRICT_OBJC_MSGSEND = YES; 435 | GCC_C_LANGUAGE_STANDARD = gnu99; 436 | GCC_NO_COMMON_BLOCKS = YES; 437 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 438 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 439 | GCC_WARN_UNDECLARED_SELECTOR = YES; 440 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 441 | GCC_WARN_UNUSED_FUNCTION = YES; 442 | GCC_WARN_UNUSED_VARIABLE = YES; 443 | IPHONEOS_DEPLOYMENT_TARGET = 10.0; 444 | MTL_ENABLE_DEBUG_INFO = NO; 445 | SDKROOT = iphoneos; 446 | TARGETED_DEVICE_FAMILY = "1,2"; 447 | VALIDATE_PRODUCT = YES; 448 | VERSIONING_SYSTEM = "apple-generic"; 449 | VERSION_INFO_PREFIX = ""; 450 | }; 451 | name = Release; 452 | }; 453 | 9C1632E11DA57134001FB468 /* Debug */ = { 454 | isa = XCBuildConfiguration; 455 | buildSettings = { 456 | CODE_SIGN_IDENTITY = ""; 457 | DEFINES_MODULE = YES; 458 | DEVELOPMENT_TEAM = C75GEDTP26; 459 | DYLIB_COMPATIBILITY_VERSION = 1; 460 | DYLIB_CURRENT_VERSION = 1; 461 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 462 | INFOPLIST_FILE = "$(SRCROOT)/Framework/Info.plist"; 463 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 464 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 465 | MODULEMAP_FILE = Framework/module.modulemap; 466 | PRODUCT_BUNDLE_IDENTIFIER = com.heshammegid.HMSegmentedControl; 467 | PRODUCT_NAME = "$(TARGET_NAME)"; 468 | SKIP_INSTALL = YES; 469 | }; 470 | name = Debug; 471 | }; 472 | 9C1632E21DA57134001FB468 /* Release */ = { 473 | isa = XCBuildConfiguration; 474 | buildSettings = { 475 | CODE_SIGN_IDENTITY = ""; 476 | DEFINES_MODULE = YES; 477 | DEVELOPMENT_TEAM = C75GEDTP26; 478 | DYLIB_COMPATIBILITY_VERSION = 1; 479 | DYLIB_CURRENT_VERSION = 1; 480 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 481 | INFOPLIST_FILE = "$(SRCROOT)/Framework/Info.plist"; 482 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 483 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 484 | MODULEMAP_FILE = Framework/module.modulemap; 485 | PRODUCT_BUNDLE_IDENTIFIER = com.heshammegid.HMSegmentedControl; 486 | PRODUCT_NAME = "$(TARGET_NAME)"; 487 | SKIP_INSTALL = YES; 488 | }; 489 | name = Release; 490 | }; 491 | 9C1633071DA572BA001FB468 /* Debug */ = { 492 | isa = XCBuildConfiguration; 493 | buildSettings = { 494 | DEVELOPMENT_TEAM = C75GEDTP26; 495 | INFOPLIST_FILE = "$(SRCROOT)/HMSegmentedControlExample/HMSegmentedControlExample-Info.plist"; 496 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 497 | PRODUCT_BUNDLE_IDENTIFIER = com.heshammegid.HMSegmentedControlExample; 498 | PRODUCT_NAME = "$(TARGET_NAME)"; 499 | }; 500 | name = Debug; 501 | }; 502 | 9C1633081DA572BA001FB468 /* Release */ = { 503 | isa = XCBuildConfiguration; 504 | buildSettings = { 505 | DEVELOPMENT_TEAM = C75GEDTP26; 506 | INFOPLIST_FILE = "$(SRCROOT)/HMSegmentedControlExample/HMSegmentedControlExample-Info.plist"; 507 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 508 | PRODUCT_BUNDLE_IDENTIFIER = com.heshammegid.HMSegmentedControlExample; 509 | PRODUCT_NAME = "$(TARGET_NAME)"; 510 | }; 511 | name = Release; 512 | }; 513 | /* End XCBuildConfiguration section */ 514 | 515 | /* Begin XCConfigurationList section */ 516 | 9C1632D21DA57134001FB468 /* Build configuration list for PBXProject "HMSegmentedControl" */ = { 517 | isa = XCConfigurationList; 518 | buildConfigurations = ( 519 | 9C1632DE1DA57134001FB468 /* Debug */, 520 | 9C1632DF1DA57134001FB468 /* Release */, 521 | ); 522 | defaultConfigurationIsVisible = 0; 523 | defaultConfigurationName = Release; 524 | }; 525 | 9C1632E01DA57134001FB468 /* Build configuration list for PBXNativeTarget "HMSegmentedControl" */ = { 526 | isa = XCConfigurationList; 527 | buildConfigurations = ( 528 | 9C1632E11DA57134001FB468 /* Debug */, 529 | 9C1632E21DA57134001FB468 /* Release */, 530 | ); 531 | defaultConfigurationIsVisible = 0; 532 | defaultConfigurationName = Release; 533 | }; 534 | 9C1633061DA572BA001FB468 /* Build configuration list for PBXNativeTarget "HMSegmentedControlExample" */ = { 535 | isa = XCConfigurationList; 536 | buildConfigurations = ( 537 | 9C1633071DA572BA001FB468 /* Debug */, 538 | 9C1633081DA572BA001FB468 /* Release */, 539 | ); 540 | defaultConfigurationIsVisible = 0; 541 | defaultConfigurationName = Release; 542 | }; 543 | /* End XCConfigurationList section */ 544 | }; 545 | rootObject = 9C1632CF1DA57134001FB468 /* Project object */; 546 | } 547 | -------------------------------------------------------------------------------- /HMSegmentedControl/HMSegmentedControl.m: -------------------------------------------------------------------------------- 1 | // 2 | // HMSegmentedControl.m 3 | // HMSegmentedControl 4 | // 5 | // Created by Hesham Abd-Elmegid on 23/12/12. 6 | // Copyright (c) 2012-2015 Hesham Abd-Elmegid. All rights reserved. 7 | // 8 | 9 | #import "HMSegmentedControl.h" 10 | #import 11 | #import 12 | 13 | @interface HMScrollView : UIScrollView 14 | @end 15 | 16 | @interface HMSegmentedControl () 17 | 18 | @property (nonatomic, strong) CALayer *selectionIndicatorStripLayer; 19 | @property (nonatomic, strong) CALayer *selectionIndicatorBoxLayer; 20 | @property (nonatomic, strong) CALayer *selectionIndicatorArrowLayer; 21 | @property (nonatomic, readwrite) CGFloat segmentWidth; 22 | @property (nonatomic, readwrite) NSArray *segmentWidthsArray; 23 | @property (nonatomic, strong) HMScrollView *scrollView; 24 | 25 | @end 26 | 27 | @implementation HMScrollView 28 | 29 | - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { 30 | if (!self.dragging) { 31 | [self.nextResponder touchesBegan:touches withEvent:event]; 32 | } else { 33 | [super touchesBegan:touches withEvent:event]; 34 | } 35 | } 36 | 37 | - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{ 38 | if (!self.dragging) { 39 | [self.nextResponder touchesMoved:touches withEvent:event]; 40 | } else{ 41 | [super touchesMoved:touches withEvent:event]; 42 | } 43 | } 44 | 45 | - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { 46 | if (!self.dragging) { 47 | [self.nextResponder touchesEnded:touches withEvent:event]; 48 | } else { 49 | [super touchesEnded:touches withEvent:event]; 50 | } 51 | } 52 | 53 | @end 54 | 55 | @implementation HMSegmentedControl 56 | 57 | - (id)initWithCoder:(NSCoder *)aDecoder { 58 | self = [super initWithCoder:aDecoder]; 59 | if (self) { 60 | [self commonInit]; 61 | } 62 | return self; 63 | } 64 | 65 | - (id)initWithFrame:(CGRect)frame { 66 | self = [super initWithFrame:frame]; 67 | 68 | if (self) { 69 | [self commonInit]; 70 | } 71 | 72 | return self; 73 | } 74 | 75 | - (id)initWithSectionTitles:(NSArray *)sectiontitles { 76 | self = [super initWithFrame:CGRectZero]; 77 | 78 | if (self) { 79 | [self commonInit]; 80 | self.sectionTitles = sectiontitles; 81 | self.type = HMSegmentedControlTypeText; 82 | } 83 | 84 | return self; 85 | } 86 | 87 | - (id)initWithSectionImages:(NSArray *)sectionImages sectionSelectedImages:(NSArray *)sectionSelectedImages { 88 | self = [super initWithFrame:CGRectZero]; 89 | 90 | if (self) { 91 | [self commonInit]; 92 | self.sectionImages = sectionImages; 93 | self.sectionSelectedImages = sectionSelectedImages; 94 | self.type = HMSegmentedControlTypeImages; 95 | } 96 | 97 | return self; 98 | } 99 | 100 | - (instancetype)initWithSectionImages:(NSArray *)sectionImages sectionSelectedImages:(NSArray *)sectionSelectedImages titlesForSections:(NSArray *)sectiontitles { 101 | self = [super initWithFrame:CGRectZero]; 102 | 103 | if (self) { 104 | [self commonInit]; 105 | 106 | if (sectionImages.count != sectiontitles.count) { 107 | [NSException raise:NSRangeException format:@"***%s: Images bounds (%ld) Don't match Title bounds (%ld)", sel_getName(_cmd), (unsigned long)sectionImages.count, (unsigned long)sectiontitles.count]; 108 | } 109 | 110 | self.sectionImages = sectionImages; 111 | self.sectionSelectedImages = sectionSelectedImages; 112 | self.sectionTitles = sectiontitles; 113 | self.type = HMSegmentedControlTypeTextImages; 114 | } 115 | 116 | return self; 117 | } 118 | 119 | - (void)awakeFromNib { 120 | [super awakeFromNib]; 121 | 122 | self.segmentWidth = 0.0f; 123 | } 124 | 125 | - (void)commonInit { 126 | self.scrollView = [[HMScrollView alloc] init]; 127 | self.scrollView.scrollsToTop = NO; 128 | self.scrollView.showsVerticalScrollIndicator = NO; 129 | self.scrollView.showsHorizontalScrollIndicator = NO; 130 | [self addSubview:self.scrollView]; 131 | 132 | _backgroundColor = [UIColor whiteColor]; 133 | self.opaque = NO; 134 | _selectionIndicatorColor = [UIColor colorWithRed:52.0f/255.0f green:181.0f/255.0f blue:229.0f/255.0f alpha:1.0f]; 135 | _selectionIndicatorBoxColor = _selectionIndicatorColor; 136 | 137 | self.selectedSegmentIndex = 0; 138 | self.segmentEdgeInset = UIEdgeInsetsMake(0, 5, 0, 5); 139 | self.selectionIndicatorHeight = 5.0f; 140 | self.selectionIndicatorEdgeInsets = UIEdgeInsetsMake(0.0f, 0.0f, 0.0f, 0.0f); 141 | self.selectionStyle = HMSegmentedControlSelectionStyleTextWidthStripe; 142 | self.selectionIndicatorLocation = HMSegmentedControlSelectionIndicatorLocationUp; 143 | self.segmentWidthStyle = HMSegmentedControlSegmentWidthStyleFixed; 144 | self.userDraggable = YES; 145 | self.touchEnabled = YES; 146 | self.verticalDividerEnabled = NO; 147 | self.type = HMSegmentedControlTypeText; 148 | self.verticalDividerWidth = 1.0f; 149 | _verticalDividerColor = [UIColor blackColor]; 150 | self.borderColor = [UIColor blackColor]; 151 | self.borderWidth = 1.0f; 152 | 153 | self.shouldAnimateUserSelection = YES; 154 | 155 | self.selectionIndicatorArrowLayer = [CALayer layer]; 156 | self.selectionIndicatorStripLayer = [CALayer layer]; 157 | self.selectionIndicatorBoxLayer = [CALayer layer]; 158 | self.selectionIndicatorBoxLayer.opacity = self.selectionIndicatorBoxOpacity; 159 | self.selectionIndicatorBoxLayer.borderWidth = 1.0f; 160 | self.selectionIndicatorBoxOpacity = 0.2; 161 | 162 | self.contentMode = UIViewContentModeRedraw; 163 | } 164 | 165 | - (void)layoutSubviews { 166 | [super layoutSubviews]; 167 | 168 | [self updateSegmentsRects]; 169 | } 170 | 171 | - (void)setFrame:(CGRect)frame { 172 | [super setFrame:frame]; 173 | 174 | [self updateSegmentsRects]; 175 | } 176 | 177 | - (void)setSectionTitles:(NSArray *)sectionTitles { 178 | _sectionTitles = sectionTitles; 179 | 180 | [self setNeedsLayout]; 181 | [self setNeedsDisplay]; 182 | } 183 | 184 | - (void)setSectionImages:(NSArray *)sectionImages { 185 | _sectionImages = sectionImages; 186 | 187 | [self setNeedsLayout]; 188 | [self setNeedsDisplay]; 189 | } 190 | 191 | - (void)setSelectionIndicatorLocation:(HMSegmentedControlSelectionIndicatorLocation)selectionIndicatorLocation { 192 | _selectionIndicatorLocation = selectionIndicatorLocation; 193 | 194 | if (selectionIndicatorLocation == HMSegmentedControlSelectionIndicatorLocationNone) { 195 | self.selectionIndicatorHeight = 0.0f; 196 | } 197 | } 198 | 199 | - (void)setSelectionIndicatorBoxOpacity:(CGFloat)selectionIndicatorBoxOpacity { 200 | _selectionIndicatorBoxOpacity = selectionIndicatorBoxOpacity; 201 | 202 | self.selectionIndicatorBoxLayer.opacity = _selectionIndicatorBoxOpacity; 203 | } 204 | 205 | - (void)setSegmentWidthStyle:(HMSegmentedControlSegmentWidthStyle)segmentWidthStyle { 206 | // Force HMSegmentedControlSegmentWidthStyleFixed when type is HMSegmentedControlTypeImages. 207 | if (self.type == HMSegmentedControlTypeImages) { 208 | _segmentWidthStyle = HMSegmentedControlSegmentWidthStyleFixed; 209 | } else { 210 | _segmentWidthStyle = segmentWidthStyle; 211 | } 212 | } 213 | 214 | - (void)setBorderType:(HMSegmentedControlBorderType)borderType { 215 | _borderType = borderType; 216 | [self setNeedsDisplay]; 217 | } 218 | 219 | #pragma mark - Drawing 220 | 221 | - (CGSize)measureTitleAtIndex:(NSUInteger)index { 222 | if (index >= self.sectionTitles.count) { 223 | return CGSizeZero; 224 | } 225 | 226 | id title = self.sectionTitles[index]; 227 | CGSize size = CGSizeZero; 228 | BOOL selected = (index == self.selectedSegmentIndex) ? YES : NO; 229 | if ([title isKindOfClass:[NSString class]] && !self.titleFormatter) { 230 | NSDictionary *titleAttrs = selected ? [self resultingSelectedTitleTextAttributes] : [self resultingTitleTextAttributes]; 231 | size = [(NSString *)title sizeWithAttributes:titleAttrs]; 232 | } else if ([title isKindOfClass:[NSString class]] && self.titleFormatter) { 233 | size = [self.titleFormatter(self, title, index, selected) size]; 234 | } else if ([title isKindOfClass:[NSAttributedString class]]) { 235 | size = [(NSAttributedString *)title size]; 236 | } else { 237 | NSAssert(title == nil, @"Unexpected type of segment title: %@", [title class]); 238 | size = CGSizeZero; 239 | } 240 | return CGRectIntegral((CGRect){CGPointZero, size}).size; 241 | } 242 | 243 | - (NSAttributedString *)attributedTitleAtIndex:(NSUInteger)index { 244 | id title = self.sectionTitles[index]; 245 | BOOL selected = (index == self.selectedSegmentIndex) ? YES : NO; 246 | 247 | if ([title isKindOfClass:[NSAttributedString class]]) { 248 | return (NSAttributedString *)title; 249 | } else if (!self.titleFormatter) { 250 | NSDictionary *titleAttrs = selected ? [self resultingSelectedTitleTextAttributes] : [self resultingTitleTextAttributes]; 251 | 252 | // the color should be cast to CGColor in order to avoid invalid context on iOS7 253 | UIColor *titleColor = titleAttrs[NSForegroundColorAttributeName]; 254 | 255 | if (titleColor) { 256 | NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithDictionary:titleAttrs]; 257 | 258 | dict[NSForegroundColorAttributeName] = (id)titleColor.CGColor; 259 | 260 | titleAttrs = [NSDictionary dictionaryWithDictionary:dict]; 261 | } 262 | 263 | return [[NSAttributedString alloc] initWithString:(NSString *)title attributes:titleAttrs]; 264 | } else { 265 | return self.titleFormatter(self, title, index, selected); 266 | } 267 | } 268 | 269 | - (void)drawRect:(CGRect)rect { 270 | [self.backgroundColor setFill]; 271 | UIRectFill([self bounds]); 272 | 273 | self.selectionIndicatorArrowLayer.backgroundColor = self.selectionIndicatorColor.CGColor; 274 | 275 | self.selectionIndicatorStripLayer.backgroundColor = self.selectionIndicatorColor.CGColor; 276 | 277 | self.selectionIndicatorBoxLayer.backgroundColor = self.selectionIndicatorBoxColor.CGColor; 278 | self.selectionIndicatorBoxLayer.borderColor = self.selectionIndicatorBoxColor.CGColor; 279 | 280 | // Remove all sublayers to avoid drawing images over existing ones 281 | self.scrollView.layer.sublayers = nil; 282 | 283 | CGRect oldRect = rect; 284 | 285 | if (self.type == HMSegmentedControlTypeText) { 286 | [self.sectionTitles enumerateObjectsUsingBlock:^(id titleString, NSUInteger idx, BOOL *stop) { 287 | 288 | CGFloat stringWidth = 0; 289 | CGFloat stringHeight = 0; 290 | CGSize size = [self measureTitleAtIndex:idx]; 291 | stringWidth = size.width; 292 | stringHeight = size.height; 293 | CGRect rectDiv = CGRectZero; 294 | CGRect fullRect = CGRectZero; 295 | 296 | // Text inside the CATextLayer will appear blurry unless the rect values are rounded 297 | BOOL locationUp = (self.selectionIndicatorLocation == HMSegmentedControlSelectionIndicatorLocationUp); 298 | BOOL selectionStyleNotBox = (self.selectionStyle != HMSegmentedControlSelectionStyleBox); 299 | 300 | CGFloat y = roundf((CGRectGetHeight(self.frame) - selectionStyleNotBox * self.selectionIndicatorHeight) / 2 - stringHeight / 2 + self.selectionIndicatorHeight * locationUp); 301 | CGRect rect; 302 | if (self.segmentWidthStyle == HMSegmentedControlSegmentWidthStyleFixed) { 303 | rect = CGRectMake((self.segmentWidth * idx) + (self.segmentWidth - stringWidth) / 2, y, stringWidth, stringHeight); 304 | rectDiv = CGRectMake((self.segmentWidth * idx) - (self.verticalDividerWidth / 2), self.selectionIndicatorHeight * 2, self.verticalDividerWidth, self.frame.size.height - (self.selectionIndicatorHeight * 4)); 305 | fullRect = CGRectMake(self.segmentWidth * idx, 0, self.segmentWidth, oldRect.size.height); 306 | } else { 307 | // When we are drawing dynamic widths, we need to loop the widths array to calculate the xOffset 308 | CGFloat xOffset = 0; 309 | NSInteger i = 0; 310 | for (NSNumber *width in self.segmentWidthsArray) { 311 | if (idx == i) 312 | break; 313 | xOffset = xOffset + [width floatValue]; 314 | i++; 315 | } 316 | 317 | CGFloat widthForIndex = [[self.segmentWidthsArray objectAtIndex:idx] floatValue]; 318 | rect = CGRectMake(xOffset, y, widthForIndex, stringHeight); 319 | fullRect = CGRectMake(self.segmentWidth * idx, 0, widthForIndex, oldRect.size.height); 320 | rectDiv = CGRectMake(xOffset - (self.verticalDividerWidth / 2), self.selectionIndicatorHeight * 2, self.verticalDividerWidth, self.frame.size.height - (self.selectionIndicatorHeight * 4)); 321 | } 322 | 323 | // Fix rect position/size to avoid blurry labels 324 | rect = CGRectMake(ceilf(rect.origin.x), ceilf(rect.origin.y), ceilf(rect.size.width), ceilf(rect.size.height)); 325 | 326 | CATextLayer *titleLayer = [CATextLayer layer]; 327 | titleLayer.frame = rect; 328 | titleLayer.alignmentMode = kCAAlignmentCenter; 329 | if ([UIDevice currentDevice].systemVersion.floatValue < 10.0 ) { 330 | titleLayer.truncationMode = kCATruncationEnd; 331 | } 332 | titleLayer.string = [self attributedTitleAtIndex:idx]; 333 | titleLayer.contentsScale = [[UIScreen mainScreen] scale]; 334 | 335 | [self.scrollView.layer addSublayer:titleLayer]; 336 | 337 | // Vertical Divider 338 | if (self.isVerticalDividerEnabled && idx > 0) { 339 | CALayer *verticalDividerLayer = [CALayer layer]; 340 | verticalDividerLayer.frame = rectDiv; 341 | verticalDividerLayer.backgroundColor = self.verticalDividerColor.CGColor; 342 | 343 | [self.scrollView.layer addSublayer:verticalDividerLayer]; 344 | } 345 | 346 | [self addBackgroundAndBorderLayerWithRect:fullRect]; 347 | }]; 348 | } else if (self.type == HMSegmentedControlTypeImages) { 349 | [self.sectionImages enumerateObjectsUsingBlock:^(id iconImage, NSUInteger idx, BOOL *stop) { 350 | UIImage *icon = iconImage; 351 | CGFloat imageWidth = icon.size.width; 352 | CGFloat imageHeight = icon.size.height; 353 | CGFloat y = roundf(CGRectGetHeight(self.frame) - self.selectionIndicatorHeight) / 2 - imageHeight / 2 + ((self.selectionIndicatorLocation == HMSegmentedControlSelectionIndicatorLocationUp) ? self.selectionIndicatorHeight : 0); 354 | CGFloat x = self.segmentWidth * idx + (self.segmentWidth - imageWidth)/2.0f; 355 | CGRect rect = CGRectMake(x, y, imageWidth, imageHeight); 356 | 357 | CALayer *imageLayer = [CALayer layer]; 358 | imageLayer.frame = rect; 359 | 360 | if (self.selectedSegmentIndex == idx) { 361 | if (self.sectionSelectedImages) { 362 | UIImage *highlightIcon = [self.sectionSelectedImages objectAtIndex:idx]; 363 | imageLayer.contents = (id)highlightIcon.CGImage; 364 | } else { 365 | imageLayer.contents = (id)icon.CGImage; 366 | } 367 | } else { 368 | imageLayer.contents = (id)icon.CGImage; 369 | } 370 | 371 | [self.scrollView.layer addSublayer:imageLayer]; 372 | // Vertical Divider 373 | if (self.isVerticalDividerEnabled && idx>0) { 374 | CALayer *verticalDividerLayer = [CALayer layer]; 375 | verticalDividerLayer.frame = CGRectMake((self.segmentWidth * idx) - (self.verticalDividerWidth / 2), self.selectionIndicatorHeight * 2, self.verticalDividerWidth, self.frame.size.height-(self.selectionIndicatorHeight * 4)); 376 | verticalDividerLayer.backgroundColor = self.verticalDividerColor.CGColor; 377 | 378 | [self.scrollView.layer addSublayer:verticalDividerLayer]; 379 | } 380 | 381 | [self addBackgroundAndBorderLayerWithRect:rect]; 382 | }]; 383 | } else if (self.type == HMSegmentedControlTypeTextImages){ 384 | [self.sectionImages enumerateObjectsUsingBlock:^(id iconImage, NSUInteger idx, BOOL *stop) { 385 | UIImage *icon = iconImage; 386 | CGFloat imageWidth = icon.size.width; 387 | CGFloat imageHeight = icon.size.height; 388 | 389 | CGFloat stringHeight = [self measureTitleAtIndex:idx].height; 390 | CGFloat yOffset = roundf(((CGRectGetHeight(self.frame) - self.selectionIndicatorHeight) / 2) - (stringHeight / 2)); 391 | 392 | CGFloat imageXOffset = self.segmentEdgeInset.left; // Start with edge inset 393 | CGFloat textXOffset = self.segmentEdgeInset.left; 394 | CGFloat textWidth = 0; 395 | 396 | if (self.segmentWidthStyle == HMSegmentedControlSegmentWidthStyleFixed) { 397 | imageXOffset = (self.segmentWidth * idx) + (self.segmentWidth / 2.0f) - (imageWidth / 2.0f); 398 | textXOffset = self.segmentWidth * idx; 399 | textWidth = self.segmentWidth; 400 | } else if (self.segmentWidthStyle == HMSegmentedControlSegmentWidthStyleDynamic) { 401 | // When we are drawing dynamic widths, we need to loop the widths array to calculate the xOffset 402 | CGFloat xOffset = 0; 403 | NSInteger i = 0; 404 | 405 | for (NSNumber *width in self.segmentWidthsArray) { 406 | if (idx == i) { 407 | break; 408 | } 409 | 410 | xOffset = xOffset + [width floatValue]; 411 | i++; 412 | } 413 | 414 | imageXOffset = xOffset + ([self.segmentWidthsArray[idx] floatValue] / 2.0f) - (imageWidth / 2.0f); //(self.segmentWidth / 2.0f) - (imageWidth / 2.0f) 415 | textXOffset = xOffset; 416 | textWidth = [self.segmentWidthsArray[idx] floatValue]; 417 | } 418 | 419 | CGFloat imageYOffset = roundf((CGRectGetHeight(self.frame) - self.selectionIndicatorHeight) / 2.0f); 420 | CGRect imageRect = CGRectMake(imageXOffset, imageYOffset, imageWidth, imageHeight); 421 | CGRect textRect = CGRectMake(textXOffset, yOffset, textWidth, stringHeight); 422 | 423 | // Fix rect position/size to avoid blurry labels 424 | textRect = CGRectMake(ceilf(textRect.origin.x), ceilf(textRect.origin.y), ceilf(textRect.size.width), ceilf(textRect.size.height)); 425 | 426 | CATextLayer *titleLayer = [CATextLayer layer]; 427 | titleLayer.frame = textRect; 428 | titleLayer.alignmentMode = kCAAlignmentCenter; 429 | titleLayer.string = [self attributedTitleAtIndex:idx]; 430 | if ([UIDevice currentDevice].systemVersion.floatValue < 10.0 ) { 431 | titleLayer.truncationMode = kCATruncationEnd; 432 | } 433 | CALayer *imageLayer = [CALayer layer]; 434 | imageLayer.frame = imageRect; 435 | 436 | if (self.selectedSegmentIndex == idx) { 437 | if (self.sectionSelectedImages) { 438 | UIImage *highlightIcon = [self.sectionSelectedImages objectAtIndex:idx]; 439 | imageLayer.contents = (id)highlightIcon.CGImage; 440 | } else { 441 | imageLayer.contents = (id)icon.CGImage; 442 | } 443 | } else { 444 | imageLayer.contents = (id)icon.CGImage; 445 | } 446 | 447 | [self.scrollView.layer addSublayer:imageLayer]; 448 | titleLayer.contentsScale = [[UIScreen mainScreen] scale]; 449 | [self.scrollView.layer addSublayer:titleLayer]; 450 | 451 | [self addBackgroundAndBorderLayerWithRect:imageRect]; 452 | }]; 453 | } 454 | 455 | // Add the selection indicators 456 | if (self.selectedSegmentIndex != HMSegmentedControlNoSegment) { 457 | if (self.selectionStyle == HMSegmentedControlSelectionStyleArrow) { 458 | if (!self.selectionIndicatorArrowLayer.superlayer) { 459 | [self setArrowFrame]; 460 | [self.scrollView.layer addSublayer:self.selectionIndicatorArrowLayer]; 461 | } 462 | } else { 463 | if (!self.selectionIndicatorStripLayer.superlayer) { 464 | self.selectionIndicatorStripLayer.frame = [self frameForSelectionIndicator]; 465 | [self.scrollView.layer addSublayer:self.selectionIndicatorStripLayer]; 466 | 467 | if (self.selectionStyle == HMSegmentedControlSelectionStyleBox && !self.selectionIndicatorBoxLayer.superlayer) { 468 | self.selectionIndicatorBoxLayer.frame = [self frameForFillerSelectionIndicator]; 469 | [self.scrollView.layer insertSublayer:self.selectionIndicatorBoxLayer atIndex:0]; 470 | } 471 | } 472 | } 473 | } 474 | } 475 | 476 | - (void)addBackgroundAndBorderLayerWithRect:(CGRect)fullRect { 477 | // Background layer 478 | CALayer *backgroundLayer = [CALayer layer]; 479 | backgroundLayer.frame = fullRect; 480 | [self.layer insertSublayer:backgroundLayer atIndex:0]; 481 | 482 | // Border layer 483 | if (self.borderType & HMSegmentedControlBorderTypeTop) { 484 | CALayer *borderLayer = [CALayer layer]; 485 | borderLayer.frame = CGRectMake(0, 0, fullRect.size.width, self.borderWidth); 486 | borderLayer.backgroundColor = self.borderColor.CGColor; 487 | [backgroundLayer addSublayer: borderLayer]; 488 | } 489 | if (self.borderType & HMSegmentedControlBorderTypeLeft) { 490 | CALayer *borderLayer = [CALayer layer]; 491 | borderLayer.frame = CGRectMake(0, 0, self.borderWidth, fullRect.size.height); 492 | borderLayer.backgroundColor = self.borderColor.CGColor; 493 | [backgroundLayer addSublayer: borderLayer]; 494 | } 495 | if (self.borderType & HMSegmentedControlBorderTypeBottom) { 496 | CALayer *borderLayer = [CALayer layer]; 497 | borderLayer.frame = CGRectMake(0, fullRect.size.height - self.borderWidth, fullRect.size.width, self.borderWidth); 498 | borderLayer.backgroundColor = self.borderColor.CGColor; 499 | [backgroundLayer addSublayer: borderLayer]; 500 | } 501 | if (self.borderType & HMSegmentedControlBorderTypeRight) { 502 | CALayer *borderLayer = [CALayer layer]; 503 | borderLayer.frame = CGRectMake(fullRect.size.width - self.borderWidth, 0, self.borderWidth, fullRect.size.height); 504 | borderLayer.backgroundColor = self.borderColor.CGColor; 505 | [backgroundLayer addSublayer: borderLayer]; 506 | } 507 | } 508 | 509 | - (void)setArrowFrame { 510 | self.selectionIndicatorArrowLayer.frame = [self frameForSelectionIndicator]; 511 | 512 | self.selectionIndicatorArrowLayer.mask = nil; 513 | 514 | UIBezierPath *arrowPath = [UIBezierPath bezierPath]; 515 | 516 | CGPoint p1 = CGPointZero; 517 | CGPoint p2 = CGPointZero; 518 | CGPoint p3 = CGPointZero; 519 | 520 | if (self.selectionIndicatorLocation == HMSegmentedControlSelectionIndicatorLocationDown) { 521 | p1 = CGPointMake(self.selectionIndicatorArrowLayer.bounds.size.width / 2, 0); 522 | p2 = CGPointMake(0, self.selectionIndicatorArrowLayer.bounds.size.height); 523 | p3 = CGPointMake(self.selectionIndicatorArrowLayer.bounds.size.width, self.selectionIndicatorArrowLayer.bounds.size.height); 524 | } 525 | 526 | if (self.selectionIndicatorLocation == HMSegmentedControlSelectionIndicatorLocationUp) { 527 | p1 = CGPointMake(self.selectionIndicatorArrowLayer.bounds.size.width / 2, self.selectionIndicatorArrowLayer.bounds.size.height); 528 | p2 = CGPointMake(self.selectionIndicatorArrowLayer.bounds.size.width, 0); 529 | p3 = CGPointMake(0, 0); 530 | } 531 | 532 | [arrowPath moveToPoint:p1]; 533 | [arrowPath addLineToPoint:p2]; 534 | [arrowPath addLineToPoint:p3]; 535 | [arrowPath closePath]; 536 | 537 | CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init]; 538 | maskLayer.frame = self.selectionIndicatorArrowLayer.bounds; 539 | maskLayer.path = arrowPath.CGPath; 540 | self.selectionIndicatorArrowLayer.mask = maskLayer; 541 | } 542 | 543 | - (CGRect)frameForSelectionIndicator { 544 | CGFloat indicatorYOffset = 0.0f; 545 | 546 | if (self.selectionIndicatorLocation == HMSegmentedControlSelectionIndicatorLocationDown) { 547 | indicatorYOffset = self.bounds.size.height - self.selectionIndicatorHeight + self.selectionIndicatorEdgeInsets.bottom; 548 | } 549 | 550 | if (self.selectionIndicatorLocation == HMSegmentedControlSelectionIndicatorLocationUp) { 551 | indicatorYOffset = self.selectionIndicatorEdgeInsets.top; 552 | } 553 | 554 | CGFloat sectionWidth = 0.0f; 555 | 556 | if (self.type == HMSegmentedControlTypeText) { 557 | CGFloat stringWidth = [self measureTitleAtIndex:self.selectedSegmentIndex].width; 558 | sectionWidth = stringWidth; 559 | } else if (self.type == HMSegmentedControlTypeImages) { 560 | UIImage *sectionImage = [self.sectionImages objectAtIndex:self.selectedSegmentIndex]; 561 | CGFloat imageWidth = sectionImage.size.width; 562 | sectionWidth = imageWidth; 563 | } else if (self.type == HMSegmentedControlTypeTextImages) { 564 | CGFloat stringWidth = [self measureTitleAtIndex:self.selectedSegmentIndex].width; 565 | UIImage *sectionImage = [self.sectionImages objectAtIndex:self.selectedSegmentIndex]; 566 | CGFloat imageWidth = sectionImage.size.width; 567 | sectionWidth = MAX(stringWidth, imageWidth); 568 | } 569 | 570 | if (self.selectionStyle == HMSegmentedControlSelectionStyleArrow) { 571 | CGFloat widthToEndOfSelectedSegment = (self.segmentWidth * self.selectedSegmentIndex) + self.segmentWidth; 572 | CGFloat widthToStartOfSelectedIndex = (self.segmentWidth * self.selectedSegmentIndex); 573 | 574 | CGFloat x = widthToStartOfSelectedIndex + ((widthToEndOfSelectedSegment - widthToStartOfSelectedIndex) / 2) - (self.selectionIndicatorHeight/2); 575 | return CGRectMake(x - (self.selectionIndicatorHeight / 2), indicatorYOffset, self.selectionIndicatorHeight * 2, self.selectionIndicatorHeight); 576 | } else { 577 | if (self.selectionStyle == HMSegmentedControlSelectionStyleTextWidthStripe && 578 | sectionWidth <= self.segmentWidth && 579 | self.segmentWidthStyle != HMSegmentedControlSegmentWidthStyleDynamic) { 580 | CGFloat widthToEndOfSelectedSegment = (self.segmentWidth * self.selectedSegmentIndex) + self.segmentWidth; 581 | CGFloat widthToStartOfSelectedIndex = (self.segmentWidth * self.selectedSegmentIndex); 582 | 583 | CGFloat x = ((widthToEndOfSelectedSegment - widthToStartOfSelectedIndex) / 2) + (widthToStartOfSelectedIndex - sectionWidth / 2); 584 | return CGRectMake(x + self.selectionIndicatorEdgeInsets.left, indicatorYOffset, sectionWidth - self.selectionIndicatorEdgeInsets.right, self.selectionIndicatorHeight); 585 | } else { 586 | if (self.segmentWidthStyle == HMSegmentedControlSegmentWidthStyleDynamic) { 587 | CGFloat selectedSegmentOffset = 0.0f; 588 | 589 | NSInteger i = 0; 590 | for (NSNumber *width in self.segmentWidthsArray) { 591 | if (self.selectedSegmentIndex == i) 592 | break; 593 | selectedSegmentOffset = selectedSegmentOffset + [width floatValue]; 594 | i++; 595 | } 596 | return CGRectMake(selectedSegmentOffset + self.selectionIndicatorEdgeInsets.left, indicatorYOffset, [[self.segmentWidthsArray objectAtIndex:self.selectedSegmentIndex] floatValue] - self.selectionIndicatorEdgeInsets.right, self.selectionIndicatorHeight + self.selectionIndicatorEdgeInsets.bottom); 597 | } 598 | 599 | return CGRectMake((self.segmentWidth + self.selectionIndicatorEdgeInsets.left) * self.selectedSegmentIndex, indicatorYOffset, self.segmentWidth - self.selectionIndicatorEdgeInsets.right, self.selectionIndicatorHeight); 600 | } 601 | } 602 | } 603 | 604 | - (CGRect)frameForFillerSelectionIndicator { 605 | if (self.segmentWidthStyle == HMSegmentedControlSegmentWidthStyleDynamic) { 606 | CGFloat selectedSegmentOffset = 0.0f; 607 | 608 | NSInteger i = 0; 609 | for (NSNumber *width in self.segmentWidthsArray) { 610 | if (self.selectedSegmentIndex == i) { 611 | break; 612 | } 613 | selectedSegmentOffset = selectedSegmentOffset + [width floatValue]; 614 | 615 | i++; 616 | } 617 | 618 | return CGRectMake(selectedSegmentOffset, 0, [[self.segmentWidthsArray objectAtIndex:self.selectedSegmentIndex] floatValue], CGRectGetHeight(self.frame)); 619 | } 620 | return CGRectMake(self.segmentWidth * self.selectedSegmentIndex, 0, self.segmentWidth, CGRectGetHeight(self.frame)); 621 | } 622 | 623 | - (void)updateSegmentsRects { 624 | self.scrollView.contentInset = UIEdgeInsetsZero; 625 | self.scrollView.frame = CGRectMake(0, 0, CGRectGetWidth(self.frame), CGRectGetHeight(self.frame)); 626 | 627 | if ([self sectionCount] > 0) { 628 | self.segmentWidth = self.frame.size.width / [self sectionCount]; 629 | } 630 | 631 | if (self.type == HMSegmentedControlTypeText && self.segmentWidthStyle == HMSegmentedControlSegmentWidthStyleFixed) { 632 | [self.sectionTitles enumerateObjectsUsingBlock:^(id titleString, NSUInteger idx, BOOL *stop) { 633 | CGFloat stringWidth = [self measureTitleAtIndex:idx].width + self.segmentEdgeInset.left + self.segmentEdgeInset.right; 634 | self.segmentWidth = MAX(stringWidth, self.segmentWidth); 635 | }]; 636 | } else if (self.type == HMSegmentedControlTypeText && self.segmentWidthStyle == HMSegmentedControlSegmentWidthStyleDynamic) { 637 | NSMutableArray *mutableSegmentWidths = [NSMutableArray array]; 638 | 639 | [self.sectionTitles enumerateObjectsUsingBlock:^(id titleString, NSUInteger idx, BOOL *stop) { 640 | CGFloat stringWidth = [self measureTitleAtIndex:idx].width + self.segmentEdgeInset.left + self.segmentEdgeInset.right; 641 | [mutableSegmentWidths addObject:[NSNumber numberWithFloat:stringWidth]]; 642 | }]; 643 | self.segmentWidthsArray = [mutableSegmentWidths copy]; 644 | } else if (self.type == HMSegmentedControlTypeImages) { 645 | for (UIImage *sectionImage in self.sectionImages) { 646 | CGFloat imageWidth = sectionImage.size.width + self.segmentEdgeInset.left + self.segmentEdgeInset.right; 647 | self.segmentWidth = MAX(imageWidth, self.segmentWidth); 648 | } 649 | } else if (self.type == HMSegmentedControlTypeTextImages && self.segmentWidthStyle == HMSegmentedControlSegmentWidthStyleFixed){ 650 | //lets just use the title.. we will assume it is wider then images... 651 | [self.sectionTitles enumerateObjectsUsingBlock:^(id titleString, NSUInteger idx, BOOL *stop) { 652 | CGFloat stringWidth = [self measureTitleAtIndex:idx].width + self.segmentEdgeInset.left + self.segmentEdgeInset.right; 653 | self.segmentWidth = MAX(stringWidth, self.segmentWidth); 654 | }]; 655 | } else if (self.type == HMSegmentedControlTypeTextImages && self.segmentWidthStyle == HMSegmentedControlSegmentWidthStyleDynamic) { 656 | NSMutableArray *mutableSegmentWidths = [NSMutableArray array]; 657 | 658 | int i = 0; 659 | [self.sectionTitles enumerateObjectsUsingBlock:^(id titleString, NSUInteger idx, BOOL *stop) { 660 | CGFloat stringWidth = [self measureTitleAtIndex:idx].width + self.segmentEdgeInset.right; 661 | UIImage *sectionImage = [self.sectionImages objectAtIndex:i]; 662 | CGFloat imageWidth = sectionImage.size.width + self.segmentEdgeInset.left; 663 | 664 | CGFloat combinedWidth = MAX(imageWidth, stringWidth); 665 | 666 | [mutableSegmentWidths addObject:[NSNumber numberWithFloat:combinedWidth]]; 667 | }]; 668 | self.segmentWidthsArray = [mutableSegmentWidths copy]; 669 | } 670 | 671 | self.scrollView.scrollEnabled = self.isUserDraggable; 672 | self.scrollView.contentSize = CGSizeMake([self totalSegmentedControlWidth], self.frame.size.height); 673 | } 674 | 675 | - (NSUInteger)sectionCount { 676 | if (self.type == HMSegmentedControlTypeText) { 677 | return self.sectionTitles.count; 678 | } else if (self.type == HMSegmentedControlTypeImages || 679 | self.type == HMSegmentedControlTypeTextImages) { 680 | return self.sectionImages.count; 681 | } 682 | 683 | return 0; 684 | } 685 | 686 | - (void)willMoveToSuperview:(UIView *)newSuperview { 687 | // Control is being removed 688 | if (newSuperview == nil) 689 | return; 690 | 691 | if (self.sectionTitles || self.sectionImages) { 692 | [self updateSegmentsRects]; 693 | } 694 | } 695 | 696 | #pragma mark - Touch 697 | 698 | - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { 699 | UITouch *touch = [touches anyObject]; 700 | CGPoint touchLocation = [touch locationInView:self]; 701 | 702 | CGRect enlargeRect = CGRectMake(self.bounds.origin.x - self.enlargeEdgeInset.left, 703 | self.bounds.origin.y - self.enlargeEdgeInset.top, 704 | self.bounds.size.width + self.enlargeEdgeInset.left + self.enlargeEdgeInset.right, 705 | self.bounds.size.height + self.enlargeEdgeInset.top + self.enlargeEdgeInset.bottom); 706 | 707 | if (CGRectContainsPoint(enlargeRect, touchLocation)) { 708 | NSInteger segment = 0; 709 | if (self.segmentWidthStyle == HMSegmentedControlSegmentWidthStyleFixed) { 710 | segment = (touchLocation.x + self.scrollView.contentOffset.x) / self.segmentWidth; 711 | } else if (self.segmentWidthStyle == HMSegmentedControlSegmentWidthStyleDynamic) { 712 | // To know which segment the user touched, we need to loop over the widths and substract it from the x position. 713 | CGFloat widthLeft = (touchLocation.x + self.scrollView.contentOffset.x); 714 | for (NSNumber *width in self.segmentWidthsArray) { 715 | widthLeft = widthLeft - [width floatValue]; 716 | 717 | // When we don't have any width left to substract, we have the segment index. 718 | if (widthLeft <= 0) 719 | break; 720 | 721 | segment++; 722 | } 723 | } 724 | 725 | NSUInteger sectionsCount = 0; 726 | 727 | if (self.type == HMSegmentedControlTypeImages) { 728 | sectionsCount = [self.sectionImages count]; 729 | } else if (self.type == HMSegmentedControlTypeTextImages || self.type == HMSegmentedControlTypeText) { 730 | sectionsCount = [self.sectionTitles count]; 731 | } 732 | 733 | if (segment != self.selectedSegmentIndex && segment < sectionsCount) { 734 | // Check if we have to do anything with the touch event 735 | if (self.isTouchEnabled) 736 | [self setSelectedSegmentIndex:segment animated:self.shouldAnimateUserSelection notify:YES]; 737 | } 738 | } 739 | } 740 | 741 | #pragma mark - Scrolling 742 | 743 | - (CGFloat)totalSegmentedControlWidth { 744 | if (self.type == HMSegmentedControlTypeText && self.segmentWidthStyle == HMSegmentedControlSegmentWidthStyleFixed) { 745 | return self.sectionTitles.count * self.segmentWidth; 746 | } else if (self.segmentWidthStyle == HMSegmentedControlSegmentWidthStyleDynamic) { 747 | return [[self.segmentWidthsArray valueForKeyPath:@"@sum.self"] floatValue]; 748 | } else { 749 | return self.sectionImages.count * self.segmentWidth; 750 | } 751 | } 752 | 753 | - (void)scrollToSelectedSegmentIndex:(BOOL)animated { 754 | CGRect rectForSelectedIndex = CGRectZero; 755 | CGFloat selectedSegmentOffset = 0; 756 | if (self.segmentWidthStyle == HMSegmentedControlSegmentWidthStyleFixed) { 757 | rectForSelectedIndex = CGRectMake(self.segmentWidth * self.selectedSegmentIndex, 758 | 0, 759 | self.segmentWidth, 760 | self.frame.size.height); 761 | 762 | selectedSegmentOffset = (CGRectGetWidth(self.frame) / 2) - (self.segmentWidth / 2); 763 | } else { 764 | NSInteger i = 0; 765 | CGFloat offsetter = 0; 766 | for (NSNumber *width in self.segmentWidthsArray) { 767 | if (self.selectedSegmentIndex == i) 768 | break; 769 | offsetter = offsetter + [width floatValue]; 770 | i++; 771 | } 772 | 773 | rectForSelectedIndex = CGRectMake(offsetter, 774 | 0, 775 | [[self.segmentWidthsArray objectAtIndex:self.selectedSegmentIndex] floatValue], 776 | self.frame.size.height); 777 | 778 | selectedSegmentOffset = (CGRectGetWidth(self.frame) / 2) - ([[self.segmentWidthsArray objectAtIndex:self.selectedSegmentIndex] floatValue] / 2); 779 | } 780 | 781 | 782 | CGRect rectToScrollTo = rectForSelectedIndex; 783 | rectToScrollTo.origin.x -= selectedSegmentOffset; 784 | rectToScrollTo.size.width += selectedSegmentOffset * 2; 785 | [self.scrollView scrollRectToVisible:rectToScrollTo animated:animated]; 786 | } 787 | 788 | #pragma mark - Index Change 789 | 790 | - (void)setSelectedSegmentIndex:(NSInteger)index { 791 | [self setSelectedSegmentIndex:index animated:NO notify:NO]; 792 | } 793 | 794 | - (void)setSelectedSegmentIndex:(NSUInteger)index animated:(BOOL)animated { 795 | [self setSelectedSegmentIndex:index animated:animated notify:NO]; 796 | } 797 | 798 | - (void)setSelectedSegmentIndex:(NSUInteger)index animated:(BOOL)animated notify:(BOOL)notify { 799 | _selectedSegmentIndex = index; 800 | [self setNeedsDisplay]; 801 | 802 | if (index == HMSegmentedControlNoSegment) { 803 | [self.selectionIndicatorArrowLayer removeFromSuperlayer]; 804 | [self.selectionIndicatorStripLayer removeFromSuperlayer]; 805 | [self.selectionIndicatorBoxLayer removeFromSuperlayer]; 806 | } else { 807 | [self scrollToSelectedSegmentIndex:animated]; 808 | 809 | if (animated) { 810 | // If the selected segment layer is not added to the super layer, that means no 811 | // index is currently selected, so add the layer then move it to the new 812 | // segment index without animating. 813 | if(self.selectionStyle == HMSegmentedControlSelectionStyleArrow) { 814 | if ([self.selectionIndicatorArrowLayer superlayer] == nil) { 815 | [self.scrollView.layer addSublayer:self.selectionIndicatorArrowLayer]; 816 | 817 | [self setSelectedSegmentIndex:index animated:NO notify:YES]; 818 | return; 819 | } 820 | }else { 821 | if ([self.selectionIndicatorStripLayer superlayer] == nil) { 822 | [self.scrollView.layer addSublayer:self.selectionIndicatorStripLayer]; 823 | 824 | if (self.selectionStyle == HMSegmentedControlSelectionStyleBox && [self.selectionIndicatorBoxLayer superlayer] == nil) 825 | [self.scrollView.layer insertSublayer:self.selectionIndicatorBoxLayer atIndex:0]; 826 | 827 | [self setSelectedSegmentIndex:index animated:NO notify:YES]; 828 | return; 829 | } 830 | } 831 | 832 | if (notify) 833 | [self notifyForSegmentChangeToIndex:index]; 834 | 835 | // Restore CALayer animations 836 | self.selectionIndicatorArrowLayer.actions = nil; 837 | self.selectionIndicatorStripLayer.actions = nil; 838 | self.selectionIndicatorBoxLayer.actions = nil; 839 | 840 | // Animate to new position 841 | [CATransaction begin]; 842 | [CATransaction setAnimationDuration:0.15f]; 843 | [CATransaction setAnimationTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]]; 844 | [self setArrowFrame]; 845 | self.selectionIndicatorBoxLayer.frame = [self frameForSelectionIndicator]; 846 | self.selectionIndicatorStripLayer.frame = [self frameForSelectionIndicator]; 847 | self.selectionIndicatorBoxLayer.frame = [self frameForFillerSelectionIndicator]; 848 | [CATransaction commit]; 849 | } else { 850 | // Disable CALayer animations 851 | NSMutableDictionary *newActions = [[NSMutableDictionary alloc] initWithObjectsAndKeys:[NSNull null], @"position", [NSNull null], @"bounds", nil]; 852 | self.selectionIndicatorArrowLayer.actions = newActions; 853 | [self setArrowFrame]; 854 | 855 | self.selectionIndicatorStripLayer.actions = newActions; 856 | self.selectionIndicatorStripLayer.frame = [self frameForSelectionIndicator]; 857 | 858 | self.selectionIndicatorBoxLayer.actions = newActions; 859 | self.selectionIndicatorBoxLayer.frame = [self frameForFillerSelectionIndicator]; 860 | 861 | if (notify) 862 | [self notifyForSegmentChangeToIndex:index]; 863 | } 864 | } 865 | } 866 | 867 | - (void)notifyForSegmentChangeToIndex:(NSInteger)index { 868 | if (self.superview) 869 | [self sendActionsForControlEvents:UIControlEventValueChanged]; 870 | 871 | if (self.indexChangeBlock) 872 | self.indexChangeBlock(index); 873 | } 874 | 875 | #pragma mark - Styling Support 876 | 877 | - (NSDictionary *)resultingTitleTextAttributes { 878 | NSDictionary *defaults = @{ 879 | NSFontAttributeName : [UIFont systemFontOfSize:19.0f], 880 | NSForegroundColorAttributeName : [UIColor blackColor], 881 | }; 882 | 883 | NSMutableDictionary *resultingAttrs = [NSMutableDictionary dictionaryWithDictionary:defaults]; 884 | 885 | if (self.titleTextAttributes) { 886 | [resultingAttrs addEntriesFromDictionary:self.titleTextAttributes]; 887 | } 888 | 889 | return [resultingAttrs copy]; 890 | } 891 | 892 | - (NSDictionary *)resultingSelectedTitleTextAttributes { 893 | NSMutableDictionary *resultingAttrs = [NSMutableDictionary dictionaryWithDictionary:[self resultingTitleTextAttributes]]; 894 | 895 | if (self.selectedTitleTextAttributes) { 896 | [resultingAttrs addEntriesFromDictionary:self.selectedTitleTextAttributes]; 897 | } 898 | 899 | return [resultingAttrs copy]; 900 | } 901 | 902 | @end 903 | --------------------------------------------------------------------------------