不借助第三方插件利用ScrollView自身delegate實現下拉刷新和上拉加載

下拉刷新功能基本上在所有的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];


這裏的準備工作其實就是在scrollview裏面先加入一個activityIndicator和一個label

下拉刷新

// 下拉刷新
- (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 ++;
            ...
        }];
    }
}














發佈了83 篇原創文章 · 獲贊 24 · 訪問量 34萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章