Question

I want to create UIScrollView with scrolling buttons.So when user press left arrow button, scroll must scroll properly.

The issue is: when I click button 3 times quickly scroll can't scroll properly (because of many calls of scrollRectToVisible). May be I can stop current animation before next animation?

P.S. If I set [self scrollScrollViewToIndex:index animated:NO] everything works properly, but I need animation

Here is my code:

- (void)scrollScrollViewToIndex:(int)index animated:(BOOL)animated
{
    NSLog(@"scrolled to index: %d", index);
    CGFloat offsetX = CGRectGetWidth(_scrollMain.frame) * index;
    CGRect scrollRect = CGRectMake(offsetX, 0, CGRectGetWidth(_scrollMain.frame), CGRectGetHeight(_scrollMain.frame));    
    [_scrollMain scrollRectToVisible:scrollRect animated:animated];
//    [self.scrollMain setContentOffset:CGPointMake(offsetX, 0) animated:animated];
}

- (IBAction)leftArrowPressed:(id)sender
{
    int indexOfVoucher = [_arrayVouchers indexOfObject:_voucher];
    indexOfVoucher--;
    self.voucher = [_arrayVouchers objectAtIndex:indexOfVoucher];
    [self updateViewWithVoucherWithScrolling:YES];
}

- (IBAction)rightArrowPressed:(id)sender
{
    int indexOfVoucher = [_arrayVouchers indexOfObject:_voucher];
    indexOfVoucher++;
    self.voucher = [_arrayVouchers objectAtIndex:indexOfVoucher];
    [self updateViewWithVoucherWithScrolling:YES];
}

- (void)updateViewWithVoucherWithScrolling:(BOOL)withScrolling
{
    int indexOfVoucher = [_arrayVouchers indexOfObject:_voucher];
    _leftArrowButton.hidden = _rightArrowButton.hidden = NO;
    if (indexOfVoucher == 0)
    {
        _leftArrowButton.hidden = YES;
    }
    else if (indexOfVoucher == [_arrayVouchers count] - 1)
    {
        self.rightArrowButton.hidden = YES;
    }
    if (withScrolling)
    {
       [self scrollScrollViewToIndex:indexOfVoucher animated:YES]; 
    }
}

update: working code according to Mar0ux's advice

- (void)scrollScrollViewToIndex:(int)index animated:(BOOL)animated
{
    NSLog(@"scrolled to index: %d", index);
    CGFloat offsetX = CGRectGetWidth(_scrollMain.frame) * index;

    if (animated)
    {
        [UIView animateWithDuration:0.5
                              delay:0.0
                            options:UIViewAnimationCurveEaseInOut | UIViewAnimationOptionBeginFromCurrentState //Multiple options
                         animations:^ {
                             //                         [self.scrollMain setContentOffset:CGPointMake(offsetX, 0) animated:NO];
                             CGRect scrollRect = CGRectMake(offsetX, 0, CGRectGetWidth(_scrollMain.frame), CGRectGetHeight(_scrollMain.frame));
                             [_scrollMain scrollRectToVisible:scrollRect animated:NO];
                         }
                         completion:^ (BOOL finished) {

                         }];
    }
    else
    {
        CGRect scrollRect = CGRectMake(offsetX, 0, CGRectGetWidth(_scrollMain.frame), CGRectGetHeight(_scrollMain.frame));
        [_scrollMain scrollRectToVisible:scrollRect animated:NO];
    }
}
Était-ce utile?

La solution

You can always animate the contentOffset property yourself and use UIViewAnimationOptionBeginFromCurrentState option. As soon as the second animation begins, the first will end, and by using current state option, the second animation will start from where the first left off.

Autres conseils

A few suggestions:

1) do you really want the user hammering on the button while its scrolling? If so then I suggest that your UI design may need redesign.

2) when you perturb the UI in an action method, its best to post other UI actions by dispatching a block with the code to the main queue - the button hiliting will look better.

3) in your specific case, you could in the action method disable the button, then re-enable it when the scrolling has stopped.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top