UITableView在contentInset后无法滚动

3
我是一名有用的助手,可以为您进行翻译。以下是您需要翻译的内容:

我正在开发一个项目,其中包括一个表格视图和一个文本框。

当文本框获得/失去焦点时,我使用以下方法:

-(void)enableInset {

CGFloat offSet = -30.0f;
UIEdgeInsets inset = UIEdgeInsetsMake(placesMapView.frame.size.height - offSet, 0.0f, 0.0f, 00.f);

// Updating the tableView position.
placesTableView.contentInset = inset;
placesTableView.contentOffset = CGPointMake(0.0f, -(placesMapView.frame.size.height - offSet));
placesTableView.scrollIndicatorInsets = inset;
}

- (void)disableInset {
CGFloat offset = self.navigationController.navigationBar.frame.size.height  + [UIApplication sharedApplication].statusBarFrame.size.height;
UIEdgeInsets inset = UIEdgeInsetsMake(offset, 0.0f, 0.0f, 00.f);
placesTableView.contentInset = inset;
placesTableView.contentOffset = CGPointMake(0.0f, -offset);
placesTableView.scrollIndicatorInsets = inset;
}

在viewDidLayoutSubviews中调用了enableInset方法。然后当我调用disableInset和enableInset时,UITableView就无法滚动了。

我做错了什么?有任何想法可以寻找答案吗?

编辑: 如果有帮助的话,我在github上添加了这个项目:

https://github.com/Loadex/PlaceViewer

复现bug的步骤: 滚动列表,点击搜索栏,点击取消,尝试再次滚动列表。

当UIActionSheet被解除显示时,奇怪地点击筛选按钮,此时滚动又可以正常工作了。


经过一些测试,我不知道为什么,但如果我在此之后显示UIActionSheet,当它被解除时,tableView会再次滚动回来。 - Loadex
2个回答

2
在寻找解决方案时,我发现您的 placesTableView 的 contentInset 底部在不同状态下一直在改变。当您可以看到地图并且 tableView 表现正常时,初始状态下它为 0。当您点击搜索字段后键盘弹出时,它被设置为 216。我想这是 tableView 和键盘之间某些自动通信(通过通知或者在 PlacesQueryTableViewController 中执行的一些操作)引起的。这很好,因为我们希望底部的插入会在键盘弹出时设置为键盘顶部。现在问题来了,当我点击取消按钮时,contentInset.bottom 被设置为 -216。
我无法完全解释为什么会发生这种情况,但我怀疑这与插入的自动更改方式有关。我猜测它做了类似于 tableView.contentInset.bottom -= heightOfKeyboard 的事情,而这可能是在动画完成后才发生的,而不是之前。您的问题的源头在于您在动画完成之前更改了 contentInset 底部,因此也在那个自动更改发生之前进行更改。因此,您将底部设置为 0,用户一旦点击取消,系统就会进来并将其减小键盘的高度,结果为 216。这至少是我认为发生的事情。
要解决这个问题,避免更改 contentInset 底部,并只更改顶部。虽然 placesTableView.contentInset.top 是只读的,但如果您像下面的代码一样操作,您可以绕过它。我只更改了每个方法中与插入相关的两行代码,希望您能理解我的做法。
-(void)enableInset {
NSLog(@"Enabling insets");
// Setting the tableView to overlay the map view
CGFloat offSet = [placestableViewController tableView:placestableViewController.tableView heightForRowAtIndexPath:nil] - 30.0f;
UIEdgeInsets inset = placesTableView.contentInset; // UIEdgeInsetsMake(placesMapView.frame.size.height - offSet, 0.0f, 0.0f, 0.0f);
inset.top = placesMapView.frame.size.height - offSet;

// Updating the tableView position.
placesTableView.contentInset = inset;
placesTableView.contentOffset = CGPointMake(0.0f, -(placesMapView.frame.size.height - offSet));
placesTableView.scrollIndicatorInsets = inset;

placesMapView.hidden = NO;
[placestableViewController loadObjects];}


- (void)disableInset {
NSLog(@"Disable insets");
CGFloat offset = self.navigationController.navigationBar.frame.size.height  + [UIApplication sharedApplication].statusBarFrame.size.height;
UIEdgeInsets inset = placesTableView.contentInset;// UIEdgeInsetsMake(offset, 0.0f, 0.0f, 0.0f);
inset.top = offset;

placesTableView.contentInset = inset;
placesTableView.contentOffset = CGPointMake(0.0f, -offset);
placesTableView.scrollIndicatorInsets = inset;

// Hidding the map while in search
placesMapView.hidden = YES;}

顺便说一下,如果您想知道我如何在不同状态下找到contentInset值,那很简单。我所做的是在- (void)viewDidLoad中将自己设置为placesTableView的代理,像这样placesTableView.delegate = self;。我还必须更改@interface语句以@interface KrackMapViewController() <UITableViewDelegate>的方式来表示我们符合UITableViewDelegate。现在,这里有个技巧:UITableViewDelegate符合UIScrollViewDelegate。这意味着我们可以实现滚动视图委托方法。特别有趣的一个方法是:

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView { NSLog(@"Did scroll with insetTop: %f, insetBottom: %f, contentOffset: %f", placesTableView.contentInset.top, placesTableView.contentInset.bottom, placesTableView.contentOffset.y); }

这让我们知道您何时开始拖动tableView,在那里简单地NSLog出不同的参数。

希望这对您有所帮助。如果这对您有用,请告诉我。


感谢您的时间和答案,我也进行了一些研究,找到了一个可行的解决方案。请查看我的答案,也许您可以帮助我知道到底发生了什么。 :-) - Loadex
通过一些修改,这个程序完美地实现了我想要做的事情。在文本视图中隐藏和取消隐藏UILabel,就像“笔记”应用程序文本视图中的时间戳一样。谢谢。 - ChrisOSX

1

在进行了一些研究后,我发现以下内容:

当键盘弹出并收起时,TableView不会滚动,原因是TableView似乎认为它显示在整个屏幕上。我尝试在TableView中添加更多的数据,可以看到视图稍微滚动了一下。

我认为发生的事情是当键盘隐藏时,一些自动调用正在干扰我的enableInset方法所设置的内容。这是我的工作解决方案:

我注册了hideKeyboard事件:

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(keyboardDidHide:)
                                             name:UIKeyboardDidHideNotification
                                           object:nil];

在回调函数中,我调用了 enableInset:。
- (void)keyboardDidHide: (NSNotification *) notif{
    [self enableInset];
}

视图再次向后滚动。 欢迎任何关于此的解释。


是的,这绝对也是一个可行的解决方案。然而,这段代码所做的是假设存在问题,并等待该问题发生后再进行修复。在良好的代码设计和编程艺术精神中,我建议使用我在答案中提供的代码。这是因为我只是让系统按照它的方式运行,而不进行干扰。你的代码正在干扰系统,等待错误然后修复它。虽然两种修复此错误的方法仍然有效。 - vegather
谢谢您的回复,我现在很忙,但今晚我会尝试您的解决方案! - Loadex

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接