Làm cách nào để sử dụng UISegmentedControl để chuyển đổi chế độ xem?


82

Tôi đang cố gắng tìm ra cách sử dụng các trạng thái khác nhau của UISegmentedControl để chuyển đổi chế độ xem, tương tự như cách Apple thực hiện trong App Store khi chuyển đổi giữa 'Trả phí cao nhất' và 'Miễn phí hàng đầu'.

Câu trả lời:


113

Cách tiếp cận đơn giản nhất là có hai chế độ xem mà bạn có thể chuyển đổi khả năng hiển thị của chúng để cho biết chế độ xem nào đã được chọn. Đây là một số mã mẫu về cách nó có thể được thực hiện, chắc chắn không phải là một cách được tối ưu hóa để xử lý các chế độ xem mà chỉ để chứng minh cách bạn có thể sử dụng UISegmentControl để chuyển đổi chế độ xem hiển thị:

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


Tất nhiên, bạn có thể căn cứ lại mã để ẩn / hiển thị chế độ xem bên phải.


4
'chắc chắn không phải là một cách tối ưu hóa để xử lý các lượt xem' - tại sao?
Adam Waite

3
@AdamWaite vì tất cả các khung nhìn phải được lưu trữ vĩnh viễn trong bộ nhớ. Nếu chế độ xem của bạn quá phức tạp và / hoặc chứa nhiều yếu tố khác, nó sẽ ảnh hưởng đến hiệu suất tổng thể. Đoạn mã đó cũng có thể được cấu trúc lại.
Stas

@Stas Bạn là đúng, nó tốt hơn để chia logic giữa nhiều bộ điều khiển xem, mỗi chịu trách nhiệm về hành động của mình và hành vi
tf.alves

sử dụng chế độ xem vùng chứa có thể dẫn đến sự cố với thanh điều hướng. đặc biệt là khi bạn đang sử dụng một trong mờ. từ kinh nghiệm của tôi nó không phải là một giải pháp recommendable
DamirDiz

45

Trong trường hợp của tôi, các khung nhìn của tôi khá phức tạp và tôi không thể chỉ thay đổi thuộc tính ẩn của các khung nhìn khác nhau vì nó sẽ chiếm quá nhiều bộ nhớ.

Tôi đã thử một số giải pháp và không có giải pháp nào phù hợp với tôi hoặc hoạt động không bình thường, đặc biệt là với titleView của navBar không phải lúc nào cũng hiển thị phân khúc

Tôi đã tìm thấy bài đăng trên blog này về sự cố giải thích cách thực hiện điều đó theo cách thích hợp. Có vẻ như anh ấy đã nhận được sự hỗ trợ của các kỹ sư Apple tại WWDC'2010 để đưa ra giải pháp này.

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

Giải pháp trong liên kết này là giải pháp tốt nhất mà tôi đã tìm thấy về vấn đề này cho đến nay. Với một chút điều chỉnh, nó cũng hoạt động tốt với thanh tab ở dưới cùng


Cảm ơn bạn đã tìm thấy tuyệt vời. Chắc chắn là một giải pháp tốt đẹp và thanh lịch cho phương pháp luận này.
Shiun

1
Tôi đã cố gắng làm cho điều này hoạt động bình thường với thanh công cụ ở dưới cùng mà không thành công, stackoverflow.com/questions/4748120/… Bạn có thể vui lòng giúp tôi không?
Erik

Có cách nào để có hoạt ảnh lật ngang giữa các Chế độ xem không. Hay nó chỉ hoạt động mà không có hoạt ảnh?
aneuryzm

Có, đây có vẻ là một giải pháp tuyệt vời, nhưng làm cách nào để điều chỉnh điều này để hoạt động với tabBarController với navigationControllers đã có bên trong?
Vladimir Stazhilov

2
May mắn thay, việc triển khai Bộ điều khiển chế độ xem vùng chứa đã hoạt động hoàn hảo! Ngay cả các segues hoạt động như mong đợi.
jweyrich

17

Hoặc nếu nó là một bảng, bạn có thể tải lại bảng và trong cellForRowAtIndex, điền bảng từ các nguồn dữ liệu khác nhau dựa trên tùy chọn phân đoạn đã chọn.


7

Một ý tưởng là để chế độ xem với các điều khiển được phân đoạn có chế độ xem vùng chứa mà bạn điền vào các lượt xem phụ khác nhau (thêm dưới dạng một lượt xem phụ duy nhất của chế độ xem vùng chứa khi các phân đoạn được bật tắt). Bạn thậm chí có thể có các bộ điều khiển chế độ xem riêng biệt cho các chế độ xem phụ đó, mặc dù bạn phải chuyển tiếp các phương thức quan trọng như "viewWillAppear" và "viewWillDisappear" nếu bạn cần chúng (và họ sẽ phải được cho biết chúng đang ở trong bộ điều khiển điều hướng nào).

Nói chung, điều đó hoạt động khá tốt vì bạn có thể bố trí chế độ xem chính với vùng chứa trong IB và các chế độ xem phụ sẽ lấp đầy bất kỳ không gian nào mà vùng chứa cho phép chúng có (đảm bảo mặt nạ tự động khôi phục kích thước của bạn được thiết lập đúng cách).


3

Hãy thử sử dụng SNFSegmentedViewController, một thành phần mã nguồn mở thực hiện chính xác những gì bạn đang tìm kiếm với một thiết lập như thế nào UITabBarController.


2

Từ câu trả lời của @Ronnie Liew, tôi tạo ra cái này:

//
//  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

Chỉ định .H trong

 UISegmentedControl *lblSegChange;

- (IBAction)segValChange:(UISegmentedControl *) sender

Khai báo .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

Phiên bản Swift:

Bộ điều khiển chế độ xem cha chịu trách nhiệm thiết lập kích thước và vị trí của chế độ xem của mỗi bộ điều khiển chế độ xem con. Chế độ xem của bộ điều khiển chế độ xem con trở thành một phần của hệ thống phân cấp chế độ xem của bộ điều khiển chế độ xem mẹ.

Xác định thuộc tính lười biếng:

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

Hiển thị / Ẩn Bộ điều khiển Chế độ xem Trẻ em:

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

Quản lý SegmentedControl tapEvent

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

Và tất nhiên bạn có thể sử dụng trong các lớp bộ điều khiển chế độ xem con của bạn:

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

Tham khảo: https://cocoacasts.com/managing-view-controllers-with-container-view-controllers/


1
Mặc dù liên kết này có thể trả lời câu hỏi, nhưng tốt hơn hết bạn nên đưa các phần thiết yếu của câu trả lời vào đây và cung cấp liên kết để tham khảo. Các câu trả lời chỉ có liên kết có thể trở nên không hợp lệ nếu trang được liên kết thay đổi. - Từ đánh giá
Basile Perrenoud

2
@BasilePerrenoud Vừa cập nhật câu trả lời với phần quan trọng và quan trọng nhất của giải pháp.
SlavisaPetkovic

1

Một phiên bản Swift nhanh chóng:

@IBAction func segmentControlValueChanged(_ sender: UISegmentedControl) {

    if segmentControl.selectedSegmentIndex == 0 {

        // do something
    } else {

        // do something else
    }
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.