SwiftUI如何滚动文本至首个子字符串匹配位置?
问题
在iOS 15的SwiftUI应用中,我有一个用于显示长字符串的垂直滚动页面,代码如下:
struct TextScrollView: View { var formattedText: AttributedString var searchTerm: String? var body: some View { ScrollView { Text(self.formattedText) } .padding(.all) .font(.body) } //body } //TextScrollView
需求是:如果传入searchTerm,且该字符串在formattedText中至少存在一次匹配,则自动将文本滚动至首个匹配位置,逻辑示例如下:
if let searchTerm = self.searchTerm, let range = self.formattedText.range(of: searchTerm, options: .caseInsensitive) { //scroll text to range }
请问该需求是否可以实现?
可以实现,具体方案如下
iOS 15的SwiftUI原生Text和ScrollView没有直接提供获取文本范围位置并滚动的API,不过可以通过包装UIKit的UITextView来实现这个功能,步骤如下:
1. 实现UIViewRepresentable包装UITextView
创建一个支持自动滚动到指定文本范围的WrappedTextView:
struct WrappedTextView: UIViewRepresentable { let attributedText: NSAttributedString let searchTerm: String? let font: UIFont func makeUIView(context: Context) -> UITextView { let textView = UITextView() textView.isEditable = false textView.isScrollEnabled = true textView.font = font textView.textContainerInset = UIEdgeInsets(top: 16, left: 16, bottom: 16, right: 16) return textView } func updateUIView(_ uiView: UITextView, context: Context) { uiView.attributedText = attributedText guard let searchTerm = searchTerm, !searchTerm.isEmpty else { return } // 查找匹配的文本范围 let range = attributedText.mutableString.range(of: searchTerm, options: .caseInsensitive) if range.location != NSNotFound { // 滚动到匹配位置,带动画更自然 uiView.scrollRangeToVisible(range) } } }
2. 修改原TextScrollView使用包装后的组件
把原来的ScrollView和Text替换成上面的WrappedTextView,注意将AttributedString转换为NSAttributedString:
struct TextScrollView: View { var formattedText: AttributedString var searchTerm: String? var body: some View { WrappedTextView( attributedText: NSAttributedString(formattedText), searchTerm: searchTerm, font: UIFont.preferredFont(forTextStyle: .body) ) .edgesIgnoringSafeArea(.bottom) } }
补充说明
- SwiftUI原生
Text无法直接获取文本布局的位置信息,而UIKit的UITextView可以通过scrollRangeToVisible(_:)轻松实现滚动到指定文本范围的功能 - 代码中保留了需求里的大小写不敏感匹配逻辑
- 如果需要高亮搜索到的文本,可以在
updateUIView方法中对attributedText进行富文本修改,比如添加背景色标记匹配内容
内容的提问来源于stack exchange,提问作者protasm
相关产品推荐
相关产品推荐

