Desplácese hasta la parte inferior de textView programáticamente

Hice un button que agrega un poco de text a un textView y quiero que se desplace automáticamente hacia abajo mientras se presiona para que el usuario pueda ver el nuevo text agregado.
No puedo usar esta solución en Swift porque no conozco Objective-C. ¿Alguien sabe cómo puedo desplazarme a la parte inferior de un textView en Swift? Gracias.

Intenté tanto la compensación de contenido como las soluciones scrolltoview, obtuve resultados mixtos y el desplazamiento entrecortado; Haber mirado a continuación parecía funcionar y producir un desplazamiento consistente hacia abajo cuando es necesario.

En viewdidload:

 self.storyTextView.layoutManager.allowsNonContiguousLayout = false 

Luego cuando sea necesario:

 let stringLength:Int = self.storyTextView.text.characters.count self.storyTextView.scrollRangeToVisible(NSMakeRange(stringLength-1, 0)) 

Entonces, si hace clic en el enlace que publicó, la respuesta aceptada muestra este código objective C:

 -(void)scrollTextViewToBottom:(UITextView *)textView { if(textView.text.length > 0 ) { NSRange bottom = NSMakeRange(textView.text.length -1, 1); [textView scrollRangeToVisible:bottom]; } } 

Entonces tu desafío es convertir ese código a Swift.

Romperlo en pedazos y abordarlos uno a la vez. Primero, la definición del método en sí.

El método se llama scrollTextViewToBottom. Toma un UITextView como un parámetro y no devuelve un resultado. ¿Cómo escribiría esa definición de método en Swift?

Luego mira que el cuerpo del método. La statement if debería ser exactamente la misma en Swift. La creación de un NSRange es casi idéntica. Solo necesitas cambiarlo un poco:

 let bottom = NSMakeRange(textView.text.length -1, 1) 

La parte que probablemente sea la más difícil para alguien que no sabe Objective-C es la llamada al método. Está enviando el post scrollRangeToVisible al object textView . El parámetro pasado es bottom . Mira si puedes reescribir esa línea en Swift. Luego juntar todo el asunto.

Simplemente, donde myTextView es el UITextView en cuestión:

 let bottom = myTextView.contentSize.height myTextView.setContentOffset(CGPoint(x: 0, y: bottom), animated: true) // Scrolls to end 

Swift 3

 let bottom = NSMakeRange(textLog.text.characters.count - 1, 1) textLog.scrollRangeToVisible(bottom) 

Idioma: Swift

Siga los pasos a continuación:
//Declarar

 @IBOutlet weak var trTextDataRead: UITextView! 

