Заголовок раздела UITableView и нижний колонтитул раздела не обновляются (проблема перерисовки) - PullRequest
2 голосов
/ 26 апреля 2010

ОБНОВЛЕНИЕ 4.0

Похоже, что iOS 4.0 здесь что-то изменила. Тот же код, создающий неправильные фоны для заголовка раздела в описанном сценарии, работает с 4.0 согласно моей первой быстрой проверке!

Оригинал

У меня есть сгруппированный стиль UITableView с пользовательским заголовком и представлением нижнего колонтитула. В нижний колонтитул я положил UILabel и UIButton.

Нажатие на кнопку скрывает или показывает некоторые строки, обновляет UILabel в представлении нижнего колонтитула и, наконец, изменяет размер представления нижнего колонтитула.

В основном все работает нормально. НО текстовая метка не обновляется на экране. Он обновляется в текстовом свойстве UILabel, но только если я прокручиваю нижний колонтитул раздела из видимой области и прокручиваю его назад, он обновляется. Так что это типичная проблема перерисовки здесь UITableView.

Я пробовал каждый метод для принудительного обновления, как needsLayout и т. Д. Ничего не помогало.

Я видел несколько связанных вопросов, но с другим поведением и без решения. Любая помощь / идеи?

Спасибо, Герд

UPDATE:

У меня проблемы с нижним колонтитулом, так что вот мой viewForFooterInSection.

В основном я хочу свернуть / развернуть раздел, но не полностью (это было легко), а только пустую ячейку (ItemSize empty). FooterView имеет большой размер, если он свернут, и будет уменьшаться при расширении. Кроме того, текст метки изменится.

- (UIView *)tableView: (UITableView *)tableView viewForFooterInSection: (NSInteger)section{
NSLog(@"viewForFooterInSection section:%i", section);

UIButton *myView;
UILabel *label;

if ([[[self.sectionStatus objectAtIndex:section] valueForKey:@"collapseStatus"] isEqual:@"collapse"]){ 
    myView = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 320, 52)];
    [myView setBackgroundImage:[UIImage imageNamed:@"ItemViewFooter.png"] forState:UIControlStateNormal];
    label = [[UILabel alloc] initWithFrame:CGRectMake(20, 32, 300, 20)];
    label.text = NSLocalizedString(@"list_expand",@"");
} else { //is expanded
    myView = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 320, 21)];
    [myView setBackgroundImage:[UIImage imageNamed:@"ListCollapseExpand.png"] forState:UIControlStateNormal];
    label = [[UILabel alloc] initWithFrame:CGRectMake(20, 1, 300, 20)];
    label.text = NSLocalizedString(@"list_collapse",@"");
}

myView.tag=section;
[myView addTarget:self action:@selector(collapseExpandAction:) forControlEvents:UIControlEventTouchUpInside];
myView.backgroundColor = [UIColor clearColor];
myView.adjustsImageWhenHighlighted = NO;
myView.showsTouchWhenHighlighted = YES;

label.textColor = FONTCOLOR;
label.font = [UIFont systemFontOfSize:14];
label.numberOfLines = 1;
label.textAlignment = UITextAlignmentCenter;
label.backgroundColor = [UIColor clearColor];
[myView addSubview:label];
return myView;

};

В методе действия кнопки я сохраняю статус свертывания / развертывания раздела и количество отображаемых строк. Чем я удаляю или вставляю строки. (Это должно быть с помощью вставки / удаления, потому что мне нужна анимация).

- (void) collapseExpandSection: (NSInteger) section{
NSMutableArray *paths = [NSMutableArray arrayWithCapacity:10];
NSInteger row;
NSInteger numberOfDisplayedItems=[[[self.sectionStatus objectAtIndex:section] valueForKey:@"numberOfDisplayedRows"] intValue];
id <NSFetchedResultsSectionInfo> sectionInfo = [[fetchedResultsController sections] objectAtIndex:section];
NSInteger numberOfAllItems=[sectionInfo numberOfObjects];
Item *tmpItem=nil;
NSSet *itemsWithSizes=nil;

//filter not used cells
for ( row = 0; row < numberOfAllItems; row++ ) {
    tmpItem=[fetchedResultsController objectAtIndexPath:[NSIndexPath indexPathForRow:row inSection:section]];
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"itemSize != nil"];
    NSSet *itemsWithSizes = [tmpItem.itemSizes filteredSetUsingPredicate:predicate];
    if ([itemsWithSizes count]==0){ 
        [paths addObject:[NSIndexPath indexPathForRow:row inSection:section]]; //all unused cells
    };
}

