使用UITextView + Image wrap

时间:2018-03-19 05:13:43

标签: ios swift cocoa-touch uicollectionview uicollectionreusableview

我有一个测验,其中每个问题可能有也可能没有图像,以及未知长度的问题文本。

我正在使用Collection View,其中问题在标题中,答案在单元格中。我希望标题高度是动态的,以考虑图像和可变文本长度。我很接近,但仍有一些小问题。

在浏览SO和互联网时,我发现了两种计算Label和TextView文本高度的方法。 TextView计算通常返回更高的高度:

高度计算

func getHeightForLabelWith(width:CGFloat, font:UIFont, text:String) -> CGFloat {
    let label:UILabel = UILabel.init(frame: CGRect.init(x: 0, y: 0, width: width, height: CGFloat.greatestFiniteMagnitude))
    label.numberOfLines = 0
    label.lineBreakMode = NSLineBreakMode.byWordWrapping
    label.font = font
    label.text = text
    label.sizeToFit()
    return label.frame.height
}

func getHeightForUItextViewWith(width: CGFloat, font:UIFont, text: String) -> CGFloat {
    let textView: UITextView = UITextView.init(frame: CGRect.init(x: 0, y: 0, width: width, height: CGFloat.greatestFiniteMagnitude))
    textView.isScrollEnabled = false
    textView.font = font
    textView.text = text
    textView.sizeToFit()
    return textView.frame.height
}

的ViewController

override func viewDidLoad() {
    super.viewDidLoad()

    self.collectionView.dataSource = self
    self.collectionView.delegate = self

    let flowLayout = UICollectionViewFlowLayout()
    flowLayout.sectionInset = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)
    flowLayout.minimumLineSpacing = 10
    flowLayout.minimumInteritemSpacing = 10

    collectionView.collectionViewLayout = flowLayout
}

func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
    let header = collectionView.dequeueReusableSupplementaryView(ofKind: UICollectionElementKindSectionHeader, withReuseIdentifier: "HeaderCell", for: indexPath) as! HeaderCell

    header.text = headerText
    header.image = headerImage

    return header
}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
    let height = getHeightForUItextViewWith(width: self.collectionView.bounds.width, font: UIFont.boldSystemFont(ofSize: 20), text: headerText)
    return CGSize(width: self.collectionView.bounds.width, height: max(height, 80))
}

HeaderCell

class HeaderCell: UICollectionReusableView {
    var image: UIImage?
    var text: String?

    var textView: UITextView = {
        var view = UITextView()
        view.translatesAutoresizingMaskIntoConstraints = false
        view.isScrollEnabled = false
        view.font = UIFont.boldSystemFont(ofSize: 20.0)
        return view
    }()

    var imageView: UIImageView = {
        var view = UIImageView()
        view.translatesAutoresizingMaskIntoConstraints = false
        return view
    }()

    override init(frame: CGRect) {
        super.init(frame: frame)
        self.cellInit()
    }

    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)!
        self.cellInit()
    }

    func cellInit() {
        self.addSubview(textView)
        self.addSubview(imageView)

        textView.backgroundColor = .orange
    }

    override func layoutSubviews() {
        super.layoutSubviews()

        if let text = text {
            textView.text = text

            textView.leftAnchor.constraint(equalTo: self.leftAnchor).isActive = true
            textView.rightAnchor.constraint(equalTo: self.rightAnchor).isActive = true
            textView.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
            textView.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true

            textView.sizeToFit()
        }

        if let _ = text, let image = image {
            imageView.image = image

            imageView.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
            imageView.leadingAnchor.constraint(equalTo: self.leadingAnchor).isActive = true
            imageView.heightAnchor.constraint(lessThanOrEqualToConstant: 100.0).isActive = true
            imageView.widthAnchor.constraint(lessThanOrEqualToConstant: 100.0).isActive = true

            let imageFrame = UIBezierPath(rect: imageView.frame)
            textView.textContainer.exclusionPaths = [imageFrame]

            textView.sizeToFit()
        }
    }
}

捕捉:

  1. 小文字,无图像:截止和几乎全宽
  2. 小文字,图片:截止和几乎一半的宽度
  3. enter image description here enter image description here 3.大文字,无图像:超高,全宽 4.大文字,图像:截止,全宽,图像下的额外空间(不确定是否可以减少)

    enter image description here enter image description here

    我希望我已经为某人提供了足够的信息来提供反馈。

    修改:Sample project @ G Drive

0 个答案:

没有答案