聊天介面-自適應文字,聊天介面自適應

來源:互聯網
上載者:User

聊天介面-自適應文字,聊天介面自適應

該篇文章主要介紹一個實現聊天介面的思路過程,源碼可以在 源碼連結 獲得,該工程實現聊天的準系統,功能還不夠完善,歡迎大家提PR,如下所示

我希望通過相對簡單的方式實現介面的布局,沒有複雜的計算達到自適應的效果。

iOS8新功能介紹

雖然self size cell最終沒有在我的工程中用到,但是這是我曾經挖過的坑,所以在此做了簡單的介紹。

在iOS 8 中,UITableView新增一項功能 self size cells,這是一項通過 UITableViewCell 的約束自動自動計算UITableView contentSize 的技術。這個新特性給我們帶來兩個個好處。

  • 我們不再需要為了自適應文字,去計算每個cell 中文字所需要的高度。
  • 而且有更高的效能。(因為UITableView每次reloadData的時候都會重新計算 cell 的高度,意味著如果有1萬個 cell 要展示,需要 調用heightForRowAtIndexPath一萬次,這效率是特別低的)

我們通過一個簡單的demo來介紹一下 Self Size Cells 的用法,demo 源碼
效果

使用步驟是
  • 為UITableViewCell添加約束
  • 設定UITableView 的estimatedRowHeight屬性
  • 設定 rowHeight為 UITableViewAutomaticDimension
  • 有一點需要注意,代碼中不能實現heightForRowAtIndexPath 這個方法
    添加約束,有一個原則是,除了自適應text的高度不需要約束外,需要確定所有必要約束

用代碼來說就是(這裡用到第三方庫 SnapKit 做代碼約束 SnapKit 傳送門)

textview.snp_makeConstraints{ (make)in  make.top.equalTo(self.contentView).offset(15)  make.width.equalTo(100)  make.left.equalTo(self.contentView).offset(15)  make.bottom.equalTo(self.contentView).offset(-15)}

對於UILabel 來說還需要把numberOfLines置為0
然後設定UITableView的必要屬性

messageTable.estimatedRowHeight=44messageTable.rowHeight=UITableViewAutomaticDimension

以上便是,使用self size cell 的所有步驟。

實戰篇

接下來便是實戰部分,我希望在聊天頁面中使用self size cell 這個功能,聊天頁面的

以下下是我為messageCell 製作約束圖,事實上用的是代碼約束,詳情可以查看我的源碼

問題

如果我想實現 一個功能像一樣下拉重新整理,而且訊息停留在原來的訊息頁面上,如所示

分析:在重新整理資料後 調用tableview.reloadData 方法,可以重新整理tableview 顯示的資料,不過tableview 會滾動到最頂部。幸運的是tableView是UIScrollView的子類,如果我們改變了內容,contentSize 這個屬性一定會改變,也就是說系統一定會掉用contentSize的set方法。如果我們重新這個set 方法,在每次掉用setContentSize 的時候計算出之前視窗所在的位置,並且在設定完contentSize後移動到計算號的位置,就能平滑的上拉載入更多的曆史訊息了。

下面是實現平滑滾動的關鍵代碼

@objc(JChatMessageTable)class JChatMessageTable: UITableView {  var isFlashToLoad:Bool! = false  override var contentSize: CGSize {    didSet {        if self.isFlashToLoad != false {          if !CGSizeEqualToSize(self.contentSize, CGSizeZero) {            if oldValue.height < self.contentSize.height {              var offset = self.contentOffset              offset.y = self.contentSize.height - oldValue.height              self.contentOffset = offset            }          }        }          self.isFlashToLoad = false    }  }  override init(frame: CGRect, style: UITableViewStyle) {    super.init(frame: frame, style: style)  }  required init?(coder aDecoder: NSCoder) {      fatalError("init(coder:) has not been implemented")  }  func loadMoreMessage() {    self.isFlashToLoad = true    self.reloadData()  }}

想法是好的,但是現實總是殘酷的,在具體實行的時候出現了一個新的問題,因為我用的是Self size cell 來自適應UITableView的contentSize的, Self size cell 在處理UITableView 的contentSize時候並不是一次性賦值成功的,它是每5個點的增加height(contentSize.height),直到合適的高度位置, 也就是說 contentSize的 Set 方法會被掉用很多次,而且上面的代碼完全沒有作用(可以想象結果是只有最後一次掉用contentSize的Set方法起到了作用小於5個點的位移量,由於這個變化真的很小,我也是在這個地方被坑了一次),由於 Self size cells 的這個特性,似乎很難實現這個功能。

此時我果斷放棄了使用Self Size Cells ,雖然比較心痛,不過我們大致瞭解了Self size cell 是如何自適應高度的。
self size cell 主要給我們帶來兩個好處

  • 能夠得到更高的執行效率
  • 我們不需要為文字的frame進行複雜的計算 ,只需要設定width的約束和位置,就能夠得到自適應的Size

由於messageTable 訊息的展示是通過分頁載入訊息的方式,第一次只會添加20條的訊息,也就不會出現調用heightForRowAtIndexPath時間過長的卡頓問題。但是如果使用者不斷的下拉重新整理heightForRowAtIndexPath的執行時間也會出現線性增加,所以為了減少這方面的時間開支,我們在每次成功載入一個新的cell 的時候把高度緩衝起來,這樣就可以減少計算的時間,每次只需要計算新展現的曆史訊息高度就可以了。

  • 第一個問題經過分析我們可以通過緩衝高度的方式提高效能.
  • 對於第二點,也是最重要的一點,如何不通過手動計算獲得UITableViewCell所需要的高度,經過分析發現UITableViewCell 有一個方法systemLayoutSizeFittingSize可以計算返回自身的高度,所以我接下來產生一個全域的UITableViewCell 用於計算UITableViewCell 的高度這樣我們就不需要手動計算Cell的高度了。通過
    messageCell.systemLayoutSizeFittingSize(CGSizeZero).height + 1//這裡的 +1 是為了彌補分隔線的高度
    返回的高度就是UITableView所需要的高度。
自適應輸入框

接下來,我們需要實現如的效果,輸入框能夠自適應輸入文字的大小JChatInputView

我們需要輸入框能夠自適應文本的大小,我們

需要給TextView 添加如下約束

inputTextView?.snp_makeConstraints(closure: { (make) ->Voidin    make.right.equalTo(self.showMoreBtn.snp_left).offset(-5)    make.left.equalTo(self.switchBtn.snp_right).offset(5)    make.top.equalTo(inputWrapView).offset(5)    make.bottom.equalTo(inputWrapView).offset(-5)    make.height.greaterThanOrEqualTo(30)    make.height.lessThanOrEqualTo(100)})

inputWarpView 添加如下約束。不需要添加高度約束, 因為inputWarpView的高度由TextView 的高度和其他約束計算得出

inputTextView?.snp_makeConstraints(closure: { (make) ->Voidin    make.right.bottom.left.equalTo(superView)})

到此介紹了一個聊天介面的自適應UI部分,靈活的使用約束可以減少大量的代碼。

作者:HuminiOS-極光

原文:http://www.jianshu.com/p/44884eb52eff

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.