在UIView中捕获UIDeviceOrientationDidChangeNotification时,UIInterfaceOrientation尚未更新 [英] UIInterfaceOrientation not yet updated when UIDeviceOrientationDidChangeNotification caught in UIView

查看:115
本文介绍了在UIView中捕获UIDeviceOrientationDidChangeNotification时,UIInterfaceOrientation尚未更新的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个开放源代码库,以提供类似于iMessage的文本输入视图- MessageComposerView (与问题相关).视图将像inputAccessoryView一样粘在键盘上,并随文本一起增长,但不会在键盘显示时消失.

I'm working on an open source library to provide an iMessage-like text input view - MessageComposerView (relevant to question). The view will stick to the keyboard like an inputAccessoryView and grow with text, but won't disappear when the keyboard does.

我最近在旋转这个自定义UIView时遇到了一个令人困扰的问题,该自定义UIView仅在通过initWithFrame实例化视图时才会出现.基本上,如果通过initWithFrame实例化了视图,则在捕获到UIDeviceOrientationDidChangeNotification通知时,UIInterfaceOrientation和框架尚未更新.这是两种实例化方式.

I have recently run into a maddening issue when rotating this custom UIView that only appears if the view has been instantiated via initWithFrame. Basically at the point when a UIDeviceOrientationDidChangeNotification notification has been caught if the view has been instantiated via initWithFrame, the UIInterfaceOrientation and frame have NOT yet been updated. Here are both ways instantiating.

loadNibNamed:

self.messageComposerView = [[NSBundle mainBundle] loadNibNamed:@"MessageComposerView" owner:nil options:nil][0];
self.messageComposerView.frame = CGRectMake(0,
                                            self.view.frame.size.height - self.messageComposerView.frame.size.height,
                                            self.messageComposerView.frame.size.width,
                                            self.messageComposerView.frame.size.height);

initWithFrame:

self.messageComposerView = [[MessageComposerView alloc] initWithFrame:CGRectMake(0, self.view.frame.size.height-54, 320, 54)];

在通过loadNibNamed初始化并旋转为横向时,在收到UIDeviceOrientationDidChangeNotification通知后:

When init via loadNibNamed and rotated to landscape, upon receiving a UIDeviceOrientationDidChangeNotification notification:

  • UIDeviceOrientation = [[通知对象]方向] = UIInterfaceOrientationLandscapeLeft
  • UIInterfaceOrientation = [UIApplication sharedApplication] .statusBarOrientation = UIDeviceOrientationLandscapeRight
  • self.frame.size =(宽度= 480,高度= 90)
  • UIDeviceOrientation = [[notification object] orientation] = UIInterfaceOrientationLandscapeLeft
  • UIInterfaceOrientation = [UIApplication sharedApplication].statusBarOrientation = UIDeviceOrientationLandscapeRight
  • self.frame.size = (width=480, height=90)

此处要注意的是,界面和设备方向均为横向,并且宽度已更改为横向宽度(在iPhone 6.1仿真器上测试).现在执行相同的测试,但使用initWithFrame:

Important to note here is that both the interface and device orientations are landscape and the width has already been changed to landscape width (testing on iPhone 6.1 simulator). Now performing the same test but using initWithFrame:

  • UIDeviceOrientation = [[通知对象]方向] = UIDeviceOrientationLandscapeRight
  • UIInterfaceOrientation = [UIApplication sharedApplication] .statusBarOrientation = UIInterfaceOrientationPortrait
  • self.frame.size =(宽度= 320,高度= 54)
  • UIDeviceOrientation = [[notification object] orientation] = UIDeviceOrientationLandscapeRight
  • UIInterfaceOrientation = [UIApplication sharedApplication].statusBarOrientation = UIInterfaceOrientationPortrait
  • self.frame.size = (width=320, height=54)

这次,请注意界面方向仍为纵向,并且框架宽度未更改为横向宽度.如果我在setFrame:(CGRect)frame方法中设置了一个断点,则可以看到在捕获并处理了UIDeviceOrientationDidChangeNotification之后,该框架已设置为风景"框架.

This time notice that the interface orientation is still portrait and that the frame width has NOT changed to landscape width. If I set a breakpoint in the setFrame:(CGRect)frame method I can see that the frame is set to the Landscape frame AFTER the UIDeviceOrientationDidChangeNotification has been caught and handled.

两个init方法的设置几乎相同:

Both init methods have almost identical setup:

