iOS-----UIScrollView

在做项目是有时候会遇到设置自动滚动图片,UIScrollView是一个挺有意思东西,所以做了下总结

DEMO:

.h

#import <UIKit/UIKit.h>

@interface ImagePlayView : UIView<UIScrollViewDelegate>

@property (nonatomic, strong) UIScrollView * scroll;
@property (nonatomic, strong) UIPageControl * play;
@property (nonatomic, strong) NSTimer * timer;

@end

.m

#import "ImagePlayView.h"

// 定义图片的总数

#define ImageCount 3;

@implementation ImagePlayView

- (id) initWithFrame:(CGRect)frame
{
    if (self = [super initWithFrame:frame])
    {
        // 创建一个UIscrollView组件,作为滚动组件的头视图
        CGRect headScroll = CGRectMake(0, 0, self.frame.size.width, self.frame.size.height);
        _scroll = [[UIScrollView alloc] initWithFrame:headScroll];
        // 取消水平滚动条
        _scroll.showsHorizontalScrollIndicator = NO;
        // 取消弹性设置
        _scroll.bounces = NO;
        // 设置分页
        _scroll.pagingEnabled = YES;
        [self addSubview: _scroll];
// 循环创建多个UIImageView for (int i = 0; i < ImageCount ; i ++) { UIImageView * imageV = [[UIImageView alloc] initWithFrame:CGRectMake(i * self.frame.size.width, 0, self.frame.size.width, self.frame.size.height)]; imageV.image = [UIImage imageNamed:[NSString stringWithFormat:@"banner-%d",i + 1]]; [_scroll addSubview: imageV]; } _scroll.contentSize = CGSizeMake(3 * self.frame.size.width, 0); _scroll.delegate = self; // 设置分页指示器 _play = [[UIPageControl alloc] initWithFrame:CGRectMake(0, 0, self.frame.size.width/3, 20)]; // 设置分页器的位置 _play.center = CGPointMake(self.frame.size.width/2, self.frame.size.height/1.2); // 设置其它页指示器圆点的颜色 _play.pageIndicatorTintColor = [UIColor grayColor]; // 设置当前页指示器圆点的颜色 _play.currentPageIndicatorTintColor = [UIColor grayColor]; // 设置分页器的页数 _play.numberOfPages = ImageCount; // 设置当前是第几页 _play.currentPageIndicatorTintColor = 0; [self addSubview:_play]; //设置计时器 _timer = [NSTimer scheduledTimerWithTimeInterval:1.0
target:self
selector:@selector(time)
userInfo:nil repeats:YES]; // 先获取当前的消息循环,利用消息循环设置计时器对象的优先级和控件的优先级相同 NSRunLoop *runLoop = [NSRunLoop currentRunLoop]; [runLoop addTimer:self.timer forMode:NSRunLoopCommonModes]; } return self; } -(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView { // 解决第一个Bug:按住滚动内容拖拽或不松手,一旦松手就会滚动好多次。
// 解决方法当开始拖动时令计时器失效。当拖动结束后再新建一个计时器
[self.timer invalidate]; // 计时器一旦失效,就不能再使用了
// 所以赋给它一个空指针
self.timer = nil; } // 在UIScrollView拖动的过程中会执行这个方法 -(void)scrollViewDidScroll:(UIScrollView *)scrollView { // 先获根据内容的偏移位置,获取当前的页数 int page =( scrollView.contentOffset.x+scrollView.frame.size.width*0.5)/ scrollView.frame.size.width; // 在拖动的过程中把当前的页码告知分页控制器组件 self.play.currentPage = page; } // 在拖动结束后会执行这个方法 -(void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate { // 当拖动结束后再新建一个计时器, 第一个Bug解除了 self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0
target:self
selector:@selector(time)
userInfo:nil
repeats:YES
]; // 解决第二个BUg:当拖动点击别的控件时。
// 将停止滚动,这是由于单线程执行,而计时器对象和网络对象的优先级小于控件的优先级,所以当拖动控件时,就不会再执行NSTimer 计时器对象的操作。
// 解决方法如下:每当新建一个NSTimer计时器,就先获取当前的消息循环,并在消息循环中设置
NSTimer的优先级和控件的优先级相同 ,这时 程序会分时间片给优先级相同的对象;
NSRunLoop *runRoop = [NSRunLoop currentRunLoop];
// 获取当前的消息循环
// 利用消息循环为timer对象设置优先级和控件的优先级相同

[runRoop addTimer:self.timer forMode:NSRunLoopCommonModes];
}

// NSTimer处理事件的方法
- (void) time {

// 获取当前的页数

// 0,1,2

    NSInteger page = self.play.currentPage;
    if (page == self.play.numberOfPages-1) {
        page = 0;
    }else{
        page++;
    }
    
    // 根据当前的页数计算内容偏移量contentOffset的大小
    // 通过代码设置contentOffset偏移,实现自动滚动
    // 非动画方式
    //self.scrollView.contentOffset = CGPointMake(page*self.scrollView.frame.size.width, 0);
    
    // 通过动画方式
    [self.scroll setContentOffset:CGPointMake(page*self.scroll.frame.size.width, 0) animated:YES];

}

@end
posted @ 2015-11-10 12:03    阅读(213)  评论(0编辑  收藏  举报