2009-09-29 37 views
20

Vì vậy, UITableView hỗ trợ cuộn "vô hạn" về cơ bản. Có thể có giới hạn nhưng kẻ hút đó có thể cuộn trong thời gian looonnnggg. Tôi muốn bắt chước hành vi này với UIScrollView nhưng có hai trở ngại cơ bản:UIScrollView. Bất kỳ suy nghĩ nào về việc triển khai cuộn/thu phóng "vô hạn"?

1) scrollView.contentSize được cố định tại thời điểm tạo. 2) phóng to có thể thổi bất kỳ chương trình tải xuống tất cả xuống địa ngục vì nó có thể gây nổ dữ liệu infinte.

Có những người khác ở đó cân nhắc ý tưởng này? Tôi biết, chúng tôi chủ yếu nói về việc tạo lại Google Maps tại đây. Mọi thông tin chi tiết sẽ được đánh giá cao.

Chúc mừng, Doug

+0

Bạn đã xem MapKit chưa? –

+0

cũng UITableView là một phân lớp của UIScrollView –

Trả lời

10

Trong khi nó không thể có một UIScrollView thực sự vô hạn, có một số thủ thuật đơn giản bạn có thể sử dụng để mô phỏng hành vi đó.

  1. Xử lý chế độ xem cố định được xử lý bởi chế độ xem cuộn của bạn và khi khởi chạy hoặc đặt nhanh, đặt độ lệch nội dung sao cho bạn thấy ở giữa chế độ xem được xử lý. Sau đó, chỉ cần xem phần bù đắp nội dung (sử dụng KVO hoặc phương pháp khác) và nếu bạn ở gần cạnh bất kỳ, hãy cập nhật nội dung của chế độ xem bằng một tập hợp nội dung mới (bù đắp phù hợp) và đặt lại thuộc tính contentOffset của chế độ xem cuộn để quay lại ở giữa.
  2. Xử lý thu phóng: thực hiện tương tự, chỉ lần này xem hệ số thu phóng trên chế độ xem cuộn. Bất cứ khi nào nó đến một điểm nào đó, hãy thực hiện một số thao tác với bất kỳ dữ liệu nào bạn đang trình bày để nó xuất hiện thu nhỏ, sau đó đặt lại hệ số thu phóng thành 1.0. Ví dụ: nếu bạn đang cuộn một hình ảnh và nó được phóng to để xuất hiện lớn gấp hai lần, hãy áp dụng một số loại biến đổi để tạo hình ảnh gấp hai lần, sau đó đặt lại hệ số thu phóng của chế độ xem thành 1.0. Hình ảnh sẽ vẫn xuất hiện thu nhỏ, nhưng chế độ xem cuộn sẽ có thể tiếp tục phóng to thêm khi cần thiết. (Google Maps sẽ thực hiện thêm một bước nữa khi tải xuống chế độ xem chi tiết hơn khi người dùng phóng to - bạn có thể hoặc không chọn triển khai chế độ này.)
+2

Đây là một liên kết http://iphonedevelopment.blogspot.com/2009/02/kvo-and-iphone-sdk.html giải thích KVO cho bất kỳ ai không biết đó là gì. Giống như tôi đã không. – Grumdrig

+4

Vấn đề với giải pháp này là 'setContentOffset' hủy bỏ bất kỳ thao tác cuộn nào đang diễn ra và chuyển động đột ngột dừng lại. Tôi không biết cách nào để xác định tốc độ xem đang di chuyển hay cách khởi động lại chuyển động đó nếu tôi đã làm. – Grumdrig

+0

Nhưng tại sao phải thay đổi bù đắp nội dung? Hãy để nó cuộn, chỉ cần đảm bảo bạn giữ và di chuyển các khung nhìn hình ảnh tương ứng với những gì người dùng nhìn thấy. –

0

Có thể đặt contentSize thành giá trị khổng lồ và sau đó chuyển giới hạn số lượt xem cơ bản xung quanh để theo dõi vị trí xem như trong mẫu Tiling sẽ thực hiện thủ thuật.

Để giảm thiểu khả năng cuối cùng đạt được cạnh và phải đột ngột quay lại chế độ xem (hủy bỏ bất kỳ cuộn hiện đang chuyển động nào), chế độ xem có thể được quay lại khi nó dừng lại, theo thời gian.

Dù sao, đó là những gì tôi sắp thử.

+0

