2011-12-15 16 views
15

Estoy intentando un editor de texto enriquecido (con capacidad de exportación HTML) para una aplicación de iPhone en la que estoy trabajando, y decidí usar el soporte WebKit de iOS 5 para contentEditable/designMode. He golpeado una pared con un problema que se está rompiendo por lo que necesito. Al editar el contenido en UIWebView, no hay desplazamiento automático para seguir el cursor, como, por ejemplo, en UITextView. Al escribir, el cursor continúa debajo de scrollView y el usuario tiene que desplazarse hacia arriba manualmente.Desplazamiento automático cuando contentEditable/designMode en un UIWebView

Aquí hay un código relevante:

- (void)webViewDidFinishLoad:(UIWebView *)webView 
{ 
    NSString *string = @"document.body.contentEditable=true;document.designMode='on';void(0)"; 
    [webView stringByEvaluatingJavaScriptFromString:string]; 

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil]; 
} 

Alguna idea de cómo solucionar este problema? No estoy seguro si esto también ocurre en Safari o solo en la implementación de WebKit UIWebView.

Si llega a este problema, asegúrese de cabeza a https://bugreport.apple.com y duplicar rdar: // 16455638.

Respuesta

3

para responder a mi propia pregunta, al final terminamos haciendo un montón de trabajo para asegurarse de que esto funciona correctamente a través de múltiples versiones de iOS. Nos encontramos con que todos los eventos de desplazamiento se debieron a la UIWebView tratando de gestionar su UIWebScrollView. Decidimos en lugar de utilizar un UIWebView, tomaríamos el interior UIWebDocumentView/UIWebBrowserView y añadirlo a nuestra propia visión de desplazamiento. Esto nos permitió gestionar el tamaño del contenido y desplazarnos y eliminar la mayoría de los problemas que experimentamos anteriormente.

+0

Quiero explorar esta ruta, pero me preocupa porque esas son clases privadas, creo (en realidad no documentadas). ¿Tuviste algún problema cuando enviaste esta aplicación? ¿Hay formas "seguras" de hacer esto y cosas que evitar? Al igual que, ¿tiene que crear un UIWebView y luego reparent las vistas, vs crear estas otras clases directamente - para evitar el rechazo de la tienda de aplicaciones? – eselk

+1

@eselk Utilizamos muchos trucos, como el método swizzling, ISA swizzling, etc. En este caso, es mucho más simple. Tomamos la subvista desde la vista de desplazamiento, que está expuesta en la API pública y la agregamos a otra vista de desplazamiento, que está bajo nuestro control. –

+0

@LeoNatan ¿Puedes escribir algún código para lo mismo? – iDhaval

1

Primero Debe registrar las notificaciones del teclado, y en ese método keyboardWillShow, active un método de desplazamiento con un intervalo de 0.1 minutos.

-(void) keyboardWillShow:(NSNotification *)note 
    { 

     timer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(scroll) userInfo:nil repeats:YES]; 

    } 

    -(void) keyboardWillHide:(NSNotification *)note 
    { 
     [timer invalidate]; 

    } 

Haga que un miembro sea variable en el archivo .h y asigne memoria para ello en el método init().

NSString *prevStr; 

dentro de ese método de desplazamiento, haga lo siguiente.

-(void)scroll{ 

    if (![prevStr isEqualToString:[WebView stringByEvaluatingJavaScriptFromString:@"document.body.innerHTML"]]) { 
     prevStr = [[WebView stringByEvaluatingJavaScriptFromString:@"document.body.innerHTML"] retain]; 
     NSInteger height = [[WebView stringByEvaluatingJavaScriptFromString:@"document.body.offsetHeight;"] intValue]; 
     NSString* javascript = [NSString stringWithFormat:@"window.scrollBy(0, %d);", height]; 
     [WebView stringByEvaluatingJavaScriptFromString:javascript]; 
    } 

} 

Esto le permitirá desplazarse a la parte inferior cuando se está editando el contenido y el contenido es mayor que el marco de vista Web. Y en otros momentos podrá desplazarse hacia la parte superior de la página (el desplazamiento automático se retendrá en ese momento).

+0

