• (九)UIScrollView和PageControl的分页


    涉及到内容的滚动与拖拽,使用UIScrllView。

    对于滚动的多张图片,由于超出屏幕,应该使用代码添加代码。

    添加的细节是:图片的宽高即为滚动视图的宽高,图片的y=0,x=图片的序号乘以图片的宽度。

    为了美观,还应该去掉水平滚动条,代码为:

    self.scrollView.showsHorizontalScrollIndicator = NO;

    一定不要忘了设定滚动范围:这里仅仅进行水平滚动,因此垂直滚动范围为0,即当前视图宽度。

    CGFloat contentW = imageCount * self.imageW;
    self.scrollView.contentSize = CGSizeMake(contentW, 0);

    这样可以实现多张图片,但是滑动时无法自动停留在一个图片上,而会卡在中间,这需要分页来解决。

    self.scrollView.pagingEnabled = YES;
    启动分页以后,会自动根据ScrollView的宽度进行分页。

    为了用户体验,应该用小圆点来指示总页数和当前位置,这个控件称为Page Control。

    但是在动态添加图片时会盖住这个控件,因此可以采用另一个插入方法,指定将视图插入到index=0处(最顶层,也就是最下层)。

    [self.scrollView insertSubview:imageView atIndex:0];

    另一个细节,为了将Page Control设置在UIScrollView的上层,又要在其上方,直接拖动会使得UIScrollView将其吸收,可以通过直接修改y值来实现拖动。

    为了得到当前页码供Page Control切换,应该设置ScrollView的代理,设置代理的另一种方法是在ScrollView上右键拖线到当前根视图View。

    Tip:代理方法的命名规范,以类名开头

    为了算出页码,可以根据contentOffset方法来判断。

    用下面的方法来切换页码即可:页码总数用numberOfPages来设置。

    self.pageControl.currentPage = self.scrollView.contentOffset.x / self.imageW;

    这样的缺点是如果右边的图片占优势,无法动态的切换页码,为了动态的切换原点,应该在contentOffset基础上加上一半图片宽度,来达到准确修改页码。

    - (void)scrollViewDidScroll:(UIScrollView *)scrollView{
        self.pageControl.currentPage = (self.scrollView.contentOffset.x + self.imageW * 0.5) / self.imageW;
    }

    但是这样似乎会出现问题,使劲点击小圆点圆点会前进。只需要禁用Page Control的Enable属性即可解决。


    实现自动翻页:

    要借助定时器,NSTimer或者CADisplayLink,后者适合用来做游戏,可以实现短时间间隔。做事的频率低,用NSTimer。因此这里使用NSTimer。

    Tip:schedu...方法不用使用fire可以自动开始。

    [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(nextImage) userInfo:nil repeats:YES];

    Tip:定时器执行的是target的@selector中的方法。

    Tip:ScrollView自带动画。方法有animated参数。

    为了自动切换页码,注意的是不要直接修改pageControl的currentPage,因为前面的委托函数会实时检测当前位置,会引起冲突,应该弄一个临时变量来获取和达到下一页,真正的currentPage依然由委托实现。

    - (void)nextImage{
        //1.增加Page Control的页码
        int page = 0;
        if (self.pageControl.currentPage == imageCount - 1) {
            page = 0;
        }else{
            page = self.pageControl.currentPage + 1;
        }
        CGPoint offset = CGPointMake(page * self.imageW, 0);
        [self.scrollView setContentOffset:offset animated:YES];
    }

    问题一:

    单线程工作,如果有其他滚动操作,就不能自动翻页了。

    问题二:

    如果按住页码不让跳,定时器无法跳转,会累计定时器的次数,在松手时一次性跳完。


    问题二的解决方法是在用户拽住的时候停止定时器,松手的时候再开启定时器,应该用代理。

    Tip:定时器禁用后无法再启用,因此应该重新定义定时器。

    - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView{
        [self.timer invalidate];
        self.timer = nil;
    }
    
    - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate{
        self.timer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(nextImage) userInfo:nil repeats:YES];
    }

    问题一的解决:

    一个程序默认会开一个线程(主线程),处理UI界面和事件。

    注意,UI界面的刷新只能交给主线程来做。

    因此应该时分复用来处理每个内容。

    应该通过获取当前的消息循环(RunLoop),来将定时器的优先级提高。

    Tip:在学习一个方法时,如果一个参数不是枚举而是字符串,那么字符串一般是和这个方法在同一个文件中用宏进行定义的,因此可以在上面查到。

    提高定时器优先级的方法为:

    [[NSRunLoop currentRunLoop ] addTimer:self.timer forMode:NSRunLoopCommonModes];

    Tip:以后使用定时器一定要小心,否则容易造成定时器不响应而引发问题。


    问题三:如果图片的数量非常的多,那么提前创建这么多ImageView是不明智的。

    一种方法是用到的时候再创建(类似TableCell的思路),另一种方法是循环利用这些ImageView。

    用三个ImageView就可以实现这种循环。

    无限滚动的另一个好处就是最后一张向右拖动到第一张,第一张向左拖动到最后一张。

    重点是代理方法(didScroll)。

    这种方式适用于大量图片。

  • 相关阅读:
    VIM于换行EOL的思考
    wp7给图片和按钮添加背景图片
    wp7打开加速度传感器
    java值传递、引用传递
    keychron k1长时间不使用蓝牙,蓝牙连接不上解决方案
    IE浏览器切换64位和32位
    文件和注册表的重定向解决方法
    Windows C++遍历所有进程的命令行
    c++ fstream open 失败原因
    解析wrk压测工具
  • 原文地址:https://www.cnblogs.com/aiwz/p/6154244.html
Copyright © 2020-2023  润新知