【问题标题】:UIInterfaceOrientation not yet updated when UIDeviceOrientationDidChangeNotification caught in UIView当 UIDeviceOrientationDidChangeNotification 在 UIView 中捕获时,UIInterfaceOrientation 尚未更新
【发布时间】:2013-11-17 10:27:15
【问题描述】:

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

我最近在旋转此自定义 UIView 时遇到了一个令人抓狂的问题,该自定义 UIView 仅在视图已通过 initWithFrame 实例化时出现。如果视图已通过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 被捕获和处理之后,框架被设置为横向框架。

两种初始化方法的设置几乎相同:

- (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 进行必要的视图调整:

- (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 的时间。我使用此通知进行框架调整,并且需要已将宽度更新为横向宽度。

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

【问题讨论】:

  • 您可以删除初始化代码中的self.frame = frame; 行。对super 的调用应该已经这样做了。

标签: ios objective-c uiview rotation autoresizingmask


【解决方案1】:

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

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

【讨论】:

  • 我非常感谢你。我一直专注于解决为什么在捕获UIDeviceOrientationDidChangeNotification 时尚未调整框架大小,以至于我完全忽略了在其他地方进行重新配置的可能性。我仍然很好奇为什么会出现这个问题,但从我期待 UIDeviceOrientation 更改的确切时刻 UIInterfaceOrientation 更改这一事实来看,我认为我的方法一开始就有缺陷。
猜你喜欢
  • 2016-12-12
  • 1970-01-01
  • 1970-01-01
  • 2021-01-29
  • 1970-01-01
  • 2016-03-01
  • 2016-08-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多