4

У меня есть текстовое поле внутри UICollectionViewCell, которое может получать статус первого ответчика. Ячейка в настоящее время не отображается на экране, и я хочу прокрутить до ячейки, исходя из нажатия кнопки с UISegmentedControl. Для этого контроля есть два сегмента ... и удар во второй сегмент должен прокручиваться до первой ячейки во 2-й секции UICollectionView. После этого ячейка должна выбираться программно, а затем текстовое поле внутри этой ячейки должно получить статус первого ответчика и вызвать клавиатуру.UICollectionView: активирование, прокрутка и назначение первого ответчика удаленной ячейке

Что происходит сейчас (в моем методе действий от изменения значения из сегментированного управления) является то, что вызов -[UICollectionView selectItemAtIndexPath:animated:scrollPosition:] не прокрутка к нему на всех (и я использую UICollectionViewScrollPositionTop, может также быть «…None»). Если я распечатаю список вручную, ячейка действительно выбрана (в этом состоянии будет более темный цвет фона), но текстовое поле, конечно, не имеет первого статуса ответчика.

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

- (void)directionSegmentedControlChanged:(UISegmentedControl *)sender { 
    NSIndexPath *path = [NSIndexPath indexPathForItem:0 inSection:sender.selectedSegmentIndex]; 
    UICollectionViewLayoutAttributes *attributes = [self.collectionView layoutAttributesForItemAtIndexPath:path]; 
    [self.collectionView setContentOffset:attributes.frame.origin animated:YES]; 
    [self.collectionView selectItemAtIndexPath:path animated:NO scrollPosition:UICollectionViewScrollPositionNone]; 
    [self.collectionView.delegate collectionView:self.collectionView didSelectItemAtIndexPath:path]; 
} 

- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath { 
    BDKCollectionViewCell *cell = (BDKCollectionViewCell *)[collectionView cellForItemAtIndexPath:indexPath]; 
    [cell.textField becomeFirstResponder]; 
} 

Проблема здесь состоит в том, что клетка, как это видно в -[collectionView:didSelectItemAtIndexPath:] равна нулю, потому что это не в видимом множестве ячеек представления коллекции, когда метод увольняют.

Каков наилучший способ решить эту проблему? Я попытался подбросить свой код прокрутки внутри блока [UIView animateWithDuration:animations:completion:] и назначил первого ответчика после его завершения, но вручную анимируя представление коллекции таким образом, пренебрегает загрузкой любой из ячеек, которые должны прокручиваться мимо. Есть идеи?


Update: большое спасибо @Esker, который предложил мне просто выполнить «фокус выбора» действие после задержки с использованием Grand Central Dispatch. Мое решение оказалось таким.

- (void)directionSegmentedControlChanged:(UISegmentedControl *)sender { 
    NSIndexPath *path = [NSIndexPath indexPathForItem:0 inSection:sender.selectedSegmentIndex]; 

    UICollectionViewLayoutAttributes *attributes = [self.collectionView layoutAttributesForItemAtIndexPath:path]; 
    [self.collectionView setContentOffset:attributes.frame.origin animated:YES]; 

    dispatch_time_t startAfter = dispatch_time(DISPATCH_TIME_NOW, 0.28 * NSEC_PER_SEC); 
    dispatch_after(startAfter, dispatch_get_main_queue(), ^{ 
     [self.collectionView selectItemAtIndexPath:path animated:NO scrollPosition:UICollectionViewScrollPositionNone]; 
     [self collectionView:self.collectionView didSelectItemAtIndexPath:path]; 
    }); 
} 
+0

Работает как очарование! Благодаря! –

ответ

1

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

  1. Если желаемое поле ячейки/текста в настоящее время видно, немедленно отправьте его becomeFirstResponder и прокрутите к ячейке, если хотите.
  2. В противном случае, установите свойство в вашем контроллере представления или подобный класс, который указывает, что текстовое поле, потребности сосредоточиться, и которые нужно сосредоточиться
  3. Сообщить вид вид таблицы/сбора для перемещения по заданной траектории индекса
  4. В collectionView:cellForItemAtIndexPath: вы можете попробовать проверить это свойство, чтобы увидеть, нужно ли получать текстовое поле в заданном indexPath, и если да, отправьте его becomeFirstResponder, но я обнаружил, что это не сработает, если ячейка прокручивается в представлении, предположительно, потому что на данный момент, когда вы настраиваете новую ячейку, она еще не находится в иерархии представлений.Поэтому я добавил чек, если becomeFirstResponder возвращает NO в этот момент, я пытаюсь снова после задержки:
dispatch_after(someDelay, dispatch_get_main_queue(), ^(void){ 
    [self getFocus:textField]; 
}); 

Метод getFocus оба отправить becomeFirstResponder в текстовое поле и ясно, что имущество, Дорожки текстовое поле нуждается в фокусе.

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

+0

Спасибо, что нашли время ответить! Ваш фрагмент кода помог - поскольку мой последний способ выполнял 'performSelector: afterDelay:', и, поскольку я нахожусь в крайнем случае, ваш блок намного чище. Вы получаете бонус ответа, и я отредактирую свой вопрос с моим решением. –

+0

Отлично, рад, что сработал. Я чувствую, что должно быть более элегантное решение, но я еще не придумал его. –

+0

Согласен ... Я размышлял над подачей отчета об ошибке с Apple. Это поможет мне сформулировать правильное ... эм, предложение. –