iOS ScrollView 下拉放大 升级 带上下拉刷新
在上一篇《iOS ScrollView 下拉放大》已经介绍了基本的下拉放大,接下来再加上下拉刷新
定义下拉刷新状态
typedef enum { RefreshStateIdle, RefreshStatePullRefresh, RefreshStateReadyRefresh, RefreshStateRefreshing } RefreshState;
定义下拉刷新需使用的变量
{ // Refresh UILabel *_refreshLabel; RefreshState _refreshState; CGFloat _refreshHeight; }
下拉刷新的实现是在下拉刷的新阀值detal小于下拉放大阀值alpha的基础上进行的,接下来就初始化下拉刷新的变量了
_refreshState = RefreshStateIdle; _refreshHeight = 40; _refreshLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, - _refreshHeight, self.view.bounds.size.width, _refreshHeight)]; _refreshLabel.textAlignment = NSTextAlignmentCenter; _refreshLabel.textColor = [UIColor redColor]; _refreshLabel.text = @"刷新..."; [self.view addSubview:_refreshLabel];
然后改造ScrollView代理方法了,在处理下拉放大的过程中同时处理下拉刷新
#pragma mark - ScrollView Delegate - (void)scrollViewDidScroll:(UIScrollView *)scrollView { if (_refreshState == RefreshStateRefreshing) { return; } CGFloat offsetY = scrollView.contentOffset.y; NSLog(@"offsetY: %f",offsetY); CGFloat top = scrollView.contentInset.top; if (!_zoomIn) { if (offsetY < -top) { // 下拉 CGRect frame = _zoomView.frame; frame.origin.y = offsetY; frame.size.height = -offsetY; _zoomView.frame = frame; // 处理下拉 if (_refreshState != RefreshStateRefreshing && !_decelerating) { frame = _refreshLabel.frame; frame.origin.y = -offsetY - top; _refreshLabel.frame = frame; if ((-offsetY - top) < _refreshHeight) { [self setRefreshState:RefreshStatePullRefresh]; } else { [self setRefreshState:RefreshStateReadyRefresh]; } } if (!_decelerating && -offsetY > 1.9 * _zoomHeight) { [self setRefreshState:RefreshStateIdle]; frame.origin.y = -_refreshHeight; _refreshLabel.frame = frame; scrollView.contentInset = UIEdgeInsetsMake(scrollView.bounds.size.height, 0, 0, 0); frame.origin.y = -scrollView.bounds.size.height; frame.size.height = scrollView.bounds.size.height; _zoomView.frame = frame; _zoomIn = YES; scrollView.contentSize = CGSizeMake(0, 1); // 使上拉有弹簧效果 } } } else { // 上拉 if (!_decelerating && (offsetY + top) / top > 0.3) { scrollView.contentInset = UIEdgeInsetsMake(_zoomHeight, 0, 0, 0); CGRect frame = _zoomView.frame; frame.origin.y = -_zoomHeight; frame.size.height = _zoomHeight; _zoomView.frame = frame; _zoomIn = NO; scrollView.contentSize = CGSizeMake(0, _contentSize.height); // 恢复正常 } } } - (void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView { _decelerating = YES; } - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { _decelerating = NO; } - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate { if (_refreshState == RefreshStateRefreshing) { return; } CGRect frame = _refreshLabel.frame; if (_refreshState == RefreshStateReadyRefresh) { [self setRefreshState:RefreshStateRefreshing]; frame.origin.y = 0; } else { [self setRefreshState:RefreshStateIdle]; frame.origin.y = -_refreshHeight; } _refreshLabel.frame = frame; } #pragma mark - Refresh - (void)setRefreshState:(RefreshState)state { _refreshState = state; if (_refreshState == RefreshStateIdle) { _refreshLabel.text = @"下拉刷新"; } else if (_refreshState == RefreshStatePullRefresh) { _refreshLabel.text = @"下拉刷新"; } else if (_refreshState == RefreshStateReadyRefresh) { _refreshLabel.text = @"松开刷新"; } else if (_refreshState == RefreshStateRefreshing) { _refreshLabel.text = @"刷新..."; [self loadData]; } }
处理滑动的过程中,如果当前正在刷新那么立即返回。下拉过程中根据offsetY值判断到达阀值,在到达刷新阀值detal后并且没有达到放大阀值alpha,那么松手的时候就进入刷新状态,没有达到下拉刷新阀值detal就松手的情况下就恢复正常。如果在达到下拉刷新阀值detal后继续下拉到达放大阀值,那么就将刷新状态置为idle,同时隐藏刷新View,做放大操作。
当然,刷新完成后还要报告刷新完成,以处理刷新View
#pragma mark - Load Data - (void)loadData { __weak typeof(self) weakSelf = self; dispatch_async(dispatch_get_global_queue(0, 0), ^{ sleep(5); dispatch_async(dispatch_get_main_queue(), ^{ if (weakSelf) { __strong typeof(weakSelf) strongSelf = weakSelf; [strongSelf refreshFinish]; } }); }); } - (void)refreshFinish { [self setRefreshState:RefreshStateIdle]; CGRect frame = _refreshLabel.frame; frame.origin.y = -_refreshHeight; _refreshLabel.frame = frame; }