用像Instagram这样的“更多”button展开UITableView中的UILabel
我有一个项目(这是由其他人写的),其中有一个饲料的内容和文本显示在一个表视图。 每个post对应于表格视图中的一个部分,每个部分都有自己的行,对应于内容,文本,像button等元素。
我需要在表格视图单元格内使用“更多”button来显示标题的简短标签,当点击更多button时,标签将展开为标题适合的任何大小,全部发生在表格视图单元格内。 当点击更多button时,我将标签的numberOfLines
属性更改为零,并且由于单元格具有自动高度,所有我需要的是重新加载该特定的标题单元格。 (如果在显示单元格之前将numberOfLines
设置为0,则单元格会正确显示扩展的大小。)
我试过了:
[tableView beginUpdates];
tableView endUpdates];
我已经尝试过各种animation选项:
[tableView reloadRowsAtIndexPaths:@[myPath] withRowAnimation:UITableViewRowAnimation(Bottom,Top,None etc)];
我试过了:
[tableView reloadSections:[NSIndexSet indexSetWithIndex:myPath.section] withRowAnimation:UITableViewRowAnimation(Top,Bottom,None etc)];
但他们都产生了相同的结果:整个表视图布局变得混乱:它跳转到另一个单元格,一些视图变成空白,单元格重叠,单元格内的video停止播放,标签不扩展(但刷新内部本身,如简短的预览TXT一行从顶部/底部animation,但不扩大)。
什么可能导致整个表视图的混乱,以及如何能够正确地重新加载一个单元格和扩展animation,而不会搞乱整个布局? 我已经看到了很多关于这个的问题和答案,但是他们都推荐我已经尝试和解释过的选项。
我的应用程序的目标是iOS 8.0+
更新:这里是相关的代码(有关与布局无关的内部工作的一些部分,删除):
MyCell *cell = (MyCell *)[tableView dequeueReusableCellWithIdentifier: MyCellIdentifier forIndexPath:indexPath]; cell.delegate = self; cell.indexPathToReloadOnAnimation = indexPath; cell.shouldShortenCaption = YES; id post = self.posts[indexPath.section] ; [cell setPost:post]; return cell;
而且在setPost:
里面:
if(self.shouldShortenCaption){ captionLabel.numberOfLines = 2; }else{ captionLabel.numberOfLines = 0; } NSString *text = [some calculated (deterministic) text from post object];
button操作很简单:
self.shouldShortenCaption = NO; [one of the reload codes that I've written above in the question]
更新2:这里有一些关于这个问题的更多的方法:
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { if (section < self.posts.count) { return 59; }else return 0; } - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section { if (section < self.posts.count) { MyFeedHeader *header = [tableView dequeueReusableCellWithIdentifier:MyFeedHeaderIdentifier]; header.delegate = self; [header setPostIndex:section]; [header setPost:self.posts[section]] ; return header; } else return nil; }
标题的setPost:
方法基本上将相关文本设置为标签(与标题无关,它们是完全不同的单元格,有问题的单元格不是标题单元格)。 该表没有任何页脚方法。 关于身高的唯一方法是上面的方法。
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { if (section >= self.posts.count) { return 1; } id post = self.posts[section]; [calculate number of rows, which is deterministic] return [number of rows]; } - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { BOOL hasCursor = self.cursor && self.hasMore ? 1 : 0; return self.posts.count + hasCursor; }
(post数和游标和hasMore也是确定性的)。
更新3:我问了一个问题(这不是重复的,即使有类似的问题),并得到了一个有用的答案,解决了我的问题。 请问下面的人请详细说明他们低估的原因吗?
这是一个例子: https : //github.com/DonMag/DynamicCellHeight
表B是完成“更多/更less”的一种方式(表A是我玩过的另一种布局)。 它使用[tableView beginUpdates]; tableView endUpdates];
[tableView beginUpdates]; tableView endUpdates];
触发表格重新布局的方法。
关键是要正确设置所有的约束,所以自动布局引擎可以做到你所期望的。
这个例子是在Swift中,但是应该很容易地转换回Obj-C(我想我是先在Obj-C中做的)。
编辑:一些额外的笔记…
这是使用dynamic高度表格视图单元的一个非常标准的方法。 元素之间的垂直间隔约束有效地“推出”了单元格的边界。 点击此处切换2和0之间的标签的numberOfLines
属性(零意味着根据需要多行)。 对表视图上的beginUpdates
/ endUpdates
进行的顺序调用将通知自动布局引擎重新计算行高, 而无需重新加载数据。
对于这个例子,我确实使用了一些“欺骗”来获得平滑的展开/折叠效果……你在这里看到的多行标签包含在一个UIView
(with clipsToBounds
true)中。 有第二个,重复的多行标签(alpha 0,所以它是不可见的),正在控制的高度。 我发现,将可见标签上的numberOfLines
改为“snapped”为2行,然后发生尺寸改变animation…导致文本“跳来跳去”。
只是为了这个,为了比较起见,我在GitHub上添加了“不太好”的版本。