UISegmentedControl을 사용하여 뷰를 전환하는 방법은 무엇입니까?


82

저는 UISegmentedControl의 다양한 상태를 사용하여 뷰를 전환하는 방법을 알아 내려고합니다. Apple이 'Top Paid'와 'Top Free'사이를 전환 할 때 App Store에서 수행하는 방식과 유사합니다.

답변:


113

가장 간단한 방법은 어떤보기가 선택되었는지 표시하도록 가시성을 전환 할 수있는 두 개의보기를 갖는 것입니다. 다음은이를 수행 할 수있는 방법에 대한 몇 가지 샘플 코드입니다. 확실히 뷰를 처리하는 최적화 된 방법은 아니지만 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

자네 말이 맞아 @Stas, 그것은 그 자신의 행동과 행동에 대한 각각의 책임 여러 뷰 컨트롤러 사이의 논리 분할하는 것이 좋습니다
tf.alves

컨테이너보기를 사용하면 탐색 모음에 문제가 발생할 수 있습니다. 특히 반투명 한 것을 사용할 때. 내 경험에서 자사가 아닌 추천 솔루션
DamirDiz

45

제 경우에는 뷰가 매우 복잡하고 너무 많은 메모리를 차지하기 때문에 다른 뷰의 숨겨진 속성을 변경할 수 없습니다.

몇 가지 솔루션을 시도했지만 그중 일부는 나를 위해 일했거나 특히 navBar의 titleView를 사용하여 뷰를 밀거나 터뜨릴 때 항상 segmentedControl을 표시하지 않는 경우에 잘못 수행했습니다.

적절한 방법으로 수행하는 방법을 설명하는 문제에 대한이 블로그 게시물을 찾았습니다. 그는 WWDC'2010에서 Apple 엔지니어의 도움을 받아이 솔루션을 고안 한 것 같습니다.

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

이 링크의 해결책은 지금까지이 문제에 대해 찾은 최상의 솔루션입니다. 약간의 조정으로 하단의 tabBar에서도 잘 작동했습니다.


훌륭한 발견에 감사드립니다. 이 방법론을위한 훌륭하고 우아한 솔루션입니다.
Shiun 2010

1
성공하지 못한 상태에서 하단의 도구 모음을 사용하여 제대로 작동하도록 시도했습니다. stackoverflow.com/questions/4748120/… 도와주세요.
에릭

뷰 사이에 수평 플립 애니메이션을 만드는 방법이 있습니까? 아니면 애니메이션없이 만 작동합니까?
aneuryzm

예, 이것은 훌륭한 솔루션 인 것 같지만 이미 navigationController가있는 tabBarController와 함께 작동하도록 어떻게 조정합니까?
Vladimir Stazhilov 2012 년

2
다행히도 Container View Controller 구현 은 완벽하게 작동했습니다! segues도 예상대로 작동합니다.
jweyrich

17

또는 테이블 인 경우 테이블을 다시로드하고 cellForRowAtIndex에서 선택한 세그먼트 옵션에 따라 다른 데이터 소스에서 테이블을 채울 수 있습니다.


7

한 가지 아이디어는 세그먼트 화 된 컨트롤이있는 뷰에 다른 하위 뷰로 채우는 컨테이너 뷰를 갖도록하는 것입니다 (세그먼트가 토글 될 때 컨테이너 뷰의 단독 하위 뷰로 추가). 필요한 경우 "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 버전 :

부모 뷰 컨트롤러는 각 자식 뷰 컨트롤러의 뷰 크기와 위치를 설정합니다. 자식 뷰 컨트롤러의 뷰는 부모 뷰 컨트롤러의 뷰 계층 구조의 일부가됩니다.

지연 속성 정의 :

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

SegmentedControl tapEvent 관리

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

물론 자식 뷰 컨트롤러 클래스 내에서 사용할 수 있습니다.

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

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.