2012-09-04 44 views
2

我在为一本书编写一些东西,像读者。当用户旋转手机时,我想增加字体大小。我正在使用UITableView来显示文本块。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+上运行。

回答

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]; 
} 
2

一个简单的方法来做到这将是存储顶部可见单元的索引路径,改变字体大小,然后还原顶电池:

NSIndexPath* topCellIndexPath = [[_tableView indexPathsForVisibleRows] objectAtIndex:0]; 
//Insert code to change font size here 
[_tableView scrollToRowAtIndexPath:topCellIndexPath atScrollPosition:UITableViewScrollPositionTop animated:NO]; 

这个代码可以放在这的运行的任何方法当方向发生变化时,例如您在问题中提出的orientationChanged:方法。

这不会考虑到在单元格中间滚动一下,所以如果单元格的高度很大,它将无法正常工作,并且需要使用内容偏移量的更复杂的方法。让我知道如果是这样的话。

+0

谢谢您的帮助。我只是测试这个出路。我认为它会起作用,但是你能否更具体地在哪里找到“willChange”和“didChange”事件的方向?我应该使用代表吗? – Gio

+0

我在什么时候保存topCellIndexPath更有兴趣? – Gio

+0

旋转设备不应改变单元格的位置,它只是因为您要更改字体大小而改变。在捕获方向变化的任何方法中,您可以添加三行来存储顶部单元格,更改恢复顶部单元格的字体大小,它应该可以正常工作。 (编辑答案反映了这一点) – Ander

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:方法,但是我不确定这个函数是如何工作的,所以我不能太具体。

+0

谢谢,但这不是一个解决方案。它的高度增加是因为它意味着要这样。我希望它增加。我需要的只是检测设备是否会旋转,但在实际使用之前。 – Gio

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]; 
    } 
} 
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]; 
} 
5

斯威夫特3版本赛义德·阿里·沙美岛的答案(willRotateToInterfaceOrientationdidRotateFromInterfaceOrientation已废弃):

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

感谢您将此翻译成Swift 3!完美的作品! – bgolson

相关问题