it-swarm.com.ru

Удаление пустого места, если заголовок раздела скрыт в UICollectionView

У меня есть два раздела в UICollectionView. Я хочу показать заголовок раздела в UICollectionView только для 1-го раздела. Не в 0-м разделе.

Поэтому я попытался вернуть nil в viewForSupplementaryElementOfKind: метод для section == 0 и возвращает представление для section == 1.

Вылетает и показывает ошибку ниже:

Assertion failure in -[UICollectionView _createPreparedSupplementaryViewForElementOfKind:atIndexPath:withLayoutAttributes:applyAttributes]:

Вот мой код для дополнительного просмотра.

- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
{
    UICollectionReusableView *sectionHeader = nil;
    if (kind == UICollectionElementKindSectionHeader && indexPath.section == 1) {
        sectionHeader = [collectionView dequeueReusableSupplementaryViewOfKind:kind withReuseIdentifier:@"EventSectionHeader" forIndexPath:indexPath];
        sectionHeader.layer.borderWidth = .5f;
        sectionHeader.layer.borderColor = [UIColor colorWithRed:221.0 / 255.0 green:223.0 / 255.0 blue:220.0 / 255.0 alpha:1.0].CGColor;
    }

    return sectionHeader;
}

Я обнаружил, что возвращение nil в методе viewForSupplementaryElementOfKind: приводит к сбою и для других. Другие ответы, предлагающие удалить этот метод. 

Но я хочу показать заголовок раздела только для определенных разделов. Как добиться этого возвращающегося представления только для одного раздела? Благодарю. Любая помощь будет оценена.

Правка:

Как сказал @san, я обновил код, чтобы скрыть заголовок раздела. Оно работает. Он скрывает заголовок. Но я все еще вижу пустое место вместо заголовка раздела. Ожидаемые результаты: не должно быть места для заголовка раздела, если он скрыт.

обновленный код:

- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
{

    UICollectionReusableView *sectionHeader = nil;
    if (kind == UICollectionElementKindSectionHeader) {
        sectionHeader = [collectionView dequeueReusableSupplementaryViewOfKind:kind withReuseIdentifier:@"EventSectionHeader" forIndexPath:indexPath];
        sectionHeader.layer.borderWidth = .5f;
        sectionHeader.layer.borderColor = [UIColor colorWithRed:221.0 / 255.0 green:223.0 / 255.0 blue:220.0 / 255.0 alpha:1.0].CGColor;
        if (indexPath.section == 0) {
            sectionHeader.hidden = YES;

        }else {
            sectionHeader.hidden = NO;
        }
    }

    return sectionHeader;
}

Я даже попытался установить фрейм для sectionHeader, как сказал @san. Но не повезло. тот же результат.

39
Dinesh Raja

Наконец я нашел ответ на свой вопрос. Я что-то пропустил. В любом случае, извините за других пользователей.

Я установил высоту и ширину заголовка внутри метода ниже до сих пор, как сказал @san.

- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath

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

Это действительно хорошо работает для меня:

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section
{
    if (section == 0) {
        return CGSizeZero;
    }else {
        return CGSizeMake(CGRectGetWidth(collectionView.bounds), 135);
    }
}

UPDATE: Так как кто-то задал вопрос о моем умении в комментариях, добавьте Apple Ссылка на документацию для возврата CGSizeZero вышеуказанным способом. 

80
Dinesh Raja

Документация для collectionView:viewForSupplementaryElementOfKind:atIndexPath: гласит:

Этот метод всегда должен возвращать действительный объект просмотра. Если вам не нужен дополнительный вид в конкретном случае, объект макета не должен создавать атрибуты для этого вида. Кроме того, вы можете скрыть представления, установив для скрытого свойства соответствующих атрибутов значение YES или для свойства alpha атрибутов атрибутов значение 0. Чтобы скрыть представления верхнего и нижнего колонтитула в макете потока, вы также можете установить ширину и высоту этих представлений. до 0.

Учитывая, что вы уже пытались установить высоту на ноль и скрыть представление, вы должны создать подкласс UICollectionViewFlowLayout и реализовать layoutAttributesForSupplementaryViewOfKind:atIndexPath:

Проверьте indexPath (как вы уже делаете) и верните nil, если вы не хотите никаких атрибутов макета для этого конкретного дополнительного представления.

- (UICollectionViewLayoutAttributes *)layoutAttributesForSupplementaryViewOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
{
    if([indexPath section] == 0)
    {
         return nil;
    }

    return [super layoutAttributesForSupplementaryViewOfKind:kind atIndexPath:indexPath];
}
23
CaptainRedmuff

Документация ясно говорит - 

Возвращаемое значение

Настроенный дополнительный вид объекта. Вы не должны возвращать ноль из этого метода.

Так что вам нужно следовать -

Этот метод всегда должен возвращать действительный объект просмотра. Если вам не нужен дополнительный вид в конкретном случае, объект макета не должен создавать атрибуты для этого вида. Кроме того, вы можете скрыть представления, установив для скрытого свойства соответствующих атрибутов значение YES или для свойства alpha атрибутов атрибутов значение 0. Чтобы скрыть представления верхнего и нижнего колонтитула в макете потока, вы также можете установить ширину и высоту этих представлений. до 0.

Подходя к вашему коду, ниже у вас должен работать фрагмент кода:

- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
{
    UICollectionReusableView *sectionHeader = nil;
    if (kind == UICollectionElementKindSectionHeader) {
        sectionHeader = [collectionView dequeueReusableSupplementaryViewOfKind:kind withReuseIdentifier:@"EventSectionHeader" forIndexPath:indexPath];

        if(indexPath.section == 1)
          {
             sectionHeader.layer.borderWidth = .5f;
             sectionHeader.layer.borderColor = [UIColor colorWithRed:221.0 / 255.0 green:223.0 / 255.0 blue:220.0 / 255.0 alpha:1.0].CGColor;
          }
        else
        {
          sectionHeader.frame = CGRectZero;
          sectionHeader.hidden = YES;
        }
    }

    return sectionHeader;
}
10
San

В моем случае я дал вставку для разделов, чтобы она давала мне пустое место Так что, если вы реализовали следующий метод, сделайте это следующим образом

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
        if <condition for which you want to hide section>{
            return UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
        }else{
            return UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)
        }
    }
0
Nikunj Acharya