if (numberOfDisplayedItems == numberOfAllItems){ //currently all shown => Collapse
    [self.tableView beginUpdates];
    [[self.sectionStatus objectAtIndex:section] setValue:[NSNumber numberWithInt:(numberOfDisplayedItems-[paths count])] forKey:@"numberOfDisplayedRows"];
    [[self.sectionStatus objectAtIndex:section] setValue:@"collapse" forKey:@"collapseStatus"];
    [self.tableView deleteRowsAtIndexPaths:paths withRowAnimation:UITableViewRowAnimationFade];
    [self.tableView endUpdates];
} else { //Not all shown so expand with the unused cells
    [[self.sectionStatus objectAtIndex:section] setValue:[NSNumber numberWithInt:(numberOfDisplayedItems+[paths count])] forKey:@"numberOfDisplayedRows"];
    [[self.sectionStatus objectAtIndex:section] setValue:@"expand" forKey:@"collapseStatus"];
    [self.tableView beginUpdates];
    [self.tableView insertRowsAtIndexPaths:paths withRowAnimation:UITableViewRowAnimationFade];
    [self.tableView endUpdates];
}
return;
* +1034 *};

В общем, все это работает нормально. После того, как блоки начинаются / заканчиваются, для каждого раздела вызывается viewForFooter, и текст метки в свойстве устанавливается правильно. Однако дисплей не обновляется правильно. Как только возобновится повторное отображение (прокрутка с прокруткой), дисплей будет в порядке.

Ответы [ 3 ]

4 голосов
/ 26 апреля 2010

Там 2 проблемы.
Первая проблема заключается в том, что нижний колонтитул раздела не обновляется. Попробуйте позвонить [tableView reloadData] или [tableView reloadSections:sections withRowAnimation:UITableViewRowAnimationFade] после обновления (возможно, с dalay).
Вторая проблема - утечки памяти в myView и label. Кроме того, почему вы используете метку, когда вы можете использовать внутреннюю метку кнопки? Постскриптум Не выделяйте UIButton объект напрямую, потому что он фабричный. Позвоните [UIButton buttonWithType:UIButtonTypeCustom] вместо.

Upd: Другим способом обновления является непосредственное обновление нижнего колонтитула путем доступа к представлениям нижнего колонтитула.

- (void) collapseExpandSection: (NSInteger) section{

Убедитесь, что этот раздел действительно является вашей кнопкой

 - (void) collapseExpandSection: (UIButton*) sender{
// Do update of sender here
// Do other stuff
}

Также вы можете попробовать следующий трюк: создать объект UIView в делегате, добавить свою кнопку и метку на нем и вернуть вместо самого просмотра.

3 голосов
/ 27 октября 2011

Моя проблема заключалась в том, что я расширял заголовок раздела, чтобы отобразить панель поиска, но он не перерисовывал представление, пока я не прокрутил UITableView.

У меня был свой собственный класс SectionHeader, который разделял UIView и управлял поиском.

После моей анимации я просто использовал это для принудительного обновления. Это не красиво, но работает.

CGPoint point = CGPointMake(((UIScrollView *)self.superview).contentOffset.x,
                            ((UIScrollView *)self.superview).contentOffset.y+1);
[((UIScrollView *)self.superview) setContentOffset:point animated:NO];

point = CGPointMake(((UIScrollView *)self.superview).contentOffset.x, 
                    ((UIScrollView *)self.superview).contentOffset.y-1);
[((UIScrollView *)self.superview) setContentOffset:point animated:NO];

В основном заставьте UITableView прокрутить вниз на 1 пиксель и вверх на 1 пиксель.

0 голосов
/ 04 апреля 2016

У меня была такая же проблема, когда я хотел обновить заголовок раздела после вставки новой строки. Я обнаружил, что вызов метода tableView reloadSections() с настройкой анимации .None после вызова метода insertRows сработал для меня (оба вызова в одном и том же блоке обновления tableView). Я получил нужную анимацию вставки, а также был обновлен заголовок раздела.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...