IBTRefreshTableView.m 9.34 KB
//
//  IBTRefreshTableView.m
//  XFFruit
//
//  Created by Xummer on 4/11/15.
//  Copyright (c) 2015 Xummer. All rights reserved.
//

#import "IBTRefreshTableView.h"

@interface IBTRefreshTableView ()
{
    BOOL _loading;
}

@property (strong, nonatomic) UIView *refreshFooterView;
@property (assign) BOOL footerAnimating;

@end

@implementation IBTRefreshTableView

#pragma mark - Life Cycle
- (id)initWithFrame:(CGRect)frame style:(UITableViewStyle)style {
    self = [super initWithFrame:frame style:style];
    if (self) {
        
    }
    return self;
}

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        
    }
    return self;
}

- (void)awakeFromNib {
    [super awakeFromNib];
}

- (void)layoutSubviews {
    [super layoutSubviews];
    
    if (_refreshFooterView) {
        CGRect frame = _refreshFooterView.frame;
        frame.origin.y = self.contentSize.height;
        _refreshFooterView.frame = frame;
    }
}

- (void)didMoveToWindow {
    [super didMoveToWindow];
    
    if (!self.window) {
        if (_refreshControl) {
            [_refreshControl endRefreshing];
        }
        
        if (_refreshFooterView) {
            [_loadMoreView updateState:kLoadStateNormal];
        }
    }
    
}

#pragma mark - Setter
- (void)setRefreshFooterView:(UIView *)refreshFooterView {
    if (_refreshFooterView != refreshFooterView) {
        [_refreshFooterView removeFromSuperview];
        _refreshFooterView = refreshFooterView;
        [self addSubview:refreshFooterView];
        
        [self setNeedsLayout];
    }
}

#pragma mark - Over Write
- (void)reloadData {
    [super reloadData];
    CGRect bounds = self.bounds;
    CGSize size = self.contentSize;
    UIEdgeInsets inset = self.contentInset;
    if (size.height < bounds.size.height - inset.bottom ||
        [self.dataSource tableView:self numberOfRowsInSection:0] == 0) {
        self.refreshFooterView = nil;
    }
    else {
        self.refreshFooterView = _loadMoreView;
    }
}

- (void)scrollToTopAnimated:(BOOL)animated {
    [self setContentOffset:CGPointZero animated:animated];
}

- (void)scrollToBottomAnimated:(BOOL)animated {
    
    //    CGFloat vh = [self getVisibleHeight];
    //
    //    [self setContentOffset:CGPointMake(0, self.contentSize.height - vh) animated:animated];
    
    NSInteger lastSection = [super numberOfSections];
    if (lastSection > 0) {
        lastSection -= 1;
    }
    else {
        return;
    }
    
    NSInteger lastRow = [super numberOfRowsInSection:lastSection];
    if (lastRow > 0) {
        lastRow -= 1;
    }
    else {
        return;
    }
    
    NSIndexPath *indexP = [NSIndexPath indexPathForRow:lastRow inSection:lastSection];
    
    [super scrollToRowAtIndexPath:indexP
                 atScrollPosition:UITableViewScrollPositionBottom
                         animated:animated];
}

- (void)addRefreshControlWithText:(NSString *)text {
    if (!_refreshControl) {
        self.refreshControl = [[UIRefreshControl alloc] init];
        [_refreshControl addTarget:self
                            action:@selector(handleRefresh:)
                  forControlEvents:UIControlEventValueChanged];
    }
    
    if (text.length > 0) {
        _refreshControl.attributedTitle = [[NSAttributedString alloc] initWithString:text];
    }
    
    if (!_refreshControl.superview) {
        [self addSubview:_refreshControl];
    }
}

- (void)removeRefreshControl {
    if (_refreshControl && _refreshControl.superview) {
        [_refreshControl removeFromSuperview];
    }
}

- (void)handleRefresh:(id)sender {
    //    UIRefreshControl *refreshControl = (UIRefreshControl *)sender;
    if ([_refreshDelegate respondsToSelector:@selector(startRefreshData:)]) {
        // Do networking in |startRefreshData:|
        [_refreshDelegate startRefreshData:self];
    }
}

- (void)endRefresh:(id)sender {
    if ([_refreshDelegate respondsToSelector:@selector(endRefreshData:)]) {
        [_refreshDelegate endRefreshData:self];
    }
    
    [self endRefreshWithState:kRefreshStateFailed];
}

- (void)endRefreshWithState:(RefreshState)state {
    //    NSString *textStr;
    //    switch (state) {
    //        case kLoadStateFinished:
    //            textStr = @"刷新成功";
    //            break;
    //        case kLoadStateFailed:
    //            textStr = @"刷新失败";
    //            break;
    //        case kRefreshStateTimeOut
    //            textStr = @"连接超时";
    //            break;
    //        default:
    //            break;
    //    }
    //
    //    if (textStr.length > 0) {
    //        _refreshControl.attributedTitle = [[NSAttributedString alloc] initWithString:textStr];
    //    }
    
    if (_refreshControl.refreshing) {
        [_refreshControl endRefreshing];
        
        // Fix ContentInset became -60 when UIRefreshController endRefreshing
        // http://stackoverflow.com/questions/20101572/ios7-uirefreshcontrol-changes-contentinset
        if (self.contentInset.top < 0) {
            UIEdgeInsets inset = self.contentInset;
            inset.top = 0;
            self.contentInset = inset;
        }
    }
}

