【问题标题】:How do I use a UISegmentedControl to switch views?如何使用 UISegmentedControl 切换视图?
【发布时间】:2010-11-06 00:51:29
【问题描述】:

我试图弄清楚如何使用 UISegmentedControl 的不同状态来切换视图,类似于 Apple 在 App Store 中在“热门付费”和“热门免费”之间切换时的做法。

【问题讨论】:

    标签: ios objective-c iphone uisegmentedcontrol


    【解决方案1】:

    最简单的方法是拥有两个视图,您可以切换它们的可见性以指示选择了哪个视图。这是一些关于如何完成的示例代码,绝对不是处理视图的优化方式,只是为了演示如何使用 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];
      }
    }
    


    您当然可以进一步重构代码以隐藏/显示正确的视图。

    【讨论】:

    • '绝对不是处理视图的优化方式' - 为什么?
    • @AdamWaite 因为所有视图都必须永久存储在内存中。如果您的视图过于复杂和/或包含许多其他元素,则会影响整体性能。这段代码也可以重构。
    • @Stas 你说得对,最好在多个视图控制器之间拆分逻辑,每个控制器负责自己的动作和行为
    • 使用容器视图可能会导致导航栏出现问题。特别是当您使用半透明的时。根据我的经验,它不是一个值得推荐的解决方案
    【解决方案2】:

    在我的情况下,我的视图非常复杂,我不能只更改不同视图的隐藏属性,因为它会占用太多内存。

    我尝试了几种解决方案,但没有一个对我有用,或者执行不规律,特别是导航栏的 titleView 在推送/弹出视图时并不总是显示 segmentedControl。

    我发现这篇关于问题的博文解释了如何以正确的方式进行操作。似乎他在 WWDC'2010 的 Apple 工程师的帮助下想出了这个解决方案。

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

    此链接中的解决方案是迄今为止我发现的有关该问题的最佳解决方案。稍加调整后,底部的 tabBar 也能正常工作

    【讨论】:

    • 感谢您的精彩发现。对于这种方法而言,绝对是一个不错且优雅的解决方案。
    • 我试图通过底部的工具栏正常工作,但没有成功,stackoverflow.com/questions/4748120/…你能帮帮我吗?
    • 有没有办法在视图之间设置水平翻转动画。还是只能在没有动画的情况下工作?
    • 是的,这似乎是一个很好的解决方案,但我该如何调整它以与 tabBarController 一起工作,其中导航控制器已经在里面?
    • 幸运的是,Implementing a Container View Controller 完美运行!甚至 segues 也能按预期工作。
    【解决方案3】:

    或者,如果它是一个表格,您可以重新加载表格并在 cellForRowAtIndex 中,根据所选的段选项从不同的数据源填充表格。

    【讨论】:

      【解决方案4】:

      一个想法是让带有分段控件的视图有一个容器视图,您可以在其中填充不同的子视图(在切换分段时添加为容器视图的唯一子视图)。您甚至可以为这些子视图设置单独的视图控制器,但如果需要它们,您必须转发诸如“viewWillAppear”和“viewWillDisappear”之类的重要方法(并且必须告知它们所在的导航控制器)。

      一般来说效果很好,因为您可以在 IB 中使用容器布置主视图,而子视图将填充容器允许它们拥有的任何空间(确保您的自动调整大小掩码设置正确)。

      【讨论】:

        【解决方案5】:

        尝试使用SNFSegmentedViewController,这是一个开源组件,可以通过UITabBarController 之类的设置完全满足您的需求。

        【讨论】:

          【解决方案6】:

          根据@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
          

          【讨论】:

            【解决方案7】:

            中分配.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];
             }
            } 
            

            【讨论】:

              【解决方案8】:

              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 点击事件

              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/

              【讨论】:

              • 虽然此链接可能会回答问题,但最好在此处包含答案的基本部分并提供链接以供参考。如果链接页面发生更改,仅链接答案可能会失效。 - From Review
              • @BasilePerrenoud 刚刚用解决方案的关键和最重要的部分更新了答案。
              【解决方案9】:

              快速的 Swift 版本:

              @IBAction func segmentControlValueChanged(_ sender: UISegmentedControl) {
              
                  if segmentControl.selectedSegmentIndex == 0 {
              
                      // do something
                  } else {
              
                      // do something else
                  }
              }
              

              【讨论】:

                猜你喜欢
                • 2015-09-23
                • 2011-07-13
                • 2012-05-15
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多