在iOS 5中使用UISegmentedControl切换视图控制器

问题描述 投票:37回答:6

我正在尝试一些非常简单的事情,但不知怎的,我无法让它发挥作用。我尝试做的就是使用UISegmentedControl在2个视图控制器之间切换,例如你可以在Highlights选项卡的App Store应用程序中看到它。

我正在使用iOS5和Storyboard。

这是我的Storyboad阵容:

所以我有一个根视图控制器和两个UITableViews - 这2个我想切换的TableViews。

这是实现文件的样子

#import "SegmentedLocationViewController.h"
#import "PastEventsLocationViewController.h"
#import "FutureEventsLocationViewController.h"

@interface SegmentedLocationViewController()
@property (weak, nonatomic) IBOutlet UISegmentedControl *segmentedControl;
@property (strong, nonatomic) NSArray *viewControllers;
@end


@implementation SegmentedLocationViewController

@synthesize segmentedControl = _segmentedControl;
@synthesize viewControllers = _viewControllers;

- (IBAction)indexDidChangeForSegmentedControl:(UISegmentedControl*)segmentedControl
{
    NSLog(@"index: %d", segmentedControl.selectedSegmentIndex);
}

- (void)setupViewControllers
{
    PastEventsLocationViewController *pastEventsLocationViewController = [[PastEventsLocationViewController alloc] initWithStyle:UITableViewStylePlain];
    FutureEventsLocationViewController *futureEventsLocationViewController = [[FutureEventsLocationViewController alloc] initWithStyle:UITableViewStylePlain];

    self.viewControllers = [NSArray arrayWithObjects:pastEventsLocationViewController, futureEventsLocationViewController, nil];
}

- (void)setupUI
{
    [self.segmentedControl addTarget:self action:@selector(indexDidChangeForSegmentedControl:) forControlEvents:UIControlEventValueChanged];
}

// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad
{
    [super viewDidLoad];
    [self setupViewControllers];
    [self setupUI];
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return YES;
}

@end

我可以触发switch事件并可以记录当前选择的索引。但我不知道从哪里开始。

也许有人可以将我的注意力转向某个方向......?

ios uiviewcontroller uikit uisegmentedcontrol
6个回答
82
投票

此代码非常适合您的目的,我将其用于我的一个新应用程序。 它使用新的UIViewController包含API,允许你自己的UIViewControllers中的UIViewControllers,而无需手动转发像viewDidAppear:这样的东西的麻烦

- (void)viewDidLoad {
    [super viewDidLoad];
    // add viewController so you can switch them later. 
    UIViewController *vc = [self viewControllerForSegmentIndex:self.typeSegmentedControl.selectedSegmentIndex];
    [self addChildViewController:vc];
    vc.view.frame = self.contentView.bounds;
    [self.contentView addSubview:vc.view];
    self.currentViewController = vc;
}
- (IBAction)segmentChanged:(UISegmentedControl *)sender {
    UIViewController *vc = [self viewControllerForSegmentIndex:sender.selectedSegmentIndex];
    [self addChildViewController:vc];
    [self transitionFromViewController:self.currentViewController toViewController:vc duration:0.5 options:UIViewAnimationOptionTransitionFlipFromBottom animations:^{
        [self.currentViewController.view removeFromSuperview];
        vc.view.frame = self.contentView.bounds;
        [self.contentView addSubview:vc.view];
    } completion:^(BOOL finished) {
        [vc didMoveToParentViewController:self];
        [self.currentViewController removeFromParentViewController];
        self.currentViewController = vc;
    }];
    self.navigationItem.title = vc.title;
}

- (UIViewController *)viewControllerForSegmentIndex:(NSInteger)index {
    UIViewController *vc;
    switch (index) {
        case 0:
            vc = [self.storyboard instantiateViewControllerWithIdentifier:@"FooViewController"];
            break;
        case 1:
            vc = [self.storyboard instantiateViewControllerWithIdentifier:@"BarViewController"];
            break;
    }
    return vc;
}

我从Ray Wenderlichs的书iOS5 by tutorial的第22章得到了这些东西。不幸的是,我没有教学的公共链接。但是有一个WWDC 2011视频标题为“实现UIViewController遏制”

编辑

self.typeSegmentedControl是你的UISegmentedControl的出口

self.contentView是容器视图的出口

qazxsw poi只是我们用来存储你目前使用的qazxsw poi的一个属性


8
投票

这是Matthias Bauch的解决方案,但无论如何都想过在Swift中分享它!编辑:添加指向Swift 2.0现成演示应用程序的链接。 self.currentViewController

UIViewController

2
投票

对于想要在swift中实现相同的人

https://github.com/ahmed-abdurrahman/taby-segmented-control

故事板视图

var currentViewController: UIViewController? @IBOutlet weak var contentView: UIView! @IBOutlet weak var segmentedControl: UISegmentedControl! @IBAction func switchHappeningTabs(sender: UISegmentedControl) { if let vc = viewControllerForSelectedSegmentIndex(sender.selectedSegmentIndex) { self.addChildViewController(vc) self.transitionFromViewController(self.currentViewController!, toViewController: vc, duration: 0.5, options: UIViewAnimationOptions.TransitionFlipFromRight, animations: { self.currentViewController!.view.removeFromSuperview() vc.view.frame = self.contentView.bounds self.contentView.addSubview(vc.view) }, completion: { finished in vc.didMoveToParentViewController(self) self.currentViewController!.removeFromParentViewController() self.currentViewController = vc } ) } } override func viewDidLoad() { super.viewDidLoad() if let vc = self.viewControllerForSelectedSegmentIndex(self.segmentedControl.selectedSegmentIndex) { self.addChildViewController(vc) self.contentView.addSubview(vc.view) self.currentViewController = vc } } func viewControllerForSelectedSegmentIndex(index: Int) -> UIViewController? { var vc: UIViewController? switch index { case 0: vc = self.storyboard?.instantiateViewControllerWithIdentifier("FooViewController") as? UIViewController case 1: vc = self.storyboard?.instantiateViewControllerWithIdentifier("BarViewController") as? UIViewController default: return nil } return vc }


