iOS-UITableView你需要掌握的屬性

背景

  • 在現(xiàn)今的開發(fā)中,UITableView和UICollectionView算是最最流行的控件了,基本上每一個應用內部都會多次使用到這類控件,它們統(tǒng)一都繼承自UIScrollView
  • 平時我們都會用它們來展示數(shù)據(jù),但是也有很多情況,比如頁面上下拖動的時候導航欄透明度改變、一個工具欄在頁面向上拖動到一定程度后懸浮到一個位置不動了、再比如簡書的個人頁面,頭像在導航欄上,頭像會隨著頁面的上下拖動變大變小、再比如上拉下拉刷新的實現(xiàn)、再比如點擊狀態(tài)欄,tabbleView如果不是在最頂部,那么它會立即滾動到頁面最頂部等等等等,這些效果全部都是通過UIScrollView的一些屬性實現(xiàn)的
  • 而且這類控件也算是我們開發(fā)中最基本的控件了,基本我們天天都需要和它們打交道,所以說,掌握它們的使用不僅僅是對我們最基本的要求,也可以讓我們實現(xiàn)很多效果,但是這些都需要建立在對它們一些易混淆屬性理解的基礎之上
  • 本文將以UITableView為例說明下它的一些關鍵屬性,并結合一些屬性簡單實現(xiàn)下拉刷新
  • 先來看下這篇文章最后結合相關屬性講解的一個小Demo效果
refresh.gif

知識點

1)contenSize -- 滾動視圖內容的尺寸

  • 這個屬性是CGSize類型的,它決定了你的滾動視圖是否能滾動,能夠滾動多遠
  • 這個屬性對于實現(xiàn)我們本文要講解的下拉刷新是至關重要的,我們需要明確contenSize包含了tabbleview的什么內容,也就是什么內容才算是contenSize的一部分
  • 除了UITableviewCell屬于contenSize的一部分之外,tabbleview的頭部和尾部視圖也算是它的contenSize的一部分
  • 如果設置了內邊距,那么內邊距是不算contenSize的一部分的
  • 如果給tabbleview添加子控件,這個子控件也不屬于contenSize的一部分
  • 而且給scrollview內部子控件添加約束時,最頭疼的其實就是這個contenSize,它的contenSize需要根據(jù)子控件的尺寸以及子控件與scrollview之間的間距計算
偏移量.png

2)contentOffset -- 偏移量

  • 是一個CGPoint類型的屬性,一般而言,上下滑動,我們需要它的contentOffset.y,左右滑動我們需要它的contentOffset.x
  • 這是一個滾動視圖最最基本的屬性,也是最重要的屬性,基本上,上述所有效果都是基于它來實現(xiàn)的
  • 當tabbleview是在一個導航條下面的話,那么系統(tǒng)會自動將tabbleview內容增加64的頂部內邊距,因此它的偏移量y值默認是-64
  • 我們可以這樣去理解它,以一個上下滾動的tabbleview為例,contentOffset.y = tabbleview的frame的左上角的y值 - tabbleview的內容的左上角的y值,而且這個坐標系以tabbleview的內容的左上角為坐標原點
坐標系.png

3)showsHorizontalScrollIndicatorshowsVerticalScrollIndicator

  • 是BOOL類型的,決定了是否隱藏水平或者垂直方法滾動條,之所以提及這2個屬性是要說一個注意點,比如我們在使用scrollview時,如果我們需要遍歷scrollview的子控件數(shù)組,我們就需要注意這2個控件,它也算scrollview的子控件

4)scrollsToTop

  • 一個BOOL類型的屬性,可以控制點擊狀態(tài)欄,是否讓不在頂部的滾動視圖回到最頂部
  • 屬性默認為YES,也就是系統(tǒng)默認幫我們實現(xiàn)了這個效果
  • 需要說明的是如果頁面有2個及以上滾動視圖的時候,你需要控制哪一個滾動視圖支持scrollsToTop,哪些不支持

5)estimatedHeight --- 估算高度

  • 這里針對tabbleview說一下這個屬性,因為tabbleview不需要我們自己計算contensize,所以默認情況下,tabbleview都是先調用heightForRow方法然后再去調用cellForRow方法,而且heightForRow會根據(jù)當前tabbleview有多少行就去調用多少次,無論是否cell當前被展示

  • 如果我們給了tabbleview一個估算高度,那么它可以減少heightForRow方法的調用頻率,延遲計算目前不需要展示cell的高度,需要展示再去計算,這個也算是這個屬性的優(yōu)點

  • 它也是有一定缺點的,既然是估算高度,那我們給多少算合適的,其實給多給少都不太好,給少了,它調用heightForRow方法就會多,給少了,雖然調用heightForRow方法少,但是tabbleview計算它的contensize的誤差就越大,明顯效果就是滾動條的高度很奇怪(跳躍性很大),所以還是根據(jù)cell平均值給一個估算高度

6)cellForRowAtIndexPath和indexPathForSelectedRow

  • cellForRowAtIndexPath這個方法根據(jù)傳入的indexPath可以獲得顯示在tableView上的某一行cell
  • indexPathForSelectedRow這個方法可以在系統(tǒng)沒有傳入indexPath的方法或者自定義的方法中,通過該方法獲得被選中的cell的indexPath,可以得到section,row,也是非常實用的

