Swift 让我来告诉你封装下拉刷新多么简单
linger
8年前
<p style="text-align:center"><img alt="Swift 让我来告诉你封装下拉刷新多么简单" src="https://simg.open-open.com/show/41b03f3dfc9d768c37995884c3a83ff4.jpg"></p> <p>下拉刷新可以说是每个项目的必须品,最近在做一个 <code>Swift</code> 的项目,本着以锻炼自己的目的,封装了一个下拉刷新库 <code>LCRefresh</code> ,在这里分享给大家。</p> <h2>1、如何使用 LCRefresh</h2> <p>使用 <code>LCRefresh</code> 非常方便,只需添加一行代码。</p> <p>添加下拉刷新 和 上拉加载</p> <pre> <code class="language-swift">table.addRefreshHeaderWithBlock { print("Header 刷新") //TODO } table.addRefreshFooterWithBlock { print("Footer 刷新") //TODO }</code></pre> <p>完成刷新</p> <pre> <code class="language-swift">weak var weakSelf = self if weakSelf!.table.isHeaderRefreshing() { weakSelf!.table.endHeaderRefreshing() } if weakSelf!.table.isFooterRefreshing() { weakSelf!.table.endFooterRefreshing() }</code></pre> <p>数据加载完毕</p> <pre> <code class="language-swift">weakSelf!.table.setDataLoadover() weakSelf!.table.resetDataLoad()</code></pre> <p>刷新的效果图</p> <p><img alt="Swift 让我来告诉你封装下拉刷新多么简单" src="https://simg.open-open.com/show/b8ae8f90c7a41eaaa256188c72f0cdee.png"></p> <p>HeaderRefresh.png</p> <p><img alt="Swift 让我来告诉你封装下拉刷新多么简单" src="https://simg.open-open.com/show/1cd0efccae651813595e2aac5a008f81.png"></p> <p>FooterRefresh.png</p> <h2>2、如何去封装自己的刷新控件</h2> <blockquote> <p>这里分享一下封装刷新控件的心路历程</p> </blockquote> <h3>① 创建刷新视图,并创建View的各种状态</h3> <p><img alt="Swift 让我来告诉你封装下拉刷新多么简单" src="https://simg.open-open.com/show/81f0e1cff347febb329a0a63f8935ca6.jpg"></p> <p>LCRefreshHeader</p> <pre> <code class="language-swift">extension LCRefreshHeader{ /** 各种状态切换 */ private func setNomalStatus() { if activity.isAnimating() { activity.stopAnimating() } activity.hidden = true contenLab.text = "下拉可以刷新" image.hidden = false UIView.animateWithDuration(0.2) { self.image.transform = CGAffineTransformIdentity } } private func setWaitRefreshStatus() { if activity.isAnimating() { activity.stopAnimating() } activity.hidden = true contenLab.text = "松开立即刷新" image.hidden = false UIView.animateWithDuration(0.2) { self.image.transform = CGAffineTransformMakeRotation(CGFloat(-M_PI)) } } private func setRefreshingStatus() { activity.hidden = false activity.startAnimating() contenLab.text = "正在刷新数据..." image.hidden = true } }</code></pre> <h3>②拓展 <code>UIScrollView</code> 把刷新View添加在 <code>ScrollView</code> 上</h3> <pre> <code class="language-swift">/** 添加下拉刷新 */ func addRefreshHeaderWithBlock(refreshBlock:()->Void){ /** 添加header */ weak var weakSelf = self header = LCRefreshHeader.instanceFromNibBundle() as? LCRefreshHeader guard header != nil else{ print("Header加载失败") return } header!.center = LCRefreshHeaderCenter let headerView = UIView.init(frame: CGRectMake(LCRefreshHeaderX, LCRefreshHeaderY, LCRefreshScreenWidth, LCRefreshHeaderHeight)) headerView.backgroundColor = UIColor.clearColor() headerView.addSubview(header!) weakSelf!.addSubview(headerView) /** 设置代理信息 */ weakSelf!.delegate = weakSelf weakSelf!.panGestureRecognizer.addTarget(weakSelf!, action: #selector(UIScrollView.scrollViewDragging(_:))) lcHeaderBlock = refreshBlock }</code></pre> <blockquote> <p>添加视图,设置 delegate 来监测 <code>ScrollView</code> 滑动,由于是在 extension 中,delegate 中的 <code>scrollViewDidEndDragging</code> 方法无响应,最后采取了监测 <code>ScrollView</code> 的 <code>pan</code> 手势识别,来处理拖拽响应。<br> 如果你有好的建议,欢迎与我讨论</p> </blockquote> <h3>③根据<code>ScrollView</code>的 <code>contentOffset</code> 来区分是下拉刷新还是上拉加载,然后根据 <code>contentOffset</code> 的值来切换刷新View的状态</h3> <pre> <code class="language-swift">/** 滑动相关 */ public func scrollViewDidScroll(scrollView: UIScrollView) { let offSet = scrollView.contentOffset.y let scrollHeight = scrollView.bounds.size.height let inset = scrollView.contentInset var currentOffset = offSet + scrollHeight - inset.bottom let maximumOffset = scrollView.contentSize.height /** 数据未充满屏幕的情况 **/ if maximumOffset < scrollHeight { currentOffset = offSet + maximumOffset - inset.bottom } if offSet < 0 { /** 下拉刷新 */ scrollHeader(offSet) refreshObj = LCRefreshObject.Header }else if currentOffset - maximumOffset > 0 { /** 上拉刷新 */ guard footer!.refreshStatus != LCRefreshFooterStatus.Loadover else { return } scrollFooter(currentOffset - maximumOffset) refreshObj = LCRefreshObject.Footer }else{ /** 无刷新对象 */ refreshObj = LCRefreshObject.None } }</code></pre> <p>View状态切换</p> <pre> <code class="language-swift">private func scrollHeader(offSet: CGFloat) {//参数为负数 guard header != nil else{ print("Header加载失败") return } guard header!.refreshStatus != LCRefreshHeaderStatus.Refreshing else{ return } if offSet < -LCRefreshHeaderHeight { header!.setStatus(LCRefreshHeaderStatus.WaitRefresh) }else{ header!.setStatus(LCRefreshHeaderStatus.Normal) } }</code></pre> <h3>④最后拖拽结束时再根据刷新对象切换View 到刷新状态。</h3> <pre> <code class="language-swift">/** 拖拽相关 */ func scrollViewDragging(pan: UIPanGestureRecognizer){ if pan.state == .Ended{ if refreshObj == LCRefreshObject.Header { draggHeader() }else if refreshObj == LCRefreshObject.Footer{ draggFooter() } } }</code></pre> <blockquote> <p>这之间涉及到<code>contentOffset</code>值的设置,在这里就不一一明说了,给出的源码里都有。</p> </blockquote> <p>现在只是开发出了这一种样式,以后会更多的样式以供大家使用,当然,你也可以根据给出的源码自己来修改样式。</p> <p><br> 来自:http://www.jianshu.com/p/725cd8028c8a<br> </p>