简体   繁体   中英

Reuse same UIView on multiple UIViewControllers

Background - I have an app with three UIVIewControllers that act like sub-apps ie they show very different content from each other (but are similarly themed). For example you could have an 'animals app' and the three UIViewControllers could be 'dog', 'cat', 'rabbit'. These have a UINavigationBar with a 'settings' button that loads a custom UIView . This UIView animates onto the screen and shows settings specific to that UIViewController .

Problem - I would like to have one UIView that can get called by any of the UIViewControllers but it's contents, in this case a submenu, would be specific to that 'sub app'.

My progress so far - I have managed to get the UIView working fine if the code is all written in the same UIViewController which calls it. What is the correct way of creating the UIView , calling it with parameters (such as what to put in the submenu).

At the moment I have the following code on the NavigationItem.rightBarButtonItem:

-(void)showSettings:(id)sender
{
    if (_menuCounter == 0) {
        [self addOverlay];
        _settingsSubView = [[UIView alloc] initWithFrame:CGRectMake((_screenWidth * 0.5), (_barHeight - (_screenHeight * 0.5)), (_screenWidth * 0.5), (_screenHeight * 0.5))];
        _settingsSubView.backgroundColor = [UIColor purpleColor];
        NSLog(@"Settings width  = %fl", _barHeight);
        NSLog(@"Screen width    = %fl", _screenWidth);
        NSLog(@"Settings X      = %fl, Settings height = %fl", _settingsSubView.frame.origin.x, _settingsSubView.frame.size.height);

        UITableView *settingsTSV = [[UITableView alloc] initWithFrame:CGRectMake((_screenWidth * 0.05), (_barHeight), (_screenWidth * 0.4), (_screenHeight * 0.4))];

        UIButton *settingsCloseBtn = [[UIButton alloc] init];
        [settingsCloseBtn setFrame:CGRectMake((_screenWidth * 0.4), (_screenHeight * 0.45), (_screenWidth * 0.1), (_screenHeight * 0.05))];

        [settingsCloseBtn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
        [settingsCloseBtn setTitle:@"Close" forState:UIControlStateNormal];
        [settingsCloseBtn addTarget:self action:@selector(closeMenu)forControlEvents:UIControlEventTouchUpInside];
        [settingsCloseBtn setContentHorizontalAlignment:UIControlContentHorizontalAlignmentCenter];

        [_settingsSubView addSubview:settingsTSV];
        [_settingsSubView addSubview:settingsCloseBtn];

        [self.view addSubview:_settingsSubView];
        [self openMenu];
    } else {
        [self closeMenu];
    }
}
-(void)closeMenu
{
    _menuCounter = 0;
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationCurve:UIViewAnimationCurveLinear];
    [UIView setAnimationDuration:0.3f];
    [_settingsSubView setFrame:CGRectMake((_screenWidth * 0.5), (_barHeight - (_screenHeight * 0.9)), (_screenWidth * 0.5), (_screenHeight * 0.5))];
    [UIView commitAnimations];
    NSLog(@"%fl",_settingsSubView.frame.origin.y);
    [_overlayView removeFromSuperview];
}
-(void)openMenu
{
    _menuCounter = 1;
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationCurve:UIViewAnimationCurveLinear];
    [UIView setAnimationDuration:0.3f];
    [_settingsSubView setFrame:CGRectMake((_screenWidth * 0.5), (_barHeight), (_screenWidth * 0.5), (_screenHeight * 0.5))];
    [UIView commitAnimations];
}
-(void)addOverlay
{
    _overlayView = [[UIView alloc] initWithFrame:CGRectMake(0, _barHeight, _screenWidth, _screenHeight)];
    _overlayView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.5f];
    [self.view addSubview:_overlayView];
}

So, how would I make it so that a UIView (SubMenuView) can be called by any of the UIViewControllers and have the same animation that I have here but with different parameters loaded based on the 'requesting' UIVewController ?

Edit - I have tried a few more things and can't seem to get this working, not sure categories are what I need right now as I seem to be stuck on a 'stage before the use of categories' as in; I can't even load the UIView properly yet. Here is a image of what I am trying to achieve:

在此处输入图片说明

Note that the three UIViewControllers are different but the UIView that includes a sub menu is the same UIView but before it is loaded, different parameters are sent so when it draws it has the correct menu items.

In have also tried to import the SubMenuView.h and then create an instance of it:

SubMenyView *subMenuViewInstance = [SubMenuView alloc] innit];
[self.view addSubView:subMenuViewInstance];

SubMenuView.m is then loaded but it has no reference to the UIViewController that called it so I can't draw the UIView or edit the UINavigationController . Doing this from the UIViewController I would normally just use

[self.view addSubView:_settingsSubView];
// Run the method that animates the UIView onto the screen...

So basically, how do I do those last two lines with a separate UIView class rather than writing all the code within the UIViewController.m of each of the UIViewControllers ?

You can create a Category for example:

#import "UIView+OpticalEffects.h"

@implementation UIView (OpticalEffects)

- (void)configureShadowWithColor:(UIColor *)color {
    UIBezierPath *shadowPath = [UIBezierPath bezierPathWithRect:self.bounds];
    //and so on
}

- (void)configureShadowWithBlackColor 
{
    [self configureShadowWithColor:[UIColor blackColor]];
}


- (UIImageView *)imageViewFromView 
{
    CGRect screenRect = UIScreen.mainScreen.bounds;
    UIGraphicsBeginImageContext(screenRect.size);
//and so on
    return capturedImageView;
}

- (void)addInnerVerticalShadow 
{
    CAGradientLayer *gradientLayer = [CAGradientLayer layer] ;
    gradientLayer.frame = CGRectMake(0, 0, 20, self.bounds.size.height);
//and so on
}

@end

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM