iphone - how to scroll uiscrollview from event tou

2019-07-18 17:05发布

问题:

structure UIViewController - UIScrollview - UIButton

I'm going to make scrollview can receive button event. So whenever user do scrolling(dragging) on the button, the scrollview react as scrolling itself.

I made button down and moved handler with event forwarding like below

- (IBAction)buttonTouchedMove:(id)sender withEvent:(UIEvent *)event {
    [[sender nextResponder] touchesMoved:[event allTouches] withEvent:event];
}
- (IBAction)buttonTouchedDown:(id)sender withEvent:(UIEvent *)event {
    [[sender nextResponder] touchesBegan:[event allTouches] withEvent:event];
}

and to move scrollview as touches change, I made below codes

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    UITouch *touch = [touches anyObject];
    self.oldPoint = [touch locationInView:self.view];
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    CGPoint offset = self.scrollView1.contentOffset;
    UITouch *touch = [touches anyObject];
    self.newPoint = [touch locationInView:self.view];
    int diffX = newPoint.x - oldPoint.x;
    offset.x = offset.x - diffX;
    [scrollView1 setContentOffset:offset animated:YES];
    self.oldPoint = self.newPoint;
}

but, scrollview react strange.. not move enough as I touch moved.

回答1:

// get the button width

CGFloat buttonWidth = self.theButton.frame.size.width;
// replace your button name here


// now get the view width

CGFloat viewWidth = self.view.frame.size.width;
// replace your view name here

// now get the multiplier which i said u as 10

CGFloat mult = viewWidth / buttonWidth;

// and now use it in your code

.
.
.
 diffX = mult*(newPoint.x - oldPoint.x);
.
.
.


回答2:

Final answer, Using UIView animation, I got what i want.

- (IBAction)buttonTouchedDown:(id)sender withEvent:(UIEvent *)event {
    UITouch *touch = [[event allTouches] anyObject];
    self.oldPoint = [touch locationInView:self.view];
    self.velocity = 0;
    isButtonTouchedDown = YES;
}

- (IBAction)buttonTouchedMove:(id)sender withEvent:(UIEvent *)event {
    CGPoint offset = self.scrollView1.contentOffset;
    UITouch *touch = [[event allTouches] anyObject];
    self.newPoint = [touch locationInView:self.view];
    int diffX = self.newPoint.x - self.oldPoint.x;
    velocity = diffX;

    offset.x = offset.x - diffX;
    [self.scrollView1 setContentOffset:offset animated:NO];
    self.oldPoint = self.newPoint;
}

There is a trick..I calculated velocity by differentiating moved distance in TouchedMove function. In Button TouchUp event handler, I controlled Scrollview with velocity value and CurveEaseout animation to scroll more. By offering very short duration of animation and repeating it if there is no event(button touched down). It becomes very similar with scrollview's animation.

- (IBAction)buttonTouchedUp:(id)sender withEvent:(UIEvent *)event {
    CGPoint offset = self.scrollView1.contentOffset;
    amountX = (self.velocity)*(abs(self.velocity));
    dX = amountX;
    isButtonTouchedDown = NO;
    if (offset.x - amountX < 0) {
        offset.x = 0;
        [scrollView1 setContentOffset:offset animated:YES];
    }
    else if (abs(dX) < 70) { // 70: content item size
        offset.x = roundf(offset.x/70)*70;
        [scrollView1 setContentOffset:offset animated:YES];
    }
    else {
        [self endScrollAnimation];
    }

- (void)startAnimation:(float)x moveAmount:(float)moveAmount
{
    CGPoint offset = self.scrollView1.contentOffset;
    [UIView beginAnimations:nil context:nil];
    [UIView setAnimationDuration:duration];

    offset.x = x < 0 ? offset.x + moveAmount : offset.x -moveAmount;

    [UIView setAnimationCurve:UIViewAnimationCurveLinear];
    [UIView setAnimationDelegate:self];
    [UIView setAnimationDidStopSelector:@selector(endScrollAnimation)];
    [scrollView1 setContentOffset:offset animated:NO];
    [UIView commitAnimations];

}

- (void)endScrollAnimation
{
    CGPoint offset = self.scrollView1.contentOffset;
    float slowMoveAmount = abs(amountX) * 0.05;
    float fastMoveAmount = abs(amountX) * 0.1;
    if (isButtonTouchedDown) {
        return;
    }
    else if (abs(dX) > abs(amountX)*0.35 && offset.x > 0) {
        [self startAnimation:dX moveAmount:fastMoveAmount];
        dX  = dX < 0 ? dX + fastMoveAmount : dX -fastMoveAmount;
    }
    else if (abs(dX) > slowMoveAmount && offset.x > 0) {
        [self startAnimation:dX moveAmount:slowMoveAmount];
        dX = dX < 0 ? dX + slowMoveAmount : dX - slowMoveAmount;
    }
    else {
        offset.x = roundf(offset.x/70)*70;
        [scrollView1 setContentOffset:offset animated:YES];
    }
}