您的当前位置:首页正文

iOS横向滚动视图自定义封装

来源:华拓网

适用人群:iOS开发人员。
本文内容:iOS横向滚动视图自定义封装。

视图内容如下图:

record.gif

代码展示&使用举例:

1.ScrollPageView.h代码如下:

#import <UIKit/UIKit.h>

@interface ScrollPageView : UIView

/** 总页数 */
@property (nonatomic, assign) NSInteger pageNum;
/** YES 还有上一页 */
@property (nonatomic, assign, readonly) BOOL hasLastPage;
/** YES 还有下一页 */
@property (nonatomic, assign, readonly) BOOL hasNextPage;

/** 自定义pageView */
@property (nonatomic, strong) void(^addScrollPageView)(UIView *pageView, NSInteger currentIndex);
/** pageView点击事件 */
@property (nonatomic, strong) void(^pageViewDidClicked)(UIView *pageView, NSInteger currentIndex);
/** pageView滚动事件 */
@property (nonatomic, strong) void(^pageViewDidScroll)(UIView *pageView, NSInteger currentIndex);

/** 调用show显示视图 */
- (void)show;

/** 滚动到上一页 */
- (void)scrollToLastPage;

/** 滚动到下一页 */
- (void)scrollToNextPage;

@end
2.ScrollPageView.m代码如下:
#import "ScrollPageView.h"

static NSInteger const BasePageViewTag = 100;

@interface ScrollPageView()<UIScrollViewDelegate>

@property (nonatomic, assign) NSInteger currentIndex;

@property (nonatomic, assign) CGFloat spacing;
@property (nonatomic, assign) CGFloat pageWidth;
@property (nonatomic, assign) CGFloat pageHeight;

@property (nonatomic, strong) UIScrollView *scrollView;

@end

@implementation ScrollPageView

- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        self.backgroundColor = [UIColor whiteColor];
        [self addSubview:self.scrollView];
        
        self.pageNum = 0;
        self.currentIndex = 0;
        self.spacing = 10;
        self.pageWidth = self.frame.size.width-_spacing*4;
        self.pageHeight = self.frame.size.height;
    }
    return self;
}

- (void)show {
    CGFloat spacing = _spacing;
    CGFloat pageWidth = _pageWidth;
    CGFloat pageHeight = _pageHeight;
    for (int i=0; i<self.pageNum; i++) {
        UIView *pageView = [[UIView alloc] initWithFrame:CGRectMake(pageWidth*i+spacing*2+spacing*i, 0, pageWidth, pageHeight)];
        pageView.tag = BasePageViewTag+i;
        UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(pageViewClicked:)];
        [pageView addGestureRecognizer:tap];
        if (self.addScrollPageView) {
            self.addScrollPageView(pageView, i);
        }
        [self.scrollView addSubview:pageView];
    }
    
    CGFloat scrollViewContentWidth = spacing*2*2+pageWidth*self.pageNum+spacing*(self.pageNum-1);
    [self.scrollView setContentSize:CGSizeMake(scrollViewContentWidth, pageHeight)];
}

- (BOOL)hasLastPage {
    return self.currentIndex>0;
}

- (BOOL)hasNextPage {
    return self.currentIndex<self.pageNum-1;
}

- (void)scrollToLastPage {
    if (self.hasLastPage) {
        CGFloat offsetX = self.scrollView.contentOffset.x - (_pageWidth+_spacing);
        [self.scrollView setContentOffset:CGPointMake(offsetX, 0) animated:YES];
        self.currentIndex --;
        if (self.pageViewDidScroll) {
            self.pageViewDidScroll(self.scrollView.subviews[self.currentIndex], self.currentIndex);
        }
    }
}

- (void)scrollToNextPage {
    if (self.hasNextPage) {
        CGFloat offsetX = self.scrollView.contentOffset.x + (_pageWidth+_spacing);
        [self.scrollView setContentOffset:CGPointMake(offsetX, 0) animated:YES];
        self.currentIndex ++;
        if (self.pageViewDidScroll) {
            self.pageViewDidScroll(self.scrollView.subviews[self.currentIndex], self.currentIndex);
        }
    }
}

#pragma mark - action

- (void)pageViewClicked:(UITapGestureRecognizer *)sender {
    if (self.pageViewDidClicked) {
        self.pageViewDidClicked(sender.view, sender.view.tag-BasePageViewTag);
    }
}

#pragma mark - scrollViewDelegate

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
    [self updateScrollViewContentOffset:scrollView];
}

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
    [self updateScrollViewContentOffset:scrollView];
}

