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


82

私は、UISegmentedControlのさまざまな状態を使用してビューを切り替える方法を理解しようとしています。これは、Appleが「TopPaid」と「TopFree」の間を切り替えたときにAppStoreで行う方法と似ています。

回答:


113

最も簡単なアプローチは、表示を切り替えてどちらのビューが選択されているかを示すことができる2つのビューを用意することです。これは、その実行方法に関するサンプルコードです。ビューを処理するための最適化された方法ではありませんが、UISegmentControlを使用して表示ビューを切り替える方法を示しています。

- (IBAction)segmentSwitch:(id)sender {
  UISegmentedControl *segmentedControl = (UISegmentedControl *) sender;
  NSInteger selectedSegment = segmentedControl.selectedSegmentIndex;

  if (selectedSegment == 0) {
    //toggle the correct view to be visible
    [firstView setHidden:NO];
    [secondView setHidden:YES];
  }
  else{
    //toggle the correct view to be visible
    [firstView setHidden:YES];
    [secondView setHidden:NO];
  }
}


もちろん、コードをさらにリファクタリングして、正しいビューを表示/非表示にすることもできます。


4
「ビューを処理するための最適化された方法ではありません」-なぜですか?
Adam Waite

3
@AdamWaiteは、すべてのビューを永続的にメモリに保存する必要があるためです。ビューが複雑すぎたり、他の多くの要素が含まれている場合は、全体的なパフォーマンスに影響します。そのコードもリファクタリングできます。
Stas 2013

@Stasそうです、ロジックを複数のView Controllerに分割し、それぞれが独自のアクションと動作を担当することをお
勧め

コンテナビューを使用すると、ナビゲーションバーで問題が発生する可能性があります。特に半透明のものを使用している場合。私の経験から、それは推奨される解決策ではありません
DamirDiz 2015年

45

私の場合、ビューは非常に複雑で、メモリを大量に消費するため、さまざまなビューの非表示プロパティを変更することはできません。

私はいくつかの解決策を試しましたが、どれもうまくいかなかった、または不規則に実行されました。特に、ビューをプッシュ/ポップしたときに、navBarのtitleViewが常にsegmentedControlを表示するとは限りません。

適切な方法でそれを行う方法を説明する問題についてのこのブログ投稿を見つけました。彼はこの解決策を考え出すためにWWDC'2010でアップルのエンジニアの助けを借りたようです。

http://redartisan.com/2010/6/27/uisegmented-control-view-switching-revisited

このリンクの解決策は、これまでの問題について私が見つけた最良の解決策を伝えています。少し調整するだけで、下部のタブバーでも問題なく機能しました


素晴らしい発見をありがとう。この方法論のための間違いなく素晴らしくてエレガントな解決策。
紫雲

1
下部のツールバーを使用してこれを正しく機能させようとしましたが、成功しませんでした。stackoverflow.com/ questions / 4748120 / …手伝ってくれませんか。
エリック

ビューの間に水平フリップアニメーションを配置する方法はありますか?それとも、アニメーションなしでのみ機能しますか?
動脈瘤

はい、これは素晴らしい解決策のようですが、navigationControllersがすでに含まれているtabBarControllerで機能するようにこれを調整するにはどうすればよいですか?
ウラジミールスタジロフ2012年

2
幸い、Container ViewControllerの実装は問題なく機能しました。セグエでさえ期待通りに機能します。
jweyrich 2012

17

または、テーブルの場合は、テーブルをリロードし、cellForRowAtIndexで、選択したセグメントオプションに基づいてさまざまなデータソースからテーブルにデータを入力できます。


7

1つのアイデアは、セグメント化されたコントロールを含むビューに、さまざまなサブビューで埋めるコンテナービューを持たせることです(セグメントが切り替えられたときに、コンテナービューの唯一のサブビューとして追加します)。これらのサブビューに個別のビューコントローラーを設定することもできますが、必要に応じて「viewWillAppear」や「viewWillDisappear」などの重要なメソッドを転送する必要があります(また、どのナビゲーションコントローラーの下にあるかを通知する必要があります)。

IBでコンテナを使用してメインビューをレイアウトでき、サブビューはコンテナで許可されているスペースをすべて埋めることができるため、通常は非常にうまく機能します(自動サイズ変更マスクが適切に設定されていることを確認してください)。



2

@Ronnie Liewの回答から、私はこれを作成します。

