如何检测程序化生成的UIView的旋转?

11

我有一个通过编程方式创建的UIView:

- (id)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:CGRectMake(0, 0, frame.size.width, frame.size.height)];
    if (self) {
        self.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:.5];

        UIImageView* closeButton = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"modal_close.png"]];

        closeButton.frame = CGRectMake(self.frame.size.width*.89, self.frame.size.height*.09, closeButton.frame.size.width, closeButton.frame.size.height);

        UIButton* button = [[UIButton alloc] initWithFrame:CGRectMake(self.frame.size.width*.89, self.frame.size.height*.09,20, 20)];

        [button addTarget:self action:@selector(close) forControlEvents:UIControlEventTouchUpInside];

        UIView* mainView = [[UIView alloc] initWithFrame:CGRectMake(self.frame.size.width*.1,self.frame.size.height*.1,self.frame.size.width*.8,self.frame.size.height*.8)];

        mainView.backgroundColor = [UIColor whiteColor];
        _displayMainView = mainView;        

        [self addSubview:_displayMainView];
        [self addSubview:closeButton];
        [self addSubview:button];

        mainView = nil;
        closeButton = nil;
    }
    return self;
}

我该如何检测旋转?该检测用于作为现有视图之上的模态视图。这是一个只针对iPad的应用,如果这一点有所影响。


你是指UIVIew的旋转角度还是设备的方向? - Marcelo Cantos
请查看这个优秀的答案 - https://dev59.com/Y3RB5IYBdhLWcg3wZmhz#3897243 - beryllium
3个回答

43

你可以让设备开始生成旋转通知:

  [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];

将您自己的选择器添加为设备旋转通知的观察者:

      [[NSNotificationCenter defaultCenter] addObserver: self selector:   @selector(deviceOrientationDidChange:) name: UIDeviceOrientationDidChangeNotification object: nil];

然后编写您的通知处理程序

- (void)deviceOrientationDidChange:(NSNotification *)notification {
     //Obtain current device orientation
     UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];

      //Do my thing
 }

记得在你的自定义UIView的dealloc方法被调用时(或者你完成时),移除观察者并停止产生设备变更通知。

-(void) dealloc{
[[NSNotificationCenter defaultCenter] removeObserver: self];
[[UIDevice currentDevice] endGeneratingDeviceOrientationNotifications];
}

这对你的问题有所帮助吗?


3
不要使用此选项,因为它会激活设备的加速度计。 加速度计会一直保持激活状态,直到您调用 endGeneratingDeviceOrientationNotifications。但如果您的视图是单元格视图,则它将永远不会被释放,除非您释放表视图(这很可能不会发生)。您可以改用 if UIScreen.main.bounds.height > UIScreen.main.bounds.width 来代替。 - Edward Anthony

6

我正在为Swift 3重写@clearwater82的答案,因为我最终使用了他的方法:

我在我的视图的init方法中添加了以下代码(对于控制器来说,它将在其viewDidLoad方法中):

// Handle rotation
UIDevice.current.beginGeneratingDeviceOrientationNotifications()
NotificationCenter.default.addObserver(
    self,
    selector: #selector(self.orientationChanged(notification:)),
    name: NSNotification.Name.UIDeviceOrientationDidChange,
    object: nil
)

我随后在我的视图中添加了orientationChanged方法。 您可以根据需要重命名此方法,但请记得在上面的代码片段中同时更改它:

// Called when device orientation changes
@objc func orientationChanged(notification: Notification) {
    // handle rotation here
}

最后,我添加了deinit方法,在视图被移除时移除不必要的通知:
deinit {
    NotificationCenter.default.removeObserver(self)
    UIDevice.current.endGeneratingDeviceOrientationNotifications()
}

这段代码的作用是将视图从通知观察者中移除,然后停止设备生成其他旋转通知。这种方法对我很有用,但您可能不希望在移除视图时停止生成通知。
希望这对您有所帮助,祝好!

名称:UIDevice.orientationDidChangeNotification。适用于Swift 5。 - Guilherme

4
我认为你有两个选择:
  1. 将视图放在自定义的UIViewController中,并覆盖shouldAutorotateToInterfaceOrientation:方法,使其返回您想支持的所有方向的YES。视图控制器将自动旋转和调整内容(您的视图)。你只需确保具有正确的autoresizeMask(如果使用autolayout,则为约束)。
  2. 直接通过加速度计观察设备方向的变化。然后在需要时调整您的视图。
如果可以的话,第一种方法确实是您应该选择的方法。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接