2
投票

A是根视图控制器,B,C是子视图控制器。单击细分时,添加子视图控制器。

结果

import UIKit class HomeController: UIViewController { var currentViewController:UIViewController? @IBOutlet weak var homeController: UIView! override func viewDidLoad() { super.viewDidLoad() let initialController:UIViewController = self.viewControllerForSegmentedIndex(0) self.addChildViewController(initialController) initialController.view.frame = self.homeController.bounds self.homeController.addSubview(initialController.view) self.currentViewController = initialController } @IBAction func segmentChanged(sender: UISegmentedControl) { let viewCOntroller:UIViewController = viewControllerForSegmentedIndex(sender.selectedSegmentIndex) self.addChildViewController(viewCOntroller) self.transitionFromViewController(self.currentViewController!, toViewController: viewCOntroller, duration: 0.5, options: UIViewAnimationOptions.TransitionFlipFromBottom, animations: { self.currentViewController?.view.removeFromSuperview() viewCOntroller.view.frame = self.homeController.bounds self.homeController.addSubview(viewCOntroller.view) }, completion:{ finished in viewCOntroller.didMoveToParentViewController(self) self.currentViewController?.removeFromParentViewController() self.currentViewController = viewCOntroller }) } func viewControllerForSegmentedIndex(index:Int) -> UIViewController { var viewController:UIViewController? switch index { case 0: viewController = self.storyboard?.instantiateViewControllerWithIdentifier("StoryboardIdForFirstController") break case 1: viewController = self.storyboard?.instantiateViewControllerWithIdentifier("StoryboardIdForSecondController") break case 2: viewController = self.storyboard?.instantiateViewControllerWithIdentifier("StoryboardIdForThirdController") break default: break } return viewController! } }

设计

enter image description here

result

0
投票

您可以将初始视图控制器嵌入导航控制器中。通过选择故事板中的视图控制器,然后编辑 - >嵌入 - >导航控制器来完成此操作。

在indexDidChangeForSegmentedControl:方法中,只需将相应的视图控制器推送到导航堆栈:

design

但是当你使用故事板时,你的方法根本没有意义。我不知道你是否可以使用segue将单个分段控制按钮连接到视图控制器。就试一试吧。


0
投票

我最终使用导航控制器来实现类似的功能。

import UIKit

class SegmentViewController: UIViewController {

    @IBOutlet weak var containerView: UIView!

    var leftViewController: LeftViewController!
    var rightViewController: RightViewController!


    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        if let sb = storyboard {
            leftViewController = sb.instantiateViewControllerWithIdentifier("leftViewController") as! LeftViewController

            switchViewController(from: nil, to: leftViewController)
        } else {
            print("storyboard is nil")
        }
    }

    func switchViewController(from fromVC: UIViewController?, to toVC: UIViewController?) {
        if let from = fromVC {
            from.willMoveToParentViewController(nil)
            from.view.removeFromSuperview()
            from.removeFromParentViewController()
        } else {
            print("fromVC is nil")
        }

        if let to = toVC {
            self.addChildViewController(to)
            to.view.frame = CGRectMake(0, 0, containerView.frame.width, containerView.frame.height)
            self.containerView.insertSubview(to.view, atIndex: 0)
            to.didMoveToParentViewController(self)
        } else {
            print("toVC is nil")
        }
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.

        removeViewController()
    }

    func removeViewController() {
        if let leftVC = leftViewController {
            if let _ = leftVC.parentViewController {
                print("leftVC is using")
            } else {
                print("set leftVC = nil")
                leftViewController = nil
            }
        }

        if let rightVC = rightViewController {
            if let _ = rightVC.parentViewController {
                print("rightVC is using")
            } else {
                print("set rightVC = nil")
                rightViewController = nil
            }
        }
    }


    @IBAction func onSegmentValueChanged(sender: UISegmentedControl) {
        UIView.beginAnimations("xxx", context: nil)
        UIView.setAnimationDuration(0.4)
        UIView.setAnimationCurve(.EaseInOut)

        switch sender.selectedSegmentIndex {
        case 0:
            UIView.setAnimationTransition(.FlipFromRight, forView: self.containerView, cache: true)

            if let leftVC = leftViewController {
                switchViewController(from: rightViewController, to: leftVC)
            } else {
                if let sb = storyboard {
                    leftViewController = sb.instantiateViewControllerWithIdentifier("leftViewController") as! LeftViewController
                    switchViewController(from: rightViewController, to: leftViewController)
                } else {
                    print("storyboard is nil")
                }
            }
        default:
            UIView.setAnimationTransition(.FlipFromLeft, forView: self.containerView, cache: true)

            if let rightVC = rightViewController {
                switchViewController(from: leftViewController, to: rightVC)
            } else {
                if let sb = storyboard {
                    rightViewController = sb.instantiateViewControllerWithIdentifier("rightViewController") as! RightViewController
                    switchViewController(from: leftViewController, to: rightViewController)
                } else {
                    print("storyboard is nil")
                }
            }
        }

        UIView.commitAnimations()
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.