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;
一样。我还必须将@interface
statement 更改为@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 之后不滚动的主要内容,如果未能解决你的问题,请参考以下文章
在 UITableView 中的 UINib 中重新加载 UITableView
使用 UITableView 在 UITableView 上自动滚动 UIImageView
如果 UITableView 在 UIScrollView 中,则无法在 UITableView 上执行滑动删除