Bluesky app fork with some witchin' additions 💫

Fix UITextView line height adjustment for DynamicType, always use the max width for the view (#2916)

* fix text being cut off

* adjust line height for dynamictype

authored by hailey.at and committed by

GitHub d2e5f83c 43206d9f

+24 -19
+24 -19
modules/react-native-ui-text-view/ios/RNUITextViewShadow.swift
··· 40 40 self.setAttributedText() 41 41 } 42 42 43 - // Tell yoga not to use flexbox 43 + // Returning true here will tell Yoga to not use flexbox and instead use our custom measure func. 44 44 override func isYogaLeafNode() -> Bool { 45 45 return true 46 46 } 47 47 48 - // We only need to insert text children 48 + // We should only insert children that are UITextView shadows 49 49 override func insertReactSubview(_ subview: RCTShadowView!, at atIndex: Int) { 50 50 if subview.isKind(of: RNUITextViewChildShadow.self) { 51 51 super.insertReactSubview(subview, at: atIndex) 52 52 } 53 53 } 54 54 55 - // Whenever the subvies update, set the text 55 + // Every time the subviews change, we need to reformat and render the text. 56 56 override func didUpdateReactSubviews() { 57 57 self.setAttributedText() 58 58 } ··· 64 64 return 65 65 } 66 66 67 - // Update the text 67 + // Since we are inside the shadow view here, we have to find the real view and update the text. 68 68 self.bridge.uiManager.addUIBlock { uiManager, viewRegistry in 69 69 guard let textView = viewRegistry?[self.reactTag] as? RNUITextView else { 70 70 return ··· 100 100 // Create the attributed string with the generic attributes 101 101 let string = NSMutableAttributedString(string: child.text, attributes: attributes) 102 102 103 - // Set the paragraph style attributes if necessary 103 + // Set the paragraph style attributes if necessary. We can check this by seeing if the provided 104 + // line height is not 0.0. 104 105 let paragraphStyle = NSMutableParagraphStyle() 105 106 if child.lineHeight != 0.0 { 106 - paragraphStyle.minimumLineHeight = child.lineHeight 107 - paragraphStyle.maximumLineHeight = child.lineHeight 107 + // Whenever we change the line height for the text, we are also removing the DynamicType 108 + // adjustment for line height. We need to get the multiplier and apply that to the 109 + // line height. 110 + let scaleMultiplier = scaledFontSize / child.fontSize 111 + paragraphStyle.minimumLineHeight = child.lineHeight * scaleMultiplier 112 + paragraphStyle.maximumLineHeight = child.lineHeight * scaleMultiplier 113 + 108 114 string.addAttribute( 109 115 NSAttributedString.Key.paragraphStyle, 110 116 value: paragraphStyle, 111 117 range: NSMakeRange(0, string.length) 112 118 ) 113 119 114 - // Store that height 120 + // To calcualte the size of the text without creating a new UILabel or UITextView, we have 121 + // to store this line height for later. 115 122 self.lineHeight = child.lineHeight 116 123 } else { 117 124 self.lineHeight = font.lineHeight ··· 124 131 self.dirtyLayout() 125 132 } 126 133 127 - // Create a YGSize based on the max width 134 + // To create the needed size we need to: 135 + // 1. Get the max size that we can use for the view 136 + // 2. Calculate the height of the text based on that max size 137 + // 3. Determine how many lines the text is, and limit that number if it exceeds the max 138 + // 4. Set the frame size and return the YGSize. YGSize requires Float values while CGSize needs CGFloat 128 139 func getNeededSize(maxWidth: Float) -> YGSize { 129 - // Create the max size and figure out the size of the entire text 130 140 let maxSize = CGSize(width: CGFloat(maxWidth), height: CGFloat(MAXFLOAT)) 131 141 let textSize = self.attributedText.boundingRect(with: maxSize, options: .usesLineFragmentOrigin, context: nil) 132 142 133 - // Figure out how many total lines there are 134 - let totalLines = Int(ceil(textSize.height / self.lineHeight)) 143 + var totalLines = Int(ceil(textSize.height / self.lineHeight)) 135 144 136 - // Default to the text size 137 - var neededSize: CGSize = textSize.size 138 - 139 - // If the total lines > max number, return size with the max 140 145 if self.numberOfLines != 0, totalLines > self.numberOfLines { 141 - neededSize = CGSize(width: CGFloat(maxWidth), height: CGFloat(CGFloat(self.numberOfLines) * self.lineHeight)) 146 + totalLines = self.numberOfLines 142 147 } 143 148 144 - self.frameSize = neededSize 145 - return YGSize(width: Float(neededSize.width), height: Float(neededSize.height)) 149 + self.frameSize = CGSize(width: CGFloat(maxWidth), height: CGFloat(CGFloat(totalLines) * self.lineHeight)) 150 + return YGSize(width: Float(self.frameSize.width), height: Float(self.frameSize.height)) 146 151 } 147 152 }