仅使用一个.xib文件的纵向和横向的替代iOS布局

Dav*_*igh 41 xcode interface-builder xib screen-orientation ios

使用xcode中的界面构建器和一个.xib文件,如何在横向和纵向方向之间旋转时创建备用布局?

请参见不同布局的图表 在此输入图像描述

Nb.绿色视图/区域将包含横向流动的3个项目,在纵向中,这3个项目将在绿色视图/区域内垂直流动.

MeX*_*eXx 44

一种方法是在.xib文件中有三个视图.第一个是ViewController的普通视图,没有子视图.

然后根据需要创建纵向和横向视图.这三个都必须是根级视图(看一下截图)

在此输入图像描述

在Viewcontroller中,创建2个IBOutlet,一个用于纵向,一个用于横向视图,并将它们与界面构建器中的相应视图连接:

IBOutlet UIView *_portraitView;
IBOutlet UIView *_landscapeView;
UIView *_currentView;
Run Code Online (Sandbox Code Playgroud)

_currentView需要第三个视图来跟踪当前正在显示这些视图中的哪一个.然后创建一个这样的新函数:

-(void)setUpViewForOrientation:(UIInterfaceOrientation)orientation
{
    [_currentView removeFromSuperview];
    if(UIInterfaceOrientationIsLandscape(orientation))
    {
        [self.view addSubview:_landscapeView];
        _currentView = _landscapeView;
    }
    else
    {
        [self.view addSubview:_portraitView];
        _currentView = _portraitView;
    }
}
Run Code Online (Sandbox Code Playgroud)

您需要从两个不同的位置调用此函数,首先进行初始化:

-(void)viewDidLoad
{
    [super viewDidLoad];
    UIInterfaceOrientation interfaceOrientation = [[UIApplication sharedApplication] statusBarOrientation];
    [self setUpViewForOrientation:interfaceOrientation];
}
Run Code Online (Sandbox Code Playgroud)

第二个方向改变:

-(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
    [self setUpViewForOrientation:toInterfaceOrientation];
}
Run Code Online (Sandbox Code Playgroud)

希望对你有所帮助!

  • 一个很大的问题是你如何处理IBOutlets?如果你有,在两个版本上都说相同的标签.您只能将一个IBOutlet连接到您的控制器.... (14认同)
  • 加载第二个视图可能无法为转换设置动画.因此,它不会向用户提供有关哪个组件移动到哪个位置的反馈. (5认同)

Grz*_*ski 14

没有自动支持方式,因为它违反Apple设计.您应该有一个ViewController支持两种方向.

但是如果你真的想这样做,你需要在旋转事件上重新加载xib并加载不同的nib文件.

-(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
    [[NSBundle mainBundle] loadNibNamed:[self nibNameForInterfaceOrientation:toInterfaceOrientation] owner:self options:nil];
    [self viewDidLoad];
}

- (NSString*) nibNameForInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    NSString *postfix = (UIInterfaceOrientationIsLandscape(interfaceOrientation)) ? @"portrait" : @"landscape";
    return [NSString stringWithFormat:@"%@-%@", NSStringFromClass([self class]), postfix];
}
Run Code Online (Sandbox Code Playgroud)

然后用"横向"和"纵向"创建两个后固定的nib文件.

  • 它可能不是你想要的答案,但Apple建议不要做你的建议:https://developer.apple.com/library/ios/featuredarticles/ViewControllerPGforiPhoneOS/RespondingtoDeviceOrientationChanges/RespondingtoDeviceOrients.Changes.html#//apple_ref/ DOC/UID/TP40007457-CH7-SW14 (3认同)

Tom*_*ift 8

我喜欢@ MeXx的解决方案,但它有在内存中保留两个不同视图层次结构的开销.此外,如果任何子视图的状态(例如颜色)发生变化,则在切换层次结构时需要对其进行映射.

另一种解决方案可能是使用自动布局并为每个方向交换每个子视图的约束.如果您在两个方向的子视图之间有1:1的映射,这将最有效.

可以理解的是,您希望使用IB来直观地定义每个方向的布局.根据我的计划,您必须执行@MeXx规定的操作,但是一旦加载了nib(awakeFromNib)并在layout(viewWillLayoutSubviews)上重新应用了正确的set ,就创建了一个存储两组约束的机制.抓取并存储其约束后,您可以丢弃辅助视图层次结构.(由于约束是特定于视图的,因此您可能会创建新约束以应用于实际子视图).

对不起,我没有任何代码.这只是现阶段的计划.

最后的注意事项 - 使用xib比使用故事板更容易,因为在故事板中描述居住在视图控制器主视图之外的视图是很痛苦的(这是理想的,因为否则它是PITA编辑的).Blach!