scrollViewWillEndDragging:withVelocity:targetContentOffset: не работает на краях UISCrollView

Я пытаюсь реализовать пользовательскую панель вкладок, которая прокручивается и имеет подкачку на каждом элементе панели вкладок. Для этого я использую делегат scrollViewWillEndDragging:withVelocity: targetContentOffset: который отлично работает с одной проблемой.

как работает моя подкачка, если contentOffset находится рядом с правильным элементом, он targetContentOffset изменяется на смещение этого элемента. То же самое с левой стороной.

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

Я проверил с отладчиком и targetContentOffset - >x действительно 0 (в первом случае - слева от самого левого элемента). Так что проблема не в UIScrollView прокрутки есть. Я заблудился.

вот мой реализованный делегат:

- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView
                 withVelocity:(CGPoint)velocity
          targetContentOffset:(inout CGPoint *)targetContentOffset{
     NSInteger index = lrintf(targetContentOffset->x/self.tabWidth);
     targetContentOffset->x = index * self.tabWidth;
}

здесь диаграмма, объясняющая, что я хочу сделать.

|-------|-------|-------|-------|-------|-------|-------|
|       |       |       |       |       |       |       |
|       |       |       |       |       |       |       |
|_______|_______|_______|_______|_______|_______|_______|

        |_______________________________________|
         where it is and i scroll it to the left

   <----|

   |_______________________________________|
              where it would stop

|_______________________________________|
        where i want it to stop

5 ответов


кажется, это известная проблема. После некоторых исследований и разговоров с другими людьми было высказано предположение, что это может быть ошибка, которая оказалась правильной. Я сообщил об этом Apple, и он был отмечен как дубликат, но все еще открыт. Просто отвечаю за тех из вас, у кого та же проблема. Я обходил его, как предлагает Big Papoo, используя смещение, близкое к тому, что я хочу (кажется, 0.1). То же самое с правым концом.


проблема исправлена на iOS 6.0.

теперь он работает так, как должен.


Я попытался установить окончательное смещение на что-то немного от нуля или размер содержимого, как предложил Big Papoo, но заметил, что это удаляет отскок от прокрутки. Мое решение состояло в том, чтобы проверить исходный targetContentOffset, чтобы увидеть, равен ли он нулю или contentSize и оставить его, если это:

- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset {

    float expectedOffset = targetContentOffset->x;
    if (expectedOffset == 0 || expectedOffset == scrollView.contentSize.width) return; // Scroll view will bounce so leave the targetContentOffset.

    float targetOffset = [self roundedOffset:expectedOffset]; // Round your offset.

    // Adjust the offset to make sure it works.
    if (targetOffset == 0) targetOffset = 1;
    else if (targetOffset == SCROLLVIEW_WIDTH) targetOffset = SCROLLVIEW_WIDTH - 1;

    targetContentOffset->x = targetOffset;
}

вы можете, конечно, затем использовать scrollViewDidEndDecelerating: чтобы переместить scrollview на 1 точку.


Я нашел 2 недокументированных поведения, которые вы можете исследовать : - Установка нуля, поскольку окончательное смещение не работает, я предлагаю поставить 1 или что-нибудь больше нуля (0,5 может работать, не тестируется) - Вам лучше проверить знак скорости и вычислить окончательное смещение, чтобы быть на левой или правой стороне текущей точки, где пользователь удалил палец. Не пытайтесь сделать прокрутку назад с другой стороны.


Если вы используете горизонтальное табличное представление, то внутри scrollViewWillEndDragging:withVelocity:targetContentOffset: function вы можете вызвать:

[self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:<index> inSection:<section>] atScrollPosition:UITableViewScrollPositionTop animated:YES];

Я обнаружил, что это работает намного лучше, чем пытаться манипулировать targetContentOffset->y в горизонтальном табличном представлении.