как переместить одно направление в UIScrollView при прокрутке

#ios #objective-c #uiscrollview

#iOS #objective-c #uiscrollview

Вопрос:

Я новичок в objective-c. Я создаю UIScrollView объект и добавляю в свой вид с помощью этого кода:

 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;
        }
    }
  

в моем коде я добавляю 4 вида в моем ScrollView с другим цветом, теперь я хочу, чтобы при прокрутке в моем ScrollView определялись dx и dy (dx: расстояние движения по оси.x и dy: расстояние движения по оси.y) и проверял эти две переменные, и когда :

Примечание: я хочу, чтобы при любом касании ScrollView и перемещении касаний по оси (x или y) или касаний по обеим осям (x и y) проверялось это :

если (dx > dy) отключить горизонтальную прокрутку и перемещение в вертикальную сторону!!! иначе перемещение в горизонтальную сторону и отключение вертикальной прокрутки!!!

 - (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");
    }
}
  

пожалуйста, подскажите мне, ребята. Я не могу отключить одну сторону и переместить другую сторону!!! Спасибо

Ответ №1:

Если я правильно вас понял, вы хотите отключить прокрутку в направлении, которое меньше перетаскивалось пользователем. Если это так, UIScrollView уже предлагает такую возможность:

 scrollView.directionalLockEnabled = YES;
  

Когда для этого параметра установлено значение true, UIScrollView сам обработает правильную блокировку направления.

Для получения дополнительной информации ознакомьтесь с документацией: ссылка

Комментарии:

1. мой друг, ты прав, но при двойном перетаскивании по обеим осям (x amp; y) прокрутка работает, а я этого не хочу.

Ответ №2:

Вы можете достичь желаемого результата, добавив некоторый код в свой делегат. Это мой ViewController.m файл. -viewDidLoad , #import инструкции и другие методы опущены.

 @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 amp;amp; currentOffset.y != initialOffset.y) {

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

    } else if (direction == 2 amp;amp; 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
  

Когда вы начнете перетаскивание, делегат сбросит флаг direction в состояние «неизвестно» и сохранит текущее смещение содержимого. После каждого перемещения будет вызываться ваш -scrollViewDidScroll: . Там вы решаете, какое направление является преобладающим (если это еще не было сделано), и соответствующим образом корректируете текущее смещение прокрутки, удаляя смещение x (или y).

Я протестировал это с теми же настройками, которые вы предоставили, только я использовал UIImageView inside UIScrollView и настроил все через InterfaceBuilder, но это должно работать нормально. Теоретически, с помощью этого метода вы могли бы заменить directionLock , но помните, что -scrollViewDidScroll этот метод вызывается много раз во время действия, и каждый раз он перезаписывает смещение содержимого (если прокрутка происходит в обоих направлениях). Таким образом, если вы оставите directionLock включенным, вы сохраните многие вызовы, setContentOffset: которые выполняет делегат.