的UITableView校正滚动位置装置旋转后(UITableView correcting scr

2019-07-31 08:42发布

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版本赛义德·阿里·沙美岛的答案(的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)
        })
}


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