2013-10-03 17 views
22

Gọi ContainerView là chế độ xem vùng chứa chính với hai chế độ xem nội dung con: NavigationViewContentView.Hoán đổi chế độ xem con trong chế độ xem vùng chứa

Example of View Layout

Tôi muốn để có thể trao đổi trên bộ điều khiển của ContentView với quan điểm khác. Ví dụ, trao đổi một bộ điều khiển trang chủ với một bộ điều khiển trang tin tức. Hiện tại, cách duy nhất tôi có thể nghĩ để làm điều này là sử dụng một đại biểu để thông báo cho ContainerView rằng tôi muốn chuyển đổi chế độ xem. Điều này có vẻ giống như một cách cẩu thả để làm điều này bởi vì các ContainerViewController sẽ kết thúc có một loạt các đại biểu đặc biệt cho tất cả các subviews.

Điều này cũng cần liên lạc với NavigationView có thông tin về chế độ xem hiện tại trong ContentView. Ví dụ: nếu người dùng ở trên trang tin tức, thanh điều hướng trong chế độ xem điều hướng sẽ hiển thị rằng nút tin tức hiện đang được chọn.

Câu hỏi A: Có cách nào để trao đổi các điều khiển trong ContentView mà không có một phương pháp đại biểu gọi ContainerView bản thân? Tôi muốn làm điều này theo chương trình (không có bảng phân cảnh).

Câu hỏi B: Làm thế nào tôi có thể trao đổi bộ điều khiển trong ContentView từ NavigationView mà không có một cuộc gọi đại biểu? Tôi muốn làm điều này theo chương trình (không có bảng phân cảnh).

+2

Bạn đã xem UIPageViewController chưa? "Bộ điều khiển xem trang cho phép người dùng điều hướng giữa các trang nội dung, trong đó mỗi trang được quản lý bởi đối tượng bộ điều khiển chế độ xem" – shadowhorst

Trả lời

37

Khi bạn có tầm nhìn đứa trẻ đó có bộ điều khiển điểm riêng của họ, bạn sẽ có sau khi mô hình điều khiển chứa tùy chỉnh. Xem Creating Custom Container View Controllers để biết thêm thông tin.

Giả sử bạn đã theo mô hình chứa tùy chỉnh, khi bạn muốn thay đổi bộ điều khiển xem đứa trẻ (và xem liên quan) cho "quan điểm nội dung", bạn sẽ làm điều đó theo chương trình với một cái gì đó như:

UIViewController *newController = ... // instantiate new controller however you want 
UIViewController *oldController = ... // grab the existing controller for the current "content view"; perhaps you maintain this in your own ivar; perhaps you just look this up in self.childViewControllers 

newController.view.frame = oldController.view.frame; 

[oldController willMoveToParentViewController:nil]; 
[self addChildViewController:newController];   // incidentally, this does the `willMoveToParentViewController` for the new controller for you 

[self transitionFromViewController:oldController 
        toViewController:newController 
          duration:0.5 
          options:UIViewAnimationOptionTransitionCrossDissolve 
         animations:^{ 
          // no further animations required 
         } 
         completion:^(BOOL finished) { 
          [oldController removeFromParentViewController]; // incidentally, this does the `didMoveToParentViewController` for the old controller for you 
          [newController didMoveToParentViewController:self]; 
         }]; 

Khi bạn thực hiện theo cách này, không cần bất kỳ giao thức giao thức đại biểu nào có bộ điều khiển của chế độ xem nội dung (trừ những gì iOS đã cung cấp với phương thức Managing Child View Controllers in a Custom Container).


Bằng cách này, này giả định rằng bộ điều khiển con ban đầu liên quan đến mà xem nội dung đã được bổ sung như sau:

UIViewController *childController = ... // instantiate the content view's controller any way you want 
[self addChildViewController:childController]; 
childController.view.frame = ... // set the frame any way you want 
[self.view addSubview:childController.view]; 
[childController didMoveToParentViewController:self]; 