#pragma mark - privite method

- (void)updateScrollViewContentOffset:(UIScrollView *)scrollView {
    CGFloat offsetX = scrollView.contentOffset.x;
    
    CGFloat spacing = _spacing;
    CGFloat pageWidth = _pageWidth;
    
    CGFloat lastPageCenterX = 0;
    for (int i=0; i<self.pageNum; i++) {
        CGFloat pageCenterX = spacing*2+pageWidth/2.0+pageWidth*i+spacing*i;
        if (lastPageCenterX < offsetX && offsetX <= pageCenterX) {
            [scrollView setContentOffset:CGPointMake(pageCenterX-pageWidth/2.0-spacing*2, 0) animated:YES];
            self.currentIndex = i;
            if (self.pageViewDidScroll) {
                self.pageViewDidScroll(self.scrollView.subviews[self.currentIndex], self.currentIndex);
            }
            break;
        } else {
            lastPageCenterX = pageCenterX;
        }
    }
}

#pragma mark - lazy load

- (UIScrollView *)scrollView {
    if (!_scrollView) {
        _scrollView = [[UIScrollView alloc] initWithFrame:self.bounds];
        _scrollView.delegate = self;
        _scrollView.backgroundColor = [UIColor clearColor];
        _scrollView.showsHorizontalScrollIndicator = NO;
        //UIScrollViewDecelerationRateNormal:正常减速(默认值)
        //UIScrollViewDecelerationRateFast:快速减速
        _scrollView.decelerationRate = UIScrollViewDecelerationRateFast;//快速减速
    }
    return _scrollView;
}

3.使用举例如下:

在新建工程自带ViewController界面更改:

#import "ViewController.h"
#import "ScrollPageView.h"

@interface ViewController ()

@property (nonatomic, strong) ScrollPageView *scrollPageView;

@property (nonatomic, strong) UIButton *lastPageButton;
@property (nonatomic, strong) UIButton *nextPageButton;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    ScrollPageView *view = [[ScrollPageView alloc] initWithFrame:CGRectMake(0, 200, self.view.frame.size.width, 150)];
    view.pageNum = 4;
    view.addScrollPageView = ^(UIView *pageView, NSInteger currentIndex) {
        NSArray *colors = @[[UIColor redColor], [UIColor yellowColor], [UIColor blueColor], [UIColor greenColor]];
        pageView.backgroundColor = colors[currentIndex];
    };
    view.pageViewDidClicked = ^(UIView *pageView, NSInteger currentIndex) {
        NSLog(@"page view did clicked at index : %ld", currentIndex);
    };
    __weak typeof (ViewController *) _self = self;
    view.pageViewDidScroll = ^(UIView *pageView, NSInteger currentIndex) {
        [_self pageViewDidScroll];
    };
    [view show];
    self.scrollPageView = view;
    [self.view addSubview:_scrollPageView];
    
    UIButton *lastPageButton = [UIButton buttonWithType:UIButtonTypeCustom];
    lastPageButton.frame = CGRectMake(100, 400, 100, 50);
    [lastPageButton setTitle:@"上一页" forState:UIControlStateNormal];
    [lastPageButton setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
    [lastPageButton setTitleColor:[UIColor grayColor] forState:UIControlStateDisabled];
    [lastPageButton addTarget:self action:@selector(lastPageButtonAction:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:lastPageButton];
    self.lastPageButton = lastPageButton;
    lastPageButton.enabled = NO;
    
    UIButton *nextPageButton = [UIButton buttonWithType:UIButtonTypeCustom];
    nextPageButton.frame = CGRectMake(200, 400, 100, 50);
    [nextPageButton setTitle:@"下一页" forState:UIControlStateNormal];
    [nextPageButton setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
    [nextPageButton setTitleColor:[UIColor grayColor] forState:UIControlStateDisabled];
    [nextPageButton addTarget:self action:@selector(nextPageButtonAction:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:nextPageButton];
    self.nextPageButton = nextPageButton;
}

- (void)lastPageButtonAction:(UIButton *)sender {
    [_scrollPageView scrollToLastPage];
}

- (void)nextPageButtonAction:(UIButton *)sender {
    [_scrollPageView scrollToNextPage];
}

- (void)pageViewDidScroll {
    self.lastPageButton.enabled = self.scrollPageView.hasLastPage;
    self.nextPageButton.enabled = self.scrollPageView.hasNextPage;
}