// método Cunstom

 func insertTextView(text: String){ //Insert text trTextDataRead.text.append(text) //Scroll to the end let btm = NSMakeRange(trTextDataRead.text.lengthOfBytes(using: String.Encoding.utf8), 0) trTextDataRead.scrollRangeToVisible(btm) } 

UITextView tiene una propiedad contentOffsent . Puede establecer textView.contentOffset o textView.setContentOffset(offset, animated: true)

Por ejemplo, si el contentSize de la vista de text es (100, 500) pero la altura de la vista de text es solo de 100, luego, para desplazarse hacia abajo, establezca la propiedad contentOffset en (0, 400) (esto es para un text vertical ver). Más genéricamente, la fórmula para desplazarse hacia abajo es textView.contentSize.height-textView.height . Cada vez que se presiona su button, configure el desplazamiento.

También recomendaría leer la documentation y tratar de resolverlo. Swift e iOS están bastante bien documentados y una pregunta como esta se puede search fácilmente a través de Google.

Edit: Esto funciona porque UITextView henetworkinga de UIScrollView .

Sidenote: escribí una subclass UITextView donde puedes configurar la alignment del text vertical, así que si estableces la alignment del text en .Bottom , el text se alineará con la parte inferior de la vista.

 class TextView: UITextView { enum VerticalAlignment: Int { case Top = 0, Middle, Bottom } var verticalAlignment: VerticalAlignment = .Middle //override contentSize property and observe using didSet override var contentSize: CGSize { didSet { let textView = self let height = textView.bounds.size.height let contentHeight:CGFloat = contentSize.height var topCorrect: CGFloat = 0.0 switch(self.verticalAlignment){ case .Top: textView.contentOffset = CGPointZero //set content offset to top case .Middle: topCorrect = (height - contentHeight * textView.zoomScale)/2.0 topCorrect = topCorrect < 0 ? 0 : topCorrect textView.contentOffset = CGPoint(x: 0, y: -topCorrect) case .Bottom: topCorrect = textView.bounds.size.height - contentHeight topCorrect = topCorrect < 0 ? 0 : topCorrect textView.contentOffset = CGPoint(x: 0, y: -topCorrect) } if contentHeight >= height { //if the contentSize is greater than the height topCorrect = contentHeight - height //set the contentOffset to be the topCorrect = topCorrect < 0 ? 0 : topCorrect //contentHeight - height of textView textView.contentOffset = CGPoint(x: 0, y: topCorrect) } } } // MARK: - UIView override func layoutSubviews() { super.layoutSubviews() let size = self.contentSize //forces didSet to be called self.contentSize = size } } 

En el ejemplo anterior (sacado directamente de mi subclass), notará que uso extensamente la propiedad contentOffset . Hago algunos cálculos para determinar dónde debe basarse el desplazamiento en la propiedad de alignment vertical y luego establecer la propiedad de desplazamiento de contenido de acuerdo (que es cómo se desplaza mediante progtwigción con una vista de desplazamiento)

Utilizo lo siguiente en una aplicación que se desplaza hacia abajo automáticamente cuando se agrega text:

Primero al inicializar tu textView, haz lo siguiente:

 textView.layoutManager.allowsNonContiguousLayout = false textView.addObserver(self, forKeyPath: "contentSize", options: .new, context: nil) 

A continuación, agregue el siguiente método de observación:

 override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { var bottom = textView.contentSize.height - textView.frame.size.height if bottom < 0 { bottom = 0 } if textView.contentOffset.y != bottom { textView.setContentOffset(CGPoint(x: 0, y: bottom), animated: true) } } 

la configuration permite a NonContiguousLayout a problemas de tamaño de contenido fijo falso para mí.

Al agregar el observador contentSize se observará cualquier cambio nuevo en el contenido Size de textView y se llamará a la function -observeValue (forKeyPath …) cuando se realicen cambios.

En la function -observeValue (…) , primero obtenemos la parte inferior (y contentOffset cuando se desplaza completamente hacia abajo). A continuación, comprobamos si ese valor es negativo, lo que significa que la altura contentSize es más pequeña que la altura del marco textView y no se puede realizar ningún desplazamiento. Si intenta desplazarse mediante progtwigción con ese valor negativo, causará esa inestabilidad infame que muchas personas conocen y aman. Entonces, para evitar esta inestabilidad, simplemente establecemos el valor de lo que ya debería ser, 0 o también puedes regresar .

Luego, simplemente probamos para ver si el contenido de la solución no es igual al valor inferior , le damos ese nuevo valor. Esto evita configurar el contenido del juego cuando no es necesario configurarlo.

Si está tratando con la propiedad attributedText de UITextView:

en viewDidLoad ()

 self.storyTextView.layoutManager.allowsNonContiguousLayout = false 

en tu método de desplazamiento

 let stringLength:Int = self.storyTextView.attributedText.string.characters.count self.storyTextView.scrollRangeToVisible(NSMakeRange(stringLength-1, 0)) 

Mucha gente está explicando cómo desplazarse hacia abajo, pero una cosa a tener en count es que esto no funcionará si lo coloca en viewDidLoad . Por ejemplo: necesitaba usar esto para desplazar un logging al final cuando la página se cargó. Para hacer esto, tuve que implementar el siguiente código

 - (void) viewDidLoad { [super viewDidLoad]; [_logTextView setText:[Logger loadLogText]]; } - (void) viewDidLayoutSubviews { [_logTextView setContentOffset:CGPointMake( 0.0, _logTextView.contentSize.height - _logTextView.frame.size.height ) animated:NO ]; } 

El desplazamiento real de UITextView no se puede hacer en viewDidLoad .

En mi viewDidLoad implementación de viewDidLoad , configuré el text para el textbox.

En mi implementación viewDidLayoutSubviews , establecí el offset de contenido para UITextView generando un CGPoint utilizando la altura del contenido de las vistas de text less la altura de la vista de text. De esta manera, cuando se desplaza hacia abajo, la parte inferior del text no está en la parte superior del cuadro y en su lugar, la parte inferior del text está en la parte inferior del cuadro.