2012-06-15 3 views
6

У меня есть представление, которое имеет две метки. Когда я прокручиваю влево, я заполняю следующий текст для текста. Точно так же прокручивание правых загружает предыдущий контент. Я хочу дать ярлыки, как они прокручиваются слева или справа. Раньше я использовал прокрутку, но у меня была проблема с памятью. Поэтому я использую один вид и нажимаю жесты следующего или предыдущего содержимого. Я хочу добавить скользящий эффект прокрутки в ярлыки. Как я могу это сделать?Прокрутить эффект с помощью жестов в iOS

+0

Кстати, пока я показываю способ анимации ярлыков ниже, я не понимаю, почему у вас будет «проблема с памятью» со списком прокрутки. Если вы публикуете этот код, мы можем помочь вам найти вашу проблему с памятью, если хотите. – Rob

+0

использовать покрытие поток его лучший и дать красивый взгляд – parag

ответ

15

Я не совсем уверен, какой эффект вы ищете, но вы можете сделать что-то подобное, что создает новую временную метку, выставляет ее на экран, анимирует перемещение ее по ярлыку, который у вас есть экран, а затем, когда это будет сделано, сбрасывает старый и удаляет временную метку. Это то, что реализация не-autolayout может выглядеть следующим образом:

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 
    // Do any additional setup after loading the view. 

    UISwipeGestureRecognizer *left = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(leftSwipe:)]; 
    [left setDirection:UISwipeGestureRecognizerDirectionLeft]; 
    [self.view addGestureRecognizer:left]; 
    // if non-ARC, release it 
    // [release left]; 

    self.label1.text = @"Mo"; 
} 

- (void)leftSwipe:(UISwipeGestureRecognizer *)gesture 
{ 
    NSString *newText; 
    UILabel *existingLabel = self.label1; 

    // in my example, I'm just going to toggle the value between Mo and Curly 

    if ([existingLabel.text isEqualToString:@"Curly"]) 
     newText = @"Mo"; 
    else 
     newText = @"Curly"; 

    // create new label 

    UILabel *tempLabel = [[UILabel alloc] initWithFrame:existingLabel.frame]; 
    [existingLabel.superview addSubview:tempLabel]; 
    tempLabel.text = newText; 

    // move the new label off-frame to the right 

    tempLabel.transform = CGAffineTransformMakeTranslation(tempLabel.superview.bounds.size.width, 0); 

    // animate the sliding of them into place 

    [UIView animateWithDuration:0.5 
        animations:^{ 
         tempLabel.transform = CGAffineTransformIdentity; 
         existingLabel.transform = CGAffineTransformMakeTranslation(-existingLabel.superview.bounds.size.width, 0); 
        } 
        completion:^(BOOL finished) { 
         existingLabel.text = newText; 
         existingLabel.transform = CGAffineTransformIdentity; 
         [tempLabel removeFromSuperview]; 
        }]; 

    // if non-ARC, release it 
    // [release tempLabel]; 
} 

Эта анимация оживляет этикетку по его надтаблице. Вы можете убедиться, что для параметра superview установлено значение «Подзаголовок клипа». Таким образом, анимация будет ограничена границами этого superview, что дает немного более отполированный вид.

Обратите внимание, что при использовании автоматического макета идея одинаков (хотя выполнение сложнее). В основном настройте свои ограничения, чтобы новое представление было справа, затем в блоке анимации обновите/замените ограничения, чтобы исходная метка была слева, а новая - в месте оригинальной метки и, наконец, в блок завершения сбрасывает ограничения исходной метки и удаляет временную метку.


Кстати, все это гораздо проще, если вы знакомы с одним из встроенных переходов:

- (void)leftSwipe:(UISwipeGestureRecognizer *)gesture 
{ 
    NSString *newText; 
    UILabel *existingLabel = self.label1; 

    // in my example, I'm just going to toggle the value between Mo and Curly 

    if ([existingLabel.text isEqualToString:@"Curly"]) 
     newText = @"Mo"; 
    else 
     newText = @"Curly"; 

    [UIView transitionWithView:existingLabel // or try `existingLabel.superview` 
         duration:0.5 
         options:UIViewAnimationOptionTransitionFlipFromRight 
        animations:^{ 
         existingLabel.text = newText; 
        } 
        completion:nil]; 
} 
+0

Большое спасибо за ваш подробный ответ. Теперь анимация в порядке. Но анимация scrollview лучше. Проблема со списком прокрутки: Внутри scrollview есть другое представление. Всякий раз, когда пользователь просматривает новое представление, добавляется внутри прокрутки. Но после 50 просмотров приложение выходит из строя с предупреждением о памяти. Я что-то пробовал, но не нашел решения. Поэтому решили удалить прокрутку. – Oktay

+0

@Oktay похоже, что у вас есть простая ошибка/утечка в коде прокрутки. Многие люди используют scrollviews без каких-либо проблем. Опять же, если вы публикуете свой код, я подозреваю, что он легко исправляется. – Rob

+0

@Oktay Вы говорите, что вам нравится анимация прокрутки лучше, но я не уверен, что вам нравится в этом. Поскольку он использует жест панорамы (т. Е. Это непрерывный жест, который начинает двигаться, как только вы начинаете перемещать палец по экрану)? Я сделал жестом салфетки, а не жест пан, потому что ваше название предполагало, что вы этого хотели, но непрерывный жест жеста очень прост. Или есть что-то еще в прокрутке, которую вы предпочитаете? – Rob

