ifish/Ifish/controllers/IfishTabControllers/消息/IfishIMFiles/Sessions/View/NTESPageView.m

327 lines
8.8 KiB
Objective-C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// NTESPageView.m
// NIM
//
// Created by chris on 15/12/16.
// Copyright © 2015年 Netease. All rights reserved.
//
#import "NTESPageView.h"
@interface NTESPageScrollView : UIScrollView
@end
@interface NTESPageView ()
{
NSInteger _currentPage;
NSInteger _currentPageForRotation;
}
@property (nonatomic,strong) NSMutableArray *pages;
- (void)setupControls;
//重新载入的流程
- (void)calculatePageNumbers;
- (void)reloadPage;
- (void)raisePageIndexChangedDelegate;
@end
@implementation NTESPageView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
[self setupControls];
}
return self;
}
- (id)initWithCoder:(NSCoder *)aDecoder
{
if (self = [super initWithCoder:aDecoder])
{
[self setupControls];
}
return self;
}
- (void)setFrame:(CGRect)frame{
CGFloat originalWidth = self.frame.size.width;
[super setFrame:frame];
if (originalWidth != frame.size.width) {
[self reloadData];
}
}
- (void)dealloc
{
_scrollView.delegate = nil;
}
- (void)layoutSubviews
{
[super layoutSubviews];
[_scrollView setFrame:self.bounds];
CGSize size = self.bounds.size;
[self.scrollView setContentSize:CGSizeMake(size.width * [self.pages count], size.height)];
for (NSInteger i = 0; i < [self.pages count]; i++)
{
id obj = [self.pages objectAtIndex:i];
if ([obj isKindOfClass:[UIView class]])
{
[(UIView *)obj setFrame:CGRectMake(size.width * i, 0, size.width, size.height)];
}
}
//CGSize size = self.bounds.size;
BOOL animation = NO;
if (self.pageViewDelegate && [self.pageViewDelegate respondsToSelector:@selector(needScrollAnimation)])
{
animation = [self.pageViewDelegate needScrollAnimation];
}
[self.scrollView scrollRectToVisible:CGRectMake(_currentPage * size.width, 0, size.width, size.height)
animated:animation];
}
- (void)setupControls
{
if (_scrollView == nil)
{
_scrollView = [[NTESPageScrollView alloc]initWithFrame:self.bounds];
_scrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
[self addSubview:_scrollView];
_scrollView.pagingEnabled = YES;
_scrollView.showsVerticalScrollIndicator = NO;
_scrollView.showsHorizontalScrollIndicator = NO;
_scrollView.delegate = self;
_scrollView.scrollsToTop = NO;
}
}
#pragma mark - 对外接口
- (void)scrollToPage: (NSInteger)page
{
if (_currentPage != page || page == 0)
{
_currentPage = page;
[self reloadData];
}
}
- (void)reloadData
{
[self calculatePageNumbers];
[self reloadPage];
}
- (UIView *)viewAtIndex: (NSInteger)index
{
UIView *view = nil;
if (index >= 0 && index < [_pages count])
{
id obj = [_pages objectAtIndex:index];
if ([obj isKindOfClass:[UIView class]])
{
view = obj;
}
}
return view;
}
- (NSInteger)currentPage
{
return _currentPage;
}
- (NSInteger)pageInBound:(NSInteger)value min:(NSInteger)min max:(NSInteger)max{
if (max < min) {
max = min;
}
NSInteger bounded = value;
if (bounded > max) {
bounded = max;
}
if (bounded < min) {
bounded = min;
}
return bounded;
}
#pragma mark - Page载入和销毁
- (void)loadPagesForCurrentPage:(NSInteger)currentPage
{
NSUInteger count = [_pages count];
if (count == 0)
{
return;
}
NSInteger first = [self pageInBound:currentPage - 1 min:0 max:count - 1];
NSInteger last = [self pageInBound:currentPage + 1 min:0 max:count - 1];
NSRange range = NSMakeRange(first, last - first + 1);
for (NSUInteger index = 0; index < count; index++)
{
if (NSLocationInRange(index, range))
{
id obj = [_pages objectAtIndex:index];
if (![obj isKindOfClass:[UIView class]])
{
if (_dataSource && [_dataSource respondsToSelector:@selector(pageView:viewInPage:)])
{
UIView *view = [_dataSource pageView:self viewInPage:index];
[_pages replaceObjectAtIndex:index withObject:view];
[self.scrollView addSubview:view];
CGSize size = self.bounds.size;
[view setFrame:CGRectMake(size.width * index, 0, size.width, size.height)];
}
else
{
assert(0);
}
}
}
else
{
id obj = [_pages objectAtIndex:index];
if ([obj isKindOfClass:[UIView class]])
{
[obj removeFromSuperview];
[_pages replaceObjectAtIndex:index withObject:[NSNull null]];
}
}
}
}
- (void)calculatePageNumbers
{
NSInteger numberOfPages = 0;
for (id obj in _pages)
{
if ([obj isKindOfClass:[UIView class]])
{
[(UIView *)obj removeFromSuperview];
}
}
if(_dataSource && [_dataSource respondsToSelector:@selector(numberOfPages:)])
{
numberOfPages = [_dataSource numberOfPages:self];
}
self.pages = [NSMutableArray arrayWithCapacity:numberOfPages];
for (NSInteger i = 0; i < numberOfPages; i ++)
{
[_pages addObject:[NSNull null]];
}
//注意这里设置delegate是因为计算contentsize的时候会引起scrollViewDidScroll执行修改currentpage的值这样在贴图举个例子前面的分类页数比后面的分类页数多前面的分类滚动到最后面一页后再显示后面的分类会显示不正确
self.scrollView.delegate = nil;
CGSize size = self.bounds.size;
[self.scrollView setContentSize:CGSizeMake(size.width * numberOfPages, size.height)];
self.scrollView.delegate = self;
}
- (void)reloadPage
{
//reload的时候尽量记住上次的位置
if (_currentPage >= [_pages count])
{
_currentPage = [_pages count] - 1;
}
if (_currentPage < 0)
{
_currentPage = 0;
}
[self loadPagesForCurrentPage:_currentPage];
[self raisePageIndexChangedDelegate];
[self setNeedsLayout];
}
#pragma mark - ScrollView Delegate
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
CGFloat width = scrollView.bounds.size.width;
CGFloat offsetX = scrollView.contentOffset.x;
NSInteger page = (NSInteger)(fabs(offsetX / width));
if (page >= 0 && page < [_pages count])
{
if (_currentPage == page) {
return;
}
_currentPage = page;
[self loadPagesForCurrentPage:_currentPage];
}
if (_pageViewDelegate && [_pageViewDelegate respondsToSelector:@selector(pageViewDidScroll:)])
{
[_pageViewDelegate pageViewDidScroll:self];
}
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
[self raisePageIndexChangedDelegate];
}
#pragma mark - 辅助方法
- (void)raisePageIndexChangedDelegate
{
if (_pageViewDelegate && [_pageViewDelegate respondsToSelector:@selector(pageViewScrollEnd:currentIndex:totolPages:)])
{
[_pageViewDelegate pageViewScrollEnd:self
currentIndex:_currentPage
totolPages:[_pages count]];
}
}
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
duration:(NSTimeInterval)duration
{
_scrollView.delegate = nil;
_currentPageForRotation = _currentPage;
}
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
duration:(NSTimeInterval)duration
{
CGSize size = self.bounds.size;
_scrollView.contentSize = CGSizeMake(size.width * [_pages count], size.height);
for (NSUInteger i = 0; i < [_pages count]; i++)
{
id obj = [_pages objectAtIndex:i];
if ([obj isKindOfClass:[UIView class]])
{
[(UIView *)obj setFrame:CGRectMake(size.width * i, 0, size.width, size.height)];
/*
//这里有点ugly,先这样吧...
if ([obj respondsToSelector:@selector(reset)])
{
[obj performSelector:@selector(reset)];
}*/
}
}
_scrollView.contentOffset = CGPointMake(_currentPageForRotation * self.bounds.size.width, 0);
_scrollView.delegate = self;
}
@end
@implementation NTESPageScrollView
//fix: swipe to delete in a UITableView which is embeded in a UIScrollView
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRequireFailureOfGestureRecognizer:(nonnull UIGestureRecognizer *)otherGestureRecognizer
{
return [otherGestureRecognizer.view.superview isKindOfClass:[UITableView class]];
}
@end