【问题标题】:Understanding coordinates, views, subviews, and orientation changes了解坐标、视图、子视图和方向变化
【发布时间】:2013-02-26 18:12:47
【问题描述】:

所以,我正在为 iPad 构建一个 iOS 应用程序。该应用程序中嵌入了视频聊天。我已经得到了视频聊天、通知等所有工作。我的问题是界面。顺便说一句,我是 iOS 编程的菜鸟;我两周前才开始这样做。抱歉,如果这篇文章有点长,我只是想强调一下这里可能发生的一切以及我的思考过程。欢迎任何批评。

我有一个显示大部分信息的 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];
    }
    
  • 我按照苹果文档中的描述实现了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 - 如果我需要设置它们,请纠正我相对于其他东西;我看到它们在情节提要中相对于 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 和应用程序本身的坐标之间切换的坐标系统、执行的不同函数的优先顺序(awakeFromNib、第一次从情节提要设置的视图坐标、viewDidLoad 等)以及重新绘制子视图,或者结合所有这些问题,可能还有更多。接下来我将调查这些问题。

如果有人提到实现我想要的最佳实践,我也将不胜感激;正如我所说,我对此并不陌生,不幸的是,苹果文档并未涵盖就我的案例而言被认为是最佳实践的内容。文章链接也将不胜感激。

【问题讨论】:

  • 我刚刚意识到其中很大一部分是我启用了自动布局和自动调整大小,当方向改变时,应用程序会随意调整视图大小;在我完成所有问题的调试后,我将在此处发布一个完整的解决方案,除非有人来发布一个。我仍然希望我的解决方案/答案中有任何 cmets 让我更清楚。谢谢!

标签: iphone ios objective-c ipad uistoryboard


【解决方案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;
    };
}

【讨论】:

  • 第一部分不是必须的;参考此页面上的文档:developer.apple.com/library/mac/#documentation/Cocoa/Reference/… 您可以看到该对象是您要从中接收通知的对象,如果您将其设置为 nil,它将接收来自所有可以生成它的来源的通知。唯一可以生成 UIDeviceOrientationDidChangeNotification 的对象是设备,所以不需要设置。感谢第二部分;我喜欢!
【解决方案2】:

昨天经过几个小时的调试,我修复了我的代码。以下是所有出错的地方,希望对如何以编程方式处理切换方向有帮助:

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

我仍然欢迎任何关于人们如何处理横向和纵向布局的 cmets!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-06-01
    • 2013-07-05
    • 1970-01-01
    • 2017-03-10
    • 2022-10-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多