Chat interface-adaptive text and chat interface self-adaptive
This article mainly introduces the thought process of implementing the chat interface. The source code can be obtained through the source code link. This project implements the basic chat functions, and the functions are not complete enough. You are welcome to raise the PR, as shown below:
I hope to achieve the interface layout in a relatively simple way, without complex computing to achieve adaptive results.
New Functions of iOS8
Although self size cell is not used in my project at the end, it is a pitfall I have dug, so I made a brief introduction here.
In iOS 8, UITableView adds the self size cells function, which is a technology that automatically calculates the UITableView contentSize Based on the constraints of UITableViewCell. This new feature brings us two benefits.
- We no longer need to calculate the height required by the text in each cell for adaptive text.
- And higher performance. (Because UITableView recalculates the height of the cell every time it reloadData, it means that if there are 10 thousand cells to be displayed, heightForRowAtIndexPath needs to be called 10 thousand times, which is very inefficient)
We will introduce the usage of Self Size Cells through a simple demo. The demo source code
Effect
The procedure is
- Add constraints for UITableViewCell
- Set the estimatedRowHeight attribute of UITableView
- Set rowHeight to UITableViewAutomaticDimension.
- Note that the heightForRowAtIndexPath method cannot be implemented in the code.
To add constraints, you must determine all necessary constraints except for the self-adaptive text height.
The code is (the third-party library SnapKit is used to constrain the SnapKit portal)
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)}
For UILabel, set numberOfLines to 0.
Then set the required attributes of UITableView.
messageTable.estimatedRowHeight=44messageTable.rowHeight=UITableViewAutomaticDimension
The above is all the steps to use self size cell.
Practice
Next, I want to use the self size cell function on the chat page.
The following is a constraint graph for messageCell. In fact, code constraints are used. For details, see my source code.
Problem
If I want to implement a pull-down refresh function, and the message stays on the original message page, as shown in
Analysis: Call the tableview. reloadData method after refreshing the data. You can refresh the data displayed in tableview, but tableview will scroll to the top. Fortunately, tableView is a subclass of UIScrollView. If we change the content, the contentSize attribute will change. That is to say, the system will definitely drop the contentSize set method. If we re-set this method, calculate the position of the previous window when setContentSize is used every time, and move it to the position of the computing number after setting the contentSize, you can smoothly pull up and load more historical messages.
The following are the key code for smooth scrolling.
@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() }}
The idea is good, but the reality is always cruel. A new problem arises during the implementation, because Self size cell is used to adapt to the contentSize of UITableView, the Self size cell does not assign a value at a time when processing the contentSize of the UITableView. It increases the height (contentSize) for every five vertices. height), until the appropriate height position, that is, the contentSize Set method will be used out many times, the above Code does not work at all (it can be imagined that only the last time the Set Method with contentSize is used to offset less than five points, because this change is really small, I got stuck here too.) due to this feature of Self size cells, it seems difficult to implement this feature.
At this point, I gave up using Self Size Cells. Although this is a heartache, we have a general idea of how Self size Cells are adaptive to height.
Self size cell mainly brings us two benefits
- Higher execution efficiency
- We do not need to perform complex calculation for the text frame. We only need to set the width constraint and position to get the adaptive Size.
Because messageTable displays messages by means of loading messages by PAGE, only 20 messages will be added for the first time, and the issue of calling heightForRowAtIndexPath for too long will not occur. However, if the execution time of heightForRowAtIndexPath is also linearly increased from the drop-down list, in order to reduce the time expenditure, we cache the height of each successful loading of a new cell, which reduces the computing time. Each time we only need to calculate the height of the new historical message.
- The first problem is analyzed. We can improve the performance by caching height.
- The second and most important point is how to obtain the height required by UITableViewCell without manual calculation. After analysis, we found that UITableViewCell has a method systemLayoutSizeFittingSize that can calculate the height of the returned value, so I will generate a global UITableViewCell to calculate the height of UITableViewCell, so we do not need to manually calculate the height of the Cell. Pass
MessageCell. systemLayoutSizeFittingSize (CGSizeZero). height + 1 // here + 1 is used to make up the height of the separator line
The returned height is the height required by UITableView.
Adaptive input box
Next, we need to implement the effect as shown in the following figure. The input box can automatically input the size of the JChatInputView text.
We need the input box to adapt the size of the text.
You need to add the following constraints to 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 adds the following constraints. You do not need to add a height constraint because the height of inputWarpView is calculated by the height of TextView and other constraints.
inputTextView?.snp_makeConstraints(closure: { (make) ->Voidin make.right.bottom.left.equalTo(superView)})
This section describes the adaptive UI of a chat interface. flexible use of constraints can reduce a large amount of code.
Author: HuminiOS-Aurora
Original article: http://www.jianshu.com/p/44884eb52eff