代码之家  ›  专栏  ›  技术社区  ›  Neal L

ui分段控制最佳实践

  •  23
  • Neal L  · 技术社区  · 16 年前

    我正在努力找出使用 UISegmentedControl 对于iPhone应用程序。我在StackOverflow上读了几篇文章,看到了一些人的想法,但我还不能找到最好的方法。我提到的职位是:

    Changing Views from UISegmentedControl How do I use a UISegmentedControl to switch views?

    似乎可以选择:

    • 在ib中添加每个视图,并将它们放在一起,然后显示/隐藏它们
    • 在ib中分别创建每个子视图,然后在主视图中创建一个容器来填充所需的子视图。
    • 设置一个非常高或非常宽的 UIView 并根据所选片段左右或上下设置动画
    • 使用A UITabBarController 换掉这些子观点-看起来很愚蠢
    • 对于表格,重新加载表格并在 cellForRowAtIndex 并根据所选的段选项从不同的数据源或节填充表(我的应用程序不是这样)

    那么,哪种方法最适合子视图/非表方法?哪一个最容易实现?你能分享一些示例代码吗?

    谢谢!

    3 回复  |  直到 11 年前
        1
  •  11
  •   Noah Witherspoon    16 年前

    我将使用您提到的第二个选项,在ib中创建子视图,并在主视图中交换它们。这将是一个很好的使用机会 UIViewController ,unbclassed:在初始设置中,使用 -initWithNibName:bundle: (其中第一个参数是包含单个子视图的NIB的名称,第二个参数是 nil 并添加其 view 必要时作为主视图的子视图。这将有助于保持低内存占用:默认的 ui视图控制器 当接收到内存警告时,如果没有超级视图,则释放其视图。只要从视图层次中删除隐藏视图,就可以将控制器保留在内存中,而不必担心释放任何内容。

    (根据评论编辑:)

    你不需要子类 ui视图控制器 ,但每个视图都需要单独的XIB。您也不需要向ib中的包含视图添加任何内容。

    实例变量,在处理所有这一切的任何类的接口中:

     UIViewController *controllerOne;
     UIViewController *controllerTwo;
    
     UIViewController *currentController;
    
     IBOutlet UIView *theContainerView;
    

    在你的设置中( -applicationDidFinishLaunching: 或者什么)

     controllerOne = [[UIViewController alloc] initWithNibName:@"MyFirstView" bundle:nil];
     controllerTwo = [[UIViewController alloc] initWithNibName:@"MySecondView" bundle:nil];
    

    切换到控制器:

     - (void)switchToController:(UIViewController *)newCtl
     {
          if(newCtl == currentController)
               return;
          if([currentController isViewLoaded])
               [currentController.view removeFromSuperview];
    
          if(newCtl != nil)
               [theContainerView addSubview:newCtl.view];
    
          currentController = newCtl;
     }
    

    那就叫它,例如,

     [self switchToController:controllerOne];
    
        2
  •  19
  •   crafterm    16 年前

    我在iPad应用程序中也遇到了这个需求。

    我的解决方案是为 处理与这些视图相关的业务逻辑的每种视图样式 (即与每个段相关),并通过编程将其添加/删除为 响应所选段的“管理”控制器的子视图 指数变化。

    为此,必须创建一个额外的uiviewController子类来管理 uiSegmentedControl更改,并添加/删除子视图。

    下面的代码完成了所有这些工作,同时还考虑了一些注意事项/额外事项:

    • viewwill显示/viewwill消失/etc,不在子视图上调用 自动,需要通过“管理”控制器告知
    • viewwill appear/viewwill消失/etc,不调用“管理” 当它在导航控制器中时,因此 导航控制器委派
    • 如果您想从 段的子视图,您需要重新调用“管理”视图 因为子视图是在 导航层次结构,不会引用导航 控制器。
    • 如果在导航控制器方案中使用,返回按钮是 自动设置为段的名称。

    接口:

    @interface SegmentManagingViewController : UIViewController <UINavigationControllerDelegate> {
        UISegmentedControl    * segmentedControl;
        UIViewController      * activeViewController;
        NSArray               * segmentedViewControllers;
    }
    
    @property (nonatomic, retain) IBOutlet UISegmentedControl * segmentedControl;
    @property (nonatomic, retain) UIViewController            * activeViewController;
    @property (nonatomic, retain) NSArray                     * segmentedViewControllers;
    
    @end
    

    实施:

    @interface SegmentManagingViewController ()
    - (void)didChangeSegmentControl:(UISegmentedControl *)control;
    @end
    
    @implementation SegmentManagingViewController
    
    @synthesize segmentedControl, activeViewController, segmentedViewControllers;
    
    - (void)viewDidLoad {
        [super viewDidLoad];
    
        UIViewController * controller1 = [[MyViewController1 alloc] initWithParentViewController:self];
        UIViewController * controller2 = [[MyViewController2 alloc] initWithParentViewController:self];
        UIViewController * controller3 = [[MyViewController3 alloc] initWithParentViewController:self];
    
        self.segmentedViewControllers = [NSArray arrayWithObjects:controller1, controller2, controller3, nil];
        [controller1 release];
        [controller2 release];
        [controller3 release];
    
        self.navigationItem.titleView = self.segmentedControl =
        [[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObjects:@"Seg 1", @"Seg 2", @"Seg 3", nil]];
        self.segmentedControl.selectedSegmentIndex = 0;
        self.segmentedControl.segmentedControlStyle = UISegmentedControlStyleBar;
    
        [self.segmentedControl addTarget:self action:@selector(didChangeSegmentControl:) forControlEvents:UIControlEventValueChanged];
    
        [self didChangeSegmentControl:self.segmentedControl]; // kick everything off
    }
    
    - (void)viewWillAppear:(BOOL)animated {
        [super viewWillAppear:animated];
        [self.activeViewController viewWillAppear:animated];
    }
    
    - (void)viewDidAppear:(BOOL)animated {
        [super viewDidAppear:animated];
        [self.activeViewController viewDidAppear:animated];
    }
    
    - (void)viewWillDisappear:(BOOL)animated {
        [super viewWillDisappear:animated];
        [self.activeViewController viewWillDisappear:animated];
    }
    
    - (void)viewDidDisappear:(BOOL)animated {
        [super viewDidDisappear:animated];
        [self.activeViewController viewDidDisappear:animated];
    }
    
    #pragma mark -
    #pragma mark UINavigationControllerDelegate control
    
    // Required to ensure we call viewDidAppear/viewWillAppear on ourselves (and the active view controller)
    // inside of a navigation stack, since viewDidAppear/willAppear insn't invoked automatically. Without this
    // selected table views don't know when to de-highlight the selected row.
    
    - (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
        [viewController viewDidAppear:animated];
    }
    
    - (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
        [viewController viewWillAppear:animated];
    }
    
    #pragma mark -
    #pragma mark Segment control
    
    - (void)didChangeSegmentControl:(UISegmentedControl *)control {
        if (self.activeViewController) {
            [self.activeViewController viewWillDisappear:NO];
            [self.activeViewController.view removeFromSuperview];
            [self.activeViewController viewDidDisappear:NO];
        }
    
        self.activeViewController = [self.segmentedViewControllers objectAtIndex:control.selectedSegmentIndex];
    
        [self.activeViewController viewWillAppear:NO];
        [self.view addSubview:self.activeViewController.view];
        [self.activeViewController viewDidAppear:NO];
    
        NSString * segmentTitle = [control titleForSegmentAtIndex:control.selectedSegmentIndex];
        self.navigationItem.backBarButtonItem  = [[UIBarButtonItem alloc] initWithTitle:segmentTitle style:UIBarButtonItemStylePlain target:nil action:nil];
    }
    
    #pragma mark -
    #pragma mark Memory management
    
    - (void)dealloc {
        self.segmentedControl = nil;
        self.segmentedViewControllers = nil;
        self.activeViewController = nil;
        [super dealloc];
    }
    
    @end
    

    希望这有帮助。

        3
  •  3
  •   PopUp    14 年前

    下面是一个很好的教程,进一步解释了这个概念: http://redartisan.com/2010/5/26/uisegmented-control-view-switching

    以及Github的位置: https://github.com/crafterm/SegmentedControlExample.git