Don_Mag

Untitled

Aug 20th, 2021 (edited)
1,401
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1.  
  2. extension String {
  3.     func height(withConstrainedWidth width: CGFloat, font: UIFont) -> CGFloat {
  4.         let constraintRect = CGSize(width: width, height: .greatestFiniteMagnitude)
  5.         let boundingBox = self.boundingRect(with: constraintRect, options: .usesLineFragmentOrigin, attributes: [NSAttributedString.Key.font: font], context: nil)
  6.        
  7.         return ceil(boundingBox.height)
  8.     }
  9.    
  10.     func width(withConstrainedHeight height: CGFloat, font: UIFont) -> CGFloat {
  11.         let constraintRect = CGSize(width: .greatestFiniteMagnitude, height: height)
  12.         let boundingBox = self.boundingRect(with: constraintRect, options: .usesLineFragmentOrigin, attributes: [NSAttributedString.Key.font: font], context: nil)
  13.        
  14.         return ceil(boundingBox.width)
  15.     }
  16. }
  17.  
  18. class CommentCell: UICollectionViewCell {
  19.     let profileImageView = UIImageView()
  20.     let nameLabel = UILabel()
  21.     let titleLabel = UILabel()
  22.     let commentLabel = UILabel()
  23.    
  24.     var titleFont: UIFont = .systemFont(ofSize: 16.0)
  25.     var commentFont: UIFont = .systemFont(ofSize: 16.0)
  26.  
  27.     override init(frame: CGRect) {
  28.         super.init(frame: frame)
  29.         commonInit()
  30.     }
  31.     required init?(coder: NSCoder) {
  32.         super.init(coder: coder)
  33.         commonInit()
  34.     }
  35.     func commonInit() -> Void {
  36.         contentView.backgroundColor = UIColor(white: 0.95, alpha: 1.0)
  37.  
  38.         commentLabel.numberOfLines = 6
  39.        
  40.         [titleLabel, commentLabel].forEach { v in
  41.             v.setContentHuggingPriority(.required, for: .vertical)
  42.             v.backgroundColor = .yellow
  43.         }
  44.        
  45.         [profileImageView, nameLabel, titleLabel, commentLabel].forEach { v in
  46.             v.translatesAutoresizingMaskIntoConstraints = false
  47.             contentView.addSubview(v)
  48.         }
  49.        
  50.         profileImageView.backgroundColor = .red
  51.         nameLabel.text = "Name Label"
  52.         titleLabel.text = "Title Label"
  53.        
  54.         let g = contentView
  55.        
  56.         NSLayoutConstraint.activate([
  57.            
  58.             profileImageView.topAnchor.constraint(equalTo: g.topAnchor, constant: 8.0),
  59.             profileImageView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 8.0),
  60.             profileImageView.widthAnchor.constraint(equalToConstant: 80.0),
  61.             profileImageView.heightAnchor.constraint(equalTo: profileImageView.widthAnchor),
  62.            
  63.             nameLabel.leadingAnchor.constraint(equalTo: profileImageView.trailingAnchor, constant: 8.0),
  64.             nameLabel.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -8.0),
  65.             nameLabel.centerYAnchor.constraint(equalTo: profileImageView.centerYAnchor),
  66.            
  67.             titleLabel.topAnchor.constraint(equalTo: profileImageView.bottomAnchor, constant: 8.0),
  68.             titleLabel.leadingAnchor.constraint(equalTo: profileImageView.leadingAnchor, constant: 0.0),
  69.             titleLabel.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -8.0),
  70.  
  71.             commentLabel.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 8.0),
  72.             commentLabel.leadingAnchor.constraint(equalTo: titleLabel.leadingAnchor, constant: 0.0),
  73.             commentLabel.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -8.0),
  74.             commentLabel.bottomAnchor.constraint(lessThanOrEqualTo: g.bottomAnchor, constant: -8.0),
  75.  
  76.         ])
  77.     }
  78. }
  79.  
  80. class SampleViewController: UIViewController {
  81.    
  82.     var collectionView: UICollectionView!
  83.     var collectionViewHeightConstraint: NSLayoutConstraint!
  84.     var flowLayout: UICollectionViewFlowLayout!
  85.  
  86.     var comments: [String] = []
  87.    
  88.     let shortComments: [String] = [
  89.         "First example.",
  90.         "This is a short set... it should have a max of two lines.",
  91.         "String with some text.",
  92.         "This is a longer string for the two-line label.",
  93.         "This potential solution regarding two-line-labels works better in this case.",
  94.         "Last short string.",
  95.     ]
  96.  
  97.     let longComments: [String] = [
  98.         "This is a set of longer strings.",
  99.         "Depending on the available view-width, it may not work well if the text is too long.",
  100.         "Our final example string will be much longer than the others. This will demonstrate that, unless we also set a max-width, the calculated width will end up extending the label outside the bounds of our view (assuming we're on an iPhone in Portrait orientation).",
  101.         "A label can contain an arbitrary amount of text, but UILabel may shrink, wrap, or truncate the text, depending on the size of the bounding rectangle and properties you set. You can control the font, text color, alignment, highlighting, and shadowing of the text in the label.",
  102.         "You can set the title, image, and other appearance properties of a button. In addition, you can specify a different appearance for each button state.",
  103.         "Displays a rounded rectangle that can contain editable text. When a user taps a text field, a keyboard appears; when a user taps Return in the keyboard, the keyboard disappears and the text field can handle the input in an application-specific way. UITextField supports overlay views to display additional information, such as a bookmarks icon. UITextField also provides a clear text control a user taps to erase the contents of the text field.",
  104.     ]
  105.  
  106.     var commentToggle: Int = 0
  107.    
  108.     let titleFont: UIFont = .systemFont(ofSize: 18.0)
  109.     let commentFont: UIFont = .systemFont(ofSize: 12.0)
  110.    
  111.     override func viewDidLoad() {
  112.         super.viewDidLoad()
  113.        
  114.         let toggleButton = UIButton()
  115.         toggleButton.setTitle("Toggle Data", for: [])
  116.         toggleButton.setTitleColor(.white, for: .normal)
  117.         toggleButton.setTitleColor(.gray, for: .highlighted)
  118.         toggleButton.backgroundColor = .systemBlue
  119.         toggleButton.addTarget(self, action: #selector(toggleTapped(_:)), for: .touchUpInside)
  120.        
  121.         flowLayout = UICollectionViewFlowLayout()
  122.         flowLayout.scrollDirection = .horizontal
  123.  
  124.         collectionView = UICollectionView(frame: .zero, collectionViewLayout: flowLayout)
  125.        
  126.         toggleButton.translatesAutoresizingMaskIntoConstraints = false
  127.         collectionView.translatesAutoresizingMaskIntoConstraints = false
  128.        
  129.         view.addSubview(toggleButton)
  130.         view.addSubview(collectionView)
  131.  
  132.         let g = view.safeAreaLayoutGuide
  133.        
  134.         collectionViewHeightConstraint = collectionView.heightAnchor.constraint(equalToConstant: flowLayout.itemSize.height)
  135.        
  136.         NSLayoutConstraint.activate([
  137.  
  138.             toggleButton.topAnchor.constraint(equalTo: g.topAnchor, constant: 40.0),
  139.             toggleButton.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 60.0),
  140.             toggleButton.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -60.0),
  141.  
  142.             collectionView.topAnchor.constraint(equalTo: toggleButton.bottomAnchor, constant: 40.0),
  143.             collectionView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 20.0),
  144.             collectionView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -20.0),
  145.             collectionViewHeightConstraint,
  146.         ])
  147.        
  148.         collectionView.dataSource = self
  149.         collectionView.delegate = self
  150.        
  151.         collectionView.register(CommentCell.self, forCellWithReuseIdentifier: "commentCell")
  152.        
  153.         updateViews()
  154.     }
  155.    
  156.     func updateViews() -> Void {
  157.        
  158.         // assuming we want the cell width to be 280-pts,
  159.         //  with 8-pts "padding" on each side
  160.         //  the cell's title label and comment label Widths are: 264-pts
  161.         let w: CGFloat = 264.0
  162.        
  163.         // Max 6 lines? Then get height of 6 lines
  164.         let sixLines: String = "1\n2\n3\n4\n5\n6"
  165.         let sixLineHeight: CGFloat = sixLines.height(withConstrainedWidth: w, font: commentFont)
  166.        
  167.         // start with short comments
  168.         comments = commentToggle % 2 == 0 ? shortComments : longComments
  169.        
  170.         var maxCommentHeight: CGFloat = 0
  171.        
  172.         for i in 0..<comments.count {
  173.             let h: CGFloat = comments[i].height(withConstrainedWidth: w, font: commentFont)
  174.             maxCommentHeight = max(h, maxCommentHeight)
  175.             if maxCommentHeight >= sixLineHeight {
  176.                 maxCommentHeight = sixLineHeight
  177.                 break
  178.             }
  179.         }
  180.        
  181.         // get height of title label
  182.         let th: CGFloat = "A".height(withConstrainedWidth: w, font: titleFont)
  183.        
  184.         // cell height will be
  185.         //  profileImageView height (80)
  186.         //  +
  187.         //  title label height
  188.         //  +
  189.         //  maxCommentHeight
  190.         //  +
  191.         //  vertical spacing (4 spaces * 8)
  192.         let cellHeight: CGFloat = 80.0 + th + maxCommentHeight + 32.0
  193.        
  194.         flowLayout.itemSize = CGSize(width: w + 16.0, height: cellHeight)
  195.        
  196.         collectionViewHeightConstraint.constant = flowLayout.itemSize.height
  197.  
  198.         collectionView.reloadData()
  199.     }
  200.    
  201.     @objc func toggleTapped(_ sender: Any?) -> Void {
  202.         commentToggle += 1
  203.         updateViews()
  204.     }
  205.  
  206. }
  207.  
  208. extension SampleViewController: UICollectionViewDataSource, UICollectionViewDelegate {
  209.     func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
  210.         return comments.count
  211.     }
  212.    
  213.     func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
  214.         let c = collectionView.dequeueReusableCell(withReuseIdentifier: "commentCell", for: indexPath) as! CommentCell
  215.         c.titleLabel.font = titleFont
  216.         c.commentLabel.font = commentFont
  217.         c.commentLabel.text = comments[indexPath.item]
  218.         return c
  219.     }
  220.    
  221. }
  222.  
  223. // -------------------
  224. // original paste follows
  225. // -------------------
  226.  
  227.         // assuming comment label Width is 260-pts
  228.         let w: CGFloat = 260.0
  229.        
  230.         // assuming font of comment label
  231.         let font: UIFont = .systemFont(ofSize: 12.0)
  232.        
  233.         // Max 6 lines? Then get height of 6 lines
  234.         let sixLines: String = "1\n2\n3\n4\n5\n6"
  235.         let sixLineHeight: CGFloat = sixLines.height(withConstrainedWidth: w, font: font)
  236.        
  237.         var maxCommentHeight: CGFloat = 0
  238.        
  239.         for i in 0..<comments.count {
  240.             let h: CGFloat = comments[i].height(withConstrainedWidth: w, font: font)
  241.             print("h:", h)
  242.             maxCommentHeight = max(h, maxCommentHeight)
  243.             if maxCommentHeight > sixLineHeight {
  244.                 maxCommentHeight = sixLineHeight
  245.                 break
  246.             }
  247.         }
  248.        
  249.         print("Max comment height:", maxCommentHeight)
  250.  
  251.         // set itemSize of collection view flow layout to
  252.         // CGSize(width: w, height: maxCommentHeight)
  253.  
RAW Paste Data