···4040 self.setAttributedText()
4141 }
42424343- // Tell yoga not to use flexbox
4343+ // Returning true here will tell Yoga to not use flexbox and instead use our custom measure func.
4444 override func isYogaLeafNode() -> Bool {
4545 return true
4646 }
47474848- // We only need to insert text children
4848+ // We should only insert children that are UITextView shadows
4949 override func insertReactSubview(_ subview: RCTShadowView!, at atIndex: Int) {
5050 if subview.isKind(of: RNUITextViewChildShadow.self) {
5151 super.insertReactSubview(subview, at: atIndex)
5252 }
5353 }
54545555- // Whenever the subvies update, set the text
5555+ // Every time the subviews change, we need to reformat and render the text.
5656 override func didUpdateReactSubviews() {
5757 self.setAttributedText()
5858 }
···6464 return
6565 }
66666767- // Update the text
6767+ // Since we are inside the shadow view here, we have to find the real view and update the text.
6868 self.bridge.uiManager.addUIBlock { uiManager, viewRegistry in
6969 guard let textView = viewRegistry?[self.reactTag] as? RNUITextView else {
7070 return
···100100 // Create the attributed string with the generic attributes
101101 let string = NSMutableAttributedString(string: child.text, attributes: attributes)
102102103103- // Set the paragraph style attributes if necessary
103103+ // Set the paragraph style attributes if necessary. We can check this by seeing if the provided
104104+ // line height is not 0.0.
104105 let paragraphStyle = NSMutableParagraphStyle()
105106 if child.lineHeight != 0.0 {
106106- paragraphStyle.minimumLineHeight = child.lineHeight
107107- paragraphStyle.maximumLineHeight = child.lineHeight
107107+ // Whenever we change the line height for the text, we are also removing the DynamicType
108108+ // adjustment for line height. We need to get the multiplier and apply that to the
109109+ // line height.
110110+ let scaleMultiplier = scaledFontSize / child.fontSize
111111+ paragraphStyle.minimumLineHeight = child.lineHeight * scaleMultiplier
112112+ paragraphStyle.maximumLineHeight = child.lineHeight * scaleMultiplier
113113+108114 string.addAttribute(
109115 NSAttributedString.Key.paragraphStyle,
110116 value: paragraphStyle,
111117 range: NSMakeRange(0, string.length)
112118 )
113119114114- // Store that height
120120+ // To calcualte the size of the text without creating a new UILabel or UITextView, we have
121121+ // to store this line height for later.
115122 self.lineHeight = child.lineHeight
116123 } else {
117124 self.lineHeight = font.lineHeight
···124131 self.dirtyLayout()
125132 }
126133127127- // Create a YGSize based on the max width
134134+ // To create the needed size we need to:
135135+ // 1. Get the max size that we can use for the view
136136+ // 2. Calculate the height of the text based on that max size
137137+ // 3. Determine how many lines the text is, and limit that number if it exceeds the max
138138+ // 4. Set the frame size and return the YGSize. YGSize requires Float values while CGSize needs CGFloat
128139 func getNeededSize(maxWidth: Float) -> YGSize {
129129- // Create the max size and figure out the size of the entire text
130140 let maxSize = CGSize(width: CGFloat(maxWidth), height: CGFloat(MAXFLOAT))
131141 let textSize = self.attributedText.boundingRect(with: maxSize, options: .usesLineFragmentOrigin, context: nil)
132142133133- // Figure out how many total lines there are
134134- let totalLines = Int(ceil(textSize.height / self.lineHeight))
143143+ var totalLines = Int(ceil(textSize.height / self.lineHeight))
135144136136- // Default to the text size
137137- var neededSize: CGSize = textSize.size
138138-139139- // If the total lines > max number, return size with the max
140145 if self.numberOfLines != 0, totalLines > self.numberOfLines {
141141- neededSize = CGSize(width: CGFloat(maxWidth), height: CGFloat(CGFloat(self.numberOfLines) * self.lineHeight))
146146+ totalLines = self.numberOfLines
142147 }
143148144144- self.frameSize = neededSize
145145- return YGSize(width: Float(neededSize.width), height: Float(neededSize.height))
149149+ self.frameSize = CGSize(width: CGFloat(maxWidth), height: CGFloat(CGFloat(totalLines) * self.lineHeight))
150150+ return YGSize(width: Float(self.frameSize.width), height: Float(self.frameSize.height))
146151 }
147152}