2011-07-24 31 views
8

Tôi đang viết một ứng dụng có chế độ xem giá sách như iBooks.Cách kéo và di chuyển thứ gì đó và cuộn cùng lúc trong UIScrollView

Vấn đề bây giờ là: Tôi có thể kéo và thả một cuốn sách từ trên nơi để another.But làm thế nào để làm cho những xảy ra cùng một lúc khi tôi kéo cuốn sách để dưới cùng của scrollview:

  1. làm cho scrollview cuộn xuống
  2. giữ cuốn sách theo ngón tay của tôi
  3. nơi những cuốn sách khác tại nơi đúng với hình ảnh động như di chuyển các ứng dụng trong bàn đạp

tôi biết có một AQGridView trong Github, nhưng có vẻ như bản demo springboard không hỗ trợ di chuyển và di chuyển cùng lúc. (Tôi đã đặt scrollEnable thành YES)

Trả lời

13

Tôi sẽ cung cấp cho bạn giải pháp của mình, nhưng vì toàn bộ sẽ chỉ cung cấp cho bạn các đoạn mã có liên quan.

Ngoài ra, hãy nhớ rằng tôi sử dụng trình nhận dạng cử chỉ để kéo (UILongPressGestureRecognizer) vì đó là cách người dùng bắt đầu kéo trong ứng dụng của tôi, bằng cách giữ ngón tay của mình ấn vào đối tượng. Vì vậy, mỗi subview bạn có thể kéo xung quanh có UILongPressGestureRecognizer riêng của nó được gán cho nó, và target/selector của bộ nhận dạng đó nằm trong một lớp khác quản lý cả scrollview và subviews.

đây là mục tiêu của nhận dạng cử chỉ:

-(void)dragged:(UILongPressGestureRecognizer *)panRecog 
{ 
    if (panRecog.state == UIGestureRecognizerStateBegan) 
    { 
     UIView * pannedView = panRecog.view; 

     dragView = pannedView; 
     dragView.center = [panRecog locationInView:scrollView]; 

     [scrollView bringSubviewToFront:dragView]; 

     [self startDrag]; // Not important, changes some stuff on screen to show the user he is dragging 
     return; 
    } 

    if (panRecog.state == UIGestureRecognizerStateChanged) 
    { 
     int xDelta = dragView.center.x - [panRecog locationInView:scrollView].x; 
     dragView.center = [panRecog locationInView:scrollView]; 

     [self scrollIfNeeded:[panRecog locationInView:scrollView.superview] withDelta:xDelta]; 

     return; 
    } 

    if (panRecog.state == UIGestureRecognizerStateEnded) 
    { 
     [self endDrag]; // Not important, changes some stuff on screen to show the user he is not dragging anymore 
    } 
} 

Những điều có liên quan cho bạn:

  • Khi bắt đầu kéo tôi ghi nhận những xem tôi kéo trong dragView và thiết lập trung tâm của nó là vị trí ngón tay của bạn có liên quan đến scrollview nó đang ở.
  • startDrag không quan trọng đối với bạn, nó thay đổi một số nội dung trên màn hình để hiển thị người dùng mà anh đang kéo
  • Khi chúng ta thực sự di chuyển đối tượng của mình (UIGestureRecognizerStateChanged), tôi lấy số điểm mà người dùng di chuyển ngón tay của mình và sử dụng đồng bằng đó cùng với vị trí ngón tay của người dùng để kiểm tra xem scrollview có cần di chuyển trong scrollIfNeeded hay không.

Đây là mã

-(void)scrollIfNeeded:(CGPoint)locationInScrollSuperview withDelta:(int)xDelta 
{ 
    UIView * scrollSuperview = scrollView.superview; 
    CGRect bounds = scrollSuperview.bounds; 
    CGPoint scrollOffset = scrollView.contentOffset; 
    int xOfs = 0; 
    int speed = 10; 

    if ((locationInScrollSuperview.x > bounds.size.width * 0.7) && (xDelta < 0)) 
    { 
     xOfs = speed * locationInScrollSuperview.x/bounds.size.width; 
    } 

    if ((locationInScrollSuperview.x < bounds.size.width * 0.3) && (xDelta > 0)) 
    { 
     xOfs = -speed * (1.0f - locationInScrollSuperview.x/bounds.size.width); 
    } 

    if (xOfs < 0) 
    { 
     if (scrollOffset.x == 0) return; 
     if (xOfs < -scrollOffset.x) xOfs = -scrollOffset.x; 
    } 
    scrollOffset.x += xOfs; 
    CGRect rect = CGRectMake(scrollOffset.x, 0, scrollView.bounds.size.width, scrollView.bounds.size.height); 
    [scrollView scrollRectToVisible:rect animated:NO]; 
    CGPoint center = dragView.center; 
    center.x += xOfs; 
    dragView.center=center; 
} 

điều này chỉ làm cho cuộn ngang, nhưng xử lý dọc sẽ là khá tương tự. Những gì nó làm là:

  • Kiểm tra xem bạn có kéo vào vùng ranh giới của chế độ xem cuộn hay không (tôi sử dụng đường viền 30% sang trái và phải làm vùng sẽ cuộn). Nhưng chỉ khi người dùng di chuyển theo hướng đó (xDelta < 0 cho bên trái, xDelta> 0 cho bên phải)
  • tiếp theo tôi tính toán bao nhiêu để di chuyển scrollview, sử dụng hằng số tốc độ và chia tỷ lệ này với khoảng cách người dùng đến từ biên giới thực tế của scrollview để tốc độ tỷ lệ với mức độ cạnh của người dùng.
  • Bước cuối cùng là cuộn scrollview bằng scrollRectToVisible không hoạt hình. Tất nhiên, chế độ xem được kéo của bạn sẽ di chuyển dọc theo, vì vậy chúng tôi bù đắp cho điều đó với độ lệch đối diện của tâm của nó.

Hy vọng điều này có thể giúp bạn.

+0

Đó là những gì tôi cần! Thực sự cảm ơn – ultragtx

+0

Thực hiện tốt, cảm ơn;)! – Oliver

+0

Công trình này tuyệt vời! Tuy nhiên, xDelta caluclation nên là vị trí hiện tại trừ đi vị trí cuối cùng. giá trị cuối cùng trừ đi giá trị ban đầu, sao cho một người dùng xDelta dương trừ đi được kéo sang phải và xDelta âm nghĩa là họ đã kéo sang trái. nhưng nó cũng hoạt động theo cách của bạn. :) – ucangetit

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