Open rydamckinney opened 1 year ago
Hi @rydamckinney
I think this would be a bit tricky to achieve on all platforms, since the text views work a bit differently on iOS, where scrolling is part of the UITextView
, compared to on macOS, where the NSTextView
must be added to a scroll view.
Would be nice to have though 👍
Not sure about macOS, but this can be done easily on iOS:
struct MyTextView: UIViewRepresentable {
typealias UIViewType = UITextView
/* ... */
func sizeThatFits(_ proposal: ProposedViewSize, uiView: UITextView, context: Context) -> CGSize? {
// make sure we have a valid proposed width:
guard let proposedWidth = proposal.width, proposedWidth > 0, proposedWidth < .infinity else {
return nil
}
// calculate size of UITextView that fits current text:
var sizeThatFits = uiView.sizeThatFits(CGSize(
width: proposedWidth,
height: .greatestFiniteMagnitude
))
// fill parent horizontally:
sizeThatFits.width = proposedWidth
return sizeThatFits
}
}
It's just an example of unconstrained, dynamic size. Constraining the minimum and maximum height should be straightforward.
Thank you @darrarski! Did you get this to work @rydamckinney?
Hey @danielsaidi Yes I was able to get this working, thought not in the context of RichTextKit.
I needed markdown live syntax highlighting for the text input so I modified a fork of HighlightedTextEditor
(https://github.com/kyle-n/HighlightedTextEditor) to switch between 2 wrapped NSTextViews
(fixed vs dynamic height) based on the usage.
The solution should be generalizable to RichTextKit
. The dynamic height view works in a pretty hacky way by checking & changing a constant height constraint on the scroll view that holds the NSTextView
anytime that the text is changed. While it works, there's some dropped frames / animation glitches that I don't have a workaround for.
The rest of the code is pretty specific to the view hierarchy it's embedded in so I'm not sharing that so as to not confuse others (as I was led astray by many use-case-specific solutions I encountered in my research).
Here's the crux of the logic:
open class DynamicHeightNSTextView: NSTextView {
...
open override func didChangeText() {
super.didChangeText()
self.invalidateIntrinsicContentSize()
if let scrollHeight = self.scrollViewHeight {
NSAnimationContext.runAnimationGroup { context in
context.duration = 0.25
//scrollHeight is a constant NSLayoutConstraint for the containing scrollview's height
scrollHeight.constant = min(self.maxHeight, max(self.intrinsicContentSize.height, self.minHeight))
}
}
}
...
}
Thank you for sharing @rydamckinney!
I will keep this issue open for when I have time to return to this project.
This feature would be my dream!
I have what I think is a simpler question but which has led me here -- how can I get the RichTextEditor to dynamically adjust its height based on the text content inside, so that it doesn't have to scroll for you to see all the text? I'm working in iOS (and SwiftUI).
Is it currently possible to make the
RichTextEditor
frame dynamic with the following behavior?