我正在为一本书构建类似读者的东西。当用户旋转手机时,我想增加字体大小。我正在使用UITableView
来显示文本块。
问题是,增加字体大小会增加表格视图中行的高度,如果我在纵向模式下阅读第320段,我会在横向模式下获得280或类似内容。
我已使用以下代码设置了旋转通知侦听器:
UIDevice *device = [UIDevice currentDevice];
[device beginGeneratingDeviceOrientationNotifications];
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc addObserver:self
selector:@selector(orientationChanged:)
name:UIDeviceOrientationDidChangeNotification
object:device];
并尝试在旋转前保存最后一个段落索引,然后在旋转后向下滚动到它但我似乎无法达到预期的效果。
处理这种情况的最佳方法是什么?我在哪里实际实现“之前”和“之后”轮换状态?
我希望它适用于iOS 4 +。
答案 0 :(得分:5)
快速3 版本的Said Ali Samed的回答(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)
})
}
答案 1 :(得分:4)
使用委托方法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];
}
答案 2 :(得分:2)
一种简单的方法是存储顶部可见单元格的索引路径,更改字体大小然后恢复顶部单元格:
NSIndexPath* topCellIndexPath = [[_tableView indexPathsForVisibleRows] objectAtIndex:0];
//Insert code to change font size here
[_tableView scrollToRowAtIndexPath:topCellIndexPath atScrollPosition:UITableViewScrollPositionTop animated:NO];
此代码可以放在方向更改时运行的任何方法中,例如您在问题中添加的orientationChanged:
方法。
这不会考虑在单元格中间向下滚动,因此如果单元格的高度很大,则无法正常工作,并且需要使用内容偏移的更复杂的方法。如果是这种情况,请告诉我。
答案 3 :(得分:1)
由于我无法得到一个好的答案,我会自己回答。我到处寻找,但无法找到一种方法来做我想要的,所以我只是使用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];
}
答案 4 :(得分:0)
首先,要重新加载所有表格单元格,请使用[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:
方法。但我不确定这个功能是如何工作的,所以我不能太具体。
答案 5 :(得分:0)
- (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];
}
}