ios - 当 UIDeviceOrientationDidChangeNotification 在 UIView 中捕获时,UIInterfaceOrientation 尚未更新

标签 ios objective-c uiview rotation autoresizingmask

我正在开发一个开源库来提供类似 iMessage 的文本输入 View - MessageComposerView (与问题有关)。 View 将像 inputAccessoryView 一样粘在键盘上并随着文本增长,但不会在键盘消失时消失。

我最近在旋转此自定义 UIView 时遇到了一个令人抓狂的问题,该自定义 UIView 仅在 View 已通过 initWithFrame 实例化时出现.如果 View 已通过 initWithFrame 实例化,则基本上是在捕获 UIDeviceOrientationDidChangeNotification 通知时。 ,UIInterfaceOrientation 和框架尚未更新。这是实例化的两种方式。
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通知:
  • UIDeviceOrientation = [[通知对象] 方向] = UIInterfaceOrientationLandscapeLeft
  • UIInterfaceOrientation = [UIApplication sharedApplication].statusBarOrientation = UIDeviceOrientationLandscapeRight
  • self.frame.size =(宽度=480,高度=90)

  • 这里需要注意的重要一点是界面和设备方向都是横向的,并且宽度已经更改为横向宽度(在 iPhone 6.1 模拟器上测试)。现在执行相同的测试,但使用 initWithFrame :
  • UIDeviceOrientation = [[通知对象] 方向] = UIDeviceOrientationLandscapeRight
  • UIInterfaceOrientation = [UIApplication sharedApplication].statusBarOrientation = UIInterfaceOrientationPortrait
  • self.frame.size =(宽度=320,高度=54)

  • 这次请注意界面方向仍然是纵向的,并且框架宽度没有更改为横向宽度。如果我在 setFrame:(CGRect)frame 中设置断点方法我可以看到,在 UIDeviceOrientationDidChangeNotification 被捕获和处理之后,框架被设置为景观框架。

    两种 init 方法的设置几乎相同:
    - (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进行必要的 View 调整:
    - (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];
    }
    

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

    我希望在程序设置中缺少某种自动旋转属性,该属性隐藏在 XIB 的某个地方,但就是找不到。我已经经历了大概十几个 UIDeviceOrientationDidChangeNotification stackoverflow 没有找到解决方案的帖子。

    最佳答案

    MessageComposerView 看起来很整洁,谢谢分享。

    而不是听UIDeviceOrientationDidChangeNotification , 你应该执行 layoutSubviews .它被调用以响应旋转和系统需要的任何其他 UIView重新定位其 subview (https://stackoverflow.com/a/5330162/1181421)。在那里,您可以相对于 UIView 定位您的 subview 。的框架,您可以确定该框架是正确的。

    关于ios - 当 UIDeviceOrientationDidChangeNotification 在 UIView 中捕获时,UIInterfaceOrientation 尚未更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19974246/

    相关文章:

    ios - Xcode6 ipa 分发问题

    ios - 文件存在于主线程上,但后台线程表示不存在(iOS)

    ios - 在 Objective-C 中解析 XML

    javascript - Phonegap(Cordova)图片上传到服务器太大

    objective-c - 诸如 `%15@` 之类的格式说明符在 NSLog 中有效,但不适用于 NSString stringWithFormat

    c++ - 你如何实现语法高亮?

    objective-c - UILabel 不会调整大小

    objective-c - 如何在 iOS 上找回图片的真实位置?

    ios - 设置 self.view = nil 的效果

    iphone - 如何设置 View 框架宽度? (为什么不能直接设置?)