UITableView 在 contentInset 之后不滚动

Posted

技术标签:

【中文标题】UITableView 在 contentInset 之后不滚动【英文标题】:UITableView Not Scrolling after contentInset 【发布时间】:2014-05-19 06:42:41 【问题描述】:

我正在做一个项目,我有一个 tableview 和一个 uitextfield。

当 uitextfield 获得/失去焦点时,我正在应用以下方法:

-(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

重现错误: 滚动列表,点击搜索栏,点击取消,再次尝试滚动列表。

奇怪地点击过滤器按钮,当 UIActionSheet 被关闭时,滚动再次起作用。

【问题讨论】:

经过一些测试,我不知道为什么,但是如果我在那之后显示 UIActionSheet,当被解除时,tableView 又会回滚。 【参考方案1】:

在为您的问题寻找解决方案时,我注意到您的 placesTableView 的 contentInset 的底部在不同的状态下不断变化。在您可以看到地图的初始状态时,它为 0,并且 tableView 的行为符合预期。在点击搜索字段后键盘出现时,它被设置为 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; 一样。我还必须将@interfacestatement 更改为@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 输出不同的参数。

我希望这会有所帮助。让我知道这是否适合您。

【讨论】:

感谢您的时间和回答,我也做了一些研究,找到了一个可行的解决方案。在下面查看我的答案,也许您可​​以帮助我了解真正发生的事情。 :-) 经过一些修改,这非常适合我想要做的事情。在文本视图中隐藏和取消隐藏 UILabel。就像 Notes 应用程序文本视图中的时间戳一样。谢谢。【参考方案2】:

经过一些研究,我注意到了:

释放键盘时的 TableView 没有滚动,因为 tableview 似乎认为它显示在整个屏幕上。我尝试在 tableview 中添加更多数据,我们可以看到视图正在滚动一点。

我相信发生的事情是,当键盘被隐藏时,会完成一些自动调用,并弄乱我在 enableInset 方法中设置的内容。这是我的工作解决方案:

我注册了 hideKeyboard 事件:

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

在回调中我调用了 enableInset:

- (void)keyboardDidHide: (NSNotification *) notif
    [self enableInset];

并且视图再次向后滚动。 欢迎对此作出任何解释。

【讨论】:

是的,这绝对是一个可行的解决方案。但是,此代码所做的是假设存在问题,并等到问题发生后再修复它。本着良好的代码设计和编程艺术的精神,我建议使用我在答案中提供的代码。这是因为我只是让系统做它所做的事情而不受干扰。您的代码正在做的是干扰系统,等待错误然后修复它。不过,修复此错误的两种方法仍然有效。 感谢您的回复,我现在很着急,但我今晚会尝试您的解决方案!

以上是关于UITableView 在 contentInset 之后不滚动的主要内容,如果未能解决你的问题,请参考以下文章

处理ios11以上的pop回来的回收效果

在 UITableView 中的 UINib 中重新加载 UITableView

使用 UITableView 在 UITableView 上自动滚动 UIImageView

如果 UITableView 在 UIScrollView 中,则无法在 UITableView 上执行滑动删除

如何在没有数组的 UITableView 中显示 UITableView Cell?

尝试在用户向 iOS 中的 UITableView 添加行时动态增加 UITableView 的高度