0

再利用可能なボタンバー? ここまで来ましたが、今は「戻るボタン」の要件に問題があります。

次のようなレイアウト ソリューションが必要です。

  • iOS 5.0 および 6.0 で動作します
  • 上部にいくつかのボタンがあるカスタム ビューがあります。このビューは、シーンごとに Interface Builder でボタンを手動で複製するのではなく、すべての画面 (シーン) で再利用できる必要があります。
  • その上部のカスタム ビューにカスタムの「戻る」ボタンがあります。実装しなければならないデザインでは、デフォルトのナビゲーション バーをそのまま使用することはできません
  • UINavigationController とうまく連携します。ユーザーが「戻る」ボタンをタップすると、メイン ビュー コントローラー (ボタン バーを含む) はそのまま残りますが、実際のシーン コンテンツを表す子ビュー コントローラーは前のシーンに戻る必要があります。

現在の問題は、「戻る」ボタンで子コントローラーが変更されないことです。親コントローラーが変更され、ボタン バーのあるシーンの前のシーンに戻ります。私はこれをいくつかの異なる方法で試しました。自分のやり方が正しくないのか、それともできないのか、よくわかりません。

1つの可能性は、独自の「戻る」機能を実装し、子View Controllerのスタックを保持し、ユーザーが「戻る」をタップしたときにそれらを手動で変更することです。ただし、これは扱いにくく、UINavigationController を使用する場合に比べて設計が不十分です。

おそらく、私はこれで間違った方向に進んでいます。Interface Builder のすべてのシーンでボタン バーを複製することはできませんが、おそらくプログラムで作成する必要があります。そうすれば、すべてのシーンからそのコードを簡単に呼び出すことができます。次に、「通常の」ビュー コントローラーを用意し、UINavigationController を使用する方が簡単です。しかし、そのルートに行き、これまで持っていたものを完全に破棄する前に、別の方法があるかどうかを確認したかった.


私のソリューションの一部の概要は次のとおりです。

ButtonBarController を作成し、必要なボタンの UIView とコンテンツ ペインの UIView を使用して Storyboard をレイアウトしました。また、戻るボタンの上にアプリのロゴが付いたボタン (アプリのメイン画面に移動するため) を重ねました。

次に、他の各画面用のコントローラーを作成しました。これらのサブスクリーン/子ビュー コントローラーでは、最初にコンテンツ ペインに収まるように適切なサイズで UIView を追加し、次に必要な他のすべてのコントロールを追加します。これらの子ビュー コントローラーはすべて、ボタン バー コントローラーへの参照の取得や、3.5 インチ画面と 4 インチ画面のビューのサイズ変更を支援するコードなど、いくつかの一般的なタスクを処理する別のコントローラーから継承しました。

changeToControllerWithIndex メソッドを作成しました。アプリがロードされたとき、ユーザーがメイン ボタン バーのボタンの 1 つをクリックしてシーンを変更したとき、または別のシーンの変更を必要とするシーンで何かが発生したときに、これを呼び出します。このメソッドをオーバーロードして、2 つの追加情報を提供します。子ビュー コントローラーが必要とする追加情報を 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];
        }
    }   
}

次に、個々のView Controllerを設定するためのオーバーロードされたメソッドがあります...一部のものは、他のものよりも少し準備が必要です。

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

「戻る」ナビゲーションを管理するのが難しいと言いました。上記のコードは、ナビゲーション コントローラーが適切な「戻る」履歴を維持することを保証し、ボタン バー ボタンの 1 つを使用して画面を変更するたびに新たに開始します。子コントローラー内のボタンを使用してシーンからシーンに移動する場合、次のように戻ることができます。

- (IBAction)backButtonPressed:(id)sender {
    [childNavigationController popViewControllerAnimated:YES];
    if ([[childNavigationController viewControllers] count] <= 1) {
        //Root view
        [homeButton setHidden:NO];
        [backButton setHidden:YES];
    }
}
4

1 に答える 1

1

少なくとも 1 つのカスタム コンテナー ビュー コントローラー (ルート ビュー コントローラー) を実装する必要があると思います。これは、カスタム ボタン バーをホストするものです。ボタン バーの下に、他の VC を管理する UINavigationController を追加します。手始めにこれを見てください:

@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];
}
于 2012-10-24T20:52:35.460 に答える