how to move one direction in UIScrollView when scr

2019-07-06 14:44发布

问题:

I'm new in objective-c. I create UIScrollView object and add in my view with this code:

height = self.view.frame.size.height;
width = self.view.frame.size.width;

scrollbar = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, width, height)];
scrollbar.delegate = self;
scrollbar.backgroundColor = [UIColor whiteColor];
scrollbar.maximumZoomScale = 1.0;
scrollbar.minimumZoomScale = 1.0;
scrollbar.clipsToBounds = YES;
scrollbar.showsHorizontalScrollIndicator = YES;
scrollbar.pagingEnabled = YES;
[scrollbar setContentSize:CGSizeMake(width*4, height*4)];
[self.view addSubview:scrollbar];

for (int i = 1; i <= 4; i++) {
    first = [[FirstViewController alloc]initWithNibName:@"FirstViewController" bundle:nil];
    first.view.frame = CGRectMake((i-1)*width, 0, width, height*4);
    [scrollbar addSubview:first.view];

    switch (i) {
          ase 1:
              first.view.backgroundColor = [UIColor blueColor];
              break;
          case 2:
              first.view.backgroundColor = [UIColor redColor];
              break;
          case 3:
              first.view.backgroundColor = [UIColor greenColor];
              break;
          case 4:
              first.view.backgroundColor = [UIColor grayColor];
              break;
          default:
              break;
        }
    }

in my code I add 4 view in my ScrollView with different color now I want when scrolling on my ScrollView detect dx & dy (dx: driving distance on Axis.x & dy:driving distance on Axis.y) and check these two variable and when :

Notic: I want when any one touch on ScrollView and moving touch on Axis (x or y) or touch on Both Axis (x and y) check this :

if (dx > dy) disable horizontal scroll and moving in vertical side!!! else moving in horizontal side and disable vertical scroll!!!

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {

    CGRect visibleRect = CGRectMake(scrollView.contentOffset.x, scrollView.contentOffset.y, scrollView.contentOffset.x + scrollView.bounds.size.width, scrollView.contentOffset.y + scrollView.bounds.size.height);

    NSLog(@"%f,%f",visibleRect.origin.x,visibleRect.origin.y);

    /*NSLog(@"x : %f",scrollView.contentOffset.x);
    NSLog(@"y : %f",scrollView.contentOffset.y);*/
    if (fabsf(scrollView.contentOffset.x) > fabsf(scrollView.contentOffset.y)) {
        NSLog(@"Vertical Side");
    }
    else {
        NSLog(@"Horizontal Side");
    }
}

please guide me guys. I can't disable one side and move another side!!! thanks

回答1:

You can achieve the result you want adding some code to your delegate. This is my ViewController.m file. -viewDidLoad, #import statements and the other methods are omitted.

@interface ViewController () {
    CGPoint initialOffset;
    NSInteger direction; // 0 undefined, 1 horizontal, 2 vertical
}
@end

@implementation ViewController

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    // retrieve current offset
    CGPoint currentOffset = scrollView.contentOffset;

    // do we know which is the predominant direction?
    if (direction == 0) {

        // no.

        CGFloat dx = currentOffset.x - initialOffset.x;
        CGFloat dy = currentOffset.y - initialOffset.y;

        // we need to decide in which direction we are moving

        if (fabs(dx) >= fabs(dy)) {
            direction = 1; // horizontal
        } else if (fabs(dy) > fabs(dx)) {
            direction = 2;
        }

    }

    // ok now we have the direction. update the offset if necessary
    if (direction == 1 && currentOffset.y != initialOffset.y) {

        // remove y offset
        currentOffset.y  = initialOffset.y;
        // update
        [scrollView setContentOffset:currentOffset];

    } else if (direction == 2 && currentOffset.x != initialOffset.x) {

        currentOffset.x = initialOffset.x;
        [scrollView setContentOffset:currentOffset];

    }
}

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
    // store the current offset
    initialOffset = scrollView.contentOffset;

    // reset flag
    direction = 0; // AKA undefined
}

@end

When you start dragging, the delegate will reset the flag direction to "unknown" state, and store the current content offset. After every dragging move, your -scrollViewDidScroll: will be called. There, you decide which is the predominant direction (if this hasn't been done yet) and correct the current scrolling offset accordingly, by removing the x (or y) offset.

I tested this with the same settings you provided, only I used a UIImageView inside UIScrollView and I set up everything via InterfaceBuilder, but it should work fine. Theoretically, with this method you could replace directionLock, but remember that -scrollViewDidScroll is called many times during an action, and every time it rewrites the content offset (if the scrolling is happening in both directions). So if you leave directionLock enabled, you save many of the calls to setContentOffset: that the delegate performs.



回答2:

If i understood you right, you want to disable scrolling in the direction that has been dragged less by the user. If so, UIScrollView already offers an option to do so:

scrollView.directionalLockEnabled = YES;

When this option is set to true UIScrollView will handle the correct direction lock by itself.

For more information look at the documentation: link