├── .gitignore ├── LICENSE ├── SMPagerTab.podspec ├── SMPagerTab.xcodeproj ├── project.pbxproj └── project.xcworkspace │ └── contents.xcworkspacedata ├── SMPagerTab ├── AppDelegate.h ├── AppDelegate.m ├── Base.lproj │ ├── LaunchScreen.xib │ └── Main.storyboard ├── Images.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── Info.plist ├── SMPagerTabView │ ├── SMPagerTabView.h │ ├── SMPagerTabView.m │ ├── UIViewAdditions.h │ └── UIViewAdditions.m ├── SMTopWindow.h ├── SMTopWindow.m ├── SMWebViewController.h ├── SMWebViewController.m ├── ViewController.h ├── ViewController.m └── main.m ├── SMPagerTabTests ├── Info.plist └── SMPagerTabTests.m └── readme.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | build/ 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | xcuserdata 13 | *.xccheckout 14 | *.moved-aside 15 | DerivedData 16 | *.hmap 17 | *.ipa 18 | *.xcuserstate 19 | 20 | # CocoaPods 21 | # 22 | # We recommend against adding the Pods directory to your .gitignore. However 23 | # you should judge for yourself, the pros and cons are mentioned at: 24 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control 25 | # 26 | #Pods/ 27 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 戴铭 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 | 23 | -------------------------------------------------------------------------------- /SMPagerTab.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = "SMPagerTab" 3 | s.version = "0.0.1" 4 | s.homepage = "https://github.com/ming1016/PagerTab" 5 | s.license = "MIT" 6 | s.author = { "ming1016" => "ming1016@foxmail.com" } 7 | s.source = { :git => "https://github.com/ming1016/PagerTab.git" :tag => s.version.to_s } 8 | s.source_files = 'SMPagerTab/SMPagerTabView/**/*.{h,m}' 9 | s.dependency 'Masonry', '~> 0.6.2' 10 | end 11 | -------------------------------------------------------------------------------- /SMPagerTab.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 3A8602521B47EA1100A423B7 /* UIViewAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A8602511B47EA1100A423B7 /* UIViewAdditions.m */; }; 11 | 3A8602551B480A8100A423B7 /* SMWebViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A8602541B480A8100A423B7 /* SMWebViewController.m */; }; 12 | 3AB014651B47E39E00F80FF7 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 3AB014641B47E39E00F80FF7 /* main.m */; }; 13 | 3AB014681B47E39E00F80FF7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 3AB014671B47E39E00F80FF7 /* AppDelegate.m */; }; 14 | 3AB0146B1B47E39E00F80FF7 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3AB0146A1B47E39E00F80FF7 /* ViewController.m */; }; 15 | 3AB0146E1B47E39E00F80FF7 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 3AB0146C1B47E39E00F80FF7 /* Main.storyboard */; }; 16 | 3AB014701B47E39E00F80FF7 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 3AB0146F1B47E39E00F80FF7 /* Images.xcassets */; }; 17 | 3AB014731B47E39E00F80FF7 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 3AB014711B47E39E00F80FF7 /* LaunchScreen.xib */; }; 18 | 3AB0147F1B47E39E00F80FF7 /* SMPagerTabTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 3AB0147E1B47E39E00F80FF7 /* SMPagerTabTests.m */; }; 19 | 3AB014921B47E59D00F80FF7 /* SMPagerTabView.m in Sources */ = {isa = PBXBuildFile; fileRef = 3AB014911B47E59D00F80FF7 /* SMPagerTabView.m */; }; 20 | 3E1098931B9BEFD400E5A27C /* SMTopWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = 3E1098921B9BEFD400E5A27C /* SMTopWindow.m */; }; 21 | /* End PBXBuildFile section */ 22 | 23 | /* Begin PBXContainerItemProxy section */ 24 | 3AB014791B47E39E00F80FF7 /* PBXContainerItemProxy */ = { 25 | isa = PBXContainerItemProxy; 26 | containerPortal = 3AB014571B47E39E00F80FF7 /* Project object */; 27 | proxyType = 1; 28 | remoteGlobalIDString = 3AB0145E1B47E39E00F80FF7; 29 | remoteInfo = SMPagerTab; 30 | }; 31 | /* End PBXContainerItemProxy section */ 32 | 33 | /* Begin PBXFileReference section */ 34 | 3A8602501B47EA1100A423B7 /* UIViewAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UIViewAdditions.h; sourceTree = ""; }; 35 | 3A8602511B47EA1100A423B7 /* UIViewAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UIViewAdditions.m; sourceTree = ""; }; 36 | 3A8602531B480A8100A423B7 /* SMWebViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SMWebViewController.h; sourceTree = ""; }; 37 | 3A8602541B480A8100A423B7 /* SMWebViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SMWebViewController.m; sourceTree = ""; }; 38 | 3AB0145F1B47E39E00F80FF7 /* SMPagerTab.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SMPagerTab.app; sourceTree = BUILT_PRODUCTS_DIR; }; 39 | 3AB014631B47E39E00F80FF7 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 40 | 3AB014641B47E39E00F80FF7 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 41 | 3AB014661B47E39E00F80FF7 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 42 | 3AB014671B47E39E00F80FF7 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 43 | 3AB014691B47E39E00F80FF7 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 44 | 3AB0146A1B47E39E00F80FF7 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 45 | 3AB0146D1B47E39E00F80FF7 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 46 | 3AB0146F1B47E39E00F80FF7 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 47 | 3AB014721B47E39E00F80FF7 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; 48 | 3AB014781B47E39E00F80FF7 /* SMPagerTabTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SMPagerTabTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 49 | 3AB0147D1B47E39E00F80FF7 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 50 | 3AB0147E1B47E39E00F80FF7 /* SMPagerTabTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SMPagerTabTests.m; sourceTree = ""; }; 51 | 3AB014901B47E59D00F80FF7 /* SMPagerTabView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SMPagerTabView.h; sourceTree = ""; }; 52 | 3AB014911B47E59D00F80FF7 /* SMPagerTabView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SMPagerTabView.m; sourceTree = ""; }; 53 | 3E1098911B9BEFD400E5A27C /* SMTopWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SMTopWindow.h; sourceTree = ""; }; 54 | 3E1098921B9BEFD400E5A27C /* SMTopWindow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SMTopWindow.m; sourceTree = ""; }; 55 | /* End PBXFileReference section */ 56 | 57 | /* Begin PBXFrameworksBuildPhase section */ 58 | 3AB0145C1B47E39E00F80FF7 /* Frameworks */ = { 59 | isa = PBXFrameworksBuildPhase; 60 | buildActionMask = 2147483647; 61 | files = ( 62 | ); 63 | runOnlyForDeploymentPostprocessing = 0; 64 | }; 65 | 3AB014751B47E39E00F80FF7 /* Frameworks */ = { 66 | isa = PBXFrameworksBuildPhase; 67 | buildActionMask = 2147483647; 68 | files = ( 69 | ); 70 | runOnlyForDeploymentPostprocessing = 0; 71 | }; 72 | /* End PBXFrameworksBuildPhase section */ 73 | 74 | /* Begin PBXGroup section */ 75 | 3AB014561B47E39E00F80FF7 = { 76 | isa = PBXGroup; 77 | children = ( 78 | 3AB014611B47E39E00F80FF7 /* SMPagerTab */, 79 | 3AB0147B1B47E39E00F80FF7 /* SMPagerTabTests */, 80 | 3AB014601B47E39E00F80FF7 /* Products */, 81 | ); 82 | sourceTree = ""; 83 | }; 84 | 3AB014601B47E39E00F80FF7 /* Products */ = { 85 | isa = PBXGroup; 86 | children = ( 87 | 3AB0145F1B47E39E00F80FF7 /* SMPagerTab.app */, 88 | 3AB014781B47E39E00F80FF7 /* SMPagerTabTests.xctest */, 89 | ); 90 | name = Products; 91 | sourceTree = ""; 92 | }; 93 | 3AB014611B47E39E00F80FF7 /* SMPagerTab */ = { 94 | isa = PBXGroup; 95 | children = ( 96 | 3AB0148F1B47E56400F80FF7 /* SMPagerTabView */, 97 | 3AB014691B47E39E00F80FF7 /* ViewController.h */, 98 | 3AB0146A1B47E39E00F80FF7 /* ViewController.m */, 99 | 3A8602531B480A8100A423B7 /* SMWebViewController.h */, 100 | 3A8602541B480A8100A423B7 /* SMWebViewController.m */, 101 | 3E1098901B9BEFC200E5A27C /* Helper */, 102 | 3AB0146C1B47E39E00F80FF7 /* Main.storyboard */, 103 | 3AB0146F1B47E39E00F80FF7 /* Images.xcassets */, 104 | 3AB014711B47E39E00F80FF7 /* LaunchScreen.xib */, 105 | 3AB014621B47E39E00F80FF7 /* Supporting Files */, 106 | ); 107 | path = SMPagerTab; 108 | sourceTree = ""; 109 | }; 110 | 3AB014621B47E39E00F80FF7 /* Supporting Files */ = { 111 | isa = PBXGroup; 112 | children = ( 113 | 3AB014661B47E39E00F80FF7 /* AppDelegate.h */, 114 | 3AB014671B47E39E00F80FF7 /* AppDelegate.m */, 115 | 3AB014631B47E39E00F80FF7 /* Info.plist */, 116 | 3AB014641B47E39E00F80FF7 /* main.m */, 117 | ); 118 | name = "Supporting Files"; 119 | sourceTree = ""; 120 | }; 121 | 3AB0147B1B47E39E00F80FF7 /* SMPagerTabTests */ = { 122 | isa = PBXGroup; 123 | children = ( 124 | 3AB0147E1B47E39E00F80FF7 /* SMPagerTabTests.m */, 125 | 3AB0147C1B47E39E00F80FF7 /* Supporting Files */, 126 | ); 127 | path = SMPagerTabTests; 128 | sourceTree = ""; 129 | }; 130 | 3AB0147C1B47E39E00F80FF7 /* Supporting Files */ = { 131 | isa = PBXGroup; 132 | children = ( 133 | 3AB0147D1B47E39E00F80FF7 /* Info.plist */, 134 | ); 135 | name = "Supporting Files"; 136 | sourceTree = ""; 137 | }; 138 | 3AB0148F1B47E56400F80FF7 /* SMPagerTabView */ = { 139 | isa = PBXGroup; 140 | children = ( 141 | 3A8602501B47EA1100A423B7 /* UIViewAdditions.h */, 142 | 3A8602511B47EA1100A423B7 /* UIViewAdditions.m */, 143 | 3AB014901B47E59D00F80FF7 /* SMPagerTabView.h */, 144 | 3AB014911B47E59D00F80FF7 /* SMPagerTabView.m */, 145 | ); 146 | path = SMPagerTabView; 147 | sourceTree = ""; 148 | }; 149 | 3E1098901B9BEFC200E5A27C /* Helper */ = { 150 | isa = PBXGroup; 151 | children = ( 152 | 3E1098911B9BEFD400E5A27C /* SMTopWindow.h */, 153 | 3E1098921B9BEFD400E5A27C /* SMTopWindow.m */, 154 | ); 155 | name = Helper; 156 | sourceTree = ""; 157 | }; 158 | /* End PBXGroup section */ 159 | 160 | /* Begin PBXNativeTarget section */ 161 | 3AB0145E1B47E39E00F80FF7 /* SMPagerTab */ = { 162 | isa = PBXNativeTarget; 163 | buildConfigurationList = 3AB014821B47E39E00F80FF7 /* Build configuration list for PBXNativeTarget "SMPagerTab" */; 164 | buildPhases = ( 165 | 3AB0145B1B47E39E00F80FF7 /* Sources */, 166 | 3AB0145C1B47E39E00F80FF7 /* Frameworks */, 167 | 3AB0145D1B47E39E00F80FF7 /* Resources */, 168 | ); 169 | buildRules = ( 170 | ); 171 | dependencies = ( 172 | ); 173 | name = SMPagerTab; 174 | productName = SMPagerTab; 175 | productReference = 3AB0145F1B47E39E00F80FF7 /* SMPagerTab.app */; 176 | productType = "com.apple.product-type.application"; 177 | }; 178 | 3AB014771B47E39E00F80FF7 /* SMPagerTabTests */ = { 179 | isa = PBXNativeTarget; 180 | buildConfigurationList = 3AB014851B47E39E00F80FF7 /* Build configuration list for PBXNativeTarget "SMPagerTabTests" */; 181 | buildPhases = ( 182 | 3AB014741B47E39E00F80FF7 /* Sources */, 183 | 3AB014751B47E39E00F80FF7 /* Frameworks */, 184 | 3AB014761B47E39E00F80FF7 /* Resources */, 185 | ); 186 | buildRules = ( 187 | ); 188 | dependencies = ( 189 | 3AB0147A1B47E39E00F80FF7 /* PBXTargetDependency */, 190 | ); 191 | name = SMPagerTabTests; 192 | productName = SMPagerTabTests; 193 | productReference = 3AB014781B47E39E00F80FF7 /* SMPagerTabTests.xctest */; 194 | productType = "com.apple.product-type.bundle.unit-test"; 195 | }; 196 | /* End PBXNativeTarget section */ 197 | 198 | /* Begin PBXProject section */ 199 | 3AB014571B47E39E00F80FF7 /* Project object */ = { 200 | isa = PBXProject; 201 | attributes = { 202 | LastUpgradeCheck = 0640; 203 | ORGANIZATIONNAME = starming; 204 | TargetAttributes = { 205 | 3AB0145E1B47E39E00F80FF7 = { 206 | CreatedOnToolsVersion = 6.4; 207 | }; 208 | 3AB014771B47E39E00F80FF7 = { 209 | CreatedOnToolsVersion = 6.4; 210 | TestTargetID = 3AB0145E1B47E39E00F80FF7; 211 | }; 212 | }; 213 | }; 214 | buildConfigurationList = 3AB0145A1B47E39E00F80FF7 /* Build configuration list for PBXProject "SMPagerTab" */; 215 | compatibilityVersion = "Xcode 3.2"; 216 | developmentRegion = English; 217 | hasScannedForEncodings = 0; 218 | knownRegions = ( 219 | en, 220 | Base, 221 | ); 222 | mainGroup = 3AB014561B47E39E00F80FF7; 223 | productRefGroup = 3AB014601B47E39E00F80FF7 /* Products */; 224 | projectDirPath = ""; 225 | projectRoot = ""; 226 | targets = ( 227 | 3AB0145E1B47E39E00F80FF7 /* SMPagerTab */, 228 | 3AB014771B47E39E00F80FF7 /* SMPagerTabTests */, 229 | ); 230 | }; 231 | /* End PBXProject section */ 232 | 233 | /* Begin PBXResourcesBuildPhase section */ 234 | 3AB0145D1B47E39E00F80FF7 /* Resources */ = { 235 | isa = PBXResourcesBuildPhase; 236 | buildActionMask = 2147483647; 237 | files = ( 238 | 3AB0146E1B47E39E00F80FF7 /* Main.storyboard in Resources */, 239 | 3AB014731B47E39E00F80FF7 /* LaunchScreen.xib in Resources */, 240 | 3AB014701B47E39E00F80FF7 /* Images.xcassets in Resources */, 241 | ); 242 | runOnlyForDeploymentPostprocessing = 0; 243 | }; 244 | 3AB014761B47E39E00F80FF7 /* Resources */ = { 245 | isa = PBXResourcesBuildPhase; 246 | buildActionMask = 2147483647; 247 | files = ( 248 | ); 249 | runOnlyForDeploymentPostprocessing = 0; 250 | }; 251 | /* End PBXResourcesBuildPhase section */ 252 | 253 | /* Begin PBXSourcesBuildPhase section */ 254 | 3AB0145B1B47E39E00F80FF7 /* Sources */ = { 255 | isa = PBXSourcesBuildPhase; 256 | buildActionMask = 2147483647; 257 | files = ( 258 | 3AB014921B47E59D00F80FF7 /* SMPagerTabView.m in Sources */, 259 | 3A8602551B480A8100A423B7 /* SMWebViewController.m in Sources */, 260 | 3A8602521B47EA1100A423B7 /* UIViewAdditions.m in Sources */, 261 | 3E1098931B9BEFD400E5A27C /* SMTopWindow.m in Sources */, 262 | 3AB0146B1B47E39E00F80FF7 /* ViewController.m in Sources */, 263 | 3AB014681B47E39E00F80FF7 /* AppDelegate.m in Sources */, 264 | 3AB014651B47E39E00F80FF7 /* main.m in Sources */, 265 | ); 266 | runOnlyForDeploymentPostprocessing = 0; 267 | }; 268 | 3AB014741B47E39E00F80FF7 /* Sources */ = { 269 | isa = PBXSourcesBuildPhase; 270 | buildActionMask = 2147483647; 271 | files = ( 272 | 3AB0147F1B47E39E00F80FF7 /* SMPagerTabTests.m in Sources */, 273 | ); 274 | runOnlyForDeploymentPostprocessing = 0; 275 | }; 276 | /* End PBXSourcesBuildPhase section */ 277 | 278 | /* Begin PBXTargetDependency section */ 279 | 3AB0147A1B47E39E00F80FF7 /* PBXTargetDependency */ = { 280 | isa = PBXTargetDependency; 281 | target = 3AB0145E1B47E39E00F80FF7 /* SMPagerTab */; 282 | targetProxy = 3AB014791B47E39E00F80FF7 /* PBXContainerItemProxy */; 283 | }; 284 | /* End PBXTargetDependency section */ 285 | 286 | /* Begin PBXVariantGroup section */ 287 | 3AB0146C1B47E39E00F80FF7 /* Main.storyboard */ = { 288 | isa = PBXVariantGroup; 289 | children = ( 290 | 3AB0146D1B47E39E00F80FF7 /* Base */, 291 | ); 292 | name = Main.storyboard; 293 | sourceTree = ""; 294 | }; 295 | 3AB014711B47E39E00F80FF7 /* LaunchScreen.xib */ = { 296 | isa = PBXVariantGroup; 297 | children = ( 298 | 3AB014721B47E39E00F80FF7 /* Base */, 299 | ); 300 | name = LaunchScreen.xib; 301 | sourceTree = ""; 302 | }; 303 | /* End PBXVariantGroup section */ 304 | 305 | /* Begin XCBuildConfiguration section */ 306 | 3AB014801B47E39E00F80FF7 /* Debug */ = { 307 | isa = XCBuildConfiguration; 308 | buildSettings = { 309 | ALWAYS_SEARCH_USER_PATHS = NO; 310 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 311 | CLANG_CXX_LIBRARY = "libc++"; 312 | CLANG_ENABLE_MODULES = YES; 313 | CLANG_ENABLE_OBJC_ARC = YES; 314 | CLANG_WARN_BOOL_CONVERSION = YES; 315 | CLANG_WARN_CONSTANT_CONVERSION = YES; 316 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 317 | CLANG_WARN_EMPTY_BODY = YES; 318 | CLANG_WARN_ENUM_CONVERSION = YES; 319 | CLANG_WARN_INT_CONVERSION = YES; 320 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 321 | CLANG_WARN_UNREACHABLE_CODE = YES; 322 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 323 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 324 | COPY_PHASE_STRIP = NO; 325 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 326 | ENABLE_STRICT_OBJC_MSGSEND = YES; 327 | GCC_C_LANGUAGE_STANDARD = gnu99; 328 | GCC_DYNAMIC_NO_PIC = NO; 329 | GCC_NO_COMMON_BLOCKS = YES; 330 | GCC_OPTIMIZATION_LEVEL = 0; 331 | GCC_PREPROCESSOR_DEFINITIONS = ( 332 | "DEBUG=1", 333 | "$(inherited)", 334 | ); 335 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 336 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 337 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 338 | GCC_WARN_UNDECLARED_SELECTOR = YES; 339 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 340 | GCC_WARN_UNUSED_FUNCTION = YES; 341 | GCC_WARN_UNUSED_VARIABLE = YES; 342 | IPHONEOS_DEPLOYMENT_TARGET = 8.4; 343 | MTL_ENABLE_DEBUG_INFO = YES; 344 | ONLY_ACTIVE_ARCH = YES; 345 | SDKROOT = iphoneos; 346 | TARGETED_DEVICE_FAMILY = "1,2"; 347 | }; 348 | name = Debug; 349 | }; 350 | 3AB014811B47E39E00F80FF7 /* Release */ = { 351 | isa = XCBuildConfiguration; 352 | buildSettings = { 353 | ALWAYS_SEARCH_USER_PATHS = NO; 354 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 355 | CLANG_CXX_LIBRARY = "libc++"; 356 | CLANG_ENABLE_MODULES = YES; 357 | CLANG_ENABLE_OBJC_ARC = YES; 358 | CLANG_WARN_BOOL_CONVERSION = YES; 359 | CLANG_WARN_CONSTANT_CONVERSION = YES; 360 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 361 | CLANG_WARN_EMPTY_BODY = YES; 362 | CLANG_WARN_ENUM_CONVERSION = YES; 363 | CLANG_WARN_INT_CONVERSION = YES; 364 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 365 | CLANG_WARN_UNREACHABLE_CODE = YES; 366 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 367 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 368 | COPY_PHASE_STRIP = NO; 369 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 370 | ENABLE_NS_ASSERTIONS = NO; 371 | ENABLE_STRICT_OBJC_MSGSEND = YES; 372 | GCC_C_LANGUAGE_STANDARD = gnu99; 373 | GCC_NO_COMMON_BLOCKS = YES; 374 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 375 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 376 | GCC_WARN_UNDECLARED_SELECTOR = YES; 377 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 378 | GCC_WARN_UNUSED_FUNCTION = YES; 379 | GCC_WARN_UNUSED_VARIABLE = YES; 380 | IPHONEOS_DEPLOYMENT_TARGET = 8.4; 381 | MTL_ENABLE_DEBUG_INFO = NO; 382 | SDKROOT = iphoneos; 383 | TARGETED_DEVICE_FAMILY = "1,2"; 384 | VALIDATE_PRODUCT = YES; 385 | }; 386 | name = Release; 387 | }; 388 | 3AB014831B47E39E00F80FF7 /* Debug */ = { 389 | isa = XCBuildConfiguration; 390 | buildSettings = { 391 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 392 | INFOPLIST_FILE = SMPagerTab/Info.plist; 393 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 394 | PRODUCT_NAME = "$(TARGET_NAME)"; 395 | }; 396 | name = Debug; 397 | }; 398 | 3AB014841B47E39E00F80FF7 /* Release */ = { 399 | isa = XCBuildConfiguration; 400 | buildSettings = { 401 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 402 | INFOPLIST_FILE = SMPagerTab/Info.plist; 403 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 404 | PRODUCT_NAME = "$(TARGET_NAME)"; 405 | }; 406 | name = Release; 407 | }; 408 | 3AB014861B47E39E00F80FF7 /* Debug */ = { 409 | isa = XCBuildConfiguration; 410 | buildSettings = { 411 | BUNDLE_LOADER = "$(TEST_HOST)"; 412 | FRAMEWORK_SEARCH_PATHS = ( 413 | "$(SDKROOT)/Developer/Library/Frameworks", 414 | "$(inherited)", 415 | ); 416 | GCC_PREPROCESSOR_DEFINITIONS = ( 417 | "DEBUG=1", 418 | "$(inherited)", 419 | ); 420 | INFOPLIST_FILE = SMPagerTabTests/Info.plist; 421 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 422 | PRODUCT_NAME = "$(TARGET_NAME)"; 423 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/SMPagerTab.app/SMPagerTab"; 424 | }; 425 | name = Debug; 426 | }; 427 | 3AB014871B47E39E00F80FF7 /* Release */ = { 428 | isa = XCBuildConfiguration; 429 | buildSettings = { 430 | BUNDLE_LOADER = "$(TEST_HOST)"; 431 | FRAMEWORK_SEARCH_PATHS = ( 432 | "$(SDKROOT)/Developer/Library/Frameworks", 433 | "$(inherited)", 434 | ); 435 | INFOPLIST_FILE = SMPagerTabTests/Info.plist; 436 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 437 | PRODUCT_NAME = "$(TARGET_NAME)"; 438 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/SMPagerTab.app/SMPagerTab"; 439 | }; 440 | name = Release; 441 | }; 442 | /* End XCBuildConfiguration section */ 443 | 444 | /* Begin XCConfigurationList section */ 445 | 3AB0145A1B47E39E00F80FF7 /* Build configuration list for PBXProject "SMPagerTab" */ = { 446 | isa = XCConfigurationList; 447 | buildConfigurations = ( 448 | 3AB014801B47E39E00F80FF7 /* Debug */, 449 | 3AB014811B47E39E00F80FF7 /* Release */, 450 | ); 451 | defaultConfigurationIsVisible = 0; 452 | defaultConfigurationName = Release; 453 | }; 454 | 3AB014821B47E39E00F80FF7 /* Build configuration list for PBXNativeTarget "SMPagerTab" */ = { 455 | isa = XCConfigurationList; 456 | buildConfigurations = ( 457 | 3AB014831B47E39E00F80FF7 /* Debug */, 458 | 3AB014841B47E39E00F80FF7 /* Release */, 459 | ); 460 | defaultConfigurationIsVisible = 0; 461 | defaultConfigurationName = Release; 462 | }; 463 | 3AB014851B47E39E00F80FF7 /* Build configuration list for PBXNativeTarget "SMPagerTabTests" */ = { 464 | isa = XCConfigurationList; 465 | buildConfigurations = ( 466 | 3AB014861B47E39E00F80FF7 /* Debug */, 467 | 3AB014871B47E39E00F80FF7 /* Release */, 468 | ); 469 | defaultConfigurationIsVisible = 0; 470 | defaultConfigurationName = Release; 471 | }; 472 | /* End XCConfigurationList section */ 473 | }; 474 | rootObject = 3AB014571B47E39E00F80FF7 /* Project object */; 475 | } 476 | -------------------------------------------------------------------------------- /SMPagerTab.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /SMPagerTab/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // SMPagerTab 4 | // 5 | // Created by ming on 15/7/4. 6 | // Copyright (c) 2015年 starming. 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 | -------------------------------------------------------------------------------- /SMPagerTab/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // SMPagerTab 4 | // 5 | // Created by ming on 15/7/4. 6 | // Copyright (c) 2015年 starming. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | #import "SMTopWindow.h" 11 | #import "ViewController.h" 12 | 13 | @interface AppDelegate () 14 | 15 | @end 16 | 17 | @implementation AppDelegate 18 | 19 | 20 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 21 | // Override point for customization after application launch. 22 | // [SMTopWindow work]; 23 | return YES; 24 | } 25 | 26 | - (void)applicationWillResignActive:(UIApplication *)application { 27 | // 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. 28 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 29 | } 30 | 31 | - (void)applicationDidEnterBackground:(UIApplication *)application { 32 | // 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. 33 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 34 | } 35 | 36 | - (void)applicationWillEnterForeground:(UIApplication *)application { 37 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 38 | } 39 | 40 | - (void)applicationDidBecomeActive:(UIApplication *)application { 41 | // 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. 42 | } 43 | 44 | - (void)applicationWillTerminate:(UIApplication *)application { 45 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 46 | } 47 | 48 | @end 49 | -------------------------------------------------------------------------------- /SMPagerTab/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 22 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /SMPagerTab/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /SMPagerTab/Images.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 | "idiom" : "ipad", 35 | "size" : "29x29", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "29x29", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "40x40", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "40x40", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "76x76", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "76x76", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } -------------------------------------------------------------------------------- /SMPagerTab/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | com.starming.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | UISupportedInterfaceOrientations~ipad 40 | 41 | UIInterfaceOrientationPortrait 42 | UIInterfaceOrientationPortraitUpsideDown 43 | UIInterfaceOrientationLandscapeLeft 44 | UIInterfaceOrientationLandscapeRight 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /SMPagerTab/SMPagerTabView/SMPagerTabView.h: -------------------------------------------------------------------------------- 1 | // 2 | // SMPagerTabView.h 3 | // SMPagerTab 4 | // 5 | // Created by ming on 15/7/4. 6 | // Copyright (c) 2015年 starming. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "UIViewAdditions.h" 11 | 12 | @protocol SMPagerTabViewDelegate; 13 | 14 | @interface SMPagerTabView : UIView 15 | 16 | @property (nonatomic, weak) id delegate; 17 | 18 | @property (nonatomic, assign) CGFloat tabFrameHeight; //头部tab高 19 | @property (nonatomic, strong) UIColor* tabBackgroundColor; //头部tab背景颜色 20 | @property (nonatomic, assign) CGFloat tabButtonFontSize; //头部tab按钮字体大小 21 | @property (nonatomic, assign) CGFloat tabMargin; //头部tab左右两端和边缘的间隔 22 | @property (nonatomic, assign) UIColor* tabButtonTitleColorForNormal; 23 | @property (nonatomic, assign) UIColor* tabButtonTitleColorForSelected; 24 | @property (nonatomic, assign) CGFloat selectedLineWidth; //下划线的宽 25 | 26 | /*! 27 | * @brief 自定义完毕后开始build UI 28 | */ 29 | - (void)buildUI; 30 | /*! 31 | * @brief 控制选中tab的button 32 | */ 33 | - (void)selectTabWithIndex:(NSUInteger)index animate:(BOOL)isAnimate; 34 | - (void)showRedDotWithIndex:(NSUInteger)index; 35 | - (void)hideRedDotWithIndex:(NSUInteger)index; 36 | @end 37 | 38 | @protocol SMPagerTabViewDelegate 39 | @required 40 | - (NSUInteger)numberOfPagers:(SMPagerTabView *)view; 41 | - (UIViewController *)pagerViewOfPagers:(SMPagerTabView *)view indexOfPagers:(NSUInteger)number; 42 | @optional 43 | /*! 44 | * @brief 切换到不同pager可执行的事件 45 | */ 46 | - (void)whenSelectOnPager:(NSUInteger)number; 47 | @end 48 | -------------------------------------------------------------------------------- /SMPagerTab/SMPagerTabView/SMPagerTabView.m: -------------------------------------------------------------------------------- 1 | // 2 | // SMPagerTabView.m 3 | // SMPagerTab 4 | // 5 | // Created by ming on 15/7/4. 6 | // Copyright (c) 2015年 starming. All rights reserved. 7 | // 8 | 9 | #import "SMPagerTabView.h" 10 | 11 | @interface SMPagerTabView() 12 | 13 | @property (nonatomic, strong) UIScrollView* bodyScrollView; 14 | @property (nonatomic, strong) NSMutableArray* viewsArray; 15 | 16 | @property (nonatomic, assign) NSUInteger continueDraggingNumber; 17 | @property (nonatomic, assign) CGFloat startOffsetX; 18 | @property (nonatomic, assign) NSUInteger currentTabSelected; 19 | 20 | @property (nonatomic, assign) BOOL isBuildUI; 21 | @property (nonatomic, assign) BOOL isUseDragging; //是否使用手拖动的,自动的就设置为NO 22 | @property (nonatomic, assign) BOOL isEndDecelerating; 23 | 24 | @property (nonatomic, strong) UIView* tabView; 25 | @property (nonatomic, strong) UIView* tabSelectedLine; 26 | @property (nonatomic, strong) NSMutableArray* tabButtons; 27 | @property (nonatomic, strong) NSMutableArray* tabRedDots; //按钮上的红点 28 | @property (nonatomic, strong) UIView* selectedLine; 29 | @property (nonatomic, assign) CGFloat selectedLineOffsetXBeforeMoving; 30 | 31 | @end 32 | 33 | @implementation SMPagerTabView 34 | 35 | - (void)buildUI { 36 | _isBuildUI = NO; 37 | _isUseDragging = NO; 38 | _isEndDecelerating = YES; 39 | _startOffsetX = 0; 40 | _continueDraggingNumber = 0; 41 | 42 | NSUInteger number = [self.delegate numberOfPagers:self]; 43 | for (int i = 0; i < number; i++) { 44 | //ScrollView部分 45 | UIViewController* vc = [self.delegate pagerViewOfPagers:self indexOfPagers:i]; 46 | [self.viewsArray addObject:vc]; 47 | [self.bodyScrollView addSubview:vc.view]; 48 | 49 | //tab上按钮 50 | UIButton* itemButton = [UIButton buttonWithType:UIButtonTypeCustom]; 51 | CGFloat itemButtonWidth = (self.width - self.tabMargin*2)/number; 52 | [itemButton setFrame:CGRectMake(self.tabMargin + itemButtonWidth*i, 0, itemButtonWidth, self.tabFrameHeight)]; 53 | [itemButton.titleLabel setBaselineAdjustment:UIBaselineAdjustmentAlignCenters]; 54 | [itemButton.titleLabel setFont:[UIFont systemFontOfSize:self.tabButtonFontSize]]; 55 | [itemButton setTitle:vc.title forState:UIControlStateNormal]; 56 | [itemButton setTitleColor:self.tabButtonTitleColorForNormal forState:UIControlStateNormal]; 57 | [itemButton setTitleColor:self.tabButtonTitleColorForSelected forState:UIControlStateSelected]; 58 | [itemButton addTarget:self action:@selector(onTabButtonSelected:) forControlEvents:UIControlEventTouchUpInside]; 59 | itemButton.tag = i; 60 | [self.tabButtons addObject:itemButton]; 61 | [self.tabView addSubview:itemButton]; 62 | 63 | //tab上的红点 64 | UIView* aRedDot = [[UIView alloc] initWithFrame:CGRectMake(itemButton.width / 2 + [self buttonTitleRealSize:itemButton].width / 2 + 3, itemButton.height / 2 - [self buttonTitleRealSize:itemButton].height / 2, 8, 8)]; 65 | aRedDot.backgroundColor = [UIColor redColor]; 66 | aRedDot.layer.cornerRadius = aRedDot.width/2.0f; 67 | aRedDot.layer.masksToBounds = YES; 68 | aRedDot.hidden = YES; 69 | [self.tabRedDots addObject:aRedDot]; 70 | [itemButton addSubview:aRedDot]; 71 | } 72 | 73 | //tabView 74 | [self.tabView setBackgroundColor:self.tabBackgroundColor]; 75 | _isBuildUI = YES; 76 | // [self setNeedsDisplay]; 77 | [self setNeedsLayout]; 78 | } 79 | - (CGSize)buttonTitleRealSize:(UIButton *)button { 80 | CGSize size = CGSizeZero; 81 | size = [button.titleLabel.text sizeWithAttributes:@{NSFontAttributeName: button.titleLabel.font}]; 82 | return size; 83 | } 84 | - (void)layoutSubviews { 85 | if (_isBuildUI) { 86 | self.bodyScrollView.contentSize = CGSizeMake(self.width * [self.viewsArray count], self.tabFrameHeight); 87 | for (int i = 0; i < [self.viewsArray count]; i++) { 88 | UIViewController* vc = self.viewsArray[i]; 89 | vc.view.frame = CGRectMake(self.bodyScrollView.width * i, self.tabFrameHeight, self.bodyScrollView.width, self.bodyScrollView.height); 90 | } 91 | } 92 | } 93 | 94 | #pragma mark - Tab 95 | - (void)onTabButtonSelected:(UIButton *)button { 96 | [self selectTabWithIndex:button.tag animate:YES]; 97 | } 98 | - (void)selectTabWithIndex:(NSUInteger)index animate:(BOOL)isAnimate { 99 | UIButton *preButton = self.tabButtons[self.currentTabSelected]; 100 | preButton.selected = NO; 101 | UIButton *currentButton = self.tabButtons[index]; 102 | currentButton.selected = YES; 103 | _currentTabSelected = index; 104 | 105 | void(^moveSelectedLine)(void) = ^(void) { 106 | self.selectedLine.center = CGPointMake(currentButton.center.x, self.selectedLine.center.y); 107 | self.selectedLineOffsetXBeforeMoving = self.selectedLine.origin.x; 108 | // self.selectedLineWidth = [self buttonTitleRealSize:currentButton].width; 109 | }; 110 | //移动select line 111 | if (isAnimate) { 112 | [UIView animateWithDuration:0.3 animations:^{ 113 | moveSelectedLine(); 114 | }]; 115 | } else { 116 | moveSelectedLine(); 117 | } 118 | [self switchWithIndex:index animate:isAnimate]; 119 | if ([self.delegate respondsToSelector:@selector(whenSelectOnPager:)]) { 120 | [self.delegate whenSelectOnPager:index]; 121 | } 122 | [self hideRedDotWithIndex:index]; 123 | } 124 | 125 | /*! 126 | * @brief Selected Line跟随移动 127 | */ 128 | - (void)moveSelectedLineByScrollWithOffsetX:(CGFloat)offsetX { 129 | CGFloat textGap = (self.width - self.tabMargin * 2 - self.selectedLine.width * self.tabButtons.count) / (self.tabButtons.count * 2); 130 | CGFloat speed = 50; 131 | //移动的距离 132 | CGFloat movedFloat = self.selectedLineOffsetXBeforeMoving + (offsetX * (textGap + self.selectedLine.width + speed)) / [UIScreen mainScreen].bounds.size.width; 133 | //最大右移值 134 | CGFloat selectedLineRightBarrier = _selectedLineOffsetXBeforeMoving + textGap * 2 + self.selectedLine.width; 135 | //最大左移值 136 | CGFloat selectedLineLeftBarrier = _selectedLineOffsetXBeforeMoving - textGap * 2 - self.selectedLine.width; 137 | CGFloat selectedLineNewX = 0; 138 | 139 | //连续拖动时的处理 140 | BOOL isContinueDragging = NO; 141 | if (_continueDraggingNumber > 1) { 142 | isContinueDragging = YES; 143 | } 144 | 145 | if (movedFloat > selectedLineRightBarrier && !isContinueDragging) { 146 | //右慢拖动设置拦截 147 | selectedLineNewX = selectedLineRightBarrier; 148 | } else if (movedFloat < selectedLineLeftBarrier && !isContinueDragging) { 149 | //左慢拖动设置的拦截 150 | selectedLineNewX = selectedLineLeftBarrier; 151 | } else { 152 | //连续拖动可能超过总长的情况需要拦截 153 | if (isContinueDragging) { 154 | if (movedFloat > self.width - (self.tabMargin + textGap + self.selectedLine.width)) { 155 | selectedLineNewX = self.width - (self.tabMargin + textGap + self.selectedLine.width); 156 | } else if (movedFloat < self.tabMargin + textGap) { 157 | selectedLineNewX = self.tabMargin + textGap; 158 | } else { 159 | selectedLineNewX = movedFloat; 160 | } 161 | } else { 162 | //无拦截移动 163 | selectedLineNewX = movedFloat; 164 | } 165 | } 166 | [self.selectedLine setFrame:CGRectMake(selectedLineNewX, self.selectedLine.frame.origin.y, self.selectedLine.frame.size.width, self.selectedLine.frame.size.height)]; 167 | 168 | } 169 | /*! 170 | * @brief 红点 171 | */ 172 | - (void)showRedDotWithIndex:(NSUInteger)index { 173 | UIView* redDot = self.tabRedDots[index]; 174 | redDot.hidden = NO; 175 | } 176 | - (void)hideRedDotWithIndex:(NSUInteger)index { 177 | UIView* redDot = self.tabRedDots[index]; 178 | redDot.hidden = YES; 179 | } 180 | 181 | #pragma mark - BodyScrollView 182 | - (void)switchWithIndex:(NSUInteger)index animate:(BOOL)isAnimate { 183 | [self.bodyScrollView setContentOffset:CGPointMake(index*self.width, 0) animated:isAnimate]; 184 | _isUseDragging = NO; 185 | } 186 | 187 | #pragma mark - ScrollView Delegate 188 | - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView { 189 | if (scrollView == self.bodyScrollView) { 190 | _continueDraggingNumber += 1; 191 | if (_isEndDecelerating) { 192 | _startOffsetX = scrollView.contentOffset.x; 193 | } 194 | _isUseDragging = YES; 195 | _isEndDecelerating = NO; 196 | } 197 | } 198 | /*! 199 | * @brief 对拖动过程中的处理 200 | */ 201 | - (void)scrollViewDidScroll:(UIScrollView *)scrollView { 202 | if (scrollView == self.bodyScrollView) { 203 | CGFloat movingOffsetX = scrollView.contentOffset.x - _startOffsetX; 204 | if (_isUseDragging) { 205 | //tab处理事件待完成 206 | [self moveSelectedLineByScrollWithOffsetX:movingOffsetX]; 207 | } 208 | } 209 | } 210 | /*! 211 | * @brief 手释放后pager归位后的处理 212 | */ 213 | - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { 214 | if (scrollView == self.bodyScrollView) { 215 | [self selectTabWithIndex:(int)scrollView.contentOffset.x/self.bounds.size.width animate:YES]; 216 | _isUseDragging = YES; 217 | _isEndDecelerating = YES; 218 | _continueDraggingNumber = 0; 219 | } 220 | } 221 | /*! 222 | * @brief 自动停止 223 | */ 224 | - (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView { 225 | if (scrollView == self.bodyScrollView) { 226 | //tab处理事件待完成 227 | [self selectTabWithIndex:(int)scrollView.contentOffset.x/self.bounds.size.width animate:YES]; 228 | } 229 | } 230 | 231 | 232 | 233 | #pragma mark - Setter/Getter 234 | /*! 235 | * @brief 头部tab 236 | */ 237 | - (UIView *)tabView { 238 | if (!_tabView) { 239 | self.tabView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, self.width, _tabFrameHeight)]; 240 | [self addSubview:_tabView]; 241 | } 242 | return _tabView; 243 | } 244 | - (NSMutableArray *)tabButtons { 245 | if (!_tabButtons) { 246 | self.tabButtons = [[NSMutableArray alloc] init]; 247 | } 248 | return _tabButtons; 249 | } 250 | - (NSMutableArray *)tabRedDots { 251 | if (!_tabRedDots) { 252 | self.tabRedDots = [[NSMutableArray alloc] init]; 253 | } 254 | return _tabRedDots; 255 | } 256 | - (CGFloat)tabFrameHeight { 257 | if (!_tabFrameHeight) { 258 | self.tabFrameHeight = 40; 259 | } 260 | return _tabFrameHeight; 261 | } 262 | - (CGFloat)tabMargin { 263 | if (!_tabMargin) { 264 | self.tabMargin = 38; 265 | } 266 | return _tabMargin; 267 | } 268 | - (NSUInteger)currentTabSelected { 269 | if (!_currentTabSelected) { 270 | self.currentTabSelected = 0; 271 | } 272 | return _currentTabSelected; 273 | } 274 | - (UIColor *)tabBackgroundColor { 275 | if (!_tabBackgroundColor) { 276 | self.tabBackgroundColor = [UIColor whiteColor]; 277 | } 278 | return _tabBackgroundColor; 279 | } 280 | - (CGFloat)tabButtonFontSize { 281 | if (!_tabButtonFontSize) { 282 | self.tabButtonFontSize = 14; 283 | } 284 | return _tabButtonFontSize; 285 | } 286 | - (UIColor *)tabButtonTitleColorForNormal { 287 | if (!_tabButtonTitleColorForNormal) { 288 | self.tabButtonTitleColorForNormal = [UIColor blackColor]; 289 | } 290 | return _tabButtonTitleColorForNormal; 291 | } 292 | - (UIColor *)tabButtonTitleColorForSelected { 293 | if (!_tabButtonTitleColorForSelected) { 294 | self.tabButtonTitleColorForSelected = [UIColor redColor]; 295 | } 296 | return _tabButtonTitleColorForSelected; 297 | } 298 | - (UIView *)selectedLine { 299 | if (!_selectedLine) { 300 | self.selectedLine = [[UIView alloc] initWithFrame:CGRectMake(0, self.tabView.height - 2, self.selectedLineWidth, 2)]; 301 | _selectedLine.backgroundColor = [UIColor redColor]; 302 | [self addSubview:_selectedLine]; 303 | } 304 | return _selectedLine; 305 | } 306 | - (CGFloat)selectedLineWidth { 307 | if (!_selectedLineWidth) { 308 | self.selectedLineWidth = 42; 309 | } 310 | return _selectedLineWidth; 311 | } 312 | - (CGFloat)selectedLineOffsetXBeforeMoving { 313 | if (!_selectedLineOffsetXBeforeMoving) { 314 | self.selectedLineOffsetXBeforeMoving = 0; 315 | } 316 | return _selectedLineOffsetXBeforeMoving; 317 | } 318 | 319 | 320 | /*! 321 | * @brief 滑动pager主体 322 | */ 323 | - (UIScrollView*)bodyScrollView { 324 | if (!_bodyScrollView) { 325 | self.bodyScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, _tabFrameHeight, self.width, self.height - _tabFrameHeight)]; 326 | _bodyScrollView.delegate = self; 327 | _bodyScrollView.pagingEnabled = YES; 328 | _bodyScrollView.userInteractionEnabled = YES; 329 | _bodyScrollView.bounces = NO; 330 | _bodyScrollView.showsHorizontalScrollIndicator = NO; 331 | _bodyScrollView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleWidth; 332 | [self addSubview:_bodyScrollView]; 333 | } 334 | return _bodyScrollView; 335 | } 336 | - (NSMutableArray *)viewsArray { 337 | if (!_viewsArray) { 338 | self.viewsArray = [[NSMutableArray alloc] init]; 339 | } 340 | return _viewsArray; 341 | } 342 | 343 | 344 | @end 345 | -------------------------------------------------------------------------------- /SMPagerTab/SMPagerTabView/UIViewAdditions.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | @interface UIView (TTCategory) 5 | 6 | @property(nonatomic) CGFloat left; 7 | @property(nonatomic) CGFloat top; 8 | @property(nonatomic) CGFloat right; 9 | @property(nonatomic) CGFloat bottom; 10 | 11 | @property(nonatomic) CGFloat width; 12 | @property(nonatomic) CGFloat height; 13 | 14 | @property(nonatomic) CGFloat centerX; 15 | @property(nonatomic) CGFloat centerY; 16 | 17 | @property(nonatomic,readonly) CGFloat screenX; 18 | @property(nonatomic,readonly) CGFloat screenY; 19 | @property(nonatomic,readonly) CGFloat screenViewX; 20 | @property(nonatomic,readonly) CGFloat screenViewY; 21 | @property(nonatomic,readonly) CGRect screenFrame; 22 | 23 | @property(nonatomic) CGPoint origin; 24 | @property(nonatomic) CGSize size; 25 | 26 | @property(nonatomic) BOOL visible; 27 | 28 | /** 29 | * Finds the first descendant view (including this view) that is a member of a particular class. 30 | */ 31 | - (UIView*)descendantOrSelfWithClass:(Class)cls; 32 | 33 | /** 34 | * Finds the first ancestor view (including this view) that is a member of a particular class. 35 | */ 36 | - (UIView*)ancestorOrSelfWithClass:(Class)cls; 37 | 38 | /** 39 | * Removes all subviews. 40 | */ 41 | - (void)removeAllSubviews; 42 | 43 | 44 | /** 45 | * Calculates the offset of this view from another view in screen coordinates. 46 | */ 47 | - (CGPoint)offsetFromView:(UIView*)otherView; 48 | 49 | 50 | /** 51 | * The view controller whose view contains this view. 52 | */ 53 | - (UIViewController*)viewController; 54 | 55 | 56 | - (void)addSubviews:(NSArray *)views; 57 | 58 | @end 59 | -------------------------------------------------------------------------------- /SMPagerTab/SMPagerTabView/UIViewAdditions.m: -------------------------------------------------------------------------------- 1 | #import "UIViewAdditions.h" 2 | 3 | 4 | @implementation UIView (TTCategory) 5 | 6 | - (BOOL)visible{ 7 | return !self.hidden; 8 | } 9 | 10 | - (void)setVisible:(BOOL)visible{ 11 | self.hidden = !visible; 12 | } 13 | 14 | - (CGFloat)left { 15 | return self.frame.origin.x; 16 | } 17 | 18 | - (void)setLeft:(CGFloat)x { 19 | CGRect frame = self.frame; 20 | frame.origin.x = x; 21 | self.frame = frame; 22 | } 23 | 24 | - (CGFloat)top { 25 | return self.frame.origin.y; 26 | } 27 | 28 | - (void)setTop:(CGFloat)y { 29 | CGRect frame = self.frame; 30 | frame.origin.y = y; 31 | self.frame = frame; 32 | } 33 | 34 | - (CGFloat)right { 35 | return self.frame.origin.x + self.frame.size.width; 36 | } 37 | 38 | - (void)setRight:(CGFloat)right { 39 | CGRect frame = self.frame; 40 | frame.origin.x = right - frame.size.width; 41 | self.frame = frame; 42 | } 43 | 44 | - (CGFloat)bottom { 45 | return self.frame.origin.y + self.frame.size.height; 46 | } 47 | 48 | - (void)setBottom:(CGFloat)bottom { 49 | CGRect frame = self.frame; 50 | frame.origin.y = bottom - frame.size.height; 51 | self.frame = frame; 52 | } 53 | 54 | - (CGFloat)centerX { 55 | return self.center.x; 56 | } 57 | 58 | - (void)setCenterX:(CGFloat)centerX { 59 | self.center = CGPointMake(centerX, self.center.y); 60 | } 61 | 62 | - (CGFloat)centerY { 63 | return self.center.y; 64 | } 65 | 66 | - (void)setCenterY:(CGFloat)centerY { 67 | self.center = CGPointMake(self.center.x, centerY); 68 | } 69 | 70 | - (CGFloat)width { 71 | return self.frame.size.width; 72 | } 73 | 74 | - (void)setWidth:(CGFloat)width { 75 | CGRect frame = self.frame; 76 | frame.size.width = width; 77 | self.frame = frame; 78 | } 79 | 80 | - (CGFloat)height { 81 | return self.frame.size.height; 82 | } 83 | 84 | - (void)setHeight:(CGFloat)height { 85 | CGRect frame = self.frame; 86 | frame.size.height = height; 87 | self.frame = frame; 88 | } 89 | 90 | - (CGFloat)screenX { 91 | CGFloat x = 0; 92 | for (UIView* view = self; view; view = view.superview) { 93 | x += view.left; 94 | } 95 | return x; 96 | } 97 | 98 | - (CGFloat)screenY { 99 | CGFloat y = 0; 100 | for (UIView* view = self; view; view = view.superview) { 101 | y += view.top; 102 | } 103 | return y; 104 | } 105 | 106 | - (CGFloat)screenViewX { 107 | CGFloat x = 0; 108 | for (UIView* view = self; view; view = view.superview) { 109 | x += view.left; 110 | 111 | if ([view isKindOfClass:[UIScrollView class]]) { 112 | UIScrollView* scrollView = (UIScrollView*)view; 113 | x -= scrollView.contentOffset.x; 114 | } 115 | } 116 | 117 | return x; 118 | } 119 | 120 | - (CGFloat)screenViewY { 121 | CGFloat y = 0; 122 | for (UIView* view = self; view; view = view.superview) { 123 | y += view.top; 124 | 125 | if ([view isKindOfClass:[UIScrollView class]]) { 126 | UIScrollView* scrollView = (UIScrollView*)view; 127 | y -= scrollView.contentOffset.y; 128 | } 129 | } 130 | return y; 131 | } 132 | 133 | - (CGRect)screenFrame { 134 | return CGRectMake(self.screenViewX, self.screenViewY, self.width, self.height); 135 | } 136 | 137 | - (CGPoint)origin { 138 | return self.frame.origin; 139 | } 140 | 141 | - (void)setOrigin:(CGPoint)origin { 142 | CGRect frame = self.frame; 143 | frame.origin = origin; 144 | self.frame = frame; 145 | } 146 | 147 | - (CGSize)size { 148 | return self.frame.size; 149 | } 150 | 151 | - (void)setSize:(CGSize)size { 152 | CGRect frame = self.frame; 153 | frame.size = size; 154 | self.frame = frame; 155 | } 156 | 157 | - (CGPoint)offsetFromView:(UIView*)otherView { 158 | CGFloat x = 0, y = 0; 159 | for (UIView* view = self; view && view != otherView; view = view.superview) { 160 | x += view.left; 161 | y += view.top; 162 | } 163 | return CGPointMake(x, y); 164 | } 165 | /* 166 | - (CGFloat)orientationWidth { 167 | return UIInterfaceOrientationIsLandscape(TTInterfaceOrientation()) 168 | ? self.height : self.width; 169 | } 170 | 171 | - (CGFloat)orientationHeight { 172 | return UIInterfaceOrientationIsLandscape(TTInterfaceOrientation()) 173 | ? self.width : self.height; 174 | } 175 | */ 176 | - (UIView*)descendantOrSelfWithClass:(Class)cls { 177 | if ([self isKindOfClass:cls]) 178 | return self; 179 | 180 | for (UIView* child in self.subviews) { 181 | UIView* it = [child descendantOrSelfWithClass:cls]; 182 | if (it) 183 | return it; 184 | } 185 | 186 | return nil; 187 | } 188 | 189 | - (UIView*)ancestorOrSelfWithClass:(Class)cls { 190 | if ([self isKindOfClass:cls]) { 191 | return self; 192 | } else if (self.superview) { 193 | return [self.superview ancestorOrSelfWithClass:cls]; 194 | } else { 195 | return nil; 196 | } 197 | } 198 | 199 | - (void)removeAllSubviews { 200 | while (self.subviews.count) { 201 | UIView* child = self.subviews.lastObject; 202 | [child removeFromSuperview]; 203 | } 204 | } 205 | 206 | 207 | 208 | - (UIViewController*)viewController { 209 | for (UIView* next = [self superview]; next; next = next.superview) { 210 | UIResponder* nextResponder = [next nextResponder]; 211 | if ([nextResponder isKindOfClass:[UIViewController class]]) { 212 | return (UIViewController*)nextResponder; 213 | } 214 | } 215 | return nil; 216 | } 217 | 218 | 219 | - (void)addSubviews:(NSArray *)views 220 | { 221 | for (UIView* v in views) { 222 | [self addSubview:v]; 223 | } 224 | } 225 | 226 | @end 227 | -------------------------------------------------------------------------------- /SMPagerTab/SMTopWindow.h: -------------------------------------------------------------------------------- 1 | // 2 | // SMTopWindow.h 3 | // WeiboOffline 4 | // 5 | // Created by DaiMing on 15/9/6. 6 | // Copyright (c) 2015年 starming. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface SMTopWindow : NSObject 12 | 13 | + (void)work; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /SMPagerTab/SMTopWindow.m: -------------------------------------------------------------------------------- 1 | // 2 | // SMTopWindow.m 3 | // WeiboOffline 4 | // 5 | // Created by DaiMing on 15/9/6. 6 | // Copyright (c) 2015年 starming. All rights reserved. 7 | // 8 | 9 | #import "SMTopWindow.h" 10 | #import 11 | 12 | @implementation SMTopWindow 13 | 14 | static UIWindow *topWinow; 15 | 16 | + (void)initialize { 17 | topWinow = [[UIWindow alloc] init]; 18 | topWinow.frame = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, 20); 19 | topWinow.windowLevel = UIWindowLevelAlert; 20 | [topWinow addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(winTap)]]; 21 | } 22 | 23 | + (void)work { 24 | topWinow.hidden = NO; 25 | } 26 | 27 | //点击时 28 | + (void)winTap { 29 | UIWindow *window = [UIApplication sharedApplication].keyWindow; 30 | [self seachScrollViewInView:window]; 31 | } 32 | 33 | //递归搜索所有view查找当前位置合适的scroll view 34 | + (void)seachScrollViewInView:(UIView *)view { 35 | for (UIScrollView *subView in view.subviews) { 36 | if ([subView isKindOfClass:[UIScrollView class]] && [self isCurrentShowView:subView]) { 37 | //开始进行滚动 38 | CGPoint offset = subView.contentOffset; 39 | offset.y = -subView.contentInset.top; 40 | [subView setContentOffset:offset animated:YES]; 41 | } 42 | //寻找子视图的子视图 43 | [self seachScrollViewInView:subView]; 44 | } 45 | } 46 | 47 | //根据位置判断是否合适 48 | + (BOOL)isCurrentShowView:(UIView *)view { 49 | UIWindow *keyWindow = [UIApplication sharedApplication].keyWindow; 50 | CGRect currentFrame = [keyWindow convertRect:view.frame fromView:view.superview]; 51 | CGRect winBounds = keyWindow.bounds; 52 | BOOL intersects = CGRectIntersectsRect(currentFrame, winBounds); 53 | return !view.isHidden && view.alpha > 0.01 && view.window == keyWindow && intersects; 54 | 55 | } 56 | @end 57 | -------------------------------------------------------------------------------- /SMPagerTab/SMWebViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // SMWebViewController.h 3 | // SMPagerTab 4 | // 5 | // Created by ming on 15/7/4. 6 | // Copyright (c) 2015年 starming. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface SMWebViewController : UIViewController 12 | 13 | @property (nonatomic, strong) NSString* webUrlString; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /SMPagerTab/SMWebViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // SMWebViewController.m 3 | // SMPagerTab 4 | // 5 | // Created by ming on 15/7/4. 6 | // Copyright (c) 2015年 starming. All rights reserved. 7 | // 8 | 9 | #import "SMWebViewController.h" 10 | 11 | @interface SMWebViewController () 12 | @property (nonatomic, strong) UIWebView* webView; 13 | @end 14 | 15 | @implementation SMWebViewController 16 | 17 | - (void)viewDidLoad { 18 | [super viewDidLoad]; 19 | 20 | } 21 | 22 | #pragma mark - setter/getter 23 | - (void)setWebUrlString:(NSString *)webUrlString { 24 | NSURLRequest* webReq = [[NSURLRequest alloc]initWithURL:[NSURL URLWithString:webUrlString]]; 25 | [self.webView loadRequest:webReq]; 26 | } 27 | 28 | - (UIWebView *)webView { 29 | if (!_webView) { 30 | self.webView = [[UIWebView alloc] initWithFrame:self.view.frame]; 31 | _webView.scalesPageToFit = YES; 32 | _webView.scrollView.directionalLockEnabled = YES; 33 | _webView.scrollView.showsHorizontalScrollIndicator = NO; 34 | [self.view addSubview:_webView]; 35 | } 36 | return _webView; 37 | } 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /SMPagerTab/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // SMPagerTab 4 | // 5 | // Created by ming on 15/7/4. 6 | // Copyright (c) 2015年 starming. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "SMPagerTabView.h" 11 | 12 | @interface ViewController : UIViewController 13 | 14 | 15 | @end 16 | 17 | -------------------------------------------------------------------------------- /SMPagerTab/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // SMPagerTab 4 | // 5 | // Created by ming on 15/7/4. 6 | // Copyright (c) 2015年 starming. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "UIViewAdditions.h" 11 | #import "SMWebViewController.h" 12 | 13 | @interface ViewController () 14 | @property (nonatomic, strong) NSMutableArray *allVC; 15 | @property (nonatomic, strong) SMPagerTabView *segmentView; 16 | @end 17 | 18 | @implementation ViewController 19 | 20 | - (void)viewDidLoad { 21 | [super viewDidLoad]; 22 | self.view.backgroundColor = [UIColor whiteColor]; 23 | _allVC = [NSMutableArray array]; 24 | SMWebViewController *one = [[SMWebViewController alloc]initWithNibName:nil bundle:nil]; 25 | one.title = @"我的"; 26 | one.webUrlString = @"https://github.com/ming1016"; 27 | [_allVC addObject:one]; 28 | 29 | SMWebViewController *two = [[SMWebViewController alloc]initWithNibName:nil bundle:nil]; 30 | two.title = @"已阅"; 31 | two.webUrlString = @"https://github.com/ming1016/RSSRead"; 32 | [_allVC addObject:two]; 33 | 34 | SMWebViewController *three = [[SMWebViewController alloc]initWithNibName:nil bundle:nil]; 35 | three.title = @"文章"; 36 | three.webUrlString = @"https://github.com/ming1016/study"; 37 | [_allVC addObject:three]; 38 | 39 | self.segmentView.delegate = self; 40 | //可自定义背景色和tab button的文字颜色等 41 | //开始构建UI 42 | [_segmentView buildUI]; 43 | //起始选择一个tab 44 | [_segmentView selectTabWithIndex:1 animate:NO]; 45 | //显示红点,点击消失 46 | [_segmentView showRedDotWithIndex:0]; 47 | } 48 | 49 | #pragma mark - DBPagerTabView Delegate 50 | - (NSUInteger)numberOfPagers:(SMPagerTabView *)view { 51 | return [_allVC count]; 52 | } 53 | - (UIViewController *)pagerViewOfPagers:(SMPagerTabView *)view indexOfPagers:(NSUInteger)number { 54 | return _allVC[number]; 55 | } 56 | 57 | - (void)whenSelectOnPager:(NSUInteger)number { 58 | NSLog(@"页面 %lu",(unsigned long)number); 59 | } 60 | 61 | #pragma mark - setter/getter 62 | - (SMPagerTabView *)segmentView { 63 | if (!_segmentView) { 64 | self.segmentView = [[SMPagerTabView alloc]initWithFrame:CGRectMake(0, 22, self.view.width, self.view.height - 22)]; 65 | [self.view addSubview:_segmentView]; 66 | } 67 | return _segmentView; 68 | } 69 | 70 | @end 71 | -------------------------------------------------------------------------------- /SMPagerTab/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // SMPagerTab 4 | // 5 | // Created by ming on 15/7/4. 6 | // Copyright (c) 2015年 starming. 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 | -------------------------------------------------------------------------------- /SMPagerTabTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | com.starming.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /SMPagerTabTests/SMPagerTabTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // SMPagerTabTests.m 3 | // SMPagerTabTests 4 | // 5 | // Created by ming on 15/7/4. 6 | // Copyright (c) 2015年 starming. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface SMPagerTabTests : XCTestCase 13 | 14 | @end 15 | 16 | @implementation SMPagerTabTests 17 | 18 | - (void)setUp { 19 | [super setUp]; 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | } 22 | 23 | - (void)tearDown { 24 | // Put teardown code here. This method is called after the invocation of each test method in the class. 25 | [super tearDown]; 26 | } 27 | 28 | - (void)testExample { 29 | // This is an example of a functional test case. 30 | XCTAssert(YES, @"Pass"); 31 | } 32 | 33 | - (void)testPerformanceExample { 34 | // This is an example of a performance test case. 35 | [self measureBlock:^{ 36 | // Put the code you want to measure the time of here. 37 | }]; 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # PagerTab 2 | 页面滑动切换tab 3 | --------------------------------------------------------------------------------