LoginSignup
2
3

More than 5 years have passed since last update.

プログラムにフリックさせてイベントを受け取る

Posted at
  • フリックで左右にスクロールできるだけでなく、ナビゲーションバーにあるボタンからも左右にスクロールできるUIを想定。(標準のメールアプリみたいなイメージ)
  • ボタンからスクロールした場合も、フリックしたときと同様に、スクロール前後のイベントを受け取ってあれこれやりたい。
MainViewController.m
- (void)viewDidLoad {
    [super viewDidLoad];

    self.scrollContainer.animationDelegate = self;
}

- (void)scrollViewWillBeginDragging:(ScrollContainer *)scrollContainer {
    NSLog(@"offset: %d", self.scrollContainer.contentOffset.x);
}

- (void)scrollViewDidEndDecelerating:(ScrollContainer *)scrollContainer {
    NSLog(@"offset: %d", self.scrollContainer.contentOffset.x);
}

- (void)segmentDidChange:(id)sender {
    if (![sender isKindOfClass:[UISegmentControl class]]) {
        return;
    }
    UISegmentControl *segmentControl = sender;

    if (segmentControl.selectedSegmentIndex == 0) {
        [self.scrollContainer moveToPreviousContent];
    } else if (segmentControl.selectedSegmentIndex == 1) {
        [self.scrollContainer moveToNextContent];
    }
}
  • UISegmentControlで作ったボタンが押されると、ScrollContainerクラスのメソッドを呼び出して、左右どちらかにスクロールされる。
  • ScrollContainerは以下のようなUIScrollViewのサブクラス。
ScrollContainer.m
static CGFloat kContentWidth = 320.0f;

- (void)moveToNextContent {
    [UIView beginAnimation:nil context:NULL];
    [UIView setAnimationDuration:0.3f];
    [UIView setAnimationDelegate:self.animationDelegate];
    [UIView setAnimationWillStartSelector:@selector(scrollViewWillBeginDragging:)];
    [UIView setAnimationDidStopSelector:@selector(scrollViewDidEndDecelerating:)];

    CGPoint nextContentOffset = CGPointMake(self.contentOffset.x + kContentWidth, 0);
    self.contentOffset = nextContentOffset;

    [UIView commitAnimations];
}

- (void)moveToPreviousContent {
    [UIView beginAnimation:nil context:NULL];
    [UIView setAnimationDuration:0.3f];
    [UIView setAnimationDelegate:self.animationDelegate];
    [UIView setAnimationWillStartSelector:@selector(scrollViewWillBeginDragging:)];
    [UIView setAnimationDidStopSelector:@selector(scrollViewDidEndDecelerating:)];

    CGPoint previousContentOffset = CGPointMake(self.contentOffset.x - kContentWidth, 0);
    self.contentOffset = previousContentOffset;

    [UIView commitAnimations];
}
  • setContentOffset:animated:メソッドでもプログラムによるフリックを実現できるんだけど、スクロール前後のイベントを受け取ってあれこれすることはできないっぽい。
  • そこで、UIViewクラスのアニメーションを使って、アニメーション前後のイベントを利用する。
  • setAnimationWillStartSelector:setAnimationDidStopSelector:に直接scrollViewDidEndDecelerating:などを指定することで、プログラムによるフリックの場合でもイベントを受け取ることができる。
2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3