澎湃iPad上线版本

UIScrollView+GifPullToRefresh.m 11KB

    // // UIScrollView+GifPullToRefresh.m // CHGifRefreshControl // // Created by HangChen on 12/1/13. // Copyright (c) 2013 Hang Chen (https://github.com/cyndibaby905) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #import "UIScrollView+GifPullToRefresh.h" #import <objc/runtime.h> #define GifRefreshControlHeight 110 @interface CHGifRefreshControl() - (void)removeObservers; @end typedef enum { GifPullToRefreshStateDrawing = 0, GifPullToRefreshStateLoading, } GifPullToRefreshState; static char UIScrollViewGifPullToRefresh; @implementation UIScrollView (GifPullToRefresh) - (void)setRefreshControl:(CHGifRefreshControl *)pullToRefreshView { [self willChangeValueForKey:@"UIScrollViewGifPullToRefresh"]; objc_setAssociatedObject(self, &UIScrollViewGifPullToRefresh, pullToRefreshView, OBJC_ASSOCIATION_ASSIGN); [self didChangeValueForKey:@"UIScrollViewGifPullToRefresh"]; } - (CHGifRefreshControl *)refreshControl { return objc_getAssociatedObject(self, &UIScrollViewGifPullToRefresh); } - (void)addPullToRefreshWithDrawingImgs:(NSArray*)drawingImgs andLoadingImgs:(NSArray*)loadingImgs andActionHandler:(void (^)(void))actionHandler { CHGifRefreshControl *view = [[CHGifRefreshControl alloc] initWithFrame:CGRectMake(0, -GifRefreshControlHeight, self.bounds.size.width, GifRefreshControlHeight)]; if ([[UIDevice currentDevice].systemVersion floatValue] >= 7.0) { view.originalContentInsectY = 64; } view.scrollView = self; view.pullToRefreshActionHandler = actionHandler; view.drawingImgs = drawingImgs; view.loadingImgs = loadingImgs; [self addSubview:view]; self.refreshControl = view; } - (void)removePullToRefresh { [self.refreshControl removeObservers]; } - (void)didFinishPullToRefresh:(void (^)(void))animate completion:(void (^)(void))completion { [self.refreshControl endLoading:^{ if (animate) { animate(); } } completion:^{ if (completion) { completion(); } }]; } @end @implementation CHGifRefreshControl { GifPullToRefreshState _state; BOOL _isTrigged; UIImageView *_refreshView; UILabel *_refreshTimeLabel; NSDate *_lastUpdateDate; } - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { self.backgroundColor = [UIColor clearColor]; _refreshView = [[UIImageView alloc] initWithFrame:self.bounds]; _refreshView.contentMode = UIViewContentModeScaleAspectFit; _refreshView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; [self addSubview:_refreshView]; _refreshTimeLabel = [[UILabel alloc]initWithFrame:CGRectMake(0, CGRectGetHeight(self.bounds)-20, CGRectGetWidth(self.bounds), 18)]; _refreshTimeLabel.textColor = [UIColor colorWithHexString:TextGray]; _refreshTimeLabel.font = appFont(15, NO); _refreshTimeLabel.textAlignment = NSTextAlignmentCenter; _refreshTimeLabel.autoresizingMask = AutoresizingAuto; _refreshTimeLabel.backgroundColor = [UIColor clearColor]; _refreshTimeLabel.text = @"刚刚"; [self addSubview:_refreshTimeLabel]; } return self; } - (void)dealloc { [self removeObservers]; } - (void)removeObservers { [_scrollView removeObserver:self forKeyPath:@"contentOffset"]; [_scrollView removeObserver:self forKeyPath:@"pan.state"]; _scrollView = nil; } - (void)setScrollView:(UIScrollView *)scrollView { [self removeObservers]; _scrollView = scrollView; [_scrollView addObserver:self forKeyPath:@"contentOffset" options:NSKeyValueObservingOptionNew context:nil]; [_scrollView addObserver:self forKeyPath:@"pan.state" options:NSKeyValueObservingOptionNew context:nil]; } - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { // 刷新操作:栏目导航页和频道页刷新时异常(bug:5968) 首页:快速多次下拉刷新,会卡住(bug:5967) if (_state == GifPullToRefreshStateLoading) { _refreshTimeLabel.text = getUpdateStringFromDate(_lastUpdateDate); _refreshTimeLabel.hidden = NO; return; } if (self.scrollView.contentOffset.y + self.originalContentInsectY <= 0) { if ([keyPath isEqualToString:@"pan.state"]) { if (self.scrollView.panGestureRecognizer.state == UIGestureRecognizerStateEnded && _isTrigged) { [self setState:GifPullToRefreshStateLoading]; [UIView animateWithDuration:0.2 delay:0 options:UIViewAnimationOptionAllowUserInteraction|UIViewAnimationOptionBeginFromCurrentState animations:^{ self.scrollView.contentOffset = CGPointMake(0, -GifRefreshControlHeight - self.originalContentInsectY); self.scrollView.contentInset = UIEdgeInsetsMake(GifRefreshControlHeight + self.originalContentInsectY, 0.0f, 0.0f, 0.0f); } completion:^(BOOL finished) { if (self.pullToRefreshActionHandler) { self.pullToRefreshActionHandler(); } }]; }else if (self.scrollView.panGestureRecognizer.state == UIGestureRecognizerStateBegan) { _refreshTimeLabel.text = getUpdateStringFromDate(_lastUpdateDate); _refreshTimeLabel.hidden = NO; } } else if([keyPath isEqualToString:@"contentOffset"]){ [self scrollViewContentOffsetChanged]; } } } - (void)manulHeadRefresh { [self setState:GifPullToRefreshStateLoading]; [UIView animateWithDuration:0.2 delay:0 options:UIViewAnimationOptionAllowUserInteraction|UIViewAnimationOptionBeginFromCurrentState animations:^{ self.scrollView.contentOffset = CGPointMake(0, -GifRefreshControlHeight-self.topicFrangePageInsectY ); self.scrollView.contentInset = UIEdgeInsetsMake(GifRefreshControlHeight+self.topicFrangePageInsectY, 0.0f, 0.0f, 0.0f); } completion:^(BOOL finished) { if (self.pullToRefreshActionHandler) { self.pullToRefreshActionHandler(); } }]; } - (void)scrollViewContentOffsetChanged { if (_state != GifPullToRefreshStateLoading) { if (self.scrollView.isDragging && self.scrollView.contentOffset.y + self.originalContentInsectY < -GifRefreshControlHeight && !_isTrigged) { _isTrigged = YES; } else { if (self.scrollView.isDragging && self.scrollView.contentOffset.y + self.originalContentInsectY > -GifRefreshControlHeight) { _isTrigged = NO; } [self setState:GifPullToRefreshStateDrawing]; } } } - (void)setState:(GifPullToRefreshState)aState{ CGFloat offset = -(self.scrollView.contentOffset.y + self.originalContentInsectY); CGFloat percent = 0; if (offset < 0) { offset = 0; } if (offset > GifRefreshControlHeight) { offset = GifRefreshControlHeight; } percent = offset / GifRefreshControlHeight; NSUInteger drawingIndex = percent * (self.drawingImgs.count - 1); switch (aState) { case GifPullToRefreshStateDrawing: [_refreshView stopAnimating]; _refreshView.image = self.drawingImgs[drawingIndex]; break; case GifPullToRefreshStateLoading: _refreshView.animationImages = self.loadingImgs; _refreshView.animationDuration = (CGFloat)self.loadingImgs.count/40.0; [_refreshView startAnimating]; break; default: break; } _state = aState; } - (void)endLoading:(void (^)(void))animate completion:(void (^)(void))completion { if (_state == GifPullToRefreshStateLoading || _state == GifPullToRefreshStateDrawing) { _isTrigged = NO; [self setState:GifPullToRefreshStateDrawing]; if (animate) { animate(); } [UIView animateWithDuration:0.35 delay:0 options:UIViewAnimationOptionAllowUserInteraction|UIViewAnimationOptionBeginFromCurrentState animations:^{ _refreshTimeLabel.hidden = YES; self.scrollView.contentInset = UIEdgeInsetsMake(self.originalContentInsectY, 0.0f, 0.0f, 0.0f); } completion:^(BOOL finished) { _lastUpdateDate = [NSDate date]; if (completion) { completion(); } }]; // [UIView animateWithDuration:0.2 animations:^{ // // } completion:^(BOOL finished) { // [UIView animateWithDuration:0.35 // delay:0 // options:UIViewAnimationOptionAllowUserInteraction|UIViewAnimationOptionBeginFromCurrentState // animations:^{ // _refreshTimeLabel.hidden = YES; // self.scrollView.contentInset = UIEdgeInsetsMake(self.originalContentInsectY, 0.0f, 0.0f, 0.0f); // } // completion:^(BOOL finished) { // _lastUpdateDate = [NSDate date]; // if (completion) { // completion(); // } // }]; // }]; } } @end