UIBarButtonItem with separate portrait and landscape images - layoutSubviews not called when popping a view controller from UINavigationController

大憨熊 提交于 2019-12-10 20:08:02

问题


I want to show completely custom buttons in UINavigationController's UIToolbar, and support portrait and landscape. Currently I have implemented a RotatingButton (a UIView subclass) class, which contains one UIButton that fills the whole RotatingButton frame. A RotatingButton also contains two images, for portrait and landscape orientations, and the heights of these images differ. Then this RotatingButton gets wrapped into UIBarButtonItem as a custom view.

Currently, in RotatingButton's layoutSubviews, I am setting the whole view's bounds, and setting the button the appropriate image for the current orientation. This works well and handles rotations as desired.

- (void) createLayout {
    [self addButtonIfNeeded];
    UIDeviceOrientation currentOrientation = [[UIDevice currentDevice] orientation];
    if(UIInterfaceOrientationIsLandscape(currentOrientation)) {
        [self.button setImage:self.landscapeImage forState:UIControlStateNormal];
        self.button.frame = CGRectMake(0.0, 0.0, self.landscapeImage.size.width / 2, self.landscapeImage.size.height / 2);
        self.bounds = CGRectMake(0.0, 0.0, self.landscapeImage.size.width / 2, self.landscapeImage.size.height / 2);
    } else {
        [self.button setImage:self.portraitImage forState:UIControlStateNormal];
        self.button.frame = CGRectMake(0.0, 0.0, self.portraitImage.size.width / 2, self.portraitImage.size.height / 2);
        self.bounds = CGRectMake(0.0, 0.0, self.portraitImage.size.width / 2, self.portraitImage.size.height / 2);
    }
}

- (void) layoutSubviews {
    [super layoutSubviews];
    [self createLayout];
}

However, this problem remains:

  1. Starting view at portrait orientation
  2. Push a view controller onto stack
  3. Rotate the device to landscape (the current view reacts appropriately)
  4. Pop the last view controller: the previous view reacts otherwise well, but the RotatingButtons' layoutSubviews don't get called, and the buttons remain larger than they should.

So, currently after popping a view controller, the previous UIBarButtonItems don't have their layoutSubviews called, and they remain too large (or too small, if we start from landscape and rotate to portrait in another view). How to solve this problem?


回答1:


This is a really tricky question. You should try overriding viewWillAppear: to call [self.view setNeedsLayout] to force a layout update whenever the view is about to appear.




回答2:


I didn't find a completely satisfactory solution, but my buttons happened to be of suitable size, and this kind of a solution worked very well for me:

UIBarButtonItem* b = [[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStylePlain target:target action:selector];
UIImage *barButton = [portraitImage resizableImageWithCapInsets:UIEdgeInsetsMake(10, 10, 10, 10)];
UIImage *barButton_land = [landscapeImage resizableImageWithCapInsets:UIEdgeInsetsMake(10, 10, 10, 10)];
[b setBackgroundImage:barButton forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
[b setBackgroundImage:barButton_land forState:UIControlStateNormal barMetrics:UIBarMetricsLandscapePhone];

And then obviously adding the created button as rightBarButtonItem/leftBarButtonItem, or as you may want to use it.

The problem with this is that if your buttons are not wide enough, the buttons may look completely wrong (since the middle content of the image is tiled in this solution).



来源:https://stackoverflow.com/questions/15569478/uibarbuttonitem-with-separate-portrait-and-landscape-images-layoutsubviews-not

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!