- (void)addLoadMoreFootWithText:(NSString *)text {
    if (!_loadMoreView) {
        CGRect frame = (CGRect){
            .origin.x = 0,
            .origin.y = 0,
            .size.width = CGRectGetWidth(self.bounds),
            .size.height = 44
        };
        self.loadMoreView = [[IBTScrollLoadMoreView alloc] initWithFrame:frame];
        _loadMoreView.textColor = [UIColor grayColor];
        
        _loadMoreView.loadMoreText = text;
    }
    
    self.refreshFooterView = _loadMoreView;
    [_loadMoreView updateState:kLoadStateNormal];
}

- (void)removeLoadMoreFoot {
    if (self.refreshFooterView == _loadMoreView) {
        self.refreshFooterView = nil;
    }
}

- (void)endLoadMoreWithState:(LoadMoreState)state {
    if (self.refreshFooterView) {
        [_loadMoreView updateState:state];
        
        _loading = NO;
        
        if ([_refreshDelegate respondsToSelector:@selector(endLoadMoreData:)]) {
            [_refreshDelegate endLoadMoreData:self];
        }
        
        [self hideLoadMoreView];
    }
}

- (void)resetLoadMoreFoot {
    [self endLoadMoreWithState:kLoadStateNormal];
}

- (void)endLoadWithFailed {
    [self endLoadMoreWithState:kLoadStateFailed];
}

- (void)hideLoadMoreView {
    if (UIEdgeInsetsEqualToEdgeInsets(self.contentInset, UIEdgeInsetsZero)) {
        return;
    }
    
    if (_footerAnimating) {
        [self performSelector:@selector(hideLoadMoreView) withObject:nil afterDelay:.2f];
        return;
    }
    
    _footerAnimating = YES;
    [UIView animateWithDuration:.2f
                     animations:^{
                         self.contentInset = UIEdgeInsetsZero;
                     }
                     completion:^(BOOL finished) {
                         _footerAnimating = NO;
                     }];
}

- (void)showLoadMoreView {
    UIEdgeInsets insets = UIEdgeInsetsMake(0, 0, CGRectGetHeight(_loadMoreView.frame), 0);
    if (UIEdgeInsetsEqualToEdgeInsets(self.contentInset, insets)) {
        return;
    }
    
    if (_footerAnimating) {
        [self performSelector:@selector(showLoadMoreView) withObject:nil afterDelay:.2f];
        return;
    }
    
    _footerAnimating = YES;
    [UIView animateWithDuration:.2f
                     animations:^{
                         self.contentInset = insets;
                     }
                     completion:^(BOOL finished) {
                         _footerAnimating = NO;
                     }];
}

- (void)tableViewDidScroll:(UIScrollView *)scrollView {
    
    if (!_refreshFooterView) {
        return;
    }
    if (_loadMoreView.currentState == kLoadStateLoading) {
        CGFloat offsetH = CGRectGetHeight(_loadMoreView.frame);
        scrollView.contentInset = UIEdgeInsetsMake(0, 0, offsetH, 0);
    }
    else if (scrollView.isDragging) {
        
        CGFloat maxOffsetY = scrollView.contentSize.height - CGRectGetHeight(scrollView.frame);
        
        //        NSLog(@" %f - %f", scrollView.contentOffset.y, maxOffsetY );
        
        if (_loadMoreView.currentState == kLoadStateDraging &&
            scrollView.contentOffset.y > maxOffsetY &&
            scrollView.contentOffset.y < maxOffsetY + CGRectGetHeight(_loadMoreView.frame) &&
            !_loading)
        {
            [_loadMoreView updateState:kLoadStateNormal];
        }
        else if ((_loadMoreView.currentState == kLoadStateNormal ||
                  _loadMoreView.currentState >= kLoadStateFinished) &&
                 scrollView.contentOffset.y > maxOffsetY + CGRectGetHeight(_loadMoreView.frame) &&
                 !_loading)
        {
            [_loadMoreView updateState:kLoadStateDraging];
        }
        
        if (scrollView.contentInset.bottom != 0) {
            scrollView.contentInset = UIEdgeInsetsZero;
        }
    }
}

- (void)tableviewDidEndDragging:(UIScrollView *)scrollView {
    
    CGFloat maxOffsetY = scrollView.contentSize.height - CGRectGetHeight(scrollView.frame);
    if (scrollView.contentOffset.y >= maxOffsetY + CGRectGetHeight(_loadMoreView.frame) &&
        !_loading) {
        
        _loading = YES;
        [_loadMoreView updateState:kLoadStateLoading];
        
        [self showLoadMoreView];
        
        if ([_refreshDelegate respondsToSelector:@selector(startLoadMoreData:)]) {
            [_refreshDelegate startLoadMoreData:self];
        }
    }
}

@end