从横向旋转到纵向 (iPad) 后 UITableView 的奇怪行为

Posted

技术标签:

【中文标题】从横向旋转到纵向 (iPad) 后 UITableView 的奇怪行为【英文标题】:Strange Behavior for UITableView after rotation from Landscape to Portrait (iPad) 【发布时间】:2012-11-09 10:18:20 【问题描述】:

我试图在方法中旋转后读取tableview的contentOffset

willRotateToInterfaceOrientation:duration:.我使用 UITableViewController 和 tableHeaderView 中的搜索栏创建了一个示例。

场景 1: 给定设备是纵向的,我隐藏了搜索栏 然后我将设备旋转到横向 在那之后,我不希望看到 UISearchbar 和 contentOffset 保持不变。

场景 2: 给定设备处于横向状态,我隐藏了搜索栏 然后我将设备旋转到纵向 在那之后,我不希望看到 UISearchbar 和 contentOffset 保持不变。

场景 1 正在按预期工作。场景 2 弹出 Searchbar 并且 contentoffset 为零

有人知道为什么 ContentOffset 为零吗?我希望它是 44(搜索栏的高度)。

有没有办法解决这个问题?你会怎么做?

//
//  ViewController.m
//  test
//

#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

- (id)initWithStyle:(UITableViewStyle)style

    self = [super initWithStyle:style];
    if (self) 
        // Custom initialization
    
    return self;


- (void)viewDidLoad

    [super viewDidLoad];

    // Uncomment the following line to preserve selection between presentations.
    // self.clearsSelectionOnViewWillAppear = NO;

    // Uncomment the following line to display an Edit button in the navigation bar for this view controller.
    // self.navigationItem.rightBarButtonItem = self.editButtonItem;



- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration

    //is necessary to prevent showing searchbar
    dispatch_async(dispatch_get_main_queue(), ^


        double y = self.tableView.contentOffset.y;

        self.tableView.contentInset = UIEdgeInsetsMake(-1*y, 0, 0, 0);

        NSLog(@"y %f",y);
        NSLog(@"Begin offset %@",NSStringFromCGPoint(self.tableView.contentOffset));
    );



- (void)viewDidAppear:(BOOL)animated

    self.tableView.tableHeaderView = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, self.tableView.frame.size.width, 44)];


#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView

#warning Potentially incomplete method implementation.
    // Return the number of sections.
    return 0;


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section

#warning Incomplete method implementation.
    // Return the number of rows in the section.
    return 0;


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) 
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    

    // Configure the cell...

    return cell;


#pragma mark - Table view delegate

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath




@end

【问题讨论】:

我知道显式设置 tableHeaderView 应该避免这种情况,但是您是否尝试过使用 -(CGFloat) tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section 委托方法的代码?尝试在其中返回 44.0 看看是否有帮助。 此方法仅返回 tableView:viewForHeaderInSection 中标题部分的高度(不是 tableHeaderView 的)。 contentoffset 为零真的很奇怪。我希望这不是 API 中的错误 嗯,我根据你的代码创建了一个项目,我没有看到这两个方向之间有什么区别。两者都返回 0/0,搜索栏仍保留在屏幕上。两个(可能是幼稚的)问题:为什么要使用 dispatch 而不仅仅是更改内容值,如果您只是将搜索栏滑出屏幕,为什么要更改 contentInset 而不是 contentOffset 我试图在旋转过程中隐藏搜索栏。尝试在 iPad 上以横向模式隐藏搜索栏,然后将设备旋转到纵向。然后你会看到搜索栏会弹出。我正在尝试使用 UIEdgeInsets 来保持 UISearchbar 锁定在顶部。 【参考方案1】:

我想我知道问题出在哪里:

UITableView 具有默认的自动调整大小掩码。因此,在将设备从纵向旋转到横向之后,UITableView 变得越来越小(这不会改变偏移量)。如果用户现在转回纵向,则 UITableView 需要被拉伸并自动滚动到顶部。为了解决这个问题,我使用了一个变量来注册每个“用户滚动”,比如

scrollViewWillBeginDragging(注册) scrollViewDidEndDecelerating(取消注册) 在“scrollViewDidScroll”中检查滚动是否来自用户(如果是来自用户保存偏移值)

最后,在“willRotateToInterfaceOrientation”方法中,我将临时保存的偏移量设置为 UITableView 以使其保持在同一位置。

我希望会有更好的解决方案,因为我解决这个问题的方法有点棘手。

【讨论】:

【参考方案2】:

我今天遇到了类似的问题,我找到了解决方案。 声明了一个维护 tableView 的 contentOffset 的实例变量。 在 - (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration 方法调用期间保留 contentOffset 值并将其应用于 - (void)viewWillLayoutSubviews 方法。我们需要重写这个方法。

- (void)willRotateToInterfaceOrientation(UIInterfaceOrientation)toInterfaceOrientation      duration:(NSTimeInterval)duration

    self.contentOffset = self.tableView.contentOffset;


- (void)viewWillLayoutSubviews

    [super viewWillLayoutSubviews];
    self.tableView.contentOffset = self.contentOffset;

这解决了我的问题,没有任何令人耳目一新的问题。

【讨论】:

以上是关于从横向旋转到纵向 (iPad) 后 UITableView 的奇怪行为的主要内容,如果未能解决你的问题,请参考以下文章

将 ipad 从纵向旋转到横向时,Div 保持相同的宽度

元素无法从纵向切换到横向 ipad

当我在 iOS7 的 iPad 中将视图从纵向旋转到横向或反之亦然时,UITextfield shouldChangeCharactersInRange 没有调用

在两个视图之间切换以及从纵向切换到横向时出现 iPad 方向问题,反之亦然

从纵向模式旋转到横向模式时,搜索栏会丢失 FirstResponder

iPad 模态控制器在旋转后被解散