[iOS]UIScrollview自定义分页的实现方法
来源:互联网 发布:apache c cgi 编辑:程序博客网 时间:2024/04/28 11:19
UIScrollView
及其子类UITableView
, UICollectionView
为iOS开发带来了极大的方便, 其分页(pagingEnabled
)功能也很常用, 但是功能却有些局限, 页只能按UIScrollview
的bounds
尺寸划分, 如果要实现自定义分页宽度或高度就需要一些技巧.
方法一
类似iOS 6中MobileSafari, 如图所示的分页方法:
StackOverflow上提供的实现思路如下:
- 将
UIScrollview
的bounds
限制再屏幕中间那一页的位置 - 禁用
UIScrollview
的clipsToBouds
, 从而能显示超出bounds
的内容
此时已经可以在借助UIScrollview
原有分页功能的基础上实现了"视觉上"与MobileSafari类似的效果, 但因为UIScrollview
的尺寸限制, 超出范围的触摸事件不会被UIScrollview
收到, 影响体验, 要把触摸事件传递给UIScrollview
, 方法如下:
- 用一个全屏的(或者其他你想要的尺寸)
UIView
子类, 这里我们命名为CustomUIView
来做UIScrollview
的superView
重写
CustomUIView
的hitTest:withEvent
方法:- (UIView *) hitTest:(CGPoint) point withEvent:(UIEvent *)event { if ([self pointInside:point withEvent:event]) { return scrollView; } return nil; }
通过重写hitTest, 就可以将
CustomUIView
接受到的触摸事件传递给UIScrollView
方法二
前一种方法保留了UIScrollView
原有的分页功能, 而下面这种更加灵活的自定义分页方法则完全自制了一个分页功能:
DMPagingScrollView就是一个很好的实现, 其自定义分页的思路大致如下(需要参考DMPagingScrollView.m代码):
- 用实例变量
pageWidth
记录自定义分页的宽度 - 通过实现
UIScrollView
的delegate方法, 来记录每次拖动UIScrollView
动作的相关参数(位移, 加速度…) - 在
scrollViewDidEndDecelerating:
等一些标志拖动结束的delegate方法中调用snapToPage
方法, 在snapToPage
方法中, 借助之前收集的动作参数计算出contentOffset
, 并通过setContentOffset:offset animated:YES
来移动.
这种方式的关键就在contentOffset
的计算中(DMPagingScrollView.m pageOffsetForComponent:
方法), 如果计算的不正确, 就会严重影响拖动UIScrollView
的手感.
DMPagingScrollView通过subclassing UIScrollview
将自定义分页相关的过程操作封装在DMPagingScrollView
里面, 同时支持横向纵向的自定义分页, 十分方便. 类似地, 我们也可以对UITableView
,UICollectionView
进行同样的处理.
此外, 通过参考pageOffsetForComponent:
中的计算方法, 我们甚至可以让每一页的宽度都不同, 从而大大提升了分页的灵活性, 比如我实现的这种:
- (CGFloat)pageOffset { CGFloat totalWidth = self.collectionView.contentSize.width; CGFloat visibleWidth = self.collectionView.bounds.size.width; CGFloat currentOffset = self.collectionView.contentOffset.x; CGFloat dragVelocity = _dragVelocity.x; CGFloat dragDisplacement = _dragDisplacement.x; NSInteger nearestIndex = 0; CGFloat minDis = CGFLOAT_MAX; CGFloat nearestOffset = 0; CGFloat prevOffset = 0; CGFloat nextOffset = 0; CGFloat totalOffset = 0; // self.pagesWidths is an NSArray that contains each page's width for (NSInteger i = 0; i < self.pagesWidths.count; i++) { CGFloat dis = ABS(totalOffset - currentOffset); if (dis < minDis) { minDis = dis; prevOffset = nearestOffset; nearestOffset = totalOffset; if (i == self.pagesWidths.count - 1) { nextOffset = totalOffset; } else { nextOffset = totalOffset + [(NSNumber *)self.pagesWidths[i] floatValue]; } } totalOffset += [(NSNumber *)self.pagesWidths[i] floatValue]; } NSInteger lowerIndex; NSInteger upperIndex; CGFloat lowerOffset; CGFloat upperOffset; if (currentOffset - nearestOffset < 0) { lowerIndex = nearestIndex - 1; upperIndex = nearestIndex; lowerOffset = prevOffset; upperOffset = nearestOffset; } else { lowerIndex = nearestIndex; upperIndex = nearestIndex + 1; lowerOffset = nearestOffset; upperOffset = nextOffset; } CGFloat newOffset; if (ABS(dragDisplacement) < DRAG_DISPLACEMENT_THRESHOLD || dragDisplacement * dragVelocity < 0) { if (currentOffset - lowerOffset > upperOffset - currentOffset) { newOffset = upperOffset; } else { newOffset = lowerOffset; } } else { if (dragVelocity > 0) { newOffset = upperOffset; } else { newOffset = lowerOffset; } } if (newOffset > totalWidth - visibleWidth) newOffset = totalWidth - visibleWidth; if (newOffset < 0) newOffset = 0; return newOffset;}
- [iOS]UIScrollview自定义分页的实现方法
- UIScrollView实现自定义分页的大小
- UIScrollView分页的实现
- UIScrollView分页的实现
- UIScrollView分页的实现
- 实现UIScrollView的分页
- 可自定义分页宽度的UIScrollView(Swift实现)
- iOS UIScrollView中实现分页滚动--定时自动滚动分页
- IOS中表格的实现方法:UIScrollView+UILabel
- iOS UIScrollView循环拖动的思路和实现方法
- iOS: UIScrollView的方法flashScrollIndicators
- iOS: UIScrollView的方法touchesShouldCancelInContentView:
- ios UIScrollView 分页显示
- UIScrollView的分页效果的实现
- block代替协议自定义UIScrollView实现分页效果
- UIScrollView代理方法的实现
- UIScrollView实现分页
- UIScrollView实现分页效果
- 深入分析JavaWeb 33 -- 开发自己简易的JDBC框架
- 从头认识Spring-3.2 简单的AOP日志实现-需要记录方法的运行时间
- 在Eclipse中,如何把一个java项目变成web项目?
- Log4j配置详细说明
- C#中窗体渐显渐隐
- [iOS]UIScrollview自定义分页的实现方法
- Android,iOS打开手机QQ与指定用户聊天界面
- js 检测输入框变更
- Innodb索引和锁的学习笔记
- Ubuntu加挂新硬盘全套解决方案
- Skia图片解码模块流程分析
- 从Hadoop到Spark的架构实践
- 深入分析JavaWeb 34 -- DBUtils框架学习
- asp.net经典问题之“未将对象引用设置到对象的实例”