[英]Custom button bar with custom back navigation button
可重复使用的按钮栏? 让我参与其中,但是现在我遇到了“后退按钮”要求的麻烦。
我需要一个布局解决方案:
当前的问题是“后退”按钮不会更改子控制器,而是会更改父控制器,并返回到带有按钮栏的场景之前的上一个场景。 我已经尝试了几种不同的方法。 我不确定是否做得不正确,或者无法完成。
一种可能是实现我自己的“后退”功能,保留一堆子视图控制器,并在用户点击“后退”时手动更改它们。 但是,这很尴尬,与使用UINavigationController相比,设计较差。
也许我在这方面走错了路。 我不能接受在Interface Builder中的每个场景中复制按钮栏……但是也许我应该以编程方式创建它,然后我可以轻松地从每个场景中调用该代码。 然后,我将拥有“常规”视图控制器,并且使用UINavigationController会更容易。 但是在走那条路线并完全废弃我到目前为止的东西之前,我想看看是否还有另一种方法。
以下是我的解决方案的某些部分的概述:
我创建了一个ButtonBarController,将Storyboard布局为带有所需按钮的UIView和内容窗格的UIView。 我还在后退按钮上方放置了一个带有应用程序徽标的按钮(转到应用程序的主屏幕)。
然后,我为其他每个屏幕创建了一个控制器。 在那些子屏幕/子视图控制器中,我将首先以合适的大小添加一个UIView以适合我的内容窗格,然后再添加我想要的所有其他控件。 我让所有这些子视图控制器都继承自另一个控制器,该控制器负责一些常见的任务-例如获取对按钮栏控制器的引用,并提供代码来帮助调整3.5“和4”屏幕的视图大小。
我创建了一个changeToControllerWithIndex方法; 我在应用程序加载时,用户单击主按钮栏上的按钮之一来更改场景时,或在需要更改另一场景的场景中发生任何事情时调用此方法。 我重载了此方法,以提供另外两个信息:向NSDictionary提供子视图控制器所需的任何其他信息,并告诉它这是顶层场景还是我们需要后退按钮。
(注意:在Identity Inspector中为那些子视图控制器设置Storyboard ID很重要。我一直不小心在Attribute Inspector中设置Title。)
- (void)changeToControllerWithIndex:(NSInteger)index {
[self changeToControllerWithIndex:index withPayload:nil isRootView:YES];
}
// This is the method that will change the active view controller and the view that is shown
- (void)changeToControllerWithIndex:(NSInteger)index withPayload:(id)payload isRootView:(BOOL)isRootView
{
if (YES) {
self.index = index;
// The code below will properly remove the the child view controller that is
// currently being shown to the user and insert the new child view controller.
UIViewController *vc = [self setupViewControllerForIndex:index withPayload:payload];
if (isRootView) {
NSLog(@"putting navigation controller in");
childNavigationController = [[UINavigationController alloc] initWithRootViewController:vc];
[childNavigationController setNavigationBarHidden:YES];
[self addChildViewController:childNavigationController];
[childNavigationController didMoveToParentViewController:self];
if (self.currentViewController){
[self.currentViewController willMoveToParentViewController:nil];
[self transitionFromViewController:self.currentViewController toViewController:childNavigationController duration:0 options:UIViewAnimationOptionTransitionNone animations:^{
[self.currentViewController.view removeFromSuperview];
} completion:^(BOOL finished) {
[self.currentViewController removeFromParentViewController];
self.currentViewController = childNavigationController;
}];
} else {
[self.currentView addSubview:childNavigationController.view];
self.currentViewController = childNavigationController;
}
[self.currentView addSubview:childNavigationController.view];
//We are at the root of the navigation path, so no back button for us
[homeButton setHidden:NO];
[backButton setHidden:YES];
} else {
//Not a root view -- we're in navigation and want a back button
[childNavigationController pushViewController:vc animated:NO];
[homeButton setHidden:YES];
[backButton setHidden:NO];
}
}
}
然后,我有一个重载的方法来设置每个单独的视图控制器……有些需要比另一些更多的准备。
- (UIViewController *)setupViewControllerForIndex:(NSInteger)index {
return [self setupViewControllerForIndex:index withPayload:nil];
}
// This is where you instantiate each child controller and setup anything you need on them, like delegates and public properties.
- (UIViewController *)setupViewControllerForIndex:(NSInteger)index withPayload:(id)payload {
UIViewController *vc = nil;
if (index == CONTROLLER_HOME){
vc = [self.storyboard instantiateViewControllerWithIdentifier:@"Home"];
} else if (index == CONTROLLER_CATEGORIES){
SAVECategoryViewController *child = [self.storyboard instantiateViewControllerWithIdentifier:@"Categories"];
if (payload) {
child.currentCategory = [(NSNumber *) [(NSDictionary *)payload objectForKey:ATTRIBUTE_CAT_ID] integerValue];
} else {
child.currentCategory = CATEGORY_ALL;
}
vc = child;
} //etc for all the other controllers...
payload = nil;
return vc;
}
我提到了管理“后退”导航的困难。 上面的代码可确保导航控制器保持适当的“后退”历史记录,无论何时我们使用按钮栏按钮之一来更改屏幕,都将重新开始。 当我们确实使用子控制器内的按钮在场景之间导航时,可以通过以下方法返回:
- (IBAction)backButtonPressed:(id)sender {
[childNavigationController popViewControllerAnimated:YES];
if ([[childNavigationController viewControllers] count] <= 1) {
//Root view
[homeButton setHidden:NO];
[backButton setHidden:YES];
}
}
我认为您需要实现至少一个自定义容器视图控制器-根视图控制器。 那将是托管自定义按钮栏的那个。 在按钮栏下方,您将添加一个UINavigationController来管理其他VC。 首先看一下:
@implementation RootVC
//...
- (void)viewDidLoad
{
self.navVC = [[UINavigationController alloc] initWithRootViewController:someOtherVC];
self.navVC.navigationBarHidden = YES;
self.navVC.view.frame = ...;
[self addChildViewController:self.navVC];
[self.view addSubview:self.navVC.view];
[self.navVC didMoveToParentViewController:self];
}
- (void)backButtonTouched:(UIButton *)button
{
[self.navVC popViewControllerAnimated:YES];
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.