iOS UITableViewCell 内容在第一次滚动时移动
Posted
技术标签:
【中文标题】iOS UITableViewCell 内容在第一次滚动时移动【英文标题】:iOS UITableViewCell contents move on first scroll 【发布时间】:2015-04-28 15:01:47 【问题描述】:您可以在下面的 gif 中看到 UITableView 单元格内容的第一次滚动时移动了一点点。你几乎看不到它,边距变宽了 1 个像素。我以前从未遇到过这种情况。似乎在第一次滚动之前存在一些布局问题,并且在事后自行解决。 XCode 中没有警告,这些自定义单元格非常简单,没有布局代码覆盖。
我不知道从哪里开始,我该如何发现这个故障?
更新。我现在已经实施了一个明显的解决方法:
- (void)scrollTableToFixGlitch
[self.tableView setContentOffset:CGPointMake(0, 1)];
[self.tableView setContentOffset:CGPointMake(0, -1)];
- (void)viewDidLoad
[super viewDidLoad];
[self scrollTableToFixGlitch];
仍在调查问题。我试过通用的 UITableViewCells,没有任何改变。似乎是 View Controller 的根视图或 tableview 布局的问题,而不是表格单元格的问题。
更新 2。
我排除了所有动画问题,问题出在不同区域的某个地方。在一个非常简化的项目上很容易重新创建故障。我的标签栏控制器基于MHCustomTabBarController,带有自定义segues 和其他一些附加功能。以下是重现故障的方法。设置一个项目,您的初始 VC 嵌入到导航控制器中。下一个控制器 MHCustomTabBarController 或子类被推送到导航堆栈。标签栏中第一个可见的 VC 是通用表视图控制器。就是这样。仅当标签栏控制器被推入导航堆栈时才会出现故障。
这是我认为标签栏控制器的一些代码:
-(void) viewWillAppear:(BOOL)animated
[super viewWillAppear:animated];
if (self.childViewControllers.count < 1)
[self performSegueWithIdentifier:@"viewController1" sender:[self.buttons objectAtIndex:0]];
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
if (![segue isKindOfClass:[MHTabBarSegue class]])
[super prepareForSegue:segue sender:sender];
return;
self.oldViewController = self.destinationViewController;
//if view controller isn't already contained in the viewControllers-Dictionary
if (![self.viewControllersByIdentifier objectForKey:segue.identifier])
[self.viewControllersByIdentifier setObject:segue.destinationViewController forKey:segue.identifier];
[self.buttons setValue:@NO forKeyPath:@"selected"];
[sender setSelected:YES];
self.selectedIndex = [self.buttons indexOfObject:sender];
self.destinationIdentifier = segue.identifier;
self.destinationViewController = [self.viewControllersByIdentifier objectForKey:self.destinationIdentifier];
[[NSNotificationCenter defaultCenter] postNotificationName:MHCustomTabBarControllerViewControllerChangedNotification object:nil];
还有一个自定义的 segue 代码:
@implementation MHTabBarSegue
- (void) perform
MHCustomTabBarController *tabBarViewController = (MHCustomTabBarController *)self.sourceViewController;
UIViewController *destinationViewController = (UIViewController *) tabBarViewController.destinationViewController;
//remove old viewController
if (tabBarViewController.oldViewController)
[tabBarViewController.oldViewController willMoveToParentViewController:nil];
[tabBarViewController.oldViewController.view removeFromSuperview];
[tabBarViewController.oldViewController removeFromParentViewController];
destinationViewController.view.frame = tabBarViewController.container.bounds;
[tabBarViewController addChildViewController:destinationViewController];
[tabBarViewController.container addSubview:destinationViewController.view];
[destinationViewController didMoveToParentViewController:tabBarViewController];
@end
更新 3
在我的研究中,我发现 - viewWillAppear 在子控制器第一次出现时不会被调用。但在所有后续时间中都会调用它。
【问题讨论】:
【参考方案1】:也许滚动视图contentSize
比滚动视图的框架宽(在这种情况下特别是宽度)导致双向滚动。
您可以尝试将contentSize
宽度减小到滚动视图的宽度,然后
self.scrollView.alwaysBounceHorizontal = NO;
如果这不起作用,解决方案是在 UIScrollView
委托的帮助下以编程方式禁用水平滚动
self.scrollView.delegate = self;
[self.scrollView setShowsHorizontalScrollIndicator:NO];
//for the below UIScrollView delegate function to work do the necessary step in the bottom of my answer.
-(void)scrollViewDidScroll:(UIScrollView *)scrollView
if (scrollView.contentOffset.x > 0)
scrollView.contentOffset = CGPointMake(0, scrollView.contentOffset.y);
在你的 .h 文件中,你应该通过添加UIScrollViewDelegate
将接口行更改为下面的
@interface ViewController : UIViewController <UIScrollViewDelegate>
你很可能非常了解这个委托部分,但对其他人来说可能需要它:D
【讨论】:
感谢您的建议,但在我的情况下没有水平滚动。表格视图正确滚动。内容视图的布局存在问题。第一次滚动后它会发生一点变化。 当我在 gif 中看到UISegmentedControl
时,我认为 tableviews 在 UIScrollView 内
啊,我明白了。它实际上不是 UISegmentedControl,它有点像我从头开始制作的标签栏控制器。由于我刚刚使用通用 UITableViewCell 测试了这个案例并且问题仍然存在,我相信问题源于这个选项卡控制器,它是自定义动画。我现在正在调查。
我明白了。自定义标签栏实现看起来不错。祝你好运找到故障。如果您发布一些代码,我会尝试调试。【参考方案2】:
原答案
啊,我终于找到了这种行为的根源。我几乎可以肯定这是由于某些准备方法没有正确调用而发生的。正如我在 update 3 中所述,我发现当我的 TabBarController 被推送到堆叠的导航时,TableViewController 中不会调用 -viewWillAppear 方法。我在 SO 上找到了大量关于此事的报道,这显然是一个众所周知的问题。
我添加了一个简单的修复程序,只是为了检查我的自定义 Segue 是否正确:
//added this line
[destinationViewController viewWillAppear:YES];
[tabBarViewController.container addSubview:destinationViewController.view];
它就像一个魅力,没有闪烁!现在我必须为这个调用找出一个更合适的地方,因为对这样的方法的显式调用会破坏很多东西。
可能最好的地方是在 UINavigationControllerDelegate 的 -navigationController:willShowViewController:animated: 方法中。
不管怎样,问题解决了。希望它能帮助遇到同样问题的人。
更新实际上,我对此并不完全正确。 -viewWillAppear 在我的标签栏控制器被推送到导航堆栈时被调用。它没有被翻译成 TableViewController。所以不需要访问 NavigationControllerDelegate。对自定义 segue 进行简单修复就足够了。
【讨论】:
以上是关于iOS UITableViewCell 内容在第一次滚动时移动的主要内容,如果未能解决你的问题,请参考以下文章
iOS 设计具有可定制内容的 UITableViewCell
在第二次搜索时带有自定义 UITableViewCell 的 UISearchDisplayController 失去 UITableViewCell 连接
如何阻止 UITableView 在 iOS 7 中剪辑 UITableViewCell 内容
iOS Swift - UITableViewCell 自定义子类不显示内容
无法再与 iOS 14 中的 UICollectionViewCell 或 UITableViewCell 中的内容进行交互 [重复]