聊天界面-自适应文字

2017-02-07 10:02:42 +08:00
 jpush

该篇文章主要介绍一个实现聊天界面的思路过程,源码可以在 源码链接 获得,该工程实现聊天的基本功能,功能还不够完善,欢迎大家提 PR ,效果图如下所示

我希望通过相对简单的方式实现界面的布局,没有复杂的计算达到自适应的效果。

iOS8 新功能介绍

虽然 self size cell 最终没有在我的工程中用到,但是这是我曾经挖过的坑,所以在此做了简单的介绍。

在 iOS 8 中, UITableView 新增一项功能 self size cells ,这是一项通过 UITableViewCell 的约束自动自动计算 UITableView contentSize 的技术。这个新特性给我们带来两个个好处。

我们通过一个简单的 demo 来介绍一下 Self Size Cells 的用法,demo 源码 效果如图

使用步骤是

用代码来说就是(这里用到第三方库 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=44
messageTable.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 主要给我们带来两个好处

由于 messageTable 消息的展示是通过分页加载消息的方式,第一次只会添加 20 条的消息,也就不会出现调用 heightForRowAtIndexPath 时间过长的卡顿问题。但是如果用户不断的下拉刷新 heightForRowAtIndexPath 的执行时间也会出现线性的增加,所以为了减少这方面的时间开支,我们在每次成功加载一个新的 cell 的时候把高度缓存起来,这样就可以减少计算的时间,每次只需要计算新展现的历史消息高度就可以了。

返回的高度就是 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

8458 次点击
所在节点    iPhone
4 条回复
hoythan
2017-02-07 10:05:44 +08:00
UI 巨丑
Refac
2017-02-07 11:28:20 +08:00
看风格以为是 Android
SourceMan
2017-02-07 11:32:07 +08:00
软文软文咯,还把 iOS 的 UI 搞得跟 Android 一样
UnknownR
2017-02-07 12:53:03 +08:00
最想吐槽一点,顶部状态栏图标嫑用黑色的

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/338639

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX