Repository: shunFSKi/FSScrollContentView
Branch: master
Commit: bab93772ebf9
Files: 31
Total size: 90.2 KB
Directory structure:
gitextract_1xem8x04/
├── .gitignore
├── .travis.yml
├── FSScrollContentView.podspec
├── FSScrollContentViewDemo/
│ ├── FSScrollContentViewDemo/
│ │ ├── AppDelegate.h
│ │ ├── AppDelegate.m
│ │ ├── Assets.xcassets/
│ │ │ └── AppIcon.appiconset/
│ │ │ └── Contents.json
│ │ ├── Base.lproj/
│ │ │ ├── LaunchScreen.storyboard
│ │ │ └── Main.storyboard
│ │ ├── ChildViewController.h
│ │ ├── ChildViewController.m
│ │ ├── Info.plist
│ │ ├── TestViewController.h
│ │ ├── TestViewController.m
│ │ ├── ViewController.h
│ │ ├── ViewController.m
│ │ └── main.m
│ ├── FSScrollContentViewDemo.xcodeproj/
│ │ ├── project.pbxproj
│ │ ├── project.xcworkspace/
│ │ │ └── contents.xcworkspacedata
│ │ └── xcshareddata/
│ │ └── xcschemes/
│ │ └── FSScrollContentViewDemo.xcscheme
│ └── FSScrollContentViewLib/
│ ├── FSPageContentView.h
│ ├── FSPageContentView.m
│ ├── FSScrollContentView.h
│ ├── FSSegmentTitleView.h
│ └── FSSegmentTitleView.m
├── FSScrollContentViewLib/
│ ├── FSPageContentView.h
│ ├── FSPageContentView.m
│ ├── FSScrollContentView.h
│ ├── FSSegmentTitleView.h
│ └── FSSegmentTitleView.m
├── LICENSE
└── README.md
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
# Xcode
#
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
## Build generated
build/
DerivedData/
## Various settings
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata/
## Other
*.moved-aside
*.xcuserstate
## Obj-C/Swift specific
*.hmap
*.ipa
*.dSYM.zip
*.dSYM
# CocoaPods
#
# We recommend against adding the Pods directory to your .gitignore. However
# you should judge for yourself, the pros and cons are mentioned at:
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
#
# Pods/
# Carthage
#
# Add this line if you want to avoid checking in source code from Carthage dependencies.
# Carthage/Checkouts
Carthage/Build
# fastlane
#
# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
# screenshots whenever they are needed.
# For more information about the recommended setup visit:
# https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md
fastlane/report.xml
fastlane/screenshots
#Code Injection
#
# After new code Injection tools there's a generated folder /iOSInjectionProject
# https://github.com/johnno1962/injectionforxcode
iOSInjectionProject/
================================================
FILE: .travis.yml
================================================
language: objective-c
xcode_project: FSScrollContentViewDemo.xcodeproj
================================================
FILE: FSScrollContentView.podspec
================================================
#
# Be sure to run `pod spec lint FSScrollContentView.podspec' to ensure this is a
# valid spec and to remove all comments including this before submitting the spec.
#
# To learn more about Podspec attributes see http://docs.cocoapods.org/specification.html
# To see working Podspecs in the CocoaPods repo see https://github.com/CocoaPods/Specs/
#
Pod::Spec.new do |s|
# ――― Spec Metadata ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
#
# These will help people to find your library, and whilst it
# can feel like a chore to fill in it's definitely to your advantage. The
# summary should be tweet-length, and the description more in depth.
#
s.name = "FSScrollContentView"
s.version = "1.0.9"
s.summary = "titleView pageView linkage."
# This description is used to generate tags and improve search results.
# * Think: What does it do? Why did you write it? What is the focus?
# * Try to keep it short, snappy and to the point.
# * Write the description between the DESC delimiters below.
# * Finally, don't worry about the indent, CocoaPods strips it!
s.description = <<-DESC
修复解决父视图循环引用问题,这是一个顶部标签与内容页联动框架
DESC
s.homepage = "https://github.com/shunFSKi/FSScrollContentView"
# s.screenshots = "www.example.com/screenshots_1.gif", "www.example.com/screenshots_2.gif"
# ――― Spec License ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
#
# Licensing your code is important. See http://choosealicense.com for more info.
# CocoaPods will detect a license file if there is a named LICENSE*
# Popular ones are 'MIT', 'BSD' and 'Apache License, Version 2.0'.
#
s.license = "MIT"
# s.license = { :type => "MIT", :file => "FILE_LICENSE" }
# ――― Author Metadata ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
#
# Specify the authors of the library, with email addresses. Email addresses
# of the authors are extracted from the SCM log. E.g. $ git log. CocoaPods also
# accepts just a name if you'd rather not provide an email address.
#
# Specify a social_media_url where others can refer to, for example a twitter
# profile URL.
#
s.author = { "fengshun" => "fengshun_ios@126.com" }
# Or just: s.author = "fengshun"
# s.authors = { "fengshun" => "fengshun@huim.com" }
# s.social_media_url = "http://twitter.com/fengshun"
# ――― Platform Specifics ――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
#
# If this Pod runs only on iOS or OS X, then specify the platform and
# the deployment target. You can optionally include the target after the platform.
#
# s.platform = :ios
s.platform = :ios, "7.0"
# When using multiple platforms
# s.ios.deployment_target = "5.0"
# s.osx.deployment_target = "10.7"
# s.watchos.deployment_target = "2.0"
# s.tvos.deployment_target = "9.0"
# ――― Source Location ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
#
# Specify the location from where the source should be retrieved.
# Supports git, hg, bzr, svn and HTTP.
#
s.source = { :git => "https://github.com/shunFSKi/FSScrollContentView.git", :tag => "1.0.9" }
# ――― Source Code ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
#
# CocoaPods is smart about how it includes source code. For source files
# giving a folder will include any swift, h, m, mm, c & cpp files.
# For header files it will include any header in the folder.
# Not including the public_header_files will make all headers public.
#
s.source_files = "FSScrollContentViewLib", "FSScrollContentViewLib/**/*.{h,m}"
# s.exclude_files = "Classes/Exclude"
# s.public_header_files = "Classes/**/*.h"
# ――― Resources ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
#
# A list of resources included with the Pod. These are copied into the
# target bundle with a build phase script. Anything else will be cleaned.
# You can preserve files from being cleaned, please don't preserve
# non-essential files like tests, examples and documentation.
#
# s.resource = "icon.png"
# s.resources = "Resources/*.png"
# s.preserve_paths = "FilesToSave", "MoreFilesToSave"
# ――― Project Linking ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
#
# Link your library with frameworks, or libraries. Libraries do not include
# the lib prefix of their name.
#
# s.framework = "UIKit"
# s.frameworks = "SomeFramework", "AnotherFramework"
# s.library = "iconv"
# s.libraries = "iconv", "xml2"
# ――― Project Settings ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
#
# If your library depends on compiler flags you can set them in the xcconfig hash
# where they will only apply to your library. If you depend on other Podspecs
# you can include multiple dependencies to ensure it works.
# s.requires_arc = true
# s.xcconfig = { "HEADER_SEARCH_PATHS" => "$(SDKROOT)/usr/include/libxml2" }
# s.dependency "JSONKit", "~> 1.4"
end
================================================
FILE: FSScrollContentViewDemo/FSScrollContentViewDemo/AppDelegate.h
================================================
//
// AppDelegate.h
// FSScrollContentViewDemo
//
// Created by huim on 2017/5/3.
// Copyright © 2017年 fengshun. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window;
@end
================================================
FILE: FSScrollContentViewDemo/FSScrollContentViewDemo/AppDelegate.m
================================================
//
// AppDelegate.m
// FSScrollContentViewDemo
//
// Created by huim on 2017/5/3.
// Copyright © 2017年 fengshun. All rights reserved.
//
#import "AppDelegate.h"
#import "ViewController.h"
@interface AppDelegate ()
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
UINavigationController *nav = [[UINavigationController alloc]initWithRootViewController:[[ViewController alloc]init]];
self.window.rootViewController = nav;
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application {
// 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.
// Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
}
- (void)applicationDidEnterBackground:(UIApplication *)application {
// 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.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
// 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.
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
// 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.
}
- (void)applicationWillTerminate:(UIApplication *)application {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
@end
================================================
FILE: FSScrollContentViewDemo/FSScrollContentViewDemo/Assets.xcassets/AppIcon.appiconset/Contents.json
================================================
{
"images" : [
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "60x60",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "60x60",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: FSScrollContentViewDemo/FSScrollContentViewDemo/Base.lproj/LaunchScreen.storyboard
================================================
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11134" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11106"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="EHf-IW-A2E">
<objects>
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="Llm-lL-Icb"/>
<viewControllerLayoutGuide type="bottom" id="xb3-aO-Qok"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="53" y="375"/>
</scene>
</scenes>
</document>
================================================
FILE: FSScrollContentViewDemo/FSScrollContentViewDemo/Base.lproj/Main.storyboard
================================================
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11134" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11106"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="tne-QT-ifu">
<objects>
<viewController id="BYZ-38-t0r" customClass="ViewController" customModuleProvider="" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
</objects>
</scene>
</scenes>
</document>
================================================
FILE: FSScrollContentViewDemo/FSScrollContentViewDemo/ChildViewController.h
================================================
//
// ChildViewController.h
// FSScrollContentViewDemo
//
// Created by 冯顺 on 2017/5/3.
// Copyright © 2017年 fengshun. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface ChildViewController : UIViewController
@property (nonatomic, strong) NSString *titleStr;
@end
================================================
FILE: FSScrollContentViewDemo/FSScrollContentViewDemo/ChildViewController.m
================================================
//
// ChildViewController.m
// FSScrollContentViewDemo
//
// Created by 冯顺 on 2017/5/3.
// Copyright © 2017年 fengshun. All rights reserved.
//
#import "ChildViewController.h"
@interface ChildViewController ()
@end
@implementation ChildViewController
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
NSLog(@"---%@",self.title);
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.view.backgroundColor = [ChildViewController randomColor];
}
+ (UIColor*) randomColor{
NSInteger r = arc4random() % 255;
NSInteger g = arc4random() % 255;
NSInteger b = arc4random() % 255;
return [UIColor colorWithRed:r/255.0 green:g/255.0 blue:b/255.0 alpha:1];
}
@end
================================================
FILE: FSScrollContentViewDemo/FSScrollContentViewDemo/Info.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
</dict>
</plist>
================================================
FILE: FSScrollContentViewDemo/FSScrollContentViewDemo/TestViewController.h
================================================
//
// TestViewController.h
// FSScrollContentViewDemo
//
// Created by huim on 2017/5/4.
// Copyright © 2017年 fengshun. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface TestViewController : UIViewController
@end
================================================
FILE: FSScrollContentViewDemo/FSScrollContentViewDemo/TestViewController.m
================================================
//
// TestViewController.m
// FSScrollContentViewDemo
//
// Created by huim on 2017/5/4.
// Copyright © 2017年 fengshun. All rights reserved.
//
#import "TestViewController.h"
#import "FSScrollContentView.h"
#import "ChildViewController.h"
@interface TestViewController ()<FSPageContentViewDelegate,FSSegmentTitleViewDelegate>
@property (nonatomic, strong) FSPageContentView *pageContentView;
@property (nonatomic, strong) FSSegmentTitleView *titleView;
@end
@implementation TestViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.automaticallyAdjustsScrollViewInsets = NO;
self.view.backgroundColor = [UIColor whiteColor];
self.title = @"pageContentView";
self.titleView = [[FSSegmentTitleView alloc]initWithFrame:CGRectMake(0, 64, CGRectGetWidth(self.view.bounds), 50) titles:@[@"全部",@"服饰穿搭",@"生活百货",@"美食吃货",@"美容护理",@"母婴儿童",@"数码家电",@"其他"] delegate:self indicatorType:FSIndicatorTypeEqualTitle];
self.titleView.titleSelectFont = [UIFont systemFontOfSize:10];
self.titleView.selectIndex = 2;
[self.view addSubview:_titleView];
NSMutableArray *childVCs = [[NSMutableArray alloc]init];
for (NSString *title in @[@"全部",@"服饰穿搭",@"生活百货",@"美食吃货",@"美容护理",@"母婴儿童",@"数码家电",@"其他"]) {
ChildViewController *vc = [[ChildViewController alloc]init];
vc.title = title;
[childVCs addObject:vc];
}
self.pageContentView = [[FSPageContentView alloc]initWithFrame:CGRectMake(0, 114, CGRectGetWidth(self.view.bounds), CGRectGetHeight(self.view.bounds) - 90) childVCs:childVCs parentVC:self delegate:self];
self.pageContentView.contentViewCurrentIndex = 2;
// self.pageContentView.contentViewCanScroll = NO;//设置滑动属性
[self.view addSubview:_pageContentView];
}
#pragma mark --
- (void)FSSegmentTitleView:(FSSegmentTitleView *)titleView startIndex:(NSInteger)startIndex endIndex:(NSInteger)endIndex
{
self.pageContentView.contentViewCurrentIndex = endIndex;
self.title = @[@"全部",@"服饰穿搭",@"生活百货",@"美食吃货",@"美容护理",@"母婴儿童",@"数码家电",@"其他"][endIndex];
}
- (void)FSContenViewDidEndDecelerating:(FSPageContentView *)contentView startIndex:(NSInteger)startIndex endIndex:(NSInteger)endIndex
{
self.titleView.selectIndex = endIndex;
self.title = @[@"全部",@"服饰穿搭",@"生活百货",@"美食吃货",@"美容护理",@"母婴儿童",@"数码家电",@"其他"][endIndex];
}
@end
================================================
FILE: FSScrollContentViewDemo/FSScrollContentViewDemo/ViewController.h
================================================
//
// ViewController.h
// FSScrollContentViewDemo
//
// Created by huim on 2017/5/3.
// Copyright © 2017年 fengshun. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
@end
================================================
FILE: FSScrollContentViewDemo/FSScrollContentViewDemo/ViewController.m
================================================
//
// ViewController.m
// FSScrollContentViewDemo
//
// Created by huim on 2017/5/3.
// Copyright © 2017年 fengshun. All rights reserved.
//
#import "ViewController.h"
#import "FSScrollContentView.h"
#import "TestViewController.h"
@interface ViewController ()<FSPageContentViewDelegate,FSSegmentTitleViewDelegate>
@property (nonatomic, strong) FSPageContentView *pageContentView;
@property (nonatomic, strong) FSSegmentTitleView *titleView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.automaticallyAdjustsScrollViewInsets = NO;
self.view.backgroundColor = [UIColor whiteColor];
//demo1
self.titleView = [[FSSegmentTitleView alloc]initWithFrame:CGRectMake(0, 64, CGRectGetWidth(self.view.bounds), 50) titles:@[@"全部",@"服饰穿搭",@"生活百货",@"美食吃货",@"美容护理",@"母婴儿童",@"数码家电",@"其他"] delegate:self indicatorType:0];
self.titleView.indicatorColor = [UIColor blueColor];
[self.view addSubview:_titleView];
self.titleView.backgroundColor = [UIColor lightGrayColor];
//demo2
FSSegmentTitleView *titleView2 = [[FSSegmentTitleView alloc]initWithFrame:CGRectMake(0, 124, CGRectGetWidth(self.view.bounds), 50) titles:@[@"全部",@"服饰穿搭",@"生活百货",@"美食吃货",@"美容护理",@"母婴儿童",@"数码家电",@"其他"] delegate:nil indicatorType:0];
[self.view addSubview:titleView2];
titleView2.backgroundColor = [UIColor lightGrayColor];
//demo3
FSSegmentTitleView *titleView3 = [[FSSegmentTitleView alloc]initWithFrame:CGRectMake(0, 194, CGRectGetWidth(self.view.bounds), 50) titles:@[@"全部",@"服饰穿搭",@"生活百货",@"美食吃货",@"美容护理",@"母婴儿童",@"数码家电",@"其他"] delegate:nil indicatorType:2];
titleView3.indicatorExtension = 6;
[self.view addSubview:titleView3];
titleView3.backgroundColor = [UIColor lightGrayColor];
//demo4
FSSegmentTitleView *titleView4 = [[FSSegmentTitleView alloc]initWithFrame:CGRectMake(0, 264, CGRectGetWidth(self.view.bounds), 50) titles:@[@"全部",@"服饰穿搭",@"生活百货",@"美食吃货",@"美容护理",@"母婴儿童",@"数码家电",@"其他"] delegate:nil indicatorType:3];
[self.view addSubview:titleView4];
titleView4.backgroundColor = [UIColor lightGrayColor];
//demo5
FSSegmentTitleView *titleView5 = [[FSSegmentTitleView alloc]initWithFrame:CGRectMake(0, 334, CGRectGetWidth(self.view.bounds), 50) titles:@[@"全部",@"服饰穿搭",@"生活百货",@"美食吃货",@"美容护理",@"母婴儿童",@"数码家电",@"其他"] delegate:nil indicatorType:3];
titleView5.titleSelectFont = [UIFont systemFontOfSize:20];
[self.view addSubview:titleView5];
titleView5.backgroundColor = [UIColor lightGrayColor];
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
btn.backgroundColor = [UIColor blackColor];
[btn setTitle:@"pageContentView" forState:UIControlStateNormal];
btn.frame = CGRectMake(50, 400, 50, 30);
[btn sizeToFit];
[btn addTarget:self action:@selector(click) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:btn];
}
- (void)click
{
TestViewController *vc = [[TestViewController alloc]init];
[self.navigationController pushViewController:vc animated:YES];
}
@end
================================================
FILE: FSScrollContentViewDemo/FSScrollContentViewDemo/main.m
================================================
//
// main.m
// FSScrollContentViewDemo
//
// Created by huim on 2017/5/3.
// Copyright © 2017年 fengshun. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
int main(int argc, char * argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
================================================
FILE: FSScrollContentViewDemo/FSScrollContentViewDemo.xcodeproj/project.pbxproj
================================================
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
A36A9A811EB9889E00A2F2C5 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = A36A9A801EB9889E00A2F2C5 /* main.m */; };
A36A9A841EB9889E00A2F2C5 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = A36A9A831EB9889E00A2F2C5 /* AppDelegate.m */; };
A36A9A871EB9889F00A2F2C5 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = A36A9A861EB9889F00A2F2C5 /* ViewController.m */; };
A36A9A8A1EB9889F00A2F2C5 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = A36A9A881EB9889F00A2F2C5 /* Main.storyboard */; };
A36A9A8C1EB9889F00A2F2C5 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A36A9A8B1EB9889F00A2F2C5 /* Assets.xcassets */; };
A36A9A8F1EB988A000A2F2C5 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = A36A9A8D1EB988A000A2F2C5 /* LaunchScreen.storyboard */; };
A39D66591EDFEDC200D3F407 /* FSPageContentView.m in Sources */ = {isa = PBXBuildFile; fileRef = A39D66551EDFEDC200D3F407 /* FSPageContentView.m */; };
A39D665A1EDFEDC200D3F407 /* FSSegmentTitleView.m in Sources */ = {isa = PBXBuildFile; fileRef = A39D66581EDFEDC200D3F407 /* FSSegmentTitleView.m */; };
A3A324621EBACDB30065A8CB /* TestViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = A3A324611EBACDB30065A8CB /* TestViewController.m */; };
F083365D1EBA31E800667BAF /* ChildViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F083365C1EBA31E800667BAF /* ChildViewController.m */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
A36A9A7C1EB9889E00A2F2C5 /* FSScrollContentViewDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = FSScrollContentViewDemo.app; sourceTree = BUILT_PRODUCTS_DIR; };
A36A9A801EB9889E00A2F2C5 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
A36A9A821EB9889E00A2F2C5 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
A36A9A831EB9889E00A2F2C5 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
A36A9A851EB9889E00A2F2C5 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = "<group>"; };
A36A9A861EB9889F00A2F2C5 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = "<group>"; };
A36A9A891EB9889F00A2F2C5 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
A36A9A8B1EB9889F00A2F2C5 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
A36A9A8E1EB988A000A2F2C5 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
A36A9A901EB988A000A2F2C5 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
A39D664E1EDFED4000D3F407 /* FSPageContentView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FSPageContentView.h; sourceTree = "<group>"; };
A39D664F1EDFED4000D3F407 /* FSPageContentView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FSPageContentView.m; sourceTree = "<group>"; };
A39D66501EDFED4000D3F407 /* FSScrollContentView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FSScrollContentView.h; sourceTree = "<group>"; };
A39D66511EDFED4000D3F407 /* FSSegmentTitleView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FSSegmentTitleView.h; sourceTree = "<group>"; };
A39D66521EDFED4100D3F407 /* FSSegmentTitleView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FSSegmentTitleView.m; sourceTree = "<group>"; };
A39D66541EDFEDC200D3F407 /* FSPageContentView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FSPageContentView.h; sourceTree = "<group>"; };
A39D66551EDFEDC200D3F407 /* FSPageContentView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FSPageContentView.m; sourceTree = "<group>"; };
A39D66561EDFEDC200D3F407 /* FSScrollContentView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FSScrollContentView.h; sourceTree = "<group>"; };
A39D66571EDFEDC200D3F407 /* FSSegmentTitleView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FSSegmentTitleView.h; sourceTree = "<group>"; };
A39D66581EDFEDC200D3F407 /* FSSegmentTitleView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FSSegmentTitleView.m; sourceTree = "<group>"; };
A3A324601EBACDB30065A8CB /* TestViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TestViewController.h; sourceTree = "<group>"; };
A3A324611EBACDB30065A8CB /* TestViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TestViewController.m; sourceTree = "<group>"; };
F083365B1EBA31E800667BAF /* ChildViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ChildViewController.h; sourceTree = "<group>"; };
F083365C1EBA31E800667BAF /* ChildViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ChildViewController.m; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
A36A9A791EB9889E00A2F2C5 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
A36A9A731EB9889E00A2F2C5 = {
isa = PBXGroup;
children = (
A39D66531EDFEDC200D3F407 /* FSScrollContentViewLib */,
A36A9A7E1EB9889E00A2F2C5 /* FSScrollContentViewDemo */,
A36A9A7D1EB9889E00A2F2C5 /* Products */,
A39D664C1EDFED4000D3F407 /* Frameworks */,
);
sourceTree = "<group>";
};
A36A9A7D1EB9889E00A2F2C5 /* Products */ = {
isa = PBXGroup;
children = (
A36A9A7C1EB9889E00A2F2C5 /* FSScrollContentViewDemo.app */,
);
name = Products;
sourceTree = "<group>";
};
A36A9A7E1EB9889E00A2F2C5 /* FSScrollContentViewDemo */ = {
isa = PBXGroup;
children = (
A36A9A821EB9889E00A2F2C5 /* AppDelegate.h */,
A36A9A831EB9889E00A2F2C5 /* AppDelegate.m */,
A36A9A851EB9889E00A2F2C5 /* ViewController.h */,
A36A9A861EB9889F00A2F2C5 /* ViewController.m */,
A3A324601EBACDB30065A8CB /* TestViewController.h */,
A3A324611EBACDB30065A8CB /* TestViewController.m */,
F083365B1EBA31E800667BAF /* ChildViewController.h */,
F083365C1EBA31E800667BAF /* ChildViewController.m */,
A36A9A881EB9889F00A2F2C5 /* Main.storyboard */,
A36A9A8B1EB9889F00A2F2C5 /* Assets.xcassets */,
A36A9A8D1EB988A000A2F2C5 /* LaunchScreen.storyboard */,
A36A9A901EB988A000A2F2C5 /* Info.plist */,
A36A9A7F1EB9889E00A2F2C5 /* Supporting Files */,
);
path = FSScrollContentViewDemo;
sourceTree = "<group>";
};
A36A9A7F1EB9889E00A2F2C5 /* Supporting Files */ = {
isa = PBXGroup;
children = (
A36A9A801EB9889E00A2F2C5 /* main.m */,
);
name = "Supporting Files";
sourceTree = "<group>";
};
A39D664C1EDFED4000D3F407 /* Frameworks */ = {
isa = PBXGroup;
children = (
A39D664D1EDFED4000D3F407 /* FSScrollContentViewLib */,
);
name = Frameworks;
sourceTree = "<group>";
};
A39D664D1EDFED4000D3F407 /* FSScrollContentViewLib */ = {
isa = PBXGroup;
children = (
A39D664E1EDFED4000D3F407 /* FSPageContentView.h */,
A39D664F1EDFED4000D3F407 /* FSPageContentView.m */,
A39D66501EDFED4000D3F407 /* FSScrollContentView.h */,
A39D66511EDFED4000D3F407 /* FSSegmentTitleView.h */,
A39D66521EDFED4100D3F407 /* FSSegmentTitleView.m */,
);
name = FSScrollContentViewLib;
path = ../FSScrollContentViewLib;
sourceTree = "<group>";
};
A39D66531EDFEDC200D3F407 /* FSScrollContentViewLib */ = {
isa = PBXGroup;
children = (
A39D66541EDFEDC200D3F407 /* FSPageContentView.h */,
A39D66551EDFEDC200D3F407 /* FSPageContentView.m */,
A39D66561EDFEDC200D3F407 /* FSScrollContentView.h */,
A39D66571EDFEDC200D3F407 /* FSSegmentTitleView.h */,
A39D66581EDFEDC200D3F407 /* FSSegmentTitleView.m */,
);
path = FSScrollContentViewLib;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
A36A9A7B1EB9889E00A2F2C5 /* FSScrollContentViewDemo */ = {
isa = PBXNativeTarget;
buildConfigurationList = A36A9A931EB988A000A2F2C5 /* Build configuration list for PBXNativeTarget "FSScrollContentViewDemo" */;
buildPhases = (
A36A9A781EB9889E00A2F2C5 /* Sources */,
A36A9A791EB9889E00A2F2C5 /* Frameworks */,
A36A9A7A1EB9889E00A2F2C5 /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = FSScrollContentViewDemo;
productName = FSScrollContentViewDemo;
productReference = A36A9A7C1EB9889E00A2F2C5 /* FSScrollContentViewDemo.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
A36A9A741EB9889E00A2F2C5 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0830;
ORGANIZATIONNAME = fengshun;
TargetAttributes = {
A36A9A7B1EB9889E00A2F2C5 = {
CreatedOnToolsVersion = 8.3.1;
DevelopmentTeam = P5NAKU59Y6;
ProvisioningStyle = Automatic;
};
};
};
buildConfigurationList = A36A9A771EB9889E00A2F2C5 /* Build configuration list for PBXProject "FSScrollContentViewDemo" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = A36A9A731EB9889E00A2F2C5;
productRefGroup = A36A9A7D1EB9889E00A2F2C5 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
A36A9A7B1EB9889E00A2F2C5 /* FSScrollContentViewDemo */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
A36A9A7A1EB9889E00A2F2C5 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
A36A9A8F1EB988A000A2F2C5 /* LaunchScreen.storyboard in Resources */,
A36A9A8C1EB9889F00A2F2C5 /* Assets.xcassets in Resources */,
A36A9A8A1EB9889F00A2F2C5 /* Main.storyboard in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
A36A9A781EB9889E00A2F2C5 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
A36A9A871EB9889F00A2F2C5 /* ViewController.m in Sources */,
A36A9A841EB9889E00A2F2C5 /* AppDelegate.m in Sources */,
A39D66591EDFEDC200D3F407 /* FSPageContentView.m in Sources */,
A39D665A1EDFEDC200D3F407 /* FSSegmentTitleView.m in Sources */,
A3A324621EBACDB30065A8CB /* TestViewController.m in Sources */,
A36A9A811EB9889E00A2F2C5 /* main.m in Sources */,
F083365D1EBA31E800667BAF /* ChildViewController.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXVariantGroup section */
A36A9A881EB9889F00A2F2C5 /* Main.storyboard */ = {
isa = PBXVariantGroup;
children = (
A36A9A891EB9889F00A2F2C5 /* Base */,
);
name = Main.storyboard;
sourceTree = "<group>";
};
A36A9A8D1EB988A000A2F2C5 /* LaunchScreen.storyboard */ = {
isa = PBXVariantGroup;
children = (
A36A9A8E1EB988A000A2F2C5 /* Base */,
);
name = LaunchScreen.storyboard;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
A36A9A911EB988A000A2F2C5 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 10.3;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
};
name = Debug;
};
A36A9A921EB988A000A2F2C5 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 10.3;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
VALIDATE_PRODUCT = YES;
};
name = Release;
};
A36A9A941EB988A000A2F2C5 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
DEVELOPMENT_TEAM = P5NAKU59Y6;
INFOPLIST_FILE = FSScrollContentViewDemo/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 7.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.huim.FSScrollContentViewDemo;
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Debug;
};
A36A9A951EB988A000A2F2C5 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
DEVELOPMENT_TEAM = P5NAKU59Y6;
INFOPLIST_FILE = FSScrollContentViewDemo/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 7.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.huim.FSScrollContentViewDemo;
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
A36A9A771EB9889E00A2F2C5 /* Build configuration list for PBXProject "FSScrollContentViewDemo" */ = {
isa = XCConfigurationList;
buildConfigurations = (
A36A9A911EB988A000A2F2C5 /* Debug */,
A36A9A921EB988A000A2F2C5 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
A36A9A931EB988A000A2F2C5 /* Build configuration list for PBXNativeTarget "FSScrollContentViewDemo" */ = {
isa = XCConfigurationList;
buildConfigurations = (
A36A9A941EB988A000A2F2C5 /* Debug */,
A36A9A951EB988A000A2F2C5 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = A36A9A741EB9889E00A2F2C5 /* Project object */;
}
================================================
FILE: FSScrollContentViewDemo/FSScrollContentViewDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata
================================================
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:FSScrollContentViewDemo.xcodeproj">
</FileRef>
</Workspace>
================================================
FILE: FSScrollContentViewDemo/FSScrollContentViewDemo.xcodeproj/xcshareddata/xcschemes/FSScrollContentViewDemo.xcscheme
================================================
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0830"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "A36A9A7B1EB9889E00A2F2C5"
BuildableName = "FSScrollContentViewDemo.app"
BlueprintName = "FSScrollContentViewDemo"
ReferencedContainer = "container:FSScrollContentViewDemo.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "A36A9A7B1EB9889E00A2F2C5"
BuildableName = "FSScrollContentViewDemo.app"
BlueprintName = "FSScrollContentViewDemo"
ReferencedContainer = "container:FSScrollContentViewDemo.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "A36A9A7B1EB9889E00A2F2C5"
BuildableName = "FSScrollContentViewDemo.app"
BlueprintName = "FSScrollContentViewDemo"
ReferencedContainer = "container:FSScrollContentViewDemo.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "A36A9A7B1EB9889E00A2F2C5"
BuildableName = "FSScrollContentViewDemo.app"
BlueprintName = "FSScrollContentViewDemo"
ReferencedContainer = "container:FSScrollContentViewDemo.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
================================================
FILE: FSScrollContentViewDemo/FSScrollContentViewLib/FSPageContentView.h
================================================
//
// FSPageContentView.h
// Huim
//
// Created by huim on 2017/4/28.
// Copyright © 2017年 huim. All rights reserved.
//
#import <UIKit/UIKit.h>
@class FSPageContentView;
@protocol FSPageContentViewDelegate <NSObject>
@optional
/**
FSPageContentView开始滑动
@param contentView FSPageContentView
*/
- (void)FSContentViewWillBeginDragging:(FSPageContentView *)contentView;
/**
FSPageContentView滑动调用
@param contentView FSPageContentView
@param startIndex 开始滑动页面索引
@param endIndex 结束滑动页面索引
@param progress 滑动进度
*/
- (void)FSContentViewDidScroll:(FSPageContentView *)contentView startIndex:(NSInteger)startIndex endIndex:(NSInteger)endIndex progress:(CGFloat)progress;
/**
FSPageContentView结束滑动
@param contentView FSPageContentView
@param startIndex 开始滑动索引
@param endIndex 结束滑动索引
*/
- (void)FSContenViewDidEndDecelerating:(FSPageContentView *)contentView startIndex:(NSInteger)startIndex endIndex:(NSInteger)endIndex;
/**
scrollViewDidEndDragging
@param contentView FSPageContentView
*/
- (void)FSContenViewDidEndDragging:(FSPageContentView *)contentView;
@end
@interface FSPageContentView : UIView
/**
对象方法创建FSPageContentView
@param frame frame
@param childVCs 子VC数组
@param parentVC 父视图VC
@param delegate delegate
@return FSPageContentView
*/
- (instancetype)initWithFrame:(CGRect)frame childVCs:(NSArray *)childVCs parentVC:(UIViewController *)parentVC delegate:(id<FSPageContentViewDelegate>)delegate;
@property (nonatomic, weak) id<FSPageContentViewDelegate>delegate;
/**
设置contentView当前展示的页面索引,默认为0
*/
@property (nonatomic, assign) NSInteger contentViewCurrentIndex;
/**
设置contentView能否左右滑动,默认YES
*/
@property (nonatomic, assign) BOOL contentViewCanScroll;
@end
================================================
FILE: FSScrollContentViewDemo/FSScrollContentViewLib/FSPageContentView.m
================================================
//
// FSPageContentView.m
// Huim
//
// Created by huim on 2017/4/28.
// Copyright © 2017年 huim. All rights reserved.
//
#import "FSPageContentView.h"
#define IOS_VERSION ([[[UIDevice currentDevice] systemVersion] floatValue])
static NSString *collectionCellIdentifier = @"collectionCellIdentifier";
@interface FSPageContentView ()<UICollectionViewDelegate,UICollectionViewDataSource>
@property (nonatomic, weak) UIViewController *parentVC;//父视图
@property (nonatomic, strong) NSArray *childsVCs;//子视图数组
@property (nonatomic, weak) UICollectionView *collectionView;
@property (nonatomic, assign) CGFloat startOffsetX;
@property (nonatomic, assign) BOOL isSelectBtn;//是否是滑动
@end
@implementation FSPageContentView
- (instancetype)initWithFrame:(CGRect)frame childVCs:(NSArray *)childVCs parentVC:(UIViewController *)parentVC delegate:(id<FSPageContentViewDelegate>)delegate
{
self = [super initWithFrame:frame];
if (self) {
self.parentVC = parentVC;
self.childsVCs = childVCs;
self.delegate = delegate;
[self setupSubViews];
}
return self;
}
- (void)layoutSubviews
{
[super layoutSubviews];
}
#pragma mark --LazyLoad
- (UICollectionView *)collectionView
{
if (!_collectionView) {
UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc]init];
flowLayout.itemSize = self.bounds.size;
flowLayout.minimumLineSpacing = 0;
flowLayout.minimumInteritemSpacing = 0;
flowLayout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
UICollectionView * collectionView = [[UICollectionView alloc]initWithFrame:self.bounds collectionViewLayout:flowLayout];
collectionView.showsHorizontalScrollIndicator = NO;
collectionView.pagingEnabled = YES;
collectionView.bounces = NO;
collectionView.delegate = self;
collectionView.dataSource = self;
[collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:collectionCellIdentifier];
[self addSubview:collectionView];
self.collectionView = collectionView;
}
return _collectionView;
}
#pragma mark --setup
- (void)setupSubViews
{
_startOffsetX = 0;
_isSelectBtn = NO;
_contentViewCanScroll = YES;
for (UIViewController *childVC in self.childsVCs) {
[self.parentVC addChildViewController:childVC];
}
// [self addSubview:self.collectionView];
[self.collectionView reloadData];
}
#pragma mark UICollectionView
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return self.childsVCs.count;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:collectionCellIdentifier forIndexPath:indexPath];
if (IOS_VERSION < 8.0) {
[cell.contentView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
UIViewController *childVC = self.childsVCs[indexPath.item];
childVC.view.frame = cell.contentView.bounds;
[cell.contentView addSubview:childVC.view];
}
return cell;
}
#ifdef __IPHONE_8_0
- (void)collectionView:(UICollectionView *)collectionView willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath{
[cell.contentView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
UIViewController *childVc = self.childsVCs[indexPath.row];
childVc.view.frame = cell.contentView.bounds;
[cell.contentView addSubview:childVc.view];
}
#endif
#pragma mark UIScrollView
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
_isSelectBtn = NO;
_startOffsetX = scrollView.contentOffset.x;
if (self.delegate && [self.delegate respondsToSelector:@selector(FSContentViewWillBeginDragging:)]) {
[self.delegate FSContentViewWillBeginDragging:self];
}
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
if (_isSelectBtn) {
return;
}
CGFloat scrollView_W = scrollView.bounds.size.width;
CGFloat currentOffsetX = scrollView.contentOffset.x;
NSInteger startIndex = floor(_startOffsetX/scrollView_W);
NSInteger endIndex;
CGFloat progress;
if (currentOffsetX > _startOffsetX) {//左滑left
progress = (currentOffsetX - _startOffsetX)/scrollView_W;
endIndex = startIndex + 1;
if (endIndex > self.childsVCs.count - 1) {
endIndex = self.childsVCs.count - 1;
}
}else if (currentOffsetX == _startOffsetX){//没滑过去
progress = 0;
endIndex = startIndex;
}else{//右滑right
progress = (_startOffsetX - currentOffsetX)/scrollView_W;
endIndex = startIndex - 1;
endIndex = endIndex < 0?0:endIndex;
}
if (self.delegate && [self.delegate respondsToSelector:@selector(FSContentViewDidScroll:startIndex:endIndex:progress:)]) {
[self.delegate FSContentViewDidScroll:self startIndex:startIndex endIndex:endIndex progress:progress];
}
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
CGFloat scrollView_W = scrollView.bounds.size.width;
CGFloat currentOffsetX = scrollView.contentOffset.x;
NSInteger startIndex = floor(_startOffsetX/scrollView_W);
NSInteger endIndex = floor(currentOffsetX/scrollView_W);
if (self.delegate && [self.delegate respondsToSelector:@selector(FSContenViewDidEndDecelerating:startIndex:endIndex:)]) {
[self.delegate FSContenViewDidEndDecelerating:self startIndex:startIndex endIndex:endIndex];
}
}
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
if (!decelerate) {
if (self.delegate && [self.delegate respondsToSelector:@selector(FSContenViewDidEndDragging:)]) {
[self.delegate FSContenViewDidEndDragging:self];
}
}
}
#pragma mark setter
- (void)setContentViewCurrentIndex:(NSInteger)contentViewCurrentIndex
{
if (contentViewCurrentIndex < 0||contentViewCurrentIndex > self.childsVCs.count-1) {
return;
}
_isSelectBtn = YES;
_contentViewCurrentIndex = contentViewCurrentIndex;
[self.collectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForRow:contentViewCurrentIndex inSection:0] atScrollPosition:UICollectionViewScrollPositionNone animated:NO];
}
- (void)setContentViewCanScroll:(BOOL)contentViewCanScroll
{
_contentViewCanScroll = contentViewCanScroll;
_collectionView.scrollEnabled = _contentViewCanScroll;
}
@end
================================================
FILE: FSScrollContentViewDemo/FSScrollContentViewLib/FSScrollContentView.h
================================================
//
// FSScrollContentView.h
// FSScrollContentViewDemo
//
// Created by 冯顺 on 2017/5/3.
// Copyright © 2017年 fengshun. All rights reserved.
//
#import "FSPageContentView.h"
#import "FSSegmentTitleView.h"
================================================
FILE: FSScrollContentViewDemo/FSScrollContentViewLib/FSSegmentTitleView.h
================================================
//
// FSSegmentTitleView.h
// FSScrollContentViewDemo
//
// Created by huim on 2017/5/3.
// Copyright © 2017年 fengshun. All rights reserved.
//
#import <UIKit/UIKit.h>
@class FSSegmentTitleView;
typedef enum : NSUInteger {
FSIndicatorTypeDefault,//默认与按钮长度相同
FSIndicatorTypeEqualTitle,//与文字长度相同
FSIndicatorTypeCustom,//自定义文字边缘延伸宽度
FSIndicatorTypeNone,
} FSIndicatorType;//指示器类型枚举
@protocol FSSegmentTitleViewDelegate <NSObject>
@optional
/**
切换标题
@param titleView FSSegmentTitleView
@param startIndex 切换前标题索引
@param endIndex 切换后标题索引
*/
- (void)FSSegmentTitleView:(FSSegmentTitleView *)titleView startIndex:(NSInteger)startIndex endIndex:(NSInteger)endIndex;
/**
将要开始滑动
@param titleView FSSegmentTitleView
*/
- (void)FSSegmentTitleViewWillBeginDragging:(FSSegmentTitleView *)titleView;
/**
将要停止滑动
@param titleView FSSegmentTitleView
*/
- (void)FSSegmentTitleViewWillEndDragging:(FSSegmentTitleView *)titleView;
@end
@interface FSSegmentTitleView : UIView
@property (nonatomic, weak) id<FSSegmentTitleViewDelegate>delegate;
/**
标题文字间距,默认20
*/
@property (nonatomic, assign) CGFloat itemMargin;
/**
当前选中标题索引,默认0
*/
@property (nonatomic, assign) NSInteger selectIndex;
/**
标题字体大小,默认15
*/
@property (nonatomic, strong) UIFont *titleFont;
/**
标题选中字体大小,默认15
*/
@property (nonatomic, strong) UIFont *titleSelectFont;
/**
标题正常颜色,默认black
*/
@property (nonatomic, strong) UIColor *titleNormalColor;
/**
标题选中颜色,默认red
*/
@property (nonatomic, strong) UIColor *titleSelectColor;
/**
指示器颜色,默认与titleSelectColor一样,在FSIndicatorTypeNone下无效
*/
@property (nonatomic, strong) UIColor *indicatorColor;
/**
在FSIndicatorTypeCustom时可自定义此属性,为指示器一端延伸长度,默认5
*/
@property (nonatomic, assign) CGFloat indicatorExtension;
/**
对象方法创建FSSegmentTitleView
@param frame frame
@param titlesArr 标题数组
@param delegate delegate
@param incatorType 指示器类型
@return FSSegmentTitleView
*/
- (instancetype)initWithFrame:(CGRect)frame titles:(NSArray *)titlesArr delegate:(id<FSSegmentTitleViewDelegate>)delegate indicatorType:(FSIndicatorType)incatorType;
@end
================================================
FILE: FSScrollContentViewDemo/FSScrollContentViewLib/FSSegmentTitleView.m
================================================
//
// FSSegmentTitleView.m
// FSScrollContentViewDemo
//
// Created by huim on 2017/5/3.
// Copyright © 2017年 fengshun. All rights reserved.
//
#import "FSSegmentTitleView.h"
@interface FSSegmentTitleView ()<UIScrollViewDelegate>
@property (nonatomic, strong) UIScrollView *scrollView;
@property (nonatomic, strong) NSMutableArray<UIButton *> *itemBtnArr;
@property (nonatomic, strong) UIView *indicatorView;
@property (nonatomic, assign) FSIndicatorType indicatorType;
@property (nonatomic, strong) NSArray *titlesArr;
@end
@implementation FSSegmentTitleView
- (instancetype)initWithFrame:(CGRect)frame titles:(NSArray *)titlesArr delegate:(id<FSSegmentTitleViewDelegate>)delegate indicatorType:(FSIndicatorType)incatorType
{
self = [super initWithFrame:frame];
if (self) {
[self initWithProperty];
self.titlesArr = titlesArr;
self.delegate = delegate;
self.indicatorType = incatorType;
}
return self;
}
//初始化默认属性值
- (void)initWithProperty
{
self.itemMargin = 20;
self.selectIndex = 0;
self.titleNormalColor = [UIColor blackColor];
self.titleSelectColor = [UIColor redColor];
self.titleFont = [UIFont systemFontOfSize:15];
self.indicatorColor = self.titleSelectColor;
self.indicatorExtension = 5.f;
self.titleSelectFont = self.titleFont;
}
//重新布局frame
- (void)layoutSubviews
{
[super layoutSubviews];
self.scrollView.frame = self.bounds;
if (self.itemBtnArr.count == 0) {
return;
}
CGFloat totalBtnWidth = 0.0;
UIFont *titleFont = _titleFont;
if (_titleFont != _titleSelectFont) {
for (int idx = 0; idx < self.titlesArr.count; idx++) {
UIButton *btn = self.itemBtnArr[idx];
titleFont = btn.isSelected?_titleSelectFont:_titleFont;
CGFloat itemBtnWidth = [FSSegmentTitleView getWidthWithString:self.titlesArr[idx] font:titleFont] + self.itemMargin;
totalBtnWidth += itemBtnWidth;
}
}
else
{
for (NSString *title in self.titlesArr) {
CGFloat itemBtnWidth = [FSSegmentTitleView getWidthWithString:title font:titleFont] + self.itemMargin;
totalBtnWidth += itemBtnWidth;
}
}
if (totalBtnWidth <= CGRectGetWidth(self.bounds)) {//不能滑动
CGFloat itemBtnWidth = CGRectGetWidth(self.bounds)/self.itemBtnArr.count;
CGFloat itemBtnHeight = CGRectGetHeight(self.bounds);
[self.itemBtnArr enumerateObjectsUsingBlock:^(UIButton * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
obj.frame = CGRectMake(idx * itemBtnWidth, 0, itemBtnWidth, itemBtnHeight);
}];
self.scrollView.contentSize = CGSizeMake(CGRectGetWidth(self.bounds), CGRectGetHeight(self.scrollView.bounds));
}else{//超出屏幕 可以滑动
CGFloat currentX = 0;
for (int idx = 0; idx < self.titlesArr.count; idx++) {
UIButton *btn = self.itemBtnArr[idx];
titleFont = btn.isSelected?_titleSelectFont:_titleFont;
CGFloat itemBtnWidth = [FSSegmentTitleView getWidthWithString:self.titlesArr[idx] font:titleFont] + self.itemMargin;
CGFloat itemBtnHeight = CGRectGetHeight(self.bounds);
btn.frame = CGRectMake(currentX, 0, itemBtnWidth, itemBtnHeight);
currentX += itemBtnWidth;
}
self.scrollView.contentSize = CGSizeMake(currentX, CGRectGetHeight(self.scrollView.bounds));
}
[self moveIndicatorView:YES];
}
- (void)moveIndicatorView:(BOOL)animated
{
UIFont *titleFont = _titleFont;
UIButton *selectBtn = self.itemBtnArr[self.selectIndex];
titleFont = selectBtn.isSelected?_titleSelectFont:_titleFont;
CGFloat indicatorWidth = [FSSegmentTitleView getWidthWithString:self.titlesArr[self.selectIndex] font:titleFont];
[UIView animateWithDuration:(animated?0.05:0) animations:^{
switch (_indicatorType) {
case FSIndicatorTypeDefault:
self.indicatorView.frame = CGRectMake(selectBtn.frame.origin.x , CGRectGetHeight(self.scrollView.bounds) - 2, CGRectGetWidth(selectBtn.bounds), 2);
break;
case FSIndicatorTypeEqualTitle:
self.indicatorView.center = CGPointMake(selectBtn.center.x, CGRectGetHeight(self.scrollView.bounds) - 1);
self.indicatorView.bounds = CGRectMake(0, 0, indicatorWidth, 2);
break;
case FSIndicatorTypeCustom:
self.indicatorView.center = CGPointMake(selectBtn.center.x, CGRectGetHeight(self.scrollView.bounds) - 1);
self.indicatorView.bounds = CGRectMake(0, 0, indicatorWidth + _indicatorExtension*2, 2);
break;
case FSIndicatorTypeNone:
self.indicatorView.frame = CGRectZero;
break;
default:
break;
}
} completion:^(BOOL finished) {
[self scrollSelectBtnCenter:animated];
}];
}
- (void)scrollSelectBtnCenter:(BOOL)animated
{
UIButton *selectBtn = self.itemBtnArr[self.selectIndex];
CGRect centerRect = CGRectMake(selectBtn.center.x - CGRectGetWidth(self.scrollView.bounds)/2, 0, CGRectGetWidth(self.scrollView.bounds), CGRectGetHeight(self.scrollView.bounds));
[self.scrollView scrollRectToVisible:centerRect animated:animated];
}
#pragma mark --LazyLoad
- (UIScrollView *)scrollView {
if (!_scrollView) {
_scrollView = [[UIScrollView alloc] init];
_scrollView.showsHorizontalScrollIndicator = NO;
_scrollView.showsVerticalScrollIndicator = NO;
_scrollView.scrollsToTop = NO;
_scrollView.delegate = self;
[self addSubview:_scrollView];
}
return _scrollView;
}
- (NSMutableArray<UIButton *>*)itemBtnArr
{
if (!_itemBtnArr) {
_itemBtnArr = [[NSMutableArray alloc]init];
}
return _itemBtnArr;
}
- (UIView *)indicatorView
{
if (!_indicatorView) {
_indicatorView = [[UIView alloc]init];
[self.scrollView addSubview:_indicatorView];
}
return _indicatorView;
}
#pragma mark --Setter
- (void)setTitlesArr:(NSArray *)titlesArr
{
_titlesArr = titlesArr;
[self.itemBtnArr makeObjectsPerformSelector:@selector(removeFromSuperview)];
self.itemBtnArr = nil;
for (NSString *title in titlesArr) {
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
btn.tag = self.itemBtnArr.count + 666;
[btn setTitle:title forState:UIControlStateNormal];
[btn setTitleColor:_titleNormalColor forState:UIControlStateNormal];
[btn setTitleColor:_titleSelectColor forState:UIControlStateSelected];
btn.titleLabel.font = _titleFont;
[self.scrollView addSubview:btn];
[btn addTarget:self action:@selector(btnClick:) forControlEvents:UIControlEventTouchUpInside];
if (self.itemBtnArr.count == self.selectIndex) {
btn.selected = YES;
}
[self.itemBtnArr addObject:btn];
}
[self setNeedsLayout];
[self layoutIfNeeded];
}
- (void)setItemMargin:(CGFloat)itemMargin
{
_itemMargin = itemMargin;
[self setNeedsLayout];
[self layoutIfNeeded];
}
- (void)setSelectIndex:(NSInteger)selectIndex
{
if (_selectIndex == selectIndex||selectIndex < 0||selectIndex > self.itemBtnArr.count - 1) {
return;
}
UIButton *lastBtn = [self.scrollView viewWithTag:_selectIndex + 666];
lastBtn.selected = NO;
lastBtn.titleLabel.font = _titleFont;
_selectIndex = selectIndex;
UIButton *currentBtn = [self.scrollView viewWithTag:_selectIndex + 666];
currentBtn.selected = YES;
currentBtn.titleLabel.font = _titleSelectFont;
// [self moveIndicatorView:YES];
[self setNeedsLayout];
[self layoutIfNeeded];
}
- (void)setTitleFont:(UIFont *)titleFont
{
_titleFont = titleFont;
for (UIButton *btn in self.itemBtnArr) {
btn.titleLabel.font = titleFont;
}
[self setNeedsLayout];
[self layoutIfNeeded];
}
- (void)setTitleSelectFont:(UIFont *)titleSelectFont
{
if (_titleFont == titleSelectFont) {
_titleSelectFont = _titleFont;
return;
}
_titleSelectFont = titleSelectFont;
for (UIButton *btn in self.itemBtnArr) {
btn.titleLabel.font = btn.isSelected?titleSelectFont:_titleFont;
}
[self setNeedsLayout];
[self layoutIfNeeded];
}
- (void)setTitleNormalColor:(UIColor *)titleNormalColor
{
_titleNormalColor = titleNormalColor;
for (UIButton *btn in self.itemBtnArr) {
[btn setTitleColor:titleNormalColor forState:UIControlStateNormal];
}
}
- (void)setTitleSelectColor:(UIColor *)titleSelectColor
{
_titleSelectColor = titleSelectColor;
for (UIButton *btn in self.itemBtnArr) {
[btn setTitleColor:titleSelectColor forState:UIControlStateSelected];
}
}
- (void)setIndicatorColor:(UIColor *)indicatorColor
{
_indicatorColor = indicatorColor;
self.indicatorView.backgroundColor = indicatorColor;
}
- (void)setIndicatorExtension:(CGFloat)indicatorExtension
{
_indicatorExtension = indicatorExtension;
[self setNeedsLayout];
[self layoutIfNeeded];
}
#pragma mark --Btn
- (void)btnClick:(UIButton *)btn
{
NSInteger index = btn.tag - 666;
if (index == self.selectIndex) {
return;
}
if (self.delegate&&[self.delegate respondsToSelector:@selector(FSSegmentTitleView:startIndex:endIndex:)]) {
[self.delegate FSSegmentTitleView:self startIndex:self.selectIndex endIndex:index];
}
self.selectIndex = index;
}
#pragma mark UIScrollView
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
if (self.delegate&&[self.delegate respondsToSelector:@selector(FSSegmentTitleViewWillBeginDragging:)]) {
[self.delegate FSSegmentTitleViewWillBeginDragging:self];
}
}
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset
{
if (self.delegate&&[self.delegate respondsToSelector:@selector(FSSegmentTitleViewWillEndDragging:)]) {
[self.delegate FSSegmentTitleViewWillEndDragging:self];
}
}
#pragma mark Private
/**
计算字符串长度
@param string string
@param font font
@return 字符串长度
*/
+ (CGFloat)getWidthWithString:(NSString *)string font:(UIFont *)font {
NSDictionary *attrs = @{NSFontAttributeName : font};
return [string boundingRectWithSize:CGSizeMake(0, 0) options:NSStringDrawingUsesLineFragmentOrigin attributes:attrs context:nil].size.width;
}
/**
随机色
@return 调试用
*/
+ (UIColor*) randomColor{
NSInteger r = arc4random() % 255;
NSInteger g = arc4random() % 255;
NSInteger b = arc4random() % 255;
return [UIColor colorWithRed:r/255.0 green:g/255.0 blue:b/255.0 alpha:1];
}
@end
================================================
FILE: FSScrollContentViewLib/FSPageContentView.h
================================================
//
// FSPageContentView.h
// Huim
//
// Created by huim on 2017/4/28.
// Copyright © 2017年 huim. All rights reserved.
//
#import <UIKit/UIKit.h>
@class FSPageContentView;
@protocol FSPageContentViewDelegate <NSObject>
@optional
/**
FSPageContentView开始滑动
@param contentView FSPageContentView
*/
- (void)FSContentViewWillBeginDragging:(FSPageContentView *)contentView;
/**
FSPageContentView滑动调用
@param contentView FSPageContentView
@param startIndex 开始滑动页面索引
@param endIndex 结束滑动页面索引
@param progress 滑动进度
*/
- (void)FSContentViewDidScroll:(FSPageContentView *)contentView startIndex:(NSInteger)startIndex endIndex:(NSInteger)endIndex progress:(CGFloat)progress;
/**
FSPageContentView结束滑动
@param contentView FSPageContentView
@param startIndex 开始滑动索引
@param endIndex 结束滑动索引
*/
- (void)FSContenViewDidEndDecelerating:(FSPageContentView *)contentView startIndex:(NSInteger)startIndex endIndex:(NSInteger)endIndex;
/**
scrollViewDidEndDragging
@param contentView FSPageContentView
*/
- (void)FSContenViewDidEndDragging:(FSPageContentView *)contentView;
@end
@interface FSPageContentView : UIView
/**
对象方法创建FSPageContentView
@param frame frame
@param childVCs 子VC数组
@param parentVC 父视图VC
@param delegate delegate
@return FSPageContentView
*/
- (instancetype)initWithFrame:(CGRect)frame childVCs:(NSArray *)childVCs parentVC:(UIViewController *)parentVC delegate:(id<FSPageContentViewDelegate>)delegate;
@property (nonatomic, weak) id<FSPageContentViewDelegate>delegate;
/**
设置contentView当前展示的页面索引,默认为0
*/
@property (nonatomic, assign) NSInteger contentViewCurrentIndex;
/**
设置contentView能否左右滑动,默认YES
*/
@property (nonatomic, assign) BOOL contentViewCanScroll;
@end
================================================
FILE: FSScrollContentViewLib/FSPageContentView.m
================================================
//
// FSPageContentView.m
// Huim
//
// Created by huim on 2017/4/28.
// Copyright © 2017年 huim. All rights reserved.
//
#import "FSPageContentView.h"
#define IOS_VERSION ([[[UIDevice currentDevice] systemVersion] floatValue])
static NSString *collectionCellIdentifier = @"collectionCellIdentifier";
@interface FSPageContentView ()<UICollectionViewDelegate,UICollectionViewDataSource>
@property (nonatomic, weak) UIViewController *parentVC;//父视图
@property (nonatomic, strong) NSArray *childsVCs;//子视图数组
@property (nonatomic, weak) UICollectionView *collectionView;
@property (nonatomic, assign) CGFloat startOffsetX;
@property (nonatomic, assign) BOOL isSelectBtn;//是否是滑动
@end
@implementation FSPageContentView
- (instancetype)initWithFrame:(CGRect)frame childVCs:(NSArray *)childVCs parentVC:(UIViewController *)parentVC delegate:(id<FSPageContentViewDelegate>)delegate
{
self = [super initWithFrame:frame];
if (self) {
self.parentVC = parentVC;
self.childsVCs = childVCs;
self.delegate = delegate;
[self setupSubViews];
}
return self;
}
- (void)layoutSubviews
{
[super layoutSubviews];
}
#pragma mark --LazyLoad
- (UICollectionView *)collectionView
{
if (!_collectionView) {
UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc]init];
flowLayout.itemSize = self.bounds.size;
flowLayout.minimumLineSpacing = 0;
flowLayout.minimumInteritemSpacing = 0;
flowLayout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
UICollectionView * collectionView = [[UICollectionView alloc]initWithFrame:self.bounds collectionViewLayout:flowLayout];
collectionView.showsHorizontalScrollIndicator = NO;
collectionView.pagingEnabled = YES;
collectionView.bounces = NO;
collectionView.delegate = self;
collectionView.dataSource = self;
[collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:collectionCellIdentifier];
[self addSubview:collectionView];
self.collectionView = collectionView;
}
return _collectionView;
}
#pragma mark --setup
- (void)setupSubViews
{
_startOffsetX = 0;
_isSelectBtn = NO;
_contentViewCanScroll = YES;
for (UIViewController *childVC in self.childsVCs) {
[self.parentVC addChildViewController:childVC];
}
// [self addSubview:self.collectionView];
[self.collectionView reloadData];
}
#pragma mark UICollectionView
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return self.childsVCs.count;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:collectionCellIdentifier forIndexPath:indexPath];
if (IOS_VERSION < 8.0) {
[cell.contentView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
UIViewController *childVC = self.childsVCs[indexPath.item];
childVC.view.frame = cell.contentView.bounds;
[cell.contentView addSubview:childVC.view];
}
return cell;
}
#ifdef __IPHONE_8_0
- (void)collectionView:(UICollectionView *)collectionView willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath{
[cell.contentView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
UIViewController *childVc = self.childsVCs[indexPath.row];
childVc.view.frame = cell.contentView.bounds;
[cell.contentView addSubview:childVc.view];
}
#endif
#pragma mark UIScrollView
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
_isSelectBtn = NO;
_startOffsetX = scrollView.contentOffset.x;
if (self.delegate && [self.delegate respondsToSelector:@selector(FSContentViewWillBeginDragging:)]) {
[self.delegate FSContentViewWillBeginDragging:self];
}
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
if (_isSelectBtn) {
return;
}
CGFloat scrollView_W = scrollView.bounds.size.width;
CGFloat currentOffsetX = scrollView.contentOffset.x;
NSInteger startIndex = floor(_startOffsetX/scrollView_W);
NSInteger endIndex;
CGFloat progress;
if (currentOffsetX > _startOffsetX) {//左滑left
progress = (currentOffsetX - _startOffsetX)/scrollView_W;
endIndex = startIndex + 1;
if (endIndex > self.childsVCs.count - 1) {
endIndex = self.childsVCs.count - 1;
}
}else if (currentOffsetX == _startOffsetX){//没滑过去
progress = 0;
endIndex = startIndex;
}else{//右滑right
progress = (_startOffsetX - currentOffsetX)/scrollView_W;
endIndex = startIndex - 1;
endIndex = endIndex < 0?0:endIndex;
}
if (self.delegate && [self.delegate respondsToSelector:@selector(FSContentViewDidScroll:startIndex:endIndex:progress:)]) {
[self.delegate FSContentViewDidScroll:self startIndex:startIndex endIndex:endIndex progress:progress];
}
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
CGFloat scrollView_W = scrollView.bounds.size.width;
CGFloat currentOffsetX = scrollView.contentOffset.x;
NSInteger startIndex = floor(_startOffsetX/scrollView_W);
NSInteger endIndex = floor(currentOffsetX/scrollView_W);
if (self.delegate && [self.delegate respondsToSelector:@selector(FSContenViewDidEndDecelerating:startIndex:endIndex:)]) {
[self.delegate FSContenViewDidEndDecelerating:self startIndex:startIndex endIndex:endIndex];
}
}
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
if (!decelerate) {
if (self.delegate && [self.delegate respondsToSelector:@selector(FSContenViewDidEndDragging:)]) {
[self.delegate FSContenViewDidEndDragging:self];
}
}
}
#pragma mark setter
- (void)setContentViewCurrentIndex:(NSInteger)contentViewCurrentIndex
{
if (contentViewCurrentIndex < 0||contentViewCurrentIndex > self.childsVCs.count-1) {
return;
}
_isSelectBtn = YES;
_contentViewCurrentIndex = contentViewCurrentIndex;
[self.collectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForRow:contentViewCurrentIndex inSection:0] atScrollPosition:UICollectionViewScrollPositionNone animated:NO];
}
- (void)setContentViewCanScroll:(BOOL)contentViewCanScroll
{
_contentViewCanScroll = contentViewCanScroll;
_collectionView.scrollEnabled = _contentViewCanScroll;
}
@end
================================================
FILE: FSScrollContentViewLib/FSScrollContentView.h
================================================
//
// FSScrollContentView.h
// FSScrollContentViewDemo
//
// Created by 冯顺 on 2017/5/3.
// Copyright © 2017年 fengshun. All rights reserved.
//
#import "FSPageContentView.h"
#import "FSSegmentTitleView.h"
================================================
FILE: FSScrollContentViewLib/FSSegmentTitleView.h
================================================
//
// FSSegmentTitleView.h
// FSScrollContentViewDemo
//
// Created by huim on 2017/5/3.
// Copyright © 2017年 fengshun. All rights reserved.
//
#import <UIKit/UIKit.h>
@class FSSegmentTitleView;
typedef enum : NSUInteger {
FSIndicatorTypeDefault,//默认与按钮长度相同
FSIndicatorTypeEqualTitle,//与文字长度相同
FSIndicatorTypeCustom,//自定义文字边缘延伸宽度
FSIndicatorTypeNone,
} FSIndicatorType;//指示器类型枚举
@protocol FSSegmentTitleViewDelegate <NSObject>
@optional
/**
切换标题
@param titleView FSSegmentTitleView
@param startIndex 切换前标题索引
@param endIndex 切换后标题索引
*/
- (void)FSSegmentTitleView:(FSSegmentTitleView *)titleView startIndex:(NSInteger)startIndex endIndex:(NSInteger)endIndex;
/**
将要开始滑动
@param titleView FSSegmentTitleView
*/
- (void)FSSegmentTitleViewWillBeginDragging:(FSSegmentTitleView *)titleView;
/**
将要停止滑动
@param titleView FSSegmentTitleView
*/
- (void)FSSegmentTitleViewWillEndDragging:(FSSegmentTitleView *)titleView;
@end
@interface FSSegmentTitleView : UIView
@property (nonatomic, weak) id<FSSegmentTitleViewDelegate>delegate;
/**
标题文字间距,默认20
*/
@property (nonatomic, assign) CGFloat itemMargin;
/**
当前选中标题索引,默认0
*/
@property (nonatomic, assign) NSInteger selectIndex;
/**
标题字体大小,默认15
*/
@property (nonatomic, strong) UIFont *titleFont;
/**
标题选中字体大小,默认15
*/
@property (nonatomic, strong) UIFont *titleSelectFont;
/**
标题正常颜色,默认black
*/
@property (nonatomic, strong) UIColor *titleNormalColor;
/**
标题选中颜色,默认red
*/
@property (nonatomic, strong) UIColor *titleSelectColor;
/**
指示器颜色,默认与titleSelectColor一样,在FSIndicatorTypeNone下无效
*/
@property (nonatomic, strong) UIColor *indicatorColor;
/**
在FSIndicatorTypeCustom时可自定义此属性,为指示器一端延伸长度,默认5
*/
@property (nonatomic, assign) CGFloat indicatorExtension;
/**
对象方法创建FSSegmentTitleView
@param frame frame
@param titlesArr 标题数组
@param delegate delegate
@param incatorType 指示器类型
@return FSSegmentTitleView
*/
- (instancetype)initWithFrame:(CGRect)frame titles:(NSArray *)titlesArr delegate:(id<FSSegmentTitleViewDelegate>)delegate indicatorType:(FSIndicatorType)incatorType;
@end
================================================
FILE: FSScrollContentViewLib/FSSegmentTitleView.m
================================================
//
// FSSegmentTitleView.m
// FSScrollContentViewDemo
//
// Created by huim on 2017/5/3.
// Copyright © 2017年 fengshun. All rights reserved.
//
#import "FSSegmentTitleView.h"
@interface FSSegmentTitleView ()<UIScrollViewDelegate>
@property (nonatomic, strong) UIScrollView *scrollView;
@property (nonatomic, strong) NSMutableArray<UIButton *> *itemBtnArr;
@property (nonatomic, strong) UIView *indicatorView;
@property (nonatomic, assign) FSIndicatorType indicatorType;
@property (nonatomic, strong) NSArray *titlesArr;
@end
@implementation FSSegmentTitleView
- (instancetype)initWithFrame:(CGRect)frame titles:(NSArray *)titlesArr delegate:(id<FSSegmentTitleViewDelegate>)delegate indicatorType:(FSIndicatorType)incatorType
{
self = [super initWithFrame:frame];
if (self) {
[self initWithProperty];
self.titlesArr = titlesArr;
self.delegate = delegate;
self.indicatorType = incatorType;
}
return self;
}
//初始化默认属性值
- (void)initWithProperty
{
self.itemMargin = 20;
self.selectIndex = 0;
self.titleNormalColor = [UIColor blackColor];
self.titleSelectColor = [UIColor redColor];
self.titleFont = [UIFont systemFontOfSize:15];
self.indicatorColor = self.titleSelectColor;
self.indicatorExtension = 5.f;
self.titleSelectFont = self.titleFont;
}
//重新布局frame
- (void)layoutSubviews
{
[super layoutSubviews];
self.scrollView.frame = self.bounds;
if (self.itemBtnArr.count == 0) {
return;
}
CGFloat totalBtnWidth = 0.0;
UIFont *titleFont = _titleFont;
if (_titleFont != _titleSelectFont) {
for (int idx = 0; idx < self.titlesArr.count; idx++) {
UIButton *btn = self.itemBtnArr[idx];
titleFont = btn.isSelected?_titleSelectFont:_titleFont;
CGFloat itemBtnWidth = [FSSegmentTitleView getWidthWithString:self.titlesArr[idx] font:titleFont] + self.itemMargin;
totalBtnWidth += itemBtnWidth;
}
}
else
{
for (NSString *title in self.titlesArr) {
CGFloat itemBtnWidth = [FSSegmentTitleView getWidthWithString:title font:titleFont] + self.itemMargin;
totalBtnWidth += itemBtnWidth;
}
}
if (totalBtnWidth <= CGRectGetWidth(self.bounds)) {//不能滑动
CGFloat itemBtnWidth = CGRectGetWidth(self.bounds)/self.itemBtnArr.count;
CGFloat itemBtnHeight = CGRectGetHeight(self.bounds);
[self.itemBtnArr enumerateObjectsUsingBlock:^(UIButton * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
obj.frame = CGRectMake(idx * itemBtnWidth, 0, itemBtnWidth, itemBtnHeight);
}];
self.scrollView.contentSize = CGSizeMake(CGRectGetWidth(self.bounds), CGRectGetHeight(self.scrollView.bounds));
}else{//超出屏幕 可以滑动
CGFloat currentX = 0;
for (int idx = 0; idx < self.titlesArr.count; idx++) {
UIButton *btn = self.itemBtnArr[idx];
titleFont = btn.isSelected?_titleSelectFont:_titleFont;
CGFloat itemBtnWidth = [FSSegmentTitleView getWidthWithString:self.titlesArr[idx] font:titleFont] + self.itemMargin;
CGFloat itemBtnHeight = CGRectGetHeight(self.bounds);
btn.frame = CGRectMake(currentX, 0, itemBtnWidth, itemBtnHeight);
currentX += itemBtnWidth;
}
self.scrollView.contentSize = CGSizeMake(currentX, CGRectGetHeight(self.scrollView.bounds));
}
[self moveIndicatorView:YES];
}
- (void)moveIndicatorView:(BOOL)animated
{
UIFont *titleFont = _titleFont;
UIButton *selectBtn = self.itemBtnArr[self.selectIndex];
titleFont = selectBtn.isSelected?_titleSelectFont:_titleFont;
CGFloat indicatorWidth = [FSSegmentTitleView getWidthWithString:self.titlesArr[self.selectIndex] font:titleFont];
[UIView animateWithDuration:(animated?0.05:0) animations:^{
switch (_indicatorType) {
case FSIndicatorTypeDefault:
self.indicatorView.frame = CGRectMake(selectBtn.frame.origin.x , CGRectGetHeight(self.scrollView.bounds) - 2, CGRectGetWidth(selectBtn.bounds), 2);
break;
case FSIndicatorTypeEqualTitle:
self.indicatorView.center = CGPointMake(selectBtn.center.x, CGRectGetHeight(self.scrollView.bounds) - 1);
self.indicatorView.bounds = CGRectMake(0, 0, indicatorWidth, 2);
break;
case FSIndicatorTypeCustom:
self.indicatorView.center = CGPointMake(selectBtn.center.x, CGRectGetHeight(self.scrollView.bounds) - 1);
self.indicatorView.bounds = CGRectMake(0, 0, indicatorWidth + _indicatorExtension*2, 2);
break;
case FSIndicatorTypeNone:
self.indicatorView.frame = CGRectZero;
break;
default:
break;
}
} completion:^(BOOL finished) {
[self scrollSelectBtnCenter:animated];
}];
}
- (void)scrollSelectBtnCenter:(BOOL)animated
{
UIButton *selectBtn = self.itemBtnArr[self.selectIndex];
CGRect centerRect = CGRectMake(selectBtn.center.x - CGRectGetWidth(self.scrollView.bounds)/2, 0, CGRectGetWidth(self.scrollView.bounds), CGRectGetHeight(self.scrollView.bounds));
[self.scrollView scrollRectToVisible:centerRect animated:animated];
}
#pragma mark --LazyLoad
- (UIScrollView *)scrollView {
if (!_scrollView) {
_scrollView = [[UIScrollView alloc] init];
_scrollView.showsHorizontalScrollIndicator = NO;
_scrollView.showsVerticalScrollIndicator = NO;
_scrollView.scrollsToTop = NO;
_scrollView.delegate = self;
[self addSubview:_scrollView];
}
return _scrollView;
}
- (NSMutableArray<UIButton *>*)itemBtnArr
{
if (!_itemBtnArr) {
_itemBtnArr = [[NSMutableArray alloc]init];
}
return _itemBtnArr;
}
- (UIView *)indicatorView
{
if (!_indicatorView) {
_indicatorView = [[UIView alloc]init];
[self.scrollView addSubview:_indicatorView];
}
return _indicatorView;
}
#pragma mark --Setter
- (void)setTitlesArr:(NSArray *)titlesArr
{
_titlesArr = titlesArr;
[self.itemBtnArr makeObjectsPerformSelector:@selector(removeFromSuperview)];
self.itemBtnArr = nil;
for (NSString *title in titlesArr) {
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
btn.tag = self.itemBtnArr.count + 666;
[btn setTitle:title forState:UIControlStateNormal];
[btn setTitleColor:_titleNormalColor forState:UIControlStateNormal];
[btn setTitleColor:_titleSelectColor forState:UIControlStateSelected];
btn.titleLabel.font = _titleFont;
[self.scrollView addSubview:btn];
[btn addTarget:self action:@selector(btnClick:) forControlEvents:UIControlEventTouchUpInside];
if (self.itemBtnArr.count == self.selectIndex) {
btn.selected = YES;
}
[self.itemBtnArr addObject:btn];
}
[self setNeedsLayout];
[self layoutIfNeeded];
}
- (void)setItemMargin:(CGFloat)itemMargin
{
_itemMargin = itemMargin;
[self setNeedsLayout];
[self layoutIfNeeded];
}
- (void)setSelectIndex:(NSInteger)selectIndex
{
if (_selectIndex == selectIndex||selectIndex < 0||selectIndex > self.itemBtnArr.count - 1) {
return;
}
UIButton *lastBtn = [self.scrollView viewWithTag:_selectIndex + 666];
lastBtn.selected = NO;
lastBtn.titleLabel.font = _titleFont;
_selectIndex = selectIndex;
UIButton *currentBtn = [self.scrollView viewWithTag:_selectIndex + 666];
currentBtn.selected = YES;
currentBtn.titleLabel.font = _titleSelectFont;
// [self moveIndicatorView:YES];
[self setNeedsLayout];
[self layoutIfNeeded];
}
- (void)setTitleFont:(UIFont *)titleFont
{
_titleFont = titleFont;
for (UIButton *btn in self.itemBtnArr) {
btn.titleLabel.font = titleFont;
}
[self setNeedsLayout];
[self layoutIfNeeded];
}
- (void)setTitleSelectFont:(UIFont *)titleSelectFont
{
if (_titleFont == titleSelectFont) {
_titleSelectFont = _titleFont;
return;
}
_titleSelectFont = titleSelectFont;
for (UIButton *btn in self.itemBtnArr) {
btn.titleLabel.font = btn.isSelected?titleSelectFont:_titleFont;
}
[self setNeedsLayout];
[self layoutIfNeeded];
}
- (void)setTitleNormalColor:(UIColor *)titleNormalColor
{
_titleNormalColor = titleNormalColor;
for (UIButton *btn in self.itemBtnArr) {
[btn setTitleColor:titleNormalColor forState:UIControlStateNormal];
}
}
- (void)setTitleSelectColor:(UIColor *)titleSelectColor
{
_titleSelectColor = titleSelectColor;
for (UIButton *btn in self.itemBtnArr) {
[btn setTitleColor:titleSelectColor forState:UIControlStateSelected];
}
}
- (void)setIndicatorColor:(UIColor *)indicatorColor
{
_indicatorColor = indicatorColor;
self.indicatorView.backgroundColor = indicatorColor;
}
- (void)setIndicatorExtension:(CGFloat)indicatorExtension
{
_indicatorExtension = indicatorExtension;
[self setNeedsLayout];
[self layoutIfNeeded];
}
#pragma mark --Btn
- (void)btnClick:(UIButton *)btn
{
NSInteger index = btn.tag - 666;
if (index == self.selectIndex) {
return;
}
if (self.delegate&&[self.delegate respondsToSelector:@selector(FSSegmentTitleView:startIndex:endIndex:)]) {
[self.delegate FSSegmentTitleView:self startIndex:self.selectIndex endIndex:index];
}
self.selectIndex = index;
}
#pragma mark UIScrollView
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
if (self.delegate&&[self.delegate respondsToSelector:@selector(FSSegmentTitleViewWillBeginDragging:)]) {
[self.delegate FSSegmentTitleViewWillBeginDragging:self];
}
}
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset
{
if (self.delegate&&[self.delegate respondsToSelector:@selector(FSSegmentTitleViewWillEndDragging:)]) {
[self.delegate FSSegmentTitleViewWillEndDragging:self];
}
}
#pragma mark Private
/**
计算字符串长度
@param string string
@param font font
@return 字符串长度
*/
+ (CGFloat)getWidthWithString:(NSString *)string font:(UIFont *)font {
NSDictionary *attrs = @{NSFontAttributeName : font};
return [string boundingRectWithSize:CGSizeMake(0, 0) options:NSStringDrawingUsesLineFragmentOrigin attributes:attrs context:nil].size.width;
}
/**
随机色
@return 调试用
*/
+ (UIColor*) randomColor{
NSInteger r = arc4random() % 255;
NSInteger g = arc4random() % 255;
NSInteger b = arc4random() % 255;
return [UIColor colorWithRed:r/255.0 green:g/255.0 blue:b/255.0 alpha:1];
}
@end
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2017 shunFSKi
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
# FSScrollContentView
  [](https://travis-ci.org/shunFSKi/FSScrollContentView) []() []() []()
简书:http://www.jianshu.com/p/34cecb066cc1
这是本人在整理项目时抽离了业务代码整理封装的一个通俗易懂较为实用的框架。
支持点击上方标题,切换下方内容页面,也支持滑动下方内容区域,切换上方的标题。
* 主要用来适用于多个视图左右滑动,切换顶部标签控制显示视图的需求
* 仿网易新闻,一些电商app的样式实现
* 实现简单,通俗易懂,支持一些简单的自定义
* 自动适应标签数量控制滑动或不能滑动
## 效果图

## 使用方式
**1、cocoapods**
pod search FSScrollContentView
如果找不到执行pod setup
pod 'FSScrollContentView'
**2、添加文件**
直接clone代码后将项目中的FSScrollContentViewLib文件夹导入自己项目中,导入FSScrollContentView.h头文件
## API使用说明
其实demo中有很详细的注释说明,通俗易懂
框架包含**FSPageContentView**和**FSSegmentTitleView**两个完全独立的类文件,可酌情使用
**FSPageContentView**
* 创建FSPageContentView
```
/**
对象方法创建FSPageContentView
@param frame frame
@param childVCs 子VC数组
@param parentVC 父视图VC
@param delegate delegate
@return FSPageContentView
*/
- (instancetype)initWithFrame:(CGRect)frame childVCs:(NSArray *)childVCs parentVC:(UIViewController *)parentVC delegate:(id<FSPageContentViewDelegate>)delegate;
```
* FSPageContentView属性修改
```
/**
设置contentView当前展示的页面索引,默认为0
*/
@property (nonatomic, assign) NSInteger contentViewCurrentIndex;
```
* FSPageContentView代理方法
```
/**
FSPageContentView开始滑动
@param contentView FSPageContentView
*/
- (void)FSContentViewWillBeginDragging:(FSPageContentView *)contentView;
/**
FSPageContentView滑动调用
@param contentView FSPageContentView
@param startIndex 开始滑动页面索引
@param endIndex 结束滑动页面索引
@param progress 滑动进度
*/
- (void)FSContentViewDidScroll:(FSPageContentView *)contentView startIndex:(NSInteger)startIndex endIndex:(NSInteger)endIndex progress:(CGFloat)progress;
/**
FSPageContentView结束滑动
@param contentView FSPageContentView
@param startIndex 开始滑动索引
@param endIndex 结束滑动索引
*/
- (void)FSContenViewDidEndDecelerating:(FSPageContentView *)contentView startIndex:(NSInteger)startIndex endIndex:(NSInteger)endIndex;
```
**FSSegmentTitleView**
* 创建FSSegmentTitleView
```
/**
对象方法创建FSSegmentTitleView
@param frame frame
@param titlesArr 标题数组,必须传值
@param delegate delegate
@param incatorType 指示器类型
@return FSSegmentTitleView
*/
- (instancetype)initWithFrame:(CGRect)frame titles:(NSArray *)titlesArr delegate:(id<FSSegmentTitleViewDelegate>)delegate indicatorType:(FSIndicatorType)incatorType;
```
* FSSegmentTitleView属性修改
~~/**
标题数组,必须传值
*/
@property (nonatomic, strong) NSArray *titlesArr;~~**废弃/DEPRECATED_1.0.1**
```
/**
标题文字间距,默认20
*/
@property (nonatomic, assign) CGFloat itemMargin;
/**
当前选中标题索引,默认0
*/
@property (nonatomic, assign) NSInteger selectIndex;
/**
标题字体大小,默认15
*/
@property (nonatomic, strong) UIFont *titleFont;
/**
标题正常颜色,默认black
*/
@property (nonatomic, strong) UIColor *titleNormalColor;
/**
标题选中颜色,默认red
*/
@property (nonatomic, strong) UIColor *titleSelectColor;
/**
指示器颜色,默认与titleSelectColor一样,在FSIndicatorTypeNone下无效
*/
@property (nonatomic, strong) UIColor *indicatorColor;
/**
在FSIndicatorTypeCustom时可自定义此属性,为指示器一端延伸长度,默认5
*/
@property (nonatomic, assign) CGFloat indicatorExtension;
```
* FSSegmentTitleView代理方法
```
/**
切换标题
@param titleView FSSegmentTitleView
@param startIndex 切换前标题索引
@param endIndex 切换后标题索引
*/
- (void)FSSegmentTitleView:(FSSegmentTitleView *)titleView startIndex:(NSInteger)startIndex endIndex:(NSInteger)endIndex;
```
* FSSegmentTitleView枚举类型
```
typedef enum : NSUInteger {
FSIndicatorTypeDefault,//默认与按钮长度相同
FSIndicatorTypeEqualTitle,//与文字长度相同
FSIndicatorTypeCustom,//自定义文字边缘延伸宽度
FSIndicatorTypeNone,
} FSIndicatorType;//指示器类型枚举
```
## For example
详细使用可以查看demo
```
self.titleView = [[FSSegmentTitleView alloc]initWithFrame:CGRectMake(0, 64, CGRectGetWidth(self.view.bounds), 50) delegate:self indicatorType:0];
self.titleView.titlesArr = @[@"全部",@"服饰穿搭",@"生活百货",@"美食吃货",@"美容护理",@"母婴儿童",@"数码家电",@"其他"];
[self.view addSubview:_titleView];
NSMutableArray *childVCs = [[NSMutableArray alloc]init];
for (NSString *title in self.titleView.titlesArr) {
ChildViewController *vc = [[ChildViewController alloc]init];
vc.title = title;
[childVCs addObject:vc];
}
self.pageContentView = [[FSPageContentView alloc]initWithFrame:CGRectMake(0, 114, CGRectGetWidth(self.view.bounds), CGRectGetHeight(self.view.bounds) - 90) childVCs:childVCs parentVC:self delegate:self];
[self.view addSubview:_pageContentView];
- (void)FSSegmentTitleView:(FSSegmentTitleView *)titleView startIndex:(NSInteger)startIndex endIndex:(NSInteger)endIndex
{
self.pageContentView.contentViewCurrentIndex = endIndex;
}
- (void)FSContenViewDidEndDecelerating:(FSPageContentView *)contentView startIndex:(NSInteger)startIndex endIndex:(NSInteger)endIndex
{
self.titleView.selectIndex = endIndex;
}
```
## 版本
* 2017.4.28 ——> **1.0**初始版本
* 2017.5.7 ——> **1.0.1**修改初始化方法,添加了标题选中自定义文字大小类型
## 后续
因为最近在重新整理整个项目,准备剔除之前项目的混乱代码,复杂的业务逻辑,将会不定期封装一些比较实用的小框架,目前上传的FSxxdemo都是我在重构项目过程中写的一些封装库,算是较为实用并且稳定的框架类,主要目的也是为了整理记录下来方便以后使用,这个滑动框架暂时样式较少,但是已经能够满足日常开发所用,后期我会抽时间增加更多的支持类型,比如放大选中的标题文字,增加图片类型等。每次更新都将在这里做备忘记录。———— 2017.5.4
修改初始化方法,添加了标题选中自定义文字大小类型 ———— 2017.5.7
修复iOS7下contentView无法加载的Bug,添加contentViewCanScroll属性可手动控制contentView能否滑动 ———— 2017.5.17
修复若干bug,添加cocoapods支持 ———— 2017.6.1

gitextract_1xem8x04/ ├── .gitignore ├── .travis.yml ├── FSScrollContentView.podspec ├── FSScrollContentViewDemo/ │ ├── FSScrollContentViewDemo/ │ │ ├── AppDelegate.h │ │ ├── AppDelegate.m │ │ ├── Assets.xcassets/ │ │ │ └── AppIcon.appiconset/ │ │ │ └── Contents.json │ │ ├── Base.lproj/ │ │ │ ├── LaunchScreen.storyboard │ │ │ └── Main.storyboard │ │ ├── ChildViewController.h │ │ ├── ChildViewController.m │ │ ├── Info.plist │ │ ├── TestViewController.h │ │ ├── TestViewController.m │ │ ├── ViewController.h │ │ ├── ViewController.m │ │ └── main.m │ ├── FSScrollContentViewDemo.xcodeproj/ │ │ ├── project.pbxproj │ │ ├── project.xcworkspace/ │ │ │ └── contents.xcworkspacedata │ │ └── xcshareddata/ │ │ └── xcschemes/ │ │ └── FSScrollContentViewDemo.xcscheme │ └── FSScrollContentViewLib/ │ ├── FSPageContentView.h │ ├── FSPageContentView.m │ ├── FSScrollContentView.h │ ├── FSSegmentTitleView.h │ └── FSSegmentTitleView.m ├── FSScrollContentViewLib/ │ ├── FSPageContentView.h │ ├── FSPageContentView.m │ ├── FSScrollContentView.h │ ├── FSSegmentTitleView.h │ └── FSSegmentTitleView.m ├── LICENSE └── README.md
SYMBOL INDEX (2 symbols across 2 files)
FILE: FSScrollContentViewDemo/FSScrollContentViewLib/FSSegmentTitleView.h
type FSIndicatorType (line 12) | typedef enum : NSUInteger {
FILE: FSScrollContentViewLib/FSSegmentTitleView.h
type FSIndicatorType (line 12) | typedef enum : NSUInteger {
Condensed preview — 31 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (104K chars).
[
{
"path": ".gitignore",
"chars": 1341,
"preview": "# Xcode\n#\n# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore\n\n"
},
{
"path": ".travis.yml",
"chars": 71,
"preview": "language: objective-c\nxcode_project: FSScrollContentViewDemo.xcodeproj\n"
},
{
"path": "FSScrollContentView.podspec",
"chars": 5149,
"preview": "#\n# Be sure to run `pod spec lint FSScrollContentView.podspec' to ensure this is a\n# valid spec and to remove all comm"
},
{
"path": "FSScrollContentViewDemo/FSScrollContentViewDemo/AppDelegate.h",
"chars": 285,
"preview": "//\n// AppDelegate.h\n// FSScrollContentViewDemo\n//\n// Created by huim on 2017/5/3.\n// Copyright © 2017年 fengshun. All"
},
{
"path": "FSScrollContentViewDemo/FSScrollContentViewDemo/AppDelegate.m",
"chars": 2239,
"preview": "//\n// AppDelegate.m\n// FSScrollContentViewDemo\n//\n// Created by huim on 2017/5/3.\n// Copyright © 2017年 fengshun. All"
},
{
"path": "FSScrollContentViewDemo/FSScrollContentViewDemo/Assets.xcassets/AppIcon.appiconset/Contents.json",
"chars": 585,
"preview": "{\n \"images\" : [\n {\n \"idiom\" : \"iphone\",\n \"size\" : \"29x29\",\n \"scale\" : \"2x\"\n },\n {\n \"idiom\""
},
{
"path": "FSScrollContentViewDemo/FSScrollContentViewDemo/Base.lproj/LaunchScreen.storyboard",
"chars": 1740,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard"
},
{
"path": "FSScrollContentViewDemo/FSScrollContentViewDemo/Base.lproj/Main.storyboard",
"chars": 1689,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard"
},
{
"path": "FSScrollContentViewDemo/FSScrollContentViewDemo/ChildViewController.h",
"chars": 279,
"preview": "//\n// ChildViewController.h\n// FSScrollContentViewDemo\n//\n// Created by 冯顺 on 2017/5/3.\n// Copyright © 2017年 fengshu"
},
{
"path": "FSScrollContentViewDemo/FSScrollContentViewDemo/ChildViewController.m",
"chars": 769,
"preview": "//\n// ChildViewController.m\n// FSScrollContentViewDemo\n//\n// Created by 冯顺 on 2017/5/3.\n// Copyright © 2017年 fengshu"
},
{
"path": "FSScrollContentViewDemo/FSScrollContentViewDemo/Info.plist",
"chars": 1152,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
},
{
"path": "FSScrollContentViewDemo/FSScrollContentViewDemo/TestViewController.h",
"chars": 229,
"preview": "//\n// TestViewController.h\n// FSScrollContentViewDemo\n//\n// Created by huim on 2017/5/4.\n// Copyright © 2017年 fengsh"
},
{
"path": "FSScrollContentViewDemo/FSScrollContentViewDemo/TestViewController.m",
"chars": 2370,
"preview": "//\n// TestViewController.m\n// FSScrollContentViewDemo\n//\n// Created by huim on 2017/5/4.\n// Copyright © 2017年 fengsh"
},
{
"path": "FSScrollContentViewDemo/FSScrollContentViewDemo/ViewController.h",
"chars": 223,
"preview": "//\n// ViewController.h\n// FSScrollContentViewDemo\n//\n// Created by huim on 2017/5/3.\n// Copyright © 2017年 fengshun. "
},
{
"path": "FSScrollContentViewDemo/FSScrollContentViewDemo/ViewController.m",
"chars": 3149,
"preview": "//\n// ViewController.m\n// FSScrollContentViewDemo\n//\n// Created by huim on 2017/5/3.\n// Copyright © 2017年 fengshun. "
},
{
"path": "FSScrollContentViewDemo/FSScrollContentViewDemo/main.m",
"chars": 342,
"preview": "//\n// main.m\n// FSScrollContentViewDemo\n//\n// Created by huim on 2017/5/3.\n// Copyright © 2017年 fengshun. All rights"
},
{
"path": "FSScrollContentViewDemo/FSScrollContentViewDemo.xcodeproj/project.pbxproj",
"chars": 17442,
"preview": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 46;\n\tobjects = {\n\n/* Begin PBXBuildFile section *"
},
{
"path": "FSScrollContentViewDemo/FSScrollContentViewDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata",
"chars": 168,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n version = \"1.0\">\n <FileRef\n location = \"self:FSScrollContent"
},
{
"path": "FSScrollContentViewDemo/FSScrollContentViewDemo.xcodeproj/xcshareddata/xcschemes/FSScrollContentViewDemo.xcscheme",
"chars": 3495,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n LastUpgradeVersion = \"0830\"\n version = \"1.3\">\n <BuildAction\n "
},
{
"path": "FSScrollContentViewDemo/FSScrollContentViewLib/FSPageContentView.h",
"chars": 1709,
"preview": "//\n// FSPageContentView.h\n// Huim\n//\n// Created by huim on 2017/4/28.\n// Copyright © 2017年 huim. All rights reserved"
},
{
"path": "FSScrollContentViewDemo/FSScrollContentViewLib/FSPageContentView.m",
"chars": 6651,
"preview": "//\n// FSPageContentView.m\n// Huim\n//\n// Created by huim on 2017/4/28.\n// Copyright © 2017年 huim. All rights reserved"
},
{
"path": "FSScrollContentViewDemo/FSScrollContentViewLib/FSScrollContentView.h",
"chars": 210,
"preview": "//\n// FSScrollContentView.h\n// FSScrollContentViewDemo\n//\n// Created by 冯顺 on 2017/5/3.\n// Copyright © 2017年 fengshu"
},
{
"path": "FSScrollContentViewDemo/FSScrollContentViewLib/FSSegmentTitleView.h",
"chars": 2089,
"preview": "//\n// FSSegmentTitleView.h\n// FSScrollContentViewDemo\n//\n// Created by huim on 2017/5/3.\n// Copyright © 2017年 fengsh"
},
{
"path": "FSScrollContentViewDemo/FSScrollContentViewLib/FSSegmentTitleView.m",
"chars": 10747,
"preview": "//\n// FSSegmentTitleView.m\n// FSScrollContentViewDemo\n//\n// Created by huim on 2017/5/3.\n// Copyright © 2017年 fengsh"
},
{
"path": "FSScrollContentViewLib/FSPageContentView.h",
"chars": 1709,
"preview": "//\n// FSPageContentView.h\n// Huim\n//\n// Created by huim on 2017/4/28.\n// Copyright © 2017年 huim. All rights reserved"
},
{
"path": "FSScrollContentViewLib/FSPageContentView.m",
"chars": 6651,
"preview": "//\n// FSPageContentView.m\n// Huim\n//\n// Created by huim on 2017/4/28.\n// Copyright © 2017年 huim. All rights reserved"
},
{
"path": "FSScrollContentViewLib/FSScrollContentView.h",
"chars": 210,
"preview": "//\n// FSScrollContentView.h\n// FSScrollContentViewDemo\n//\n// Created by 冯顺 on 2017/5/3.\n// Copyright © 2017年 fengshu"
},
{
"path": "FSScrollContentViewLib/FSSegmentTitleView.h",
"chars": 2089,
"preview": "//\n// FSSegmentTitleView.h\n// FSScrollContentViewDemo\n//\n// Created by huim on 2017/5/3.\n// Copyright © 2017年 fengsh"
},
{
"path": "FSScrollContentViewLib/FSSegmentTitleView.m",
"chars": 10747,
"preview": "//\n// FSSegmentTitleView.m\n// FSScrollContentViewDemo\n//\n// Created by huim on 2017/5/3.\n// Copyright © 2017年 fengsh"
},
{
"path": "LICENSE",
"chars": 1065,
"preview": "MIT License\n\nCopyright (c) 2017 shunFSKi\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\no"
},
{
"path": "README.md",
"chars": 5767,
"preview": "# FSScrollContentView\n\n . The extraction includes 31 files (90.2 KB), approximately 26.9k tokens, and a symbol index with 2 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.