├── README.md ├── .DS_Store ├── LXSegmentControl ├── Assets.xcassets │ ├── Contents.json │ ├── back.imageset │ │ ├── back@2x.png │ │ ├── back@3x.png │ │ └── Contents.json │ └── AppIcon.appiconset │ │ └── Contents.json ├── Lib │ ├── LXPageTab │ │ ├── 三角形@2x.png │ │ ├── LXPageTabItemLable.h │ │ ├── LXPageTabItemLable.m │ │ ├── LXPageTabView.h │ │ └── LXPageTabView.m │ └── XXPageTab │ │ ├── XXPageTabItemLable.h │ │ ├── XXPageTabItemLable.m │ │ ├── XXPageTabView.h │ │ └── XXPageTabView.m ├── ViewController.h ├── Category │ ├── UIImage+LX.h │ ├── UIColor+LX.h │ ├── UIImage+LX.m │ └── UIColor+LX.m ├── LXSegmentTitleViewController.h ├── LXSegmentType_0ViewController.h ├── LXSegmentType_1ViewController.h ├── AppDelegate.h ├── main.m ├── LXSegmentTitleViewController.m ├── ViewController.m ├── Info.plist ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard ├── AppDelegate.m ├── LXSegmentType_0ViewController.m ├── LX_Prefix.pch └── LXSegmentType_1ViewController.m ├── LXSegmentControl.xcodeproj ├── xcuserdata │ └── zlx.xcuserdatad │ │ ├── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ │ └── xcschemes │ │ └── xcschememanagement.plist ├── project.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcuserdata │ │ └── zlx.xcuserdatad │ │ │ ├── UserInterfaceState.xcuserstate │ │ │ └── IDEFindNavigatorScopes.plist │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist └── project.pbxproj ├── LXSegmentControlTests ├── Info.plist └── LXSegmentControlTests.m └── LXSegmentControlUITests ├── Info.plist └── LXSegmentControlUITests.m /README.md: -------------------------------------------------------------------------------- 1 | # LXPageTabDemo 2 | 3 | 页面切换,Segment控制 4 | -------------------------------------------------------------------------------- /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nick8brown/LXPageTabDemo/HEAD/.DS_Store -------------------------------------------------------------------------------- /LXSegmentControl/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /LXSegmentControl/Lib/LXPageTab/三角形@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nick8brown/LXPageTabDemo/HEAD/LXSegmentControl/Lib/LXPageTab/三角形@2x.png -------------------------------------------------------------------------------- /LXSegmentControl/Assets.xcassets/back.imageset/back@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nick8brown/LXPageTabDemo/HEAD/LXSegmentControl/Assets.xcassets/back.imageset/back@2x.png -------------------------------------------------------------------------------- /LXSegmentControl/Assets.xcassets/back.imageset/back@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nick8brown/LXPageTabDemo/HEAD/LXSegmentControl/Assets.xcassets/back.imageset/back@3x.png -------------------------------------------------------------------------------- /LXSegmentControl.xcodeproj/xcuserdata/zlx.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /LXSegmentControl.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /LXSegmentControl.xcodeproj/project.xcworkspace/xcuserdata/zlx.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nick8brown/LXPageTabDemo/HEAD/LXSegmentControl.xcodeproj/project.xcworkspace/xcuserdata/zlx.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /LXSegmentControl.xcodeproj/project.xcworkspace/xcuserdata/zlx.xcuserdatad/IDEFindNavigatorScopes.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /LXSegmentControl/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // LXSegmentControl 4 | // 5 | // Created by LX Zeng on 2018/12/3. 6 | // Copyright © 2018 https://github.com/nick8brown All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /LXSegmentControl.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /LXSegmentControl/Category/UIImage+LX.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+LX.h 3 | // HZGAPP 4 | // 5 | // Created by LX Zeng on 16/8/25. 6 | // Copyright © 2016 https://github.com/nick8brown All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UIImage (LX) 12 | 13 | + (UIImage *)getImageWithColor:(UIColor *)color; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /LXSegmentControl/Category/UIColor+LX.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIColor+LX.h 3 | // HZGAPP 4 | // 5 | // Created by LX Zeng on 16/7/4. 6 | // Copyright © 2016 https://github.com/nick8brown All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UIColor (LX) 12 | 13 | + (UIColor *)colorWithHexString:(NSString *)color; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /LXSegmentControl/LXSegmentTitleViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // LXSegmentTitleViewController.h 3 | // LXSegmentControl 4 | // 5 | // Created by LX Zeng on 2018/12/3. 6 | // Copyright © 2018 https://github.com/nick8brown All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface LXSegmentTitleViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /LXSegmentControl/LXSegmentType_0ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // LXSegmentType_0ViewController.h 3 | // LXSegmentControl 4 | // 5 | // Created by LX Zeng on 2018/12/3. 6 | // Copyright © 2018 https://github.com/nick8brown All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface LXSegmentType_0ViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /LXSegmentControl/LXSegmentType_1ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // LXSegmentType_1ViewController.h 3 | // LXSegmentControl 4 | // 5 | // Created by LX Zeng on 2018/12/3. 6 | // Copyright © 2018 https://github.com/nick8brown All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface LXSegmentType_1ViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /LXSegmentControl/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // LXSegmentControl 4 | // 5 | // Created by LX Zeng on 2018/12/3. 6 | // Copyright © 2018 https://github.com/nick8brown All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /LXSegmentControl/Lib/XXPageTab/XXPageTabItemLable.h: -------------------------------------------------------------------------------- 1 | // 2 | // XXPageTabItemLable.h 3 | // XXPageTabDemo 4 | // 5 | // Created by HJTXX on 2017/3/3. 6 | // Copyright © 2017年 HJTXX. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface XXPageTabItemLable : UILabel 12 | 13 | @property (nonatomic, strong) UIColor *fillColor; //填充色 14 | @property (nonatomic, assign) CGFloat process; //填充占比 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /LXSegmentControl/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // LXSegmentControl 4 | // 5 | // Created by LX Zeng on 2018/12/3. 6 | // Copyright © 2018 https://github.com/nick8brown All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /LXSegmentControl/Lib/LXPageTab/LXPageTabItemLable.h: -------------------------------------------------------------------------------- 1 | // 2 | // LXPageTabItemLable.h 3 | // XXPageTabDemo 4 | // 5 | // Created by LX Zeng on 2017/3/3. 6 | // Copyright © 2017年 https://github.com/nick8brown All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface LXPageTabItemLable : UILabel 12 | 13 | @property (nonatomic, strong) UIColor *fillColor; //填充色 14 | @property (nonatomic, assign) CGFloat process; //填充占比 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /LXSegmentControl.xcodeproj/xcuserdata/zlx.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | LXSegmentControl.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /LXSegmentControl/Assets.xcassets/back.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "back@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "back@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /LXSegmentControl/LXSegmentTitleViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // LXSegmentTitleViewController.m 3 | // LXSegmentControl 4 | // 5 | // Created by LX Zeng on 2018/12/3. 6 | // Copyright © 2018 https://github.com/nick8brown All rights reserved. 7 | // 8 | 9 | #import "LXSegmentTitleViewController.h" 10 | 11 | @interface LXSegmentTitleViewController () 12 | 13 | @end 14 | 15 | @implementation LXSegmentTitleViewController 16 | 17 | #pragma mark - life cycle 18 | - (void)viewDidLoad { 19 | [super viewDidLoad]; 20 | } 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /LXSegmentControl/Lib/XXPageTab/XXPageTabItemLable.m: -------------------------------------------------------------------------------- 1 | // 2 | // XXPageTabItemLable.m 3 | // XXPageTabDemo 4 | // 5 | // Created by HJTXX on 2017/3/3. 6 | // Copyright © 2017年 HJTXX. All rights reserved. 7 | // 8 | 9 | #import "XXPageTabItemLable.h" 10 | 11 | @implementation XXPageTabItemLable 12 | 13 | - (void)drawRect:(CGRect)rect { 14 | [super drawRect:rect]; 15 | 16 | if([_fillColor isKindOfClass:[UIColor class]]) { 17 | [_fillColor setFill]; 18 | UIRectFillUsingBlendMode(CGRectMake(rect.origin.x, rect.origin.y, rect.size.width*_process, rect.size.height), kCGBlendModeSourceIn); 19 | } 20 | } 21 | 22 | - (void)setProcess:(CGFloat)process { 23 | _process = process; 24 | [self setNeedsDisplay]; 25 | } 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /LXSegmentControl/Category/UIImage+LX.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+LX.m 3 | // HZGAPP 4 | // 5 | // Created by LX Zeng on 16/8/25. 6 | // Copyright © 2016 https://github.com/nick8brown All rights reserved. 7 | // 8 | 9 | #import "UIImage+LX.h" 10 | 11 | @implementation UIImage (LX) 12 | 13 | + (UIImage *)getImageWithColor:(UIColor *)color { 14 | CGRect rect = CGRectMake(0.0f, 0.0f, 1.0f, 1.0f); 15 | UIGraphicsBeginImageContext(rect.size); 16 | CGContextRef context = UIGraphicsGetCurrentContext(); 17 | CGContextSetFillColorWithColor(context, [color CGColor]); 18 | CGContextFillRect(context, rect); 19 | UIImage *theImage = UIGraphicsGetImageFromCurrentImageContext(); 20 | UIGraphicsEndImageContext(); 21 | return theImage; 22 | } 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /LXSegmentControl/Lib/LXPageTab/LXPageTabItemLable.m: -------------------------------------------------------------------------------- 1 | // 2 | // LXPageTabItemLable.m 3 | // XXPageTabDemo 4 | // 5 | // Created by LX Zeng on 2017/3/3. 6 | // Copyright © 2017年 https://github.com/nick8brown All rights reserved. 7 | // 8 | 9 | #import "LXPageTabItemLable.h" 10 | 11 | @implementation LXPageTabItemLable 12 | 13 | - (void)drawRect:(CGRect)rect { 14 | [super drawRect:rect]; 15 | 16 | if([_fillColor isKindOfClass:[UIColor class]]) { 17 | [_fillColor setFill]; 18 | UIRectFillUsingBlendMode(CGRectMake(rect.origin.x, rect.origin.y, rect.size.width*_process, rect.size.height), kCGBlendModeSourceIn); 19 | } 20 | } 21 | 22 | - (void)setProcess:(CGFloat)process { 23 | _process = process; 24 | [self setNeedsDisplay]; 25 | } 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /LXSegmentControlTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /LXSegmentControlUITests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /LXSegmentControlTests/LXSegmentControlTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // LXSegmentControlTests.m 3 | // LXSegmentControlTests 4 | // 5 | // Created by LX Zeng on 2018/12/3. 6 | // Copyright © 2018 https://github.com/nick8brown All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface LXSegmentControlTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation LXSegmentControlTests 16 | 17 | - (void)setUp { 18 | // Put setup code here. This method is called before the invocation of each test method in the class. 19 | } 20 | 21 | - (void)tearDown { 22 | // Put teardown code here. This method is called after the invocation of each test method in the class. 23 | } 24 | 25 | - (void)testExample { 26 | // This is an example of a functional test case. 27 | // Use XCTAssert and related functions to verify your tests produce the correct results. 28 | } 29 | 30 | - (void)testPerformanceExample { 31 | // This is an example of a performance test case. 32 | [self measureBlock:^{ 33 | // Put the code you want to measure the time of here. 34 | }]; 35 | } 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /LXSegmentControlUITests/LXSegmentControlUITests.m: -------------------------------------------------------------------------------- 1 | // 2 | // LXSegmentControlUITests.m 3 | // LXSegmentControlUITests 4 | // 5 | // Created by LX Zeng on 2018/12/3. 6 | // Copyright © 2018 https://github.com/nick8brown All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface LXSegmentControlUITests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation LXSegmentControlUITests 16 | 17 | - (void)setUp { 18 | // Put setup code here. This method is called before the invocation of each test method in the class. 19 | 20 | // In UI tests it is usually best to stop immediately when a failure occurs. 21 | self.continueAfterFailure = NO; 22 | 23 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. 24 | [[[XCUIApplication alloc] init] launch]; 25 | 26 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 27 | } 28 | 29 | - (void)tearDown { 30 | // Put teardown code here. This method is called after the invocation of each test method in the class. 31 | } 32 | 33 | - (void)testExample { 34 | // Use recording to get started writing UI tests. 35 | // Use XCTAssert and related functions to verify your tests produce the correct results. 36 | } 37 | 38 | @end 39 | -------------------------------------------------------------------------------- /LXSegmentControl/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // LXSegmentControl 4 | // 5 | // Created by LX Zeng on 2018/12/3. 6 | // Copyright © 2018 https://github.com/nick8brown All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | 11 | #import "LXSegmentType_0ViewController.h" 12 | #import "LXSegmentType_1ViewController.h" 13 | 14 | @interface ViewController () 15 | 16 | @end 17 | 18 | @implementation ViewController 19 | 20 | #pragma mark - life cycle 21 | - (void)viewDidLoad { 22 | [super viewDidLoad]; 23 | 24 | self.title = @"自定义SegmentControl"; 25 | 26 | // 初始化导航栏 27 | [self setupNavBar]; 28 | } 29 | 30 | #pragma mark - 初始化导航栏 31 | - (void)setupNavBar { 32 | [self.navigationController.navigationBar setTitleTextAttributes:@{NSFontAttributeName:AppFont(18), NSForegroundColorAttributeName:SYS_White_Color}]; 33 | [self.navigationController.navigationBar setBackgroundImage:[UIImage getImageWithColor:AppHTMLColor(@"4bccbc")] forBarMetrics:UIBarMetricsDefault]; 34 | } 35 | 36 | #pragma mark - 样式一 37 | - (IBAction)type_0BtnClick:(UIButton *)sender { 38 | LXSegmentType_0ViewController *segmentType_0VC = [[LXSegmentType_0ViewController alloc] init]; 39 | segmentType_0VC.title = @"样式一"; 40 | [self.navigationController pushViewController:segmentType_0VC animated:YES]; 41 | } 42 | 43 | #pragma mark - 样式二 44 | - (IBAction)type_1BtnClick:(UIButton *)sender { 45 | LXSegmentType_1ViewController *segmentType_1VC = [[LXSegmentType_1ViewController alloc] init]; 46 | segmentType_1VC.title = @"样式二"; 47 | [self.navigationController pushViewController:segmentType_1VC animated:YES]; 48 | } 49 | 50 | @end 51 | -------------------------------------------------------------------------------- /LXSegmentControl/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | UIViewControllerBasedStatusBarAppearance 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /LXSegmentControl/Category/UIColor+LX.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIColor+LX.m 3 | // HZGAPP 4 | // 5 | // Created by LX Zeng on 16/7/4. 6 | // Copyright © 2016 https://github.com/nick8brown All rights reserved. 7 | // 8 | 9 | #import "UIColor+LX.h" 10 | 11 | @implementation UIColor (LX) 12 | 13 | + (UIColor *)colorWithHexString:(NSString *)color { 14 | NSString *cString = [[color stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] uppercaseString]; 15 | 16 | // String should be 6 or 8 characters 17 | if ([cString length] < 6) { 18 | return [UIColor clearColor]; 19 | } 20 | 21 | // strip 0X if it appears 22 | if ([cString hasPrefix:@"0X"]) 23 | cString = [cString substringFromIndex:2]; 24 | if ([cString hasPrefix:@"#"]) 25 | cString = [cString substringFromIndex:1]; 26 | if ([cString length] != 6) 27 | return [UIColor clearColor]; 28 | 29 | // Separate into r, g, b substrings 30 | NSRange range; 31 | range.location = 0; 32 | range.length = 2; 33 | 34 | //r 35 | NSString *rString = [cString substringWithRange:range]; 36 | 37 | //g 38 | range.location = 2; 39 | NSString *gString = [cString substringWithRange:range]; 40 | 41 | //b 42 | range.location = 4; 43 | NSString *bString = [cString substringWithRange:range]; 44 | 45 | // Scan values 46 | unsigned int r, g, b; 47 | [[NSScanner scannerWithString:rString] scanHexInt:&r]; 48 | [[NSScanner scannerWithString:gString] scanHexInt:&g]; 49 | [[NSScanner scannerWithString:bString] scanHexInt:&b]; 50 | 51 | return [UIColor colorWithRed:((float) r / 255.0f) green:((float) g / 255.0f) blue:((float) b / 255.0f) alpha:1.0f]; 52 | } 53 | 54 | @end 55 | -------------------------------------------------------------------------------- /LXSegmentControl/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /LXSegmentControl/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /LXSegmentControl/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // LXSegmentControl 4 | // 5 | // Created by LX Zeng on 2018/12/3. 6 | // Copyright © 2018 https://github.com/nick8brown All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | 20 | self.window.backgroundColor = SYS_White_Color; 21 | [UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleLightContent; 22 | 23 | return YES; 24 | } 25 | 26 | 27 | - (void)applicationWillResignActive:(UIApplication *)application { 28 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 29 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 30 | } 31 | 32 | 33 | - (void)applicationDidEnterBackground:(UIApplication *)application { 34 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 35 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 36 | } 37 | 38 | 39 | - (void)applicationWillEnterForeground:(UIApplication *)application { 40 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 41 | } 42 | 43 | 44 | - (void)applicationDidBecomeActive:(UIApplication *)application { 45 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 46 | } 47 | 48 | 49 | - (void)applicationWillTerminate:(UIApplication *)application { 50 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 51 | } 52 | 53 | 54 | @end 55 | -------------------------------------------------------------------------------- /LXSegmentControl/Lib/XXPageTab/XXPageTabView.h: -------------------------------------------------------------------------------- 1 | // 2 | // XXPageTabView.h 3 | // XXPageTabDemo 4 | // 5 | // Created by HJTXX on 2017/2/27. 6 | // Copyright © 2017年 HJTXX. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "XXPageTabItemLable.h" 11 | 12 | typedef NS_ENUM(NSInteger, XXPageTabTitleStyle) { 13 | XXPageTabTitleStyleDefault, //正常 14 | XXPageTabTitleStyleGradient, //渐变 15 | XXPageTabTitleStyleBlend //填充 16 | }; 17 | 18 | typedef NS_ENUM(NSInteger, XXPageTabIndicatorStyle) { 19 | XXPageTabIndicatorStyleDefault, //正常,自定义宽度 20 | XXPageTabIndicatorStyleFollowText, //跟随文本长度变化 21 | XXPageTabIndicatorStyleStretch //拉伸 22 | }; 23 | 24 | @protocol XXPageTabViewDelegate 25 | @optional 26 | /*切换完成代理方法*/ 27 | - (void)pageTabViewDidEndChange; 28 | @end 29 | 30 | @interface XXPageTabView : UIView 31 | 32 | @property (nonatomic, weak) id delegate; 33 | 34 | /*设置当前选择项(无动画效果)*/ 35 | @property (nonatomic, assign) NSInteger selectedTabIndex; 36 | /*一页展示最多的item个数,如果比item总数少,按照item总数计算*/ 37 | @property (nonatomic, assign) NSInteger maxNumberOfPageItems; 38 | /*tab size,默认(self.width, 38.0)*/ 39 | @property (nonatomic, assign) CGSize tabSize; 40 | /*item的字体大小*/ 41 | @property (nonatomic, strong) UIFont *tabItemFont; 42 | /*未选择颜色*/ 43 | @property (nonatomic, strong) UIColor *unSelectedColor; 44 | /*当前选中颜色*/ 45 | @property (nonatomic, strong) UIColor *selectedColor; 46 | /*tab背景色,默认white*/ 47 | @property (nonatomic, strong) UIColor *tabBackgroundColor; 48 | /*body背景色,默认white*/ 49 | @property (nonatomic, strong) UIColor *bodyBackgroundColor; 50 | /*是否打开body的边界弹动效果*/ 51 | @property (nonatomic, assign) BOOL bodyBounces; 52 | 53 | /*Title效果设置*/ 54 | @property (nonatomic, assign) XXPageTabTitleStyle titleStyle; 55 | /*字体渐变,未选择的item的scale,默认是0.8(0~1)。仅XXPageTabTitleStyleScale生效*/ 56 | @property (nonatomic, assign) CGFloat minScale; 57 | 58 | /*Indicator效果设置*/ 59 | @property (nonatomic, assign) XXPageTabIndicatorStyle indicatorStyle; 60 | /*下标高度,默认是2.0*/ 61 | @property (nonatomic, assign) CGFloat indicatorHeight; 62 | /*下标宽度,默认是0。XXPageTabIndicatorStyleFollowText时无效*/ 63 | @property (nonatomic, assign) CGFloat indicatorWidth; 64 | 65 | - (instancetype)initWithChildControllers:(NSArray *)childControllers 66 | childTitles:(NSArray *)childTitles; 67 | 68 | @end 69 | -------------------------------------------------------------------------------- /LXSegmentControl/Lib/LXPageTab/LXPageTabView.h: -------------------------------------------------------------------------------- 1 | // 2 | // LXPageTabView.h 3 | // XXPageTabDemo 4 | // 5 | // Created by LX Zeng on 2017/2/27. 6 | // Copyright © 2017年 https://github.com/nick8brown All rights reserved. 7 | // 8 | 9 | #import 10 | #import "LXPageTabItemLable.h" 11 | 12 | typedef NS_ENUM(NSInteger, LXPageTabTitleStyle) { 13 | LXPageTabTitleStyleDefault, //正常 14 | LXPageTabTitleStyleGradient, //渐变 15 | LXPageTabTitleStyleBlend //填充 16 | }; 17 | 18 | typedef NS_ENUM(NSInteger, LXPageTabIndicatorStyle) { 19 | LXPageTabIndicatorStyleDefault, //正常,自定义宽度 20 | LXPageTabIndicatorStyleFollowText, //跟随文本长度变化 21 | LXPageTabIndicatorStyleStretch //拉伸 22 | }; 23 | 24 | @protocol LXPageTabViewDelegate 25 | @optional 26 | /*切换完成代理方法*/ 27 | - (void)pageTabViewDidEndChange; 28 | @end 29 | 30 | @interface LXPageTabView : UIView 31 | 32 | @property (nonatomic, weak) id delegate; 33 | 34 | /*设置当前选择项(无动画效果)*/ 35 | @property (nonatomic, assign) NSInteger selectedTabIndex; 36 | /*一页展示最多的item个数,如果比item总数少,按照item总数计算*/ 37 | @property (nonatomic, assign) NSInteger maxNumberOfPageItems; 38 | /*tab size,默认(self.width, 38.0)*/ 39 | @property (nonatomic, assign) CGSize tabSize; 40 | /*item的字体大小*/ 41 | @property (nonatomic, strong) UIFont *tabItemFont; 42 | /*未选择颜色*/ 43 | @property (nonatomic, strong) UIColor *unSelectedColor; 44 | /*当前选中颜色*/ 45 | @property (nonatomic, strong) UIColor *selectedColor; 46 | /*tab背景色,默认white*/ 47 | @property (nonatomic, strong) UIColor *tabBackgroundColor; 48 | /*body背景色,默认white*/ 49 | @property (nonatomic, strong) UIColor *bodyBackgroundColor; 50 | /*是否打开body的边界弹动效果*/ 51 | @property (nonatomic, assign) BOOL bodyBounces; 52 | 53 | /*Title效果设置*/ 54 | @property (nonatomic, assign) LXPageTabTitleStyle titleStyle; 55 | /*字体渐变,未选择的item的scale,默认是0.8(0~1)。仅LXPageTabTitleStyleScale生效*/ 56 | @property (nonatomic, assign) CGFloat minScale; 57 | 58 | /*Indicator效果设置*/ 59 | @property (nonatomic, assign) LXPageTabIndicatorStyle indicatorStyle; 60 | /*下标高度,默认是2.0*/ 61 | @property (nonatomic, assign) CGFloat indicatorHeight; 62 | /*下标宽度,默认是0。LXPageTabIndicatorStyleFollowText时无效*/ 63 | @property (nonatomic, assign) CGFloat indicatorWidth; 64 | 65 | - (instancetype)initWithChildControllers:(NSArray *)childControllers 66 | childTitles:(NSArray *)childTitles; 67 | 68 | @end 69 | -------------------------------------------------------------------------------- /LXSegmentControl/LXSegmentType_0ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // LXSegmentType_0ViewController.m 3 | // LXSegmentControl 4 | // 5 | // Created by LX Zeng on 2018/12/3. 6 | // Copyright © 2018 https://github.com/nick8brown All rights reserved. 7 | // 8 | 9 | #import "LXSegmentType_0ViewController.h" 10 | 11 | #import "LXSegmentTitleViewController.h" 12 | 13 | #import "XXPageTabView.h" 14 | 15 | @interface LXSegmentType_0ViewController () 16 | 17 | { 18 | XXPageTabView *_pageTabView; 19 | } 20 | 21 | @end 22 | 23 | @implementation LXSegmentType_0ViewController 24 | 25 | #pragma mark - life cycle 26 | - (void)viewDidLoad { 27 | [super viewDidLoad]; 28 | 29 | // 初始化导航栏 30 | [self setupNavBar]; 31 | 32 | // 初始化segmentType_0View 33 | [self setupSegmentType_0View]; 34 | } 35 | 36 | #pragma mark - 初始化导航栏 37 | - (void)setupNavBar { 38 | // leftBarButtonItem(返回) 39 | UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom]; 40 | btn.frame = CGRectMake(0, 0, 20, 20); 41 | [btn setImage:ImageNamed(@"back") forState:UIControlStateNormal]; 42 | [btn addTarget:self action:@selector(returnBtnClick:) forControlEvents:UIControlEventTouchUpInside]; 43 | UIBarButtonItem *returnItem = [[UIBarButtonItem alloc] initWithCustomView:btn]; 44 | 45 | self.navigationItem.leftBarButtonItems = @[returnItem]; 46 | } 47 | 48 | // 返回 49 | - (void)returnBtnClick:(UIButton *)sender { 50 | [self.navigationController popViewControllerAnimated:YES]; 51 | } 52 | 53 | #pragma mark - 初始化segmentType_0View 54 | - (void)setupSegmentType_0View { 55 | // 1.我的项目组 56 | LXSegmentTitleViewController *title_0VC = [[LXSegmentTitleViewController alloc] init]; 57 | title_0VC.view.backgroundColor = SYS_Cyan_Color; 58 | 59 | // 2.通讯录 60 | LXSegmentTitleViewController *title_1VC = [[LXSegmentTitleViewController alloc] init]; 61 | title_1VC.view.backgroundColor = SYS_Yellow_Color; 62 | 63 | [self addChildViewController:title_0VC]; 64 | [self addChildViewController:title_1VC]; 65 | 66 | _pageTabView = [[XXPageTabView alloc] initWithChildControllers:self.childViewControllers childTitles:@[@"我的好友", @"通讯录"]]; 67 | _pageTabView.frame = CGRectMake(0, SYS_NavigationBar_HEIGHT, kScreen_WIDTH, kScreen_HEIGHT-SYS_NavigationBar_HEIGHT); 68 | _pageTabView.tabSize = CGSizeMake(kScreen_WIDTH, 44); 69 | _pageTabView.tabItemFont = AppFont(15); 70 | _pageTabView.unSelectedColor = AppHTMLColor(@"999999"); 71 | _pageTabView.selectedColor = AppHTMLColor(@"4bccbc"); 72 | _pageTabView.bodyBounces = NO; 73 | _pageTabView.titleStyle = XXPageTabTitleStyleDefault; 74 | _pageTabView.indicatorStyle = XXPageTabIndicatorStyleFollowText; 75 | _pageTabView.delegate = self; 76 | [self.view addSubview:_pageTabView]; 77 | } 78 | 79 | #pragma mark - XXPageTabViewDelegate 80 | - (void)pageTabViewDidEndChange { 81 | NSInteger selectedTabIndex = _pageTabView.selectedTabIndex; 82 | NSLog(@"点击了index:%zd", selectedTabIndex); 83 | 84 | switch (selectedTabIndex) { 85 | case 0: 86 | { 87 | // 我的好友 88 | } 89 | break; 90 | case 1: 91 | { 92 | // 通讯录 93 | } 94 | break; 95 | } 96 | } 97 | 98 | @end 99 | -------------------------------------------------------------------------------- /LXSegmentControl/LX_Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // LX_Prefix.pch 3 | // LXHealthIndicatorDemo 4 | // 5 | // Created by LX Zeng on 2018/11/22. 6 | // Copyright © 2018 https://github.com/nick8brown All rights reserved. 7 | // 8 | 9 | #ifndef LX_Prefix_pch 10 | #define LX_Prefix_pch 11 | 12 | 13 | /*------------------------------视图大小位置------------------------------*/ 14 | 15 | // 屏幕尺寸 16 | #define kScreen_WIDTH [UIScreen mainScreen].bounds.size.width 17 | #define kScreen_HEIGHT [UIScreen mainScreen].bounds.size.height 18 | 19 | #define SCREEN_RATIO (kScreen_WIDTH/375) 20 | 21 | // iPhone机型 22 | #define IS_iPhone5s_Before ((kScreen_WIDTH == 320) ? YES : NO) 23 | #define IS_iPhone6s_Later ((kScreen_WIDTH == 375) ? YES : NO) 24 | #define IS_iPhone6sPlus_Later ((kScreen_WIDTH == 414) ? YES : NO) 25 | #define IS_iPhoneX ((kScreen_WIDTH == 375 && kScreen_HEIGHT == 812) ? YES : NO) 26 | 27 | // iPhone版本 28 | #define IS_iOS11_Later (([[UIDevice currentDevice].systemVersion floatValue] >= 11.0) ? YES : NO) 29 | 30 | // 系统性参数 31 | #define SYS_StatusBar_HEIGHT ((!IS_iPhoneX) ? 20 : SYS_SafeArea_TOP) 32 | #define SYS_NavigationBar_HEIGHT (SYS_StatusBar_HEIGHT+44) 33 | #define SYS_Toolbar_HEIGHT 44 34 | #define SYS_TabBar_HEIGHT ((!IS_iPhoneX) ? 49 : (49+SYS_SafeArea_BOTTOM)) 35 | #define SYS_Spacing_HEIGHT 8 36 | 37 | #define SYS_SafeArea_TOP ((IS_iPhoneX) ? 44 : 0) 38 | #define SYS_SafeArea_BOTTOM ((IS_iPhoneX) ? 34 : 0) 39 | 40 | // 最小间隔 41 | #define minimumSpacing 10 42 | 43 | 44 | /*------------------------------字体、颜色------------------------------*/ 45 | 46 | // 系统颜色 47 | #define SYS_Black_Color [UIColor blackColor] 48 | #define SYS_DarkGray_Color [UIColor darkGrayColor] 49 | #define SYS_LightGray_Color [UIColor lightGrayColor] 50 | #define SYS_White_Color [UIColor whiteColor] 51 | #define SYS_Gray_Color [UIColor grayColor] 52 | #define SYS_Red_Color [UIColor redColor] 53 | #define SYS_Green_Color [UIColor greenColor] 54 | #define SYS_Blue_Color [UIColor blueColor] 55 | #define SYS_Cyan_Color [UIColor cyanColor] 56 | #define SYS_Yellow_Color [UIColor yellowColor] 57 | #define SYS_Magenta_Color [UIColor magentaColor] 58 | #define SYS_Orange_Color [UIColor orangeColor] 59 | #define SYS_Purple_Color [UIColor purpleColor] 60 | #define SYS_Brown_Color [UIColor brownColor] 61 | #define SYS_Clear_Color [UIColor clearColor] 62 | #define SYS_Random_Color [UIColor randomColor] 63 | 64 | // 字体 65 | #define AppFont(x) [UIFont systemFontOfSize:x] 66 | #define AppBoldFont(x) [UIFont boldSystemFontOfSize:x] 67 | 68 | // 颜色 69 | #define AppColor(r, g, b) [UIColor colorWithRed:r/255.0 green:g/255.0 blue:b/255.0 alpha:1] 70 | #define AppAlphaColor(r, g, b, a) [UIColor colorWithRed:r/255.0 green:g/255.0 blue:b/255.0 alpha:a] 71 | 72 | #define AppHTMLColor(html) [UIColor colorWithHexString:html] 73 | 74 | 75 | /*------------------------------图片------------------------------*/ 76 | 77 | #define ImageNamed(name) [UIImage imageNamed:name] 78 | #define URLWithString(url) [NSURL URLWithString:url] 79 | 80 | 81 | /*------------------------------其它------------------------------*/ 82 | 83 | #import "UIColor+LX.h" 84 | #import "UIImage+LX.h" 85 | 86 | // tag基数 87 | #define BASE_TAG 100 88 | 89 | // tableView注册 90 | #define RegisterClass_for_Cell(tableViewCell) [self.tableView registerClass:[tableViewCell class] forCellReuseIdentifier:NSStringFromClass([tableViewCell class])] 91 | #define RegisterClass_for_HeaderFooterView(tableViewHeaderFooterView) [self.tableView registerClass:[tableViewHeaderFooterView class] forHeaderFooterViewReuseIdentifier:NSStringFromClass([tableViewHeaderFooterView class])] 92 | #define RegisterNib_for_Cell(tableViewCell) [self.tableView registerNib:[UINib nibWithNibName:NSStringFromClass([tableViewCell class]) bundle:[NSBundle mainBundle]] forCellReuseIdentifier:NSStringFromClass([tableViewCell class])] 93 | #define RegisterNib_for_HeaderFooterView(tableViewHeaderFooterView) [self.tableView registerNib:[UINib nibWithNibName:NSStringFromClass([tableViewCell class]) bundle:[NSBundle mainBundle]] forCellReuseIdentifier:NSStringFromClass([tableViewCell class])] 94 | 95 | // tableView出列 96 | #define DequeueReusable_Cell [tableView dequeueReusableCellWithIdentifier:NSStringFromClass([self class])] 97 | #define DequeueReusable_HeaderFooterView [tableView dequeueReusableHeaderFooterViewWithIdentifier:NSStringFromClass([self class])] 98 | 99 | 100 | #endif /* LX_Prefix_pch */ 101 | -------------------------------------------------------------------------------- /LXSegmentControl/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 29 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /LXSegmentControl/LXSegmentType_1ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // LXSegmentType_1ViewController.m 3 | // LXSegmentControl 4 | // 5 | // Created by LX Zeng on 2018/12/3. 6 | // Copyright © 2018 https://github.com/nick8brown All rights reserved. 7 | // 8 | 9 | #import "LXSegmentType_1ViewController.h" 10 | 11 | #import "LXSegmentTitleViewController.h" 12 | 13 | #import "LXPageTabView.h" 14 | 15 | #define CellIdentifier @"Cell" 16 | 17 | @interface LXSegmentType_1ViewController () 18 | 19 | { 20 | LXPageTabView *_pageTabView; 21 | } 22 | @property (nonatomic, strong) NSArray *titleArray; 23 | @property (nonatomic, strong) NSMutableArray *tableViewArray; 24 | 25 | @end 26 | 27 | @implementation LXSegmentType_1ViewController 28 | 29 | #pragma mark - lazy load 30 | - (NSArray *)titleArray { 31 | if (!_titleArray) { 32 | _titleArray = @[@"礼物TOP100", @"每日推荐", @"新星榜", @"送女友", @"送基友", @"送同事", @"送长辈"]; 33 | } 34 | return _titleArray; 35 | } 36 | 37 | - (NSMutableArray *)tableViewArray { 38 | if (!_tableViewArray) { 39 | _tableViewArray = [NSMutableArray array]; 40 | } 41 | return _tableViewArray; 42 | } 43 | 44 | #pragma mark - life cycle 45 | - (void)viewDidLoad { 46 | [super viewDidLoad]; 47 | 48 | // 初始化导航栏 49 | [self setupNavBar]; 50 | 51 | // 初始化segmentType_1View 52 | [self setupSegmentType_1View]; 53 | } 54 | 55 | #pragma mark - 初始化导航栏 56 | - (void)setupNavBar { 57 | // leftBarButtonItem(返回) 58 | UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom]; 59 | btn.frame = CGRectMake(0, 0, 20, 20); 60 | [btn setImage:ImageNamed(@"back") forState:UIControlStateNormal]; 61 | [btn addTarget:self action:@selector(returnBtnClick:) forControlEvents:UIControlEventTouchUpInside]; 62 | UIBarButtonItem *returnItem = [[UIBarButtonItem alloc] initWithCustomView:btn]; 63 | 64 | self.navigationItem.leftBarButtonItems = @[returnItem]; 65 | } 66 | 67 | // 返回 68 | - (void)returnBtnClick:(UIButton *)sender { 69 | [self.navigationController popViewControllerAnimated:YES]; 70 | } 71 | 72 | #pragma mark - 初始化segmentType_1View 73 | - (void)setupSegmentType_1View { 74 | for (int i = 0; i < self.titleArray.count; i++) { 75 | LXSegmentTitleViewController *vc = [[LXSegmentTitleViewController alloc] init]; 76 | 77 | // 初始化tableView 78 | [vc.view addSubview:[self setupTableView:i]]; 79 | 80 | [self addChildViewController:vc]; 81 | } 82 | 83 | _pageTabView = [[LXPageTabView alloc] initWithChildControllers:self.childViewControllers childTitles:self.titleArray]; 84 | _pageTabView.frame = CGRectMake(0, SYS_NavigationBar_HEIGHT, kScreen_WIDTH, kScreen_HEIGHT-SYS_NavigationBar_HEIGHT); 85 | _pageTabView.tabSize = CGSizeMake(kScreen_WIDTH, 40); 86 | _pageTabView.tabItemFont = AppFont(15); 87 | _pageTabView.unSelectedColor = AppHTMLColor(@"c8c8c8"); 88 | _pageTabView.selectedColor = AppHTMLColor(@"ffffff"); 89 | _pageTabView.tabBackgroundColor = AppHTMLColor(@"ee8c8e"); 90 | _pageTabView.bodyBounces = NO; 91 | _pageTabView.titleStyle = LXPageTabTitleStyleDefault; 92 | _pageTabView.indicatorStyle = LXPageTabIndicatorStyleDefault; 93 | _pageTabView.indicatorWidth = 20; 94 | _pageTabView.indicatorHeight = 10; 95 | _pageTabView.delegate = self; 96 | [self.view addSubview:_pageTabView]; 97 | } 98 | 99 | // 初始化tableView 100 | - (UITableView *)setupTableView:(NSInteger)index { 101 | UITableView *tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, kScreen_WIDTH, kScreen_HEIGHT-SYS_NavigationBar_HEIGHT-40) style:UITableViewStyleGrouped]; 102 | tableView.backgroundColor = SYS_White_Color; 103 | tableView.dataSource = self; 104 | tableView.delegate = self; 105 | tableView.showsHorizontalScrollIndicator = NO; 106 | tableView.showsVerticalScrollIndicator = NO; 107 | tableView.separatorStyle = UITableViewCellSeparatorStyleNone; 108 | 109 | [self.tableViewArray addObject:tableView]; 110 | 111 | return tableView; 112 | } 113 | 114 | #pragma mark - UITableViewDataSource 115 | // 段数 116 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { 117 | return 1; 118 | } 119 | 120 | // 行数 121 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 122 | return 15; 123 | } 124 | 125 | // cell样式 126 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 127 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 128 | if (!cell) { 129 | cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; 130 | } 131 | cell.textLabel.text = self.titleArray[_pageTabView.selectedTabIndex]; 132 | return cell; 133 | } 134 | 135 | #pragma mark - UITableViewDelegate 136 | // 行高 137 | - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { 138 | return 50; 139 | } 140 | 141 | // 段头高度 142 | - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { 143 | return CGFLOAT_MIN; 144 | } 145 | 146 | // 段尾高度 147 | - (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section { 148 | return CGFLOAT_MIN; 149 | } 150 | 151 | // 段头视图 152 | - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section { 153 | return [[UIView alloc] init]; 154 | } 155 | 156 | // 段尾视图 157 | - (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section { 158 | return [[UIView alloc] init]; 159 | } 160 | 161 | // 选中某行 162 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 163 | } 164 | 165 | #pragma mark - LXPageTabViewDelegate 166 | - (void)pageTabViewDidEndChange { 167 | NSInteger selectedTabIndex = _pageTabView.selectedTabIndex; 168 | NSLog(@"点击了index:%zd", selectedTabIndex); 169 | 170 | // 171 | [self.tableViewArray[selectedTabIndex] reloadData]; 172 | } 173 | 174 | @end 175 | -------------------------------------------------------------------------------- /LXSegmentControl/Lib/LXPageTab/LXPageTabView.m: -------------------------------------------------------------------------------- 1 | // 2 | // LXPageTabView.m 3 | // XXPageTabDemo 4 | // 5 | // Created by LX Zeng on 2017/2/27. 6 | // Copyright © 2017年 https://github.com/nick8brown All rights reserved. 7 | // 8 | 9 | #import "LXPageTabView.h" 10 | 11 | #define kTabDefautHeight 38.0 12 | #define kTabDefautFontSize 15.0 13 | #define kMaxNumberOfPageItems 4 14 | #define kIndicatorHeight 2.0 15 | #define kIndicatorWidth 20 16 | #define kMinScale 0.8 17 | 18 | #define HEIGHT(view) view.bounds.size.height 19 | #define WIDTH(view) view.bounds.size.width 20 | #define ORIGIN_X(view) view.frame.origin.x 21 | #define ORIGIN_Y(view) view.frame.origin.y 22 | 23 | @interface LXPageTabView () 24 | //bg 25 | @property (nonatomic, strong) UIView *bgView; //由于遇到nav->vc,vc的第一个子试图是UIScrollView会自动产生64像素偏移,所以加上一个虚拟背景(没有尺寸) 26 | 27 | //tab 28 | @property (nonatomic, strong) UIScrollView *tabView; 29 | @property (nonatomic, strong) UIImageView *indicatorView; 30 | 31 | //body 32 | @property (nonatomic, strong) UIScrollView *bodyView; 33 | 34 | //data 35 | @property (nonatomic, assign) NSInteger lastSelectedTabIndex; //记录上一次的索引 36 | @property (nonatomic, assign) NSInteger numberOfTabItems; 37 | @property (nonatomic, assign) CGFloat tabItemWidth; 38 | @property (nonatomic, strong) NSMutableArray *tabItems; 39 | @property (nonatomic, strong) NSArray *childControllers; 40 | @property (nonatomic, strong) NSArray *childTitles; 41 | 42 | //animation 43 | @property (nonatomic, assign) BOOL isNeedRefreshLayout; //滑动过程中不允许layoutSubviews 44 | @property (nonatomic, assign) BOOL isChangeByClick; //是否是通过点击改变的。因为点击可以长距离点击,部分效果不作处理会出现途中经过的按钮也会依次有效果(仿网易客户端有此效果,个人觉得并不好,头条的客户端更合理) 45 | @property (nonatomic, assign) NSInteger leftItemIndex; //记录滑动时左边的itemIndex 46 | @property (nonatomic, assign) NSInteger rightItemIndex; //记录滑动时右边的itemIndex 47 | 48 | /*LXPageTabTitleStyleScale*/ 49 | @property (nonatomic, assign) CGFloat selectedColorR; 50 | @property (nonatomic, assign) CGFloat selectedColorG; 51 | @property (nonatomic, assign) CGFloat selectedColorB; 52 | @property (nonatomic, assign) CGFloat unSelectedColorR; 53 | @property (nonatomic, assign) CGFloat unSelectedColorG; 54 | @property (nonatomic, assign) CGFloat unSelectedColorB; 55 | 56 | @end 57 | 58 | @implementation LXPageTabView 59 | 60 | #pragma mark - Life cycle 61 | - (instancetype)initWithChildControllers:(NSArray *)childControllers 62 | childTitles:(NSArray *)childTitles { 63 | self = [super init]; 64 | if(self) { 65 | _childControllers = childControllers; 66 | _childTitles = childTitles; 67 | 68 | [self initBaseSettings]; 69 | [self initTabView]; 70 | [self initMainView]; 71 | } 72 | return self; 73 | } 74 | 75 | - (void)layoutSubviews { 76 | if(_isNeedRefreshLayout) { 77 | //tab layout 78 | if(_tabSize.height <= 0) { 79 | _tabSize.height = kTabDefautHeight; 80 | } 81 | if(_tabSize.width <= 0) { 82 | _tabSize.width = WIDTH(self); 83 | } 84 | _tabItemWidth = _tabSize.width/(_numberOfTabItems<_maxNumberOfPageItems?_numberOfTabItems:_maxNumberOfPageItems); 85 | 86 | self.tabView.frame = CGRectMake(0, 0, _tabSize.width, _tabSize.height); 87 | self.tabView.contentSize = CGSizeMake(_tabItemWidth*_numberOfTabItems, 0); 88 | 89 | for(NSInteger i = 0; i < _tabItems.count; i++) { 90 | LXPageTabItemLable *tabItem = (LXPageTabItemLable *)_tabItems[i]; 91 | tabItem.frame = CGRectMake(_tabItemWidth*i, 4, _tabItemWidth, _tabSize.height-_indicatorHeight-4); 92 | } 93 | [self layoutIndicatorViewWithStyle]; 94 | 95 | //body layout 96 | self.bodyView.frame = CGRectMake(0, _tabSize.height, WIDTH(self), HEIGHT(self)-_tabSize.height); 97 | self.bodyView.contentSize = CGSizeMake(WIDTH(self)*_numberOfTabItems, 0); 98 | self.bodyView.contentOffset = CGPointMake(self.frame.size.width*_selectedTabIndex, 0); 99 | [self reviseTabContentOffsetBySelectedIndex:NO]; 100 | 101 | for(NSInteger i = 0; i < _numberOfTabItems; i++) { 102 | UIViewController *childController = _childControllers[i]; 103 | childController.view.frame = CGRectMake(WIDTH(self)*i, 0, WIDTH(self), HEIGHT(self)-_tabSize.height); 104 | } 105 | } 106 | } 107 | 108 | #pragma mark - Layout 109 | - (void)initBaseSettings { 110 | _selectedTabIndex = 0; 111 | _lastSelectedTabIndex = 0; 112 | _tabSize = CGSizeZero; 113 | _numberOfTabItems = _childControllers.count>_childTitles.count?_childTitles.count:_childControllers.count; 114 | _tabItemFont = [UIFont systemFontOfSize:kTabDefautFontSize]; 115 | _indicatorHeight = kIndicatorHeight; 116 | _indicatorWidth = kIndicatorWidth; 117 | _maxNumberOfPageItems = kMaxNumberOfPageItems; 118 | _tabItems = [NSMutableArray array]; 119 | _tabBackgroundColor = [UIColor whiteColor]; 120 | _bodyBackgroundColor = [UIColor whiteColor]; 121 | _unSelectedColor = [UIColor blackColor]; 122 | _selectedColor = [UIColor redColor]; 123 | _isNeedRefreshLayout = YES; 124 | _isChangeByClick = NO; 125 | _bodyBounces = YES; 126 | _titleStyle = LXPageTabTitleStyleDefault; 127 | _indicatorStyle = LXPageTabIndicatorStyleDefault; 128 | _minScale = kMinScale; 129 | _selectedColorR = 1; 130 | _selectedColorG = 0; 131 | _selectedColorB = 0; 132 | _unSelectedColorR = 0; 133 | _unSelectedColorG = 0; 134 | _unSelectedColorB = 0; 135 | } 136 | 137 | - (void)initTabView { 138 | [self addSubview:self.bgView]; 139 | [self addSubview:self.tabView]; 140 | 141 | for(NSInteger i = 0; i < _numberOfTabItems; i++) { 142 | LXPageTabItemLable *tabItem = [[LXPageTabItemLable alloc] init]; 143 | tabItem.font = _tabItemFont; 144 | tabItem.text = _childTitles[i]; 145 | tabItem.textColor = i==_selectedTabIndex?_selectedColor:_unSelectedColor; 146 | tabItem.textAlignment = NSTextAlignmentCenter; 147 | tabItem.userInteractionEnabled = YES; 148 | 149 | UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(changeChildControllerOnClick:)]; 150 | [tabItem addGestureRecognizer:tapRecognizer]; 151 | [_tabItems addObject:tabItem]; 152 | [self.tabView addSubview:tabItem]; 153 | } 154 | } 155 | 156 | - (void)initMainView { 157 | [self addSubview:self.bodyView]; 158 | for(NSInteger i = 0; i < _numberOfTabItems; i++) { 159 | UIViewController *childController = _childControllers[i]; 160 | [self.bodyView addSubview:childController.view]; 161 | } 162 | } 163 | 164 | /** 165 | 根据选择项修正tab的展示区域 166 | */ 167 | - (void)reviseTabContentOffsetBySelectedIndex:(BOOL)isAnimate { 168 | LXPageTabItemLable *currentTabItem = _tabItems[_selectedTabIndex]; 169 | CGFloat selectedItemCenterX = currentTabItem.center.x; 170 | 171 | CGFloat reviseX; 172 | if(selectedItemCenterX + _tabSize.width/2.0 >= self.tabView.contentSize.width) { 173 | reviseX = self.tabView.contentSize.width - _tabSize.width; //不足以到中心,靠右 174 | } else if(selectedItemCenterX - _tabSize.width/2.0 <= 0) { 175 | reviseX = 0; //不足以到中心,靠左 176 | } else { 177 | reviseX = selectedItemCenterX - _tabSize.width/2.0; //修正至中心 178 | } 179 | //如果前后没有偏移量差,setContentOffset实际不起作用;或者没有动画效果 180 | if(fabs(self.tabView.contentOffset.x - reviseX)<1 || !isAnimate) { 181 | [self finishReviseTabContentOffset]; 182 | } 183 | [self.tabView setContentOffset:CGPointMake(reviseX, 0) animated:isAnimate]; 184 | } 185 | 186 | /** 187 | tabview修正完成后的操作,无论是点击还是滑动body,此方法都是真正意义上的最后一步 188 | */ 189 | - (void)finishReviseTabContentOffset { 190 | _tabView.userInteractionEnabled = YES; 191 | _isNeedRefreshLayout = YES; 192 | _isChangeByClick = NO; 193 | if([self.delegate respondsToSelector:@selector(pageTabViewDidEndChange)]) { 194 | if(_lastSelectedTabIndex != _selectedTabIndex) { 195 | [self.delegate pageTabViewDidEndChange]; 196 | } 197 | } 198 | _lastSelectedTabIndex = _selectedTabIndex; 199 | } 200 | 201 | /** 202 | 一般常用改变selected Item方法(无动画效果,直接变色) 203 | */ 204 | - (void)changeSelectedItemToNextItem:(NSInteger)nextIndex { 205 | LXPageTabItemLable *currentTabItem = _tabItems[_selectedTabIndex]; 206 | LXPageTabItemLable *nextTabItem = _tabItems[nextIndex]; 207 | currentTabItem.textColor = _unSelectedColor; 208 | nextTabItem.textColor = _selectedColor; 209 | } 210 | 211 | #pragma mark -Title layout 212 | /** 213 | 重新设置item的缩放比例 214 | */ 215 | - (void)resetTabItemScale { 216 | for(NSInteger i = 0; i < _numberOfTabItems; i++) { 217 | LXPageTabItemLable *tabItem = _tabItems[i]; 218 | if(i != _selectedTabIndex) { 219 | tabItem.transform = CGAffineTransformMakeScale(_minScale, _minScale); 220 | } else { 221 | tabItem.transform = CGAffineTransformMakeScale(1, 1); 222 | } 223 | } 224 | } 225 | 226 | #pragma mark -Indicator layout 227 | /** 228 | 根据不同风格添加相应下标 229 | */ 230 | - (void)addIndicatorViewWithStyle { 231 | switch (_indicatorStyle) { 232 | case LXPageTabIndicatorStyleDefault: 233 | case LXPageTabIndicatorStyleFollowText: 234 | case LXPageTabIndicatorStyleStretch: 235 | [self addSubview:self.indicatorView]; 236 | break; 237 | default: 238 | break; 239 | } 240 | } 241 | 242 | /** 243 | 根据不同风格对下标layout 244 | */ 245 | - (void)layoutIndicatorViewWithStyle { 246 | switch (_indicatorStyle) { 247 | case LXPageTabIndicatorStyleDefault: 248 | case LXPageTabIndicatorStyleFollowText: 249 | case LXPageTabIndicatorStyleStretch: 250 | [self layoutIndicatorView]; 251 | break; 252 | default: 253 | break; 254 | } 255 | } 256 | 257 | - (void)layoutIndicatorView { 258 | // CGFloat indicatorWidth = [self getIndicatorWidthWithTitle:_childTitles[_selectedTabIndex]]; 259 | LXPageTabItemLable *selecedTabItem = _tabItems[_selectedTabIndex]; 260 | self.indicatorView.frame = CGRectMake(selecedTabItem.center.x-_indicatorWidth/2.0-_tabView.contentOffset.x, _tabSize.height-_indicatorHeight+1, _indicatorWidth, _indicatorHeight); 261 | } 262 | 263 | #pragma mark - Event response 264 | - (void)changeChildControllerOnClick:(UITapGestureRecognizer *)tap { 265 | NSInteger nextIndex = [_tabItems indexOfObject:tap.view]; 266 | if(nextIndex != _selectedTabIndex) { 267 | if(_titleStyle == LXPageTabTitleStyleDefault) { 268 | [self changeSelectedItemToNextItem:nextIndex]; 269 | } 270 | 271 | _isChangeByClick = YES; 272 | _tabView.userInteractionEnabled = NO; //防止快速切换 273 | _leftItemIndex = nextIndex > _selectedTabIndex?_selectedTabIndex:nextIndex; 274 | _rightItemIndex = nextIndex > _selectedTabIndex?nextIndex:_selectedTabIndex; 275 | _selectedTabIndex = nextIndex; 276 | [self.bodyView setContentOffset:CGPointMake(self.frame.size.width*_selectedTabIndex, 0) animated:YES]; 277 | } 278 | } 279 | 280 | #pragma mark - UIScrollViewDelegate 281 | - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { 282 | if(scrollView == self.bodyView) { 283 | _selectedTabIndex = self.bodyView.contentOffset.x/WIDTH(self.bodyView); 284 | [self reviseTabContentOffsetBySelectedIndex:YES]; 285 | } 286 | } 287 | 288 | - (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView { 289 | if(scrollView == self.bodyView) { 290 | [self reviseTabContentOffsetBySelectedIndex:YES]; 291 | } else { 292 | [self finishReviseTabContentOffset]; 293 | } 294 | } 295 | 296 | - (void)scrollViewDidScroll:(UIScrollView *)scrollView { 297 | if(scrollView == self.tabView) { 298 | _isNeedRefreshLayout = NO; 299 | if(self.indicatorView.superview) { 300 | LXPageTabItemLable *selecedTabItem = _tabItems[_selectedTabIndex]; 301 | self.indicatorView.frame = CGRectMake(selecedTabItem.center.x-WIDTH(self.indicatorView)/2.0-scrollView.contentOffset.x, ORIGIN_Y(self.indicatorView), WIDTH(self.indicatorView), HEIGHT(self.indicatorView)); 302 | } 303 | } else if(scrollView == self.bodyView) { 304 | //未初始化时不处理 305 | if(self.bodyView.contentSize.width <= 0) { 306 | return; 307 | } 308 | //滚动过程中不允许layout 309 | _isNeedRefreshLayout = NO; 310 | //获取当前左右item index(点击方式已获知左右index,无需根据contentoffset计算) 311 | if(!_isChangeByClick) { 312 | if(self.bodyView.contentOffset.x <= 0) { //左边界 313 | _leftItemIndex = 0; 314 | _rightItemIndex = 0; 315 | 316 | } else if(self.bodyView.contentOffset.x >= self.bodyView.contentSize.width-WIDTH(self.bodyView)) { //右边界 317 | _leftItemIndex = _numberOfTabItems-1; 318 | _rightItemIndex = _numberOfTabItems-1; 319 | 320 | } else { 321 | _leftItemIndex = (int)(self.bodyView.contentOffset.x/WIDTH(self.bodyView)); 322 | _rightItemIndex = _leftItemIndex + 1; 323 | } 324 | } 325 | 326 | //调整title 327 | switch (_titleStyle) { 328 | case LXPageTabTitleStyleDefault: 329 | [self changeTitleWithDefault]; 330 | break; 331 | case LXPageTabTitleStyleGradient: 332 | [self changeTitleWithGradient]; 333 | break; 334 | case LXPageTabTitleStyleBlend: 335 | [self changeTitleWithBlend]; 336 | break; 337 | default: 338 | break; 339 | } 340 | 341 | //调整indicator 342 | switch (_indicatorStyle) { 343 | case LXPageTabIndicatorStyleDefault: 344 | case LXPageTabIndicatorStyleFollowText: 345 | [self changeIndicatorFrame]; 346 | break; 347 | case LXPageTabIndicatorStyleStretch: 348 | { 349 | if(_isChangeByClick) { 350 | [self changeIndicatorFrame]; 351 | } else { 352 | [self changeIndicatorFrameByStretch]; 353 | } 354 | } 355 | break; 356 | default: 357 | break; 358 | } 359 | } 360 | } 361 | 362 | #pragma mark - Title animation 363 | - (void)changeTitleWithDefault { 364 | CGFloat relativeLocation = self.bodyView.contentOffset.x/WIDTH(self.bodyView)-_leftItemIndex; 365 | if(!_isChangeByClick) { 366 | if(relativeLocation > 0.5) { 367 | [self changeSelectedItemToNextItem:_rightItemIndex]; 368 | _selectedTabIndex = _rightItemIndex; 369 | } else { 370 | [self changeSelectedItemToNextItem:_leftItemIndex]; 371 | _selectedTabIndex = _leftItemIndex; 372 | } 373 | } 374 | } 375 | 376 | - (void)changeTitleWithGradient { 377 | if(_leftItemIndex != _rightItemIndex) { 378 | CGFloat rightScale = (self.bodyView.contentOffset.x/WIDTH(self.bodyView)-_leftItemIndex)/(_rightItemIndex-_leftItemIndex); 379 | CGFloat leftScale = 1-rightScale; 380 | 381 | //颜色渐变 382 | CGFloat difR = _selectedColorR-_unSelectedColorR; 383 | CGFloat difG = _selectedColorG-_unSelectedColorG; 384 | CGFloat difB = _selectedColorB-_unSelectedColorB; 385 | 386 | UIColor *leftItemColor = [UIColor colorWithRed:_unSelectedColorR+leftScale*difR green:_unSelectedColorG+leftScale*difG blue:_unSelectedColorB+leftScale*difB alpha:1]; 387 | UIColor *rightItemColor = [UIColor colorWithRed:_unSelectedColorR+rightScale*difR green:_unSelectedColorG+rightScale*difG blue:_unSelectedColorB+rightScale*difB alpha:1]; 388 | 389 | LXPageTabItemLable *leftTabItem = _tabItems[_leftItemIndex]; 390 | LXPageTabItemLable *rightTabItem = _tabItems[_rightItemIndex]; 391 | leftTabItem.textColor = leftItemColor; 392 | rightTabItem.textColor = rightItemColor; 393 | 394 | //字体渐变 395 | leftTabItem.transform = CGAffineTransformMakeScale(_minScale+(1-_minScale)*leftScale, _minScale+(1-_minScale)*leftScale); 396 | rightTabItem.transform = CGAffineTransformMakeScale(_minScale+(1-_minScale)*rightScale, _minScale+(1-_minScale)*rightScale); 397 | } 398 | } 399 | 400 | - (void)changeTitleWithBlend { 401 | CGFloat leftScale = self.bodyView.contentOffset.x/WIDTH(self.bodyView)-_leftItemIndex; 402 | if(leftScale == 0) { 403 | return; //起点和终点不处理,终点时左右index已更新,会绘画错误(你可以注释看看) 404 | } 405 | 406 | LXPageTabItemLable *leftTabItem = _tabItems[_leftItemIndex]; 407 | LXPageTabItemLable *rightTabItem = _tabItems[_rightItemIndex]; 408 | 409 | leftTabItem.textColor = _selectedColor; 410 | rightTabItem.textColor = _unSelectedColor; 411 | leftTabItem.process = leftScale; 412 | rightTabItem.process = leftScale; 413 | } 414 | 415 | #pragma mark - Indicator animation 416 | - (void)changeIndicatorFrame { 417 | //计算indicator此时的centerx 418 | CGFloat nowIndicatorCenterX = _tabItemWidth*(0.5+self.bodyView.contentOffset.x/WIDTH(self.bodyView)); 419 | //计算此时body的偏移量在一页中的占比 420 | CGFloat relativeLocation = (self.bodyView.contentOffset.x/WIDTH(self.bodyView)-_leftItemIndex)/(_rightItemIndex-_leftItemIndex); 421 | //记录左右对应的indicator宽度 422 | CGFloat leftIndicatorWidth = [self getIndicatorWidthWithTitle:_childTitles[_leftItemIndex]]; 423 | CGFloat rightIndicatorWidth = [self getIndicatorWidthWithTitle:_childTitles[_rightItemIndex]]; 424 | 425 | //左右边界的时候,占比清0 426 | if(_leftItemIndex == _rightItemIndex) { 427 | relativeLocation = 0; 428 | } 429 | //基于从左到右方向(无需考虑滑动方向),计算当前中心轴所处位置的长度 430 | // CGFloat nowIndicatorWidth = leftIndicatorWidth + (rightIndicatorWidth-leftIndicatorWidth)*relativeLocation; 431 | 432 | self.indicatorView.frame = CGRectMake(nowIndicatorCenterX-WIDTH(self.indicatorView)/2.0-_tabView.contentOffset.x, ORIGIN_Y(self.indicatorView), WIDTH(self.indicatorView), HEIGHT(self.indicatorView)); 433 | } 434 | 435 | - (void)changeIndicatorFrameByStretch { 436 | if(_indicatorWidth <= 0) { 437 | return; 438 | } 439 | 440 | //计算此时body的偏移量在一页中的占比 441 | CGFloat relativeLocation = (self.bodyView.contentOffset.x/WIDTH(self.bodyView)-_leftItemIndex)/(_rightItemIndex-_leftItemIndex); 442 | //左右边界的时候,占比清0 443 | if(_leftItemIndex == _rightItemIndex) { 444 | relativeLocation = 0; 445 | } 446 | 447 | LXPageTabItemLable *leftTabItem = _tabItems[_leftItemIndex]; 448 | LXPageTabItemLable *rightTabItem = _tabItems[_rightItemIndex]; 449 | 450 | //当前的frame 451 | CGRect nowFrame = CGRectMake(0, ORIGIN_Y(self.indicatorView), 0, HEIGHT(self.indicatorView)); 452 | 453 | //计算宽度 454 | if(relativeLocation <= 0.5) { 455 | nowFrame.size.width = _indicatorWidth+_tabItemWidth*(relativeLocation/0.5); 456 | nowFrame.origin.x = (leftTabItem.center.x-self.tabView.contentOffset.x)-_indicatorWidth/2.0; 457 | } else { 458 | nowFrame.size.width = _indicatorWidth+_tabItemWidth*((1-relativeLocation)/0.5); 459 | nowFrame.origin.x = (rightTabItem.center.x-self.tabView.contentOffset.x)+_indicatorWidth/2.0-nowFrame.size.width; 460 | } 461 | 462 | self.indicatorView.frame = nowFrame; 463 | } 464 | 465 | #pragma mark - Tool 466 | /** 467 | 根据对应文本计算下标线宽度 468 | */ 469 | - (CGFloat)getIndicatorWidthWithTitle:(NSString *)title { 470 | if(_indicatorStyle == LXPageTabIndicatorStyleDefault || _indicatorStyle == LXPageTabIndicatorStyleStretch) { 471 | return _indicatorWidth; 472 | } else { 473 | if(title.length <= 2) { 474 | return 40; 475 | } else { 476 | return title.length * _tabItemFont.pointSize + 12; 477 | } 478 | } 479 | } 480 | 481 | /** 482 | 获取color的rgb值 483 | */ 484 | - (NSArray *)getRGBWithColor:(UIColor *)color { 485 | CGFloat R, G, B; 486 | NSInteger numComponents = CGColorGetNumberOfComponents(color.CGColor); 487 | if(numComponents == 4) { 488 | const CGFloat *components = CGColorGetComponents(color.CGColor); 489 | R = components[0]; 490 | G = components[1]; 491 | B = components[2]; 492 | } 493 | return @[@(R), @(G), @(B)]; 494 | } 495 | 496 | #pragma mark - Getter/setter 497 | - (UIView *)bgView { 498 | if(!_bgView) { 499 | _bgView = [UIView new]; 500 | } 501 | return _bgView; 502 | } 503 | 504 | - (UIScrollView *)tabView { 505 | if(!_tabView) { 506 | _tabView = [UIScrollView new]; 507 | _tabView.showsVerticalScrollIndicator = NO; 508 | _tabView.showsHorizontalScrollIndicator = NO; 509 | _tabView.backgroundColor = _tabBackgroundColor; 510 | _tabView.delegate = self; 511 | _tabView.clipsToBounds = YES; 512 | } 513 | return _tabView; 514 | } 515 | 516 | - (UIScrollView *)bodyView { 517 | if(!_bodyView) { 518 | _bodyView = [UIScrollView new]; 519 | _bodyView.pagingEnabled = YES; 520 | _bodyView.showsVerticalScrollIndicator = NO; 521 | _bodyView.showsHorizontalScrollIndicator = NO; 522 | _bodyView.delegate = self; 523 | _bodyView.bounces = _bodyBounces; 524 | _bodyView.backgroundColor = _bodyBackgroundColor; 525 | } 526 | return _bodyView; 527 | } 528 | 529 | - (UIImageView *)indicatorView { 530 | if(!_indicatorView) { 531 | _indicatorView = [UIImageView new]; 532 | _indicatorView.image = [UIImage imageNamed:@"三角形"]; 533 | } 534 | return _indicatorView; 535 | } 536 | 537 | - (void)setTabBackgroundColor:(UIColor *)tabBackgroundColor { 538 | _tabBackgroundColor = tabBackgroundColor; 539 | self.tabView.backgroundColor = _tabBackgroundColor; 540 | } 541 | 542 | - (void)setBodyBackgroundColor:(UIColor *)bodyBackgroundColor { 543 | _bodyBackgroundColor = bodyBackgroundColor; 544 | self.bodyView.backgroundColor = _bodyBackgroundColor; 545 | } 546 | 547 | - (void)setSelectedTabIndex:(NSInteger)selectedTabIndex { 548 | if(selectedTabIndex >= 0 && selectedTabIndex < _numberOfTabItems && _selectedTabIndex != selectedTabIndex) { 549 | [self changeSelectedItemToNextItem:selectedTabIndex]; 550 | _selectedTabIndex = selectedTabIndex; 551 | _lastSelectedTabIndex = selectedTabIndex; 552 | [self layoutIndicatorViewWithStyle]; 553 | self.bodyView.contentOffset = CGPointMake(WIDTH(self)*_selectedTabIndex, 0); 554 | 555 | if(_titleStyle == LXPageTabTitleStyleGradient) { 556 | [self resetTabItemScale]; 557 | } 558 | } 559 | } 560 | 561 | - (void)setUnSelectedColor:(UIColor *)unSelectedColor { 562 | _unSelectedColor = unSelectedColor; 563 | for(NSInteger i = 0; i < _numberOfTabItems; i++) { 564 | LXPageTabItemLable *tabItem = _tabItems[i]; 565 | tabItem.textColor = i==_selectedTabIndex?_selectedColor:_unSelectedColor; 566 | } 567 | NSArray *rgb = [self getRGBWithColor:_unSelectedColor]; 568 | _unSelectedColorR = [rgb[0] floatValue]; 569 | _unSelectedColorG = [rgb[1] floatValue]; 570 | _unSelectedColorB = [rgb[2] floatValue]; 571 | } 572 | 573 | - (void)setSelectedColor:(UIColor *)selectedColor { 574 | _selectedColor = selectedColor; 575 | LXPageTabItemLable *tabItem = _tabItems[_selectedTabIndex]; 576 | tabItem.textColor = _selectedColor; 577 | 578 | NSArray *rgb = [self getRGBWithColor:_selectedColor]; 579 | _selectedColorR = [rgb[0] floatValue]; 580 | _selectedColorG = [rgb[1] floatValue]; 581 | _selectedColorB = [rgb[2] floatValue]; 582 | } 583 | 584 | - (void)setBodyBounces:(BOOL)bodyBounces { 585 | _bodyBounces = bodyBounces; 586 | self.bodyView.bounces = _bodyBounces; 587 | } 588 | 589 | - (void)setTabItemFont:(UIFont *)tabItemFont { 590 | _tabItemFont = tabItemFont; 591 | for(NSInteger i = 0; i < _numberOfTabItems; i++) { 592 | LXPageTabItemLable *tabItem = _tabItems[i]; 593 | tabItem.font = _tabItemFont; 594 | } 595 | } 596 | 597 | - (void)setTitleStyle:(LXPageTabTitleStyle)titleStyle { 598 | if(_titleStyle == LXPageTabTitleStyleDefault) { 599 | _titleStyle = titleStyle; 600 | if(_titleStyle == LXPageTabTitleStyleGradient) { 601 | [self resetTabItemScale]; 602 | } 603 | } 604 | } 605 | 606 | - (void)setIndicatorStyle:(LXPageTabIndicatorStyle)indicatorStyle { 607 | if(_indicatorStyle == LXPageTabIndicatorStyleDefault) { 608 | _indicatorStyle = indicatorStyle; 609 | [self addIndicatorViewWithStyle]; 610 | } 611 | } 612 | 613 | - (void)setMinScale:(CGFloat)minScale { 614 | if(minScale > 0 && minScale <= 1) { 615 | _minScale = minScale; 616 | if(_titleStyle == LXPageTabTitleStyleGradient) { 617 | [self resetTabItemScale]; 618 | } 619 | } 620 | } 621 | 622 | @end 623 | -------------------------------------------------------------------------------- /LXSegmentControl/Lib/XXPageTab/XXPageTabView.m: -------------------------------------------------------------------------------- 1 | // 2 | // XXPageTabView.m 3 | // XXPageTabDemo 4 | // 5 | // Created by HJTXX on 2017/2/27. 6 | // Copyright © 2017年 HJTXX. All rights reserved. 7 | // 8 | 9 | #import "XXPageTabView.h" 10 | 11 | #define kTabDefautHeight 38.0 12 | #define kTabDefautFontSize 15.0 13 | #define kMaxNumberOfPageItems 4 14 | #define kIndicatorHeight 2.0 15 | #define kIndicatorWidth 20 16 | #define kMinScale 0.8 17 | 18 | #define HEIGHT(view) view.bounds.size.height 19 | #define WIDTH(view) view.bounds.size.width 20 | #define ORIGIN_X(view) view.frame.origin.x 21 | #define ORIGIN_Y(view) view.frame.origin.y 22 | 23 | @interface XXPageTabView () 24 | //bg 25 | @property (nonatomic, strong) UIView *bgView; //由于遇到nav->vc,vc的第一个子试图是UIScrollView会自动产生64像素偏移,所以加上一个虚拟背景(没有尺寸) 26 | 27 | //tab 28 | @property (nonatomic, strong) UIScrollView *tabView; 29 | @property (nonatomic, strong) UIView *indicatorView; 30 | 31 | //body 32 | @property (nonatomic, strong) UIScrollView *bodyView; 33 | 34 | //data 35 | @property (nonatomic, assign) NSInteger lastSelectedTabIndex; //记录上一次的索引 36 | @property (nonatomic, assign) NSInteger numberOfTabItems; 37 | @property (nonatomic, assign) CGFloat tabItemWidth; 38 | @property (nonatomic, strong) NSMutableArray *tabItems; 39 | @property (nonatomic, strong) NSArray *childControllers; 40 | @property (nonatomic, strong) NSArray *childTitles; 41 | 42 | //animation 43 | @property (nonatomic, assign) BOOL isNeedRefreshLayout; //滑动过程中不允许layoutSubviews 44 | @property (nonatomic, assign) BOOL isChangeByClick; //是否是通过点击改变的。因为点击可以长距离点击,部分效果不作处理会出现途中经过的按钮也会依次有效果(仿网易客户端有此效果,个人觉得并不好,头条的客户端更合理) 45 | @property (nonatomic, assign) NSInteger leftItemIndex; //记录滑动时左边的itemIndex 46 | @property (nonatomic, assign) NSInteger rightItemIndex; //记录滑动时右边的itemIndex 47 | 48 | /*XXPageTabTitleStyleScale*/ 49 | @property (nonatomic, assign) CGFloat selectedColorR; 50 | @property (nonatomic, assign) CGFloat selectedColorG; 51 | @property (nonatomic, assign) CGFloat selectedColorB; 52 | @property (nonatomic, assign) CGFloat unSelectedColorR; 53 | @property (nonatomic, assign) CGFloat unSelectedColorG; 54 | @property (nonatomic, assign) CGFloat unSelectedColorB; 55 | 56 | @end 57 | 58 | @implementation XXPageTabView 59 | 60 | #pragma mark - Life cycle 61 | - (instancetype)initWithChildControllers:(NSArray *)childControllers 62 | childTitles:(NSArray *)childTitles { 63 | self = [super init]; 64 | if(self) { 65 | _childControllers = childControllers; 66 | _childTitles = childTitles; 67 | 68 | [self initBaseSettings]; 69 | [self initTabView]; 70 | [self initMainView]; 71 | } 72 | return self; 73 | } 74 | 75 | - (void)layoutSubviews { 76 | if(_isNeedRefreshLayout) { 77 | //tab layout 78 | if(_tabSize.height <= 0) { 79 | _tabSize.height = kTabDefautHeight; 80 | } 81 | if(_tabSize.width <= 0) { 82 | _tabSize.width = WIDTH(self); 83 | } 84 | _tabItemWidth = _tabSize.width/(_numberOfTabItems<_maxNumberOfPageItems?_numberOfTabItems:_maxNumberOfPageItems); 85 | 86 | self.tabView.frame = CGRectMake(0, 0, _tabSize.width, _tabSize.height); 87 | self.tabView.contentSize = CGSizeMake(_tabItemWidth*_numberOfTabItems, 0); 88 | 89 | for(NSInteger i = 0; i < _tabItems.count; i++) { 90 | XXPageTabItemLable *tabItem = (XXPageTabItemLable *)_tabItems[i]; 91 | tabItem.frame = CGRectMake(_tabItemWidth*i, 0, _tabItemWidth, _tabSize.height); 92 | } 93 | [self layoutIndicatorViewWithStyle]; 94 | 95 | //body layout 96 | self.bodyView.frame = CGRectMake(0, _tabSize.height, WIDTH(self), HEIGHT(self)-_tabSize.height); 97 | self.bodyView.contentSize = CGSizeMake(WIDTH(self)*_numberOfTabItems, 0); 98 | self.bodyView.contentOffset = CGPointMake(self.frame.size.width*_selectedTabIndex, 0); 99 | [self reviseTabContentOffsetBySelectedIndex:NO]; 100 | 101 | for(NSInteger i = 0; i < _numberOfTabItems; i++) { 102 | UIViewController *childController = _childControllers[i]; 103 | childController.view.frame = CGRectMake(WIDTH(self)*i, 0, WIDTH(self), HEIGHT(self)-_tabSize.height); 104 | } 105 | } 106 | } 107 | 108 | #pragma mark - Layout 109 | - (void)initBaseSettings { 110 | _selectedTabIndex = 0; 111 | _lastSelectedTabIndex = 0; 112 | _tabSize = CGSizeZero; 113 | _numberOfTabItems = _childControllers.count>_childTitles.count?_childTitles.count:_childControllers.count; 114 | _tabItemFont = [UIFont systemFontOfSize:kTabDefautFontSize]; 115 | _indicatorHeight = kIndicatorHeight; 116 | _indicatorWidth = kIndicatorWidth; 117 | _maxNumberOfPageItems = kMaxNumberOfPageItems; 118 | _tabItems = [NSMutableArray array]; 119 | _tabBackgroundColor = [UIColor whiteColor]; 120 | _bodyBackgroundColor = [UIColor whiteColor]; 121 | _unSelectedColor = [UIColor blackColor]; 122 | _selectedColor = [UIColor redColor]; 123 | _isNeedRefreshLayout = YES; 124 | _isChangeByClick = NO; 125 | _bodyBounces = YES; 126 | _titleStyle = XXPageTabTitleStyleDefault; 127 | _indicatorStyle = XXPageTabIndicatorStyleDefault; 128 | _minScale = kMinScale; 129 | _selectedColorR = 1; 130 | _selectedColorG = 0; 131 | _selectedColorB = 0; 132 | _unSelectedColorR = 0; 133 | _unSelectedColorG = 0; 134 | _unSelectedColorB = 0; 135 | } 136 | 137 | - (void)initTabView { 138 | [self addSubview:self.bgView]; 139 | [self addSubview:self.tabView]; 140 | 141 | for(NSInteger i = 0; i < _numberOfTabItems; i++) { 142 | XXPageTabItemLable *tabItem = [[XXPageTabItemLable alloc] init]; 143 | tabItem.font = _tabItemFont; 144 | tabItem.text = _childTitles[i]; 145 | tabItem.textColor = i==_selectedTabIndex?_selectedColor:_unSelectedColor; 146 | tabItem.textAlignment = NSTextAlignmentCenter; 147 | tabItem.userInteractionEnabled = YES; 148 | 149 | UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(changeChildControllerOnClick:)]; 150 | [tabItem addGestureRecognizer:tapRecognizer]; 151 | [_tabItems addObject:tabItem]; 152 | [self.tabView addSubview:tabItem]; 153 | } 154 | } 155 | 156 | - (void)initMainView { 157 | [self addSubview:self.bodyView]; 158 | for(NSInteger i = 0; i < _numberOfTabItems; i++) { 159 | UIViewController *childController = _childControllers[i]; 160 | [self.bodyView addSubview:childController.view]; 161 | } 162 | } 163 | 164 | /** 165 | 根据选择项修正tab的展示区域 166 | */ 167 | - (void)reviseTabContentOffsetBySelectedIndex:(BOOL)isAnimate { 168 | XXPageTabItemLable *currentTabItem = _tabItems[_selectedTabIndex]; 169 | CGFloat selectedItemCenterX = currentTabItem.center.x; 170 | 171 | CGFloat reviseX; 172 | if(selectedItemCenterX + _tabSize.width/2.0 >= self.tabView.contentSize.width) { 173 | reviseX = self.tabView.contentSize.width - _tabSize.width; //不足以到中心,靠右 174 | } else if(selectedItemCenterX - _tabSize.width/2.0 <= 0) { 175 | reviseX = 0; //不足以到中心,靠左 176 | } else { 177 | reviseX = selectedItemCenterX - _tabSize.width/2.0; //修正至中心 178 | } 179 | //如果前后没有偏移量差,setContentOffset实际不起作用;或者没有动画效果 180 | if(fabs(self.tabView.contentOffset.x - reviseX)<1 || !isAnimate) { 181 | [self finishReviseTabContentOffset]; 182 | } 183 | [self.tabView setContentOffset:CGPointMake(reviseX, 0) animated:isAnimate]; 184 | } 185 | 186 | /** 187 | tabview修正完成后的操作,无论是点击还是滑动body,此方法都是真正意义上的最后一步 188 | */ 189 | - (void)finishReviseTabContentOffset { 190 | _tabView.userInteractionEnabled = YES; 191 | _isNeedRefreshLayout = YES; 192 | _isChangeByClick = NO; 193 | if([self.delegate respondsToSelector:@selector(pageTabViewDidEndChange)]) { 194 | if(_lastSelectedTabIndex != _selectedTabIndex) { 195 | [self.delegate pageTabViewDidEndChange]; 196 | } 197 | } 198 | _lastSelectedTabIndex = _selectedTabIndex; 199 | } 200 | 201 | /** 202 | 一般常用改变selected Item方法(无动画效果,直接变色) 203 | */ 204 | - (void)changeSelectedItemToNextItem:(NSInteger)nextIndex { 205 | XXPageTabItemLable *currentTabItem = _tabItems[_selectedTabIndex]; 206 | XXPageTabItemLable *nextTabItem = _tabItems[nextIndex]; 207 | currentTabItem.textColor = _unSelectedColor; 208 | nextTabItem.textColor = _selectedColor; 209 | } 210 | 211 | #pragma mark -Title layout 212 | /** 213 | 重新设置item的缩放比例 214 | */ 215 | - (void)resetTabItemScale { 216 | for(NSInteger i = 0; i < _numberOfTabItems; i++) { 217 | XXPageTabItemLable *tabItem = _tabItems[i]; 218 | if(i != _selectedTabIndex) { 219 | tabItem.transform = CGAffineTransformMakeScale(_minScale, _minScale); 220 | } else { 221 | tabItem.transform = CGAffineTransformMakeScale(1, 1); 222 | } 223 | } 224 | } 225 | 226 | #pragma mark -Indicator layout 227 | /** 228 | 根据不同风格添加相应下标 229 | */ 230 | - (void)addIndicatorViewWithStyle { 231 | switch (_indicatorStyle) { 232 | case XXPageTabIndicatorStyleDefault: 233 | case XXPageTabIndicatorStyleFollowText: 234 | case XXPageTabIndicatorStyleStretch: 235 | [self addSubview:self.indicatorView]; 236 | break; 237 | default: 238 | break; 239 | } 240 | } 241 | 242 | /** 243 | 根据不同风格对下标layout 244 | */ 245 | - (void)layoutIndicatorViewWithStyle { 246 | switch (_indicatorStyle) { 247 | case XXPageTabIndicatorStyleDefault: 248 | case XXPageTabIndicatorStyleFollowText: 249 | case XXPageTabIndicatorStyleStretch: 250 | [self layoutIndicatorView]; 251 | break; 252 | default: 253 | break; 254 | } 255 | } 256 | 257 | - (void)layoutIndicatorView { 258 | CGFloat indicatorWidth = [self getIndicatorWidthWithTitle:_childTitles[_selectedTabIndex]]; 259 | XXPageTabItemLable *selecedTabItem = _tabItems[_selectedTabIndex]; 260 | self.indicatorView.frame = CGRectMake(selecedTabItem.center.x-indicatorWidth/2.0-_tabView.contentOffset.x, _tabSize.height-_indicatorHeight, indicatorWidth, _indicatorHeight); 261 | } 262 | 263 | #pragma mark - Event response 264 | - (void)changeChildControllerOnClick:(UITapGestureRecognizer *)tap { 265 | NSInteger nextIndex = [_tabItems indexOfObject:tap.view]; 266 | if(nextIndex != _selectedTabIndex) { 267 | if(_titleStyle == XXPageTabTitleStyleDefault) { 268 | [self changeSelectedItemToNextItem:nextIndex]; 269 | } 270 | 271 | _isChangeByClick = YES; 272 | _tabView.userInteractionEnabled = NO; //防止快速切换 273 | _leftItemIndex = nextIndex > _selectedTabIndex?_selectedTabIndex:nextIndex; 274 | _rightItemIndex = nextIndex > _selectedTabIndex?nextIndex:_selectedTabIndex; 275 | _selectedTabIndex = nextIndex; 276 | [self.bodyView setContentOffset:CGPointMake(self.frame.size.width*_selectedTabIndex, 0) animated:YES]; 277 | } 278 | } 279 | 280 | #pragma mark - UIScrollViewDelegate 281 | - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { 282 | if(scrollView == self.bodyView) { 283 | _selectedTabIndex = self.bodyView.contentOffset.x/WIDTH(self.bodyView); 284 | [self reviseTabContentOffsetBySelectedIndex:YES]; 285 | } 286 | } 287 | 288 | - (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView { 289 | if(scrollView == self.bodyView) { 290 | [self reviseTabContentOffsetBySelectedIndex:YES]; 291 | } else { 292 | [self finishReviseTabContentOffset]; 293 | } 294 | } 295 | 296 | - (void)scrollViewDidScroll:(UIScrollView *)scrollView { 297 | if(scrollView == self.tabView) { 298 | _isNeedRefreshLayout = NO; 299 | if(self.indicatorView.superview) { 300 | XXPageTabItemLable *selecedTabItem = _tabItems[_selectedTabIndex]; 301 | self.indicatorView.frame = CGRectMake(selecedTabItem.center.x-WIDTH(self.indicatorView)/2.0-scrollView.contentOffset.x, ORIGIN_Y(self.indicatorView), WIDTH(self.indicatorView), HEIGHT(self.indicatorView)); 302 | } 303 | } else if(scrollView == self.bodyView) { 304 | //未初始化时不处理 305 | if(self.bodyView.contentSize.width <= 0) { 306 | return; 307 | } 308 | //滚动过程中不允许layout 309 | _isNeedRefreshLayout = NO; 310 | //获取当前左右item index(点击方式已获知左右index,无需根据contentoffset计算) 311 | if(!_isChangeByClick) { 312 | if(self.bodyView.contentOffset.x <= 0) { //左边界 313 | _leftItemIndex = 0; 314 | _rightItemIndex = 0; 315 | 316 | } else if(self.bodyView.contentOffset.x >= self.bodyView.contentSize.width-WIDTH(self.bodyView)) { //右边界 317 | _leftItemIndex = _numberOfTabItems-1; 318 | _rightItemIndex = _numberOfTabItems-1; 319 | 320 | } else { 321 | _leftItemIndex = (int)(self.bodyView.contentOffset.x/WIDTH(self.bodyView)); 322 | _rightItemIndex = _leftItemIndex + 1; 323 | } 324 | } 325 | 326 | //调整title 327 | switch (_titleStyle) { 328 | case XXPageTabTitleStyleDefault: 329 | [self changeTitleWithDefault]; 330 | break; 331 | case XXPageTabTitleStyleGradient: 332 | [self changeTitleWithGradient]; 333 | break; 334 | case XXPageTabTitleStyleBlend: 335 | [self changeTitleWithBlend]; 336 | break; 337 | default: 338 | break; 339 | } 340 | 341 | //调整indicator 342 | switch (_indicatorStyle) { 343 | case XXPageTabIndicatorStyleDefault: 344 | case XXPageTabIndicatorStyleFollowText: 345 | [self changeIndicatorFrame]; 346 | break; 347 | case XXPageTabIndicatorStyleStretch: 348 | { 349 | if(_isChangeByClick) { 350 | [self changeIndicatorFrame]; 351 | } else { 352 | [self changeIndicatorFrameByStretch]; 353 | } 354 | } 355 | break; 356 | default: 357 | break; 358 | } 359 | } 360 | } 361 | 362 | #pragma mark - Title animation 363 | - (void)changeTitleWithDefault { 364 | CGFloat relativeLocation = self.bodyView.contentOffset.x/WIDTH(self.bodyView)-_leftItemIndex; 365 | if(!_isChangeByClick) { 366 | if(relativeLocation > 0.5) { 367 | [self changeSelectedItemToNextItem:_rightItemIndex]; 368 | _selectedTabIndex = _rightItemIndex; 369 | } else { 370 | [self changeSelectedItemToNextItem:_leftItemIndex]; 371 | _selectedTabIndex = _leftItemIndex; 372 | } 373 | } 374 | } 375 | 376 | - (void)changeTitleWithGradient { 377 | if(_leftItemIndex != _rightItemIndex) { 378 | CGFloat rightScale = (self.bodyView.contentOffset.x/WIDTH(self.bodyView)-_leftItemIndex)/(_rightItemIndex-_leftItemIndex); 379 | CGFloat leftScale = 1-rightScale; 380 | 381 | //颜色渐变 382 | CGFloat difR = _selectedColorR-_unSelectedColorR; 383 | CGFloat difG = _selectedColorG-_unSelectedColorG; 384 | CGFloat difB = _selectedColorB-_unSelectedColorB; 385 | 386 | UIColor *leftItemColor = [UIColor colorWithRed:_unSelectedColorR+leftScale*difR green:_unSelectedColorG+leftScale*difG blue:_unSelectedColorB+leftScale*difB alpha:1]; 387 | UIColor *rightItemColor = [UIColor colorWithRed:_unSelectedColorR+rightScale*difR green:_unSelectedColorG+rightScale*difG blue:_unSelectedColorB+rightScale*difB alpha:1]; 388 | 389 | XXPageTabItemLable *leftTabItem = _tabItems[_leftItemIndex]; 390 | XXPageTabItemLable *rightTabItem = _tabItems[_rightItemIndex]; 391 | leftTabItem.textColor = leftItemColor; 392 | rightTabItem.textColor = rightItemColor; 393 | 394 | //字体渐变 395 | leftTabItem.transform = CGAffineTransformMakeScale(_minScale+(1-_minScale)*leftScale, _minScale+(1-_minScale)*leftScale); 396 | rightTabItem.transform = CGAffineTransformMakeScale(_minScale+(1-_minScale)*rightScale, _minScale+(1-_minScale)*rightScale); 397 | } 398 | } 399 | 400 | - (void)changeTitleWithBlend { 401 | CGFloat leftScale = self.bodyView.contentOffset.x/WIDTH(self.bodyView)-_leftItemIndex; 402 | if(leftScale == 0) { 403 | return; //起点和终点不处理,终点时左右index已更新,会绘画错误(你可以注释看看) 404 | } 405 | 406 | XXPageTabItemLable *leftTabItem = _tabItems[_leftItemIndex]; 407 | XXPageTabItemLable *rightTabItem = _tabItems[_rightItemIndex]; 408 | 409 | leftTabItem.textColor = _selectedColor; 410 | rightTabItem.textColor = _unSelectedColor; 411 | leftTabItem.fillColor = _unSelectedColor; 412 | rightTabItem.fillColor = _selectedColor; 413 | leftTabItem.process = leftScale; 414 | rightTabItem.process = leftScale; 415 | } 416 | 417 | #pragma mark - Indicator animation 418 | - (void)changeIndicatorFrame { 419 | //计算indicator此时的centerx 420 | CGFloat nowIndicatorCenterX = _tabItemWidth*(0.5+self.bodyView.contentOffset.x/WIDTH(self.bodyView)); 421 | //计算此时body的偏移量在一页中的占比 422 | CGFloat relativeLocation = (self.bodyView.contentOffset.x/WIDTH(self.bodyView)-_leftItemIndex)/(_rightItemIndex-_leftItemIndex); 423 | //记录左右对应的indicator宽度 424 | CGFloat leftIndicatorWidth = [self getIndicatorWidthWithTitle:_childTitles[_leftItemIndex]]; 425 | CGFloat rightIndicatorWidth = [self getIndicatorWidthWithTitle:_childTitles[_rightItemIndex]]; 426 | 427 | //左右边界的时候,占比清0 428 | if(_leftItemIndex == _rightItemIndex) { 429 | relativeLocation = 0; 430 | } 431 | //基于从左到右方向(无需考虑滑动方向),计算当前中心轴所处位置的长度 432 | CGFloat nowIndicatorWidth = leftIndicatorWidth + (rightIndicatorWidth-leftIndicatorWidth)*relativeLocation; 433 | 434 | self.indicatorView.frame = CGRectMake(nowIndicatorCenterX-nowIndicatorWidth/2.0-_tabView.contentOffset.x, ORIGIN_Y(self.indicatorView), nowIndicatorWidth, HEIGHT(self.indicatorView)); 435 | } 436 | 437 | - (void)changeIndicatorFrameByStretch { 438 | if(_indicatorWidth <= 0) { 439 | return; 440 | } 441 | 442 | //计算此时body的偏移量在一页中的占比 443 | CGFloat relativeLocation = (self.bodyView.contentOffset.x/WIDTH(self.bodyView)-_leftItemIndex)/(_rightItemIndex-_leftItemIndex); 444 | //左右边界的时候,占比清0 445 | if(_leftItemIndex == _rightItemIndex) { 446 | relativeLocation = 0; 447 | } 448 | 449 | XXPageTabItemLable *leftTabItem = _tabItems[_leftItemIndex]; 450 | XXPageTabItemLable *rightTabItem = _tabItems[_rightItemIndex]; 451 | 452 | //当前的frame 453 | CGRect nowFrame = CGRectMake(0, ORIGIN_Y(self.indicatorView), 0, HEIGHT(self.indicatorView)); 454 | 455 | //计算宽度 456 | if(relativeLocation <= 0.5) { 457 | nowFrame.size.width = _indicatorWidth+_tabItemWidth*(relativeLocation/0.5); 458 | nowFrame.origin.x = (leftTabItem.center.x-self.tabView.contentOffset.x)-_indicatorWidth/2.0; 459 | } else { 460 | nowFrame.size.width = _indicatorWidth+_tabItemWidth*((1-relativeLocation)/0.5); 461 | nowFrame.origin.x = (rightTabItem.center.x-self.tabView.contentOffset.x)+_indicatorWidth/2.0-nowFrame.size.width; 462 | } 463 | 464 | self.indicatorView.frame = nowFrame; 465 | } 466 | 467 | #pragma mark - Tool 468 | /** 469 | 根据对应文本计算下标线宽度 470 | */ 471 | - (CGFloat)getIndicatorWidthWithTitle:(NSString *)title { 472 | if(_indicatorStyle == XXPageTabIndicatorStyleDefault || _indicatorStyle == XXPageTabIndicatorStyleStretch) { 473 | return _indicatorWidth; 474 | } else { 475 | if(title.length <= 2) { 476 | return 40; 477 | } else { 478 | return title.length * _tabItemFont.pointSize + 12; 479 | } 480 | } 481 | } 482 | 483 | /** 484 | 获取color的rgb值 485 | */ 486 | - (NSArray *)getRGBWithColor:(UIColor *)color { 487 | CGFloat R, G, B; 488 | NSInteger numComponents = CGColorGetNumberOfComponents(color.CGColor); 489 | if(numComponents == 4) { 490 | const CGFloat *components = CGColorGetComponents(color.CGColor); 491 | R = components[0]; 492 | G = components[1]; 493 | B = components[2]; 494 | } 495 | return @[@(R), @(G), @(B)]; 496 | } 497 | 498 | #pragma mark - Getter/setter 499 | - (UIView *)bgView { 500 | if(!_bgView) { 501 | _bgView = [UIView new]; 502 | } 503 | return _bgView; 504 | } 505 | 506 | - (UIScrollView *)tabView { 507 | if(!_tabView) { 508 | _tabView = [UIScrollView new]; 509 | _tabView.showsVerticalScrollIndicator = NO; 510 | _tabView.showsHorizontalScrollIndicator = NO; 511 | _tabView.backgroundColor = _tabBackgroundColor; 512 | _tabView.delegate = self; 513 | _tabView.clipsToBounds = YES; 514 | } 515 | return _tabView; 516 | } 517 | 518 | - (UIScrollView *)bodyView { 519 | if(!_bodyView) { 520 | _bodyView = [UIScrollView new]; 521 | _bodyView.pagingEnabled = YES; 522 | _bodyView.showsVerticalScrollIndicator = NO; 523 | _bodyView.showsHorizontalScrollIndicator = NO; 524 | _bodyView.delegate = self; 525 | _bodyView.bounces = _bodyBounces; 526 | _bodyView.backgroundColor = _bodyBackgroundColor; 527 | } 528 | return _bodyView; 529 | } 530 | 531 | - (UIView *)indicatorView { 532 | if(!_indicatorView) { 533 | _indicatorView = [UIView new]; 534 | _indicatorView.backgroundColor = _selectedColor; 535 | } 536 | return _indicatorView; 537 | } 538 | 539 | - (void)setTabBackgroundColor:(UIColor *)tabBackgroundColor { 540 | _tabBackgroundColor = tabBackgroundColor; 541 | self.tabView.backgroundColor = _tabBackgroundColor; 542 | } 543 | 544 | - (void)setBodyBackgroundColor:(UIColor *)bodyBackgroundColor { 545 | _bodyBackgroundColor = bodyBackgroundColor; 546 | self.bodyView.backgroundColor = _bodyBackgroundColor; 547 | } 548 | 549 | - (void)setSelectedTabIndex:(NSInteger)selectedTabIndex { 550 | if(selectedTabIndex >= 0 && selectedTabIndex < _numberOfTabItems && _selectedTabIndex != selectedTabIndex) { 551 | [self changeSelectedItemToNextItem:selectedTabIndex]; 552 | _selectedTabIndex = selectedTabIndex; 553 | _lastSelectedTabIndex = selectedTabIndex; 554 | [self layoutIndicatorViewWithStyle]; 555 | self.bodyView.contentOffset = CGPointMake(WIDTH(self)*_selectedTabIndex, 0); 556 | 557 | if(_titleStyle == XXPageTabTitleStyleGradient) { 558 | [self resetTabItemScale]; 559 | } 560 | } 561 | } 562 | 563 | - (void)setUnSelectedColor:(UIColor *)unSelectedColor { 564 | _unSelectedColor = unSelectedColor; 565 | for(NSInteger i = 0; i < _numberOfTabItems; i++) { 566 | XXPageTabItemLable *tabItem = _tabItems[i]; 567 | tabItem.textColor = i==_selectedTabIndex?_selectedColor:_unSelectedColor; 568 | } 569 | NSArray *rgb = [self getRGBWithColor:_unSelectedColor]; 570 | _unSelectedColorR = [rgb[0] floatValue]; 571 | _unSelectedColorG = [rgb[1] floatValue]; 572 | _unSelectedColorB = [rgb[2] floatValue]; 573 | } 574 | 575 | - (void)setSelectedColor:(UIColor *)selectedColor { 576 | _selectedColor = selectedColor; 577 | XXPageTabItemLable *tabItem = _tabItems[_selectedTabIndex]; 578 | tabItem.textColor = _selectedColor; 579 | self.indicatorView.backgroundColor = _selectedColor; 580 | 581 | NSArray *rgb = [self getRGBWithColor:_selectedColor]; 582 | _selectedColorR = [rgb[0] floatValue]; 583 | _selectedColorG = [rgb[1] floatValue]; 584 | _selectedColorB = [rgb[2] floatValue]; 585 | } 586 | 587 | - (void)setBodyBounces:(BOOL)bodyBounces { 588 | _bodyBounces = bodyBounces; 589 | self.bodyView.bounces = _bodyBounces; 590 | } 591 | 592 | - (void)setTabItemFont:(UIFont *)tabItemFont { 593 | _tabItemFont = tabItemFont; 594 | for(NSInteger i = 0; i < _numberOfTabItems; i++) { 595 | XXPageTabItemLable *tabItem = _tabItems[i]; 596 | tabItem.font = _tabItemFont; 597 | } 598 | } 599 | 600 | - (void)setTitleStyle:(XXPageTabTitleStyle)titleStyle { 601 | if(_titleStyle == XXPageTabTitleStyleDefault) { 602 | _titleStyle = titleStyle; 603 | if(_titleStyle == XXPageTabTitleStyleGradient) { 604 | [self resetTabItemScale]; 605 | } 606 | } 607 | } 608 | 609 | - (void)setIndicatorStyle:(XXPageTabIndicatorStyle)indicatorStyle { 610 | if(_indicatorStyle == XXPageTabIndicatorStyleDefault) { 611 | _indicatorStyle = indicatorStyle; 612 | [self addIndicatorViewWithStyle]; 613 | } 614 | } 615 | 616 | - (void)setMinScale:(CGFloat)minScale { 617 | if(minScale > 0 && minScale <= 1) { 618 | _minScale = minScale; 619 | if(_titleStyle == XXPageTabTitleStyleGradient) { 620 | [self resetTabItemScale]; 621 | } 622 | } 623 | } 624 | 625 | @end 626 | -------------------------------------------------------------------------------- /LXSegmentControl.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 2436BCF121B4CDC500E8D063 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 2436BCF021B4CDC500E8D063 /* AppDelegate.m */; }; 11 | 2436BCF421B4CDC500E8D063 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 2436BCF321B4CDC500E8D063 /* ViewController.m */; }; 12 | 2436BCF721B4CDC500E8D063 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 2436BCF521B4CDC500E8D063 /* Main.storyboard */; }; 13 | 2436BCF921B4CDC700E8D063 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2436BCF821B4CDC700E8D063 /* Assets.xcassets */; }; 14 | 2436BCFC21B4CDC700E8D063 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 2436BCFA21B4CDC700E8D063 /* LaunchScreen.storyboard */; }; 15 | 2436BCFF21B4CDC700E8D063 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 2436BCFE21B4CDC700E8D063 /* main.m */; }; 16 | 2436BD0921B4CDC700E8D063 /* LXSegmentControlTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 2436BD0821B4CDC700E8D063 /* LXSegmentControlTests.m */; }; 17 | 2436BD1421B4CDC700E8D063 /* LXSegmentControlUITests.m in Sources */ = {isa = PBXBuildFile; fileRef = 2436BD1321B4CDC700E8D063 /* LXSegmentControlUITests.m */; }; 18 | 2436BD3B21B4CFD000E8D063 /* UIColor+LX.m in Sources */ = {isa = PBXBuildFile; fileRef = 2436BD2421B4CFD000E8D063 /* UIColor+LX.m */; }; 19 | 2436BD3C21B4CFD000E8D063 /* UIImage+LX.m in Sources */ = {isa = PBXBuildFile; fileRef = 2436BD2621B4CFD000E8D063 /* UIImage+LX.m */; }; 20 | 2436BD5B21B4D22F00E8D063 /* LXSegmentType_0ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 2436BD5A21B4D22F00E8D063 /* LXSegmentType_0ViewController.m */; }; 21 | 2436BD5E21B4D23A00E8D063 /* LXSegmentType_1ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 2436BD5D21B4D23A00E8D063 /* LXSegmentType_1ViewController.m */; }; 22 | 2436BD6121B4D57800E8D063 /* LXSegmentTitleViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 2436BD6021B4D57800E8D063 /* LXSegmentTitleViewController.m */; }; 23 | 2436BD6721B4FCEB00E8D063 /* XXPageTabItemLable.m in Sources */ = {isa = PBXBuildFile; fileRef = 2436BD6321B4FCEB00E8D063 /* XXPageTabItemLable.m */; }; 24 | 2436BD6821B4FCEB00E8D063 /* XXPageTabView.m in Sources */ = {isa = PBXBuildFile; fileRef = 2436BD6421B4FCEB00E8D063 /* XXPageTabView.m */; }; 25 | 2436BD6F21B4FCF200E8D063 /* 三角形@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 2436BD6B21B4FCF200E8D063 /* 三角形@2x.png */; }; 26 | 2436BD7021B4FCF200E8D063 /* LXPageTabItemLable.m in Sources */ = {isa = PBXBuildFile; fileRef = 2436BD6C21B4FCF200E8D063 /* LXPageTabItemLable.m */; }; 27 | 2436BD7121B4FCF200E8D063 /* LXPageTabView.m in Sources */ = {isa = PBXBuildFile; fileRef = 2436BD6D21B4FCF200E8D063 /* LXPageTabView.m */; }; 28 | /* End PBXBuildFile section */ 29 | 30 | /* Begin PBXContainerItemProxy section */ 31 | 2436BD0521B4CDC700E8D063 /* PBXContainerItemProxy */ = { 32 | isa = PBXContainerItemProxy; 33 | containerPortal = 2436BCE421B4CDC500E8D063 /* Project object */; 34 | proxyType = 1; 35 | remoteGlobalIDString = 2436BCEB21B4CDC500E8D063; 36 | remoteInfo = LXSegmentControl; 37 | }; 38 | 2436BD1021B4CDC700E8D063 /* PBXContainerItemProxy */ = { 39 | isa = PBXContainerItemProxy; 40 | containerPortal = 2436BCE421B4CDC500E8D063 /* Project object */; 41 | proxyType = 1; 42 | remoteGlobalIDString = 2436BCEB21B4CDC500E8D063; 43 | remoteInfo = LXSegmentControl; 44 | }; 45 | /* End PBXContainerItemProxy section */ 46 | 47 | /* Begin PBXFileReference section */ 48 | 2436BCEC21B4CDC500E8D063 /* LXSegmentControl.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = LXSegmentControl.app; sourceTree = BUILT_PRODUCTS_DIR; }; 49 | 2436BCEF21B4CDC500E8D063 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 50 | 2436BCF021B4CDC500E8D063 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 51 | 2436BCF221B4CDC500E8D063 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 52 | 2436BCF321B4CDC500E8D063 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 53 | 2436BCF621B4CDC500E8D063 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 54 | 2436BCF821B4CDC700E8D063 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 55 | 2436BCFB21B4CDC700E8D063 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 56 | 2436BCFD21B4CDC700E8D063 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 57 | 2436BCFE21B4CDC700E8D063 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 58 | 2436BD0421B4CDC700E8D063 /* LXSegmentControlTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = LXSegmentControlTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 59 | 2436BD0821B4CDC700E8D063 /* LXSegmentControlTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LXSegmentControlTests.m; sourceTree = ""; }; 60 | 2436BD0A21B4CDC700E8D063 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 61 | 2436BD0F21B4CDC700E8D063 /* LXSegmentControlUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = LXSegmentControlUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 62 | 2436BD1321B4CDC700E8D063 /* LXSegmentControlUITests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LXSegmentControlUITests.m; sourceTree = ""; }; 63 | 2436BD1521B4CDC700E8D063 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 64 | 2436BD2321B4CFD000E8D063 /* UIImage+LX.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIImage+LX.h"; sourceTree = ""; }; 65 | 2436BD2421B4CFD000E8D063 /* UIColor+LX.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIColor+LX.m"; sourceTree = ""; }; 66 | 2436BD2621B4CFD000E8D063 /* UIImage+LX.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIImage+LX.m"; sourceTree = ""; }; 67 | 2436BD2721B4CFD000E8D063 /* UIColor+LX.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIColor+LX.h"; sourceTree = ""; }; 68 | 2436BD4521B4CFD500E8D063 /* LX_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LX_Prefix.pch; sourceTree = ""; }; 69 | 2436BD5921B4D22F00E8D063 /* LXSegmentType_0ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LXSegmentType_0ViewController.h; sourceTree = ""; }; 70 | 2436BD5A21B4D22F00E8D063 /* LXSegmentType_0ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LXSegmentType_0ViewController.m; sourceTree = ""; }; 71 | 2436BD5C21B4D23A00E8D063 /* LXSegmentType_1ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LXSegmentType_1ViewController.h; sourceTree = ""; }; 72 | 2436BD5D21B4D23A00E8D063 /* LXSegmentType_1ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LXSegmentType_1ViewController.m; sourceTree = ""; }; 73 | 2436BD5F21B4D57800E8D063 /* LXSegmentTitleViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LXSegmentTitleViewController.h; sourceTree = ""; }; 74 | 2436BD6021B4D57800E8D063 /* LXSegmentTitleViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LXSegmentTitleViewController.m; sourceTree = ""; }; 75 | 2436BD6321B4FCEB00E8D063 /* XXPageTabItemLable.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XXPageTabItemLable.m; sourceTree = ""; }; 76 | 2436BD6421B4FCEB00E8D063 /* XXPageTabView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XXPageTabView.m; sourceTree = ""; }; 77 | 2436BD6521B4FCEB00E8D063 /* XXPageTabView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XXPageTabView.h; sourceTree = ""; }; 78 | 2436BD6621B4FCEB00E8D063 /* XXPageTabItemLable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XXPageTabItemLable.h; sourceTree = ""; }; 79 | 2436BD6A21B4FCF200E8D063 /* LXPageTabView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LXPageTabView.h; sourceTree = ""; }; 80 | 2436BD6B21B4FCF200E8D063 /* 三角形@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "三角形@2x.png"; sourceTree = ""; }; 81 | 2436BD6C21B4FCF200E8D063 /* LXPageTabItemLable.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LXPageTabItemLable.m; sourceTree = ""; }; 82 | 2436BD6D21B4FCF200E8D063 /* LXPageTabView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LXPageTabView.m; sourceTree = ""; }; 83 | 2436BD6E21B4FCF200E8D063 /* LXPageTabItemLable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LXPageTabItemLable.h; sourceTree = ""; }; 84 | /* End PBXFileReference section */ 85 | 86 | /* Begin PBXFrameworksBuildPhase section */ 87 | 2436BCE921B4CDC500E8D063 /* Frameworks */ = { 88 | isa = PBXFrameworksBuildPhase; 89 | buildActionMask = 2147483647; 90 | files = ( 91 | ); 92 | runOnlyForDeploymentPostprocessing = 0; 93 | }; 94 | 2436BD0121B4CDC700E8D063 /* Frameworks */ = { 95 | isa = PBXFrameworksBuildPhase; 96 | buildActionMask = 2147483647; 97 | files = ( 98 | ); 99 | runOnlyForDeploymentPostprocessing = 0; 100 | }; 101 | 2436BD0C21B4CDC700E8D063 /* Frameworks */ = { 102 | isa = PBXFrameworksBuildPhase; 103 | buildActionMask = 2147483647; 104 | files = ( 105 | ); 106 | runOnlyForDeploymentPostprocessing = 0; 107 | }; 108 | /* End PBXFrameworksBuildPhase section */ 109 | 110 | /* Begin PBXGroup section */ 111 | 2436BCE321B4CDC500E8D063 = { 112 | isa = PBXGroup; 113 | children = ( 114 | 2436BCEE21B4CDC500E8D063 /* LXSegmentControl */, 115 | 2436BD0721B4CDC700E8D063 /* LXSegmentControlTests */, 116 | 2436BD1221B4CDC700E8D063 /* LXSegmentControlUITests */, 117 | 2436BCED21B4CDC500E8D063 /* Products */, 118 | ); 119 | sourceTree = ""; 120 | }; 121 | 2436BCED21B4CDC500E8D063 /* Products */ = { 122 | isa = PBXGroup; 123 | children = ( 124 | 2436BCEC21B4CDC500E8D063 /* LXSegmentControl.app */, 125 | 2436BD0421B4CDC700E8D063 /* LXSegmentControlTests.xctest */, 126 | 2436BD0F21B4CDC700E8D063 /* LXSegmentControlUITests.xctest */, 127 | ); 128 | name = Products; 129 | sourceTree = ""; 130 | }; 131 | 2436BCEE21B4CDC500E8D063 /* LXSegmentControl */ = { 132 | isa = PBXGroup; 133 | children = ( 134 | 2436BD4521B4CFD500E8D063 /* LX_Prefix.pch */, 135 | 2436BD2821B4CFD000E8D063 /* Lib */, 136 | 2436BD2121B4CFD000E8D063 /* Category */, 137 | 2436BCEF21B4CDC500E8D063 /* AppDelegate.h */, 138 | 2436BCF021B4CDC500E8D063 /* AppDelegate.m */, 139 | 2436BCF221B4CDC500E8D063 /* ViewController.h */, 140 | 2436BCF321B4CDC500E8D063 /* ViewController.m */, 141 | 2436BD5921B4D22F00E8D063 /* LXSegmentType_0ViewController.h */, 142 | 2436BD5A21B4D22F00E8D063 /* LXSegmentType_0ViewController.m */, 143 | 2436BD5C21B4D23A00E8D063 /* LXSegmentType_1ViewController.h */, 144 | 2436BD5D21B4D23A00E8D063 /* LXSegmentType_1ViewController.m */, 145 | 2436BD5F21B4D57800E8D063 /* LXSegmentTitleViewController.h */, 146 | 2436BD6021B4D57800E8D063 /* LXSegmentTitleViewController.m */, 147 | 2436BCF521B4CDC500E8D063 /* Main.storyboard */, 148 | 2436BCF821B4CDC700E8D063 /* Assets.xcassets */, 149 | 2436BCFA21B4CDC700E8D063 /* LaunchScreen.storyboard */, 150 | 2436BCFD21B4CDC700E8D063 /* Info.plist */, 151 | 2436BCFE21B4CDC700E8D063 /* main.m */, 152 | ); 153 | path = LXSegmentControl; 154 | sourceTree = ""; 155 | }; 156 | 2436BD0721B4CDC700E8D063 /* LXSegmentControlTests */ = { 157 | isa = PBXGroup; 158 | children = ( 159 | 2436BD0821B4CDC700E8D063 /* LXSegmentControlTests.m */, 160 | 2436BD0A21B4CDC700E8D063 /* Info.plist */, 161 | ); 162 | path = LXSegmentControlTests; 163 | sourceTree = ""; 164 | }; 165 | 2436BD1221B4CDC700E8D063 /* LXSegmentControlUITests */ = { 166 | isa = PBXGroup; 167 | children = ( 168 | 2436BD1321B4CDC700E8D063 /* LXSegmentControlUITests.m */, 169 | 2436BD1521B4CDC700E8D063 /* Info.plist */, 170 | ); 171 | path = LXSegmentControlUITests; 172 | sourceTree = ""; 173 | }; 174 | 2436BD2121B4CFD000E8D063 /* Category */ = { 175 | isa = PBXGroup; 176 | children = ( 177 | 2436BD2721B4CFD000E8D063 /* UIColor+LX.h */, 178 | 2436BD2421B4CFD000E8D063 /* UIColor+LX.m */, 179 | 2436BD2321B4CFD000E8D063 /* UIImage+LX.h */, 180 | 2436BD2621B4CFD000E8D063 /* UIImage+LX.m */, 181 | ); 182 | path = Category; 183 | sourceTree = ""; 184 | }; 185 | 2436BD2821B4CFD000E8D063 /* Lib */ = { 186 | isa = PBXGroup; 187 | children = ( 188 | 2436BD6221B4FCEB00E8D063 /* XXPageTab */, 189 | 2436BD6921B4FCF200E8D063 /* LXPageTab */, 190 | ); 191 | path = Lib; 192 | sourceTree = ""; 193 | }; 194 | 2436BD6221B4FCEB00E8D063 /* XXPageTab */ = { 195 | isa = PBXGroup; 196 | children = ( 197 | 2436BD6521B4FCEB00E8D063 /* XXPageTabView.h */, 198 | 2436BD6421B4FCEB00E8D063 /* XXPageTabView.m */, 199 | 2436BD6621B4FCEB00E8D063 /* XXPageTabItemLable.h */, 200 | 2436BD6321B4FCEB00E8D063 /* XXPageTabItemLable.m */, 201 | ); 202 | path = XXPageTab; 203 | sourceTree = ""; 204 | }; 205 | 2436BD6921B4FCF200E8D063 /* LXPageTab */ = { 206 | isa = PBXGroup; 207 | children = ( 208 | 2436BD6A21B4FCF200E8D063 /* LXPageTabView.h */, 209 | 2436BD6D21B4FCF200E8D063 /* LXPageTabView.m */, 210 | 2436BD6E21B4FCF200E8D063 /* LXPageTabItemLable.h */, 211 | 2436BD6C21B4FCF200E8D063 /* LXPageTabItemLable.m */, 212 | 2436BD6B21B4FCF200E8D063 /* 三角形@2x.png */, 213 | ); 214 | path = LXPageTab; 215 | sourceTree = ""; 216 | }; 217 | /* End PBXGroup section */ 218 | 219 | /* Begin PBXNativeTarget section */ 220 | 2436BCEB21B4CDC500E8D063 /* LXSegmentControl */ = { 221 | isa = PBXNativeTarget; 222 | buildConfigurationList = 2436BD1821B4CDC700E8D063 /* Build configuration list for PBXNativeTarget "LXSegmentControl" */; 223 | buildPhases = ( 224 | 2436BCE821B4CDC500E8D063 /* Sources */, 225 | 2436BCE921B4CDC500E8D063 /* Frameworks */, 226 | 2436BCEA21B4CDC500E8D063 /* Resources */, 227 | ); 228 | buildRules = ( 229 | ); 230 | dependencies = ( 231 | ); 232 | name = LXSegmentControl; 233 | productName = LXSegmentControl; 234 | productReference = 2436BCEC21B4CDC500E8D063 /* LXSegmentControl.app */; 235 | productType = "com.apple.product-type.application"; 236 | }; 237 | 2436BD0321B4CDC700E8D063 /* LXSegmentControlTests */ = { 238 | isa = PBXNativeTarget; 239 | buildConfigurationList = 2436BD1B21B4CDC700E8D063 /* Build configuration list for PBXNativeTarget "LXSegmentControlTests" */; 240 | buildPhases = ( 241 | 2436BD0021B4CDC700E8D063 /* Sources */, 242 | 2436BD0121B4CDC700E8D063 /* Frameworks */, 243 | 2436BD0221B4CDC700E8D063 /* Resources */, 244 | ); 245 | buildRules = ( 246 | ); 247 | dependencies = ( 248 | 2436BD0621B4CDC700E8D063 /* PBXTargetDependency */, 249 | ); 250 | name = LXSegmentControlTests; 251 | productName = LXSegmentControlTests; 252 | productReference = 2436BD0421B4CDC700E8D063 /* LXSegmentControlTests.xctest */; 253 | productType = "com.apple.product-type.bundle.unit-test"; 254 | }; 255 | 2436BD0E21B4CDC700E8D063 /* LXSegmentControlUITests */ = { 256 | isa = PBXNativeTarget; 257 | buildConfigurationList = 2436BD1E21B4CDC700E8D063 /* Build configuration list for PBXNativeTarget "LXSegmentControlUITests" */; 258 | buildPhases = ( 259 | 2436BD0B21B4CDC700E8D063 /* Sources */, 260 | 2436BD0C21B4CDC700E8D063 /* Frameworks */, 261 | 2436BD0D21B4CDC700E8D063 /* Resources */, 262 | ); 263 | buildRules = ( 264 | ); 265 | dependencies = ( 266 | 2436BD1121B4CDC700E8D063 /* PBXTargetDependency */, 267 | ); 268 | name = LXSegmentControlUITests; 269 | productName = LXSegmentControlUITests; 270 | productReference = 2436BD0F21B4CDC700E8D063 /* LXSegmentControlUITests.xctest */; 271 | productType = "com.apple.product-type.bundle.ui-testing"; 272 | }; 273 | /* End PBXNativeTarget section */ 274 | 275 | /* Begin PBXProject section */ 276 | 2436BCE421B4CDC500E8D063 /* Project object */ = { 277 | isa = PBXProject; 278 | attributes = { 279 | LastUpgradeCheck = 1000; 280 | ORGANIZATIONNAME = "https://github.com/nick8brown"; 281 | TargetAttributes = { 282 | 2436BCEB21B4CDC500E8D063 = { 283 | CreatedOnToolsVersion = 10.0; 284 | }; 285 | 2436BD0321B4CDC700E8D063 = { 286 | CreatedOnToolsVersion = 10.0; 287 | TestTargetID = 2436BCEB21B4CDC500E8D063; 288 | }; 289 | 2436BD0E21B4CDC700E8D063 = { 290 | CreatedOnToolsVersion = 10.0; 291 | TestTargetID = 2436BCEB21B4CDC500E8D063; 292 | }; 293 | }; 294 | }; 295 | buildConfigurationList = 2436BCE721B4CDC500E8D063 /* Build configuration list for PBXProject "LXSegmentControl" */; 296 | compatibilityVersion = "Xcode 9.3"; 297 | developmentRegion = en; 298 | hasScannedForEncodings = 0; 299 | knownRegions = ( 300 | en, 301 | Base, 302 | ); 303 | mainGroup = 2436BCE321B4CDC500E8D063; 304 | productRefGroup = 2436BCED21B4CDC500E8D063 /* Products */; 305 | projectDirPath = ""; 306 | projectRoot = ""; 307 | targets = ( 308 | 2436BCEB21B4CDC500E8D063 /* LXSegmentControl */, 309 | 2436BD0321B4CDC700E8D063 /* LXSegmentControlTests */, 310 | 2436BD0E21B4CDC700E8D063 /* LXSegmentControlUITests */, 311 | ); 312 | }; 313 | /* End PBXProject section */ 314 | 315 | /* Begin PBXResourcesBuildPhase section */ 316 | 2436BCEA21B4CDC500E8D063 /* Resources */ = { 317 | isa = PBXResourcesBuildPhase; 318 | buildActionMask = 2147483647; 319 | files = ( 320 | 2436BD6F21B4FCF200E8D063 /* 三角形@2x.png in Resources */, 321 | 2436BCFC21B4CDC700E8D063 /* LaunchScreen.storyboard in Resources */, 322 | 2436BCF921B4CDC700E8D063 /* Assets.xcassets in Resources */, 323 | 2436BCF721B4CDC500E8D063 /* Main.storyboard in Resources */, 324 | ); 325 | runOnlyForDeploymentPostprocessing = 0; 326 | }; 327 | 2436BD0221B4CDC700E8D063 /* Resources */ = { 328 | isa = PBXResourcesBuildPhase; 329 | buildActionMask = 2147483647; 330 | files = ( 331 | ); 332 | runOnlyForDeploymentPostprocessing = 0; 333 | }; 334 | 2436BD0D21B4CDC700E8D063 /* Resources */ = { 335 | isa = PBXResourcesBuildPhase; 336 | buildActionMask = 2147483647; 337 | files = ( 338 | ); 339 | runOnlyForDeploymentPostprocessing = 0; 340 | }; 341 | /* End PBXResourcesBuildPhase section */ 342 | 343 | /* Begin PBXSourcesBuildPhase section */ 344 | 2436BCE821B4CDC500E8D063 /* Sources */ = { 345 | isa = PBXSourcesBuildPhase; 346 | buildActionMask = 2147483647; 347 | files = ( 348 | 2436BD6121B4D57800E8D063 /* LXSegmentTitleViewController.m in Sources */, 349 | 2436BCF421B4CDC500E8D063 /* ViewController.m in Sources */, 350 | 2436BD7021B4FCF200E8D063 /* LXPageTabItemLable.m in Sources */, 351 | 2436BD3C21B4CFD000E8D063 /* UIImage+LX.m in Sources */, 352 | 2436BCFF21B4CDC700E8D063 /* main.m in Sources */, 353 | 2436BD3B21B4CFD000E8D063 /* UIColor+LX.m in Sources */, 354 | 2436BD5B21B4D22F00E8D063 /* LXSegmentType_0ViewController.m in Sources */, 355 | 2436BD6721B4FCEB00E8D063 /* XXPageTabItemLable.m in Sources */, 356 | 2436BD6821B4FCEB00E8D063 /* XXPageTabView.m in Sources */, 357 | 2436BD7121B4FCF200E8D063 /* LXPageTabView.m in Sources */, 358 | 2436BCF121B4CDC500E8D063 /* AppDelegate.m in Sources */, 359 | 2436BD5E21B4D23A00E8D063 /* LXSegmentType_1ViewController.m in Sources */, 360 | ); 361 | runOnlyForDeploymentPostprocessing = 0; 362 | }; 363 | 2436BD0021B4CDC700E8D063 /* Sources */ = { 364 | isa = PBXSourcesBuildPhase; 365 | buildActionMask = 2147483647; 366 | files = ( 367 | 2436BD0921B4CDC700E8D063 /* LXSegmentControlTests.m in Sources */, 368 | ); 369 | runOnlyForDeploymentPostprocessing = 0; 370 | }; 371 | 2436BD0B21B4CDC700E8D063 /* Sources */ = { 372 | isa = PBXSourcesBuildPhase; 373 | buildActionMask = 2147483647; 374 | files = ( 375 | 2436BD1421B4CDC700E8D063 /* LXSegmentControlUITests.m in Sources */, 376 | ); 377 | runOnlyForDeploymentPostprocessing = 0; 378 | }; 379 | /* End PBXSourcesBuildPhase section */ 380 | 381 | /* Begin PBXTargetDependency section */ 382 | 2436BD0621B4CDC700E8D063 /* PBXTargetDependency */ = { 383 | isa = PBXTargetDependency; 384 | target = 2436BCEB21B4CDC500E8D063 /* LXSegmentControl */; 385 | targetProxy = 2436BD0521B4CDC700E8D063 /* PBXContainerItemProxy */; 386 | }; 387 | 2436BD1121B4CDC700E8D063 /* PBXTargetDependency */ = { 388 | isa = PBXTargetDependency; 389 | target = 2436BCEB21B4CDC500E8D063 /* LXSegmentControl */; 390 | targetProxy = 2436BD1021B4CDC700E8D063 /* PBXContainerItemProxy */; 391 | }; 392 | /* End PBXTargetDependency section */ 393 | 394 | /* Begin PBXVariantGroup section */ 395 | 2436BCF521B4CDC500E8D063 /* Main.storyboard */ = { 396 | isa = PBXVariantGroup; 397 | children = ( 398 | 2436BCF621B4CDC500E8D063 /* Base */, 399 | ); 400 | name = Main.storyboard; 401 | sourceTree = ""; 402 | }; 403 | 2436BCFA21B4CDC700E8D063 /* LaunchScreen.storyboard */ = { 404 | isa = PBXVariantGroup; 405 | children = ( 406 | 2436BCFB21B4CDC700E8D063 /* Base */, 407 | ); 408 | name = LaunchScreen.storyboard; 409 | sourceTree = ""; 410 | }; 411 | /* End PBXVariantGroup section */ 412 | 413 | /* Begin XCBuildConfiguration section */ 414 | 2436BD1621B4CDC700E8D063 /* Debug */ = { 415 | isa = XCBuildConfiguration; 416 | buildSettings = { 417 | ALWAYS_SEARCH_USER_PATHS = NO; 418 | CLANG_ANALYZER_NONNULL = YES; 419 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 420 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 421 | CLANG_CXX_LIBRARY = "libc++"; 422 | CLANG_ENABLE_MODULES = YES; 423 | CLANG_ENABLE_OBJC_ARC = YES; 424 | CLANG_ENABLE_OBJC_WEAK = YES; 425 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 426 | CLANG_WARN_BOOL_CONVERSION = YES; 427 | CLANG_WARN_COMMA = YES; 428 | CLANG_WARN_CONSTANT_CONVERSION = YES; 429 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 430 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 431 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 432 | CLANG_WARN_EMPTY_BODY = YES; 433 | CLANG_WARN_ENUM_CONVERSION = YES; 434 | CLANG_WARN_INFINITE_RECURSION = YES; 435 | CLANG_WARN_INT_CONVERSION = YES; 436 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 437 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 438 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 439 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 440 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 441 | CLANG_WARN_STRICT_PROTOTYPES = YES; 442 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 443 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 444 | CLANG_WARN_UNREACHABLE_CODE = YES; 445 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 446 | CODE_SIGN_IDENTITY = "iPhone Developer"; 447 | COPY_PHASE_STRIP = NO; 448 | DEBUG_INFORMATION_FORMAT = dwarf; 449 | ENABLE_STRICT_OBJC_MSGSEND = YES; 450 | ENABLE_TESTABILITY = YES; 451 | GCC_C_LANGUAGE_STANDARD = gnu11; 452 | GCC_DYNAMIC_NO_PIC = NO; 453 | GCC_NO_COMMON_BLOCKS = YES; 454 | GCC_OPTIMIZATION_LEVEL = 0; 455 | GCC_PREPROCESSOR_DEFINITIONS = ( 456 | "DEBUG=1", 457 | "$(inherited)", 458 | ); 459 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 460 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 461 | GCC_WARN_UNDECLARED_SELECTOR = YES; 462 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 463 | GCC_WARN_UNUSED_FUNCTION = YES; 464 | GCC_WARN_UNUSED_VARIABLE = YES; 465 | IPHONEOS_DEPLOYMENT_TARGET = 12.0; 466 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 467 | MTL_FAST_MATH = YES; 468 | ONLY_ACTIVE_ARCH = YES; 469 | SDKROOT = iphoneos; 470 | }; 471 | name = Debug; 472 | }; 473 | 2436BD1721B4CDC700E8D063 /* Release */ = { 474 | isa = XCBuildConfiguration; 475 | buildSettings = { 476 | ALWAYS_SEARCH_USER_PATHS = NO; 477 | CLANG_ANALYZER_NONNULL = YES; 478 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 479 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 480 | CLANG_CXX_LIBRARY = "libc++"; 481 | CLANG_ENABLE_MODULES = YES; 482 | CLANG_ENABLE_OBJC_ARC = YES; 483 | CLANG_ENABLE_OBJC_WEAK = YES; 484 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 485 | CLANG_WARN_BOOL_CONVERSION = YES; 486 | CLANG_WARN_COMMA = YES; 487 | CLANG_WARN_CONSTANT_CONVERSION = YES; 488 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 489 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 490 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 491 | CLANG_WARN_EMPTY_BODY = YES; 492 | CLANG_WARN_ENUM_CONVERSION = YES; 493 | CLANG_WARN_INFINITE_RECURSION = YES; 494 | CLANG_WARN_INT_CONVERSION = YES; 495 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 496 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 497 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 498 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 499 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 500 | CLANG_WARN_STRICT_PROTOTYPES = YES; 501 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 502 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 503 | CLANG_WARN_UNREACHABLE_CODE = YES; 504 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 505 | CODE_SIGN_IDENTITY = "iPhone Developer"; 506 | COPY_PHASE_STRIP = NO; 507 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 508 | ENABLE_NS_ASSERTIONS = NO; 509 | ENABLE_STRICT_OBJC_MSGSEND = YES; 510 | GCC_C_LANGUAGE_STANDARD = gnu11; 511 | GCC_NO_COMMON_BLOCKS = YES; 512 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 513 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 514 | GCC_WARN_UNDECLARED_SELECTOR = YES; 515 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 516 | GCC_WARN_UNUSED_FUNCTION = YES; 517 | GCC_WARN_UNUSED_VARIABLE = YES; 518 | IPHONEOS_DEPLOYMENT_TARGET = 12.0; 519 | MTL_ENABLE_DEBUG_INFO = NO; 520 | MTL_FAST_MATH = YES; 521 | SDKROOT = iphoneos; 522 | VALIDATE_PRODUCT = YES; 523 | }; 524 | name = Release; 525 | }; 526 | 2436BD1921B4CDC700E8D063 /* Debug */ = { 527 | isa = XCBuildConfiguration; 528 | buildSettings = { 529 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 530 | CODE_SIGN_STYLE = Automatic; 531 | GCC_PREFIX_HEADER = "$(SRCROOT)/$(PROJECT_NAME)/LX_Prefix.pch"; 532 | INFOPLIST_FILE = LXSegmentControl/Info.plist; 533 | LD_RUNPATH_SEARCH_PATHS = ( 534 | "$(inherited)", 535 | "@executable_path/Frameworks", 536 | ); 537 | PRODUCT_BUNDLE_IDENTIFIER = "https---github.com-nick8brown.LXSegmentControl"; 538 | PRODUCT_NAME = "$(TARGET_NAME)"; 539 | TARGETED_DEVICE_FAMILY = "1,2"; 540 | }; 541 | name = Debug; 542 | }; 543 | 2436BD1A21B4CDC700E8D063 /* Release */ = { 544 | isa = XCBuildConfiguration; 545 | buildSettings = { 546 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 547 | CODE_SIGN_STYLE = Automatic; 548 | GCC_PREFIX_HEADER = "$(SRCROOT)/$(PROJECT_NAME)/LX_Prefix.pch"; 549 | INFOPLIST_FILE = LXSegmentControl/Info.plist; 550 | LD_RUNPATH_SEARCH_PATHS = ( 551 | "$(inherited)", 552 | "@executable_path/Frameworks", 553 | ); 554 | PRODUCT_BUNDLE_IDENTIFIER = "https---github.com-nick8brown.LXSegmentControl"; 555 | PRODUCT_NAME = "$(TARGET_NAME)"; 556 | TARGETED_DEVICE_FAMILY = "1,2"; 557 | }; 558 | name = Release; 559 | }; 560 | 2436BD1C21B4CDC700E8D063 /* Debug */ = { 561 | isa = XCBuildConfiguration; 562 | buildSettings = { 563 | BUNDLE_LOADER = "$(TEST_HOST)"; 564 | CODE_SIGN_STYLE = Automatic; 565 | INFOPLIST_FILE = LXSegmentControlTests/Info.plist; 566 | LD_RUNPATH_SEARCH_PATHS = ( 567 | "$(inherited)", 568 | "@executable_path/Frameworks", 569 | "@loader_path/Frameworks", 570 | ); 571 | PRODUCT_BUNDLE_IDENTIFIER = "https---github.com-nick8brown.LXSegmentControlTests"; 572 | PRODUCT_NAME = "$(TARGET_NAME)"; 573 | TARGETED_DEVICE_FAMILY = "1,2"; 574 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/LXSegmentControl.app/LXSegmentControl"; 575 | }; 576 | name = Debug; 577 | }; 578 | 2436BD1D21B4CDC700E8D063 /* Release */ = { 579 | isa = XCBuildConfiguration; 580 | buildSettings = { 581 | BUNDLE_LOADER = "$(TEST_HOST)"; 582 | CODE_SIGN_STYLE = Automatic; 583 | INFOPLIST_FILE = LXSegmentControlTests/Info.plist; 584 | LD_RUNPATH_SEARCH_PATHS = ( 585 | "$(inherited)", 586 | "@executable_path/Frameworks", 587 | "@loader_path/Frameworks", 588 | ); 589 | PRODUCT_BUNDLE_IDENTIFIER = "https---github.com-nick8brown.LXSegmentControlTests"; 590 | PRODUCT_NAME = "$(TARGET_NAME)"; 591 | TARGETED_DEVICE_FAMILY = "1,2"; 592 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/LXSegmentControl.app/LXSegmentControl"; 593 | }; 594 | name = Release; 595 | }; 596 | 2436BD1F21B4CDC700E8D063 /* Debug */ = { 597 | isa = XCBuildConfiguration; 598 | buildSettings = { 599 | CODE_SIGN_STYLE = Automatic; 600 | INFOPLIST_FILE = LXSegmentControlUITests/Info.plist; 601 | LD_RUNPATH_SEARCH_PATHS = ( 602 | "$(inherited)", 603 | "@executable_path/Frameworks", 604 | "@loader_path/Frameworks", 605 | ); 606 | PRODUCT_BUNDLE_IDENTIFIER = "https---github.com-nick8brown.LXSegmentControlUITests"; 607 | PRODUCT_NAME = "$(TARGET_NAME)"; 608 | TARGETED_DEVICE_FAMILY = "1,2"; 609 | TEST_TARGET_NAME = LXSegmentControl; 610 | }; 611 | name = Debug; 612 | }; 613 | 2436BD2021B4CDC700E8D063 /* Release */ = { 614 | isa = XCBuildConfiguration; 615 | buildSettings = { 616 | CODE_SIGN_STYLE = Automatic; 617 | INFOPLIST_FILE = LXSegmentControlUITests/Info.plist; 618 | LD_RUNPATH_SEARCH_PATHS = ( 619 | "$(inherited)", 620 | "@executable_path/Frameworks", 621 | "@loader_path/Frameworks", 622 | ); 623 | PRODUCT_BUNDLE_IDENTIFIER = "https---github.com-nick8brown.LXSegmentControlUITests"; 624 | PRODUCT_NAME = "$(TARGET_NAME)"; 625 | TARGETED_DEVICE_FAMILY = "1,2"; 626 | TEST_TARGET_NAME = LXSegmentControl; 627 | }; 628 | name = Release; 629 | }; 630 | /* End XCBuildConfiguration section */ 631 | 632 | /* Begin XCConfigurationList section */ 633 | 2436BCE721B4CDC500E8D063 /* Build configuration list for PBXProject "LXSegmentControl" */ = { 634 | isa = XCConfigurationList; 635 | buildConfigurations = ( 636 | 2436BD1621B4CDC700E8D063 /* Debug */, 637 | 2436BD1721B4CDC700E8D063 /* Release */, 638 | ); 639 | defaultConfigurationIsVisible = 0; 640 | defaultConfigurationName = Release; 641 | }; 642 | 2436BD1821B4CDC700E8D063 /* Build configuration list for PBXNativeTarget "LXSegmentControl" */ = { 643 | isa = XCConfigurationList; 644 | buildConfigurations = ( 645 | 2436BD1921B4CDC700E8D063 /* Debug */, 646 | 2436BD1A21B4CDC700E8D063 /* Release */, 647 | ); 648 | defaultConfigurationIsVisible = 0; 649 | defaultConfigurationName = Release; 650 | }; 651 | 2436BD1B21B4CDC700E8D063 /* Build configuration list for PBXNativeTarget "LXSegmentControlTests" */ = { 652 | isa = XCConfigurationList; 653 | buildConfigurations = ( 654 | 2436BD1C21B4CDC700E8D063 /* Debug */, 655 | 2436BD1D21B4CDC700E8D063 /* Release */, 656 | ); 657 | defaultConfigurationIsVisible = 0; 658 | defaultConfigurationName = Release; 659 | }; 660 | 2436BD1E21B4CDC700E8D063 /* Build configuration list for PBXNativeTarget "LXSegmentControlUITests" */ = { 661 | isa = XCConfigurationList; 662 | buildConfigurations = ( 663 | 2436BD1F21B4CDC700E8D063 /* Debug */, 664 | 2436BD2021B4CDC700E8D063 /* Release */, 665 | ); 666 | defaultConfigurationIsVisible = 0; 667 | defaultConfigurationName = Release; 668 | }; 669 | /* End XCConfigurationList section */ 670 | }; 671 | rootObject = 2436BCE421B4CDC500E8D063 /* Project object */; 672 | } 673 | --------------------------------------------------------------------------------