基于内容以编程方式自动调整UITableViewCell

时间:2018-05-22 12:24:58

标签: ios swift uitableview

我正在创建一个模拟与真实用户聊天的应用程序,用于聊天日志布局我正在使用UITableView,因为我对Swift很新,但是习惯用其他语言编程,我正在创建整个布局编程。

目前我的ViewController看起来像这样

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

    @IBOutlet weak var navigationBar: UINavigationBar!
    @IBOutlet weak var tableView: UITableView!

    let rows: [String] = [
        "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam euismod nunc id nulla ultricies tempus. Mauris a euismod nunc."
    ]

    func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return rows.count;
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "AiMessageCell") as! AiMessageCell

//        cell.textLabel?.text = rows[indexPath.row]
//        cell.textLabel?.numberOfLines = 0;

        return cell
    }

    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
//        tableView.beginUpdates()
//        tableView.endUpdates()

        return UITableViewAutomaticDimension;
    }

    override func viewDidLoad() {
        super.viewDidLoad()

//        tableView.estimatedRowHeight = 140
//        tableView.rowHeight = UITableViewAutomaticDimension;

        tableView.register(AiMessageCell.self, forCellReuseIdentifier: "AiMessageCell")
        tableView.register(UserMessageCell.self, forCellReuseIdentifier: "UserMessageCell")
        tableView.register(UserSelectionCell.self, forCellReuseIdentifier: "UserSelectionCell")
    }
}

它只需要单行并基于它(当前没有将文本传递给单元格)输出一行到我的UITableView

我有AiMessageCell逻辑

class AiMessageCell: UITableViewCell, NSLayoutManagerDelegate {

//    @IBOutlet weak var wrapper: UIView!

    override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)

        let wrapper = UIView(
            frame: CGRect(
                x: 10, y: 10,
                width: UIScreen.main.bounds.width - 10 - 10,
                height: 45
            )
        )

        let balloon = UIView(
            frame: CGRect(
                x: 40, y: 0,
                width: 80,
                height: 45.5
            )
        )
        balloon.layer.cornerRadius = 10;
        balloon.backgroundColor = UIColor.init(
            red: CGFloat(240/255.0),
            green: CGFloat(240/255.0),
            blue: CGFloat(240/255.0),
            alpha: CGFloat(1.0)
        );

        let message = UITextView(
            frame: CGRect(
                x: 10, y: 5,
                width: balloon.layer.bounds.width - 10,
                height: balloon.layer.bounds.height - 10
            )
        );
        message.text = "What is shown in the scrollable content area of a scroll view is determined by its subviews. ";
        message.font = UIFont.systemFont(ofSize: 16);
        message.isEditable = false;
        message.isScrollEnabled = false;
        message.isSelectable = false;
        message.backgroundColor = UIColor.clear;
        message.layoutManager.delegate = self;

        let avatar = UIImageView(
            image: UIImage(named: "avatar")
        );

        avatar.clipsToBounds = true;
        avatar.layer.cornerRadius = 15;

        let calculated = message.sizeThatFits(
            CGSize(width: wrapper.bounds.width - 50, height: CGFloat.greatestFiniteMagnitude)
        )

        avatar.frame = CGRect(x: 0, y: calculated.height - 25, width: 30, height: 30)

        message.frame.size = CGSize(width: calculated.width, height: calculated.height)
        balloon.frame.size = CGSize(width: calculated.width + 20, height: calculated.height + 5);
        wrapper.frame.size = CGSize(width: wrapper.bounds.width, height: balloon.bounds.height);

        balloon.addSubview(message)

        wrapper.addSubview(balloon)
        wrapper.addSubview(avatar)

        wrapper.backgroundColor = UIColor.purple
        contentView.backgroundColor = UIColor.green

        contentView.addSubview(wrapper)
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    func setTimeout(_ delay:TimeInterval, block:@escaping ()->Void) -> Void {
        Timer.scheduledTimer(timeInterval: delay, target: BlockOperation(block: block), selector: #selector(Operation.main), userInfo: nil, repeats: false)
    }

    func layoutManager(_ layoutManager: NSLayoutManager, lineSpacingAfterGlyphAt glyphIndex: Int, withProposedLineFragmentRect rect: CGRect) -> CGFloat {
        return 5;
    }
}

这里我正构建整个消息行,其中包含“user”头像和消息气泡(UITextView),它会自动调整为文本。

这就出现了问题,尽管消息气泡是自动调整文本,表行高度是固定的。

这就是它的样子,老实说至少尝试了5个不同的答案,但没有运气。目前我认为问题是因为我的wrapper(紫色块)和单元格content view(绿色块)之间没有约束

enter image description here

2 个答案:

答案 0 :(得分:1)

您的故事板中需要检查约束。看起来你似乎忘记了从底部文本块到底部单元格的约束。然后取消注释

tableView.estimatedRowHeight = 140

答案 1 :(得分:1)

我认为这里的问题是您使用框架而不是布局约束来定义单元格子视图大小。当您使用x = tf.placeholder(tf.float32, [None, nPixels]) y_ = tf.placeholder(tf.float32, [None, nLabels]) cross_entropy = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(y, y_)) accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32)) with tf.Session() as sess: tf.initialize_all_variables().run() for j in range(nSteps): i = nstep % nSteps batch_xs = np.reshape(x_train,(nSteps,bSize,nPixels)) batch_ys = np.reshape(y_train,(nSteps,bSize,nLabels)) sess.run(train_step, feed_dict={x: batch_xs[i], y_: batch_ys[i]}) if j % 100 ==0: train_acc = sess.run(accuracy, feed_dict={x: x_train,y_: y_train}) test_acc = sess.run(accuracy, feed_dict={x: x_test, y_: y_test})) loss = sess.run(cross_entropy, feed_dict={x: batch_xs[i], y_: batch_ys[i]}) 时,您需要在UITableViewCell的顶部和底部正确设置约束。

而不是使用代理人,我认为它比UITableViewAutomaticDimension评论的方式更清晰:

viewDidLoad