Як мені використовувати UISegmentedControl для перемикання подань?


82

Я намагаюся зрозуміти, як використовувати різні стани UISegmentedControl для перемикання переглядів, подібно до того, як Apple робить це в 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
"точно не оптимізований спосіб обробки поглядів" - чому?
Адам Уейт

3
@AdamWaite, тому що всі подання повинні зберігатися в пам'яті постійно. Якщо ваші погляди занадто складні та / або містять багато інших елементів, це вплине на загальну ефективність. Цей фрагмент коду також можна реконструювати.
Стас

@Stas Ви маєте рацію, краще розділити логіку між кількома контролерами перегляду, кожен відповідальний за свої дії та поведінку
tf.alves

використання переглядів контейнерів може призвести до проблем з панеллю навігації. особливо коли ви використовуєте напівпрозорий. з мого досвіду, це не рекомендується рішення
DamirDiz

45

У моєму випадку мої погляди досить складні, і я не можу просто змінити приховану властивість різних поглядів, оскільки це займе занадто багато пам'яті.

Я спробував кілька рішень, і жодне з них не працювало для мене, або виконувалося нестабільно, спеціально з тим, що titleView навігаційної панелі не завжди відображає segmentedControl при натисканні / видаванні подань.

Я знайшов цю публікацію в блозі про проблему, яка пояснює, як це зробити належним чином. Здається, він мав допомогу інженерів Apple з WWDC'2010, щоб запропонувати це рішення.

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

Рішення за цим посиланням надає найкраще рішення, яке я знайшов про проблему на сьогодні. З невеликим налаштуванням він також чудово працював із панеллю табуляцій внизу


Дякую за чудову знахідку. Безумовно, приємне та елегантне рішення для цієї методології.
Shiun

1
Я намагався зробити це належним чином за допомогою панелі інструментів внизу без успіху, stackoverflow.com/questions/4748120/ ... Чи можете ви допомогти мені?
Ерік,

Чи є спосіб мати горизонтальну фліп-анімацію між переглядами. Або це працює лише без анімації?
аневризм

Так, це здається чудовим рішенням, але як налаштувати це для роботи з tabBarController з навігаційними контролерами, що вже є?
Володимир Стажилов

2
На щастя, впровадження контролера перегляду контейнерів працювало бездоганно! Навіть сеги працюють, як очікувалося.
jweyrich

17

Або якщо це таблиця, ви можете перезавантажити таблицю, а в cellForRowAtIndex заповнити таблицю з різних джерел даних на основі вибраного параметра сегменту.


7

Одна ідея полягає в тому, щоб у представлення з сегментованими елементами керування було представлення контейнера, яке ви заповнюєте різними підпроглядами (додайте як єдиний підгляд подання контейнера, коли сегменти перемикаються). Ви навіть можете мати окремі контролери перегляду для цих підпрограм, хоча вам доведеться пересилати такі важливі методи, як "viewWillAppear" та "viewWillDisappear", якщо вони вам потрібні (і їм доведеться повідомити, під яким контролером навігації вони перебувають).

Як правило, це працює досить добре, тому що ви можете розкласти основний вигляд за допомогою контейнера в IB, а підпрограми заповнять будь-який простір, який їм надає контейнер (переконайтеся, що ваші маски автоматичного розміру встановлені належним чином).


3

Спробуйте використати SNFSegmentedViewControllerкомпонент з відкритим кодом, який робить саме те, що ви шукаєте, з таким налаштуванням UITabBarController.


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

Заявити .М

- (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 Щойно оновив відповідь ключовою та найважливішою частиною рішення.
Славіса Петкович

1

Швидка швидка версія:

@IBAction func segmentControlValueChanged(_ sender: UISegmentedControl) {

    if segmentControl.selectedSegmentIndex == 0 {

        // do something
    } else {

        // do something else
    }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.