UIScrollView: листание по горизонтали, прокрутка по вертикали? - PullRequest
81 голосов
/ 08 апреля 2009

Как я могу заставить UIScrollView, при котором подкачка и прокрутка включены, двигаться только вертикально или горизонтально в данный момент?

Насколько я понимаю, свойство directionalLockEnabled должно достигать этого, но при диагональном перелистывании вид по-прежнему вызывает прокрутку по диагонали вместо ограничения движения одной осью.

Редактировать: чтобы быть более понятным, я бы хотел, чтобы пользователь мог прокручивать по горизонтали ИЛИ по вертикали, но не одновременно одновременно.

Ответы [ 19 ]

2 голосов
/ 15 июля 2015

Это улучшенное решение icompot, которое было для меня довольно нестабильным. Этот работает отлично, и его легко реализовать:

- (void) scrollViewWillBeginDragging: (UIScrollView *) scrollView
{
    self.oldContentOffset = scrollView.contentOffset;
}

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

    float XOffset = fabsf(self.oldContentOffset.x - scrollView.contentOffset.x );
    float YOffset = fabsf(self.oldContentOffset.y - scrollView.contentOffset.y );

        if (scrollView.contentOffset.x != self.oldContentOffset.x && (XOffset >= YOffset) )
        {

            scrollView.pagingEnabled = YES;
            scrollView.contentOffset = CGPointMake(scrollView.contentOffset.x,
                                                   self.oldContentOffset.y);

        }
        else
        {
            scrollView.pagingEnabled = NO;
               scrollView.contentOffset = CGPointMake( self.oldContentOffset.x,
                                                   scrollView.contentOffset.y);
        }

}


- (void) scrollViewDidEndDecelerating: (UIScrollView *) scrollView
{
    self.oldContentOffset = scrollView.contentOffset;
}
2 голосов
/ 21 октября 2015

Для дальнейшего использования я опирался на ответ Андрея Танасова и нашел следующее решение, которое отлично работает.

Сначала определите переменную для хранения contentOffset и установите для нее координаты 0,0

var positionScroll = CGPointMake(0, 0)

Теперь добавьте следующее в делегат scrollView:

override func scrollViewWillBeginDragging(scrollView: UIScrollView) {
    // Note that we are getting a reference to self.scrollView and not the scrollView referenced passed by the method
    // For some reason, not doing this fails to get the logic to work
    self.positionScroll = (self.scrollView?.contentOffset)!
}

override func scrollViewDidScroll(scrollView: UIScrollView) {

    // Check that contentOffset is not nil
    // We do this because the scrollViewDidScroll method is called on viewDidLoad
    if self.scrollView?.contentOffset != nil {

        // The user wants to scroll on the X axis
        if self.scrollView?.contentOffset.x > self.positionScroll.x || self.scrollView?.contentOffset.x < self.positionScroll.x {

            // Reset the Y position of the scrollView to what it was BEFORE scrolling started
            self.scrollView?.contentOffset = CGPointMake((self.scrollView?.contentOffset.x)!, self.positionScroll.y);
            self.scrollView?.pagingEnabled = true
        }

        // The user wants to scroll on the Y axis
        else {
            // Reset the X position of the scrollView to what it was BEFORE scrolling started
            self.scrollView?.contentOffset = CGPointMake(self.positionScroll.x, (self.scrollView?.contentOffset.y)!);
            self.collectionView?.pagingEnabled = false
        }

    }

}

Надеюсь, это поможет.

1 голос
/ 10 июля 2012

Если у вас большой вид прокрутки ... и вы хотите ограничить диагональную прокрутку http://chandanshetty01.blogspot.in/2012/07/restricting-diagonal-scrolling-in.html

1 голос
/ 08 апреля 2009

Из документов:

"значением по умолчанию является НЕТ, что означает, что прокрутка разрешена как в горизонтальном, так и в вертикальном направлении. Если значение равно ДА, и пользователь начинает перетаскивать в одном общем направлении (по горизонтали или вертикали), представление прокрутки отключает прокрутку другое направление. "

Я думаю, что важной частью является "если ... пользователь начинает перетаскивание в одном общем направлении". Так что, если они начнут тянуть по диагонали, это не сработает. Не то, чтобы эти документы всегда были надежными, когда дело доходит до интерпретации, - но это, кажется, соответствует тому, что вы видите.

Это на самом деле кажется разумным. Я должен спросить - почему вы хотите ограничить только горизонтальной или только вертикальной в любое время? Может быть, UIScrollView не инструмент для вас?

1 голос
/ 09 октября 2009

Необходимо сбросить _isHorizontalScroll на NO в touchesEnded и touchesCancelled.

1 голос
/ 17 августа 2010

Мой вид состоит из 10 горизонтальных видов, и некоторые из этих видов состоят из нескольких вертикальных видов, так что вы получите что-то вроде этого:


1.0   2.0   3.1    4.1
      2.1   3.1
      2.2
      2.3

С включенной подкачкой по горизонтальной и вертикальной оси

Представление также имеет следующие атрибуты:

[self setDelaysContentTouches:NO];
[self setMultipleTouchEnabled:NO];
[self setDirectionalLockEnabled:YES];

Теперь, чтобы предотвратить прокрутку по диагонали, сделайте следующее:

-(void)scrollViewDidScroll:(UIScrollView *)scrollView {
    int pageWidth = 768;
    int pageHeight = 1024;
    int subPage =round(self.contentOffset.y / pageHeight);
    if ((int)self.contentOffset.x % pageWidth != 0 && (int)self.contentOffset.y % pageHeight != 0) {
        [self setContentOffset:CGPointMake(self.contentOffset.x, subPage * pageHeight];
    } 
}

Работает для меня как шарм!

0 голосов
/ 09 июня 2009

Если вы не пытались сделать это в бета-версии 3.0, я рекомендую вам попробовать. В настоящее время я использую ряд табличных представлений в представлении прокрутки, и это работает так, как ожидалось. (Ну, в любом случае, прокрутка работает. Нашел этот вопрос, когда искал решение совершенно другой проблемы ...)

0 голосов
/ 08 апреля 2009

Если вы используете конструктор интерфейса для разработки интерфейса - это можно сделать довольно легко.

В конструкторе интерфейса просто щелкните UIScrollView и выберите параметр (в инспекторе), который ограничивает его прокруткой только одним способом.

0 голосов
/ 28 июня 2015

Для тех, кто ищет в Swift второе решение @AndreyTarantsov, оно выглядит следующим образом:

    var positionScroll:CGFloat = 0

    func scrollViewWillBeginDragging(scrollView: UIScrollView) {
        positionScroll = self.theScroll.contentOffset.x
    }

    func scrollViewDidScroll(scrollView: UIScrollView) {
        if self.theScroll.contentOffset.x > self.positionScroll || self.theScroll.contentOffset.x < self.positionScroll{
             self.theScroll.pagingEnabled = true
        }else{
            self.theScroll.pagingEnabled = false
        }
    }

что мы делаем здесь, это сохраняем текущую позицию непосредственно перед перетаскиванием scrollview и затем проверяем, увеличился или уменьшился x по сравнению с текущей позицией x. Если да, то установите для pagingEnabled значение true, если нет (y увеличилось / уменьшилось), а для pagingEnabled установлено значение false

Надеюсь, что это будет полезно новичкам!

...