NSIndexPath для текущей позиции таблицы

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

image1

По мере роста разделов и строк моего табличного представления это пригодится пользователям в качестве быстрого инструмента, особенно для небольших устройств. Однако я сталкиваюсь с рассолом, приравнивая точки прокрутки к положению первой ячейки раздела, но я бы предпочел, если возможно, получить позицию заголовков разделов.

Моя цель - обновить segmentControl.selectedSegmentIndex при касании (простая часть), а также при прокрутке (рассол), чтобы это было более плавное взаимодействие с пользовательским интерфейсом.

Я настроил свой selectedSegmentIndex для прокрутки к определенным разделам при нажатии с помощью этих NSIndexPaths с IBAction:

NSIndexPath *aboutIndex = [NSIndexPath indexPathForRow:0 inSection:0];
NSIndexPath *contactIndex = [NSIndexPath indexPathForRow:0 inSection:1];
NSIndexPath *publicationsIndex = [NSIndexPath indexPathForRow:0 inSection:2];
NSIndexPath *settingsIndex = [NSIndexPath indexPathForRow:0 inSection:3];

switch (self.segmentControl.selectedSegmentIndex)
{
    case 0: [self.tableView scrollToRowAtIndexPath:aboutIndex atScrollPosition:UITableViewScrollPositionTop animated:YES];
        break;
    //etc etc
    ...

Используя тот же код, я поместил его в метод scrollViewDidScroll:, как и следовало ожидать, но мне трудно получить конкретный indexPath текущей точки прокрутки tableView. Я сначала попробовал это, а также [self.tableView indexPathsForVisibleRows]:

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

    NSIndexPath *currentIndex = [self.tableView indexPathForRowAtPoint:CGPointMake(0, self.tableView.contentOffset.y)];
    NSLog(@"current is %@", currentIndex);

    //And then changing the selectedSegmentIndex on scroll:

    if ((currentIndex >= aboutIndex) && (currentIndex < contactIndex)) {
        self.segmentControl.selectedSegmentIndex = 0;
    // other else if's
    ...
}

Иногда это работает, когда он хочет в основном, и только при прокрутке вниз я получаю нуль при ручной прокрутке вверх. Поэтому я изменил его на:

if ([currentIndex isEqual:aboutIndex]) {
    self.segmentControl.selectedSegmentIndex = 0;
} else if ([currentIndex isEqual:contactIndex]) {
    self.segmentControl.selectedSegmentIndex = 1;
} else if ([currentIndex isEqual:publicationsIndex]) {
    self.segmentControl.selectedSegmentIndex = 2;
} else if ([currentIndex isEqual:settingsIndex]) {
    self.segmentControl.selectedSegmentIndex = 3;
}

Который работает все время, кроме прокрутки вверх. Почему я получаю нулевую прокрутку вверх?


person soulshined    schedule 13.01.2015    source источник


Ответы (2)


Чтобы ответить на ваш последний вопрос («кто-нибудь знает, как получить происхождение заголовка раздела?»), UITableView есть метод - (CGRect)rectForSection:(NSInteger)section, который возвращает CGRect раздела. См. документацию: https://developer.apple.com/library/ios/documentation/UIKit/Reference/UITableView_Class/index.html

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

В качестве альтернативы вы, вероятно, могли бы также использовать - (CGRect)rectForHeaderInSection:(NSInteger)section, так как верхняя координата должна быть одинаковой на обоих.

И, конечно же, вы можете сравнить его с положением прокрутки, чтобы получить относительное положение на экране этих CGRect.

person jnpdx    schedule 13.01.2015
comment
хм, так надежнее, спасибо, не могу поверить, что я проглядел это. Сделал это тяжелее для себя, чем должно было быть. Однако это вызывает некоторые незначительные сбои в пользовательском интерфейсе, selectedSegmentIndex переходит к постукнутому индексу к предыдущему индексу прокрутки, но я подозреваю, что это не связано. Я подправлю это. спасибо - person soulshined; 13.01.2015
comment
кажется, что это tableView contentOffset.y вызывает несоответствия. учет вставки текста - это самое близкое, что вы можете получить к «абсолютному» происхождению. - person soulshined; 13.01.2015
comment
Прости, что я должен был сделать это с тобой. Мне было тяжело с этим методом, я закончил тем, что создал CGRects для tableView для прокрутки вместо путей индекса, но scrollRectToVisible не создал «отполированный Apple» вид, который вы ожидаете от ОС. Я играл с этим, как вы можете видеть, уже 2 дня, но нашел лучшее решение, которое сработало для моего проекта, а также перекрестные ссылки Rect с позицией currentOffset.y. Спасибо за помощь - person soulshined; 15.01.2015
comment
Хорошо. Я хотел бы указать будущим посетителям, что вопрос был отредактирован с тех пор, как я ответил на него. - person jnpdx; 15.01.2015
comment
Будущие посетители. Я не хотел, чтобы исходный вопрос затерялся во второй части моего вопроса. Его ответ не является неправильным методом. - person soulshined; 15.01.2015

После долгих экспериментов с этим я действительно хотел, чтобы это выглядело полированным и плавным, и я нашел лучшее решение, чем jn_pdx. Хотя его ответ был находчивым и в правильном направлении, я попробовал это таким образом и создал CGRects для разделов, но единственным жизнеспособным способом, который я нашел для прокрутки до - (CGRect)rectForSection:(NSInteger)section, был [self.tableView scrollRectToVisible:animated:] , при этом прямоугольник буквально прокручивается до тех пор, пока он не видимый, поэтому при прокрутке вниз он работает, потому что он переносит верхнюю часть tableView туда, где он виден, что в данном случае оказывается верхней частью экрана, но при прокрутке вверх он прокручивает прямоугольник, пока он не станет видимым, который заканчивается внизу экрана (нежелательный эффект), потому что это первая точка, в которой он становится видимым. Поэтому вместо этого я решил сохранить методы и ссылки NSIndexPath. Я достиг этого, реализовав следующее

Для нажатия на segmentedControl:

- (IBAction)segmentIndexChanged:(id)sender {

//Created the NSIndexPaths for all the sections 1st cells
NSIndexPath *aboutIndex = [NSIndexPath indexPathForRow:0 inSection:0];
NSIndexPath *contactIndex = [NSIndexPath indexPathForRow:0 inSection:1];
NSIndexPath *publicationsIndex = [NSIndexPath indexPathForRow:0 inSection:2];
NSIndexPath *settingsIndex = [NSIndexPath indexPathForRow:0 inSection:3];

    //Scroll to the top most part of the cell
    switch (self.segmentControl.selectedSegmentIndex)
    {
    case 0:
        [self.tableView scrollToRowAtIndexPath:aboutIndex atScrollPosition:UITableViewScrollPositionTop animated:YES];
        break;
    case 1:
        [self.tableView scrollToRowAtIndexPath:contactIndex atScrollPosition:UITableViewScrollPositionTop animated:YES];
        break;
    case 2:
        [self.tableView scrollToRowAtIndexPath:publicationsIndex atScrollPosition:UITableViewScrollPositionTop animated:YES];
        break;
    case 3:
        [self.tableView scrollToRowAtIndexPath:settingsIndex atScrollPosition:UITableViewScrollPositionTop animated:YES];
        break;
    default:
        break; 
    } 
}

Затем, когда UITableView прокручивается вручную, я обновляю selectedSegmentIndex путем прямой корреляции с NSIndexPath, к которому он прокручивается при нажатии.

Для прокрутки UITableView:

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

//Created a rect correlating to the tapped Index Paths
CGRect aboutRect = [self.tableView rectForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];
CGRect contactRect = [self.tableView rectForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:1]];
CGRect publicationsRect = [self.tableView rectForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:2]];
CGRect settingsRect = [self.tableView rectForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:3]];
//Get the current table view contentOffset point in CGRect form instead of CGFloat
CGRect scrollY = CGRectMake(0, self.tableView.contentOffset.y, self.tableView.bounds.size.width, self.tableView.bounds.size.height);
// NSLog current y point
NSLog(@"scrollY %@", NSStringFromCGRect(scrollY));

//Catch the intersecting points with CGRectContainsRect not CGRectEqualToRect
    if (CGRectContainsRect(scrollY, aboutRect)) {
        self.segmentControl.selectedSegmentIndex = 0;
    } else if (CGRectContainsRect(scrollY, contactRect)) {
        self.segmentControl.selectedSegmentIndex = 1;
    } else if (CGRectContainsRect(scrollY, publicationsRect)) {
        self.segmentControl.selectedSegmentIndex = 2;
    } else if (CGRectContainsRect(scrollY, settingsRect)) {
        self.segmentControl.selectedSegmentIndex = 3;
    }
}

И работает безотказно и стабильно

person soulshined    schedule 15.01.2015