2011-08-26 35 views
6

Tôi bắt nguồn từ một lớp học từ UIView, chỉ để nhận ra rằng có những hạn chế thực sự về kích thước của nó do bộ nhớ. Tôi có UIView này bên trong UIScrollView.Tránh UIView tạo canvas vẽ rất lớn

Có cách nào để tôi đưa nội dung nào đó vào trong chế độ xem cuộn không phải là lớp có nguồn gốc từ UIView mà tôi vẫn có thể vẽ và có thể rất lớn không?

Tôi không ngại phải trả lời các sự kiện phơi sáng hình chữ nhật, giống như một sự kiện khi sử dụng các hệ thống cửa sổ thông thường.

Cảm ơn.

Trả lời

5

Những thứ bên trong của UIScrollView phải là UIViews, bị giới hạn kích thước vì lý do bộ nhớ. UIView duy trì một cửa hàng sao lưu bitmap cho lý do hiệu suất, do đó, nó phải phân bổ bộ nhớ tỷ lệ thuận với kích thước của nó.

Cách thông thường mà bạn xử lý việc này là tạo một số UIViews và trao đổi chúng khi người dùng cuộn xung quanh. Các phiên bản khác của việc đó là sử dụng CATiledLayer. Không ai trong số đó cung cấp cho bạn mô hình vẽ "canvas khổng lồ". Đó là vào bạn để phá vỡ mọi thứ và vẽ chúng khi cần thiết. Đây là cách tiếp cận thông thường.

Nếu bạn thực sự muốn một canvas khổng lồ, đề xuất của tôi sẽ là CGPDFContext. Có hỗ trợ phong phú hiện có cho những điều này, đặc biệt là sử dụng UIWebView (hãy nhớ, bạn có thể mở các URI data: để tránh đọc tệp từ đĩa). Và bạn có thể vẽ trực tiếp các phần của chúng bằng cách áp dụng biến đổi affine và sau đó là CGContextDrawPDFPage. CGBitmapContext là một cách tiếp cận khác, nhưng nó có thể đòi hỏi nhiều bộ nhớ hơn cho một lượng nhỏ bản vẽ.

2

Vì vậy, bạn có một UIView bên trong một UIScrollView, nhưng bạn muốn bạn UIView có giới hạn rất lớn (ví dụ, vì vậy nó phù hợp với kích thước của UIScrollView 's contentSize của bạn). Nhưng bạn không muốn vẽ toàn bộ UIView mỗi khi cần hiển thị hoặc bạn cũng không thể vừa với toàn bộ nội dung của nó trong bộ nhớ cùng một lúc.

Hãy UIView của bạn sử dụng một sự ủng hộ CAScrollLayer, như sau:

// MyCustomUIView.m 

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

Thêm một phương pháp để cập nhật vị trí cuộn khi người dùng cuộn các UIScrollView chứa của bạn UIView:

// MyCustomUIView.m 

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

    [scrollLayer scrollToPoint:scrollOffset]; 
} 

Đảm bảo rằng khi bạn vẽ UIView, bạn chỉ vẽ các phần có trong số CGRect được cung cấp cho bạn:

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

Bây giờ, trong UIScrollViewDelegate của bạn, bạn sẽ cần phải thông báo CAScrollLayer xem ủng hộ của bạn khi phụ huynh UIScrollView cập nhật:

// 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]; 
} 

Bạn cũng có thể sử dụng CATiledLayer, đó là dễ dàng hơn vì bạn không cần phải theo dõi vị trí cuộn - thay vào đó, phương thức drawRect của bạn sẽ được gọi với mỗi ô khi cần. Tuy nhiên, điều này sẽ làm cho chế độ xem của bạn mờ dần. Nó có thể là mong muốn nếu bạn có ý định bộ nhớ cache các phần của quan điểm của bạn và không nhớ các bản cập nhật chậm.