Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/webpack/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Iphone UITableView在设备旋转后校正滚动位置_Iphone_Ios_Uitableview_Scroll_Screen Rotation - Fatal编程技术网

Iphone UITableView在设备旋转后校正滚动位置

Iphone UITableView在设备旋转后校正滚动位置,iphone,ios,uitableview,scroll,screen-rotation,Iphone,Ios,Uitableview,Scroll,Screen Rotation,我在为一本书建立一个类似读者的东西。当用户旋转手机时,我想增加字体大小。我正在使用UITableView来显示文本块 问题是,增加字体大小会增加表格视图中行的高度,如果我在纵向模式下阅读第320段,在横向模式下会得到280或类似的结果 我使用以下代码设置了一个旋转通知侦听器: UIDevice *device = [UIDevice currentDevice]; [device beginGeneratingDeviceOrientationNo

我在为一本书建立一个类似读者的东西。当用户旋转手机时,我想增加字体大小。我正在使用
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+上工作。

一个简单的方法是存储顶部可见单元格的索引路径,更改字体大小,然后恢复顶部单元格:

NSIndexPath* topCellIndexPath = [[_tableView indexPathsForVisibleRows] objectAtIndex:0];
//Insert code to change font size here
[_tableView scrollToRowAtIndexPath:topCellIndexPath atScrollPosition:UITableViewScrollPositionTop animated:NO];
此代码可以放在方向更改时运行的任何方法中,例如问题中的
orientationChanged:
方法


这将不考虑将单元格向下滚动到一半,因此如果单元格的高度较大,则无法正常工作,需要使用内容偏移量的更复杂方法。如果是这种情况,请告诉我。

首先,要重新加载所有表格单元格,请使用
[self.tableView reloadData]

其次,在(
UITableViewCell*)tableView:(UITableView*)tableView cell for rowatinexpath:(nsindepath*)indepath
方法中添加负责收缩的代码行

例如:

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

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

既然我找不到好答案,我就自己回答。我到处都找过了,但找不到一个方法来做我想做的事情,所以我只是使用
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];
}

使用委托方法willRotateToInterfaceOrientation:将可见单元格存储在数组中,然后使用UITableView didRotateFromInterfaceOrientation的另一个委托方法:滚动到先前存储在数组中的可见索引路径。这是推荐的,您不必依赖于在不同线程中不一致的0.2秒等待来处理post rotate事件

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

Swift 3赛义德·阿里·萨米德回答的版本(
willRotateToInterfaceOrientation
didRotateFromInterfaceOrientation
被弃用):


谢谢你的帮助。我只是在测试这条路。我认为它会起作用,但是你能更具体地描述一下在哪里可以看到“willChange”和“didChange”事件?我应该使用委托吗?我更不知道什么时候保存topCellIndexPath?旋转设备不应该改变单元格位置,它只是因为更改字体大小而改变。在任何捕获方向变化的方法中,您都可以添加三行来存储顶部单元格,更改字体大小并恢复顶部单元格,这样应该可以正常工作。(编辑答案以反映这一点)这正是我所做的,但在使用
shouldAutorotateToInterfaceOrientation
方法时,它首先滚动然后旋转屏幕,因此没有任何效果。这就是为什么我在线程中添加了一点sleep,然后(在旋转完成的同时)滚动到该线程。谢谢,谢谢,但这不是解决办法。它的高度增加,因为它的意思是这样的。我希望它增加。我唯一需要做的就是在它真正旋转之前检测到设备将要旋转。谢谢你将此翻译成Swift 3!很好用!
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)
        })
}