Установить начальное смещение просмотра для UITextView в SwiftUI

Я не понимаю, где вводить начальное смещение содержимого для TextView, созданного как представимый в SwiftUI. Вот код 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, который я показал, я должен быть готов. Какие-либо предложения? Вызов этого со смещением 46 в симуляторе iPod Touch должен прокручиваться так, чтобы слово "as" было вверху экрана при первом отображении ZTextView.

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
  }

Это то, что ты искал?

Другие вопросы по тегам