├── 1@2x.png ├── 2@2x.png ├── 3@2x.png ├── 4@2x.png ├── README.md ├── RefreshDemo.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ │ └── fcx.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcuserdata │ └── fcx.xcuserdatad │ ├── xcdebugger │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ ├── RefreshDemo.xcscheme │ └── xcschememanagement.plist ├── RefreshDemo ├── AppDelegate.h ├── AppDelegate.m ├── Base.lproj │ ├── LaunchScreen.xib │ └── Main.storyboard ├── FCXRefreshView │ ├── FCXRefreshBaseView.h │ ├── FCXRefreshBaseView.m │ ├── FCXRefreshFooterView.h │ ├── FCXRefreshFooterView.m │ ├── FCXRefreshHeaderView.h │ ├── FCXRefreshHeaderView.m │ ├── UIScrollView+FCXRefresh.h │ ├── UIScrollView+FCXRefresh.m │ ├── blueArrow.png │ └── blueArrow@2x.png ├── Images.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── Info.plist ├── RefreshViewController.h ├── RefreshViewController.m ├── ViewController.h ├── ViewController.m └── main.m └── RefreshDemoTests ├── Info.plist └── RefreshDemoTests.m /1@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fengchuanxiang/RefreshView/f786cf703c0581d676b4b95615f25e65721b5568/1@2x.png -------------------------------------------------------------------------------- /2@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fengchuanxiang/RefreshView/f786cf703c0581d676b4b95615f25e65721b5568/2@2x.png -------------------------------------------------------------------------------- /3@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fengchuanxiang/RefreshView/f786cf703c0581d676b4b95615f25e65721b5568/3@2x.png -------------------------------------------------------------------------------- /4@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fengchuanxiang/RefreshView/f786cf703c0581d676b4b95615f25e65721b5568/4@2x.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RefreshView 2 | ## 该版本已不再维护 3 | * 请使用最新地址:https://github.com/FCXPods/FCXRefresh 4 | 5 | ### 6 | ```objc 7 | 给scrollview添加上下拉刷新,只需简单的两三行代码即可 8 | ``` 9 | ![](1@2x.png) 10 | ![](2@2x.png) 11 | ![](3@2x.png) 12 | ![](4@2x.png) 13 | -------------------------------------------------------------------------------- /RefreshDemo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 1901D6D51B8C3B97004E37AB /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 1901D6D41B8C3B97004E37AB /* main.m */; }; 11 | 1901D6D81B8C3B97004E37AB /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1901D6D71B8C3B97004E37AB /* AppDelegate.m */; }; 12 | 1901D6DB1B8C3B97004E37AB /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1901D6DA1B8C3B97004E37AB /* ViewController.m */; }; 13 | 1901D6DE1B8C3B97004E37AB /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 1901D6DC1B8C3B97004E37AB /* Main.storyboard */; }; 14 | 1901D6E01B8C3B98004E37AB /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1901D6DF1B8C3B98004E37AB /* Images.xcassets */; }; 15 | 1901D6E31B8C3B98004E37AB /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 1901D6E11B8C3B98004E37AB /* LaunchScreen.xib */; }; 16 | 1901D6EF1B8C3B98004E37AB /* RefreshDemoTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 1901D6EE1B8C3B98004E37AB /* RefreshDemoTests.m */; }; 17 | 1901D7081B8C3C03004E37AB /* FCXRefreshBaseView.m in Sources */ = {isa = PBXBuildFile; fileRef = 1901D7031B8C3C03004E37AB /* FCXRefreshBaseView.m */; }; 18 | 1901D7091B8C3C03004E37AB /* FCXRefreshFooterView.m in Sources */ = {isa = PBXBuildFile; fileRef = 1901D7051B8C3C03004E37AB /* FCXRefreshFooterView.m */; }; 19 | 1901D70A1B8C3C03004E37AB /* FCXRefreshHeaderView.m in Sources */ = {isa = PBXBuildFile; fileRef = 1901D7071B8C3C03004E37AB /* FCXRefreshHeaderView.m */; }; 20 | 1901D70D1B8C3C10004E37AB /* blueArrow.png in Resources */ = {isa = PBXBuildFile; fileRef = 1901D70B1B8C3C10004E37AB /* blueArrow.png */; }; 21 | 1901D70E1B8C3C10004E37AB /* blueArrow@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 1901D70C1B8C3C10004E37AB /* blueArrow@2x.png */; }; 22 | 1901D7431B8C4B16004E37AB /* UIScrollView+FCXRefresh.m in Sources */ = {isa = PBXBuildFile; fileRef = 1901D7421B8C4B16004E37AB /* UIScrollView+FCXRefresh.m */; }; 23 | 1901D7461B8C5388004E37AB /* RefreshViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1901D7451B8C5388004E37AB /* RefreshViewController.m */; }; 24 | /* End PBXBuildFile section */ 25 | 26 | /* Begin PBXContainerItemProxy section */ 27 | 1901D6E91B8C3B98004E37AB /* PBXContainerItemProxy */ = { 28 | isa = PBXContainerItemProxy; 29 | containerPortal = 1901D6C71B8C3B97004E37AB /* Project object */; 30 | proxyType = 1; 31 | remoteGlobalIDString = 1901D6CE1B8C3B97004E37AB; 32 | remoteInfo = RefreshDemo; 33 | }; 34 | /* End PBXContainerItemProxy section */ 35 | 36 | /* Begin PBXFileReference section */ 37 | 1901D6CF1B8C3B97004E37AB /* RefreshDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = RefreshDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 38 | 1901D6D31B8C3B97004E37AB /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 39 | 1901D6D41B8C3B97004E37AB /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 40 | 1901D6D61B8C3B97004E37AB /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 41 | 1901D6D71B8C3B97004E37AB /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 42 | 1901D6D91B8C3B97004E37AB /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 43 | 1901D6DA1B8C3B97004E37AB /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 44 | 1901D6DD1B8C3B97004E37AB /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 45 | 1901D6DF1B8C3B98004E37AB /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 46 | 1901D6E21B8C3B98004E37AB /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; 47 | 1901D6E81B8C3B98004E37AB /* RefreshDemoTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RefreshDemoTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 48 | 1901D6ED1B8C3B98004E37AB /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 49 | 1901D6EE1B8C3B98004E37AB /* RefreshDemoTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RefreshDemoTests.m; sourceTree = ""; }; 50 | 1901D7021B8C3C03004E37AB /* FCXRefreshBaseView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FCXRefreshBaseView.h; sourceTree = ""; }; 51 | 1901D7031B8C3C03004E37AB /* FCXRefreshBaseView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FCXRefreshBaseView.m; sourceTree = ""; }; 52 | 1901D7041B8C3C03004E37AB /* FCXRefreshFooterView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FCXRefreshFooterView.h; sourceTree = ""; }; 53 | 1901D7051B8C3C03004E37AB /* FCXRefreshFooterView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FCXRefreshFooterView.m; sourceTree = ""; }; 54 | 1901D7061B8C3C03004E37AB /* FCXRefreshHeaderView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FCXRefreshHeaderView.h; sourceTree = ""; }; 55 | 1901D7071B8C3C03004E37AB /* FCXRefreshHeaderView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FCXRefreshHeaderView.m; sourceTree = ""; }; 56 | 1901D70B1B8C3C10004E37AB /* blueArrow.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = blueArrow.png; sourceTree = ""; }; 57 | 1901D70C1B8C3C10004E37AB /* blueArrow@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "blueArrow@2x.png"; sourceTree = ""; }; 58 | 1901D7411B8C4B16004E37AB /* UIScrollView+FCXRefresh.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIScrollView+FCXRefresh.h"; sourceTree = ""; }; 59 | 1901D7421B8C4B16004E37AB /* UIScrollView+FCXRefresh.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIScrollView+FCXRefresh.m"; sourceTree = ""; }; 60 | 1901D7441B8C5388004E37AB /* RefreshViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RefreshViewController.h; sourceTree = ""; }; 61 | 1901D7451B8C5388004E37AB /* RefreshViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RefreshViewController.m; sourceTree = ""; }; 62 | /* End PBXFileReference section */ 63 | 64 | /* Begin PBXFrameworksBuildPhase section */ 65 | 1901D6CC1B8C3B97004E37AB /* Frameworks */ = { 66 | isa = PBXFrameworksBuildPhase; 67 | buildActionMask = 2147483647; 68 | files = ( 69 | ); 70 | runOnlyForDeploymentPostprocessing = 0; 71 | }; 72 | 1901D6E51B8C3B98004E37AB /* Frameworks */ = { 73 | isa = PBXFrameworksBuildPhase; 74 | buildActionMask = 2147483647; 75 | files = ( 76 | ); 77 | runOnlyForDeploymentPostprocessing = 0; 78 | }; 79 | /* End PBXFrameworksBuildPhase section */ 80 | 81 | /* Begin PBXGroup section */ 82 | 1901D6C61B8C3B97004E37AB = { 83 | isa = PBXGroup; 84 | children = ( 85 | 1901D6D11B8C3B97004E37AB /* RefreshDemo */, 86 | 1901D6EB1B8C3B98004E37AB /* RefreshDemoTests */, 87 | 1901D6D01B8C3B97004E37AB /* Products */, 88 | ); 89 | sourceTree = ""; 90 | }; 91 | 1901D6D01B8C3B97004E37AB /* Products */ = { 92 | isa = PBXGroup; 93 | children = ( 94 | 1901D6CF1B8C3B97004E37AB /* RefreshDemo.app */, 95 | 1901D6E81B8C3B98004E37AB /* RefreshDemoTests.xctest */, 96 | ); 97 | name = Products; 98 | sourceTree = ""; 99 | }; 100 | 1901D6D11B8C3B97004E37AB /* RefreshDemo */ = { 101 | isa = PBXGroup; 102 | children = ( 103 | 1901D6D61B8C3B97004E37AB /* AppDelegate.h */, 104 | 1901D6D71B8C3B97004E37AB /* AppDelegate.m */, 105 | 1901D6D91B8C3B97004E37AB /* ViewController.h */, 106 | 1901D6DA1B8C3B97004E37AB /* ViewController.m */, 107 | 1901D7441B8C5388004E37AB /* RefreshViewController.h */, 108 | 1901D7451B8C5388004E37AB /* RefreshViewController.m */, 109 | 1901D7011B8C3C03004E37AB /* FCXRefreshView */, 110 | 1901D6DC1B8C3B97004E37AB /* Main.storyboard */, 111 | 1901D6DF1B8C3B98004E37AB /* Images.xcassets */, 112 | 1901D6E11B8C3B98004E37AB /* LaunchScreen.xib */, 113 | 1901D6D21B8C3B97004E37AB /* Supporting Files */, 114 | ); 115 | path = RefreshDemo; 116 | sourceTree = ""; 117 | }; 118 | 1901D6D21B8C3B97004E37AB /* Supporting Files */ = { 119 | isa = PBXGroup; 120 | children = ( 121 | 1901D6D31B8C3B97004E37AB /* Info.plist */, 122 | 1901D6D41B8C3B97004E37AB /* main.m */, 123 | ); 124 | name = "Supporting Files"; 125 | sourceTree = ""; 126 | }; 127 | 1901D6EB1B8C3B98004E37AB /* RefreshDemoTests */ = { 128 | isa = PBXGroup; 129 | children = ( 130 | 1901D6EE1B8C3B98004E37AB /* RefreshDemoTests.m */, 131 | 1901D6EC1B8C3B98004E37AB /* Supporting Files */, 132 | ); 133 | path = RefreshDemoTests; 134 | sourceTree = ""; 135 | }; 136 | 1901D6EC1B8C3B98004E37AB /* Supporting Files */ = { 137 | isa = PBXGroup; 138 | children = ( 139 | 1901D6ED1B8C3B98004E37AB /* Info.plist */, 140 | ); 141 | name = "Supporting Files"; 142 | sourceTree = ""; 143 | }; 144 | 1901D7011B8C3C03004E37AB /* FCXRefreshView */ = { 145 | isa = PBXGroup; 146 | children = ( 147 | 1901D70B1B8C3C10004E37AB /* blueArrow.png */, 148 | 1901D70C1B8C3C10004E37AB /* blueArrow@2x.png */, 149 | 1901D7021B8C3C03004E37AB /* FCXRefreshBaseView.h */, 150 | 1901D7031B8C3C03004E37AB /* FCXRefreshBaseView.m */, 151 | 1901D7061B8C3C03004E37AB /* FCXRefreshHeaderView.h */, 152 | 1901D7071B8C3C03004E37AB /* FCXRefreshHeaderView.m */, 153 | 1901D7041B8C3C03004E37AB /* FCXRefreshFooterView.h */, 154 | 1901D7051B8C3C03004E37AB /* FCXRefreshFooterView.m */, 155 | 1901D7411B8C4B16004E37AB /* UIScrollView+FCXRefresh.h */, 156 | 1901D7421B8C4B16004E37AB /* UIScrollView+FCXRefresh.m */, 157 | ); 158 | path = FCXRefreshView; 159 | sourceTree = ""; 160 | }; 161 | /* End PBXGroup section */ 162 | 163 | /* Begin PBXNativeTarget section */ 164 | 1901D6CE1B8C3B97004E37AB /* RefreshDemo */ = { 165 | isa = PBXNativeTarget; 166 | buildConfigurationList = 1901D6F21B8C3B98004E37AB /* Build configuration list for PBXNativeTarget "RefreshDemo" */; 167 | buildPhases = ( 168 | 1901D6CB1B8C3B97004E37AB /* Sources */, 169 | 1901D6CC1B8C3B97004E37AB /* Frameworks */, 170 | 1901D6CD1B8C3B97004E37AB /* Resources */, 171 | ); 172 | buildRules = ( 173 | ); 174 | dependencies = ( 175 | ); 176 | name = RefreshDemo; 177 | productName = RefreshDemo; 178 | productReference = 1901D6CF1B8C3B97004E37AB /* RefreshDemo.app */; 179 | productType = "com.apple.product-type.application"; 180 | }; 181 | 1901D6E71B8C3B98004E37AB /* RefreshDemoTests */ = { 182 | isa = PBXNativeTarget; 183 | buildConfigurationList = 1901D6F51B8C3B98004E37AB /* Build configuration list for PBXNativeTarget "RefreshDemoTests" */; 184 | buildPhases = ( 185 | 1901D6E41B8C3B98004E37AB /* Sources */, 186 | 1901D6E51B8C3B98004E37AB /* Frameworks */, 187 | 1901D6E61B8C3B98004E37AB /* Resources */, 188 | ); 189 | buildRules = ( 190 | ); 191 | dependencies = ( 192 | 1901D6EA1B8C3B98004E37AB /* PBXTargetDependency */, 193 | ); 194 | name = RefreshDemoTests; 195 | productName = RefreshDemoTests; 196 | productReference = 1901D6E81B8C3B98004E37AB /* RefreshDemoTests.xctest */; 197 | productType = "com.apple.product-type.bundle.unit-test"; 198 | }; 199 | /* End PBXNativeTarget section */ 200 | 201 | /* Begin PBXProject section */ 202 | 1901D6C71B8C3B97004E37AB /* Project object */ = { 203 | isa = PBXProject; 204 | attributes = { 205 | LastUpgradeCheck = 0830; 206 | ORGANIZATIONNAME = fcx; 207 | TargetAttributes = { 208 | 1901D6CE1B8C3B97004E37AB = { 209 | CreatedOnToolsVersion = 6.4; 210 | DevelopmentTeam = DLHH8HAF9C; 211 | }; 212 | 1901D6E71B8C3B98004E37AB = { 213 | CreatedOnToolsVersion = 6.4; 214 | TestTargetID = 1901D6CE1B8C3B97004E37AB; 215 | }; 216 | }; 217 | }; 218 | buildConfigurationList = 1901D6CA1B8C3B97004E37AB /* Build configuration list for PBXProject "RefreshDemo" */; 219 | compatibilityVersion = "Xcode 3.2"; 220 | developmentRegion = English; 221 | hasScannedForEncodings = 0; 222 | knownRegions = ( 223 | en, 224 | Base, 225 | ); 226 | mainGroup = 1901D6C61B8C3B97004E37AB; 227 | productRefGroup = 1901D6D01B8C3B97004E37AB /* Products */; 228 | projectDirPath = ""; 229 | projectRoot = ""; 230 | targets = ( 231 | 1901D6CE1B8C3B97004E37AB /* RefreshDemo */, 232 | 1901D6E71B8C3B98004E37AB /* RefreshDemoTests */, 233 | ); 234 | }; 235 | /* End PBXProject section */ 236 | 237 | /* Begin PBXResourcesBuildPhase section */ 238 | 1901D6CD1B8C3B97004E37AB /* Resources */ = { 239 | isa = PBXResourcesBuildPhase; 240 | buildActionMask = 2147483647; 241 | files = ( 242 | 1901D6DE1B8C3B97004E37AB /* Main.storyboard in Resources */, 243 | 1901D6E31B8C3B98004E37AB /* LaunchScreen.xib in Resources */, 244 | 1901D70E1B8C3C10004E37AB /* blueArrow@2x.png in Resources */, 245 | 1901D6E01B8C3B98004E37AB /* Images.xcassets in Resources */, 246 | 1901D70D1B8C3C10004E37AB /* blueArrow.png in Resources */, 247 | ); 248 | runOnlyForDeploymentPostprocessing = 0; 249 | }; 250 | 1901D6E61B8C3B98004E37AB /* Resources */ = { 251 | isa = PBXResourcesBuildPhase; 252 | buildActionMask = 2147483647; 253 | files = ( 254 | ); 255 | runOnlyForDeploymentPostprocessing = 0; 256 | }; 257 | /* End PBXResourcesBuildPhase section */ 258 | 259 | /* Begin PBXSourcesBuildPhase section */ 260 | 1901D6CB1B8C3B97004E37AB /* Sources */ = { 261 | isa = PBXSourcesBuildPhase; 262 | buildActionMask = 2147483647; 263 | files = ( 264 | 1901D7461B8C5388004E37AB /* RefreshViewController.m in Sources */, 265 | 1901D6DB1B8C3B97004E37AB /* ViewController.m in Sources */, 266 | 1901D7081B8C3C03004E37AB /* FCXRefreshBaseView.m in Sources */, 267 | 1901D7431B8C4B16004E37AB /* UIScrollView+FCXRefresh.m in Sources */, 268 | 1901D6D81B8C3B97004E37AB /* AppDelegate.m in Sources */, 269 | 1901D70A1B8C3C03004E37AB /* FCXRefreshHeaderView.m in Sources */, 270 | 1901D7091B8C3C03004E37AB /* FCXRefreshFooterView.m in Sources */, 271 | 1901D6D51B8C3B97004E37AB /* main.m in Sources */, 272 | ); 273 | runOnlyForDeploymentPostprocessing = 0; 274 | }; 275 | 1901D6E41B8C3B98004E37AB /* Sources */ = { 276 | isa = PBXSourcesBuildPhase; 277 | buildActionMask = 2147483647; 278 | files = ( 279 | 1901D6EF1B8C3B98004E37AB /* RefreshDemoTests.m in Sources */, 280 | ); 281 | runOnlyForDeploymentPostprocessing = 0; 282 | }; 283 | /* End PBXSourcesBuildPhase section */ 284 | 285 | /* Begin PBXTargetDependency section */ 286 | 1901D6EA1B8C3B98004E37AB /* PBXTargetDependency */ = { 287 | isa = PBXTargetDependency; 288 | target = 1901D6CE1B8C3B97004E37AB /* RefreshDemo */; 289 | targetProxy = 1901D6E91B8C3B98004E37AB /* PBXContainerItemProxy */; 290 | }; 291 | /* End PBXTargetDependency section */ 292 | 293 | /* Begin PBXVariantGroup section */ 294 | 1901D6DC1B8C3B97004E37AB /* Main.storyboard */ = { 295 | isa = PBXVariantGroup; 296 | children = ( 297 | 1901D6DD1B8C3B97004E37AB /* Base */, 298 | ); 299 | name = Main.storyboard; 300 | sourceTree = ""; 301 | }; 302 | 1901D6E11B8C3B98004E37AB /* LaunchScreen.xib */ = { 303 | isa = PBXVariantGroup; 304 | children = ( 305 | 1901D6E21B8C3B98004E37AB /* Base */, 306 | ); 307 | name = LaunchScreen.xib; 308 | sourceTree = ""; 309 | }; 310 | /* End PBXVariantGroup section */ 311 | 312 | /* Begin XCBuildConfiguration section */ 313 | 1901D6F01B8C3B98004E37AB /* Debug */ = { 314 | isa = XCBuildConfiguration; 315 | buildSettings = { 316 | ALWAYS_SEARCH_USER_PATHS = NO; 317 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 318 | CLANG_CXX_LIBRARY = "libc++"; 319 | CLANG_ENABLE_MODULES = YES; 320 | CLANG_ENABLE_OBJC_ARC = YES; 321 | CLANG_WARN_BOOL_CONVERSION = YES; 322 | CLANG_WARN_CONSTANT_CONVERSION = YES; 323 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 324 | CLANG_WARN_EMPTY_BODY = YES; 325 | CLANG_WARN_ENUM_CONVERSION = YES; 326 | CLANG_WARN_INFINITE_RECURSION = YES; 327 | CLANG_WARN_INT_CONVERSION = YES; 328 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 329 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 330 | CLANG_WARN_UNREACHABLE_CODE = YES; 331 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 332 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 333 | COPY_PHASE_STRIP = NO; 334 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 335 | ENABLE_STRICT_OBJC_MSGSEND = YES; 336 | ENABLE_TESTABILITY = YES; 337 | GCC_C_LANGUAGE_STANDARD = gnu99; 338 | GCC_DYNAMIC_NO_PIC = NO; 339 | GCC_NO_COMMON_BLOCKS = YES; 340 | GCC_OPTIMIZATION_LEVEL = 0; 341 | GCC_PREPROCESSOR_DEFINITIONS = ( 342 | "DEBUG=1", 343 | "$(inherited)", 344 | ); 345 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 346 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 347 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 348 | GCC_WARN_UNDECLARED_SELECTOR = YES; 349 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 350 | GCC_WARN_UNUSED_FUNCTION = YES; 351 | GCC_WARN_UNUSED_VARIABLE = YES; 352 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 353 | MTL_ENABLE_DEBUG_INFO = YES; 354 | ONLY_ACTIVE_ARCH = YES; 355 | SDKROOT = iphoneos; 356 | }; 357 | name = Debug; 358 | }; 359 | 1901D6F11B8C3B98004E37AB /* Release */ = { 360 | isa = XCBuildConfiguration; 361 | buildSettings = { 362 | ALWAYS_SEARCH_USER_PATHS = NO; 363 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 364 | CLANG_CXX_LIBRARY = "libc++"; 365 | CLANG_ENABLE_MODULES = YES; 366 | CLANG_ENABLE_OBJC_ARC = YES; 367 | CLANG_WARN_BOOL_CONVERSION = YES; 368 | CLANG_WARN_CONSTANT_CONVERSION = YES; 369 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 370 | CLANG_WARN_EMPTY_BODY = YES; 371 | CLANG_WARN_ENUM_CONVERSION = YES; 372 | CLANG_WARN_INFINITE_RECURSION = YES; 373 | CLANG_WARN_INT_CONVERSION = YES; 374 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 375 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 376 | CLANG_WARN_UNREACHABLE_CODE = YES; 377 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 378 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 379 | COPY_PHASE_STRIP = NO; 380 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 381 | ENABLE_NS_ASSERTIONS = NO; 382 | ENABLE_STRICT_OBJC_MSGSEND = YES; 383 | GCC_C_LANGUAGE_STANDARD = gnu99; 384 | GCC_NO_COMMON_BLOCKS = YES; 385 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 386 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 387 | GCC_WARN_UNDECLARED_SELECTOR = YES; 388 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 389 | GCC_WARN_UNUSED_FUNCTION = YES; 390 | GCC_WARN_UNUSED_VARIABLE = YES; 391 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 392 | MTL_ENABLE_DEBUG_INFO = NO; 393 | SDKROOT = iphoneos; 394 | VALIDATE_PRODUCT = YES; 395 | }; 396 | name = Release; 397 | }; 398 | 1901D6F31B8C3B98004E37AB /* Debug */ = { 399 | isa = XCBuildConfiguration; 400 | buildSettings = { 401 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 402 | DEVELOPMENT_TEAM = DLHH8HAF9C; 403 | INFOPLIST_FILE = RefreshDemo/Info.plist; 404 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 405 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 406 | PRODUCT_BUNDLE_IDENTIFIER = com.app.RefreshDemo; 407 | PRODUCT_NAME = "$(TARGET_NAME)"; 408 | }; 409 | name = Debug; 410 | }; 411 | 1901D6F41B8C3B98004E37AB /* Release */ = { 412 | isa = XCBuildConfiguration; 413 | buildSettings = { 414 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 415 | DEVELOPMENT_TEAM = DLHH8HAF9C; 416 | INFOPLIST_FILE = RefreshDemo/Info.plist; 417 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 418 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 419 | PRODUCT_BUNDLE_IDENTIFIER = com.app.RefreshDemo; 420 | PRODUCT_NAME = "$(TARGET_NAME)"; 421 | }; 422 | name = Release; 423 | }; 424 | 1901D6F61B8C3B98004E37AB /* Debug */ = { 425 | isa = XCBuildConfiguration; 426 | buildSettings = { 427 | BUNDLE_LOADER = "$(TEST_HOST)"; 428 | FRAMEWORK_SEARCH_PATHS = ( 429 | "$(SDKROOT)/Developer/Library/Frameworks", 430 | "$(inherited)", 431 | ); 432 | GCC_PREPROCESSOR_DEFINITIONS = ( 433 | "DEBUG=1", 434 | "$(inherited)", 435 | ); 436 | INFOPLIST_FILE = RefreshDemoTests/Info.plist; 437 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 438 | PRODUCT_BUNDLE_IDENTIFIER = "com.wangyin..$(PRODUCT_NAME:rfc1034identifier)"; 439 | PRODUCT_NAME = "$(TARGET_NAME)"; 440 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/RefreshDemo.app/RefreshDemo"; 441 | }; 442 | name = Debug; 443 | }; 444 | 1901D6F71B8C3B98004E37AB /* Release */ = { 445 | isa = XCBuildConfiguration; 446 | buildSettings = { 447 | BUNDLE_LOADER = "$(TEST_HOST)"; 448 | FRAMEWORK_SEARCH_PATHS = ( 449 | "$(SDKROOT)/Developer/Library/Frameworks", 450 | "$(inherited)", 451 | ); 452 | INFOPLIST_FILE = RefreshDemoTests/Info.plist; 453 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 454 | PRODUCT_BUNDLE_IDENTIFIER = "com.wangyin..$(PRODUCT_NAME:rfc1034identifier)"; 455 | PRODUCT_NAME = "$(TARGET_NAME)"; 456 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/RefreshDemo.app/RefreshDemo"; 457 | }; 458 | name = Release; 459 | }; 460 | /* End XCBuildConfiguration section */ 461 | 462 | /* Begin XCConfigurationList section */ 463 | 1901D6CA1B8C3B97004E37AB /* Build configuration list for PBXProject "RefreshDemo" */ = { 464 | isa = XCConfigurationList; 465 | buildConfigurations = ( 466 | 1901D6F01B8C3B98004E37AB /* Debug */, 467 | 1901D6F11B8C3B98004E37AB /* Release */, 468 | ); 469 | defaultConfigurationIsVisible = 0; 470 | defaultConfigurationName = Release; 471 | }; 472 | 1901D6F21B8C3B98004E37AB /* Build configuration list for PBXNativeTarget "RefreshDemo" */ = { 473 | isa = XCConfigurationList; 474 | buildConfigurations = ( 475 | 1901D6F31B8C3B98004E37AB /* Debug */, 476 | 1901D6F41B8C3B98004E37AB /* Release */, 477 | ); 478 | defaultConfigurationIsVisible = 0; 479 | defaultConfigurationName = Release; 480 | }; 481 | 1901D6F51B8C3B98004E37AB /* Build configuration list for PBXNativeTarget "RefreshDemoTests" */ = { 482 | isa = XCConfigurationList; 483 | buildConfigurations = ( 484 | 1901D6F61B8C3B98004E37AB /* Debug */, 485 | 1901D6F71B8C3B98004E37AB /* Release */, 486 | ); 487 | defaultConfigurationIsVisible = 0; 488 | defaultConfigurationName = Release; 489 | }; 490 | /* End XCConfigurationList section */ 491 | }; 492 | rootObject = 1901D6C71B8C3B97004E37AB /* Project object */; 493 | } 494 | -------------------------------------------------------------------------------- /RefreshDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /RefreshDemo.xcodeproj/project.xcworkspace/xcuserdata/fcx.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fengchuanxiang/RefreshView/f786cf703c0581d676b4b95615f25e65721b5568/RefreshDemo.xcodeproj/project.xcworkspace/xcuserdata/fcx.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /RefreshDemo.xcodeproj/xcuserdata/fcx.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 8 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /RefreshDemo.xcodeproj/xcuserdata/fcx.xcuserdatad/xcschemes/RefreshDemo.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 38 | 39 | 44 | 45 | 47 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 65 | 66 | 75 | 77 | 83 | 84 | 85 | 86 | 90 | 91 | 95 | 96 | 97 | 98 | 104 | 106 | 112 | 113 | 114 | 115 | 117 | 118 | 121 | 122 | 123 | -------------------------------------------------------------------------------- /RefreshDemo.xcodeproj/xcuserdata/fcx.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | RefreshDemo.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 1901D6CE1B8C3B97004E37AB 16 | 17 | primary 18 | 19 | 20 | 1901D6E71B8C3B98004E37AB 21 | 22 | primary 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /RefreshDemo/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // RefreshDemo 4 | // 5 | // Created by fcx on 15/8/25. 6 | // Copyright (c) 2015年 fcx. 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 | -------------------------------------------------------------------------------- /RefreshDemo/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // RefreshDemo 4 | // 5 | // Created by fcx on 15/8/25. 6 | // Copyright (c) 2015年 fcx. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | return YES; 21 | } 22 | 23 | - (void)applicationWillResignActive:(UIApplication *)application { 24 | // 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. 25 | // 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. 26 | } 27 | 28 | - (void)applicationDidEnterBackground:(UIApplication *)application { 29 | // 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. 30 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 31 | } 32 | 33 | - (void)applicationWillEnterForeground:(UIApplication *)application { 34 | // 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. 35 | } 36 | 37 | - (void)applicationDidBecomeActive:(UIApplication *)application { 38 | // 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. 39 | } 40 | 41 | - (void)applicationWillTerminate:(UIApplication *)application { 42 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /RefreshDemo/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 20 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /RefreshDemo/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 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /RefreshDemo/FCXRefreshView/FCXRefreshBaseView.h: -------------------------------------------------------------------------------- 1 | // 2 | // FCXRefreshBaseView.h 3 | // RefreshPrj 4 | // 5 | // Created by fcx on 15/8/21. 6 | // Copyright (c) 2015年 fcx. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef NS_ENUM(NSInteger, FCXRefreshState) { 12 | FCXRefreshStateNormal = 1, 13 | FCXRefreshStatePulling = 2, 14 | FCXRefreshStateLoading = 3, 15 | FCXRefreshStateNoMoreData = 4 //上拉加载显示没有更多数据 16 | }; 17 | 18 | typedef NS_ENUM(NSInteger, FCXRefreshViewType) { 19 | FCXRefreshViewTypeHeader = -1, 20 | FCXRefreshViewTypeFooter = 1 21 | }; 22 | 23 | //刷新偏移量的高度 24 | static const CGFloat FCXHandingOffsetHeight = 60; 25 | //文本颜色 26 | #define FCXREFRESHTEXTCOLOR [UIColor colorWithRed:150/255.0 green:150/255.0 blue:150/255.0 alpha:1.0] 27 | 28 | @class FCXRefreshBaseView; 29 | typedef void(^FCXRefreshedHandler)(FCXRefreshBaseView *refreshView); 30 | typedef void(^FCXPullingPercentHandler)(CGFloat pullingPercent); 31 | 32 | 33 | @interface FCXRefreshBaseView : UIView 34 | { 35 | UILabel *_timeLabel; 36 | UILabel *_statusLabel; 37 | UIImageView *arrowImageView; 38 | UIActivityIndicatorView *_activityView; 39 | __weak UIScrollView *_scrollView;//!<添加刷新的scrollView 40 | UIEdgeInsets _scrollViewOriginalEdgeInsets; 41 | FCXRefreshState _refreshState;//!<当前刷新状态 42 | } 43 | 44 | @property (nonatomic, copy) FCXRefreshedHandler refreshHandler;//!<刷新的相应事件 45 | @property (nonatomic, unsafe_unretained) FCXRefreshState refreshState;//!<当前刷新状态 46 | @property (nonatomic, unsafe_unretained) CGFloat pullingPercent; 47 | @property (nonatomic, copy) FCXPullingPercentHandler pullingPercentHandler;//!<刷新的相应事件 48 | 49 | @property (nonatomic, copy) NSString *normalStateText;//!<正常状态文本 50 | @property (nonatomic, copy) NSString *pullingStateText;//!<下拉状态提示文本 51 | @property (nonatomic, copy) NSString *loadingStateText;//!<加载中的提示文本 52 | @property (nonatomic, copy) NSString *noMoreDataStateText;//!<没有更多数据提示文本 53 | 54 | 55 | //设置各种状态的文本 56 | - (void)setupStateText; 57 | 58 | /** 59 | * 添加刷新的界面 60 | * 61 | * 注:如果想自定义刷新加载界面,可在子类中重写该方法进行布局子界面 62 | */ 63 | - (void)addRefreshContentView; 64 | //自动刷新 65 | - (void)autoRefresh; 66 | //结束刷新 67 | - (void)endRefresh; 68 | // 当scrollView的contentOffset发生改变的时候调用 69 | - (void)scrollViewContentOffsetDidChange; 70 | // 当scrollView的contentSize发生改变的时候调用 71 | - (void)scrollViewContentSizeDidChange; 72 | //显示没有更多数据 73 | - (void)showNoMoreData; 74 | //重置没有更多的数据(消除没有更多数据的状态) 75 | - (void)resetNoMoreData; 76 | 77 | @end 78 | -------------------------------------------------------------------------------- /RefreshDemo/FCXRefreshView/FCXRefreshBaseView.m: -------------------------------------------------------------------------------- 1 | // 2 | // FCXRefreshBaseView.m 3 | // RefreshPrj 4 | // 5 | // Created by fcx on 15/8/21. 6 | // Copyright (c) 2015年 fcx. All rights reserved. 7 | // 8 | 9 | #import "FCXRefreshBaseView.h" 10 | 11 | 12 | @implementation FCXRefreshBaseView 13 | 14 | - (instancetype)initWithFrame:(CGRect)frame { 15 | if (self = [super initWithFrame:frame]) { 16 | [self addRefreshContentView]; 17 | [self setupStateText]; 18 | self.refreshState = FCXRefreshStateNormal; 19 | } 20 | return self; 21 | } 22 | 23 | - (void)willMoveToSuperview:(UIView *)newSuperview { 24 | [super willMoveToSuperview:newSuperview]; 25 | 26 | [self removeScrollViewObservers]; 27 | if ([newSuperview isKindOfClass:[UIScrollView class]]) { 28 | _scrollView = (UIScrollView *)newSuperview; 29 | _scrollViewOriginalEdgeInsets = _scrollView.contentInset; 30 | [self addScrollViewObservers]; 31 | } 32 | } 33 | 34 | - (void)addRefreshContentView {} 35 | - (void)setupStateText {} 36 | - (void)autoRefresh {} 37 | - (void)endRefresh { 38 | self.refreshState = FCXRefreshStateNormal; 39 | } 40 | - (void)showNoMoreData {} 41 | - (void)resetNoMoreData {} 42 | - (void)setPullingPercent:(CGFloat)pullingPercent { 43 | if (_pullingPercent != pullingPercent) { 44 | _pullingPercent = pullingPercent; 45 | if (_pullingPercentHandler) { 46 | _pullingPercentHandler(_pullingPercent); 47 | } 48 | } 49 | } 50 | 51 | #pragma mark - KVO 52 | - (void)addScrollViewObservers { 53 | [_scrollView addObserver:self forKeyPath:@"contentOffset" options:NSKeyValueObservingOptionNew context:nil]; 54 | [_scrollView addObserver:self forKeyPath:@"contentSize" options:NSKeyValueObservingOptionNew context:nil]; 55 | [_scrollView addObserver:self forKeyPath:@"contentInset" options:NSKeyValueObservingOptionNew context:nil]; 56 | } 57 | 58 | - (void)removeScrollViewObservers { 59 | if ([self.superview isKindOfClass:[UIScrollView class]]) { 60 | [self.superview removeObserver:self forKeyPath:@"contentOffset" context:nil]; 61 | [self.superview removeObserver:self forKeyPath:@"contentSize" context:nil]; 62 | [self.superview removeObserver:self forKeyPath:@"contentInset" context:nil]; 63 | } 64 | } 65 | 66 | - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { 67 | if ([keyPath isEqualToString:@"contentOffset"]) { 68 | //正在刷新 69 | if (_refreshState == FCXRefreshStateLoading) { 70 | return; 71 | } 72 | [self scrollViewContentOffsetDidChange]; 73 | } else if ([keyPath isEqualToString:@"contentSize"]) { 74 | [self scrollViewContentSizeDidChange]; 75 | } else if ([keyPath isEqualToString:@"contentInset"]) { 76 | if (_refreshState == FCXRefreshStateLoading) { 77 | return; 78 | } 79 | _scrollViewOriginalEdgeInsets = _scrollView.contentInset; 80 | } 81 | } 82 | 83 | - (void)scrollViewContentOffsetDidChange {} 84 | - (void)scrollViewContentSizeDidChange {} 85 | 86 | @end 87 | -------------------------------------------------------------------------------- /RefreshDemo/FCXRefreshView/FCXRefreshFooterView.h: -------------------------------------------------------------------------------- 1 | // 2 | // FCXRefreshFooterView.h 3 | // RefreshPrj 4 | // 5 | // Created by fcx on 15/8/21. 6 | // Copyright (c) 2015年 fcx. All rights reserved. 7 | // 8 | 9 | #import "FCXRefreshBaseView.h" 10 | 11 | @interface FCXRefreshFooterView : FCXRefreshBaseView 12 | 13 | /** 14 | * 是否自动加载更多,默认上拉超过scrollView的内容高度时,直接加载更多 15 | */ 16 | @property (nonatomic, unsafe_unretained) BOOL autoLoadMore; 17 | 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /RefreshDemo/FCXRefreshView/FCXRefreshFooterView.m: -------------------------------------------------------------------------------- 1 | // 2 | // FCXRefreshFooterView.m 3 | // RefreshPrj 4 | // 5 | // Created by fcx on 15/8/21. 6 | // Copyright (c) 2015年 fcx. All rights reserved. 7 | // 8 | 9 | #import "FCXRefreshFooterView.h" 10 | 11 | @implementation FCXRefreshFooterView 12 | 13 | - (void)setupStateText { 14 | self.normalStateText = @"上拉加载更多"; 15 | self.pullingStateText = @"松开可加载更多"; 16 | self.loadingStateText = @"正在加载更多..."; 17 | self.noMoreDataStateText = @"没有更多数据"; 18 | } 19 | 20 | - (void)addRefreshContentView { 21 | [super addRefreshContentView]; 22 | CGFloat width = self.frame.size.width; 23 | 24 | //刷新状态 25 | _statusLabel = [[UILabel alloc] init]; 26 | _statusLabel.frame = CGRectMake(0, 0, width, 60); 27 | _statusLabel.font = [UIFont fontWithName:@"HelveticaNeue-Light" size:14]; 28 | _statusLabel.textColor = FCXREFRESHTEXTCOLOR; 29 | _statusLabel.backgroundColor = [UIColor clearColor]; 30 | _statusLabel.textAlignment = NSTextAlignmentCenter; 31 | [self addSubview:_statusLabel]; 32 | 33 | //箭头图片 34 | arrowImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"blueArrow"]]; 35 | arrowImageView.frame = CGRectMake(width/2.0 - 100, 11, 15, 40); 36 | [self addSubview:arrowImageView]; 37 | 38 | //转圈动画 39 | _activityView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray]; 40 | _activityView.frame = CGRectMake(width/2.0 - 100, 10, 15, 40); 41 | [self addSubview:_activityView]; 42 | } 43 | 44 | - (void)layoutSubviews { 45 | [super layoutSubviews]; 46 | _statusLabel.frame = CGRectMake(0, 0, self.frame.size.width, 60); 47 | if (!_autoLoadMore) { 48 | arrowImageView.frame = CGRectMake(self.frame.size.width/2.0 - 100, 11, 15, 40); 49 | _activityView.frame = CGRectMake(self.frame.size.width/2.0 - 100, 10, 15, 40); 50 | } 51 | } 52 | 53 | 54 | - (void)setAutoLoadMore:(BOOL)autoLoadMore { 55 | _autoLoadMore = autoLoadMore; 56 | if (_autoLoadMore) {//自动加载更多不显示箭头 57 | [arrowImageView removeFromSuperview]; 58 | arrowImageView = nil; 59 | self.normalStateText = @"正在加载更多..."; 60 | self.pullingStateText = @"正在加载更多..."; 61 | self.loadingStateText = @"正在加载更多..."; 62 | } 63 | } 64 | 65 | - (void)scrollViewContentSizeDidChange { 66 | CGRect frame = self.frame; 67 | frame.origin.y = MAX(_scrollView.frame.size.height, _scrollView.contentSize.height); 68 | self.frame = frame; 69 | } 70 | 71 | - (void)scrollViewContentOffsetDidChange { 72 | if (self.refreshState == FCXRefreshStateNoMoreData) {//没有更多数据 73 | return; 74 | } 75 | 76 | //scrollview实际显示内容高度 77 | CGFloat realHeight = _scrollView.frame.size.height - _scrollViewOriginalEdgeInsets.top - _scrollViewOriginalEdgeInsets.bottom; 78 | /// 计算超出scrollView的高度 79 | CGFloat beyondScrollViewHeight = _scrollView.contentSize.height - realHeight; 80 | if (beyondScrollViewHeight <= 0) { 81 | //scrollView的实际内容高度没有超出本身高度不处理 82 | return; 83 | } 84 | 85 | //刚刚出现底部控件时出现的offsetY 86 | CGFloat offSetY = beyondScrollViewHeight - _scrollViewOriginalEdgeInsets.top; 87 | // 当前scrollView的contentOffsetY超出offsetY的高度 88 | CGFloat beyondOffsetHeight = _scrollView.contentOffset.y - offSetY; 89 | if (beyondOffsetHeight <= 0) { 90 | return; 91 | } 92 | 93 | if (self.autoLoadMore) {//如果是自动加载更多 94 | //大于偏移量,转为加载更多loading 95 | self.refreshState = FCXRefreshStateLoading; 96 | return; 97 | } 98 | 99 | if (_scrollView.isDragging) { 100 | if (beyondOffsetHeight > FCXHandingOffsetHeight) {//大于偏移量,转为pulling 101 | self.refreshState = FCXRefreshStatePulling; 102 | }else {//小于偏移量,转为正常normal 103 | self.refreshState = FCXRefreshStateNormal; 104 | } 105 | } else { 106 | if (self.refreshState == FCXRefreshStatePulling) {//如果是pulling状态,改为加载更多loading 107 | self.refreshState = FCXRefreshStateLoading; 108 | }else { 109 | self.refreshState = FCXRefreshStateNormal; 110 | } 111 | } 112 | 113 | if (self.pullingPercentHandler) { 114 | if (beyondOffsetHeight <= FCXHandingOffsetHeight) { 115 | //有时进度可能会到0.991..对精度要求没那么高可以忽略 116 | self.pullingPercent = beyondOffsetHeight/FCXHandingOffsetHeight; 117 | } 118 | } 119 | } 120 | 121 | - (void)setRefreshState:(FCXRefreshState)refreshState { 122 | FCXRefreshState lastRefreshState = _refreshState; 123 | if (_refreshState != refreshState) { 124 | _refreshState = refreshState; 125 | switch (refreshState) { 126 | case FCXRefreshStateNormal: 127 | { 128 | _statusLabel.text = self.normalStateText; 129 | if (lastRefreshState == FCXRefreshStateLoading) {//之前是刷新过 130 | arrowImageView.hidden = YES; 131 | } else { 132 | arrowImageView.hidden = NO; 133 | } 134 | arrowImageView.hidden = NO; 135 | [_activityView stopAnimating]; 136 | 137 | [UIView animateWithDuration:0.2 animations:^{ 138 | arrowImageView.transform = CGAffineTransformMakeRotation(0.000001 - M_PI); 139 | _scrollView.contentInset = _scrollViewOriginalEdgeInsets; 140 | }]; 141 | } 142 | break; 143 | case FCXRefreshStatePulling: 144 | { 145 | _statusLabel.text = self.pullingStateText; 146 | [UIView animateWithDuration:0.2 animations:^{ 147 | arrowImageView.transform = CGAffineTransformIdentity; 148 | }]; 149 | } 150 | break; 151 | case FCXRefreshStateLoading: 152 | { 153 | _statusLabel.text = self.loadingStateText; 154 | [_activityView startAnimating]; 155 | arrowImageView.hidden = YES; 156 | arrowImageView.transform = CGAffineTransformMakeRotation(0.000001 - M_PI); 157 | [UIView animateWithDuration:0.2 animations:^{ 158 | UIEdgeInsets inset = _scrollView.contentInset; 159 | inset.bottom += FCXHandingOffsetHeight; 160 | _scrollView.contentInset = inset; 161 | inset.bottom = self.frame.origin.y - _scrollView.contentSize.height + FCXHandingOffsetHeight; 162 | _scrollView.contentInset = inset; 163 | }]; 164 | 165 | if (self.refreshHandler) { 166 | self.refreshHandler(self); 167 | } 168 | } 169 | break; 170 | case FCXRefreshStateNoMoreData: 171 | { 172 | _statusLabel.text = self.noMoreDataStateText; 173 | } 174 | break; 175 | } 176 | } 177 | } 178 | 179 | - (void)showNoMoreData { 180 | [self endRefresh]; 181 | self.refreshState = FCXRefreshStateNoMoreData; 182 | arrowImageView.hidden = YES; 183 | } 184 | 185 | - (void)resetNoMoreData { 186 | self.refreshState = FCXRefreshStateNormal; 187 | } 188 | 189 | @end 190 | -------------------------------------------------------------------------------- /RefreshDemo/FCXRefreshView/FCXRefreshHeaderView.h: -------------------------------------------------------------------------------- 1 | // 2 | // FCXRefreshHeaderView.h 3 | // RefreshPrj 4 | // 5 | // Created by fcx on 15/8/21. 6 | // Copyright (c) 2015年 fcx. All rights reserved. 7 | // 8 | 9 | #import "FCXRefreshBaseView.h" 10 | 11 | @interface FCXRefreshHeaderView : FCXRefreshBaseView 12 | 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /RefreshDemo/FCXRefreshView/FCXRefreshHeaderView.m: -------------------------------------------------------------------------------- 1 | // 2 | // FCXRefreshHeaderView.m 3 | // RefreshPrj 4 | // 5 | // Created by fcx on 15/8/21. 6 | // Copyright (c) 2015年 fcx. All rights reserved. 7 | // 8 | 9 | #import "FCXRefreshHeaderView.h" 10 | 11 | @implementation FCXRefreshHeaderView 12 | 13 | - (void)setupStateText { 14 | self.normalStateText = @"下拉刷新"; 15 | self.pullingStateText = @"松开可刷新"; 16 | self.loadingStateText = @"正在刷新..."; 17 | } 18 | 19 | - (void)addRefreshContentView { 20 | [super addRefreshContentView]; 21 | CGFloat width = self.frame.size.width; 22 | 23 | //刷新状态 24 | _statusLabel = [[UILabel alloc] init]; 25 | _statusLabel.frame = CGRectMake(0, 15, width, 20); 26 | _statusLabel.font = [UIFont fontWithName:@"HelveticaNeue-Light" size:12]; 27 | _statusLabel.textColor = FCXREFRESHTEXTCOLOR; 28 | _statusLabel.backgroundColor = [UIColor clearColor]; 29 | _statusLabel.textAlignment = NSTextAlignmentCenter; 30 | [self addSubview:_statusLabel]; 31 | 32 | //更新时间 33 | _timeLabel = [[UILabel alloc] init]; 34 | _timeLabel.frame = CGRectMake(0, 35, width, 20); 35 | _timeLabel.font = [UIFont fontWithName:@"HelveticaNeue-Light" size:12]; 36 | _timeLabel.textColor = [UIColor colorWithRed:150/255.0 green:150/255.0 blue:150/255.0 alpha:1.0]; 37 | _timeLabel.backgroundColor = [UIColor clearColor]; 38 | _timeLabel.textAlignment = NSTextAlignmentCenter; 39 | [self addSubview:_timeLabel]; 40 | 41 | //箭头图片 42 | arrowImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"blueArrow"]]; 43 | arrowImageView.frame = CGRectMake(width/2.0 - 100, (FCXHandingOffsetHeight - 40)/2.0 + 5, 15, 40); 44 | [self addSubview:arrowImageView]; 45 | 46 | //转圈动画 47 | _activityView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray]; 48 | _activityView.frame = arrowImageView.frame; 49 | [self addSubview:_activityView]; 50 | [self updateTimeLabel]; 51 | } 52 | 53 | - (void)layoutSubviews { 54 | [super layoutSubviews]; 55 | _statusLabel.frame = CGRectMake(0, self.frame.size.height - 45, self.frame.size.width, 20); 56 | _timeLabel.frame = CGRectMake(0, 35, self.frame.size.width, 20); 57 | arrowImageView.frame = CGRectMake(self.frame.size.width/2.0 - 100, (FCXHandingOffsetHeight - 40)/2.0 + 5, 15, 40); 58 | _activityView.frame = arrowImageView.frame; 59 | } 60 | 61 | - (void)scrollViewContentOffsetDidChange { 62 | if (_scrollView.contentOffset.y > -_scrollViewOriginalEdgeInsets.top) { 63 | //向上滚动到看不见头部控件,直接返回 64 | return; 65 | } 66 | 67 | if (_scrollView.isDragging) {//正在拖拽 68 | if (_scrollView.contentOffset.y + _scrollViewOriginalEdgeInsets.top < -FCXHandingOffsetHeight) {//大于偏移量,转为pulling 69 | self.refreshState = FCXRefreshStatePulling; 70 | }else {//小于偏移量,转为正常normal 71 | self.refreshState = FCXRefreshStateNormal; 72 | } 73 | } else { 74 | if (self.refreshState == FCXRefreshStatePulling) {//如果是pulling状态,改为刷新加载loading 75 | self.refreshState = FCXRefreshStateLoading; 76 | }else { 77 | self.refreshState = FCXRefreshStateNormal; 78 | } 79 | } 80 | 81 | if (self.pullingPercentHandler) { 82 | CGFloat offsetHeight = -_scrollView.contentOffset.y - _scrollViewOriginalEdgeInsets.top; 83 | if (offsetHeight >= 0 && offsetHeight <= FCXHandingOffsetHeight) { 84 | //有时进度可能会到0.991..对精度要求没那么高可以忽略 85 | self.pullingPercent = offsetHeight/FCXHandingOffsetHeight; 86 | } 87 | } 88 | } 89 | 90 | - (void)setRefreshState:(FCXRefreshState)refreshState { 91 | FCXRefreshState lastRefreshState = _refreshState; 92 | if (_refreshState != refreshState) { 93 | _refreshState = refreshState; 94 | switch (refreshState) { 95 | case FCXRefreshStateNormal: 96 | { 97 | _statusLabel.text = self.normalStateText; 98 | if (lastRefreshState == FCXRefreshStateLoading) {//之前是在刷新 99 | [self updateTimeLabel]; 100 | } 101 | arrowImageView.hidden = NO; 102 | [_activityView stopAnimating]; 103 | 104 | [UIView animateWithDuration:0.2 animations:^{ 105 | arrowImageView.transform = CGAffineTransformIdentity; 106 | _scrollView.contentInset = _scrollViewOriginalEdgeInsets; 107 | }]; 108 | } 109 | break; 110 | case FCXRefreshStatePulling: 111 | { 112 | _statusLabel.text = self.pullingStateText; 113 | [UIView animateWithDuration:0.2 animations:^{ 114 | arrowImageView.transform = CGAffineTransformMakeRotation(0.000001 - M_PI); 115 | }]; 116 | } 117 | break; 118 | case FCXRefreshStateLoading: 119 | { 120 | _statusLabel.text = self.loadingStateText; 121 | [_activityView startAnimating]; 122 | arrowImageView.hidden = YES; 123 | arrowImageView.transform = CGAffineTransformIdentity; 124 | 125 | [UIView animateWithDuration:0.2 animations:^{ 126 | UIEdgeInsets edgeInset = _scrollViewOriginalEdgeInsets; 127 | edgeInset.top += FCXHandingOffsetHeight; 128 | _scrollView.contentInset = edgeInset; 129 | }]; 130 | 131 | if (self.refreshHandler) { 132 | self.refreshHandler(self); 133 | } 134 | } 135 | break; 136 | case FCXRefreshStateNoMoreData: 137 | { 138 | } 139 | break; 140 | } 141 | } 142 | } 143 | 144 | - (void)autoRefresh { 145 | self.refreshState = FCXRefreshStateLoading; 146 | [UIView animateWithDuration:.2 animations:^{ 147 | _scrollView.contentOffset = CGPointMake(0, -FCXHandingOffsetHeight); 148 | } completion:^(BOOL finished) { 149 | self.refreshState = FCXRefreshStateLoading; 150 | }]; 151 | } 152 | 153 | - (void)updateTimeLabel { 154 | NSMutableDictionary *threadDictionary = [[NSThread currentThread] threadDictionary] ; 155 | NSDateFormatter *dateFormatter = [threadDictionary objectForKey: @"FCXRefeshDateFormatterKey"] ; 156 | if (dateFormatter == nil) { 157 | dateFormatter = [[NSDateFormatter alloc] init] ; 158 | [dateFormatter setDateFormat: @"最后更新:今天 HH:mm"] ; 159 | [threadDictionary setObject: dateFormatter forKey: @"FCXRefeshDateFormatterKey"] ; 160 | } 161 | _timeLabel.text = [dateFormatter stringFromDate:[NSDate date]]; 162 | } 163 | 164 | @end 165 | -------------------------------------------------------------------------------- /RefreshDemo/FCXRefreshView/UIScrollView+FCXRefresh.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIScrollView+FCXRefresh.h 3 | // RefreshDemo 4 | // 5 | // Created by fcx on 15/8/25. 6 | // Copyright (c) 2015年 fcx. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "FCXRefreshBaseView.h" 11 | 12 | @class FCXRefreshHeaderView; 13 | @class FCXRefreshFooterView; 14 | 15 | @interface UIScrollView (FCXRefresh) 16 | 17 | - (FCXRefreshHeaderView *)addHeaderWithRefreshHandler:(FCXRefreshedHandler)refreshHandler; 18 | - (FCXRefreshFooterView *)addFooterWithRefreshHandler:(FCXRefreshedHandler)refreshHandler; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /RefreshDemo/FCXRefreshView/UIScrollView+FCXRefresh.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIScrollView+FCXRefresh.m 3 | // RefreshDemo 4 | // 5 | // Created by fcx on 15/8/25. 6 | // Copyright (c) 2015年 fcx. All rights reserved. 7 | // 8 | 9 | #import "UIScrollView+FCXRefresh.h" 10 | #import "FCXRefreshHeaderView.h" 11 | #import "FCXRefreshFooterView.h" 12 | 13 | @implementation UIScrollView (FCXRefresh) 14 | 15 | - (FCXRefreshHeaderView *)addHeaderWithRefreshHandler:(FCXRefreshedHandler)refreshHandler { 16 | FCXRefreshHeaderView *header = [[FCXRefreshHeaderView alloc] initWithFrame:CGRectMake(0, -60, [UIScreen mainScreen].bounds.size.width, 60)]; 17 | header.refreshHandler = refreshHandler; 18 | [self addSubview:header]; 19 | return header; 20 | } 21 | 22 | - (FCXRefreshFooterView *)addFooterWithRefreshHandler:(FCXRefreshedHandler)refreshHandler { 23 | FCXRefreshFooterView *footer = [[FCXRefreshFooterView alloc] initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, 60)]; 24 | footer.refreshHandler = refreshHandler; 25 | [self addSubview:footer]; 26 | return footer; 27 | } 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /RefreshDemo/FCXRefreshView/blueArrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fengchuanxiang/RefreshView/f786cf703c0581d676b4b95615f25e65721b5568/RefreshDemo/FCXRefreshView/blueArrow.png -------------------------------------------------------------------------------- /RefreshDemo/FCXRefreshView/blueArrow@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fengchuanxiang/RefreshView/f786cf703c0581d676b4b95615f25e65721b5568/RefreshDemo/FCXRefreshView/blueArrow@2x.png -------------------------------------------------------------------------------- /RefreshDemo/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 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /RefreshDemo/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 | 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 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /RefreshDemo/RefreshViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // RefreshViewController.h 3 | // RefreshDemo 4 | // 5 | // Created by fcx on 15/8/25. 6 | // Copyright (c) 2015年 fcx. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface RefreshViewController : UIViewController 12 | 13 | 14 | /** 15 | * 是否自动加载更多,默认上拉超过scrollView的内容高度时,直接加载更多 16 | */ 17 | @property (nonatomic, unsafe_unretained) BOOL autoLoadMore; 18 | 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /RefreshDemo/RefreshViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // RefreshViewController.m 3 | // RefreshDemo 4 | // 5 | // Created by fcx on 15/8/25. 6 | // Copyright (c) 2015年 fcx. All rights reserved. 7 | // 8 | 9 | #import "RefreshViewController.h" 10 | #import "FCXRefreshFooterView.h" 11 | #import "FCXRefreshHeaderView.h" 12 | #import "UIScrollView+FCXRefresh.h" 13 | 14 | static NSString *const FCXRefreshCellReuseID = @"FCXRefreshCellReuseID"; 15 | 16 | @interface RefreshViewController () 17 | { 18 | NSInteger _rows; 19 | UITableView *_tableView; 20 | FCXRefreshHeaderView *_headerView; 21 | FCXRefreshFooterView *_footerView; 22 | } 23 | 24 | 25 | @end 26 | 27 | @implementation RefreshViewController 28 | 29 | - (void)viewDidLoad { 30 | [super viewDidLoad]; 31 | self.view.backgroundColor = [UIColor whiteColor]; 32 | if ([self respondsToSelector:@selector(automaticallyAdjustsScrollViewInsets)]) { 33 | self.automaticallyAdjustsScrollViewInsets = NO; 34 | } 35 | self.title = @"上下拉刷新"; 36 | 37 | _rows = 12; 38 | _tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 64, self.view.frame.size.height, [UIScreen mainScreen].bounds.size.height - 64) style:UITableViewStylePlain]; 39 | _tableView.delegate = self; 40 | _tableView.dataSource = self; 41 | _tableView.rowHeight = 60; 42 | [_tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:FCXRefreshCellReuseID]; 43 | [self.view addSubview:_tableView]; 44 | 45 | [self addRefreshView]; 46 | } 47 | 48 | - (void)addRefreshView { 49 | __weak __typeof(self)weakSelf = self; 50 | 51 | //下拉刷新 52 | _headerView = [_tableView addHeaderWithRefreshHandler:^(FCXRefreshBaseView *refreshView) { 53 | [weakSelf refreshAction]; 54 | }]; 55 | 56 | //上拉加载更多 57 | _footerView = [_tableView addFooterWithRefreshHandler:^(FCXRefreshBaseView *refreshView) { 58 | [weakSelf loadMoreAction]; 59 | }]; 60 | 61 | //自动刷新 62 | _footerView.autoLoadMore = self.autoLoadMore; 63 | } 64 | 65 | - (void)refreshAction { 66 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 67 | _rows = 12; 68 | [_tableView reloadData]; 69 | [_headerView endRefresh]; 70 | }); 71 | } 72 | 73 | - (void)loadMoreAction { 74 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 75 | _rows += 12; 76 | [_tableView reloadData]; 77 | if (_rows > 24) { 78 | [_footerView showNoMoreData]; 79 | }else { 80 | [_footerView endRefresh]; 81 | } 82 | }); 83 | } 84 | 85 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 86 | return _rows; 87 | } 88 | 89 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 90 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:FCXRefreshCellReuseID forIndexPath:indexPath]; 91 | cell.textLabel.text = [NSString stringWithFormat:@"%ld", indexPath.row + 1]; 92 | return cell; 93 | } 94 | 95 | @end 96 | -------------------------------------------------------------------------------- /RefreshDemo/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // RefreshDemo 4 | // 5 | // Created by fcx on 15/8/25. 6 | // Copyright (c) 2015年 fcx. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /RefreshDemo/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // RefreshDemo 4 | // 5 | // Created by fcx on 15/8/25. 6 | // Copyright (c) 2015年 fcx. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "RefreshViewController.h" 11 | 12 | static NSString *const CellReuseID = @"CellReuseID"; 13 | 14 | @interface ViewController () 15 | 16 | 17 | @end 18 | 19 | @implementation ViewController 20 | 21 | - (void)viewDidLoad { 22 | [super viewDidLoad]; 23 | self.title = @"上下拉刷新"; 24 | 25 | UITableView *tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 64, self.view.frame.size.height, [UIScreen mainScreen].bounds.size.height - 64) style:UITableViewStylePlain]; 26 | tableView.delegate = self; 27 | tableView.dataSource = self; 28 | tableView.rowHeight = 60; 29 | [tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:CellReuseID]; 30 | [self.view addSubview:tableView]; 31 | } 32 | 33 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 34 | return 2; 35 | } 36 | 37 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 38 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellReuseID forIndexPath:indexPath]; 39 | 40 | if (indexPath.row == 0) { 41 | cell.textLabel.text = @"主动上拉加载"; 42 | }else { 43 | cell.textLabel.text = @"自动上拉加载"; 44 | } 45 | return cell; 46 | } 47 | 48 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 49 | [tableView deselectRowAtIndexPath:indexPath animated:NO]; 50 | 51 | RefreshViewController *refreshVC = [[RefreshViewController alloc] init]; 52 | if (indexPath.row == 1) { 53 | refreshVC.autoLoadMore = YES; 54 | } 55 | [self.navigationController pushViewController:refreshVC animated:YES]; 56 | } 57 | 58 | @end 59 | -------------------------------------------------------------------------------- /RefreshDemo/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // RefreshDemo 4 | // 5 | // Created by fcx on 15/8/25. 6 | // Copyright (c) 2015年 fcx. 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 | -------------------------------------------------------------------------------- /RefreshDemoTests/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 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /RefreshDemoTests/RefreshDemoTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // RefreshDemoTests.m 3 | // RefreshDemoTests 4 | // 5 | // Created by fcx on 15/8/25. 6 | // Copyright (c) 2015年 fcx. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface RefreshDemoTests : XCTestCase 13 | 14 | @end 15 | 16 | @implementation RefreshDemoTests 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 | --------------------------------------------------------------------------------