- (id)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code
        self.frame = frame;
        self.sendButton = [[UIButton alloc] initWithFrame:CGRectZero];
        self.messageTextView = [[UITextView alloc] initWithFrame:CGRectZero];
        [self setup];
        [self addSubview:self.sendButton];
        [self addSubview:self.messageTextView];

    }
    return self;
}

- (void)awakeFromNib {
    [super awakeFromNib];
    [self setup];
}

使用setup进行必要的视图调整:

With setup doing necessary view tweaks:

- (void)setup {
    self.backgroundColor = [UIColor lightGrayColor];
    self.autoresizesSubviews = YES;
    self.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleWidth;
    self.userInteractionEnabled = YES;
    self.multipleTouchEnabled = NO;

    CGRect sendButtonFrame = self.bounds;
    sendButtonFrame.size.width = 50;
    sendButtonFrame.size.height = 34;
    sendButtonFrame.origin.x = self.frame.size.width - kComposerBackgroundRightPadding - sendButtonFrame.size.width;
    sendButtonFrame.origin.y = kComposerBackgroundRightPadding;
    self.sendButton.frame = sendButtonFrame;
    self.sendButton.autoresizingMask = UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleLeftMargin;
    self.sendButton.layer.cornerRadius = 5;
    [self.sendButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
    [self.sendButton setTitleColor:[UIColor colorWithRed:210/255.0 green:210/255.0 blue:210/255.0 alpha:1.0] forState:UIControlStateHighlighted];
    [self.sendButton setTitleColor:[UIColor grayColor] forState:UIControlStateSelected];
    [self.sendButton setBackgroundColor:[UIColor orangeColor]];
    [self.sendButton setTitle:@"Send" forState:UIControlStateNormal];
    self.sendButton.titleLabel.font = [UIFont boldSystemFontOfSize:14];


    CGRect messageTextViewFrame = self.bounds;
    messageTextViewFrame.origin.x = kComposerBackgroundLeftPadding;
    messageTextViewFrame.origin.y = kComposerBackgroundTopPadding;
    messageTextViewFrame.size.width = self.frame.size.width - kComposerBackgroundLeftPadding - kComposerTextViewButtonBetweenPadding - sendButtonFrame.size.width - kComposerBackgroundRightPadding;
    messageTextViewFrame.size.height = 34;
    self.messageTextView.frame = messageTextViewFrame;
    self.messageTextView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleBottomMargin;
    self.messageTextView.showsHorizontalScrollIndicator = NO;
    self.messageTextView.layer.cornerRadius = 5;
    self.messageTextView.font = [UIFont systemFontOfSize:14];
    self.messageTextView.delegate = self;

    [self addNotifications];
    [self resizeTextViewForText:@"" animated:NO];
}

所以我的问题是,为什么通过initWithFrame我的自定义UIView初始化仍然具有纵向框架和界面方向以及接收UIDeviceOrientationDidChangeNotification的时间.我使用此通知进行帧调整,并且需要将其宽度更新为横向宽度.

So my question is, why does my custom UIView init via initWithFrame still have the portrait frame and interface orientation and the time when the UIDeviceOrientationDidChangeNotification is received. I use this notification to do my frame adjustment and need the width to have already been updated to the landscape width.

我希望在程序化设置中缺少某种自动旋转属性,该属性隐藏在XIB中,但找不到它.我遍历了十几个UIDeviceOrientationDidChangeNotification stackoverflow帖子,但没有找到解决方案.

I'm hoping there is some kind of autorotation property that I'm missing in the programmatical setup that is buried somewhere in the XIB but just can't find it. I've gone through probably a dozen UIDeviceOrientationDidChangeNotification stackoverflow posts without finding a solution.

推荐答案

MessageComposerView看起来很整洁,感谢分享.

MessageComposerView looks neat, thanks for sharing.

您应该实现layoutSubviews,而不是听UIDeviceOrientationDidChangeNotification.调用它是为了响应旋转,系统需要使用UIView来重新定位其子视图( https://stackoverflow.com/a/5330162/1181421 ).您可以在其中相对于UIView的框架放置子视图,并且可以确保框架正确无误.

Instead of listening to the UIDeviceOrientationDidChangeNotification, you should implement layoutSubviews. It is called in response to rotation and anything else the system would need the UIView to reposition its subviews (https://stackoverflow.com/a/5330162/1181421). There you can position your subviews relative to the UIView's frame, and you can be sure that the frame will be correct.

这篇关于在UIView中捕获UIDeviceOrientationDidChangeNotification时,UIInterfaceOrientation尚未更新的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