Hola Selvin, no tendría que desplazarse por la vista web a la parte inferior? Esto no es algo que necesito en todo momento. Por ejemplo, si tengo un texto largo y hago clic en medio del texto, el cursor debe permanecer donde hice clic, no desplazarse hacia abajo. O tal vez no he entendido bien? –

+0

Hola @Leo. Lamentablemente, no sé cómo hacer eso. Debido a que no puedo obtener el desplazamiento actual de la vista de desplazamiento cuando está colocando el cursor en medio del texto. Tal vez deberíamos intentar compensar el contenido actual y, si no está cerca de la parte inferior, tenemos que detener el desplazamiento automático. . – Selvin

10

Después de horas de investigación, encontré una solución mejor, así que pensé en compartirla.

Hay un error en el contenido de iOS 5 Implementación editable donde scrollView principal no se desplazará con el símbolo de intercalación. Si hace que la etiqueta del cuerpo (o cualquier elemento de tamaño dinámico) sea editable, el cursor siempre se apagará.

Si configura un div editable para desbordamiento: desplazarse, notará que el div se desplazará. El desplazamiento de div no "rebota" o tiene barras de desplazamiento de forma predeterminada, pero puede aplicar el atributo -webkit-overflow-scrolling: touch al div para solucionarlo.

Con esta información, se puede arreglar con un envoltorio de este modo:

<!DOCTYPE html> 
<html> 
<head> 
<meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0; user-scalable=no;"/> 
<style type="text/css"> 
    html, body {height: 100%;} 
    body { 
     margin: 0; 
    } 
    #wrap { 
     height: 100%; 
     width: 100%; 
     overflow-y: scroll; 
     -webkit-overflow-scrolling: touch; 
    } 
    #editor { 
     padding: 10px; 
    } 
</style> 
</head> 
<body> 
<div id="wrap"> 
    <div id="editor" contenteditable="true"> 

    </div> 
</div> 
</body> 
</html> 

Básicamente se está desplazando el div en lugar del documento.

Desafortunadamente, el "scrollView" del div no tiene conocimiento del teclado virtual, por lo que el cursor desaparecerá detrás del teclado. Sin embargo, notará que la posición de intercalación está todavía en la pantalla en la parte inferior, detrás del teclado. Para solucionarlo, reduzca la altura de div/UIWebView para acomodar el teclado.

Otra cosa es posible que desee hacer es desactivar el desplazamiento en el ScrollView principal:

webView.scrollView.scrollEnabled = NO; 

El ScrollView principal no debe desplazarse de todos modos, pero se debe evitar cualquier fallo de desplazamiento.

+0

Hola Luke, estableceré tu respuesta como la respuesta aceptada. De hecho, lo he intentado yo mismo (sin el '-webkit-overflow-scrolling'), pero lamentablemente todavía estaba algo mal. Estoy aceptando porque es lo más cercano a lo que necesitaba en la pregunta. –

+0

yo añadiría que no tiene que tener una #wrap, puede cambiar todo eso CSS en el cuerpo, y que va a funcionar tan bien. – Heilemann

+1

¡Gran solución! Pero me di cuenta de un pequeño problema: si selecciono (resaltar) una palabra y comienzo a desplazarme, el estado resaltado permanece mientras se desplaza y va solo cuando termina el desplazamiento. De todos modos para superar esto? – vivek241

0

No pude hacer el truco de configurar "desbordamiento: desplazamiento" porque estropeó nuestro css que ya era bueno (si cambiamos el desbordamiento al hacer clic en el div editable, el diseño se descompuso). Fuimos con esto:

$(this).on('keypress',function(e){ 
    //$(this) is the contenteditable div 
    var lineHeight = parseInt($(this).css('line-height')) + 2; 
    //gets the height of the div   
    newh=$(this).height(); 
    if (typeof oldh === 'undefined') 
     oldh=newh;//saves the current height 
    if(oldh!=newh)//checks if the height changes 
    { 
     //if height changes, scroll up by 1 line (plus a little 2 px)    
     window.scrollBy(0,lineHeight); 
     oldh=newh;//resave the saved height since it changed 
    } 
}); 

Espero que esto ayude a alguien. PITA

Cuestiones relacionadas