如何获得正确大小的 UIView?

Posted

技术标签:

【中文标题】如何获得正确大小的 UIView?【英文标题】:How can I get the correct size of my UIView? 【发布时间】:2013-01-11 23:10:59 【问题描述】:

问题 1:

我正在创建一个 CGRect 来显示一些使用平铺层的图像。 当我创建 CGRect 时,我基本上需要它的大小与我的 UIView 的大小完全相同。事实证明这很难.. 当我 NSLog() 输出我的mainView.bounds.size.width 或我的mainView.frame.size.width 时,它们在横向时总是错误的!他们总是像在纵向一样注销值,即使我可以看到实际视图更宽。颠倒它们也将是错误的。 在横向时将宽度设置为高度是不够的,反之亦然,我需要正确的值。

我让它看起来正确的唯一方法是在横向时手动输入 1024 的宽度,但这也并不总是有效,因为:

问题 2:

检查设备是否处于横向状态的正确方法是什么?

我一直在用

if([UIDevice currentDevice].orientation == UIDeviceOrientationLandscapeLeft || [UIDevice currentDevice].orientation == UIDeviceOrientationLandscapeRight)

但这并不总是有效。如果我在启动时将设备保持在横向模式,这是正确的,但是如果我将其设为横向,则将 iPad 平放,将仪表板保持为横向,然后启动它,然后会出现横向飞溅,但该代码认为它是纵向的。 该代码也根本不适用于 iPad 模拟器..

编辑

由于某种原因,当我决定添加对横向方向的支持时,仅检查目标摘要页面中的横向方向是不够的,我必须将我的 TabBarController 子类化并实际告诉它与

一起旋转
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation

    return YES;

我不应该这样做..对吗?如果我创建一个这样的空项目,它就不需要它。我不知道为什么。

【问题讨论】:

我记得当我将标签栏控制器放在导航控制器内时遇到了类似的问题(Apple 表示不实施的不受支持的配置)。有没有可能是你正在做的事情? @lnafziger 不,但有时我在 tabBarController 中有导航控制器,但这也不应该是问题.. 是的,这完全可以接受......也许您可以上传您的应用程序,或者更好的是展示此行为的应用程序的小版本,以便我们可以更仔细地研究它。 @lnafziger 我不喜欢上传整个应用程序,所以我不得不用一个新项目重现这种情况,但我今天没有时间,如果我有时间可能会晚一点对当前的快速修复不满意。 【参考方案1】:

问题 1: 是的,没错。 :)

问题 2: 我刚回到家,检查了我自己的代码。我用:

UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];

检查当前界面的方向。然后,你可以使用类似的东西:

if(UIInterfaceOrientationIsPortrait(self.interfaceOrientation)) 
    // Do something
 else if(UIInterfaceOrientationIsLandscape(self.interfaceOrientation))
    // Do something else

但是如果您正确处理旋转事件,您真的不需要这样做。

当我需要根据方向调整代码中的 UI 元素位置时,这是我处理旋转的典型方式:

#pragma mark - View rotation methods

// Maintain pre-ios 6 support:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation

    return YES;


// Make sure that our subviews get moved on launch:
- (void)viewWillAppear:(BOOL)animated

    [super viewWillAppear:animated];

    UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
    [self moveSubviewsToOrientation:orientation duration:0.0];


- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration

    [super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];

    [self moveSubviewsToOrientation:toInterfaceOrientation duration:duration];


// Animate the movements
- (void)moveSubviewsToOrientation:(UIInterfaceOrientation)orientation duration:(NSTimeInterval)duration

    [UIView animateWithDuration:duration
                     animations:^
                         [self.tableView reloadData];
                         if (UIInterfaceOrientationIsPortrait(orientation))
                         
                             [self moveSubviewsToPortrait];
                         
                         else
                         
                             [self moveSubviewsToLandscape];
                         
                     
                     completion:NULL];


- (void)moveSubviewsToPortrait

    // Set the frames/etc for portrait presentation
    self.logoImageView.frame = CGRectMake(229.0, 21.0, 309.0, 55.0);


- (void)moveSubviewsToLandscape

    // Set the frames/etc for landscape presentation
    self.logoImageView.frame = CGRectMake(88.0, 21.0, 309.0, 55.0);

我还将moveSubviewsToOrientation 放入viewWillAppear 以使其旋转

【讨论】:

