了解坐标,视图,子视图和方向更改

时间:2013-02-26 18:12:48

标签: iphone ios objective-c ipad uistoryboard

所以,我正在为iPad构建一个iOS应用程序。该应用程序嵌入了视频聊天功能。我已经获得了视频聊天,通知等等。我的问题在于界面。在iOS编程方面,我是一个菜鸟btw;我2周前才开始这样做。对不起,如果帖子有点长,我只是想突出显示可能在这里发挥的一切和我的思考过程。任何批评都是受欢迎的。

我有一个显示大部分信息的UIWebView(称之为webView)。单击按钮时,我希望调整大小并显示一个小的新视图,其中包含三个项目:您正在聊天的人(称之为imageOne),视频聊天(称之为imageTwo)和挂起向上按钮(称之为buttonHangUp)。如果设备处于横向,我希望新视图显示在右侧,imageOne,imageTwo和buttonHangUp处于垂直位置。如果设备处于纵向,我希望新视图显示在底部,imageOne,image Two和buttonHangUp处于水平位置。

以下是我的思维过程:

我继续第二个选项(如果有更简单的方法可以做到这一点,或者如果我应该做其他事情,请告诉我;我很想学习交易的提示和技巧)。

以下是我的代码:

  • 我在那里制作了一个全局变量isLandscape a la apple教程
  • 我制作了6个其他全局变量CGRects,每个变量用于保存纵向和横向中不同项目的位置(imageOnePortrait,imageOneLandscape等)
  • 我实现了awakeFromNib,将肖像变量设置为项目的初始位置和大小

    (void) awakeFromNib
    {
    isLandscape = NO;
    
    imageOnePortrait = self.imageOne.frame;
    imageTwoPortrait = self.imageTwo.frame;
    buttonHangUpPortrait = self.buttonHangUp.frame;
    
    [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(orientationChanged:) name:UIDeviceOrientationDidChangeNotification object:nil];
    }
    
  • 我按照apple文档中的描述实现了orientationChanged方法。但是,我用UIInterfaceOrientation替换了UIDeviceOrientation,因为UIDeviceOrientation没有发送我正在寻找的横向/纵向方向,而是面朝上和面朝下的消息

    - (void) orientationChanged:(NSNotification *)notification
    {
    UIInterfaceOrientation interfaceOrientation = [UIApplication sharedApplication].statusBarOrientation;
    if(UIInterfaceOrientationIsLandscape(interfaceOrientation) && !isLandscape)
    {
        CGRect temp = self.videoView.frame;
        temp.size.width = 360;
        temp.size.height = 748;
        temp.origin.x = 664;
        temp.origin.y = 0;
        self.videoView.frame = temp;
        self.imageOne.frame = imageOneLandscape;
        self.imageTwo.frame = imageTwoLandscape;
        self.buttonHangUp.frame = buttonHangUpLandscape;
        isLandscape = YES;
    }
    else if (UIInterfaceOrientationIsPortrait(interfaceOrientation) && isLandscape)
    {
        CGRect temp = self.videoView.frame;
        temp.size.width = 768;
        temp.size.height = 300;
        temp.origin.x = 0;
        temp.origin.y = 703;
        self.videoView.frame = temp;
        self.imageTwo.frame = imageTwoPortrait;
        self.imageOne.frame = imageOnePortrait;
        self.buttonHangUp.frame = buttonHangUpPortrait;
        isLandscape = NO;
    }
    }
    
  • 在viewDidLoad下,我设置了Landscape坐标的坐标(我假设在调用orientationMade函数之前加载了这些坐标,并且它们是相对于videoView的 - 如果我需要请更正我相对于其他东西设置它们;我看到它们相对于storyboard中的videoView设置了):

    imageOneLandscape.origin.x = 20;
    imageOneLandscape.origin.y = 20;
    imageTwoLandscape.origin.x = 20;
    imageTwoLandscape.origin.y = 288;
    buttonHangUpLandscape.origin.x = 20;
    buttonHangUpLandscape.origin.y = 556;
    
  • 在启动视频通话的功能下,我调整了webView的大小,并显示了videoView:

    CGRect temp = self.webView.frame;
    
    if(isLandscape)
    {
        temp.size.width -= self.videoView.frame.size.width;
        temp.origin.x = 0;
        temp.origin.y = 0;
        self.webView.frame = temp;
    } else {
        temp.size.height -= self.videoView.frame.size.height;
        temp.origin.x = 0;
        temp.origin.y = 0;
        self.webView.frame = temp;
    }
    
    self.videoView.hidden = FALSE;
    
  • 然后我在buttonHangUp函数中执行相反的操作

