问题描述
我已经阅读了有关此文档和Apple文档的许多其他主题,但是还没有找到针对我特定问题的解决方案.
I have read many other threads on this and the Apple docs, but haven't found a solution yet for my particular problem.
我的应用程序将UITabBarController
用作rootViewController
,并且在其中一个选项卡中,我在navigationBar
中具有UISegmentedControl
,可在三个子UITableViewController
之间进行切换.
My app uses a UITabBarController
as the rootViewController
, and in one of the tabs I have a UISegmentedControl
in the navigationBar
to switch between three child UITableViewController
s.
(在实际应用中,两个childVC是自定义的UIViewController
,我只是在示例应用中使用了三个UITableViewController
).
(In the real app two of the childVCs are a custom UIViewController
, I'm just using three UITableViewController
s for the sample app).
segmentedControl设置和切换都可以正常工作.出问题的是,只有第一个UITableViewController
可以正确显示.对于第二个和第三个,第一个单元格的一部分隐藏在navigationBar
下.当我单击所有三个按钮时,第一个仍然可以.
The segmentedControl setup and the switching all works fine. The thing that goes wrong is that only the first UITableViewController
is shown correctly. For the second and third one, part of the first cell is hidden under the navigationBar
. When I click through all three, the first one is still ok.
我制作了一个小样的应用程序来演示正在发生的事情,并使用非常明亮的颜色进行演示: https://www.dropbox.com/s/7pfutvn5jba6rva/SegmentedControlVC.zip?dl=0
I have made a little sample app to show what's going on, using very bright colors for demonstration purposes: https://www.dropbox.com/s/7pfutvn5jba6rva/SegmentedControlVC.zip?dl=0
这里还有一些代码(我没有使用情节提要):
Here is also some code (I'm not using storyboards):
// AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
FirstViewController *fvc = [[FirstViewController alloc] init];
UINavigationController *firstNavigationController = [[UINavigationController alloc] initWithRootViewController: fvc];
SecondViewController *svc = [[SecondViewController alloc] init];
UINavigationController *secondNavigationController = [[UINavigationController alloc] initWithRootViewController: svc];
// Initialize tab bar controller, add tabs controllers
UITabBarController *tabBarController = [[UITabBarController alloc] init];
tabBarController.viewControllers = @[firstNavigationController, secondNavigationController];
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.rootViewController = tabBarController;
[self.window makeKeyAndVisible];
return YES;
}
// FirstViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.title = @"One";
self.view.backgroundColor = [UIColor orangeColor];
UITableViewController *vc1 = [[UITableViewController alloc] init];
UITableViewController *vc2 = [[UITableViewController alloc] init];
UITableViewController *vc3 = [[UITableViewController alloc] init];
vc1.view.backgroundColor = [UIColor redColor];
vc2.view.backgroundColor = [UIColor blueColor];
vc3.view.backgroundColor = [UIColor greenColor];
self.viewControllers = @[vc1, vc2, vc3];
self.segmentTitles = @[@"Red", @"Blue", @"Green"];
self.segmentedControl = [[UISegmentedControl alloc] initWithItems: self.segmentTitles];
[self.segmentedControl addTarget: self
action: @selector(segmentClicked:)
forControlEvents: UIControlEventValueChanged];
self.navigationItem.titleView = self.segmentedControl;
self.segmentedControl.selectedSegmentIndex = 0;
// set the first child vc:
UIViewController *vc = self.viewControllers[0];
[self addChildViewController: vc];
vc.view.frame = self.view.bounds;
[self.view addSubview: vc.view];
self.currentVC = vc;
}
- (void)segmentClicked:(id)sender
{
if (sender == self.segmentedControl)
{
NSUInteger index = self.segmentedControl.selectedSegmentIndex;
[self loadViewController: self.viewControllers[index]];
}
}
- (void)loadViewController:(UIViewController *)vc
{
[self addChildViewController: vc];
[self transitionFromViewController: self.currentVC
toViewController: vc
duration: 1.0
options: UIViewAnimationOptionTransitionFlipFromBottom
animations: ^{
[self.currentVC.view removeFromSuperview];
vc.view.frame = self.view.bounds;
[self.view addSubview: vc.view];
} completion: ^(BOOL finished) {
[vc didMoveToParentViewController: self];
[self.currentVC removeFromParentViewController];
self.currentVC = vc;
}
];
}
显然,我的问题是,为什么会发生这种情况,我该怎么做才能解决它?
So obviously my question is, why does this happen, and what can I do to fix it?
添加屏幕截图.
基于以下答案,我将动画块中的代码更改为:
Based on the answer below I changed the code in the animation block to:
[self.currentVC.view removeFromSuperview];
if ([vc.view isKindOfClass: [UIScrollView class]])
{
UIEdgeInsets edgeInsets = UIEdgeInsetsMake(self.topLayoutGuide.length, 0, self.bottomLayoutGuide.length, 0);
[UIView performWithoutAnimation: ^{
vc.view.frame = self.view.bounds;
((UIScrollView *)vc.view).contentInset = edgeInsets;
((UIScrollView *)vc.view).scrollIndicatorInsets = edgeInsets;
}];
}
else
{
vc.view.frame = self.view.bounds;
}
[self.view addSubview: vc.view];
现在可以使用了.我还将尝试使用自定义UIViewController
Now it works. I'm going to try this with a custom UIViewController
as well.
推荐答案
问题是您没有为每个表视图设置正确的内容插图.系统会尝试为您执行此操作,但我想您的设置太复杂了,它仅对viewDidLoad
中加载的第一个表视图执行此操作.在您的loadViewController:
方法中,替换当前显示的视图时,请确保将contentInset
和scrollIndicatorInsets
都设置为上一个视图的值.我认为,如果您旋转到横向,该系统将在以后设置正确的插图.试试吧.如果没有,您将需要在viewDidLayoutSubviews
中自行完成.
The issue is that you do not set the correct content inset to each table view. The system attempts to do it for you, but I guess your setup is too complex for it, and it only does it for the first tableview that is loaded in viewDidLoad
. In your loadViewController:
method, when replacing the currently displayed view, make sure to set both the contentInset
and scrollIndicatorInsets
to the values of the previous view. I think the system will manage to set the correct insets later, in case you rotate to landscape. Try it. If it doesn't, you will need to do it on your own in viewDidLayoutSubviews
.
这篇关于带有UISegmentedControl的UINavigationBar部分覆盖了childViews的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!