//
//  ViewController.m
//  ResearchSegmentedView
//
//  Created by Ta Quoc Viet on 5/1/14.
//  Copyright (c) 2014 Ta Quoc Viet. All rights reserved.
//
#define SIZE_OF_SEGMENT 56
#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController
@synthesize theSegmentControl;
UIView *firstView;
UIView *secondView;
CGRect leftRect;
CGRect centerRect;
CGRect rightRect;
- (void)viewDidLoad
{
    [super viewDidLoad];
    leftRect = CGRectMake(-self.view.frame.size.width, SIZE_OF_SEGMENT, self.view.frame.size.width, self.view.frame.size.height-SIZE_OF_SEGMENT);
    centerRect = CGRectMake(0, SIZE_OF_SEGMENT, self.view.frame.size.width, self.view.frame.size.height-SIZE_OF_SEGMENT);
    rightRect = CGRectMake(self.view.frame.size.width, SIZE_OF_SEGMENT, self.view.frame.size.width, self.view.frame.size.height-SIZE_OF_SEGMENT);

    firstView = [[UIView alloc] initWithFrame:centerRect];
    [firstView setBackgroundColor:[UIColor orangeColor]];
    secondView = [[UIView alloc] initWithFrame:rightRect];
    [secondView setBackgroundColor:[UIColor greenColor]];
    [self.view addSubview:firstView];
    [self.view addSubview:secondView];

}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (IBAction)segmentSwitch:(UISegmentedControl*)sender {
    NSInteger selectedSegment = sender.selectedSegmentIndex;
    [UIView beginAnimations:nil context:nil];
    [UIView setAnimationDuration:0.2];
    if (selectedSegment == 0) {
        //toggle the correct view to be visible
        firstView.frame = centerRect;
        secondView.frame = rightRect;
    }
    else{
        //toggle the correct view to be visible
        firstView.frame = leftRect;
        secondView.frame = centerRect;
    }
    [UIView commitAnimations];
}
@end

2

に.Hを割り当てる

 UISegmentedControl *lblSegChange;

- (IBAction)segValChange:(UISegmentedControl *) sender

.Mを宣言する

- (IBAction)segValChange:(UISegmentedControl *) sender
{

 if(sender.selectedSegmentIndex==0)
 {
  viewcontroller1 *View=[[viewcontroller alloc]init];
  [self.navigationController pushViewController:view animated:YES];
 }
 else 
 {
  viewcontroller2 *View2=[[viewcontroller2 alloc]init];
  [self.navigationController pushViewController:view2 animated:YES];
 }
} 

2

Swiftバージョン:

親ViewControllerは、各子ViewControllerのビューのサイズと位置を設定する責任があります。子ViewControllerのビューは、親ViewControllerのビュー階層の一部になります。

怠惰なプロパティを定義します。

private lazy var summaryViewController: SummaryViewController = {
   // Load Storyboard
   let storyboard = UIStoryboard(name: "Main", bundle: Bundle.main)

   // Instantiate View Controller
   var viewController = storyboard.instantiateViewController(withIdentifier: "SummaryViewController") as! SummaryViewController

   // Add View Controller as Child View Controller
   self.add(asChildViewController: viewController)

   return viewController
}()

private lazy var sessionsViewController: SessionsViewController = {
    // Load Storyboard
    let storyboard = UIStoryboard(name: "Main", bundle: Bundle.main)

    // Instantiate View Controller
    var viewController = storyboard.instantiateViewController(withIdentifier: "SessionsViewController") as! SessionsViewController

    // Add View Controller as Child View Controller
    self.add(asChildViewController: viewController)

    return viewController
}()

子ビューコントローラーの表示/非表示:

private func add(asChildViewController viewController: UIViewController) {
    // Add Child View Controller
    addChildViewController(viewController)

    // Add Child View as Subview
    view.addSubview(viewController.view)

    // Configure Child View
    viewController.view.frame = view.bounds
    viewController.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]

    // Notify Child View Controller
    viewController.didMove(toParentViewController: self)
}

private func remove(asChildViewController viewController: UIViewController) {
    // Notify Child View Controller
    viewController.willMove(toParentViewController: nil)

    // Remove Child View From Superview
    viewController.view.removeFromSuperview()

    // Notify Child View Controller
    viewController.removeFromParentViewController()
}

SegmentedControltapEventを管理する

private func updateView() {
    if segmentedControl.selectedSegmentIndex == 0 {
        remove(asChildViewController: sessionsViewController)
        add(asChildViewController: summaryViewController)
    } else {
        remove(asChildViewController: summaryViewController)
        add(asChildViewController: sessionsViewController)
    }
}

そしてもちろん、子ViewControllerクラス内で使用することもできます。

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    print("Summary View Controller Will Appear")
}

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    print("Summary View Controller Will Disappear")
}

参照:https//cocoacasts.com/managing-view-controllers-with-container-view-controllers/


1
このリンクは質問に答えることができますが、ここに答えの本質的な部分を含めて、参照用のリンクを提供することをお勧めします。リンクされたページが変更されると、リンクのみの回答が無効になる可能性があります。-レビューから
Basile Perrenoud

2
@BasilePerrenoudソリューションの重要かつ最も重要な部分で回答を更新しました。
SlavisaPetkovic 2018年

1

クイックSwiftバージョン:

@IBAction func segmentControlValueChanged(_ sender: UISegmentedControl) {

    if segmentControl.selectedSegmentIndex == 0 {

        // do something
    } else {

        // do something else
    }
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.