Search code examples
iosuimenucontroller

Is it possible to Rotate/Affine Transform UIMenuController


Without going into the 'why' of it all, I have UITextField that is part of a view hierarchy that is forcibly 'upside down' on screen via an affine transform.

CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(180))

This works fine for all of the subviews -- including the UITextField -- until the user wants to use the copy/paste features of UIMenuController on the text field content. When the UIMenuController is shown, it is 'right side up' rather than 'upside down' like the UITextField.

Is there anyway to get a hold of the UIMenuController's view to apply the same transform when it is shown?

Currently, I am listening for the UIMenuControllerWillShowMenuNotification notification and then getting the UIMenuController. But I can't seem to find a way to apply the transform to it. Any ideas?

- (void)textFieldDidBeginEditing:(UITextField *)textField {
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(menuControllerWillShow:) name:UIMenuControllerWillShowMenuNotification object:nil];

}

- (void)menuControllerWillShow:(NSNotification*)aNotification {

    UIMenuController* menuController = [UIMenuController sharedMenuController];
    CGAffineTransform xform = CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(180));

    CGRect oldRect = menuController.menuFrame;
    CGRect newRect = CGRectApplyAffineTransform(oldRect, xform);   

    // eh... now what? 
}

Solution

  • I don't think you can modify the UIMenuController so it's upside down.

    But if it's pretty much your entire app that's altered, you could either check the device orientation or the app orientation (by checking where the status bar is) and force it to be the opposite.

    To get the device orientation you could do something like this:

    UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation]
    

    Note from the docs:

    The value of this property always returns 0 unless orientation notifications have been enabled by calling beginGeneratingDeviceOrientationNotifications.

    Or get the app orientation with this:

    UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
    
    if(orientation == 0) //Default orientation 
    {
        //UI is in Default (Portrait) -- this is really a just a failsafe. 
    }
    else if(orientation == UIInterfaceOrientationPortrait)
    { 
        //Do something if the orientation is in Portrait
    }
    else if(orientation == UIInterfaceOrientationLandscapeLeft)
    {     
       // Do something if Left
    }
    else if(orientation == UIInterfaceOrientationLandscapeRight)
    {    
        //Do something if right
    }
    

    and then set it with something like this:

    Objective-C:

    NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeLeft];
    [[UIDevice currentDevice] setValue:value forKey:@"orientation"];
    

    Swift:

    let value = UIInterfaceOrientation.LandscapeLeft.rawValue
    UIDevice.currentDevice().setValue(value, forKey: "orientation")