利用偏移量簡單實現(xiàn)一下下拉刷新(仿新浪微博)

  • 其實一開始說的那些效果實現(xiàn)起來都是不難的,主要是我們需要對這些基本且關鍵屬性非常理解,知己知彼,百戰(zhàn)不殆嘛
  • 下面的這些代碼主要是關于下拉過程中,更新下拉刷新控件文字以及箭頭狀態(tài)的描述,關于發(fā)送網絡請求,這里只是模擬一下發(fā)送,新添加的數(shù)據(jù)也是假數(shù)據(jù)
  • 關于下拉刷新控件是否作為tabbleview的頭部視圖,這個我是建議不要這樣做的,因為頭部視圖一般最好是用來作為輪播器或者廣告使用,我們一般最好把刷新控件使用addSubview的方法添加到tabbleview上面最好
下拉刷新.png
/**
 *  停止拖拽,需要在這個方法里面監(jiān)聽停止拖拽的時候偏移量,根據(jù)偏移量判斷刷新控件是否完全顯示,是的話進入刷新,不是的話直接返回
 */

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
    // 如果正在刷新, 直接返回
    if (self.isHeaderRefreshing) return;

    // 當偏移量 <= offsetY時(注意正負值), 刷新控件就完全出現(xiàn)了
    CGFloat offsetY = - (self.tableView.contentInset.top + self.headerBtn.lb_height);
    [self.loadingView stopAnimating];
    self.headerBtn.imageView.hidden = NO;
    if (self.tableView.contentOffset.y <= offsetY) { // 刷新header完全出現(xiàn)了
        // 進入刷新狀態(tài)
        [self headerBeginRefresh];
    }
}
  • 還需要在scrollViewDidScroll方法中實時根據(jù)偏移量控制下拉刷新控件文字以及箭頭的狀態(tài),這個監(jiān)控狀態(tài)的代碼這里不貼出來了,放在代碼里面有,注釋也是很詳細的
  • 開始刷新方法實現(xiàn)
#pragma mark - 開始刷新
- (void)headerBeginRefresh
{
    //如果當前正在刷新,那么不往下繼續(xù)執(zhí)行
    if (self.isHeaderRefreshing) return;
    //否則,進入刷新狀態(tài)
    self.headerRefreshing = YES;

    //顯示菊花
    self.loadingView.alpha = 1.0;
    [self.loadingView startAnimating];

    [self.headerBtn setTitle:@"加載中..." forState:UIControlStateNormal];

    self.headerBtn.imageView.transform = CGAffineTransformIdentity;
    self.headerBtn.imageView.hidden = YES;

    // 顯示加載中...,這個時候這個刷新控件是會自己懸浮在導航欄下面,不需要人為拽著不松手
    //這個效果,我們可以通過增大tabbleview的內邊距來達到這個效果
    [UIView animateWithDuration:0.25f animations:^{

        //因為刷新控件的y值就是-50,它自己高度也是50,所以只需要讓tabbleview內邊距向下走50,那么刷新控件就會完全顯示了
        UIEdgeInsets inset = self.tableView.contentInset;
        inset.top += self.headerBtn.lb_height;

        self.tableView.contentInset = inset;
    }];
    //由于是模擬發(fā)送網絡請求,所以延遲1.5秒后再去加載數(shù)據(jù)
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

        // 發(fā)送請求給服務器
        [self loadNewData];
    });
}

  • 結束刷新方法實現(xiàn)
#pragma mark - 結束刷新
- (void)headerEndRefresh
{
    self.headerRefreshing = NO;
    self.headerBtn.hidden = YES;

    // 減小內邊距
    // 刷新已經停止,不需要刷新控件顯示在用戶能看到的范圍,所以需要減少tabbleview的內邊距
    [UIView animateWithDuration:0.25 animations:^{

        UIEdgeInsets inset = self.tableView.contentInset;
        inset.top -= self.headerBtn.lb_height;
        self.tableView.contentInset = inset;

    }completion:^(BOOL finished) {//刷新控件縮回到用戶看不到的位置后,更新刷新控件以及內部子控件的狀態(tài)
        self.headerBtn.hidden = NO;
        self.loadingView.alpha = 0.0;
        [self.loadingView stopAnimating];
    }];
}

ok,效果實現(xiàn)基本結束了,感謝您的閱讀,不足之處歡迎指正

點擊查看代碼實現(xiàn)

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • 《公平》 不要總說什么男女不公平,真的公平了,你想干嘛? 《區(qū)別》 女人找備胎,這跟男人搞曖昧有什么區(qū)別? 《橫行...
    何鯨洛閱讀 457評論 0 1
  • 午后,屋外淡淡陽光,清風倘佯。一壺單叢,散發(fā)著家鄉(xiāng)的味道,在午后的時光里綻放。 我不是一朵花,我是看花人。 我也不...
    夢1212閱讀 258評論 0 0
  • 初夏時分,在這逼仄的火車車廂里,空氣中夾雜著腳臭味與汗臭味,這種混合后的味道隨著呼嚕聲與嗑瓜子的聲音,一波一波地沖...
    紅葉拂水閱讀 1,066評論 44 41
  • 從某種角度來說,語言是人最親密的朋友,和人相伴終生。那些從兒童時代就掛在口頭成為生活中重要內容的詞語和句子會一直給...
    疏食遨游客閱讀 960評論 0 1

友情鏈接更多精彩內容