31

Tôi muốn có thể di chuyển màn hình con và tắt màn hình giống như bạn duyệt giữa các hình ảnh trong ứng dụng Ảnh của iPhone, vì vậy nếu chế độ xem phụ giảm hơn 1/2 màn hình khi tôi cho đi với ngón tay của tôi nó phải animate tắt màn hình, nhưng nó cũng phải hỗ trợ swipe vì vậy nếu tốc độ swipe/pan là đủ cao nó phải animate tắt màn hình mặc dù có thể là ít hơn 1/2 tắt màn hình.Hoạt ảnh UIView dựa trên tốc độ UIPanGestureRecognizer

Ý tưởng của tôi là sử dụng UIPanGestureRecognizer và sau đó kiểm tra trên vận tốc. Điều này làm việc, nhưng làm thế nào để thiết lập một thời gian hoạt hình chính xác cho việc di chuyển của UIView dựa trên vị trí hiện tại của xem và vận tốc của chảo để nó có vẻ trơn tru? Nếu tôi đặt giá trị cố định, hoạt ảnh hoặc bắt đầu chậm hoặc nhanh so với tốc độ vuốt ngón tay của tôi.

Trả lời

47

Các tài liệu nói

Vận tốc của cử chỉ chảo, mà được thể hiện ở điểm mỗi giây. Vận tốc được chia thành các thành phần nằm ngang và dọc.

Vì vậy, tôi muốn nói, vì bạn muốn di chuyển tầm nhìn của bạn xPoints (đo theo pt) để cho nó đi ra khỏi màn hình, bạn có thể tính toán thời gian cho phong trào như vậy:

CGFloat xPoints = 320.0; 
CGFloat velocityX = [panRecognizer velocityInView:aView].x; 
NSTimeInterval duration = xPoints/velocityX; 
CGPoint offScreenCenter = moveView.center; 
offScreenCenter.x += xPoints; 
[UIView animateWithDuration:duration animations:^{ 
    moveView.center = offScreenCenter; 
}]; 

Bạn có thể muốn sử dụng + (void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion thay vào đó và thử khác nhau UIViewAnimationOptions.

20

Quan sát dựa trên vận tốc trong UIPanGestureRecognizer: Tôi không biết về kinh nghiệm của bạn, nhưng tôi thấy rằng tốc độ hệ thống tạo ra trên trình mô phỏng không hữu ích khủng khiếp. (Đó là ok trên thiết bị, nhưng có vấn đề trên giả lập.)

Nếu bạn xoay nhanh và dừng đột ngột, đợi và chỉ sau đó kết thúc cử chỉ (ví dụ: người dùng bắt đầu vuốt, nhận ra rằng đây không phải là thứ họ muốn , do đó, chúng dừng lại và sau đó nhả ngón tay của chúng), vận tốc được báo cáo bởi velocityInView: ở trạng thái UIGestureRecognizerStateEnded khi ngón tay của bạn được phát hành có vẻ là tốc độ nhanh trước khi tôi dừng lại và chờ đợi, trong khi vận tốc phù hợp trong ví dụ này sẽ bằng không (hoặc gần số không). Tóm lại, vận tốc được báo cáo là nó đã ở ngay trước khi kết thúc chảo, nhưng không phải là tốc độ ở cuối chảo.

Tôi đã tự tính toán vận tốc theo cách thủ công. (Có vẻ ngớ ngẩn rằng điều này là cần thiết, nhưng tôi không thấy bất kỳ cách nào xung quanh nó nếu tôi thực sự muốn có được tốc độ cuối cùng của chảo.) Tóm lại, khi nhà nước là UIGestureRecognizerStateChanged Tôi theo dõi hiện tại và trước translationInView CGPoint cũng như thời gian, và sau đó sử dụng các giá trị đó khi tôi ở trong UIGestureRecognizerStateEnded để tính toán vận tốc cuối cùng thực tế. Nó hoạt động khá tốt.

Đây là mã của tôi để tính toán vận tốc. Tôi tình cờ không sử dụng vận tốc để tìm ra tốc độ của hình động, nhưng tôi đang sử dụng nó để xác định liệu người dùng có thể lướt đủ nhanh hoặc đủ nhanh để khung cảnh di chuyển hơn một nửa trên màn hình và do đó kích hoạt hoạt ảnh giữa các chế độ xem, nhưng khái niệm tính toán vận tốc cuối cùng có thể áp dụng cho câu hỏi này. Dưới đây là các mã:

- (void)handlePanGesture:(UIPanGestureRecognizer *)gesture 
{ 
    static CGPoint lastTranslate; // the last value 
    static CGPoint prevTranslate; // the value before that one 
    static NSTimeInterval lastTime; 
    static NSTimeInterval prevTime; 

    CGPoint translate = [gesture translationInView:self.view]; 

    if (gesture.state == UIGestureRecognizerStateBegan) 
    { 
     lastTime = [NSDate timeIntervalSinceReferenceDate]; 
     lastTranslate = translate; 
     prevTime = lastTime; 
     prevTranslate = lastTranslate; 
    } 
    else if (gesture.state == UIGestureRecognizerStateChanged) 
    { 
     prevTime = lastTime; 
     prevTranslate = lastTranslate; 
     lastTime = [NSDate timeIntervalSinceReferenceDate]; 
     lastTranslate = translate; 

     [self moveSubviewsBy:translate]; 
    } 
    else if (gesture.state == UIGestureRecognizerStateEnded) 
    { 
     CGPoint swipeVelocity = CGPointZero; 

     NSTimeInterval seconds = [NSDate timeIntervalSinceReferenceDate] - prevTime; 
     if (seconds) 
     { 
      swipeVelocity = CGPointMake((translate.x - prevTranslate.x)/seconds, (translate.y - prevTranslate.y)/seconds); 
     } 

     float inertiaSeconds = 1.0; // let's calculate where that flick would take us this far in the future 
     CGPoint final = CGPointMake(translate.x + swipeVelocity.x * inertiaSeconds, translate.y + swipeVelocity.y * inertiaSeconds); 

     [self animateSubviewsUsing:final]; 
    } 
} 
+0

Nó không hoạt động trong iOS 6 vì bản dịch cuối cùng và lastTranslation giống nhau trong 'UIGestureRecognizerStateEnded' để vận tốc cuối cùng luôn là 0. – an0

+1

Cảm ơn, tôi hiểu. Nó là một vấn đề của giả lập. Tôi đã báo cáo lỗi cho Apple. – an0

+0

Tôi đã sửa đổi nguồn (thay đổi một vài tên biến) để hy vọng tránh nhầm lẫn này. Mã này hoạt động tốt như trước đây, nhưng hy vọng rằng các tên biến mới làm cho nó thậm chí còn ít khó hiểu hơn một chút. Cảm ơn bạn đã báo cáo lỗi cho Apple. – Rob

1

Trong hầu hết các trường hợp thiết UIViewAnimationOptionBeginFromCurrentState lựa chọn cho UIView phim hoạt hình là đủ để tạo ra một hình ảnh động hoàn hảo tiếp tục.

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