下拉刷新功能基本上在所有的app中都會被用到,而且這個功能已經被apple集成進去了,不過必須得是在tableViewController中才有,是一個叫做UIRefreshControl的控件,想看效果可以看手機QQ上面聯繫人列表下拉後的刷新。這裏不多介紹。
本篇blog主要介紹如何在scrollview中實現下拉刷新的效果。因爲有些時候我們可能更多地希望直接在scrollview中展現,而不是一定要侷限於tableviewcontroller。
當然網上有很多下拉刷新和上拉加載的第三方控件,但是我這個人還是喜歡用系統原生API自己來做,一方面更能把原理吃透,另一方面方便自己定義。
好了,廢話不多說了,直接上代碼:
準備工作:
// 設置下拉刷新的process和label
self.indicatorView = [[UIActivityIndicatorView alloc]initWithFrame:CGRectMake(self.frame.size.width/2 - 50, -25, 20, 20)];
[self.indicatorView setColor:[UIColor blackColor]];
self.pullRefreshLabel = [[UILabel alloc]initWithFrame:CGRectMake(self.frame.size.width/2 -20, -30, 90, 30)];
self.pullRefreshLabel.font = [UIFont fontWithName:@"heiti SC" size:14];
[self.pullRefreshLabel setText:@"下拉刷新"];
[self.scroll_view addSubview:self.indicatorView];
[self.scroll_view addSubview:self.pullRefreshLabel];
[self.scroll_view bringSubviewToFront:self.indicatorView];
[self.scroll_view bringSubviewToFront:self.pullRefreshLabel];
下拉刷新
// 下拉刷新
- (void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView{
if (scrollView.contentOffset.y < -50 ) {
[UIView animateWithDuration:1.0 animations:^{
// frame發生偏移,距離頂部50的距離(可自行設定)
[scrollView setContentInset:UIEdgeInsetsMake(30, 0, 0, 0)];
[self.indicatorView startAnimating];
} completion:^(BOOL finished) {
// 發起網絡請求
...
[self.indicatorView stopAnimating];
[self.pullRefreshLabel setText:@"下拉刷新"];
[scrollView setContentInset:UIEdgeInsetsMake(0, 0, 0, 0)];
// 將當前頁面置爲1
currentPage = 1;
}];
}
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
// 保持indecator的位置一直在頂端
if( scrollView.contentOffset.y < -50){
[self.pullRefreshLabel setText:@"鬆開刷新"];
self.indicatorView.frame = CGRectMake(self.frame.size.width/2-50, scrollView.contentOffset.y+20 ,30, 30);
self.pullRefreshLabel.frame = CGRectMake(self.frame.size.width/2-20, scrollView.contentOffset.y+20, 100, 30);
}else{
self.indicatorView.frame = CGRectMake(self.frame.size.width/2-50, -30 ,30, 30);
self.pullRefreshLabel.frame = CGRectMake(self.frame.size.width/2-20, -30, 100, 30);
}
}
注意兩個代理不要用錯了。一個是WillBeginDecelerating ,一個是didScroll
willBeginDecelerating就是我們往下拉scrollview然後鬆手的時候,這個代理方法會去檢測當前scrollview的contentoffset,然後根據下拉的程度決定是否進行刷新操作。這裏我定義的閾值是50
然後爲了使提示刷新的label和activityIndicator保持在一個固定的高度,就是不隨着scrollview的往下拉而一直往下走,在didScroll代理裏面計算了一下它們的位置。
上拉加載:
/ 上拉繼續獲取
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate{
/*
* 關鍵-->
* scrollView一開始並不存在偏移量,但是會設定contentSize的大小,所以contentSize.height永遠都會比contentOffset.y高一個手機屏幕的
* 高度;上拉加載的效果就是每次滑動到底部時,再往上拉的時候請求更多,那個時候產生的偏移量,就能讓contentOffset.y + 手機屏幕尺寸高大於這
* 個滾動視圖的contentSize.height
*/
if (scrollView.contentOffset.y + scrollView.frame.size.height >= scrollView.contentSize.height+50) {
// [UIView commitAnimations];
[UIView animateWithDuration:1.0 animations:^{
// frame發生的偏移量,距離底部往上提高50(可自行設定)
scrollView.contentInset = UIEdgeInsetsMake(0, 0, 50, 0);
} completion:^(BOOL finished) {
scrollView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0);
// 發送網絡請求
currentPage ++;
...
}];
}
}