22

私はUISegmentedControliPhoneアプリケーションにを使用するための「最良の」方法を見つけようとしています。私はここでstackoverflowに関するいくつかの投稿を読み、いくつかの人々のアイデアを見ましたが、これを行うための最良の方法を完全に整理することはできません。私が参照している投稿は次のとおりです。

UISegmentedControlからのビューの変更 および UISegmentedControlを使用してビューを切り替えるにはどうすればよいですか?

オプションは次のように思われます。

  • IBに各ビューを追加し、それらを互いに重ねてレイアウトしてから、表示/非表示にします
  • IBで各サブビューを個別に作成してから、メインビューにコンテナを作成して、必要なサブビューを入力します。
  • 非常に高いまたは非常に広いものを設定UIViewし、選択したセグメントに応じて左/右または上/下にアニメーション化します
  • サブビューを交換するためにを使用しUITabBarControllerてください-ばかげているようです
  • テーブルの場合は、テーブルをリロードして、cellForRowAtIndex選択したセグメントオプションに基づいてさまざまなデータソースまたはセクションからテーブルにデータを入力します(私のアプリの場合はそうではありません)

では、サブビュー/非テーブルアプローチに最適なアプローチはどれですか?実装するのが最も簡単なのはどれですか?アプローチのサンプルコードを教えていただけますか?

ありがとう!

4

3 に答える 3

19

私はiPadアプリケーションでもこの要件に出くわしました。

私が得た解決策は、ビューのスタイルごとに専用のビューコントローラーを作成して、それらのビューに関連する(つまり、各セグメントに関連する)ビジネスロジックを処理し、それに応じて「管理」コントローラーにサブビューとしてプログラムで追加/削除することでした。選択したセグメントインデックスが変更されます。

これを行うには、UISegmentedControlの変更を管理し、サブビューを追加/削除する追加のUIViewControllerサブクラスを作成する必要があります。

以下のコードはこれらすべてを実行し、いくつかの警告/追加機能も処理します。

  • viewWillAppear / viewWillDisappear / etcは、サブビューで自動的に呼び出されることはなく、「管理」コントローラーを介して通知する必要があります
  • viewWillAppear / viewWillDisappear / etcは、ナビゲーションコントローラー内にある場合、「管理」コントローラーでは呼び出されないため、ナビゲーションコントローラーのデリゲート
  • セグメントのサブビュー内からナビゲーションスタックにプッシュする場合、サブビューはナビゲーション階層の外部で作成されており、ナビゲーションコントローラーへの参照。
  • ナビゲーションコントローラーのシナリオで使用する場合、戻るボタンは自動的にセグメントの名前に設定されます。

インターフェース:

@interface SegmentManagingViewController : UIViewController <UINavigationControllerDelegate> {
    UISegmentedControl    * segmentedControl;
    UIViewController      * activeViewController;
    NSArray               * segmentedViewControllers;
}

@property (nonatomic, retain) IBOutlet UISegmentedControl * segmentedControl;
@property (nonatomic, retain) UIViewController            * activeViewController;
@property (nonatomic, retain) NSArray                     * segmentedViewControllers;

@end

実装:

@interface SegmentManagingViewController ()
- (void)didChangeSegmentControl:(UISegmentedControl *)control;
@end

@implementation SegmentManagingViewController

@synthesize segmentedControl, activeViewController, segmentedViewControllers;

- (void)viewDidLoad {
    [super viewDidLoad];

    UIViewController * controller1 = [[MyViewController1 alloc] initWithParentViewController:self];
    UIViewController * controller2 = [[MyViewController2 alloc] initWithParentViewController:self];
    UIViewController * controller3 = [[MyViewController3 alloc] initWithParentViewController:self];

    self.segmentedViewControllers = [NSArray arrayWithObjects:controller1, controller2, controller3, nil];
    [controller1 release];
    [controller2 release];
    [controller3 release];

    self.navigationItem.titleView = self.segmentedControl =
    [[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObjects:@"Seg 1", @"Seg 2", @"Seg 3", nil]];
    self.segmentedControl.selectedSegmentIndex = 0;
    self.segmentedControl.segmentedControlStyle = UISegmentedControlStyleBar;

    [self.segmentedControl addTarget:self action:@selector(didChangeSegmentControl:) forControlEvents:UIControlEventValueChanged];

    [self didChangeSegmentControl:self.segmentedControl]; // kick everything off
}

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    [self.activeViewController viewWillAppear:animated];
}

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    [self.activeViewController viewDidAppear:animated];
}

- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    [self.activeViewController viewWillDisappear:animated];
}

- (void)viewDidDisappear:(BOOL)animated {
    [super viewDidDisappear:animated];
    [self.activeViewController viewDidDisappear:animated];
}

#pragma mark -
#pragma mark UINavigationControllerDelegate control

// Required to ensure we call viewDidAppear/viewWillAppear on ourselves (and the active view controller)
// inside of a navigation stack, since viewDidAppear/willAppear insn't invoked automatically. Without this
// selected table views don't know when to de-highlight the selected row.

- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
    [viewController viewDidAppear:animated];
}

- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
    [viewController viewWillAppear:animated];
}

#pragma mark -
#pragma mark Segment control

- (void)didChangeSegmentControl:(UISegmentedControl *)control {
    if (self.activeViewController) {
        [self.activeViewController viewWillDisappear:NO];
        [self.activeViewController.view removeFromSuperview];
        [self.activeViewController viewDidDisappear:NO];
    }

    self.activeViewController = [self.segmentedViewControllers objectAtIndex:control.selectedSegmentIndex];

    [self.activeViewController viewWillAppear:NO];
    [self.view addSubview:self.activeViewController.view];
    [self.activeViewController viewDidAppear:NO];

    NSString * segmentTitle = [control titleForSegmentAtIndex:control.selectedSegmentIndex];
    self.navigationItem.backBarButtonItem  = [[UIBarButtonItem alloc] initWithTitle:segmentTitle style:UIBarButtonItemStylePlain target:nil action:nil];
}

#pragma mark -
#pragma mark Memory management

- (void)dealloc {
    self.segmentedControl = nil;
    self.segmentedViewControllers = nil;
    self.activeViewController = nil;
    [super dealloc];
}

@end

お役に立てれば。

于 2010-05-23T08:32:21.290 に答える
11

私はあなたが言及した2番目のオプション、IBでサブビューを作成し、それらをメインビューに交換したりメインビューから交換したりします。これは、サブクラス化されていないを使用する良い機会です。初期設定で、 (最初のパラメーターは個々のサブビューを含むNIBの名前であり、2番目のパラメーターは)をUIViewController使用してコントローラーを作成し、それをのサブビューとして追加します。必要に応じてメインビュー。これにより、メモリフットプリントを低く抑えることができます。メモリ警告を受け取ったときのデフォルトの動作は、スーパービューがない場合にビューを解放することです。ビュー階層から非表示のビューを削除する限り、コントローラーをメモリに保持でき、何も解放する必要はありません。-initWithNibName:bundle:nilviewUIViewController

(コメントに応じて編集:)

サブクラス化する必要はありませんがUIViewController、ビューごとに個別のXIBが必要です。また、IBの包含ビューに何も追加する必要はありません。

これらすべてを処理しているクラスのインターフェースにあるインスタンス変数:

 UIViewController *controllerOne;
 UIViewController *controllerTwo;

 UIViewController *currentController;

 IBOutlet UIView *theContainerView;

セットアップ(-applicationDidFinishLaunching:または何でも)

 controllerOne = [[UIViewController alloc] initWithNibName:@"MyFirstView" bundle:nil];
 controllerTwo = [[UIViewController alloc] initWithNibName:@"MySecondView" bundle:nil];

コントローラに切り替えるには:

 - (void)switchToController:(UIViewController *)newCtl
 {
      if(newCtl == currentController)
           return;
      if([currentController isViewLoaded])
           [currentController.view removeFromSuperview];

      if(newCtl != nil)
           [theContainerView addSubview:newCtl.view];

      currentController = newCtl;
 }

次に、たとえば、

 [self switchToController:controllerOne];
于 2010-01-22T15:46:01.400 に答える
3

この概念をさらに説明する優れたチュートリアルは次のとおりです。http://redartisan.com/2010/5/26/uisegmented-control-view-switching

それにgithubの場所: https ://github.com/crafterm/SegmentedControlExample.git

于 2012-02-12T23:38:04.990 に答える