如何使用UISegmentedControl切换视图?


82

我试图弄清楚如何使用UISegmentedControl的不同状态来切换视图,类似于Apple在“最高付费”和“最高免费”之间切换时在App Store中进行操作的方式。

Answers:


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
“绝对不是一种优化的视图处理方式”-为什么?
亚当·怀特

3
@AdamWaite,因为所有视图都必须永久存储在内存中。如果您的视图过于复杂和/或包含许多其他元素,则会影响整体性能。那段代码也可以重构。
2013年

@Stas您是对的,最好在多个视图控制器之间划分逻辑,每个视图控制器负责自己的行为和行为
tf.alves 2015年

使用容器视图可能会导致导航栏出现问题。特别是在使用半透明的时。根据我的经验,这不是一个
值得

45

就我而言,我的视图非常复杂,我不能仅更改其他视图的hidden属性,因为它会占用太多内存。

我已经尝试了几种解决方案,但没有一种对我有用,或者运行不正常,特别是在导航/弹出视图时,导航栏的titleView并不总是显示segmentedControl。

我找到了有关此问题的博客文章,该文章解释了如何以正确的方式进行操作。似乎他在WWDC'2010的苹果工程师的帮助下提出了该解决方案。

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

该链接中的解决方案是迄今为止我找到的关于该问题的最佳解决方案。稍作调整,底部的tabBar也可以正常工作


谢谢你的伟大发现。绝对是此方法的一种不错且优雅的解决方案。
Shiun

1
我试图通过底部的工具栏使该工具正常工作,但没有成功,stackoverflow.com / questions / 4748120 /…您能帮帮我吗?
Erik

有没有一种方法可以在视图之间使用水平翻转动画。还是只能在没有动画的情况下使用?
aneuryzm 2011年

是的,这似乎是一个不错的解决方案,但是如何将其调整为与内置了NavigationControllers的tabBarController一起使用?
弗拉基米尔·斯塔吉洛夫

2
幸运的是,实现Container View Controller可以完美工作!甚至segue都按预期工作。
jweyrich 2012年

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

迅捷版:

父视图控制器负责设置每个子视图控制器的视图的大小和位置。子视图控制器的视图成为父视图控制器的视图层次结构的一部分。

定义惰性属性:

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
虽然此链接可以回答问题,但最好在此处包括答案的基本部分,并提供链接以供参考。如果链接的页面发生更改,仅链接的答案可能会失效。-评分
巴西莱Perrenoud

2
@BasilePerrenoud刚刚使用解决方案的关键和最重要部分更新了答案。
SlavisaPetkovic '18

1

快速的Swift版本:

@IBAction func segmentControlValueChanged(_ sender: UISegmentedControl) {

    if segmentControl.selectedSegmentIndex == 0 {

        // do something
    } else {

        // do something else
    }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.