Как использовать UISegmentedControl для переключения представлений?


82

Я пытаюсь понять, как использовать различные состояния UISegmentedControl для переключения представлений, аналогично тому, как Apple делает это в App Store при переключении между «Top Paid» и «Top Free».

Ответы:


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
«определенно не оптимизированный способ обработки просмотров» - почему?
— Adam Waite

3
@AdamWaite, потому что все представления должны постоянно храниться в памяти. Если ваши представления слишком сложны и / или содержат много других элементов, это повлияет на общую производительность. Этот фрагмент кода тоже можно отредактировать.
— Стас

@Stas Вы правы, лучше разделить логику между несколькими контроллерами представления, каждый из которых отвечает за свои действия и поведение
— tf.alves

использование контейнерных представлений может привести к проблемам с панелью навигации. особенно если вы используете полупрозрачный. по моему опыту это не рекомендуемое решение
— DamirDiz

45

В моем случае мои представления довольно сложны, и я не могу просто изменить скрытое свойство разных представлений, потому что это займет слишком много памяти.

Я пробовал несколько решений, и ни одно из них не сработало для меня или работало беспорядочно, особенно с titleView в navBar, не всегда отображающим segmentedControl при нажатии / открытии представлений.

Я нашел это сообщение в блоге о проблеме, в котором объясняется, как это сделать правильно. Кажется, ему помогли инженеры Apple на WWDC'2010, чтобы придумать это решение.

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

Решение по этой ссылке - лучшее решение, которое я нашел до сих пор. С небольшой настройкой он также отлично работал с tabBar внизу


Спасибо за отличную находку. Определенно красивое и элегантное решение для этой методологии.
— Shiun

1
Я безуспешно пытался заставить это работать правильно с панелью инструментов внизу, stackoverflow.com/questions/4748120/ ... Не могли бы вы мне помочь?
— Эрик

Есть ли способ иметь анимацию горизонтального переворота между видами. Или работает только без анимации?
— аневризм

Да, кажется, это отличное решение, но как мне настроить его для работы с tabBarController с уже находящимися внутри navigationController?
— Владимир Стажилов

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

Объявить .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
Хотя эта ссылка может дать ответ на вопрос, лучше включить сюда основные части ответа и предоставить ссылку для справки. Ответы, содержащие только ссылки, могут стать недействительными, если ссылка на страницу изменится. - Из
— отзыва

2
@BasilePerrenoud Только что обновил ответ, указав важнейшую и наиболее важную часть решения.
— SlavisaPetkovic

1

Быстрая версия Swift:

@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.