2011-08-26 9 views
6

Obtuve una clase de UIView, solo para darme cuenta de que existen limitaciones reales en cuanto a su tamaño debido a la memoria. Tengo esta UIView dentro de UIScrollView.Evitar que UIView cree un lienzo de dibujo muy grande

¿Hay alguna manera de poner algo dentro de una vista de desplazamiento que no sea una clase derivada de UIView pero en la que todavía pueda dibujar, y que puede ser muy grande?

No me importa tener que responder a los eventos de exposición de rectángulo, como ocurre con los sistemas de ventanas convencionales.

Gracias.

Respuesta

5

Las cosas dentro de un UIScrollView deben ser UIViews, que son de tamaño restringido por razones de memoria. UIView mantiene un almacén de respaldo de mapas de bits por razones de rendimiento, por lo que debe asignar memoria proporcional a su tamaño.

La forma habitual de manejar esto es generar varios UIViews y cambiarlos a medida que el usuario se desplaza. La otra versión de eso es usar CATiledLayer. Sin embargo, ninguno de esos te da el modelo de dibujo "lona gigante". Depende de usted separar las cosas y dibujarlas según sea necesario. Este es el enfoque habitual, sin embargo.

Si realmente quieres un lienzo gigante, mi recomendación sería CGPDFContext. Existe un amplio soporte para estos, particularmente usando UIWebView (recuerde, puede abrir data: URI para evitar leer archivos del disco). Y puede dibujar partes de ellos directamente aplicando transformaciones afines y luego CGContextDrawPDFPage. CGBitmapContext es otro enfoque, pero podría requerir mucha más memoria para una pequeña cantidad de dibujo.

2

para que tenga una UIView dentro de un UIScrollView, pero usted quiere que su UIView que tienen muy anfiteatro (es decir, para que coincida con el tamaño de sus UIScrollView 's contentSize). Pero no desea dibujar el UIView completo cada vez que necesita mostrarlo, ni puede ajustar todo su contenido en la memoria a la vez.

Haga su UIView utiliza un respaldo CAScrollLayer, de la siguiente manera:

// MyCustomUIView.m 

+ (Class) layerClass 
{ 
    return [CAScrollLayer class]; 
} 

añadir un método para actualizar la posición de desplazamiento cuando el usuario desplaza el UIScrollView que contiene su UIView:

// MyCustomUIView.m 

- (void) setScrollOffset:(CGPoint)scrollOffset 
{ 
    CAScrollLayer *scrollLayer = (CAScrollLayer*)self.layer; 

    [scrollLayer scrollToPoint:scrollOffset]; 
} 

asegurar que cuando Si dibuja su UIView, solo dibujará las partes que figuran en el CGRect que le proporcionó:

- (void)drawRect:(CGRect)rect 
{ 
    // Only draw stuff that lies inside 'rect' 
    // CGRectIntersection might be handy here! 
} 

Ahora, en su UIScrollViewDelegate, tendrá que notificar a su CAScrollLayer vista respaldado cuando los padres UIScrollView actualizaciones:

// SomeUIScrollViewDelegate.m 

- (void) scrollViewDidScroll:(UIScrollView *)scrollView 
{ 
    // Offset myCustomView within the scrollview so that it is always visible 
    myCustomView.frame = CGRectMake(scrollView.contentOffset.x, 
            scrollView.contentOffset.y, 
            scrollView.bounds.size.width, 
            scrollView.bounds.size.height); 

    // "Scroll" myCustomView so that the correct portion is rendered 
    [myCustomView setScrollOffset:self.contentOffset]; 

    // Tell it to update its display 
    [myCustomView setNeedsDisplay]; 
} 

También se pueden utilizar CATiledLayer, que es más fácil porque usted no tiene que rastrear la posición de desplazamiento; en su lugar, se llamará a su método drawRect con cada panel según sea necesario. Sin embargo, esto hará que su vista se desvanezca lentamente. Puede ser deseable si tiene la intención de almacenar en caché partes de su vista y no le importa las actualizaciones lentas.

Cuestiones relacionadas