我在获取高度和宽度的准确读数方面遇到了问题。所以我制作了这个快速而又脏的应用来测试这种情况。
以下是代码:
@interface wwfpViewController ()
@property (nonatomic, strong) UIView * box;
@property (nonatomic, strong) UILabel * info;
@end
@implementation wwfpViewController
@synthesize box,info;
- (void)viewDidLoad {
[super viewDidLoad];
box=[[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
[box setBackgroundColor:[UIColor darkGrayColor]];
[box setAutoresizesSubviews:YES];
[box setAutoresizingMask:UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth];
info=[[UILabel alloc] initWithFrame:CGRectMake(10, 10, 300, 300)];
[info setTextColor:[UIColor whiteColor]];
[info setBackgroundColor:[UIColor blackColor]];
[info setLineBreakMode:NSLineBreakByWordWrapping];
[info setNumberOfLines:10];
[info setText:@"..."];
[self.view addSubview:box];
[box addSubview:info];
[self updateInfo];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(updateView:)
name:UIApplicationDidChangeStatusBarOrientationNotification
object:nil];
}
- (void) updateInfo {
CGFloat selfHeight=self.view.frame.size.height;
CGFloat selfWidth=self.view.frame.size.width;
CGFloat boxHeight=box.frame.size.height;
CGFloat boxWidth=box.frame.size.width;
int deviceOrientation=[[UIDevice currentDevice] orientation];
int statusOrientation=[[UIApplication sharedApplication] statusBarOrientation];
NSString * str=[NSString stringWithFormat:@"[height x width] \nself: [%f x %f] \nbox: [%f x %f] \ndevice: %d status: %d",selfHeight,selfWidth,boxHeight,boxWidth,deviceOrientation,statusOrientation];
[info setText:str];
}
- (void) updateView: (NSNotification*) notify {
[self updateInfo];
}
@end
当我在iPad上测试时,最初是在纵向模式下,信息标签会报告以下内容:
[height x width]
self: [1004.000000 x 768.000000]
box: [1004.000000 x 768.000000]
device: 0 status: 1
这是正确的!
然后当我将iPad旋转到风景时,我得到了这些读数:
[height x width]
self: [768.000000 x 1004.000000]
box: [1004.000000 x 768.000000]
device: 3 status: 3
实际高度x宽度:748 x 1024
但是当我在iPad上横向测试时,信息标签会报告:
[height x width]
self: [1024.000000 x 748.000000]
box: [1024.000000 x 748.000000]
device: 0 status: 3
实际高度x宽度:748 x 1024
然后当我将iPad旋转为肖像时,我得到了这些读数:
[height x width]
self: [748.000000 x 1024.000000]
box: [748.000000 x 1024.000000]
device: 1 status: 1
实际高度x宽度:1004 x 768
我将它旋转回风景,然后我得到这些读数:
[height x width]
self: [768.000000 x 1004.000000]
box: [1004.000000 x 768.000000]
device: 3 status: 3
实际高度x宽度:748 x 1024
在所有情况下,box
UIView都会覆盖整个屏幕,因此会自动调整方向更改。这些结果与模拟器一致并在实际的iPad上进行测试,我在iPhone上也有类似的经历。
在此之后,我有几个问题:
self.view
的高度和宽度与box
的高度和宽度不同,当两者在视觉上完全相同时?[UIDevice ... orientation]
在第一次使用时报告为零,我应该完全忽略它并坚持使用[UIApplication ... statusBarOrientation]
吗?答案 0 :(得分:10)
检查视图的边界而不是框架:
CGFloat selfHeight=self.view.bounds.size.height;
CGFloat selfWidth=self.view.bounds.size.width;
CGFloat boxHeight=box.bounds.size.height;
CGFloat boxWidth=box.bounds.size.width;
另外,我会使用UIViewController
方法进行方向更改并删除NSNotificationCenter
观察者。
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
[self updateInfo];
}
最后,要获得正确尺寸的第一次调用应位于viewWillAppear
,因为它在viewDidLoad
中不正确:
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self updateInfo];
}
答案 1 :(得分:1)
我尝试了你的代码,发现了一个错误。
错误原因您没有根据navigationController
制作应用appdelegate
。将window
的{{1}} rootViewController
设置为navigationController
不知道原因,但基于viewController
的视图未提供正确的框架。
我的意见 - 如果您已经在方向更改后调用方法
notification
,请不要在此使用-(void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
。那么你正在使用notification
然后NP这只是我的意见。
我想说的另一件事
box = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
你为什么不这么做?
box = [[UIView alloc] initWithFrame:self.view.bounds];
您的代码没问题。只需将窗口的rootViewController设置为navigationController或tabbarController。
这是Sample Code。
答案 2 :(得分:0)
来自Apple文档
讨论当视图的边界发生变化时,该视图会自动更改 根据每个子视图的自动调整遮罩调整其子视图的大小。 您可以通过组合常量来指定此掩码的值 在UIViewAutoresizing中使用C按位OR运算符描述。 通过组合这些常量,您可以指定哪些尺寸 视图应相对于superview增长或缩小。默认 此属性的值是UIViewAutoresizingNone,表示该属性 视图不应该调整大小。
如果设置了同一轴上的多个选项,则为默认值 行为是按比例分配大小差异 灵活的部分。柔性部分相对于柔性部分越大 其他柔性部分,它可能越多。例如, 假设此属性包含UIViewAutoresizingFlexibleWidth和 UIViewAutoresizingFlexibleRightMargin常量但不包括 UIViewAutoresizingFlexibleLeftMargin常量,从而表明 视图左边距的宽度是固定的,但视图的宽度是固定的 宽度和右边距可能会改变。因此,视图似乎锚定于 其超视图的左侧同时具有视图宽度和间隙 在视图右侧增加。
如果自动调整行为不能提供您的精确布局 需要您的视图,您可以使用自定义容器视图和覆盖 它的layoutSubviews方法可以更精确地定位您的子视图。
这可能与autoresizing masks
有关,请参阅here。
答案 3 :(得分:0)
myview = [[UIView alloc] initWithFrame:CGRectMake(0,0,self.view.frame.size.width,self.view.frame.size.height)];
为我工作
答案 4 :(得分:0)
我制作了宏vWidth
和vHeight
,它们可以正确处理所有这些逻辑,并且具有后备功能:
#define sWidth [[UIScreen mainScreen] bounds].size.width
#define sHeight [[UIScreen mainScreen] bounds].size.height
#define vWidth (\
(^float (void){\
BOOL isClassMethod = [[self class] respondsToSelector:_cmd];\
if (isClassMethod) {\
return sWidth;\
} else {\
float __vWidth = ([self isKindOfClass:[UIViewController class]]?((UIViewController *)self).view.frame.size.width:((UIView *)self).frame.size.width);\
if (!__vWidth) {\
__vWidth = ([self isKindOfClass:[UIViewController class]]?((UIViewController *)self).view.superview.frame.size.width:((UIView *)self).superview.frame.size.width);\
}\
if (!__vWidth) {\
__vWidth = sWidth;\
}\
return __vWidth;\
}\
})()\
)
#define vHeight (\
(^float (void){\
BOOL isClassMethod = [[self class] respondsToSelector:_cmd];\
if (isClassMethod) {\
return sHeight;\
} else {\
float __vHeight = ([self isKindOfClass:[UIViewController class]]?((UIViewController *)self).view.frame.size.height:((UIView *)self).frame.size.height);\
if (!__vHeight) {\
__vHeight = ([self isKindOfClass:[UIViewController class]]?((UIViewController *)self).view.superview.frame.size.height:((UIView *)self).superview.frame.size.height);\
}\
if (!__vHeight) {\
__vHeight = sHeight;\
}\
return __vHeight;\
}\
})()\
)