Wie verwende ich ein UISegmentedControl, um die Ansicht zu wechseln?

82

Ich versuche herauszufinden, wie die verschiedenen Status eines UISegmentedControl zum Wechseln der Ansichten verwendet werden können, ähnlich wie Apple es im App Store tut, wenn zwischen "Top Paid" und "Top Free" gewechselt wird.

Mark Adams
quelle

Antworten:

113

Der einfachste Ansatz besteht darin, zwei Ansichten zu haben, deren Sichtbarkeit Sie umschalten können, um anzuzeigen, welche Ansicht ausgewählt wurde. Hier ist ein Beispielcode, wie dies gemacht werden kann, definitiv keine optimierte Methode zum Behandeln der Ansichten, sondern nur um zu demonstrieren, wie Sie das UISegmentControl verwenden können, um die sichtbare Ansicht umzuschalten :

- (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];
  }
}


Sie können den Code natürlich weiter neu faktorisieren, um die richtige Ansicht auszublenden / anzuzeigen.

Ronnie Liew
quelle
4
"definitiv keine optimierte Art, mit den Ansichten umzugehen" - warum?
Adam Waite
3
@AdamWaite, da alle Ansichten dauerhaft gespeichert werden müssen. Wenn Ihre Ansichten zu kompliziert sind und / oder viele andere Elemente enthalten, wirkt sich dies auf die Gesamtleistung aus. Dieser Code könnte ebenfalls überarbeitet werden.
Stas
@Stas Sie haben Recht, es ist besser, die Logik auf mehrere Ansichts-Controller aufzuteilen, von denen jeder für seine eigenen Aktionen und Verhaltensweisen verantwortlich ist
tf.alves
Die Verwendung von Containeransichten kann zu Problemen mit der Navigationsleiste führen. besonders wenn Sie eine durchscheinende verwenden. Aus meiner Erfahrung ist es keine empfehlenswerte Lösung
DamirDiz
45

In meinem Fall sind meine Ansichten ziemlich komplex und ich kann nicht einfach die verborgene Eigenschaft verschiedener Ansichten ändern, da dies zu viel Speicherplatz beanspruchen würde.

Ich habe mehrere Lösungen ausprobiert und keine davon hat für mich funktioniert oder ist unregelmäßig ausgeführt worden, insbesondere mit der titleView der navBar, die beim Push / Popping von Ansichten nicht immer die segmentedControl anzeigt.

Ich habe diesen Blog-Beitrag über das Problem gefunden, in dem erklärt wird, wie es richtig gemacht wird. Anscheinend hatte er die Hilfe von Apple-Ingenieuren auf der WWDC'2010, um diese Lösung zu finden.

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

Die Lösung in diesem Link ist zweifellos die beste Lösung, die ich bisher zu diesem Problem gefunden habe. Mit ein wenig Anpassung funktionierte es auch gut mit einer TabBar am unteren Rand

Marc M.
quelle
Vielen Dank für den tollen Fund. Auf jeden Fall eine schöne und elegante Lösung für diese Methodik.
Shiun
1
Ich habe versucht, dies mit der Symbolleiste unten ohne Erfolg zum Laufen zu bringen. Stackoverflow.com/questions/4748120/… Können Sie mir bitte helfen?
Erik
Gibt es eine Möglichkeit, eine horizontale Flip-Animation zwischen den Ansichten zu erstellen? Oder funktioniert es nur ohne Animation?
aneuryzm
Ja, dies scheint eine großartige Lösung zu sein, aber wie kann ich dies anpassen, um mit tabBarController zu arbeiten, in dem sich bereits Navigationscontroller befinden?
Vladimir Stazhilov
2
Glücklicherweise hat die Implementierung eines Container View Controllers einwandfrei funktioniert! Sogar Segues funktionieren wie erwartet.
Jweyrich
17

Wenn es sich um eine Tabelle handelt, können Sie die Tabelle neu laden und in cellForRowAtIndex die Tabelle basierend auf der ausgewählten Segmentoption aus verschiedenen Datenquellen füllen.

lostInTransit
quelle
7

Eine Idee ist, dass die Ansicht mit den segmentierten Steuerelementen eine Containeransicht hat, die Sie mit den verschiedenen Unteransichten füllen (als einzige Unteransicht der Containeransicht hinzufügen, wenn die Segmente umgeschaltet werden). Sie können sogar separate Ansichts-Controller für diese Unteransichten haben, obwohl Sie wichtige Methoden wie "viewWillAppear" und "viewWillDisappear" weiterleiten müssen, wenn Sie sie benötigen (und ihnen muss mitgeteilt werden, unter welchem ​​Navigations-Controller sie sich befinden).

Im Allgemeinen funktioniert das ziemlich gut, da Sie die Hauptansicht mit Container in IB auslegen können und die Unteransichten den Platz füllen, den der Container zur Verfügung hat (stellen Sie sicher, dass Ihre Masken für die automatische Größe richtig eingerichtet sind).

Kendall Helmstetter Gelner
quelle
3

Versuchen Sie es mit SNFSegmentedViewControllereiner Open-Source-Komponente, die mit einem Setup genau das tut, wonach Sie suchen UITabBarController.

sethfri
quelle
2

Aus der Antwort von @Ronnie Liew erstelle ich Folgendes:

//
//  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
Neid
quelle
2

Weisen Sie .H in zu

 UISegmentedControl *lblSegChange;

- (IBAction)segValChange:(UISegmentedControl *) sender

Deklarieren Sie .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];
 }
} 
Anbu.Karthik
quelle
2

Schnelle Version:

Der übergeordnete Ansichtscontroller ist für das Festlegen der Größe und Position der Ansicht jedes untergeordneten Ansichtscontrollers verantwortlich. Die Ansicht des untergeordneten Ansichtscontrollers wird Teil der Ansichtshierarchie des übergeordneten Ansichtscontrollers.

Faule Eigenschaften definieren:

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

Untergeordnete Ansichtssteuerungen ein- / ausblenden:

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 verwalten

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

Und natürlich können Sie in Ihren untergeordneten View-Controller-Klassen Folgendes verwenden:

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

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

SlavisaPetkovic
quelle
1
Während dieser Link die Frage beantworten kann, ist es besser, die wesentlichen Teile der Antwort hier aufzunehmen und den Link als Referenz bereitzustellen. Nur-Link-Antworten können ungültig werden, wenn sich die verknüpfte Seite ändert. - Aus dem Rückblick
Basile Perrenoud
2
@BasilePerrenoud Die Antwort wurde gerade mit dem entscheidenden und wichtigsten Teil der Lösung aktualisiert.
SlavisaPetkovic
1

Eine schnelle Swift-Version:

@IBAction func segmentControlValueChanged(_ sender: UISegmentedControl) {

    if segmentControl.selectedSegmentIndex == 0 {

        // do something
    } else {

        // do something else
    }
}
Strahlende Zukunft
quelle