Nếu bạn muốn có một bộ điều khiển con nói với phụ huynh để thay đổi bộ điều khiển được liên kết với chế độ xem nội dung, bạn sẽ:

  1. Xác định giao thức cho điều này:

    @protocol ContainerParent <NSObject> 
    
    - (void)changeContentTo:(UIViewController *)controller; 
    
    @end 
    
  2. Xác định bộ điều khiển cha mẹ để phù hợp với giao thức này, ví dụ:

    #import <UIKit/UIKit.h> 
    #import "ContainerParent.h" 
    
    @interface ViewController : UIViewController <ContainerParent> 
    
    @end 
    
  3. Thực hiện phương pháp changeContentTo trong bộ điều khiển cha mẹ (giống như đã nêu ở trên):

    - (void)changeContentTo:(UIViewController *)controller 
    { 
        UIViewController *newController = controller; 
        UIViewController *oldController = ... // grab reference of current child from `self.childViewControllers or from some property where you stored it 
    
        newController.view.frame = oldController.view.frame; 
    
        [oldController willMoveToParentViewController:nil]; 
        [self addChildViewController:newController]; 
    
        [self transitionFromViewController:oldController 
             toViewController:newController 
               duration:1.0 
               options:UIViewAnimationOptionTransitionCrossDissolve 
              animations:^{ 
               // no further animations required 
              } 
              completion:^(BOOL finished) { 
               [oldController removeFromParentViewController]; 
               [newController didMoveToParentViewController:self]; 
              }]; 
    } 
    
  4. Và bộ điều khiển con hiện có thể sử dụng giao thức này trong tham chiếu đến thuộc tính self.parentViewController mà iOS cung cấp cho bạn:

    - (IBAction)didTouchUpInsideButton:(id)sender 
    { 
        id <ContainerParent> parentViewController = (id)self.parentViewController; 
        NSAssert([parentViewController respondsToSelector:@selector(changeContentTo:)], @"Parent must conform to ContainerParent protocol"); 
    
        UIViewController *newChild = ... // instantiate the new child controller any way you want 
        [parentViewController changeContentTo:newChild]; 
    } 
    
+0

Đây là những gì tôi đã thấy trong hầu hết các triển khai chế độ xem trên GitHub và đã suy ra điều này từ tài liệu. Có cách nào để làm điều này mà không có mã này trùng lặp trong mỗi bộ điều khiển? – Alex

+1

@orbv Mã này chỉ nằm trong bộ điều khiển chính, do đó không có sự trùng lặp nào liên quan. Có lẽ tôi không hiểu câu hỏi của bạn. – Rob

+1

Xcode 5 chỉ cho phép bạn sử dụng phân đoạn Nhúng khi thêm chế độ xem vùng chứa. Tôi cũng sẽ tránh đặt khung trực tiếp nếu bố cục tự động đang được sử dụng. – Abizern

-2

Dường như bạn đang bối rối. Một contentView (giả sử UIView) không 'chứa' một bộ điều khiển mà bạn sẽ trao đổi. A UIViewController xử lý của UIView. Dường như với tôi rằng bạn yêu cầu thiết lập bộ điều khiển xem cha-con.

Một bộ điều khiển chế độ xem đơn, sẽ xử lý các trình điều khiển chế độ xem con, mỗi bộ điều khiển bạn có thể xử lý khi được hiển thị trên màn hình và điều chỉnh UIViews và nội dung phù hợp. Vui lòng xem tài liệu Apple dưới đây.

Container Programming - Apple Documentation

2

Đối với loại đó của quá trình chuyển đổi, bạn cũng có thể sử dụng UIView.animateWith... hình ảnh động.

Ví dụ, giả sử rằng rootContainerView là container và contentViewController điều khiển đang hoạt động trong container, sau đó

func setContentViewController(contentViewController:UIViewController, animated:Bool = true) { 
    if animated == true { 
     addChildViewController(contentViewController) 
     contentViewController.view.alpha = 0 
     contentViewController.view.frame = rootContainerView.bounds 
     rootContainerView.addSubview(contentViewController.view) 
     self.contentViewController?.willMoveToParentViewController(nil) 

     UIView.animateWithDuration(0.3, animations: { 
      contentViewController.view.alpha = 1 
      }, completion: { (_) in 
       contentViewController.didMoveToParentViewController(self) 

       self.contentViewController?.view.removeFromSuperview() 
       self.contentViewController?.didMoveToParentViewController(nil) 
       self.contentViewController?.removeFromParentViewController() 
       self.contentViewController = contentViewController 
     }) 
    } else { 
     cleanUpChildControllerIfPossible() 

     contentViewController.view.frame = rootContainerView.bounds 
     addChildViewController(contentViewController) 
     rootContainerView.addSubview(contentViewController.view) 
     contentViewController.didMoveToParentViewController(self) 
     self.contentViewController = contentViewController 
    } 
} 

// MARK: - Private 

private func cleanUpChildControllerIfPossible() { 
    if let childController = contentViewController { 
     childController.willMoveToParentViewController(nil) 
     childController.view.removeFromSuperview() 
     childController.removeFromParentViewController() 
    } 
} 

này sẽ cung cấp cho u hình động phai đơn giản, u cũng có thể thử bất kỳ UIViewAnimationOptions, chuyển tiếp, vv

Các vấn đề liên quan