UIScrollView是iOS中非常常见的一个控件, 通常结合UIPageControl实现如下的滚动效果:
使用起来比较方便, 以下实例创建一个包含三个UIImageView的UIScrollView, 将其放在UITableView的headerView中.
准备工作
let gScreenWidth: CGFloat = UIScreen.mainScreen().bounds.size.width
let gScreenHeight: CGFloat = UIScreen.mainScreen().bounds.size.height
let gScrollViewImagesCount = 3
@IBOutlet weak var tableView: UITableView!
var headerView: UIView!
var scrollView: UIScrollView!
var pageControl: UIPageControl!
var timerScrollView: NSTimer!
其中, UIPageControl用来管理UIScrollView的scroll效果, NSTimer用来实现UIScrollView的自动滚动.
添加UIScrollView
func initScrollView() {
let scrollY: CGFloat = 0
headerView = UIView(frame: CGRectMake(0, scrollY, gScreenWidth, 300))
scrollView = UIScrollView(frame: CGRectMake(0, scrollY, headerView.frame.width, headerView.frame.height))
scrollView.delegate = self
scrollView.bounces = false
scrollView.pagingEnabled = true
scrollView.showsHorizontalScrollIndicator = false
scrollView.showsVerticalScrollIndicator = false
scrollView.directionalLockEnabled = true
scrollView.contentSize = CGSizeMake(gScreenWidth * CGFloat(gScrollViewImagesCount), scrollView.frame.height)
for(var i=0;i<gScrollViewImagesCount;i++) {
let iv: UIImageView = UIImageView(frame: CGRectMake(gScreenWidth * CGFloat(i), scrollY, gScreenWidth, scrollView.frame.height))
iv.image = UIImage(named: "sv\(i+1)")
scrollView.addSubview(iv)
}
headerView.addSubview(scrollView)
}
这里, 将三个UIImageView并列放置在UIScrollView中.
1. 设置scrollView.pagingEnabled = true, 则每一次滚动停止后UIImageView都是完整的, 不会出现只显示一般的情况.
2. 有时候会出现UIScrollView中的内容上下可以滚动的情况, 设置如下即可:
scrollView.contentSize = CGSizeMake(gScreenWidth * CGFloat(gScrollViewImagesCount), 0)
添加UIPageControl
func initPageControl() {
let pageCtlWidth: CGFloat = 180
let pageCtlHeight: CGFloat = 20
pageControl = UIPageControl(frame: CGRectMake((gScreenWidth - pageCtlWidth)/2, headerView.frame.height - pageCtlHeight, pageCtlWidth, pageCtlHeight))
pageControl.numberOfPages = gScrollViewImagesCount
pageControl.pageIndicatorTintColor = UIColor.grayColor()
pageControl.currentPageIndicatorTintColor = UIColor.whiteColor()
headerView.addSubview(pageControl)
}
UIPageControl的currentPage即对应当前显示的UIImageView.
添加NSTimer
func initTimerScrollView() {
timerScrollView = NSTimer.scheduledTimerWithTimeInterval(3, target: self, selector: Selector("nextImageScrollView"), userInfo: nil, repeats: true)
// 将timer加到NSRunLoop中, 才不会出现被scrollView和tableView等reset的情况
NSRunLoop.currentRunLoop().addTimer(self.timerScrollView, forMode: NSRunLoopCommonModes)
}
func invalideTimerScrollView() {
if (self.timerScrollView != nil) {
self.timerScrollView.invalidate()
}
}
func nextImageScrollView() {
if (pageControl != nil) {
var page: Int = pageControl.currentPage
page++;
if (page == gScrollViewImagesCount) {
page = 0
}
let point: CGPoint = CGPointMake(gScreenWidth * CGFloat(page), 0)
scrollView.setContentOffset(point, animated: true)
}
}
在定时操作中, 使用UIScrollView的setContentOffSet方法实现其滚动. 而UIPageControl的currentPage的设置可以放在这里, 但本实例将其放在下文中的一个delegate方法中.
注意
NSTimer与UIScrollView, UITableView同时使用的时候, 要注意使用NSRunLoop:
// 将timer加到NSRunLoop中, 才不会出现被scrollView和tableView等reset的情况
NSRunLoop.currentRunLoop().addTimer(self.timerScrollView, forMode: NSRunLoopCommonModes)
实现UIScrollViewDelegate协议中的方法
UIScrollViewDelegate协议包含了UIScrollView的相关方法, scrollViewDidScroll中实现UIScrollView与UIPageControl的同步.
// MARK: - scrollView delegate
func scrollViewDidScroll(scrollView: UIScrollView) {
if let sv = self.scrollView {
self.pageControl.currentPage = Int(sv.contentOffset.x / gScreenWidth + 0.5)
}
}
func scrollViewWillBeginDragging(scrollView: UIScrollView) {
self.invalideTimerScrollView()
}
func scrollViewDidEndDragging(scrollView: UIScrollView, willDecelerate decelerate: Bool) {
self.initTimerScrollView()
}
此外, 还有scrollViewDidEndDecelerating方法在滚动停止后调用.
Demo
Demo地址: DemoScrollViewPageControl