6

Если вы предпочитаете анимацию, которая ведет себя больше как вид прокрутки (то есть, с непрерывной обратной связью на жест), это может выглядеть примерно следующим:

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 

    UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panHandler:)]; 
    [self.view addGestureRecognizer:pan]; 

    self.label1.text = @"Mo"; 
} 

- (void)panHandler:(UIPanGestureRecognizer *)sender 
{ 
    if (sender.state == UIGestureRecognizerStateBegan) 
    { 
     _panLabel = [[UILabel alloc] init]; 

     // in my example, I'm just going to toggle the value between Mo and Curly 
     // you'll presumably set the label contents based upon the direction of the 
     // pan (if positive, swiping to the right, grab the "previous" label, if negative 
     // pan, grab the "next" label) 

     if ([self.label1.text isEqualToString:@"Curly"]) 
      _newText = @"Mo"; 
     else 
      _newText = @"Curly"; 

     // set the text 

     _panLabel.text = _newText; 

     // set the frame to just be off screen 

     _panLabel.frame = CGRectMake(self.label1.frame.origin.x + self.containerView.frame.size.width, 
            self.label1.frame.origin.y, 
            self.label1.frame.size.width, 
            self.label1.frame.size.height); 

     [self.containerView addSubview:_panLabel]; 

     _originalCenter = self.label1.center; // save where the original label originally was 
    } 
    else if (sender.state == UIGestureRecognizerStateChanged) 
    { 
     CGPoint translate = [sender translationInView:self.containerView]; 

     if (translate.x > 0) 
     { 
      _panLabel.center = CGPointMake(_originalCenter.x - self.containerView.frame.size.width + translate.x, _originalCenter.y); 
      self.label1.center = CGPointMake(_originalCenter.x + translate.x, _originalCenter.y); 
     } 
     else 
     { 
      _panLabel.center = CGPointMake(_originalCenter.x + self.containerView.frame.size.width + translate.x, _originalCenter.y); 
      self.label1.center = CGPointMake(_originalCenter.x + translate.x, _originalCenter.y); 
     } 
    } 
    else if (sender.state == UIGestureRecognizerStateEnded || sender.state == UIGestureRecognizerStateFailed || sender.state == UIGestureRecognizerStateCancelled) 
    { 
     CGPoint translate = [sender translationInView:self.containerView]; 
     CGPoint finalNewFieldLocation; 
     CGPoint finalOriginalFieldLocation; 
     BOOL panSucceeded; 

     if (sender.state == UIGestureRecognizerStateFailed || 
      sender.state == UIGestureRecognizerStateCancelled) 
     { 
      panSucceeded = NO; 
     } 
     else 
     { 
      // by factoring in the velocity, we can capture a flick more accurately 
      // 
      // (by the way, I don't like iOS's velocity, because if you stop moving, it records the velocity 
      // prior to stopping the move rather than noting that you actually stopped, so I usually calculate my own, 
      // but I'll leave this as is for purposes of this example) 

      CGPoint velocity = [sender velocityInView:self.containerView]; 

      if (translate.x < 0) 
       panSucceeded = ((translate.x + velocity.x * 0.5) < -(self.containerView.frame.size.width/2)); 
      else 
       panSucceeded = ((translate.x + velocity.x * 0.5) > (self.containerView.frame.size.width/2)); 
     } 

     if (panSucceeded) 
     { 
      // if we succeeded, finish moving the stuff 

      finalNewFieldLocation = _originalCenter; 
      if (translate.x < 0) 
       finalOriginalFieldLocation = CGPointMake(_originalCenter.x - self.containerView.frame.size.width, _originalCenter.y); 
      else 
       finalOriginalFieldLocation = CGPointMake(_originalCenter.x + self.containerView.frame.size.width, _originalCenter.y); 
     } 
     else 
     { 
      // if we didn't, then just return everything to where it was 

      finalOriginalFieldLocation = _originalCenter; 

      if (translate.x < 0) 
       finalNewFieldLocation = CGPointMake(_originalCenter.x + self.containerView.frame.size.width, _originalCenter.y); 
      else 
       finalNewFieldLocation = CGPointMake(_originalCenter.x - self.containerView.frame.size.width, _originalCenter.y); 
     } 

     // animate the moving of stuff to their final locations, and on completion, clean everything up 

     [UIView animateWithDuration:0.3 
           delay:0.0 
          options:UIViewAnimationOptionCurveEaseOut 
         animations:^{ 
          _panLabel.center = finalNewFieldLocation; 
          self.label1.center = finalOriginalFieldLocation; 
         } 
         completion:^(BOOL finished) { 
          if (panSucceeded) 
           self.label1.text = _newText; 
          self.label1.center = _originalCenter; 
          [_panLabel removeFromSuperview]; 
          _panLabel = nil; // in non-ARC, release instead 
         } 
     ]; 
    } 
} 

Примечание, я поставил как оригинальный ярлык, а также новый лейбл быть приготовлена ​​на, в контейнере UIVie w (называемый containerView, на удивление достаточно), так что я могу закрепить анимацию в этом контейнере.

Смежные вопросы