Ячейка отображается над заголовком раздела
У меня есть UITableView
с пользовательскими ячейками и настраиваемыми заголовками. Когда я перемещаю одну ячейку при редактировании, она появляется в виде заголовка.
Как сохранить заголовок в верхней части всех ячеек?
В приложении используется раскадровка, в случае, если это имеет значение.
Вот как это выглядит? https://www.dropbox.com/s/wg8oiar0d9oytux/iOS%20SimulatorScreenSnapz003.mov
Это мой код:
[...]
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"ListCell";
ListCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
int handleSection = [self sectionToHandle:indexPath.section];
switch (handleSection)
{
case PrivateLists:
{
if (tableView.isEditing && (indexPath.row == self.privateLists.count))
{
cell.textField.text = NSLocalizedString(@"Lägg till ny lista", nil);
cell.textField.enabled = NO;
cell.textField.userInteractionEnabled = NO;
cell.accessoryType = UITableViewCellAccessoryNone;
cell.editingAccessoryView.hidden = YES;
}
else
{
List *list = [self.privateLists objectAtIndex:indexPath.row];
cell.textField.text = list.name;
cell.textField.enabled = YES;
cell.textField.userInteractionEnabled =YES;
cell.backgroundColor = [UIColor clearColor];
cell.onTextEntered = ^(NSString* enteredString){
list.name = enteredString;
UpdateListService *service = [[UpdateListService alloc]initServiceWithList:list];
[service updatelistOnCompletion:
^(BOOL success){
DLog(@"Updated list");
NSIndexPath *newPath = [NSIndexPath indexPathForRow:0 inSection:indexPath.section];
[self.tableView moveRowAtIndexPath:indexPath toIndexPath:newPath];
[self moveListToTop:list.ListId newIndexPath:newPath];
justMovedWithoutSectionUpdate = YES;
}
onError:
^(NSError *error){
[[ActivityIndicator sharedInstance] hide];
[[ErrorHandler sharedInstance]handleError:error fromSender:self];
}];
};
}
}
break;
default:
return 0;
break;
}
return cell;
}
-(UIView *)tableView:(UITableView *)aTableView viewForHeaderInSection:(NSInteger)section
{
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 22)];
UILabel *textLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 0, 300, 21)];
[textLabel setFont:[[AXThemeManager sharedTheme]headerFontWithSize:15.0]];
[textLabel setTextColor:[[AXThemeManager sharedTheme]highlightColor]];
[textLabel setText:@"SECTION TITLE"];
[textLabel setBackgroundColor:[UIColor clearColor]];
UIImageView *backgroundView = [[UIImageView alloc]initWithImage:[AXThemeManager sharedTheme].tableviewSectionHeaderBackgroundImage];
[backgroundView setFrame:view.frame];
[view addSubview:backgroundView];
[view sendSubviewToBack:backgroundView];
[view addSubview:textLabel];
return view;
}
- (float)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
return 22;
}
- (float)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 44;
}
[...]
Ответы
Ответ 1
Хорошие новости! Я смог исправить/устранить вашу проблему двумя способами (см. Ниже).
Я бы сказал, что это, безусловно, ошибка ОС. То, что вы делаете, вызывает перемещение ячейки (используя moveRowAtIndexPath:
) для размещения над (перед) ячейки заголовка в z-порядке.
Я смог воспроизвести проблему в OS 5 и 6 с ячейками, которые сделали и не имели UITextFields, и с помощью режима tableView в режиме и из режима редактирования (в вашем видео он находится в режиме редактирования, я заметил), Это также происходит, даже если вы используете заголовки стандартных разделов.
Пол, вы говорите в одном из своих комментариев:
Я решил это плохо с помощью загрузчика и "блокировки" таблицы, пока preforming reloadDatap >
Я не уверен, что вы подразумеваете под "использованием загрузчика и блокировкой таблицы", но я определил, что вызов reloadData
после moveRowAtIndexPath:
устраняет проблему. Разве это не то, что вы хотите сделать?
[self.tableView moveRowAtIndexPath:indexPath toIndexPath:newPath];
//[self.tableView reloadData];
// per reply by Umka, below, reloadSections works and is lighter than reloadData:
[self reloadSections:[NSIndexSet indexSetWithIndex:indexPath.section] withRowAnimation:UITableViewRowAnimationNone];
Если вы не хотите этого делать, вот еще одно решение, которое кажется мне немного взломанным, но, похоже, работает хорошо (iOS 5 +):
__weak UITableViewCell* blockCell = cell; // so we can refer to cell in the block below without a retain loop warning.
...
cell.onTextEntered = ^(NSString* sText)
{
// move item in my model
NSIndexPath *newPath = [NSIndexPath indexPathForRow:0 inSection:indexPath.section];
[self.itemNames removeObjectAtIndex:indexPath.row];
[self.itemNames insertObject:sText atIndex:0];
// Then you can move cell to back
[self.tableView moveRowAtIndexPath:indexPath toIndexPath:newPath];
[self.tableView sendSubviewToBack:blockCell]; // a little hacky
// OR per @Lombax, move header to front
UIView *sectionView = [self.tableView headerViewForSection:indexPath.section];
[self.tableView bringSubviewToFront:sectionView];
Ответ 2
Это ошибка.
Вы можете быстро решить эту проблему, добавив после строки:
[self.tableView moveRowAtIndexPath:indexPath toIndexPath:newPath];
эти строки:
UIView *sectionView = [self.tableView headerViewForSection:indexPath.section];
[self.tableView bringSubviewToFront:sectionView];
Ответ 3
Не решение, но ваш код имеет множество проблем. Кто знает, что произойдет, если вы их исправите;)
(1) Ваша ячейка может быть нулевой после этой строки:
ListCell * cell = [tableView dequeueReusableCellWithIdentifier: CellIdentifier];
Он должен выглядеть так:
ListCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[ListCell alloc] initWithStyle:style
reuseIdentifier:cellIdentifier] autorelease];
}
(2) Две утечки памяти в
- (UIView *) tableView: (UITableView *) aTableView viewForHeaderInSection: (NSInteger) раздел
- → Fix (Когда вы добавляете метку в качестве subview, она получает +1 ref).
UILabel *textLabel = [[[UILabel alloc] initWithFrame:CGRectMake(10, 0, 300, 21)] autorelease];
- → Fix (Когда вы добавляете представление в виде subview, оно получает +1 ref).
UIImageView *backgroundView = [[[UIImageView alloc]initWithImage:[AXThemeManager sharedTheme].tableviewSectionHeaderBackgroundImage] autorelease];
(3) Не дефект, но это может вам помочь. Попробуйте использовать это вместо [table reloadData]. Это позволяет прекрасно анимировать вещи и не является таким хардкорным способом обновления таблицы. Я уверен, что это намного легче. Попробуйте также искать другие методы "обновления". Учитывая, что вы не удаляете строки в своем примере, что-то вроде [updateRowsFrom: idxFrom to: idxTo] поможет.
[self.tableView reloadSections:[NSIndexSet indexSetWithIndex:0]
withRowAnimation:UITableViewRowAnimationAutomatic];
Ответ 4
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
float heightForHeader = 40.0;
if (scrollView.contentOffset.y<=heightForHeader&&scrollView.contentOffset.y>=0) {
scrollView.contentInset = UIEdgeInsetsMake(-scrollView.contentOffset.y, 0, 0, 0);
} else if (scrollView.contentOffset.y>=heightForHeader) {
scrollView.contentInset = UIEdgeInsetsMake(-heightForHeader, 0, 0, 0);
}
}
Ответ 5
Что я сделал для решения этой проблемы, так это установить zPosition представления в заголовке раздела.
headerView.layer.zPosition = 1000 //just set a bigger number, it will show on top of all other cells.