es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Desplazamiento a la posición del cursor del TextEditor en SwiftUI

¿Es posible desplazarse a la posición actual del cursor del TextEditor?

Tengo una Lista con un TextEditor como última fila. Estoy desplazándome a la última fila de la Lista para asegurarme de que el TextEditor esté sobre el teclado.

El problema es que, al tener el anclaje de desplazamiento configurado en .bottom, al editar un texto largo, el texto en la parte superior no es visible ya que la scrollView se desplaza hacia la parte inferior de la fila.

Deberías poder recrear el problema con el código siguiente. Simplemente ingresa un texto largo y luego intenta editar ese texto en la parte superior.

import SwiftUI

struct ContentView: View {
    @State var items: [String] = ["Manzanas", "Naranjas", "Plátanos", "Peras", "Mangos", "Pomelos","Manzanas", "Naranjas", "Plátanos", "Peras", "Mangos", "Pomelos"]
    @State private var newItemText : String = ""

    var body: some View {
        ScrollViewReader { (proxy: ScrollViewProxy) in
            List{
                ForEach(items, id: \.self) {
                    Text("\($0)")
                }
                TextEditor(text: $newItemText)
                    .onChange(of: newItemText) { newValue in
                        proxy.scrollTo("Nuevo Item TextField", anchor: .bottom)
                    }
                    .id("Nuevo Item TextField")
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
Tags:  , , ,

Answer

  1. Avatar for davy.ai

    Sí, es posible desplazarse a la posición actual del cursor del TextEditor. Puedes hacer esto obteniendo el desplazamiento del TextEditor y usando el ScrollViewProxy para desplazarte a ese desplazamiento. Aquí tienes un ejemplo:

    struct ContentView: View {
        @State private var text: String = ""
    
        var body: some View {
            ScrollViewReader { proxy in
                VStack {
                    ForEach(0..<50) { index in
                        Text("\(index)")
                            .padding()
                    }
    
                    TextEditor(text: $text)
                        .onChange(of: text) { _ in
                            if let offset = textViewOffset(text: text, proxy: proxy) {
                                proxy.scrollTo(offset, anchor: .top)
                            }
                        }
                }
            }
        }
    
        func textViewOffset(text: String, proxy: ScrollViewProxy) -> CGFloat? {
            guard let range = text.range(of: text) else { return nil }
            let nsRange = NSRange(range, in: text)
    
            guard let rect = try? UITextView().boundingRect(
                for: nsRange,
                in: text,
                selectedRange: nsRange
            ) else { return nil }
    
            return rect.origin.y
        }
    }
    

    En este ejemplo, tenemos un ScrollViewReader que contiene una lista de vistas Text y un TextEditor. Cuando el texto en el TextEditor cambia, usamos la función textViewOffset para obtener el desplazamiento del TextEditor. Luego, usamos el ScrollViewProxy para desplazarnos a ese desplazamiento usando el ancla .top.

Comments are closed.