├── .gitignore ├── .travis.yml ├── FSScrollContentView.podspec ├── FSScrollContentViewDemo ├── FSScrollContentViewDemo.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ └── contents.xcworkspacedata │ └── xcshareddata │ │ └── xcschemes │ │ └── FSScrollContentViewDemo.xcscheme ├── 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 └── 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 /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Build generated 6 | build/ 7 | DerivedData/ 8 | 9 | ## Various settings 10 | *.pbxuser 11 | !default.pbxuser 12 | *.mode1v3 13 | !default.mode1v3 14 | *.mode2v3 15 | !default.mode2v3 16 | *.perspectivev3 17 | !default.perspectivev3 18 | xcuserdata/ 19 | 20 | ## Other 21 | *.moved-aside 22 | *.xcuserstate 23 | 24 | ## Obj-C/Swift specific 25 | *.hmap 26 | *.ipa 27 | *.dSYM.zip 28 | *.dSYM 29 | 30 | # CocoaPods 31 | # 32 | # We recommend against adding the Pods directory to your .gitignore. However 33 | # you should judge for yourself, the pros and cons are mentioned at: 34 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 35 | # 36 | # Pods/ 37 | 38 | # Carthage 39 | # 40 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 41 | # Carthage/Checkouts 42 | 43 | Carthage/Build 44 | 45 | # fastlane 46 | # 47 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 48 | # screenshots whenever they are needed. 49 | # For more information about the recommended setup visit: 50 | # https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md 51 | 52 | fastlane/report.xml 53 | fastlane/screenshots 54 | 55 | #Code Injection 56 | # 57 | # After new code Injection tools there's a generated folder /iOSInjectionProject 58 | # https://github.com/johnno1962/injectionforxcode 59 | 60 | iOSInjectionProject/ 61 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: objective-c 2 | xcode_project: FSScrollContentViewDemo.xcodeproj 3 | -------------------------------------------------------------------------------- /FSScrollContentView.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # Be sure to run `pod spec lint FSScrollContentView.podspec' to ensure this is a 3 | # valid spec and to remove all comments including this before submitting the spec. 4 | # 5 | # To learn more about Podspec attributes see http://docs.cocoapods.org/specification.html 6 | # To see working Podspecs in the CocoaPods repo see https://github.com/CocoaPods/Specs/ 7 | # 8 | 9 | Pod::Spec.new do |s| 10 | 11 | # ――― Spec Metadata ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 12 | # 13 | # These will help people to find your library, and whilst it 14 | # can feel like a chore to fill in it's definitely to your advantage. The 15 | # summary should be tweet-length, and the description more in depth. 16 | # 17 | 18 | s.name = "FSScrollContentView" 19 | s.version = "1.0.9" 20 | s.summary = "titleView pageView linkage." 21 | 22 | # This description is used to generate tags and improve search results. 23 | # * Think: What does it do? Why did you write it? What is the focus? 24 | # * Try to keep it short, snappy and to the point. 25 | # * Write the description between the DESC delimiters below. 26 | # * Finally, don't worry about the indent, CocoaPods strips it! 27 | s.description = <<-DESC 28 | 修复解决父视图循环引用问题,这是一个顶部标签与内容页联动框架 29 | DESC 30 | 31 | s.homepage = "https://github.com/shunFSKi/FSScrollContentView" 32 | # s.screenshots = "www.example.com/screenshots_1.gif", "www.example.com/screenshots_2.gif" 33 | 34 | 35 | # ――― Spec License ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 36 | # 37 | # Licensing your code is important. See http://choosealicense.com for more info. 38 | # CocoaPods will detect a license file if there is a named LICENSE* 39 | # Popular ones are 'MIT', 'BSD' and 'Apache License, Version 2.0'. 40 | # 41 | 42 | s.license = "MIT" 43 | # s.license = { :type => "MIT", :file => "FILE_LICENSE" } 44 | 45 | 46 | # ――― Author Metadata ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 47 | # 48 | # Specify the authors of the library, with email addresses. Email addresses 49 | # of the authors are extracted from the SCM log. E.g. $ git log. CocoaPods also 50 | # accepts just a name if you'd rather not provide an email address. 51 | # 52 | # Specify a social_media_url where others can refer to, for example a twitter 53 | # profile URL. 54 | # 55 | 56 | s.author = { "fengshun" => "fengshun_ios@126.com" } 57 | # Or just: s.author = "fengshun" 58 | # s.authors = { "fengshun" => "fengshun@huim.com" } 59 | # s.social_media_url = "http://twitter.com/fengshun" 60 | 61 | # ――― Platform Specifics ――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 62 | # 63 | # If this Pod runs only on iOS or OS X, then specify the platform and 64 | # the deployment target. You can optionally include the target after the platform. 65 | # 66 | 67 | # s.platform = :ios 68 | s.platform = :ios, "7.0" 69 | 70 | # When using multiple platforms 71 | # s.ios.deployment_target = "5.0" 72 | # s.osx.deployment_target = "10.7" 73 | # s.watchos.deployment_target = "2.0" 74 | # s.tvos.deployment_target = "9.0" 75 | 76 | 77 | # ――― Source Location ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 78 | # 79 | # Specify the location from where the source should be retrieved. 80 | # Supports git, hg, bzr, svn and HTTP. 81 | # 82 | 83 | s.source = { :git => "https://github.com/shunFSKi/FSScrollContentView.git", :tag => "1.0.9" } 84 | 85 | 86 | # ――― Source Code ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 87 | # 88 | # CocoaPods is smart about how it includes source code. For source files 89 | # giving a folder will include any swift, h, m, mm, c & cpp files. 90 | # For header files it will include any header in the folder. 91 | # Not including the public_header_files will make all headers public. 92 | # 93 | 94 | s.source_files = "FSScrollContentViewLib", "FSScrollContentViewLib/**/*.{h,m}" 95 | # s.exclude_files = "Classes/Exclude" 96 | 97 | # s.public_header_files = "Classes/**/*.h" 98 | 99 | 100 | # ――― Resources ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 101 | # 102 | # A list of resources included with the Pod. These are copied into the 103 | # target bundle with a build phase script. Anything else will be cleaned. 104 | # You can preserve files from being cleaned, please don't preserve 105 | # non-essential files like tests, examples and documentation. 106 | # 107 | 108 | # s.resource = "icon.png" 109 | # s.resources = "Resources/*.png" 110 | 111 | # s.preserve_paths = "FilesToSave", "MoreFilesToSave" 112 | 113 | 114 | # ――― Project Linking ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 115 | # 116 | # Link your library with frameworks, or libraries. Libraries do not include 117 | # the lib prefix of their name. 118 | # 119 | 120 | # s.framework = "UIKit" 121 | # s.frameworks = "SomeFramework", "AnotherFramework" 122 | 123 | # s.library = "iconv" 124 | # s.libraries = "iconv", "xml2" 125 | 126 | 127 | # ――― Project Settings ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 128 | # 129 | # If your library depends on compiler flags you can set them in the xcconfig hash 130 | # where they will only apply to your library. If you depend on other Podspecs 131 | # you can include multiple dependencies to ensure it works. 132 | 133 | # s.requires_arc = true 134 | 135 | # s.xcconfig = { "HEADER_SEARCH_PATHS" => "$(SDKROOT)/usr/include/libxml2" } 136 | # s.dependency "JSONKit", "~> 1.4" 137 | 138 | end 139 | -------------------------------------------------------------------------------- /FSScrollContentViewDemo/FSScrollContentViewDemo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | A36A9A811EB9889E00A2F2C5 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = A36A9A801EB9889E00A2F2C5 /* main.m */; }; 11 | A36A9A841EB9889E00A2F2C5 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = A36A9A831EB9889E00A2F2C5 /* AppDelegate.m */; }; 12 | A36A9A871EB9889F00A2F2C5 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = A36A9A861EB9889F00A2F2C5 /* ViewController.m */; }; 13 | A36A9A8A1EB9889F00A2F2C5 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = A36A9A881EB9889F00A2F2C5 /* Main.storyboard */; }; 14 | A36A9A8C1EB9889F00A2F2C5 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A36A9A8B1EB9889F00A2F2C5 /* Assets.xcassets */; }; 15 | A36A9A8F1EB988A000A2F2C5 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = A36A9A8D1EB988A000A2F2C5 /* LaunchScreen.storyboard */; }; 16 | A39D66591EDFEDC200D3F407 /* FSPageContentView.m in Sources */ = {isa = PBXBuildFile; fileRef = A39D66551EDFEDC200D3F407 /* FSPageContentView.m */; }; 17 | A39D665A1EDFEDC200D3F407 /* FSSegmentTitleView.m in Sources */ = {isa = PBXBuildFile; fileRef = A39D66581EDFEDC200D3F407 /* FSSegmentTitleView.m */; }; 18 | A3A324621EBACDB30065A8CB /* TestViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = A3A324611EBACDB30065A8CB /* TestViewController.m */; }; 19 | F083365D1EBA31E800667BAF /* ChildViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F083365C1EBA31E800667BAF /* ChildViewController.m */; }; 20 | /* End PBXBuildFile section */ 21 | 22 | /* Begin PBXFileReference section */ 23 | A36A9A7C1EB9889E00A2F2C5 /* FSScrollContentViewDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = FSScrollContentViewDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 24 | A36A9A801EB9889E00A2F2C5 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 25 | A36A9A821EB9889E00A2F2C5 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 26 | A36A9A831EB9889E00A2F2C5 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 27 | A36A9A851EB9889E00A2F2C5 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 28 | A36A9A861EB9889F00A2F2C5 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 29 | A36A9A891EB9889F00A2F2C5 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 30 | A36A9A8B1EB9889F00A2F2C5 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 31 | A36A9A8E1EB988A000A2F2C5 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 32 | A36A9A901EB988A000A2F2C5 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 33 | A39D664E1EDFED4000D3F407 /* FSPageContentView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FSPageContentView.h; sourceTree = ""; }; 34 | A39D664F1EDFED4000D3F407 /* FSPageContentView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FSPageContentView.m; sourceTree = ""; }; 35 | A39D66501EDFED4000D3F407 /* FSScrollContentView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FSScrollContentView.h; sourceTree = ""; }; 36 | A39D66511EDFED4000D3F407 /* FSSegmentTitleView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FSSegmentTitleView.h; sourceTree = ""; }; 37 | A39D66521EDFED4100D3F407 /* FSSegmentTitleView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FSSegmentTitleView.m; sourceTree = ""; }; 38 | A39D66541EDFEDC200D3F407 /* FSPageContentView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FSPageContentView.h; sourceTree = ""; }; 39 | A39D66551EDFEDC200D3F407 /* FSPageContentView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FSPageContentView.m; sourceTree = ""; }; 40 | A39D66561EDFEDC200D3F407 /* FSScrollContentView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FSScrollContentView.h; sourceTree = ""; }; 41 | A39D66571EDFEDC200D3F407 /* FSSegmentTitleView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FSSegmentTitleView.h; sourceTree = ""; }; 42 | A39D66581EDFEDC200D3F407 /* FSSegmentTitleView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FSSegmentTitleView.m; sourceTree = ""; }; 43 | A3A324601EBACDB30065A8CB /* TestViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TestViewController.h; sourceTree = ""; }; 44 | A3A324611EBACDB30065A8CB /* TestViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TestViewController.m; sourceTree = ""; }; 45 | F083365B1EBA31E800667BAF /* ChildViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ChildViewController.h; sourceTree = ""; }; 46 | F083365C1EBA31E800667BAF /* ChildViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ChildViewController.m; sourceTree = ""; }; 47 | /* End PBXFileReference section */ 48 | 49 | /* Begin PBXFrameworksBuildPhase section */ 50 | A36A9A791EB9889E00A2F2C5 /* Frameworks */ = { 51 | isa = PBXFrameworksBuildPhase; 52 | buildActionMask = 2147483647; 53 | files = ( 54 | ); 55 | runOnlyForDeploymentPostprocessing = 0; 56 | }; 57 | /* End PBXFrameworksBuildPhase section */ 58 | 59 | /* Begin PBXGroup section */ 60 | A36A9A731EB9889E00A2F2C5 = { 61 | isa = PBXGroup; 62 | children = ( 63 | A39D66531EDFEDC200D3F407 /* FSScrollContentViewLib */, 64 | A36A9A7E1EB9889E00A2F2C5 /* FSScrollContentViewDemo */, 65 | A36A9A7D1EB9889E00A2F2C5 /* Products */, 66 | A39D664C1EDFED4000D3F407 /* Frameworks */, 67 | ); 68 | sourceTree = ""; 69 | }; 70 | A36A9A7D1EB9889E00A2F2C5 /* Products */ = { 71 | isa = PBXGroup; 72 | children = ( 73 | A36A9A7C1EB9889E00A2F2C5 /* FSScrollContentViewDemo.app */, 74 | ); 75 | name = Products; 76 | sourceTree = ""; 77 | }; 78 | A36A9A7E1EB9889E00A2F2C5 /* FSScrollContentViewDemo */ = { 79 | isa = PBXGroup; 80 | children = ( 81 | A36A9A821EB9889E00A2F2C5 /* AppDelegate.h */, 82 | A36A9A831EB9889E00A2F2C5 /* AppDelegate.m */, 83 | A36A9A851EB9889E00A2F2C5 /* ViewController.h */, 84 | A36A9A861EB9889F00A2F2C5 /* ViewController.m */, 85 | A3A324601EBACDB30065A8CB /* TestViewController.h */, 86 | A3A324611EBACDB30065A8CB /* TestViewController.m */, 87 | F083365B1EBA31E800667BAF /* ChildViewController.h */, 88 | F083365C1EBA31E800667BAF /* ChildViewController.m */, 89 | A36A9A881EB9889F00A2F2C5 /* Main.storyboard */, 90 | A36A9A8B1EB9889F00A2F2C5 /* Assets.xcassets */, 91 | A36A9A8D1EB988A000A2F2C5 /* LaunchScreen.storyboard */, 92 | A36A9A901EB988A000A2F2C5 /* Info.plist */, 93 | A36A9A7F1EB9889E00A2F2C5 /* Supporting Files */, 94 | ); 95 | path = FSScrollContentViewDemo; 96 | sourceTree = ""; 97 | }; 98 | A36A9A7F1EB9889E00A2F2C5 /* Supporting Files */ = { 99 | isa = PBXGroup; 100 | children = ( 101 | A36A9A801EB9889E00A2F2C5 /* main.m */, 102 | ); 103 | name = "Supporting Files"; 104 | sourceTree = ""; 105 | }; 106 | A39D664C1EDFED4000D3F407 /* Frameworks */ = { 107 | isa = PBXGroup; 108 | children = ( 109 | A39D664D1EDFED4000D3F407 /* FSScrollContentViewLib */, 110 | ); 111 | name = Frameworks; 112 | sourceTree = ""; 113 | }; 114 | A39D664D1EDFED4000D3F407 /* FSScrollContentViewLib */ = { 115 | isa = PBXGroup; 116 | children = ( 117 | A39D664E1EDFED4000D3F407 /* FSPageContentView.h */, 118 | A39D664F1EDFED4000D3F407 /* FSPageContentView.m */, 119 | A39D66501EDFED4000D3F407 /* FSScrollContentView.h */, 120 | A39D66511EDFED4000D3F407 /* FSSegmentTitleView.h */, 121 | A39D66521EDFED4100D3F407 /* FSSegmentTitleView.m */, 122 | ); 123 | name = FSScrollContentViewLib; 124 | path = ../FSScrollContentViewLib; 125 | sourceTree = ""; 126 | }; 127 | A39D66531EDFEDC200D3F407 /* FSScrollContentViewLib */ = { 128 | isa = PBXGroup; 129 | children = ( 130 | A39D66541EDFEDC200D3F407 /* FSPageContentView.h */, 131 | A39D66551EDFEDC200D3F407 /* FSPageContentView.m */, 132 | A39D66561EDFEDC200D3F407 /* FSScrollContentView.h */, 133 | A39D66571EDFEDC200D3F407 /* FSSegmentTitleView.h */, 134 | A39D66581EDFEDC200D3F407 /* FSSegmentTitleView.m */, 135 | ); 136 | path = FSScrollContentViewLib; 137 | sourceTree = ""; 138 | }; 139 | /* End PBXGroup section */ 140 | 141 | /* Begin PBXNativeTarget section */ 142 | A36A9A7B1EB9889E00A2F2C5 /* FSScrollContentViewDemo */ = { 143 | isa = PBXNativeTarget; 144 | buildConfigurationList = A36A9A931EB988A000A2F2C5 /* Build configuration list for PBXNativeTarget "FSScrollContentViewDemo" */; 145 | buildPhases = ( 146 | A36A9A781EB9889E00A2F2C5 /* Sources */, 147 | A36A9A791EB9889E00A2F2C5 /* Frameworks */, 148 | A36A9A7A1EB9889E00A2F2C5 /* Resources */, 149 | ); 150 | buildRules = ( 151 | ); 152 | dependencies = ( 153 | ); 154 | name = FSScrollContentViewDemo; 155 | productName = FSScrollContentViewDemo; 156 | productReference = A36A9A7C1EB9889E00A2F2C5 /* FSScrollContentViewDemo.app */; 157 | productType = "com.apple.product-type.application"; 158 | }; 159 | /* End PBXNativeTarget section */ 160 | 161 | /* Begin PBXProject section */ 162 | A36A9A741EB9889E00A2F2C5 /* Project object */ = { 163 | isa = PBXProject; 164 | attributes = { 165 | LastUpgradeCheck = 0830; 166 | ORGANIZATIONNAME = fengshun; 167 | TargetAttributes = { 168 | A36A9A7B1EB9889E00A2F2C5 = { 169 | CreatedOnToolsVersion = 8.3.1; 170 | DevelopmentTeam = P5NAKU59Y6; 171 | ProvisioningStyle = Automatic; 172 | }; 173 | }; 174 | }; 175 | buildConfigurationList = A36A9A771EB9889E00A2F2C5 /* Build configuration list for PBXProject "FSScrollContentViewDemo" */; 176 | compatibilityVersion = "Xcode 3.2"; 177 | developmentRegion = English; 178 | hasScannedForEncodings = 0; 179 | knownRegions = ( 180 | en, 181 | Base, 182 | ); 183 | mainGroup = A36A9A731EB9889E00A2F2C5; 184 | productRefGroup = A36A9A7D1EB9889E00A2F2C5 /* Products */; 185 | projectDirPath = ""; 186 | projectRoot = ""; 187 | targets = ( 188 | A36A9A7B1EB9889E00A2F2C5 /* FSScrollContentViewDemo */, 189 | ); 190 | }; 191 | /* End PBXProject section */ 192 | 193 | /* Begin PBXResourcesBuildPhase section */ 194 | A36A9A7A1EB9889E00A2F2C5 /* Resources */ = { 195 | isa = PBXResourcesBuildPhase; 196 | buildActionMask = 2147483647; 197 | files = ( 198 | A36A9A8F1EB988A000A2F2C5 /* LaunchScreen.storyboard in Resources */, 199 | A36A9A8C1EB9889F00A2F2C5 /* Assets.xcassets in Resources */, 200 | A36A9A8A1EB9889F00A2F2C5 /* Main.storyboard in Resources */, 201 | ); 202 | runOnlyForDeploymentPostprocessing = 0; 203 | }; 204 | /* End PBXResourcesBuildPhase section */ 205 | 206 | /* Begin PBXSourcesBuildPhase section */ 207 | A36A9A781EB9889E00A2F2C5 /* Sources */ = { 208 | isa = PBXSourcesBuildPhase; 209 | buildActionMask = 2147483647; 210 | files = ( 211 | A36A9A871EB9889F00A2F2C5 /* ViewController.m in Sources */, 212 | A36A9A841EB9889E00A2F2C5 /* AppDelegate.m in Sources */, 213 | A39D66591EDFEDC200D3F407 /* FSPageContentView.m in Sources */, 214 | A39D665A1EDFEDC200D3F407 /* FSSegmentTitleView.m in Sources */, 215 | A3A324621EBACDB30065A8CB /* TestViewController.m in Sources */, 216 | A36A9A811EB9889E00A2F2C5 /* main.m in Sources */, 217 | F083365D1EBA31E800667BAF /* ChildViewController.m in Sources */, 218 | ); 219 | runOnlyForDeploymentPostprocessing = 0; 220 | }; 221 | /* End PBXSourcesBuildPhase section */ 222 | 223 | /* Begin PBXVariantGroup section */ 224 | A36A9A881EB9889F00A2F2C5 /* Main.storyboard */ = { 225 | isa = PBXVariantGroup; 226 | children = ( 227 | A36A9A891EB9889F00A2F2C5 /* Base */, 228 | ); 229 | name = Main.storyboard; 230 | sourceTree = ""; 231 | }; 232 | A36A9A8D1EB988A000A2F2C5 /* LaunchScreen.storyboard */ = { 233 | isa = PBXVariantGroup; 234 | children = ( 235 | A36A9A8E1EB988A000A2F2C5 /* Base */, 236 | ); 237 | name = LaunchScreen.storyboard; 238 | sourceTree = ""; 239 | }; 240 | /* End PBXVariantGroup section */ 241 | 242 | /* Begin XCBuildConfiguration section */ 243 | A36A9A911EB988A000A2F2C5 /* Debug */ = { 244 | isa = XCBuildConfiguration; 245 | buildSettings = { 246 | ALWAYS_SEARCH_USER_PATHS = NO; 247 | CLANG_ANALYZER_NONNULL = YES; 248 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 249 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 250 | CLANG_CXX_LIBRARY = "libc++"; 251 | CLANG_ENABLE_MODULES = YES; 252 | CLANG_ENABLE_OBJC_ARC = YES; 253 | CLANG_WARN_BOOL_CONVERSION = YES; 254 | CLANG_WARN_CONSTANT_CONVERSION = YES; 255 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 256 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 257 | CLANG_WARN_EMPTY_BODY = YES; 258 | CLANG_WARN_ENUM_CONVERSION = YES; 259 | CLANG_WARN_INFINITE_RECURSION = YES; 260 | CLANG_WARN_INT_CONVERSION = YES; 261 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 262 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 263 | CLANG_WARN_UNREACHABLE_CODE = YES; 264 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 265 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 266 | COPY_PHASE_STRIP = NO; 267 | DEBUG_INFORMATION_FORMAT = dwarf; 268 | ENABLE_STRICT_OBJC_MSGSEND = YES; 269 | ENABLE_TESTABILITY = YES; 270 | GCC_C_LANGUAGE_STANDARD = gnu99; 271 | GCC_DYNAMIC_NO_PIC = NO; 272 | GCC_NO_COMMON_BLOCKS = YES; 273 | GCC_OPTIMIZATION_LEVEL = 0; 274 | GCC_PREPROCESSOR_DEFINITIONS = ( 275 | "DEBUG=1", 276 | "$(inherited)", 277 | ); 278 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 279 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 280 | GCC_WARN_UNDECLARED_SELECTOR = YES; 281 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 282 | GCC_WARN_UNUSED_FUNCTION = YES; 283 | GCC_WARN_UNUSED_VARIABLE = YES; 284 | IPHONEOS_DEPLOYMENT_TARGET = 10.3; 285 | MTL_ENABLE_DEBUG_INFO = YES; 286 | ONLY_ACTIVE_ARCH = YES; 287 | SDKROOT = iphoneos; 288 | }; 289 | name = Debug; 290 | }; 291 | A36A9A921EB988A000A2F2C5 /* Release */ = { 292 | isa = XCBuildConfiguration; 293 | buildSettings = { 294 | ALWAYS_SEARCH_USER_PATHS = NO; 295 | CLANG_ANALYZER_NONNULL = YES; 296 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 297 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 298 | CLANG_CXX_LIBRARY = "libc++"; 299 | CLANG_ENABLE_MODULES = YES; 300 | CLANG_ENABLE_OBJC_ARC = YES; 301 | CLANG_WARN_BOOL_CONVERSION = YES; 302 | CLANG_WARN_CONSTANT_CONVERSION = YES; 303 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 304 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 305 | CLANG_WARN_EMPTY_BODY = YES; 306 | CLANG_WARN_ENUM_CONVERSION = YES; 307 | CLANG_WARN_INFINITE_RECURSION = YES; 308 | CLANG_WARN_INT_CONVERSION = YES; 309 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 310 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 311 | CLANG_WARN_UNREACHABLE_CODE = YES; 312 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 313 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 314 | COPY_PHASE_STRIP = NO; 315 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 316 | ENABLE_NS_ASSERTIONS = NO; 317 | ENABLE_STRICT_OBJC_MSGSEND = YES; 318 | GCC_C_LANGUAGE_STANDARD = gnu99; 319 | GCC_NO_COMMON_BLOCKS = YES; 320 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 321 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 322 | GCC_WARN_UNDECLARED_SELECTOR = YES; 323 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 324 | GCC_WARN_UNUSED_FUNCTION = YES; 325 | GCC_WARN_UNUSED_VARIABLE = YES; 326 | IPHONEOS_DEPLOYMENT_TARGET = 10.3; 327 | MTL_ENABLE_DEBUG_INFO = NO; 328 | SDKROOT = iphoneos; 329 | VALIDATE_PRODUCT = YES; 330 | }; 331 | name = Release; 332 | }; 333 | A36A9A941EB988A000A2F2C5 /* Debug */ = { 334 | isa = XCBuildConfiguration; 335 | buildSettings = { 336 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 337 | DEVELOPMENT_TEAM = P5NAKU59Y6; 338 | INFOPLIST_FILE = FSScrollContentViewDemo/Info.plist; 339 | IPHONEOS_DEPLOYMENT_TARGET = 7.0; 340 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 341 | PRODUCT_BUNDLE_IDENTIFIER = com.huim.FSScrollContentViewDemo; 342 | PRODUCT_NAME = "$(TARGET_NAME)"; 343 | }; 344 | name = Debug; 345 | }; 346 | A36A9A951EB988A000A2F2C5 /* Release */ = { 347 | isa = XCBuildConfiguration; 348 | buildSettings = { 349 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 350 | DEVELOPMENT_TEAM = P5NAKU59Y6; 351 | INFOPLIST_FILE = FSScrollContentViewDemo/Info.plist; 352 | IPHONEOS_DEPLOYMENT_TARGET = 7.0; 353 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 354 | PRODUCT_BUNDLE_IDENTIFIER = com.huim.FSScrollContentViewDemo; 355 | PRODUCT_NAME = "$(TARGET_NAME)"; 356 | }; 357 | name = Release; 358 | }; 359 | /* End XCBuildConfiguration section */ 360 | 361 | /* Begin XCConfigurationList section */ 362 | A36A9A771EB9889E00A2F2C5 /* Build configuration list for PBXProject "FSScrollContentViewDemo" */ = { 363 | isa = XCConfigurationList; 364 | buildConfigurations = ( 365 | A36A9A911EB988A000A2F2C5 /* Debug */, 366 | A36A9A921EB988A000A2F2C5 /* Release */, 367 | ); 368 | defaultConfigurationIsVisible = 0; 369 | defaultConfigurationName = Release; 370 | }; 371 | A36A9A931EB988A000A2F2C5 /* Build configuration list for PBXNativeTarget "FSScrollContentViewDemo" */ = { 372 | isa = XCConfigurationList; 373 | buildConfigurations = ( 374 | A36A9A941EB988A000A2F2C5 /* Debug */, 375 | A36A9A951EB988A000A2F2C5 /* Release */, 376 | ); 377 | defaultConfigurationIsVisible = 0; 378 | defaultConfigurationName = Release; 379 | }; 380 | /* End XCConfigurationList section */ 381 | }; 382 | rootObject = A36A9A741EB9889E00A2F2C5 /* Project object */; 383 | } 384 | -------------------------------------------------------------------------------- /FSScrollContentViewDemo/FSScrollContentViewDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /FSScrollContentViewDemo/FSScrollContentViewDemo.xcodeproj/xcshareddata/xcschemes/FSScrollContentViewDemo.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /FSScrollContentViewDemo/FSScrollContentViewDemo/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // FSScrollContentViewDemo 4 | // 5 | // Created by huim on 2017/5/3. 6 | // Copyright © 2017年 fengshun. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /FSScrollContentViewDemo/FSScrollContentViewDemo/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // FSScrollContentViewDemo 4 | // 5 | // Created by huim on 2017/5/3. 6 | // Copyright © 2017年 fengshun. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | #import "ViewController.h" 11 | 12 | @interface AppDelegate () 13 | 14 | @end 15 | 16 | @implementation AppDelegate 17 | 18 | 19 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 20 | // Override point for customization after application launch. 21 | UINavigationController *nav = [[UINavigationController alloc]initWithRootViewController:[[ViewController alloc]init]]; 22 | self.window.rootViewController = nav; 23 | return YES; 24 | } 25 | 26 | 27 | - (void)applicationWillResignActive:(UIApplication *)application { 28 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 29 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 30 | } 31 | 32 | 33 | - (void)applicationDidEnterBackground:(UIApplication *)application { 34 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 35 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 36 | } 37 | 38 | 39 | - (void)applicationWillEnterForeground:(UIApplication *)application { 40 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 41 | } 42 | 43 | 44 | - (void)applicationDidBecomeActive:(UIApplication *)application { 45 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 46 | } 47 | 48 | 49 | - (void)applicationWillTerminate:(UIApplication *)application { 50 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 51 | } 52 | 53 | 54 | @end 55 | -------------------------------------------------------------------------------- /FSScrollContentViewDemo/FSScrollContentViewDemo/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /FSScrollContentViewDemo/FSScrollContentViewDemo/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /FSScrollContentViewDemo/FSScrollContentViewDemo/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /FSScrollContentViewDemo/FSScrollContentViewDemo/ChildViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ChildViewController.h 3 | // FSScrollContentViewDemo 4 | // 5 | // Created by 冯顺 on 2017/5/3. 6 | // Copyright © 2017年 fengshun. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ChildViewController : UIViewController 12 | 13 | @property (nonatomic, strong) NSString *titleStr; 14 | @end 15 | -------------------------------------------------------------------------------- /FSScrollContentViewDemo/FSScrollContentViewDemo/ChildViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ChildViewController.m 3 | // FSScrollContentViewDemo 4 | // 5 | // Created by 冯顺 on 2017/5/3. 6 | // Copyright © 2017年 fengshun. All rights reserved. 7 | // 8 | 9 | #import "ChildViewController.h" 10 | 11 | @interface ChildViewController () 12 | 13 | @end 14 | 15 | @implementation ChildViewController 16 | 17 | - (void)viewWillAppear:(BOOL)animated 18 | { 19 | [super viewWillAppear:animated]; 20 | NSLog(@"---%@",self.title); 21 | } 22 | 23 | - (void)viewDidLoad { 24 | [super viewDidLoad]; 25 | // Do any additional setup after loading the view. 26 | self.view.backgroundColor = [ChildViewController randomColor]; 27 | } 28 | 29 | + (UIColor*) randomColor{ 30 | NSInteger r = arc4random() % 255; 31 | NSInteger g = arc4random() % 255; 32 | NSInteger b = arc4random() % 255; 33 | return [UIColor colorWithRed:r/255.0 green:g/255.0 blue:b/255.0 alpha:1]; 34 | } 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /FSScrollContentViewDemo/FSScrollContentViewDemo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /FSScrollContentViewDemo/FSScrollContentViewDemo/TestViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // TestViewController.h 3 | // FSScrollContentViewDemo 4 | // 5 | // Created by huim on 2017/5/4. 6 | // Copyright © 2017年 fengshun. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface TestViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /FSScrollContentViewDemo/FSScrollContentViewDemo/TestViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // TestViewController.m 3 | // FSScrollContentViewDemo 4 | // 5 | // Created by huim on 2017/5/4. 6 | // Copyright © 2017年 fengshun. All rights reserved. 7 | // 8 | 9 | #import "TestViewController.h" 10 | #import "FSScrollContentView.h" 11 | #import "ChildViewController.h" 12 | 13 | @interface TestViewController () 14 | @property (nonatomic, strong) FSPageContentView *pageContentView; 15 | @property (nonatomic, strong) FSSegmentTitleView *titleView; 16 | @end 17 | 18 | @implementation TestViewController 19 | 20 | - (void)viewDidLoad { 21 | [super viewDidLoad]; 22 | // Do any additional setup after loading the view. 23 | self.automaticallyAdjustsScrollViewInsets = NO; 24 | self.view.backgroundColor = [UIColor whiteColor]; 25 | self.title = @"pageContentView"; 26 | self.titleView = [[FSSegmentTitleView alloc]initWithFrame:CGRectMake(0, 64, CGRectGetWidth(self.view.bounds), 50) titles:@[@"全部",@"服饰穿搭",@"生活百货",@"美食吃货",@"美容护理",@"母婴儿童",@"数码家电",@"其他"] delegate:self indicatorType:FSIndicatorTypeEqualTitle]; 27 | self.titleView.titleSelectFont = [UIFont systemFontOfSize:10]; 28 | self.titleView.selectIndex = 2; 29 | [self.view addSubview:_titleView]; 30 | 31 | NSMutableArray *childVCs = [[NSMutableArray alloc]init]; 32 | for (NSString *title in @[@"全部",@"服饰穿搭",@"生活百货",@"美食吃货",@"美容护理",@"母婴儿童",@"数码家电",@"其他"]) { 33 | ChildViewController *vc = [[ChildViewController alloc]init]; 34 | vc.title = title; 35 | [childVCs addObject:vc]; 36 | } 37 | self.pageContentView = [[FSPageContentView alloc]initWithFrame:CGRectMake(0, 114, CGRectGetWidth(self.view.bounds), CGRectGetHeight(self.view.bounds) - 90) childVCs:childVCs parentVC:self delegate:self]; 38 | self.pageContentView.contentViewCurrentIndex = 2; 39 | // self.pageContentView.contentViewCanScroll = NO;//设置滑动属性 40 | [self.view addSubview:_pageContentView]; 41 | } 42 | 43 | #pragma mark -- 44 | - (void)FSSegmentTitleView:(FSSegmentTitleView *)titleView startIndex:(NSInteger)startIndex endIndex:(NSInteger)endIndex 45 | { 46 | self.pageContentView.contentViewCurrentIndex = endIndex; 47 | self.title = @[@"全部",@"服饰穿搭",@"生活百货",@"美食吃货",@"美容护理",@"母婴儿童",@"数码家电",@"其他"][endIndex]; 48 | } 49 | 50 | - (void)FSContenViewDidEndDecelerating:(FSPageContentView *)contentView startIndex:(NSInteger)startIndex endIndex:(NSInteger)endIndex 51 | { 52 | self.titleView.selectIndex = endIndex; 53 | self.title = @[@"全部",@"服饰穿搭",@"生活百货",@"美食吃货",@"美容护理",@"母婴儿童",@"数码家电",@"其他"][endIndex]; 54 | } 55 | 56 | @end 57 | -------------------------------------------------------------------------------- /FSScrollContentViewDemo/FSScrollContentViewDemo/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // FSScrollContentViewDemo 4 | // 5 | // Created by huim on 2017/5/3. 6 | // Copyright © 2017年 fengshun. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /FSScrollContentViewDemo/FSScrollContentViewDemo/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // FSScrollContentViewDemo 4 | // 5 | // Created by huim on 2017/5/3. 6 | // Copyright © 2017年 fengshun. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "FSScrollContentView.h" 11 | #import "TestViewController.h" 12 | 13 | @interface ViewController () 14 | @property (nonatomic, strong) FSPageContentView *pageContentView; 15 | @property (nonatomic, strong) FSSegmentTitleView *titleView; 16 | @end 17 | 18 | @implementation ViewController 19 | 20 | - (void)viewDidLoad { 21 | [super viewDidLoad]; 22 | // Do any additional setup after loading the view, typically from a nib. 23 | self.automaticallyAdjustsScrollViewInsets = NO; 24 | self.view.backgroundColor = [UIColor whiteColor]; 25 | //demo1 26 | self.titleView = [[FSSegmentTitleView alloc]initWithFrame:CGRectMake(0, 64, CGRectGetWidth(self.view.bounds), 50) titles:@[@"全部",@"服饰穿搭",@"生活百货",@"美食吃货",@"美容护理",@"母婴儿童",@"数码家电",@"其他"] delegate:self indicatorType:0]; 27 | self.titleView.indicatorColor = [UIColor blueColor]; 28 | [self.view addSubview:_titleView]; 29 | self.titleView.backgroundColor = [UIColor lightGrayColor]; 30 | //demo2 31 | FSSegmentTitleView *titleView2 = [[FSSegmentTitleView alloc]initWithFrame:CGRectMake(0, 124, CGRectGetWidth(self.view.bounds), 50) titles:@[@"全部",@"服饰穿搭",@"生活百货",@"美食吃货",@"美容护理",@"母婴儿童",@"数码家电",@"其他"] delegate:nil indicatorType:0]; 32 | [self.view addSubview:titleView2]; 33 | titleView2.backgroundColor = [UIColor lightGrayColor]; 34 | //demo3 35 | FSSegmentTitleView *titleView3 = [[FSSegmentTitleView alloc]initWithFrame:CGRectMake(0, 194, CGRectGetWidth(self.view.bounds), 50) titles:@[@"全部",@"服饰穿搭",@"生活百货",@"美食吃货",@"美容护理",@"母婴儿童",@"数码家电",@"其他"] delegate:nil indicatorType:2]; 36 | titleView3.indicatorExtension = 6; 37 | [self.view addSubview:titleView3]; 38 | titleView3.backgroundColor = [UIColor lightGrayColor]; 39 | //demo4 40 | FSSegmentTitleView *titleView4 = [[FSSegmentTitleView alloc]initWithFrame:CGRectMake(0, 264, CGRectGetWidth(self.view.bounds), 50) titles:@[@"全部",@"服饰穿搭",@"生活百货",@"美食吃货",@"美容护理",@"母婴儿童",@"数码家电",@"其他"] delegate:nil indicatorType:3]; 41 | [self.view addSubview:titleView4]; 42 | titleView4.backgroundColor = [UIColor lightGrayColor]; 43 | 44 | //demo5 45 | FSSegmentTitleView *titleView5 = [[FSSegmentTitleView alloc]initWithFrame:CGRectMake(0, 334, CGRectGetWidth(self.view.bounds), 50) titles:@[@"全部",@"服饰穿搭",@"生活百货",@"美食吃货",@"美容护理",@"母婴儿童",@"数码家电",@"其他"] delegate:nil indicatorType:3]; 46 | titleView5.titleSelectFont = [UIFont systemFontOfSize:20]; 47 | [self.view addSubview:titleView5]; 48 | titleView5.backgroundColor = [UIColor lightGrayColor]; 49 | 50 | UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom]; 51 | btn.backgroundColor = [UIColor blackColor]; 52 | [btn setTitle:@"pageContentView" forState:UIControlStateNormal]; 53 | btn.frame = CGRectMake(50, 400, 50, 30); 54 | [btn sizeToFit]; 55 | [btn addTarget:self action:@selector(click) forControlEvents:UIControlEventTouchUpInside]; 56 | [self.view addSubview:btn]; 57 | 58 | 59 | } 60 | 61 | - (void)click 62 | { 63 | TestViewController *vc = [[TestViewController alloc]init]; 64 | [self.navigationController pushViewController:vc animated:YES]; 65 | } 66 | 67 | 68 | 69 | 70 | 71 | @end 72 | -------------------------------------------------------------------------------- /FSScrollContentViewDemo/FSScrollContentViewDemo/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // FSScrollContentViewDemo 4 | // 5 | // Created by huim on 2017/5/3. 6 | // Copyright © 2017年 fengshun. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /FSScrollContentViewDemo/FSScrollContentViewLib/FSPageContentView.h: -------------------------------------------------------------------------------- 1 | // 2 | // FSPageContentView.h 3 | // Huim 4 | // 5 | // Created by huim on 2017/4/28. 6 | // Copyright © 2017年 huim. All rights reserved. 7 | // 8 | 9 | #import 10 | @class FSPageContentView; 11 | 12 | @protocol FSPageContentViewDelegate 13 | 14 | @optional 15 | 16 | /** 17 | FSPageContentView开始滑动 18 | 19 | @param contentView FSPageContentView 20 | */ 21 | - (void)FSContentViewWillBeginDragging:(FSPageContentView *)contentView; 22 | 23 | /** 24 | FSPageContentView滑动调用 25 | 26 | @param contentView FSPageContentView 27 | @param startIndex 开始滑动页面索引 28 | @param endIndex 结束滑动页面索引 29 | @param progress 滑动进度 30 | */ 31 | - (void)FSContentViewDidScroll:(FSPageContentView *)contentView startIndex:(NSInteger)startIndex endIndex:(NSInteger)endIndex progress:(CGFloat)progress; 32 | 33 | /** 34 | FSPageContentView结束滑动 35 | 36 | @param contentView FSPageContentView 37 | @param startIndex 开始滑动索引 38 | @param endIndex 结束滑动索引 39 | */ 40 | - (void)FSContenViewDidEndDecelerating:(FSPageContentView *)contentView startIndex:(NSInteger)startIndex endIndex:(NSInteger)endIndex; 41 | 42 | /** 43 | scrollViewDidEndDragging 44 | 45 | @param contentView FSPageContentView 46 | */ 47 | - (void)FSContenViewDidEndDragging:(FSPageContentView *)contentView; 48 | 49 | @end 50 | 51 | @interface FSPageContentView : UIView 52 | 53 | /** 54 | 对象方法创建FSPageContentView 55 | 56 | @param frame frame 57 | @param childVCs 子VC数组 58 | @param parentVC 父视图VC 59 | @param delegate delegate 60 | @return FSPageContentView 61 | */ 62 | - (instancetype)initWithFrame:(CGRect)frame childVCs:(NSArray *)childVCs parentVC:(UIViewController *)parentVC delegate:(id)delegate; 63 | 64 | @property (nonatomic, weak) iddelegate; 65 | 66 | /** 67 | 设置contentView当前展示的页面索引,默认为0 68 | */ 69 | @property (nonatomic, assign) NSInteger contentViewCurrentIndex; 70 | 71 | /** 72 | 设置contentView能否左右滑动,默认YES 73 | */ 74 | @property (nonatomic, assign) BOOL contentViewCanScroll; 75 | 76 | @end 77 | -------------------------------------------------------------------------------- /FSScrollContentViewDemo/FSScrollContentViewLib/FSPageContentView.m: -------------------------------------------------------------------------------- 1 | // 2 | // FSPageContentView.m 3 | // Huim 4 | // 5 | // Created by huim on 2017/4/28. 6 | // Copyright © 2017年 huim. All rights reserved. 7 | // 8 | 9 | #import "FSPageContentView.h" 10 | 11 | #define IOS_VERSION ([[[UIDevice currentDevice] systemVersion] floatValue]) 12 | static NSString *collectionCellIdentifier = @"collectionCellIdentifier"; 13 | 14 | @interface FSPageContentView () 15 | 16 | @property (nonatomic, weak) UIViewController *parentVC;//父视图 17 | @property (nonatomic, strong) NSArray *childsVCs;//子视图数组 18 | @property (nonatomic, weak) UICollectionView *collectionView; 19 | @property (nonatomic, assign) CGFloat startOffsetX; 20 | @property (nonatomic, assign) BOOL isSelectBtn;//是否是滑动 21 | 22 | @end 23 | 24 | @implementation FSPageContentView 25 | 26 | - (instancetype)initWithFrame:(CGRect)frame childVCs:(NSArray *)childVCs parentVC:(UIViewController *)parentVC delegate:(id)delegate 27 | { 28 | self = [super initWithFrame:frame]; 29 | if (self) { 30 | self.parentVC = parentVC; 31 | self.childsVCs = childVCs; 32 | self.delegate = delegate; 33 | 34 | [self setupSubViews]; 35 | } 36 | return self; 37 | } 38 | 39 | - (void)layoutSubviews 40 | { 41 | [super layoutSubviews]; 42 | } 43 | 44 | #pragma mark --LazyLoad 45 | 46 | - (UICollectionView *)collectionView 47 | { 48 | if (!_collectionView) { 49 | UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc]init]; 50 | flowLayout.itemSize = self.bounds.size; 51 | flowLayout.minimumLineSpacing = 0; 52 | flowLayout.minimumInteritemSpacing = 0; 53 | flowLayout.scrollDirection = UICollectionViewScrollDirectionHorizontal; 54 | 55 | UICollectionView * collectionView = [[UICollectionView alloc]initWithFrame:self.bounds collectionViewLayout:flowLayout]; 56 | collectionView.showsHorizontalScrollIndicator = NO; 57 | collectionView.pagingEnabled = YES; 58 | collectionView.bounces = NO; 59 | collectionView.delegate = self; 60 | collectionView.dataSource = self; 61 | [collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:collectionCellIdentifier]; 62 | [self addSubview:collectionView]; 63 | self.collectionView = collectionView; 64 | } 65 | return _collectionView; 66 | } 67 | 68 | #pragma mark --setup 69 | - (void)setupSubViews 70 | { 71 | _startOffsetX = 0; 72 | _isSelectBtn = NO; 73 | _contentViewCanScroll = YES; 74 | 75 | for (UIViewController *childVC in self.childsVCs) { 76 | [self.parentVC addChildViewController:childVC]; 77 | } 78 | // [self addSubview:self.collectionView]; 79 | [self.collectionView reloadData]; 80 | } 81 | 82 | #pragma mark UICollectionView 83 | 84 | - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section 85 | { 86 | return self.childsVCs.count; 87 | } 88 | 89 | - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath 90 | { 91 | UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:collectionCellIdentifier forIndexPath:indexPath]; 92 | if (IOS_VERSION < 8.0) { 93 | [cell.contentView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)]; 94 | UIViewController *childVC = self.childsVCs[indexPath.item]; 95 | childVC.view.frame = cell.contentView.bounds; 96 | [cell.contentView addSubview:childVC.view]; 97 | } 98 | return cell; 99 | } 100 | 101 | #ifdef __IPHONE_8_0 102 | - (void)collectionView:(UICollectionView *)collectionView willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath{ 103 | [cell.contentView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)]; 104 | UIViewController *childVc = self.childsVCs[indexPath.row]; 105 | childVc.view.frame = cell.contentView.bounds; 106 | [cell.contentView addSubview:childVc.view]; 107 | } 108 | #endif 109 | 110 | #pragma mark UIScrollView 111 | 112 | - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView 113 | { 114 | _isSelectBtn = NO; 115 | _startOffsetX = scrollView.contentOffset.x; 116 | 117 | if (self.delegate && [self.delegate respondsToSelector:@selector(FSContentViewWillBeginDragging:)]) { 118 | [self.delegate FSContentViewWillBeginDragging:self]; 119 | } 120 | } 121 | 122 | - (void)scrollViewDidScroll:(UIScrollView *)scrollView 123 | { 124 | if (_isSelectBtn) { 125 | return; 126 | } 127 | CGFloat scrollView_W = scrollView.bounds.size.width; 128 | CGFloat currentOffsetX = scrollView.contentOffset.x; 129 | NSInteger startIndex = floor(_startOffsetX/scrollView_W); 130 | NSInteger endIndex; 131 | CGFloat progress; 132 | if (currentOffsetX > _startOffsetX) {//左滑left 133 | progress = (currentOffsetX - _startOffsetX)/scrollView_W; 134 | endIndex = startIndex + 1; 135 | if (endIndex > self.childsVCs.count - 1) { 136 | endIndex = self.childsVCs.count - 1; 137 | } 138 | }else if (currentOffsetX == _startOffsetX){//没滑过去 139 | progress = 0; 140 | endIndex = startIndex; 141 | }else{//右滑right 142 | progress = (_startOffsetX - currentOffsetX)/scrollView_W; 143 | endIndex = startIndex - 1; 144 | endIndex = endIndex < 0?0:endIndex; 145 | } 146 | 147 | if (self.delegate && [self.delegate respondsToSelector:@selector(FSContentViewDidScroll:startIndex:endIndex:progress:)]) { 148 | [self.delegate FSContentViewDidScroll:self startIndex:startIndex endIndex:endIndex progress:progress]; 149 | } 150 | } 151 | 152 | - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView 153 | { 154 | CGFloat scrollView_W = scrollView.bounds.size.width; 155 | CGFloat currentOffsetX = scrollView.contentOffset.x; 156 | NSInteger startIndex = floor(_startOffsetX/scrollView_W); 157 | NSInteger endIndex = floor(currentOffsetX/scrollView_W); 158 | 159 | if (self.delegate && [self.delegate respondsToSelector:@selector(FSContenViewDidEndDecelerating:startIndex:endIndex:)]) { 160 | [self.delegate FSContenViewDidEndDecelerating:self startIndex:startIndex endIndex:endIndex]; 161 | } 162 | } 163 | 164 | - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate 165 | { 166 | if (!decelerate) { 167 | if (self.delegate && [self.delegate respondsToSelector:@selector(FSContenViewDidEndDragging:)]) { 168 | [self.delegate FSContenViewDidEndDragging:self]; 169 | } 170 | } 171 | } 172 | 173 | #pragma mark setter 174 | 175 | - (void)setContentViewCurrentIndex:(NSInteger)contentViewCurrentIndex 176 | { 177 | if (contentViewCurrentIndex < 0||contentViewCurrentIndex > self.childsVCs.count-1) { 178 | return; 179 | } 180 | _isSelectBtn = YES; 181 | _contentViewCurrentIndex = contentViewCurrentIndex; 182 | [self.collectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForRow:contentViewCurrentIndex inSection:0] atScrollPosition:UICollectionViewScrollPositionNone animated:NO]; 183 | } 184 | 185 | - (void)setContentViewCanScroll:(BOOL)contentViewCanScroll 186 | { 187 | _contentViewCanScroll = contentViewCanScroll; 188 | _collectionView.scrollEnabled = _contentViewCanScroll; 189 | } 190 | 191 | @end 192 | -------------------------------------------------------------------------------- /FSScrollContentViewDemo/FSScrollContentViewLib/FSScrollContentView.h: -------------------------------------------------------------------------------- 1 | // 2 | // FSScrollContentView.h 3 | // FSScrollContentViewDemo 4 | // 5 | // Created by 冯顺 on 2017/5/3. 6 | // Copyright © 2017年 fengshun. All rights reserved. 7 | // 8 | 9 | 10 | #import "FSPageContentView.h" 11 | #import "FSSegmentTitleView.h" 12 | -------------------------------------------------------------------------------- /FSScrollContentViewDemo/FSScrollContentViewLib/FSSegmentTitleView.h: -------------------------------------------------------------------------------- 1 | // 2 | // FSSegmentTitleView.h 3 | // FSScrollContentViewDemo 4 | // 5 | // Created by huim on 2017/5/3. 6 | // Copyright © 2017年 fengshun. All rights reserved. 7 | // 8 | 9 | #import 10 | @class FSSegmentTitleView; 11 | 12 | typedef enum : NSUInteger { 13 | FSIndicatorTypeDefault,//默认与按钮长度相同 14 | FSIndicatorTypeEqualTitle,//与文字长度相同 15 | FSIndicatorTypeCustom,//自定义文字边缘延伸宽度 16 | FSIndicatorTypeNone, 17 | } FSIndicatorType;//指示器类型枚举 18 | 19 | @protocol FSSegmentTitleViewDelegate 20 | 21 | @optional 22 | 23 | /** 24 | 切换标题 25 | 26 | @param titleView FSSegmentTitleView 27 | @param startIndex 切换前标题索引 28 | @param endIndex 切换后标题索引 29 | */ 30 | - (void)FSSegmentTitleView:(FSSegmentTitleView *)titleView startIndex:(NSInteger)startIndex endIndex:(NSInteger)endIndex; 31 | 32 | /** 33 | 将要开始滑动 34 | 35 | @param titleView FSSegmentTitleView 36 | */ 37 | - (void)FSSegmentTitleViewWillBeginDragging:(FSSegmentTitleView *)titleView; 38 | 39 | /** 40 | 将要停止滑动 41 | 42 | @param titleView FSSegmentTitleView 43 | */ 44 | - (void)FSSegmentTitleViewWillEndDragging:(FSSegmentTitleView *)titleView; 45 | 46 | @end 47 | 48 | @interface FSSegmentTitleView : UIView 49 | 50 | @property (nonatomic, weak) iddelegate; 51 | 52 | /** 53 | 标题文字间距,默认20 54 | */ 55 | @property (nonatomic, assign) CGFloat itemMargin; 56 | 57 | /** 58 | 当前选中标题索引,默认0 59 | */ 60 | @property (nonatomic, assign) NSInteger selectIndex; 61 | 62 | /** 63 | 标题字体大小,默认15 64 | */ 65 | @property (nonatomic, strong) UIFont *titleFont; 66 | 67 | /** 68 | 标题选中字体大小,默认15 69 | */ 70 | @property (nonatomic, strong) UIFont *titleSelectFont; 71 | 72 | /** 73 | 标题正常颜色,默认black 74 | */ 75 | @property (nonatomic, strong) UIColor *titleNormalColor; 76 | 77 | /** 78 | 标题选中颜色,默认red 79 | */ 80 | @property (nonatomic, strong) UIColor *titleSelectColor; 81 | 82 | /** 83 | 指示器颜色,默认与titleSelectColor一样,在FSIndicatorTypeNone下无效 84 | */ 85 | @property (nonatomic, strong) UIColor *indicatorColor; 86 | 87 | /** 88 | 在FSIndicatorTypeCustom时可自定义此属性,为指示器一端延伸长度,默认5 89 | */ 90 | @property (nonatomic, assign) CGFloat indicatorExtension; 91 | 92 | /** 93 | 对象方法创建FSSegmentTitleView 94 | 95 | @param frame frame 96 | @param titlesArr 标题数组 97 | @param delegate delegate 98 | @param incatorType 指示器类型 99 | @return FSSegmentTitleView 100 | */ 101 | - (instancetype)initWithFrame:(CGRect)frame titles:(NSArray *)titlesArr delegate:(id)delegate indicatorType:(FSIndicatorType)incatorType; 102 | 103 | @end 104 | -------------------------------------------------------------------------------- /FSScrollContentViewDemo/FSScrollContentViewLib/FSSegmentTitleView.m: -------------------------------------------------------------------------------- 1 | // 2 | // FSSegmentTitleView.m 3 | // FSScrollContentViewDemo 4 | // 5 | // Created by huim on 2017/5/3. 6 | // Copyright © 2017年 fengshun. All rights reserved. 7 | // 8 | 9 | #import "FSSegmentTitleView.h" 10 | 11 | @interface FSSegmentTitleView () 12 | 13 | 14 | 15 | @property (nonatomic, strong) UIScrollView *scrollView; 16 | 17 | @property (nonatomic, strong) NSMutableArray *itemBtnArr; 18 | 19 | @property (nonatomic, strong) UIView *indicatorView; 20 | 21 | @property (nonatomic, assign) FSIndicatorType indicatorType; 22 | 23 | @property (nonatomic, strong) NSArray *titlesArr; 24 | 25 | @end 26 | 27 | @implementation FSSegmentTitleView 28 | 29 | - (instancetype)initWithFrame:(CGRect)frame titles:(NSArray *)titlesArr delegate:(id)delegate indicatorType:(FSIndicatorType)incatorType 30 | { 31 | self = [super initWithFrame:frame]; 32 | if (self) { 33 | [self initWithProperty]; 34 | self.titlesArr = titlesArr; 35 | self.delegate = delegate; 36 | self.indicatorType = incatorType; 37 | } 38 | return self; 39 | } 40 | //初始化默认属性值 41 | - (void)initWithProperty 42 | { 43 | self.itemMargin = 20; 44 | self.selectIndex = 0; 45 | self.titleNormalColor = [UIColor blackColor]; 46 | self.titleSelectColor = [UIColor redColor]; 47 | self.titleFont = [UIFont systemFontOfSize:15]; 48 | self.indicatorColor = self.titleSelectColor; 49 | self.indicatorExtension = 5.f; 50 | self.titleSelectFont = self.titleFont; 51 | } 52 | //重新布局frame 53 | - (void)layoutSubviews 54 | { 55 | [super layoutSubviews]; 56 | self.scrollView.frame = self.bounds; 57 | if (self.itemBtnArr.count == 0) { 58 | return; 59 | } 60 | CGFloat totalBtnWidth = 0.0; 61 | UIFont *titleFont = _titleFont; 62 | 63 | if (_titleFont != _titleSelectFont) { 64 | for (int idx = 0; idx < self.titlesArr.count; idx++) { 65 | UIButton *btn = self.itemBtnArr[idx]; 66 | titleFont = btn.isSelected?_titleSelectFont:_titleFont; 67 | CGFloat itemBtnWidth = [FSSegmentTitleView getWidthWithString:self.titlesArr[idx] font:titleFont] + self.itemMargin; 68 | totalBtnWidth += itemBtnWidth; 69 | } 70 | } 71 | else 72 | { 73 | for (NSString *title in self.titlesArr) { 74 | CGFloat itemBtnWidth = [FSSegmentTitleView getWidthWithString:title font:titleFont] + self.itemMargin; 75 | totalBtnWidth += itemBtnWidth; 76 | } 77 | } 78 | if (totalBtnWidth <= CGRectGetWidth(self.bounds)) {//不能滑动 79 | CGFloat itemBtnWidth = CGRectGetWidth(self.bounds)/self.itemBtnArr.count; 80 | CGFloat itemBtnHeight = CGRectGetHeight(self.bounds); 81 | [self.itemBtnArr enumerateObjectsUsingBlock:^(UIButton * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { 82 | obj.frame = CGRectMake(idx * itemBtnWidth, 0, itemBtnWidth, itemBtnHeight); 83 | }]; 84 | self.scrollView.contentSize = CGSizeMake(CGRectGetWidth(self.bounds), CGRectGetHeight(self.scrollView.bounds)); 85 | }else{//超出屏幕 可以滑动 86 | CGFloat currentX = 0; 87 | for (int idx = 0; idx < self.titlesArr.count; idx++) { 88 | UIButton *btn = self.itemBtnArr[idx]; 89 | titleFont = btn.isSelected?_titleSelectFont:_titleFont; 90 | CGFloat itemBtnWidth = [FSSegmentTitleView getWidthWithString:self.titlesArr[idx] font:titleFont] + self.itemMargin; 91 | CGFloat itemBtnHeight = CGRectGetHeight(self.bounds); 92 | btn.frame = CGRectMake(currentX, 0, itemBtnWidth, itemBtnHeight); 93 | currentX += itemBtnWidth; 94 | } 95 | self.scrollView.contentSize = CGSizeMake(currentX, CGRectGetHeight(self.scrollView.bounds)); 96 | } 97 | [self moveIndicatorView:YES]; 98 | } 99 | 100 | - (void)moveIndicatorView:(BOOL)animated 101 | { 102 | UIFont *titleFont = _titleFont; 103 | UIButton *selectBtn = self.itemBtnArr[self.selectIndex]; 104 | titleFont = selectBtn.isSelected?_titleSelectFont:_titleFont; 105 | CGFloat indicatorWidth = [FSSegmentTitleView getWidthWithString:self.titlesArr[self.selectIndex] font:titleFont]; 106 | [UIView animateWithDuration:(animated?0.05:0) animations:^{ 107 | switch (_indicatorType) { 108 | case FSIndicatorTypeDefault: 109 | self.indicatorView.frame = CGRectMake(selectBtn.frame.origin.x , CGRectGetHeight(self.scrollView.bounds) - 2, CGRectGetWidth(selectBtn.bounds), 2); 110 | break; 111 | case FSIndicatorTypeEqualTitle: 112 | self.indicatorView.center = CGPointMake(selectBtn.center.x, CGRectGetHeight(self.scrollView.bounds) - 1); 113 | self.indicatorView.bounds = CGRectMake(0, 0, indicatorWidth, 2); 114 | break; 115 | case FSIndicatorTypeCustom: 116 | self.indicatorView.center = CGPointMake(selectBtn.center.x, CGRectGetHeight(self.scrollView.bounds) - 1); 117 | self.indicatorView.bounds = CGRectMake(0, 0, indicatorWidth + _indicatorExtension*2, 2); 118 | break; 119 | case FSIndicatorTypeNone: 120 | self.indicatorView.frame = CGRectZero; 121 | break; 122 | default: 123 | break; 124 | } 125 | } completion:^(BOOL finished) { 126 | [self scrollSelectBtnCenter:animated]; 127 | }]; 128 | } 129 | 130 | - (void)scrollSelectBtnCenter:(BOOL)animated 131 | { 132 | UIButton *selectBtn = self.itemBtnArr[self.selectIndex]; 133 | CGRect centerRect = CGRectMake(selectBtn.center.x - CGRectGetWidth(self.scrollView.bounds)/2, 0, CGRectGetWidth(self.scrollView.bounds), CGRectGetHeight(self.scrollView.bounds)); 134 | [self.scrollView scrollRectToVisible:centerRect animated:animated]; 135 | } 136 | 137 | #pragma mark --LazyLoad 138 | 139 | - (UIScrollView *)scrollView { 140 | if (!_scrollView) { 141 | _scrollView = [[UIScrollView alloc] init]; 142 | _scrollView.showsHorizontalScrollIndicator = NO; 143 | _scrollView.showsVerticalScrollIndicator = NO; 144 | _scrollView.scrollsToTop = NO; 145 | _scrollView.delegate = self; 146 | [self addSubview:_scrollView]; 147 | } 148 | return _scrollView; 149 | } 150 | 151 | - (NSMutableArray*)itemBtnArr 152 | { 153 | if (!_itemBtnArr) { 154 | _itemBtnArr = [[NSMutableArray alloc]init]; 155 | } 156 | return _itemBtnArr; 157 | } 158 | 159 | - (UIView *)indicatorView 160 | { 161 | if (!_indicatorView) { 162 | _indicatorView = [[UIView alloc]init]; 163 | [self.scrollView addSubview:_indicatorView]; 164 | } 165 | return _indicatorView; 166 | } 167 | 168 | #pragma mark --Setter 169 | 170 | - (void)setTitlesArr:(NSArray *)titlesArr 171 | { 172 | _titlesArr = titlesArr; 173 | [self.itemBtnArr makeObjectsPerformSelector:@selector(removeFromSuperview)]; 174 | self.itemBtnArr = nil; 175 | for (NSString *title in titlesArr) { 176 | UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom]; 177 | btn.tag = self.itemBtnArr.count + 666; 178 | [btn setTitle:title forState:UIControlStateNormal]; 179 | [btn setTitleColor:_titleNormalColor forState:UIControlStateNormal]; 180 | [btn setTitleColor:_titleSelectColor forState:UIControlStateSelected]; 181 | btn.titleLabel.font = _titleFont; 182 | [self.scrollView addSubview:btn]; 183 | [btn addTarget:self action:@selector(btnClick:) forControlEvents:UIControlEventTouchUpInside]; 184 | if (self.itemBtnArr.count == self.selectIndex) { 185 | btn.selected = YES; 186 | } 187 | [self.itemBtnArr addObject:btn]; 188 | } 189 | [self setNeedsLayout]; 190 | [self layoutIfNeeded]; 191 | } 192 | 193 | - (void)setItemMargin:(CGFloat)itemMargin 194 | { 195 | _itemMargin = itemMargin; 196 | 197 | [self setNeedsLayout]; 198 | [self layoutIfNeeded]; 199 | } 200 | 201 | - (void)setSelectIndex:(NSInteger)selectIndex 202 | { 203 | if (_selectIndex == selectIndex||selectIndex < 0||selectIndex > self.itemBtnArr.count - 1) { 204 | return; 205 | } 206 | UIButton *lastBtn = [self.scrollView viewWithTag:_selectIndex + 666]; 207 | lastBtn.selected = NO; 208 | lastBtn.titleLabel.font = _titleFont; 209 | _selectIndex = selectIndex; 210 | UIButton *currentBtn = [self.scrollView viewWithTag:_selectIndex + 666]; 211 | currentBtn.selected = YES; 212 | currentBtn.titleLabel.font = _titleSelectFont; 213 | // [self moveIndicatorView:YES]; 214 | [self setNeedsLayout]; 215 | [self layoutIfNeeded]; 216 | } 217 | 218 | - (void)setTitleFont:(UIFont *)titleFont 219 | { 220 | _titleFont = titleFont; 221 | for (UIButton *btn in self.itemBtnArr) { 222 | btn.titleLabel.font = titleFont; 223 | } 224 | [self setNeedsLayout]; 225 | [self layoutIfNeeded]; 226 | } 227 | 228 | - (void)setTitleSelectFont:(UIFont *)titleSelectFont 229 | { 230 | if (_titleFont == titleSelectFont) { 231 | _titleSelectFont = _titleFont; 232 | return; 233 | } 234 | _titleSelectFont = titleSelectFont; 235 | for (UIButton *btn in self.itemBtnArr) { 236 | btn.titleLabel.font = btn.isSelected?titleSelectFont:_titleFont; 237 | } 238 | 239 | [self setNeedsLayout]; 240 | [self layoutIfNeeded]; 241 | } 242 | 243 | - (void)setTitleNormalColor:(UIColor *)titleNormalColor 244 | { 245 | _titleNormalColor = titleNormalColor; 246 | for (UIButton *btn in self.itemBtnArr) { 247 | [btn setTitleColor:titleNormalColor forState:UIControlStateNormal]; 248 | } 249 | } 250 | 251 | - (void)setTitleSelectColor:(UIColor *)titleSelectColor 252 | { 253 | _titleSelectColor = titleSelectColor; 254 | for (UIButton *btn in self.itemBtnArr) { 255 | [btn setTitleColor:titleSelectColor forState:UIControlStateSelected]; 256 | } 257 | } 258 | 259 | - (void)setIndicatorColor:(UIColor *)indicatorColor 260 | { 261 | _indicatorColor = indicatorColor; 262 | self.indicatorView.backgroundColor = indicatorColor; 263 | } 264 | 265 | - (void)setIndicatorExtension:(CGFloat)indicatorExtension 266 | { 267 | _indicatorExtension = indicatorExtension; 268 | [self setNeedsLayout]; 269 | [self layoutIfNeeded]; 270 | } 271 | 272 | #pragma mark --Btn 273 | 274 | - (void)btnClick:(UIButton *)btn 275 | { 276 | NSInteger index = btn.tag - 666; 277 | if (index == self.selectIndex) { 278 | return; 279 | } 280 | if (self.delegate&&[self.delegate respondsToSelector:@selector(FSSegmentTitleView:startIndex:endIndex:)]) { 281 | [self.delegate FSSegmentTitleView:self startIndex:self.selectIndex endIndex:index]; 282 | } 283 | self.selectIndex = index; 284 | } 285 | 286 | #pragma mark UIScrollView 287 | - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView 288 | { 289 | if (self.delegate&&[self.delegate respondsToSelector:@selector(FSSegmentTitleViewWillBeginDragging:)]) { 290 | [self.delegate FSSegmentTitleViewWillBeginDragging:self]; 291 | } 292 | } 293 | 294 | - (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset 295 | { 296 | if (self.delegate&&[self.delegate respondsToSelector:@selector(FSSegmentTitleViewWillEndDragging:)]) { 297 | [self.delegate FSSegmentTitleViewWillEndDragging:self]; 298 | } 299 | } 300 | 301 | 302 | #pragma mark Private 303 | /** 304 | 计算字符串长度 305 | 306 | @param string string 307 | @param font font 308 | @return 字符串长度 309 | */ 310 | + (CGFloat)getWidthWithString:(NSString *)string font:(UIFont *)font { 311 | NSDictionary *attrs = @{NSFontAttributeName : font}; 312 | return [string boundingRectWithSize:CGSizeMake(0, 0) options:NSStringDrawingUsesLineFragmentOrigin attributes:attrs context:nil].size.width; 313 | } 314 | 315 | /** 316 | 随机色 317 | 318 | @return 调试用 319 | */ 320 | + (UIColor*) randomColor{ 321 | NSInteger r = arc4random() % 255; 322 | NSInteger g = arc4random() % 255; 323 | NSInteger b = arc4random() % 255; 324 | return [UIColor colorWithRed:r/255.0 green:g/255.0 blue:b/255.0 alpha:1]; 325 | } 326 | 327 | 328 | @end 329 | -------------------------------------------------------------------------------- /FSScrollContentViewLib/FSPageContentView.h: -------------------------------------------------------------------------------- 1 | // 2 | // FSPageContentView.h 3 | // Huim 4 | // 5 | // Created by huim on 2017/4/28. 6 | // Copyright © 2017年 huim. All rights reserved. 7 | // 8 | 9 | #import 10 | @class FSPageContentView; 11 | 12 | @protocol FSPageContentViewDelegate 13 | 14 | @optional 15 | 16 | /** 17 | FSPageContentView开始滑动 18 | 19 | @param contentView FSPageContentView 20 | */ 21 | - (void)FSContentViewWillBeginDragging:(FSPageContentView *)contentView; 22 | 23 | /** 24 | FSPageContentView滑动调用 25 | 26 | @param contentView FSPageContentView 27 | @param startIndex 开始滑动页面索引 28 | @param endIndex 结束滑动页面索引 29 | @param progress 滑动进度 30 | */ 31 | - (void)FSContentViewDidScroll:(FSPageContentView *)contentView startIndex:(NSInteger)startIndex endIndex:(NSInteger)endIndex progress:(CGFloat)progress; 32 | 33 | /** 34 | FSPageContentView结束滑动 35 | 36 | @param contentView FSPageContentView 37 | @param startIndex 开始滑动索引 38 | @param endIndex 结束滑动索引 39 | */ 40 | - (void)FSContenViewDidEndDecelerating:(FSPageContentView *)contentView startIndex:(NSInteger)startIndex endIndex:(NSInteger)endIndex; 41 | 42 | /** 43 | scrollViewDidEndDragging 44 | 45 | @param contentView FSPageContentView 46 | */ 47 | - (void)FSContenViewDidEndDragging:(FSPageContentView *)contentView; 48 | 49 | @end 50 | 51 | @interface FSPageContentView : UIView 52 | 53 | /** 54 | 对象方法创建FSPageContentView 55 | 56 | @param frame frame 57 | @param childVCs 子VC数组 58 | @param parentVC 父视图VC 59 | @param delegate delegate 60 | @return FSPageContentView 61 | */ 62 | - (instancetype)initWithFrame:(CGRect)frame childVCs:(NSArray *)childVCs parentVC:(UIViewController *)parentVC delegate:(id)delegate; 63 | 64 | @property (nonatomic, weak) iddelegate; 65 | 66 | /** 67 | 设置contentView当前展示的页面索引,默认为0 68 | */ 69 | @property (nonatomic, assign) NSInteger contentViewCurrentIndex; 70 | 71 | /** 72 | 设置contentView能否左右滑动,默认YES 73 | */ 74 | @property (nonatomic, assign) BOOL contentViewCanScroll; 75 | 76 | @end 77 | -------------------------------------------------------------------------------- /FSScrollContentViewLib/FSPageContentView.m: -------------------------------------------------------------------------------- 1 | // 2 | // FSPageContentView.m 3 | // Huim 4 | // 5 | // Created by huim on 2017/4/28. 6 | // Copyright © 2017年 huim. All rights reserved. 7 | // 8 | 9 | #import "FSPageContentView.h" 10 | 11 | #define IOS_VERSION ([[[UIDevice currentDevice] systemVersion] floatValue]) 12 | static NSString *collectionCellIdentifier = @"collectionCellIdentifier"; 13 | 14 | @interface FSPageContentView () 15 | 16 | @property (nonatomic, weak) UIViewController *parentVC;//父视图 17 | @property (nonatomic, strong) NSArray *childsVCs;//子视图数组 18 | @property (nonatomic, weak) UICollectionView *collectionView; 19 | @property (nonatomic, assign) CGFloat startOffsetX; 20 | @property (nonatomic, assign) BOOL isSelectBtn;//是否是滑动 21 | 22 | @end 23 | 24 | @implementation FSPageContentView 25 | 26 | - (instancetype)initWithFrame:(CGRect)frame childVCs:(NSArray *)childVCs parentVC:(UIViewController *)parentVC delegate:(id)delegate 27 | { 28 | self = [super initWithFrame:frame]; 29 | if (self) { 30 | self.parentVC = parentVC; 31 | self.childsVCs = childVCs; 32 | self.delegate = delegate; 33 | 34 | [self setupSubViews]; 35 | } 36 | return self; 37 | } 38 | 39 | - (void)layoutSubviews 40 | { 41 | [super layoutSubviews]; 42 | } 43 | 44 | #pragma mark --LazyLoad 45 | 46 | - (UICollectionView *)collectionView 47 | { 48 | if (!_collectionView) { 49 | UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc]init]; 50 | flowLayout.itemSize = self.bounds.size; 51 | flowLayout.minimumLineSpacing = 0; 52 | flowLayout.minimumInteritemSpacing = 0; 53 | flowLayout.scrollDirection = UICollectionViewScrollDirectionHorizontal; 54 | 55 | UICollectionView * collectionView = [[UICollectionView alloc]initWithFrame:self.bounds collectionViewLayout:flowLayout]; 56 | collectionView.showsHorizontalScrollIndicator = NO; 57 | collectionView.pagingEnabled = YES; 58 | collectionView.bounces = NO; 59 | collectionView.delegate = self; 60 | collectionView.dataSource = self; 61 | [collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:collectionCellIdentifier]; 62 | [self addSubview:collectionView]; 63 | self.collectionView = collectionView; 64 | } 65 | return _collectionView; 66 | } 67 | 68 | #pragma mark --setup 69 | - (void)setupSubViews 70 | { 71 | _startOffsetX = 0; 72 | _isSelectBtn = NO; 73 | _contentViewCanScroll = YES; 74 | 75 | for (UIViewController *childVC in self.childsVCs) { 76 | [self.parentVC addChildViewController:childVC]; 77 | } 78 | // [self addSubview:self.collectionView]; 79 | [self.collectionView reloadData]; 80 | } 81 | 82 | #pragma mark UICollectionView 83 | 84 | - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section 85 | { 86 | return self.childsVCs.count; 87 | } 88 | 89 | - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath 90 | { 91 | UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:collectionCellIdentifier forIndexPath:indexPath]; 92 | if (IOS_VERSION < 8.0) { 93 | [cell.contentView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)]; 94 | UIViewController *childVC = self.childsVCs[indexPath.item]; 95 | childVC.view.frame = cell.contentView.bounds; 96 | [cell.contentView addSubview:childVC.view]; 97 | } 98 | return cell; 99 | } 100 | 101 | #ifdef __IPHONE_8_0 102 | - (void)collectionView:(UICollectionView *)collectionView willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath{ 103 | [cell.contentView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)]; 104 | UIViewController *childVc = self.childsVCs[indexPath.row]; 105 | childVc.view.frame = cell.contentView.bounds; 106 | [cell.contentView addSubview:childVc.view]; 107 | } 108 | #endif 109 | 110 | #pragma mark UIScrollView 111 | 112 | - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView 113 | { 114 | _isSelectBtn = NO; 115 | _startOffsetX = scrollView.contentOffset.x; 116 | 117 | if (self.delegate && [self.delegate respondsToSelector:@selector(FSContentViewWillBeginDragging:)]) { 118 | [self.delegate FSContentViewWillBeginDragging:self]; 119 | } 120 | } 121 | 122 | - (void)scrollViewDidScroll:(UIScrollView *)scrollView 123 | { 124 | if (_isSelectBtn) { 125 | return; 126 | } 127 | CGFloat scrollView_W = scrollView.bounds.size.width; 128 | CGFloat currentOffsetX = scrollView.contentOffset.x; 129 | NSInteger startIndex = floor(_startOffsetX/scrollView_W); 130 | NSInteger endIndex; 131 | CGFloat progress; 132 | if (currentOffsetX > _startOffsetX) {//左滑left 133 | progress = (currentOffsetX - _startOffsetX)/scrollView_W; 134 | endIndex = startIndex + 1; 135 | if (endIndex > self.childsVCs.count - 1) { 136 | endIndex = self.childsVCs.count - 1; 137 | } 138 | }else if (currentOffsetX == _startOffsetX){//没滑过去 139 | progress = 0; 140 | endIndex = startIndex; 141 | }else{//右滑right 142 | progress = (_startOffsetX - currentOffsetX)/scrollView_W; 143 | endIndex = startIndex - 1; 144 | endIndex = endIndex < 0?0:endIndex; 145 | } 146 | 147 | if (self.delegate && [self.delegate respondsToSelector:@selector(FSContentViewDidScroll:startIndex:endIndex:progress:)]) { 148 | [self.delegate FSContentViewDidScroll:self startIndex:startIndex endIndex:endIndex progress:progress]; 149 | } 150 | } 151 | 152 | - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView 153 | { 154 | CGFloat scrollView_W = scrollView.bounds.size.width; 155 | CGFloat currentOffsetX = scrollView.contentOffset.x; 156 | NSInteger startIndex = floor(_startOffsetX/scrollView_W); 157 | NSInteger endIndex = floor(currentOffsetX/scrollView_W); 158 | 159 | if (self.delegate && [self.delegate respondsToSelector:@selector(FSContenViewDidEndDecelerating:startIndex:endIndex:)]) { 160 | [self.delegate FSContenViewDidEndDecelerating:self startIndex:startIndex endIndex:endIndex]; 161 | } 162 | } 163 | 164 | - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate 165 | { 166 | if (!decelerate) { 167 | if (self.delegate && [self.delegate respondsToSelector:@selector(FSContenViewDidEndDragging:)]) { 168 | [self.delegate FSContenViewDidEndDragging:self]; 169 | } 170 | } 171 | } 172 | 173 | #pragma mark setter 174 | 175 | - (void)setContentViewCurrentIndex:(NSInteger)contentViewCurrentIndex 176 | { 177 | if (contentViewCurrentIndex < 0||contentViewCurrentIndex > self.childsVCs.count-1) { 178 | return; 179 | } 180 | _isSelectBtn = YES; 181 | _contentViewCurrentIndex = contentViewCurrentIndex; 182 | [self.collectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForRow:contentViewCurrentIndex inSection:0] atScrollPosition:UICollectionViewScrollPositionNone animated:NO]; 183 | } 184 | 185 | - (void)setContentViewCanScroll:(BOOL)contentViewCanScroll 186 | { 187 | _contentViewCanScroll = contentViewCanScroll; 188 | _collectionView.scrollEnabled = _contentViewCanScroll; 189 | } 190 | 191 | @end 192 | -------------------------------------------------------------------------------- /FSScrollContentViewLib/FSScrollContentView.h: -------------------------------------------------------------------------------- 1 | // 2 | // FSScrollContentView.h 3 | // FSScrollContentViewDemo 4 | // 5 | // Created by 冯顺 on 2017/5/3. 6 | // Copyright © 2017年 fengshun. All rights reserved. 7 | // 8 | 9 | 10 | #import "FSPageContentView.h" 11 | #import "FSSegmentTitleView.h" 12 | -------------------------------------------------------------------------------- /FSScrollContentViewLib/FSSegmentTitleView.h: -------------------------------------------------------------------------------- 1 | // 2 | // FSSegmentTitleView.h 3 | // FSScrollContentViewDemo 4 | // 5 | // Created by huim on 2017/5/3. 6 | // Copyright © 2017年 fengshun. All rights reserved. 7 | // 8 | 9 | #import 10 | @class FSSegmentTitleView; 11 | 12 | typedef enum : NSUInteger { 13 | FSIndicatorTypeDefault,//默认与按钮长度相同 14 | FSIndicatorTypeEqualTitle,//与文字长度相同 15 | FSIndicatorTypeCustom,//自定义文字边缘延伸宽度 16 | FSIndicatorTypeNone, 17 | } FSIndicatorType;//指示器类型枚举 18 | 19 | @protocol FSSegmentTitleViewDelegate 20 | 21 | @optional 22 | 23 | /** 24 | 切换标题 25 | 26 | @param titleView FSSegmentTitleView 27 | @param startIndex 切换前标题索引 28 | @param endIndex 切换后标题索引 29 | */ 30 | - (void)FSSegmentTitleView:(FSSegmentTitleView *)titleView startIndex:(NSInteger)startIndex endIndex:(NSInteger)endIndex; 31 | 32 | /** 33 | 将要开始滑动 34 | 35 | @param titleView FSSegmentTitleView 36 | */ 37 | - (void)FSSegmentTitleViewWillBeginDragging:(FSSegmentTitleView *)titleView; 38 | 39 | /** 40 | 将要停止滑动 41 | 42 | @param titleView FSSegmentTitleView 43 | */ 44 | - (void)FSSegmentTitleViewWillEndDragging:(FSSegmentTitleView *)titleView; 45 | 46 | @end 47 | 48 | @interface FSSegmentTitleView : UIView 49 | 50 | @property (nonatomic, weak) iddelegate; 51 | 52 | /** 53 | 标题文字间距,默认20 54 | */ 55 | @property (nonatomic, assign) CGFloat itemMargin; 56 | 57 | /** 58 | 当前选中标题索引,默认0 59 | */ 60 | @property (nonatomic, assign) NSInteger selectIndex; 61 | 62 | /** 63 | 标题字体大小,默认15 64 | */ 65 | @property (nonatomic, strong) UIFont *titleFont; 66 | 67 | /** 68 | 标题选中字体大小,默认15 69 | */ 70 | @property (nonatomic, strong) UIFont *titleSelectFont; 71 | 72 | /** 73 | 标题正常颜色,默认black 74 | */ 75 | @property (nonatomic, strong) UIColor *titleNormalColor; 76 | 77 | /** 78 | 标题选中颜色,默认red 79 | */ 80 | @property (nonatomic, strong) UIColor *titleSelectColor; 81 | 82 | /** 83 | 指示器颜色,默认与titleSelectColor一样,在FSIndicatorTypeNone下无效 84 | */ 85 | @property (nonatomic, strong) UIColor *indicatorColor; 86 | 87 | /** 88 | 在FSIndicatorTypeCustom时可自定义此属性,为指示器一端延伸长度,默认5 89 | */ 90 | @property (nonatomic, assign) CGFloat indicatorExtension; 91 | 92 | /** 93 | 对象方法创建FSSegmentTitleView 94 | 95 | @param frame frame 96 | @param titlesArr 标题数组 97 | @param delegate delegate 98 | @param incatorType 指示器类型 99 | @return FSSegmentTitleView 100 | */ 101 | - (instancetype)initWithFrame:(CGRect)frame titles:(NSArray *)titlesArr delegate:(id)delegate indicatorType:(FSIndicatorType)incatorType; 102 | 103 | @end 104 | -------------------------------------------------------------------------------- /FSScrollContentViewLib/FSSegmentTitleView.m: -------------------------------------------------------------------------------- 1 | // 2 | // FSSegmentTitleView.m 3 | // FSScrollContentViewDemo 4 | // 5 | // Created by huim on 2017/5/3. 6 | // Copyright © 2017年 fengshun. All rights reserved. 7 | // 8 | 9 | #import "FSSegmentTitleView.h" 10 | 11 | @interface FSSegmentTitleView () 12 | 13 | 14 | 15 | @property (nonatomic, strong) UIScrollView *scrollView; 16 | 17 | @property (nonatomic, strong) NSMutableArray *itemBtnArr; 18 | 19 | @property (nonatomic, strong) UIView *indicatorView; 20 | 21 | @property (nonatomic, assign) FSIndicatorType indicatorType; 22 | 23 | @property (nonatomic, strong) NSArray *titlesArr; 24 | 25 | @end 26 | 27 | @implementation FSSegmentTitleView 28 | 29 | - (instancetype)initWithFrame:(CGRect)frame titles:(NSArray *)titlesArr delegate:(id)delegate indicatorType:(FSIndicatorType)incatorType 30 | { 31 | self = [super initWithFrame:frame]; 32 | if (self) { 33 | [self initWithProperty]; 34 | self.titlesArr = titlesArr; 35 | self.delegate = delegate; 36 | self.indicatorType = incatorType; 37 | } 38 | return self; 39 | } 40 | //初始化默认属性值 41 | - (void)initWithProperty 42 | { 43 | self.itemMargin = 20; 44 | self.selectIndex = 0; 45 | self.titleNormalColor = [UIColor blackColor]; 46 | self.titleSelectColor = [UIColor redColor]; 47 | self.titleFont = [UIFont systemFontOfSize:15]; 48 | self.indicatorColor = self.titleSelectColor; 49 | self.indicatorExtension = 5.f; 50 | self.titleSelectFont = self.titleFont; 51 | } 52 | //重新布局frame 53 | - (void)layoutSubviews 54 | { 55 | [super layoutSubviews]; 56 | self.scrollView.frame = self.bounds; 57 | if (self.itemBtnArr.count == 0) { 58 | return; 59 | } 60 | CGFloat totalBtnWidth = 0.0; 61 | UIFont *titleFont = _titleFont; 62 | 63 | if (_titleFont != _titleSelectFont) { 64 | for (int idx = 0; idx < self.titlesArr.count; idx++) { 65 | UIButton *btn = self.itemBtnArr[idx]; 66 | titleFont = btn.isSelected?_titleSelectFont:_titleFont; 67 | CGFloat itemBtnWidth = [FSSegmentTitleView getWidthWithString:self.titlesArr[idx] font:titleFont] + self.itemMargin; 68 | totalBtnWidth += itemBtnWidth; 69 | } 70 | } 71 | else 72 | { 73 | for (NSString *title in self.titlesArr) { 74 | CGFloat itemBtnWidth = [FSSegmentTitleView getWidthWithString:title font:titleFont] + self.itemMargin; 75 | totalBtnWidth += itemBtnWidth; 76 | } 77 | } 78 | if (totalBtnWidth <= CGRectGetWidth(self.bounds)) {//不能滑动 79 | CGFloat itemBtnWidth = CGRectGetWidth(self.bounds)/self.itemBtnArr.count; 80 | CGFloat itemBtnHeight = CGRectGetHeight(self.bounds); 81 | [self.itemBtnArr enumerateObjectsUsingBlock:^(UIButton * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { 82 | obj.frame = CGRectMake(idx * itemBtnWidth, 0, itemBtnWidth, itemBtnHeight); 83 | }]; 84 | self.scrollView.contentSize = CGSizeMake(CGRectGetWidth(self.bounds), CGRectGetHeight(self.scrollView.bounds)); 85 | }else{//超出屏幕 可以滑动 86 | CGFloat currentX = 0; 87 | for (int idx = 0; idx < self.titlesArr.count; idx++) { 88 | UIButton *btn = self.itemBtnArr[idx]; 89 | titleFont = btn.isSelected?_titleSelectFont:_titleFont; 90 | CGFloat itemBtnWidth = [FSSegmentTitleView getWidthWithString:self.titlesArr[idx] font:titleFont] + self.itemMargin; 91 | CGFloat itemBtnHeight = CGRectGetHeight(self.bounds); 92 | btn.frame = CGRectMake(currentX, 0, itemBtnWidth, itemBtnHeight); 93 | currentX += itemBtnWidth; 94 | } 95 | self.scrollView.contentSize = CGSizeMake(currentX, CGRectGetHeight(self.scrollView.bounds)); 96 | } 97 | [self moveIndicatorView:YES]; 98 | } 99 | 100 | - (void)moveIndicatorView:(BOOL)animated 101 | { 102 | UIFont *titleFont = _titleFont; 103 | UIButton *selectBtn = self.itemBtnArr[self.selectIndex]; 104 | titleFont = selectBtn.isSelected?_titleSelectFont:_titleFont; 105 | CGFloat indicatorWidth = [FSSegmentTitleView getWidthWithString:self.titlesArr[self.selectIndex] font:titleFont]; 106 | [UIView animateWithDuration:(animated?0.05:0) animations:^{ 107 | switch (_indicatorType) { 108 | case FSIndicatorTypeDefault: 109 | self.indicatorView.frame = CGRectMake(selectBtn.frame.origin.x , CGRectGetHeight(self.scrollView.bounds) - 2, CGRectGetWidth(selectBtn.bounds), 2); 110 | break; 111 | case FSIndicatorTypeEqualTitle: 112 | self.indicatorView.center = CGPointMake(selectBtn.center.x, CGRectGetHeight(self.scrollView.bounds) - 1); 113 | self.indicatorView.bounds = CGRectMake(0, 0, indicatorWidth, 2); 114 | break; 115 | case FSIndicatorTypeCustom: 116 | self.indicatorView.center = CGPointMake(selectBtn.center.x, CGRectGetHeight(self.scrollView.bounds) - 1); 117 | self.indicatorView.bounds = CGRectMake(0, 0, indicatorWidth + _indicatorExtension*2, 2); 118 | break; 119 | case FSIndicatorTypeNone: 120 | self.indicatorView.frame = CGRectZero; 121 | break; 122 | default: 123 | break; 124 | } 125 | } completion:^(BOOL finished) { 126 | [self scrollSelectBtnCenter:animated]; 127 | }]; 128 | } 129 | 130 | - (void)scrollSelectBtnCenter:(BOOL)animated 131 | { 132 | UIButton *selectBtn = self.itemBtnArr[self.selectIndex]; 133 | CGRect centerRect = CGRectMake(selectBtn.center.x - CGRectGetWidth(self.scrollView.bounds)/2, 0, CGRectGetWidth(self.scrollView.bounds), CGRectGetHeight(self.scrollView.bounds)); 134 | [self.scrollView scrollRectToVisible:centerRect animated:animated]; 135 | } 136 | 137 | #pragma mark --LazyLoad 138 | 139 | - (UIScrollView *)scrollView { 140 | if (!_scrollView) { 141 | _scrollView = [[UIScrollView alloc] init]; 142 | _scrollView.showsHorizontalScrollIndicator = NO; 143 | _scrollView.showsVerticalScrollIndicator = NO; 144 | _scrollView.scrollsToTop = NO; 145 | _scrollView.delegate = self; 146 | [self addSubview:_scrollView]; 147 | } 148 | return _scrollView; 149 | } 150 | 151 | - (NSMutableArray*)itemBtnArr 152 | { 153 | if (!_itemBtnArr) { 154 | _itemBtnArr = [[NSMutableArray alloc]init]; 155 | } 156 | return _itemBtnArr; 157 | } 158 | 159 | - (UIView *)indicatorView 160 | { 161 | if (!_indicatorView) { 162 | _indicatorView = [[UIView alloc]init]; 163 | [self.scrollView addSubview:_indicatorView]; 164 | } 165 | return _indicatorView; 166 | } 167 | 168 | #pragma mark --Setter 169 | 170 | - (void)setTitlesArr:(NSArray *)titlesArr 171 | { 172 | _titlesArr = titlesArr; 173 | [self.itemBtnArr makeObjectsPerformSelector:@selector(removeFromSuperview)]; 174 | self.itemBtnArr = nil; 175 | for (NSString *title in titlesArr) { 176 | UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom]; 177 | btn.tag = self.itemBtnArr.count + 666; 178 | [btn setTitle:title forState:UIControlStateNormal]; 179 | [btn setTitleColor:_titleNormalColor forState:UIControlStateNormal]; 180 | [btn setTitleColor:_titleSelectColor forState:UIControlStateSelected]; 181 | btn.titleLabel.font = _titleFont; 182 | [self.scrollView addSubview:btn]; 183 | [btn addTarget:self action:@selector(btnClick:) forControlEvents:UIControlEventTouchUpInside]; 184 | if (self.itemBtnArr.count == self.selectIndex) { 185 | btn.selected = YES; 186 | } 187 | [self.itemBtnArr addObject:btn]; 188 | } 189 | [self setNeedsLayout]; 190 | [self layoutIfNeeded]; 191 | } 192 | 193 | - (void)setItemMargin:(CGFloat)itemMargin 194 | { 195 | _itemMargin = itemMargin; 196 | 197 | [self setNeedsLayout]; 198 | [self layoutIfNeeded]; 199 | } 200 | 201 | - (void)setSelectIndex:(NSInteger)selectIndex 202 | { 203 | if (_selectIndex == selectIndex||selectIndex < 0||selectIndex > self.itemBtnArr.count - 1) { 204 | return; 205 | } 206 | UIButton *lastBtn = [self.scrollView viewWithTag:_selectIndex + 666]; 207 | lastBtn.selected = NO; 208 | lastBtn.titleLabel.font = _titleFont; 209 | _selectIndex = selectIndex; 210 | UIButton *currentBtn = [self.scrollView viewWithTag:_selectIndex + 666]; 211 | currentBtn.selected = YES; 212 | currentBtn.titleLabel.font = _titleSelectFont; 213 | // [self moveIndicatorView:YES]; 214 | [self setNeedsLayout]; 215 | [self layoutIfNeeded]; 216 | } 217 | 218 | - (void)setTitleFont:(UIFont *)titleFont 219 | { 220 | _titleFont = titleFont; 221 | for (UIButton *btn in self.itemBtnArr) { 222 | btn.titleLabel.font = titleFont; 223 | } 224 | [self setNeedsLayout]; 225 | [self layoutIfNeeded]; 226 | } 227 | 228 | - (void)setTitleSelectFont:(UIFont *)titleSelectFont 229 | { 230 | if (_titleFont == titleSelectFont) { 231 | _titleSelectFont = _titleFont; 232 | return; 233 | } 234 | _titleSelectFont = titleSelectFont; 235 | for (UIButton *btn in self.itemBtnArr) { 236 | btn.titleLabel.font = btn.isSelected?titleSelectFont:_titleFont; 237 | } 238 | 239 | [self setNeedsLayout]; 240 | [self layoutIfNeeded]; 241 | } 242 | 243 | - (void)setTitleNormalColor:(UIColor *)titleNormalColor 244 | { 245 | _titleNormalColor = titleNormalColor; 246 | for (UIButton *btn in self.itemBtnArr) { 247 | [btn setTitleColor:titleNormalColor forState:UIControlStateNormal]; 248 | } 249 | } 250 | 251 | - (void)setTitleSelectColor:(UIColor *)titleSelectColor 252 | { 253 | _titleSelectColor = titleSelectColor; 254 | for (UIButton *btn in self.itemBtnArr) { 255 | [btn setTitleColor:titleSelectColor forState:UIControlStateSelected]; 256 | } 257 | } 258 | 259 | - (void)setIndicatorColor:(UIColor *)indicatorColor 260 | { 261 | _indicatorColor = indicatorColor; 262 | self.indicatorView.backgroundColor = indicatorColor; 263 | } 264 | 265 | - (void)setIndicatorExtension:(CGFloat)indicatorExtension 266 | { 267 | _indicatorExtension = indicatorExtension; 268 | [self setNeedsLayout]; 269 | [self layoutIfNeeded]; 270 | } 271 | 272 | #pragma mark --Btn 273 | 274 | - (void)btnClick:(UIButton *)btn 275 | { 276 | NSInteger index = btn.tag - 666; 277 | if (index == self.selectIndex) { 278 | return; 279 | } 280 | if (self.delegate&&[self.delegate respondsToSelector:@selector(FSSegmentTitleView:startIndex:endIndex:)]) { 281 | [self.delegate FSSegmentTitleView:self startIndex:self.selectIndex endIndex:index]; 282 | } 283 | self.selectIndex = index; 284 | } 285 | 286 | #pragma mark UIScrollView 287 | - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView 288 | { 289 | if (self.delegate&&[self.delegate respondsToSelector:@selector(FSSegmentTitleViewWillBeginDragging:)]) { 290 | [self.delegate FSSegmentTitleViewWillBeginDragging:self]; 291 | } 292 | } 293 | 294 | - (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset 295 | { 296 | if (self.delegate&&[self.delegate respondsToSelector:@selector(FSSegmentTitleViewWillEndDragging:)]) { 297 | [self.delegate FSSegmentTitleViewWillEndDragging:self]; 298 | } 299 | } 300 | 301 | 302 | #pragma mark Private 303 | /** 304 | 计算字符串长度 305 | 306 | @param string string 307 | @param font font 308 | @return 字符串长度 309 | */ 310 | + (CGFloat)getWidthWithString:(NSString *)string font:(UIFont *)font { 311 | NSDictionary *attrs = @{NSFontAttributeName : font}; 312 | return [string boundingRectWithSize:CGSizeMake(0, 0) options:NSStringDrawingUsesLineFragmentOrigin attributes:attrs context:nil].size.width; 313 | } 314 | 315 | /** 316 | 随机色 317 | 318 | @return 调试用 319 | */ 320 | + (UIColor*) randomColor{ 321 | NSInteger r = arc4random() % 255; 322 | NSInteger g = arc4random() % 255; 323 | NSInteger b = arc4random() % 255; 324 | return [UIColor colorWithRed:r/255.0 green:g/255.0 blue:b/255.0 alpha:1]; 325 | } 326 | 327 | 328 | @end 329 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 shunFSKi 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FSScrollContentView 2 | 3 | ![badge-languages](https://img.shields.io/badge/language-ObjC-orange.svg) ![badge-platforms](https://img.shields.io/badge/platforms-iOS7-lightgrey.svg) [![Build Status](https://travis-ci.org/shunFSKi/FSScrollContentView.svg?branch=master)](https://travis-ci.org/shunFSKi/FSScrollContentView) [![CocoaPods](https://img.shields.io/cocoapods/v/FSScrollContentView.svg)]() [![CocoaPods](https://img.shields.io/cocoapods/dt/FSScrollContentView.svg)]() [![CocoaPods](https://img.shields.io/cocoapods/l/FSScrollContentView.svg)]() 4 | 5 | 简书:http://www.jianshu.com/p/34cecb066cc1 6 | 7 | 这是本人在整理项目时抽离了业务代码整理封装的一个通俗易懂较为实用的框架。 8 | 支持点击上方标题,切换下方内容页面,也支持滑动下方内容区域,切换上方的标题。 9 | * 主要用来适用于多个视图左右滑动,切换顶部标签控制显示视图的需求 10 | * 仿网易新闻,一些电商app的样式实现 11 | * 实现简单,通俗易懂,支持一些简单的自定义 12 | * 自动适应标签数量控制滑动或不能滑动 13 | ## 效果图 14 | ![几种类型的效果图](https://github.com/shunFSKi/ImageResources/blob/master/scrollContentView.gif) 15 | ## 使用方式 16 | **1、cocoapods** 17 | 18 | pod search FSScrollContentView 19 | 如果找不到执行pod setup 20 | pod 'FSScrollContentView' 21 | 22 | **2、添加文件** 23 | 24 | 直接clone代码后将项目中的FSScrollContentViewLib文件夹导入自己项目中,导入FSScrollContentView.h头文件 25 | ## API使用说明 26 | 其实demo中有很详细的注释说明,通俗易懂 27 | 框架包含**FSPageContentView**和**FSSegmentTitleView**两个完全独立的类文件,可酌情使用 28 | 29 | **FSPageContentView** 30 | 31 | * 创建FSPageContentView 32 | ``` 33 | /** 34 | 对象方法创建FSPageContentView 35 | 36 | @param frame frame 37 | @param childVCs 子VC数组 38 | @param parentVC 父视图VC 39 | @param delegate delegate 40 | @return FSPageContentView 41 | */ 42 | - (instancetype)initWithFrame:(CGRect)frame childVCs:(NSArray *)childVCs parentVC:(UIViewController *)parentVC delegate:(id)delegate; 43 | ``` 44 | * FSPageContentView属性修改 45 | ``` 46 | /** 47 | 设置contentView当前展示的页面索引,默认为0 48 | */ 49 | @property (nonatomic, assign) NSInteger contentViewCurrentIndex; 50 | ``` 51 | * FSPageContentView代理方法 52 | ``` 53 | /** 54 | FSPageContentView开始滑动 55 | 56 | @param contentView FSPageContentView 57 | */ 58 | - (void)FSContentViewWillBeginDragging:(FSPageContentView *)contentView; 59 | 60 | /** 61 | FSPageContentView滑动调用 62 | 63 | @param contentView FSPageContentView 64 | @param startIndex 开始滑动页面索引 65 | @param endIndex 结束滑动页面索引 66 | @param progress 滑动进度 67 | */ 68 | - (void)FSContentViewDidScroll:(FSPageContentView *)contentView startIndex:(NSInteger)startIndex endIndex:(NSInteger)endIndex progress:(CGFloat)progress; 69 | 70 | /** 71 | FSPageContentView结束滑动 72 | 73 | @param contentView FSPageContentView 74 | @param startIndex 开始滑动索引 75 | @param endIndex 结束滑动索引 76 | */ 77 | - (void)FSContenViewDidEndDecelerating:(FSPageContentView *)contentView startIndex:(NSInteger)startIndex endIndex:(NSInteger)endIndex; 78 | ``` 79 | **FSSegmentTitleView** 80 | * 创建FSSegmentTitleView 81 | ``` 82 | /** 83 | 对象方法创建FSSegmentTitleView 84 | 85 | @param frame frame 86 | @param titlesArr 标题数组,必须传值 87 | @param delegate delegate 88 | @param incatorType 指示器类型 89 | @return FSSegmentTitleView 90 | */ 91 | - (instancetype)initWithFrame:(CGRect)frame titles:(NSArray *)titlesArr delegate:(id)delegate indicatorType:(FSIndicatorType)incatorType; 92 | ``` 93 | * FSSegmentTitleView属性修改 94 | 95 | ~~/** 96 | 标题数组,必须传值 97 | */ 98 | @property (nonatomic, strong) NSArray *titlesArr;~~**废弃/DEPRECATED_1.0.1** 99 | ``` 100 | 101 | /** 102 | 标题文字间距,默认20 103 | */ 104 | @property (nonatomic, assign) CGFloat itemMargin; 105 | 106 | /** 107 | 当前选中标题索引,默认0 108 | */ 109 | @property (nonatomic, assign) NSInteger selectIndex; 110 | 111 | /** 112 | 标题字体大小,默认15 113 | */ 114 | @property (nonatomic, strong) UIFont *titleFont; 115 | 116 | /** 117 | 标题正常颜色,默认black 118 | */ 119 | @property (nonatomic, strong) UIColor *titleNormalColor; 120 | 121 | /** 122 | 标题选中颜色,默认red 123 | */ 124 | @property (nonatomic, strong) UIColor *titleSelectColor; 125 | 126 | /** 127 | 指示器颜色,默认与titleSelectColor一样,在FSIndicatorTypeNone下无效 128 | */ 129 | @property (nonatomic, strong) UIColor *indicatorColor; 130 | 131 | /** 132 | 在FSIndicatorTypeCustom时可自定义此属性,为指示器一端延伸长度,默认5 133 | */ 134 | @property (nonatomic, assign) CGFloat indicatorExtension; 135 | ``` 136 | * FSSegmentTitleView代理方法 137 | ``` 138 | /** 139 | 切换标题 140 | 141 | @param titleView FSSegmentTitleView 142 | @param startIndex 切换前标题索引 143 | @param endIndex 切换后标题索引 144 | */ 145 | - (void)FSSegmentTitleView:(FSSegmentTitleView *)titleView startIndex:(NSInteger)startIndex endIndex:(NSInteger)endIndex; 146 | ``` 147 | * FSSegmentTitleView枚举类型 148 | ``` 149 | typedef enum : NSUInteger { 150 | FSIndicatorTypeDefault,//默认与按钮长度相同 151 | FSIndicatorTypeEqualTitle,//与文字长度相同 152 | FSIndicatorTypeCustom,//自定义文字边缘延伸宽度 153 | FSIndicatorTypeNone, 154 | } FSIndicatorType;//指示器类型枚举 155 | ``` 156 | ## For example 157 | 158 | 详细使用可以查看demo 159 | ``` 160 | self.titleView = [[FSSegmentTitleView alloc]initWithFrame:CGRectMake(0, 64, CGRectGetWidth(self.view.bounds), 50) delegate:self indicatorType:0]; 161 | self.titleView.titlesArr = @[@"全部",@"服饰穿搭",@"生活百货",@"美食吃货",@"美容护理",@"母婴儿童",@"数码家电",@"其他"]; 162 | [self.view addSubview:_titleView]; 163 | 164 | NSMutableArray *childVCs = [[NSMutableArray alloc]init]; 165 | for (NSString *title in self.titleView.titlesArr) { 166 | ChildViewController *vc = [[ChildViewController alloc]init]; 167 | vc.title = title; 168 | [childVCs addObject:vc]; 169 | } 170 | self.pageContentView = [[FSPageContentView alloc]initWithFrame:CGRectMake(0, 114, CGRectGetWidth(self.view.bounds), CGRectGetHeight(self.view.bounds) - 90) childVCs:childVCs parentVC:self delegate:self]; 171 | [self.view addSubview:_pageContentView]; 172 | 173 | - (void)FSSegmentTitleView:(FSSegmentTitleView *)titleView startIndex:(NSInteger)startIndex endIndex:(NSInteger)endIndex 174 | { 175 | self.pageContentView.contentViewCurrentIndex = endIndex; 176 | } 177 | 178 | - (void)FSContenViewDidEndDecelerating:(FSPageContentView *)contentView startIndex:(NSInteger)startIndex endIndex:(NSInteger)endIndex 179 | { 180 | self.titleView.selectIndex = endIndex; 181 | } 182 | ``` 183 | ## 版本 184 | * 2017.4.28 ——> **1.0**初始版本 185 | * 2017.5.7 ——> **1.0.1**修改初始化方法,添加了标题选中自定义文字大小类型 186 | ## 后续 187 | 因为最近在重新整理整个项目,准备剔除之前项目的混乱代码,复杂的业务逻辑,将会不定期封装一些比较实用的小框架,目前上传的FSxxdemo都是我在重构项目过程中写的一些封装库,算是较为实用并且稳定的框架类,主要目的也是为了整理记录下来方便以后使用,这个滑动框架暂时样式较少,但是已经能够满足日常开发所用,后期我会抽时间增加更多的支持类型,比如放大选中的标题文字,增加图片类型等。每次更新都将在这里做备忘记录。———— 2017.5.4 188 | 189 | 修改初始化方法,添加了标题选中自定义文字大小类型 ———— 2017.5.7 190 | 191 | 修复iOS7下contentView无法加载的Bug,添加contentViewCanScroll属性可手动控制contentView能否滑动 ———— 2017.5.17 192 | 193 | 修复若干bug,添加cocoapods支持 ———— 2017.6.1 194 | 195 | ![](https://github.com/shunFSKi/ImageResources/blob/master/qrcode_for_gh_e49d866d2f7a_258.jpg) 196 | --------------------------------------------------------------------------------