Điều này dường như hoạt động tốt, FYI. Tôi đang sử dụng 4 lượt xem có cùng kích thước với chế độ xem có chứa di chuyển cùng với cuộn. Tôi đã dựa trên mã của tôi trên (trên một nửa của) Cuộn mẫu. – Grumdrig

+0

Dự án ví dụ cuộn vô hạn của Apple đề xuất sử dụng phương pháp này. – zakdances

13

Tôi vừa hoàn thành việc triển khai cuộn chuyển cho tôi. Trong triển khai của tôi, tôi có UITableViewCell với một scrollView và Navigationbuttons. ScrollView chứa x lượt xem tất cả với cùng chiều rộng. lượt xem được đặt theo chiều ngang và phân trang được bật.

scrollView.clipsToBounds = YES; 
scrollView.scrollEnabled = YES; 
scrollView.pagingEnabled = YES; 
scrollView.showsHorizontalScrollIndicator = NO; 

codelogic của tôi là như sau:

  1. Trong chức năng khởi tạo của tôi, tôi
    • tạo mọi quan điểm (đối với scrollview) và
    • đặt chúng vào một mảng và
    • thêm chúng vào scrollView
  2. Sau đó, tôi gọi một hàm tính toán vòng lặp vị trí cho mỗi lần xem (mỗi khi bạn phát hiện một cuộn, chức năng này cũng sẽ cần được gọi). Nó luôn luôn lấy phần tử đầu tiên của mảng và đặt frame thành (0,0, ..., ...), thứ hai với (i * width, 0, ...., ....) và như vậy trên. Chức năng beeing gọi là trông như thế này:

    - (void)updateOffsetsOfViews{ 
        int xpos = 0; 
        for (int i=0; i<[views count]; i++) { 
         UIImageView *_view = [views objectAtIndex:i]; 
         CGRect aFrame = _view.frame; 
         aFrame.origin.x = xpos; 
         aFrame.origin.y = 0.0; 
         _view.frame = aFrame; 
         xpos += viewWidth; 
        } 
        float center = 0; 
        if(fmod([views count],2) == 1){ 
         center = viewWidth * ([views count]-1)/2; 
        }else { 
         center = viewWidth * [views count]/2; 
        } 
        [scrollView setContentOffset:CGPointMake(center, 0)]; 
        lastOffset = center; 
    } 
    
  3. Sau đó (vẫn còn trong quá trình khởi tạo) tôi thêm một người quan sát

    [scrollView addObserver:self forKeyPath:@"contentOffset" options:0 context:nil]; 
    

    vì vậy mỗi lần một cái gì đó trong những thay đổi scrollview tôi nhận được (observeValueForKeyPath) - chức năng được gọi, trông giống như sau:

    - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context 
    { 
        UIImageView *_viewFirst = (UIImageView *)[views objectAtIndex:0]; 
        if (fmod([scrollView contentOffset].x,viewWidth) == 0.0) { 
         if ([scrollView contentOffset].x > lastOffset) { 
          [views removeObjectAtIndex:0]; 
          [views addObject:_viewFirst];     
          [self updateOffsetsOfViews];  
         }else if ([scrollView contentOffset].x < lastOffset) { 
          UIImageView *_viewLast = (UIImageView *)[views lastObject]; 
          [views removeLastObject]; 
          [views insertObject:_viewLast atIndex:0];    
          [self updateOffsetsOfViews]; 
         } 
        } 
    } 
    
  4. Và trong dealloc hoặc viewDidUnload (phụ thuộc vào cách bạn triển khai) đừng quên làm lại đã quan sát.

    [scrollView removeObserver:self forKeyPath:@"contentOffset"]; 
    

Hope this helps, bạn có thể nhận thấy một số phí, nhưng trong việc thực hiện của tôi, tôi cũng hỗ trợ như di chuyển 5 trang (cũng ... không giới hạn) cùng một lúc và autoanimated di chuyển vv để bạn có thể thấy một cái gì đó có thể bị vứt đi.

+1

Giải pháp khá tốt, nhưng không thực hiện so sánh dấu phẩy động bằng cách sử dụng ==, nó sẽ phá vỡ. –

+0

Tôi đã thử mã của bạn.Nhưng khi tôi nhanh chóng cuộn 2 trang, Mã sẽ không xử lý đúng. – jeswang

2

Lưu ý rằng khi cuộn động, contentOffset thay đổi nhiều lần, không chỉ từng trang, mà còn với từng bước trong hoạt ảnh.

Các vấn đề liên quan