I'm building something like a reader for a book. When the user rotates the phone I want to increase the font size. I'm using a UITableView
to display chunks of text.
Problem is that, increasing the font size increases height of rows in my table view and if I was reading paragraph 320 in portrait mode I get 280 or something similar in landscape mode.
I have set up a rotation notification listener using this code:
UIDevice *device = [UIDevice currentDevice];
[device beginGeneratingDeviceOrientationNotifications];
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc addObserver:self
selector:@selector(orientationChanged:)
name:UIDeviceOrientationDidChangeNotification
object:device];
and tried to save the last paragraph index before rotation and then scroll down to it after the rotation but I can't seem to achieve desired effect.
What's the best way to handle this kind of situation and where do I actually implement "before" and "after" states of rotation?
I'd like it to work on iOS 4+.
Answer 1:
雨燕3.0版本赛义德·阿里·沙美岛的答案(的willRotateToInterfaceOrientation
和didRotateFromInterfaceOrientation
已废弃):
override func willTransition(to newCollection: UITraitCollection, with coordinator: UIViewControllerTransitionCoordinator) {
coordinator.animate(alongsideTransition: { context in
// Save the visible row position
self.visibleRows = self.tableView.indexPathsForVisibleRows!
context.viewController(forKey: UITransitionContextViewControllerKey.from)
}, completion: { context in
// Scroll to the saved position prior to screen rotate
self.tableView.scrollToRow(at: self.visibleRows[0], at: .top, animated: false)
})
}
Answer 2:
使用委托方法willRotateToInterfaceOrientation:在可见的细胞存储在数组中,然后使用的UITableView didRotateFromInterfaceOrientation的其他委托方法:滚动到前面的阵列中存储的可视索引路径。 这是建议,你不必依靠不一致0.2秒在不同的线程来处理旋转后等待事件。
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
// Save the visible row position
visibleRows = [tableview indexPathsForVisibleRows];
}
-(void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
// Scroll to the saved position prior to screen rotate
[tableView scrollToRowAtIndexPath:[visibleRows objectAtIndex:0] atScrollPosition:UITableViewScrollPositionTop animated:NO];
}
Answer 3:
一个简单的方法来做到这将是存储顶部可见单元的索引路径,改变字体大小,然后还原顶电池:
NSIndexPath* topCellIndexPath = [[_tableView indexPathsForVisibleRows] objectAtIndex:0];
//Insert code to change font size here
[_tableView scrollToRowAtIndexPath:topCellIndexPath atScrollPosition:UITableViewScrollPositionTop animated:NO];
这个代码可以摆在那的运行时方向的变化,如任何方法orientationChanged:
你把问题的方法。
这不会考虑到已经滚动中途下来的细胞,所以如果你的细胞的高度大,将无法正常工作,以及需要使用的内容偏移更复杂的方法。 让我知道如果是这种情况。
Answer 4:
因为我无法得到一个很好的答案,我会回答自己。 我到处找,但找不到办法做我想要的东西,所以我只是用shouldAutorotateToInterfaceOrientation
方法来增加字体的大小,然后开始有点线程睡眠0.2秒,并且滚动到所需的行之后。 谢谢你的帮助。
编辑:使用委托方法willRotateToInterfaceOrientation:在可见的细胞存储在数组中,然后使用委托方法didRotateFromInterfaceOrientation:滚动到你的数组中记录的可见索引路径。
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
// Save the visible row position
visibleRows = [tableview indexPathsForVisibleRows];
}
-(void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
// Scroll to the saved position prior to screen rotate
[tableView scrollToRowAtIndexPath:[visibleRows objectAtIndex:0] atScrollPosition:UITableViewScrollPositionTop animated:NO];
}
Answer 5:
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)
fromInterfaceOrientation
{
NSLog(@"didRotateFromInterfaceOrientation:%d",fromInterfaceOrientation);
[tableView reloadRowsAtIndexPaths:[tableView indexPathsForVisibleRows] withRowAnimation:UITableViewRowAnimationNone];
}
然后,我会建议增加无论是interfaceOrientation数量或干脆表格的宽度,以出列单元格名称的方式的tableView知道细胞的一个旋转与那些在另一个不同。 像这样:
- (UITableViewCell *)tableView:(UITableView *)tv
cellForRowAtIndexPath:(NSIndexPath *)indexPath
withType:(NSString *)s_type
{
UITableViewCell *cell = nil;
// add width of table to the name so that rotations will change the cell dequeue names
s_cell = [s_cell stringByAppendingString:
[NSString stringWithFormat:@"%@%d",@"Width",(int)tv.bounds.size.width]
];
NSLog(@"%@",s_cell);
cell = [tv dequeueReusableCellWithIdentifier:s_cell];
if( cell == nil ) {
cell = [[[UITableViewCell alloc]
initWithFrame:CGRectZero reuseIdentifier:s_cell] autorelease];
}
}
Answer 6:
首先,重新加载所有的表格单元格的使用[self.tableView reloadData]
其次,添加的代码行负责(内侧收缩UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
方法。
例:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
//Some identifier and recycling stuff
if (UIInterfaceOrientationIsPortrait(self.interfaceOrientation)) {
//Make labels smaller
}
else {
//Make them bigger
}
}
或者,你可以打电话给你updateCellForRotate:forRow:
使它们时方法。 但我不知道该函数是如何工作的,所以我不能太具体。
文章来源: UITableView correcting scroll position after device rotation