发生了一些错误的事情:

  • 当我切换方向时,videoView并不总是移动或调整大小,当它移动时,移动通常会延迟(在其余项目旋转后一秒钟发生)
  • 当我切换到横向时,imageOne和imageTwo被水平压扁,并且不在我将其设置为对齐的对齐方式
  • 当我切换到肖像时,事情似乎一直很好。 videoView总是到正确的位置,因此它的子视图(imageOne,imageTwo和buttonHangUp)。
  • 当我将ipad平放而不改变方向时,imageOne和imageTwo从纵向视图中消失
  • 即使我将视图设置为在viewDidLoad中以不同的布局显示,它们也会重置为故事板中的布局

有人能告诉我这里发生了什么以及为什么会这样吗?这对我来说非常困惑。我认为它与坐标系统在webView和app本身的坐标之间切换,执行的不同函数的优先顺序(awakeFromNib,第一次从storyboard,viewDidLoad等设置的视图坐标)和重新绘制子视图,或者结合所有这些问题,甚至更多。我接下来将调查这些问题。

我还要感谢有人提到实现我想要的最佳实践。正如我所说,我对此不熟悉,但遗憾的是,苹果文档并没有涵盖我的案例中最佳做法。文章的链接也将受到赞赏。

2 个答案:

答案 0 :(得分:1)

嗯,你有一个非常长的问题,但我会给你一部分并告诉你为什么你的设备方向不能正常工作。

您未指定要为其生成通知的对象。

改变这个:

    [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(orientationChanged:) 
name:UIDeviceOrientationDidChangeNotification object:nil]

对此:

[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
        [[NSNotificationCenter defaultCenter]
         addObserver:self selector:@selector(orientationChanged:)
         name:UIDeviceOrientationDidChangeNotification
         object:[UIDevice currentDevice]];

另外值得注意的是,您没有充分利用通知中心的强大功能。你做了额外的工作,而没有抓住通知内发送的实际方向。您不需要每次都检查UIInterfaceOrientation,您可以从注释中抓取设备方向,如下所示:

- (void) orientationChanged:(NSNotification *)note
{
    UIDevice *device = note.object;
    switch(device.orientation)//do whatever you want in each orientation
    {
        case UIDeviceOrientationPortrait:
            break;
        case UIDeviceOrientationPortraitUpsideDown:
            break;
        case UIDeviceOrientationLandscapeLeft:
            break;
        case UIDeviceOrientationLandscapeRight:
            break;
        default:
            break;
    };
}

答案 1 :(得分:0)

我昨天经过几个小时的调试后修复了我的代码。以下是所有出错的事情,并希望能够以编程方式处理切换方向的有用指南:

  • 首先,在awakeFromNib中,不要放置任何处理cooridinates和位置的代码。 awakeFromNib在视图开始加载之前被调用,因此它对位置一无所知。在viewDidLoad中执行所有坐标初始化。
  • 其次,确保将autolayout设置为off,并为任何容器视图将autoresize子视图设置为off。这让我耽误了一段时间。
  • 第三,使用此处描述的调用设备方向的苹果方法:http://developer.apple.com/library/ios/#featuredarticles/ViewControllerPGforiPhoneOS/RespondingtoDeviceOrientationChanges/RespondingtoDeviceOrientationChanges.html#//apple_ref/doc/uid/TP40007457-CH7-SW14。我发现它比上面描述的状态栏方向更可靠。
  • 第四,这在上面的代码中是错误的并且是我的错误,请确保初始化您需要移动的所有组件的大小。上面用于在横向和纵向之间移动的CGRects已定义了原点,但没有大小,这导致我的视​​图在设置时消失。
  • 第五,最后,当滑块出现/消失时,确保对横向和纵向全局变量进行尺寸调整,因为如果设备被滑块向后翻转,则滑块上方的代码会模糊不清webView的一部分。

我仍然欢迎任何关于人们如何处理风景和肖像布局的评论!