基本上它是从viewDidLoad调用的,但是当我在横向启动应用程序时,这不重要吗?还是应用程序总是将视图加载为纵向? self.interfaceOrientation 显然做同样的事情。从平坦的横向发射时,它仍然认为它是纵向的.. 是的,这就是我的猜测。根据我的经验,viewDidLoad 中尚未设置框架/边界。尝试按照我的建议移动它,看看你会得到什么。界面可能还没有旋转(视图控制器总是以纵向启动,然后旋转到横向)。 是的,我想这就是他的意思。无论如何,这些都不适合我.. self.interfaceOrientation 一直认为它是纵向的,即使我是横向的。为了确定,我将整个 viewDidLoad 放入 viewWillAppear 中,没有任何改变.. 我知道它应该如何工作,但它仍然没有.. :( 我现在尝试调用if(UIDeviceInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation]))NSLog(@"Landscape");elseNSLog(@"Portrait");,即使状态栏是横向的,它也会打印出“Portrait”。状态栏在我启动应用程序之前处于横向状态,它仍然认为它是纵向的。我尝试了几种方法,结果相同,我的设备显示为横向,但变量返回纵向。我不知道是什么去做。【参考方案2】:

我对此有点挣扎,以下是我发现的一些事实:

1- 当设备正面朝上或朝下时,设备会恢复到正面朝上或朝下之前的最后一个方向,因为这两个方向本身并不一定会告诉您设备是纵向还是横向。例如,如果您处于横向模式,然后将设备平面朝上,然后启动应用程序,它将以横向方向启动。

2- 调用 viewDidLoad 时,尚未设置边界,因此您需要将任何与方向相关的调用放入 viewWillAppear 或 viewDidLayoutSubviews 中。

3- 如果出于某种奇怪的原因,您需要在 viewDidLoad 之前使用边界,或者可能在模型中做某事,我发现放置与方向有关的设置的最佳方法是信任状态栏,例如,您可以按如下方式调用。

if(UIInterfaceOrientationIsPortrait([[UIApplication sharedApplication] statusBarOrientation]))

PS:关于您添加的问题,请参阅: https://developer.apple.com/library/ios/#qa/qa2010/qa1688.html

您很可能是最后两颗子弹中的一颗。我之前遇到过这个问题,坦率地说,我发现它最容易实现:

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation;

为了安全起见,特别是行为已从 iOS5 更改为 iOS6 的所有 VC。

http://developer.apple.com/library/ios/#featuredarticles/ViewControllerPGforiPhoneOS/RespondingtoDeviceOrientationChanges/RespondingtoDeviceOrientationChanges.html#//apple_ref/doc/uid/TP40007457-CH7-SW1

希望对你有帮助

【讨论】:

嗯,现在我开始认为我的设备或我的代码有问题..这行代码根本不起作用..它总是说这里是肖像.. 回读您的问题,我没有在模拟器模式下测试我的 cmets(关于您的 ipad 评论)。另一方面,当你说这行代码不起作用时,你的意思是在 viewDidLoad 还是 ViewDidAppear 中?还要确保在这些方法中调用 super。 我还是觉得哪里有问题。这最初只是一个 iPhone 应用程序,现在我正在添加对 iPad 的支持,并且我想要它的横向。现在我只有一个 TabBar 连接了一个 UIView。我已经对 TabBarController 进行了子类化,将 shouldAutorotate..:YES 添加到它们两者中,并且它确实会旋转,但是如果它以横向方式启动,则所有不同的 if 语句都会返回纵向。如果我在 didAutorotate (或其他任何名称)中添加代码,它就会正确。问题是,在横向启动时,我的屏幕右侧出现了这个巨大的白色间隙,就像纵向一样.. 你看到我下面的评论了吗,我说界面总是以纵向启动,然后旋转到横向(当您处于横向模式时)?只要你正确地实现了它们,只要你在 viewDidRotate 中调用适当的方法来更新适当的方向,它启动什么都没关系... @Inafziger。有趣的。对 iphone 似乎是正确的,但对 iPad 却不是; iPad 始终以最后一个状态栏方向启动。同样,我没有使用模拟器。

以上是关于如何获得正确大小的 UIView?的主要内容,如果未能解决你的问题,请参考以下文章

如何获得旋转的 UIView 的正确框架(包括正确的位置)

如何在 UITableViewCell swift 中获得正确的 UIView 宽度

使用多个 UIView 获得正确的视角

如何使用 drawRect 覆盖在 UIView 子类的某些区域中获得透明度

如何使用 imageio 调整图像大小以获得正确的 ICO 文件?

如何获得 ImageRendition 大小?