7

Tôi đang cố gắng tạo lại hành vi của trình đơn trượt lên của ứng dụng Google Maps iOS mới.Tạo chế độ xem trang trình bày tương tự như ứng dụng Google Maps iOS mới, các sự cố với nhiều UIPanGestureRecognizer

Vì vậy, về cơ bản đó là chế độ xem bạn có thể trượt lên bằng cách di chuyển lên đến một điểm nhất định hoặc trượt xuống đến một điểm nhất định. Chế độ xem này cũng có thể trượt sang phải và sang trái như chế độ xem cuộn được phân trang.

Cần di chuyển lên hoặc xuống hoặc trượt sang một bên nhưng không phải cả hai cùng một lúc.

Sau nhiều nghiên cứu và thử nghiệm, tôi có một thứ gần gũi nhưng không hoàn toàn hoạt động như cần.

Triển khai của tôi là UIScrollView với khung 320x400 và chế độ xem nội dung 960x400 với cuộn được phân trang. Sau đó, tôi thêm một UIPanGestureRecognizer xử lý các slide lên của toàn bộ xem.

Đây là handleTouch IBAction của PanRecognizer:

- (IBAction)handlePan:(UIPanGestureRecognizer *)sender { 
NSLog(@"Panning"); 
    CGPoint translatedPoint = [(UIPanGestureRecognizer*)sender translationInView:self.view]; 

    if([(UIPanGestureRecognizer*)sender state] == UIGestureRecognizerStateBegan) { 
     _firstX = [[sender view] center].x; 
     _firstY = [[sender view] center].y; 
    } 
    if (!IS_IPHONE_5) { 
     if (_firstY < 216) 
      translatedPoint = CGPointMake(_firstX, 216); 
     else 
      translatedPoint = CGPointMake(_firstX, _firstY+translatedPoint.y); 
    } 
    else { 
     if (_firstY < 307) 
      translatedPoint = CGPointMake(_firstX, 307); 
     else 
      translatedPoint = CGPointMake(_firstX, _firstY+translatedPoint.y); 
    } 
    [[sender view] setCenter:translatedPoint]; 
    if([(UIPanGestureRecognizer*)sender state] == UIGestureRecognizerStateEnded) { 
     CGFloat velocityY = (0.2*[(UIPanGestureRecognizer*)sender velocityInView:self.view].y); 

     CGFloat finalX = _firstX; 
     CGFloat finalY = translatedPoint.y + velocityY; 
     if(finalY < _firstY) { 
      if (IS_IPHONE_5) 
       finalY = 307; 
      else 
       finalY = 216; 
     } 
     else if(finalY > _firstY) { 

      if (IS_IPHONE_5) 
       finalY = 605; 
      else 
       finalY = 515; 
     } 

     CGFloat animationDuration = (ABS(velocityY)*.0002)+.2; 
     [UIView beginAnimations:nil context:NULL]; 
     [UIView setAnimationDuration:animationDuration]; 
     [UIView setAnimationCurve:UIViewAnimationCurveEaseOut]; 
     [UIView setAnimationDelegate:self]; 
     [UIView setAnimationDidStopSelector:@selector(animationDidFinish)]; 
     [[sender view] setCenter:CGPointMake(finalX, finalY)]; 
     [UIView commitAnimations]; 
    }} 

Vì vậy, về cơ bản nếu chảo trượt nhìn lên và không để hai bên. Vấn đề tôi có với phương pháp handlePan này là tôi không thể làm cho nó hoạt động sao cho nó không cho phép cuộn cao hơn một điểm. Tôi đang cố gắng làm gì với:

if (_firstY < 216) 
      translatedPoint = CGPointMake(_firstX, 216); 
     else 
      translatedPoint = CGPointMake(_firstX, _firstY+translatedPoint.y); 

Vấn đề lớn nhất là công cụ nhận dạng cử chỉ của UIScrollView đang xử lý chảo cùng thời điểm tôi thêm. Điều đó có nghĩa là UIScrollView được trượt lên và sang hai bên cùng một lúc nếu tôi trượt màn hình bằng ngón tay của mình bằng cách di chuyển nó sang hai bên.

Tương tự xảy ra nếu tôi cố trượt sang hai bên và di chuyển chế độ xem lên 1 pixel trong khi thực hiện, trình nhận dạng pan của tôi kết thúc và trượt chế độ xem lên hoàn toàn.

Cách khắc phục mà tôi tìm thấy là đặt trình nhận dạng pan của tôi để yêu cầu trình nhận dạng pan UIScrollview không hoạt động.

[_panGestureRecognizer requireGestureRecognizerToFail: _slideUpScrollView.panGestureRecognizer]; 

Vì vậy, bây giờ khi tôi trượt sang bên, nó hoạt động và không di chuyển chế độ xem. Vấn đề suy nghĩ là nó đặt chính nó như là thất bại chỉ khi bạn loại bỏ ngón tay của bạn và xem không di chuyển sang hai bên. Điều gì xảy ra là bạn không thể di chuyển chế độ xem lên nữa nhưng nếu bạn nhấp vào bên trong nó sẽ thực hiện "UIGestureRecognizerStateEnded" nếu và trượt chế độ xem lên.

Tôi đã xem các chủ đề của UIPanGestureRecognizer và xem xét một vài tùy chọn bao gồm, phân lớp trình nhận dạng pan của tôi để làm cho nó nhận ra chỉ có các cửa sổ trượt lên chứ không phải các mặt bên.

Các bạn có nghĩ rằng tôi đang sử dụng đúng chiến lược hay tôi nên xem nó theo cách khác? Giải pháp lý tưởng sẽ là khi một slide sang bên được ghi lại, nó chỉ di chuyển nội dung theo chiều ngang và được xử lý bởi UIScrollView và khi một pan ngang được ghi lại, nó chỉ quét theo chiều dọc và được xử lý bởi bộ thu âm của tôi. Hành vi tương tự mà Safari có với cuộn ngang và dọc. Mặc dù tôi không tìm ra cách để thực hiện điều đó.

Cảm ơn bạn đã đọc, hãy cho tôi biết suy nghĩ của bạn. Nó sẽ là tuyệt vời nếu nhiều ứng dụng có một trình đơn tuyệt vời lên như Google Maps!

Chỉnh sửa: Tôi đang nhắm mục tiêu iOS 6.

+0

Vui lòng giải thích các biến finalX, Y và _firstX, Y. Nó sẽ hữu ích cho tôi. – arunit21

+0

_firstX, Y là để lưu vị trí bắt đầu khi panning bắt đầu. Sau đó, nó được so sánh với finalX, Y để thiết lập/thiết lập lại vị trí cuộn nếu cần thiết. – Blackcode

Trả lời

5

OK, tôi đã tìm ra!

Tôi đã sử dụng các ví dụ từ UIPanGestureRecognizer - Only vertical or horizontal để giới hạn chảo của tôi lên và xuống để cuộn dọc và biến nó thành trạng thái không thành công khi được quét theo chiều ngang.

Tôi cũng đã sử dụng: Restricting UIPanGestureRecognizer movement để chặn chế độ xem từ panning đến xa hoặc xuống.

Cuối cùng tôi đảo ngược các requiresToFail tới:

[_slideUpScrollView.panGestureRecognizer requireGestureRecognizerToFail:_panGestureRecognizer]; 

Và có nó hoạt động!

Hãy cho tôi biết nếu bạn có câu hỏi hoặc có cải tiến để đề xuất!

Cảm ơn!

+5

bạn có thể xin vui lòng gửi bản sao làm việc (mẫu) của điều này? – harshitgupta

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