在 SwiftUI 中为 UITextView 设置初始视图偏移量

Posted

技术标签:

【中文标题】在 SwiftUI 中为 UITextView 设置初始视图偏移量【英文标题】:Set Initial View Offset for UITextView in SwiftUI 【发布时间】:2020-11-29 19:12:39 【问题描述】:

我很难为在 SwiftUI 中创建为可表示的 TextView 注入初始内容偏移量的位置。这是 TextView 代码,后面是使用它的 ContentView。我的目标是能够将长文本视图重新定位到隐藏或关闭视图时停止的位置。

import SwiftUI
import UIKit

struct ZTextView: UIViewRepresentable

    
    @Binding var text: String
    
    func makeUIView(context: Context) -> UITextView
    
        let textView = UITextView()
        textView.font = UIFont.preferredFont(forTextStyle: UIFont.TextStyle.largeTitle)
        
        textView.autocapitalizationType = .sentences
        textView.isSelectable = true
        textView.isUserInteractionEnabled = true
        
        textView.delegate = context.coordinator
        
        return textView
    
    
    func updateUIView(_ uiView: UITextView, context: Context)
    
        uiView.text = text
    
    
    // COORDINATOR
    
    func makeCoordinator() -> Coordinator
    
        Coordinator($text)
    
    
    class Coordinator: NSObject, UITextViewDelegate
    
        var text: Binding<String>
        
        init(_ text: Binding<String>)
        
            self.text = text
        
        
        func textViewDidChange(_ textView: UITextView)
        
            self.text.wrappedValue = textView.text
            print("change")
            getOffset(textView)
        
        
        func scrollViewDidScroll(_ scrollView: UIScrollView)
        
            print("scroll")
        
        
        func getOffset(_ textView: UITextView)
        
            let topLeft = CGPoint(x: textView.bounds.minX, y: textView.bounds.minY)
            let bottomRight = CGPoint(x: textView.bounds.maxX, y: textView.bounds.maxY)
            guard let topLeftTextPosition = textView.closestPosition(to: topLeft),
                  let bottomRightTextPosition = textView.closestPosition(to: bottomRight)
            else 
                return
            
            let charOffset = textView.offset(from: textView.beginningOfDocument, to: topLeftTextPosition)
            let length = textView.offset(from: topLeftTextPosition, to: bottomRightTextPosition)
            
            print("Offset: \(charOffset), Length: \(length)")
        
        
        
    
    
    func setOffset(textview: UITextView, offset: Int)
    
        let range = NSRange(location: offset, length: 1)
        textview.scrollRangeToVisible(range)
    

ContentView 代码。

import SwiftUI

struct ContentView: View

    @State var text = "Mary\nhad\na\nlittle\nlamb\nwho's\nfleece\nwas\nwhite\nas\nsnow.\n\nEverywhere\nthat\nMary\nwent\nthe\nlamb\nwas\nsure\nto\ngo.\n"
    var body: some View
    
        ZTextView(text: $text)
            .padding()
    


我一直在尝试各种可能性,但显然对 SwiftUI 的理解不足以实现这一点。我有一个类似的应用程序只使用 UIKit,所以我知道它可以完成,只是现在如何或在哪里。

看来,如果我能弄清楚在哪里调用我展示的 setOffset 方法,我应该已经准备好了。有什么建议么?在 iPod Touch 模拟器上以 46 的偏移量调用它应该滚动,因此当 ZTextView 首次显示时,“as”一词位于屏幕顶部。

【问题讨论】:

【参考方案1】:

在这方面还需要帮助吗?我遇到了您的问题,寻求非常相似的帮助。我最终找到了至少可以满足我特定需求的方法。

您需要在 ZTextView 类中创建与偏移属性的绑定。绑定是必要的,因此只要偏移量的值发生变化,就会调用 updateUIView(),从而更新您的 ZTextView。更新可能来自您的 ContentView 在这种情况下,偏移量可能是 @State 属性或来自发布偏移值的 Observable 对象(我的情况)。

所以,给ZTextView添加绑定并修改updateUIView(),如下所示:

  @Binding var offset: CGPoint

  func updateUIView(_ uiView: UITextView, context: Context) 
      uiView.text = text
      uiView.contentOffset = offset
  

这就是你要找的吗?

【讨论】:

以上是关于在 SwiftUI 中为 UITextView 设置初始视图偏移量的主要内容,如果未能解决你的问题,请参考以下文章

SwiftUI UITextView 协调器不起作用

UITextView 的 SwiftUI Wrapper 未更新 ObservedObject

作为 UITextView inputAccessoryView 的 SwiftUI 视图具有不正确的框架

如何在 ios 中为 UITextView 设置内容插入

如何在 UITextView 中为文本着色

SwiftUI:在输入之前将 TextField 大小扩展到字体大小